/* IBE Common-always-loaded utilities. */
function clearField(f) {
  if (f.value == f.defaultValue) {
    f.value = "";
  }
}
function checkField(f) {
  if (f.value == "") {
    f.value = f.defaultValue;
  }
}

function getObj(id) {
  if (id == undefined) return null;
  var obj = null;
  if (document.getElementById) {
    obj = document.getElementById(id);
  } else if (document.all) {
    obj = document.all[id];
  }
  return obj;
}

function getObjsByName(id) {
  if (id == undefined) return null;
  return document.getElementsByName(id);
}

function getObjByName(id) {
  if (id == undefined) return null;
  var e = document.getElementsByName(id);
  if (e.length > 0)  return e[0];
  return null;
}

function getObjByIdThenName(id) {
  var e = getObj(id);
  if (e == null) e = getObjByName(id);
  return e;
}

function getEnabledObjByName(id) {
  if (id == undefined) return null;
  var es = document.getElementsByName(id);
  for (var i = 0; i < es.length; i++) {
    var e = es[i];
    if (!e.disabled) return e;
  }
  return null;
}

function getEnabledObjById(id) {
  if (id == undefined) return null;
  var e = document.getElementById(id);
  if (!e.disabled) return e;
  return null;
}

function toggleLayer(whichLayer, show) {
  if (document.getElementById) {
    var obj = getObj(whichLayer);
    if (obj) obj.style.display = show ? "" : "none";
  }
}

function toggleId(id) {
  if (document.getElementById) {
    var obj = getObj(id);
    var show = obj.style.display == "none";
    if (obj) obj.style.display = show ? "" : "none";
  }
}

function activate(id, isActive) {
  var obj = getObj(id);
  if (obj != null) {
    obj.readOnly = !isActive;
    obj.disabled = !isActive;
  }
}

function replaceHtml(e, html) {
  var obj = getObj(e);
  if (!obj) return;
  obj.innerHTML = html;
}

function showHide(e, show, setDisplay) {
  if (show) setVisible(e, setDisplay);
  else setHidden(e, setDisplay);
  return getObj(e);
}

function toggleVisible(elementId) {
  var obj = getObj(elementId);
  if (obj) {
    var s = obj.style;
    if (s.display == '' || s.display == 'visible') {
      setHidden(elementId, true);
    } else {
      setVisible(elementId, true);
    }
  }
}

function setVisible(elementID, setDisplay) {
  // If second arg is true then set style.display to apropriate value depending on type
  var obj = getObj(elementID);
  if (obj != null) {
    if (setDisplay)
      obj.style.display = '';
    obj.style.visibility = 'visible';
  }
}

function setVisibleObj(obj, setDisplay) {
  // If second arg is true then set style.display to apropriate value depending on type
  if (obj != null) {
    if (setDisplay)
      obj.style.display = '';
    obj.style.visibility = 'visible';
  }
}

function setHidden(elementID, setDisplay) {
  // If second arg is true then set style.display to 'none'
  var obj = getObj(elementID);
  if (obj != null) {
    obj.style.visibility = 'hidden';
    if (setDisplay)
      obj.style.display = 'none';
  }
}

function setHiddenObj(obj, setDisplay) {
  // If second arg is true then set style.display to 'none'
  if (obj != null) {
    obj.style.visibility = 'hidden';
    if (setDisplay)
      obj.style.display = 'none';
  }
}

function displayFor(e) {
  var tn = e.tagName.toUpperCase();
  var t = 'block';
  if (tn == 'TR')t = 'table-row';
  if (tn == 'TD')t = 'table-cell';
  if (tn == 'TABLE')t = 'table';
  return t;
}
function winStat(s) {
  window.status = s;
  return true;
}
function omo(e, isOver, cssClass) {
  var cl = e.className;
  if (isOver) {
    e.style.cursor = 'pointer';
    if (cssClass) e.className = (cl ? cl : '') + '___xxx ' + cssClass;
  } else {
    e.style.cursor = 'default';
    if (cssClass) e.className = cl.replace('___xxx ' + cssClass, '');
  }
}

