r8899@llin: dpavlin | 2005-11-16 16:32:37 +0100
[webpac2] / web / iwf / iwfajax.js
index a2f3f05..d68e5c8 100644 (file)
@@ -1,52 +1,88 @@
-// -----------------------------------------------------------------------------\r
-// IWF - Interactive Website Framework.  Javascript library for creating\r
-// responsive thin client interfaces.\r
-//\r
-// Copyright (C) 2005 Brock Weaver brockweaver@gmail.com\r
-//\r
-//     This library is free software; you can redistribute it and/or modify\r
-// it under the terms of the GNU Lesser General Public License as published\r
-// by the Free Software Foundation; either version 2.1 of the License, or\r
-// (at your option) any later version.\r
-//\r
-//     This library is distributed in the hope that it will be useful, but\r
-// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
-// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public\r
-// License for more details.\r
+// =========================================================================\r
+/// IWF - Interactive Website Framework.  Javascript library for creating\r
+/// responsive thin client interfaces.\r
+///\r
+/// Copyright (C) 2005 Brock Weaver brockweaver@users.sourceforge.net\r
+///\r
+///     This library is free software; you can redistribute it and/or modify\r
+/// it under the terms of the GNU Lesser General Public License as published\r
+/// by the Free Software Foundation; either version 2.1 of the License, or\r
+/// (at your option) any later version.\r
+///\r
+///     This library is distributed in the hope that it will be useful, but\r
+/// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+/// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public\r
+/// License for more details.\r
+///\r
+///    You should have received a copy of the GNU Lesser General Public License\r
+/// along with this library; if not, write to the Free Software Foundation,\r
+/// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+///\r
+/// Brock Weaver\r
+/// brockweaver@users.sourceforge.net\r
+/// 1605 NW Maple Pl\r
+/// Ankeny, IA 50021\r
+///\r
+//! http://iwf.sourceforge.net/\r
+// --------------------------------------------------------------------------\r
+//! NOTE: To minimize file size, strip all fluffy comments (except the LGPL, of course!)\r
+//! using the following regex (global flag and multiline on):\r
+//!            ^\t*//([^/!].*|$)\r
 //\r
-//    You should have received a copy of the GNU Lesser General Public License\r
-// along with this library; if not, write to the Free Software Foundation,\r
-// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+// This reduces file size by about 30%, give or take.\r
 //\r
-// Brock Weaver\r
-// brockweaver@gmail.com\r
-// 1605 NW Maple Pl\r
-// Ankeny, IA 50021\r
-// -----------------------------------------------------------------------------\r
+//!  To rip out only logging statements (commented or uncommented):\r
+//!            ^/{0,2}iwfLog.*\r
+// --------------------------------------------------------------------------\r
+\r
 \r
 // --------------------------------------------------------------------------\r
-// iwfajax.js\r
+//\r
+//! iwfajax.js\r
 //\r
 // Thread-safe background xml request via XmlHttpRequest object\r
 //\r
-// Dependencies:\r
-// iwfxml.js\r
-// iwfcore.js\r
-// iwfgui.js (optional -- pretty progress bar)\r
+//! Dependencies:\r
+//! iwfxml.js\r
+//! iwfcore.js\r
+//! iwfgui.js (optional -- pretty progress bar)\r
 //\r
-// Brock Weaver - brockweaver@sourceforge.net - iwf.sourceforge.net\r
-// v 0.1 - 2005-06-05\r
-// Initial release.\r
-// --------------------------------------------------------------------------\r
-// Known Issues:\r
-//  AddToHistory does not work\r
-//  Iframe not implemented\r
+//! Brock Weaver - brockweaver@users.sourceforge.net\r
+//! v 0.2 - 2005-11-14\r
+//! core bug patch\r
 // --------------------------------------------------------------------------\r
+//! v 0.1 - 2005-06-05\r
+//! Initial release.\r
+//\r
+//! Known Issues:\r
+//!  AddToHistory does not work\r
+//!  Iframe not implemented\r
+//\r
+// =========================================================================\r
+\r
+\r
+\r
+\r
+// show progress bar if they included iwfgui.js, window.status otherwise.\r
+var _iwfShowGuiProgress = iwfExists(window.iwfShow);\r
+\r
+\r
+\r
+\r
+\r
+\r
+// -----------------------------------\r
+// Begin: Dependency Check\r
+// -----------------------------------\r
 \r
 if (!window.iwfGetById || !window.iwfXmlDoc){\r
        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);\r
 }\r
 \r
