/*
** Evonux 2005-2008
** Evonux JavaScript Tools (EJST) - version 0.4.3
**
** tested: IE 6.0/7.0, Firefox 2.0, Safari 2.0/3.0, Konqueror
**         Mac OS X, Windows XP/Vista, Linux
**
** All rights reserved
*/

if (!Evonux)
  Evonux = {};

Evonux.debug = false;

Evonux.SITE_URL = window.location.hostname;
Evonux._include = new Array();
Evonux.trans = new Array();
Evonux.bufferid = 'buffer';
Evonux.loadingId = 'evonux_loading';
Evonux.PIC_DIR = Evonux.SITE_ROOT +'/pic';
Evonux.JS_DIR = Evonux.SITE_ROOT +'/js';
Evonux.mainWrapId = 'wrap';
Evonux.menuCornerRightId = 'menutop_rightcorner';
Evonux.menuCornerLeftId = 'menutop_leftcorner';

Evonux._calcPowerLevel = 0;
Evonux._browser = false;
Evonux._browserv = 0;
Evonux._os = false;
Evonux._id = 0;

Evonux._mouseX = 0;
Evonux._mouseY = 0;

Evonux.Local = {};

// ----------------------------------------------------------------------------
// Standard functions
Evonux.W = function(input)
{ // static
    document.write(input);
}
Evonux.$ = function(id)
{ // static
    if (typeof(id) == 'string')
      return document.getElementById(id);
    return id; // It may be object itself
}
Evonux.Exit = function(code) {throw (code ? code : 'evonux: Evonux.Exit() function called');}
/*
** Dynamically adds a JS script
*/
Evonux.Include = function(src, specialType)
{
    var objHead = document.getElementsByTagName('head')[0];
    if (!objHead) // No head found (should have been found!)
    {
	var objHtml = document.getElementsByTagName('html')[0],
	    objBody = document.getElementsByTagName('body')[0];
	if (objBody) // Else, document is definitely very badly made !
	{
	    objHead = document.createElement('head');
	    objBody.insertBefore(objHead, objBody);
	}
    }
    var objScript = document.createElement('script');
    objScript.type = (specialType ? specialType : 'text/javascript');
    objScript.src = src;
    objHead.appendChild(objScript);
}
/*
** Returns true if file is already included, false else
*/
Evonux.IncludeRegister = function(name)
{
    // Looks for file
    if (Evonux._include[name])
      return true;
    // Registers file
    Evonux._include[name] = true;
    return false;
}
/**
 * Same as Evonux.Include except it writes directly <script>...</script> declaration
 */
Evonux.Require = function(src, specialType)
{
    document.write('<script type="'+ (specialType ? specialType : 'text/javascript') +'" src="'+ src +'"><\/script>');
}
/*
** Returns unique id
*/
Evonux.GetId = function()
{
    return 'evonuxid'+ (Evonux._id++);
}
Evonux.TopParent = function()
{ // static
    docRef = document.getElementsByTagName('body')[0];
    while (docRef.parentNode != null)
      docRef = docRef.parentNode;
    return docRef;
}
Evonux.IsSSL = function()
{
    var re_https = new RegExp('^https', 'i');
    return re_https.test(window.location.href);
}
/*
** Programs an event
*/
if (document.addEventListener)
Evonux.AddEventListener = function(e, handler, obj, useCaption)
{ // static
    if (arguments.length < 4) useCaption = true;
    var _obj = (obj ? obj : window);
    return _obj.addEventListener(e, handler, useCaption);
}
else
Evonux.AddEventListener = function(e, handler, obj, useCaption)
{ // static
    if (arguments.length < 4) useCaption = true;
    if (obj) return obj.attachEvent('on'+ e, handler);
    window.attachEvent('on'+ e, handler);
}
/*
** Cancels an event
*/
if (document.removeEventListener)
Evonux.RemoveEventListener = function(e, handler, obj)
{ // static
    var _obj = (obj ? obj : window.document);
    _obj.removeEventListener(e, handler, true);
}
else
Evonux.RemoveEventListener = function(e, handler, obj)
{ // static
    var _obj = (obj ? obj : window.document);
    _obj.detachEvent('on'+ e, handler);
}
/*
** Stops event propagation
*/
Evonux.StopPropagation = function(e)
{
    e.cancelBubble = true;
    if (e.stopPropagation)
      e.stopPropagation();
}