function getPosition(o) {
  var start = getSelectionStart(o);
  if (start == getSelectionEnd(o)) {
    return start;
  } else {
    return -1;
  }
}

function setPosition(o, p) {
  if (o.createTextRange) {
    var r = document.selection.createRange();
    r.moveStart('character', -o.value.length);
    r.moveStart('character', p);
    r.moveEnd('character', 0);
    r.select();
  } else {
    o.selectionStart = p;
    o.selectionEnd = p;
  }
}

function getSelectionStart(o) {
  if (o.createTextRange) {
    var r = document.selection.createRange().duplicate();
    r.moveEnd('character', o.value.length);
    if (r.text == '') {
      return o.value.length;
    }
    return o.value.lastIndexOf(r.text);
  } else {
    return o.selectionStart;
  }
}

function getSelectionEnd(o) {
  if (o.createTextRange) {
    var r = document.selection.createRange().duplicate();
    r.moveStart('character', -o.value.length);
    return r.text.length;
  } else {
    return o.selectionEnd;
  }
}
function airlineWinOpen(doc) {
  var w = window.open(doc, 'CarrierPromo', 'scrollbars=no,resizable=no,height=' + IBE.CarrierPromoHeight + ',width=' + IBE.CarrierPromoWidth);
  if (w) w.focus();
}

function openPopupWindow(url) {
  var a = arguments;
  var h = a.length > 1 ? a[1] : 600;
  var v = a.length > 2 ? a[2] : 500;
  if (url.indexOf(':') == -1 && url.indexOf('?') == -1) url += ':popup';
  var w = window.open(url, 'PopupWindow', 'scrollbars=yes,resizable=yes,height=' + h + ',width=' + v);
  if (w) w.focus();
}

function openNewBrowserWindow(url) {
  window.open(url);
}

function goToUrl(url) {
  document.location.href = url
}

/*****************Globals****************/
var ckpaste_currentText = '';//initualizes the text of the text area.
var ckpaste_elem = null;//this will be the textarea.
var ckpaste_pasteMsg = 'Cannot paste into this field';
/****************************************/

/****************************************************************************
 void ckpaste_preventPaste();
 initializes the copy paste monitor.

 ****************************************************************************/

function ckpaste_preventPaste(elem, msg) {
  ckpaste_elem = elem;

  if (msg) {
    ckpaste_pasteMsg = msg
  } else if (msg === false) {
    ckpaste_pasteMsg = msg;
  }

  ckpaste_currentText = ckpaste_elem.defaultValue;
  if (document.all) {//it it is ie do the onpaste function
    ckpaste_elem.onpaste = ckpaste_showMessage;
    ckpaste_elem.oncontextmenu = ckpaste_showMessage;
    ckpaste_elem.onkeyup = ckpaste_checkText;
    ckpaste_elem.onblur = ckpaste_checkText;
    ckpaste_elem.onchange = ckpaste_checkText;
  } else {
    ckpaste_elem.addEventListener("keyup", ckpaste_checkText, true);
    ckpaste_elem.addEventListener("blur", ckpaste_checkText, true);
    ckpaste_elem.addEventListener("change", ckpaste_checkText, true);
  }
}

/****************************************************************************
 void ckpaste_preventPaste()
 checks the length of the string in the textbox and compares it with
 the length of the string in the saved ckpaste_currentText string. If the
 text box text is 10 characters longer than the saved string then it
 assumes that they have pasted.  it puts the current string back into
 the textarea over what they pasted and then shows them the message.
 if it isn't longer then it just puts the text into the saved text.

 ****************************************************************************/

