/* (c) http://vkontakte.ru/ */

var base_domain = base_domain || "/";

var browser = {
  opera: /opera/i.test(navigator.userAgent),
  msie: (!this.opera && /msie/i.test(navigator.userAgent)),
  msie6: (!this.opera && /msie 6/i.test(navigator.userAgent)),
  mozilla: /firefox/i.test(navigator.userAgent),
  chrome: /chrome/i.test(navigator.userAgent),
  safari: (!(/chrome/i.test(navigator.userAgent)) && /webkit|safari|khtml/i.test(navigator.userAgent))
}

function getLang(){
  try{
    var args = Array.prototype.slice.call(arguments);
    var key = args.shift();
    if(!key)return '...';
    var val = (window.langpack && window.langpack[key]) || window[key];
    if(!val){
      return key.replace(/_/g, ' ');
    }
    if(isFunction(val)){
      return val.apply(null, args);
    }else{
      return val;
    }
  }catch(e){
    debugLog('lang error:' + e.message + '(' + Array.prototype.slice.call(arguments).join(', ') + ')');
  }
}
/**
 * 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{ if(ge('debuglog')){
    if(msg===null)msg = '[NULL]';
    else if(msg===undefined)msg = '[UNDEFINED]';
    ge('debuglog').innerHTML += '['+(((new Date()).getTime() - _logTimer)/1000)+'] ' + msg.toString().replace(/</g, '&lt;').replace(/>/g, '&gt;')+"<br/>";
  } }catch(e){}
}

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

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 hide(elem){
  if (arguments.length > 1) {
    for (var i = 0; i < arguments.length; i++) {
      hide(arguments[i]);
    }
    return;
  }
  elem = ge(elem);
  if (!elem) return;
  if (getStyle(elem, 'display') != "none")
    data(elem, "olddisplay", elem.style.display);
  elem.style.display = "none";
}
function isVisible(elem) {
 elem = ge(elem);
 return getStyle(elem, 'display') != 'none' && getStyle(elem, 'visibility') != 'hidden';
}
function toggle(elem) {
  if (isVisible(elem)) {
    hide(elem);
  } else {
    show(elem);
  }
}
window.shide = toggle;

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, woBounds) {
  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 (!woBounds) 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.replace(/<(?:.|\s)*?>/g, ""); }
function escapeRE(s) { return s.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$0'); }

/**
 *  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;
}


// Extending object by another
function extend() {
  // copy reference to target object
  var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

  // Handle a deep copy situation
  if (typeof target === "boolean") {
    deep = target;
    target = arguments[1] || {};
    // skip the boolean and the target
    i = 2;
  }

  // Handle case when target is a string or something (possible in deep copy)
  if (typeof target !== "object" && !isFunction(target))
    target = {};

  // return target object if only one argument is passed
  if (length == i) {
    return target;
  }

  for (; i < length; i++)
    // Only deal with non-null/undefined values
    if ((options = arguments[i]) != null)
      // Extend the base object
      for (var name in options) {
        var src = target[name], copy = options[name];

        // Prevent never-ending loop
        if (target === copy)
          continue;

        // Recurse if we're merging object values
        if (deep && copy && typeof copy === "object" && !copy.nodeType)
          target[name] = extend(deep,
            // Never move original objects, clone them
            src || (copy.length != null ? [] : { })
          , copy);

        // Don't bring in undefined values
        else if (copy !== undefined)
          target[name] = copy;
      }

  // Return the modified object
  return target;
}


/**
 * CSS classes
 **/

function hasClass(obj, name) {
  obj=ge(obj);
  return obj && (new RegExp('(\\s|^)' + name + '(\\s|$)')).test(obj.className);
}

function addClass(obj, name) {
  obj=ge(obj);
  if (obj && !hasClass(obj, name)) obj.className = (obj.className ? obj.className + ' ' : '') + name;
}

function removeClass(obj, name) {
  obj=ge(obj);
  if (obj && hasClass(obj, name)) obj.className = obj.className.replace((new RegExp('(\\s|^)' + name + '(\\s|$)')), ' ');
}

// Get computed style
function getStyle(elem, name, force) {
  if (force === undefined) force = true;
  if (!force) {
    return elem.style[name];
  }
  if (name == "width" || name == "height") {
    return getSize(elem, true)[({'width':0, 'height':1})[name]] + 'px';
  }
  var ret, defaultView = document.defaultView || window;
  if (defaultView.getComputedStyle) {
    name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
    var computedStyle = defaultView.getComputedStyle( elem, null );
      if (computedStyle)
        ret = computedStyle.getPropertyValue(name);
  } else if (elem.currentStyle) {
    if (name == 'opacity' && browser.msie) {
      var filter = elem.currentStyle['filter'];
      return filter && filter.indexOf("opacity=") >= 0 ?
        (parseFloat(filter.match(/opacity=([^)]*)/)[1] ) / 100) + '' : '1';
    }
    var camelCase = name.replace(/\-(\w)/g, function(all, letter){
      return letter.toUpperCase();
    });
    ret = elem.currentStyle[name] || elem.currentStyle[camelCase];
    // If we're not dealing with a regular pixel number
    // but a number that has a weird ending, we need to convert it to pixels
    if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
      // Remember the original values
      var left = style.left, rsLeft = elem.runtimeStyle.left;

      // Put in the new values to get a computed value out
      elem.runtimeStyle.left = elem.currentStyle.left;
      style.left = ret || 0;
      ret = style.pixelLeft + "px";

      // Revert the changed values
      style.left = left;
      elem.runtimeStyle.left = rsLeft;
    }
  }
  return ret;
}

function setStyle(elem, name, value){
  elem = ge(elem);
  if (name == 'opacity'){
    if (browser.msie) {elem.style.filter = "alpha(opacity=" + value*100 + ")"; elem.style.zoom = 1; };
    elem.style.opacity = value;
  } else elem.style[name] = typeof(value) == 'number' && !(/z-?index|font-?weight|opacity|zoom|line-?height/i).test(name) ? value + 'px': value;
}

/**
 * Store data connected to element
 **/

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];
  }
}

/**
 * Simple FX
 **/
function animate(el, params, speed, callback) {
  el = ge(el);
  var options = extend({}, typeof speed == 'object' ? speed : {duration: speed, onComplete: callback || function(){}});
  var tween = data(el, 'tween');
  if (tween) {
    tween.setOptions(options);
  } else {
    tween = data(el, 'tween', new Fx.Base(el, options));
  }
  return tween.custom(params);
}

function fadeTo(el, speed, to, callback) {return animate(el, {opacity: to}, speed, callback);}

var Fx = fx = {};

Fx.Transitions = {
  linear: function(t, b, c, d) { return c*t/d + b; },
  sineInOut: function(t, b, c, d) { return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; }
};

Fx.Attrs = [
  [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
  [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
  [ "opacity" ]
];

function genFx(type, num){
  var obj = {};
  each( Fx.Attrs.concat.apply([], Fx.Attrs.slice(0,num)), function(){
    obj[this] = type;
  });
  return obj;
};

// Shortcuts for custom animations
each({slideDown: genFx('show', 1),
 slideUp: genFx('hide', 1),
 slideToggle: genFx('toggle', 1),
 fadeIn: {opacity: 'show'},
 fadeOut: {opacity: 'hide'},
 fadeToggle: {opacity: 'toggle'}}, function(f, val){
 window[f] = function(el, speed, callback){return animate(el, val, speed, callback);}
});


Fx.Base = function(el, options){
  this.element = ge(el);
  this.setOptions(options);
  this.now = {};
};
Fx.Base.prototype = {

  setOptions: function(options){
    if (this.isTweening()) return;
    this.options = extend({
      onComplete: function(){},
      transition: Fx.Transitions.sineInOut,
      duration: 500
    }, options || {});
  },

  step: function(){
    var time = new Date().getTime();
    if (time < this.time + this.options.duration){
      this.cTime = time - this.time;
      this.setNow();
    } else {
      setTimeout(this.options.onComplete.bind(this, this.element), 10);
      this.clearTimer();
      this.now = this.to;
      if (this.options.hide) hide(this.element);
      if (this.options.hide || this.options.show) {
        this.now = this.options.orig;
      }
      this.increase();
      return false;
    }
    this.increase();
    return true;
  },

  setNow: function(){
    for (p in this.from) {
      if (isArray(this.to[p])) // color fx
        this.now[p] = [Math.min(parseInt(this.compute(this.from[p][0], this.to[p][0])), 255), Math.min(parseInt(this.compute(this.from[p][1], this.to[p][1])), 255), Math.min(parseInt(this.compute(this.from[p][2], this.to[p][2])), 255)];
      else
        this.now[p] = this.compute(this.from[p], this.to[p]);
    }
  },

  compute: function(from, to){
    var change = to - from;
    return this.options.transition(this.cTime, from, change, this.options.duration);
  },

  clearTimer: function(){
    clearInterval(this.timer);
    this.timer = null;
    return this;
  },

  _start: function(from, to){
    if (this.timer) return;
    this.from = from;
    this.to = to;
    this.time = new Date().getTime();
    if (this.step()) this.timer = setInterval(this.step.bind(this), 13);
    return this;
  },

  increase: function(){
    for (var p in this.now) {
      if (isArray(this.now[p])) setStyle(this.element, p, 'rgb(' + this.now[p].join(',') + ')');
      else setStyle(this.element, p, this.now[p]);
    }
  },

  isTweening: function() {
    return this.timer ? true : false;
  },

  custom: function(prop){
    if (this.isTweening()) return false;

    var from = {}, to = {}, visible = isVisible(this.element), from_val, self = this;

    self.options.show = self.options.hide = false;
    self.options.orig = {};

    for (p in prop) {
      if (prop[p] == 'show' && visible || prop[p] == 'hide' && !visible)
        return this.options.onComplete.call(this, this.element);
    }
    each(prop, function(name, val){
     if (/backgroundColor|borderBottomColor|borderLeftColor|borderRightColor|borderTopColor|color|outlineColor/.test(name)) {
      from_val = getColor(self.element, name);
      val = getRGB(val);
     } else {
      from_val = parseFloat(getStyle(self.element, name)) || 0;
      val = val == 'toggle' ? visible ? 'hide' : 'show' : val;
      if (val == 'show') {
        self.options.show = true;
        val = from_val;
        from_val = (name == "width" || name == "height" ? 1 : 0);
        show(self.element);
      } else if (val == 'hide') {
        self.options.hide = true;
        val = 0;
      } else {
        var parts = val.toString().match(/^([\d+-.]+)(.*)$/);
        val = parts ? parseFloat(parts[1]) : val;
      }
      if (self.options.hide || self.options.show)
        self.options.orig[name] = getStyle(self.element, name, false);

      if ((name == "height" || name == "width") && self.element.style) {
        self.element.style.overflow = 'hidden';
        self.element.style.display = 'block';
      }
      if (name == "opacity" && val > 0 && !visible) {
        setStyle(self.element, 'opacity', 0);
        from_val = 0;
        show(self.element);
      }
     }
     if (from_val != val || (isArray(from_val) && from_val.join(',') == val.join(','))) {
      from[name] = from_val;
      to[name] = val;
     }
    });
    return this._start(from, to);
  }
};

// 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);
}


/**
 * Events
 **/
var KEY = window.KEY = {
  LEFT: 37,
   UP: 38,
   RIGHT: 39,
   DOWN: 40,
   DEL: 8,
   TAB: 9,
   RETURN: 13,
   ESC: 27,
   PAGEUP: 33,
   PAGEDOWN: 34,
   SPACE: 32
 };

function addEvent(elem, types, handler) {
  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 (elem.addEventListener)
        elem.addEventListener(type, handle, false);
      else if (elem.attachEvent)
        elem.attachEvent('on' + type, handle);
    }
    handlers.push(handler);
  });

  elem = null;
}

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 && data(elem, "handle")) {

      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 = 0; i < (handlers[event.type] || []).length; i++) {
    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);
  }
}

