﻿/**
*
*  uno.xml.loader.js v 0.0.4.0  (Part of [uno-js].)
*
*  Released by Hideki Yamamoto - LGPL equiv.
*
**/

if(!uno){alert('uno.xml.loader.js requires uno.js');}
try{Namespace.register("uno.xml");uno.xml = {};}catch(ex){};
////////////////////////////CROSSWBROWSER XML PARSE////////////////////////////////
uno.xml.parse = function(xmlstring){
    var xmlDoc = false;
    try{var xmlParser = new DOMParser();xmlDoc = xmlParser.parseFromString(xmlstring, "text/xml");}catch(errr){
    try{xmlDoc= new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async=false;
        xmlDoc.loadXML(xmlstring);}catch(err){uno.throwerror('There was an error parsing the xml string or the browser do not support xml parsing.\n'+err.message);
}   }return xmlDoc;};
///////////////////////CROSBROWSER SYNCRONOUS XML LOAD////////////////////////////////
uno.xml.syncload = function(url) {
    var xmlDoc = false;
    //Chrome, safari
    if (is_chrome || is_safari) {
        var page_request = new XMLHttpRequest();
        //get page synchronously 
        page_request.open('GET', url, false);
        page_request.send(null);
        return page_request.responseXML;
    } else {
        //Internet Explorer
        try { xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); } catch (exxx) {
            //Firefox, Mozilla, Opera, etc.
            try { xmlDoc = document.implementation.createDocument("", "", null); } catch (exx) {
                uno.throwerror('This browser have a problem creating a new xml document using the w3c way[document.implementation.createDocument("", "", null)]\n' + exx.message);
        }   }
        try { xmlDoc.async = false; xmlDoc.load(url); } catch (ex) { uno.throwerror('There was an error invoking a [xmlDoc.async = false;xmlDoc.load(url)] : \n' + ex.message); }
        return xmlDoc;
}   };
////////////////////////////CROSSBROWSER ASYNCRONOUS XML LOAD////////////////////////////////
uno.xml.asyncload = function(url, onstep, onfinish, onerrorfinish){
    var idx = uno.xml._asyncjobs.length;
    uno.xml._asyncjobs[idx] = new uno.xml._asyncjob(url, onstep, onfinish, onerrorfinish);
    uno.xml._processasyncget(idx);};
uno.xml.asyncloadpost = function(url,elm,onstep,onfinish,onerrorfinish){
    var idx = uno.xml._asyncjobs.length;
    uno.xml._asyncjobs[idx] = new uno.xml._asyncjob(url,onstep,onfinish,onerrorfinish);
    uno.xml._processasyncpost(idx,elm);};
uno.xml.asyncloadframe = function(url,elm,onstart,onfinish){
    if (!uno.upload){alert('uno.xml.asyncloadframe(url,elm_or_elmid,onfinish) requires uno.upload.js');}
    var frameid = uno.upload.form(url,elm,onstart,uno.xml._postprocessasyncframe);
    var idx = uno.xml._framefinishes.length;
    uno.xml._framefinishes[idx] = new uno.xml._framefinish(frameid, onfinish);};

/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////PRIVATE IMPLEMENTATION DETAILS//////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////PRE AND POST PROCESSES///////////////////////////////
uno.xml._processasyncget = function(idx){
    uno.xml._asyncjobs[idx].req = uno.xml._createxmlreq();
    uno.xml._asyncjobs[idx].req.onreadystatechange = function(){eval('uno.xml._postprocessasync(' + idx + ')');};
    uno.xml._asyncjobs[idx].req.open("GET", uno.xml._asyncjobs[idx].url, true);
    uno.xml._asyncjobs[idx].req.send('');};
uno.xml._processasyncpost = function(idx,elm_or_elmid) {
    uno.xml._asyncjobs[idx].req = uno.xml._createxmlreq();
    uno.xml._asyncjobs[idx].req.onreadystatechange = function() { eval('uno.xml._postprocessasync(' + idx + ')'); };
    uno.xml._asyncjobs[idx].req.open("POST", uno.xml._asyncjobs[idx].url, true);
    uno.xml._asyncjobs[idx].req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    uno.xml._asyncjobs[idx].req.send(uno.xml._serialize($(elm_or_elmid)));};