function ckpaste_checkText(event) {
  event = event || window.event; // window.event for IE
  if (ckpaste_elem && event && event.keyCode) {
    var newTextLength = ckpaste_elem.value.length;//gets length of the textarea right now.
    var ckpaste_currentTextLength = ckpaste_currentText.length;//gets length of the saved text from the textarea
    //    if (newTextLength > (1 + ckpaste_currentTextLength)) {
    //      alert('event.keyCode: ' + event.keyCode + ', newTextLength: ' + newTextLength + ", ckpaste_currentTextLength: " + ckpaste_currentTextLength);
    //    }
    var codeForSelectingFromPrevList = 13;
    if (newTextLength > (ckpaste_currentTextLength + 10) && //is the new more then 10 characters longer?
        event.keyCode != codeForSelectingFromPrevList) {
      ckpaste_elem.value = ckpaste_currentText;//put the saved text back in/
      ckpaste_showMessage();//tell them they cannot paste.
    } else {
      ckpaste_currentText = ckpaste_elem.value;//if it is ok then save the text.
    }
  }
}
/****************************************************************************
 void ckpaste_showMessage();
 if they calling function wants to show a message when they paste then
 the message is alerted.
 ****************************************************************************/

function ckpaste_showMessage() {
  if (ckpaste_pasteMsg !== false) {
    alert(ckpaste_pasteMsg);
    return false;
  }
  return true;
}

function validEmail(f) {
  return f && f.length > 4; // Fusk
}
function submitNewsMail(f) {
  var nl = f.CRM_EMAIL;
  if (nl.defaultValue != nl.value && validEmail(nl.value)) {
    f.submit();
  } else {
    alert(UiText.get("Javascript.Util.Email"));
    nl.focus();
    nl.select();
  }
  return false;
}

function clickLink(link) {
  if (!link.nodeName) {
    link = getObj(link);
  }

  if (link.nodeName == 'a' || link.nodeName == 'A') {
    if (!link.onclick || link.onclick()) {
      var target = link.target ? link.target : '_self';
      window.open(link.href, target, '');
    }
    return false;
  }

  return true;
}

function findChildById(root, id) {
  if (nullOrUndefined(root)) return document.getElementById(id);
  else {
    ibeerror("Function not yet implemented.");
  }
}

function findChildrenByName(root, name) {
  if (nullOrUndefined(root)) return document.getElementsByName(name);
  else {
    var list = new Array();
    ibeerror("Function not yet implemented.");
  }
}

function getFieldName(elementId) {
  var d = getObjByIdThenName(elementId);
  if (d != null) return d.name;
  return '';
}

function getFieldValue(elementId, form) {
  var d = findChildById(form, elementId);
  if (d == null || d.type == 'radio') {
    var es = findChildrenByName(form, elementId);
    if (es != null) {
      if (es.length == 1) {
        var e = es[0];
        return e.value;
      } else {
        for (var i = 0; i < es.length; i++) {
          var r = es.item(i);
          if (r.checked) return r.value;
        }
      }
    }
  } else if (d.type == 'checkbox') {
    return field.checked;
  } else {
    return d.value;
  }
  return '';
}

function getValueFromFieldObject(field) {
  if (field == null || field.type == 'radio') {
    var es = getFieldsFromForm(field.form, field.name);
    if (es != null) {
      if (es.length == 1) {
        var e = es[0];
        return e.value;
      } else {
        for (var i = 0; i < es.length; i++) {
          var r = es.item(i);
          if (r.checked) return r.value;
        }
      }
    }
  } else if (field.type == 'checkbox') {
    return field.checked;
  } else {
    return field.value;
  }
  return '';
}

function stringToBool(s) {
  return s == "true";
}

function doInnerHTML(elementId, html, mode) {
  if (mode == 'append') {
    appendToInnerHTML(elementId, html);
  } else {
    setInnerHTML(elementId, html);
  }
}

function doElementsInnerHTML(element, html, mode) {
  if (mode == 'append') {
    appendToElementsInnerHTML(element, html);
  } else {
    setElementsInnerHTML(element, html);
  }
}

function setInnerHTML(elementID, html) {
  var e = getObj(elementID);
  if (e != null && propertyExists(e.innerHTML)) {
    e.innerHTML = html;
  }
}

function setElementsInnerHTML(e, html) {
  if (e != null && propertyExists(e.innerHTML)) {
    e.innerHTML = html;
  }
}

function appendToInnerHTML(elementId, html) {
  var e = getObj(elementId);
  if (e != null && propertyExists(e.innerHTML)) {
    e.innerHTML = e.innerHTML + html;
  }
}

