
function set_errorfield(name,message){

var el = document.getElementById(name);
if (!el) return;
el.className = 'formError';

if(el.tagName.toUpperCase() == 'TR'){
cell_index = el.cells.length > 1? 1 : el.cells.length - 1;
if (cell_index >= 0) {
el.cells[cell_index].className = 'formError';
el.cells[cell_index].innerHTML = el.cells[cell_index].innerHTML+'<br><font color=red>'+message+'</font>';
}
}else if(el.tagName.toUpperCase() == 'TD'){
el.innerHTML = el.innerHTML+'<br><font color=red>'+message+'</font>';
}
}

function menu(id){
var el = document.getElementById(id);
if(el.style.display=='none'){
  el.style.display= 'block';
  img = document.getElementById(id+'_img');
  if(img) img.src='http://static.album.bg/images/arru.gif';
  SetCookie('vm_'+id,'block');
}
else{
 el.style.display= 'none';
  img = document.getElementById(id+'_img');
  if(img) img.src='http://static.album.bg/images/arrd.gif';
  SetCookie('vm_'+id,'none');
}

}

function setCookie(sName, sValue,sTime)
{
    document.cookie = sName + "=" + escape(sValue) + "; path=/";
}

function getCookie(name){
    var dc = document.cookie;
    var prefix = name + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1){
        begin = dc.indexOf(prefix);
        if (begin != 0) return null;
    }
    else{
        begin += 2;
    }
    var end = document.cookie.indexOf(";", begin);
    if (end == -1){
        end = dc.length;
    }
    return unescape(dc.substring(begin + prefix.length, end));
}

function d(el){
return document.getElementById(el);
}

function _nl2br(mess){
mess = mess.replace(/\r\n|\n/gim,"<br />");
return mess;
}
function _br2nl(str){
str = str.replace(/<br.{0,3}>/gim,"\n");
return str;
}
function html_entity_decode(str) {
    try {
var tarea = document.createElement('textarea');
tarea.innerHTML = str;
return tarea.value;
} catch (e) {
// for IE add <div id="htmlconverter" style="display:none;"></div> to the page
document.getElementById("htmlconverter").innerHTML = '<textarea id="innerConverter">' + str + '</textarea>';
var content = document.getElementById("innerConverter").value;
document.getElementById("htmlconverter").innerHTML = "";
return content;
}
}
// TODO: rewrite this function with a better and a more complete one
function htmlspecialchars(s) {
var str = new String(s);
str = str.replace(/&/g, "&amp;");
str = str.replace(/\</g, "&lt;");
str = str.replace(/\>/g, "&gt;");
str = str.replace(/"/g, "&quot;");
return str;
}

function getAge(date){
d = new Date();
var server_time_offset = 0;
if(Current.get('server_time_offset')) server_times_offset = Current.get('server_time_offset');

var curr = d.getTime()/1000;

d.setFullYear(date.substring(0,4));
d.setMonth(date.substring(5,7)-1);
d.setDate(date.substring(8,10));
d.setHours(date.substring(11,13));
d.setMinutes(date.substring(14,16));
d.setSeconds(date.substring(17,19));

date = d.getTime()/1000;
var diff = curr-date+server_time_offset;
if(diff<0) diff =0;
var iv ='';
var sv = '';
if(diff > 2*365*24*3600){
iv = Math.round(diff/(356*24*3600)); sv = (iv != 1 ? 'години' : 'година');
}else if(diff > 30*24*3600){
iv = Math.round(diff/(30*24*3600)); sv = (iv != 1? 'месеца' : 'месец');
}else if(diff > 7*24*3600){
iv = Math.round(diff/(7*24*3600)); sv = (iv != 1? 'седмици' : 'седмица');
}else if(diff > 1*24*3600){
iv = Math.round(diff/(24*3600)); sv = (iv != 1? 'дни' : 'ден');
}else if(diff > 3600){
iv = Math.round(diff/(3600)); sv = (iv != 1? 'часа' : 'час');
}else if(diff > 60){
iv = Math.round(diff/(60)); sv = (iv != 1? 'минути' : 'минута');
}else{

iv = diff;
sv = (iv != 1? 'секунди' : 'секунда');
}
return "преди "+(iv<0?1:iv)+" "+sv;
}

function getImageSrc(image,type){

//da se mahne sled update-a na SQL-a
switch(image.server){
case 'storage0.album.bg': image.server=0; break;
case 'storage1.album.bg': image.server=1; break;
case 'storage2.album.bg': image.server=2; break;
case 'storage3.album.bg': image.server=3; break;
case 'storage4.album.bg': image.server=4; break;
}

var src = '';
switch(type){
case '': src = 'http://storage'+image.server+'.album.bg/'+image.path+'/'+image.filename; break;
case 1: src = 'http://storage'+image.server+'.album.bg/'+image.path+'/'+image.filename_th1; break;
case 2: src = 'http://storage'+image.server+'.album.bg/'+image.path+'/'+image.filename_th2; break;
case 3: src = 'http://storage'+image.server+'.album.bg/'+image.path+'/'+image.filename_th3; break;
case 4: src = 'http://storage'+image.server+'.album.bg/'+image.path+'/'+image.filename_th4; break;
}

return src;
}

function getImageDimsArray(size, image) {
var image_dim = {};
if (image.width && image.height) {
if ((image.rotate / 90) % 2 != 0) {
tmp_wh       = image.width;
image.width  = image.height;
image.height = tmp_wh;
}
if (image.width < size && image.height < size) {
image_dim = {
width: image.width,
height: image.height
};
} else {
if (image.width > image.height)
ratio = image.width / size;
else
ratio = image.height / size;

image_dim = {
width: Math.round(image.width / ratio),
height: Math.round(image.height / ratio)
};
}
}
return image_dim;
}

function getImageFromCurrent(prefix) {
prefix = (prefix == null)? 'image'  : prefix;
var keys = ['server', 'path', 'filename', 'filename_th1', 'filename_th2', 'filename_th3', 'filename_th4', 'permissions', 'publicLocked', 'width', 'height', 'rotate'];
var image = {};
for (var i = 0; i < keys.length; i++) {
var key = keys[i] + '';
try {
image[key] = Current.get(prefix + key.ucFirst());
} catch (err) {}
}
return image;
}

String.prototype.ucFirst = function () {
return this.substr(0,1).toUpperCase() + this.substr(1,this.length);
};

function min() {
var _min = null;
for (var i = 0; i < min.arguments.length; i++) {
if (_min == null || _min > min.arguments[i])
_min = min.arguments[i];
}
return _min;
}

function reset_form(form) {
if (!form || !form.tagName == 'FORM') return;
form.reset();
for (var i = 0; i < form.elements.length; i++) {
with (form.elements[i].style) {
borderStyle = '';
borderColor = '';
color = '';
}
}
}//Loader
document.write("<div id='loader' class='loader'><b>Loging..</b></div>");
document.write("<div id='loader_bg' class='loader_bg'></div>");

function getHttp(){
var xmlHttp = null;
try {
xmlHttp = new XMLHttpRequest();
} catch (e) {
var progIds = ['MSXML2.XMLHTTP', 'Microsoft.XMLHTTP', 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0'];
var success = false;
for (var iterator = 0; (iterator < progIds.length) && ( ! success); iterator ++) {
try {
xmlHttp = new ActiveXObject(progIds[iterator]);
success = true;
} catch (e) {}
}
if ( ! success ) {
return null;
}
}
return xmlHttp;
}

function call(url, handler, data, target, method, reset_form_style) {
var http = this.getHttp();
if (!http) alert('No HTTP Object');
if (!method) method = 'GET';
http.onreadystatechange = function() {
ch_load_status(http.readyState,target);
if (http.readyState == 4) {
if (http.status == 200) {
if (http.responseXML != null) {
//alert(http.responseText);
if (http.responseXML.getElementsByTagName('errors')[0]) {
var form_object = $(target);
if (reset_form_style && form_object && form_object.tagName == 'FORM') {
for (var i = 0; i < form_object.elements.length; i++) {
with (form_object.elements[i].style) {
borderStyle = '';
borderColor = '';
color = '';
}
}
}
set_xml_error(target,http.responseXML.getElementsByTagName('error'));
} else if (handler) {
//return handler(http.responseXML);
if (typeof(handler)=='string') {
return eval(handler+'(http.responseXML)');
} else {
return handler(http.responseXML);
}
}
}
}
}
return false;
};
http.open(method, url, true);
http.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
http.send(typeof data == 'undefined'? '' : data);
}
function set_xml_error(target, errors) {
var f = $(target);
var errorShown = false;
if (f && f.tagName == 'FORM') {
var shown_errors = {};
for (var i = 0; i < f.elements.length; i++) {
for (var j = 0; j < errors.length; j++) {
 if (
 f.elements[i].name == errors[j].getAttribute('key') ||
 f.elements[i].name == 'data[' + errors[j].getAttribute('key') + ']'
 ) {
if (f.elements[i].type == 'radio') {
if (shown_errors[f.elements[i].name]) continue;
shown_errors[f.elements[i].name] = true;
}
f.elements[i].style.borderStyle = 'solid';
f.elements[i].style.borderWidth = '1px';
f.elements[i].style.borderColor = '#F00';
f.elements[i].style.color = '#F00';
var messageText = errors[j].firstChild && errors[j].firstChild.nodeValue? errors[j].firstChild.nodeValue : errors[j].getAttribute('type') + ' ' + errors[j].getAttribute('key');
floatingMessages.createMsg('<strong>Грешка</strong><br />' + messageText, 'error', 5000);
errorShown = true;
break;
}
}
}
}
if (!errorShown) {
for (var i = 0; i < errors.length; i++) {
var messageText = errors[i].firstChild && errors[i].firstChild.nodeValue? errors[i].firstChild.nodeValue : 'Възникнала е грешка при опита за извършване на избраното действие.';
floatingMessages.createMsg('<strong>Грешка</strong><br />' + messageText, 'error', 5000);
}
}
}
function ch_load_status(status,target){
var ld = $('loader');
var ldbg = $('loader_bg');
if(target){
if(target != 'hide_loader'){
var te  = $(target);
var xy = get_cumulative_offset(te);
ldbg.style.left = xy[0]+'px';
ldbg.style.top = xy[1]+'px';
ldbg.style.width = te.offsetWidth+'px';
ldbg.style.height = te.offsetHeight+'px';
ldbg.style.zIndex = '999';

ld.style.right = 'auto';
ld.style.left = (xy[0]+(te.offsetWidth/2)-30)+'px';
ld.style.top = (xy[1]+(te.offsetHeight/2)-10)+'px';
ld.style.zIndex = '1000';
}
}else if(target != 'hide_loader'){
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
ldbg.style.right = '';
ldbg.style.top = scrollTop+'px';
ldbg.style.width = '';
ldbg.style.height ='';
ldbg.style.zIndex = '999';

ld.style.right = '0px';
ld.style.left = '';
ld.style.top = scrollTop+'px';
ld.style.zIndex = '1000';
}else {
ldbg.style.display='none';
ld.style.display='none';
}
if(ld && target != 'hide_loader'){
switch(status){
case 0: //0 = uninitialized
ld.style.display = 'block';
ldbg.style.display = 'block';
ld.innerHTML = "Изчакайте";
break;
case 1: //1 = loading
ld.style.display = 'block';
ldbg.style.display = 'block';
ld.innerHTML = "Зарежда...";
break;
case 2: //2 = loaded
ld.style.display = 'block';
ldbg.style.display = 'block';
ld.innerHTML = "Зарежда";
break;
case 3: //3 = interactive
ld.style.display = 'block';
ldbg.style.display = 'block';
ld.innerHTML = "Обработва";
break;
case 4: //4 = complete
ld.innerHTML = "Завърши";
ld.style.display = 'none';
ldbg.style.display = 'none';
break;
}
}

}



// VSS 1.0
// Interface JS Module
// CBH Technologies 2006

//###########################################
// SYSTEM

var isIE = false;
if(navigator.appName == "Microsoft Internet Explorer")  isIE = true;


function cel(tagName, type, name, value) {
var el = document.createElement(tagName);
el.type = type? type : '';
el.name = name? name : '';
el.value = value? value : '';
return el;
}

function appendChildren(container) {
for (var i = 1; i < appendChildren.arguments.length; i++) {
container.appendChild(appendChildren.arguments[i]);
}
return container;
}

function ce(tagName,id,className){
var el =  document.createElement(tagName);
el.id = id;
el.className = className;
return el;
}

function cn(el,pos){
//if(isIE) return el.childNodes[pos];
var c = 0;
for(i=0;i<el.childNodes.length;i++){
if(el.childNodes[i].tagName){
if(c == pos) return el.childNodes[i];
c++;
}
}
return null;
}

function cnl(el){
if(isIE) return el.childNodes.length;
var c = 0;
for(i=0;i<el.childNodes.length;i++){
if(el.childNodes[i].tagName && el.childNodes[i].tagName!='undefined'){
c++;
}
}
return c;
}

function ae(el,ev,func){
if(isIE){
el.attachEvent("on"+ev,func);
}
else{
el.addEventListener(ev,func,false);
}
return true;
}

function rm (node,removeSelf) {
    while (node.childNodes.length > 0) {
        rm(node.childNodes[0],true);
}
if(removeSelf && node && node.parentNode) node.parentNode.removeChild(node);
return true;
}

function sh(el){
if(el.style.display!='none'){
el.style.display = 'none';
return 'none';
}
else{
el.style.display = 'block';
return 'block';
}
}

function  get_cumulative_offset(element) {
var valueT = 0, valueL = 0;
do {
  valueT += element.offsetTop  || 0;
  valueL += element.offsetLeft || 0;
  element = element.offsetParent;
} while (element);
return [valueL, valueT];
}

function ale(func){
var oldonload = window.onload;
if (typeof window.onload != 'function'){
    window.onload = func;
} else {
window.onload = function(){
oldonload();
func();
}
}
}

Array.prototype.max = function() {
var m = -1;
if (typeof this[0] == "number") m = this[0];
for (i=this.length; i>0; i--) {
if (typeof this[i] == "number")
m = Math.max(m,this[i]);
}
return m;
}
var Current = {
set: function(name,value){
eval("Current."+name+"='"+value+"';");
},
get: function(name){
return eval("Current."+name+";");
}
};
/*  Prototype JavaScript framework, version 1.5.0
 *  (c) 2005-2007 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://prototype.conio.net/
 *
/*--------------------------------------------------------------------------*/

var Prototype = {
  Version: '1.5.0',
  BrowserFeatures: {
    XPath: !!document.evaluate
  },

  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
  emptyFunction: function() {},
  K: function(x) { return x }
}

var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

var Abstract = new Object();

Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
}

Object.extend(Object, {
  inspect: function(object) {
    try {
      if (object === undefined) return 'undefined';
      if (object === null) return 'null';
      return object.inspect ? object.inspect() : object.toString();
    } catch (e) {
      if (e instanceof RangeError) return '...';
      throw e;
    }
  },

  keys: function(object) {
    var keys = [];
    for (var property in object)
      keys.push(property);
    return keys;
  },

  values: function(object) {
    var values = [];
    for (var property in object)
      values.push(object[property]);
    return values;
  },

  clone: function(object) {
    return Object.extend({}, object);
  }
});

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

Function.prototype.bindAsEventListener = function(object) {
  var __method = this, args = $A(arguments), object = args.shift();
  return function(event) {
    return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
  }
}

Object.extend(Number.prototype, {
  toColorPart: function() {
    var digits = this.toString(16);
    if (this < 16) return '0' + digits;
    return digits;
  },

  succ: function() {
    return this + 1;
  },

  times: function(iterator) {
    $R(0, this, true).each(iterator);
    return this;
  }
});

var Try = {
  these: function() {
    var returnValue;

    for (var i = 0, length = arguments.length; i < length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }

    return returnValue;
  }
}

/*--------------------------------------------------------------------------*/

var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
  initialize: function(callback, frequency) {
    this.callback = callback;
    this.frequency = frequency;
    this.currentlyExecuting = false;

    this.registerCallback();
  },

  registerCallback: function() {
    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  stop: function() {
    if (!this.timer) return;
    clearInterval(this.timer);
    this.timer = null;
  },

  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback(this);
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}
String.interpret = function(value){
  return value == null ? '' : String(value);
}

Object.extend(String.prototype, {
  gsub: function(pattern, replacement) {
    var result = '', source = this, match;
    replacement = arguments.callee.prepareReplacement(replacement);

    while (source.length > 0) {
      if (match = source.match(pattern)) {
        result += source.slice(0, match.index);
        result += String.interpret(replacement(match));
        source  = source.slice(match.index + match[0].length);
      } else {
        result += source, source = '';
      }
    }
    return result;
  },

  sub: function(pattern, replacement, count) {
    replacement = this.gsub.prepareReplacement(replacement);
    count = count === undefined ? 1 : count;

    return this.gsub(pattern, function(match) {
      if (--count < 0) return match[0];
      return replacement(match);
    });
  },

  scan: function(pattern, iterator) {
    this.gsub(pattern, iterator);
    return this;
  },

  truncate: function(length, truncation) {
    length = length || 30;
    truncation = truncation === undefined ? '...' : truncation;
    return this.length > length ?
      this.slice(0, length - truncation.length) + truncation : this;
  },

  strip: function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  },

  stripTags: function() {
    return this.replace(/<\/?[^>]+>/gi, '');
  },

  stripScripts: function() {
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
  },

  extractScripts: function() {
    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
    return (this.match(matchAll) || []).map(function(scriptTag) {
      return (scriptTag.match(matchOne) || ['', ''])[1];
    });
  },

  evalScripts: function() {
    return this.extractScripts().map(function(script) { return eval(script) });
  },

  escapeHTML: function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
  },

  unescapeHTML: function() {
    var div = document.createElement('div');
    div.innerHTML = this.stripTags();
    return div.childNodes[0] ? (div.childNodes.length > 1 ?
      $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
      div.childNodes[0].nodeValue) : '';
  },

  toQueryParams: function(separator) {
    var match = this.strip().match(/([^?#]*)(#.*)?$/);
    if (!match) return {};

    return match[1].split(separator || '&').inject({}, function(hash, pair) {
      if ((pair = pair.split('='))[0]) {
        var name = decodeURIComponent(pair[0]);
        var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;

        if (hash[name] !== undefined) {
          if (hash[name].constructor != Array)
            hash[name] = [hash[name]];
          if (value) hash[name].push(value);
        }
        else hash[name] = value;
      }
      return hash;
    });
  },

  toArray: function() {
    return this.split('');
  },

  succ: function() {
    return this.slice(0, this.length - 1) +
      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
  },

  camelize: function() {
    var parts = this.split('-'), len = parts.length;
    if (len == 1) return parts[0];

    var camelized = this.charAt(0) == '-'
      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
      : parts[0];

    for (var i = 1; i < len; i++)
      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

    return camelized;
  },

  capitalize: function(){
    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
  },

  underscore: function() {
    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
  },

  dasherize: function() {
    return this.gsub(/_/,'-');
  },

  inspect: function(useDoubleQuotes) {
    var escapedString = this.replace(/\\/g, '\\\\');
    if (useDoubleQuotes)
      return '"' + escapedString.replace(/"/g, '\\"') + '"';
    else
      return "'" + escapedString.replace(/'/g, '\\\'') + "'";
  }
});

String.prototype.gsub.prepareReplacement = function(replacement) {
  if (typeof replacement == 'function') return replacement;
  var template = new Template(replacement);
  return function(match) { return template.evaluate(match) };
}

String.prototype.parseQuery = String.prototype.toQueryParams;

var Template = Class.create();
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype = {
  initialize: function(template, pattern) {
    this.template = template.toString();
    this.pattern  = pattern || Template.Pattern;
  },

  evaluate: function(object) {
    return this.template.gsub(this.pattern, function(match) {
      var before = match[1];
      if (before == '\\') return match[2];
      return before + String.interpret(object[match[3]]);
    });
  }
}

var $break    = new Object();
var $continue = new Object();

var Enumerable = {
  each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        try {
          iterator(value, index++);
        } catch (e) {
          if (e != $continue) throw e;
        }
      });
    } catch (e) {
      if (e != $break) throw e;
    }
    return this;
  },

  eachSlice: function(number, iterator) {
    var index = -number, slices = [], array = this.toArray();
    while ((index += number) < array.length)
      slices.push(array.slice(index, index+number));
    return slices.map(iterator);
  },

  all: function(iterator) {
    var result = true;
    this.each(function(value, index) {
      result = result && !!(iterator || Prototype.K)(value, index);
      if (!result) throw $break;
    });
    return result;
  },

  any: function(iterator) {
    var result = false;
    this.each(function(value, index) {
      if (result = !!(iterator || Prototype.K)(value, index))
        throw $break;
    });
    return result;
  },

  collect: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      results.push((iterator || Prototype.K)(value, index));
    });
    return results;
  },

  detect: function(iterator) {
    var result;
    this.each(function(value, index) {
      if (iterator(value, index)) {
        result = value;
        throw $break;
      }
    });
    return result;
  },

  findAll: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (iterator(value, index))
        results.push(value);
    });
    return results;
  },

  grep: function(pattern, iterator) {
    var results = [];
    this.each(function(value, index) {
      var stringValue = value.toString();
      if (stringValue.match(pattern))
        results.push((iterator || Prototype.K)(value, index));
    })
    return results;
  },

  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  },

  inGroupsOf: function(number, fillWith) {
    fillWith = fillWith === undefined ? null : fillWith;
    return this.eachSlice(number, function(slice) {
      while(slice.length < number) slice.push(fillWith);
      return slice;
    });
  },

  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  },

  invoke: function(method) {
    var args = $A(arguments).slice(1);
    return this.map(function(value) {
      return value[method].apply(value, args);
    });
  },

  max: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value >= result)
        result = value;
    });
    return result;
  },

  min: function(iterator) {
    var result;
    this.each(function(value, index) {
      value = (iterator || Prototype.K)(value, index);
      if (result == undefined || value < result)
        result = value;
    });
    return result;
  },

  partition: function(iterator) {
    var trues = [], falses = [];
    this.each(function(value, index) {
      ((iterator || Prototype.K)(value, index) ?
        trues : falses).push(value);
    });
    return [trues, falses];
  },

  pluck: function(property) {
    var results = [];
    this.each(function(value, index) {
      results.push(value[property]);
    });
    return results;
  },

  reject: function(iterator) {
    var results = [];
    this.each(function(value, index) {
      if (!iterator(value, index))
        results.push(value);
    });
    return results;
  },

  sortBy: function(iterator) {
    return this.map(function(value, index) {
      return {value: value, criteria: iterator(value, index)};
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }).pluck('value');
  },

  toArray: function() {
    return this.map();
  },

  zip: function() {
    var iterator = Prototype.K, args = $A(arguments);
    if (typeof args.last() == 'function')
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      return iterator(collections.pluck(index));
    });
  },

  size: function() {
    return this.toArray().length;
  },

  inspect: function() {
    return '#<Enumerable:' + this.toArray().inspect() + '>';
  }
}

Object.extend(Enumerable, {
  map:     Enumerable.collect,
  find:    Enumerable.detect,
  select:  Enumerable.findAll,
  member:  Enumerable.include,
  entries: Enumerable.toArray
});
var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Object.extend(Array.prototype, Enumerable);

if (!Array.prototype._reverse)
  Array.prototype._reverse = Array.prototype.reverse;

Object.extend(Array.prototype, {
  _each: function(iterator) {
    for (var i = 0, length = this.length; i < length; i++)
      iterator(this[i]);
  },

  clear: function() {
    this.length = 0;
    return this;
  },

  first: function() {
    return this[0];
  },

  last: function() {
    return this[this.length - 1];
  },

  compact: function() {
    return this.select(function(value) {
      return value != null;
    });
  },

  flatten: function() {
    return this.inject([], function(array, value) {
      return array.concat(value && value.constructor == Array ?
        value.flatten() : [value]);
    });
  },

  without: function() {
    var values = $A(arguments);
    return this.select(function(value) {
      return !values.include(value);
    });
  },

  indexOf: function(object) {
    for (var i = 0, length = this.length; i < length; i++)
      if (this[i] == object) return i;
    return -1;
  },

  reverse: function(inline) {
    return (inline !== false ? this : this.toArray())._reverse();
  },

  reduce: function() {
    return this.length > 1 ? this : this[0];
  },

  uniq: function() {
    return this.inject([], function(array, value) {
      return array.include(value) ? array : array.concat([value]);
    });
  },

  clone: function() {
    return [].concat(this);
  },

  size: function() {
    return this.length;
  },

  inspect: function() {
    return '[' + this.map(Object.inspect).join(', ') + ']';
  }
});

Array.prototype.toArray = Array.prototype.clone;

function $w(string){
  string = string.strip();
  return string ? string.split(/\s+/) : [];
}

if(window.opera){
  Array.prototype.concat = function(){
    var array = [];
    for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
    for(var i = 0, length = arguments.length; i < length; i++) {
      if(arguments[i].constructor == Array) {
        for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
          array.push(arguments[i][j]);
      } else {
        array.push(arguments[i]);
      }
    }
    return array;
  }
}
var Hash = function(obj) {
  Object.extend(this, obj || {});
};

Object.extend(Hash, {
  toQueryString: function(obj) {
    var parts = [];

	  this.prototype._each.call(obj, function(pair) {
      if (!pair.key) return;

      if (pair.value && pair.value.constructor == Array) {
        var values = pair.value.compact();
        if (values.length < 2) pair.value = values.reduce();
        else {
        	key = encodeURIComponent(pair.key);
          values.each(function(value) {
            value = value != undefined ? encodeURIComponent(value) : '';
            parts.push(key + '=' + encodeURIComponent(value));
          });
          return;
        }
      }
      if (pair.value == undefined) pair[1] = '';
      parts.push(pair.map(encodeURIComponent).join('='));
	  });

    return parts.join('&');
  }
});

Object.extend(Hash.prototype, Enumerable);
Object.extend(Hash.prototype, {
  _each: function(iterator) {
    for (var key in this) {
      var value = this[key];
      if (value && value == Hash.prototype[key]) continue;

      var pair = [key, value];
      pair.key = key;
      pair.value = value;
      iterator(pair);
    }
  },

  keys: function() {
    return this.pluck('key');
  },

  values: function() {
    return this.pluck('value');
  },

  merge: function(hash) {
    return $H(hash).inject(this, function(mergedHash, pair) {
      mergedHash[pair.key] = pair.value;
      return mergedHash;
    });
  },

  remove: function() {
    var result;
    for(var i = 0, length = arguments.length; i < length; i++) {
      var value = this[arguments[i]];
      if (value !== undefined){
        if (result === undefined) result = value;
        else {
          if (result.constructor != Array) result = [result];
          result.push(value)
        }
      }
      delete this[arguments[i]];
    }
    return result;
  },

  toQueryString: function() {
    return Hash.toQueryString(this);
  },

  inspect: function() {
    return '#<Hash:{' + this.map(function(pair) {
      return pair.map(Object.inspect).join(': ');
    }).join(', ') + '}>';
  }
});

function $H(object) {
  if (object && object.constructor == Hash) return object;
  return new Hash(object);
};
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
  initialize: function(start, end, exclusive) {
    this.start = start;
    this.end = end;
    this.exclusive = exclusive;
  },

  _each: function(iterator) {
    var value = this.start;
    while (this.include(value)) {
      iterator(value);
      value = value.succ();
    }
  },

  include: function(value) {
    if (value < this.start)
      return false;
    if (this.exclusive)
      return value < this.end;
    return value <= this.end;
  }
});

var $R = function(start, end, exclusive) {
  return new ObjectRange(start, end, exclusive);
}

var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
    ) || false;
  },

  activeRequestCount: 0
}

Ajax.Responders = {
  responders: [],

  _each: function(iterator) {
    this.responders._each(iterator);
  },

  register: function(responder) {
    if (!this.include(responder))
      this.responders.push(responder);
  },

  unregister: function(responder) {
    this.responders = this.responders.without(responder);
  },

  dispatch: function(callback, request, transport, json) {
    this.each(function(responder) {
      if (typeof responder[callback] == 'function') {
        try {
          responder[callback].apply(responder, [request, transport, json]);
        } catch (e) {}
      }
    });
  }
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
  onCreate: function() {
    Ajax.activeRequestCount++;
  },
  onComplete: function() {
    Ajax.activeRequestCount--;
  }
});

Ajax.Base = function() {};
Ajax.Base.prototype = {
  setOptions: function(options) {
    this.options = {
      method:       'post',
      asynchronous: true,
      contentType:  'application/x-www-form-urlencoded',
      encoding:     'UTF-8',
      parameters:   ''
    }
    Object.extend(this.options, options || {});

    this.options.method = this.options.method.toLowerCase();
    if (typeof this.options.parameters == 'string')
      this.options.parameters = this.options.parameters.toQueryParams();
  }
}

Ajax.Request = Class.create();
Ajax.Request.Events =
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
  _complete: false,

  initialize: function(url, options) {
    this.transport = Ajax.getTransport();
    this.setOptions(options);
    this.request(url);
  },

  request: function(url) {
    this.url = url;
    this.method = this.options.method;
    var params = this.options.parameters;

    if (!['get', 'post'].include(this.method)) {
      // simulate other verbs over post
      params['_method'] = this.method;
      this.method = 'post';
    }

    params = Hash.toQueryString(params);
    if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='

    // when GET, append parameters to URL
    if (this.method == 'get' && params)
      this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;

    try {
      Ajax.Responders.dispatch('onCreate', this, this.transport);

      this.transport.open(this.method.toUpperCase(), this.url,
        this.options.asynchronous);

      if (this.options.asynchronous)
        setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);

      this.transport.onreadystatechange = this.onStateChange.bind(this);
      this.setRequestHeaders();

      var body = this.method == 'post' ? (this.options.postBody || params) : null;

      this.transport.send(body);

      /* Force Firefox to handle ready state 4 for synchronous requests */
      if (!this.options.asynchronous && this.transport.overrideMimeType)
        this.onStateChange();

    }
    catch (e) {
      this.dispatchException(e);
    }
  },

  onStateChange: function() {
    var readyState = this.transport.readyState;
    if (readyState > 1 && !((readyState == 4) && this._complete))
      this.respondToReadyState(this.transport.readyState);
  },

  setRequestHeaders: function() {
    var headers = {
      'X-Requested-With': 'XMLHttpRequest',
      'X-Prototype-Version': Prototype.Version,
      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
    };

    if (this.method == 'post') {
      headers['Content-type'] = this.options.contentType +
        (this.options.encoding ? '; charset=' + this.options.encoding : '');

      /* Force "Connection: close" for older Mozilla browsers to work
       * around a bug where XMLHttpRequest sends an incorrect
       * Content-length header. See Mozilla Bugzilla #246651.
       */
      if (this.transport.overrideMimeType &&
          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
            headers['Connection'] = 'close';
    }

    // user-defined headers
    if (typeof this.options.requestHeaders == 'object') {
      var extras = this.options.requestHeaders;

      if (typeof extras.push == 'function')
        for (var i = 0, length = extras.length; i < length; i += 2)
          headers[extras[i]] = extras[i+1];
      else
        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
    }

    for (var name in headers)
      this.transport.setRequestHeader(name, headers[name]);
  },

  success: function() {
    return !this.transport.status
        || (this.transport.status >= 200 && this.transport.status < 300);
  },

  respondToReadyState: function(readyState) {
    var state = Ajax.Request.Events[readyState];
    var transport = this.transport, json = this.evalJSON();

    if (state == 'Complete') {
      try {
        this._complete = true;
        (this.options['on' + this.transport.status]
         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
         || Prototype.emptyFunction)(transport, json);
      } catch (e) {
        this.dispatchException(e);
      }

      if ((this.getHeader('Content-type') || 'text/javascript').strip().
        match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
          this.evalResponse();
    }

    try {
      (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
      Ajax.Responders.dispatch('on' + state, this, transport, json);
    } catch (e) {
      this.dispatchException(e);
    }

    if (state == 'Complete') {
      // avoid memory leak in MSIE: clean up
      this.transport.onreadystatechange = Prototype.emptyFunction;
    }
  },

  getHeader: function(name) {
    try {
      return this.transport.getResponseHeader(name);
    } catch (e) { return null }
  },

  evalJSON: function() {
    try {
      var json = this.getHeader('X-JSON');
      return json ? eval('(' + json + ')') : null;
    } catch (e) { return null }
  },

  evalResponse: function() {
    try {
      return eval(this.transport.responseText);
    } catch (e) {
      this.dispatchException(e);
    }
  },

  dispatchException: function(exception) {
    (this.options.onException || Prototype.emptyFunction)(this, exception);
    Ajax.Responders.dispatch('onException', this, exception);
  }
});

Ajax.Updater = Class.create();

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
  initialize: function(container, url, options) {
    this.container = {
      success: (container.success || container),
      failure: (container.failure || (container.success ? null : container))
    }

    this.transport = Ajax.getTransport();
    this.setOptions(options);

    var onComplete = this.options.onComplete || Prototype.emptyFunction;
    this.options.onComplete = (function(transport, param) {
      this.updateContent();
      onComplete(transport, param);
    }).bind(this);

    this.request(url);
  },

  updateContent: function() {
    var receiver = this.container[this.success() ? 'success' : 'failure'];
    var response = this.transport.responseText;

    if (!this.options.evalScripts) response = response.stripScripts();

    if (receiver = $(receiver)) {
      if (this.options.insertion)
        new this.options.insertion(receiver, response);
      else
        receiver.update(response);
    }

    if (this.success()) {
      if (this.onComplete)
        setTimeout(this.onComplete.bind(this), 10);
    }
  }
});

Ajax.PeriodicalUpdater = Class.create();
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
  initialize: function(container, url, options) {
    this.setOptions(options);
    this.onComplete = this.options.onComplete;

    this.frequency = (this.options.frequency || 2);
    this.decay = (this.options.decay || 1);

    this.updater = {};
    this.container = container;
    this.url = url;

    this.start();
  },

  start: function() {
    this.options.onComplete = this.updateComplete.bind(this);
    this.onTimerEvent();
  },

  stop: function() {
    this.updater.options.onComplete = undefined;
    clearTimeout(this.timer);
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
  },

  updateComplete: function(request) {
    if (this.options.decay) {
      this.decay = (request.responseText == this.lastText ?
        this.decay * this.options.decay : 1);

      this.lastText = request.responseText;
    }
    this.timer = setTimeout(this.onTimerEvent.bind(this),
      this.decay * this.frequency * 1000);
  },

  onTimerEvent: function() {
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
  }
});
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (typeof element == 'string')
    element = document.getElementById(element);
  return Element.extend(element);
}

if (Prototype.BrowserFeatures.XPath) {
  document._getElementsByXPath = function(expression, parentElement) {
    var results = [];
    var query = document.evaluate(expression, $(parentElement) || document,
      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, length = query.snapshotLength; i < length; i++)
      results.push(query.snapshotItem(i));
    return results;
  };
}

document.getElementsByClassName = function(className, parentElement) {
  if (Prototype.BrowserFeatures.XPath) {
    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
    return document._getElementsByXPath(q, parentElement);
  } else {
    var children = ($(parentElement) || document.body).getElementsByTagName('*');
    var elements = [], child;
    for (var i = 0, length = children.length; i < length; i++) {
      child = children[i];
      if (Element.hasClassName(child, className))
        elements.push(Element.extend(child));
    }
    return elements;
  }
};

/*--------------------------------------------------------------------------*/

if (!window.Element)
  var Element = new Object();

Element.extend = function(element) {
  if (!element || _nativeExtensions || element.nodeType == 3) return element;

  if (!element._extended && element.tagName && element != window) {
    var methods = Object.clone(Element.Methods), cache = Element.extend.cache;

    if (element.tagName == 'FORM')
      Object.extend(methods, Form.Methods);
    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
      Object.extend(methods, Form.Element.Methods);

    Object.extend(methods, Element.Methods.Simulated);

    for (var property in methods) {
      var value = methods[property];
      if (typeof value == 'function' && !(property in element))
        element[property] = cache.findOrStore(value);
    }
  }

  element._extended = true;
  return element;
};

Element.extend.cache = {
  findOrStore: function(value) {
    return this[value] = this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
  }
};

