1 |
// ----------------------------------------------------------------------------- |
// ========================================================================= |
2 |
// IWF - Interactive Website Framework. Javascript library for creating |
/// IWF - Interactive Website Framework. Javascript library for creating |
3 |
// responsive thin client interfaces. |
/// responsive thin client interfaces. |
4 |
// |
/// |
5 |
// Copyright (C) 2005 Brock Weaver brockweaver@gmail.com |
/// Copyright (C) 2005 Brock Weaver brockweaver@users.sourceforge.net |
6 |
// |
/// |
7 |
// This library is free software; you can redistribute it and/or modify |
/// This library is free software; you can redistribute it and/or modify |
8 |
// it under the terms of the GNU Lesser General Public License as published |
/// it under the terms of the GNU Lesser General Public License as published |
9 |
// by the Free Software Foundation; either version 2.1 of the License, or |
/// by the Free Software Foundation; either version 2.1 of the License, or |
10 |
// (at your option) any later version. |
/// (at your option) any later version. |
11 |
// |
/// |
12 |
// This library is distributed in the hope that it will be useful, but |
/// This library is distributed in the hope that it will be useful, but |
13 |
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
/// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
14 |
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
/// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
15 |
// License for more details. |
/// License for more details. |
16 |
|
/// |
17 |
|
/// You should have received a copy of the GNU Lesser General Public License |
18 |
|
/// along with this library; if not, write to the Free Software Foundation, |
19 |
|
/// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 |
|
/// |
21 |
|
/// Brock Weaver |
22 |
|
/// brockweaver@users.sourceforge.net |
23 |
|
/// 1605 NW Maple Pl |
24 |
|
/// Ankeny, IA 50021 |
25 |
|
/// |
26 |
|
//! http://iwf.sourceforge.net/ |
27 |
|
// -------------------------------------------------------------------------- |
28 |
|
//! NOTE: To minimize file size, strip all fluffy comments (except the LGPL, of course!) |
29 |
|
//! using the following regex (global flag and multiline on): |
30 |
|
//! ^\t*//([^/!].*|$) |
31 |
// |
// |
32 |
// You should have received a copy of the GNU Lesser General Public License |
// This reduces file size by about 30%, give or take. |
|
// along with this library; if not, write to the Free Software Foundation, |
|
|
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
33 |
// |
// |
34 |
// Brock Weaver |
//! To rip out only logging statements (commented or uncommented): |
35 |
// brockweaver@gmail.com |
//! ^/{0,2}iwfLog.* |
36 |
// 1605 NW Maple Pl |
// -------------------------------------------------------------------------- |
37 |
// Ankeny, IA 50021 |
|
|
// ----------------------------------------------------------------------------- |
|
38 |
|
|
39 |
// -------------------------------------------------------------------------- |
// -------------------------------------------------------------------------- |
40 |
// iwfajax.js |
// |
41 |
|
//! iwfajax.js |
42 |
// |
// |
43 |
// Thread-safe background xml request via XmlHttpRequest object |
// Thread-safe background xml request via XmlHttpRequest object |
44 |
// |
// |
45 |
// Dependencies: |
//! Dependencies: |
46 |
// iwfxml.js |
//! iwfxml.js |
47 |
// iwfcore.js |
//! iwfcore.js |
48 |
// iwfgui.js (optional -- pretty progress bar) |
//! iwfgui.js (optional -- pretty progress bar) |
49 |
// |
// |
50 |
// Brock Weaver - brockweaver@sourceforge.net - iwf.sourceforge.net |
//! Brock Weaver - brockweaver@users.sourceforge.net |
51 |
// v 0.1 - 2005-06-05 |
//! v 0.2 - 2005-11-14 |
52 |
// Initial release. |
//! core bug patch |
|
// -------------------------------------------------------------------------- |
|
|
// Known Issues: |
|
|
// AddToHistory does not work |
|
|
// Iframe not implemented |
|
53 |
// -------------------------------------------------------------------------- |
// -------------------------------------------------------------------------- |
54 |
|
//! v 0.1 - 2005-06-05 |
55 |
|
//! Initial release. |
56 |
|
// |
57 |
|
//! Known Issues: |
58 |
|
//! AddToHistory does not work |
59 |
|
//! Iframe not implemented |
60 |
|
// |
61 |
|
// ========================================================================= |
62 |
|
|
63 |
|
|
64 |
|
|
65 |
|
|
66 |
|
// show progress bar if they included iwfgui.js, window.status otherwise. |
67 |
|
var _iwfShowGuiProgress = iwfExists(window.iwfShow); |
68 |
|
|
69 |
|
|
70 |
|
|
71 |
|
|
72 |
|
|
73 |
|
|
74 |
|
// ----------------------------------- |
75 |
|
// Begin: Dependency Check |
76 |
|
// ----------------------------------- |
77 |
|
|
78 |
if (!window.iwfGetById || !window.iwfXmlDoc){ |
if (!window.iwfGetById || !window.iwfXmlDoc){ |
79 |
iwfLog("IWF Dependency Error: iwfajax.js is dependent upon both iwfcore.js and iwfxml.js, so you *must* reference those files first.\n\nExample:\n\n<script type='text/javascript' src='iwfcore.js'></script>\n<script type='text/javascript' src='iwfxml.js'></script>\n<script type='text/javascript' src='iwfajax.js'></script>", true); |
iwfLog("IWF Dependency Error: iwfajax.js is dependent upon both iwfcore.js and iwfxml.js, so you *must* reference those files first.\n\nExample:\n\n<script type='text/javascript' src='iwfcore.js'></script>\n<script type='text/javascript' src='iwfxml.js'></script>\n<script type='text/javascript' src='iwfajax.js'></script>", true); |
80 |
} |
} |
81 |
|
|
82 |
// ----------------------------------- |
// ----------------------------------- |
83 |
|
// End: Dependency Check |
84 |
|
// ----------------------------------- |
85 |
|
|
86 |
|
// ----------------------------------- |
87 |
// Begin: AJAX Request and Response |
// Begin: AJAX Request and Response |
88 |
// ----------------------------------- |
// ----------------------------------- |
89 |
|
|
98 |
if (req.readyState == 4) { |
if (req.readyState == 4) { |
99 |
_iwfOnRequestEnd(); |
_iwfOnRequestEnd(); |
100 |
if (req.status == 200 || req.status == 0) { |
if (req.status == 200 || req.status == 0) { |
101 |
iwfLog('exact response from server:\n\n' + req.responseText); |
//iwfLog('exact response from server:\n\n' + req.responseText); |
102 |
_iwfResponseHandler(req.responseText, localCallback, localTarget); |
_iwfResponseHandler(req.responseText, localCallback, localTarget); |
103 |
} else { |
} else { |
104 |
_iwfOnRequestError(req.status, req.statusText, req.responseText); |
_iwfOnRequestError(req.status, req.statusText, req.responseText); |
157 |
} |
} |
158 |
|
|
159 |
if (localTarget){ |
if (localTarget){ |
160 |
var elTgt = iwfGetOrCreateWithinForm(urlOrForm, 'iwfTarget', 'input', 'hidden'); |
var elTgt = iwfGetOrCreateByNameWithinForm(urlOrForm, 'iwfTarget', 'input', 'hidden'); |
161 |
if (elTgt){ |
if (elTgt){ |
162 |
iwfAttribute(elTgt, 'value', localTarget); |
iwfAttribute(elTgt, 'value', localTarget); |
163 |
iwfRemoveAttribute(elTgt, 'disabled'); |
iwfRemoveAttribute(elTgt, 'disabled'); |
194 |
// prevent any browser caching of our url by requesting a unique url everytime... |
// prevent any browser caching of our url by requesting a unique url everytime... |
195 |
url += ((url.indexOf('?') > -1) ? '&' : '?') + 'iwfRequestId=' + new Date().valueOf(); |
url += ((url.indexOf('?') > -1) ? '&' : '?') + 'iwfRequestId=' + new Date().valueOf(); |
196 |
|
|
197 |
iwfLog("url = " + url); |
//iwfLog("url = " + url); |
198 |
iwfLog("method = " + method); |
//iwfLog("method = " + method); |
199 |
iwfLog("postdata = " + postdata); |
//iwfLog("postdata = " + postdata); |
200 |
iwfLog("contenttype = " + contentType); |
//iwfLog("contenttype = " + contentType); |
201 |
|
|
202 |
|
|
203 |
var req = null; |
var req = null; |
204 |
if (!addToHistory){ |
if (!addToHistory){ |
205 |
iwfLog("using XHR to perform request..."); |
//iwfLog("using XHR to perform request..."); |
206 |
// use XHR to perform the request, as this will |
// use XHR to perform the request, as this will |
207 |
// prevent the browser from adding it to history. |
// prevent the browser from adding it to history. |
208 |
req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); |
req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); |
265 |
// if there is a target specified in the <form> tag, |
// if there is a target specified in the <form> tag, |
266 |
// copy its contents to a hidden <input type='hidden'> tag. |
// copy its contents to a hidden <input type='hidden'> tag. |
267 |
|
|
268 |
iwfLog("total elements in form named '" + form.name + "': " + form.elements.length); |
//iwfLog("total elements in form named '" + form.name + "': " + form.elements.length); |
269 |
for(var i=0;i<form.elements.length;i++){ |
for(var i=0;i<form.elements.length;i++){ |
270 |
var el = form.elements[i]; |
var el = form.elements[i]; |
271 |
var nm = iwfAttribute(el, 'name'); |
var nm = iwfAttribute(el, 'name'); |
275 |
case 'input': |
case 'input': |
276 |
switch(iwfAttribute(el, 'type')){ |
switch(iwfAttribute(el, 'type')){ |
277 |
case 'checkbox': |
case 'checkbox': |
278 |
|
if (iwfAttribute(el, 'checked')){ |
279 |
|
val = 'on'; |
280 |
|
} |
281 |
case 'radio': |
case 'radio': |
282 |
if (iwfAttribute(el, 'checked')){ |
if (iwfAttribute(el, 'checked')){ |
283 |
val = iwfAttribute(el, 'value'); |
val = iwfAttribute(el, 'value'); |
314 |
} |
} |
315 |
break; |
break; |
316 |
case 'textarea': |
case 'textarea': |
317 |
val = iwfAttribute(el, 'innerText'); |
val = iwfAttribute(el, 'innerText') || el.value; |
318 |
break; |
break; |
319 |
case 'button': |
case 'button': |
320 |
if (el == ctl){ |
if (el == ctl){ |
321 |
val = iwfAttribute(el, 'innerText'); |
val = iwfAttribute(el, 'innerText') || el.value; |
322 |
} |
} |
323 |
break; |
break; |
324 |
case 'select': |
case 'select': |
349 |
} |
} |
350 |
|
|
351 |
function _iwfResponseReceived(doc){ |
function _iwfResponseReceived(doc){ |
352 |
iwfLog('iframeloaded'); |
iwfLog('iframeloaded'); |
353 |
var xmlDoc = new iwfXmlDoc(doc.innerHTML); |
var xmlDoc = new iwfXmlDoc(doc.innerHTML); |
354 |
} |
} |
355 |
|
|
372 |
for(var i=0; i< doc.response.childNodes.length; i++){ |
for(var i=0; i< doc.response.childNodes.length; i++){ |
373 |
var node = doc.response.childNodes[i]; |
var node = doc.response.childNodes[i]; |
374 |
if (node.nodeName.indexOf("#") != 0){ |
if (node.nodeName.indexOf("#") != 0){ |
375 |
iwfLog('node.target=' + node.target + '\ntgt=' + tgt); |
//iwfLog('node.target=' + node.target + '\ntgt=' + tgt); |
376 |
if (!tgt) { |
if (!tgt) { |
377 |
// server target is ignored if a client target exists. |
// server target is ignored if a client target exists. |
378 |
tgt = node.target; |
tgt = node.target; |
461 |
// our html to inject contains a form node. |
// our html to inject contains a form node. |
462 |
// bubble up the chain until we find a <form> node, or we have no parents |
// bubble up the chain until we find a <form> node, or we have no parents |
463 |
var elParent = el; |
var elParent = el; |
464 |
while (elParent && elParent.tagName.toLowerCase() != 'form'){ |
// I have doubts about adding elParent.tagName here |
465 |
|
// but I don't have better idea. -dpavlin |
466 |
|
while (elParent && elParent.tagName && elParent.tagName.toLowerCase() != 'form'){ |
467 |
elParent = iwfGetParent(elParent); |
elParent = iwfGetParent(elParent); |
468 |
} |
} |
469 |
|
|
470 |
if (elParent && elParent.tagName.toLowerCase() == 'form'){ |
if (elParent && elParent.tagName && elParent.tagName.toLowerCase() == 'form'){ |
471 |
iwfLog('IWF Ajax Error: Attempting to inject html which contains a <form> node into a target element which is itself a <form> node, or is already contained by a <form> node.\nThis is bad html, and will not work appropriately on some major browsers.', true); |
iwfLog('IWF Ajax Error: Attempting to inject html which contains a <form> node into a target element which is itself a <form> node, or is already contained by a <form> node.\nThis is bad html, and will not work appropriately on some major browsers.', true); |
472 |
} |
} |
473 |
} |
} |
502 |
|
|
503 |
// this code is the worst hack in this entire framework. |
// this code is the worst hack in this entire framework. |
504 |
// the code in the try portion should work anywhere -- but |
// the code in the try portion should work anywhere -- but |
505 |
// ie barfs when you try to set the innerHTML on a script element. |
// IE barfs when you try to set the innerHTML on a script element. |
506 |
// not only that, but ie won't parse script unless a visible element |
// not only that, but IE won't parse script unless a visible element |
507 |
// is contained in the innerHTML when it is set, so we need the <code>ie hack here</code> |
// is contained in the innerHTML when it is set, so we need the <code>IE hack here</code> |
508 |
// and it cannot be removed. |
// and it cannot be removed. |
509 |
// I don't understand why creating a new node and setting its innerHTML causes the browsers |
// I don't understand why creating a new node and setting its innerHTML causes the browsers |
510 |
// to parse and execute the script, but it does. |
// to parse and execute the script, but it does. |
516 |
// Plus I'm getting lazy. :) |
// Plus I'm getting lazy. :) |
517 |
// |
// |
518 |
try { |
try { |
519 |
// moz (DOM) |
//! moz (DOM) |
520 |
var elScript = iwfGetOrCreateById('iwfScript' + i, 'script', 'body'); |
var elScript = iwfGetOrCreateById('iwfScript' + i, 'script'); |
521 |
elScript.type = 'text/javascript'; |
elScript.type = 'text/javascript'; |
522 |
elScript.defer = 'true'; |
elScript.defer = 'true'; |
523 |
elScript.innerHTML = scriptHtml; |
elScript.innerHTML = scriptHtml; |
524 |
|
|
525 |
|
iwfAppendChild('body', elScript); |
526 |
|
|
527 |
} catch(e){ |
} catch(e){ |
528 |
// ie hack -- need a visible tag within a non-script element to have scripting apply... Don't ask me why, ask the IE team why... |
//iwfLog("IE Hack for injecting script tag...", true); |
529 |
|
//! IE hack |
530 |
|
// IE needs a visible tag within a non-script element to have scripting apply... Don't ask me why, ask the IE team why. |
531 |
|
// My guess is the visible element causes the page to at least partially re-render, which in turn kicks off any script parsing |
532 |
|
// code in IE. |
533 |
var elDiv = iwfGetOrCreateById('iwfScript' + i, '<div style="display:none"></div>', 'body'); |
var elDiv = iwfGetOrCreateById('iwfScript' + i, '<div style="display:none"></div>', 'body'); |
534 |
elDiv.innerHTML = '<code>ie hack here</code><script id="iwfScript' + i + '" defer="true">' + scriptHtml + '</script' + '>'; |
elDiv.innerHTML = '<code>IE hack here</code><script id="iwfScript' + i + '" defer="true">' + scriptHtml + '</script' + '>'; |
535 |
} |
} |
536 |
|
|
537 |
i++; |
i++; |
543 |
|
|
544 |
function iwfCleanScripts(){ |
function iwfCleanScripts(){ |
545 |
var i = 0; |
var i = 0; |
546 |
while((el = iwfGetById('iwfScript' + i))){ |
while(iwfRemoveNode('iwfScript' + (i++))); |
547 |
iwfRemoveNode(el); |
|
|
i++; |
|
|
} |
|
548 |
} |
} |
549 |
|
|
550 |
|
|
554 |
var _iwfRequestTicker = null; |
var _iwfRequestTicker = null; |
555 |
var _iwfRequestTickCount = 0; |
var _iwfRequestTickCount = 0; |
556 |
var _iwfRequestTickDuration = 100; |
var _iwfRequestTickDuration = 100; |
557 |
|
|
558 |
|
|
559 |
|
// TODO: make the styles applied be configurable variables at the top of this file. |
560 |
|
function _iwfGetBusyBar(inner){ |
561 |
|
var b = iwfGetById('iwfBusy'); |
562 |
|
if (!b){ |
563 |
|
b = iwfGetOrCreateById('iwfBusy', 'div', 'body'); |
564 |
|
if(b.style){ |
565 |
|
b.style.position = 'absolute'; |
566 |
|
b.style.border = '1px solid black'; |
567 |
|
b.style.backgroundColor = '#efefef'; |
568 |
|
b.style.textAlign = 'center'; |
569 |
|
} |
570 |
|
iwfWidth(b, 100); |
571 |
|
iwfHeight(b, 20); |
572 |
|
iwfZIndex(b, 9999); |
573 |
|
|
574 |
|
iwfX(b, 0); |
575 |
|
iwfY(b, 0); |
576 |
|
|
577 |
|
// iwfX(b, iwfClientWidth() - iwfWidth(b)-5); |
578 |
|
// iwfY(b, iwfClientHeight() - iwfHeight(b)-5); |
579 |
|
|
580 |
|
iwfHide(b); |
581 |
|
} |
582 |
|
|
583 |
|
|
584 |
|
|
585 |
|
var bb = iwfGetById('iwfBusyBar'); |
586 |
|
if(!bb){ |
587 |
|
bb = iwfGetOrCreateById('iwfBusyBar', 'div', b); |
588 |
|
bb.style.backgroundColor = 'navy'; |
589 |
|
bb.style.color = 'white'; |
590 |
|
bb.style.textAlign = 'center'; |
591 |
|
iwfWidth(bb, 1); |
592 |
|
iwfHeight(bb, 20); |
593 |
|
iwfX(bb, 0); |
594 |
|
iwfY(bb, 0); |
595 |
|
} |
596 |
|
|
597 |
|
if(inner){ |
598 |
|
return bb; |
599 |
|
} else { |
600 |
|
return b; |
601 |
|
} |
602 |
|
|
603 |
|
} |
604 |
|
|
605 |
function _iwfOnRequestStart(){ |
function _iwfOnRequestStart(){ |
606 |
_iwfPendingRequests++; |
_iwfPendingRequests++; |
607 |
_iwfTotalRequests++; |
_iwfTotalRequests++; |
612 |
_iwfRequestTickCount = 0; |
_iwfRequestTickCount = 0; |
613 |
if (window.iwfOnRequestStart){ |
if (window.iwfOnRequestStart){ |
614 |
_iwfRequestTickDuration = iwfOnRequestStart(); |
_iwfRequestTickDuration = iwfOnRequestStart(); |
615 |
|
} else if (_iwfShowGuiProgress) { |
616 |
|
// use gui busy implementation |
617 |
|
var bb = _iwfGetBusyBar(true); |
618 |
|
iwfWidth(bb, 1); |
619 |
|
bb.innerHTML = '0%'; |
620 |
|
iwfShow(_iwfGetBusyBar(false)); |
621 |
} else { |
} else { |
622 |
// use default busy implementation... |
// use default busy implementation... |
|
// TODO: make this better! |
|
623 |
window.status = 'busy.'; |
window.status = 'busy.'; |
624 |
} |
} |
625 |
if (!_iwfRequestTickDuration){ |
if (!_iwfRequestTickDuration){ |
634 |
if (window.iwfOnRequestTick){ |
if (window.iwfOnRequestTick){ |
635 |
iwfOnRequestTick(_iwfRequestTickCount, _iwfRequestTickDuration, _iwfPendingRequests); |
iwfOnRequestTick(_iwfRequestTickCount, _iwfRequestTickDuration, _iwfPendingRequests); |
636 |
} else if (!window.iwfOnRequestStart) { |
} else if (!window.iwfOnRequestStart) { |
637 |
// use default busy implementation... |
if (_iwfShowGuiProgress) { |
638 |
// TODO: make this better! |
// use gui busy implementation |
639 |
window.status = 'busy...............................................'.substr(0, (_iwfRequestTickCount % 45) + 5); |
var bar = _iwfGetBusyBar(true); |
640 |
|
if(bar){ |
641 |
|
var w = iwfWidth(bar) + 1; |
642 |
|
if (w > 95){ |
643 |
|
w = 95; |
644 |
|
} |
645 |
|
iwfWidth(bar, w); |
646 |
|
bar.innerHTML = "loading " + iwfIntFormat(w) + "%"; |
647 |
|
} |
648 |
|
} else { |
649 |
|
// use default busy implementation... |
650 |
|
window.status = 'busy...............................................'.substr(0, (_iwfRequestTickCount % 45) + 5); |
651 |
|
} |
652 |
} else { |
} else { |
653 |
// they didn't define a tick function, |
// they didn't define a tick function, |
654 |
// but they did define a start one, so do nothing. |
// but they did define a start one, so do nothing. |
665 |
if (window.iwfOnRequestEnd){ |
if (window.iwfOnRequestEnd){ |
666 |
iwfOnRequestEnd(); |
iwfOnRequestEnd(); |
667 |
} else if (!window.iwfOnRequestStart) { |
} else if (!window.iwfOnRequestStart) { |
668 |
// use default busy implementation... |
if (_iwfShowGuiProgress) { |
669 |
// TODO: make this better! |
// use gui busy implementation |
670 |
window.status = 'done.'; |
var bar = _iwfGetBusyBar(true); |
671 |
|
if(bar){ |
672 |
|
iwfWidth(bar, 100); |
673 |
|
bar.innerHTML = "Done"; |
674 |
|
iwfHideGentlyDelay(_iwfGetBusyBar(false), 15, 500); |
675 |
|
} |
676 |
|
} else { |
677 |
|
// use default busy implementation... |
678 |
|
window.status = 'done.'; |
679 |
|
} |
680 |
} else { |
} else { |
681 |
// they didn't define an end function, |
// they didn't define an end function, |
682 |
// but they did define a start one, so do nothing. |
// but they did define a start one, so do nothing. |
686 |
if (window.iwfOnRequestProgress){ |
if (window.iwfOnRequestProgress){ |
687 |
iwfOnRequestProgress(_iwfPendingRequests, _iwfTotalRequests); |
iwfOnRequestProgress(_iwfPendingRequests, _iwfTotalRequests); |
688 |
} else if (!window.iwfOnRequestStart) { |
} else if (!window.iwfOnRequestStart) { |
689 |
// use default busy implementation... |
if (_iwfShowGuiProgress) { |
690 |
// TODO: make this better! |
// use gui busy implementation |
691 |
window.status = 'Remaining: ' + _iwfPendingRequests; |
var pct = (1 - (_iwfPendingRequests/_iwfTotalRequests)) * 100; |
692 |
|
if (pct > 100){ |
693 |
|
pct = 100; |
694 |
|
} |
695 |
|
var bar = _iwfGetBusyBar(true); |
696 |
|
if(bar){ |
697 |
|
iwfWidth(bar, pct); |
698 |
|
bar.innerHTML = "loading " + iwfIntFormat(pct) + "%"; |
699 |
|
} |
700 |
|
} else { |
701 |
|
// use default busy implementation... |
702 |
|
window.status = 'Remaining: ' + _iwfPendingRequests; |
703 |
|
} |
704 |
} else { |
} else { |
705 |
// they didn't define an end function, |
// they didn't define an end function, |
706 |
// but they did define a start one, so do nothing. |
// but they did define a start one, so do nothing. |