/**
 * Copyright (c) 2007 Hoang Hac Solutions Team. All rights reserved.
 *
 * The copyright to the computer software herein is the property of
 * Hoang Hac Solutions Team. The software may be used and/or copied only
 * with the written permission of Hoang Hac Solutions Team. or in accordance
 * with the terms and conditions stipulated in the agreement/contract
 * under which the software has been supplied.
 *
 * @author: Vien Nguyen [vien.ly.hhac@gmail.com]
 */
function getAbsolutePosition(element) {
  if (element.getBoundingClientRect) {
    var rect = element.getBoundingClientRect();
    return {x: rect.left, y: rect.top };
  } else if (element.ownerDocument.getBoxObjectFor) {
    var box = element.ownerDocument.getBoxObjectFor(element);
    var pos = { x: box.x, y: box.y };
    //mozilla bug#186229
    for (var parent = element; parent && parent != document.body &&
        parent != document.documentElement; parent = parent.parentNode) {
      if (parent.scrollLeft) pos.x -= parent.scrollLeft;
      if (parent.scrollTop) pos.y -= parent.scrollTop;
    }
    return pos;
  } else {
    var x = 0;
    var y = 0;
    var parent = element;
    for (var parent = element; parent; parent = parent.offsetParent) {
      x += parent.offsetLeft;
      y += parent.offsetTop;
      var edge = opwv.Util.getEdgeSize(parent);
      x += edge.left;
      y += edge.top;
    }
    for (var parent = element; parent && parent != document.body &&
        parent != document.documentElement; parent = parent.parentNode) {
      if (parent.scrollLeft) x -= parent.scrollLeft;
      if (parent.scrollTop) y -= parent.scrollTop;
    }
    return {x: x, y: y};
  }
};

/**
 * Strip tags from the specified text before decoding.
 *
 * @param text the text to be stripped then decoded
 * @return the resulting string
 */
function stripAndDecodeHTML(text) {
  var stripped = stripTags(text);
  return unescapeHTML(stripped);
};

/**
 * Decodes the specified string, replacing characters:
 * <ul>
 * <li> &lt; => '<' </li>
 * <li> &gt; => '>' </li>
 * <li> &amp; => '&' </li>
 * <li> &nbsp; => ' ' </li>
 * <li> &quot; => '"' </li>
 * </ui>
 *
 * @param text the text to be decoded
 * @return the resulting string
 */