Element.Methods = {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function(element) {
    element = $(element);
    Element[Element.visible(element) ? 'hide' : 'show'](element);
    return element;
  },

  hide: function(element) {
    $(element).style.display = 'none';
    return element;
  },

  show: function(element) {
    $(element).style.display = '';
    return element;
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
    return element;
  },

  update: function(element, html) {
    html = typeof html == 'undefined' ? '' : html.toString();
    $(element).innerHTML = html.stripScripts();
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  replace: function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    if (element.outerHTML) {
      element.outerHTML = html.stripScripts();
    } else {
      var range = element.ownerDocument.createRange();
      range.selectNodeContents(element);
      element.parentNode.replaceChild(
        range.createContextualFragment(html.stripScripts()), element);
    }
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  inspect: function(element) {
    element = $(element);
    var result = '<' + element.tagName.toLowerCase();
    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
      var property = pair.first(), attribute = pair.last();
      var value = (element[property] || '').toString();
      if (value) result += ' ' + attribute + '=' + value.inspect(true);
    });
    return result + '>';
  },

  recursivelyCollect: function(element, property) {
    element = $(element);
    var elements = [];
    while (element = element[property])
      if (element.nodeType == 1)
        elements.push(Element.extend(element));
    return elements;
  },

  ancestors: function(element) {
    return $(element).recursivelyCollect('parentNode');
  },

  descendants: function(element) {
    return $A($(element).getElementsByTagName('*'));
  },

  immediateDescendants: function(element) {
    if (!(element = $(element).firstChild)) return [];
    while (element && element.nodeType != 1) element = element.nextSibling;
    if (element) return [element].concat($(element).nextSiblings());
    return [];
  },

  previousSiblings: function(element) {
    return $(element).recursivelyCollect('previousSibling');
  },

  nextSiblings: function(element) {
    return $(element).recursivelyCollect('nextSibling');
  },

  siblings: function(element) {
    element = $(element);
    return element.previousSiblings().reverse().concat(element.nextSiblings());
  },

  match: function(element, selector) {
    if (typeof selector == 'string')
      selector = new Selector(selector);
    return selector.match($(element));
  },

  up: function(element, expression, index) {
    return Selector.findElement($(element).ancestors(), expression, index);
  },

  down: function(element, expression, index) {
    return Selector.findElement($(element).descendants(), expression, index);
  },

  previous: function(element, expression, index) {
    return Selector.findElement($(element).previousSiblings(), expression, index);
  },

  next: function(element, expression, index) {
    return Selector.findElement($(element).nextSiblings(), expression, index);
  },

  getElementsBySelector: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element, args);
  },

  getElementsByClassName: function(element, className) {
    return document.getElementsByClassName(className, element);
  },

  readAttribute: function(element, name) {
    element = $(element);
    if (document.all && !window.opera) {
      var t = Element._attributeTranslations;
      if (t.values[name]) return t.values[name](element, name);
      if (t.names[name])  name = t.names[name];
      var attribute = element.attributes[name];
      if(attribute) return attribute.nodeValue;
    }
    return element.getAttribute(name);
  },

  getHeight: function(element) {
    return $(element).getDimensions().height;
  },

  getWidth: function(element) {
    return $(element).getDimensions().width;
  },

  classNames: function(element) {
    return new Element.ClassNames(element);
  },

  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    var elementClassName = element.className;
    if (elementClassName.length == 0) return false;
    if (elementClassName == className ||
        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
      return true;
    return false;
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).add(className);
    return element;
  },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).remove(className);
    return element;
  },

  toggleClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
    return element;
  },

  observe: function() {
    Event.observe.apply(Event, arguments);
    return $A(arguments).first();
  },

  stopObserving: function() {
    Event.stopObserving.apply(Event, arguments);
    return $A(arguments).first();
  },

  // removes whitespace-only text node children
  cleanWhitespace: function(element) {
    element = $(element);
    var node = element.firstChild;
    while (node) {
      var nextNode = node.nextSibling;
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        element.removeChild(node);
      node = nextNode;
    }
    return element;
  },

  empty: function(element) {
    return $(element).innerHTML.match(/^\s*$/);
  },

  descendantOf: function(element, ancestor) {
    element = $(element), ancestor = $(ancestor);
    while (element = element.parentNode)
      if (element == ancestor) return true;
    return false;
  },

  scrollTo: function(element) {
    element = $(element);
    var pos = Position.cumulativeOffset(element);
    window.scrollTo(pos[0], pos[1]);
    return element;
  },

  getStyle: function(element, style) {
    element = $(element);
    if (['float','cssFloat'].include(style))
      style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
    style = style.camelize();
    var value = element.style[style];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css[style] : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[style];
      }
    }

    if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
      value = element['offset'+style.capitalize()] + 'px';

    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
    if(style == 'opacity') {
      if(value) return parseFloat(value);
      if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
        if(value[1]) return parseFloat(value[1]) / 100;
      return 1.0;
    }
    return value == 'auto' ? null : value;
  },

  setStyle: function(element, style) {
    element = $(element);
    for (var name in style) {
      var value = style[name];
      if(name == 'opacity') {
        if (value == 1) {
          value = (/Gecko/.test(navigator.userAgent) &&
            !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
        } else if(value == '') {
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
        } else {
          if(value < 0.00001) value = 0;
          if(/MSIE/.test(navigator.userAgent) && !window.opera)
            element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
              'alpha(opacity='+value*100+')';
        }
      } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
      element.style[name.camelize()] = value;
    }
    return element;
  },

  getDimensions: function(element) {
    element = $(element);
    var display = $(element).getStyle('display');
    if (display != 'none' && display != null) // Safari bug
      return {width: element.offsetWidth, height: element.offsetHeight};

    // All *Width and *Height properties give 0 on elements with display none,
    // so enable the element temporarily
    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = 'block';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      element._madePositioned = true;
      element.style.position = 'relative';
      // Opera returns the offset relative to the positioning context, when an
      // element is position relative but top and left have not been defined
      if (window.opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    return element;
  },

  undoPositioned: function(element) {
    element = $(element);
    if (element._madePositioned) {
      element._madePositioned = undefined;
      element.style.position =
        element.style.top =
        element.style.left =
        element.style.bottom =
        element.style.right = '';
    }
    return element;
  },

  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return element;
    element._overflow = element.style.overflow || 'auto';
    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
      element.style.overflow = 'hidden';
    return element;
  },

  undoClipping: function(element) {
    element = $(element);
    if (!element._overflow) return element;
    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
    element._overflow = null;
    return element;
  }
};

Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});

Element._attributeTranslations = {};

Element._attributeTranslations.names = {
  colspan:   "colSpan",
  rowspan:   "rowSpan",
  valign:    "vAlign",
  datetime:  "dateTime",
  accesskey: "accessKey",
  tabindex:  "tabIndex",
  enctype:   "encType",
  maxlength: "maxLength",
  readonly:  "readOnly",
  longdesc:  "longDesc"
};

Element._attributeTranslations.values = {
  _getAttr: function(element, attribute) {
    return element.getAttribute(attribute, 2);
  },

  _flag: function(element, attribute) {
    return $(element).hasAttribute(attribute) ? attribute : null;
  },

  style: function(element) {
    return element.style.cssText.toLowerCase();
  },

  title: function(element) {
    var node = element.getAttributeNode('title');
    return node.specified ? node.nodeValue : null;
  }
};

Object.extend(Element._attributeTranslations.values, {
  href: Element._attributeTranslations.values._getAttr,
  src:  Element._attributeTranslations.values._getAttr,
  disabled: Element._attributeTranslations.values._flag,
  checked:  Element._attributeTranslations.values._flag,
  readonly: Element._attributeTranslations.values._flag,
  multiple: Element._attributeTranslations.values._flag
});

Element.Methods.Simulated = {
  hasAttribute: function(element, attribute) {
    var t = Element._attributeTranslations;
    attribute = t.names[attribute] || attribute;
    return $(element).getAttributeNode(attribute).specified;
  }
};

// IE is missing .innerHTML support for TABLE-related elements
if (document.all && !window.opera){
  Element.Methods.update = function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    var tagName = element.tagName.toUpperCase();
    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
      var div = document.createElement('div');
      switch (tagName) {
        case 'THEAD':
        case 'TBODY':
          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
          depth = 2;
          break;
        case 'TR':
          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
          depth = 3;
          break;
        case 'TD':
          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
          depth = 4;
      }
      $A(element.childNodes).each(function(node){
        element.removeChild(node)
      });
      depth.times(function(){ div = div.firstChild });

      $A(div.childNodes).each(
        function(node){ element.appendChild(node) });
    } else {
      element.innerHTML = html.stripScripts();
    }
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  }
};

Object.extend(Element, Element.Methods);

var _nativeExtensions = false;

if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
  ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
    var className = 'HTML' + tag + 'Element';
    if(window[className]) return;
    var klass = window[className] = {};
    klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
  });

Element.addMethods = function(methods) {
  Object.extend(Element.Methods, methods || {});

  function copy(methods, destination, onlyIfAbsent) {
    onlyIfAbsent = onlyIfAbsent || false;
    var cache = Element.extend.cache;
    for (var property in methods) {
      var value = methods[property];
      if (!onlyIfAbsent || !(property in destination))
        destination[property] = cache.findOrStore(value);
    }
  }

  if (typeof HTMLElement != 'undefined') {
    copy(Element.Methods, HTMLElement.prototype);
    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
    copy(Form.Methods, HTMLFormElement.prototype);
    [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
      copy(Form.Element.Methods, klass.prototype);
    });
    _nativeExtensions = true;
  }
}

var Toggle = new Object();
Toggle.display = Element.toggle;

/*--------------------------------------------------------------------------*/

Abstract.Insertion = function(adjacency) {
  this.adjacency = adjacency;
}

Abstract.Insertion.prototype = {
  initialize: function(element, content) {
    this.element = $(element);
    this.content = content.stripScripts();

    if (this.adjacency && this.element.insertAdjacentHTML) {
      try {
        this.element.insertAdjacentHTML(this.adjacency, this.content);
      } catch (e) {
        var tagName = this.element.tagName.toUpperCase();
        if (['TBODY', 'TR'].include(tagName)) {
          this.insertContent(this.contentFromAnonymousTable());
        } else {
          throw e;
        }
      }
    } else {
      this.range = this.element.ownerDocument.createRange();
      if (this.initializeRange) this.initializeRange();
      this.insertContent([this.range.createContextualFragment(this.content)]);
    }

    setTimeout(function() {content.evalScripts()}, 10);
  },

  contentFromAnonymousTable: function() {
    var div = document.createElement('div');
    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
    return $A(div.childNodes[0].childNodes[0].childNodes);
  }
}

var Insertion = new Object();

Insertion.Before = Class.create();
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  initializeRange: function() {
    this.range.setStartBefore(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment, this.element);
    }).bind(this));
  }
});

Insertion.Top = Class.create();
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(true);
  },

  insertContent: function(fragments) {
    fragments.reverse(false).each((function(fragment) {
      this.element.insertBefore(fragment, this.element.firstChild);
    }).bind(this));
  }
});

Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.appendChild(fragment);
    }).bind(this));
  }
});

Insertion.After = Class.create();
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  initializeRange: function() {
    this.range.setStartAfter(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment,
        this.element.nextSibling);
    }).bind(this));
  }
});

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
  initialize: function(element) {
    this.element = $(element);
  },

  _each: function(iterator) {
    this.element.className.split(/\s+/).select(function(name) {
      return name.length > 0;
    })._each(iterator);
  },

  set: function(className) {
    this.element.className = className;
  },

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set($A(this).concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set($A(this).without(classNameToRemove).join(' '));
  },

  toString: function() {
    return $A(this).join(' ');
  }
};

Object.extend(Element.ClassNames.prototype, Enumerable);
var Selector = Class.create();
Selector.prototype = {
  initialize: function(expression) {
    this.params = {classNames: []};
    this.expression = expression.toString().strip();
    this.parseExpression();
    this.compileMatcher();
  },

  parseExpression: function() {
    function abort(message) { throw 'Parse error in selector: ' + message; }

    if (this.expression == '')  abort('empty expression');

    var params = this.params, expr = this.expression, match, modifier, clause, rest;
    while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
      params.attributes = params.attributes || [];
      params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
      expr = match[1];
    }

    if (expr == '*') return this.params.wildcard = true;

    while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
      modifier = match[1], clause = match[2], rest = match[3];
      switch (modifier) {
        case '#':       params.id = clause; break;
        case '.':       params.classNames.push(clause); break;
        case '':
        case undefined: params.tagName = clause.toUpperCase(); break;
        default:        abort(expr.inspect());
      }
      expr = rest;
    }

    if (expr.length > 0) abort(expr.inspect());
  },

  buildMatchExpression: function() {
    var params = this.params, conditions = [], clause;

    if (params.wildcard)
      conditions.push('true');
    if (clause = params.id)
      conditions.push('element.readAttribute("id") == ' + clause.inspect());
    if (clause = params.tagName)
      conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
    if ((clause = params.classNames).length > 0)
      for (var i = 0, length = clause.length; i < length; i++)
        conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
    if (clause = params.attributes) {
      clause.each(function(attribute) {
        var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
        var splitValueBy = function(delimiter) {
          return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
        }

        switch (attribute.operator) {
          case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
          case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
          case '|=':      conditions.push(
                            splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
                          ); break;
          case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
          case '':
          case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
          default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
        }
      });
    }

    return conditions.join(' && ');
  },

  compileMatcher: function() {
    this.match = new Function('element', 'if (!element.tagName) return false; \
      element = $(element); \
      return ' + this.buildMatchExpression());
  },

  findElements: function(scope) {
    var element;

    if (element = $(this.params.id))
      if (this.match(element))
        if (!scope || Element.childOf(element, scope))
          return [element];

    scope = (scope || document).getElementsByTagName(this.params.tagName || '*');

    var results = [];
    for (var i = 0, length = scope.length; i < length; i++)
      if (this.match(element = scope[i]))
        results.push(Element.extend(element));

    return results;
  },

  toString: function() {
    return this.expression;
  }
}

Object.extend(Selector, {
  matchElements: function(elements, expression) {
    var selector = new Selector(expression);
    return elements.select(selector.match.bind(selector)).map(Element.extend);
  },

  findElement: function(elements, expression, index) {
    if (typeof expression == 'number') index = expression, expression = false;
    return Selector.matchElements(elements, expression || '*')[index || 0];
  },

  findChildElements: function(element, expressions) {
    return expressions.map(function(expression) {
      return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
        var selector = new Selector(expr);
        return results.inject([], function(elements, result) {
          return elements.concat(selector.findElements(result || element));
        });
      });
    }).flatten();
  }
});

function $$() {
  return Selector.findChildElements(document, $A(arguments));
}
var Form = {
  reset: function(form) {
    $(form).reset();
    return form;
  },

  serializeElements: function(elements, getHash) {
    var data = elements.inject({}, function(result, element) {
      if (!element.disabled && element.name) {
        var key = element.name, value = $(element).getValue();
        if (value != undefined) {
          if (result[key]) {
            if (result[key].constructor != Array) result[key] = [result[key]];
            result[key].push(value);
          }
          else result[key] = value;
        }
      }
      return result;
    });

    return getHash ? data : Hash.toQueryString(data);
  }
};

Form.Methods = {
  serialize: function(form, getHash) {
    return Form.serializeElements(Form.getElements(form), getHash);
  },

  getElements: function(form) {
    return $A($(form).getElementsByTagName('*')).inject([],
      function(elements, child) {
        if (Form.Element.Serializers[child.tagName.toLowerCase()])
          elements.push(Element.extend(child));
        return elements;
      }
    );
  },

  getInputs: function(form, typeName, name) {
    form = $(form);
    var inputs = form.getElementsByTagName('input');

    if (!typeName && !name) return $A(inputs).map(Element.extend);

    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
      var input = inputs[i];
      if ((typeName && input.type != typeName) || (name && input.name != name))
        continue;
      matchingInputs.push(Element.extend(input));
    }

    return matchingInputs;
  },

  disable: function(form) {
    form = $(form);
    form.getElements().each(function(element) {
      element.blur();
      element.disabled = 'true';
    });
    return form;
  },

  enable: function(form) {
    form = $(form);
    form.getElements().each(function(element) {
      element.disabled = '';
    });
    return form;
  },

  findFirstElement: function(form) {
    return $(form).getElements().find(function(element) {
      return element.type != 'hidden' && !element.disabled &&
        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
    });
  },

  focusFirstElement: function(form) {
    form = $(form);
    form.findFirstElement().activate();
    return form;
  }
}

Object.extend(Form, Form.Methods);

/*--------------------------------------------------------------------------*/

Form.Element = {
  focus: function(element) {
    $(element).focus();
    return element;
  },

  select: function(element) {
    $(element).select();
    return element;
  }
}

Form.Element.Methods = {
  serialize: function(element) {
    element = $(element);
    if (!element.disabled && element.name) {
      var value = element.getValue();
      if (value != undefined) {
        var pair = {};
        pair[element.name] = value;
        return Hash.toQueryString(pair);
      }
    }
    return '';
  },

  getValue: function(element) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    return Form.Element.Serializers[method](element);
  },

  clear: function(element) {
    $(element).value = '';
    return element;
  },

  present: function(element) {
    return $(element).value != '';
  },

  activate: function(element) {
    element = $(element);
    element.focus();
    if (element.select && ( element.tagName.toLowerCase() != 'input' ||
      !['button', 'reset', 'submit'].include(element.type) ) )
      element.select();
    return element;
  },

  disable: function(element) {
    element = $(element);
    element.disabled = true;
    return element;
  },

  enable: function(element) {
    element = $(element);
    element.blur();
    element.disabled = false;
    return element;
  }
}

Object.extend(Form.Element, Form.Element.Methods);
var Field = Form.Element;
var $F = Form.Element.getValue;

/*--------------------------------------------------------------------------*/

Form.Element.Serializers = {
  input: function(element) {
    switch (element.type.toLowerCase()) {
      case 'checkbox':
      case 'radio':
        return Form.Element.Serializers.inputSelector(element);
      default:
        return Form.Element.Serializers.textarea(element);
    }
  },

  inputSelector: function(element) {
    return element.checked ? element.value : null;
  },

  textarea: function(element) {
    return element.value;
  },

  select: function(element) {
    return this[element.type == 'select-one' ?
      'selectOne' : 'selectMany'](element);
  },

  selectOne: function(element) {
    var index = element.selectedIndex;
    return index >= 0 ? this.optionValue(element.options[index]) : null;
  },

  selectMany: function(element) {
    var values, length = element.length;
    if (!length) return null;

    for (var i = 0, values = []; i < length; i++) {
      var opt = element.options[i];
      if (opt.selected) values.push(this.optionValue(opt));
    }
    return values;
  },

  optionValue: function(opt) {
    // extend element because hasAttribute may not be native
    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
  }
}

/*--------------------------------------------------------------------------*/

Abstract.TimedObserver = function() {}
Abstract.TimedObserver.prototype = {
  initialize: function(element, frequency, callback) {
    this.frequency = frequency;
    this.element   = $(element);
    this.callback  = callback;

    this.lastValue = this.getValue();
    this.registerCallback();
  },

  registerCallback: function() {
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
  },

  onTimerEvent: function() {
    var value = this.getValue();
    var changed = ('string' == typeof this.lastValue && 'string' == typeof value
      ? this.lastValue != value : String(this.lastValue) != String(value));
    if (changed) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  }
}

Form.Element.Observer = Class.create();
Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.Observer = Class.create();
Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});

/*--------------------------------------------------------------------------*/

Abstract.EventObserver = function() {}
Abstract.EventObserver.prototype = {
  initialize: function(element, callback) {
    this.element  = $(element);
    this.callback = callback;

    this.lastValue = this.getValue();
    if (this.element.tagName.toLowerCase() == 'form')
      this.registerFormCallbacks();
    else
      this.registerCallback(this.element);
  },

  onElementEvent: function() {
    var value = this.getValue();
    if (this.lastValue != value) {
      this.callback(this.element, value);
      this.lastValue = value;
    }
  },

  registerFormCallbacks: function() {
    Form.getElements(this.element).each(this.registerCallback.bind(this));
  },

  registerCallback: function(element) {
    if (element.type) {
      switch (element.type.toLowerCase()) {
        case 'checkbox':
        case 'radio':
          Event.observe(element, 'click', this.onElementEvent.bind(this));
          break;
        default:
          Event.observe(element, 'change', this.onElementEvent.bind(this));
          break;
      }
    }
  }
}

Form.Element.EventObserver = Class.create();
Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

Form.EventObserver = Class.create();
Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
  getValue: function() {
    return Form.serialize(this.element);
  }
});
if (!window.Event) {
  var Event = new Object();
}

Object.extend(Event, {
  KEY_BACKSPACE: 8,
  KEY_TAB:       9,
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,
  KEY_HOME:     36,
  KEY_END:      35,
  KEY_PAGEUP:   33,
  KEY_PAGEDOWN: 34,

  element: function(event) {
    return event.target || event.srcElement;
  },

  isLeftClick: function(event) {
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },

  pointerX: function(event) {
    return event.pageX || (event.clientX +
      (document.documentElement.scrollLeft || document.body.scrollLeft));
  },

  pointerY: function(event) {
    return event.pageY || (event.clientY +
      (document.documentElement.scrollTop || document.body.scrollTop));
  },

  stop: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },

  // find the first node with the given tagName, starting from the
  // node the event was triggered on; traverses the DOM upwards
  findElement: function(event, tagName) {
    var element = Event.element(event);
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  },

  observers: false,

  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },

  unloadCache: function() {
    if (!Event.observers) return;
    for (var i = 0, length = Event.observers.length; i < length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.attachEvent))
      name = 'keydown';

    Event._observeAndCache(element, name, observer, useCapture);
  },

  stopObserving: function(element, name, observer, useCapture) {
    element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.detachEvent))
      name = 'keydown';

    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      try {
        element.detachEvent('on' + name, observer);
      } catch (e) {
		alert('error detaching...');
	  }
    }
  }
});

/* prevent memory leaks in IE */
if (navigator.appVersion.match(/\bMSIE\b/))
  Event.observe(window, 'unload', Event.unloadCache, false);
var Position = {
  // set to true if needed, warning: firefox performance problems
  // NOT neeeded for page scrolling, only if draggable contained in
  // scrollable elements
  includeScrollOffsets: false,

  // must be called before calling withinIncludingScrolloffset, every time the
  // page is scrolled
  prepare: function() {
    this.deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
    this.deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
  },

  realOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return [valueL, valueT];
  },

  cumulativeOffset2: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += (element.offsetTop  || 0) + (parseInt(Element.getStyle(element, "border-top-width")) || 0);
      valueL += (element.offsetLeft || 0) + (parseInt(Element.getStyle(element, "border-left-width")) || 0);
      element = element.offsetParent;
    } while (element);
    return [valueL, valueT];
  },

  cumulativeOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return [valueL, valueT];
  },

  positionedOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if(element.tagName=='BODY') break;
        var p = Element.getStyle(element, 'position');
        if (p == 'relative' || p == 'absolute') break;
      }
    } while (element);
    return [valueL, valueT];
  },

  offsetParent: function(element) {
    if (element.offsetParent) return element.offsetParent;
    if (element == document.body) return element;

    while ((element = element.parentNode) && element != document.body)
      if (Element.getStyle(element, 'position') != 'static')
        return element;

    return document.body;
  },

  // caches x/y coordinate pair to use with overlap
  within: function(element, x, y) {
    if (this.includeScrollOffsets)
      return this.withinIncludingScrolloffsets(element, x, y);
    this.xcomp = x;
    this.ycomp = y;
    this.offset = this.cumulativeOffset(element);

    return (y >= this.offset[1] &&
            y <  this.offset[1] + element.offsetHeight &&
            x >= this.offset[0] &&
            x <  this.offset[0] + element.offsetWidth);
  },

  withinIncludingScrolloffsets: function(element, x, y) {
    var offsetcache = this.realOffset(element);

    this.xcomp = x + offsetcache[0] - this.deltaX;
    this.ycomp = y + offsetcache[1] - this.deltaY;
    this.offset = this.cumulativeOffset(element);

    return (this.ycomp >= this.offset[1] &&
            this.ycomp <  this.offset[1] + element.offsetHeight &&
            this.xcomp >= this.offset[0] &&
            this.xcomp <  this.offset[0] + element.offsetWidth);
  },

  // within must be called directly before
  overlap: function(mode, element) {
    if (!mode) return 0;
    if (mode == 'vertical')
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
        element.offsetHeight;
    if (mode == 'horizontal')
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
        element.offsetWidth;
  },

  page: function(forElement) {
    var valueT = 0, valueL = 0;

    var element = forElement;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent==document.body)
        if (Element.getStyle(element,'position')=='absolute') break;

    } while (element = element.offsetParent);

    element = forElement;
    do {
      if (!window.opera || element.tagName=='BODY') {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return [valueL, valueT];
  },

  clone: function(source, target) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || {})

    // find page position of source
    source = $(source);
    var p = Position.page(source);

    // find coordinate system to use
    target = $(target);
    var delta = [0, 0];
    var parent = null;
    // delta [0,0] will do fine with position: fixed elements,
    // position:absolute needs offsetParent deltas
    if (Element.getStyle(target,'position') == 'absolute') {
      parent = Position.offsetParent(target);
      delta = Position.page(parent);
    }

    // correct by body offsets (fixes Safari)
    if (parent == document.body) {
      delta[0] -= document.body.offsetLeft;
      delta[1] -= document.body.offsetTop;
    }

    // set position
    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
  },

  absolutize: function(element) {
    element = $(element);
    if (element.style.position == 'absolute') return;
    Position.prepare();

    var offsets = Position.positionedOffset(element);
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    element._originalLeft   = left - parseFloat(element.style.left  || 0);
    element._originalTop    = top  - parseFloat(element.style.top || 0);
    element._originalWidth  = element.style.width;
    element._originalHeight = element.style.height;

    element.style.position = 'absolute';
    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.width  = width + 'px';
    element.style.height = height + 'px';
  },

  relativize: function(element) {
    element = $(element);
    if (element.style.position == 'relative') return;
    Position.prepare();

    element.style.position = 'relative';
    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.style.top    = top + 'px';
    element.style.left   = left + 'px';
    element.style.height = element._originalHeight;
    element.style.width  = element._originalWidth;
  }
}

// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  Position.cumulativeOffset = function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      if (element.offsetParent == document.body)
        if (Element.getStyle(element, 'position') == 'absolute') break;

      element = element.offsetParent;
    } while (element);

    return [valueL, valueT];
  }
}

