/* $Date: 2009-08-07 02:00:06 +0200 (fr, 07 aug 2009) $    $Revision: 5169 $ */
function $(id) {
  return document.getElementById(id);
}
function $S(id){
  return document.getElementById(id).style;
}
function $C(tag){
  return document.createElement(tag);
}
function $CA(tag, parent, attribs, styles){
  var e=$C(tag);
  if (attribs) e = $A(e, attribs);
  if (styles) e = $AS(e, styles);
  parent.appendChild(e);
  return e;
}
function $A(elem, attribs) {
  for(prop in attribs)
    elem[prop] = attribs[prop];
  return elem;
}
function $AS(elem, styles) {
  for(prop in styles)
    elem.style[prop] = styles[prop];
  return elem;
}

function translate(txt) {
  var response = NFN.BaseMaster.Translate(txt);
  if (response.error) return txt;
  else return response.value;
}

function translateArr(txt) {
  var response = NFN.BaseMaster.TranslateArr(txt);
  if (response.error) return txt;
  else return response.value;
}

function addCssToHead(css) {
  var head = document.getElementsByTagName("head")[0];
  if (head.innerHTML.indexOf(css) < 0) {
    var lnk = $C('link');
    lnk.type = 'text/css';
    lnk.media = 'screen,print';
    lnk.rel = 'stylesheet';
    lnk.href = css;
    head.appendChild(lnk);
  }
}
function addJSToHead(js) {
  var head = document.getElementsByTagName("head")[0];
  if (head.innerHTML.indexOf(js) < 0) {
    var lnk = $C('script');
    lnk.type = 'text/javascript';
    lnk.src = js;
    head.appendChild(lnk);
  }
}

function getAbsolutePosition(div) {
  var currdiv = div;
  var apos = {left:currdiv.offsetLeft, top:currdiv.offsetTop};
  while (currdiv.offsetParent) {
    currdiv = currdiv.offsetParent;
    apos.left += currdiv.offsetLeft;
    apos.top += currdiv.offsetTop;
  }
  return apos;
}

function openMediabank(callback) {
  window.open("/admin/DocumentBank/DocumentBank.aspx?callback=" + callback, 'MB', 'width=900,height=600,resizable=yes');
}

function nfndebug(mess) {
  try { console.log(mess); }
  catch (e) {}
}

function validateEmail(email) {
  var emailRegExp = new RegExp("^([\\w-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([\\w-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$", "i")
  return emailRegExp.test(email);
}



window.size = function() {
  var w = 0;
  var h = 0;
  if (!window.innerWidth) {
    if (!(document.documentElement.clientWidth == 0)) {
      w = document.documentElement.clientWidth;
      h = document.documentElement.clientHeight;
    }
    else {
      w = document.body.clientWidth;
      h = document.body.clientHeight;
    }
  }
  else {
    w = window.innerWidth;
    h = window.innerHeight;
  }
  return {width:w,height:h};
}

window.center = function() {
  var hWnd = (arguments[0] != null) ? arguments[0] : {width:0,height:0};

  var _x = 0;
  var _y = 0;
  var offsetX = 0;
  var offsetY = 0;

  if (!window.pageYOffset) {
    if (!(document.documentElement.scrollTop == 0)) {
      offsetY = document.documentElement.scrollTop;
      offsetX = document.documentElement.scrollLeft;
    }
    else {
      offsetY = document.body.scrollTop;
      offsetX = document.body.scrollLeft;
    }
  }
  else {
    offsetX = window.pageXOffset;
    offsetY = window.pageYOffset;
  }

  _x = ((this.size().width-hWnd.width)/2)+offsetX;
  _y = ((this.size().height-hWnd.height)/2)+offsetY;

  return{x:_x,y:_y};
}

/*Window.prototype.size = _Window_size;
Window.prototype.center = _Window_center;*/