function appendToElementsInnerHTML(e, html) {
  if (e != null && propertyExists(e.innerHTML)) {
    e.innerHTML = e.innerHTML + html;
  }
}

function getInnerHTML(elementId) {
  var e = getObj(elementId);
  if (e != null && propertyExists(e.innerHTML)) {
    return e.innerHTML;
  }
  return '';
}

function hasInnerHTML(elementId) {
  var e = getObj(elementId);
  if (e != null && propertyExists(e.innerHTML)) {
    return notEmptyString(trimString(e.innerHTML));
  }
  return false;
}

function clearInnerHTML(elementId) {
  setInnerHTML(elementId, '');
}

function notEmptyString(s) {
  return !emptyString(s);
}

function emptyString(s) {
  return s == null || s == "";
}

function trimString(s) {
  return s.replace(/^\s*/, "").replace(/\s*$/, "");
}

function setSrc(id, src) {
  var e = getObj(id);
  if (e != null && propertyExists(e.src)) {
    e.src = src;
  }
}

function propertyExists(property) {
  return typeof(property) !== 'undefined';
}

/**
 * Finds first parent element of type type. Searches recursively upwards the tree.
 * @param type The type to search for.
 * @param fromObj The object whos parent we examine.
 */
function findParentElementOfType(type, fromObj) {
  if (fromObj == null || fromObj == undefined) return null;
  if (fromObj.parentNode == null || fromObj.parentNode == undefined) return null;
  if (fromObj.parentNode.tagName == type) return fromObj.parentNode;
  return findParentElementOfType(type, fromObj.parentNode);
}

function removeAllTrFromTd(e) {
  do {
    var tdes = e.getElementsByTagName('td');
    if (tdes.length < 1) return;
    var tde = tdes[0];
    tde.parentNode.removeChild(tde);
  } while (tdes.length > 0)
}

/**
 * Checks if javascript function exists, returns true if that is the case.
 * @param funcName
 */
function functionExists(funcName) {
  return typeof funcName == 'string' && eval('typeof ' + funcName) == 'function';
}

function stringIsNumeric(s) {
  var validChars = "0123456789.,";
  return stringIncludesValidCharsOnly(s, validChars);
}

function stringIsInteger(s) {
  var validChars = "0123456789";
  return stringIncludesValidCharsOnly(s, validChars);
}

function stringIsPhoneNumber(s) {
  var validChars = "0123456789+-() ";
  return stringIncludesValidCharsOnly(s, validChars);
}

function stringIsDigitsAndDash(s) {
  var validChars = "0123456789-";
  return stringIncludesValidCharsOnly(s, validChars);
}

function stringIncludesValidCharsOnly(s, validChars) {
  if (s === undefined || s === null) return true;
  for (var i = 0; i < s.length; i++) {
    var c = s.charAt(i);
    if (validChars.indexOf(c) == -1) return false;
  }
  return true;
}

/**
 * Logs a string, if id is set, appends it to the element with that id. If not it checks if console.log is available
 * and uses that. If not, see if element with id 'console' is available. If not, alert is used.
 * @param s The string to be logged.
 * @param id The id of the element.
 */
function ibelog(s, id) {
  if (isProdEnvironment()) return;
  var e = getObj('console');
  if (getObj(id) != null) appendToInnerHTML(id, s + '<br>\n');
  else if (typeof console == 'object' && typeof console.log == 'function') console.log(s);
  else if (e != null) appendToInnerHTML('console', s + '<br>\n');
  else alert(s); // Do not allow alert in production environment.
}

/**
 * Logs a warning message to console. Should not output anything if in production!
 * @param s The string to be logged.
 */
function ibewarning(s) {
  if (isProdEnvironment()) return;
  if (typeof console == 'object' && typeof console.warning == 'function') {
    console.warning(s);
  } else {
    ibelog('Warning: ' + s);
  }
}

/**
 * Logs an error message to console. Should not output anything if in production!
 * @param s The string to be logged.
 */
function ibeerror(s) {
  if (isProdEnvironment()) return;
  if (typeof console == 'object' && typeof console.error == 'function') {
    console.error(s);
  } else {
    ibelog('Error: ' + s);
  }
}