Element.addMethods();Object.extend(Event, {
  _domReady : function() {
    if (arguments.callee.done) return;
    arguments.callee.done = true;
 
    if (Event._timer)  clearInterval(Event._timer);
    
    Event._readyCallbacks.each(function(f) { f() });
    Event._readyCallbacks = null;
    
  },
  onDOMReady : function(f) {
    if (!this._readyCallbacks) {
      var domReady = this._domReady;
      
      if (domReady.done) return f();
      
      if (document.addEventListener)
        document.addEventListener("DOMContentLoaded", domReady, false);
        
        /*@cc_on @*/
        /*@if (@_win32)
            var dummy = location.protocol == "https:" ?  "https://javascript:void(0)" : "javascript:void(0)";
            document.write("<script id=__ie_onload defer src='" + dummy + "'><\/script>");
            document.getElementById("__ie_onload").onreadystatechange = function() {
                if (this.readyState == "complete") { domReady(); }
            };
        /*@end @*/
        
        if (/WebKit/i.test(navigator.userAgent)) { 
          this._timer = setInterval(function() {
            if (/loaded|complete/.test(document.readyState)) domReady(); 
          }, 10);
        }
        
        Event.observe(window, 'load', domReady);
        Event._readyCallbacks =  [];
    }
    Event._readyCallbacks.push(f);
  }
});
if(!CBH) var CBH = {};
CBH.Idea = Class.create();
CBH.Idea.prototype = {

initialize: function(options){
this.options = {
width: 100,
height: 100,
delay: 300
};
this.observers = {};
Object.extend(this.options,options);
},

init: function(container,options){
if(this.container){
window.clearTimeout(this.timer);
if(this.container != $(container)) this.forceHide();
else return false;
}
this.container = $(container);
this.container.onmouseout = this.hide.bindAsEventListener(this);
//this.container.style.border = "solid 2px red";
this.htmlElement = ce('div','','');
this.htmlElement.style.position = 'absolute';
this.htmlElement.style.border = 'solid 1px #000';

Object.extend(this.options,options);
this.limiter = $(options.limiter)?$(options.limiter):document.body;
this.timer = window.setTimeout(this.show.bind(this),this.options.delay);
return false;
},

show: function(){
if(!this.container) return false;
this.container.onmouseout = function(){return false;}

this.offs = Position.cumulativeOffset(this.container);
this.limits = Position.cumulativeOffset(this.limiter);

this.htmlElement.style.left = this.offs[0]+'px';
this.htmlElement.style.top = this.offs[1]+'px';
this.htmlElement.style.width = this.container.offsetWidth+'px';
this.htmlElement.style.height = this.container.offsetHeight+'px';
//this.htmlElement.onmouseout = this.hide.bindAsEventListener(this);
$('absholder').appendChild(this.htmlElement);

/* r.20 */
this.observers.hide = this.hide.bindAsEventListener(this);
Event.observe(document,"mouseup",this.observers.hide);
/**/
this.resizeTo();
},

resizeTo: function(){
var wDone = false;
var hDone = false;
if(this.options.width - this.htmlElement.offsetWidth > 1){
var targetWidth = Math.round(this.htmlElement.offsetWidth+((this.options.width-this.htmlElement.offsetWidth)*0.3));
var targetLeft =  (this.offs[0]  - Math.round((this.htmlElement.offsetWidth - this.container.offsetWidth)/2));
if(targetLeft < this.limits[0]) targetLeft = this.limits[0];
if(targetLeft + targetWidth >= this.limits[0] + this.limiter.offsetWidth) targetLeft = (this.limits[0] + this.limiter.offsetWidth) - targetWidth-1;

this.htmlElement.style.left = targetLeft+'px';
this.htmlElement.style.width =  targetWidth+'px';
}else{
wDone = true;
}
if(this.options.height-this.htmlElement.offsetHeight > 1){
var targetHeight = Math.round(this.htmlElement.offsetHeight+((this.options.height-this.htmlElement.offsetHeight)*0.3));
var targetTop =  (this.offs[1]  - Math.round((this.htmlElement.offsetHeight - this.container.offsetHeight)/2));
if(targetTop < this.limits[1]) targetTop = this.limits[1];
if(targetTop + targetHeight >= this.limits[1] + this.limiter.offsetHeight) targetTop = (this.limits[1] + this.limiter.offsetHeight) - targetHeight-1;

this.htmlElement.style.top = targetTop+'px';
this.htmlElement.style.height =  targetHeight+'px';
}else{
hDone = true;
}
if(!wDone || !hDone) this.timer = window.setTimeout(this.resizeTo.bind(this),10);
else this.fill();
},

hide: function(event){
if(this.htmlElement && event){
var el = event.relatedTarget?event.relatedTarget:event.toElement;
if(el && el != this.htmlElement && !Element.childOf(el,this.htmlElement)){
this.forceHide();
return;
}
/* r.20 */
var el =Event.element(event);
if(el && el != this.htmlElement && !Element.childOf(el,this.htmlElement)){
this.forceHide();
return;
}
/**/
}
},

forceHide: function(){
window.clearTimeout(this.timer);
rm(this.htmlElement,true);
if(this.container) {
this.container.onmouseout = function(){return false;}
//this.container.style.border = "none";
this.container = null;
}
/* r.20 */
if(this.observers.hide) Event.stopObserving(document,"mouseup",this.observers.hide);
/**/
},

fill: function(){
alert('bug');
},

toggleMenu: function(el,target){
Element.toggle(target);
el.style.display='none';
this.htmlElement.style.width = this.htmlElement.childNodes[0].offsetWidth+'px';
this.htmlElement.style.height = this.htmlElement.childNodes[0].offsetHeight+'px';
}

};
if(!CBH) var CBH = {};
CBH.AvatarMenu = Class.create();
CBH.AvatarMenu.prototype = {

initialize: function(){

},

init: function(container,userId,username,permissions,size){
if(this.container){
this.cancelHide();
this.hide();
}
this.container = $(container);
this.container.item = {
user_id: userId,
username: username,
permissions: permissions,
size: size
}
this.userId = userId;
this.username = username;
this.size = size;
this.permissions=permissions?permissions:'0';
this.show();
this.createMenu();
},

initFromEvent: function(event){
var el = Event.element(event);
this.init(el,el.item.user_id,el.item.username,el.item.permissions,el.item.size);
},

show: function(){
this.htmlElement = ce('div','','avatar_menu');
var butt = ce('div','','avatar_menu_button');
butt.onclick = this.toggleMenu.bindAsEventListener(this);
butt.innerHTML = '&nbsp;';
this.htmlElement.appendChild(butt);
var img = ce('img','','avatar_menu_img');
img.src = this.container.src;
img.style.width = this.size+'px';
img.style.height = this.size+'px';
img.onclick = this.openProfile.bindAsEventListener(this);
img.style.cursor = 'pointer';
this.htmlElement.appendChild(img);
/*
var usrnm = ce('div','','');
usrnm.innerHTML = this.username;
usrnm.style.backgroundColor = '#FFF';
this.htmlElement.appendChild(usrnm);
*/
this.offs = Position.cumulativeOffset(this.container);

this.htmlElement.style.width = this.size+25+'px';
this.htmlElement.style.height = this.size+10+'px';
this.htmlElement.style.left = this.offs[0]-6-(this.size-this.container.offsetWidth)/2+'px';
this.htmlElement.style.top = this.offs[1]-6-(this.size-this.container.offsetHeight)/2+'px';
document.body.appendChild(this.htmlElement);
this.htmlElement.onmouseout = this.checkHide.bindAsEventListener(this);
this.htmlElement.onmouseover = this.cancelHide.bindAsEventListener(this);
/*
this.htmlElement.style.opacity = '0.0';
this.htmlElement.style.filter = 'alpha(opacity:0)';
new Effect.Appear(this.htmlElement, { duration: 0.2, from: 0.0, to: 1.0});
*/
},

openProfile: function(){
document.location.href = '/'+this.username+'/';
},

hide: function(){
rm(this.htmlElement,true);
},

cancelHide: function(){
clearTimeout(this.timer);
},

checkHide: function(event){
var el = event.relatedTarget?event.relatedTarget:event.toElement;
if(el != this.htmlElement && !Element.childOf(el.parentNode,this.htmlElement)){
 this.timer = window.setTimeout(this.hide.bind(this),200);
}
},
toggleMenu: function(){

if(this.subMenuElement.style.display!='block'){
this.subMenuElement.style.display='block';

                this.subMenuElement.childNodes[1].style.opacity = '0.0';
                this.subMenuElement.childNodes[1].style.filter = 'alpha(opacity:0)';
                new Effect.Appear(this.subMenuElement.childNodes[1], { duration: 0.5, from: 0.0, to: 1.0});
//this.htmlElement.style.borderRight = '0px';
}else{
this.subMenuElement.style.display='none';
//this.htmlElement.style.borderStyle= 'outset';
//this.htmlElement.style.borderWidth= '1px';
}

},

createMenu: function(){

this.subMenuElement = ce('div','','avatar_menu_submenu');
var h = ce('h5','','');
h.innerHTML = this.username;
this.subMenuElement.appendChild(h);
var ul = ce('ul','','');
if(Current.get('sess_user_id') && this.userId != Current.get('sess_user_id')){
var l1 = ce('li','','');
var a1 = ce('a','','');
a1.onclick = this.openContactForm.bindAsEventListener(this);
a1.href = 'javascript:void(0);';

if(this.permissions==0){
a1.innerHTML = 'Добави в познати';
l1.appendChild(a1);
}
else{
var s = ce('span','','');

a1.innerHTML = ' - промени?';

if(this.permissions==1) s.innerHTML = 'Познат ';
if(this.permissions==2) s.innerHTML = 'Приятел ';
if(this.permissions==3) s.innerHTML = 'VIP ';

s.appendChild(a1);
l1.appendChild(s);
l1.appendChild(ce('hr','',''));
}
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/communication/?m=4&l='+this.userId+'';
a1.innerHTML = 'Напиши съобщение';
l1.appendChild(a1);
ul.appendChild(l1);

}else if(Current.get('sess_user_id') == this.userId ){
 var l1 = ce('li','','');
 var a1 = ce('a','','');
 a1.innerHTML = 'Смени аватара';
 a1.href = '/account/avatar/';
 l1.appendChild(a1);
 l1.appendChild(ce('hr','',''));
 ul.appendChild(l1);

}


var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/';
a1.innerHTML = 'Страница';
l1.appendChild(a1);
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/albums/';
a1.innerHTML = 'Албуми';
l1.appendChild(a1);
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/profile/';
a1.innerHTML = 'Профил';
l1.appendChild(a1);
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/favorites/';
a1.innerHTML = 'Любими';
l1.appendChild(a1);
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/tags/';
a1.innerHTML = 'Тагове';
l1.appendChild(a1);
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/contacts/';
a1.innerHTML = 'Познати';
l1.appendChild(a1);
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/comments/';
a1.innerHTML = 'Коментари';
l1.appendChild(a1);
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/calendar/';
a1.innerHTML = 'Календар';
l1.appendChild(a1);
ul.appendChild(l1);

var l1 = ce('li','','');
var a1 = ce('a','','');
a1.href = '/'+this.username+'/history/';
a1.innerHTML = 'Последно разгледани';
l1.appendChild(a1);
ul.appendChild(l1);

this.subMenuElement.style.left = this.htmlElement.offsetWidth-2+'px';
this.subMenuElement.style.top = '-1px';
this.subMenuElement.appendChild(ul);
this.htmlElement.appendChild(this.subMenuElement);
},

openContactForm: function() {
CBH.Contacts.editor({
username: this.username,
user_id: Current.get('sess_user_id'),
contact_id: this.userId,
permissions: this.permissions
});
return false;
}



}
var avatarMenu = new CBH.AvatarMenu();
//#########################################################################################
CBH.Avatar = Class.create();
Object.extend(CBH.Avatar.prototype, CBH.Idea.prototype);
Object.extend(CBH.Avatar.prototype, {

// TODO: find a way to call the parent's function here
init: function(container, options) {
if (this.container) {
window.clearTimeout(this.timer);
if (this.container != $(container))
this.forceHide();
else
return false;
}
this.container = $(container);
this.container.init = {
options: options
};
this.container.onmouseout = this.hide.bindAsEventListener(this);
//this.container.style.border = "solid 2px red";
this.htmlElement = ce('div', '', '');
this.htmlElement.style.position = 'absolute';
this.htmlElement.style.border = 'solid 1px #000';

Object.extend(this.options,options);
this.limiter = $(options.limiter)? $(options.limiter) : document.body;
this.timer = window.setTimeout(this.show.bind(this), this.options.delay);
return false;
},

initFromEvent: function(event) {
var el = Event.element(event);
this.init(el, el.init.options);
},

fill: function(){
// update the params, if needed
var params = {
user_id: Current.get('sess_user_id'),
contact_id: this.options.userinfo.user_id,
permissions: this.options.userinfo.permissions,
banned: this.options.userinfo.banned
};
params = CBH.Contacts.updateParams(params);
this.options.userinfo.permissions = parseInt(params.permissions);
this.options.userinfo.banned = parseInt(params.banned);
// start building the innerHTML
this.htmlElement.style.border = 'none';
var addHTML = "";
var prepareContactForm = false;
var HTML = ""+
"<div class='content amenu'><div class='area'><a class='close' onClick='Avatar.forceHide();return false;'></a>"+
"<h3>"+this.options.userinfo.username+"</h3>";
if (Current.get('sess_user_id') && this.options.userinfo.user_id != Current.get('sess_user_id')) {
if (this.options.userinfo.banned) {
HTML += "<p>за теб е: <span>Блокиран</span>";
HTML += "<a href='javascript:void(0);' id='Avatar_delete' style='margin:5px auto;'>Изтрий и отблокирай</a></p>";
} else if (!this.options.userinfo.permissions) {
HTML += "<p>";
HTML += "<a href='javascript:void(0);' id='Avatar_change_type' style='font-weight: bold;margin:5px auto;'>Добави в познати</a>";
HTML += "<a href='javascript:void(0);' id='Avatar_ban' style='margin:5px auto;'>Блокирай</a>";
HTML += "</p>";
} else {
HTML += "<p>за теб е: ";

switch (this.options.userinfo.permissions) {
case 1: HTML += "<span>Познат</span>"; break;
case 2: HTML += "<span>Приятел</span>"; break;
case 3: HTML += "<span>VIP</span>"; break;
}

HTML += "<span style='font-size: 10px'>";
HTML += "<a href='javascript:void(0);' id='Avatar_change_type'>(промени)</a>";
HTML += "<a href='javascript:void(0);' id='Avatar_ban'>Блокирай</a>";
HTML += "<a href='javascript:void(0);' id='Avatar_delete'>Изтрий</a>";
HTML += "</span></p>";
}
addHTML = "<li><a href='/communication/?m=4&l="+this.options.userinfo.user_id+"'>Изпрати съобщение</a></li>";
} else if (Current.get('sess_user_id') == this.options.userinfo.user_id) {
HTML += "<p><a href='/account/avatar/' style='font-weight: bold;margin:5px auto;'>Смени аватара</a></p>";
addHTML = "<li><a href='/account/'>Настойки на акaунта</a></li>";
} else {
//Not Logged
HTML += "<p><a href='/login/' style='font-weight: bold;margin:5px auto;'>Добави в познати</a></p>";
}
if (typeof this.options.userinfo.images != 'undefined') {
HTML += "<p style='text-align:right;'>"+this.options.userinfo.images+" снимки</p>";
}
HTML += "<a href='/"+this.options.userinfo.username+"/'><img src='"+this.container.src+"'></a>";
HTML += ""+
"<ul>"+
"<li><a href='/"+this.options.userinfo.username+"/'><strong>Страница</strong></a></li>"+
"<li><a href='/"+this.options.userinfo.username+"/profile/'><strong>Профил</strong></a></li>"+
""+addHTML+
"</ul>"+
"<a class='more' onClick='Avatar.toggleMenu(this,\"аvatar_more\");return false;'></a>"+
"<ul id='аvatar_more' style='display:none'>"+
"<li><a href='/"+this.options.userinfo.username+"/albums/'>Албуми</a></li>"+
"<li><a href='/"+this.options.userinfo.username+"/favorites/'>Любими</a></li>"+
"<li><a href='/"+this.options.userinfo.username+"/tags/'>Тагове</a></li>"+
"<li><a href='/"+this.options.userinfo.username+"/contacts/'>Познати</a></li>"+
"<li><a href='/"+this.options.userinfo.username+"/comments/'>Коментари</a></li>"+
"<li><a href='/"+this.options.userinfo.username+"/calendar/'>Календар</a></li>"+
"<li><a href='/"+this.options.userinfo.username+"/history/'>Последно разгледани</a></li>"+
"</ul>"+
"<em style='display:block;clear:both'></em>"+
"</div></div>";
this.htmlElement.innerHTML =  HTML;
if ($('Avatar_change_type'))
$('Avatar_change_type').onclick = this.contactEdit.bindAsEventListener(this);
if ($('Avatar_ban'))
$('Avatar_ban').onclick = this.contactBan.bindAsEventListener(this);
if ($('Avatar_delete'))
$('Avatar_delete').onclick = this.contactDelete.bindAsEventListener(this);

this.htmlElement.style.padding = '0px 5px 5px 0px';
this.htmlElement.style.width = this.htmlElement.childNodes[0].offsetWidth+'px';
this.htmlElement.style.height = this.htmlElement.childNodes[0].offsetHeight+'px';
this.htmlElement.style.background = 'transparent url(http://static.album.bg/images/shadow.png)';
this.htmlElement.style.backgroundPosition = 'bottom right';

},

contactBan: function() {
this.forceHide();
CBH.Contacts.ban({
username: this.options.userinfo.username,
user_id: Current.get('sess_user_id'),
contact_id: this.options.userinfo.user_id,
permissions: this.options.userinfo.permissions
});
return false;
},

contactDelete: function() {
this.forceHide();
CBH.Contacts.del({
username: this.options.userinfo.username,
user_id: Current.get('sess_user_id'),
contact_id: this.options.userinfo.user_id,
permissions: this.options.userinfo.permissions,
banned: this.options.userinfo.banned
});
return false;
},

contactEdit: function() {
this.forceHide();
CBH.Contacts.editor({
username: this.options.userinfo.username,
user_id: Current.get('sess_user_id'),
contact_id: this.options.userinfo.user_id,
permissions: this.options.userinfo.permissions
});
return false;
}

});
var Avatar = new CBH.Avatar({delay: 500,width:174,height:180});
if(!CBH) var CBH = {};
//############################################
CBH.Drag = Class.create();
CBH.Drag.prototype = {

initialize: function(container){
this.container = $(container);
this._attachBehaviors();
this.timer=null;
},

_attachBehaviors: function() {
//Init Elements & Events
for(var i=0;i<this.container.childNodes.length;i++){
if(this.container.childNodes[i].tagName!='undefined'){
this.container.childNodes[i].onmousedown = this.dragStart.bindAsEventListener(this);
}
}
//Init Scrolling Step
//this.scrollingStep = Math.round(this.container.offsetWidth/this.elements[0].offsetWidth);

//Init Container Offsets
var offs = Position.cumulativeOffset(this.container.parentNode);
this.container.parentNode._offsetWidth = offs[0];
this.container.parentNode._offsetHeight = offs[1];

//Attach Master Events
document.body.onmouseup = this.dragStop.bindAsEventListener(this);
document.body.onmousemove = this.dragMove.bindAsEventListener(this);
document.body.onselectstart = this.cancelEvent.bindAsEventListener(this);
document.body.ondragstart = this.cancelEvent.bindAsEventListener(this);
},

attachOnDragStopHandler: function(handler){
this.onDragStopHandler = handler;
},
dragStart: function(event){
this.sourceElement = Event.element(event).parentNode.parentNode;

//Drag only if target is child of the container
if(this.sourceElement.parentNode != this.container) {
this.sourceElement = null;
return;
}
clearTimeout(this.timer);
this.timer = null;
if(this.clone) this.killClone();
this.sourceElement = Event.element(event).parentNode.parentNode;
this.makeClone();
return false;
},

dragStop: function(event){
if(this.sourceElement && this.targetElement){
try{
if(this.sourceElement.item_index != this.targetElement.item_index)
if(this.onDragStopHandler) eval(this.onDragStopHandler+"(this.sourceElement.item_index,this.targetElement.item_index)");
}
catch(ex){ /*alert(ex);*/ }
}
else{
clearTimeout(this.timer);
this.timer = null;
if(this.clone) this.killClone();
return false;
}
},

success: function(data){
this.container.insertBefore(this.sourceElement,this.targetElement);
clearTimeout(this.timer);
this.timer = null;
if(this.clone) this.killClone();
return false;
},

dragMove: function(event){
if(this.clone){

var x = Event.pointerX(event);
var y = Event.pointerY(event);

this.clone.style.top =  y+5+'px';
this.clone.style.left =  x+5+'px';

//Scroll Down
if(y > this.container.parentNode.offsetHeight + this.container.parentNode._offsetHeight){
if(this.container.parentNode.scrollTop < this.container.parentNode.scrollHeight){
this.container.parentNode.scrollTop = parseInt(this.container.parentNode.scrollTop) + 30;
}
}
//Scroll Up
if(y < this.container.parentNode._offsetHeight){
if(this.container.parentNode.scrollTop > 0){
this.container.parentNode.scrollTop = parseInt(this.container.parentNode.scrollTop) - 30;
}
}
//The Target & Marker
var trg = Event.element(event).parentNode.parentNode;
if(trg.parentNode == this.container){
if(this.targetElement){
this.targetElement.style.borderLeft= 'solid 3px #FFF';
}
//Selecet right element if poiner is in right part of target element
if(event.offsetX > trg.offsetWidth/2){
var num = this.getIndex(trg);
if(num) trg = this.container.childNodes[num+1];
}
trg.style.borderLeft= 'solid 3px #000';
this.targetElement = trg;
}
}
return false;
},

cancelEvent: function (event){
return false;
},

makeClone: function(){
if(!this.timer){
this.timer = setTimeout(this.makeClone.bind(this),250);
return;
}
else{
if(!this.sourceElement) return;
this.clone = this.sourceElement.cloneNode(true);
this.clone.className = 'image_very_small_cloned';
this.clone.id = 'dragClone';
$('absholder').appendChild(this.clone);
}
},

killClone: function(){
Element.remove('dragClone');
this.clone = null;
if(this.targetElement){
this.targetElement.style.borderLeft= 'solid 3px #FFF';
this.targetElement = null;
}
this.sourceElement = null;
},

getIndex: function(el){
for(var i=0;i<this.container.childNodes.length;i++){
if(this.container.childNodes[i].tagName!='undefined'){
if(el == this.container.childNodes[i]) return i;
}
}
return 0;
}

}
var Topics = {

api_base: function() {
//Here we use a function in order to evaluate the URL dynamically every time we need it.
//This allows us to use Current.get(...), because Current is updated after Topics is created.
return '/api.php?object=discussions&page=' + Current.get('page') + '&';
},

submit_form: function(form) {
var url = Topics.api_base();
for (var i = 0; i < form.elements.length; i++) {
if (form.elements[i].name) {
url += '&' + form.elements[i].name + '=' + encodeURIComponent(form.elements[i].value);
}
}
call(url, 'Topics.update', '', form, 'POST', true);
},

edit: function(topic_id, container_id) {
var url = Topics.api_base() + 'action=get_edit_form&id=' + topic_id;
call(url, function(data) {
var html = Topics.get_data(data);
if ($(container_id)) {
$(container_id).__innerHTML__ = $(container_id).innerHTML;
$(container_id).innerHTML = html;
}
}, '', null);
return false;
},

edit_cancel: function(form_id, container_id) {
if ($(form_id)) rm($(form_id), true);
if ($(container_id)) $(container_id).innerHTML = $(container_id).__innerHTML__;
return false;
},

del: function(topic_id, container_id) {
var url = Topics.api_base() + 'action=delete&id=' + topic_id;
call(url, 'Topics.update', '', null, 'POST');
return false;
},

del_with_confirmation: function(topic_id, container_id) {
CBH.Dialogs.confirm({
message: 'Сигурен ли си, че искаш да изтриеш избраното?',
ok_callback: function() {
Topics.del(topic_id, container_id);
}
});
return false;
},

get_data: function(data) {
var object = data.getElementsByTagName('object');
return object[0].text? object[0].text : object[0].childNodes[1].nodeValue;
},

evaluate: function(data) {
var code = data.getElementsByTagName('evaluate');
if (code[0]) {
return eval(code[0].text? code[0].text : code[0].childNodes[1].nodeValue);
}
},

update: function(data, container_id) {
if (!container_id) container_id = 'frame';
if ($(container_id))
$(container_id).innerHTML = Topics.get_data(data);
Topics.evaluate(data);
}

}
if(!CBH) var CBH = {};
CBH.ModalDialog = {

init: function(){
CBH.ModalDialog.scrollables = new Array();
CBH.ModalDialog.backgr = document.createElement('div');
CBH.ModalDialog.backgr.className = 'modal_dialog_background';

CBH.ModalDialog.div = document.createElement('div');
CBH.ModalDialog.div.className="modal_dialog";


CBH.ModalDialog.closeBar = document.createElement('a');
CBH.ModalDialog.closeBar.href="javascript:void(0)";
CBH.ModalDialog.closeBar.title="Затвори прозореца";
CBH.ModalDialog.closeBar.onclick=CBH.ModalDialog.close;
CBH.ModalDialog.closeBar.innerHTML="&nbsp;";
CBH.ModalDialog.closeBar.className="modal_dialog_close";
CBH.ModalDialog.div.appendChild(CBH.ModalDialog.closeBar);

CBH.ModalDialog.title = document.createElement('h2');
CBH.ModalDialog.title.className="modal_dialog_title";
CBH.ModalDialog.div.appendChild(CBH.ModalDialog.title);

CBH.ModalDialog.content = document.createElement('div');
CBH.ModalDialog.content.className="modal_dialog_content";
CBH.ModalDialog.div.appendChild(CBH.ModalDialog.content);

},
setScrollable: function(element){
CBH.ModalDialog.scrollables.push(element);
},
setTitle: function(title){
CBH.ModalDialog.title.innerHTML = title;
},
setHTMLElement: function(element){
CBH.ModalDialog.htmlElement = element;
CBH.ModalDialog.htmlElementOldParent = element.parentNode;

CBH.ModalDialog.content.appendChild(CBH.ModalDialog.htmlElement);
},
setWidth: function(width){
CBH.ModalDialog.div.style.width = width+"px";
CBH.ModalDialog.div.style.marginLeft = - Math.floor(width/2)+'px';
},
setHeight: function(height){
CBH.ModalDialog.div.style.height = height+"px";
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
CBH.ModalDialog.div.style.marginTop = scrollTop- Math.floor(height/2)+'px';
},
getPageSize: function(){

var xScroll, yScroll;

if (window.innerHeight && window.scrollMaxY) {
xScroll = document.body.scrollWidth;
yScroll = window.innerHeight + window.scrollMaxY;
} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}

var windowWidth, windowHeight;
if (self.innerHeight) {// all except Explorer
windowWidth = self.innerWidth;
windowHeight = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight;
} else if (document.body) { // other Explorers
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}

// for small pages with total height less then height of the viewport
if(yScroll < windowHeight){
pageHeight = windowHeight;
} else {
pageHeight = yScroll;
}

// for small pages with total width less then width of the viewport
if(xScroll < windowWidth){
pageWidth = windowWidth;
} else {
pageWidth = xScroll;
}
arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight)
return arrayPageSize;
},
open: function(){
for(var i=0;i<CBH.ModalDialog.scrollables.length;i++){
$(CBH.ModalDialog.scrollables[i]).style.overflowY='hidden';
}
if(document.body){
var winSize = this.getPageSize();
$('absholder').appendChild(CBH.ModalDialog.backgr);
$('absholder').appendChild(CBH.ModalDialog.div);
CBH.ModalDialog.backgr.style.width = '100%';
CBH.ModalDialog.backgr.style.height = winSize[1]+'px';
}else {
document.documentElement.appendChild(CBH.ModalDialog.backgr);
document.documentElement.appendChild(CBH.ModalDialog.div);
}
//Autofocus on the first input of the dialog
var inputs = CBH.ModalDialog.div.getElementsByTagName('input');
if (inputs && inputs.length && inputs[0].focus)
inputs[0].focus();
},
close: function(){
if(CBH.ModalDialog.htmlElementOldParent){
CBH.ModalDialog.htmlElementOldParent.appendChild(CBH.ModalDialog.htmlElement);
}
Element.remove(CBH.ModalDialog.backgr);
Element.remove(CBH.ModalDialog.div);
for(var i=0;i<CBH.ModalDialog.scrollables.length;i++){
$(CBH.ModalDialog.scrollables[i]).style.overflowY='scroll';
}

}
};
if (!CBH) var CBH = {};
CBH.Dialogs = {

confirm: function(params) {
default_params = {
width: 400,
height: 150,
title: 'Потвърждение',
ok_callback: CBH.ModalDialog.close,
cancel_callback: CBH.ModalDialog.close
};
for (k in default_params) {
if (typeof params[k] == 'undefined') {
params[k] = default_params[k];
}
}
CBH.Dialogs.__ok_callback__ = params.ok_callback;
CBH.Dialogs.__cancel_callback__ = params.cancel_callback;
var confirm_form = ce('div');
confirm_form.innerHTML = '<form>' +
'<p style="text-align: center;">' + params.message + '</p>' +
'<div style="text-align: center; margin-top: 20px;">' +
'<input type="button" value="Да" ' +
' onclick="' +
'CBH.ModalDialog.close(); ' +
'CBH.Dialogs.__ok_callback__(); ' +
'" class="submit" ' + 
' style="margin-right: 10px; width: 80px;" />' +
'<input type="button" value="Не" onclick="CBH.Dialogs.__cancel_callback__();" class="cancel" ' +
' style="width: 80px;" />' +
'</div>' +
'</form>';
CBH.ModalDialog.init();
CBH.ModalDialog.setTitle(params.title);
CBH.ModalDialog.setHTMLElement(confirm_form);
CBH.ModalDialog.setWidth(params.width);
CBH.ModalDialog.setHeight(params.height);
CBH.ModalDialog.open();
return false;
},

message: function(params) {
default_params = {
width: 400,
height: 150,
title: 'Информация',
accept_button: 'Да',
ok_callback: CBH.ModalDialog.close
};
for (k in default_params) {
if (typeof params[k] == 'undefined') {
params[k] = default_params[k];
}
}
CBH.Dialogs.__ok_callback__ = params.ok_callback;
var confirm_form = ce('div');
confirm_form.innerHTML = '<form>' +
'<p style="text-align: center;">' + params.message + '</p>' +
'<div style="text-align: center; margin-top: 20px;">' +
'<input type="button" value="'+ params.accept_button +'" ' +
' onclick="' +
'CBH.ModalDialog.close(); ' +
'CBH.Dialogs.__ok_callback__(); ' +
'" class="submit" ' + 
' style="margin-right: 10px; width: 80px;" />' +
'</div>' +
'</form>';
CBH.ModalDialog.init();
CBH.ModalDialog.setTitle(params.title);
CBH.ModalDialog.setHTMLElement(confirm_form);
CBH.ModalDialog.setWidth(params.width);
CBH.ModalDialog.setHeight(params.height);
CBH.ModalDialog.open();
return false;
}

}
if (!CBH) var CBH = {};
CBH.Contacts = {};      // the global interface to using contacts functionallity
CBH.Contacts.data = {}; // the global permissions status cache

/**
 * Automatic permissions editor
 * Required: user_id, username, contact_id, permissions
 * Optional: avatar_icon, width, height, banned
 */
CBH.Contacts.editor = function(params) {
var form = new CBH.ContactForm(CBH.ModalDialog);
form.avatarIcon = params.avatar_icon;
params = CBH.Contacts.updateParams(params);
form.createForm(params);

CBH.ModalDialog.init();
if (params.permissions || params.banned) {
CBH.ModalDialog.setTitle('Промени:');
} else {
CBH.ModalDialog.setTitle('Добави в познати:');
}

if (!params.width) params.width = 320;
if (!params.height) params.height = 160;
CBH.ModalDialog.setHTMLElement(form.htmlElement);
CBH.ModalDialog.setWidth(params.width);
CBH.ModalDialog.setHeight(params.height);
CBH.ModalDialog.open();
};

/**
 * Confirm dialog and a ban action
 * Required: username, contact_id
 * Optional: message, post_base, user_id
 */
CBH.Contacts.ban = function(params) {
params = CBH.Contacts.updateParams(params);
CBH.Dialogs.confirm({
message: params.message? params.message : 'Сигурен ли си, че искаш да <b>блокираш</b> потребител <b>' + params.username + '</b>?<br /><br /><span style="color: red; font-weight: bold;">Това ще изтрие всички негови коментари на твои снимки!</span>',
ok_callback: function() { CBH.Contacts.action_ban(params); },
height: 170
});
};

/**
 * Confirm dialog and a delete action
 * Required: username, contact_id
 * Optional: message, banned, post_by_form, user_id
 */
CBH.Contacts.del = function(params) {
params = CBH.Contacts.updateParams(params);
var extraMessage = params.banned? ' С това действие ще отблокираш потребителя.' : '';
CBH.Dialogs.confirm({
message: params.message? params.message : 'Сигурен ли си, че искаш да изтриеш потребител <b>' + params.username + '</b> от твоите контакти?' + extraMessage,
ok_callback: function() { CBH.Contacts.action_del(params); }
});
};

/**
 * Deletes the specified user
 * Required: user_id, contact_id, post_by_form
 */
CBH.Contacts.action_del = function(params) {
var url = params.post_by_form? params.post_by_form : '/api.php?object=contacts&action=delete';
for (key in params) {
if (key == 'user_id' || key == 'contact_id') {
url += '&data[' + key + ']=' + encodeURIComponent(params[key]);
}
}
if (params.post_by_form) {
CBH.Contacts.post_by_form(url);
} else {
call(url, function(data) {
if (params.handler) params.handler(data)
else CBH.Contacts.success(data);
try {
var new_permissions = params;
new_permissions.permissions = 0;
new_permissions.banned = 0;
CBH.Contacts.data[params.user_id + '_' + params.contact_id] = new_permissions;
} catch (e) {}
}, params.post_data, params.target, 'POST');
}
};

/**
 * Bans the specified user
 * Required: user_id, contact_id, post_by_form
 */
CBH.Contacts.action_ban = function(params) {
var url = params.post_by_form? params.post_by_form : '/api.php?object=contacts&action=ban';
for (key in params) {
if (key == 'user_id' || key == 'contact_id') {
url += '&data[' + key + ']=' + encodeURIComponent(params[key]);
}
}
if (params.post_by_form) {
CBH.Contacts.post_by_form(url);
} else {
call(url, params.handler? params.handler : CBH.Contacts.success, params.post_data, params.target, 'POST');
}
};

/**
 * Use this function to post to the page itself the given URL
 * Required: url
 */
CBH.Contacts.post_by_form = function(url) {
var form = document.createElement('form');
form.method = 'POST';
form.action = url;
form.style.display = 'none';
document.body.appendChild(form);
form.submit();
};

/**
 * Called automatically when an edit/ban/delete action completes successfully; updates the JS-global permission status cache
 */
CBH.Contacts.success = function(data) {
floatingMessages.createMsg('Промята беше извършена успешно.', '0', 3000);
if (data.getElementsByTagName) {
var object = data.getElementsByTagName('object');
if (object[0].text) {
eval('data=' + object[0].text);
} else {
eval('data=' + object[0].childNodes[1].nodeValue);
}
}
var o = data[0];
if (o && o.user_id && o.contact_id) {
CBH.Contacts.data[o.user_id + '_' + o.contact_id] = o;
}
};

/**
 * Use this to update the parameters in `params` so that they are more adequate for the current load of the page
 */
CBH.Contacts.updateParams = function(params) {
if (!params) return params;
var user_id = params.user_id? params.user_id : Current.get('sess_user_id');
if (!user_id) user_id = '0';
var contact_id = params.contact_id? params.contact_id : '0';
var key = user_id + '_' + contact_id;
if (CBH.Contacts.data[key]) {
var o = CBH.Contacts.data[key];
for (var k in params) {
if (typeof o[k] != 'undefined') {
params[k] = o[k];
}
}
}
return params;
};
if(!CBH) var CBH = {};
CBH.ImageMenu = Class.create();
CBH.ImageMenu.prototype = {

initialize: function(){

},

init: function(container,imageId,prevURL,nextURL){
if(imageId == this.imageId) return;
if(this.htmlElement){
rm(this.htmlElement,true);
}
if(prevURL) this.prevURL = prevURL;
if(nextURL) this.nextURL = nextURL;
this.container = $(container);
this.container.onmouseout = this.hide.bindAsEventListener(this);
this.imageId = imageId;
var i1 = new Image();
i1.src='http://static.album.bg/images/avatar2.gif';
var prev = new Image();
prev.src='http://static.album.bg/images/prev2.gif';
var next = new Image();
next.src='http://static.album.bg/images/next2.gif';
//this.show();
this.offs = new Array();
this.wiatForOffsetAndShow();
},

wiatForOffsetAndShow: function(){
if(this.offs[0] && this.offs[1]) this.show();
else{
this.offs = Position.cumulativeOffset(this.container);
if(!this.offs[0] || !this.offs[1]) setTimeout(this.wiatForOffsetAndShow.bind(this),500);
else{
//if(this.container.offsetWidth < 300 || this.container.offsetHeight < 300) alert('small '+this.container.offsetWidth+' x '+this.container.offsetHeight);
this.show();
}
}
},

showInlineComments: function(event){
if(this.comments){
for(var i=0;i<this.comments.length;i++){
var c = new CBH.InlineComment();
c.createElement(this.comments[i],this.offs);
}
this.commentAreShown = true;
var el = Event.element(event);
                el.title = 'Скрий вградените коментари';
                el.src='http://static.album.bg/images/comments_hide.png';

}
},

hideInlineComments: function(event){
if(this.comments){
for(var i=0;i<this.comments.length;i++){
rm($('inline_comment_'+this.comments[i].id),true);
}
this.commentAreShown = false;
                        var el = Event.element(event);
                        el.title = 'Покажи вградените коментари';
                        el.src='http://static.album.bg/images/comments_show.png';
}
},

checkInlineComments: function(event){
if(this.commentAreShown){
this.hideInlineComments(event);
}else{
this.showInlineComments(event);
}
},

show: function(){
this.htmlElement = ce('div','','image_menu');
this.htmlElement.onmouseout = this.hide.bindAsEventListener(this);

if(this.prevURL){
var prev = ce('a','','image_nav_prev');
prev.href = this.prevURL;
prev.title = 'Предишна';
var img = ce('img','','');
img.src='http://static.album.bg/images/prev2.gif';
prev.appendChild(img);
}
                if(this.nextURL){
                        var next = ce('a','','image_nav_next');
                        next.href = this.nextURL;
                        next.title = 'Следваща';
                        var img = ce('img','','');
                        img.src='http://static.album.bg/images/next2.gif';
                        next.appendChild(img);
                }
if(prev || next){
                this.nav = ce('div','','image_nav');
this.nav.onmouseout = this.hide.bindAsEventListener(this);
if(prev) this.nav.appendChild(prev);
if(next) this.nav.appendChild(next);
}
var a = ce('a','','');
a.href = '/account/avatar_select/?image='+this.container.src;
a.title = 'Направи аватар.';
var img = ce('img','','');
img.src='http://static.album.bg/images/avatar2.gif';
a.appendChild(img);
this.htmlElement.appendChild(a);


if(Current.get('sess_user_id')){
var img = ce('img','','');
img.title = 'Добави вграден коментар';
img.src='http://static.album.bg/images/comments_add.png';
img.onclick = InlineComments.init.bind(InlineComments,this.container,this.imageId);
this.htmlElement.appendChild(img);
}

if(this.comments){
img = ce('img','','');
if(!this.commentAreShown){
img.title = 'Покажи вградените коментари';
img.src='http://static.album.bg/images/comments_show.png';
}else{
                                img.title = 'Скрий вградените коментари';
                                img.src='http://static.album.bg/images/comments_hide.png';
}
img.onclick = this.checkInlineComments.bindAsEventListener(this);
this.htmlElement.appendChild(img);
}

$('absholder').appendChild(this.htmlElement);
this.htmlElement.style.left = this.offs[0]- 20 + this.container.offsetWidth - (20*this.htmlElement.childNodes.length) +'px';
this.htmlElement.style.top = this.offs[1]+ 5 +'px';
if(this.nav){
$('absholder').appendChild(this.nav);
this.nav.style.left = this.offs[0]+'px';
this.nav.style.top = this.offs[1] + this.container.offsetHeight - 40+'px';
this.nav.style.width = this.container.offsetWidth+'px';
//this.nav.style.width = '500px';
this.nav.style.display = 'none';
new Effect.Appear(this.nav, { duration: 0.5, from: 0.0, to: 1.0 });
}

},

hide: function(event){
var el = event.relatedTarget?event.relatedTarget:event.toElement;
if( el!=null && el != this.container && el != this.htmlElement && !Element.childOf(el,this.htmlElement) && el != this.nav && !Element.childOf(el,this.nav)){
this.imageId = null;
rm(this.htmlElement,true);
if(this.nav) rm(this.nav,true);
}
},

cancelEvent: function(event){
return false;
}

};
var imageMenu = new CBH.ImageMenu();
if(!CBH) var CBH = {};
CBH.Form = Class.create();
CBH.Form.prototype = {

initialize: function(){

},

createForm: function(){
return true;
},

submit: function(){
call('/api.php?'+Form.serialize(this.htmlElement),this.success.bind(this),'',this.htmlElement);
},

reset: function(){
return true;
},

success: function(){
alert('Nema Bace!');
return true;

},

error: function(){
return true;
}

};

CBH.ContactForm = Class.create();
Object.extend(CBH.ContactForm.prototype,CBH.Form.prototype);
Object.extend(CBH.ContactForm.prototype,{

initialize: function(dialog){
this.dialog = dialog;
},

createForm: function(params){
this.htmlElement = ce('FORM','','');
var html = ""+
"<table style='height:100%;width:100%'>"+
"<tr>"+
"<td rowspan='2' valign='top'><img src='http://avatars.album.bg/"+params.username+".gif'></td>"+
"<th align='left'>Маркирай като:</th>"+
"</tr>"+
"<tr>"+
"<td valign='top'>"+
"<input type='radio' id='rb1' "+((params.permissions==1 || !params.permissions)?'checked':'')+" value='1' name='data[permissions]' /> <label for='rb1'>Познат <small>(само му следя  снимките)</small></label><br />"+
"<input type='radio' id='rb2' "+(params.permissions==2?'checked':'')+" value='2' name='data[permissions]' /> <label for='rb2'>Приятел</label><br />"+
"<input type='radio' id='rb3' "+(params.permissions==3?'checked':'')+" value='3' name='data[permissions]' /> <label for='rb3'>VIP</label><br />";
html +="</td>"+
"</tr>"+
"<tr>"+
"<td colspan=2 align='right' valign='top'>"+
"<input type='hidden' name='object' value='contacts'>"+
"<input type='hidden' name='action' value='"+(params.permissions==0?'add':'edit')+"'>"+
"<input type='hidden' name='data[contact_id]' value='"+params.contact_id+"'>"+
"<input type='button' class='submit' name='submit' value='"+(params.permissions==0?'Добави':'Промени')+"' />&nbsp;"+
"<input type='button' name='reset' value='Отказ' />"+
"</td>"+
"</tr>"+
"</table>";
this.htmlElement.innerHTML = html;
this.handler = params.handler;
this.htmlElement.submit.onclick = this.submit.bindAsEventListener(this);
this.htmlElement.reset.onclick = this.reset.bindAsEventListener(this);
},

success: function(data){
if (this.handler) {
this.dialog.close();
this.handler.call(this, data);
} else {
var object = data.getElementsByTagName('object');
if (object[0].text) {
eval('data=' + object[0].text);
} else {
eval('data=' + object[0].childNodes[1].nodeValue);
}
if (this.avatarIcon) {
this.avatarIcon.item.permissions = data[0].permissions;
this.avatarIcon.onmouseover = avatarMenu.initFromEvent.bindAsEventListener(avatarMenu);
}
this.dialog.close();
CBH.Contacts.success(data);
}
},

reset: function(){
this.dialog.close();
},

error: function(){
}

});

CBH.updatePermissionsText = function(permission, placeholderId) {
var permissions_texts = {
0: 'Всички',
2: 'Приятели',
3: 'Vip',
4: 'Само за мен'
};
if (!placeholderId)
placeholderId = 'image_permissions_text';
var placeholder = $(placeholderId);
if (placeholder)
placeholder.innerHTML = permissions_texts[permission];
}