/*
** Retrieves object that launched event
*/
Evonux.GetEventLauncher = function(e)
{
    var target;

    if (e.target)
      target =  e.target;
    else if (e.srcElement)
      target =  e.srcElement;
    if (target.nodeType == 3) // defeat Safari bug
      target =  target.parentNode;
    return target;
}
Evonux.GetButton = function(e)
{
    var button;
    button = (e.button ? e.button : e.which);
    return button;
}
Evonux.GetKey = function(e)
{
    var key = e.keyCode;
    return key;
}

/*
** Records mouse position
*/
if (document.all)
{
Evonux.RecordMousePosition = function(e)
 { // static
     Evonux._mouseX = e.clientX + document.documentElement.scrollLeft;
     Evonux._mouseY = e.clientY + document.documentElement.scrollTop;
 }
Evonux.GetMouseCoord = function(e)
 { // static
     if (!e) var e = window.event;
     return new Array(e.clientX + document.documentElement.scrollLeft,
		      e.clientY + document.documentElement.scrollTop);
 }
}
else
{
Evonux.RecordMousePosition = function(e)
 { // static
     Evonux._mouseX = e.pageX;
     Evonux._mouseY = e.pageY;
}
Evonux.GetMouseCoord = function(e)
 { // static
     if (!e) var e = window.event;
     return new Array(e.pageX, e.pageY);
 }
}
/*
** Returns an array with size of obj : [width, height]
** Main window if no argument
*/
Evonux.GetObjSize = function(obj)
 {
     if (obj)
       return Array(obj.offsetWidth, obj.offsetHeight);
     var w = window, db = document.documentElement; // document.body
     if (w.innerWidth)
       return Array(w.innerWidth, w.innerHeight);
     return Array(db.offsetWidth, db.offsetHeight); // clientHeight / clientWidth
 }
/*
** Return actual style property for an object (JS, style="" or CSS)
*/

if (window.getComputedStyle)
Evonux.GetStyleProp = function(obj, prop)
{
    return document.defaultView.getComputedStyle(obj, null).getPropertyValue(prop);
}
else if (document.defaultView)
Evonux.GetStyleProp = function(obj, prop)
{
    var a;
    if (a = document.defaultView.getComputedStyle(obj, null))
      return a.getPropertyValue(prop);
    return false;
}
else
Evonux.GetStyleProp = function(obj, prop)
{
    // IE
    var re_dash2capital = /-([a-z]{1})/;
    for (k = 0; re_dash2capital.test(prop) && k < 10;k++)
      prop = prop.replace(re_dash2capital, RegExp.$1.toUpperCase());
    return obj.currentStyle[prop];
}

Evonux.GetOffsetLeftActual = function(obj)
{
    var offsetLeft = 0;
    for (; obj.offsetParent && obj.tagName.toLowerCase() != 'body'; obj = obj.offsetParent)
      offsetLeft += obj.offsetLeft;
    return offsetLeft;
}
Evonux.GetOffsetTopActual = function(obj)
{
    var offsetTop = 0;
    for (; obj.offsetParent && obj.tagName.toLowerCase() != 'body'; obj = obj.offsetParent)
      offsetTop += obj.offsetTop;
    return offsetTop;
}

Evonux.GetOS = function()
{
    if (Evonux._os)
      return Evonux._os;
    if (navigator.userAgent.toLowerCase().indexOf('linux') != -1)
      return (Evonux._os = 'linux');
    if (navigator.userAgent.toLowerCase().indexOf('mac') != -1)
      return (Evonux._os = 'mac');
    if (navigator.userAgent.toLowerCase().indexOf('win') != -1)
      return (Evonux._os = 'win');
    if (navigator.userAgent.toLowerCase().indexOf('bsd') != -1)
      return (Evonux._os = 'bsd');
    return (Evonux._os = 'undefined');
}
Evonux.GetBrowser = function()
{
    if (Evonux._browser)
      return Evonux._browser;
    var nav_name = navigator.userAgent.toLowerCase(),
        b = 'undefined';
    if (window.opera)    // opera
      b = 'opera';
    else if (/msie/.test(nav_name))    // internet explorer
      b = 'msie';
    else if (/firebird/.test(nav_name))    // firebird
      b = 'firebird';
    else if (/firefox/.test(nav_name) || /iceweasel/.test(nav_name))    // firefox
      b = 'firefox';
    else if (/netscape/.test(nav_name))    // netscape
      b = 'netscape';
    else if (/epiphany/.test(nav_name))    // epiphany
      b = 'epiphany';
    else if (/konqueror/.test(nav_name))    // konqueror
      b = 'konqueror';
    else if (/galeon/.test(nav_name))    // galeon
      b = 'galeon';
    else if (/safari|webkit/.test(nav_name))    // safari
      b = 'safari';
    else if (/mozilla/.test(nav_name))    // mozilla
      b = 'mozilla';
    Evonux._browser = b;
    return b;
}
Evonux.GetBrowserVersion = function()
{
    if (Evonux._browserv)
      return Evonux._browserv;
    var nav_name = navigator.userAgent.toLowerCase(),
        b = Evonux.GetBrowser();
    if (b == 'firefox') b = 'firefox|iceweasel';
    var re_version = new RegExp('('+ b +')'+'[\/ ]{1}([0-9\.]+)', 'i');
    re_version.exec(nav_name);
    return Evonux._browserv = parseInt(RegExp.$2);
}

