
/**
 * DOM
 **/
function ge() {
  var ea;
  for (var i = 0; i < arguments.length; i++) {
    var e = arguments[i];
    if (typeof e == 'string')
      e = document.getElementById(e);
    if (arguments.length == 1)
      return e;
    if (!ea)
      ea = new Array();
    ea.push(e);
  }
  return ea;
}

var _logTimer = (new Date()).getTime();
function debugLog(msg){
  try {
    var t = '['+(((new Date()).getTime() - _logTimer)/1000)+'] ';
    if (ge('debuglog')) {
      if (msg===null) msg = '[NULL]'; else if (msg===undefined) msg = '[UNDEFINED]';
      ge('debuglog').innerHTML += t + msg.toString().replace('<', '&lt;').replace('>', '&gt;')+'<br/>';
    }
    if(window.console && console.log){console.log(t + msg);}
  } catch (e) {}
}


function show(elem) {
  if (arguments.length > 1) {
    for (var i = 0; i < arguments.length; i++) {
      show(arguments[i]);
    }
    return;
  }
  elem = ge(elem);
  if (!elem) return;
  var old = data(elem, "olddisplay");
  elem.style.display = old || "";

  if (getStyle(elem, 'display') == "none" ) {
    if (elem.tagName.toLowerCase() == 'tr' && !browser.msie) {
      elem.style.display = 'table-row';
    } else if (elem.tagName.toLowerCase() == 'table' && !browser.msie) {
      elem.style.display = 'table';
    } else {
      elem.style.display = data(elem, "olddisplay", "block");
    }
  }
}


function getXY(obj) {
 if (!obj || obj == undefined) return;
 var left = 0, top = 0;
 if (obj.offsetParent) {
  do {
   left += obj.offsetLeft;
   top += obj.offsetTop;
  } while (obj = obj.offsetParent);
 }
 return [left,top];
}

function getSize(elem, withoutBounds) {
  var s = [0, 0];
  if (elem == document) {
    s =  [Math.max(
        document.documentElement["clientWidth"],
        document.body["scrollWidth"], document.documentElement["scrollWidth"],
        document.body["offsetWidth"], document.documentElement["offsetWidth"]
      ), Math.max(
        document.documentElement["clientHeight"],
        document.body["scrollHeight"], document.documentElement["scrollHeight"],
        document.body["offsetHeight"], document.documentElement["offsetHeight"]
      )];
  } else if (elem){
    function getWH() {
      s = [elem.offsetWidth, elem.offsetHeight];
      if (!withoutBounds) return;
      var padding = 0, border = 0;
      each(s, function(i, v) {
        var which = i ? ['Top', 'Bottom'] : ['Left', 'Right'];
        each(which, function(){
          s[i] -= parseFloat(getStyle(elem, "padding" + this)) || 0;
          s[i] -= parseFloat(getStyle(elem, "border" + this + "Width")) || 0;
        });
      });
      s = [Math.round(s[0]), Math.round(s[1])];
    }
    if (!isVisible(elem)) {
      var props = {position: "absolute", visibility: "hidden", display:"block"};
      var old = {};
      each(props, function(i, val){
        old[i] = elem.style[i];
        elem.style[i] = val;
      });
      getWH();
      each(props, function(i, val){
        elem.style[i] = old[i];
      });
    } else getWH();

  }
  return s;
}


/**
 *  Useful utils
 */