CBH.ImagePermissionsForm = Class.create();
Object.extend(CBH.ImagePermissionsForm.prototype,CBH.Form.prototype);
Object.extend(CBH.ImagePermissionsForm.prototype,{

initialize: function(dialog){
this.dialog = dialog;
},

createForm: function(params){
this.htmlElement = ce('FORM','','');
var imagePublicLocked = parseInt(Current.get('imagePublicLocked'));
var htmlSlider1 = imagePublicLocked? "<div style='font-style: italic; width: 209px;'>не може да бъде променяно</div>" : "<dl id='slider_track_1'><dt id='slider_handle_1'></dt></dl>";
var html = ""+
"<div style='width:300px;'>"+
"<div class='details'>"+
"<div class='body'>"+
"<span style='line-height:16px;font-size:13px;'>Изполвай плъзгачите за да промениш нивата за достъп до снимката.</span><br /><br /><br />"+
"<div><div class='clear'></div>"+
"<div class='slider_selector'>" + htmlSlider1 + "</div>" +
"<div class='slider_title'>Видима за: <input id='input_handle_1' type='hidden' name='data[permissions]' value='" + params.permissions + "' /></div>"+
"</div><div class='clear'></div><div>"+
"<div class='slider_selector'><dl id='slider_track_2'><dt id='slider_handle_2'></dt></dl></div>"+
"<div class='slider_title'><small>Могат да коментират:<input id='input_handle_2' type='hidden' name='data[permissions_to_comment]' /></small></div>"+
"</div><div class='clear'></div><div>"+
"<div class='slider_selector'><dl id='slider_track_3'><dt id='slider_handle_3'></dt></dl></div>"+
"<div class='slider_title'><small>Могат да тагват:<input id='input_handle_3' type='hidden' name='data[permissions_to_tag]' /></small></div>"+
"</div><div class='clear'></div><div>"+
"<div class='slider_selector'><dl id='slider_track_4'><dt id='slider_handle_4'></dt></dl></div>"+
"<div class='slider_title'><small>Ниво на сигурност:<input id='input_handle_4' type='hidden' name='data[safety_level]' /></small></div>"+
"</div>"+
"</div><div class='clear'></div>"+
"<div style='float:right;padding-right:10px;'>"+
"<input type='hidden' name='object' value='images'>"+
"<input type='hidden' name='action' value='change_permissions'>"+
"<input type='hidden' name='data[image_id]' value='"+params.image_id+"'>"+
"<input type='button' value='Отказ' name='reset' class='cancel_small'>&nbsp;&nbsp;"+
"<input type='button' value='Запази' name='submit' class='submit_small'>"+
"</div>"+
"</div>"+
"</div>";
this.htmlElement.innerHTML = html;
this.htmlElement.submit.onclick = this.submit.bindAsEventListener(this);
this.htmlElement.reset.onclick = this.reset.bindAsEventListener(this);
},

initSliders: function(s1,s2,s3,s4){

if(s1>0) s1--;
if ($('slider_track_1')) {
var slider_1_range = new Array(0,8,17,34,40);
var slider_1 = new CBH.Slider('slider_handle_1','slider_track_1',{
range: $R(1,40),
values: $R(1,40),
onChange: function(val){this.uglyHack(val);},
onSlide: function(val){this.uglyHack(val);},
uglyHack: function(val){
var rval =  Math.ceil(val/10);
for(var i=0;i<slider_1_range.length;i++){if(val > slider_1_range[i] && val <= slider_1_range[i+1]){rval=i+1;break;}}
$('slider_track_1').style.background = "url(http://static.album.bg/images/permissions_4tracks.png)";
$('slider_track_1').style.backgroundPosition = "0px -"+(120-((rval-1)*40))+"px";
if(rval==4) rval++;
$('input_handle_1').value = (5-rval);
}
});slider_1.setValue(slider_1_range[4-s1],0);
}

var slider_2_range = new Array(0,5,14,30,40,50);
var slider_2 = new CBH.Slider('slider_handle_2','slider_track_2',{
range: $R(1,50),
values: $R(1,50),
onChange: function(val){this.uglyHack(val);},
onSlide: function(val){this.uglyHack(val);},
uglyHack: function(val){
var rval =  Math.ceil(val/10);
for(var i=0;i<slider_2_range.length;i++){if(val > slider_2_range[i] && val <= slider_2_range[i+1]){rval=i+1;break;}}
$('slider_track_2').style.background = "url(http://static.album.bg/images/permissions_4tracks.png)";
$('slider_track_2').style.backgroundPosition = "0px -"+(320-((rval-1)*40))+"px";
$('input_handle_2').value = (5-rval);

}
});slider_2.setValue(slider_2_range[5-s2],0);

var slider_3_range = new Array(0,5,14,30,40,50);
var slider_3 = new CBH.Slider('slider_handle_3','slider_track_3',{
range: $R(1,50),
values: $R(1,50),
onChange: function(val){this.uglyHack(val);},
onSlide: function(val){this.uglyHack(val);},
uglyHack: function(val){
var rval =  Math.ceil(val/10);
for(var i=0;i<slider_3_range.length;i++){if(val > slider_3_range[i] && val <= slider_3_range[i+1]){rval=i+1;break;}}
$('slider_track_3').style.background = "url(http://static.album.bg/images/permissions_4tracks.png)";
$('slider_track_3').style.backgroundPosition = "0px -"+(320-((rval-1)*40))+"px";
$('input_handle_3').value = (5-rval);
}
});
slider_3.setValue(slider_3_range[5-s3],0);

var slider_4_range = new Array(0,12,22,30);
var slider_4 = new CBH.Slider('slider_handle_4','slider_track_4',{
range: $R(1,30),
values: $R(1,30),
onChange: function(val){this.uglyHack(val);},
onSlide: function(val){this.uglyHack(val);},
uglyHack: function(val){
var rval =  Math.ceil(val/10);
for(var i=0;i<slider_4_range.length;i++){if(val > slider_4_range[i] && val <= slider_4_range[i+1]){rval=i+1;break;}}
$('slider_track_4').style.background = "url(http://static.album.bg/images/permissions_4tracks.png)";
$('slider_track_4').style.backgroundPosition = "0px -"+(440-((rval-1)*40))+"px";
$('input_handle_4').value = (3-rval);
}
});slider_4.setValue(slider_4_range[3-s4],0);

},

success: function(data){
Current.set('imagePermissions', $('input_handle_1').value);
Current.set('imagePermissionsToComment', $('input_handle_2').value);
Current.set('imagePermissionsToTag', $('input_handle_3').value);
CBH.updatePermissionsText(Current.get('imagePermissions'), 'image_permissions_text');
this.dialog.close();
floatingMessages.createMsg('Снимката беше редактирана успешно.','0',3000);
},

reset: function(){
this.dialog.close();
},

error: function(){
}

});
CBH.AlbumForm = Class.create();
Object.extend(CBH.AlbumForm.prototype,CBH.Form.prototype);
Object.extend(CBH.AlbumForm.prototype,{

initialize: function(dialog,element,type){
this.dialog = dialog;
this.type = type;
this.container = element;
},

createForm: function(params){
this.htmlElement = ce('FORM','','');

var html = ""+
"<table style='height:100%;width:100%'>"+
"<tr>"+
"<td>"+
"<label>Заглавие</label>"+
"</td><td>"+
"<input type='text' name='data[name]'>"+
"</td>"+
"</tr>"+
"<tr>"+
"<td>"+
"<label>Описание</label>"+
"</td><td>"+
"<textarea name='data[description]'></textarea>"+
"</td>"+
"</tr>"+

"<tr>"+
"<td colspan=2 align='right'>"+
"<input type='hidden' name='object' value='albums'>"+
"<input type='hidden' name='action' value='add'>"+
"<input type='button' class='submit' name='submit' value='Добави'>&nbsp;"+
"<input type='button' name='reset' value='Отказ'>"+
"</td>"+
"</tr>"+
"</table>";
this.htmlElement.innerHTML = html;
this.htmlElement.submit.onclick = this.submit.bindAsEventListener(this);
this.htmlElement.reset.onclick = this.reset.bindAsEventListener(this);

},

success: function(data){
rm(this.container,false);
var object = data.getElementsByTagName('object');
if(object[0].text){
eval('var result = '+object[0].text);
}else {
eval('var result = '+object[0].childNodes[1].nodeValue);
}
for(var i=0; i<result.length; i++){
if(this.type=='form'){
var item = this.createItem2(result[i],i);
this.container.appendChild(item);
}else{

var perrow = 6;
if(i%perrow==0 && i>0){var clr = document.createElement('div'); clr.className='clear';this.container.appendChild(clr);}
var div = document.createElement('div');
if(i%perrow==0) div.className = 'column first';
else if(i%perrow==perrow-1) div.className = 'column last';
else div.className = 'column';

var item = this.createItem(result[i]);
div.appendChild(item);
this.container.appendChild(div);
}

}
this.dialog.close();
floatingMessages.createMsg('Албумът беше добавен успешно.','0',3000);
},

createItem: function(item){
var div = ce('div','','album_small');
var a = document.createElement('a');
a.href = '/'+Current.get('username')+'/albums/'+item.id+'/';

var image = document.createElement('img');
if(item.filename_th1!=null){
image.src= getImageSrc(item,1);
}else {
image.src= 'http://static.album.bg/images/empty_album_th1.gif';
}

a.appendChild(image);
div.appendChild(a);


var h4 = ce('h4','','');
var a2 = ce('a','','');
a2.href= '/'+Current.get('username')+'/albums/'+item.id+'/';
a2.innerHTML = item.name;
h4.appendChild(a2);
div.appendChild(h4);

var p = ce('p','','');
var strong = ce('strong','','');
strong.innerHTML = item.total_images+' снимки';
p.appendChild(strong);

div.appendChild(p);
return div;
},

createItem2: function(item,pos){
var div = ce('div','','');
var i = ce('input','','');
i.type='checkbox';
i.name='albums[]';
i.value=item.id;
i.id = 'albums_'+item.id;
if(pos==0) i.checked = true;
div.appendChild(i);
var lab = ce('label','','');
lab.setAttribute('for','albums_'+item.id);
lab.innerHTML = item.name;
div.appendChild(lab);
return div;
},

reset: function(){
this.dialog.close();
},

error: function(){
}
});
if(!CBH) var CBH = {};
CBH.LinkMenu = Class.create();
CBH.LinkMenu.prototype = {

initialize: function(){
this.observers = {};
},

init: function(container){
if(this.container){
//this.cancelHide();
this.hide();
this.htmlElement = null;
}
this.container = $(container);
if(this.container.className.indexOf('active_object')==-1)
set_menu_style(this.container,'_arrow_clicked');
else set_menu_style(this.container,'active_object_arrow_clicked');
this.prepare();
},

prepare: function(){
this.htmlElement = cn(this.container,2);
this.offs = Position.cumulativeOffset(this.container);

this.htmlElement.style.left = this.offs[0]+'px';
this.htmlElement.style.top = this.offs[1]+this.container.offsetHeight-0+'px';

this.htmlElement.style.display='block';

this.observers.hide = this.hide.bindAsEventListener(this);
Event.observe(document,"mouseup",this.observers.hide);
//this.container.onmouseout = this.checkHide.bindAsEventListener(this);
//this.container.onmouseover = this.cancelHide.bindAsEventListener(this);

this.shadow = ce('div','','shadow');
//this.shadow.style.backgroundColor = '#000000';

this.shadow.style.width = this.htmlElement.offsetWidth+'px';
this.shadow.style.height = this.htmlElement.offsetHeight+4+'px';
this.shadow.style.top = parseInt(this.htmlElement.style.top)+'px';
this.shadow.style.left = parseInt(this.htmlElement.style.left)+4+'px';
this.container.appendChild(this.shadow);
this.htmlElement.style.zIndex = 10015;
this.shadow.style.zIndex = 10010;
var wtf = cn(this.htmlElement,0);
wtf.style.opacity = '0.0';
wtf.style.filter = 'alpha(Opacity:0)';
new Effect.Appear(wtf, { duration: 0.3, from: 0.0, to: 1.0});
this.show();
},

cancelHide: function(){
clearTimeout(this.timer);
if(this.effect) this.effect.cancel();
},

checkHide: function(event){
var el = event.relatedTarget?event.relatedTarget:event.toElement;
if(el != this.container && !Element.childOf(el,this.container)){
 this.hide();
}
},

        
        show: function(){
/*
var el = this.htmlElement;
if(this.htmlElement) this.effect =  new Effect.SlideDown(el, { duration: 2.5, from: 0.0, to: 2.0, afterFinish: function() { el.style.display='block'; }} );
*/
 if(this.htmlElement){
 this.htmlElement.style.display = 'block';
this.shadow.style.display = 'block';
}

        },

hide: function(){
/*
                var el = this.htmlElement;
if(this.htmlElement) this.effect =  new Effect.SlideUp(el, { duration: 0.5, from: 1.0, to: 0.0,  afterFinish: function() { el.style.display='none'; }})
*/
if(this.htmlElement) {
this.htmlElement.style.display = 'none';
                this.htmlElement = null;

if(this.container.className.indexOf('active_object')==-1)
set_menu_style(this.container,'');
else set_menu_style(this.container,'active_object');
this.shadow.style.display = 'none';
}
Event.stopObserving(document,"mouseup",this.observers.hide);
}

/*
toggleMenu: function(){
if(!this.htmlElement) return;
if(this.htmlElement.style.display!='block'){
this.htmlElement.style.display='block';
this.shadow.style.display = 'block';
this.htmlElement.style.opacity = '100';
}else{
this.htmlElement.style.display='none';
this.htmlElement.style.opacity = '0';
this.htmlElement = null;
this.container.className = '';
this.shadow.style.display = 'none';
}

}
*/

};
var linkMenu = new CBH.LinkMenu();
if(!CBH) var CBH = {};
CBH.FloatingMessages = Class.create();
CBH.FloatingMessages.prototype = {

initialize: function(){
this.loopStep = 100;
this.opacityStep = 5;
},

createMsg: function(message,level,ttl){
if(!this.container){
this.container = ce('div','','floating_messages');
$('absholder').appendChild(this.container);
this.loop();
}
if(!level) level = 0;
if(!ttl) ttl = 3000;
var box = ce('div','','floating_messages_box');
Element.addClassName(box,'level_'+level);
box.innerHTML = message+"<div><small>&nbsp;</small></div>";
box.ttl = ttl;
box.opacity = 60;
this.container.appendChild(box);
},

loop: function() {
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
this.container.style.paddingTop = scrollTop+'px';
for(var i=0;i<this.container.childNodes.length;i++){
var ttl = this.container.childNodes[i].ttl?this.container.childNodes[i].ttl:0;
var opacity = this.container.childNodes[i].opacity?this.container.childNodes[i].opacity:0;
if(!ttl || ttl<=0){
if(!opacity || opacity<=0){
rm(this.container.childNodes[i],true);
}
else{
this.container.childNodes[i].opacity-= this.opacityStep;
this.setOpacity(this.container.childNodes[i],this.container.childNodes[i].opacity);
}
}else{
this.container.childNodes[i].ttl = this.container.childNodes[i].ttl - this.loopStep;
}
}
setTimeout(this.loop.bind(this),this.loopStep)
},

setOpacity: function(el,opacity){
// IE/Win
el.style.filter = "alpha(opacity:"+opacity+")";

// Safari<1.2, Konqueror
el.style.KHTMLOpacity = opacity/100;

// Older Mozilla and Firefox
el.style.MozOpacity = opacity/100;

// Safari 1.2, newer Firefox and Mozilla, CSS3
el.style.opacity = opacity/100;
}

};
var floatingMessages = new CBH.FloatingMessages();
var InlineForm = {
parent: null,
form: null,
field: null,
type: null,
target: null,
select: null,
data: null,

init: function(el,name,type,noInner,customSubmit){
if(InlineForm.parent != el){
InlineForm.rst();
}
if (!customSubmit)
customSubmit = null;
InlineForm.parent = el;
InlineForm.parent._onclick = InlineForm.parent.onclick;
InlineForm.parent.onclick = null;
InlineForm.type = type?type:0;
InlineForm.field = name;
InlineForm.parent.innerHTML = InlineForm.parent.innerHTML.replace(/^\s*|\s*$/g,"");
InlineForm.form = ce('form','','');
InlineForm.form.onsubmit= function(){return false};
InlineForm.form.id = 'InlineForm_';
Element.removeClassName(InlineForm.parent,'editable');
switch(InlineForm.type){
//input
case 0:
var input  = ce('input','','text');
input.type = 'text';
input.name = InlineForm.field;
if(!noInner || InlineForm.parent.updated){
input.value = InlineForm.parent.innerHTML;
}
break;
//textarea
case 1:
var input  = ce('textarea','','');
input.rows = 3;
input.cols = 32;
input.name = InlineForm.field;
if(!noInner || InlineForm.parent.updated){
input.value = _br2nl(InlineForm.parent.innerHTML);
}
break;
//input + li
case 2:
                                var input  = ce('input','','');
                                input.type = 'text';
                                input.name = InlineForm.field;
break;
case 3:
case 4:
var input  = ce('select','','');
input.name = InlineForm.field;
input.style.width = '155px';
InlineForm.select = input;
var opt = ce('option','','');
                                opt.value = '';
                                opt.text =  'Loading..';
                                InlineForm.select.options.add(opt,0);
break;
}
var div =ce('div','','buttons');

InlineForm.form.appendChild(input);
var sbmt = ce('input','','submit');
sbmt.type = 'button';
sbmt.value = 'Запази';
ae(sbmt, 'click', customSubmit? customSubmit : InlineForm.sbmt);
div.appendChild(sbmt);

var rst = ce('input','','');
rst.type = 'button';
rst.value = 'Отказ';
ae(rst,'click',InlineForm.rst);
div.appendChild(rst);
InlineForm.form.appendChild(div);

InlineForm.parent._innerHTML = InlineForm.parent.innerHTML;
InlineForm.parent.innerHTML = '';
InlineForm.parent.appendChild(InlineForm.form);
if(InlineForm.type==3)  call("/api.php?object=albums&action=list","InlineForm.fill_select","",InlineForm.form.id);
if(InlineForm.type==4)  call("/api.php?object=groups&action=list","InlineForm.fill_select","",InlineForm.form.id);
},
rst: function(e){
if(InlineForm.parent){
InlineForm.parent.onclick = InlineForm.parent._onclick;
try { InlineForm.parent.removeChild(InlineForm.form); } catch (e) {}
InlineForm.parent.innerHTML = InlineForm.parent._innerHTML;
Element.removeClassName(InlineForm.parent,'editable');
InlineForm.parent = null;
}
// Stop event propagation, in order to hide the form
var evt = e? e : window.event;
if (evt)
Event.stop(evt);
},
set_target: function(id){
InlineForm.target = $(id);
},
sbmt: function(){
var url = '/api.php?';
for(var i=0;i<InlineForm.form.elements.length;i++){
if(InlineForm.form.elements[i].name) {
if(InlineForm.form.elements[i].type == 'hidden'){
url += '&'+InlineForm.form.elements[i].name+'='+encodeURIComponent(InlineForm.form.elements[i].value);
}
else{
url += '&data['+InlineForm.form.elements[i].name+']='+encodeURIComponent(InlineForm.form.elements[i].value);
}
}

}
call(url,"InlineForm.set","",InlineForm.form.id);
},
set: function(data){
var object = data.getElementsByTagName('object');
if(object[0].text){
eval('data = '+object[0].text);
}else {
eval('data = '+object[0].childNodes[1].nodeValue);
}
switch (InlineForm.type) {
//input
case 0:
eval('var text = data[0].'+InlineForm.field);
InlineForm.parent.innerHTML = text;
floatingMessages.createMsg('Снимката беше редактирана успешно.','0',3000);
                        break;
                        //textarea
                        case 1:
eval('var text = data[0].'+InlineForm.field);
InlineForm.parent.innerHTML = _nl2br(text);
floatingMessages.createMsg('Снимката беше редактирана успешно.','0',3000);
                        break;
                        //input + li
                        case 2:
                rm(InlineForm.target,false);
for(var i=0;i<data.length;i++){
var li = ce('li','','');
var a1 = ce('a','','');
a1.href = '';
eval('a1.innerHTML = data[i].'+InlineForm.field);
li.appendChild(a1);
                                        var a2 = ce('a','','');
                                        a2.href = '/api.php?object=images&action=remove_tag_from_image&id='+data[i].image_tag_id;
if(isIE) Event.observe(a2,'click',ActiveLink.sbmt,true);
else a2.onclick = ActiveLink.sbmt;
a2.className = 'image_details_close details close';
a2.innerHTML = '&nbsp;';
                                        li.appendChild(a2);
InlineForm.target.appendChild(li);
}
InlineForm.parent.innerHTML = InlineForm.parent._innerHTML;
floatingMessages.createMsg('Тагът беше добавен успешно.','0',3000);
break;
//albums (image in album)
case 3:
rm(InlineForm.target,false);
for(var i=0;i<data.length;i++){
                                        var li = ce('li','','');
                                        var a1 = ce('a','','');
                                        a1.href = '/'+Current.get('username')+'/albums/'+data[i].id+'/';
                                        a1.innerHTML = data[i].name;
                                        li.appendChild(a1);
                                        var a2 = ce('a','','');
                                        a2.href = '/api.php?object=images&action=delete_from_album&image_id='+data[i].image_id+'&album_id='+data[i].id;

if(isIE) Event.observe(a2,'click',ActiveLink.sbmt,true);
else a2.onclick = ActiveLink.sbmt;
a2.className = 'details close';
a2.innerHTML = '&nbsp;';

                                        li.appendChild(a2);
                                        InlineForm.target.appendChild(li);
}
InlineForm.parent.innerHTML = InlineForm.parent._innerHTML;
floatingMessages.createMsg('Албумът беше добавен успешно.','0',3000);
break;
//groups (image in groups)
case 4:
rm(InlineForm.target, false);
for (var i=0; i < data.length; i++) {
var li = ce('li', '', '');
var a1 = ce('a', '', '');
a1.href = '/groups/' + data[i].id + '/';
a1.innerHTML = data[i].name;
li.appendChild(a1);
var a2 = ce('a', '', '');
a2.href = '/api.php?object=images&action=delete_from_group&image_id='+data[i].image_id+'&group_id='+data[i].id;

if (isIE) Event.observe(a2, 'click', ActiveLink.sbmt, true);
else a2.onclick = ActiveLink.sbmt;
a2.className = 'details close';
a2.innerHTML = '&nbsp;';

li.appendChild(a2);
InlineForm.target.appendChild(li);
}
InlineForm.parent.innerHTML = InlineForm.parent._innerHTML;
floatingMessages.createMsg('Добавянето беше успешно.', '0', 3000);
break;
        }
InlineForm.parent.onclick = InlineForm.parent._onclick;
InlineForm.parent.updated = true;
InlineForm.parent = null;
},
add: function(name,value){
var hidden = ce('input','','');
hidden.type = 'hidden';
hidden.name = name;
hidden.value = value;
InlineForm.form.appendChild(hidden);
},
fill_select: function(data){
var object = data.getElementsByTagName('object');
if(object[0].text){
eval('data = '+object[0].text);
}else {
eval('data = '+object[0].childNodes[1].nodeValue);
}
if(InlineForm.select){
rm(InlineForm.select,false);
for(var i=0;i<data.length;i++){
var opt = ce('option','','');
opt.value = data[i].id;
opt.text =  data[i].name;
InlineForm.select.options.add(opt,i);
}
}
InlineForm.data = data;
}
};

var ActiveLink = {
        sbmt: function(event){
ActiveLink.el = Event.element(event);
                var url =  ActiveLink.el.href;
                call(url,"ActiveLink.success","",ActiveLink.el.parentNode.parentNode.id);
return false;
        },
        success: function(data){
                rm(ActiveLink.el.parentNode,true);
return false;
        }
};

// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
//  Justin Palmer (http://encytemedia.com/)
//  Mark Pilgrim (http://diveintomark.org/)
//  Martin Bialasinki
// 
// See scriptaculous.js for full license.  

/* ------------- element ext -------------- */  
 
// converts rgb() and #xxx to #xxxxxx format,  
// returns self (or first argument) if not convertable  
String.prototype.parseColor = function() {  
  var color = '#';  
  if(this.slice(0,4) == 'rgb(') {  
    var cols = this.slice(4,this.length-1).split(',');  
    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);  
  } else {  
    if(this.slice(0,1) == '#') {  
      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();  
      if(this.length==7) color = this.toLowerCase();  
    }  
  }  
  return(color.length==7 ? color : (arguments[0] || this));  
}

Element.collectTextNodes = function(element) {  
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue : 
      (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
  }).flatten().join('');
}

Element.collectTextNodesIgnoreClass = function(element, className) {  
  return $A($(element).childNodes).collect( function(node) {
    return (node.nodeType==3 ? node.nodeValue : 
      ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? 
        Element.collectTextNodes(node) : ''));
  }).flatten().join('');
}

Element.setStyle = function(element, style) {
  element = $(element);
  for(k in style) element.style[k.camelize()] = style[k];
}

Element.setContentZoom = function(element, percent) {  
  Element.setStyle(element, {fontSize: (percent/100) + 'em'});   
  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);  
}

Element.getOpacity = function(element){  
  var opacity;
  if (opacity = Element.getStyle(element, 'opacity'))  
    return parseFloat(opacity);  
  if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
    if(opacity[1]) return parseFloat(opacity[1]) / 100;  
  return 1.0;  
}

Element.setOpacity = function(element, value){  
  element= $(element);  
  if (value == 1){
    Element.setStyle(element, { opacity: 
      (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
      0.999999 : null });
    if(/MSIE/.test(navigator.userAgent))  
      Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  
  } else {  
    if(value < 0.00001) value = 0;  
    Element.setStyle(element, {opacity: value});
    if(/MSIE/.test(navigator.userAgent))  
     Element.setStyle(element, 
       { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
                 'alpha(opacity='+value*100+')' });  
  }   
}  
 
Element.getInlineOpacity = function(element){  
  return $(element).style.opacity || '';
}  

Element.childrenWithClassName = function(element, className) {  
  return $A($(element).getElementsByTagName('*')).select(
    function(c) { return Element.hasClassName(c, className) });
}

Array.prototype.call = function() {
  var args = arguments;
  this.each(function(f){ f.apply(this, args) });
}

/*--------------------------------------------------------------------------*/

var Effect = {
  tagifyText: function(element) {
    var tagifyStyle = 'position:relative';
    if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';
    element = $(element);
    $A(element.childNodes).each( function(child) {
      if(child.nodeType==3) {
        child.nodeValue.toArray().each( function(character) {
          element.insertBefore(
            Builder.node('span',{style: tagifyStyle},
              character == ' ' ? String.fromCharCode(160) : character), 
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element, effect) {
    var elements;
    if(((typeof element == 'object') || 
        (typeof element == 'function')) && 
       (element.length))
      elements = element;
    else
      elements = $(element).childNodes;
      
    var options = Object.extend({
      speed: 0.1,
      delay: 0.0
    }, arguments[2] || {});
    var masterDelay = options.delay;

    $A(elements).each( function(element, index) {
      new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
    });
  },
  PAIRS: {
    'slide':  ['SlideDown','SlideUp'],
    'blind':  ['BlindDown','BlindUp'],
    'appear': ['Appear','Fade']
  },
  toggle: function(element, effect) {
    element = $(element);
    effect = (effect || 'appear').toLowerCase();
    var options = Object.extend({
      queue: { position:'end', scope:(element.id || 'global') }
    }, arguments[2] || {});
    Effect[Element.visible(element) ? 
      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
  }
};

var Effect2 = Effect; // deprecated

/* ------------- transitions ------------- */

Effect.Transitions = {}

Effect.Transitions.linear = function(pos) {
  return pos;
}
Effect.Transitions.sinoidal = function(pos) {
  return (-Math.cos(pos*Math.PI)/2) + 0.5;
}
Effect.Transitions.reverse  = function(pos) {
  return 1-pos;
}
Effect.Transitions.flicker = function(pos) {
  return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
}
Effect.Transitions.wobble = function(pos) {
  return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
}
Effect.Transitions.pulse = function(pos) {
  return (Math.floor(pos*10) % 2 == 0 ? 
    (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));
}
Effect.Transitions.none = function(pos) {
  return 0;
}
Effect.Transitions.full = function(pos) {
  return 1;
}

/* ------------- core effects ------------- */

Effect.ScopedQueue = Class.create();
Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
  initialize: function() {
    this.effects  = [];
    this.interval = null;
  },
  _each: function(iterator) {
    this.effects._each(iterator);
  },
  add: function(effect) {
    var timestamp = new Date().getTime();
    
    var position = (typeof effect.options.queue == 'string') ? 
      effect.options.queue : effect.options.queue.position;
    
    switch(position) {
      case 'front':
        // move unstarted effects after this effect  
        this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
            e.startOn  += effect.finishOn;
            e.finishOn += effect.finishOn;
          });
        break;
      case 'end':
        // start effect after last queued effect has finished
        timestamp = this.effects.pluck('finishOn').max() || timestamp;
        break;
    }
    
    effect.startOn  += timestamp;
    effect.finishOn += timestamp;
    this.effects.push(effect);
    if(!this.interval) 
      this.interval = setInterval(this.loop.bind(this), 40);
  },
  remove: function(effect) {
    this.effects = this.effects.reject(function(e) { return e==effect });
    if(this.effects.length == 0) {
      clearInterval(this.interval);
      this.interval = null;
    }
  },
  loop: function() {
    var timePos = new Date().getTime();
    this.effects.invoke('loop', timePos);
  }
});

Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if(typeof queueName != 'string') return queueName;
    
    if(!this.instances[queueName])
      this.instances[queueName] = new Effect.ScopedQueue();
      
    return this.instances[queueName];
  }
}
Effect.Queue = Effect.Queues.get('global');

Effect.DefaultOptions = {
  transition: Effect.Transitions.sinoidal,
  duration:   1.0,   // seconds
  fps:        25.0,  // max. 25fps due to Effect.Queue implementation
  sync:       false, // true for combining
  from:       0.0,
  to:         1.0,
  delay:      0.0,
  queue:      'parallel'
}

Effect.Base = function() {};
Effect.Base.prototype = {
  position: null,
  start: function(options) {
    this.options      = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
    this.currentFrame = 0;
    this.state        = 'idle';
    this.startOn      = this.options.delay*1000;
    this.finishOn     = this.startOn + (this.options.duration*1000);
    this.event('beforeStart');
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).add(this);
  },
  loop: function(timePos) {
    if(timePos >= this.startOn) {
      if(timePos >= this.finishOn) {
        this.render(1.0);
        this.cancel();
        this.event('beforeFinish');
        if(this.finish) this.finish(); 
        this.event('afterFinish');
        return;  
      }
      var pos   = (timePos - this.startOn) / (this.finishOn - this.startOn);
      var frame = Math.round(pos * this.options.fps * this.options.duration);
      if(frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  render: function(pos) {
    if(this.state == 'idle') {
      this.state = 'running';
      this.event('beforeSetup');
      if(this.setup) this.setup();
      this.event('afterSetup');
    }
    if(this.state == 'running') {
      if(this.options.transition) pos = this.options.transition(pos);
      pos *= (this.options.to-this.options.from);
      pos += this.options.from;
      this.position = pos;
      this.event('beforeUpdate');
      if(this.update) this.update(pos);
      this.event('afterUpdate');
    }
  },
  cancel: function() {
    if(!this.options.sync)
      Effect.Queues.get(typeof this.options.queue == 'string' ? 
        'global' : this.options.queue.scope).remove(this);
    this.state = 'finished';
  },
  event: function(eventName) {
    if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
    if(this.options[eventName]) this.options[eventName](this);
  },
  inspect: function() {
    return '#<Effect:' + $H(this).inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
}

Effect.Parallel = Class.create();
Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
  initialize: function(effects) {
    this.effects = effects || [];
    this.start(arguments[1]);
  },
  update: function(position) {
    this.effects.invoke('render', position);
  },
  finish: function(position) {
    this.effects.each( function(effect) {
      effect.render(1.0);
      effect.cancel();
      effect.event('beforeFinish');
      if(effect.finish) effect.finish(position);
      effect.event('afterFinish');
    });
  }
});

Effect.Opacity = Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    // make this work on IE on elements without 'layout'
    if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
      Element.setStyle(this.element, {zoom: 1});
    var options = Object.extend({
      from: Element.getOpacity(this.element) || 0.0,
      to:   1.0
    }, arguments[1] || {});
    this.start(options);
  },
  update: function(position) {
    Element.setOpacity(this.element, position);
  }
});

Effect.Move = Class.create();
Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    var options = Object.extend({
      x:    0,
      y:    0,
      mode: 'relative'
    }, arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    // Bug in Opera: Opera returns the "real" position of a static element or
    // relative element that does not have top/left explicitly set.
    // ==> Always set top and left for position relative elements in your stylesheets 
    // (to 0 if you do not need them) 
    Element.makePositioned(this.element);
    this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0');
    this.originalTop  = parseFloat(Element.getStyle(this.element,'top')  || '0');
    if(this.options.mode == 'absolute') {
      // absolute movement, so we need to calc deltaX and deltaY
      this.options.x = this.options.x - this.originalLeft;
      this.options.y = this.options.y - this.originalTop;
    }
  },
  update: function(position) {
    Element.setStyle(this.element, {
      left: this.options.x  * position + this.originalLeft + 'px',
      top:  this.options.y  * position + this.originalTop  + 'px'
    });
  }
});

// for backwards compatibility
Effect.MoveBy = function(element, toTop, toLeft) {
  return new Effect.Move(element, 
    Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
};

Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
  initialize: function(element, percent) {
    this.element = $(element)
    var options = Object.extend({
      scaleX: true,
      scaleY: true,
      scaleContent: true,
      scaleFromCenter: false,
      scaleMode: 'box',        // 'box' or 'contents' or {} with provided values
      scaleFrom: 100.0,
      scaleTo:   percent
    }, arguments[2] || {});
    this.start(options);
  },
  setup: function() {
    this.restoreAfterFinish = this.options.restoreAfterFinish || false;
    this.elementPositioning = Element.getStyle(this.element,'position');
    
    this.originalStyle = {};
    ['top','left','width','height','fontSize'].each( function(k) {
      this.originalStyle[k] = this.element.style[k];
    }.bind(this));
      
    this.originalTop  = this.element.offsetTop;
    this.originalLeft = this.element.offsetLeft;
    
    var fontSize = Element.getStyle(this.element,'font-size') || '100%';
    ['em','px','%'].each( function(fontSizeType) {
      if(fontSize.indexOf(fontSizeType)>0) {
        this.fontSize     = parseFloat(fontSize);
        this.fontSizeType = fontSizeType;
      }
    }.bind(this));
    
    this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
    
    this.dims = null;
    if(this.options.scaleMode=='box')
      this.dims = [this.element.offsetHeight, this.element.offsetWidth];
    if(/^content/.test(this.options.scaleMode))
      this.dims = [this.element.scrollHeight, this.element.scrollWidth];
    if(!this.dims)
      this.dims = [this.options.scaleMode.originalHeight,
                   this.options.scaleMode.originalWidth];
  },
  update: function(position) {
    var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
    if(this.options.scaleContent && this.fontSize)
      Element.setStyle(this.element, {fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
  },
  finish: function(position) {
    if (this.restoreAfterFinish) Element.setStyle(this.element, this.originalStyle);
  },
  setDimensions: function(height, width) {
    var d = {};
    if(this.options.scaleX) d.width = width + 'px';
    if(this.options.scaleY) d.height = height + 'px';
    if(this.options.scaleFromCenter) {
      var topd  = (height - this.dims[0])/2;
      var leftd = (width  - this.dims[1])/2;
      if(this.elementPositioning == 'absolute') {
        if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
        if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
      } else {
        if(this.options.scaleY) d.top = -topd + 'px';
        if(this.options.scaleX) d.left = -leftd + 'px';
      }
    }
    Element.setStyle(this.element, d);
  }
});

Effect.Highlight = Class.create();
Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    // Prevent executing on elements not in the layout flow
    if(Element.getStyle(this.element, 'display')=='none') { this.cancel(); return; }
    // Disable background image during the effect
    this.oldStyle = {
      backgroundImage: Element.getStyle(this.element, 'background-image') };
    Element.setStyle(this.element, {backgroundImage: 'none'});
    if(!this.options.endcolor)
      this.options.endcolor = Element.getStyle(this.element, 'background-color').parseColor('#ffffff');
    if(!this.options.restorecolor)
      this.options.restorecolor = Element.getStyle(this.element, 'background-color');
    // init color calculations
    this._base  = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
    this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
  },
  update: function(position) {
    Element.setStyle(this.element,{backgroundColor: $R(0,2).inject('#',function(m,v,i){
      return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
  },
  finish: function() {
    Element.setStyle(this.element, Object.extend(this.oldStyle, {
      backgroundColor: this.options.restorecolor
    }));
  }
});

Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
    this.start(arguments[1] || {});
  },
  setup: function() {
    Position.prepare();
    var offsets = Position.cumulativeOffset(this.element);
    if(this.options.offset) offsets[1] += this.options.offset;
    var max = window.innerHeight ? 
      window.height - window.innerHeight :
      document.body.scrollHeight - 
        (document.documentElement.clientHeight ? 
          document.documentElement.clientHeight : document.body.clientHeight);
    this.scrollStart = Position.deltaY;
    this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
  },
  update: function(position) {
    Position.prepare();
    window.scrollTo(Position.deltaX, 
      this.scrollStart + (position*this.delta));
  }
});

/* ------------- combination effects ------------- */

Effect.Fade = function(element) {
  var oldOpacity = Element.getInlineOpacity(element);
  var options = Object.extend({
  from: Element.getOpacity(element) || 1.0,
  to:   0.0,
  afterFinishInternal: function(effect) { with(Element) { 
    if(effect.options.to!=0) return;
    hide(effect.element);
    setStyle(effect.element, {opacity: oldOpacity}); }}
  }, arguments[1] || {});
  return new Effect.Opacity(element,options);
}

Effect.Appear = function(element) {
  var options = Object.extend({
  from: (Element.getStyle(element, 'display') == 'none' ? 0.0 : Element.getOpacity(element) || 0.0),
  to:   1.0,
  beforeSetup: function(effect) { with(Element) {
    setOpacity(effect.element, effect.options.from);
    show(effect.element); }}
  }, arguments[1] || {});
  return new Effect.Opacity(element,options);
}

Effect.Puff = function(element) {
  element = $(element);
  var oldStyle = { opacity: Element.getInlineOpacity(element), position: Element.getStyle(element, 'position') };
  return new Effect.Parallel(
   [ new Effect.Scale(element, 200, 
      { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), 
     new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], 
     Object.extend({ duration: 1.0, 
      beforeSetupInternal: function(effect) { with(Element) {
        setStyle(effect.effects[0].element, {position: 'absolute'}); }},
      afterFinishInternal: function(effect) { with(Element) {
         hide(effect.effects[0].element);
         setStyle(effect.effects[0].element, oldStyle); }}
     }, arguments[1] || {})
   );
}

Effect.BlindUp = function(element) {
  element = $(element);
  Element.makeClipping(element);
  return new Effect.Scale(element, 0, 
    Object.extend({ scaleContent: false, 
      scaleX: false, 
      restoreAfterFinish: true,
      afterFinishInternal: function(effect) { with(Element) {
        [hide, undoClipping].call(effect.element); }} 
    }, arguments[1] || {})
  );
}

Effect.BlindDown = function(element) {
  element = $(element);
  var oldHeight = Element.getStyle(element, 'height');
  var elementDimensions = Element.getDimensions(element);
  return new Effect.Scale(element, 100, 
    Object.extend({ scaleContent: false, 
      scaleX: false,
      scaleFrom: 0,
      scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
      restoreAfterFinish: true,
      afterSetup: function(effect) { with(Element) {
        makeClipping(effect.element);
        setStyle(effect.element, {height: '0px'});
        show(effect.element); 
      }},  
      afterFinishInternal: function(effect) { with(Element) {
        undoClipping(effect.element);
        setStyle(effect.element, {height: oldHeight});
      }}
    }, arguments[1] || {})
  );
}

Effect.SwitchOff = function(element) {
  element = $(element);
  var oldOpacity = Element.getInlineOpacity(element);
  return new Effect.Appear(element, { 
    duration: 0.4,
    from: 0,
    transition: Effect.Transitions.flicker,
    afterFinishInternal: function(effect) {
      new Effect.Scale(effect.element, 1, { 
        duration: 0.3, scaleFromCenter: true,
        scaleX: false, scaleContent: false, restoreAfterFinish: true,
        beforeSetup: function(effect) { with(Element) {
          [makePositioned,makeClipping].call(effect.element);
        }},
        afterFinishInternal: function(effect) { with(Element) {
          [hide,undoClipping,undoPositioned].call(effect.element);
          setStyle(effect.element, {opacity: oldOpacity});
        }}
      })
    }
  });
}

Effect.DropOut = function(element) {
  element = $(element);
  var oldStyle = {
    top: Element.getStyle(element, 'top'),
    left: Element.getStyle(element, 'left'),
    opacity: Element.getInlineOpacity(element) };
  return new Effect.Parallel(
    [ new Effect.Move(element, {x: 0, y: 100, sync: true }), 
      new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
    Object.extend(
      { duration: 0.5,
        beforeSetup: function(effect) { with(Element) {
          makePositioned(effect.effects[0].element); }},
        afterFinishInternal: function(effect) { with(Element) {
          [hide, undoPositioned].call(effect.effects[0].element);
          setStyle(effect.effects[0].element, oldStyle); }} 
      }, arguments[1] || {}));
}

Effect.Shake = function(element) {
  element = $(element);
  var oldStyle = {
    top: Element.getStyle(element, 'top'),
    left: Element.getStyle(element, 'left') };
	  return new Effect.Move(element, 
	    { x:  20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
	  new Effect.Move(effect.element,
	    { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
	  new Effect.Move(effect.element,
	    { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
	  new Effect.Move(effect.element,
	    { x: -40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
	  new Effect.Move(effect.element,
	    { x:  40, y: 0, duration: 0.1,  afterFinishInternal: function(effect) {
	  new Effect.Move(effect.element,
	    { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { with(Element) {
        undoPositioned(effect.element);
        setStyle(effect.element, oldStyle);
  }}}) }}) }}) }}) }}) }});
}