uno.xml._postprocessasyncframe = function(frameid,doc){
    var idx = uno.xml._asyncjobs.length;
    uno.xml._asyncjobs[idx] = new uno.xml._asyncjob('', false, uno.xml._getframefinish(frameid), false);
    uno.xml._asyncjobs[idx].req = new uno.xml._fakerq(uno.unhtmlentities(doc.body.innerHTML));
    uno.xml._postprocessasync(idx);};
uno.xml._postprocessasync = function(idx) {
    if (uno.xml._asyncjobs[idx].req.readyState == 4) {// only if req shows "loaded"
        if (uno.xml._asyncjobs[idx].req.status == 200) {// only if "OK"
            if (uno.xml._asyncjobs[idx].processed == false) {
                uno.xml._asyncjobs[idx].processed = true;
                //If the response do not contain a Header["Content-Type" = "text/xml;charset=UTF-8"]
                //req.contentText will be available but req.responseXML will not be parsed.
                //Workaround:[manual parsing, encapsulating a fake request class for readonly javascript properties]:
                //if ((uno.xml._asyncjobs[idx].req.responseXML == null)||(uno.xml._asyncjobs[idx].req.responseXML.decumentElement == null)) {
                try {
                    var text = uno.xml._asyncjobs[idx].req.responseText;
                     delete uno.xml._asyncjobs[idx].req;
                     uno.xml._asyncjobs[idx].req = new uno.xml._fakerq(text);
                 } catch (ex) { uno.throwerror('Error executing a workaround(No text/xml Content-Type header in loaded xml response.)' + '\n' + ex.message) }
                 //}//end of workaround
                 if (uno.debug) { alert(uno.xml._asyncjobs[idx].req.responseText); }
                 uno.xml._invoker(uno.xml._asyncjobs[idx].onfinish, uno.xml._asyncjobs[idx].req, 'onfinish', 'Terminating the XMLHttpRequest Async Job correctly, invoking the onfinish handler', uno.xml._asyncjobs[idx].url);
        }   } else {// only if NOT "OK"
                var s2 = uno.xml._asyncjobs[idx].req.responseText;
                if (uno.debug) { alert(s); }
                if (uno.xml._asyncjobs[idx].onerrorfinish) { uno.xml._invokerstatus(uno.xml._asyncjobs[idx].onerrorfinish, uno.xml._asyncjobs[idx].req, 'onerrorfinish', 'Terminating the XMLHttpRequest Async Job WITH ERRORS, invoking the onerrorfinish handler'); }
                else if (uno.xml._asyncjobs[idx].onfinish) { uno.xml._invoker(uno.xml._asyncjobs[idx].onfinish, uno.xml._asyncjobs[idx].req, 'onfinish', 'Terminating the XMLHttpRequest Async Job with errors, invoking the onfinish handler because the onerrorfinish handler is not available', uno.xml._asyncjobs[idx].url); }
                else { uno.throwerror('Terminating the XMLHttpRequest Async Job for the url ' + uno.xml._asyncjobs[idx].url + ' with an error : \n' + uno.xml._asyncjobs[idx].req.status); }
    }   } else {// only if req do not show "loaded"
        uno.xml._invokerstatus(uno.xml._asyncjobs[idx].onstep, uno.xml._asyncjobs[idx].req, 'onstep', 'Stepping the XMLHttpRequest Async Job , invoking the onstep handler');
}   };
/////////////////////////FAKE CLASS FOR MISSING HEADER AND FRAME PARSING/////////////////////
uno.xml._fakerq = function(xmlstring){this.readyState = 4;this.status = 200;this.statusText = 'OK';this.responseText = xmlstring;try{this.responseXML = uno.xml.parse(xmlstring);}catch(ex){this.responseXML=null;}};
/////////////////////////////////MEMORY STRUCTURE FOR ASYC JOBS////////////////////////////
uno.xml._asyncjobs = new Array();
uno.xml._asyncjob = function(_url, _onstep, _onfinish, _onerrorfinish){
    this.processed = false;this.req = false;this.url = _url;
    this.onstep = _onstep;this.onfinish = _onfinish;this.onerrorfinish = _onerrorfinish;};
