/**
 * @author Dmitri Snytkine
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Svn:	$Id:$
 *
 * @author     Dmitri Snytkine <email12@sharedlog.com>
 * @version    Release:  @package_version@
 * @copyright  2005-2008 (or current year) ExamNotes.net inc.
 * @license    http://www.gnu.org/licenses/gpl-3.0.txt The GNU General Public License (GPL) version 3
 * @link       http://wiki.sharedlog.com   Sharedlog.com project wiki
 * @category   Image processing
 *
 *
 */
var $Y = YAHOO, //
 $D = YAHOO.util.Dom, //
 $C = $D.getElementsByClassName, //
 $E = YAHOO.util.Event, //
 $CONN = YAHOO.util.Connect, //
 $ = YAHOO.util.Dom.get, //
 $LANG = YAHOO.lang, //
 $J = YAHOO.lang.JSON;

//$Y.namespace('oFrm');
if (!oSL) {
    var oSL = {};
}
if (!oSL.oFrm) {
    oSL.oFrm = {};
}

oSL.oFrm.toString = function(){
    return 'oSL.oFrm object';
}


/**
 * Callback object for ConnectionManager
 */
oSL.oFrm.fUploadCallback = {

    toString: function(){
        return 'object oSL.oFrm.fUploadCallback';
    },
    
    /**
     * This will not be used because the response
     * in the iframe will usually have javascript
     * that will call this window's fParseQfJson()
     * @param {Object} o
     */
    upload: function(o){
        //var myiframe = $('_yuiResizeMonitor');
    
    },
    success: function(o){
        //$Y.log('formJax 71 this: ' + this); // oSL
        var json;
        try {
            json = $J.parse(o.responseText);
        } 
        catch (e) {
            alert("Invalid json data in responceText " + $LANG.dump(e) + "\nresText: " + $LANG.dump(o.responseText));
        }
        //alert('51 this is: ' + this + ' json: ' + $LANG.dump(json));
        //$Y.log('formJax 72 this: ' + this);
        this.oFrm.fParseResponce(json);
    },
    failure: function(o){
        //alert('boo hoo ' + $LANG.dump(o));
        $Y.log('boo hoo ' + $LANG.dump(o), "warn");
    },
    /**
     * Timeout must be high
     * to allow uploading large files,
     * otherwise the process may timeout while
     * the file is being uploaded
     */
    timeout: 395000,
    
    scope: oSL
}

/**
 * Parse responce json object
 * and updates elements on page
 *
 * responce json object may come from
 * 2 different pages - one where the form
 * is actually submitted. In this case the
 * page will have a javascript that calls
 * this method directly and passes json object
 *
 * Second case if json comes from fUploadCallback
 * in this case json contains details about file
 * upload progress.
 * In this case we must calculate the % of upload
 * and update elements in the progress bar 'div' element
 * which will be in this object under .oMyForm ( like: this.oMyForm.plbltxt)
 *
 * In order to make it easy to tell which page responce came from
 * we will make it so progress.php puts all data in the 'progress' key
 * and form page will put under 'form' key
 *
 * When the upload is done we should do
 * some custom action. This could be redirecting user to another page
 * or removing the html form. At the very least we should
 * re-enable this.elBtnSubmit.disabled = false
 *
 * @param {Object} o
 */