Effect.SlideDown = function(element) {
  element = $(element);
  Element.cleanWhitespace(element);
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
  var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
  var elementDimensions = Element.getDimensions(element);
  return new Effect.Scale(element, 100, Object.extend({ 
    scaleContent: false, 
    scaleX: false, 
    scaleFrom: 0,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) { with(Element) {
      makePositioned(effect.element);
      makePositioned(effect.element.firstChild);
      if(window.opera) setStyle(effect.element, {top: ''});
      makeClipping(effect.element);
      setStyle(effect.element, {height: '0px'});
      show(element); }},
    afterUpdateInternal: function(effect) { with(Element) {
      setStyle(effect.element.firstChild, {bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
    afterFinishInternal: function(effect) { with(Element) {
      undoClipping(effect.element); 
      undoPositioned(effect.element.firstChild);
      undoPositioned(effect.element);
      setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
    }, arguments[1] || {})
  );
}
  
Effect.SlideUp = function(element) {
  element = $(element);
  Element.cleanWhitespace(element);
  var oldInnerBottom = Element.getStyle(element.firstChild, 'bottom');
  return new Effect.Scale(element, 0, 
   Object.extend({ scaleContent: false, 
    scaleX: false, 
    scaleMode: 'box',
    scaleFrom: 100,
    restoreAfterFinish: true,
    beforeStartInternal: function(effect) { with(Element) {
      makePositioned(effect.element);
      makePositioned(effect.element.firstChild);
      if(window.opera) setStyle(effect.element, {top: ''});
      makeClipping(effect.element);
      show(element); }},  
    afterUpdateInternal: function(effect) { with(Element) {
      setStyle(effect.element.firstChild, {bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px' }); }},
    afterFinishInternal: function(effect) { with(Element) {
        [hide, undoClipping].call(effect.element); 
        undoPositioned(effect.element.firstChild);
        undoPositioned(effect.element);
        setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); }}
   }, arguments[1] || {})
  );
}

// Bug in opera makes the TD containing this element expand for a instance after finish 
Effect.Squish = function(element) {
  return new Effect.Scale(element, window.opera ? 1 : 0, 
    { restoreAfterFinish: true,
      beforeSetup: function(effect) { with(Element) {
        makeClipping(effect.element); }},  
      afterFinishInternal: function(effect) { with(Element) {
        hide(effect.element); 
        undoClipping(effect.element); }}
  });
}

Effect.Grow = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransistion: Effect.Transitions.sinoidal,
    scaleTransition: Effect.Transitions.sinoidal,
    opacityTransition: Effect.Transitions.full
  }, arguments[1] || {});
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    height: element.style.height,
    width: element.style.width,
    opacity: Element.getInlineOpacity(element) };

  var dims = Element.getDimensions(element);    
  var initialMoveX, initialMoveY;
  var moveX, moveY;
  
  switch (options.direction) {
    case 'top-left':
      initialMoveX = initialMoveY = moveX = moveY = 0; 
      break;
    case 'top-right':
      initialMoveX = dims.width;
      initialMoveY = moveY = 0;
      moveX = -dims.width;
      break;
    case 'bottom-left':
      initialMoveX = moveX = 0;
      initialMoveY = dims.height;
      moveY = -dims.height;
      break;
    case 'bottom-right':
      initialMoveX = dims.width;
      initialMoveY = dims.height;
      moveX = -dims.width;
      moveY = -dims.height;
      break;
    case 'center':
      initialMoveX = dims.width / 2;
      initialMoveY = dims.height / 2;
      moveX = -dims.width / 2;
      moveY = -dims.height / 2;
      break;
  }
  
  return new Effect.Move(element, {
    x: initialMoveX,
    y: initialMoveY,
    duration: 0.01, 
    beforeSetup: function(effect) { with(Element) {
      hide(effect.element);
      makeClipping(effect.element);
      makePositioned(effect.element);
    }},
    afterFinishInternal: function(effect) {
      new Effect.Parallel(
        [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
          new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
          new Effect.Scale(effect.element, 100, {
            scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, 
            sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
        ], Object.extend({
             beforeSetup: function(effect) { with(Element) {
               setStyle(effect.effects[0].element, {height: '0px'});
               show(effect.effects[0].element); }},
             afterFinishInternal: function(effect) { with(Element) {
               [undoClipping, undoPositioned].call(effect.effects[0].element); 
               setStyle(effect.effects[0].element, oldStyle); }}
           }, options)
      )
    }
  });
}

Effect.Shrink = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransistion: Effect.Transitions.sinoidal,
    scaleTransition: Effect.Transitions.sinoidal,
    opacityTransition: Effect.Transitions.none
  }, arguments[1] || {});
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    height: element.style.height,
    width: element.style.width,
    opacity: Element.getInlineOpacity(element) };

  var dims = Element.getDimensions(element);
  var moveX, moveY;
  
  switch (options.direction) {
    case 'top-left':
      moveX = moveY = 0;
      break;
    case 'top-right':
      moveX = dims.width;
      moveY = 0;
      break;
    case 'bottom-left':
      moveX = 0;
      moveY = dims.height;
      break;
    case 'bottom-right':
      moveX = dims.width;
      moveY = dims.height;
      break;
    case 'center':  
      moveX = dims.width / 2;
      moveY = dims.height / 2;
      break;
  }
  
  return new Effect.Parallel(
    [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
      new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
      new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
    ], Object.extend({            
         beforeStartInternal: function(effect) { with(Element) {
           [makePositioned, makeClipping].call(effect.effects[0].element) }},
         afterFinishInternal: function(effect) { with(Element) {
           [hide, undoClipping, undoPositioned].call(effect.effects[0].element);
           setStyle(effect.effects[0].element, oldStyle); }}
       }, options)
  );
}

Effect.Pulsate = function(element) {
  element = $(element);
  var options    = arguments[1] || {};
  var oldOpacity = Element.getInlineOpacity(element);
  var transition = options.transition || Effect.Transitions.sinoidal;
  var reverser   = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) };
  reverser.bind(transition);
  return new Effect.Opacity(element, 
    Object.extend(Object.extend({  duration: 3.0, from: 0,
      afterFinishInternal: function(effect) { Element.setStyle(effect.element, {opacity: oldOpacity}); }
    }, options), {transition: reverser}));
}

Effect.Fold = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height };
  Element.makeClipping(element);
  return new Effect.Scale(element, 5, Object.extend({   
    scaleContent: false,
    scaleX: false,
    afterFinishInternal: function(effect) {
    new Effect.Scale(element, 1, { 
      scaleContent: false, 
      scaleY: false,
      afterFinishInternal: function(effect) { with(Element) {
        [hide, undoClipping].call(effect.element); 
        setStyle(effect.element, oldStyle);
      }} });
  }}, arguments[1] || {}));
}

//######################################################################
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// See scriptaculous.js for full license.

var Builder = {
  NODEMAP: {
    AREA: 'map',
    CAPTION: 'table',
    COL: 'table',
    COLGROUP: 'table',
    LEGEND: 'fieldset',
    OPTGROUP: 'select',
    OPTION: 'select',
    PARAM: 'object',
    TBODY: 'table',
    TD: 'table',
    TFOOT: 'table',
    TH: 'table',
    THEAD: 'table',
    TR: 'table'
  },
  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
  //       due to a Firefox bug
  node: function(elementName) {
    elementName = elementName.toUpperCase();
    
    // try innerHTML approach
    var parentTag = this.NODEMAP[elementName] || 'div';
    var parentElement = document.createElement(parentTag);
    try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
      parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
    } catch(e) {}
    var element = parentElement.firstChild || null;
      
    // see if browser added wrapping tags
    if(element && (element.tagName != elementName))
      element = element.getElementsByTagName(elementName)[0];
    
    // fallback to createElement approach
    if(!element) element = document.createElement(elementName);
    
    // abort if nothing could be created
    if(!element) return;

    // attributes (or text)
    if(arguments[1])
      if(this._isStringOrNumber(arguments[1]) ||
        (arguments[1] instanceof Array)) {
          this._children(element, arguments[1]);
        } else {
          var attrs = this._attributes(arguments[1]);
          if(attrs.length) {
            try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
              parentElement.innerHTML = "<" +elementName + " " +
                attrs + "></" + elementName + ">";
            } catch(e) {}
            element = parentElement.firstChild || null;
            // workaround firefox 1.0.X bug
            if(!element) {
              element = document.createElement(elementName);
              for(attr in arguments[1]) 
                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
            }
            if(element.tagName != elementName)
              element = parentElement.getElementsByTagName(elementName)[0];
            }
        } 

    // text, or array of children
    if(arguments[2])
      this._children(element, arguments[2]);

     return element;
  },
  _text: function(text) {
     return document.createTextNode(text);
  },
  _attributes: function(attributes) {
    var attrs = [];
    for(attribute in attributes)
      attrs.push((attribute=='className' ? 'class' : attribute) +
          '="' + attributes[attribute].toString().escapeHTML() + '"');
    return attrs.join(" ");
  },
  _children: function(element, children) {
    if(typeof children=='object') { // array can hold nodes and text
      children.flatten().each( function(e) {
        if(typeof e=='object')
          element.appendChild(e)
        else
          if(Builder._isStringOrNumber(e))
            element.appendChild(Builder._text(e));
      });
    } else
      if(Builder._isStringOrNumber(children)) 
         element.appendChild(Builder._text(children));
  },
  _isStringOrNumber: function(param) {
    return(typeof param=='string' || typeof param=='number');
  }
}
//######################################################################
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//           (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
// 
// See scriptaculous.js for full license.

/*--------------------------------------------------------------------------*/

var Droppables = {
  drops: [],

  remove: function(element) {
    this.drops = this.drops.reject(function(d) { return d.element==$(element) });
  },

  add: function(element) {
    element = $(element);
    var options = Object.extend({
      greedy:     true,
      hoverclass: null,
      tree:       false
    }, arguments[1] || {});

    // cache containers
    if(options.containment) {
      options._containers = [];
      var containment = options.containment;
      if((typeof containment == 'object') && 
        (containment.constructor == Array)) {
        containment.each( function(c) { options._containers.push($(c)) });
      } else {
        options._containers.push($(containment));
      }
    }
    
    if(options.accept) options.accept = [options.accept].flatten();

    Element.makePositioned(element); // fix IE
    options.element = element;

    this.drops.push(options);
  },
  
  findDeepestChild: function(drops) {
    deepest = drops[0];
      
    for (i = 1; i < drops.length; ++i)
      if (Element.isParent(drops[i].element, deepest.element))
        deepest = drops[i];
    
    return deepest;
  },

  isContained: function(element, drop) {
    var containmentNode;
    if(drop.tree) {
      containmentNode = element.treeNode; 
    } else {
      containmentNode = element.parentNode;
    }
    return drop._containers.detect(function(c) { return containmentNode == c });
  },
  
  isAffected: function(point, element, drop) {
    return (
      (drop.element!=element) &&
      ((!drop._containers) ||
        this.isContained(element, drop)) &&
      ((!drop.accept) ||
        (Element.classNames(element).detect( 
          function(v) { return drop.accept.include(v) } ) )) &&
      Position.within(drop.element, point[0], point[1]) );
  },

  deactivate: function(drop) {
    if(drop.hoverclass)
      Element.removeClassName(drop.element, drop.hoverclass);
    this.last_active = null;
  },

  activate: function(drop) {
    if(drop.hoverclass)
      Element.addClassName(drop.element, drop.hoverclass);
    this.last_active = drop;
  },

  show: function(point, element) {
    if(!this.drops.length) return;
    var affected = [];
    
    if(this.last_active) this.deactivate(this.last_active);
    this.drops.each( function(drop) {
      if(Droppables.isAffected(point, element, drop))
        affected.push(drop);
    });
        
    if(affected.length>0) {
      drop = Droppables.findDeepestChild(affected);
      Position.within(drop.element, point[0], point[1]);
      if(drop.onHover)
        drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
      
      Droppables.activate(drop);
    }
  },

  fire: function(event, element) {
    if(!this.last_active) return;
    Position.prepare();

    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
      if (this.last_active.onDrop) 
        this.last_active.onDrop(element, this.last_active.element, event);
  },

  reset: function() {
    if(this.last_active)
      this.deactivate(this.last_active);
  }
}

var Draggables = {
drags: [],
observers: [],

register: function(draggable) {
if(this.drags.length == 0) {
this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
this.eventKeypress  = this.keyPress.bindAsEventListener(this);
Event.observe(document, "mouseup", this.eventMouseUp);
Event.observe(document, "mousemove", this.eventMouseMove);
Event.observe(document, "keypress", this.eventKeypress);
}
this.drags.push(draggable);
},

unregister: function(draggable) {
this.drags = this.drags.reject(function(d) { return d==draggable });
if(this.drags.length == 0) {
Event.stopObserving(document, "mouseup", this.eventMouseUp);
Event.stopObserving(document, "mousemove", this.eventMouseMove);
Event.stopObserving(document, "keypress", this.eventKeypress);
}
},

activate: function(draggable) {
window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
this.activeDraggable = draggable;
},

deactivate: function() {
this.activeDraggable = null;
},

updateDrag: function(event) {
if(!this.activeDraggable) return;
var pointer = [Event.pointerX(event), Event.pointerY(event)];
// Mozilla-based browsers fire successive mousemove events with
// the same coordinates, prevent needless redrawing (moz bug?)
if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
this._lastPointer = pointer;
this.activeDraggable.updateDrag(event, pointer);
},

endDrag: function(event) {
if(!this.activeDraggable) return;
this._lastPointer = null;
this.activeDraggable.endDrag(event);
this.activeDraggable = null;
},

keyPress: function(event) {
if(this.activeDraggable)
this.activeDraggable.keyPress(event);
},

addObserver: function(observer) {
this.observers.push(observer);
this._cacheObserverCallbacks();
},

removeObserver: function(element) {  // element instead of observer fixes mem leaks
this.observers = this.observers.reject( function(o) { return o.element==element });
this._cacheObserverCallbacks();
},

notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
if(this[eventName+'Count'] > 0)
this.observers.each( function(o) {
if(o[eventName]) o[eventName](eventName, draggable, event);
});
},

_cacheObserverCallbacks: function() {
['onStart','onEnd','onDrag'].each( function(eventName) {
Draggables[eventName+'Count'] = Draggables.observers.select(
function(o) { return o[eventName]; }
).length;
});
}
}

/*--------------------------------------------------------------------------*/