var Browser = {
  init: function () {
    this.browser = this.searchString(this.dataBrowser) || "Okänd webbläsare";
    this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || "Okänd version";
    this.OS = this.searchString(this.dataOS) || "an unknown OS";

    this.isIE = this.browser == "Internet Explorer";
    this.isIE7 = this.browser == "Internet Explorer" && this.version >= 7;
    this.isIE6 = this.browser == "Internet Explorer" && this.version < 7;
    this.isGecko = this.browser == "Mozilla";
    this.isFF = this.browser == "Firefox";
    this.isFF2 = this.browser == "Firefox" && this.version < 3;
    this.isChrome = this.browser == "Chrome";
    this.isSafari = this.browser == "Safari";
    this.isOpera = this.browser == "Opera";
    this.isMac = this.OS == "Mac";
    this.isWindows = this.OS == "Windows";
  },
  searchString: function (data) {
    for (var i=0;i<data.length;i++) {
      var dataString = data[i].string;
      var dataProp = data[i].prop;
      this.versionSearchString = data[i].versionSearch || data[i].identity;
      if (dataString) {
        if (dataString.indexOf(data[i].subString) != -1) return data[i].identity;
      }
      else if (dataProp) return data[i].identity;
    }
  },
  searchVersion: function (dataString) {
    var index = dataString.indexOf(this.versionSearchString);
    if (index == -1) return;
    return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
  },
  dataBrowser: [
    { string: navigator.userAgent, subString: "Chrome", identity: "Chrome" },
    { string: navigator.userAgent, subString: "OmniWeb", versionSearch: "OmniWeb/", identity: "OmniWeb" },
    { string: navigator.vendor, subString: "Apple", identity: "Safari"},
    { prop: window.opera, identity: "Opera" },
    { string: navigator.vendor, subString: "iCab", identity: "iCab" },
    { string: navigator.vendor, subString: "KDE", identity: "Konqueror" },
    { string: navigator.userAgent, subString: "Firefox", identity: "Firefox" },
    { string: navigator.vendor, subString: "Camino", identity: "Camino" },
    { string: navigator.userAgent, subString: "Netscape", identity: "Netscape" },
    { string: navigator.userAgent, subString: "MSIE", identity: "Internet Explorer", versionSearch: "MSIE" },
    { string: navigator.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv" },
    { string: navigator.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla" }
  ],
  dataOS : [
    { string: navigator.platform, subString: "Win", identity: "Windows" },
    { string: navigator.platform, subString: "Mac", identity: "Mac" },
    { string: navigator.platform, subString: "Linux", identity: "Linux" }
  ]
};
Browser.init();



/***** Extensions of HTMLElement object *****/

function _HTMLElement_getChildNodes() {
  var allnodes = this.childNodes;
  var nodes = new Array();
  for (var i=0; i < allnodes.length; i++)
    if (allnodes[i].nodeName != "#text") {
      if (document.all) _assignMethods(allnodes[i]);
      nodes.push(allnodes[i]);
    }
  return nodes;
}
function _HTMLElement_getFirstChild() {
  var allnodes = this.childNodes;
  var anode = null;
  for (var i=0; i < allnodes.length && anode == null; i++)
    if (allnodes[i].nodeName != "#text")
      anode = allnodes[i];
  if (document.all && anode) _assignMethods(anode)
  return anode;
}
function _HTMLElement_getChildNode(idx) {
  var nodes = this.getChildNodes();
  return nodes[idx];
}
function _HTMLElement_absPos() {
  var currdiv = this;
  var apos = {left:currdiv.offsetLeft, top:currdiv.offsetTop};
  while (currdiv.offsetParent) {
    currdiv = currdiv.offsetParent;
    apos.left += currdiv.offsetLeft;
    apos.top += currdiv.offsetTop;
  }
  return apos;
}

function _assignMethods(elem) {
  elem.getChildNodes = _HTMLElement_getChildNodes;
  elem.getFirstChild = _HTMLElement_getFirstChild;
  elem.getChildNode = _HTMLElement_getChildNode;
  elem.absPos = _HTMLElement_absPos;
}

if(!document.all) {
  _assignMethods(HTMLElement.prototype);
}
else {
  var _createElement = document.createElement;
  document.createElement = function(tag) {
    var _elem = _createElement(tag);
    if (_elem) _assignMethods(_elem);
    return _elem;
  }

  var _getElementById = document.getElementById;
  document.getElementById = function(id) {
    var _elem = _getElementById(id);
    if (_elem) _assignMethods(_elem);
    return _elem;
  }

  var _getElementsByTagName = document.getElementsByTagName;
  document.getElementsByTagName = function(tag) {
    var _arr = _getElementsByTagName(tag);
    for (var i=0; i < _arr.length; i++)
      _assignMethods(_arr[i]);
    return _arr;
  }
}




/***** Extensions of Date object *****/

Date.prototype.add = function(addtype, amount) {
  var aDate = this.clone();
  if (addtype == "y") aDate.setFullYear(aDate.getFullYear() + amount);
  else if (addtype == "M") aDate.setMonth(aDate.getMonth() + amount);
  else if (addtype == "d") aDate.setDate(aDate.getDate() + amount);
  else if (addtype == "H") aDate.setHours(aDate.getHours() + amount);
  else if (addtype == "m") aDate.setMinutes(aDate.getMinutes() + amount);
  else if (addtype == "s") aDate.setSeconds(aDate.getSeconds() + amount);
  return aDate;
}
Date.prototype.addYears = function(amount) { return this.add("y", amount); }
Date.prototype.addMonths = function(amount) { return this.add("M", amount); }
Date.prototype.addDays = function(amount) { return this.add("d", amount); }
Date.prototype.addHours = function(amount) { return this.add("H", amount); }
Date.prototype.addMinutes = function(amount) { return this.add("m", amount); }
Date.prototype.addSeconds = function(amount) { return this.add("s", amount); }
Date.prototype.clone = function() {
  var aDate = new Date(this.getFullYear(), this.getMonth(), this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds());
  return aDate;
}
Date.prototype.monthName = function() {
  var amonth = this.getMonth();
  if (amonth == 0) return translate("Januari");
  else if (amonth == 1) return translate("Februari");
  else if (amonth == 2) return translate("Mars");
  else if (amonth == 3) return translate("April");
  else if (amonth == 4) return translate("Maj");
  else if (amonth == 5) return translate("Juni");
  else if (amonth == 6) return translate("Juli");
  else if (amonth == 7) return translate("Augusti");
  else if (amonth == 8) return translate("September");
  else if (amonth == 9) return translate("Oktober");
  else if (amonth == 10) return translate("November");
  else if (amonth == 11) return translate("December");
  else return "";
}
Date.prototype.dayName = function() {
  var aday = this.getDay();
  if (aday == 0) return translate("Söndag");
  else if (aday == 1) return translate("Måndag");
  else if (aday == 2) return translate("Tisdag");
  else if (aday == 3) return translate("Onsdag");
  else if (aday == 4) return translate("Torsdag");
  else if (aday == 5) return translate("Fredag");
  else if (aday == 6) return translate("Lördag");
  else return "";
}
Date.prototype.dayEquals = function(adate) {
  return this.getFullYear() == adate.getFullYear() && this.getMonth() == adate.getMonth() && this.getDate() == adate.getDate();
}
Date.prototype.dateString = function() {
  var m = (this.getMonth() < 9 ? "0" : "") + String(this.getMonth() + 1);
  var d = (this.getDate() < 10 ? "0" : "") + String(this.getDate());
  return this.getFullYear() + "-" + m + "-" + d;
}
Date.prototype.dateTimeString = function() {
  var h = (this.getHours() < 10 ? "0" : "") + String(this.getHours());
  var m = (this.getMinutes() < 10 ? "0" : "") + String(this.getMinutes());
  var s = (this.getSeconds() < 10 ? "0" : "") + String(this.getSeconds());
  return this.dateString + " " + h + ":" + m + ":" + s;
}




/***** Extensions of Number object *****/

Number.formatFunctions = {count:0};
Number.prototype.NaN         = 'NaN';
Number.prototype.posInfinity = 'Infinity';
Number.prototype.negInfinity = '-Infinity';

Number.prototype.numberFormat = function(format, context) {
  if (isNaN(this) ) return Number.prototype.NaNstring;
  else if (this == +Infinity ) return Number.prototype.posInfinity;
  else if ( this == -Infinity) return Number.prototype.negInfinity;
  else if (Number.formatFunctions[format] == null) Number.createNewFormat(format);
  return this[Number.formatFunctions[format]](context);
}

Number.createNewFormat = function(format) {
  var funcName = "format" + Number.formatFunctions.count++;
  Number.formatFunctions[format] = funcName;
  var code = "Number.prototype." + funcName + " = function(context){\n";

  var formats = format.split(";");
  switch (formats.length) {
    case 1:
      code += Number.createTerminalFormat(format);
      break;
    case 2:
      code += "return (this < 0) ? this.numberFormat(\""
        + String.escape(formats[1])
        + "\", 1) : this.numberFormat(\""
        + String.escape(formats[0])
        + "\", 2);";
      break;
    case 3:
      code += "return (this < 0) ? this.numberFormat(\""
        + String.escape(formats[1])
        + "\", 1) : ((this == 0) ? this.numberFormat(\""
        + String.escape(formats[2])
        + "\", 2) : this.numberFormat(\""
        + String.escape(formats[0])
        + "\", 3));";
      break;
    default:
      code += "throw 'Too many semicolons in format string';";
      break;
  }
  eval(code + "}");
}

Number.createTerminalFormat = function(format) {
  // If there is no work to do, just return the literal value
  if (format.length > 0 && format.search(/[0#?]/) == -1)
    return "return '" + String.escape(format) + "';\n";

  // Negative values are always displayed without a minus sign when section separators are used.
  var code = "var val = (context == null) ? new Number(this) : Math.abs(this);\n";
  var thousands = false;
  var lodp = format;
  var rodp = "";
  var ldigits = 0;
  var rdigits = 0;
  var scidigits = 0;
  var scishowsign = false;
  var sciletter = "";
  // Look for (and remove) scientific notation instructions, which can be anywhere
  m = format.match(/\..*(e)([+-]?)(0+)/i);
  if (m) {
    sciletter = m[1];
    scishowsign = (m[2] == "+");
    scidigits = m[3].length;
    format = format.replace(/(e)([+-]?)(0+)/i, "");
  }
  // Split around the decimal point
  var m = format.match(/^([^.]*)\.(.*)$/);
  if (m) {
    lodp = m[1].replace(/\./g, "");
    rodp = m[2].replace(/\./g, "");
  }
  // Look for %
  if (format.indexOf('%') >= 0) code += "val *= 100;\n";
  // Look for comma-scaling to the left of the decimal point
  m = lodp.match(/(,+)(?:$|[^0#?,])/);
  if (m) code += "val /= " + Math.pow(1000, m[1].length) + "\n;";
  // Look for comma-separators
  if (lodp.search(/[0#?],[0#?]/) >= 0) thousands = true;
  // Nuke any extraneous commas
  if ((m) || thousands) lodp = lodp.replace(/,/g, "");
  // Figure out how many digits to the l/r of the decimal place
  m = lodp.match(/0[0#?]*/);
  if (m) ldigits = m[0].length;
  m = rodp.match(/[0#?]*/);
  if (m) rdigits = m[0].length;
  // Scientific notation takes precedence over rounding etc
  if (scidigits > 0) {
    code += "var sci = Number.toScientific(val,"
      + ldigits + ", " + rdigits + ", " + scidigits + ", " + scishowsign + ");\n"
      + "var arr = [sci.l, sci.r];\n";
  }
  else {
    // If there is no decimal point, round to nearest integer, AWAY from zero
    if (format.indexOf('.') < 0)
      code += "val = (val > 0) ? Math.ceil(val) : Math.floor(val);\n";
    // Numbers are rounded to the correct number of digits to the right of the decimal
    code += "var arr = val.round(" + rdigits + ").toFixed(" + rdigits + ").split('.');\n";
    // There are at least "ldigits" digits to the left of the decimal, so add zeros if needed.
    code += "arr[0] = (val < 0 ? '-' : '') + String.leftPad((val < 0 ? arr[0].substring(1) : arr[0]), "
        + ldigits + ", '0');\n";
  }
  // Add thousands separators
  if (thousands) code += "arr[0] = Number.addSeparators(arr[0]);\n";
  // Insert the digits into the formatting string.  On the LHS, extra digits are copied
  // into the result.  On the RHS, rounding has chopped them off.
  code += "arr[0] = Number.injectIntoFormat(arr[0].reverse(), '" + String.escape(lodp.reverse()) + "', true).reverse();\n";
  if (rdigits > 0) code += "arr[1] = Number.injectIntoFormat(arr[1], '" + String.escape(rodp) + "', false);\n";
  if (scidigits > 0) code += "arr[1] = arr[1].replace(/(\\d{" + rdigits + "})/, '$1" + sciletter + "' + sci.s);\n";
  return code + "return arr.join('.');\n";
}

Number.toScientific = function(val, ldigits, rdigits, scidigits, showsign) {
  var result = {l:"", r:"", s:""};
  var ex = "";
  // Make ldigits + rdigits significant figures
  var before = Math.abs(val).toFixed(ldigits + rdigits + 1).trim('0');
  // Move the decimal point to the right of all digits we want to keep,
  // and round the resulting value off
  var after = Math.round(new Number(before.replace(".", "").replace(new RegExp("(\\d{" + (ldigits + rdigits) + "})(.*)"), "$1.$2"))).toFixed(0);
  // Place the decimal point in the new string
  if (after.length >= ldigits)
    after = after.substring(0, ldigits) + "." + after.substring(ldigits);
  else
    after += '.';
  // Find how much the decimal point moved.  This is #places to LODP in the original
  // number, minus the #places in the new number.  There are no left-padded zeroes in
  // the new number, so the calculation for it is simpler than for the old number.
  result.s = (before.indexOf(".") - before.search(/[1-9]/)) - after.indexOf(".");
  // The exponent is off by 1 when it gets moved to the left.
  if (result.s < 0) result.s++;
  // Split the value around the decimal point and pad the parts appropriately.
  result.l = (val < 0 ? '-' : '') + String.leftPad(after.substring(0, after.indexOf(".")), ldigits, "0");
  result.r = after.substring(after.indexOf(".") + 1);
  if (result.s < 0) ex = "-";
  else if (showsign) ex = "+";
  result.s = ex + String.leftPad(Math.abs(result.s).toFixed(0), scidigits, "0");
  return result;
}

Number.prototype.round = function(decimals) {
  if (decimals > 0) {
    var m = this.toFixed(decimals + 1).match(new RegExp("(-?\\d*)\.(\\d{" + decimals + "})(\\d)\\d*$"));
    if (m && m.length)
      return new Number(m[1] + "." + String.leftPad(Math.round(m[2] + "." + m[3]), decimals, "0"));
  }
  return this;
}

Number.injectIntoFormat = function(val, format, stuffExtras) {
  var i = 0;
  var j = 0;
  var result = "";
  var revneg = val.charAt(val.length - 1) == '-';

  if ( revneg ) val = val.substring(0, val.length - 1);
  while (i < format.length && j < val.length && format.substring(i).search(/[0#?]/) >= 0) {
    if (format.charAt(i).match(/[0#?]/)) {
      // It's a formatting character; copy the corresponding character
      // in the value to the result
      if (val.charAt(j) != '-') result += val.charAt(j);
      else result += "0";
      j++;
    }
    else
      result += format.charAt(i);
    ++i;
  }
  if ( revneg && j == val.length )
    result += '-';
  if (j < val.length) {
    if (stuffExtras) result += val.substring(j);
    if ( revneg ) result += '-';
  }
  if (i < format.length) result += format.substring(i);
  return result.replace(/#/g, "").replace(/\?/g, " ");
}

Number.addSeparators = function(val) {
  return val.reverse().replace(/(\d{3})/g, "$1,").reverse().replace(/^(-)?,/, "$1");
}




/***** Extensions of String object *****/


String.prototype.reverse = function() {
  var res = "";
  for (var i = this.length; i > 0; --i) {
    res += this.charAt(i - 1);
  }
  return res;
}

String.prototype.trim = function(ch) {
  if (!ch) ch = ' ';
  return this.replace(new RegExp("^" + ch + "+|" + ch + "+$", "g"), "");
}

String.leftPad = function (val, size, ch) {
  var result = new String(val);
  if (ch == null) {
    ch = " ";
  }
  while (result.length < size) {
    result = ch + result;
  }
  return result;
}

String.escape = function(string) {
  return string.replace(/('|\\)/g, "\\$1");
}
