/*
  MTK (Müzso Toolkit) v0.5, 2006-05-08
  Copyright (c) 2006, Trilobita Informatics Co. (müzso)
  http://www.trilobita.hu/
  http://muzso.hu/
  
  MTK is licensed under the LGPL (or GNU Lesser General Public License) v2.1.
  
  Inspired by:
    
    1. The Dojo Toolkit.
       http://dojotoolkit.org/
    
    2. Steve's Custom Alert Demonstration
       steve@slayeroffice.com
       http://slayeroffice.com/
  
  Tested with browsers:
    - IE 5.5
    - IE 6.0
    - Firefox 1.5
  
  Tested with formats:
    - HTML 4.01 Transitional/Strict
    - XHTML 1.0 Transitional/Strict
  
  TODO: graceful degradation on unsupported browser versions.
*/

var mtk = {};

mtk.browser = {};
mtk.browser.opera = navigator.userAgent.indexOf ("Opera") >= 0;
mtk.browser.khtml = (navigator.appVersion.indexOf("Konqueror") >= 0)
  || (navigator.appVersion.indexOf("Safari") >= 0)
;
mtk.browser.safari = navigator.appVersion.indexOf("Safari") >= 0;
var geckoPos = navigator.userAgent.indexOf("Gecko");
mtk.browser.mozilla = mtk.browser.moz = (geckoPos >= 0) && (!mtk.browser.khtml);
if (mtk.browser.mozilla) {
  // gecko version is YYYYMMDD
  mtk.browser.geckoVersion = navigator.userAgent.substring(geckoPos + 6, geckoPos + 14);
}
mtk.browser.ie = (document.all) && (!mtk.browser.opera);
mtk.browser.ie50 = mtk.browser.ie && navigator.appVersion.indexOf("MSIE 5.0") >= 0;
mtk.browser.ie55 = mtk.browser.ie && navigator.appVersion.indexOf("MSIE 5.5") >= 0;
mtk.browser.ie60 = mtk.browser.ie && navigator.appVersion.indexOf("MSIE 6.0") >= 0;