Function.prototype.bind = function(object) {
  var __method = this;
  return function() {
    return __method.apply(object, arguments);
  }
};
function isFunction(obj) {return Object.prototype.toString.call(obj) === "[object Function]"; }
function isArray(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; }
function now() { return +new Date; }
function trim(text) { return (text || "").replace(/^\s+|\s+$/g, ""); }
function stripHTML(text) { return text ? text.replace(/<(?:.|\s)*?>/g, "") : ''; }
function escapeRE(s) { return s ? s.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0') : ''; }
function intval(value) {
  if (value === true) return 1;
  return isNaN(parseInt(value)) ? 0 : parseInt(value);
}
function winToUtf(text) {
  var m, i, j, code;
  m = text.match(/&#[0-9]{2}[0-9]*;/gi);
  for (j in m) {
    var val = '' + m[j]; // buggy IE6
    code = intval(val.substr(2, val.length - 3));
    if (code >= 32 && ('&#' + code + ';' == val)) { // buggy IE6
      text = text.replace(val, String.fromCharCode(code));
    }
  }
  text = text.replace(/&quot;/gi, '"').replace(/&amp;/gi, '&').replace(/&lt;/gi, '<').replace(/&gt;/gi, '>');
  return text;
}

/**
 *  Arrays, objects
 **/

function each(object, callback) {
  var name, i = 0, length = object.length;

  if ( length === undefined ) {
    for ( name in object )
      if ( callback.call( object[ name ], name, object[ name ] ) === false )
        break;
  } else
    for ( var value = object[0];
      i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}

  return object;
};
function indexOf(arr, value, from) {
  from = (from == null) ? 0 : from;
  var m = arr.length;
  for(var i = from; i < m; i++)
    if (arr[i] == value)
       return i;
   return -1;
}

function clone(obj) {
  var newObj = {};
  for (var i in obj) {
    newObj[i] = obj[i];
  }
  return newObj;
}


var expand = "VK" + now(), vk_uuid = 0, vk_cache = {};

// Get or set element data
function data(elem, name, data) {
  var id = elem[ expand ], undefined;
  if ( !id )
    id = elem[ expand ] = ++vk_uuid;

  if (name && !vk_cache[id])
    vk_cache[id] = {};

  if (data !== undefined)
    vk_cache[id][name] = data;

  return name ?
    vk_cache[id][name] :
    id;
}

function removeData(elem, name) {
  var id = elem[expand];
  if (name) {
    if (vk_cache[id]) {
      delete vk_cache[id][name];
      name = "";
      for (name in vk_cache[id])
        break;

      if (!name)
        removeData(elem);
    }
  } else {
    try {
      delete elem[expand];
    } catch(e){ // fix for IE
      if (elem.removeAttribute)
        elem.removeAttribute(expand);
    }
    delete vk_cache[id];
  }
}

// Parse strings looking for color tuples [255,255,255]
function getRGB(color) {
  var result;
  if ( color && isArray(color) && color.length == 3 )
    return color;
  if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
    return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];
  if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
    return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
  if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
    return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
  if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
    return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
}

function getColor(elem, attr) {
	var color;
	do {
		color = getStyle(elem, attr);
		if (color != '' && color != 'transparent' || elem.nodeName.toLowerCase() == "body")
			break;
		attr = "backgroundColor";
	} while (elem = elem.parentNode);
	return getRGB(color);
}

function scrollToTop(speed) {
 if (speed == undefined) speed = 400;
 if (speed) {
  animate(document.getElementsByTagName('html')[0], {scrollTop: 0}, speed);
  animate(document.getElementsByTagName('body')[0], {scrollTop: 0}, speed);
 } else window.scroll(0, 0);
}

/**
 * Events
 **/


function addEvent(elem, types, handler, custom) {
  elem = ge(elem);
  if (!elem || elem.nodeType == 3 || elem.nodeType == 8 )
    return;

  // For whatever reason, IE has trouble passing the window object
  // around, causing it to be cloned in the process
  if (elem.setInterval && elem != window)
    elem = window;

  var events = data(elem, "events") || data(elem, "events", []),
      handle = data(elem, "handle") || data(elem, "handle", function(){
        _eventHandle.apply(arguments.callee.elem, arguments);
      });
  // Add elem as a property of the handle function
  // This is to prevent a memory leak with non-native
  // event in IE.
  handle.elem = elem;
  each(types.split(/\s+/), function(index, type) {
    var handlers = events[type];
    if (!handlers) {
      handlers = events[type] = new Array();
      if (!custom && elem.addEventListener)
        elem.addEventListener(type, handle, false);
      else if (!custom && elem.attachEvent)
        elem.attachEvent('on' + type, handle);
    }
    handlers.push(handler);
  });

  elem = null;
}

function triggerEvent(elem, type) {
  var handle = data(elem, "handle");
  if (handle) {
    setTimeout(function() {handle.call(elem, {type: type, target: elem})}, 0);
  }
}

function removeEvent(elem, type, handler) {
  elem = ge(elem);
  if (!elem) return;
  var events = data(elem, "events");
  if (events) {
    if (typeof(type) == 'string' && isArray(events[type])) {
      if (isFunction(handler)) {
        for (var i = 0; i < events[type].length; i++) {
          if (events[type][i] == handler) {
            delete events[type][i];
            break;
          }
        }
      } else {
        for (var i = 0; i < events[type].length; i++) {
          delete events[type][i];
        }
      }
    } else {
      for (var i in events) {
        removeEvent(elem, i);
      }
      return;
    }
    for (var ret in events[type]) break;
    if (!ret) {
      if (elem.removeEventListener)
        elem.removeEventListener(type, data(elem, "handle"), false);
      else if (elem.detachEvent)
        elem.detachEvent("on" + type, data(elem, "handle"));
      ret = null;
      delete events[type];
    }
  }
}

function cancelEvent(event) {
  var e = event.originalEvent || event;
  if (e.preventDefault)
      e.preventDefault();
  if (e.stopPropagation)
      e.stopPropagation();
  e.cancelBubble = true;
  e.returnValue = false;
  return false;
}

function _eventHandle(event) {
  event = event || window.event;

  var originalEvent = event;
  event = clone(originalEvent);
  event.originalEvent = originalEvent;

  if (!event.target)
    event.target = event.srcElement || document;

  // check if target is a textnode (safari)
  if ( event.target.nodeType == 3 )
    event.target = event.target.parentNode;

  if (!event.relatedTarget && event.fromElement)
    event.relatedTarget = event.fromElement == event.target;

  if ( event.pageX == null && event.clientX != null ) {
    var doc = document.documentElement, body = document.body;
    event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
    event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
  }

  if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
    event.which = event.charCode || event.keyCode;

  // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
  if ( !event.metaKey && event.ctrlKey )
    event.metaKey = event.ctrlKey;

  // Add which for click: 1 == left; 2 == middle; 3 == right
  // Note: button is not normalized, so don't use it
  if ( !event.which && event.button )
    event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));

  var handlers = data(this, "events");
  if (!handlers || typeof(event.type) != 'string' || !handlers[event.type] || !handlers[event.type].length) {
    return;
  }
  try {
  //fixed: handlers[event.type] = undefined
  for (var i in (handlers[event.type] || [])) {
    if (event.type == 'mouseover' || event.type == 'mouseout') {
      var parent = event.relatedElement;
      // Traverse up the tree
      while ( parent && parent != this )
        try { parent = parent.parentNode; }
        catch(e) { parent = this; }
      if (parent == this) {
        continue
      }
    }
    var ret = handlers[event.type][i].apply(this, arguments);
    if (ret === false) {
      cancelEvent(event);
    }
  }
  } catch (e) {
    debugLog(event.target.id+"."+event.type+": "+e.message);
  }
}