Evonux.IsIE6 = function ()
{
    return ((Evonux.GetBrowser() == 'msie') && (Evonux.GetBrowserVersion() < 7));
}

Evonux.TypeOf = function(obj)
{
    var _type = typeof(obj);
    if ((_type == 'object') && obj.type)
      return obj.type;
    return _type;
}
// Calculates available calculation power
Evonux.AvailableCalcPower = function(recalc)
{
    if ((Evonux._calcPowerLevel > 0) && !recalc)
      return Evonux._calcPowerLevel;
    var now = new Date();
    nowMS0 = now.getTime();
    for (k = 1, i = 0; k < 1000; k++)
      i += eval('Math.sqrt(k) + Math.sin(k) + Math.cos(k)');
    now = new Date();
    nowMS = now.getTime() - nowMS0;

    // Fast calc availability : [50,100%]
    if (nowMS <= 150)
      Evonux._calcPowerLevel = Math.floor(100 - ((nowMS / 150) * 50));
    // Low calc availability  : [1,50%]
    else
    {
	if (nowMS > 2000)
	    nowMS = 2000;
	tmp = 50 - ((nowMS / 2000) * 50);
	Evonux._calcPowerLevel = (tmp > 0 ? Math.floor(tmp) : 1);
    }

    return Evonux._calcPowerLevel;
}

Evonux.Deselect = function()
{
    if (document.selection)
      document.selection.empty();
    else if (window.getSelection)
      window.getSelection().removeAllRanges();
}

Evonux.BlockRightClick = function(e)
{
    var b = Evonux.GetButton(e);
    if (b == 2 || b == 3)
      Evonux.StopPropagation(e);
    return false;
}

Evonux.SetTitle = function(new_title)
{
    document.title = Evonux.TITLE + (new_title ? ' - '+ new_title : '');
}
/*
** Adds website title if it does not exist
*/
Evonux.MagnifyTitle = function()
{
    var re_title = new RegExp('^'+ Evonux.TITLE +' - ', 'i');
    if (!re_title.test(document.title) && document.title != Evonux.TITLE)
      document.title = Evonux.TITLE +' - '+ document.title;
}

Evonux.popup = new Array();
Evonux.PopUp = function(url, name, option)
{
    if (arguments.length < 3) option = '';
    if (arguments.length < 2) name = 'popup';
    if (arguments.length < 1) url = 'http://www.evonux.com';
    Evonux.popup[name] = window.open(url, name, option);
    return false;
}
Evonux.GetPopUp = function(name)
{
    if (!name) return Evonux.popup['popup'];
    return Evonux.popup[name];
}

// Always refreshes mouse position record
//Evonux.AddEventListener('mousemove', Evonux.RecordMousePosition, window.document);

// ----------------------------------------------------------------------------
// Misc
Evonux.ObjProps = function(obj)
{
    var output = '';

    for (i in obj)
      output += i +', ';
    return output;
}

Evonux.CSSset = function(objId, prop, value)
{
    eval('Evonux.$(\''+ objId +'\').'+ prop +' = \''+ value +'\'');
    return value;
}