//////////////////////////////MORE MEMORY STRUCTURE FOR FRAME JOBS/////////////////////////    
uno.xml._framefinishes = new Array();
uno.xml._framefinish = function(_frameid,_onfinish){
    this.frameid = _frameid;
    this.onfinish = _onfinish;};
uno.xml._getframefinish = function(frameid){
    for(var i=0;i<uno.xml._framefinishes.length;i++){
        if(uno.xml._framefinishes[i].frameid == frameid){return uno.xml._framefinishes[i].onfinish;}
    }return false;};
//////////////////////////////////////////MISCELLANEOUS///////////////////////////////
uno.xml._createxmlreq = function(){
    var newreq = false;
    if(window.XMLHttpRequest && !(window.ActiveXObject)){
        try {newreq = new XMLHttpRequest();}
        catch(ex){newreq = false;}
    }else if(window.ActiveXObject){
   	    try {newreq = new ActiveXObject("Msxml2.XMLHTTP");}
   	    catch(ex){
   	        try {newreq = new ActiveXObject("Microsoft.XMLHTTP");}
       	    catch(ex){newreq = false;
    }   }   }
    if(!newreq){uno.throwerror('This browser is neither w3c or mozilla compatible*[2008], uno.xml javascript framework will not work.');}
    return newreq;
};
uno.xml._collect = function(a,f){
    var n=[];
    for(var i=0;i<a.length;i++){var v=f(a[i]);if(v!=null){n.push(v);}}
    return n;};
uno.xml._serialize = function(f){
    var g=function(n){return f.getElementsByTagName(n)};
    var nv=function(e){if(e.name)return encodeURIComponent(e.name)+'='+encodeURIComponent(e.value);else return ''};
    var c1=function(i){if((i.type!='radio'&&i.type!='checkbox')||i.checked)return nv(i)};
    var i=uno.xml._collect(g('input'),c1);var s=uno.xml._collect(g('select'),nv);var t=uno.xml._collect(g('textarea'),nv);
    return i.concat(s).concat(t).join('&');};
uno.xml._invoker = function(func,req,hname,errorsituation,url){
 if(func){
  try{func(req);}catch(exxxx){
   try{func(req.responseXML);}catch(exxx){
    try{func(req.contentText);}catch(exx){
     try{func();}catch(ex){
      var msg = 'Situation:' + errorsituation + '\n';
      msg = msg + 'The handler '+hname+' could not be invoked without errors in any of the following ways.Set it to false to not have it executed.\n';
      msg = uno.xml_builderrorline(msg,hname+'(xmlrequest)',exxxx);
      msg = uno.xml_builderrorline(msg,hname+'(xmlrequest.responseXML)',exxx);
      msg = uno.xml_builderrorline(msg,hname+'(xmlrequest.contentText)',exx);
      msg = uno.xml_builderrorline(msg,hname+'()',ex);
      uno.throwerror(msg);
}}}}}};
uno.xml._invokerstatus = function(func,req,hname,errorsituation){
 if(func){
  try{func(req);}catch(exxxy){
   try{func(req.statusText);}catch(exx){
    try{func();}catch(ex){
     var msg = 'Situation:' + errorsituation + '\n';
     msg = msg + 'The handler '+hname+' could not be invoked without errors in any of the following ways.Set it to false to not have it executed.\n';
     msg = uno.xml_builderrorline(msg,hname+'(xmlrequest)',exxxy);
     msg = uno.xml_builderrorline(msg,hname+'(xmlrequest.statusText)',exx);
     msg = uno.xml_builderrorline(msg,hname+'()',ex);
     uno.throwerror(msg);
}}}}};
uno.xml_builderrorline = function(msg,hname,ex){return msg + '\n- ' + hname + ';\n  error was : ' + ex.message + '.';}