// Prevent memory leaks in IE
// And prevent errors on refresh with events like mouseover in other browsers
// Window isn't included so as not to unbind existing unload events
addEvent(window, "unload", function(){
  for (var id in vk_cache)
    if (vk_cache[id].handle && vk_cache[id].handle.elem != window)
      removeEvent(vk_cache[id].handle.elem);
});

// Dom ready event handler
(function(){
  var isRdy = false, rdyBnd = false, rdyList = [];

  window.onDomReady = function(fn) {
    bindRdy();
    if (isRdy){
      fn.call(document);
    } else {
      rdyList.push(function() {
        fn.call(document);
      });
    }
  };

  var rdy = function() {
    if (!isRdy) {
      isRdy = true;
      if (rdyList) {
        var l = rdyList;
        l.reverse();
        while (fn = l.pop()) {
          fn.apply(document);
        }
        rdyList = null;
      }
    }
  };

  var bindRdy = function() {
    if (rdyBnd) return;
      rdyBnd = true;

    if(document.addEventListener && !browser.opera)
      document.addEventListener("DOMContentLoaded", rdy, false);
    if (browser.msie && window == top) (function(){
        if (isRdy) return;
        try {document.documentElement.doScroll("left"); }
        catch (e) { setTimeout(arguments.callee,0); return; }
        rdy();
      })();
    if (browser.opera) document.addEventListener("DOMContentLoaded", function(){
      if (isRdy) return;
        rdy();
    }, false);
    if (browser.safari) {
      (function(){
        if(isRdy) return;
        if (document.readyState != "loaded" && document.readyState != "complete") {
          setTimeout(arguments.callee,0);
          return;
        }
        rdy();
      })();
    }
    addEvent(window, "load", rdy);
  }
})();

/**
 * Ajax
 **/
 function serializeForm(form) {
    if (typeof(form) != 'object') {
      return false;
    }
    var result = new Array();
    var g = function(n) {
      return form.getElementsByTagName(n)
    };
    var nv = function(i, e){
      if (e.name) result[e.name] = (browser.msie && !e.value) ? form[e.name].value : e.value;
    };
    each(g('input'), function(i, e) {
      if ((e.type != 'radio' && e.type != 'checkbox') || e.checked) return nv(i, e);
    });
    each(g('select'), nv);
    each(g('textarea'), nv);

    return result;
  }

 function Ajax(onDone, onFail, eval_res){
   var _t = this;
   this.onDone = onDone;
   this.onFail = onFail;
   var tram = null;
   try { tram = new XMLHttpRequest(); }
   catch(e) { tram = null; }
   if (!tram) {
    try { if(!tram) tram = new ActiveXObject("Msxml2.XMLHTTP"); }
    catch(e) { tram = null; }
   }
   if (!tram) {
    try { if(!tram) tram = new ActiveXObject("Microsoft.XMLHTTP"); }
    catch(e) { tram = null; }
   }

   var readystatechange = function(url, data) {
      if(tram.readyState == 4 ) {
       if(tram.status >= 200 && tram.status < 300) {
         if(eval_res) parseRes();
         if( _t.onDone ) _t.onDone(extend(_t, {url: url, data: data}), tram.responseText);
       } else {
         if( _t.onFail ) _t.onFail(extend(_t, {url: url, data: data}), tram.responseText);
       }
     }
  };

   var parseRes = function(){
     if(!tram || !tram.responseText)return;
     var res = tram.responseText.replace(/^[\s\n]+/g, '');

     if(res.substr(0,10)=="<noscript>")
     {
       try{
         var arr = res.substr(10).split("</noscript>");
         eval(arr[0]);
         tram.responseText = arr[1];
       }catch(e){
         debugLog('eval ajax script:' + e.message);
       }
     }else{}
   };
   this.get = function(u, d, f){
     tram.onreadystatechange = function(){ readystatechange(u, d); };
     f = f || false;
     var q = (typeof(d) != 'string') ? ajx2q(d) : d;
     u = u + (q ? ('?'+q) : '');
     tram.open('GET', u, !f);

     tram.setRequestHeader("X-Requested-With", "XMLHttpRequest");
     tram.send('');
   };
   this.post = function(u, d, f){
     tram.onreadystatechange = function(){ readystatechange(u, d); };
     f = f || false;
     var q = (typeof(d) != 'string') ? ajx2q(d) : d;
     try {
       tram.open('POST', u, !f);
     } catch(e) {
       debugLog('ajax post error: '+e.message);
     }
     tram.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
     tram.setRequestHeader("X-Requested-With", "XMLHttpRequest");
     tram.send(q);
   };

 }

(function(){
  var ajaxObjs = {};
  window.Ajax.Get = function(p){
    var a = (p.key)?ajaxObjs[p.key]:null;
    if(!a){
      a = new Ajax(p.onDone, p.onFail, p.eval);
      if(p.key)ajaxObjs[p.key] = a;
    }
    a.get(p.url, p.query, p.sync);
  }
  window.Ajax.Post = function(p){
    var a = (p.key)?ajaxObjs[p.key]:null;
    if(!a){
      a = new Ajax(p.onDone, p.onFail, p.eval);
      if(p.key)ajaxObjs[p.key] = a;
    }
    a.post(p.url, p.query, p.sync);
  }
  window.Ajax.postWithCaptcha = function(url, data, options){
    var onSuccess, onFail, onCaptchaShow, onCaptchaHide;
    onSuccess = options.onSuccess;
    onFail = options.onFail;
    onCaptchaShow = options.onCaptchaShow;
    onCaptchaHide = options.onCaptchaHide;
    var difficulty = options.difficultCaptcha ? '' : 's=1&';
    var p = {
      url: url,
      query: data,
      onFail: function(ajaxObj, responseText) {
        if (isFunction(onFail)) onFail(ajaxObj, responseText);
        if (window.Ajax._captchaBox) {
          window.Ajax._captchaBox.setOptions({onHide: function(){}}).hide();
          if (isFunction(onCaptchaHide)) onCaptchaHide(true);
        }
      },
      onDone: function(ajaxObj, responseText) {
        var response;
        try {
        response = eval('(' + responseText + ')');
        if (response.ok && response.ok == -2) {
          if (window.Ajax._captchaBox == undefined) {
             window.Ajax._captchaBox = new MessageBox({title: getLang('captcha_enter_code'), width: 300});
          }
          var box = window.Ajax._captchaBox;
          box.removeButtons();
          var key;
          var onClick = function(){
           removeEvent(key, 'keypress');
           if (typeof(p.query) == 'object') {
             extend(p.query, {'captcha_sid': response.captcha_sid, 'captcha_key': key.value});
           } else {
             p.query += '&captcha_sid=' + response.captcha_sid + '&captcha_key=' + key.value;
           }
           Ajax.Post(p);
           hide('captchaKey');
           show('captchaLoader');
           return false;
          };
//          box.addButton({label: captcha_cancel, style: 'button_no', onClick: function(){
          box.addButton({label: getLang('captcha_cancel'), style: 'button_no', onClick: function(){
            removeEvent(key, 'keypress');
            box.hide();
          }});
//          box.addButton({label: captcha_send, onClick: onClick});
          box.addButton({label: getLang('captcha_send'), onClick: onClick});
          box.setOptions({onHide: onCaptchaHide});
          box.content('<div style="text-align: center; height: 76px"><a href="#" id="refreshCaptcha" title="Нажмите, чтобы обновить картинку"><img id="captchaImg" class="captchaImg" src="'+base_domain+'captcha.php?' + difficulty + 'sid=' + response.captcha_sid + '"/></a><div /><input id="captchaKey" name="captcha_key" type="text" style="width: 120px; margin: 3px 0px 0px;" maxlength="7"/><img id="captchaLoader" src="'+base_domain+'images/progress7.gif" style="display:none; margin-top: 13px;" /></div>');
          box.show();
          if (isFunction(onCaptchaShow)) onCaptchaShow();
          key = ge('captchaKey');
          addEvent(key, 'keypress', function(e){ if(e.keyCode==13){ onClick(); }});
          addEvent(ge('refreshCaptcha'), 'click', onClick);
          key.focus();
         } else {
            throw "Exit";
         }
       } catch (e) { // if captcha test passed
         if (response && typeof(response.text) == 'string')
           responseText = response.text;
         if (window.Ajax._captchaBox) {
           window.Ajax._captchaBox.setOptions({onHide: function(){}}).hide();
           if (isFunction(onCaptchaHide)) onCaptchaHide(true);
         }
         if (isFunction(onSuccess)) onSuccess(ajaxObj, responseText);
       }
      }
     };
    Ajax.Post(p);
  }
})();

 function ajx2q(qa)
 {
   var query = [], q, i =0;

   for (var key in qa) {
     if (qa[key] === undefined || qa[key] === null || typeof(qa[key]) == 'function') continue;
     if (isArray(qa[key])) {
       for (var i = 0; i < qa[key].length; ++i) {
         if (qa[key][i] === undefined || qa[key][i] === null || typeof(qa[key][i]) == 'function') continue;
         query.push(encodeURIComponent(key) + '[]=' + encodeURIComponent(qa[key][i]));
       }
     } else {
       query.push(encodeURIComponent(key) + '=' + encodeURIComponent(qa[key]));
     }
   }
   return query.join('&');
 }

 var ajaxHistory = $ah = new (function(){
   var _t = this;

   var curHash = "";
   var curHashes = {};
   var frame = null;
   var forceLoad = false;
   var order = null;

   //_t.frameLoading = false;
   _t.enabled = false;
   _t.useCache = true;
   _t.onLoad = {};
   _t.cache = {};

   var setHash = function(hash){
     hash = hash.replace("#","");
     if(location.hash != "#" + hash){
      debugLog('set: '+hash);
       location.hash = "#" + hash;
       if(browser.msie){
         frame.src = 'blank.html?ahHash='+encodeURIComponent(hash);
       }
     }
     return true;
   };
   var getHash = function(){
     if(!browser.msie)return location.hash.replace("#","");
     try{
       var hash = frame.contentWindow.document.location.search.match(/ahHash=(.*)$/);
       //var hash = frame.src.match(/ahHash=(.*)$/);
       return decodeURIComponent((hash && hash[1]) || "").replace("#","");
     }catch(e){return curHash;}
   };
   var splitHash = function(hash){
     if(!hash)return {};
     hash = hash.split("/");
     if(hash.length == 1){
       if(!_t.onLoad['default'])return {};
       if(_t.onLoad['default'].show)hash[0] = _t.onLoad['default'].show.from(hash[0]);
       return {'default':sortParams(hash[0])};
     }
     var parsed = {};
     for(var i=0;i<hash.length;i+=2){
       var h = hash[i];var p = hash[i+1];
       if(_t.onLoad[h].show){p = sortParams(_t.onLoad[h].show.from(p));}
       else{
         p = sortParams(p);
         if(!p && _t.onLoad[h])p = sortParams(_t.onLoad[h].def);
       }
       parsed[h] = p;
     }
     return parsed;
   };
   var joinHash = function(hash){
     var joined = [];
     var def = true;
     for(var i in hash){
       def = def && (i=='default');
       var p = sortParams(hash[i]);
       if(_t.onLoad[i].show){
         var p1 = _t.onLoad[i].show.to(splitParams(hash[i]));
         if(p1)p = p1;
       }
       joined.push(i + "/" + p);
     }
     if(def && joined[0])return joined[0].split("/")[1];
     return joined.sort().join("/");
   };
   var splitParams = function(params){
     if(!params)return {};
     if(typeof(params)!='string')return params;
     if(!/&|=/.test(params))return params;
     var vals = params.split("&");
     var p = {};
     for(var i=0;i<vals.length;i++){
       var v = vals[i].split("=");
       p[v[0]] = v[1];
     }
     return p;
   };
   var sortParams = function(params){
     if(typeof(params)=='number')return params+'';
     if(typeof(params)!='string'){
       params = ajx2q(params);
     }
     return params.split("&").sort().join("&");
   };

  var handler = function(){
    var origHash = getHash();
    if(origHash==curHash && !forceLoad)return;
    var state = splitHash(origHash);
    var hash = joinHash(state);
    if(hash != curHash || forceLoad){
      curHash = hash;
       var ordered = order || _t.onLoad;
      for(var i in ordered){
        if(order)i = ordered[i];
        var l = _t.onLoad[i];
        var p = state[i] || sortParams(l.def);
        if(p!=curHashes[i] || i == forceLoad){
          var addAuto = !forceLoad ? '&auto=1' : '';
          forceLoad = false;
          if(l.before && !l.before(splitParams(p))){
            curHashes[i] = p;
            continue;
          }
          if(!_t.cache[i])_t.cache[i] = {};
          if(!_t.useCache || !_t.cache[i][p]){
            _t.getData(l,i,p + addAuto,hash);
          }else if(l.done){
            l.done({}, _t.cache[i][p]);
          }
          curHashes[i] = p;
        }
      }
      if (browser.msie) {
        debugLog("fix hash: "+curHash);
        if(location.hash!='#' + curHash)
          location.hash = '#' + curHash;
      }
    }
  };

  var inited = false;
 _t.init = function(){
   if(!this.enabled || inited)return;
   inited = true;
   for(var i in _t.onLoad){
     var p = sortParams(_t.onLoad[i].def);
     curHashes[i] = p;
   };


   if(browser.msie){
     var initHash = encodeURIComponent(location.hash);
     frame = document.createElement('iframe');
     frame.style.position = 'absolute';
     frame.style.visibility  = 'hidden';
     frame.id = 'ahFrame';
     addEvent(frame, 'readystatechange', function() {
      if (this.contentWindow.document.readyState != 'complete') {
        return;
      }
      handler();
     });
     frame.src = "/blank.html?ahHash=" + initHash;
     document.body.appendChild(frame);
   } else {
     setInterval(handler,150);
   }
 };
 _t.go = function(s, params){
   if(params===undefined){params = s; s = 'default';}
   var state = splitHash(curHash);
   state[s] = sortParams(params);
   var hash = joinHash(state);
   setHash(hash);
   forceLoad = s;
 };
 _t.getData = function(loadObj, id, params, hash){
   var a = new Ajax(
   (function(l,i,p,t){return function(res,text){
     if(l.done)l.done(res,text);
     if(t.useCache)_t.cache[i][p] = text;
   };})(loadObj,id,params, _t),
   (function(l,i,p,t){return function(res,text){
     if(l.fail)l.fail(res,text);
   };})(loadObj,id,params, _t),
   true);
   a.post(loadObj.url, params );
 };
 _t.prepare = function(id, params){
   _t.enabled = true;
   if(params===undefined){params = id; id = 'default';}
   _t.onLoad[id] = params;
 };
 _t.validateHash = function(hash){return joinHash(splitHash(hash));};
 _t.clearCache = function(id){_t.cache[id] = {}};
 _t.setHash = function(s, hash){
  if(hash===undefined){hash = s; s = 'default';}
   hash = hash.replace("#","");
   if(location.hash != "#" + hash){
    debugLog('set1: '+hash);
     location.hash = "#" + hash;
     curHash = hash;
     curHashes[s] = curHash;
   }
 };
})();