mtk.addOnLoad = function (func) {
  var useargs = true;
  var _func1;
  if (typeof func == "string") {
    if (typeof window[func] == "function") {
      _func1 = window[func];
    } else {
      _func1 = function () {
        eval(func);
      }
      useargs = false;
    }
  } else {
    _func1 = func;
  }
  if (typeof _func1 == "function") {
    var _func2;
    if (arguments.length = 1 || !useargs) {
      _func2 = _func1;
    } else {
      var args = [];
      for (var i = 0; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      _func2 = function () {
        _func1.apply(window, args);
      }
    }
    if (typeof window.onload != "function") {
      window.onload = _func2;
    }
    else {
      var oldOnload = window.onload;
      window.onload = function () {
        oldOnload();
        _func2();
      }
    }
  }
}

mtk.addOnUnload = function (func) {
  var useargs = true;
  var _func1;
  if (typeof func == "string") {
    if (typeof window[func] == "function") {
      _func1 = window[func];
    } else {
      _func1 = function () {
        eval(func);
      }
      useargs = false;
    }
  } else {
    _func1 = func;
  }
  if (typeof _func1 == "function") {
    var _func2;
    if (arguments.length = 1 || !useargs) {
      _func2 = _func1;
    } else {
      var args = [];
      for (var i = 0; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      _func2 = function () {
        _func1.apply(window, args);
      }
    }
    if (typeof window.onunload != "function") {
      window.onunload = _func2;
    }
    else {
      var oldOnUnload = window.onunload;
      window.onunload = function () {
        oldOnUnload();
        _func2();
      }
    }
  }
}

mtk.addOnClick = function (node, func, thisObj) {
  if (node && (typeof func == "function" || typeof func == "string")) {
    var _thisObj;
    var _func1;
    var useargs = true;
    if (arguments.length <= 2) {
      _thisObj = node;
    } else {
      _thisObj = thisObj;
    }
    if (typeof func == "string") {
      if (typeof _thisObj[func] == "function") {
        _func1 = _thisObj[func];
      } else {
        _func1 = function () {
          eval(func);
        }
        useargs = false;
      }
    } else {
      _func1 = func;
    }
    if (typeof _func1 == "function") {
      var _func2;
      if (arguments.length <= 3 || !useargs) {
        _func2 = function () {
          _func1.apply(_thisObj);
        }
      } else {
        var args = [];
        for (var i = 3; i < arguments.length; i++) {
          args.push(arguments[i]);
        }
        _func2 = function () {
          _func1.apply(_thisObj, args);
        }
      }

      if (typeof node.onclick != "function") {
        node.onclick = _func2;
      }
      else {
        var oldOnClick = node.onclick;
        node.onclick = function () {
          oldOnClick();
          _func2();
        }
      }
    }
  }
}

mtk.exists = function (obj, name) {
  var p = name.split(".");
  for (var i = 0; i < p.length; i++) {
    if (!(obj[p[i]]))
      return false;
    obj = obj[p[i]];
  }
  return true;
}

mtk.body = function () {
  return document.body || document.getElementsByTagName("body")[0];
}

mtk.getViewportWidth = function () {
  var w = 0;

  if (window.innerWidth) {
    w = window.innerWidth;
  }

  if (mtk.exists(document, "documentElement.clientWidth")) {
    // IE6 Strict
    var w2 = document.documentElement.clientWidth;
    // this lets us account for scrollbars
    if (!w || w2 && w2 < w) {
      w = w2;
    }
    return w;
  }

  if (document.body) {
    // IE
    return document.body.clientWidth;
  }

  return 0;
}

mtk.getViewportHeight = function () {
  if (window.innerHeight) {
    return window.innerHeight;
  }

  if (mtk.exists(document, "documentElement.clientHeight")) {
    // IE6 Strict
    return document.documentElement.clientHeight;
  }

  if (document.body) {
    // IE
    return document.body.clientHeight;
  }

  return 0;
}

mtk.getViewportSize = function () {
  var ret = [mtk.getViewportWidth(), mtk.getViewportHeight()];
  ret.w = ret[0];
  ret.h = ret[1];

  return ret;
}

mtk.getScrollOffset = function () {
  var ret = [0, 0];

  if (window.pageYOffset) {
    ret = [window.pageXOffset, window.pageYOffset];
  } else if (mtk.exists(document, "documentElement.scrollTop")) {
    ret = [document.documentElement.scrollLeft, document.documentElement.scrollTop];
  } else if (document.body) {
    ret = [document.body.scrollLeft, document.body.scrollTop];
  }

  ret.x = ret[0];
  ret.y = ret[1];

  return ret;
}

mtk.moveToCenter = function (node) {
  var scroll_offset = mtk.getScrollOffset();
  var viewport_size = mtk.getViewportSize();
  var w = node.offsetWidth;
  var h = node.offsetHeight;

  var x = scroll_offset[0] + (viewport_size[0] - w) / 2;
  var y = scroll_offset[1] + (viewport_size[1] - h) / 2;

  with (node.style) {
    position = "absolute";
    left = x + "px";
    top = y + "px";
  }
}

/* float between 0.0 (transparent) and 1.0 (opaque) */
mtk.setOpacity = function (node, opacity, dontFixOpacity) {
  if (!dontFixOpacity) {
    if (opacity >= 1.0) {
      if (mtk.borwser.ie) {
        mtk.clearOpacity(node);
        return;
      }
      else {
        opacity = 0.999999;
      }
    }
    else if (opacity < 0.0) {
      opacity = 0;
    }
  }
  if (mtk.browser.ie) {
    if (node.nodeName.toLowerCase() == "tr") {
      // FIXME: is this too naive? will we get more than we want?
      var tds = node.getElementsByTagName("td");
      for (var x = 0; x < tds.length; x++) {
        tds[x].style.filter = "Alpha(Opacity=" + opacity * 100 + ")";
      }
    }
    node.style.filter = "Alpha(Opacity=" + opacity * 100 + ")";
  }
  else if(mtk.borwser.moz) {
    node.style.opacity = opacity; // ffox 1.0 directly supports "opacity"
    node.style.MozOpacity = opacity;
  }
  else if(mtk.browser.safari) {
    node.style.opacity = opacity; // 1.3 directly supports "opacity"
    node.style.KhtmlOpacity = opacity;
  }
  else {
    node.style.opacity = opacity;
  }
}

mtk.getOpacity = function (node) {
  if (mtk.browser.ie) {
    var opac = (
        node.filters
        && node.filters.alpha
        && typeof node.filters.alpha.opacity == "number"
      ? node.filters.alpha.opacity : 100) / 100
    ;
  }
  else {
    var opac = node.style.opacity
      || node.style.MozOpacity
      || node.style.KhtmlOpacity
      || 1
    ;
  }
  return (opac >= 0.999999 ? 1.0 : Number(opac));
}

mtk.clearOpacity = function (node) {
  if (mtk.browser.ie) {
    if (node.filters && node.filters.alpha) {
      node.style.filter = ""; // FIXME: may get rid of other filter effects
    }
  }
  else if (mtk.browser.moz) {
    node.style.opacity = 1;
    node.style.MozOpacity = 1;
  }
  else if (mtk.browser.safari) {
    node.style.opacity = 1;
    node.style.KhtmlOpacity = 1;
  }
  else {
    node.style.opacity = 1;
  }
}

mtk.dialog = {
  // "mc" stands for "modal controller"
  mc: null,
  bgiframe: null
};

mtk.dialog.byId = function(id) {
  var d = document;
  var e = d.getElementById(id);
  var b = mtk.body();

  if (!(e && e.nodeName && e.nodeName.toLowerCase() == "div")) {
    // if parameter is not a DIV node, then return
    return;
  }

  with(e.style) {
    display = "none";
    position = "absolute";
    zIndex = 999;
  }

  b.appendChild(e);

  if (!this.mc) {
    this.mc = d.createElement("div");
    with (this.mc.style) {
      display = "none";
      position = "absolute";
      left = top = "0px";
      zIndex = 998;
      backgroundColor = "transparent";
      if (mtk.browser.ie) {
        backgroundImage = "url('x.png')";
      }
      /*
        The "background-image" style attribute is required only by IE to
        prevent actions on lower z-index elements. However the image does not
        have to exist, it works with an url pointing to a non-existent image,
        too.
      */
    }
    this.mc.id = "modalContainer";
    b.appendChild(this.mc);
    
    // In IE we need an iframe to cover possible form elements that are on the page
    // and under the dialog's layer. Otherwise these form-elements would be visible
    // even through the div layer.
    // Important!
    // If your site is served over SSL (a "https://" url), then adding an iframe
    // with an "about:blank" src attribute would trigger a warning window in IE
    // to appear each time you load a new page.
    // The warning would have the following message:
    // "This page contains both secure and nonsecure items. Do you want to display
    //  the nonsecure items?"
    // However IE does not pop up this warning if we load a non-existant url
    // to the iframe (at least IE6 did not complain). So we use the same "x.png"
    // here as before for the backgroundImage hack.
    // IE sux. :-(
    if (mtk.browser.ie && !this.bgiframe) {
      this.bgiframe = d.createElement("<iframe frameborder='0' src='x.png'>");
      with (this.bgiframe.style) {
        display = "none";
        position = "absolute";
        left = top = "0px";
      }
      this.bgiframe.style.zIndex = this.mc.style.zIndex;
      mtk.setOpacity(this.bgiframe, 0.0);
      b.appendChild(this.bgiframe);
    }
  }

  e.show = function() {
    var h = document.documentElement.scrollHeight || mtk.body().scrollHeight;
    var w = mtk.getViewportWidth();
    mtk.dialog.mc.style.width = w + "px";
    mtk.dialog.mc.style.height = h + "px";
    mtk.dialog.mc.style.display = "block";
    this.style.display = "block";
    mtk.moveToCenter(this);
    if (mtk.browser.ie) {
      mtk.dialog.bgiframe.style.left = this.style.left;
      mtk.dialog.bgiframe.style.top = this.style.top;
      mtk.dialog.bgiframe.style.width = this.offsetWidth + "px";
      mtk.dialog.bgiframe.style.height = this.offsetHeight + "px";
      mtk.dialog.bgiframe.style.display = "block";
    }
  }
  e.hide = function() {
    this.style.display = "none";
    mtk.dialog.mc.style.display = "none";
    if (mtk.browser.ie) {
      mtk.dialog.bgiframe.style.display = "none";
    }
  }
  e.setCloseControl = function(node, func) {
    node.onclick = null;
    mtk.addOnClick(node, this.hide, this);
    if (typeof func == "function" || typeof func == "string") {
      var args = [node, func, node];
      if (arguments.length > 2) {
        for (var i = 2; i < arguments.length; i++) {
          args.push(arguments[i]);
        }
      }
      mtk.addOnClick.apply(node, args);
    }
  }
  return e;
}

mtk.xmlhttp = {};
mtk.xmlhttp.msxmls = ['MSXML5', 'MSXML4', 'MSXML3', 'MSXML2', 'Microsoft'];

mtk.xmlhttp.getXMLHttpRequest = function () {
  var http = null;
  if (typeof XMLHttpRequest != "undefined") {
    try {
      http = new XMLHttpRequest();
    }
    catch (e) { }
  }
  if (!http) {
    if (typeof ActiveXObject != "undefined") {
      for (var i = 0; i < mtk.xmlhttp.msxmls.length; i++) {
        var progid = mtk.xmlhttp.msxmls[i];
        try {
          return new ActiveXObject(progid + '.XMLHTTP');
        }
        catch (e) { }
        if (http) {
          mtk.xmlhttp.msxmls = [progid];
          break;
        }
      }
      throw new Error("No XML component installed!");
    }
  }
  
  return http;
}

/**
 * Creates an HTTP GET request and sends the response to the callback function.
 *
 * Note:
 *  - Dynamic arguments in the URI should be escaped with encodeURIComponent().
 *  - The uri must be in the same "domain" as we are, even if it's absolute.
 */
mtk.xmlhttp.httpGet = function (uri, callbackFunction, callbackParameter) {
  var xmlHttp = this.getXMLHttpRequest();
  var bAsync = true;
  if (!callbackFunction) {
    bAsync = false;
  }
  xmlHttp.open("GET", uri, bAsync);
  xmlHttp.send(null);

  if (bAsync) {
    if (typeof callbackFunction == "function") {
      xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState == 4) {
          callbackFunction(xmlHttp.responseText, xmlHttp, callbackParameter);
        }
      }
    }
    return xmlHttp;
  }
  else {
    return xmlHttp.responseText;
  }
}

/**
 * Creates an HTTP POST request and sends the response to the callback function.
 *
 * Note: passing null or undefined for 'object' makes the request fail in Opera 8.
 *       Pass an empty string instead.
 */
mtk.xmlhttp.httpPost = function (uri, object, callbackFunction, callbackParameter) {
  var xmlHttp = this.getXMLHttpRequest();
  var bAsync = true;
  if (!callbackFunction) {
    bAsync = false;
  }
  xmlHttp.open("POST", uri, bAsync);

  var toSend = "";
  if (typeof object == "object") {
    xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    for (var i in object) {
      toSend += (toSend ? "&" : "") + encodeURIComponent(i) + "=" + encodeURIComponent(object[i]);
    }
  }
  else {
    toSend = object;
  }
  xmlHttp.send(toSend);

  if (bAsync) {
    if (typeof callbackFunction == "function") {
      xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState == 4) {
          callbackFunction(xmlHttp.responseText, xmlHttp, callbackParameter);
        }
      }
    }
    return xmlHttp;
  }
  else {
    return xmlHttp.responseText;
  }
}