oSL.oFrm.fParseResponce = function(json){
    //alert($LANG.dump(json));
    //$Y.log('127 this: ' + this + ' obj: ' + $LANG.dump(json)); // oSL.oFrm object
    var strMessage = '', qfe, errorDiv;
    switch (true) {
        case json.hasOwnProperty('exception'):
            if (json.hasOwnProperty('errHeader')) {
                strMessage += '<u>' + json.errHeader + '</u><br>';
            }
            if (this.barDiv) {
                errorDiv = this.barDiv;
            }
            else {
                errorDiv = $('qfe');
            }
            
            if (errorDiv) {
                errorDiv.innerHTML = '<div id="qfErrors">' + strMessage + json.exception + '</div>';
            }
            else {
                alert(json.exception);
            }
            break;
            
        case json.hasOwnProperty('progress'):
            //alert('106 this is ' + this + ' element to update: ' + this.oMyForm.plbltxt);
            //this.oMyForm.plbltxt.innerHTML = $LANG.dump(json);
            $Y.log('140 progress: ' + $LANG.dump(json));
            this.oMyForm.update(json);
            break;
            
        case json.hasOwnProperty('form'):
            $Y.log('formJax 144 this: ' + this); //oSL.oFrm object
            $Y.log('formJax 145 json: ' + $LANG.dump(json.form));
            // alert('132 ' + $LANG.dump(json));
            // First must update progress bar to 'done' status (100%), cancell timeout, interval
            if (this.oMyForm) {
                this.oMyForm.finishup();
            }
            
            /**   
         *
         * Now actually do stuff with returned json
         */
            if (json.form['message'] && json.form['mid']) {
                /**
             * This is a newly added message
             */
                if (oSL.blogPage && oSL.blogPage.appendReply) {
                    oSL.blogPage.appendReply(json.form.message, json.form.mid);
                }
            }
            else {
                /**
             * this is a html of the form
             */
                if (oSL.blogPage && oSL.blogPage.formPanel) {
                    //oSL.blogPage.fClearPanelBody();
                    oSL.blogPage.formPanel.setBody(json.form);
                }
            }
            /*
         if (this.elBtnSubmit) {
         this.elBtnSubmit.disabled = false;
         }
         */
            break;
            
        case json.hasOwnProperty('show'):
            
            $Y.log('formJax 180 ' + json.show);
            oSL.blogPage.replaceMessage(json.show);
            break;
            
        case json.hasOwnProperty('info'):
		this.json = json;
		//alert('this is ' + this); // oSL.oFrm object
            //alert('json: ' + $LANG.dump(json.info));
            //$Y.log('formJax 188 ' + $LANG.dump(json.info), "window");
            /**
         * Here we will reuse the already defined dom elements
         * this.oMyForm.pbheader
         * this.oMyForm.pbleft
         * this.oMyForm.pbright
         *
         */
            /**
         * In case upload progress bar still has not reached 100% we will
         * cancel the upload progress updating now
         * otherwise it may still update the text on the progress bar
         * when we already started updating bar with text
         * about file processing progress
         */
            setTimeout("oSL.updateBar()", 0);
                      
            break;
            
        case json.hasOwnProperty('redirect'):
            $Y.log('formJax 193 ' + json.redirect);
			this.redirect = json.redirect;
			setTimeout("oSL.redirect()", 0);
            
            break;
            
        case json.hasOwnProperty('success'):
        case json.hasOwnProperty('errors'):
            $Y.log('formJax 199', "warn");
            if (oSL && oSL.fParseQf) {
                oSL.fParseQf(json);
            }
            break;
    }
    
    if (this.elBtnSubmit) {
        this.elBtnSubmit.disabled = false;
    }
    
    
}

oSL.redirect = function(){
	window.location = oSL.oFrm.redirect;
}

oSL.updateBar = function(){
	var o = oSL.oFrm, json = oSL.oFrm.json;
				//alert('json: ' + $LANG.dump(json));
                if (o.oMyForm) {
                    o.oMyForm.finishup();
                    o.oMyForm.cancelRun();
                    o.oMyForm.markAsDone();
                }
                
                if (json.info.a1 && json.info.a1 !== '' && o.oMyForm.pbheader) {
                    o.oMyForm.pbheader.innerHTML = json.info.a1;
                }
                
                if (json.info.a2 && json.info.a2 !== '' && o.oMyForm.pbleft) {
                    o.oMyForm.pbleft.innerHTML = json.info.a2;
                }
                
                if (json.info.a3 && json.info.a3 !== '' && o.oMyForm.pbright) {
                    o.oMyForm.pbright.innerHTML = json.info.a3;
                }
                
                
                if (json.info.i && json.info.i !== '' && o.oMyForm.setBar) {
                    o.oMyForm.setBar(json.info.i);
                }
}

oSL.oFrm.setFormError = function(inputName, sErr){
    //alert('159 ' + inputName + 'err: ' + sErr);
    var elError;
    
    if (this.uForm && this.uForm.elements) {
        //alert('162\n');
        //$Y.log('163' + $LANG.dump(this.uForm.elements))
        //$Y.log('164' + $LANG.dump(this.uForm.elements[inputName]));
        if (!this.elError) {
            this.elError = document.createElement('span');
            $D.setStyle(this.elError, 'color', '#FF0000');
            $D.insertBefore(this.elError, this.uForm.elements[inputName]);
        }
        this.elError.innerHTML = sErr + '<br>';
        
    }
    
}
/**
 * Object maker function
 * but not a constructor - 'new' not used with it.
 *
 * This function is run to instantiate
 * object that handles progress bar of
 * uploads
 *
 * This function is run ONLY if form
 * has at least one file to be uploaded
 *
 * @param {Object} rootDiv
 * @param {Object} sUrl
 * @param {Object} myTimeout
 * @param {Object} initText
 */