var Draggable = Class.create();
Draggable.prototype = {
  initialize: function(element) {
    var options = Object.extend({
      handle: false,
      starteffect: function(element) {
        element._opacity = Element.getOpacity(element); 
        new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); 
      },
      reverteffect: function(element, top_offset, left_offset) {
        var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
        element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur});
      },
      endeffect: function(element) {
        var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0
        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity}); 
      },
      zindex: 1000,
      revert: false,
      scroll: false,
      scrollSensitivity: 20,
      scrollSpeed: 15,
      snap: false   // false, or xy or [x,y] or function(x,y){ return [x,y] }
    }, arguments[1] || {});

    this.element = $(element);
    
    if(options.handle && (typeof options.handle == 'string')) {
      var h = Element.childrenWithClassName(this.element, options.handle, true);
      if(h.length>0) this.handle = h[0];
    }
    if(!this.handle) this.handle = $(options.handle);
    if(!this.handle) this.handle = this.element;
    
    if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML)
      options.scroll = $(options.scroll);

    Element.makePositioned(this.element); // fix IE    

    this.delta    = this.currentDelta();
    this.options  = options;
    this.dragging = false;   

    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
    Event.observe(this.handle, "mousedown", this.eventMouseDown);
    
    Draggables.register(this);
  },
  
  destroy: function() {
    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
    Draggables.unregister(this);
  },
  
  currentDelta: function() {
    return([
      parseInt(Element.getStyle(this.element,'left') || '0'),
      parseInt(Element.getStyle(this.element,'top') || '0')]);
  },
  
  initDrag: function(event) {
    if(Event.isLeftClick(event)) {    
      // abort on form elements, fixes a Firefox issue
      var src = Event.element(event);
      if(src.tagName && (
        src.tagName=='INPUT' ||
        src.tagName=='SELECT' ||
        src.tagName=='OPTION' ||
        src.tagName=='BUTTON' ||
        src.tagName=='TEXTAREA')) return;
        
      if(this.element._revert) {
        this.element._revert.cancel();
        this.element._revert = null;
      }
      
      var pointer = [Event.pointerX(event), Event.pointerY(event)];
      var pos     = Position.cumulativeOffset(this.element);
      this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
      
      Draggables.activate(this);
      Event.stop(event);
    }
  },
  
  startDrag: function(event) {
    this.dragging = true;
    
    if(this.options.zindex) {
      this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
      this.element.style.zIndex = this.options.zindex;
    }
    
    if(this.options.ghosting) {
      this._clone = this.element.cloneNode(true);
      Position.absolutize(this.element);
      this.element.parentNode.insertBefore(this._clone, this.element);
    }
    
    if(this.options.scroll) {
      if (this.options.scroll == window) {
        var where = this._getWindowScroll(this.options.scroll);
        this.originalScrollLeft = where.left;
        this.originalScrollTop = where.top;
      } else {
        this.originalScrollLeft = this.options.scroll.scrollLeft;
        this.originalScrollTop = this.options.scroll.scrollTop;
      }
    }
    
    Draggables.notify('onStart', this, event);
    if(this.options.starteffect) this.options.starteffect(this.element);
  },
  
  updateDrag: function(event, pointer) {
    if(!this.dragging) this.startDrag(event);
    Position.prepare();
    Droppables.show(pointer, this.element);
    Draggables.notify('onDrag', this, event);
    this.draw(pointer);
    if(this.options.change) this.options.change(this);
    
    if(this.options.scroll) {
      this.stopScrolling();
      
      var p;
      if (this.options.scroll == window) {
        with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
      } else {
        p = Position.page(this.options.scroll);
        p[0] += this.options.scroll.scrollLeft;
        p[1] += this.options.scroll.scrollTop;
        p.push(p[0]+this.options.scroll.offsetWidth);
        p.push(p[1]+this.options.scroll.offsetHeight);
      }
      var speed = [0,0];
      if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
      if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
      if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
      if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
      this.startScrolling(speed);
    }
    
    // fix AppleWebKit rendering
    if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
    
    Event.stop(event);
  },
  
  finishDrag: function(event, success) {
    this.dragging = false;

    if(this.options.ghosting) {
      Position.relativize(this.element);
      Element.remove(this._clone);
      this._clone = null;
    }

    if(success) Droppables.fire(event, this.element);
    Draggables.notify('onEnd', this, event);

    var revert = this.options.revert;
    if(revert && typeof revert == 'function') revert = revert(this.element);
    
    var d = this.currentDelta();
    if(revert && this.options.reverteffect) {
      this.options.reverteffect(this.element, 
        d[1]-this.delta[1], d[0]-this.delta[0]);
    } else {
      this.delta = d;
    }

    if(this.options.zindex)
      this.element.style.zIndex = this.originalZ;

    if(this.options.endeffect) 
      this.options.endeffect(this.element);

    Draggables.deactivate(this);
    Droppables.reset();
  },
  
  keyPress: function(event) {
    if(event.keyCode!=Event.KEY_ESC) return;
    this.finishDrag(event, false);
    Event.stop(event);
  },
  
  endDrag: function(event) {
    if(!this.dragging) return;
    this.stopScrolling();
    this.finishDrag(event, true);
    Event.stop(event);
  },
  
  draw: function(point) {
    var pos = Position.cumulativeOffset(this.element);
    var d = this.currentDelta();
    pos[0] -= d[0]; pos[1] -= d[1];
    
    if(this.options.scroll && (this.options.scroll != window)) {
      pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
      pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
    }
    
    var p = [0,1].map(function(i){ 
      return (point[i]-pos[i]-this.offset[i]) 
    }.bind(this));
    
    if(this.options.snap) {
      if(typeof this.options.snap == 'function') {
        p = this.options.snap(p[0],p[1],this);
      } else {
      if(this.options.snap instanceof Array) {
        p = p.map( function(v, i) {
          return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
      } else {
        p = p.map( function(v) {
          return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
      }
    }}
    
    var style = this.element.style;
    if((!this.options.constraint) || (this.options.constraint=='horizontal'))
      style.left = p[0] + "px";
    if((!this.options.constraint) || (this.options.constraint=='vertical'))
      style.top  = p[1] + "px";
    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
  },
  
  stopScrolling: function() {
    if(this.scrollInterval) {
      clearInterval(this.scrollInterval);
      this.scrollInterval = null;
      Draggables._lastScrollPointer = null;
    }
  },
  
  startScrolling: function(speed) {
    this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
    this.lastScrolled = new Date();
    this.scrollInterval = setInterval(this.scroll.bind(this), 10);
  },
  
  scroll: function() {
    var current = new Date();
    var delta = current - this.lastScrolled;
    this.lastScrolled = current;
    if(this.options.scroll == window) {
      with (this._getWindowScroll(this.options.scroll)) {
        if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
          var d = delta / 1000;
          this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
        }
      }
    } else {
      this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
      this.options.scroll.scrollTop  += this.scrollSpeed[1] * delta / 1000;
    }
    
    Position.prepare();
    Droppables.show(Draggables._lastPointer, this.element);
    Draggables.notify('onDrag', this);
    Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
    Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
    Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
    if (Draggables._lastScrollPointer[0] < 0)
      Draggables._lastScrollPointer[0] = 0;
    if (Draggables._lastScrollPointer[1] < 0)
      Draggables._lastScrollPointer[1] = 0;
    this.draw(Draggables._lastScrollPointer);
    
    if(this.options.change) this.options.change(this);
  },
  
  _getWindowScroll: function(w) {
    var T, L, W, H;
    with (w.document) {
      if (w.document.documentElement && documentElement.scrollTop) {
        T = documentElement.scrollTop;
        L = documentElement.scrollLeft;
      } else if (w.document.body) {
        T = body.scrollTop;
        L = body.scrollLeft;
      }
      if (w.innerWidth) {
        W = w.innerWidth;
        H = w.innerHeight;
      } else if (w.document.documentElement && documentElement.clientWidth) {
        W = documentElement.clientWidth;
        H = documentElement.clientHeight;
      } else {
        W = body.offsetWidth;
        H = body.offsetHeight
      }
    }
    return { top: T, left: L, width: W, height: H };
  }
}

/*--------------------------------------------------------------------------*/

var SortableObserver = Class.create();
SortableObserver.prototype = {
  initialize: function(element, observer) {
    this.element   = $(element);
    this.observer  = observer;
    this.lastValue = Sortable.serialize(this.element);
  },
  
  onStart: function() {
    this.lastValue = Sortable.serialize(this.element);
  },
  
  onEnd: function() {
    Sortable.unmark();
    if(this.lastValue != Sortable.serialize(this.element))
      this.observer(this.element)
  }
}

var Sortable = {
  sortables: {},
  
  _findRootElement: function(element) {
    while (element.tagName != "BODY") {  
      if(element.id && Sortable.sortables[element.id]) return element;
      element = element.parentNode;
    }
  },

  options: function(element) {
    element = Sortable._findRootElement($(element));
    if(!element) return;
    return Sortable.sortables[element.id];
  },
  
  destroy: function(element){
    var s = Sortable.options(element);
    
    if(s) {
      Draggables.removeObserver(s.element);
      s.droppables.each(function(d){ Droppables.remove(d) });
      s.draggables.invoke('destroy');
      
      delete Sortable.sortables[s.element.id];
    }
  },

  create: function(element) {
    element = $(element);
    var options = Object.extend({ 
      element:     element,
      tag:         'li',       // assumes li children, override with tag: 'tagname'
      dropOnEmpty: false,
      tree:        false,
      treeTag:     'ul',
      overlap:     'vertical', // one of 'vertical', 'horizontal'
      constraint:  'vertical', // one of 'vertical', 'horizontal', false
      containment: element,    // also takes array of elements (or id's); or false
      handle:      false,      // or a CSS class
      only:        false,
      hoverclass:  null,
      ghosting:    false,
      scroll:      false,
      scrollSensitivity: 20,
      scrollSpeed: 15,
      format:      /^[^_]*_(.*)$/,
      onChange:    Prototype.emptyFunction,
      onUpdate:    Prototype.emptyFunction
    }, arguments[1] || {});

    // clear any old sortable with same element
    this.destroy(element);

    // build options for the draggables
    var options_for_draggable = {
      revert:      true,
      scroll:      options.scroll,
      scrollSpeed: options.scrollSpeed,
      scrollSensitivity: options.scrollSensitivity,
      ghosting:    options.ghosting,
      constraint:  options.constraint,
      handle:      options.handle };

    if(options.starteffect)
      options_for_draggable.starteffect = options.starteffect;

    if(options.reverteffect)
      options_for_draggable.reverteffect = options.reverteffect;
    else
      if(options.ghosting) options_for_draggable.reverteffect = function(element) {
        element.style.top  = 0;
        element.style.left = 0;
      };

    if(options.endeffect)
      options_for_draggable.endeffect = options.endeffect;

    if(options.zindex)
      options_for_draggable.zindex = options.zindex;

    // build options for the droppables  
    var options_for_droppable = {
      overlap:     options.overlap,
      containment: options.containment,
      tree:        options.tree,
      hoverclass:  options.hoverclass,
      onHover:     Sortable.onHover
      //greedy:      !options.dropOnEmpty
    }
    
    var options_for_tree = {
      onHover:      Sortable.onEmptyHover,
      overlap:      options.overlap,
      containment:  options.containment,
      hoverclass:   options.hoverclass
    }

    // fix for gecko engine
    Element.cleanWhitespace(element); 

    options.draggables = [];
    options.droppables = [];

    // drop on empty handling
    if(options.dropOnEmpty || options.tree) {
      Droppables.add(element, options_for_tree);
      options.droppables.push(element);
    }

    (this.findElements(element, options) || []).each( function(e) {
      // handles are per-draggable
      var handle = options.handle ? 
        Element.childrenWithClassName(e, options.handle)[0] : e;    
      options.draggables.push(
        new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
      Droppables.add(e, options_for_droppable);
      if(options.tree) e.treeNode = element;
      options.droppables.push(e);      
    });
    
    if(options.tree) {
      (Sortable.findTreeElements(element, options) || []).each( function(e) {
        Droppables.add(e, options_for_tree);
        e.treeNode = element;
        options.droppables.push(e);
      });
    }

    // keep reference
    this.sortables[element.id] = options;

    // for onupdate
    Draggables.addObserver(new SortableObserver(element, options.onUpdate));

  },

  // return all suitable-for-sortable elements in a guaranteed order
  findElements: function(element, options) {
    return Element.findChildren(
      element, options.only, options.tree ? true : false, options.tag);
  },
  
  findTreeElements: function(element, options) {
    return Element.findChildren(
      element, options.only, options.tree ? true : false, options.treeTag);
  },

  onHover: function(element, dropon, overlap) {
    if(Element.isParent(dropon, element)) return;

    if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
      return;
    } else if(overlap>0.5) {
      Sortable.mark(dropon, 'before');
      if(dropon.previousSibling != element) {
        var oldParentNode = element.parentNode;
        element.style.visibility = "hidden"; // fix gecko rendering
        dropon.parentNode.insertBefore(element, dropon);
        if(dropon.parentNode!=oldParentNode) 
          Sortable.options(oldParentNode).onChange(element);
        Sortable.options(dropon.parentNode).onChange(element);
      }
    } else {
      Sortable.mark(dropon, 'after');
      var nextElement = dropon.nextSibling || null;
      if(nextElement != element) {
        var oldParentNode = element.parentNode;
        element.style.visibility = "hidden"; // fix gecko rendering
        dropon.parentNode.insertBefore(element, nextElement);
        if(dropon.parentNode!=oldParentNode) 
          Sortable.options(oldParentNode).onChange(element);
        Sortable.options(dropon.parentNode).onChange(element);
      }
    }
  },
  
  onEmptyHover: function(element, dropon, overlap) {
    var oldParentNode = element.parentNode;
    var droponOptions = Sortable.options(dropon);
        
    if(!Element.isParent(dropon, element)) {
      var index;
      
      var children = Sortable.findElements(dropon, {tag: droponOptions.tag});
      var child = null;
            
      if(children) {
        var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
        
        for (index = 0; index < children.length; index += 1) {
          if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
            offset -= Element.offsetSize (children[index], droponOptions.overlap);
          } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
            child = index + 1 < children.length ? children[index + 1] : null;
            break;
          } else {
            child = children[index];
            break;
          }
        }
      }
      
      dropon.insertBefore(element, child);
      
      Sortable.options(oldParentNode).onChange(element);
      droponOptions.onChange(element);
    }
  },

  unmark: function() {
    if(Sortable._marker) Element.hide(Sortable._marker);
  },

  mark: function(dropon, position) {
    // mark on ghosting only
    var sortable = Sortable.options(dropon.parentNode);
    if(sortable && !sortable.ghosting) return; 

    if(!Sortable._marker) {
      Sortable._marker = $('dropmarker') || document.createElement('DIV');
      Element.hide(Sortable._marker);
      Element.addClassName(Sortable._marker, 'dropmarker');
      Sortable._marker.style.position = 'absolute';
      document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
    }    
    var offsets = Position.cumulativeOffset(dropon);
    Sortable._marker.style.left = offsets[0] + 'px';
    Sortable._marker.style.top = offsets[1] + 'px';
    
    if(position=='after')
      if(sortable.overlap == 'horizontal') 
        Sortable._marker.style.left = (offsets[0]+dropon.clientWidth) + 'px';
      else
        Sortable._marker.style.top = (offsets[1]+dropon.clientHeight) + 'px';
    
    Element.show(Sortable._marker);
  },
  
  _tree: function(element, options, parent) {
    var children = Sortable.findElements(element, options) || [];
  
    for (var i = 0; i < children.length; ++i) {
      var match = children[i].id.match(options.format);

      if (!match) continue;
      
      var child = {
        id: encodeURIComponent(match ? match[1] : null),
        element: element,
        parent: parent,
        children: new Array,
        position: parent.children.length,
        container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase())
      }
      
      /* Get the element containing the children and recurse over it */
      if (child.container)
        this._tree(child.container, options, child)
      
      parent.children.push (child);
    }

    return parent; 
  },

  /* Finds the first element of the given tag type within a parent element.
    Used for finding the first LI[ST] within a L[IST]I[TEM].*/
  _findChildrenElement: function (element, containerTag) {
    if (element && element.hasChildNodes)
      for (var i = 0; i < element.childNodes.length; ++i)
        if (element.childNodes[i].tagName == containerTag)
          return element.childNodes[i];
  
    return null;
  },

  tree: function(element) {
    element = $(element);
    var sortableOptions = this.options(element);
    var options = Object.extend({
      tag: sortableOptions.tag,
      treeTag: sortableOptions.treeTag,
      only: sortableOptions.only,
      name: element.id,
      format: sortableOptions.format
    }, arguments[1] || {});
    
    var root = {
      id: null,
      parent: null,
      children: new Array,
      container: element,
      position: 0
    }
    
    return Sortable._tree (element, options, root);
  },

  /* Construct a [i] index for a particular node */
  _constructIndex: function(node) {
    var index = '';
    do {
      if (node.id) index = '[' + node.position + ']' + index;
    } while ((node = node.parent) != null);
    return index;
  },

  sequence: function(element) {
    element = $(element);
    var options = Object.extend(this.options(element), arguments[1] || {});
    
    return $(this.findElements(element, options) || []).map( function(item) {
      return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
    });
  },

  setSequence: function(element, new_sequence) {
    element = $(element);
    var options = Object.extend(this.options(element), arguments[2] || {});
    
    var nodeMap = {};
    this.findElements(element, options).each( function(n) {
        if (n.id.match(options.format))
            nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
        n.parentNode.removeChild(n);
    });
   
    new_sequence.each(function(ident) {
      var n = nodeMap[ident];
      if (n) {
        n[1].appendChild(n[0]);
        delete nodeMap[ident];
      }
    });
  },
  
  serialize: function(element) {
    element = $(element);
    var options = Object.extend(Sortable.options(element), arguments[1] || {});
    var name = encodeURIComponent(
      (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
    
    if (options.tree) {
      return Sortable.tree(element, arguments[1]).children.map( function (item) {
        return [name + Sortable._constructIndex(item) + "=" + 
                encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
      }).flatten().join('&');
    } else {
      return Sortable.sequence(element, arguments[1]).map( function(item) {
        return name + "[]=" + encodeURIComponent(item);
      }).join('&');
    }
  }
}

/* Returns true if child is contained within element */
Element.isParent = function(child, element) {
  if (!child.parentNode || child == element) return false;

  if (child.parentNode == element) return true;

  return Element.isParent(child.parentNode, element);
}

Element.findChildren = function(element, only, recursive, tagName) {    
  if(!element.hasChildNodes()) return null;
  tagName = tagName.toUpperCase();
  if(only) only = [only].flatten();
  var elements = [];
  $A(element.childNodes).each( function(e) {
    if(e.tagName && e.tagName.toUpperCase()==tagName &&
      (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
        elements.push(e);
    if(recursive) {
      var grandchildren = Element.findChildren(e, only, recursive, tagName);
      if(grandchildren) elements.push(grandchildren);
    }
  });

  return (elements.length>0 ? elements.flatten() : []);
}

Element.offsetSize = function (element, type) {
  if (type == 'vertical' || type == 'height')
    return element.offsetHeight;
  else
    return element.offsetWidth;
}
//######################################################################
var CropDraggable=Class.create();
Object.extend(Object.extend(CropDraggable.prototype,Draggable.prototype),{
initialize:function(_1){
this.options=Object.extend({drawMethod:function(){}},arguments[1]||{});
this.element=$(_1);
this.handle=this.element;
this.delta=this.currentDelta();
this.dragging=false;
this.eventMouseDown=this.initDrag.bindAsEventListener(this);
Event.observe(this.handle,"mousedown",this.eventMouseDown);
Draggables.register(this);
},
draw:function(_2){
var _3=Position.cumulativeOffset(this.element);
var d=this.currentDelta();
_3[0]-=d[0];
_3[1]-=d[1];
var p=[0,1].map(function(i){
return (_2[i]-_3[i]-this.offset[i]);
}.bind(this));
this.options.drawMethod(p);
},
unregister:function(){
Draggables.unregister(this);
}
});
var Cropper={};
Cropper.Img=Class.create();
Cropper.Img.prototype={
initialize:function(_7,_8){
this.options=Object.extend({ratioDim:{x:0,y:0},minWidth:0,minHeight:0,initWidth:0,initHeight:0,displayOnInit:false,onDragNotify:Prototype.emptyFunction,onEndCrop:Prototype.emptyFunction,onInitCrop:Prototype.emptyFunction,captureKeys:true},_8||{});
if(this.options.minWidth>0&&this.options.minHeight>0){
this.options.ratioDim.x=this.options.minWidth;
this.options.ratioDim.y=this.options.minHeight;
}
this.img=$(_7);
this.clickCoords={x:0,y:0};
this.dragging=false;
this.resizing=false;
this.isWebKit=/Konqueror|Safari|KHTML/.test(navigator.userAgent);
this.isIE=/MSIE/.test(navigator.userAgent);
this.isOpera8=/Opera\s[1-8]/.test(navigator.userAgent);
this.ratioX=0;
this.ratioY=0;
this.attached=false;
/*
$A(document.getElementsByTagName("script")).each(function(s){
if(s.src.match(/cropper\.js/)){
var _a=s.src.replace(/cropper\.js(.*)?/,"");
var _b=document.createElement("link");
_b.rel="stylesheet";
_b.type="text/css";
_b.href=_a+"cropper.css";
_b.media="screen";
document.getElementsByTagName("head")[0].appendChild(_b);
}
});
*/
if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0){
var _c=this.getGCD(this.options.ratioDim.x,this.options.ratioDim.y);
this.ratioX=this.options.ratioDim.x/_c;
this.ratioY=this.options.ratioDim.y/_c;
}
this.subInitialize();
if(this.img.complete||this.isWebKit){
this.onLoad();
}else{
Event.observe(this.img,"load",this.onLoad.bindAsEventListener(this));
}
},
getGCD:function(a,b){
if(b==0){
return a;
}
return this.getGCD(b,a%b);
},
onLoad:function(){
var _f="imgCrop_";
var _10=this.img.parentNode;
var _11="";
if(this.isOpera8){
_11=" opera8";
}
this.imgWrap=Builder.node("div",{"class":_f+"wrap"+_11});
if(this.isIE){
this.north=Builder.node("div",{"class":_f+"overlay "+_f+"north"},[Builder.node("span")]);
this.east=Builder.node("div",{"class":_f+"overlay "+_f+"east"},[Builder.node("span")]);
this.south=Builder.node("div",{"class":_f+"overlay "+_f+"south"},[Builder.node("span")]);
this.west=Builder.node("div",{"class":_f+"overlay "+_f+"west"},[Builder.node("span")]);
var _12=[this.north,this.east,this.south,this.west];
}else{
this.overlay=Builder.node("div",{"class":_f+"overlay"});
var _12=[this.overlay];
}
this.dragArea=Builder.node("div",{"class":_f+"dragArea"},_12);
this.handleN=Builder.node("div",{"class":_f+"handle "+_f+"handleN"});
this.handleNE=Builder.node("div",{"class":_f+"handle "+_f+"handleNE"});
this.handleE=Builder.node("div",{"class":_f+"handle "+_f+"handleE"});
this.handleSE=Builder.node("div",{"class":_f+"handle "+_f+"handleSE"});
this.handleS=Builder.node("div",{"class":_f+"handle "+_f+"handleS"});
this.handleSW=Builder.node("div",{"class":_f+"handle "+_f+"handleSW"});
this.handleW=Builder.node("div",{"class":_f+"handle "+_f+"handleW"});
this.handleNW=Builder.node("div",{"class":_f+"handle "+_f+"handleNW"});
this.selArea=Builder.node("div",{"class":_f+"selArea"},[Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeNorth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeEast"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeSouth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeWest"},[Builder.node("span")]),this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW,Builder.node("div",{"class":_f+"clickArea"})]);
$(this.selArea).setStyle({backgroundColor:"transparent",backgroundRepeat:"no-repeat",backgroundPosition:"0 0"});
this.imgWrap.appendChild(this.img);
this.imgWrap.appendChild(this.dragArea);
this.dragArea.appendChild(this.selArea);
this.dragArea.appendChild(Builder.node("div",{"class":_f+"clickArea"}));
_10.appendChild(this.imgWrap);
this.startDragObserver = this.startDrag.bindAsEventListener(this);
Event.observe(this.dragArea,"mousedown",this.startDragObserver);
this.onDragObserver = this.onDrag.bindAsEventListener(this);
Event.observe(document,"mousemove",this.onDragObserver);
this.endCropObserver = this.endCrop.bindAsEventListener(this);
Event.observe(document,"mouseup",this.endCropObserver);
var _13=[this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW];
for(var i=0;i<_13.length;i++){
Event.observe(_13[i],"mousedown",this.startResize.bindAsEventListener(this));
}
if(this.options.captureKeys){
Event.observe(document,"keydown",this.handleKeys.bindAsEventListener(this));
}
this.cropDragable = new CropDraggable(this.selArea,{drawMethod:this.moveArea.bindAsEventListener(this)});
this.setParams();
},
setParams:function(){
this.imgW=this.img.width;
this.imgH=this.img.height;
if(!this.isIE){
$(this.overlay).setStyle({width:this.imgW+"px",height:this.imgH+"px"});
$(this.overlay).hide();
$(this.selArea).setStyle({backgroundImage:"url("+this.img.src+")"});
}else{
$(this.north).setStyle({height:0});
$(this.east).setStyle({width:0,height:0});
$(this.south).setStyle({height:0});
$(this.west).setStyle({width:0,height:0});
}
$(this.imgWrap).setStyle({"width":this.imgW+"px","height":this.imgH+"px"});
$(this.selArea).hide();
var _15=Position.positionedOffset(this.imgWrap);
this.wrapOffsets={"top":_15[1],"left":_15[0]};
var _16={x1:0,y1:0,x2:0,y2:0};
this.setAreaCoords(_16);
if(this.options.initWidth>0&&this.options.initHeight>0&&this.options.displayOnInit){
_16.x1=Math.ceil((this.imgW-this.options.initWidth)/2);
_16.y1=Math.ceil((this.imgH-this.options.initHeight)/2);
_16.x2=_16.x1+this.options.initWidth;
_16.y2=_16.y1+this.options.initHeight;

this.selArea.show();

this.drawArea();
this.endCrop();
//alert(this.options.onInitCrop);
}
this.attached=true;
},
remove:function(){
this.attached=false;
this.imgWrap.parentNode.insertBefore(this.img,this.imgWrap);
this.imgWrap.parentNode.removeChild(this.imgWrap);
Event.stopObserving(this.dragArea,"mousedown",this.startDragObserver);
Event.stopObserving(document,"mousemove",this.onDragObserver);
Event.stopObserving(document,"mouseup",this.endCropObserver);
var _17=[this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW];
if(this.cropDragable) this.cropDragable.unregister();
this.cropDragable = null;
for(var i=0;i<_17.length;i++){
Event.stopObserving(_17[i],"mousedown",this.startResize.bindAsEventListener(this));
}
if(this.options.captureKeys){
Event.stopObserving(document,"keydown",this.handleKeys.bindAsEventListener(this));
}
},
reset:function(){
if(!this.attached){
this.onLoad();
}else{
this.setParams();
}
this.endCrop();
},
handleKeys:function(e){
var dir={x:0,y:0};
if(!this.dragging){
switch(e.keyCode){
case (37):
dir.x=-1;
break;
case (38):
dir.y=-1;
break;
case (39):
dir.x=1;
break;
case (40):
dir.y=1;
break;
}
if(dir.x!=0||dir.y!=0){
if(e.shiftKey){
dir.x*=10;
dir.y*=10;
}
this.moveArea([this.areaCoords.x1+dir.x,this.areaCoords.y1+dir.y]);
Event.stop(e);
}
}
},
calcW:function(){
return (this.areaCoords.x2-this.areaCoords.x1);
},
calcH:function(){
return (this.areaCoords.y2-this.areaCoords.y1);
},
moveArea:function(_1b){
this.setAreaCoords({x1:_1b[0],y1:_1b[1],x2:_1b[0]+this.calcW(),y2:_1b[1]+this.calcH()},true);
this.drawArea();
},
cloneCoords:function(_1c){
return {x1:_1c.x1,y1:_1c.y1,x2:_1c.x2,y2:_1c.y2};
},
setAreaCoords:function(_1d,_1e,_1f,_20,_21){
var _22=typeof _1e!="undefined"?_1e:false;
var _23=typeof _1f!="undefined"?_1f:false;
if(_1e){
var _24=_1d.x2-_1d.x1;
var _25=_1d.y2-_1d.y1;
if(_1d.x1<0){
_1d.x1=0;
_1d.x2=_24;
}
if(_1d.y1<0){
_1d.y1=0;
_1d.y2=_25;
}
if(_1d.x2>this.imgW){
_1d.x2=this.imgW;
_1d.x1=this.imgW-_24;
}
if(_1d.y2>this.imgH){
_1d.y2=this.imgH;
_1d.y1=this.imgH-_25;
}
}else{
if(_1d.x1<0){
_1d.x1=0;
}
if(_1d.y1<0){
_1d.y1=0;
}
if(_1d.x2>this.imgW){
_1d.x2=this.imgW;
}
if(_1d.y2>this.imgH){
_1d.y2=this.imgH;
}
if(typeof (_20)!="undefined"){
if(this.ratioX>0){
this.applyRatio(_1d,{x:this.ratioX,y:this.ratioY},_20,_21);
}else{
if(_23){
this.applyRatio(_1d,{x:1,y:1},_20,_21);
}
}
var _26={a1:_1d.x1,a2:_1d.x2};
var _27={a1:_1d.y1,a2:_1d.y2};
var _28=this.options.minWidth;
var _29=this.options.minHeight;
if((_28==0||_29==0)&&_23){
if(_28>0){
_29=_28;
}else{
if(_29>0){
_28=_29;
}
}
}
this.applyMinDimension(_26,_28,_20.x,{min:0,max:this.imgW});
this.applyMinDimension(_27,_29,_20.y,{min:0,max:this.imgH});
_1d={x1:_26.a1,y1:_27.a1,x2:_26.a2,y2:_27.a2};
}
}
this.areaCoords=_1d;
},
applyMinDimension:function(_2a,_2b,_2c,_2d){
if((_2a.a2-_2a.a1)<_2b){
if(_2c==1){
_2a.a2=_2a.a1+_2b;
}else{
_2a.a1=_2a.a2-_2b;
}
if(_2a.a1<_2d.min){
_2a.a1=_2d.min;
_2a.a2=_2b;
}else{
if(_2a.a2>_2d.max){
_2a.a1=_2d.max-_2b;
_2a.a2=_2d.max;
}
}
}
},
applyRatio:function(_2e,_2f,_30,_31){
var _32;
if(_31=="N"||_31=="S"){
_32=this.applyRatioToAxis({a1:_2e.y1,b1:_2e.x1,a2:_2e.y2,b2:_2e.x2},{a:_2f.y,b:_2f.x},{a:_30.y,b:_30.x},{min:0,max:this.imgW});
_2e.x1=_32.b1;
_2e.y1=_32.a1;
_2e.x2=_32.b2;
_2e.y2=_32.a2;
}else{
_32=this.applyRatioToAxis({a1:_2e.x1,b1:_2e.y1,a2:_2e.x2,b2:_2e.y2},{a:_2f.x,b:_2f.y},{a:_30.x,b:_30.y},{min:0,max:this.imgH});
_2e.x1=_32.a1;
_2e.y1=_32.b1;
_2e.x2=_32.a2;
_2e.y2=_32.b2;
}
},
applyRatioToAxis:function(_33,_34,_35,_36){
var _37=Object.extend(_33,{});
var _38=_37.a2-_37.a1;
var _39=Math.floor(_38*_34.b/_34.a);
var _3a;
var _3b;
var _3c=null;
if(_35.b==1){
_3a=_37.b1+_39;
if(_3a>_36.max){
_3a=_36.max;
_3c=_3a-_37.b1;
}
_37.b2=_3a;
}else{
_3a=_37.b2-_39;
if(_3a<_36.min){
_3a=_36.min;
_3c=_3a+_37.b2;
}
_37.b1=_3a;
}
if(_3c!=null){
_3b=Math.floor(_3c*_34.a/_34.b);
if(_35.a==1){
_37.a2=_37.a1+_3b;
}else{
_37.a1=_37.a1=_37.a2-_3b;
}
}
return _37;
},
drawArea:function(){
if(!this.isIE){
$(this.overlay).show();
}
var _3d=this.calcW();
var _3e=this.calcH();
var _3f=this.areaCoords.x2;
var _40=this.areaCoords.y2;
var _41=this.selArea.style;
_41.left=this.areaCoords.x1+"px";
_41.top=this.areaCoords.y1+"px";
_41.width=_3d+"px";
_41.height=_3e+"px";
var _42=Math.ceil((_3d-6)/2)+"px";
var _43=Math.ceil((_3e-6)/2)+"px";
this.handleN.style.left=_42;
this.handleE.style.top=_43;
this.handleS.style.left=_42;
this.handleW.style.top=_43;
if(this.isIE){
this.north.style.height=this.areaCoords.y1+"px";
var _44=this.east.style;
_44.top=this.areaCoords.y1+"px";
_44.height=_3e+"px";
_44.left=_3f+"px";
_44.width=(this.img.width-_3f)+"px";
var _45=this.south.style;
_45.top=_40+"px";
_45.height=(this.img.height-_40)+"px";
var _46=this.west.style;
_46.top=this.areaCoords.y1+"px";
_46.height=_3e+"px";
_46.width=this.areaCoords.x1+"px";
}else{
_41.backgroundPosition="-"+this.areaCoords.x1+"px "+"-"+this.areaCoords.y1+"px";
}
this.options.onDragNotify(this.areaCoords,{width:this.calcW(),height:this.calcH()});
this.subDrawArea();
this.forceReRender();

},
forceReRender:function(){
if(this.isIE||this.isWebKit){
var n=document.createTextNode(" ");
var d,el,fixEL,i;
if(this.isIE){
fixEl=this.selArea;
}else{
if(this.isWebKit){
fixEl=document.getElementsByClassName("imgCrop_marqueeSouth",this.imgWrap)[0];
d=Builder.node("div","");
d.style.visibility="hidden";
var _49=["SE","S","SW"];
for(i=0;i<_49.length;i++){
el=document.getElementsByClassName("imgCrop_handle"+_49[i],this.selArea)[0];
if(el.childNodes.length){
el.removeChild(el.childNodes[0]);
}
el.appendChild(d);
}
}
}
fixEl.appendChild(n);
fixEl.removeChild(n);
}
},
startResize:function(e){
this.startCoords=this.cloneCoords(this.areaCoords);
this.resizing=true;
this.resizeHandle=Event.element(e).classNames().toString().replace(/([^N|NE|E|SE|S|SW|W|NW])+/,"");
Event.stop(e);
},
startDrag:function(e){
this.selArea.show();
this.clickCoords=this.getCurPos(e);
this.setAreaCoords({x1:this.clickCoords.x,y1:this.clickCoords.y,x2:this.clickCoords.x,y2:this.clickCoords.y});
this.dragging=true;
this.onDrag(e);
Event.stop(e);
},
getCurPos:function(e){
return curPos={x:Event.pointerX(e)-this.wrapOffsets.left,y:Event.pointerY(e)-this.wrapOffsets.top};
},
onDrag:function(e){
var _4e=null;
if(this.dragging||this.resizing){
var _4f=this.getCurPos(e);
var _50=this.cloneCoords(this.areaCoords);
var _51={x:1,y:1};
}
if(this.dragging){
if(_4f.x<this.clickCoords.x){
_51.x=-1;
}
if(_4f.y<this.clickCoords.y){
_51.y=-1;
}
this.transformCoords(_4f.x,this.clickCoords.x,_50,"x");
this.transformCoords(_4f.y,this.clickCoords.y,_50,"y");
}else{
if(this.resizing){
_4e=this.resizeHandle;
if(_4e.match(/E/)){
this.transformCoords(_4f.x,this.startCoords.x1,_50,"x");
if(_4f.x<this.startCoords.x1){
_51.x=-1;
}
}else{
if(_4e.match(/W/)){
this.transformCoords(_4f.x,this.startCoords.x2,_50,"x");
if(_4f.x<this.startCoords.x2){
_51.x=-1;
}
}
}
if(_4e.match(/N/)){
this.transformCoords(_4f.y,this.startCoords.y2,_50,"y");
if(_4f.y<this.startCoords.y2){
_51.y=-1;
}
}else{
if(_4e.match(/S/)){
this.transformCoords(_4f.y,this.startCoords.y1,_50,"y");
if(_4f.y<this.startCoords.y1){
_51.y=-1;
}
}
}
}
}
if(this.dragging||this.resizing){
this.setAreaCoords(_50,false,e.shiftKey,_51,_4e);
this.drawArea();
Event.stop(e);
}
},
transformCoords:function(_52,_53,_54,_55){
var _56=new Array();
if(_52<_53){
_56[0]=_52;
_56[1]=_53;
}else{
_56[0]=_53;
_56[1]=_52;
}
if(_55=="x"){
_54.x1=_56[0];
_54.x2=_56[1];
}else{
_54.y1=_56[0];
_54.y2=_56[1];
}
},
endCrop:function(){
this.dragging=false;
this.resizing=false;
this.options.onEndCrop(this.areaCoords,{width:this.calcW(),height:this.calcH()});
},
subInitialize:function(){
},
subDrawArea:function(){
}
};
Cropper.ImgWithPreview=Class.create();
Object.extend(Object.extend(Cropper.ImgWithPreview.prototype,Cropper.Img.prototype),{
subInitialize:function(){
this.hasPreviewImg=false;
if(typeof (this.options.previewWrap)!="undefined"&&this.options.minWidth>0&&this.options.minHeight>0){
this.previewWrap=$(this.options.previewWrap);
this.previewImg=this.img.cloneNode(false);
this.options.displayOnInit=true;
this.hasPreviewImg=true;
this.previewWrap.addClassName("imgCrop_previewWrap");
this.previewWrap.setStyle({width:this.options.minWidth+"px",height:this.options.minHeight+"px"});
this.previewWrap.appendChild(this.previewImg);
}
},
subDrawArea:function(){
if(this.hasPreviewImg){
var _57=this.calcW();
var _58=this.calcH();
var _59={x:this.imgW/_57,y:this.imgH/_58};
var _5a={x:_57/this.options.minWidth,y:_58/this.options.minHeight};
var _5b={w:Math.ceil(this.options.minWidth*_59.x)+"px",h:Math.ceil(this.options.minHeight*_59.y)+"px",x:"-"+Math.ceil(this.areaCoords.x1/_5a.x)+"px",y:"-"+Math.ceil(this.areaCoords.y1/_5a.y)+"px"};
var _5c=this.previewImg.style;
_5c.width=_5b.w;
_5c.height=_5b.h;
_5c.left=_5b.x;
_5c.top=_5b.y;
}
}
});

var Comments = {

parent: null,
form: null,
editActive: false,
apiBase: '/api.php?',

init: function(id,form_id){
Comments.parent = $(id);
Comments.form = $(form_id);
},
submit: function(){
Comments.submitForm(Comments.form);
},
submitForm: function(form) {
var url = Comments.apiBase;
for(var i = 0; i < form.elements.length; i++) {
if (form.elements[i].name) {
if (form.elements[i].type == 'hidden')
url += '&' + form.elements[i].name + '=' + encodeURIComponent(form.elements[i].value);
else
url += '&data[' + form.elements[i].name + ']=' + encodeURIComponent(form.elements[i].value);
}
}
call(url,"Comments.set","",Comments.form.id);
},
edit: function(comment_id){
if (Comments.editActive)
this.closeEdit();
Comments.editActive = true;
Comments.commentElement = $('comment_'+comment_id);
for (var i = 0; i < Comments.commentElement.childNodes.length; i++) {
if (Comments.commentElement.childNodes[i].tagName == 'P') {
Comments.value = Comments.commentElement.childNodes[i].innerHTML;
Comments.element = Comments.commentElement.childNodes[i];
rm(Comments.element, false);
break;
}
}

var commentForm = ce('form');
commentForm.method = 'POST';
commentForm.action = Comments.apiBase;

Comments.commentElementInput = ce('textarea', '', '');
Comments.commentElementInput.name = 'comment';
Comments.commentElementInput.value = html_entity_decode($('ctext_' + comment_id).innerHTML);

var div = ce('div', '', 'buttons');
var sbmt = ce('input', '', 'submit');
sbmt.type = 'button';
sbmt.value = 'Запази';
sbmt.onclick = function() { Comments.submitForm(commentForm); };
div.appendChild(sbmt);
var rst = ce('input', '', '');
rst.type = 'button';
rst.value = 'Отказ';
rst.onclick = Comments.closeEdit;
div.appendChild(rst);

appendChildren(
commentForm,
Comments.commentElementInput,
cel('input', 'hidden', 'comment_id', comment_id),
cel('input', 'hidden', 'image_id', Current.get('image_id')),
cel('input', 'hidden', 'object', 'images'),
cel('input', 'hidden', 'action', 'edit_comment'),
div
);

Comments.element.appendChild(commentForm);
},

closeEdit: function(){
//if (Comments.element) {
//rm(Comments.commentEditElement,true);
//}
Comments.element.innerHTML = Comments.value;
Comments.editActive = false;
},

del: function(comment_id){
var url = Comments.apiBase + 'object=images&action=delete_comment&image_id='+Current.get('image_id')+'&comment_id='+comment_id;
call(url,"Comments.set","",Comments.parent);
return false;
},

setInvitationStatus: function(comment_id, invitation_status, image_id, callback) {
if (!image_id) image_id = Current.get('image_id');
if (!callback || callback == '') callback = "Comments.set";
var url = Comments.apiBase + 'object=images&action=set_invitation_status&image_id='+image_id+'&comment_id='+comment_id+'&invitation_status='+invitation_status;
call(url, callback, "", null);
return false;
},

acceptGroupInvitation: function(commentId, groupAccess, imageId, imagePermissions, callback) {
Comments.imageToPublicConfirmation(groupAccess, function() {
Comments.init('comments', 'comments_form');
Comments.setInvitationStatus(commentId, 1, imageId, callback);
}, imagePermissions);
},

imageToPublicConfirmation: function(groupAccess, callback, imagePermissions) {
if (typeof imagePermissions == 'undefined' || imagePermissions == null)
imagePermissions = Current.get('imagePermissions');
var allow = (imagePermissions == 0? true : (groupAccess >= 2));
if (allow) {
if (groupAccess < 2) {
// The image is public, so we need to disallow the user to alter its visibility
Current.set('imagePublicLocked', 1);
}
callback();
return false;
}
CBH.ModalDialog.__callback__ = callback;
var confirm_text = 'Статусът на снимката трябва да бъде променен на публична, за да бъде добавена избраната снимка в публично-видима група.' +
   '<br /><br />Моля, потвърдете, че искате <strong>да смените статуса на снимката на публична</strong>.'
var confirm_form = ce('div');
confirm_form.innerHTML = '<form>' +
'<p>' + confirm_text + '</p>' +
'<div style="text-align: center; margin-top: 20px;">' +
'<input type="button" value="Да" ' +
' onclick="' +
'Current.set(\'imagePublicLocked\', 1); ' +
'Current.set(\'imagePermissions\', 0); ' +
'CBH.updatePermissionsText(Current.get(\'imagePermissions\'), \'image_permissions_text\'); ' +
'CBH.ModalDialog.close(); ' +
'CBH.ModalDialog.__callback__(); ' +
'" class="submit" ' + 
' style="margin-right: 10px; width: 80px;" />' +
'<input type="button" value="Не" onclick="CBH.ModalDialog.close();" class="cancel" ' +
' style="width: 80px;" />' +
'</div>' +
'</form>';
CBH.ModalDialog.init();
CBH.ModalDialog.setTitle('Права на снимката');
CBH.ModalDialog.setHTMLElement(confirm_form);
CBH.ModalDialog.setWidth(450);
CBH.ModalDialog.setHeight(180);
CBH.ModalDialog.open();
return false;
},

buildInvitationHtml: function(data, placeholder, callback) {
if (!data || !placeholder)
return false;
if (!callback)
callback = '';
//The unary "+" here is used to convert values to numbers (empty strings, null's, etc. also)
var sess_user_id = (+Current.get('sess_user_id'));
var user_id = (+Current.get('user_id'));
//Invitation accepted status and user-can-accept-invitation status
var key = (+data.invitation_status) + '.' + ((sess_user_id > 0 && sess_user_id == user_id)? '1' : '0');
//Different texts and actions for different invitation statuses and user-can-accept-invitation status
var group = '';
if (typeof Current.social_data == 'undefined') 
	Current.social_data = {menu: 4, fb: false, twitter: false};
if (data.group_name == null) {
group = '[изтрита група]';
} else {
group = '<a href="/groups/' + data.group_id + '">' + data.group_name + '</a>';
}
var toolbox = '<div><input type="button" class="submit" onclick="Comments.acceptGroupInvitation(' + data.id + ',' + data.group_access + ',' + data.image_id + ',' + data.image_permissions + ',&quot;' + callback + '&quot;); CBH.Social.dialog({menu: Current.social_data.menu, fb: Current.social_data.fb, twitter: Current.social_data.twitter}); return false;" value="Приеми">' +
  '<input type="button" class="cancel" onclick="Comments.setInvitationStatus(' + data.id + ',2,' + data.image_id + ',&quot;' + callback + '&quot;); return false;" value="Откажи"></div>';
var html = '';
switch (key) {
case '0.1':html = 'Ти и твоята снимка сте поканени за членство в група ' + group + ': ' + toolbox + ''; break;
case '1.1':html = 'Ти си приел поканата за членство в група ' + group + '.'; break;
case '2.1':html = 'Ти си отказал поканата за членство в група ' + group + '.'; break;
case '3.1':html = 'Вече си член на група ' + group + ' и не можеш да приемеш отправената покана.'; break;
case '1.0':html = 'Авторът на снимката е приел поканата за членство в група ' + group + '.'; break;
case '2.0':html = 'Авторът на снимката е отказал поканата за членство в група ' + group + '.'; break;
default:html = 'Авторът на снимката е поканен за членство в група ' + group + '.'; break;
};
var groupInvitation = ce('div');
groupInvitation.innerHTML = '<div class="clear"></div><div class="comment-invitation">' + html + '</div>';
placeholder.appendChild(groupInvitation);
},

set: function(data) {
rm(Comments.parent, false);
var object = data.getElementsByTagName('object');
if(object[0].text){
eval('data = '+object[0].text);
}else {
eval('data = '+object[0].childNodes[1].nodeValue);
}
if(InlineComments){
InlineComments.hideInlineCommentsForced();
InlineComments.commentsAreShown=true;
InlineComments.comments = new Array();
}
for(var i=0;i<data.length;i++){
if(data[i].coords){
data[i].coords = data[i].coords.replace(/[^\d,]+/gi,"");
var buff = data[i].coords.split(",");

data[i].x1= parseInt(buff[2]);
data[i].y1= parseInt(buff[3]);
data[i].x2= parseInt(buff[0]);
data[i].y2= parseInt(buff[1]);

if(InlineComments) InlineComments.comments.push(data[i]);
}
var div = ce('div', 'comment_' + data[i].id, 'comment');

// store the original comment's text
var div_html = ce('div', 'ctext_' + data[i].id);
div_html.style.display = 'none';
div_html.innerHTML = htmlspecialchars(data[i].comment);
div.appendChild(div_html);

var img = ce('img','','');
img.src = 'http://avatars.album.bg/'+data[i].username+'.gif';

img.item={};
img.item.username=data[i].username;

if(data[i].permissions){
img.item.permissions  =data[i].permissions;
}else {

}
img.item.user_id  = data[i].user_id;
img.item.size = 60;
img.init = {
options: {
userinfo: {
user_id: data[i].user_id,
username: data[i].username,
permissions: data[i].permissions? data[i].permissions : 0,
online: data[i].online? data[i].online : 0,
banned: data[i].banned? data[i].banned : 0
},
limiter: 'frame'
}
};
img.onmouseover = Avatar.initFromEvent.bindAsEventListener(Avatar);

div.appendChild(img);

if(Current.get('sess_user_id') && ( Current.get('sess_user_id') == data[i].user_id || Current.get('sess_user_id') == Current.get('user_id') ) ) {
var buttons = ce('div','','buttons');

if(Current.get('sess_user_id') == data[i].user_id){
var edit = ce('a','','');
edit.innerHTML = 'Редактирай';
edit.onclick = this.edit.bind(this,data[i].id);
buttons.appendChild(edit);
}
if(Current.get('sess_user_id') == data[i].user_id || Current.get('sess_user_id') == Current.get('user_id')){
var del = ce('a','','');
del.innerHTML = 'Изтрий';
del.onclick = this.del.bind(this,data[i].id);
buttons.appendChild(del);
}

div.appendChild(buttons);
}
var h4 = ce('h4','','');
h4.innerHTML = data[i].username;
div.appendChild(h4);
var small = ce('small','','');
small.innerHTML = '( '+getAge(data[i].add_date)+' )';
h4.appendChild(small);

if (data[i].coords) {
//Comment's note image
var _k = 1;
var _w = data[i].x2 - data[i].x1;
var _h = data[i].y2 - data[i].y1;

var image = getImageFromCurrent();
if (_w > 400 || _h > 400) {
_fit = getImageDimsArray(240, image);
_k = min(_fit.width / _w, _fit.height / _h);
_w = Math.round(_w * _k);
_h = Math.round(_h * _k);
img_url = getImageSrc(image, 2);
} else {
img_url = getImageSrc(image, 3);
}

var imageNote = ce('span', '', '');
imageNote.innerHTML = '<span style="margin: 5px; background: url(' + img_url + ') -' + Math.round(data[i].x1 * _k) + 'px -' + Math.round(data[i].y1 * _k) + 'px no-repeat; ' + 
  'width:' + _w + 'px; height:' + _h + 'px; border: solid 1px #ddd; display: block; float: left;"></span>';
div.appendChild(imageNote);
}

//Comment's text
var p = ce('p','','');
p.innerHTML = _nl2br(data[i].comment_html);
div.appendChild(p);

//Group Invitations
if (data[i].group_id) {
Comments.buildInvitationHtml(data[i], div);
}

Comments.parent.appendChild(div);
}
if(InlineComments && InlineComments.comments.length > 0) {
InlineComments.commentsAreShown = false;
InlineComments.showInlineComments(null);
}
for(var i=0;i<Comments.form.elements.length;i++){
if(Comments.form.elements[i].name=='comment') Comments.form.elements[i].value='';
}
// Reset the comment form's styles
var textarea = $('commentArea');
if (textarea)
textarea.style.cssText = '';
// Remove the selection from the group invitation selector, if any
var gis = $('group_invitation_selector');
if (gis && gis.options && gis.options[0]) {
gis.options[0].selected = "selected";
}
},
add: function(name,value){
var hidden = ce('input','','');
hidden.type = 'hidden';
hidden.name = name;
hidden.value = value;
Comments.form.appendChild(hidden);
}
}
var Favorites = {
parent: null,
button: null,
image_id: null,
action: 'add_favorite',

init: function(id,button_id,image_id){
Favorites.parent = $(id);
Favorites.button = $(button_id);
Favorites.image_id = image_id;
},
set_action: function(action){
this.action = action;
},
submit: function(){
if(Favorites.action=='add_favorite'){
if(!confirm('Сигурен ли си че искаш да добавиш тази снимка в любими?')) return false;
}else {
if(!confirm('Сигурен ли си че искаш да изтриеш тази снимка от любими?')) return false;
}
var url = '/api.php?';
                url += '&object=images&action='+Favorites.action+'&image_id='+Favorites.image_id;
                call(url,"Favorites.set","",Favorites.parent);
},
set: function(data){
if(Favorites.action=='add_favorite'){
Favorites.button.style.backgroundImage='url(http://static.album.bg/images/image_h_menu_favorites_del.png)';
Favorites.action = 'delete_favorite';
}else{
Favorites.button.style.backgroundImage='url(http://static.album.bg/images/image_h_menu_favorites_add.png)';
Favorites.action = 'add_favorite';
}
rm(Favorites.parent,false);
var object = data.getElementsByTagName('object');

if(object[0].text){
eval('data = '+object[0].text);
}else {
eval('data = '+object[0].childNodes[1].nodeValue);
}
for(var i=0;i<data.length;i++){
var div = ce('div','','contact_very_small');
var img = ce('img','','');
img.src = 'http://avatars.album.bg/'+data[i].username+'.gif';
img.onmouseover = avatarMenu.init.bind(avatarMenu,img,data[i].user_id,data[i].username,data[i].permissions,40);
div.appendChild(img);
Favorites.parent.appendChild(div);

}
if(data.length==0) Favorites.parent.parentNode.parentNode.style.display = 'none';
else {
/*if(data.length > 12) {
Favorites.parent.style.height='100px';
Favorites.parent.style.overflow = 'hidden';
}*/
Favorites.parent.parentNode.parentNode.style.display = 'block';
}

}
};
if(!CBH) var CBH = {};
CBH.Uploader = Class.create();
CBH.Uploader.prototype = {

initialize: function(inputs,inputs_hidden,thumbs){
this.counter = 1;
this.inputs = $(inputs);
this.inputs_hidden = $(inputs_hidden);
this.thumbs = $(thumbs);
this.maxfiles = 20;
this.warned = false;
},

cptlz: function (val) {
val = val.split(' ');
var newVal = '';
if(val.length > 1){
for(var c=0; c < val.length; c++) {
newVal += val[c].substring(0,1).toUpperCase() + val[c].substring(1,val[c].length) + ' ';
}
return newVal;
}
return val;
},

rplc: function (val){
val = val.replace(/([^a-z0-9]+)+/gi," ");
val = val.replace("%20"," ");
val = val.replace(/(\s+)/g," ");
val = val.replace(/([a-z]+)([0-9]+)/gi,"$1 $2 ");
return val;
},

fixPath: function (val){
return 'file:///'+val.replace(/(\\)+/gi,"/");
},

getName: function(val){
return val.substr(val.lastIndexOf("\\")+1,val.lastIndexOf(".")-val.lastIndexOf("\\")-1);
},
getFileName: function(val){
return val.substr(val.lastIndexOf("\\")+1);
},

checkExtension: function(val){
var ext = val.substr(val.lastIndexOf(".")+1);
var re = new RegExp("(JPG|JPEG|GIF|PNG|TIFF|BMP|PNG|ZIP)");
if(!re.test(ext.toUpperCase())){
var re = new RegExp("(RAR|GZ|GZIP|BZIP2|TAR|CAB|ISO|ARJ|LZH|CHM|Z|CPIO|RPM|DEB|NSIS)");
if(re.test(ext.toUpperCase())){
alert(ext.toUpperCase()+' Архивите не се поддържат от Албум. Моля архивирай снимките си в ZIP формат за да ги качиш наведнъж!');
return false;
}
else{
alert('Позволените типове файлове са : .jpg, .jpeg, .gif, .tiff, .bmp, .png или .ZIP (архив).');
return false;
}
}
return true;
},

setUploadFile: function(event){
var el = Event.element(event);
if(!this.checkExtension(el.value)) {
Element.remove(el);
this.makeNewInput();
return false;
}

for(var i=0; i<this.inputs.childNodes.length;i++){
if(this.inputs.childNodes[i].firstChild){
if(this.inputs.childNodes[i].firstChild.value == el.value){
alert('Tози файл го има в списъка за качване. Моля избери някой друг.');
Element.remove(el);
this.makeNewInput();
return false;
}
}
}

var div = ce('div','input_div_'+this.counter,'input_file');

div.appendChild(el);

var cls = ce('a','','');
cls.href='#';
cls.title = '';
cls.innerHTML = 'изтрий';
cls.fuid = this.counter;
cls.onclick =  this.removeUploadFile.bindAsEventListener(this);
div.appendChild(cls);

// this.thumbs.appendChild(li);


this.inputs.appendChild(div);
el.onchange = null;
//this.inputs_hidden.appendChild(el);
//el.style.display = 'none';
this.makeNewInput();
},

makeNewInput:function(){
this.counter ++;
var inp = ce('input','input_'+this.counter,'');
inp.type='file';
inp.name = 'file_'+this.counter+'';
inp.onchange =this.setUploadFile.bindAsEventListener(this);
this.inputs.appendChild(inp);
if(this.inputs.childNodes.length > this.maxfiles){
if(!this.warned){
//alert('Максималният брой фаилове които можеш да качиш на веднъж е '+this.maxfiles+'.');
this.warned = true;
}
Element.remove(inp);
var span = ce('span','','');
span.innerHTML = 'Максимум '+this.maxfiles+' файла наведнъж .';
this.inputs.appendChild(span);
}

},

removeUploadFile: function(event){
var el = Event.element(event);
//Element.remove($('thumb_'+el.fuid));
Element.remove($('input_div_'+el.fuid));
//Element.remove($('input_'+el.fuid));
if(this.thumbs.childNodes.length == this.maxfiles-1){
$('input_'+this.counter).disabled = false;
}
}

};














function fileQueued(file, queuelength) {
var listingfiles = document.getElementById("SWFUploadFileListingFiles");

if(!listingfiles.getElementsByTagName("ul")[0]) {

var info = document.createElement("h4");
info.appendChild(document.createTextNode("File queue"));

listingfiles.appendChild(info);

var ul = document.createElement("ul")
listingfiles.appendChild(ul);
}

listingfiles = listingfiles.getElementsByTagName("ul")[0];

var li = document.createElement("li");
li.id = file.id;
li.className = "SWFUploadFileItem";
li.innerHTML = file.name + " <span class='progressBar' id='" + file.id + "progress'></span><a id='" + file.id + "deletebtn' class='cancelbtn' href='javascript:swfu.cancelFile(\"" + file.id + "\");'><!-- IE --></a>";

listingfiles.appendChild(li);

var queueinfo = document.getElementById("queueinfo");
queueinfo.innerHTML = queuelength + " files queued";
document.getElementById(swfu.movieName + "UploadBtn").style.display = "block";
document.getElementById("cancelqueuebtn").style.display = "block";
}

function uploadFileCancelled(file, queuelength) {
var li = document.getElementById(file.id);
li.innerHTML = file.name + " - cancelled";
li.className = "SWFUploadFileItem uploadCancelled";
var queueinfo = document.getElementById("queueinfo");
queueinfo.innerHTML = queuelength + " files queued";
}

function uploadFileStart(file, position, queuelength) {
var div = document.getElementById("queueinfo");
div.innerHTML = "Uploading file " + position + " of " + queuelength;

var li = document.getElementById(file.id);
li.className += " fileUploading";
}

function uploadProgress(file, bytesLoaded) {

var progress = document.getElementById(file.id + "progress");
var percent = Math.ceil((bytesLoaded / file.size) * 200)
progress.style.background = "#f0f0f0 url(/images/progressbar.png) no-repeat -" + (200 - percent) + "px 0";
}

function uploadError(errno) {
// SWFUpload.debug(errno);
}

function uploadFileComplete(file) {
var li = document.getElementById(file.id);
li.className = "SWFUploadFileItem uploadCompleted";
}

function cancelQueue() {
swfu.cancelQueue();
document.getElementById(swfu.movieName + "UploadBtn").style.display = "none";
document.getElementById("cancelqueuebtn").style.display = "none";
}

function uploadQueueComplete(file) {
var div = document.getElementById("queueinfo");
div.innerHTML = "All files uploaded..."
document.getElementById("cancelqueuebtn").style.display = "none";
}





if(!CBH) var CBH = {};
CBH.Voter = Class.create();
CBH.Voter.prototype = {

initialize: function(){
this.titles = new Array('Лоша','Слаба','Средна','Добра','Супер');
},
init: function(htmlElement,params){
if(this.htmlElement == $(htmlElement))return;
this.htmlElement = $(htmlElement);

if(this.htmlElement.params) this.params = this.htmlElement.params;
else this.params = params;
var kids = this._getDirectChildrenByTag(this.htmlElement,'SPAN');
this.htmlElement.onmouseout = this.reset.bindAsEventListener(this);
this.stars = this._getDirectChildrenByTag(kids[0],'DIV');
if(this.params.canVote==true){
for(var i=0;i<this.stars.length;i++){
this.stars[i].index = i+1;
this.stars[i].title = 'Гласувай';
this.stars[i].style.cursor = 'pointer';
this.stars[i].onmouseover = this.showCurrent.bindAsEventListener(this);
this.stars[i].onclick = this.vote.bindAsEventListener(this);
}
}
var offs = Position.cumulativeOffset2(this.htmlElement);
this.title = ce('div','','title');
this.title.innerHTML = this.titles[(Math.round(parseFloat(this.params.rating)-0.5)-1)]||'<small style="font-size:12px;">Няма гласове</small>';

this.htmlElement.appendChild(this.title);
this.title.style.left = offs[0]+'px';
this.title.style.top = offs[1]-this.title.offsetHeight+'px';

this.info = ce('div','','info');
var html = '<b>'+this.params.rating+'</b> / '+this.params.votes+' гласа';
if(this.params.justVoted){
html += '<div>Благодаря че гласува!</div>';
this.params.justVoted = false;
}
else if(this.params.canVote==false){
html += '<div>';
if(!Current.get('sess_user_id')) html += 'Гласувай: <a href="/login/">Вход</a>';
else if(Current.get('sess_user_id') == Current.get('user_id')) html += 'Не можеш да гласуваш за твои снимки';
else if(parseInt(Current.get('banned'))) html += 'Не можеш да гласуваш, тъй като си блокиран';
else html += 'Вече си гласувал';
html += '</div>';
}
this.info.innerHTML = html;
this.info.style.left = offs[0]+'px';
this.info.style.top = offs[1]+this.htmlElement.offsetHeight+'px';

this.htmlElement.appendChild(this.info);
Element.addClassName(this.htmlElement,'active_obj');

},
vote: function(event){
var el = Event.element(event);
var url = '/api.php?object=images&action=vote&data[image_id]='+this.params.image_id+'&data[user_id]='+this.params.user_id+'&data[rating]='+el.index;
if (this.params.group_id) {
url += '&data[group_id]=' + this.params.group_id;
}
call(url,this.success.bind(this),'','');
},

success: function(data){
this.xmlData = data;
var object = data.getElementsByTagName('object');
if(object[0].text){
eval('var result = '+object[0].text);
}else {
eval('var result = '+object[0].childNodes[1].nodeValue);
}
var params = {
image_id: result.id,
rating: result.rating,
user_id: result.user_id,
votes: result.votes,
canVote: false,
justVoted: true
};
//update other html elements
if($('image_rating'))  $('image_rating').innerHTML=result.rating;
if($('image_votes'))  $('image_votes').innerHTML=result.votes;

if(this.htmlElement){
this.htmlElement.params = params;
this.params = params;

var buff = this.htmlElement;
this.doReset(document.body);
this.init(buff);
}
floatingMessages.createMsg('Благодаря за твоя глас.');

},
    
_getDirectChildrenByTag: function(e, tagName) {
  var kids = new Array();
  var allKids = e.childNodes;
  for( var i = 0 ; i < allKids.length ; i++ )
 if ( allKids[i] && allKids[i].tagName && allKids[i].tagName == tagName )
kids.push(allKids[i]);
  return kids;
   },

load: function(){
call(this.url,this.fill.bind(this),'',this.container);
},

clear: function(){
for(var i=0;i<this.stars.length;i++){
this.stars[i].className = 'off';
}
},

doReset: function(el){
if(el != this.htmlElement && !Element.childOf(el,this.htmlElement)){
rm(this.title,true);
rm(this.info,true);
this.clear();
for(var i=0;i<this.stars.length;i++){
this.stars[i].style.cursor = '';
this.stars[i].title = '';
this.stars[i].onmouseover = function(){return false;};
this.stars[i].onclick = function(){return false;};
}
for(var i=0;i<Math.round(parseFloat(this.params.rating));i++){
this.stars[i].className = 'on';
}
Element.removeClassName(this.htmlElement,'active_obj');
this.htmlElement = null;
}
},

reset: function(event){
var el = event.relatedTarget?event.relatedTarget:event.toElement;
this.doReset(el);
},

showCurrent: function(event){
var el = Event.element(event);
this.clear();
this.title.innerHTML = this.titles[el.index-1];
for(var i=0;i<el.index;i++){
this.stars[i].className = 'hi';
}
}


};
var voter = new CBH.Voter();
if(!CBH) var CBH = {};
CBH.InlineComments = Class.create();
CBH.InlineComments.prototype = {

initialize: function(container,imageId){
this.container = $(container);
this.imageId = imageId;

this.commentsAreShown = false;
},

init: function(){
//alert('Избери част от снимката, и добави бележка.');
if(this.htmlElement){
rm(this.htmlElement,true);
this.htmlElement = null;
}
this.container.onclick = function(){return false;}
this.container.parentNode.onclick = function(){return false;}

this.offs = Position.cumulativeOffset(this.container);
this.htmlElement = ce('div','','comment_box');
$('comment_form').style.display = 'none';

var title = ce('h4','','');
title.innerHTML = 'Бележка:';
this.htmlElement.appendChild(title);
var form = ce('form','comments_form2','');
var i = ce('input','','');i.type='hidden';i.name='object';i.value='images';form.appendChild(i);
var i = ce('input','','');i.type='hidden';i.name='action';i.value='add_comment';form.appendChild(i);
var i = ce('input','','');i.type='hidden';i.name='image_id';i.value=this.imageId;form.appendChild(i);
var i = ce('input','','');i.type='hidden';i.name='data[coords]';i.value='';form.appendChild(i);
this.htmlElement.coords = i;
var i = ce('textarea','','');i.name='comment';i.rows=4;i.cols=40;form.appendChild(i);i.value='';
var i = ce('input','','');i.type='button';i.value='Отказ';i.onclick=this.addCommentHide.bindAsEventListener(this);form.appendChild(i);
var i = ce('input','','submit');i.type='button';i.value='Запази';i.onclick=this.addCommentSubmit.bindAsEventListener(this);form.appendChild(i);

this.htmlElement.appendChild(form);
$('absholder').appendChild(this.htmlElement);
this.crop = new Cropper.Img( this.container, { onDragNotify:this.addCommentDrag.bind(this),onEndCrop: this.addCommentShow.bind(this),onInitCrop:this.addCommentShow.bind(this),initWidth: 40,initHeight: 40, displayOnInit: true} );
return false;
},

addCommentDrag: function(coords,dimensions){
//if(!this.crop.attached || !this.htmlElement) return false;
if(!this.htmlElement) return false;
//floatingMessages.createMsg(coords.x1+' x '+coords.y1 ,'3',1000);
if ((this.container.offsetWidth-300-coords.x1) > 0 || this.container.offsetWidth < 300) this.htmlElement.style.left = (this.offs[0]+coords.x1) + 'px';
else this.htmlElement.style.left = (this.offs[0]+this.container.offsetWidth - 300)+'px';
this.htmlElement.style.top = this.offs[1] + coords.y2 + 10 +'px';
this.htmlElement.style.width = '300px';
},

addCommentShow: function(coords, dimensions){
//if(!this.crop.attached) return false;
//if(coords.x1==0 && coords.y1==0 && coords.x2==0 && coords.y2==0) { this.addCommentHide(); return false; }
$('comment_form').style.display = 'none';
this.htmlElement.coords.value = '(('+coords.x1+','+coords.y1+'),('+coords.x2+','+coords.y2+'))';
this.htmlElement.style.display = 'block';
},

addCommentHide: function(){
this.htmlElement.style.display = 'none';
if(this.crop){
this.crop.remove();
}
$('comment_form').style.display = 'block';
},

addCommentSubmit: function(){
Comments.init('comments','comments_form2');
Comments.submit();
this.addCommentHide();
},

showInlineComments: function(event){
if(!this.offs) this.offs = Position.cumulativeOffset(this.container);
if(this.comments && this.commentsAreShown==false){
for(var i=0;i<this.comments.length;i++){
var c = new CBH.InlineComment();
c.createElement(this.comments[i],this.offs);
}
this.commentsAreShown = true;
}
},

hideInlineComments: function(event){
var el = event.relatedTarget?event.relatedTarget:event.toElement;
if(!el || el.isComment) return;
if(!this.offs) this.offs = Position.cumulativeOffset(this.container);
this.hideInlineCommentsForced();
},

hideInlineCommentsForced: function(){
if(this.comments && this.commentsAreShown==true){
for(var i=0;i<this.comments.length;i++){
var tel = $('inline_comment_'+this.comments[i].id);
if(tel) rm(tel,true);
}
}
this.commentsAreShown = false;
}
};


if(!CBH) var CBH = {};
CBH.InlineComment = Class.create();
CBH.InlineComment.prototype = {

initialize: function(){

},

createElement: function(items,offs){
this.htmlElement = ce('a','inline_comment_'+items.id,'inline_comment');
//this.htmlElement.isComment = true;
this.htmlElement.items = items;
this.htmlElement.title = items.comment;
/*
var opacity = 50;
this.htmlElement.style.filter = "alpha(opacity:"+opacity+")";
this.htmlElement.style.KHTMLOpacity = opacity/100;
this.htmlElement.style.MozOpacity = opacity/100;
this.htmlElement.style.opacity = opacity/100;
*/
this.htmlElement.style.left = offs[0]+items.x1+'px';
this.htmlElement.style.top = offs[1]+items.y1+'px';
this.htmlElement.style.width = items.x2 - items.x1+'px';
this.htmlElement.style.height = items.y2 - items.y1+'px';
this.htmlElement.onmouseover = this.showDetails.bindAsEventListener(this);
this.htmlElement.onmouseout = this.checkHide.bindAsEventListener(this);

var border = ce('div','','border');
border.isComment = true;
this.htmlElement.appendChild(border);


// Details
this.details  = ce('div','','details');
this.details.style.top =  items.y2 - items.y1+5+'px';
this.details.style.left = '0px';
var img = ce('img','','');
img.src = 'http://avatars.album.bg/'+items.username+'.gif';
img.item={};
img.item.username  =items.username;
if(items.permissions){
img.item.permissions  =items.permissions;
}else {

}
img.item.user_id  = items.user_id;
img.item.size = 30;
//img.onmouseover = avatarMenu.initFromEvent.bindAsEventListener(avatarMenu);

this.details.appendChild(img);
var h4 = ce('h4','','');
h4.innerHTML = items.username;
this.details.appendChild(h4);
var p = ce('p','','');
p.innerHTML = items.comment
this.details.appendChild(p);
var small = ce('small','','');
//small.innerHTML = 'Коментирано на: '+items.add_date;
//this.details.appendChild(small);
this.htmlElement.appendChild(this.details);

$('absholder').appendChild(this.htmlElement);
},

showDetails: function(event){
el = Event.element(event);
if(el == this.htmlElement || Element.childOf(el,this.htmlElement)){
this.htmlElement.style.borderColor = "#D25924";
this.details.style.display = 'block';
clearTimeout(this.timer);
}
event.cancelBubble = true;
},

checkHide: function(event){
if(this.htmlElement && event){
var el = event.relatedTarget?event.relatedTarget:event.toElement;
if(el != this.htmlElement && !Element.childOf(el,this.htmlElement)){
this.timer = window.setTimeout(this.hideDetails.bind(this),200);
}
}
},

hideDetails: function(){
this.htmlElement.style.borderColor = '';
this.details.style.display = 'none';
}

};if(!CBH) var CBH = {};
CBH.Rotator = Class.create();
CBH.Rotator.prototype = {
        
        initialize: function(container){
this.container = $(container);
this.create();
this.angle = 0;
        },
        
        init: function(container){

        },
        
create: function(){
this.offs = Position.cumulativeOffset(this.container);
this.htmlElement = ce('div','','rotator');
var left = ce('а','','left');
left.onclick = this.rotate.bind(this,90);
this.htmlElement.appendChild(left);

var right = ce('а','','right');
right.onclick = this.rotate.bind(this,90);
this.htmlElement.appendChild(right);
var imageholder = ce('span','','imageholder');
this.image = ce('img','','');
this.image.align='absmiddle';
rExp = /th3\.(jpg|jpeg|gif|png|tiff|bmp)$/gi;
oldSrc = new String(this.container.src);
var newSrc = oldSrc.replace(rExp, "th2.$1");
//alert(this.image.src);
this.image.src = '/image_rotate.php?angle=0&url='+newSrc;
imageholder.appendChild(this.image);
this.htmlElement.appendChild(imageholder);
var buttons = ce('span','','buttons');
this.ok = ce('input','','submit_small');
this.ok.type='button';
this.ok.value='Запиши';
this.ok.onclick = this.submit.bind(this);
buttons.appendChild(this.ok);
var cancel = ce('input','','cancel_small');
cancel.type='button';
cancel.value='Отказ';
cancel.onclick = this.close.bind(this);
buttons.appendChild(cancel);
this.htmlElement.appendChild(buttons);
this.htmlElement.style.top = this.offs[1]+(this.container.offsetHeight/2)-100+'px';
this.htmlElement.style.left = this.offs[0]+(this.container.offsetWidth/2)-100+'px';
$('absholder').appendChild(this.htmlElement);
},

submit: function(){
var url = '/api.php?object=images&action=rotate&image_id='+Current.get('image_id')+'&angle='+this.angle;
call(url,this.checkStatus.bind(this),"","");
this.setLoading(true);
},

checkStatus: function(data){
this.success();
        var object = data.getElementsByTagName('object');
if(status_msg = object[0].getAttribute('status_msg')){
if(status_msg =='FILEPROCESS_COMPLETED') this.success();
else if(status_msg =='FILEPROCESS_COMPLETED_WITH_ERRORS') alert('ERRRRRORRRRRRRR');
else if(status_msg =='PROCESSING_FILES') window.setTimeout(this.reCheckStatus.bind(this),1000);
}else{
if(object[0].text){
eval('data = '+object[0].text);
}else {
eval('data = '+object[0].childNodes[1].nodeValue);
}
this.upload_sid = data.upload_sid;
window.setTimeout(this.reCheckStatus.bind(this),2000);
}
},

setLoading: function(status){
if(status){
this.loader = ce('div','','loader');
this.loader_bg = ce('div','','loader_bg');
$('absholder').appendChild(this.loader);
$('absholder').appendChild(this.loader_bg);

var offs = Position.cumulativeOffset(this.container);
this.loader_bg.style.left = offs[0]+'px';
this.loader_bg.style.top = offs[1]+'px';
this.loader_bg.style.width = this.container.offsetWidth+'px';
this.loader_bg.style.height = this.container.offsetHeight+'px';
this.loader_bg.style.zIndex = '999';
this.loader_bg.style.display='block';

this.loader.style.right = 'auto';
this.loader.style.left = (offs[0]+(this.container.offsetWidth/2)-50)+'px';
this.loader.style.top = (offs[1]+(this.container.offsetHeight/2)-10)+'px';
this.loader.style.zIndex = '1000';
this.loader.style.display='block';
this.loader.innerHTML = 'Завъртане..';

}else{
rm(this.loader,true);
rm(this.loader_bg,true);
}

},

reCheckStatus: function(){
var url = '/api.php?object=fileprocess&upload_sid='+this.upload_sid;
call(url,this.checkStatus.bind(this),'',"");
},

success: function(){
//alert('success');
//this.setLoading(false);
//window.location.reload();
                rExp = /(#|\?)(.*)/gi;
                var oldLocation = new String(window.location.href);
                var newLocation = oldLocation.replace(rExp, "");
window.location.href = newLocation+'?reload';
},

rotate: function(angle){
this.angle = (this.angle + angle)%360;
if(!this.angle) this.angle = 0;
this.image.src = '/image_rotate.php?angle='+this.angle+'&url='+this.container.src;
},
        
        close: function(){
        rm(this.htmlElement,true);
        }
        
};

if(!CBH) var CBH = {};
CBH.SliderBox = Class.create();
CBH.SliderBox.prototype = {
        
initialize: function(params){
this.container = $(params.container);
Element.cleanWhitespace(this.container);
Element.cleanWhitespace(this.container.childNodes[0]);


this.params = params;
this.currentPage = params.currentPage;
this.totalPages = params.totalPages;
this.scrollOffset = params.scrollOffset;
this.url = params.url;
this.direction = params.direction;
this.auto = params.autoPlay;
if(params.createItem) this.createItem = params.createItem.bind(this);
if(params.onChange) this.onChange = params.onChange.bind(this);

this.timer = null;
this.prev = $(params.prev);
this.next = $(params.next);
this.page = $(params.page);


//Attach Events
this.prev.onclick = this.processPage.bind(this,-1);
this.prev.ondblclick = this.processPage.bind(this,-1);
this.next.onclick = this.processPage.bind(this,1);
this.next.ondblclick = this.processPage.bind(this,1);


if(this.currentPage){
this.container.scrollLeft = this.currentPage*this.scrollOffset;
// SUPER STUPID PATCH FOR SAFARI
if (this.container.scrollLeft != this.currentPage*this.scrollOffset){
this.container.scrollLeft = this.currentPage*this.scrollOffset;
}
}
//this.autoPlay();
},
        
        processPage: function(pos){
                this.auto = 0;
                var targetPage = this.currentPage+pos;
                if(targetPage >= this.totalPages-1){
                        targetPage = this.totalPages-1;
// IE 6 bugs with dual class names ...
                        //Element.addClassName(this.next,'disabled');
this.next.className = 'next_disabled';
                }else if(this.totalPages!=1) this.next.className = 'next';
                if(targetPage <= 0){
                        targetPage = 0;
// IE 6 bugs with dual class names ...
                        //Element.addClassName(this.prev,'disabled');
this.prev.className = 'prev_disabled';
                }else if(this.totalPages!=1) this.prev.className = 'prev';
                if(targetPage != this.currentPage) this.gotoPage(targetPage);
return false;
        },
        
        gotoPage: function(page){
                page = parseInt(page);
                if(page > this.totalPages-1) page = this.totalPages-1;
                if(page < 0) page = 0;
                if(page == this.currentPage) return false;
                if(this.container.childNodes[0].childNodes[page].childNodes.length == 0){
                        this.call(page);
                }
                if(page>0  && this.currentPage > page && this.container.childNodes[0].childNodes[page-1].childNodes.length == 0){
                        this.call(page-1);
                }
                if(page < this.totalPages-1 && this.currentPage < page && this.container.childNodes[0].childNodes[page+1].childNodes.length == 0){
                        this.call(page+1);
                }
                window.clearTimeout(this.timer);
                if(this.direction) this.scrollWidthTo(page*this.scrollOffset);
                else this.scrollHeightTo(page*this.scrollOffset);
                this.currentPage = page;
if(this.page) this.page.innerHTML = this.currentPage+1;
                if(this.onChange) this.onChange(this.currentPage);

        },
        
        scrollWidthTo: function(pos){
                if(pos < 0 )  pos = 0;
                if(pos >= this.container.scrollWidth) pos = this.container.scrollWidth;
                var smooth = 0.1 *(pos-this.container.scrollLeft);
                if (smooth > 0) smooth = Math.ceil(smooth);
                else smooth = Math.floor(smooth);
                if(Math.abs(smooth)  < 1) {
                        this.container.scrollLeft = pos;
                        return;
                }
                this.container.scrollLeft += smooth ;
                this.timer = window.setTimeout(this.scrollWidthTo.bind(this,pos),10);
        },
        
        scrollHeightTo: function(pos){
                if(pos < 0 ) pos = 0;
                if(pos >= this.container.scrollHeight) pos = this.container.scrollHeight;
                var smooth = 0.1 *(pos-this.container.scrollTop);
                if (smooth > 0) smooth = Math.ceil(smooth);
                else smooth = Math.floor(smooth);
                if(Math.abs(smooth)  < 1) {
                        this.container.scrollTop = pos;
                        return;
                }
                this.container.scrollTop += smooth ;
                this.timer = window.setTimeout(this.scrollHeightTo.bind(this,pos),10);
        },
        
        call: function(page){
                call(this.url+'page='+page,this.fill.bind(this,page),'','');
        },
        
        fill: function(page,data){
                var object = data.getElementsByTagName('object');
                if(object[0].text){
                        eval('var result = '+object[0].text);
                }else {
                        eval('var result = '+object[0].childNodes[1].nodeValue);
                }
                rm(this.container.childNodes[0].childNodes[page]);
                for(var i=0;i<result.length;i++){i
                        var item = this.createItem(result[i]);
                        this.container.childNodes[0].childNodes[page].appendChild(item);
                }
        },
        
        autoPlay: function(){
                if(this.auto>0){
                        if(this.currentPage+1 > this.totalPages-1) this.gotoPage(0);
                        else this.gotoPage(this.currentPage+1);
                        window.setTimeout(this.autoPlay.bind(this),this.auto);
                }
        }
        
};
if(!CBH) var CBH = {};
CBH.ThumbInfo = Class.create();
CBH.ThumbInfo.prototype = {
        
        initialize: function(params){
if(params.width) this.width = params.width;
if(params.height) this.height = params.height;
        },
        
        init: function(container,params){
        if(this.container){
        window.clearTimeout(this.timer);
        if(this.container != $(container)) this.hide();
        else return false;
        }
                this.container = $(container);
                this.container.onmouseout = this.hide.bindAsEventListener(this);
                this.htmlElement = ce('div','','thumb_info');
                if(params.width) this.width = params.width;
                if(params.height) this.height = params.height;
                this.timer = window.setTimeout(this.show.bind(this),500);
        },
        
        show: function(){
        if(!this.container) return false;
        this.container.onmouseout = function(){return false;}
        var w = this.width - this.container.offsetWidth;
        var h = this.height - this.container.offsetHeight;

        offs1 = Position.cumulativeOffset2(this.container);
                offs2 = Position.realOffset(this.container);

                this.offs = new Array(offs1[0]-offs2[0],offs1[1]-offs2[1]);

        this.htmlElement.style.left = this.offs[0]+'px';
        this.htmlElement.style.top = this.offs[1]+'px';
        this.htmlElement.style.width = this.container.offsetWidth+'px';
        this.htmlElement.style.height = this.container.offsetHeight+'px';
        this.htmlElement.onmouseout = this.hide.bindAsEventListener(this);
        $('absholder').appendChild(this.htmlElement);
        this.resizeTo();
        },
        
        resizeTo: function(){
        var wDone = false;
        var hDone = false;
        if(this.width - this.htmlElement.offsetWidth > 1){
        this.htmlElement.style.width =  Math.round(this.htmlElement.offsetWidth+((this.width-this.htmlElement.offsetWidth)*0.1))+'px';
        this.htmlElement.style.left = (this.offs[0] - Math.round((this.htmlElement.offsetWidth - this.container.offsetWidth)/2))+'px';
        }else{
        this.htmlElement.style.width = this.width+'px';
        this.htmlElement.style.left = (this.offs[0]  - Math.round((this.htmlElement.offsetWidth - this.container.offsetWidth)/2))+'px';
        wDone = true;
        }
        if(this.height-this.htmlElement.offsetHeight > 1){
        this.htmlElement.style.height = Math.round(this.htmlElement.offsetHeight+((this.height-this.htmlElement.offsetHeight)*0.1))+'px';
        this.htmlElement.style.top = (this.offs[1] - Math.round((this.htmlElement.offsetHeight - this.container.offsetHeight)/2))+'px';
        }else{
        this.htmlElement.style.height = this.height+'px';
        this.htmlElement.style.top = (this.offs[1] - Math.round((this.htmlElement.offsetHeight - this.container.offsetHeight)/2))+'px';
        hDone = true;
        }
        if(!wDone || !hDone) this.timer = window.setTimeout(this.resizeTo.bind(this),10);
        else this.fill();
        },
        
        fill: function(){
this.htmlElement.className = 'thumb_info_done';
var name = ce('a','','');
name.href='#';
name.innerHTML = 'Image Name';
this.htmlElement.appendChild(name);

var img = ce('img','','');
img.src = this.container.src;
//img.style.width = '140px';
//img.style.height = '100px';
this.htmlElement.appendChild(img);

var talbum = ce('div','','');
talbum.innerHTML = 'Album: ';
var album = ce('a','','');
album.href='#';
album.innerHTML = 'Summer 2006';
talbum.appendChild(album);
this.htmlElement.appendChild(talbum);

var tuser = ce('div','','');
tuser.innerHTML = 'From: ';

var user = ce('a','','');
user.href='#';
user.innerHTML = 'cbfl';
tuser.appendChild(user);
this.htmlElement.appendChild(tuser);
        },
        
        hide: function(event){
        if(this.htmlElement && event){
var el = event.relatedTarget?event.relatedTarget:event.toElement;
if(el != this.htmlElement && !Element.childOf(el,this.htmlElement)){
window.clearTimeout(this.timer);
rm(this.htmlElement,true);
this.container.onmouseout = function(){return false;}
this.container = null;
}
}
}
        
};

if(!CBH) var CBH = {};
CBH.Communication = Class.create();
CBH.Communication.prototype = {

initialize: function(params){
this.contactBanned = false;
this.menu = $(params.menu);
this.list = $(params.list);
this.messages = $(params.messages);
this.form = $(params.form);
this.form_banned = $(params.form_banned);
this.info = $(params.info);
this.imageCache = new Array();
this.update(getCookie('comM'),getCookie('comL'),true);
},

buildHtml: function(currentMenu, el, placeholder) {
if (!placeholder || !el)
return false;
switch (currentMenu) {
case 1:
case 3:
case 4:
var span_wrap = ce('span','','');
span_wrap.style.float = 'right';
//span_wrap.setStyle({float: 'right'});
var b= ce('a','','');
b.href='/'+el.items.username+'/';
b.innerHTML='Страница';
span_wrap.appendChild(b);
var span = ce('span','','delete');
span.innerHTML = 'Изтрий разговора';
span.style.clear = 'both';
//span.setStyle({clear: 'both'});
span_wrap.appendChild(span);
placeholder.appendChild(span_wrap);
span.onclick=this.remove.bind(this, el.items.id);
var img = ce('img','','');
img.src = 'http://avatars.album.bg/'+el.items.username+'.gif';
placeholder.appendChild(img);
var h3 = ce('h3','','title');
h3.innerHTML=el.items.username;
placeholder.appendChild(h3);
if (currentMenu == '1') {
}
break;
case 5:
case 2:
var b= ce('a','','');
b.href='/'+Current.get('sess_username')+'/images/'+el.items.id+'/';
b.innerHTML='Отвори снимката';
placeholder.appendChild(b);
var img = ce('img','','');
img.src = getImageSrc(el.items,1);
placeholder.appendChild(img);
var h3 = ce('h3','','title');
h3.innerHTML=el.items.title;
placeholder.appendChild(h3);
var s = ce('span','','');
//s.innerHTML='Видяна: <strong>'+el.items.views+'</strong> пъти<br />Коментари: <strong>'+el.items.comments+'</strong><br/> Рейтинг: <strong>'+el.items.rating+'</strong> oт '+el.items.votes+' гласа';
s.innerHTML='Коментари: <strong>'+el.items.comments+'</strong><br/> Рейтинг: <strong>'+el.items.rating+'</strong> oт '+el.items.votes+' гласа';
placeholder.appendChild(s);
break;
}
},

prepare: function(menu,list){
ret = {};
if(this.currentMenu!=menu){
if(this.currentMenu){Element.removeClassName($('communication_menu_'+this.currentMenu),'active_object')}
try{Element.addClassName($('communication_menu_'+menu),'active_object');}catch (e){}
}
if(this.currentList!=list){
if(this.currentList){Element.removeClassName($('communication_list_'+this.currentList),'active_object');}
}
if(list){
for (var i = 1; i <= 5; i++)
$('empty_panel_' + i).style.display = 'none';
var el = $('communication_list_'+list);
if(el){
Element.addClassName(el,'active_object');
if(this.info.current != menu+'_'+list){
rm(this.info,false);
this.info.current = menu+'_'+list;
this.buildHtml(menu, el, this.info);
}
this.info.style.display = 'block';
if (!this.contactBanned) {
this.form.style.display = 'block';
this.form_banned.style.display = 'none';
} else {
this.form.style.display = 'none';
this.form_banned.style.display = 'block';
}
this.messages.style.display = 'block';
}else{
this.info.style.display = 'none';
this.form.style.display = 'none';
this.form_banned.style.display = 'none';
this.messages.style.display = 'none';
}
ret.loader = 'communication_messages';

}else{
this.info.style.display = 'none';
this.form.style.display = 'none';
this.form_banned.style.display = 'none';
this.messages.style.display = 'none';
ret.loader = 'communication_list';
}
return ret;
},

update: function(menu,list,auto){
if(this.processing) return;
window.clearTimeout(this.timer);
if(!menu) menu=1;
var p = this.prepare(menu,list);
var message='';
cc = $('communication_'+menu+'_messages_'+list);
if(cc) message=cc.last || '';
if(auto) p.loader ='';
if(!this.currentMenu) p.loader='communication';
call('/api.php?object=communication&menu='+menu+'&list='+list+'&message='+message,this.redraw.bind(this),'',p.loader);
this.processing = true;
        },

post: function(){
window.clearTimeout(this.timer);
var mm = $('communication_form_message');
var message='';
if(this.currentMenu == 1)
cc = $('communication_'+this.currentMenu+'_messages_'+this.currentList);if(cc) message=cc.last||'';
call('/api.php?object=communication&action=add&menu='+this.currentMenu+'&list='+this.currentList+'&message='+message+'&m='+encodeURIComponent(mm.value),this.redraw.bind(this),'','');
mm.value = '';
},

remove: function(list, event) {
event.stopPropagation();
event.cancelBubble = true;
var current = this;
CBH.Dialogs.confirm({
message: 'Сигурен ли си, че искаш да изтриеш този разговор?',
ok_callback: function() { 
window.clearTimeout(current.timer);
call('/api.php?object=communication&action=remove&menu='+current.currentMenu+'&list='+list+'&message=',current.update.bind(current, getCookie('comM'),'',true),'','');
}
});
},

redraw: function(data){
var object = data.getElementsByTagName('object');
if(object[0].text){
eval('var result = '+object[0].text);
}else {
eval('var result = '+object[0].childNodes[1].nodeValue);
}
data = result;
data.currentMenu = parseInt(data.currentMenu);
this.totalMenu = 0;
for(var i=0;i<data.menu.length;i++){
var el = $('communication_menu_'+data.menu[i].id);
if(el){
//Element.cleanWhitespace(el);
//Element.cleanWhitespace(el.childNodes[0]);
el.childNodes[0].childNodes[0].innerHTML = data.menu[i].messages;
Element.removeClassName(el,'active_object');
if(data.currentMenu == data.menu[i].id) Element.addClassName(el,'active_object');
el.onclick = this.update.bind(this,data.menu[i].id,'',false);
}
else{
var el = ce('div','communication_menu_'+data.menu[i].id,'');
el.items = data.menu[i];
el.onclick = this.update.bind(this,data.menu[i].id,'',false);
var a = ce('a','','');
var info = ce('em','','');info.innerHTML = data.menu[i].messages;a.appendChild(info);
var s = ce('strong','','');s.innerHTML = data.menu[i].title;a.appendChild(s);
el.appendChild(a);
this.menu.appendChild(el);
}
if (!data.menu[i].not_total_messages) {
this.totalMenu += parseInt(data.menu[i].messages)||0;
}
if(!this.imageCache[data.menu[i].id]) this.imageCache[data.menu[i].id] = new Array();
}

//[cbfl] tova da se opravi !
var tt = $('total_new_messages');
if(tt){
if(this.totalMenu>0) tt.style.color = '#D82200';
else tt.style.color = '#1A3D97';
tt.innerHTML = '('+(this.totalMenu<99?this.totalMenu:'99+')+')';
}

this.contactBanned = false;

rm(this.list,false);
if (data.list) {
for (var i = 1; i <= data.menu.length; i++)
$('empty_list_' + i).style.display = 'none';
this.totalList = 0;
for (var i=0;i<data.list.length;i++) {
this.totalList+=parseInt(data.list[i].messages);
var el = ce('div','communication_list_'+data.list[i].id,'');
el.items = data.list[i];
if (data.currentList == data.list[i].id) {
this.contactBanned = data.list[i].contact_banned != 0 && !!(data.list[i].contact_banned);
Element.addClassName(el,'active_object');
if (this.info.current != data.currentMenu + '_' + data.currentList) {
rm(this.info, false);
this.info.current = data.currentMenu + '_' + data.currentList;
this.buildHtml(data.currentMenu, el, this.info);
}
}
el.onclick = this.update.bind(this,data.currentMenu,data.list[i].id,false);
switch(data.currentMenu){
case 1:
var a = ce('a','','');
if(parseInt(data.list[i].messages)>0){ var info = ce('em','','');info.innerHTML = data.list[i].messages;a.appendChild(info);}
/*if(Element.hasClassName(el, 'active_object')) { var s = ce('em','','');s.innerHTML = 'X';s.style.margin = '0';a.appendChild(s); s.onclick=this.remove.bind(this, data.list[i].id);}*/
if(this.imageCache[data.currentMenu][data.list[i].id]){
a.appendChild(this.imageCache[data.currentMenu][data.list[i].id]);
}
else{
var img = ce('img','','');img.src = 'http://avatars.album.bg/'+data.list[i].username+'.gif';a.appendChild(img);
this.imageCache[data.currentMenu][data.list[i].id] = img;
}
var s = ce('strong','','');s.innerHTML = data.list[i].username; if (data.list[i].online == 't') s.innerHTML += ' <span class="user-online-small"></span>';a.appendChild(s);
var s = ce('small','','');s.innerHTML = new String(data.list[i].date).replace(/\.(.*)$/, '');;a.appendChild(s);
el.appendChild(a);
break;
case 2:
var a = ce('a','','');
if(parseInt(data.list[i].messages)>0){var info = ce('em','','');info.innerHTML = data.list[i].messages;a.appendChild(info);}
if(this.imageCache[data.currentMenu][data.list[i].id]){
a.appendChild(this.imageCache[data.currentMenu][data.list[i].id]);
}
else{
var img = ce('img','','');img.src = img.src = getImageSrc(data.list[i],1);a.appendChild(img);
this.imageCache[data.currentMenu][data.list[i].id] = img;
}
var s = ce('strong','','');s.innerHTML = data.list[i].title;a.appendChild(s);
var s = ce('small','','');s.innerHTML = data.list[i].date;a.appendChild(s);
el.appendChild(a);
break;
case 3:
//dd
break;
case 4:
var a = ce('a','','');
if(parseInt(data.list[i].messages)>0){ var info = ce('em','','');info.innerHTML = data.list[i].messages;a.appendChild(info);}
if(this.imageCache[data.currentMenu][data.list[i].id]){
a.appendChild(this.imageCache[data.currentMenu][data.list[i].id]);
}
else{
var img = ce('img','','');img.src = 'http://avatars.album.bg/'+data.list[i].username+'.gif';a.appendChild(img);
this.imageCache[data.currentMenu][data.list[i].id] = img;
}
var s = ce('strong','','');s.innerHTML = data.list[i].username;a.appendChild(s);
var s = ce('small','','');s.innerHTML= (data.list[i].fname||'')+' '+(data.list[i].lname||'');a.appendChild(s);
el.appendChild(a);
break;
case 5:
//Invitations
var a = ce('a','','');
if(parseInt(data.list[i].messages)>0){var info = ce('em','','');info.innerHTML = data.list[i].messages;a.appendChild(info);}
if(this.imageCache[data.currentMenu][data.list[i].id]){
a.appendChild(this.imageCache[data.currentMenu][data.list[i].id]);
}
else{
var img = ce('img','','');img.src = img.src = getImageSrc(data.list[i],1);a.appendChild(img);
this.imageCache[data.currentMenu][data.list[i].id] = img;
}
var s = ce('strong','','');s.innerHTML = data.list[i].title;a.appendChild(s);
var s = ce('small','','');s.innerHTML = data.list[i].date;a.appendChild(s);
el.appendChild(a);
break;
}
this.list.appendChild(el);
}
/*
//More
//alert(this.totalList+''+data.menu[data.currentMenu].messages);
if(this.totalList<=data.menu[data.currentMenu].messages){
var el = ce('a','','');el.innerHTML='More>>';this.list.appendChild(el);
}
*/
this.info.style.display = 'block';
if (this.contactBanned) {
this.form.style.display = 'none';
this.form_banned.style.display = 'block';
} else {
this.form.style.display = (data.currentMenu != 5? 'block' : 'none');
this.form_banned.style.display = 'none';
}
this.messages.style.display = 'block';
}else{
for (var i = 1; i <= data.menu.length; i++) {
$('empty_list_' + i).style.display = (data.currentMenu == i)? 'block' : 'none';
}
}

if(this.currentList && ((this.currentList != data.currentList) || (this.currentMenu != data.currentMenu))){
$('communication_'+this.currentMenu+'_messages_'+this.currentList).style.display='none';
}
if(data.currentList){
var cc = $('communication_'+data.currentMenu+'_messages_'+data.currentList);
if(!cc){
var cc = ce('div','communication_'+data.currentMenu+'_messages_'+data.currentList,'');
cc.lastUsername = '';
this.messages.appendChild(cc);
}else cc.style.display='block';
if (data.currentMenu == 5) {
//Remove all children from cc
while (cc.firstChild) {
  cc.removeChild(cc.firstChild);
}
}
if(data.messages){
for(var i=data.messages.length-1;i>=0;i--){
switch(data.currentMenu){
case 1:
case 3:
case 4:
var cn = '';
if(cc.lastUsername == data.messages[i].username) cn = 'follow';
var m = ce('div','',cn);
var t = ce('small','','');t.innerHTML = new String(data.messages[i].add_date).replace(/\.(.*)$/, '');m.appendChild(t);
var t = ce('h5','','');t.innerHTML = data.messages[i].username+":";m.appendChild(t);
var t = ce('p','','');t.innerHTML = _nl2br(data.messages[i].message);m.appendChild(t);
cc.appendChild(m);
cc.lastUsername = data.messages[i].username;
break;
case 2:
//Comments
var m = ce('div','',cn);
if(cc.lastUsername == data.messages[i].username) m.className = 'follow';
else{
var a = ce('a','','');a.href='/'+data.messages[i].username+'/';
var img = ce('img','','');img.src = 'http://avatars.album.bg/'+data.messages[i].username+'.gif';a.appendChild(img);m.appendChild(a);
}
var t = ce('small','','');t.innerHTML = new String(data.messages[i].add_date).replace(/\.(.*)$/, '');m.appendChild(t);
var a = ce('a','','');a.href='/'+data.messages[i].username+'/';
var t = ce('h5','','');t.innerHTML = data.messages[i].username+":";a.appendChild(t);m.appendChild(a);
var t = ce('p','','');t.innerHTML = _nl2br(data.messages[i].message);m.appendChild(t);
cc.appendChild(m);
cc.lastUsername = data.messages[i].username;
break;
case 5:
//Invitations
var m = ce('div','',cn);
if(cc.lastUsername == data.messages[i].username) m.className = 'follow';
else{
var a = ce('a','','');a.href='/'+data.messages[i].username+'/';
var img = ce('img','','');img.src = 'http://avatars.album.bg/'+data.messages[i].username+'.gif';a.appendChild(img);m.appendChild(a);
}
var t = ce('small','','');t.innerHTML = new String(data.messages[i].add_date).replace(/\.(.*)$/, '');m.appendChild(t);
var a = ce('a','','');a.href='/'+data.messages[i].username+'/';
var t = ce('h5','','');t.innerHTML = data.messages[i].username+":";a.appendChild(t);m.appendChild(a);
var t = ce('p','','');t.innerHTML = _nl2br(data.messages[i].message);m.appendChild(t);

//Group Invitations
if (data.messages[i].group_id) {
//Again, an ugly hack: we need the class Communication's instance
Comments.buildInvitationHtml(data.messages[i], m, "__global_communication__.set");
}

cc.appendChild(m);
cc.lastUsername = data.messages[i].username;
break;
}
}
cc.last = data.messages[0].id;
if(data.messages.length>0) this.messages.scrollTop = this.messages.scrollHeight;
}
}else{
this.info.style.display = 'none';
this.form.style.display = 'none';
this.form_banned.style.display = 'none';

for (var i = 1; i <= data.menu.length; i++) {
if (data.currentMenu == i) {
if (data.list)
$('empty_panel_' + i).style.display = 'block';
} else {
$('empty_panel_' + i).style.display = 'none';
}
}
}
var formHidden = (data.currentMenu == 5);
if (this.messages) {
//TODO: get these sizes more smartly
this.messages.style.height = (formHidden? 346 : 296) + 'px';
}

this.currentMenu = data.currentMenu;
this.currentList = data.currentList;
document.cookie = "comM="+data.currentMenu+"; path=/communication/";
document.cookie = "comL="+data.currentList+"; path=/communication/";

window.clearTimeout(this.timer);
switch(data.currentMenu){
case 1: var timer=5000;break;
case 2: var timer=15000;break;
case 3: var timer=15000;break;
case 4: var timer=30000;break;
case 5: var timer=15000;break;
}
if(!timer) timer = 15000;
this.timer = window.setTimeout(this.update.bind(this,data.currentMenu,data.currentList,true),timer);
this.processing = false;
},

set: function() {
this.update(getCookie('comM'), getCookie('comL'), false);
}
};
CBH.AMenu = Class.create();
Object.extend(CBH.AMenu.prototype,CBH.Idea.prototype);
Object.extend(CBH.AMenu.prototype, {

fill: function(){
this.htmlElement.style.border = 'none';
var HTML = "";
if(this.options.inner){
var inner = $(this.options.inner);
if(inner) HTML = inner.innerHTML;
}
/*
this.htmlElement.innerHTML = "<div class='amenu_done'><a class='close' onClick='AMenu.forceHide();return false;'></a>"+
"<h3>"+this.options.title+"</h3><div>"+HTML+"<em style='display:block;clear:both'></em></div></div>";
*/
this.htmlElement.innerHTML = "<div class='content amenu'><div class='area'>"+HTML+"<em style='display:block;clear:both'></em></div></div>";
//this.htmlElement.innerHTML = "<div class='amenu_done'><div>"+HTML+"<em style='display:block;clear:both'></em><div></div>";

this.htmlElement.style.padding = '0px 5px 5px 0px';
this.htmlElement.style.width = this.htmlElement.childNodes[0].offsetWidth+'px';
this.htmlElement.style.height = this.htmlElement.childNodes[0].offsetHeight+'px';
this.htmlElement.style.background = 'transparent url(http://static.album.bg/images/shadow.png)';
this.htmlElement.style.backgroundPosition = 'bottom right';
}
});
var AMenu = new CBH.AMenu({delay: 0,width:174,height:100});
/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in swfobject){swfobject[q]=null}swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();if(!CBH) var CBH = {};
CBH.Slider = Class.create();

CBH.Slider.prototype = {
  initialize: function(handle, track, options) {
/*
    *  axis: (horizontal or vertical)
    * increment:
    * step:
    * alignX – will move the handle so that it aligns properly on the track. This will move it x pixels on the x-axis.
    * alignY – will move the handle so that it aligns properly on the track. This will move it x pixels on the y-axis.
    * disabled – will set the slider’s state to being ‘locked’ and thus won’t respond to input.
    * maximum:
    * minimum:
    * sliderValue:
    * handleImage:
    * handleDisabled:
    * values: [10, 20, 30, 40];
    * onSlide:
    * onChange:
*/
    var slider = this;

    if(handle instanceof Array) {
      this.handles = handle.collect( function(e) { return $(e) });
    } else {
      this.handles = [$(handle)];
    }
//cbfl
 this.handles.each( function(h){
 h.style.display='block';
 });

    this.track   = $(track);
    this.options = options || {};

    this.axis      = this.options.axis || 'horizontal';
    this.increment = this.options.increment || 1;
    this.step      = parseInt(this.options.step || '1');
    this.range     = this.options.range || $R(0,1);

    this.value     = 0; // assure backwards compat
    this.values    = this.handles.map( function() { return 0 });
    this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
    this.options.startSpan = $(this.options.startSpan || null);
    this.options.endSpan   = $(this.options.endSpan || null);

    this.restricted = this.options.restricted || false;

    this.maximum   = this.options.maximum || this.range.end;
    this.minimum   = this.options.minimum || this.range.start;

    // Will be used to align the handle onto the track, if necessary
    this.alignX = parseInt(this.options.alignX || '0');
    this.alignY = parseInt(this.options.alignY || '0');

    this.trackLength = this.maximumOffset() - this.minimumOffset();
    this.handleLength = this.isVertical() ? this.handles[0].offsetHeight : this.handles[0].offsetWidth;

    this.active   = false;
    this.dragging = false;
    this.disabled = false;

    if(this.options.disabled) this.setDisabled();

    // Allowed values array
    this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
    if(this.allowedValues) {
      this.minimum = this.allowedValues.min();
      this.maximum = this.allowedValues.max();
    }

    this.eventMouseDown = this.startDrag.bindAsEventListener(this);
    this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
    this.eventMouseMove = this.update.bindAsEventListener(this);

    // Initialize handles in reverse (make sure first handle is active)
    this.handles.each( function(h,i) {
      i = slider.handles.length-1-i;
      slider.setValue(parseFloat(
        (slider.options.sliderValue instanceof Array ?
          slider.options.sliderValue[i] : slider.options.sliderValue) ||
         slider.range.start), i);
      Element.makePositioned(h); // fix IE
      Event.observe(h, "mousedown", slider.eventMouseDown);
    });

    Event.observe(this.track, "mousedown", this.eventMouseDown);
    Event.observe(document, "mouseup", this.eventMouseUp);
    Event.observe(document, "mousemove", this.eventMouseMove);

    this.initialized = true;
  },
  dispose: function() {
    var slider = this;
    Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
    Event.stopObserving(document, "mouseup", this.eventMouseUp);
    Event.stopObserving(document, "mousemove", this.eventMouseMove);
    this.handles.each( function(h) {
      Event.stopObserving(h, "mousedown", slider.eventMouseDown);
    });
  },
  setDisabled: function(){
    this.disabled = true;
  },
  setEnabled: function(){
    this.disabled = false;
  },
  getNearestValue: function(value){
    if(this.allowedValues){
      if(value >= this.allowedValues.max()) return(this.allowedValues.max());
      if(value <= this.allowedValues.min()) return(this.allowedValues.min());

      var offset = Math.abs(this.allowedValues[0] - value);
      var newValue = this.allowedValues[0];
      this.allowedValues.each( function(v) {
        var currentOffset = Math.abs(v - value);
        if(currentOffset <= offset){
          newValue = v;
          offset = currentOffset;
        }
      });
      return newValue;
    }
    if(value > this.range.end) return this.range.end;
    if(value < this.range.start) return this.range.start;
    return value;
  },
  setValue: function(sliderValue, handleIdx){
    if(!this.active) {
      this.activeHandle    = this.handles[handleIdx];
      this.activeHandleIdx = handleIdx;
      this.updateStyles();
    }
    handleIdx = handleIdx || this.activeHandleIdx || 0;
    if(this.initialized && this.restricted) {
      if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
        sliderValue = this.values[handleIdx-1];
      if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
        sliderValue = this.values[handleIdx+1];
    }
    sliderValue = this.getNearestValue(sliderValue);
    this.values[handleIdx] = sliderValue;
    this.value = this.values[0]; // assure backwards compat

    this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
      this.translateToPx(sliderValue);

    this.drawSpans();
    if(!this.dragging || !this.event) this.updateFinished();
  },
  setValueBy: function(delta, handleIdx) {
    this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
      handleIdx || this.activeHandleIdx || 0);
  },
  translateToPx: function(value) {
    return Math.round(
      ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
      (value - this.range.start)) + "px";
  },
  translateToValue: function(offset) {
    return ((offset/(this.trackLength-this.handleLength) *
      (this.range.end-this.range.start)) + this.range.start);
  },
  getRange: function(range) {
    var v = this.values.sortBy(Prototype.K);
    range = range || 0;
    return $R(v[range],v[range+1]);
  },
  minimumOffset: function(){
    return(this.isVertical() ? this.alignY : this.alignX);
  },
  maximumOffset: function(){
    return(this.isVertical() ?
      this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX);
  },
  isVertical:  function(){
    return (this.axis == 'vertical');
  },
  drawSpans: function() {
    var slider = this;
    if(this.spans)
      $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
    if(this.options.startSpan)
      this.setSpan(this.options.startSpan,
        $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
    if(this.options.endSpan)
      this.setSpan(this.options.endSpan,
        $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
  },
  setSpan: function(span, range) {
    if(this.isVertical()) {
      span.style.top = this.translateToPx(range.start);
      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
    } else {
      span.style.left = this.translateToPx(range.start);
      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
    }
  },
  updateStyles: function() {
    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
    Element.addClassName(this.activeHandle, 'selected');
  },
  startDrag: function(event) {
    if(Event.isLeftClick(event)) {
      if(!this.disabled){
        this.active = true;

        var handle = Event.element(event);
        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
        if(handle==this.track) {
          var offsets  = Position.cumulativeOffset(this.track);
          this.event = event;
          this.setValue(this.translateToValue(
           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
          ));
          var offsets  = Position.cumulativeOffset(this.activeHandle);
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        } else {
          // find the handle (prevents issues with Safari)
          while((this.handles.indexOf(handle) == -1) && handle.parentNode)
            handle = handle.parentNode;

          this.activeHandle    = handle;
          this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
          this.updateStyles();

          var offsets  = Position.cumulativeOffset(this.activeHandle);
          this.offsetX = (pointer[0] - offsets[0]);
          this.offsetY = (pointer[1] - offsets[1]);
        }
      }
      Event.stop(event);
    }
  },
  update: function(event) {
   if(this.active) {
      if(!this.dragging) this.dragging = true;
      this.draw(event);
      // fix AppleWebKit rendering
      if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
      Event.stop(event);
   }
  },
  draw: function(event) {
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    var offsets = Position.cumulativeOffset(this.track);
    pointer[0] -= this.offsetX + offsets[0];
    pointer[1] -= this.offsetY + offsets[1];
    this.event = event;
    this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
    if(this.initialized && this.options.onSlide)
      this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
  },
  endDrag: function(event) {
    if(this.active && this.dragging) {
      this.finishDrag(event, true);
      Event.stop(event);
    }
    this.active = false;
    this.dragging = false;
  },
  finishDrag: function(event, success) {
    this.active = false;
    this.dragging = false;
    this.updateFinished();
  },
  updateFinished: function() {
    if(this.initialized && this.options.onChange)
      this.options.onChange(this.values.length>1 ? this.values : this.value, this);
    this.event = null;
  }
};if(!CBH) var CBH = {};
CBH.SearchForm = Class.create();
CBH.SearchForm.prototype = {

initialize: function(container,inpElement,pickTypeElement,optElement,submitButton){

this.inpElement = $(inpElement);
this.pickTypeElement = $(pickTypeElement);
this.optElement = $(optElement);
this.container = $(container);
this.submitButton = $(submitButton);

Event.observe(this.submitButton,'click',this.submit.bind(this));

//this.inpElement.onfocus = this.show.bindAsEventListener(this);
this.pickTypeElement.onclick = this.show.bindAsEventListener(this);

this.observers = {};
this.observers.hide = this.checkHide.bindAsEventListener(this);

Event.observe(this.inpElement,'focus',this.inputFocus.bind(this));
Event.observe(this.inpElement,'blur',this.inputBlur.bind(this));

var temp = this.optElement.descendants();
for(var i=0;i<temp.length;i++){
if(temp[i].tagName=='INPUT') {
if(temp[i].checked){
this.pickType(temp[i]);
}
Event.observe(temp[i],'click',this.pickTypeClick.bind(this));
}
}
this.inputBlur(null);
Event.observe(document,"mouseup",this.observers.hide);
},

show: function(){
if(this.optElement) this.optElement.style.display = 'block';
},

hide: function(event){
if(this.optElement) this.optElement.style.display = 'none';
},

checkHide: function (event){
var el =Event.element(event);
if(el && el != this.container && !Element.childOf(el,this.container)){
this.hide();
return;
}
},
inputFocus: function (event){


if(this.inpElement.value==this.inputHintValue){
this.inpElement.value='';
}
this.inpElement.style.color="#000000";

},
inputBlur: function (event){

if(!this.inpElement.value){
this.inpElement.style.color="#DDDDDD";
this.inpElement.value=this.inputHintValue;
}
},

pickTypeClick: function(event){
if(this.inpElement.value==this.inputHintValue){
this.inpElement.value='';

}
//this.inpElement.style.color="#00000";
this.pickType(Event.element(event));
this.inpElement.focus();
this.hide();
},
pickType: function(elem){
var temp = this.pickTypeElement.descendants();
for(var i=0;i<temp.length;i++){
if(temp[i].tagName=='IMG') {
temp[i].style.backgroundPosition='0px '+(39-13*(elem.value-1))+'px';
if(elem.value == 3){
//alert(Current.get('username'));
temp[i].src='http://avatars.album.bg/'+Current.get('username')+'.gif';
}else {
temp[i].src='http://static.album.bg/images/blank.gif';
}

if(elem.value==3){
this.inputHintValue='Търси в '+Current.get('username');
}else if(elem.value==2){
this.inputHintValue='Търси в автори';
}else{
this.inputHintValue='Търси във всички снимки';
}

}
}
},
submit: function(event){
if(this.inpElement.value==this.inputHintValue){
this.inpElement.value='';
return false;
}
}

}
var sf;
Event.onDOMReady(function(){
sf = new CBH.SearchForm('sForm','sInput','sPickType','sOptions','sButton');
});var fileLoadingImage = "http://static.album.bg/images/loading.gif";
var fileBottomNavCloseImage = "http://static.album.bg/images/closelabel.gif";

var resizeSpeed = 9;// controls the speed of the image resizing (1=slowest and 10=fastest)

var borderSize = 10;//if you adjust the padding in the CSS, you will need to update this variable

// -----------------------------------------------------------------------------------

//
//Global Variables
//
var imageArray = new Array;
var activeImage;

if(resizeSpeed > 10){ resizeSpeed = 10;}
if(resizeSpeed < 1){ resizeSpeed = 1;}
resizeDuration = (11 - resizeSpeed) * 0.15;

// -----------------------------------------------------------------------------------

//
//Additional methods for Element added by SU, Couloir
//- further additions by Lokesh Dhakar (huddletogether.com)
//
Object.extend(Element, {
getWidth: function(element) {
   element = $(element);
   return element.offsetWidth;
},
setWidth: function(element,w) {
   element = $(element);
    element.style.width = w +"px";
},
setHeight: function(element,h) {
   element = $(element);
    element.style.height = h +"px";
},
setTop: function(element,t) {
   element = $(element);
    element.style.top = t +"px";
},
setSrc: function(element,src) {
    element = $(element);
    element.src = src;
},
setHref: function(element,href) {
    element = $(element);
    element.href = href;
},
setInnerHTML: function(element,content) {
element = $(element);
element.innerHTML = content;
}
});

// -----------------------------------------------------------------------------------

//
//Extending built-in Array object
//- array.removeDuplicates()
//- array.empty()
//
Array.prototype.removeDuplicates = function () {
for(i = 1; i < this.length; i++){
if(this[i][0] == this[i-1][0]){
this.splice(i,1);
}
}
}

// -----------------------------------------------------------------------------------

Array.prototype.empty = function () {
for(i = 0; i <= this.length; i++){
this.shift();
}
}

// -----------------------------------------------------------------------------------

//
//Lightbox Class Declaration
//- initialize()
//- start()
//- changeImage()
//- resizeImageContainer()
//- showImage()
//- updateDetails()
//- updateNav()
//- enableKeyboardNav()
//- disableKeyboardNav()
//- keyboardNavAction()
//- preloadNeighborImages()
//- end()
//
//Structuring of code inspired by Scott Upton (http://www.uptonic.com/)
//
var Lightbox = Class.create();

Lightbox.prototype = {

// initialize()
// Constructor runs on completion of the DOM loading. Loops through anchor tags looking for
// 'lightbox' references and applies onclick events to appropriate links. The 2nd section of
// the function inserts html at the bottom of the page which is used to display the shadow
// overlay and the image container.
//
initialize: function() {
if (!document.getElementsByTagName){ return; }
var anchors = document.getElementsByTagName('a');

// loop through all anchor tags
for (var i=0; i<anchors.length; i++){
var anchor = anchors[i];

var relAttribute = String(anchor.getAttribute('rel'));

// use the string.match() method to catch 'lightbox' references in the rel attribute
if (anchor.getAttribute('href') && (relAttribute.toLowerCase().match('lightbox'))){
anchor.onclick = function () {myLightbox.start(this); return false;}
}
}

// The rest of this code inserts html at the bottom of the page that looks similar to this:
//
//<div id="overlay"></div>
//<div id="lightbox">
//<div id="outerImageContainer">
//<div id="imageContainer">
//<img id="lightboxImage">
//<div style="" id="hoverNav">
//<a href="#" id="prevLink"></a>
//<a href="#" id="nextLink"></a>
//</div>
//<div id="loading">
//<a href="#" id="loadingLink">
//<img src="images/loading.gif">
//</a>
//</div>
//</div>
//</div>
//<div id="imageDataContainer">
//<div id="imageData">
//<div id="imageDetails">
//<span id="caption"></span>
//<span id="numberDisplay"></span>
//</div>
//<div id="bottomNav">
//<a href="#" id="bottomNavClose">
//<img src="images/close.gif">
//</a>
//</div>
//</div>
//</div>
//</div>


var objBody = document.getElementsByTagName("body").item(0);

var objOverlay = document.createElement("div");
objOverlay.setAttribute('id','overlay');
objOverlay.style.display = 'none';
objOverlay.onclick = function() { myLightbox.end(); return false; }
objBody.appendChild(objOverlay);

var objLightbox = document.createElement("div");
objLightbox.setAttribute('id','lightbox');
objLightbox.style.display = 'none';
objBody.appendChild(objLightbox);

var objOuterImageContainer = document.createElement("div");
objOuterImageContainer.setAttribute('id','outerImageContainer');
objLightbox.appendChild(objOuterImageContainer);

var objImageContainer = document.createElement("div");
objImageContainer.setAttribute('id','imageContainer');
objOuterImageContainer.appendChild(objImageContainer);

var objLightboxImage = document.createElement("img");
objLightboxImage.setAttribute('id','lightboxImage');
objImageContainer.appendChild(objLightboxImage);

var objHoverNav = document.createElement("div");
objHoverNav.setAttribute('id','hoverNav');
objImageContainer.appendChild(objHoverNav);

var objPrevLink = document.createElement("a");
objPrevLink.setAttribute('id','prevLink');
objPrevLink.setAttribute('href','#');
objHoverNav.appendChild(objPrevLink);

var objNextLink = document.createElement("a");
objNextLink.setAttribute('id','nextLink');
objNextLink.setAttribute('href','#');
objHoverNav.appendChild(objNextLink);

var objLoading = document.createElement("div");
objLoading.setAttribute('id','loading');
objImageContainer.appendChild(objLoading);

var objLoadingLink = document.createElement("a");
objLoadingLink.setAttribute('id','loadingLink');
objLoadingLink.setAttribute('href','#');
objLoadingLink.onclick = function() { myLightbox.end(); return false; }
objLoading.appendChild(objLoadingLink);

var objLoadingImage = document.createElement("img");
objLoadingImage.setAttribute('src', fileLoadingImage);
objLoadingLink.appendChild(objLoadingImage);

var objImageDataContainer = document.createElement("div");
objImageDataContainer.setAttribute('id','imageDataContainer');
objImageDataContainer.className = 'clearfix';
objLightbox.appendChild(objImageDataContainer);

var objImageData = document.createElement("div");
objImageData.setAttribute('id','imageData');
objImageDataContainer.appendChild(objImageData);

var objImageDetails = document.createElement("div");
objImageDetails.setAttribute('id','imageDetails');
objImageData.appendChild(objImageDetails);

var objCaption = document.createElement("span");
objCaption.setAttribute('id','caption');
objImageDetails.appendChild(objCaption);

var objNumberDisplay = document.createElement("span");
objNumberDisplay.setAttribute('id','numberDisplay');
objImageDetails.appendChild(objNumberDisplay);

var objBottomNav = document.createElement("div");
objBottomNav.setAttribute('id','bottomNav');
objImageData.appendChild(objBottomNav);

var objBottomNavCloseLink = document.createElement("a");
objBottomNavCloseLink.setAttribute('id','bottomNavClose');
objBottomNavCloseLink.setAttribute('href','#');
objBottomNavCloseLink.onclick = function() { myLightbox.end(); return false; }
objBottomNav.appendChild(objBottomNavCloseLink);

var objBottomNavCloseImage = document.createElement("img");
objBottomNavCloseImage.setAttribute('src', fileBottomNavCloseImage);
objBottomNavCloseLink.appendChild(objBottomNavCloseImage);
},

//
//start()
//Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
//
start: function(imageLink) {

hideSelectBoxes();

// stretch overlay to fill page and fade in
var arrayPageSize = getPageSize();
Element.setHeight('overlay', arrayPageSize[1]);
new Effect.Appear('overlay', { duration: 0.1, from: 0.0, to: 0.8 });

imageArray = [];
imageNum = 0;

if (!document.getElementsByTagName){ return; }
var anchors = document.getElementsByTagName('a');

// if image is NOT part of a set..
if((imageLink.getAttribute('rel') == 'lightbox')){
// add single image to imageArray
imageArray.push(new Array(imageLink.getAttribute('href'), imageLink.getAttribute('title')));
} else {
// if image is part of a set..

// loop through anchors, find other images in set, and add them to imageArray
for (var i=0; i<anchors.length; i++){
var anchor = anchors[i];
if (anchor.getAttribute('href') && (anchor.getAttribute('rel') == imageLink.getAttribute('rel'))){
imageArray.push(new Array(anchor.getAttribute('href'), anchor.getAttribute('title')));
}
}
imageArray.removeDuplicates();
while(imageArray[imageNum][0] != imageLink.getAttribute('href')) { imageNum++;}
}

// calculate top offset for the lightbox and display
var arrayPageSize = getPageSize();
var arrayPageScroll = getPageScroll();
var lightboxTop = arrayPageScroll[1] + (arrayPageSize[3] / 10);

Element.setTop('lightbox', lightboxTop);
Element.show('lightbox');

this.changeImage(imageNum);
},

//
//changeImage()
//Hide most elements and preload image in preparation for resizing image container.
//
changeImage: function(imageNum) {

activeImage = imageNum;// update global var

// hide elements during transition
Element.show('loading');
Element.hide('lightboxImage');
Element.hide('hoverNav');
Element.hide('prevLink');
Element.hide('nextLink');
Element.hide('imageDataContainer');
Element.hide('numberDisplay');

imgPreloader = new Image();

// once image is preloaded, resize image container
imgPreloader.onload=function(){
Element.setSrc('lightboxImage', imageArray[activeImage][0]);
myLightbox.resizeImageContainer(imgPreloader.width, imgPreloader.height);
}
imgPreloader.src = imageArray[activeImage][0];
},

//
//resizeImageContainer()
//
resizeImageContainer: function( imgWidth, imgHeight) {

// get current height and width
this.wCur = Element.getWidth('outerImageContainer');
this.hCur = Element.getHeight('outerImageContainer');

// scalars based on change from old to new
this.xScale = ((imgWidth  + (borderSize * 2)) / this.wCur) * 100;
this.yScale = ((imgHeight  + (borderSize * 2)) / this.hCur) * 100;

// calculate size difference between new and old image, and resize if necessary
wDiff = (this.wCur - borderSize * 2) - imgWidth;
hDiff = (this.hCur - borderSize * 2) - imgHeight;

if(!( hDiff == 0)){ new Effect.Scale('outerImageContainer', this.yScale, {scaleX: false, duration: resizeDuration, queue: 'front'}); }
if(!( wDiff == 0)){ new Effect.Scale('outerImageContainer', this.xScale, {scaleY: false, delay: resizeDuration, duration: resizeDuration}); }

// if new and old image are same size and no scaling transition is necessary,
// do a quick pause to prevent image flicker.
if((hDiff == 0) && (wDiff == 0)){
if (navigator.appVersion.indexOf("MSIE")!=-1){ pause(250); } else { pause(100);}
}

Element.setHeight('prevLink', imgHeight);
Element.setHeight('nextLink', imgHeight);
Element.setWidth( 'imageDataContainer', imgWidth + (borderSize * 2));

this.showImage();
},

//
//showImage()
//Display image and begin preloading neighbors.
//
showImage: function(){
Element.hide('loading');
new Effect.Appear('lightboxImage', { duration: 0.3, queue: 'end', afterFinish: function(){myLightbox.updateDetails(); } });
this.preloadNeighborImages();
},

//
//updateDetails()
//Display caption, image number, and bottom nav.
//
updateDetails: function() {

Element.show('caption');
Element.setInnerHTML( 'caption', imageArray[activeImage][1]);

// if image is part of set display 'Image x of x'
if(imageArray.length > 1){
Element.show('numberDisplay');
Element.setInnerHTML( 'numberDisplay', "Image " + eval(activeImage + 1) + " of " + imageArray.length);
}

new Effect.Parallel(
[ new Effect.SlideDown( 'imageDataContainer', { sync: true, duration: resizeDuration - 0.55, from: 0.0, to: 1.0 }),
  new Effect.Appear('imageDataContainer', { sync: true, duration: 0.2 }) ],
{ duration: 0.45, afterFinish: function() {
// update overlay size and update nav
var arrayPageSize = getPageSize();
Element.setHeight('overlay', arrayPageSize[1]);
myLightbox.updateNav();
}
}
);
},

//
//updateNav()
//Display appropriate previous and next hover navigation.
//
updateNav: function() {

Element.show('hoverNav');

// if not first image in set, display prev image button
if(activeImage != 0){
Element.show('prevLink');
document.getElementById('prevLink').onclick = function() {
myLightbox.changeImage(activeImage - 1); return false;
}
}

// if not last image in set, display next image button
if(activeImage != (imageArray.length - 1)){
Element.show('nextLink');
document.getElementById('nextLink').onclick = function() {
myLightbox.changeImage(activeImage + 1); return false;
}
}

this.enableKeyboardNav();
},

//
//enableKeyboardNav()
//
enableKeyboardNav: function() {
document.onkeydown = this.keyboardAction;
},

//
//disableKeyboardNav()
//
disableKeyboardNav: function() {
document.onkeydown = '';
},

//
//keyboardAction()
//
keyboardAction: function(e) {
if (e == null) { // ie
keycode = event.keyCode;
} else { // mozilla
keycode = e.which;
}

key = String.fromCharCode(keycode).toLowerCase();

if((key == 'x') || (key == 'o') || (key == 'c')){// close lightbox
myLightbox.end();
} else if(key == 'p'){// display previous image
if(activeImage != 0){
myLightbox.disableKeyboardNav();
myLightbox.changeImage(activeImage - 1);
}
} else if(key == 'n'){// display next image
if(activeImage != (imageArray.length - 1)){
myLightbox.disableKeyboardNav();
myLightbox.changeImage(activeImage + 1);
}
}


},

//
//preloadNeighborImages()
//Preload previous and next images.
//
preloadNeighborImages: function(){

if((imageArray.length - 1) > activeImage){
preloadNextImage = new Image();
preloadNextImage.src = imageArray[activeImage + 1][0];
}
if(activeImage > 0){
preloadPrevImage = new Image();
preloadPrevImage.src = imageArray[activeImage - 1][0];
}

},

//
//end()
//
end: function() {
this.disableKeyboardNav();
Element.hide('lightbox');
new Effect.Fade('overlay', { duration: 0.2});
showSelectBoxes();
}
}

// -----------------------------------------------------------------------------------

//
// getPageScroll()
// Returns array with x,y page scroll values.
// Core code from - quirksmode.org
//
function getPageScroll(){

var yScroll;

if (self.pageYOffset) {
yScroll = self.pageYOffset;
} else if (document.documentElement && document.documentElement.scrollTop){ // Explorer 6 Strict
yScroll = document.documentElement.scrollTop;
} else if (document.body) {// all other Explorers
yScroll = document.body.scrollTop;
}

arrayPageScroll = new Array('',yScroll)
return arrayPageScroll;
}

// -----------------------------------------------------------------------------------

//
// getPageSize()
// Returns array with page width, height and window width, height
// Core code from - quirksmode.org
// Edit for Firefox by pHaez
//
function getPageSize(){

var xScroll, yScroll;

if (window.innerHeight && window.scrollMaxY) {
xScroll = document.body.scrollWidth;
yScroll = window.innerHeight + window.scrollMaxY;
} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}

var windowWidth, windowHeight;
if (self.innerHeight) {// all except Explorer
windowWidth = self.innerWidth;
windowHeight = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight;
} else if (document.body) { // other Explorers
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}

// for small pages with total height less then height of the viewport
if(yScroll < windowHeight){
pageHeight = windowHeight;
} else {
pageHeight = yScroll;
}

// for small pages with total width less then width of the viewport
if(xScroll < windowWidth){
pageWidth = windowWidth;
} else {
pageWidth = xScroll;
}


arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight)
return arrayPageSize;
}

