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'); |
276 |
switch(iwfAttribute(el, 'type')){ |
switch(iwfAttribute(el, 'type')){ |
277 |
case 'checkbox': |
case 'checkbox': |
278 |
case 'radio': |
case 'radio': |
279 |
if (iwfAttribute(el, 'checked')){ |
if (iwfAttribute(el, 'checked') || el.checked){ |
280 |
val = iwfAttribute(el, 'value'); |
val = iwfAttribute(el, 'value') || el.value; |
281 |
} |
} |
282 |
break; |
break; |
283 |
case 'button': |
case 'button': |
311 |
} |
} |
312 |
break; |
break; |
313 |
case 'textarea': |
case 'textarea': |
314 |
val = iwfAttribute(el, 'innerText'); |
val = iwfAttribute(el, 'innerText') || el.value; |
315 |
break; |
break; |
316 |
case 'button': |
case 'button': |
317 |
if (el == ctl){ |
if (el == ctl){ |
318 |
val = iwfAttribute(el, 'innerText'); |
val = iwfAttribute(el, 'innerText') || el.value; |
319 |
} |
} |
320 |
break; |
break; |
321 |
case 'select': |
case 'select': |
346 |
} |
} |
347 |
|
|
348 |
function _iwfResponseReceived(doc){ |
function _iwfResponseReceived(doc){ |
349 |
iwfLog('iframeloaded'); |
iwfLog('iframeloaded'); |
350 |
var xmlDoc = new iwfXmlDoc(doc.innerHTML); |
var xmlDoc = new iwfXmlDoc(doc.innerHTML); |
351 |
} |
} |
352 |
|
|
369 |
for(var i=0; i< doc.response.childNodes.length; i++){ |
for(var i=0; i< doc.response.childNodes.length; i++){ |
370 |
var node = doc.response.childNodes[i]; |
var node = doc.response.childNodes[i]; |
371 |
if (node.nodeName.indexOf("#") != 0){ |
if (node.nodeName.indexOf("#") != 0){ |
372 |
iwfLog('node.target=' + node.target + '\ntgt=' + tgt); |
//iwfLog('node.target=' + node.target + '\ntgt=' + tgt); |
373 |
if (!tgt) { |
if (!tgt) { |
374 |
// server target is ignored if a client target exists. |
// server target is ignored if a client target exists. |
375 |
tgt = node.target; |
tgt = node.target; |
497 |
|
|
498 |
// this code is the worst hack in this entire framework. |
// this code is the worst hack in this entire framework. |
499 |
// the code in the try portion should work anywhere -- but |
// the code in the try portion should work anywhere -- but |
500 |
// 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. |
501 |
// 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 |
502 |
// 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> |
503 |
// and it cannot be removed. |
// and it cannot be removed. |
504 |
// 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 |
505 |
// to parse and execute the script, but it does. |
// to parse and execute the script, but it does. |
511 |
// Plus I'm getting lazy. :) |
// Plus I'm getting lazy. :) |
512 |
// |
// |
513 |
try { |
try { |
514 |
// moz (DOM) |
//! moz (DOM) |
515 |
var elScript = iwfGetOrCreateById('iwfScript' + i, 'script', 'body'); |
var elScript = iwfGetOrCreateById('iwfScript' + i, 'script'); |
516 |
elScript.type = 'text/javascript'; |
elScript.type = 'text/javascript'; |
517 |
elScript.defer = 'true'; |
elScript.defer = 'true'; |
518 |
elScript.innerHTML = scriptHtml; |
elScript.innerHTML = scriptHtml; |
519 |
|
|
520 |
|
iwfAppendChild('body', elScript); |
521 |
|
|
522 |
} catch(e){ |
} catch(e){ |
523 |
// 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); |
524 |
|
//! IE hack |
525 |
|
// IE needs a visible tag within a non-script element to have scripting apply... Don't ask me why, ask the IE team why. |
526 |
|
// My guess is the visible element causes the page to at least partially re-render, which in turn kicks off any script parsing |
527 |
|
// code in IE. |
528 |
var elDiv = iwfGetOrCreateById('iwfScript' + i, '<div style="display:none"></div>', 'body'); |
var elDiv = iwfGetOrCreateById('iwfScript' + i, '<div style="display:none"></div>', 'body'); |
529 |
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' + '>'; |
530 |
} |
} |
531 |
|
|
532 |
i++; |
i++; |
538 |
|
|
539 |
function iwfCleanScripts(){ |
function iwfCleanScripts(){ |
540 |
var i = 0; |
var i = 0; |
541 |
while((el = iwfGetById('iwfScript' + i))){ |
while(iwfRemoveNode('iwfScript' + (i++))); |
542 |
iwfRemoveNode(el); |
|
|
i++; |
|
|
} |
|
543 |
} |
} |
544 |
|
|
545 |
|
|
549 |
var _iwfRequestTicker = null; |
var _iwfRequestTicker = null; |
550 |
var _iwfRequestTickCount = 0; |
var _iwfRequestTickCount = 0; |
551 |
var _iwfRequestTickDuration = 100; |
var _iwfRequestTickDuration = 100; |
552 |
|
|
553 |
|
|
554 |
|
// TODO: make the styles applied be configurable variables at the top of this file. |
555 |
|
function _iwfGetBusyBar(inner){ |
556 |
|
var b = iwfGetById('iwfBusy'); |
557 |
|
if (!b){ |
558 |
|
b = iwfGetOrCreateById('iwfBusy', 'div', 'body'); |
559 |
|
if(b.style){ |
560 |
|
b.style.position = 'absolute'; |
561 |
|
b.style.border = '1px solid black'; |
562 |
|
b.style.backgroundColor = '#efefef'; |
563 |
|
b.style.textAlign = 'center'; |
564 |
|
} |
565 |
|
iwfWidth(b, 100); |
566 |
|
iwfHeight(b, 20); |
567 |
|
iwfZIndex(b, 9999); |
568 |
|
|
569 |
|
iwfX(b, 0); |
570 |
|
iwfY(b, 0); |
571 |
|
|
572 |
|
// iwfX(b, iwfClientWidth() - iwfWidth(b)-5); |
573 |
|
// iwfY(b, iwfClientHeight() - iwfHeight(b)-5); |
574 |
|
|
575 |
|
iwfHide(b); |
576 |
|
} |
577 |
|
|
578 |
|
|
579 |
|
|
580 |
|
var bb = iwfGetById('iwfBusyBar'); |
581 |
|
if(!bb){ |
582 |
|
bb = iwfGetOrCreateById('iwfBusyBar', 'div', b); |
583 |
|
bb.style.backgroundColor = 'navy'; |
584 |
|
bb.style.color = 'white'; |
585 |
|
bb.style.textAlign = 'center'; |
586 |
|
iwfWidth(bb, 1); |
587 |
|
iwfHeight(bb, 20); |
588 |
|
iwfX(bb, 0); |
589 |
|
iwfY(bb, 0); |
590 |
|
} |
591 |
|
|
592 |
|
if(inner){ |
593 |
|
return bb; |
594 |
|
} else { |
595 |
|
return b; |
596 |
|
} |
597 |
|
|
598 |
|
} |
599 |
|
|
600 |
function _iwfOnRequestStart(){ |
function _iwfOnRequestStart(){ |
601 |
_iwfPendingRequests++; |
_iwfPendingRequests++; |
602 |
_iwfTotalRequests++; |
_iwfTotalRequests++; |
607 |
_iwfRequestTickCount = 0; |
_iwfRequestTickCount = 0; |
608 |
if (window.iwfOnRequestStart){ |
if (window.iwfOnRequestStart){ |
609 |
_iwfRequestTickDuration = iwfOnRequestStart(); |
_iwfRequestTickDuration = iwfOnRequestStart(); |
610 |
|
} else if (_iwfShowGuiProgress) { |
611 |
|
// use gui busy implementation |
612 |
|
var bb = _iwfGetBusyBar(true); |
613 |
|
iwfWidth(bb, 1); |
614 |
|
bb.innerHTML = '0%'; |
615 |
|
iwfShow(_iwfGetBusyBar(false)); |
616 |
} else { |
} else { |
617 |
// use default busy implementation... |
// use default busy implementation... |
|
// TODO: make this better! |
|
618 |
window.status = 'busy.'; |
window.status = 'busy.'; |
619 |
} |
} |
620 |
if (!_iwfRequestTickDuration){ |
if (!_iwfRequestTickDuration){ |
629 |
if (window.iwfOnRequestTick){ |
if (window.iwfOnRequestTick){ |
630 |
iwfOnRequestTick(_iwfRequestTickCount, _iwfRequestTickDuration, _iwfPendingRequests); |
iwfOnRequestTick(_iwfRequestTickCount, _iwfRequestTickDuration, _iwfPendingRequests); |
631 |
} else if (!window.iwfOnRequestStart) { |
} else if (!window.iwfOnRequestStart) { |
632 |
// use default busy implementation... |
if (_iwfShowGuiProgress) { |
633 |
// TODO: make this better! |
// use gui busy implementation |
634 |
window.status = 'busy...............................................'.substr(0, (_iwfRequestTickCount % 45) + 5); |
var bar = _iwfGetBusyBar(true); |
635 |
|
if(bar){ |
636 |
|
var w = iwfWidth(bar) + 1; |
637 |
|
if (w > 95){ |
638 |
|
w = 95; |
639 |
|
} |
640 |
|
iwfWidth(bar, w); |
641 |
|
bar.innerHTML = "loading " + iwfIntFormat(w) + "%"; |
642 |
|
} |
643 |
|
} else { |
644 |
|
// use default busy implementation... |
645 |
|
window.status = 'busy...............................................'.substr(0, (_iwfRequestTickCount % 45) + 5); |
646 |
|
} |
647 |
} else { |
} else { |
648 |
// they didn't define a tick function, |
// they didn't define a tick function, |
649 |
// but they did define a start one, so do nothing. |
// but they did define a start one, so do nothing. |
660 |
if (window.iwfOnRequestEnd){ |
if (window.iwfOnRequestEnd){ |
661 |
iwfOnRequestEnd(); |
iwfOnRequestEnd(); |
662 |
} else if (!window.iwfOnRequestStart) { |
} else if (!window.iwfOnRequestStart) { |
663 |
// use default busy implementation... |
if (_iwfShowGuiProgress) { |
664 |
// TODO: make this better! |
// use gui busy implementation |
665 |
window.status = 'done.'; |
var bar = _iwfGetBusyBar(true); |
666 |
|
if(bar){ |
667 |
|
iwfWidth(bar, 100); |
668 |
|
bar.innerHTML = "Done"; |
669 |
|
iwfHideGentlyDelay(_iwfGetBusyBar(false), 15, 500); |
670 |
|
} |
671 |
|
} else { |
672 |
|
// use default busy implementation... |
673 |
|
window.status = 'done.'; |
674 |
|
} |
675 |
} else { |
} else { |
676 |
// they didn't define an end function, |
// they didn't define an end function, |
677 |
// but they did define a start one, so do nothing. |
// but they did define a start one, so do nothing. |
681 |
if (window.iwfOnRequestProgress){ |
if (window.iwfOnRequestProgress){ |
682 |
iwfOnRequestProgress(_iwfPendingRequests, _iwfTotalRequests); |
iwfOnRequestProgress(_iwfPendingRequests, _iwfTotalRequests); |
683 |
} else if (!window.iwfOnRequestStart) { |
} else if (!window.iwfOnRequestStart) { |
684 |
// use default busy implementation... |
if (_iwfShowGuiProgress) { |
685 |
// TODO: make this better! |
// use gui busy implementation |
686 |
window.status = 'Remaining: ' + _iwfPendingRequests; |
var pct = (1 - (_iwfPendingRequests/_iwfTotalRequests)) * 100; |
687 |
|
if (pct > 100){ |
688 |
|
pct = 100; |
689 |
|
} |
690 |
|
var bar = _iwfGetBusyBar(true); |
691 |
|
if(bar){ |
692 |
|
iwfWidth(bar, pct); |
693 |
|
bar.innerHTML = "loading " + iwfIntFormat(pct) + "%"; |
694 |
|
} |
695 |
|
} else { |
696 |
|
// use default busy implementation... |
697 |
|
window.status = 'Remaining: ' + _iwfPendingRequests; |
698 |
|
} |
699 |
} else { |
} else { |
700 |
// they didn't define an end function, |
// they didn't define an end function, |
701 |
// but they did define a start one, so do nothing. |
// but they did define a start one, so do nothing. |