// Extends MessageBox
function AlertBox(title, text, callback, options) {
  var aBox = new MessageBox({title: title});
  if (typeof options == 'object') aBox.setOptions(options);
  else options = {};
  aBox.removeButtons();
  if (options.boxType == 'CONFIRM') {
   aBox.addButton({label: groups_no, style: 'button_no', onClick: aBox.hide}).addButton({label: groups_yes, onClick: function(){
    if (isFunction(callback) && callback() === false) return;
    aBox.hide();
   }});
  } else {
    aBox.addButton({label: box_close, style: 'button_no', onClick: aBox.hide});
  }
  return aBox.content(text).show();
}



var langBox;
function changeLang() {
 if (!langBox) {
  langBox = new MessageBox({title: (getLang('select_language')), width: 220});
  langBox.addButton({label: (getLang('box_close')), onClick: function(){langBox.hide(200)}});
 }
 langBox.loadContent('lang.php', {act:'lang_dialog'}).show();
 return false;
}
function doChangeLang(lang_id, hash) {
 Ajax.Send('lang.php', {act:'change_lang',lang_id: lang_id, hash:hash}, function(){
   location.reload(true);
 });
 return false;
}

function nameTip(obj) {
 if (parseInt(qCur) || obj.value.length || qd) {return;}
 show('qfriends');
 ge('qfriends').innerHTML = "<div style='border-top: 1px solid #C6D0D9; padding: 4px 18px; background-color: #FAFAFA;'>"+top_search_tip+"</div>";
};

(function(){
  var lastLength = 0;
  window.checkTextLength = function(max_len, val, warn){
    if(lastLength==val.length)return;
    lastLength=val.length;
    var n_len = replaceChars(val).length;
    warn.style.display = (n_len > max_len - 100) ? "" : "none";
    if (n_len > max_len) {
      warn.innerHTML = getLang('text_exceeds_symbol_limit', n_len - max_len);
    } else if (n_len > max_len - 100) {
      warn.innerHTML = getLang('text_N_symbols_remains', max_len - n_len);
    } else {
      warn.innerHTML = '';
    }
  };

  window.replaceChars = function(text) {
    var res = "";
    for (var i = 0; i<text.length; i++) {
      var c = text.charCodeAt(i);
      switch(c) {
        case 0x26: res += "&amp;"; break;
        case 0x3C: res += "&lt;"; break;
        case 0x3E: res += "&gt;"; break;
        case 0x22: res += "&quot;"; break;
        case 0x0D: res += ""; break;
        case 0x0A: res += "<br>"; break;
        case 0x21: res += "&#33;"; break;
        case 0x27: res += "&#39;"; break;
        default:   res += ((c > 0x80 && c < 0xC0) || c > 0x500) ? "&#"+c+";" : text.charAt(i); break;
      }
    }
    return res;
  };
})();