/**
 * Checks to see if we are in debug environment, that is, NOT in production environment.
 */
function isDebugEnvironment() {
  return IBE.debug;
}

/**
 * Checks to see if we are in debug environment, that is, NOT in production environment.
 */
function isProdEnvironment() {
  return IBE.environment === 'prod';
}

function nlToBr(s) {
  var tmp = undefined;
  var limit = 1000;
  while (limit > 0) {
    tmp = s.replace('\n', '<br>');
    if (tmp == s) break;
    s = tmp;
    limit--;
  }
  return tmp;
}
/**
 * Prints all properties for an object.
 * @param o
 */
function printAll(o) {
  ibelog(printAllToString(o));
}

function printArray(a) {
  ibelog('Array[' + a.length + '] =');
  for (var i = 0; i < a.length; i++) {
    var v = a[i];
    ibelog('  [' + i + '] =>');
    ibelog(v);
  }
}

function printAllToString(o) {
  var r = new String();
  r += '-- All variables in Object of type ' + o.getObjectTypeName() + ' --\n';
  for (var prop in o) {
    if (typeof prop !== 'string') r += prop + ' (' + typeof prop + ') =' + o[prop] + '\n';
  }
  r += '----\n';
  return r;
}

function getObjectsProperties(o) {
  var l = [];
  var i = 0;
  for (var p in o) {
    l[i++] = p;
  }
  return l;
}

function enableId(id) {
  var e = getObj(id);
  if (e) e.disabled = false;
}

function disableId(id) {
  var e = getObj(id);
  if (e) e.disabled = true;
}

function autoCompleteOff(f) {
  f.setAttribute("autocomplete", "off");
}

function setElementsClass(id, className) {
  var e = getObj(id);
  if (e != null && propertyExists(e.className)) {
    e.className = className;
  }
}

function disableSelection(element) {
  if (typeof element.onselectstart != "undefined") //IE
    element.onselectstart = function() {
      return false;
    };
  else if (typeof element.style.MozUserSelect != "undefined") //Firefox
    element.style.MozUserSelect = "none";
  else //Others
    element.onmousedown = function() {
      return false;
    };
}

function useDefault(value, defaultValue) {
  if (value === undefined || value === null) {
    return defaultValue;
  } else {
    return value;
  }
}

function trim(str) {
  return str.replace(/^\s*|\s*$/g, "");
}

function implode(list, separator) {
  var r = '';
  var isFirst = true;
  for (var i = 0; i < list.length; i++) {
    if (isFirst === true || separator === undefined) {
      isFirst = false;
    } else {
      r = r + separator;
    }
    r = r + list[i];
  }
  return r;
}

function removeListHead(list) {
  var nl = new Array();
  for (var i = 1; i < list.length; i++) {
    nl[i - 1] = list[i];
  }
  return nl;
}

/**
 * Same as split, but for lists. For example.
 * 0: "mattias is"
 * 1: "awesome"
 * separator: " "
 * will result in
 * 0: "mattias"
 * 1: "is"
 * 2: "awesome"
 * @param list
 * @param separator
 */
function splitList(list, separator) {
  var nlist = new Array();
  for (var i = 0; i < list.length; i++) {
    var l = list[i].split(separator);
    for (var j = 0; j < l.length; j++) {
      nlist[nlist.length] = l[j];
    }
  }
  return nlist;
}

function startsWith(str, v) {
  return str.substring(0, v.length) == v;
}

function endsWith(str, v) {
  return str.substring(v.length - 1, v.length) == v;
}

String.prototype.trim = function() {
  return (this.replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, ""));
};

String.prototype.startsWith = function(str) {
  return (this.match("^" + str) == str);
};

String.prototype.endsWith = function(str) {
  return (this.match(str + "$") == str);
};

function subList(list, startIndex, length) {
  var rlist = new Array();
  var endIndex = startIndex + length;
  if (length < 0) endIndex = list.length - 1;
  for (var i = startIndex; i < endIndex; i++) {
    rlist[rlist.length] = list[i];
  }

  return rlist;
}