// ----------------------------------------------------------------------------
// Math functions
if (!Math.max)
Math.max = function()
{
    var argv = arguments;
    var argc = argv.length;
    var max = argv[0];
    for (r = 0; r < argc; r++)
      max = (argv[r] > max ? argv[r] : max);
    return max;
}
if (!Math.maxRank)
Math.maxRank = function()
{
    var argv = arguments;
    var argc = argv.length;
    var max = argv[0];
    var max_rank = 0;
    for (r = 0; r < argc; r++)
    if (argv[r] > max)
    {
	max = argv[r];
	max_rank = r;
    }
    return max_rank;
}
if (!Math.min)
Math.min = function()
{
    var argv = arguments;
    var argc = argv.length;
    var min = argv[0];
    for (r = 0; r < argc; r++)
      min = (argv[r] < min ? argv[r] : min);
    return min;
}
if (!Math.minRank)
Math.minRank = function()
{
    var argv = arguments;
    var argc = argv.length;
    var min = argv[0];
    var min_rank = 0;
    for (r = 0; r < argc; r++)
    {
	if (argv[r] < min)
	    {
		min = argv[r];
		min_rank = r;
	    }
    }
    return min_rank;
}
// Returns approximation of float : number of decimals are truncated
if (!Math.floatRound)
Math.floatRound = function(floatNb, decimalLg)
{
    var exp = Math.pow(10, decimalLg);
    return Math.floor(floatNb * exp) / exp;
}
if (!Math.floatMultiply)
Math.FloatMultiply = function(a, b)
{
    var a_int, b_int,
	a_exp, b_exp;
    for (a_exp = 1, a_int = a * a_exp; a_int % 1 > 0; a_exp *= 10, a_int *= 10)
    ;
    for (b_exp = 1, b_int = b * b_exp; b_int % 1 > 0; b_exp *= 10, b_int *= 10)
    ;
    return (a_int * b_int) / (a_exp * b_exp);
}


// ----------------------------------------------------------------------------
// String functions
// Returns true only is object is a string
if (!Array.prototype.is_string)
  Array.prototype.is_string = true;
// Converts string to number
if (!String.toNb)
String.prototype.toNb = function()
{
    return eval(this);
}
// TODO: recode to avoid using RegExp! It may kill outerscope RegExp results
if (!String.trim)
String.prototype.trim = function()
{
    return this.replace(RegExp('^[ \t\v\f\n\r]+', 'g'), '').replace(RegExp('[ \t\v\f\n\r]+$', 'g'), '');
}

/**
 * Returns a Function object of a string that has form:
 * 'function (arg1 [, arg2 [,...]]) {...}'
 */