onDomReady(function(){ajaxHistory.init()});


/**
 * Other trash
 **/

var send_request_url = 'http://userapi.com/data?';

var qCur = 0, qOn = 0, sOn = 0, qfOn = 0, qd = 0, l = 0, qa = 0, qfCur = -1, newSearch = 0;
/*var qArr = [[0,'по людям', '', 'people'],
[1,'по группам', '', 'groups'],
[2,'по событиям', '', 'events'],
[3,'по аудиозаписям', '', 'audio'],
[4,'по видеозаписям', '', 'video'],
[5,'по объявлениям', '', 'ads'],
[6,'по приложениям', '', 'apps'],
[7,'по вопросам', '', 'questions'],
[8,'по заметкам', '', 'notes'],
[9,'по темам', '', 'topics']];
*/
// now in langpack

reqs = []; res = [];
friends_l = [];
friends_arr = [];
floaded = false;

function doRequest(params, resultFunc) {
  var req = createRequest(params, resultFunc);
  sendRequest(req);
}

function createRequest(params, resultFunc) {
  var req = new Object();
  req.params = params;
  req.resultFunc = resultFunc;
  req.destroy = destroy;
  var rnum = Math.floor(Math.random()*1000);
  req.num = rnum;
  req.running = 1;
  reqs[rnum] = req;
  return req;
}

function getFriends() {
 doRequest('&id='+getCookie('remixmid')+'&act=friends&to=2500&w=50', gotFriends);
}

function gotFriends(result) {
 friends_arr = result;
 var l = friends_arr.length;
 for (var i = 0; i < l; i++) {
  friends_l[i] = friends_arr[i][1].toLowerCase();
 }
 floaded = true;
}

function friendNav(k) {
  if (k == 38) {
   if (qd) {if (qCur > 0) {qCur = qCur - 1} else {qCur = qArr.length-1} genQDrop(); return true}
   if (qfCur > -1) {qfrOn(qfCur-1)} else {qfrOn(l-1)}
   return true;
  }
  if (k == 40) {
   if (qd) {if (qCur < qArr.length-1) {qCur = qCur + 1} else {qCur = 0} genQDrop(); return true}
   if (qfCur < l - 1) {qfrOn(qfCur+1)} else {qfrOn(-1)}
   return true;
  }
  if (k == 13) {
   if (qd) {hideQDrop(qCur); return true;}
   if (!parseInt(qCur) && qfCur > -1 && res.length && res[qfCur] && res[qfCur][0]) {
    window.location = base_domain+'id'+res[qfCur][0];
    return true;
   } else {
    if (!newSearch) {
     qDoSearch();
    } else {
     globalSearch();
    }
    return false;
   }
  }
  return true;
 }

function friendFilter(e) {
 var k = 0;
 if (e) {
  k = e.keyCode;
  if (!friendNav(k)) {
    return;
  }
 }
 if (parseInt(qCur)) {return;}

 res = [];
 if (!floaded) {
  qfCur = -1;
  getFriends();
  setTimeout("friendFilter()", 700);
 }

 var st = 0, en = 0, img, cl, name, q_lat;
 var q = ge('qinput').value.toLowerCase();
 if (!q.length && k != 8) {
  return;
 }
 q_lat = parseLatin(q);
 l = friends_l.length;

 for (var i = 0; i < l; i++) {
  if (q.length && friends_l[i].indexOf(q) != -1) {
   res.push(friends_arr[i]);
  } else if (q_lat && q_lat.length && friends_l[i].indexOf(q_lat) != -1) {
   res.push(friends_arr[i]);
  }
 }

 var str = '', onl = '';
 l = res.length;


 if (l > 10) {l = 10;}
 if (l) {
  for (var i = 0; i < l; i++) {
   name = res[i][1];
   if (qfCur == i) {cl = 'qfr_cell_on'} else if (qfCur > -1 && qfCur == i - 1) {cl = 'qfr_cell_un'} else {cl = 'qfr_cell'}
   pos = name.toLowerCase().indexOf(q);
   if (pos == -1 && q_lat && q_lat.length) {
    q = q_lat;
    pos = name.toLowerCase().indexOf(q);
   }
   if (pos != -1) {
    if (res[i][2].length > 1) {img = "<img src='"+res[i][2]+"'>";} else {img = "?";}
    if (res[i][3]) {onl = "<b class='qonl'>online</b>";} else {onl = "";}
    name = name.substr(0, pos) + "<span>" + name.substr(pos, q.length) + "</span>" + name.substr(pos+q.length);
   }
   str += "<div id='qfr"+i+"' class='"+cl+"' onmousemove=\"qfrOn("+i+")\" onmouseout=\"qfrOff("+i+")\" onclick=\"window.location='"+base_domain+"id"+res[i][0]+"'\"><table border=0><tr><td><div>"+img+"</div></td><td>"+name+onl+"</td></tr></table></div>";
  }
  hideQDrop(qCur);
  show('qfriends');
 } else {hide('qfriends');}
 ge('qfriends').innerHTML = str;

}

function qfrOn(i) {
 if (qfCur > -1) {qfrOff(qfCur);}
 qfOn = 1; qfCur = i;
 if (ge('qfr'+i)) ge('qfr'+i).className = 'qfr_cell_on';
 if (ge('qfr'+(i+1))) {ge('qfr'+(i+1)).className = 'qfr_cell_un';}
}

function qfrOff(i) {
 qfOn = 0;
 if (ge('qfr'+i)) ge('qfr'+i).className = 'qfr_cell';
 if (ge('qfr'+(i+1))) {ge('qfr'+(i+1)).className = 'qfr_cell';}
}

function sendRequest(req) {
 attachScript('req'+req.num, send_request_url+req.params+'&sid='+getCookie('remixsid')+'&back=reqs['+req.num+'].resultFunc');
}

function attachScript(id, src) {
 var i;
 var newreqs = [];
 for (reqnum in reqs) {
  req = reqs[reqnum];
  if (req) {
   if (req.running == 0) {
    ge('req'+req.num).parentNode.removeChild(ge('req'+req.num));
    reqs[reqnum] = null;
   } else {
    newreqs[reqnum] = req;
   }
  }
 }
 reqs = newreqs;
 var element = document.createElement('script');
 element.type = 'text/javascript';
 element.src = src;
 element.id = id;
 document.getElementsByTagName('head')[0].appendChild(element);
}

function destroy() {
 if (reqs[this.num]) {
  reqs[this.num].running = 0;
 }
}

var _cookies;
function _initCookies() {
  _cookies = {};
  var ca = document.cookie.split(';');
  for(var i = 0; i < ca.length; i++) {
    var c = ca[i].split("=");
    if(c.length == 2) _cookies[c[0].match(/^[\s]*([^\s]+?)$/i)[1]] = unescape(c[1].match(/^[\s]*([^\s]+?)$/i)[1]);
  }
}
function getCookie(name) {
  if(!_cookies) _initCookies();
  return _cookies[name];
}
function setCookie(name, value, days) {
  if(!_cookies) _initCookies();
  _cookies[name] = value;
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  }
  else var expires = "";
  document.cookie = name+"="+escape(value)+expires+"; path=/";
}