function nullOrUndefined(s) {
  var r = s === null || s === undefined;
  return r;
}

function nonFalse(s) {
  return s === undefined || s;
}

function nonTrue(s) {
  return !(s === undefined || !s);
}

Array.prototype.inArray = function (value) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == value) {
      return true;
    }
  }
  return false;
};

Array.prototype.indexInArray = function (value) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] == value) {
      return i;
    }
  }
  return -1;
};

function getCookie(name) {
  //console.log('getCookie name=' + name);
  if (!name) return null;
  var start = document.cookie.indexOf(name + "=");
  var len = start + name.length + 1;
  if (( !start ) && ( name != document.cookie.substring(0, name.length) )) {
    return null;
  }
  if (start == -1) return null;
  var end = document.cookie.indexOf(';', len);
  if (end == -1) end = document.cookie.length;
  var r = unescape(document.cookie.substring(len, end));
  //console.log('=' + r);
  return r;
}

function setCookie(name, value, expires, path, domain, secure) {
  //console.log('setcookie name=' + name + ' value=' + value);
  if (!name) return;
  var today = new Date();
  today.setTime(today.getTime());
  if (expires) {
    expires = expires * 1000 * 60 * 60 * 24;
  }
  var expires_date = new Date(today.getTime() + (expires));
  document.cookie = name + '=' + escape(value) +
                    ( ( expires ) ? ';expires=' + expires_date.toGMTString() : '' ) + //expires.toGMTString()
                    ( ( path ) ? ';path=' + path : '' ) +
                    ( ( domain ) ? ';domain=' + domain : '' ) +
                    ( ( secure ) ? ';secure' : '' );
}

function deleteCookie(name, path, domain) {
  if (getCookie(name)) document.cookie = name + '=' +
                                         ( ( path ) ? ';path=' + path : '') +
                                         ( ( domain ) ? ';domain=' + domain : '' ) +
                                         ';expires=Thu, 01-Jan-1970 00:00:01 GMT';
}

function $() {
  var elements = new Array();
  for (var i = 0; i < arguments.length; i++) {
    var element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);
    if (arguments.length == 1)
      return element;
    elements.push(element);
  }
  return elements;
}

function getElementsByClass(searchClass, node, tag) {
  var classElements = new Array();
  if (node == null)
    node = document;
  if (tag == null)
    tag = '*';
  var els = node.getElementsByTagName(tag);
  var elsLen = els.length;
  var pattern = new RegExp('(^|\\\\s)' + searchClass + '(\\\\s|$)');
  var j = 0;
  for (var i = 0; i < elsLen; i++) {
    if (pattern.test(els[i].className)) {
      classElements[j] = els[i];
      j++;
    }
  }
  return classElements;
}

function removeFnutts(s) {
  if (s.length > 2) {
    if ((s.startsWith('\'') && s.endsWith('\'')) ||
        (s.startsWith('"') && s.endsWith('"')    )) {
      return s.substring(1, s.length - 1);
    }
  }
  return s;
}

function isArray(obj) {
  if (nullOrUndefined(obj)) return false;
  if (obj.constructor.toString().indexOf("Array") == -1)
    return false;
  else
    return true;
}

function addSelectOption(selectbox, text, value) {
  if (selectbox) {
    var e = document.createElement("OPTION");
    e.text = text;
    e.value = value;
    selectbox.options.add(e);
  }
}

function greatCircleDistance(lat1, lon1, lat2, lon2) {
  var R = 6371; // km
  var d = Math.acos(Math.sin(lat1) * Math.sin(lat2) +
                    Math.cos(lat1) * Math.cos(lat2) *
                    Math.cos(lon2 - lon1)) * R;
  return d;
}

// extend Number object with methods for converting degrees/radians

Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
};

Number.prototype.toDeg = function() {  // convert radians to degrees (signed)
  return this * 180 / Math.PI;
};

Number.prototype.toBrng = function() {  // convert radians to degrees (as bearing: 0...360)
  return (this.toDeg() + 360) % 360;
};