// -----------------------------------------------------------------------------------

//
// getKey(key)
// Gets keycode. If 'x' is pressed then it hides the lightbox.
//
function getKey(e){
if (e == null) { // ie
keycode = event.keyCode;
} else { // mozilla
keycode = e.which;
}
key = String.fromCharCode(keycode).toLowerCase();

if(key == 'x'){
}
}

// -----------------------------------------------------------------------------------

//
// listenKey()
//
function listenKey () {document.onkeypress = getKey; }

// ---------------------------------------------------

function showSelectBoxes(){
selects = document.getElementsByTagName("select");
for (i = 0; i != selects.length; i++) {
selects[i].style.visibility = "visible";
}
}

// ---------------------------------------------------

function hideSelectBoxes(){
selects = document.getElementsByTagName("select");
for (i = 0; i != selects.length; i++) {
selects[i].style.visibility = "hidden";
}
}

// ---------------------------------------------------

//
// pause(numberMillis)
// Pauses code execution for specified time. Uses busy code, not good.
// Code from http://www.faqts.com/knowledge_base/view.phtml/aid/1602
//
function pause(numberMillis) {
var now = new Date();
var exitTime = now.getTime() + numberMillis;
while (true) {
now = new Date();
if (now.getTime() > exitTime)
return;
}
}