+// -----------------------------------\r
+// End: Dependency Check\r
+// -----------------------------------\r
+\r
 // -----------------------------------\r
 // Begin: AJAX Request and Response\r
 // -----------------------------------\r
@@ -62,7 +98,7 @@ function iwfRequest(urlOrForm, targetElementOnResponse, addToHistory, callback){
                if (req.readyState == 4) {\r
                        _iwfOnRequestEnd();\r
                        if (req.status == 200 || req.status == 0) {\r
-iwfLog('exact response from server:\n\n' + req.responseText);\r
+//iwfLog('exact response from server:\n\n' + req.responseText);\r
                                _iwfResponseHandler(req.responseText, localCallback, localTarget);\r
                        } else {\r
                                _iwfOnRequestError(req.status, req.statusText, req.responseText);\r
@@ -121,7 +157,7 @@ iwfLog('exact response from server:\n\n' + req.responseText);
                }\r
 \r
                if (localTarget){\r
-                       var elTgt = iwfGetOrCreateWithinForm(urlOrForm, 'iwfTarget', 'input', 'hidden');\r
+                       var elTgt = iwfGetOrCreateByNameWithinForm(urlOrForm, 'iwfTarget', 'input', 'hidden');\r
                        if (elTgt){\r
                                iwfAttribute(elTgt, 'value', localTarget);\r
                                iwfRemoveAttribute(elTgt, 'disabled');\r
@@ -158,15 +194,15 @@ iwfLog('exact response from server:\n\n' + req.responseText);
        // prevent any browser caching of our url by requesting a unique url everytime...\r
        url += ((url.indexOf('?') > -1) ? '&' : '?') + 'iwfRequestId=' + new Date().valueOf();\r
 \r
-iwfLog("url = " + url);\r
-iwfLog("method = " + method);\r
-iwfLog("postdata = " + postdata);\r
-iwfLog("contenttype = " + contentType);\r
+//iwfLog("url = " + url);\r
+//iwfLog("method = " + method);\r
+//iwfLog("postdata = " + postdata);\r
+//iwfLog("contenttype = " + contentType);\r
 \r
 \r
        var req = null;\r
        if (!addToHistory){\r
-iwfLog("using XHR to perform request...");\r
+//iwfLog("using XHR to perform request...");\r
                // use XHR to perform the request, as this will\r
                // prevent the browser from adding it to history.\r
                req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");\r
@@ -229,7 +265,7 @@ function _iwfGetFormData(form, url, ctl){
        // if there is a target specified in the <form> tag,\r
        // copy its contents to a hidden <input type='hidden'> tag.\r
 \r
-iwfLog("total elements in form named '" + form.name + "': " + form.elements.length);\r
+//iwfLog("total elements in form named '" + form.name + "': " + form.elements.length);\r
        for(var i=0;i<form.elements.length;i++){\r
                var el = form.elements[i];\r
                var nm = iwfAttribute(el, 'name');\r
@@ -310,7 +346,7 @@ iwfLog("total elements in form named '" + form.name + "': " + form.elements.leng
 }\r
 \r
 function _iwfResponseReceived(doc){\r
-       iwfLog('iframeloaded');\r
+iwfLog('iframeloaded');\r
        var xmlDoc = new iwfXmlDoc(doc.innerHTML);\r
 }\r
 \r
@@ -333,7 +369,7 @@ function _iwfResponseHandler(origText, callback, tgt){
                for(var i=0; i< doc.response.childNodes.length; i++){\r
                        var node = doc.response.childNodes[i];\r
                        if (node.nodeName.indexOf("#") != 0){\r
-iwfLog('node.target=' + node.target + '\ntgt=' + tgt);\r
+//iwfLog('node.target=' + node.target + '\ntgt=' + tgt);\r
                                if (!tgt) {\r
                                        // server target is ignored if a client target exists.\r
                                        tgt = node.target;\r
@@ -422,11 +458,13 @@ function _iwfInsertHtml(html, parentNodeId){
                        // our html to inject contains a form node.\r
                        // bubble up the chain until we find a <form> node, or we have no parents\r
                        var elParent = el;\r
-                       while (elParent && elParent.tagName.toLowerCase() != 'form'){\r
+                       // I have doubts about adding elParent.tagName here\r
+                       // but I don't have better idea. -dpavlin\r
+                       while (elParent && elParent.tagName && elParent.tagName.toLowerCase() != 'form'){\r
                                elParent = iwfGetParent(elParent);\r
                        }\r
 \r
-                       if (elParent && elParent.tagName.toLowerCase() == 'form'){\r
+                       if (elParent && elParent.tagName && elParent.tagName.toLowerCase() == 'form'){\r
                                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);\r
                        }\r
                }\r
@@ -461,9 +499,9 @@ function _iwfInsertHtml(html, parentNodeId){
 \r
                        // this code is the worst hack in this entire framework.\r
                        // the code in the try portion should work anywhere -- but\r
-                       // ie barfs when you try to set the innerHTML on a script element.\r
-                       // not only that, but ie won't parse script unless a visible element\r
-                       // is contained in the innerHTML when it is set, so we need the <code>ie hack here</code>\r
+                       // IE barfs when you try to set the innerHTML on a script element.\r
+                       // not only that, but IE won't parse script unless a visible element\r
+                       // is contained in the innerHTML when it is set, so we need the <code>IE hack here</code>\r
                        // and it cannot be removed.\r
                        // I don't understand why creating a new node and setting its innerHTML causes the browsers\r
                        // to parse and execute the script, but it does.\r
@@ -475,16 +513,22 @@ function _iwfInsertHtml(html, parentNodeId){
                        // Plus I'm getting lazy. :)\r
                        //\r
                        try {\r
-                               // moz (DOM)\r
-                               var elScript = iwfGetOrCreateById('iwfScript' + i, 'script', 'body');\r
+                               //! moz (DOM)\r
+                               var elScript = iwfGetOrCreateById('iwfScript' + i, 'script');\r
                                elScript.type = 'text/javascript';\r
                                elScript.defer = 'true';\r
                                elScript.innerHTML = scriptHtml;\r
 \r
+                               iwfAppendChild('body', elScript);\r
+\r
                        } catch(e){\r
-                               // 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...\r
+//iwfLog("IE Hack for injecting script tag...", true);\r
+                               //! IE hack\r
+                               // IE needs a visible tag within a non-script element to have scripting apply... Don't ask me why, ask the IE team why.\r
+                               // My guess is the visible element causes the page to at least partially re-render, which in turn kicks off any script parsing\r
+                               // code in IE.\r
                                var elDiv = iwfGetOrCreateById('iwfScript' + i, '<div style="display:none"></div>', 'body');\r
-                               elDiv.innerHTML = '<code>ie hack here</code><script id="iwfScript' + i + '" defer="true">' + scriptHtml + '</script' + '>';\r
+                               elDiv.innerHTML = '<code>IE hack here</code><script id="iwfScript' + i + '" defer="true">' + scriptHtml + '</script' + '>';\r
                        }\r
 \r
                        i++;\r
@@ -496,10 +540,8 @@ function _iwfInsertHtml(html, parentNodeId){
 \r
 function iwfCleanScripts(){\r
        var i = 0;\r
-       while((el = iwfGetById('iwfScript' + i))){\r
-               iwfRemoveNode(el);\r
-               i++;\r
-       }\r
+       while(iwfRemoveNode('iwfScript' + (i++)));\r
+\r
 }\r
 \r
 \r
@@ -509,6 +551,54 @@ var _iwfPendingRequests = 0;
 var _iwfRequestTicker = null;\r
 var _iwfRequestTickCount = 0;\r
 var _iwfRequestTickDuration = 100;\r
+\r
+\r
+// TODO: make the styles applied be configurable variables at the top of this file.\r
+function _iwfGetBusyBar(inner){\r
+       var b = iwfGetById('iwfBusy');\r
+       if (!b){\r
+               b = iwfGetOrCreateById('iwfBusy', 'div', 'body');\r
+               if(b.style){\r
+                       b.style.position = 'absolute';\r
+                       b.style.border = '1px solid black';\r
+                       b.style.backgroundColor = '#efefef';\r
+                       b.style.textAlign = 'center';\r
+               }\r
+               iwfWidth(b, 100);\r
+               iwfHeight(b, 20);\r
+               iwfZIndex(b, 9999);\r
+\r
+               iwfX(b, 0);\r
+               iwfY(b, 0);\r
+\r
+//             iwfX(b, iwfClientWidth() - iwfWidth(b)-5);\r
+//             iwfY(b, iwfClientHeight() - iwfHeight(b)-5);\r
+\r
+               iwfHide(b);\r
+       }\r
+\r
+\r
+\r
+       var bb = iwfGetById('iwfBusyBar');\r
+       if(!bb){\r
+               bb = iwfGetOrCreateById('iwfBusyBar', 'div', b);\r
+               bb.style.backgroundColor = 'navy';\r
+               bb.style.color = 'white';\r
+               bb.style.textAlign = 'center';\r
+               iwfWidth(bb, 1);\r
+               iwfHeight(bb, 20);\r
+               iwfX(bb, 0);\r
+               iwfY(bb, 0);\r
+       }\r
+\r
+       if(inner){\r
+               return bb;\r
+       } else {\r
+               return b;\r
+       }\r
+\r
+}\r
+\r
 function _iwfOnRequestStart(){\r
        _iwfPendingRequests++;\r
        _iwfTotalRequests++;\r
@@ -519,9 +609,14 @@ function _iwfOnRequestStart(){
                _iwfRequestTickCount = 0;\r
                if (window.iwfOnRequestStart){\r
                        _iwfRequestTickDuration = iwfOnRequestStart();\r
+               } else if (_iwfShowGuiProgress) {\r
+                       // use gui busy implementation\r
+                       var bb = _iwfGetBusyBar(true);\r
+                       iwfWidth(bb, 1);\r
+                       bb.innerHTML = '0%';\r
+                       iwfShow(_iwfGetBusyBar(false));\r
                } else {\r
                        // use default busy implementation...\r
-                       // TODO: make this better!\r
                        window.status = 'busy.';\r
                }\r
                if (!_iwfRequestTickDuration){\r
@@ -536,9 +631,21 @@ function _iwfOnRequestTick(){
        if (window.iwfOnRequestTick){\r
                iwfOnRequestTick(_iwfRequestTickCount, _iwfRequestTickDuration, _iwfPendingRequests);\r
        } else if (!window.iwfOnRequestStart) {\r
-               // use default busy implementation...\r
-               // TODO: make this better!\r
-               window.status = 'busy...............................................'.substr(0, (_iwfRequestTickCount % 45) + 5);\r
+               if (_iwfShowGuiProgress) {\r
+                       // use gui busy implementation\r
+                       var bar = _iwfGetBusyBar(true);\r
+                       if(bar){\r
+                               var w = iwfWidth(bar) + 1;\r
+                               if (w > 95){\r
+                                       w = 95;\r
+                               }\r
+                               iwfWidth(bar, w);\r
+                               bar.innerHTML = "loading " + iwfIntFormat(w) + "%";\r
+                       }\r
+               } else {\r
+                       // use default busy implementation...\r
+                       window.status = 'busy...............................................'.substr(0, (_iwfRequestTickCount % 45) + 5);\r
+               }\r
        } else {\r
                // they didn't define a tick function,\r
                // but they did define a start one, so do nothing.\r
@@ -555,9 +662,18 @@ function _iwfOnRequestEnd(){
                if (window.iwfOnRequestEnd){\r
                        iwfOnRequestEnd();\r
                } else if (!window.iwfOnRequestStart) {\r
-                       // use default busy implementation...\r
-                       // TODO: make this better!\r
-                       window.status = 'done.';\r
+                       if (_iwfShowGuiProgress) {\r
+                       // use gui busy implementation\r
+                               var bar = _iwfGetBusyBar(true);\r
+                               if(bar){\r
+                                       iwfWidth(bar, 100);\r
+                                       bar.innerHTML = "Done";\r
+                                       iwfHideGentlyDelay(_iwfGetBusyBar(false), 15, 500);\r
+                               }\r
+                       } else {\r
+                               // use default busy implementation...\r
+                               window.status = 'done.';\r
+                       }\r
                } else {\r
                        // they didn't define an end function,\r
                        // but they did define a start one, so do nothing.\r
@@ -567,9 +683,21 @@ function _iwfOnRequestEnd(){
                if (window.iwfOnRequestProgress){\r
                        iwfOnRequestProgress(_iwfPendingRequests, _iwfTotalRequests);\r
                } else if (!window.iwfOnRequestStart) {\r
-                       // use default busy implementation...\r
-                       // TODO: make this better!\r
-                       window.status = 'Remaining: ' + _iwfPendingRequests;\r
+                       if (_iwfShowGuiProgress) {\r
+                       // use gui busy implementation\r
+                               var pct = (1 - (_iwfPendingRequests/_iwfTotalRequests)) * 100;\r
+                               if (pct > 100){\r
+                                       pct = 100;\r
+                               }\r
+                               var bar = _iwfGetBusyBar(true);\r
+                               if(bar){\r
+                                       iwfWidth(bar, pct);\r
+                                       bar.innerHTML = "loading " + iwfIntFormat(pct) + "%";\r
+                               }\r
+                       } else {\r
+                               // use default busy implementation...\r
+                               window.status = 'Remaining: ' + _iwfPendingRequests;\r
+                       }\r
                } else {\r
                        // they didn't define an end function,\r
                        // but they did define a start one, so do nothing.\r