/*
 * @author Nourdine - <www.nourdine.net>
 * @copyright Nourdine 2005-2009
 * @license GPL

      ~ NouFw ~ 
       q(-_-)p
       '_) (_'
       /__/  \
     _(<_   / )_
    (__\_\_|_/__)
  miniminiframework

*/


/* ### VERSION ### */
var nouFw = {
   author: "Fabio Testolin AKA Fabs AKA Nourdine",
   license: "GPL",
   version: "1.0"
};


/* ### DOM ### */ 
nouFw.get = function (id) {
   return document.getElementById(id);
};

nouFw.getByClass = function (str, tag) {
   var els = [];
   var re = new RegExp('(?:^|\\s+)' + str + '(?:\\s+|$)');
   var tagN = tag || "*";
   var domEls = document.getElementsByTagName(tagN.toUpperCase());
   var i;
   for (i = 0; i < domEls.length; i++) {
      if (re.test(domEls[i].className)) {
         els.push(domEls[i]);
      }
   }
   return els;
}


/* ### EVENTS ### */
nouFw.addEvent = (function () {
   if (typeof window.addEventListener !== "undefined") {
      return function (el, type, fun) {
         el.addEventListener(type, fun, false);  
      };
   }
   else if (typeof window.attachEvent !== "undefined") {
      return function (el, type, fun) {
         var f = function () {
            fun.call(el); 
         }
         el.attachEvent('on' + type, f);
      };
   }
   else {}
})();
 

/* ### ANIMATION ### */ 
nouFw.anim = (function () {

   var setStyle = function (el, prop, v, u) {
      if (prop !== "opacity") {
         el.style[prop] = v + u;
      }
      else {
         // moz
         el.style.opacity = v;
         // IE shit
         el.style.filter = "alpha(opacity=" + Math.round(v * 100) + ")"; 
      }
   };

   return function (config, callBack) {

      // when the whole thing start
      var beginning = new Date().getTime();

      // it,s the core of the whole thing!
      var K = 1 / config.totTime;

      // we store the timeout here
      var timer;

      var elem = nouFw.get(config.id);
      var cssProp = config.cssProp;
      var start = config.vals[0];
      var stop = config.vals[1];
      var totalDisplacement = stop - start;
      // lenght of the animation
      var totTime = config.totTime;
      // unit of measurement
      var uom = config.uom;
      var every = (function (frm) {
         return 1000 / frm;
      })(65); // feed it with the number of photograms you want top be shot per second
      // callback shit
      var f = callBack;

      return function () {
         var elapsed = new Date().getTime() - beginning;
         // console.log("elapsed time : " + elapsed);
         var ratio = Math.sqrt((elapsed * K)); // (elapsed * K) always between 0 and 1 !!!
         if (ratio < 1) {
            // var currentVal = Math.round((ratio * totalDisplacement) + start);
            var currentVal = (ratio * totalDisplacement) + start;
            // console.log("current value (normal step) : " + currentVal);
            setStyle(elem, cssProp, currentVal, uom);
            timer = window.setTimeout(arguments.callee, every);
         }
         else {
            // last step! passo il valore finale settato dall'utente
            // console.log("current value (last step) : " + stop)
            setStyle(elem, cssProp, stop, uom);
            if (typeof f === "function") {
               f.call(elem);
            }   
            timer = null;
         }
      };     
   };
})();


/* ### AJAX ### 

var config = {
   server: "stuff.php",
   method: "GET",
   onLoading: function () {},
   onSuccess: function () {},
   onFailure: function () {}
}
*/

nouFw.Ajax = (function () {

   function getXHR() {
      var XHR;
      if (window.XMLHttpRequest) {
         return new XMLHttpRequest();
      } 
      else if (window.ActiveXObject) {
         return new ActiveXObject("Msxml2.XMLHTTP");
         if (!XHR) {
            return new ActiveXObject("Microsoft.XMLHTTP");
         }
      }
      else {
         alert("Your browser does not support AJAX!");
      }
   }

   return function (config) {
      
      var XHR = getXHR();
      
      // private stuff - unpacking the config object
      var server     = config.server;
      var method     = config.method.toLowerCase();
      var onLoading  = config.onLoading; // onloading
      var onSuccess  = config.onSuccess; // response delivered && success [XHR.status == 200]
      var onFailure  = config.onFailure; // response delivered && failure [XHR.status !== 200]
      
      // if onloading then onloading :)
      if (config.onLoading) { config.onLoading(); };

      // check mandatory arguments 
      if (!server) {
         throw new Error("The server-side application URI is missing!");
      }
      if (!method || (method !== "post" && method !== "get")) {
         throw new Error("Please specify a valid method for the Ajax request!");
      }
      if (!onSuccess) {
         throw new Error("Please specify the function to be used as a callback when data have been received succesfully!");
      }

      // associa la callBack definita dall'utente al gestore di eventi
      // onreadystatechange passando alla funzione 2 parametri:
      // - la responseText
      // - la responseXML
      // l'utente sappia che i primi due parametri che passa alla funzione
      // sono proprio queste due proprieta' dell'oggetto XMLHttpRequest!
      XHR.onreadystatechange = function () {
         if (XHR.readyState === 4) {          // # complete #
            if (XHR.status === 200) {         // # success #  
               onSuccess(XHR.responseText, XHR.responseXML);
            }
            else {                            // # not success AKA failure #
               if (onFailure) {
                  onFailure(XHR.status);
               }
               else {
                  window.alert("Problems connecting to the server! Status = " + XHR.status);
               }
            }
         }
      }

      // metodo pubblico per la spedizione dei dati
      this.send = function (querySting) {
         // IE caching problem
         var random = "&random=" + (new Date()).getTime(); 
         // apre la connessione e spedisce i dati in get o post
         if (method === "get") {
            XHR.open("get", server + "&" + querySting + random, true);
            XHR.send(null);
            // infine chiude la connessione
            // TODO la devo chiudere o no?
         }
         else {
            XHR.open("post", server, true);
            XHR.setRequestHeader("content-type", "application/x-www-form-urlencoded");
            XHR.setRequestHeader("connection", "close"); // <<< buggy in IE
            XHR.send(querySting + random);
         }
      }
   } // end of return
   
})();


/* ### FORMS ### */
nouFw.stringify = function (id) {
   // inputs of the form
   var inputs = nouFw.get(id).elements;
   // initialize output
   var str = "";
   var i;
   for (i = 0; i < inputs.length; i++) {
      switch (inputs[i].type) {
         case 'text':
         case 'select-one':
         case 'hidden':
         case 'reset':
         case 'button':
         case 'submit':
         case 'password':
         case 'textarea':
            if (i !== 0 && str !== '') {
               str += "&";
            }
            str += inputs[i].name + "=" + encodeURIComponent(inputs[i].value);
            break;
         case 'checkbox':
            // se e' checked ne aggiungo il nome/valore
            // se no niente!
            if (inputs[i].checked == true) {
               if (i !== 0) {
                  str += "&";
               }
               str += inputs[i].name + "=" + encodeURIComponent(inputs[i].value);
            }
            break;
         case 'radio':
            if (inputs[i].checked == true) {
               if (i !== 0) {
                  str += "&";
               }               
               str += inputs[i].name + "=" + encodeURIComponent(inputs[i].value);
            }
            break;
         default:
            // does nothing
            break;
      }
   }
   return str;
};