function searchOn(obj) {
 hide('qfriends'); sOn = 1;
 var qq = ge('qquery');
 var ph = obj.getAttribute('placeholder');
 if (obj.value && obj.value != ph) {return;}
 hide('topNav');
 qq.style.width = '618px';
 obj.style.width = '448px'
 ge('quickSearch').style.width = '625px';
 obj.value = ''; var qs = qd ? 'qdrop_on' : 'qdrop_off';
 ge('qchoose').innerHTML = "<div onclick=\"showQDrop()\" id='qdrop' class='"+qs+"' onmouseover=\"qOn = 1;if (!qd) {this.className='qdrop_over'}\" onmouseout=\"setTimeout('startHide()',1200); qOn = 0;if (!qd) {this.className='qdrop_off'}\">"+qArr[qCur][1]+"</div>";
 genQDrop();
 obj.style.color = '#000'; if (!qa) showQDrop();
}

function genQDrop() {
 var str = '', qoff, qover, st = '';
 for (var i = 0; i < qArr.length; i++) {
  if (i == qArr.length-1) {st = "style='border-bottom: 1px solid ";if (i!=qCur){st+="#2A5883;'";}else{st+="#839EB7;'";}} else {st='';}
  if (i != qCur) {qoff = 'qdiv_off', qover = 'qdiv_over'; if (!i) {qover='qdiv_over_top';}} else {qoff = 'qdiv_on', qover = 'qdiv_on';}
  str += "<div onclick='hideQDrop("+i+")' class='"+qoff+"' onmouseover=\"qOn = 1; this.className='"+qover+"'\" onmouseout=\"setTimeout('startHide()',1200); qOn = 0; this.className='"+qoff+"'\" "+st+">"+qArr[i][1]+"</div>";
 }
 ge('qdropdown').innerHTML = str;
}

function startHide() {
 if (qOn) return;
 hideQDrop(qCur);
}

function showQDrop() {
 if (qd) {hideQDrop(qCur);return;}
 hide('qfriends');
 genQDrop();
 qd = 1; qa = 1;
 ge('qdrop').className = 'qdrop_on';
 ge('qdropdown').style.display = 'block';
 ge('qinput').focus();
}

function hideQDrop(i) {
 qOn = 0; qCur = i; qd = 0;
 if (ge('qdrop')) {
  ge('qdrop').innerHTML = qArr[i][1];
  ge('qdrop').className = 'qdrop_off';
  ge('qdropdown').style.display = 'none';
 }
 if (sOn) ge('qinput').focus();
}

function searchOut(qi) {
 if (qOn || qfOn) {return;}
 hide('qfriends'); sOn = 0;
 var ph = qi.getAttribute('placeholder');
 if (qi.value && qi.value != ph) {return;}
 ge('qchoose').innerHTML = "";
 var qq = ge('qquery');
 qi.style.color = '#777';
 qi.style.width = '85px';
 qq.style.width = '105px';
 ge('quickSearch').style.width = '112px';
 show('topNav');
 qi.value = ph; qa = 0; qd = 0;
 var qd = ge('qdropdown');
 qd.style.display = 'none';
}

function qDoSearch() {
 var qi = ge('qinput');
 var names_only = "";
 var ph = qi.getAttribute('placeholder');
 if (!qi.value || qi.value == ph) {return;}
 if (!qCur && qi.value) {names_only = "&c[name]=1";}
 window.location = base_domain+'gsearch.php?section='+qArr[qCur][3]+'#c[section]='+qArr[qCur][3]+names_only+'&c[q]='+qi.value;
}

function parseLatin(text){
  var outtext = text;
  var lat1 = ["yo","zh","kh","ts","ch","sch","shch","sh","eh","yu","ya","YO","ZH","KH","TS","CH","SCH","SHCH","SH","EH","YU","YA","'"];
  var rus1 = ["ё", "ж", "х", "ц", "ч", "щ",  "щ",   "ш", "э", "ю", "я", "Ё", "Ж", "Х", "Ц", "Ч", "Щ",  "Щ",   "Ш", "Э", "Ю", "Я", "ь"];
  for(var i=0;i<lat1.length;i++){
    outtext = outtext.split(lat1[i]).join(rus1[i]);
  }
  var lat2 = "abvgdezijklmnoprstufhcyABVGDEZIJKLMNOPRSTUFHCY" + "ёЁ";
  var rus2 = "абвгдезийклмнопрстуфхцыАБВГДЕЗИЙКЛМНОПРСТУФХЦЫ" + "еЕ";
  for(var i=0;i<lat2.length;i++){
    outtext = outtext.split(lat2[i]).join(rus2[i]);
  }
  return (outtext==text)?null:outtext;
}

function placeholderSetup(id) {
  var el = ge(id);
  if (!el || el.type != 'text') return;
  var ph = el.getAttribute("placeholder");
  if (ph && ph != "") {
    el['active'] = 1;
    if (!el.value && !el.focused) {
      el.style.color = '#777';
      el.value = ph;
      el['active'] = 0;
    }
    if (!el['phevents']) {
    addEvent(el, 'focus', function(){
      if (el['active']) return;
      el['active'] = 1;
      el.value = '';
      el.style.color = '#000';
    });
    addEvent(el, 'blur', function(){
      if( !el['active'] || !ph || el.value != "" ) return;
      el['active'] = 0;
      el.style.color = '#777';
      el.value = ph;
    });
    }
    el['phevents'] = 1;
  }
}

function setSelRange(id, from, to) {
  var el = ge(id);
  if (!el || (el.type != 'text' && el.tagName != 'textarea')) return;
  el.focus();
  if (el.createTextRange) {
    var range = el.createTextRange();
    range.collapse(true);
    range.moveEnd('character', from);
    range.moveStart('character', to);
    range.select();
  } else if (el.setSelectionRange) {
    el.setSelectionRange(from, to);
  }
}

function focusAtEnd(id) {
  var el = ge(id);
  if (!el || (el.type != 'text' && el.tagName != 'textarea')) return;
  setSelRange(el, el.value.length, el.value.length);
}

/**
 * Message box
 **/
var _message_box_guid = 0,
    _message_boxes = [],
    _message_box_shown = false,
    _show_flash_timeout;
function MessageBox(options) {
  var defaults = {
    type: "MESSAGE", // "MESSAGE" || "POPUP"
    hideOnClick: true,
    title: "Alert",
    width: "410px",
    height: "auto",
    bodyStyle: "",
    progress: false, // AntanubiS - Progress bar.
    returnHidden: false, // AntanubiS - When hide - return previously hidden box.
    hideFlash: true
  };

  options = extend(defaults, options);

  var buttonsCount = 0, body = document.getElementsByTagName('body')[0],
      transparentBG, boxContainer, boxBG, boxContainer, boxLayout, boxTitle, boxBody, boxControls, boxProgress, buttonYes, buttonNo,
      guid = _message_box_guid++, isVisible = false, hiddenBoxes = [];

  transparentBG = document.createElement('div');
  transparentBG.className = 'popup_transparent_bg';
  hide(transparentBG);

  //boxBG = document.createElement('div');
  //boxBG.className = 'popup_box_bg';
  //hide(boxBG);

  transparentBG.innerHTML = '<iframe class="box_frame"></iframe>';
  boxContainer = document.createElement('div');
  boxContainer.className = 'popup_box_container';
  hide(boxContainer);
  boxContainer.innerHTML = '<div class="box_layout"><div class="box_title_wrap"><div class="box_title"></div></div><div class="box_body" style="'+options.bodyStyle+'"></div><div class="box_controls_wrap"><div class="box_controls"></div></div></div>';

  boxFrame = geByClass('box_frame', transparentBG)[0];
  boxLayout = geByClass('box_layout', boxContainer)[0];
  boxTitle = geByClass('box_title', boxContainer)[0];
  boxBody = geByClass('box_body', boxContainer)[0];
  boxControls = geByClass('box_controls', boxContainer)[0];

  if (options.progress) {
    boxControls.innerHTML = '<img src="' + base_domain + 'images/progress7.gif" id="' + options.progress + '" style="display: none" />';
    boxProgress = boxControls.firstChild;
  } else {
    boxProgress = null;
  }

  transparentBG.style.height = getSize(document)[1] + 'px';
  addEvent(document, 'keydown', function(e) {
    if (e.keyCode == 27) {
      hideBox();
    }
  });

  onDomReady(function() {
    body.appendChild(transparentBG);
    body.appendChild(boxContainer);
    refreshCoords();
    refreshBox();
  });

  // Refresh box position
  function refreshCoords() {
    var height = window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight);
    containerSize = getSize(boxContainer);
    boxFrame.style.top =
    boxContainer.style.top = Math.max(document.documentElement.scrollTop,  body.scrollTop) + (height - containerSize[1]) / 3 + 'px';
    boxFrame.style.marginLeft =
    boxContainer.style.marginLeft =  - containerSize[0] / 2 + 'px';
    setStyle(boxFrame, 'width', containerSize[0]);
    setStyle(boxFrame, 'height', containerSize[1]);
  }

  // Add button
  function addButton(options) {
    buttonsCount++;
    if (typeof options != 'object') options = {};
    options = extend({
        label: 'Button' + buttonsCount,
        style: 'button_yes'
    }, options);

    var buttonWrap = document.createElement('div');
    buttonWrap.className = "button_wrap " + options.style;
    buttonWrap.innerHTML = '<div class="box_button" id="button' + guid + '_' + buttonsCount + '">' + options.label + '</div>';
    if (boxProgress) {
      boxControls.insertBefore(buttonWrap, boxProgress);
    } else {
      boxControls.appendChild(buttonWrap);
    }
    addEvent(buttonWrap, 'mouseover', function() {
      addClass(this.firstChild, 'button_hover');
    });
    addEvent(buttonWrap, 'mouseout', function() {
      removeClass(this.firstChild, 'button_hover');
    });
    if (isFunction(options.onClick)) {
      addEvent(buttonWrap, 'click', options.onClick);
    }
    return buttonWrap;
  }
  // Add custom controls text
  function addControlsText(text) {
    var textWrap = document.createElement('div');
    textWrap.className = "controls_wrap";
    textWrap.innerHTML = text;
    boxControls.appendChild(textWrap);
    return textWrap;
  }

  // Remove buttons
  function removeButtons() {
    buttonsCount = 0;
    boxControls.innerHTML = '';
  }

  // Refresh box properties
  function refreshBox() {
    // Set title
    boxTitle.innerHTML = options.title;

    // Set box dimensions
    boxContainer.style.width = typeof(options.width) == 'string' ? options.width : options.width + 'px';
    boxContainer.style.height = typeof(options.height) == 'string' ? options.height : options.height + 'px';

    // Switch box type
    removeClass(boxContainer, 'box_no_controls');
    removeClass(boxContainer, 'message_box');

    removeEvent(boxContainer, 'click');
    if (options.hideOnClick && options.type == 'POPUP') {
      addEvent(boxContainer, 'click', function(){
        hideBox();
      });
    }

    switch (options.type) {
      case 'POPUP':
        addClass(boxContainer, 'box_no_controls');
        addEvent(transparentBG, 'click', function(){
          hideBox();
        });
      break;

      case 'MESSAGE':
        addClass(boxContainer, 'message_box');
        removeEvent(transparentBG, 'click');
      break;
    }
  }

  // Show box
  function showBox() {
    if (isVisible) return;
    isVisible = true;
    hiddenBoxes = [];
    each(_message_boxes, function(box_guid, box) {
      if (box_guid != guid) {
        hiddenBoxes[guid] = guid;
        box.hide();
      }
    });
    // Show blocking background
    show(transparentBG);
    // Show box

//    fadeIn(boxContainer, 200);
    show(boxContainer); // AntanubiS - Video wall posting fails with fadeIn =(

    refreshCoords();

    // Hide all flash movies on the page
    if (options.hideFlash) {
      clearTimeout(_show_flash_timeout);
      each(body.getElementsByTagName('embed'), function(i, el) {
        el.style.visibility = 'hidden';
      });
      each(body.getElementsByTagName('object'), function(i, el) {
        el.style.visibility = 'hidden';
      });
    }

    if (options.onShow) {
      options.onShow();
    }
  }
  // Hide box
  function hideBox(speed) {
    if (!isVisible) return;
    isVisible = false;

    var onHide = function () {
      hide(boxContainer);
      hide(transparentBG);
      // Show all flash movies on the page
      if (options.hideFlash) {
       if (_show_flash_timeout) clearTimeout(_show_flash_timeout);
       _show_flash_timeout = setTimeout(function() {
         each(body.getElementsByTagName('embed'), function(i, el) {
          el.style.visibility = 'visible';
         });
         each(body.getElementsByTagName('object'), function(i, el) {
          el.style.visibility = 'visible';
         });
       }, 50);
      }
      if (options.returnHidden) {
        each(hiddenBoxes, function(box_guid) {
          if (box_guid != guid) {
            _message_boxes[box_guid].show();
          }
        });
      }
      if (options.onHide) options.onHide();
    }
    if (speed > 0) {
      fadeOut(boxContainer, speed, function(){
        onHide();
      });
    } else {
      onHide();
    }
  }

  var retBox = {
    guid: guid,
    // Show box
    show: function(speed) {
      showBox(speed); return this;
    },

    // Hide box
    hide: function(speed) {
      hideBox(speed); return this;
    },

    isVisible: function() {
      return this.isVisible;
    },

    // Insert html content into the box
    content: function(html) {
      boxBody.innerHTML = html;
      refreshCoords();
      return this;
    },

    // Load html content from URL
    loadContent: function(url, params) {
      var ajax = new Ajax(function(ajaxObj, responseText) {
         boxBody.innerHTML = responseText;
         refreshCoords();
         if (options.onLoad) options.onLoad(responseText);
      }, function(ajaxObj, responseText) {
        boxBody.innerHTML = 'Request error occured.';
        if (options.onLoadError) options.onLoadError(responseText);
      });
      // Show loader
      boxBody.innerHTML = '<div class="box_loader"></div>';

      // Load remote html using get request
      if (typeof params != 'object') params = {};
      ajax.post(url, params);

      return this;
    },

    // Add button
    addButton: function(options) {
      var btn = addButton(options);
      return (options.returnBtn) ? btn : this;
    },
    // Add
    addControlsText: function(text) {
      var el = addControlsText(text);
      return (options.returnBtn) ? el : this;
    },

    // Remove buttons
    removeButtons: function(options) {
      removeButtons();
      return this;
    },

    // Update box options
    setOptions: function(newOptions) {
      options = extend(options, newOptions);
      refreshBox();
      return this;
    }
  };
  _message_boxes[guid] = retBox;
  return retBox;
};

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;'>Здесь Вы можете ввести имя и фамилию</div>";
}