if (!String.toFunction)
String.prototype.toFunction = function()
{
    if (this.length < 12) // 12 is length of 'function(){}' (smallest possible function)
      return null;
    if (!window.opera)
    {
      eval('var f = '+ this);
      return f;
    }
    // Opera bugfix
    var str = this.trim(),
        re_function = /^function[ ]*\(([ a-zA-Z0-9_\-,]+)\)[ ]*{[ ]*(.*)[ ]*}$/;
    re_function.exec(str);
    var argv = RegExp.$1.trim().split(','),
        func_body = RegExp.$2;
    // Builds list of arguments
    for (var k = 0; k < argv.length; k++)
      argv[k] = '"'+ argv[k].trim() +'"';

    return eval('new Function('+ argv.join(',') + (argv.length > 0 ? ',' : '') +'"'+ func_body.replace(/"/g, '\"')/*"*/ +'")');
}


/**
 * Calculates strings similarity
 * 0 = equal, the higher is result, the more strings are different
 */
String.prototype.LevenshteinDistance = function (s, t)
{
    var dG = new Array();

    var i; // iterates through s
    var j; // iterates through t
    var s_i; // ith character of s
    var t_j; // jth character of t
    var cost; // cost
    
    // Step 1
    var n = s.length; // length of s
    var m = t.length; // length of t
    if (n == 0)
	return m;
    if (m == 0)
	return n;
    
    // Construct a matrix containing 0..m rows and 0..n columns
    var d = new Array();

    // Step 2
    // Initialize the first row to 0..n.
    // Initialize the first column to 0..m
    for (i = 0; i <= n; i++)
    {
	d[i] = new Array();
	d[i][0] = i;
    }
    
    for (j = 0; j <= m; j++)
	d[0][j] = j;

    // Step 3
    // Examine each character of s (i from 1 to n)
    // Step 4
    // Examine each character of t (j from 1 to m)
    // Step 5
    // Determine cost
    // Step 6
    // Set cell d[i,j] of the matrix equal to the minimum of:
    // a. The cell immediately above plus 1: d[i-1,j] + 1.
    // b. The cell immediately to the left plus 1: d[i,j-1] + 1.
    // c. The cell diagonally above and to the left plus the cost: d[i-1,j-1] + cost

    // Does it ! :
    for (i = 1; i <= n; i++)
    {
	for (j = 1; j <= m; j++)
	    {
		s_i = s.charAt(i - 1);
		t_j = t.charAt(j - 1);
		cost = (s_i == t_j ? 0 : 1);

		d[i][j] = Evonux.Math.Min(d[i-1][j]   + 1,
					  d[i][j-1]   + 1,
					  d[i-1][j-1] + cost);
	    }
    }

    // Step 7
    return d[n][m];
}

if (!String.toSize)
String.prototype.toSize = function()
{
    var size = this.toNb();
    if (size > 1000000000000) // > 1TB
      return Math.floatRound(size / 1000000000000, 2) + 'TB';
    if (size > 1000000000) // > 1GB
      return Math.floatRound(size / 1000000000, 2) + 'GB';
    if (size > 1000000) // > 1MB
      return Math.floatRound(size / 1000000, 2) + 'MB';
    if (size > 1000) // > 1kB
      return Math.floatRound(size / 1000, 2) + 'kB';
    return size + 'B';
}

if (!String.urlencode)
String.prototype.urlencode = function ()
{
    var SAFECHARS = "0123456789" + // Numeric
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + // Alphabetic
    "abcdefghijklmnopqrstuvwxyz" +
    "-_.!~*'()"; // RFC2396 Mark characters
    var HEX = "0123456789ABCDEF";
    
    var plaintext = this;
    var encoded = "";
    for (var i = 0; i < plaintext.length; i++ )
    {
	var ch = plaintext.charAt(i);
	if (ch == " ")
	  encoded += "+";
	else if (SAFECHARS.indexOf(ch) != -1)
	  encoded += ch;
	else
	{
	  var charCode = ch.charCodeAt(0);
	  if (charCode > 255)
	    encoded += "+";
	  else
	  {
	    encoded += "%";
	    encoded += HEX.charAt((charCode >> 4) & 0xF);
	    encoded += HEX.charAt(charCode & 0xF);
	  }
	}
    }
    return encoded;
};

// ----------------------------------------------------------------------------
// RegExp

// Tests if compile function exists
var __re = new RegExp('a', 'i');
if (!__re.compile)
{
	RegExp.prototype.compile = function(source, options)
	{
		var re_g = new RegExp('g', 'i');
		var re_i = new RegExp('i', 'i');
		//this = new RegExp(source, options);
		this.source = source;
		this.ignoreCase = (re_i.test(options));
		this.global = (re_g.test(options));
	}
}


// ----------------------------------------------------------------------------
// Array functions
// Adds an item at the end of array
if (!Array.push)
Array.prototype.push = function()
{
    var argv = Array.prototype.push.arguments,
        argc = argv.length;
    for (var c = 0; c < argc; c++)
      this[this.length] = argv[c];
}
// Overrides useless concat base method
Array.prototype.concat2 = function()
{
    var argv = Array.prototype.concat2.arguments,
        argc = argv.length,
	a = this;
    for (var c = 0; c < argc; c++) // for each Array to concat
      for (var n = 0, lg_n = argv[c].length; n < lg_n; n++) // for each cell in this Array
        a.push(argv[c][n]);
    return a;
}
Array.concat2 = function()
{ // static
    var argv = Array.concat2.arguments,
	argc = argv.length,
	a = new Array();
    for (var c = 0; c < argc; c++)
      a = a.concat2(argv[c]);
    return a;
}
if (!Array.prototype.del)
Array.prototype.del = function(rank, length)
{
    if (arguments.length < 2) length = 1;
    if (rank == 'last') rank = this.length - 1;
    this.splice(rank, length);
    return this.length;
}

// ------------------------------------------------------------
// List tables
Evonux.List = {};

Evonux.List.Highlight = function(obj, display)
{
    if (display)
    {
      obj.style.backgroundColor = 'rgb(255,255,200)';
      obj.style.color = 'rgb(255,255,255)';
    }
    else
    {
      obj.style.backgroundColor = '';
      obj.style.color = '';
    }
}

// ------------------------------------------------------------
// Forms
/*
** Returns selected value of a select from its id (not name !)
*/
Evonux.GetSelectedValue = function(sel_id)
{
    var sel = Evonux.$(sel_id);
    if (!sel)
      return false;
    return sel.options[sel.selectedIndex].value;
}

// ------------------------------------------------------------
// First steps
Evonux.MagnifyTitle();

// ------------------------------------------------------------
// INCLUDES
Evonux.Require(Evonux.JS_DIR +'/evonux/dom.js');
Evonux.Require(Evonux.JS_DIR +'/evonux/xml.js');
Evonux.Require(Evonux.JS_DIR +'/evonux/text.js');

window.addEvent('domready', function () {
	Evonux.Text.HeadersToImg({node:$('content')});
})