oSL.oUpForm = function(rootDiv, sUrl, myTimeout, initText){

    /**
     * These var will become private variables on returned object
     */
    var totalBytes, //
 width = 400, //
 timeLeft = 0, //
 interval, //
 isDone = false, //
 curWidth = 0, //
 iDelay = (myTimeout) ? parseInt(myTimeout, 10) : 1000, //
 oTimeout, //
 bReset = false, //
 intRequestCount = 0, //
 aBuffer = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], //
 makeRequest = function(){
        //alert('starting async request to ' + sUrl);
        oSL.oFrm.oCheckRequest = $CONN.asyncRequest('GET', sUrl, oSL.oFrm.fUploadCallback);
    };
    
    return {
        toString: function(){
            return 'object oUpForm';
        },
        
        fMakeDivs: function(){
        
            if (rootDiv.firstChild) {
                rootDiv.removeChild(rootDiv.firstChild);
            }
            
            this.pfrm = document.createElement("div");
            this.pfrm.setAttribute("id", 'pfrm');
            this.pfrm.style.width = (width + 24) + "px";
            
            this.pbheader = document.createElement("div");
            this.pbheader.setAttribute("id", 'pbheader');
            this.pbheader.style.width = (width + 4) + "px";
            
            this.pbfooter = this.pbheader.cloneNode(false);
            this.pbfooter.id = 'pbfooter';
            
            this.pbrd = this.pbheader.cloneNode(false);
            this.pbrd.id = 'pbrd';
            
            this.pbar = document.createElement("div");
            this.pbar.setAttribute("id", 'pbar');
            this.pbar.style.width = '0';
            
            var iText = document.createTextNode(initText); // initial text to show
            this.pbheader.appendChild(iText);
            
            this.pbleft = document.createElement("span");
            this.pbright = this.pbleft.cloneNode(false);
            this.pbleft.id = 'pbleft';
            this.pbright.id = 'pbright';
            
            this.pbfooter.appendChild(this.pbleft);
            this.pbfooter.appendChild(this.pbright);
            
            this.pbrd.appendChild(this.pbar);
            
            this.pfrm.appendChild(this.pbheader);
            this.pfrm.appendChild(this.pbrd);
            this.pfrm.appendChild(this.pbfooter);
            
            rootDiv.appendChild(this.pfrm);
            
        },
        
        /**
         * This method will parse json object o,
         * calculate the value of %
         * generate text like Uploaded 1,232 of 5,984 bytes
         * Upload speed, time remaining
         * and update the style in progress bar
         * as well as text
         * if upload is done - this will be indicated in json object
         * then it will cancell this.oTimeout
         * otherwise it will call this.check() again
         * and the cycle repeats.
         *
         * Also IMPORTANT - this method must check to make sure this.prfm
         * already exists, otherwise it will run fMakeDivs to create
         * the initial divs for displaying progress bar.
         * @param {Object} o
         */
        update: function(json){
            var delay = iDelay;
            if (!totalBytes && json.progress.total) {
                totalBytes = json.progress.total;
            }
            /**
             * max number of checks is 100,
             * just in case... to prevent infinite loop
             */
            if (intRequestCount < 100) {
                intRequestCount += 1;
                
                if (json.progress === 'no') {
                    /**
                     * this means that uploadprogress_get_info
                     * is not available on the server.
                     * in this case it does not make sense
                     * to keep checking the server, instead
                     * should just display a generic
                     * 'progress' indicator
                     *
                     * @todo write function to display generic progress
                     *
                     */
                }
                else {
                    /**
                     * In case the 'done' is returned
                     * on the first 2 requests, we will try one more time
                     */
                    if ((json.progress != 'done') || intRequestCount < 3) {
                        if (json.progress != 'done') {
                            if (json.progress.left && (parseInt(json.progress.left, 10)) > 10 && (intRequestCount > 2)) {
                            
                                /**
                                 * delay will be not less than 4 seconds (4000 milliseconds)
                                 */
                                delay = Math.min(((json.progress.left / 6) * 1000), 4000);
                            }
                            
                            if (json.progress.message1) {
                                this.pbleft.innerHTML = json.progress.message1; //$LANG.dump(json); 
                            }
                            if (json.progress.message2) {
                                this.pbright.innerHTML = json.progress.message2;
                            }
                            if (json.bytes_uploaded) {
                            
                                /**
                                 * Need to calculate timeRemaining,
                                 * based on bytes_left and last speed
                                 */
                                this.cancelRun();
                                //timeLeft = ((parseInt(json.bytes_total, 10) - parseInt(json.bytes_uploaded, 10)) / parseInt(json.speed_average, 10));
                                timeLeft = ((json.bytes_total - json.bytes_uploaded) / json.speed_average);
                                timeLeft = Math.round(timeLeft * 1000) / 1000;
                                
                                curWidth = Math.ceil(width / 100 * json.progress.percent);
                                
                                this.run(timeLeft);
                                
                            }
                            
                        }
                        else {
                        
                            this.finishup(); // bad idea - makes the bar jump to 100% in case if has not initiated yet.
                        }
                        this.check(delay);
                    }
                    else {
                        /**
                         * If progress bar has not reached 100% yet,
                         * we should now manually move it to 100%
                         *
                         */
                        this.finishup();
                        //alert('all done: ' + json.progress + ' intRequestCount: ' + intRequestCount);
                    }
                } // end if json.progress != 'no'
            } // end if intRequestCount < 60
        },
        /**
         * Move the progress bar constantly
         * This methods should start moving the
         * progress bar from current position
         * to the 100% mark (width value)
         * In must calculate the necessary speed (numer of
         * milliseconds it takes to move by one pixel) based
         * on calculated distance (width - curPos) and time
         * in which it must complete the run (intSeconds)
         * @param {integer} intSeconds number of seconds
         * in which to complete the run
         *
         *
         */
        run: function(intSeconds){
            var speed;
            speed = Math.ceil(intSeconds / (width - aBuffer[0]) * 1000); // time it takes to move one step (in milliseconds)
            //alert('speed: ' + speed);
            //oSL.oFrm.interval = setInterval("oSL.oFrm.oMyForm.advance()", speed);
            interval = setInterval(this.advance, speed);
        },
        
        finishup: function(){
            this.cancelTimeout();
            this.cancelRun();
            if (!isDone) {
                this.pbar.style.width = width + 'px';
                this.pbheader.innerHTML = 'Done!';
                this.pbleft.innerHTML = 'Upload complete';
                this.pbright.innerHTML = 'Uploaded ' + totalBytes + '(100%)';
            }
            oSL.oFrm.elBtnSubmit.disabled = false;
            
        },
        
        markAsDone: function(){
            isDone = true;
        },
        
        setBar: function(percent){
            var barWidth = (parseInt(width) * parseInt(percent) / 100) + 'px';
            oSL.oFrm.oMyForm.pbar.style.width = barWidth;
        },
        
        advance: function(){
        
            var styleWidth = 0, curIndex;
            // alert('this is: ' + this); // object Window
            
            if (curWidth <= width) {
                /**
                 * logic:
                 * if aBuffer has 10 elements -
                 * pop one of the top and use it to set style
                 * then push curWidth to the end of array.
                 * else - just put the curWidth to aBuffer array
                 */
                //$('qfe').innerHTML = 'aBuffer length: ' + aBuffer.length + ' first: ' + aBuffer[0] + ' last: ' + aBuffer[(aBuffer.length - 1)];
                
                if (curWidth > aBuffer[0]) {
                    bReset = false;
                    if (curWidth < aBuffer[(aBuffer.length - 1)]) {
                        for (var i = 0; i < aBuffer.length; i += 1) {
                            if (aBuffer[i] === curWidth) {
                                curIndex = i;
                                break;
                            }
                        }
                        if (curIndex) {
                            aBuffer.splice(curIndex);
                            //$('qfe2').innerHTML = 'spliced. New length: ' + aBuffer.length;
                        }
                    }
                    
                    
                    if (aBuffer.length >= 15) {
                        styleWidth = aBuffer.shift() + 'px';
                        oSL.oFrm.oMyForm.pbar.style.width = styleWidth;
                    }
                    
                    aBuffer.push(curWidth);
                    curWidth += 1;
                    //$('qfe2').innerHTML = 'curWidth: ' + curWidth;
                }
                else {
                    /**
                     * bReset = true
                     * will cause the check to be done in one second,
                     * regardless...
                     */
                    bReset = true;
                }
                
            }
            else {
                oSL.oFrm.oMyForm.cancelRun();
            }
            
        },
        /**
         * This function will be called from the async request callback:success
         * and also initially from the onDomReady
         * It must make async request after this.timeout milliseconds
         * using this.sUrl
         */
        check: function(delay){
            //alert('check start ' + this.pfrm);
            delay = (delay && !bReset) ? delay : iDelay;
            if (!this.pfrm) {
                //alert('no pfrm yet');
                this.fMakeDivs();
            }
            
            oTimeout = setTimeout(makeRequest, delay);
        },
        
        cancelRun: function(){
            if (interval) {
                clearInterval(interval);
                interval = null;
            }
        },
        
        cancelTimeout: function(){
            if (oTimeout) {
                clearTimeout(oTimeout);
            }
            else {
                alert('no Timeout');
            }
        }
    }
    
} // end oUpForm()
oSL.parseForm = function(startRun, oForm, mustHaveFile){
    $Y.log('formJax 512 this: ' + this + ' startRun: ' + startRun); // oSL
    this.oFrm.uForm = $('uForm');
    //alert('442 ' + oSL.oFrm.uForm);
    /**
     * Dom element where to display upload progress bar
     */
    //this.oFrm.barDiv = $('pbar');
    sInitText = (!oSL.sInitText) ? 'Uploading' : oSL.sInitText; //oSL.sInitText
    sFiles = (!oSL.sFiles) ? 'numer of files' : oSL.sFiles;
    /**
     * Value of form hidden element UPLOAD_IDENTIFIER
     */
    var uploadId = '12345',    /**
     * Extra var to be added to POST request
     * @param {Object} e
     */
    sExtraParams = (startRun !== true) ? 'ajaxid=1&iframeid=1' : 'ajaxid=1&iframeid=1&hasuploadid=1', //
    /**
     * One form element
     * @param {Object} e
     */
    formElement,    /**
     * Function to change behaviour of form
     * @param {Object} e
     */
    hijaxForm,    /**
     * Form action (a url where to post the form)
     */
    fAction,    /**
     * Array of form elements
     */
    aEls,    /**
     * counter
     */
    i,    /**
     * Form has a file to be uploaded
     */
    hasFile = false,    /**
     * Form element Submit button
     */
    elBtnSubmit,    /**
     * Form input element
     * in case we need to create one for UPLOAD_IDENTIFIER
     * @param {Object} min
     * @param {Object} max
     */
    elUID,    /**
     * Random number generator
     * @param {Object} min
     * @param {Object} max
     */
    getRandomInt = function(min, max){
        return Math.floor(Math.random() * (max - min + 1)) + min;
    };
    
    if (this.oFrm.uForm) {
        fAction = this.oFrm.uForm.action;
        aEls = this.oFrm.uForm.elements
        $Y.log('formJax 582 aEls count ' + aEls.length + ' sExtraParams: ' + sExtraParams);
        
        for (i = 0; i < aEls.length; i++) {
            if (aEls[i] && aEls[i].getAttribute && (aEls[i].getAttribute('type') === 'submit')) {
                this.oFrm.elBtnSubmit = aEls[i];
            }
        }
        
        /**
         * this method is called on click to form 'submit' button
         *
         * @param {Object} e
         */
        hijaxForm = function(e){
            var aFileInputs = [], barDiv, elNewTr, elNewTd, elNewTd2, numFiles = 0;
            oSL.aTrs = [];
            //alert('597 this is ' + this + ' e is ' + e);
            $Y.log('formJax.js 597 this: ' + this + ' uploadId: ' + uploadId + ' e: ' + e, "warn"); // ok, uploadId worked 12345
            if (e) {
                $E.preventDefault(e);
            }
            if (oSL.blogPage && oSL.blogPage.editor) {
                $Y.log('formJax 580');
                oSL.blogPage.editor.saveHTML();
                $Y.log(' formJax 584 mbody value: ' + oSL.oFrm.uForm.elements['mbody'].value);
            }
            if (oSL.oFrm.elBtnSubmit) {
                oSL.oFrm.elBtnSubmit.disabled = true;
            }
            
            for (i = 0; i < aEls.length; i++) {
                if (aEls[i] && aEls[i].getAttribute && (aEls[i].getAttribute('type') === 'file')) {
                    aFileInputs.push(aEls[i]);
                    oSL.aTrs.push($D.getAncestorByTagName(aEls[i], 'tr'));
                    if (aEls[i].value !== '') {
                        //alert('we have a file');
                        hasFile = true;
                        numFiles += 1;
                    }
                }
            }
            
            
            if ((mustHaveFile === true) && (hasFile !== true)) {
                alert('Must have at least one file to upload');
                oSL.oFrm.elBtnSubmit.disabled = false;
                return true;
            }
            
            /**
             * Check for UPLOAD_IDENTIFIER id
             * If the form does not have this field we can add it dynamically
             * with javascript right now
             * this field MUST be in the form BEFORE the first file element,
             * so we inserting it as the first element in the form
             * just to be sure
             */
            if (!aEls['UPLOAD_IDENTIFIER'] || aEls['UPLOAD_IDENTIFIER'] === '') {
            
                uploadId = getRandomInt(1000000, 9000000) + '.' + getRandomInt(1000000, 9000000);
                elUID = document.createElement("input");
                elUID.setAttribute('type', 'hidden');
                elUID.setAttribute('name', 'UPLOAD_IDENTIFIER');
                elUID.setAttribute('value', uploadId);
                
                $D.insertBefore(elUID, oSL.oFrm.uForm.firstChild);
                
            }
            else {
                uploadId = aEls['UPLOAD_IDENTIFIER'].value;
                $Y.log('formJax 619 uploadId: ' + uploadId);
            }
            
            /**
             * If hasFile then we also launch
             * upload progress monitor
             */
            /**
             * This form will be submitted again,
             * this time by YUI Connection manager,
             * so we need to prevent default behaviour again.
             * @param {Object} e
             */
            $E.addListener(oSL.oFrm.uForm, "submit", function(e){
                $E.preventDefault(e);
            });
            
            $CONN.setForm(oSL.oFrm.uForm, true);
            
            oSL.oFrm.uplObj = $CONN.asyncRequest('POST', fAction, oSL.oFrm.fUploadCallback, sExtraParams);
            
            
            $Y.log('formJax 649 fileInputs count: ' + aFileInputs.length, "error");
            
            /**
             * If this form has both - at least one file being uploaded
             * and uploadId was present in form
             * as well as barDiv element,
             * then we should start the upload progress monitor
             */
            if (hasFile && uploadId) {
                if (oSL.oMy && oSL.oMy.toggleNewAlbum) {
                    oSL.oMy.toggleNewAlbum(true); // this will collapse 'add new album' form fields
                }
                $D.setStyle(oSL.aTrs, 'visibility', 'collapse');
                $D.setStyle(oSL.aTrs, 'display', 'none');
                elNewTr = document.createElement('tr');
                elNewTd = document.createElement('td');
                elNewTd2 = document.createElement('td');
                
                barDiv = document.createElement('div');
                barDiv.id = 'progressBar';
                elNewTd2.appendChild(barDiv);
                elNewTr.appendChild(elNewTd);
                elNewTr.appendChild(elNewTd2);
                
                $D.insertBefore(elNewTr, oSL.aTrs[0]);
                
                oSL.oFrm.oMyForm = oSL.oUpForm(barDiv, '/progress.php?up=' + uploadId, null, sInitText + ' (' + sFiles + ': ' + numFiles + ')'); // oSL.oFrm.barDiv
                /**
                 * wait 1/2 second before starting to check progress
                 * to give enough time for upload_progress extension to initialize
                 * otherwise the progress bar will jump to 'Done' immediately
                 */
                oSL.oFrm.oMyForm.check(700);
            }
        }
        
        /**
         * The only way it works in Chrome is that
         * we subscribe to onClick on submit button
         * and NOT to form onSubmit
         */
        if (startRun === true) {
            $Y.log('formJax 685 this: ' + this + ' form: ' + this.oFrm.uForm, "warn"); // object oSL           
            hijaxForm();
        }
        else {
            $E.addListener(this.oFrm.elBtnSubmit, "click", hijaxForm);
        }
        
    }
    else {
        // alert('Unable to find form with id "oSL.oFrm.uForm"');
    }
    
};


/*


 $E.onDOMReady(function(){


 oSL.parseForm();


 


 });


 */