function unescapeHTML(text) {
  if (!text || text.length == 0) return text;
  var callback = function(ignore, str) {
    str = str.toLowerCase();
    if (str == "lt") return "<";
    if (str == "gt") return ">";
    if (str == "amp") return "&";
    if (str == "nbsp") return " ";
    if (str == "quot") return '"';
    return String.fromCharCode(str.substr(1));
  };
  return text.replace(
      /&(lt|gt|amp|nbsp|quot|#[A-Za-z0-9]+);/gi, callback);
};

/**
 * HTML enocoding function
 *
 * @param text String to be encoded
 * @return string encoded text 
 */
function encodeHTML (text) {
  if (!text || text.length == 0) return text;
  return text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
};
/**
 *  Convert text to html
 * @param text String to be converted
 * @return HTML text
 * */
function convertToHtml(text) {
  if (!text || text.length == 0) {
    return "";
  }
  return text.replace(/[\r]?\n/g, '<br>').replace(/ /g, '&nbsp;');
};

/**
 * Convert HTML to text
 * @paam html HTML to be converted
 * @return text
 * */
function convertToText (html) {
  if (!html || html.length == 0) {
    return "";
  }
  var text = html.replace(/<br[\/]?>/ig, '\n')
      .replace(/<div>/ig, '\n')
      .replace(/<p>/ig, '\n\n');
  returnstripAndDecodeHTML(text);
};

function stripTags(text, replace) {
  if (!text || text.length == 0) return text;
  return text.replace(/<\/?[^>]+>/gi, replace ? replace : "");
};

/**
 * This function takes a string representation of a size and returns an integer
 * form of the size.  For example, "1MB" would return 1048576 (1024*1024).
 * @param size a string that indicates the desired size
 * @return an integer representing the size, in bytes
 */
function getSizeFromString(size) {
  size = trim(size);
  var result = parseInt(size);
  var suffix = trim(size.substring(("" + result).length));
  suffix = suffix.toUpperCase();
  switch (suffix) {
    case "B":
      break;
    case "KB":
      result = result * 1024;
      break;
    case "MB":
      result = result * 1024 * 1024;
      break;
    case "GB":
      result = result * 1024 * 1024 * 1024;
      break;
    case "TB":
      result = result * 1024 * 1024 * 1024 * 1024;
      break;
  }
  return (result);
};

function trim (text) {
  if (!text || text.length == 0) return text;
  return text.replace(/^\s+|\s+$/g, "");
};
  
function cloneArray (array) {
  return Array.apply(null, array);
};

function mapToString (map) {
  var array = new Array();
  var value;
  var str;
  for (var key in map) {
    value = map[key];
    if (value instanceof Function) {
      // Skip methods
    } else {
      array.push(key + "=" + map[key]);
    }
  }
  return array.join("\n");
};


function getWindowSize(w) {
  if (w.innerWidth && w.innerHeight) {
    // Safari - while Safari supports document.body.clientHeight and
    // document.documentElement.clientHeight, the results of the call is
    // always "2" for Safari 2.0.4
    return { w: w.innerWidth, h: w.innerHeight };
  } else if (w.document.documentElement.clientWidth &&
      w.document.documentElement.clientHeight) {
    return { w: w.document.documentElement.clientWidth,
        h: w.document.documentElement.clientHeight };
  } else if (w.document.body.clientWidth &&
      w.document.body.clientHeight) {
    return { w: w.document.body.clientWidth,
        h: w.document.body.clientHeight };
  }
  return { w: 0, h: 0 };
};

function getWindowPosition (w) {
  if (w.screenLeft != undefined && w.screenTop != undefined) {
    return { x: w.screenLeft, y: w.screenTop };
  } else if (w.screenX != undefined && w.screenY != undefined) {
    return { x: w.screenX, y: w.screenY };  
  }
  return { x: 0, y: 0 };
};

function getScreenSize () {
  if(screen.width && screen.height) {
    return { x: screen.width, y: screen.height };
  }
  return { x: 0, y: 0 };
};



function moveToCenter (win, element, w, h) {
  var size = opwv.Util.getWindowSize(win);
  var width = Math.min(w, size.w);
  var height = Math.min(h, size.h);
  element.style.width = width + "px";
  element.style.height = height + "px";
  element.style.left = (size.w - width) / 2 + "px";
  element.style.top = (size.h - height) / 2 + "px"; 
};



function addClassName (element, className) {
  removeClassName(element, className);
  element.className += " " + className;
};

function removeClassName (element, className) {
  var newClassName = "";
  var classes = element.className.split(" ");
  for (var i = 0; i < classes.length; i++) {
    if (classes[i] != className) {
      if (i > 0) newClassName += " ";
      newClassName += classes[i];
    }
  }
  element.className = newClassName;
};

function hasClassName (element, className) {
  var classes = element.className.split(" ");
  for (var i = 0; i < classes.length; i++) {
    if (classes[i] == className) return true;
  }
  return false;
};

function hide (element) {
  element.style.display = "none";
};

function isHidden (element) {
  if (element.style.display == undefined) {
    // Safari - unless explicitly defined in CSS, HTML, or javascript, styles
    // are undefined (Safari 2.0.4)
    return (false);
  }
  return element.style.display.toLowerCase() == "none";
};

function show (element) {
  element.style.display = "";
};

function remove (element) {
  if (element && element.parentNode) {
    element.parentNode.removeChild(element);
  }
};

function isLeftClick (event) {
  return (event.which && event.which == 1) ||
      (event.button && (event.button == 1));
};

/**
 * Get the pressed button from an event
 *
 * @param event  Event object
 * @return boolean true if right button is pressed
 */
function isRightClick (event) {
  return (event.which == 2 || event.button == 2);
};

function getEventSource (event) {
  return event.target || event.srcElement;
};


function roundCorner(element) {
  element.style.position = "relative";
  for (var i = 0; i < 4; i++) {
    var div = element.ownerDocument.createElement("div");
    addClassName(div, "corner");
    div.style.position = "absolute";
    div.style.overflow = "hidden";
    div.style.height = (i == 3 ? 2 : 1) + "px";
    div.style.width = (i == 0 ? 5 : 4 - i) + "px";
    div.style.top = i + "px";
    div.style.left = "0px";
    element.appendChild(div);
    var div = div.cloneNode(false);
    div.style.left = "auto";
    div.style.right = "0px";
    element.appendChild(div);
  }
};



function replaceSelectedString (element, string) {
  if (element.ownerDocument.selection) {
    element.focus();
    var range = element.ownerDocument.selection.createRange();
    range.text = string;
    range.collapse(false);
  } else if (element.selectionStart != undefined &&
      element.selectionEnd !=  undefined) {
    var pos = element.selectionStart;
    element.value = element.value.substring(0, element.selectionStart) +
      string + element.value.substring(element.selectionEnd);
    element.selectionStart = element.selectionEnd = pos+string.length;
  }
};


/**
 * Sets the cursor position of the specified textarea.
 *
 * @param textarea the textarea
 * @param pos the position to set, measured in characters; the cursor
 * will be set after the specified character position
 */
function setCursorPosition (textarea, pos) {
  if (textarea.setSelectionRange) {
    // For Firefox
    textarea.setSelectionRange(pos, pos);
  } else if (textarea.createTextRange) {
    // For IE
    var range = textarea.createTextRange();
    range.collapse(true);
    range.moveStart('character', pos);
    range.moveEnd('character', pos);
    range.select();
  }
};



/**
 * Returns the first value of the specified cookie.  If the cookie does not exist,
 * null is returned.
 * 
 * Note: It is apparently possible to have multiple cookies of the same name.
 *
 * @param cookieName the name of the desired cookie
 * @return the cookie value or null
 */
function getCookie (cookieName) {
  var regex = new RegExp("(?:; )?" + cookieName + "=([^;]*);?");
  if (regex.test(document.cookie)) {
    return (decodeURIComponent(RegExp["$1"]));
  } else {
    return (null);
  }
};

/**
 * Returns the (array of) values of the specified cookie. If the cookie does not exist,
 * null is returned.
 * 
 * Note: It is apparently possible to have multiple cookies of the same name.
 * 
 * @param cookieName the name of the desired cookie
 * @return array of cookie values or null
 */
function getCookies (cookieName){
  var regex = new RegExp("(?:; )?" + cookieName + "=([^;]*);?");
  var cookieValues = regex.exec(document.cookie);
  if (null != cookieValues) {
    for (var i = 0; i < cookieValues.length; i++) {
      cookieValues[i] = decodeURIComponent(cookieValues[i]);
    }
  }
  return cookieValues;
};


/**
 * Returns true if the browser has built in XPath support, false otherwise.
 */
function hasNativeXPathSupport (xml) {
  var result = false;
  // An override to make debugging easier.  This override will enable the
  // Google XPath/XSLT library for all browsers
  if (window.overrideNativeXPath) {
    return (result);
  }
  if (!xml) {
    if (document.implementation &&
        document.implementation.createDocument) {
      xml = document.implementation.createDocument("", "", null);
    }
  }
  if (window.ActiveXObject) {
    result = true;
  } else if (xml.evaluate) {
    result = true;
  }
  return (result);
};


/**
 * Is a string null or empty?
 *
 * @param str String to test
 * @param trimStr Boolean whether trim the string before testing
 * @return true/false
 */
function isStringNullOrEmpty (str, trimStr) {
  var isNOE = !str;
  if (!isNOE) {
    if (trimStr) {
      str = this.trim(str);
    }
    isNOE = (str.length == 0);
  }
  return isNOE;
};

/**
 * Is an array null or empty?
 *
 * @param arr Array to test
 * @return true/false
 */
function isArrayNullOrEmpty (arr) {
  var isNOE = !arr;
  if (!isNOE) {
    isNOE = (arr.length == 0);
  }
  return isNOE;
};


/**
 * Function Equivalent to java.net.URLDecoder.decode(String, "UTF-8")
 * JavaScript's decodeURIComponent has not compatibility with Java's
 * URDecoder.
 */
function decodeURL (str) {
  var s0, i, j, s, ss, u, n, f;
  s0 = "";    // decoded str
  for (i = 0; i < str.length; i++) { // scan the source str
    s = str.charAt(i);
    if (s == "+") {
      s0 += " ";  // "+" should be changed to SP
    } else {
      if (s != "%") {
        s0 += s;  // add an unescaped char
      } else {    // escape sequence decoding
        u = 0;    // unicode of the character
        f = 1;    // escape flag, zero means end of this sequence
        while (true) {
          ss = "";        // local str to parse as int
          for (j = 0; j < 2; j++ ) {  // get two maximum hex characters for parse
            sss = str.charAt(++i);
            if (((sss >= "0") && (sss <= "9")) || 
               ((sss >= "a") && (sss <= "f"))  ||
               ((sss >= "A") && (sss <= "F"))) {
              ss += sss;      // if hex, add the hex character
            } else {
              --i;
              break;    // not a hex char., exit the loop
            }
          }
          n = parseInt(ss, 16); // parse the hex str as byte
          if (n <= 0x7f) {
            u = n;
            f = 1;   // single byte format
          }
          if ((n >= 0xc0) && (n <= 0xdf)) {
            u = n & 0x1f;
            f = 2;   // double byte format
          }
          if ((n >= 0xe0) && (n <= 0xef)) {
            u = n & 0x0f;
            f = 3;   // triple byte format
          }
          if ((n >= 0xf0) && (n <= 0xf7)) {
            u = n & 0x07;
            f = 4;   // quaternary byte format (extended)
          }
          if ((n >= 0x80) && (n <= 0xbf)) {
            u = (u << 6) + (n & 0x3f);
            --f;  // not a first, shift and add 6 lower bits
          }
          if (f <= 1) {
            break;  // end of the utf byte sequence
          }
          if (str.charAt(i + 1) == "%") {
            i++;          // test for the next shift byte
          } else {
            break; // abnormal, format error
          }
        }
        s0 += String.fromCharCode(u); // add the escaped character
      }
    }
  }
  return s0;
};

/**
 * Number Only
 */
function numbersonly(e, decimal) {
    var key;
    var keychar;

    if (window.event) {
       key = window.event.keyCode;
    }
    else if (e) {
       key = e.which;
    }
    else {
       return true;
    }
    keychar = String.fromCharCode(key);

    if ((key==null) || (key==0) || (key==8) ||  (key==9) || (key==13) || (key==27) ) {
       return true;
    }
    else if ((("0123456789").indexOf(keychar) > -1)) {
       return true;
    }
    else if (decimal && (keychar == ".")) { 
      return true;
    }
    else
       return false;
};