var PhotoTagger = function() {

	var that = this;
	this.pid = 0;
	var photoarea, photoarea_style;
	var photo, photo_w, photo_h, photo_w_percent, photo_h_percent;
	var photo_x = -1, photo_y = -1;
	var tagframe = null, tagframe_style, tagging = 0, dragging = 0;
	var tagframe_x, tagframe_y, tagframe_w, tagframe_h, tagframe_whalf, tagframe_hhalf;
	var tagframe_min_w = 30, tagframe_min_h = 30, new_frame_w = 100, new_frame_h = 100;
	var tagframespy = null, tagframespy_style, tagframespy_need_init = 1, frame_created = false;
	var nw_style, n_style, ne_style, w_style, e_style, sw_style, s_style, se_style;
	var x_offset, y_offset;
	var selector_style = null, selector_w, selector_need_init;
	var friends = [], current_friends = [], friends_subset = [], friends_html = "";
	var tagbox = null, tagbox_style, tagbox_shown = 0;
	var tagboxspy = null, tagboxspy_style, tagboxspy_need_init = 1;
	var fadedphoto = null, fadedphoto_style, fadedphoto_need_init = 1;
	var onmove_func = null;
	var tagname_style, tagname_shown = false;
	var tags_coordinates, need_process_coordinates = 0, displayed_tag = null;
	var ajax, reset_photo_timeout = 0, reset_photo_count = 0;
	var isIE = navigator.userAgent.indexOf("MSIE") != -1;

	this.tags = [];

	this.create = function(photo_id, tags_coords) {
//ge('pageHeader').innerHTML+="init<br>";
		that.reset(photo_id);
		that.processTagsCoordinates(tags_coords);
//		setTimeout(function(){addEvent(ge('photoarea'), 'onmousemove', that.showTagOnMove);}, 500);
//	setTimeout(function(){ge('photoarea').attachEvent('onmousemove', function(){alert('1');})}, 1000);
//		setTimeout(function(){addEvent(ge('photoarea'), 'mousemove', function(){alert("!!!");})}, 1);
//addEvent(window, 'load', function(){photoarea, 'mousemove', function(){alert("!!!");}});
//window.onLoad = function(){addEvent(ge('photoarea'), 'mousemove', function(){alert("!!!");})};
//		addEvent(ge('photoarea'), 'mousemove', function(){alert("!!!");});
//photoarea.onmousemove = "alert('1');";
		addEvent(photoarea, 'mousemove', that.showTagOnMove);
	}

	this.reset = function(photo_id) {
		that.tags = tags_coordinates = [];
		that.hideTag();
		that.hideTagBox();
		that.pid = photo_id;
		photoarea = ge('photoarea');
		photoarea_style = photoarea.style;
		photo = ge('myphoto');
		clearTimeout(reset_photo_timeout);
//		old_w = old_h = -1;
		need_process_coordinates = 0;
		photo_w = photo_h = photo_w_percent = photo_h_percent = 0;
		reset_photo_count = 0;
//setTimeout(function(){
		that.resetPhoto();
//}, 2000);
		tagframespy_need_init = 1;
		tagboxspy_need_init = 1;
		fadedphoto_need_init = 1;
		selector_need_init = 1;
		that.endTagging();
	}

	this.resetPhoto = function () {
		reset_photo_count++;
//opera.postError('resetting photo, ' + photo.width + ', ' + photo.height);
		if (reset_photo_count > 100 || (photo.width > 30 && photo.height > 20)) {
//ge('myphoto').height = '438';

//		if (old_w == photo.width && old_h == photo.height) {
/*
if (window.console){
	console.log('photo was reset with ' + photo.width + ', ' + photo.height + ' after ' + reset_photo_count);
}
if (window.opera) {
	opera.postError('photo was reset with ' + photo.width + ', ' + photo.height + ' after ' + reset_photo_count);
}
*/
			photo_w = photo.width;
			photo_h = photo.height;
			photo_w_percent = photo_w / 100.0;
			photo_h_percent = photo_h / 100.0;
			photoarea_style.width = photo_w + 'px';
			photoarea_style.height = photo_h + 'px';
			var xy = getXY(photoarea);
			photo_x = xy[0];
			photo_y = xy[1];
			if (need_process_coordinates) {
				that.processTagsCoordinates(tags_coordinates);
			}
//ge('pageHeader').innerHTML = "reset photo<br>";
			if (isIE) {
				ge('photoborder').style.display = 'none';
				ge('photoborder').style.display = '';
			}
//console.log("resetting to ", photo_w, photo_h);
		} else {
//			old_w = photo.width, old_h = photo.height;
			reset_photo_timeout = setTimeout(that.resetPhoto, 40 * reset_photo_count);
		}
	}

	this.showFadedPhoto = function() {
		if (!fadedphoto) {
			fadedphoto = ge('fadedphoto');
			fadedphoto_style = fadedphoto.style;
		}
		if (fadedphoto_need_init) {
			fadedphoto.style.width = photo_w + 'px';
			fadedphoto.style.height = photo_h + 'px';
			fadedphoto_need_init = 0;
		}
		fadedphoto_style.display = "block";
	}

	this.isFrameCreated = function() {
		return frame_created;
	}

	this.beginTagging = function(e) {
//console.profile();
		ge('photomsgwrap').innerHTML = '<div id="photomsg"><div id="message"><table id="tagging_message" width="100%"><tr><td align="left">Нажмите на любое место на фотографии, там будет ваша отметка.</td><td valign="middle" width="100px"><a href="javascript://" onClick="tagger.endTagging();">Готово</a></td></tr></table></div></div>';
		show('photomsgwrap');
		if (isIE) {
/*
			ge('photomsgwrap').style.height = '0px';
			ge('photomsgwrap').style.height = '';
			photoarea_style.height = photoarea_style.height;
*/
			photoarea_style.top = '1px';
			photoarea_style.top = '';
			//that.resetPhoto();
		}
		photo_y = getXY(photoarea)[1];
		window.photo_message = 1;
		window.scroll(0, getXY(ge('tagging_message'))[1] - 20);
		ge('myphotolink').onclick = function(e){return false;};
		ge('photoareaouter').onclick = function(e) {return cancelEvent(e);};
		photo.style.cursor = "crosshair";
		photoarea_style.cursor = "crosshair";
		removeEvent(photoarea, 'mousemove', that.showTagOnMove);
		addEvent(photoarea, 'mousedown', that.beginCreateFrame);
//		addEvent(photoarea, 'mousemove', that.creatingFrame);
//		addEvent(photoarea, 'mouseup', that.endCreateFrame);
		if (!tagframe) {
			tagframe = ge('tagframe');
			tagframe_style = tagframe.style;
			addEvent(tagframe, "mousedown", that.frameMouseDown);
			addEvent(ge('nw'), "mousedown", that.frameMouseDown);
			addEvent(ge('ne'), "mousedown", that.frameMouseDown);
			addEvent(ge('n'), "mousedown", that.frameMouseDown);
			addEvent(ge('w'), "mousedown", that.frameMouseDown);
			addEvent(ge('e'), "mousedown", that.frameMouseDown);
			addEvent(ge('sw'), "mousedown", that.frameMouseDown);
			addEvent(ge('s'), "mousedown", that.frameMouseDown);
			addEvent(ge('se'), "mousedown", that.frameMouseDown);
			addEvent(tagframe, "mouseup", that.frameMouseUp);
			addEvent(ge('nw'), "mouseup", that.frameMouseUp);
			addEvent(ge('ne'), "mouseup", that.frameMouseUp);
			addEvent(ge('n'), "mouseup", that.frameMouseUp);
			addEvent(ge('w'), "mouseup", that.frameMouseUp);
			addEvent(ge('e'), "mouseup", that.frameMouseUp);
			addEvent(ge('sw'), "mouseup", that.frameMouseUp);
			addEvent(ge('s'), "mouseup", that.frameMouseUp);
			addEvent(ge('se'), "mouseup", that.frameMouseUp);
			nw_style = ge('nw').style;
			n_style = ge('n').style;
			ne_style = ge('ne').style;
			w_style = ge('w').style;
			e_style = ge('e').style;
			sw_style = ge('sw').style;
			s_style = ge('s').style;
			se_style = ge('se').style;
		}
		if (!tagframespy) {
			tagframespy = ge('tagframespy');
			tagframespy_style = tagframespy.style;
		}
		if (tagframespy_need_init) {
			tagframespy.src = photo.src;
			tagframespy_need_init = 0;
		}
		if (!selector_style) {
			selector_style = ge('selector').style;
//			setTimeout(function() {
				that.initAjax(function(ajax, result) {
					eval(result);
					friends = fr.slice();
					current_friends = fr.slice();
//					that.fillSelector(current_friends);
					that.fillSelector();
				});
				ajax.get('/photos.php?act=get');
//			}, 50);
		} else if (selector_need_init) {
			current_friends = friends.slice();
//			that.fillSelector(current_friends);
			that.fillSelector();
		}
		tagging = 1;
//console.profileEnd();
	}

	this.endTagging = function(e) {
		if (!tagging) {
			return;
		}

		addEvent(photoarea, 'mousemove', that.showTagOnMove);
		removeEvent(photoarea, 'mousedown', that.beginCreateFrame);
		hide('photomsgwrap');
		if (isIE) {
			photoarea_style.top = '1px';
			photoarea_style.top = '';
		}
		photo_y = getXY(photoarea)[1];
		photo.style.cursor = "";
		photoarea_style.cursor = "";
		window.photo_message = 1;
		ge('myphotolink').onclick = "";
		if (window.nextPhoto) {
			ge('photoareaouter').onclick = nextPhoto;
		}
		tagframe_style.display = 'none';
		that.hideHelpers();
		if (fadedphoto_style) {
			fadedphoto_style.display = 'none';
		}
		selector_style.display = 'none';
		frame_created = false;
		ge('name').value = '';
		tagging = 0;
	}

	var begin_create_x, begin_create_y, was_created;

	this.beginCreateFrame = function(e) {
		if (e.button != 0 && e.button != 1) {
			return true;
		}
		selector_style.display = 'none';
		was_created = 0;
		begin_create_x = that.mousePosX(e);
		begin_create_y = that.mousePosY(e);
		addEvent(photoarea, 'mousemove', that.creatingFrame);
		addEvent(photoarea, 'mouseup', that.endCreateFrame);
		return cancelEvent(e);
	}

	this.creatingFrame = function(e) {
		if (!was_created) {
			var x = that.mousePosX(e), y = that.mousePosY(e);
			var handle = '', delta_x = x - begin_create_x, delta_y = y - begin_create_y, new_x, new_y;
			if (delta_x <= -5 && delta_y <= -5) {
				handle = 'nw';
				new_x = x; new_y = y;
			} else if (delta_x <= -5 && delta_y >= 5) {
				handle = 'sw';
				new_x = x; new_y = begin_create_y;
			} else if (delta_x >= 5 && delta_y <= -5) {
				handle = 'ne';
				new_x = begin_create_x; new_y = y;
			} else if (delta_x >= 5 && delta_y >= 5) {
				handle = 'se';
				new_x = begin_create_x; new_y = begin_create_y;
			}
			if (handle) {
				that.createFrame(e, new_x, new_y, Math.abs(x - begin_create_x), Math.abs(y - begin_create_y));
				that.frameMouseDown(e, handle);
				was_created = 1;
			}
		}
		return false;
	}

	this.endCreateFrame = function(e) {
		if (!was_created) {
			that.createFrame(e);
			was_created = 1;
		}
		return false;
	}

	this.createFrame = function(e, x, y, w, h) {


//console.profile();
		var mouse_x = x || that.mousePosX(e);
		var mouse_y = y || that.mousePosY(e);
		that.showFadedPhoto();
		that.updateFrameSize(w || Math.min(new_frame_w, photo_w), h || Math.min(new_frame_h, photo_h));
		that.updateFramePosition(mouse_x - photo_x - tagframe_whalf, mouse_y - photo_y - tagframe_hhalf);
		that.updateHelpers();
		tagframe_style.display = 'block';
		that.showHelpers();
		removeEvent(photoarea, 'mousemove', that.creatingFrame);
		removeEvent(photoarea, 'mouseup', that.endCreateFrame);
		if (!selector_w) {
			selector_w = ge('selector').clientWidth;
		}
		friends_subset = [];
		show('userlistlabel');
		that.updateSelectorPosition();
		selector_style.display = 'block';
		ge('name').focus();
		frame_created = true;
//console.profileEnd();
//console.log('creating');
		return false;
	}

	this.updateFrameSize = function(w, h) {
		if (w > -1) {
			tagframe_w = w;	tagframe_whalf = w / 2 | 0;
			tagframe_style.width = w + 'px';
//			ge('tagframespycontainer').style.width = w + 'px';
		}
		if (h > -1) {
			tagframe_h = h; tagframe_hhalf = h / 2 | 0;
			tagframe_style.height = h + 'px';
//			ge('tagframespycontainer').style.height = h + 'px';
		}
	}

	this.fixFrameSize = function() {
		var new_w = -1, new_h = -1, new_x = -1, new_y = -1;
		if (tagframe_w < tagframe_min_w) {
			new_w = Math.min(tagframe_min_w, photo_w);
		}
		if (tagframe_h < tagframe_min_h) {
			new_h = Math.min(tagframe_min_h, photo_h);
		}
		that.updateFrameSize(new_w, new_h);
		that.updateFramePosition(tagframe_x, tagframe_y);
		that.updateHelpers();
	}

	this.updateFramePosition = function(x, y) {
//	console.log(x, y, photo_w, tagframe_w, photo_h, tagframe_h);
		if (x != -1) {
			x = Math.min(photo_w - tagframe_w, Math.max(0, x));
			tagframe_x = x;
			tagframe_style.left = x + "px";
			tagframespy_style.left = -x + "px";
		}
		if (y != -1) {
			y = Math.min(photo_h - tagframe_h, Math.max(0, y));
			tagframe_y = y;
			tagframe_style.top = y + "px";
			tagframespy_style.top = -y + "px";
		}
	}

	this.showHelpers = function() {
		nw_style.display = 'block'; n_style.display = 'block'; ne_style.display = 'block'; w_style.display = 'block'; e_style.display = 'block'; sw_style.display = 'block'; s_style.display = 'block'; se_style.display = 'block';
	}

	this.updateHelpers = function() {
		nw_style.left = tagframe_x - 5 + 'px';
		nw_style.top = tagframe_y - 5 + 'px';
		n_style.left = tagframe_x + tagframe_whalf - 5 + "px";
		n_style.top = tagframe_y - 5 + 'px';
		ne_style.left = tagframe_x + tagframe_w - 5 + 'px';
		ne_style.top = tagframe_y - 5 + 'px';
		w_style.left = tagframe_x - 5 + "px";
		w_style.top = tagframe_y + tagframe_hhalf - 5 + "px";
		e_style.left = tagframe_x + tagframe_w - 5 + "px";
		e_style.top = tagframe_y + tagframe_hhalf - 5 + "px";
		sw_style.left = tagframe_x - 5 + 'px';
		sw_style.top = tagframe_y + tagframe_h - 5 + 'px';
		s_style.left = tagframe_x + tagframe_whalf - 5 + "px";
		s_style.top = tagframe_y + tagframe_h - 5 + 'px';
		se_style.left = tagframe_x + tagframe_w - 5 + 'px';
		se_style.top = tagframe_y + tagframe_h - 5 + 'px';
	}

	this.hideHelpers = function(exclude) {
		nw_style.display = 'none'; n_style.display = 'none'; ne_style.display = 'none'; w_style.display = 'none'; e_style.display = 'none'; sw_style.display = 'none'; s_style.display = 'none'; se_style.display = 'none';
		if (exclude) {
			exclude.display = 'block';
		}
	}

	this.updateSelectorPosition = function() {
		if (tagframe_x + tagframe_w + 20 + selector_w < photo_w + 113) {
			selector_style.left = photo_x + tagframe_x + tagframe_w + 20 + 'px';
		} else {
			selector_style.left = photo_x + tagframe_x - 20 - selector_w + 'px';
		}
		selector_style.top = photo_y + tagframe_y + 'px';
	}

var w_stub = 0, h_stub = 0;
		var saved_tagframe_x, saved_tagframe_y;
		var saved_tagframe_w, saved_tagframe_h;



	this.frameMouseDown = function(e, target_id) {
		if (e.button != 0 && e.button != 1) {
			return true;
		}
		var target = null;
		if (!target_id) {
			target = (e.srcElement) ? e.srcElement : e.target;
			target_id = target.id == '' ? target.parentNode.id : target.id;
		}
//console.log(targetid);

		saved_tagframe_x = tagframe_x, saved_tagframe_y = tagframe_y;
		saved_tagframe_w = tagframe_w, saved_tagframe_h = tagframe_h;

		switch(target_id) {
			case 'tagframespy':
			case 'nw':
			case 'n':
			case 'ne':
			case 'w':
			case 'e':
			case 'sw':
			case 's':
			case "se":
//				that.hideHelpers((target || ge(target_id)).style);
				that.hideHelpers();
//			nw_style.display = 'none'; n_style.display = 'none'; ne_style.display = 'none'; w_style.display = 'none'; e_style.display = 'none'; sw_style.display = 'none'; s_style.display = 'none'; se_style.display = 'none';
				that.setMoveFunction(target_id, e);
				removeEvent(photoarea, 'mousedown', that.beginCreateFrame);
				addEvent(document.body, 'mouseup', that.frameMouseUp);
				addEvent(document.body, 'dragend', that.frameMouseUp);
				selector_style.display = 'none';
				dragging = 1;
		}

		return cancelEvent(e);
	}

	var preonmove_functions = {
		'tagframespy': function(e) {
				x_offset = tagframe_x - that.mousePosX(e);
				y_offset = tagframe_y - that.mousePosY(e);
				photoarea_style.cursor = "move";
				onmove_func = that.frameMouseMove;
			},
		'nw': function(e) {
//				hideHelpers('nw');
//				current_helper = h_nw;
				if (e) {
					x_offset = tagframe_x + photo_x - that.mousePosX(e);
					y_offset = tagframe_y + photo_y - that.mousePosY(e);
				}
				tagframe_style.cursor = photoarea_style.cursor = 'nw-resize';
				onmove_func = function (e) {
					var no_change = true;
					var x = that.mousePosX(e) - photo_x + x_offset;
					var y = that.mousePosY(e) - photo_y + y_offset;
					var x_norm = Math.min(tagframe_x + tagframe_w - w_stub, Math.max(0, x));
					var y_norm = Math.min(tagframe_y + tagframe_h - h_stub, Math.max(0, y));
					if (x > x_norm) {
						that.updateFrameSize(0, saved_tagframe_h + saved_tagframe_y - y_norm);
						that.updateFramePosition(x_norm, y_norm);
						that.setMoveFunction('ne');
						no_change = false;
					}
					if (y > y_norm) {
						that.updateFrameSize(saved_tagframe_w + saved_tagframe_x - x_norm, 0);
						that.updateFramePosition(x_norm, y_norm);
						that.setMoveFunction('sw');
						no_change = false;
					}
					if (no_change) {
						that.updateFrameSize(saved_tagframe_w + saved_tagframe_x - x_norm, saved_tagframe_h + saved_tagframe_y - y_norm);
						that.updateFramePosition(x_norm, y_norm);
					}
					return cancelEvent(e);
				};
		},
		'n': function(e) {
//				hideHelpers(targetid);
//				current_helper = h_n;
				if (e) {
					y_offset = tagframe_y + photo_y - that.mousePosY(e);
				}
				tagframe_style.cursor = photoarea_style.cursor = 'n-resize';
				onmove_func = function (e) {
					var y = that.mousePosY(e) - photo_y + y_offset;
					var y_norm = Math.min(saved_tagframe_y + saved_tagframe_h, Math.max(0, y));
					if (y > y_norm) {
						that.updateFrameSize(-1, 0);
						that.updateFramePosition(-1, saved_tagframe_h + saved_tagframe_y);
						that.setMoveFunction('s');
					} else {
						that.updateFrameSize(-1, saved_tagframe_h + saved_tagframe_y - y_norm);
						that.updateFramePosition(-1, y_norm);
					}
					return cancelEvent(e);
				};
			},
		'ne': function(e) {
//				hideHelpers(targetid);
//				current_helper = h_ne;
				if (e) {
					x_offset = tagframe_x + photo_x + tagframe_w - that.mousePosX(e);
					y_offset = tagframe_y + photo_y - that.mousePosY(e);
				}
				tagframe_style.cursor = photoarea_style.cursor = 'ne-resize';
				onmove_func = function (e) {
					var no_change = true;
					var x = that.mousePosX(e) - photo_x + x_offset;
					var y = that.mousePosY(e) - photo_y + y_offset;
					var x_norm = Math.min(photo_w, Math.max(tagframe_x + w_stub, x));
					var y_norm = Math.min(saved_tagframe_y + saved_tagframe_h - h_stub, Math.max(0, y));
					if (x < x_norm) {
						that.updateFrameSize(0, saved_tagframe_h + saved_tagframe_y - y_norm);
						that.updateFramePosition(-1, y_norm);
						that.setMoveFunction('nw');
						no_change = false;
					}
					if (y > y_norm) {
						that.updateFrameSize(x_norm - saved_tagframe_x, saved_tagframe_h + saved_tagframe_y - y);
						that.updateFramePosition(-1, saved_tagframe_y + saved_tagframe_h);
						that.setMoveFunction('se');
						no_change = false;
					}
					if (no_change) {
						that.updateFrameSize(x_norm - saved_tagframe_x, saved_tagframe_h + saved_tagframe_y - y_norm);
						that.updateFramePosition(-1, y_norm);
					}
					return cancelEvent(e);
				};
			},
		'w': function(e) {
//				hideHelpers(targetid);
//				current_helper = h_w;
				if (e) {
					x_offset = tagframe_x + photo_x - that.mousePosX(e);
				}
				tagframe_style.cursor = photoarea_style.cursor = 'w-resize';
				onmove_func = function (e) {
					var x = that.mousePosX(e) - photo_x + x_offset;
					var x_norm = Math.min(saved_tagframe_x + saved_tagframe_w - w_stub, Math.max(0, x));
					if (x > x_norm) {
						that.updateFrameSize(0, -1);
						that.updateFramePosition(saved_tagframe_x + saved_tagframe_w, -1);
						that.setMoveFunction('e');
					} else {
						that.updateFrameSize(saved_tagframe_w + saved_tagframe_x - x_norm, -1);
						that.updateFramePosition(x_norm, -1);
					}
					return cancelEvent(e);
				};
			},
		'e': function(e) {
//				hideHelpers(targetid);
//				current_helper = h_e;
				if (e) {
				x_offset = tagframe_x + photo_x + tagframe_w - that.mousePosX(e);
				}
				tagframe_style.cursor = photoarea_style.cursor = 'e-resize';
				onmove_func = function (e) {
					var x = that.mousePosX(e) - photo_x + x_offset;
					var x_norm = Math.min(photo_w, Math.max(saved_tagframe_x + w_stub, x));
					if (x < x_norm) {
						that.updateFrameSize(0, -1);
						that.setMoveFunction('w');
					} else {
						that.updateFrameSize(x_norm - saved_tagframe_x, -1);
					}
					return cancelEvent(e);
				};
			},
		'sw': function(e) {
//				hideHelpers(targetid);
//				current_helper = h_sw;
				if (e) {
					x_offset = tagframe_x + photo_x - that.mousePosX(e);
					y_offset = tagframe_y + photo_y + tagframe_h - that.mousePosY(e);
				}
				tagframe_style.cursor = photoarea_style.cursor = 'sw-resize';
				onmove_func = function (e) {
					var no_change = true;
					var x = that.mousePosX(e) - photo_x + x_offset;
					var y = that.mousePosY(e) - photo_y + y_offset;
					var x_norm = Math.min(saved_tagframe_x + saved_tagframe_w - w_stub, Math.max(0, x));
					var y_norm = Math.min(photo_h, Math.max(tagframe_y + h_stub, y));
					if (x > x_norm) {
						that.updateFrameSize(0, y_norm - saved_tagframe_y);
						that.updateFramePosition(saved_tagframe_x + saved_tagframe_w, -1);
						that.setMoveFunction('se');
						no_change = false;
					}
					if (y < y_norm) {
						that.updateFrameSize(saved_tagframe_x - x_norm + saved_tagframe_w, 0);
						that.updateFramePosition(x_norm, -1);
						that.setMoveFunction('nw');
						no_change = false;
					}
					if (no_change) {
						that.updateFrameSize(saved_tagframe_x - x_norm + saved_tagframe_w, y_norm - saved_tagframe_y);
						that.updateFramePosition(x_norm, -1);
					}
					return cancelEvent(e);
				};
			},
		's': function(e) {
//				hideHelpers(targetid);
//				current_helper = h_s;
				if (e) {
					y_offset = tagframe_y + photo_y + tagframe_h - that.mousePosY(e);
				}
				tagframe_style.cursor = photoarea_style.cursor = 's-resize';
				onmove_func = function (e) {
					var y = that.mousePosY(e) - photo_y + y_offset;
					var y_norm = Math.min(photo_h, Math.max(saved_tagframe_y, y));
					if (y < y_norm) {
						that.updateFrameSize(-1, 0);
						that.updateFramePosition(-1, saved_tagframe_y);
						that.setMoveFunction('n');
					} else {
						that.updateFrameSize(-1, y_norm - saved_tagframe_y);
					}
					return cancelEvent(e);
				};
			},
		'se': function(e) {
//				hideHelpers(targetid);
//				current_helper = h_se;
				if (e) {
					x_offset = tagframe_x + photo_x + tagframe_w - that.mousePosX(e);
					y_offset = tagframe_y + photo_y + tagframe_h - that.mousePosY(e);
				}
				tagframe_style.cursor = photoarea_style.cursor = 'se-resize';
				onmove_func = function (e) {
					var no_change = true;
					var x = that.mousePosX(e) - photo_x + x_offset;
					var y = that.mousePosY(e) - photo_y + y_offset;
					var x_norm = Math.min(photo_w, Math.max(tagframe_x + w_stub, x));
					var y_norm = Math.min(photo_h, Math.max(tagframe_y + h_stub, y));
					if (x < x_norm) {
						that.updateFrameSize(0, y_norm - saved_tagframe_y);
						that.setMoveFunction('sw');
						no_change = false;
					}
					if (y < y_norm) {
						that.updateFrameSize(x_norm - saved_tagframe_x, 0);
						that.setMoveFunction('ne');
						no_change = false;
					}
					if (no_change) {
						that.updateFrameSize(x_norm - saved_tagframe_x, y_norm - saved_tagframe_y);
					}
//					that.updateFramePosition(saved_tagframe_x, saved_tagframe_y);
					return cancelEvent(e);
				};
			}
	};

	this.setMoveFunction = function(index, e) {
		saved_tagframe_x = tagframe_x, saved_tagframe_y = tagframe_y;
		saved_tagframe_w = tagframe_w, saved_tagframe_h = tagframe_h;
		if (onmove_func) {
			removeEvent(document.body, 'mousemove', onmove_func);
			removeEvent(document.body, 'drag', onmove_func);
		}
		preonmove_functions[index](e);
//console.log(onmove_func);
		addEvent(document.body, 'mousemove', onmove_func);
		addEvent(document.body, 'drag', onmove_func);
	}

	this.frameMouseMove = function(e) {
		var mouse_x = that.mousePosX(e);
		var mouse_y = that.mousePosY(e);
		that.updateFramePosition(mouse_x + x_offset, mouse_y + y_offset);
		return cancelEvent(e);
	}

	this.frameMouseUp = function(e) {
		if (e.button == 2 && !isIE) {
			tagframe_style.display = 'none';
			that.hideHelpers();
			fadedphoto_style.display = 'none';
			selector_style.display = 'none';
			frame_created = false;
		}
		if (dragging) {
//console.log('here');
			tagframe_style.cursor = '';
			photoarea_style.cursor = 'crosshair';
			removeEvent(document.body, 'mousemove', onmove_func);
			removeEvent(document.body, 'drag', onmove_func);
			removeEvent(document.body, 'mouseup', that.frameMouseUp);
			removeEvent(document.body, 'dragend', that.frameMouseUp);
			setTimeout(function(){
				addEvent(photoarea, 'mousedown', that.beginCreateFrame);
	//			addEvent(photoarea, 'mousemove', that.creatingFrame);
	//			addEvent(photoarea, 'mouseup', that.endCreateFrame);
			});
			that.fixFrameSize();
			dragging = 0;
			that.updateSelectorPosition();
			that.updateHelpers();
			that.showHelpers();
			selector_style.display = 'block';
		}
		return cancelEvent(e);
	}

	this.fillSelector = function(friends_array) {
//console.profile("2");
		if (friends_array || !friends_html.length) {
//console.debug("building html");
			var friend, i = 0, str = "", checked = (friends_array && friends_array.length == 1) ? "checked" : "";
			friends_array = friends_array || friends;
			while(friend = friends_array[i++]) {
				str += '<input id="f'+ i +'" type="checkbox" '+ checked +' value="'+ friend.id +'" friend="'+ friend.name +'" onclick="tagger.submitTag('+ (friend.index || i-1) +');"/><label for="f'+ i +'">'+ friend.name +'</label><br/>';
				if (i == 1 && friend.id == friends[0].id) {
					str += "<hr/>";
				}
			}
			if (!friends_array) {
				friends_html = str;
			}
		}
		ge('userlist').innerHTML = str;
		selector_need_init = 0;
//console.profileEnd("2");
	}

	this.refineSelector = function(e) {
		var value = (e.target || e.srcElement).value;
		switch(e.keyCode) {
			case 16: case 17: case 18: case 35: case 36: case 37: case 38: case 39: case 40: return; break;
			case 13: that.submitInput(value); return;
			case 27: that.endTagging();
		}
		var i = 0, friend, term = value.toLowerCase();
		friends_subset = [];
		while(friend = current_friends[i++]) {
			if (friend.name_lowered.indexOf(term) != -1) {
				friend.index = i - 1;
				friends_subset.push(friend);
			}
		}
		if (!friends_subset.length) {
			hide('userlistlabel');
		} else {
			show('userlistlabel');
		}
		that.fillSelector(friends_subset);
	}

	this.submitTag = function(friend_index, tag_text ) {

//console.profile("1");
		var x1_percent = tagframe_x / photo_w * 100;
		var y1_percent = tagframe_y / photo_h * 100;
		var x2_percent = (tagframe_x + tagframe_w) / photo_w * 100;
		var y2_percent = (tagframe_y + tagframe_h) / photo_h * 100;
		new_frame_w = tagframe_w;
		new_frame_h = tagframe_h;

//		tag_coords.push(new Array(tfX, tfY, tfX + tfW, tfY + tfH, activePersonID, activePersonName));
//		lastAddedTag = tag_coords.length - 1;

		show("selector_progressbar");
		hide("selector_buttons");
//hide('tagging_instructions_status_message');
//		ajax.post(ajax_setter_uri, params);

		//remove that id from the tagging list
		var friend;
		if (!tag_text) {
			friend = current_friends[friend_index];
//			current_friends.splice(friend_index, 1);
		} else {
			friend = {id: 0, name: tag_text};
		}
		//removeTagOption(activePersonName, activePersonID);


		params = {'pid': that.pid, 'subject': friend.id, 'name': friend.name, 'add': 1, 'x': x1_percent, 'y': y1_percent, 'x2': x2_percent, 'y2': y2_percent};

		photo_win( urlwork() + '&command=Q&Q=' + tag_text + '&I=' + document.getElementById('pid__').value + '&X=' + x1_percent  + '-' + y1_percent + '-' + x2_percent  + '-' + y2_percent , 'addotm', 200, 150 );

//console.log(params);
		that.initAjax(function() {
			var new_tag_coordinate = [tagframe_x, tagframe_y, tagframe_x + tagframe_w, tagframe_y + tagframe_h, friend.id, friend.name];
			return function(ajax, result){
				var new_tag_id = result.split('!')[0];
				new_tag_coordinate.push(new_tag_id | 0);
				result = result.substr(new_tag_id.length + 1);
				ge('phototags_wrap').innerHTML = '<div id="phototags">'+result+'</div>';
				hide("selector_progressbar");
				show("selector_buttons");
				var i = 0, tag;
				while(tag = tags_coordinates[i++]) {
					if (tag[4] == new_tag_coordinate[4]) {
						tags_coordinates.splice(i-1, 1);
						break;
					}
				}
				tags_coordinates.push(new_tag_coordinate);
			};
		}());
		ajax.post('/photos.php?act=put', params);




		tagframe_style.display = 'none';
		that.hideHelpers();
		fadedphoto_style.display = 'none';
		selector_style.display = 'none';
		frame_created = false;
		ge('name').value = '';
//		that.fillSelector(current_friends);
		that.fillSelector();
//console.profileEnd("1");
	}

	this.submitInput = function(value) {

		if (friends_subset.length == 1) {
			that.submitTag(friends_subset[0].index);
		} else if (value.length > 0) {
			that.submitTag(0, value);
		} else {
			return;
		}
	}

	this.confirmTag = function(id) {
		that.initAjax(function() {
			hide('msg');
		});
		ajax.post('/photos.php?act=a_confirm_tag', 'id=' + id);
	}

	this.removeTag = function(tag_id, photo_id) {
		var i = 0, tag;
		while(tag = tags_coordinates[i++]) {
			if (tag[6] == tag_id) {
				tags_coordinates.splice(i-1, 1);
				break;
			}
		}
		that.hideTagBox();
		that.initAjax(function(ajax, result) {
			var new_phototags = "";
			if (result.length) {
				new_phototags = '<div id="phototags">'+result+'</div>';
			}
			ge('phototags_wrap').innerHTML = new_phototags;
		});
		ajax.post('/photos.php?act=put', {'pid': photo_id, 'tag_id': tag_id});
		return false;
	}

	this.processTagsCoordinates = function(tags_coords) {
		var i = 0, tag;
		tags_coordinates = tags_coords;
		if (photo_w == 0 || photo_h == 0) {
			need_process_coordinates = 1;
			return;
		}
		need_process_coordinates = 0;
//console.log("processing with ", photo_w, photo_h);
//console.log(tags_coordinates, photo_w, photo_h);
		while(tag = tags_coordinates[i++]) {
			tag[0] = Math.round(tag[0] * photo_w / 100);
			tag[1] = Math.round(tag[1] * photo_h / 100);
			tag[2] = Math.round(tag[2] * photo_w / 100);
			tag[3] = Math.round(tag[3] * photo_h / 100);
			if (!tag[2]) {
				tag[0] -= 83;
				tag[2] = tag[0] + 166;
			}
			if (!tag[3]) {
				tag[1] -= 83;
				tag[3] = tag[1] + 166;
			}
		}
//console.log(tags_coordinates);
	}

	this.showTagOnMove = function(e) {
//console.log('moving');
		if (need_process_coordinates) {
			return;
		}
		var evt = e || window.event;
//ge('pageHeader').innerHTML+=e.layerX + ", " + e.layerY+"<br>";
//ge('pageHeader').innerHTML+="moving<br>";
		var x = that.mousePosX(evt) - photo_x, y = that.mousePosY(evt) - photo_y;
//console.log(x, y);
//ge('pageHeader').innerHTML = x +", "+y + ",,,,, " + that.mousePosX(evt) +", "+ findX(photoarea);
		if (displayed_tag && x >= displayed_tag[0] && y >= displayed_tag[1] && x <= displayed_tag[2] && y <= displayed_tag[3]) {
			return;
		}
		var i = 0, tag, found = false;
		while(tag = tags_coordinates[i++]) {
      if (i > 100) {
        break;
      }
//console.log(tag);
			if (x >= tag[0] && y >= tag[1] && x <= tag[2] && y <= tag[3]) {
				if (!tagname_style) {
					tagname_style = ge('tagname').style;
				}
//console.log(tag);
				displayed_tag = tag;
				tagname_style.visibility = 'hidden';
				tagname_style.display = 'block';
				tagname_style.left = tag[0] + 'px';
				tagname_style.top = tag[3] + 'px';
				tagname_style.width = '';
				var tagname = ge('tagname');
				if (tag[4]) {
					tagname.innerHTML = '<a id="tagnamelink" href="/id'+ tag[4] +'" onClick="window.location=\'/id'+ tag[4] +'\';return cancelEvent(event);">' + tag[5] + '</a>';
				} else {
					tagname.innerHTML = tag[5];
				}
				if (tagname.clientWidth > tag[2] - tag[0] - 6) {
					if (tag[4]) {
						tagname.innerHTML = '<a id="tagnamelink" href="/id'+ tag[4] +'" onClick="window.location=\'/id'+ tag[4] +'\';return cancelEvent(event);">' + tag[5].replace(/ /, "<br/>") + '</a>';
					} else {
						tagname.innerHTML = tag[5].replace(/ /, "<br/>");
					}
					if (tagname.clientWidth > tag[2] - tag[0] - 6) {
						if (tagname.clientWidth + tag[0] > photo_w) {
							tagname_style.left = photo_w - tagname.clientWidth + 'px';
						}
					} else {
						tagname_style.width = tag[2] - tag[0] - 6 + 'px';
					}
				} else {
					tagname_style.width = tag[2] - tag[0] - 6 + 'px';
				}
				if (tagname.clientHeight + tag[3] > photo_h) {
					tagname_style.top = photo_h - tagname.clientHeight + 'px';
				}
				tagname_style.visibility = 'visible';
//ge('pageHeader').innerHTML = "showing at: " +tag[0] +", "+tag[3];
				found = true;
			}
		}
		if (!found) {
			that.hideTag();
		}
	}

	this.hideTag = function() {
		if (displayed_tag) {
			displayed_tag = null;
			tagname_style.display = 'none';
		}
	}

	this.checkTagHide = function(e) {
		var target = e.relatedTarget || e.toElement;
		if (!target) {
			return;
		}
		if (target.id && target.id != "tagname" && target.id != "tagnamelink") {
			that.hideTag();
		}
	}

	this.showTagBox = function(x1, y1, x2, y2) {
		if (frame_created || photo_w == 0 || photo_h == 0) {
			return;
		}
		if (!tagbox) {
			tagbox = ge('tagbox');
			tagbox_style = tagbox.style;
		}
		if (!tagboxspy) {
			tagboxspy = ge('tagboxspy');
		}
		if (tagboxspy_need_init) {
			tagboxspy.src = photo.src;
			tagboxspy_style = tagboxspy.style;
			tagboxspy_need_init = 0;
		}

		x1 = Math.max(0, (photo_w_percent * x1 | 0) - 3);
		y1 = Math.max(0, (photo_h_percent * y1 | 0) - 3);
		x2 = Math.min(photo_w - x1 - 6, (photo_w_percent * x2 | 0) - x1 - 3);
		y2 = Math.min(photo_h - y1 - 6, (photo_h_percent * y2 | 0) - y1 - 3);

//		x1 = 0;
//		x2 = photo_w;
//		y1 = 0;
//		y2 = photo_h;

		that.showFadedPhoto();
		tagbox_style.display = 'block';
		tagbox_style.left = x1 + 'px';
		tagbox_style.top = y1 + 'px';
		tagbox_style.width = x2 + 'px';
		tagbox_style.height = y2 + 'px';
/*
		tagbox_style.left = Math.max(0, x1 - 3 | 0) + 'px';
		tagbox_style.top = Math.max(0, y1 - 3 | 0) + 'px';
		tagbox_style.width = Math.min(photo_w, (x2 - x1 | 0)) + 'px';
		tagbox_style.height = Math.min(photo_h, (y2 - y1 | 0)) + 'px';
*/
		tagboxspy_style.left = (-x1 - 3) + 'px';
		tagboxspy_style.top = (-y1 - 3) + 'px';

		tagbox_shown = 1;
	}

	this.hideTagBox = function(e) {
//return;
		if (!tagbox_shown) {
			return;
		}

		if (e) {
			var target = (e.srcElement) ? e.srcElement : e.target;
			if (target.tagName != "A") {
				return;
			}
		}

		tagbox_style.display = 'none';
		fadedphoto_style.display = 'none';
		tagbox_shown = 0;
	}

	this.initAjax = function(onDone, onFail) {
//		ajax = new Ajax(onDone, onFail);
//		return;
		if (!ajax) {
			ajax = new Ajax(onDone, onFail);
		} else {
			ajax.onDone = onDone || null;
			ajax.onFail = onFail || null;
		}
	}

	/*
	if(!browser.msie) {
		this.mousePosX = mousePosX;
		this.mousePosY = mousePosY;
	} else {
		this.mousePosX = function(e) { return mousePosX(e) - 2; }
		this.mousePosY = function(e) { return mousePosY(e) - 2; }
	}
	*/
	this.mousePosX = function(e) { return e.pageX; }
	this.mousePosY = function(e) { return e.pageY; }
}

tagger = new PhotoTagger();