function greatCircleDistance2(lat1, lon1, lat2, lon2) {
  var R = 6371; // km
  var dLat = (lat2 - lat1).toRad();
  var dLon = (lon2 - lon1).toRad();
  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
          Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
          Math.sin(dLon / 2) * Math.sin(dLon / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c;
  return d;
}

function setInnerHtmlToLoadingAnimation(elementID) {
  setInnerHTML(elementID, '<div class="largeLoadingAnimationContainer">' +
                          '<img src="/system/image/loading_animation_small.gif" alt="Loading"/>' +
                          '</div>');

}

function setInnerHtmlToSmallLoadingAnimation(elementID, width, paddingTop) {
  if (paddingTop === undefined) paddingTop = "2px";
  setInnerHTML(elementID, '<img style="padding-left:8px; padding-top: ' + paddingTop + ';' +
                          (width ? 'width:' + width + ';' : '') +
                          '" src="/system/image/loading_16x16.gif" alt="Loading"/>');

}

function getRandomUnusedId(id) {
  while (getObj(id)) {
    id = id + (Math.random() * 10);
  }
  return id;
}

function clearElement(element) {
  if (element) while (element.firstChild) element.removeChild(element.firstChild);
}

/** Context class **/
function Context(key) {

  this.contextKey = key;

  this.get = function(key) {
    if (key) {
      if (this.contextKey) {
        return YAHOO.util.Cookie.getSub(this.contextKey, key);
      } else {
        return YAHOO.util.Cookie.get(key);
      }
    }
  };

  this.set = function(key, obj) {
    if (key) {
      if (this.contextKey) {
        YAHOO.util.Cookie.setSub(this.contextKey, key, obj);
      } else {
        YAHOO.util.Cookie.set(key, obj);
      }
    }
  };

}


function logoutCustomer() {
  // TODO: Fix ugly hack
  AjaxLogoutUser.startRequest(function(result) {
    if (YAHOO.util.Dom.hasClass(document.body, 'user-profiles')) {
      redirect("");
    } else {
      reloadPage();
    }
  });
}

function getSmallerAnimationHTML() {
  return '<img alt="Loading..." src="/system/image/loading_animation_smaller.gif"/>';
}

function getSmallestAnimationHTML() {
  return '<img alt="Loading..." src="/system/image/loading16x16.gif"/>';
}

/**
 * If used within an iframe, only the iframe will reload!
 */
function reloadPage() {
  window.location.reload();
}

/**
 * Reloads the window, this can be used even if in an iframe. Iframe will not reload, but instead the whole page.
 */
function reloadWindow() {
  top.location.reload();
}

function reloadParent() {
  if (parent) {
    parent.location.reload();
  }
}

function redirectOnTimeout(action, timeOut) {
  timeOut = useDefault(timeOut, 5000);
  setTimeout(function () {
    redirect(action);
  }, timeOut);
}

function redirect(action) {
  redirectPure(checkAction(action));
}

function redirectPure(path) {
  window.location.pathname = path;
}

/**
 * Shows an alert if the message is defined and not empty string, if the condition is undefined or true.
 * @param s
 * @param condition
 */
function ibealert(s, condition) {
  if (condition === undefined || condition === true) {
    if (s) alert(s);
  }
}

function checkAction(url) {
  url = prependIfNotThere(url, "/");
  if (url != "/" && url.indexOf("?") == -1) {
    url = appendIfNotThere(url, ".action");
  }
  return url;
}

function appendIfNotThere(base, add) {
  return (base.endsWith(add) ? base : base + add);
}

function prependIfNotThere(base, add) {
  return (base.startsWith(add) ? base : add + base);
}

/**
 * Returns all fields in a form with a given name. Usually just one, but radio buttons usually have more than one.
 * @param form
 * @param fieldName
 */
function getFieldsFromForm(form, fieldName) {
  var result = new Array();
  if (!form) {
    ibeerror("Trying to get field in form that is undefined.");
    return undefined;
  }
  var elements = form.elements;
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    if (element.name == fieldName) {
      result.push(element);
    }
  }
  if (result.length == 0) return null;
  return result;
}