// ---------------------------------------------------



function initLightbox() { myLightbox = new Lightbox(); }
Event.observe(window, 'load', initLightbox, false);

// ---------------------------------------------------
if (!CBH) var CBH = {};
CBH.Social = {
	dialog: function(params) {
		var default_params = {
			width: 400,
			height: 185,
			title: 'Публикуване',
			menu: 1,
			fb: false,
			twitter: false,
			ok_callback: CBH.Social.callback,
			cancel_callback: CBH.ModalDialog.close
		};
		for (k in default_params) {
			if (typeof params[k] == 'undefined') {
				params[k] = default_params[k];
			}
		}
		CBH.Dialogs.__ok_callback__ = params.ok_callback;
		CBH.Dialogs.__cancel_callback__ = params.cancel_callback;

		 if (params.fb == 2 || params.twitter == 2) {
			if (params.fb == 2 && params.twitter == 2) {
				CBH.Social.callback({menu: params.menu, fb: params.fb, twitter: params.twitter});
				return false;
			}

			if (params.fb == 2)
				CBH.Social.callback({menu: params.menu, fb: params.fb, twitter: false});
			if (params.twitter == 2)
				CBH.Social.callback({menu: params.menu, fb: false, twitter: params.twitter});
		} 
		
		 if ((params.fb == 2 || params.fb === false) && 
				 (params.twitter == 2 || params.twitter === false)) {
			 return false;
		 }

		var html = '<form id="social_form"><table cellspacing="10px;"><tr><td></td><td>Винаги</td><td>Да</td><td>Не</td></tr>';

		if (params.fb !== false && params.fb != 2) {
			html += '<tr><td style="text-align: right;">Публикувай във Facebook:</td>' +
				'<td><input type="radio" name="fb" '+ (params.fb == 2 ? 'checked' : '') +' value="2"/></td>' +
				'<td><input type="radio" name="fb" '+ (params.fb == 1 ? 'checked' : '') +' value="1"/></td>' +
				'<td><input type="radio" name="fb" '+ (params.fb == 0 ? 'checked' : '') +' value="0"/></td>' +
				'</tr>';
		}

		if (params.twitter !== false && params.twitter != 2) {
			html += '<tr><td style="text-align: right;">Публикувай в Twitter:</td>' +
				'<td><input type="radio" name="twitter" '+ (params.twitter == 2 ? 'checked' : '') +' value="2"/></td>' +
				'<td><input type="radio" name="twitter" '+ (params.twitter == 1 ? 'checked' : '') +' value="1"/></td>' +
				'<td><input type="radio" name="twitter" '+ (params.twitter == 0 ? 'checked' : '') +' value="0"/></td>' +
				'</tr>';
		}

		html += '</table>' +
			'<input type="hidden" name="menu" value="' + params.menu +'"/>' +
			'<div style="text-align: center; margin-top: 20px;">' +
				'<input type="button" value="Запази" ' +
				' onclick="' +
				'CBH.Dialogs.__ok_callback__($(\'social_form\').serialize(true)); ' +
				'CBH.ModalDialog.close(); ' +
				'" class="submit" ' +
				' style="margin-right: 10px; width: 80px;" />' +
				'<input type="button" value="Откажи" onclick="CBH.Dialogs.__cancel_callback__();" class="cancel" ' +
				' style="width: 80px;" />' +
				'</div>' +
			'</form>';

		var social_form = ce('div');
		social_form.innerHTML = html;

		CBH.ModalDialog.init();
		CBH.ModalDialog.setTitle(params.title);
		CBH.ModalDialog.setHTMLElement(social_form);
		CBH.ModalDialog.setWidth(params.width);
		CBH.ModalDialog.setHeight(params.height);
		CBH.ModalDialog.open();
		return false;
	},

	callback: function(options) {
		var default_options = {
			menu: 1,
			fb: false,
			twitter: false
		};
		for (k in default_options) {
			if (typeof options[k] == 'undefined') {
				options[k] = default_options[k];
			}
		}
		call('/api.php?object=social&menu='+options.menu+'&fb='+options.fb+'&twitter='+options.twitter,false,'',true);
	}
}
// ---------------------------------------------------