function getFieldFromForm(form, fieldName) {
  var r = getFieldsFromForm(form, fieldName);
  if (r) return r[0];
  else return null;
}

Object.prototype.getObjectTypeName = function() {
  return "[not implemented]";
  //var funcNameRegex = /function (.{1,})\(/;
  //var results = (funcNameRegex).exec((this).constructor.toString());
  //return (results && results.length > 1) ? results[1] : "";
};

//See ValidationUtil.java for description and ValidationUtilTest.java for tests
function isValidPassword(password) {
  var regex = /^[^\s]{6,}$/;
  return regex.test(password);
}

function isValidEmail(email) {
  var regex = /^\w+([\.\-\+]?\w+)*@\w+([\.\-\+]?\w+)*(\.\w{2,})+$/;
  return regex.test(email);
}

/* Matches 6 to 15 digits, used for phone numbers, see standard E.164 */
function isValidPhoneNumber(phoneNumber) {
  var regex = /^\d{6,15}$/;
  return regex.test(trimPhoneNumber(phoneNumber));
}

/* Trims away " .-" and leading "00" or "+" */
function trimPhoneNumber(phoneNumber) {
  var regex = /^00|^\+|[\s.-]+/;
  return phoneNumber.replace(regex, "");
}

function parseJsonList(s) {
  var e = eval(s);
  return e;
}

function parseJsonObject(s) {
  var e = eval('[' + s + ']');
  return e[0];
}

function isEmptyArray(o) {
  if (o === undefined) return true;
  if (o === null) return true;
  if (typeof o.length == 'number') {
    return o.length <= 0;
  } else {
    return false;
  }
}

function deleteElementInArray(array, index) {
  array.splice(index, 1);
}

function runSoon(func, delayInMs) {
  setTimeout(func, delayInMs);
}

/****************
 Fading functions
 ****************/

function fade(elementId, timeToFade) {
  if (!timeToFade) timeToFade = 1000.0;

  var element = document.getElementById(elementId);
  if (element == null) return;
  element.FadeState = null;

  if (element.FadeState == null) {
    if (element.style.opacity == null || element.style.opacity == '' || element.style.opacity == '1') {
      element.FadeState = 2;
    } else {
      element.FadeState = -2;
    }
  }

  if (element.FadeState == 1 || element.FadeState == -1) {
    element.FadeState = element.FadeState == 1 ? -1 : 1;
    element.FadeTimeLeft = timeToFade - element.FadeTimeLeft;
  } else {
    element.FadeState = element.FadeState == 2 ? -1 : 1;
    element.FadeTimeLeft = timeToFade;
    setTimeout("animateFade(" + new Date().getTime() + ",'" + elementId + "', " + timeToFade + ")", 33);
  }
}

function animateFade(lastTick, elementId, timeToFade) {
  if (!timeToFade) timeToFade = 1000.0;
  var curTick = new Date().getTime();
  var elapsedTicks = curTick - lastTick;

  var element = document.getElementById(elementId);

  if (element.FadeTimeLeft <= elapsedTicks) {
    element.style.opacity = element.FadeState == 1 ? '1' : '0';
    element.style.filter = 'alpha(opacity = '
      + (element.FadeState == 1 ? '100' : '0') + ')';
    element.FadeState = element.FadeState == 1 ? 2 : -2;
    return;
  }

  element.FadeTimeLeft -= elapsedTicks;
  var newOpVal = element.FadeTimeLeft / timeToFade;
  if (element.FadeState == 1)    newOpVal = 1 - newOpVal;

  element.style.opacity = newOpVal;
  element.style.filter = 'alpha(opacity = ' + (newOpVal * 100) + ')';

  setTimeout("animateFade(" + curTick + ",'" + elementId + "')", 33);
}

function insertArgument(text, arg0, arg1, arg2, arg3) {
  if (arg0) text = text.split('{0}').join(arg0);
  if (arg1) text = text.split('{1}').join(arg1);
  if (arg2) text = text.split('{2}').join(arg2);
  if (arg3) text = text.split('{3}').join(arg3);
  return text;
}

