// script.aculo.us effects.js v1.8.2
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.collectTextNodesIgnoreClass(node,className) : ''));
  }).flatten().join('');
};
Element.setContentZoom = function(element,percent) {
  element = $(element);
  element.setStyle({ fontSize: (percent / 100) + 'em' });
  if (Prototype.Browser.WebKit) window.scrollBy(0,0);
  return element;
};
Element.getInlineOpacity = function(element) {
  return $(element).style.opacity || '';
};
Element.forceRerendering = function(element) {
  try {
    element = $(element);
    var n = document.createTextNode(' ');
    element.appendChild(n);
    element.removeChild(n);
  } catch (e) { }
};
var Effect = {
  _elementDoesNotExistError: {
    name: 'ElementDoesNotExistError',
    message: 'The specified DOM element does not exist, but is required for this effect to operate'
  },
  Transitions: {
    linear: Prototype.K,
    sinoidal: function(pos) {
      return (-Math.cos(pos * Math.PI) / 2) + .5;
    },
    reverse: function(pos) {
      return 1 - pos;
    },
    flicker: function(pos) {
      var pos = ((-Math.cos(pos * Math.PI) / 4) + .75) + Math.random() / 4;
      return pos > 1 ? 1 : pos;
    },
    wobble: function(pos) {
      return (-Math.cos(pos * Math.PI * (9 * pos)) / 2) + .5;
    },
    pulse: function(pos,pulses) {
      return (-Math.cos((pos * ((pulses || 5) - .5) * 2) * Math.PI) / 2) + .5;
    },
    spring: function(pos) {
      return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
    },
    none: function(pos) {
      return 0;
    },
    full: function(pos) {
      return 1;
    }
  },
  DefaultOptions: {
    duration: 1.0,   // seconds
    fps: 100,   // 100= assume 66fps max.
    sync: false, // true for combining
    from: 0.0,
    to: 1.0,
    delay: 0.0,
    queue: 'parallel'
  },
  tagifyText: function(element) {
    var tagifyStyle = 'position:relative';
    if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
    element = $(element);
    $A(element.childNodes).each(function(child) {
      if (child.nodeType == 3) {
        child.nodeValue.toArray().each(function(character) {
          element.insertBefore(
            new Element('span',{ style: tagifyStyle }).update(
              character == ' ' ? String.fromCharCode(160) : character),
              child);
        });
        Element.remove(child);
      }
    });
  },
  multiple: function(element,effect) {
    var elements;
    if (((typeof element == 'object') ||
        Object.isFunction(element)) &&
       (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'),limit: 1 }
    },arguments[2] || {});
    Effect[element.visible() ?
      Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element,options);
  }
};
Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
/* ------------- core effects ------------- */
Effect.ScopedQueue = Class.create(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 = Object.isString(effect.options.queue) ?
      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 'with-last':
        timestamp = this.effects.pluck('startOn').max() || timestamp;
        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;
    if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
      this.effects.push(effect);
    if (!this.interval)
      this.interval = setInterval(this.loop.bind(this),15);
  },
  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();
    for (var i = 0,len = this.effects.length;i < len;i++)
      this.effects[i] && this.effects[i].loop(timePos);
  }
});
Effect.Queues = {
  instances: $H(),
  get: function(queueName) {
    if (!Object.isString(queueName)) return queueName;
    return this.instances.get(queueName) ||
      this.instances.set(queueName,new Effect.ScopedQueue());
  }
};
Effect.Queue = Effect.Queues.get('global');
Effect.Base = Class.create({
  position: null,
  start: function(options) {
    function codeForEvent(options,eventName) {
      return (
        (options[eventName + 'Internal'] ? 'this.options.' + eventName + 'Internal(this);' : '') +
        (options[eventName] ? 'this.options.' + eventName + '(this);' : '')
      );
    }
    if (options && options.transition === false) options.transition = Effect.Transitions.linear;
    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.fromToDelta = this.options.to - this.options.from;
    this.totalTime = this.finishOn - this.startOn;
    this.totalFrames = this.options.fps * this.options.duration;
    this.render = (function() {
      function dispatch(effect,eventName) {
        if (effect.options[eventName + 'Internal'])
          effect.options[eventName + 'Internal'](effect);
        if (effect.options[eventName])
          effect.options[eventName](effect);
      }
      return function(pos) {
        if (this.state === "idle") {
          this.state = "running";
          dispatch(this,'beforeSetup');
          if (this.setup) this.setup();
          dispatch(this,'afterSetup');
        }
        if (this.state === "running") {
          pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
          this.position = pos;
          dispatch(this,'beforeUpdate');
          if (this.update) this.update(pos);
          dispatch(this,'afterUpdate');
        }
      };
    })();
    this.event('beforeStart');
    if (!this.options.sync)
      Effect.Queues.get(Object.isString(this.options.queue) ?
        '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.totalTime,
          frame = (pos * this.totalFrames).round();
      if (frame > this.currentFrame) {
        this.render(pos);
        this.currentFrame = frame;
      }
    }
  },
  cancel: function() {
    if (!this.options.sync)
      Effect.Queues.get(Object.isString(this.options.queue) ?
        '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() {
    var data = $H();
    for (property in this)
      if (!Object.isFunction(this[property])) data.set(property,this[property]);
    return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
  }
});
Effect.Parallel = Class.create(Effect.Base,{
  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.Tween = Class.create(Effect.Base,{
  initialize: function(object,from,to) {
    object = Object.isString(object) ? $(object) : object;
    var args = $A(arguments),method = args.last(),
      options = args.length == 5 ? args[3] : null;
    this.method = Object.isFunction(method) ? method.bind(object) :
      Object.isFunction(object[method]) ? object[method].bind(object) :
      function(value) { object[method] = value };
    this.start(Object.extend({ from: from,to: to },options || {}));
  },
  update: function(position) {
    this.method(position);
  }
});
Effect.Event = Class.create(Effect.Base,{
  initialize: function() {
    this.start(Object.extend({ duration: 0 },arguments[0] || {}));
  },
  update: Prototype.emptyFunction
});
Effect.Opacity = Class.create(Effect.Base,{
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw (Effect._elementDoesNotExistError);
    // make this work on IE on elements without 'layout'
    if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
      this.element.setStyle({ zoom: 1 });
    var options = Object.extend({
      from: this.element.getOpacity() || 0.0,
      to: 1.0
    },arguments[1] || {});
    this.start(options);
  },
  update: function(position) {
    this.element.setOpacity(position);
  }
});
Effect.Move = Class.create(Effect.Base,{
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw (Effect._elementDoesNotExistError);
    var options = Object.extend({
      x: 0,
      y: 0,
      mode: 'relative'
    },arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    this.element.makePositioned();
    this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
    this.originalTop = parseFloat(this.element.getStyle('top') || '0');
    if (this.options.mode == 'absolute') {
      this.options.x = this.options.x - this.originalLeft;
      this.options.y = this.options.y - this.originalTop;
    }
  },
  update: function(position) {
    this.element.setStyle({
      left: (this.options.x * position + this.originalLeft).round() + 'px',
      top: (this.options.y * position + this.originalTop).round() + '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(Effect.Base,{
  initialize: function(element,percent) {
    this.element = $(element);
    if (!this.element) throw (Effect._elementDoesNotExistError);
    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 = this.element.getStyle('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 = this.element.getStyle('font-size') || '100%';
    ['em','px','%','pt'].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)
      this.element.setStyle({ fontSize: this.fontSize * currentScale + this.fontSizeType });
    this.setDimensions(this.dims[0] * currentScale,this.dims[1] * currentScale);
  },
  finish: function(position) {
    if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
  },
  setDimensions: function(height,width) {
    var d = {};
    if (this.options.scaleX) d.width = width.round() + 'px';
    if (this.options.scaleY) d.height = height.round() + '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';
      }
    }
    this.element.setStyle(d);
  }
});
Effect.Highlight = Class.create(Effect.Base,{
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw (Effect._elementDoesNotExistError);
    var options = Object.extend({ startcolor: '#ffff99' },arguments[1] || {});
    this.start(options);
  },
  setup: function() {
    // Prevent executing on elements not in the layout flow
    if (this.element.getStyle('display') == 'none') { this.cancel();return; }
    // Disable background image during the effect
    this.oldStyle = {};
    if (!this.options.keepBackgroundImage) {
      this.oldStyle.backgroundImage = this.element.getStyle('background-image');
      this.element.setStyle({ backgroundImage: 'none' });
    }
    if (!this.options.endcolor)
      this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
    if (!this.options.restorecolor)
      this.options.restorecolor = this.element.getStyle('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) {
    this.element.setStyle({ backgroundColor: $R(0,2).inject('#',function(m,v,i) {
      return m + ((this._base[i] + (this._delta[i] * position)).round().toColorPart());
    } .bind(this))
    });
  },
  finish: function() {
    this.element.setStyle(Object.extend(this.oldStyle,{
      backgroundColor: this.options.restorecolor
    }));
  }
});
Effect.ScrollTo = function(element) {
  var options = arguments[1] || {},
  scrollOffsets = document.viewport.getScrollOffsets(),
  elementOffsets = $(element).cumulativeOffset();
  if (options.offset) elementOffsets[1] += options.offset;
  return new Effect.Tween(null,
    scrollOffsets.top,
    elementOffsets[1],
    options,
    function(p) { scrollTo(scrollOffsets.left,p.round()); }
  );
};
/* ------------- combination effects ------------- */
Effect.Fade = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  var options = Object.extend({
    from: element.getOpacity() || 1.0,
    to: 0.0,
    afterFinishInternal: function(effect) {
      if (effect.options.to != 0) return;
      effect.element.hide().setStyle({ opacity: oldOpacity });
    }
  },arguments[1] || {});
  return new Effect.Opacity(element,options);
};
Effect.Appear = function(element) {
  element = $(element);
  var options = Object.extend({
    from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
    to: 1.0,
    // force Safari to render floated elements properly
    afterFinishInternal: function(effect) {
      effect.element.forceRerendering();
    },
    beforeSetup: function(effect) {
      effect.element.setOpacity(effect.options.from).show();
    }
  },arguments[1] || {});
  return new Effect.Opacity(element,options);
};
Effect.Puff = function(element) {
  element = $(element);
  var oldStyle = {
    opacity: element.getInlineOpacity(),
    position: element.getStyle('position'),
    top: element.style.top,
    left: element.style.left,
    width: element.style.width,
    height: element.style.height
  };
  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) {
         Position.absolutize(effect.effects[0].element);
       },
       afterFinishInternal: function(effect) {
         effect.effects[0].element.hide().setStyle(oldStyle);
       }
     },arguments[1] || {})
   );
};
Effect.BlindUp = function(element) {
  element = $(element);
  element.makeClipping();
  return new Effect.Scale(element,0,
    Object.extend({ scaleContent: false,
      scaleX: false,
      restoreAfterFinish: true,
      afterFinishInternal: function(effect) {
        effect.element.hide().undoClipping();
      }
    },arguments[1] || {})
  );
};
Effect.BlindDown = function(element) {
  element = $(element);
  var elementDimensions = element.getDimensions();
  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) {
      effect.element.makeClipping().setStyle({ height: '0px' }).show();
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping();
    }
  },arguments[1] || {}));
};
Effect.SwitchOff = function(element) {
  element = $(element);
  var oldOpacity = element.getInlineOpacity();
  return new Effect.Appear(element,Object.extend({
    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) {
          effect.element.makePositioned().makeClipping();
        },
        afterFinishInternal: function(effect) {
          effect.element.hide().undoClipping().undoPositioned().setStyle({ opacity: oldOpacity });
        }
      });
    }
  },arguments[1] || {}));
};
Effect.DropOut = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left'),
    opacity: element.getInlineOpacity()
  };
  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) {
          effect.effects[0].element.makePositioned();
        },
        afterFinishInternal: function(effect) {
          effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
        }
      },arguments[1] || {}));
};
Effect.Shake = function(element) {
  element = $(element);
  var options = Object.extend({
    distance: 20,
    duration: 0.5
  },arguments[1] || {});
  var distance = parseFloat(options.distance);
  var split = parseFloat(options.duration) / 10.0;
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left')
  };
  return new Effect.Move(element,{
    x: distance,y: 0,duration: split,afterFinishInternal: function(effect) {
      new Effect.Move(effect.element,{
        x: -distance * 2,y: 0,duration: split * 2,afterFinishInternal: function(effect) {
          new Effect.Move(effect.element,{
            x: distance * 2,y: 0,duration: split * 2,afterFinishInternal: function(effect) {
              new Effect.Move(effect.element,{
                x: -distance * 2,y: 0,duration: split * 2,afterFinishInternal: function(effect) {
                  new Effect.Move(effect.element,{
                    x: distance * 2,y: 0,duration: split * 2,afterFinishInternal: function(effect) {
                      new Effect.Move(effect.element,{
                        x: -distance,y: 0,duration: split,afterFinishInternal: function(effect) {
                          effect.element.undoPositioned().setStyle(oldStyle);
                        }
                      });
                    }
                  });
                }
              });
            }
          });
        }
      });
    }
  });
};
Effect.SlideDown = function(element) {
  element = $(element).cleanWhitespace();
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
  var oldInnerBottom = element.down().getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element,100,Object.extend({
    scaleContent: false,
    scaleX: false,
    scaleFrom: window.opera ? 0 : 1,
    scaleMode: { originalHeight: elementDimensions.height,originalWidth: elementDimensions.width },
    restoreAfterFinish: true,
    afterSetup: function(effect) {
      effect.element.makePositioned();
      effect.element.down().makePositioned();
      if (window.opera) effect.element.setStyle({ top: '' });
      effect.element.makeClipping().setStyle({ height: '0px' }).show();
    },
    afterUpdateInternal: function(effect) {
      effect.element.down().setStyle({ bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px'
      });
    },
    afterFinishInternal: function(effect) {
      effect.element.undoClipping().undoPositioned();
      effect.element.down().undoPositioned().setStyle({ bottom: oldInnerBottom });
    }
  },arguments[1] || {})
  );
};
Effect.SlideUp = function(element) {
  element = $(element).cleanWhitespace();
  var oldInnerBottom = element.down().getStyle('bottom');
  var elementDimensions = element.getDimensions();
  return new Effect.Scale(element,window.opera ? 0 : 1,
   Object.extend({ scaleContent: false,
     scaleX: false,
     scaleMode: 'box',
     scaleFrom: 100,
     scaleMode: { originalHeight: elementDimensions.height,originalWidth: elementDimensions.width },
     restoreAfterFinish: true,
     afterSetup: function(effect) {
       effect.element.makePositioned();
       effect.element.down().makePositioned();
       if (window.opera) effect.element.setStyle({ top: '' });
       effect.element.makeClipping().show();
     },
     afterUpdateInternal: function(effect) {
       effect.element.down().setStyle({ bottom:
        (effect.dims[0] - effect.element.clientHeight) + 'px'
       });
     },
     afterFinishInternal: function(effect) {
       effect.element.hide().undoClipping().undoPositioned();
       effect.element.down().undoPositioned().setStyle({ 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) {
      effect.element.makeClipping();
    },
    afterFinishInternal: function(effect) {
      effect.element.hide().undoClipping();
    }
  });
};
Effect.Grow = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransition: 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()
  };
  var dims = element.getDimensions();
  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) {
      effect.element.hide().makeClipping().makePositioned();
    },
    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) {
            effect.effects[0].element.setStyle({ height: '0px' }).show();
          },
          afterFinishInternal: function(effect) {
            effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
          }
        },options)
      );
    }
  });
};
Effect.Shrink = function(element) {
  element = $(element);
  var options = Object.extend({
    direction: 'center',
    moveTransition: 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()
  };
  var dims = element.getDimensions();
  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) {
        effect.effects[0].element.makePositioned().makeClipping();
      },
      afterFinishInternal: function(effect) {
        effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle);
      }
    },options)
  );
};
Effect.Pulsate = function(element) {
  element = $(element);
  var options = arguments[1] || {},
    oldOpacity = element.getInlineOpacity(),
    transition = options.transition || Effect.Transitions.linear,
    reverser = function(pos) {
      return 1 - transition((-Math.cos((pos * (options.pulses || 5) * 2) * Math.PI) / 2) + .5);
    };
  return new Effect.Opacity(element,
    Object.extend(Object.extend({ duration: 2.0,from: 0,
      afterFinishInternal: function(effect) { effect.element.setStyle({ 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();
  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) {
          effect.element.hide().undoClipping().setStyle(oldStyle);
        }
      });
    }
  },arguments[1] || {}));
};
Effect.Morph = Class.create(Effect.Base,{
  initialize: function(element) {
    this.element = $(element);
    if (!this.element) throw (Effect._elementDoesNotExistError);
    var options = Object.extend({
      style: {}
    },arguments[1] || {});
    if (!Object.isString(options.style)) this.style = $H(options.style);
    else {
      if (options.style.include(':'))
        this.style = options.style.parseStyle();
      else {
        this.element.addClassName(options.style);
        this.style = $H(this.element.getStyles());
        this.element.removeClassName(options.style);
        var css = this.element.getStyles();
        this.style = this.style.reject(function(style) {
          return style.value == css[style.key];
        });
        options.afterFinishInternal = function(effect) {
          effect.element.addClassName(effect.options.style);
          effect.transforms.each(function(transform) {
            effect.element.style[transform.style] = '';
          });
        };
      }
    }
    this.start(options);
  },
  setup: function() {
    function parseColor(color) {
      if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
      color = color.parseColor();
      return $R(0,2).map(function(i) {
        return parseInt(color.slice(i * 2 + 1,i * 2 + 3),16);
      });
    }
    this.transforms = this.style.map(function(pair) {
      var property = pair[0],value = pair[1],unit = null;
      if (value.parseColor('#zzzzzz') != '#zzzzzz') {
        value = value.parseColor();
        unit = 'color';
      } else if (property == 'opacity') {
        value = parseFloat(value);
        if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
          this.element.setStyle({ zoom: 1 });
      } else if (Element.CSS_LENGTH.test(value)) {
        var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
        value = parseFloat(components[1]);
        unit = (components.length == 3) ? components[2] : null;
      }
      var originalValue = this.element.getStyle(property);
      return {
        style: property.camelize(),
        originalValue: unit == 'color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
        targetValue: unit == 'color' ? parseColor(value) : value,
        unit: unit
      };
    } .bind(this)).reject(function(transform) {
      return (
        (transform.originalValue == transform.targetValue) ||
        (
          transform.unit != 'color' &&
          (isNaN(transform.originalValue) || isNaN(transform.targetValue))
        )
      );
    });
  },
  update: function(position) {
    var style = {},transform,i = this.transforms.length;
    while (i--)
      style[(transform = this.transforms[i]).style] =
        transform.unit == 'color' ? '#' +
          (Math.round(transform.originalValue[0] +
            (transform.targetValue[0] - transform.originalValue[0]) * position)).toColorPart() +
          (Math.round(transform.originalValue[1] +
            (transform.targetValue[1] - transform.originalValue[1]) * position)).toColorPart() +
          (Math.round(transform.originalValue[2] +
            (transform.targetValue[2] - transform.originalValue[2]) * position)).toColorPart() :
        (transform.originalValue +
          (transform.targetValue - transform.originalValue) * position).toFixed(3) +
            (transform.unit === null ? '' : transform.unit);
    this.element.setStyle(style,true);
  }
});
Effect.Transform = Class.create({
  initialize: function(tracks) {
    this.tracks = [];
    this.options = arguments[1] || {};
    this.addTracks(tracks);
  },
  addTracks: function(tracks) {
    tracks.each(function(track) {
      track = $H(track);
      var data = track.values().first();
      this.tracks.push($H({
        ids: track.keys().first(),
        effect: Effect.Morph,
        options: { style: data }
      }));
    } .bind(this));
    return this;
  },
  play: function() {
    return new Effect.Parallel(
      this.tracks.map(function(track) {
        var ids = track.get('ids'),effect = track.get('effect'),options = track.get('options');
        var elements = [$(ids) || $$(ids)].flatten();
        return elements.map(function(e) { return new effect(e,Object.extend({ sync: true },options)) });
      }).flatten(),
      this.options
    );
  }
});
Element.CSS_PROPERTIES = $w(
  'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
  'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
  'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
  'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
  'fontSize fontWeight height left letterSpacing lineHeight ' +
  'marginBottom marginLeft marginRight marginTop markerOffset maxHeight ' +
  'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
  'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
  'right textIndent top width wordSpacing zIndex');
Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function() {
  var style,styleRules = $H();
  if (Prototype.Browser.WebKit)
    style = new Element('div',{ style: this }).style;
  else {
    String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
    style = String.__parseStyleElement.childNodes[0].style;
  }
  Element.CSS_PROPERTIES.each(function(property) {
    if (style[property]) styleRules.set(property,style[property]);
  });
  if (Prototype.Browser.IE && this.include('opacity'))
    styleRules.set('opacity',this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
  return styleRules;
};
if (document.defaultView && document.defaultView.getComputedStyle) {
  Element.getStyles = function(element) {
    var css = document.defaultView.getComputedStyle($(element),null);
    return Element.CSS_PROPERTIES.inject({},function(styles,property) {
      styles[property] = css[property];
      return styles;
    });
  };
} else {
  Element.getStyles = function(element) {
    element = $(element);
    var css = element.currentStyle,styles;
    styles = Element.CSS_PROPERTIES.inject({},function(results,property) {
      results[property] = css[property];
      return results;
    });
    if (!styles.opacity) styles.opacity = element.getOpacity();
    return styles;
  };
}
Effect.Methods = {
  morph: function(element,style) {
    element = $(element);
    new Effect.Morph(element,Object.extend({ style: style },arguments[2] || {}));
    return element;
  },
  visualEffect: function(element,effect,options) {
    element = $(element);
    var s = effect.dasherize().camelize(),klass = s.charAt(0).toUpperCase() + s.substring(1);
    new Effect[klass](element,options);
    return element;
  },
  highlight: function(element,options) {
    element = $(element);
    new Effect.Highlight(element,options);
    return element;
  }
};
$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown ' +
  'pulsate shake puff squish switchOff dropOut').each(
  function(effect) {
    Effect.Methods[effect] = function(element,options) {
      element = $(element);
      Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element,options);
      return element;
    };
  }
);
$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
  function(f) { Effect.Methods[f] = Element[f]; }
);
Element.addMethods(Effect.Methods);
// end effects.js
// window.js - modified by c wasser, Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com), VERSION 1.3
var Window = Class.create();
Window.keepMultiModalWindow = false;
Window.hasEffectLib = (typeof Effect != 'undefined');
Window.resizeEffectDuration = 0.4;
Window.prototype = {
  initialize: function() {
    var id;
    var optionIndex = 0;
    // For backward compatibility like win= new Window("id", {...}) instead of win = new Window({id: "id", ...})
    if (arguments.length > 0) {
      if (typeof arguments[0] == "string") {
        id = arguments[0];
        optionIndex = 1;
      }
      else
        id = arguments[0] ? arguments[0].id : null;
    }
    // Generate unique ID if not specified
    if (!id)
      id = "window_" + new Date().getTime();
    if ($(id))
      alert("Window " + id + " is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor");
    this.options = Object.extend({
      className: "dialog",
      blurClassName: null,
      minWidth: 100,
      minHeight: 20,
      resizable: true,
      closable: true,
      minimizable: true,
      maximizable: true,
      draggable: true,
      userData: null,
      showEffect: (Window.hasEffectLib ? Effect.Appear : Element.show),
      hideEffect: (Window.hasEffectLib ? Effect.Fade : Element.hide),
      showEffectOptions: {},
      hideEffectOptions: {},
      effectOptions: null,
      parent: document.body,
      title: "&nbsp;",
      url: null,
      onload: Prototype.emptyFunction,
      width: 200,
      height: 300,
      opacity: 1,
      recenterAuto: true,
      wiredDrag: false,
      closeCallback: null,
      destroyOnClose: false,
      gridX: 1,
      gridY: 1,
      wrap: true
    },arguments[optionIndex] || {});
    if (this.options.blurClassName)
      this.options.focusClassName = this.options.className;
    if (typeof this.options.top == "undefined" && typeof this.options.bottom == "undefined")
      this.options.top = this._round(Math.random() * 500,this.options.gridY);
    if (typeof this.options.left == "undefined" && typeof this.options.right == "undefined")
      this.options.left = this._round(Math.random() * 500,this.options.gridX);
    if (this.options.effectOptions) {
      Object.extend(this.options.hideEffectOptions,this.options.effectOptions);
      Object.extend(this.options.showEffectOptions,this.options.effectOptions);
      if (this.options.showEffect == Element.Appear)
        this.options.showEffectOptions.to = this.options.opacity;
    }
    if (Window.hasEffectLib) {
      if (this.options.showEffect == Effect.Appear)
        this.options.showEffectOptions.to = this.options.opacity;
      if (this.options.hideEffect == Effect.Fade)
        this.options.hideEffectOptions.from = this.options.opacity;
    }
    if (this.options.hideEffect == Element.hide)
      this.options.hideEffect = function() { Element.hide(this.element);if (this.options.destroyOnClose) this.destroy(); } .bind(this)
    if (this.options.parent != document.body)
      this.options.parent = $(this.options.parent);
    this.element = this._createWindow(id);
    this.element.win = this;
    // Bind event listener
    this.eventMouseDown = this._initDrag.bindAsEventListener(this);
    this.eventMouseUp = this._endDrag.bindAsEventListener(this);
    this.eventMouseMove = this._updateDrag.bindAsEventListener(this);
    this.eventOnLoad = this._getWindowBorderSize.bindAsEventListener(this);
    this.eventMouseDownContent = this.toFront.bindAsEventListener(this);
    this.eventResize = this._recenter.bindAsEventListener(this);
    this.topbar = $(this.element.id + "_top");
    this.bottombar = $(this.element.id + "_bottom");
    this.content = $(this.element.id + "_content");
    Event.observe(this.topbar,"mousedown",this.eventMouseDown);
    Event.observe(this.bottombar,"mousedown",this.eventMouseDown);
    Event.observe(this.content,"mousedown",this.eventMouseDownContent);
    Event.observe(window,"load",this.eventOnLoad);
    Event.observe(window,"resize",this.eventResize);
    Event.observe(window,"scroll",this.eventResize);
    Event.observe(this.options.parent,"scroll",this.eventResize);
    if (this.options.draggable) {
      var that = this;
      [this.topbar,this.topbar.up().previous(),this.topbar.up().next()].each(function(element) {
        element.observe("mousedown",that.eventMouseDown);
        element.addClassName("top_draggable");
      });
      [this.bottombar.up(),this.bottombar.up().previous(),this.bottombar.up().next()].each(function(element) {
        element.observe("mousedown",that.eventMouseDown);
        element.addClassName("bottom_draggable");
      });
    }
    if (this.options.resizable) {
      this.sizer = $(this.element.id + "_sizer");
      Event.observe(this.sizer,"mousedown",this.eventMouseDown);
    }
    this.useLeft = null;
    this.useTop = null;
    if (typeof this.options.left != "undefined") {
      this.element.setStyle({ left: parseFloat(this.options.left) + 'px' });
      this.useLeft = true;
    }
    else {
      this.element.setStyle({ right: parseFloat(this.options.right) + 'px' });
      this.useLeft = false;
    }
    if (typeof this.options.top != "undefined") {
      this.element.setStyle({ top: parseFloat(this.options.top) + 'px' });
      this.useTop = true;
    }
    else {
      this.element.setStyle({ bottom: parseFloat(this.options.bottom) + 'px' });
      this.useTop = false;
    }
    this.storedLocation = null;
    this.setOpacity(this.options.opacity);
    if (this.options.zIndex)
      this.setZIndex(this.options.zIndex)
    if (this.options.destroyOnClose)
      this.setDestroyOnClose(true);
    this._getWindowBorderSize();
    this.width = this.options.width;
    this.height = this.options.height;
    this.visible = false;
    this.constraint = false;
    this.constraintPad = { top: 0,left: 0,bottom: 0,right: 0 };
    if (this.width && this.height)
      this.setSize(this.options.width,this.options.height);
    this.setTitle(this.options.title)
    Windows.register(this);
  },
  // Destructor
  destroy: function() {
    this._notify("onDestroy");
    Event.stopObserving(this.topbar,"mousedown",this.eventMouseDown);
    Event.stopObserving(this.bottombar,"mousedown",this.eventMouseDown);
    Event.stopObserving(this.content,"mousedown",this.eventMouseDownContent);
    Event.stopObserving(window,"load",this.eventOnLoad);
    Event.stopObserving(window,"resize",this.eventResize);
    Event.stopObserving(window,"scroll",this.eventResize);
    Event.stopObserving(this.content,"load",this.options.onload);
    if (this._oldParent) {
      var content = this.getContent();
      var originalContent = null;
      for (var i = 0;i < content.childNodes.length;i++) {
        originalContent = content.childNodes[i];
        if (originalContent.nodeType == 1)
          break;
        originalContent = null;
      }
      if (originalContent)
        this._oldParent.appendChild(originalContent);
      this._oldParent = null;
    }
    if (this.sizer)
      Event.stopObserving(this.sizer,"mousedown",this.eventMouseDown);
    if (this.options.url)
      this.content.src = null
    if (this.iefix)
      Element.remove(this.iefix);
    Element.remove(this.element);
    Windows.unregister(this);
  },
  // Sets close callback, if it sets, it should return true to be able to close the window.
  setCloseCallback: function(callback) {
    this.options.closeCallback = callback;
  },
  // Gets window content
  getContent: function() {
    return this.content;
  },
  // Sets the content with an element id
  setContent: function(id,autoresize,autoposition) {
    var element = $(id);
    if (null == element) throw "Unable to find element '" + id + "' in DOM";
    this._oldParent = element.parentNode;
    var d = null;
    var p = null;
    if (autoresize)
      d = Element.getDimensions(element);
    if (autoposition)
      p = Position.cumulativeOffset(element);
    var content = this.getContent();
    // Clear HTML (and even iframe)
    this.setHTMLContent("");
    content = this.getContent();
    content.appendChild(element);
    element.show();
    if (autoresize)
      this.setSize(d.width,d.height);
    if (autoposition)
      this.setLocation(p[1] - this.heightN,p[0] - this.widthW);
  },
  setHTMLContent: function(html) {
    // It was an url (iframe), recreate a div content instead of iframe content
    if (this.options.url) {
      this.content.src = null;
      this.options.url = null;
      var content = "<div id=\"" + this.getId() + "_content\" class=\"" + this.options.className + "_content\"> </div>";
      $(this.getId() + "_table_content").innerHTML = content;
      this.content = $(this.element.id + "_content");
    }
    this.getContent().innerHTML = html;
  },
  setAjaxContent: function(url,options,showCentered,showModal) {
    this.showFunction = showCentered ? "showCenter" : "show";
    this.showModal = showModal || false;
    options = options || {};
    // Clear HTML (and even iframe)
    this.setHTMLContent("");
    this.onComplete = options.onComplete;
    if (!this._onCompleteHandler)
      this._onCompleteHandler = this._setAjaxContent.bind(this);
    options.onComplete = this._onCompleteHandler;
    new Ajax.Request(url,options);
    options.onComplete = this.onComplete;
  },
  _setAjaxContent: function(originalRequest) {
    Element.update(this.getContent(),originalRequest.responseText);
    if (this.onComplete)
      this.onComplete(originalRequest);
    this.onComplete = null;
    this[this.showFunction](this.showModal)
  },
  setURL: function(url) {
    // Not an url content, change div to iframe
    if (this.options.url)
      this.content.src = null;
    this.options.url = url;
    var content = "<iframe frameborder='0' name='" + this.getId() + "_content'  id='" + this.getId() + "_content' src='" + url + "' width='" + this.width + "' height='" + this.height + "'> </iframe>";
    $(this.getId() + "_table_content").innerHTML = content;
    this.content = $(this.element.id + "_content");
  },
  getURL: function() {
    return this.options.url ? this.options.url : null;
  },
  refresh: function() {
    if (this.options.url)
      $(this.element.getAttribute('id') + '_content').src = this.options.url;
  },
  // Stores position/size in a cookie, by default named with window id
  setCookie: function(name,expires,path,domain,secure) {
    name = name || this.element.id;
    this.cookie = [name,expires,path,domain,secure];
    // Get cookie
    var value = WindowUtilities.getCookie(name)
    // If exists
    if (value) {
      var values = value.split(',');
      var x = values[0].split(':');
      var y = values[1].split(':');
      var w = parseFloat(values[2]),h = parseFloat(values[3]);
      var mini = values[4];
      var maxi = values[5];
      this.setSize(w,h);
      if (mini == "true")
        this.doMinimize = true; // Minimize will be done at onload window event
      else if (maxi == "true")
        this.doMaximize = true; // Maximize will be done at onload window event
      this.useLeft = x[0] == "l";
      this.useTop = y[0] == "t";
      this.element.setStyle(this.useLeft ? { left: x[1]} : { right: x[1] });
      this.element.setStyle(this.useTop ? { top: y[1]} : { bottom: y[1] });
    }
  },
  // Gets window ID
  getId: function() {
    return this.element.id;
  },
  // Detroys itself when closing 
  setDestroyOnClose: function() {
    this.options.destroyOnClose = true;
  },
  setConstraint: function(bool,padding) {
    this.constraint = bool;
    this.constraintPad = Object.extend(this.constraintPad,padding || {});
    // Reset location to apply constraint
    if (this.useTop && this.useLeft)
      this.setLocation(parseFloat(this.element.style.top),parseFloat(this.element.style.left));
  },
  // initDrag event
  _initDrag: function(event) {
    // No resize on minimized window
    if (Event.element(event) == this.sizer && this.isMinimized())
      return;
    // No move on maximzed window
    if (Event.element(event) != this.sizer && this.isMaximized())
      return;
    if (Prototype.Browser.IE && this.heightN == 0)
      this._getWindowBorderSize();
    // Get pointer X,Y
    this.pointer = [this._round(Event.pointerX(event),this.options.gridX),this._round(Event.pointerY(event),this.options.gridY)];
    if (this.options.wiredDrag)
      this.currentDrag = this._createWiredElement();
    else
      this.currentDrag = this.element;
    // Resize
    if (Event.element(event) == this.sizer) {
      this.doResize = true;
      this.widthOrg = this.width;
      this.heightOrg = this.height;
      this.bottomOrg = parseFloat(this.element.getStyle('bottom'));
      this.rightOrg = parseFloat(this.element.getStyle('right'));
      this._notify("onStartResize");
    }
    else {
      this.doResize = false;
      // Check if click on close button, 
      var closeButton = $(this.getId() + '_close');
      if (closeButton && Position.within(closeButton,this.pointer[0],this.pointer[1])) {
        this.currentDrag = null;
        return;
      }
      this.toFront();
      if (!this.options.draggable)
        return;
      this._notify("onStartMove");
    }
    // Register global event to capture mouseUp and mouseMove
    Event.observe(document,"mouseup",this.eventMouseUp,false);
    Event.observe(document,"mousemove",this.eventMouseMove,false);
    // Add an invisible div to keep catching mouse event over iframes
    WindowUtilities.disableScreen('__invisible__','__invisible__',this.overlayOpacity);
    // Stop selection while dragging
    document.body.ondrag = function() { return false; };
    document.body.onselectstart = function() { return false; };
    this.currentDrag.show();
    Event.stop(event);
  },
  _round: function(val,round) {
    return round == 1 ? val : val = Math.floor(val / round) * round;
  },
  // updateDrag event
  _updateDrag: function(event) {
    var pointer = [this._round(Event.pointerX(event),this.options.gridX),this._round(Event.pointerY(event),this.options.gridY)];
    var dx = pointer[0] - this.pointer[0];
    var dy = pointer[1] - this.pointer[1];
    // Resize case, update width/height
    if (this.doResize) {
      var w = this.widthOrg + dx;
      var h = this.heightOrg + dy;
      dx = this.width - this.widthOrg
      dy = this.height - this.heightOrg
      // Check if it's a right position, update it to keep upper-left corner at the same position
      if (this.useLeft)
        w = this._updateWidthConstraint(w)
      else
        this.currentDrag.setStyle({ right: (this.rightOrg - dx) + 'px' });
      // Check if it's a bottom position, update it to keep upper-left corner at the same position
      if (this.useTop)
        h = this._updateHeightConstraint(h)
      else
        this.currentDrag.setStyle({ bottom: (this.bottomOrg - dy) + 'px' });
      this.setSize(w,h);
      this._notify("onResize");
    }
    // Move case, update top/left
    else {
      this.pointer = pointer;
      if (this.useLeft) {
        var left = parseFloat(this.currentDrag.getStyle('left')) + dx;
        var newLeft = this._updateLeftConstraint(left);
        // Keep mouse pointer correct
        this.pointer[0] += newLeft - left;
        this.currentDrag.setStyle({ left: newLeft + 'px' });
      }
      else
        this.currentDrag.setStyle({ right: parseFloat(this.currentDrag.getStyle('right')) - dx + 'px' });
      if (this.useTop) {
        var top = parseFloat(this.currentDrag.getStyle('top')) + dy;
        var newTop = this._updateTopConstraint(top);
        // Keep mouse pointer correct
        this.pointer[1] += newTop - top;
        this.currentDrag.setStyle({ top: newTop + 'px' });
      }
      else
        this.currentDrag.setStyle({ bottom: parseFloat(this.currentDrag.getStyle('bottom')) - dy + 'px' });
      this._notify("onMove");
    }
    if (this.iefix)
      this._fixIEOverlapping();
    this._removeStoreLocation();
    Event.stop(event);
  },
  // endDrag callback
  _endDrag: function(event) {
    // Remove temporary div over iframes
    WindowUtilities.enableScreen('__invisible__');
    if (this.doResize)
      this._notify("onEndResize");
    else
      this._notify("onEndMove");
    // Release event observing
    Event.stopObserving(document,"mouseup",this.eventMouseUp,false);
    Event.stopObserving(document,"mousemove",this.eventMouseMove,false);
    Event.stop(event);
    this._hideWiredElement();
    // Store new location/size if need be
    this._saveCookie()
    // Restore selection
    document.body.ondrag = null;
    document.body.onselectstart = null;
  },
  _updateLeftConstraint: function(left) {
    if (this.constraint && this.useLeft && this.useTop) {
      var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width;
      if (left < this.constraintPad.left)
        left = this.constraintPad.left;
      if (left + this.width + this.widthE + this.widthW > width - this.constraintPad.right)
        left = width - this.constraintPad.right - this.width - this.widthE - this.widthW;
    }
    return left;
  },
  _updateTopConstraint: function(top) {
    if (this.constraint && this.useLeft && this.useTop) {
      var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height;
      var h = this.height + this.heightN + this.heightS;
      if (top < this.constraintPad.top)
        top = this.constraintPad.top;
      if (top + h > height - this.constraintPad.bottom)
        top = height - this.constraintPad.bottom - h;
    }
    return top;
  },
  _updateWidthConstraint: function(w) {
    if (this.constraint && this.useLeft && this.useTop) {
      var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width;
      var left = parseFloat(this.element.getStyle("left"));
      if (left + w + this.widthE + this.widthW > width - this.constraintPad.right)
        w = width - this.constraintPad.right - left - this.widthE - this.widthW;
    }
    return w;
  },
  _updateHeightConstraint: function(h) {
    if (this.constraint && this.useLeft && this.useTop) {
      var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height;
      var top = parseFloat(this.element.getStyle("top"));
      if (top + h + this.heightN + this.heightS > height - this.constraintPad.bottom)
        h = height - this.constraintPad.bottom - top - this.heightN - this.heightS;
    }
    return h;
  },
  // Creates HTML window code
  _createWindow: function(id) {
    var className = this.options.className;
    var win = document.createElement("div");
    win.setAttribute('id',id);
    win.className = "dialog";
    var content;
    if (this.options.url)
      content = "<iframe frameborder=\"0\" name=\"" + id + "_content\"  id=\"" + id + "_content\" src=\"" + this.options.url + "\"> </iframe>";
    else
      content = "<div id=\"" + id + "_content\" class=\"" + className + "_content\"> </div>";
    var closeDiv = this.options.closable ? "<div class='" + className + "_close' id='" + id + "_close' onclick='Windows.close(\"" + id + "\", event)'> </div>" : "";
    var minDiv = this.options.minimizable ? "<div class='" + className + "_minimize' id='" + id + "_minimize' onclick='Windows.minimize(\"" + id + "\", event)'> </div>" : "";
    var maxDiv = this.options.maximizable ? "<div class='" + className + "_maximize' id='" + id + "_maximize' onclick='Windows.maximize(\"" + id + "\", event)'> </div>" : "";
    var seAttributes = this.options.resizable ? "class='" + className + "_sizer' id='" + id + "_sizer'" : "class='" + className + "_se'";
    var blank = "../themes/default/blank.gif";
    win.innerHTML = closeDiv + minDiv + maxDiv + "\
      <table id='" + id + "_row1' class=\"top table_window\">\
        <tr>\
          <td class='" + className + "_nw'></td>\
          <td class='" + className + "_n'><div id='" + id + "_top' class='" + className + "_title title_window'>" + this.options.title + "</div></td>\
          <td class='" + className + "_ne'></td>\
        </tr>\
      </table>\
      <table id='" + id + "_row2' class=\"mid table_window\">\
        <tr>\
          <td class='" + className + "_w'></td>\
          <td id='" + id + "_table_content' class='" + className + "_content' valign='top'>" + content + "</td>\
          <td class='" + className + "_e'></td>\
        </tr>\
      </table>\
      <table id='" + id + "_row3' class=\"bot table_window\">\
        <tr>\
          <td class='" + className + "_sw'><div><span style='float:left; width:1px; height:1px'>&nbsp;</span></div></td>\
          <td class='" + className + "_s'><div id='" + id + "_bottom' class='status_bar'><span style='float:left; width:1px; height:1px'>&nbsp;</span></div></td>\
          <td " + seAttributes + "><div><span style='float:left; width:1px; height:1px'>&nbsp;</span></div></td>\
        </tr>\
      </table>";
    var alternateHTML = closeDiv + minDiv + maxDiv + "\
      <div id='" + id + "_row2'>\
        <div id='" + id + "_table_content' class='" + className + "_content'>" + content + "</div>\
      </div>\
      <div style='display:none; position:absolute; bottom:0; z-index:0;'>\
        <div id='" + id + "_row1'>\
          <div id='" + id + "_top' class='" + className + "_title title_window'>" + this.options.title + "</div>\
        </div>\
        <div id='" + id + "_row3'>\
          <div id='" + id + "_bottom' class='status_bar'></div>\
          <div " + seAttributes + "></div>\
        </div>\
      </div>";
    win.innerHTML = this.options.wrap ? win.innerHTML : alternateHTML;
    Element.hide(win);
    this.options.parent.insertBefore(win,this.options.parent.firstChild);
    Event.observe($(id + "_content"),"load",this.options.onload);
    return win;
  },
  changeClassName: function(newClassName) {
    var className = this.options.className;
    var id = this.getId();
    $A(["_close","_minimize","_maximize","_sizer","_content"]).each(function(value) { this._toggleClassName($(id + value),className + value,newClassName + value) } .bind(this));
    this._toggleClassName($(id + "_top"),className + "_title",newClassName + "_title");
    $$("#" + id + " td").each(function(td) { td.className = td.className.sub(className,newClassName); });
    this.options.className = newClassName;
  },
  _toggleClassName: function(element,oldClassName,newClassName) {
    if (element) {
      element.removeClassName(oldClassName);
      element.addClassName(newClassName);
    }
  },
  // Sets window location
  setLocation: function(top,left) {
    top = this._updateTopConstraint(top);
    left = this._updateLeftConstraint(left);
    var e = this.currentDrag || this.element;
    e.setStyle({ top: top + 'px' });
    e.setStyle({ left: left + 'px' });
    this.useLeft = true;
    this.useTop = true;
  },
  getLocation: function() {
    var location = {};
    if (this.useTop)
      location = Object.extend(location,{ top: this.element.getStyle("top") });
    else
      location = Object.extend(location,{ bottom: this.element.getStyle("bottom") });
    if (this.useLeft)
      location = Object.extend(location,{ left: this.element.getStyle("left") });
    else
      location = Object.extend(location,{ right: this.element.getStyle("right") });
    return location;
  },
  // Gets window size
  getSize: function() {
    return { width: this.width,height: this.height };
  },
  // Sets window size
  setSize: function(width,height,useEffect) {
    width = parseFloat(width);
    height = parseFloat(height);
    // Check min and max size
    if (!this.minimized && width < this.options.minWidth)
      width = this.options.minWidth;
    if (!this.minimized && height < this.options.minHeight)
      height = this.options.minHeight;
    if (this.options.maxHeight && height > this.options.maxHeight)
      height = this.options.maxHeight;
    if (this.options.maxWidth && width > this.options.maxWidth)
      width = this.options.maxWidth;
    if (this.useTop && this.useLeft && Window.hasEffectLib && Effect.ResizeWindow && useEffect) {
      new Effect.ResizeWindow(this,null,null,width,height,{ duration: Window.resizeEffectDuration });
    } else {
      this.width = width;
      this.height = height;
      var e = this.currentDrag ? this.currentDrag : this.element;
      e.setStyle({ width: width + this.widthW + this.widthE + "px" })
      e.setStyle({ height: height + this.heightN + this.heightS + "px" })
      // Update content size
      if (!this.currentDrag || this.currentDrag == this.element) {
        var content = $(this.element.id + '_content');
        content.setStyle({ height: height + 'px' });
        content.setStyle({ width: width + 'px' });
      }
    }
  },
  updateHeight: function() {
    this.setSize(this.width,this.content.scrollHeight,true);
  },
  updateWidth: function() {
    this.setSize(this.content.scrollWidth,this.height,true);
  },
  // Brings window to front
  toFront: function() {
    if (this.element.style.zIndex < Windows.maxZIndex)
      this.setZIndex(Windows.maxZIndex + 1);
    if (this.iefix)
      this._fixIEOverlapping();
  },
  getBounds: function(insideOnly) {
    if (!this.width || !this.height || !this.visible)
      this.computeBounds();
    var w = this.width;
    var h = this.height;
    if (!insideOnly) {
      w += this.widthW + this.widthE;
      h += this.heightN + this.heightS;
    }
    var bounds = Object.extend(this.getLocation(),{ width: w + "px",height: h + "px" });
    return bounds;
  },
  computeBounds: function() {
    if (!this.width || !this.height) {
      var size = WindowUtilities._computeSize(this.content.innerHTML,this.content.id,this.width,this.height,0,this.options.className)
      if (this.height)
        this.width = size + 5
      else
        this.height = size + 5
    }
    this.setSize(this.width,this.height);
    if (this.centered)
      this._center(this.centerTop,this.centerLeft);
  },
  // Displays window modal state or not
  show: function(modal) {
    this.visible = true;
    if (modal) {
      // Hack for Safari !!
      if (typeof this.overlayOpacity == "undefined") {
        var that = this;
        setTimeout(function() { that.show(modal) },10);
        return;
      }
      Windows.addModalWindow(this);
      this.modal = true;
      this.setZIndex(Windows.maxZIndex + 1);
      Windows.unsetOverflow(this);
    }
    else
      if (!this.element.style.zIndex)
      this.setZIndex(Windows.maxZIndex + 1);
    // To restore overflow if need be
    if (this.oldStyle)
      this.getContent().setStyle({ overflow: this.oldStyle });
    this.computeBounds();
    this._notify("onBeforeShow");
    if (this.options.showEffect != Element.show && this.options.showEffectOptions)
      this.options.showEffect(this.element,this.options.showEffectOptions);
    else
      this.options.showEffect(this.element);
    //this._checkIEOverlapping();
    WindowUtilities.focusedWindow = this
    this._notify("onShow");
  },
  // Displays window modal state or not at the center of the page
  showCenter: function(modal,top,left) {
    this.centered = true;
    this.centerTop = top;
    this.centerLeft = left;
    this.show(modal);
  },
  isVisible: function() {
    return this.visible;
  },
  _center: function(top,left) {
    var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);
    var pageSize = WindowUtilities.getPageSize(this.options.parent);
    if (typeof top == "undefined")
      top = (pageSize.windowHeight - (this.height + this.heightN + this.heightS)) / 2;
    top += windowScroll.top
    if (typeof left == "undefined")
      left = (pageSize.windowWidth - (this.width + this.widthW + this.widthE)) / 2;
    left += windowScroll.left
    this.setLocation(top,left);
    this.toFront();
  },
  _recenter: function(event) {
    if (this.centered) {
      var pageSize = WindowUtilities.getPageSize(this.options.parent);
      var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);
      // Check for this stupid IE that sends dumb events
      if (this.pageSize && this.pageSize.windowWidth == pageSize.windowWidth && this.pageSize.windowHeight == pageSize.windowHeight &&
          this.windowScroll.left == windowScroll.left && this.windowScroll.top == windowScroll.top)
        return;
      this.pageSize = pageSize;
      this.windowScroll = windowScroll;
      // set height of Overlay to take up whole page and show
      if ($('overlay_modal'))
        $('overlay_modal').setStyle({ height: (pageSize.pageHeight + 'px') });
      if (this.options.recenterAuto)
        this._center(this.centerTop,this.centerLeft);
    }
  },
  // Hides window
  hide: function() {
    this.visible = false;
    if (this.modal) {
      Windows.removeModalWindow(this);
      Windows.resetOverflow();
    }
    // To avoid bug on scrolling bar
    this.oldStyle = this.getContent().getStyle('overflow') || "auto"
    this.getContent().setStyle({ overflow: "hidden" });
    this.options.hideEffect(this.element,this.options.hideEffectOptions);
    if (this.iefix)
      this.iefix.hide();
    if (!this.doNotNotifyHide)
      this._notify("onHide");
  },
  close: function() {
    // Asks closeCallback if exists
    if (this.visible) {
      if (this.options.closeCallback && !this.options.closeCallback(this))
        return;
      if (this.options.destroyOnClose) {
        var destroyFunc = this.destroy.bind(this);
        if (this.options.hideEffectOptions.afterFinish) {
          var func = this.options.hideEffectOptions.afterFinish;
          this.options.hideEffectOptions.afterFinish = function() { func();destroyFunc() }
        }
        else
          this.options.hideEffectOptions.afterFinish = function() { destroyFunc() }
      }
      Windows.updateFocusedWindow();
      this.doNotNotifyHide = true;
      this.hide();
      this.doNotNotifyHide = false;
      this._notify("onClose");
    }
  },
  minimize: function() {
    if (this.resizing)
      return;
    var r2 = $(this.getId() + "_row2");
    if (!this.minimized) {
      this.minimized = true;
      var dh = r2.getDimensions().height;
      this.r2Height = dh;
      var h = this.element.getHeight() - dh;
      if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
        new Effect.ResizeWindow(this,null,null,null,this.height - dh,{ duration: Window.resizeEffectDuration });
      } else {
        this.height -= dh;
        this.element.setStyle({ height: h + "px" });
        r2.hide();
      }
      if (!this.useTop) {
        var bottom = parseFloat(this.element.getStyle('bottom'));
        this.element.setStyle({ bottom: (bottom + dh) + 'px' });
      }
    }
    else {
      this.minimized = false;
      var dh = this.r2Height;
      this.r2Height = null;
      if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
        new Effect.ResizeWindow(this,null,null,null,this.height + dh,{ duration: Window.resizeEffectDuration });
      }
      else {
        var h = this.element.getHeight() + dh;
        this.height += dh;
        this.element.setStyle({ height: h + "px" })
        r2.show();
      }
      if (!this.useTop) {
        var bottom = parseFloat(this.element.getStyle('bottom'));
        this.element.setStyle({ bottom: (bottom - dh) + 'px' });
      }
      this.toFront();
    }
    this._notify("onMinimize");
    // Store new location/size if need be
    this._saveCookie()
  },
  maximize: function() {
    if (this.isMinimized() || this.resizing)
      return;
    if (Prototype.Browser.IE && this.heightN == 0)
      this._getWindowBorderSize();
    if (this.storedLocation != null) {
      this._restoreLocation();
      if (this.iefix)
        this.iefix.hide();
    }
    else {
      this._storeLocation();
      Windows.unsetOverflow(this);
      var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);
      var pageSize = WindowUtilities.getPageSize(this.options.parent);
      var left = windowScroll.left;
      var top = windowScroll.top;
      if (this.options.parent != document.body) {
        windowScroll = { top: 0,left: 0,bottom: 0,right: 0 };
        var dim = this.options.parent.getDimensions();
        pageSize.windowWidth = dim.width;
        pageSize.windowHeight = dim.height;
        top = 0;
        left = 0;
      }
      if (this.constraint) {
        pageSize.windowWidth -= Math.max(0,this.constraintPad.left) + Math.max(0,this.constraintPad.right);
        pageSize.windowHeight -= Math.max(0,this.constraintPad.top) + Math.max(0,this.constraintPad.bottom);
        left += Math.max(0,this.constraintPad.left);
        top += Math.max(0,this.constraintPad.top);
      }
      var width = pageSize.windowWidth - this.widthW - this.widthE;
      var height = pageSize.windowHeight - this.heightN - this.heightS;
      if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
        new Effect.ResizeWindow(this,top,left,width,height,{ duration: Window.resizeEffectDuration });
      }
      else {
        this.setSize(width,height);
        this.element.setStyle(this.useLeft ? { left: left} : { right: left });
        this.element.setStyle(this.useTop ? { top: top} : { bottom: top });
      }
      this.toFront();
      if (this.iefix)
        this._fixIEOverlapping();
    }
    this._notify("onMaximize");
    // Store new location/size if need be
    this._saveCookie()
  },
  isMinimized: function() {
    return this.minimized;
  },
  isMaximized: function() {
    return (this.storedLocation != null);
  },
  setOpacity: function(opacity) {
    if (Element.setOpacity)
      Element.setOpacity(this.element,opacity);
  },
  setZIndex: function(zindex) {
    this.element.setStyle({ zIndex: zindex });
    Windows.updateZindex(zindex,this);
  },
  setTitle: function(newTitle) {
    if (!newTitle || newTitle == "")
      newTitle = "&nbsp;";
    Element.update(this.element.id + '_top',newTitle);
  },
  getTitle: function() {
    return $(this.element.id + '_top').innerHTML;
  },
  setStatusBar: function(element) {
    var statusBar = $(this.getId() + "_bottom");
    if (typeof (element) == "object") {
      if (this.bottombar.firstChild)
        this.bottombar.replaceChild(element,this.bottombar.firstChild);
      else
        this.bottombar.appendChild(element);
    }
    else
      this.bottombar.innerHTML = element;
  },
  _checkIEOverlapping: function() {
    if (!this.iefix && (navigator.appVersion.indexOf('MSIE') > 0) && (navigator.userAgent.indexOf('Opera') < 0) && (this.element.getStyle('position') == 'absolute')) {
      new Insertion.After(this.element.id,'<iframe id="' + this.element.id + '_iefix" ' + 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
      this.iefix = $(this.element.id + '_iefix');
    }
    if (this.iefix)
      setTimeout(this._fixIEOverlapping.bind(this),50);
  },
  _fixIEOverlapping: function() {
    Position.clone(this.element,this.iefix);
    this.iefix.style.zIndex = this.element.style.zIndex - 1;
    this.iefix.show();
  },
  _getWindowBorderSize: function(event) {
    // Hack to get real window border size!!
    var div = this._createHiddenDiv(this.options.className + "_n")
    this.heightN = Element.getDimensions(div).height;
    div.parentNode.removeChild(div)
    var div = this._createHiddenDiv(this.options.className + "_s")
    this.heightS = Element.getDimensions(div).height;
    div.parentNode.removeChild(div)
    var div = this._createHiddenDiv(this.options.className + "_e")
    this.widthE = Element.getDimensions(div).width;
    div.parentNode.removeChild(div)
    var div = this._createHiddenDiv(this.options.className + "_w")
    this.widthW = Element.getDimensions(div).width;
    div.parentNode.removeChild(div);
    var div = document.createElement("div");
    div.className = this.options.className + "_overlay";
    document.body.appendChild(div);
    //alert("no timeout:\nopacity: " + div.getStyle("opacity") + "\nwidth: " + document.defaultView.getComputedStyle(div, null).width);
    var that = this;
    // Workaround for Safari!!
    setTimeout(function() { that.overlayOpacity = ($(div).getStyle("opacity"));div.parentNode.removeChild(div); },10);
    // Workaround for IE!!
    if (Prototype.Browser.IE) {
      this.heightS = $(this.getId() + "_row3").getDimensions().height;
      this.heightN = $(this.getId() + "_row1").getDimensions().height;
    }
    // Safari size fix
    if (Prototype.Browser.WebKit && Prototype.Browser.WebKitVersion < 420)
      this.setSize(this.width,this.height);
    if (this.doMaximize)
      this.maximize();
    if (this.doMinimize)
      this.minimize();
  },
  _createHiddenDiv: function(className) {
    var objBody = document.body;
    var win = document.createElement("div");
    win.setAttribute('id',this.element.id + "_tmp");
    win.className = className;
    win.style.display = 'none';
    win.innerHTML = '';
    objBody.insertBefore(win,objBody.firstChild);
    return win;
  },
  _storeLocation: function() {
    if (this.storedLocation == null) {
      this.storedLocation = { useTop: this.useTop,useLeft: this.useLeft,
        top: this.element.getStyle('top'),bottom: this.element.getStyle('bottom'),
        left: this.element.getStyle('left'),right: this.element.getStyle('right'),
        width: this.width,height: this.height
      };
    }
  },
  _restoreLocation: function() {
    if (this.storedLocation != null) {
      this.useLeft = this.storedLocation.useLeft;
      this.useTop = this.storedLocation.useTop;
      if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow)
        new Effect.ResizeWindow(this,this.storedLocation.top,this.storedLocation.left,this.storedLocation.width,this.storedLocation.height,{ duration: Window.resizeEffectDuration });
      else {
        this.element.setStyle(this.useLeft ? { left: this.storedLocation.left} : { right: this.storedLocation.right });
        this.element.setStyle(this.useTop ? { top: this.storedLocation.top} : { bottom: this.storedLocation.bottom });
        this.setSize(this.storedLocation.width,this.storedLocation.height);
      }
      Windows.resetOverflow();
      this._removeStoreLocation();
    }
  },
  _removeStoreLocation: function() {
    this.storedLocation = null;
  },
  _saveCookie: function() {
    if (this.cookie) {
      var value = "";
      if (this.useLeft)
        value += "l:" + (this.storedLocation ? this.storedLocation.left : this.element.getStyle('left'))
      else
        value += "r:" + (this.storedLocation ? this.storedLocation.right : this.element.getStyle('right'))
      if (this.useTop)
        value += ",t:" + (this.storedLocation ? this.storedLocation.top : this.element.getStyle('top'))
      else
        value += ",b:" + (this.storedLocation ? this.storedLocation.bottom : this.element.getStyle('bottom'))
      value += "," + (this.storedLocation ? this.storedLocation.width : this.width);
      value += "," + (this.storedLocation ? this.storedLocation.height : this.height);
      value += "," + this.isMinimized();
      value += "," + this.isMaximized();
      WindowUtilities.setCookie(value,this.cookie)
    }
  },
  _createWiredElement: function() {
    if (!this.wiredElement) {
      if (Prototype.Browser.IE)
        this._getWindowBorderSize();
      var div = document.createElement("div");
      div.className = "wired_frame " + this.options.className + "_wired_frame";
      div.style.position = 'absolute';
      this.options.parent.insertBefore(div,this.options.parent.firstChild);
      this.wiredElement = $(div);
    }
    if (this.useLeft)
      this.wiredElement.setStyle({ left: this.element.getStyle('left') });
    else
      this.wiredElement.setStyle({ right: this.element.getStyle('right') });
    if (this.useTop)
      this.wiredElement.setStyle({ top: this.element.getStyle('top') });
    else
      this.wiredElement.setStyle({ bottom: this.element.getStyle('bottom') });
    var dim = this.element.getDimensions();
    this.wiredElement.setStyle({ width: dim.width + "px",height: dim.height + "px" });
    this.wiredElement.setStyle({ zIndex: Windows.maxZIndex + 30 });
    return this.wiredElement;
  },
  _hideWiredElement: function() {
    if (!this.wiredElement || !this.currentDrag)
      return;
    if (this.currentDrag == this.element)
      this.currentDrag = null;
    else {
      if (this.useLeft)
        this.element.setStyle({ left: this.currentDrag.getStyle('left') });
      else
        this.element.setStyle({ right: this.currentDrag.getStyle('right') });
      if (this.useTop)
        this.element.setStyle({ top: this.currentDrag.getStyle('top') });
      else
        this.element.setStyle({ bottom: this.currentDrag.getStyle('bottom') });
      this.currentDrag.hide();
      this.currentDrag = null;
      if (this.doResize)
        this.setSize(this.width,this.height);
    }
  },
  _notify: function(eventName) {
    if (this.options[eventName])
      this.options[eventName](this);
    else
      Windows.notify(eventName,this);
  }
};
// Windows containers, register all page windows
var Windows = {
  windows: [],
  modalWindows: [],
  observers: [],
  focusedWindow: null,
  maxZIndex: 0,
  overlayShowEffectOptions: { duration: 0.5 },
  overlayHideEffectOptions: { duration: 0.5 },
  addObserver: function(observer) {
    this.removeObserver(observer);
    this.observers.push(observer);
  },
  removeObserver: function(observer) {
    this.observers = this.observers.reject(function(o) { return o == observer });
  },
  // onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBlur onBeforeShow onShow onHide onMinimize onMaximize onClose
  notify: function(eventName,win) {
    this.observers.each(function(o) { if (o[eventName]) o[eventName](eventName,win); });
  },
  // Gets window from its id
  getWindow: function(id) {
    return this.windows.detect(function(d) { return d.getId() == id });
  },
  // Gets the last focused window
  getFocusedWindow: function() {
    return this.focusedWindow;
  },
  updateFocusedWindow: function() {
    this.focusedWindow = this.windows.length >= 2 ? this.windows[this.windows.length - 2] : null;
  },
  // Registers a new window (called by Windows constructor)
  register: function(win) {
    this.windows.push(win);
  },
  // Add a modal window in the stack
  addModalWindow: function(win) {
    // Disable screen if first modal window
    if (this.modalWindows.length == 0) {
      WindowUtilities.disableScreen(win.options.className,'overlay_modal',win.overlayOpacity,win.getId(),win.options.parent);
    }
    else {
      // Move overlay over all windows
      if (Window.keepMultiModalWindow) {
        $('overlay_modal').style.zIndex = Windows.maxZIndex + 1;
        Windows.maxZIndex += 1;
        WindowUtilities._hideSelect(this.modalWindows.last().getId());
      }
      // Hide current modal window
      else
        this.modalWindows.last().element.hide();
      // Fucking IE select issue
      WindowUtilities._showSelect(win.getId());
    }
    this.modalWindows.push(win);
  },
  removeModalWindow: function(win) {
    this.modalWindows.pop();
    // No more modal windows
    if (this.modalWindows.length == 0)
      WindowUtilities.enableScreen();
    else {
      if (Window.keepMultiModalWindow) {
        this.modalWindows.last().toFront();
        WindowUtilities._showSelect(this.modalWindows.last().getId());
      }
      else
        this.modalWindows.last().element.show();
    }
  },
  // Registers a new window (called by Windows constructor)
  register: function(win) {
    this.windows.push(win);
  },
  // Unregisters a window (called by Windows destructor)
  unregister: function(win) {
    this.windows = this.windows.reject(function(d) { return d == win });
  },
  // Closes all windows
  closeAll: function() {
    this.windows.each(function(w) { Windows.close(w.getId()) });
  },
  closeAllModalWindows: function() {
    WindowUtilities.enableScreen();
    this.modalWindows.each(function(win) { if (win) win.close() });
  },
  // Minimizes a window with its id
  minimize: function(id,event) {
    var win = this.getWindow(id)
    if (win && win.visible)
      win.minimize();
    Event.stop(event);
  },
  // Maximizes a window with its id
  maximize: function(id,event) {
    var win = this.getWindow(id)
    if (win && win.visible)
      win.maximize();
    Event.stop(event);
  },
  // Closes a window with its id
  close: function(id,event) {
    var win = this.getWindow(id);
    if (win)
      win.close();
    if (event)
      Event.stop(event);
  },
  blur: function(id) {
    var win = this.getWindow(id);
    if (!win)
      return;
    if (win.options.blurClassName)
      win.changeClassName(win.options.blurClassName);
    if (this.focusedWindow == win)
      this.focusedWindow = null;
    win._notify("onBlur");
  },
  focus: function(id) {
    var win = this.getWindow(id);
    if (!win)
      return;
    if (this.focusedWindow)
      this.blur(this.focusedWindow.getId())
    if (win.options.focusClassName)
      win.changeClassName(win.options.focusClassName);
    this.focusedWindow = win;
    win._notify("onFocus");
  },
  unsetOverflow: function(except) {
    this.windows.each(function(d) { d.oldOverflow = d.getContent().getStyle("overflow") || "auto";d.getContent().setStyle({ overflow: "hidden" }) });
    if (except && except.oldOverflow)
      except.getContent().setStyle({ overflow: except.oldOverflow });
  },
  resetOverflow: function() {
    this.windows.each(function(d) { if (d.oldOverflow) d.getContent().setStyle({ overflow: d.oldOverflow }) });
  },
  updateZindex: function(zindex,win) {
    if (zindex > this.maxZIndex) {
      this.maxZIndex = zindex;
      if (this.focusedWindow)
        this.blur(this.focusedWindow.getId())
    }
    this.focusedWindow = win;
    if (this.focusedWindow)
      this.focus(this.focusedWindow.getId())
  }
};
var Dialog = {
  dialogId: null,
  onCompleteFunc: null,
  callFunc: null,
  parameters: null,
  confirm: function(content,parameters) {
    // Get Ajax return before
    if (content && typeof content != "string") {
      Dialog._runAjaxRequest(content,parameters,Dialog.confirm);
      return
    }
    content = content || "";
    parameters = parameters || {};
    var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
    var cancelLabel = parameters.cancelLabel ? parameters.cancelLabel : "Cancel";
    // Backward compatibility
    parameters = Object.extend(parameters,parameters.windowParameters || {});
    parameters.windowParameters = parameters.windowParameters || {};
    parameters.className = parameters.className || "alert";
    var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'"
    var cancelButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " cancel_button'"
    var content = "\
      <div class='" + parameters.className + "_message'>" + content + "</div>\
        <div class='" + parameters.className + "_buttons'>\
          <input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()' " + okButtonClass + "/>\
          <input type='button' value='" + cancelLabel + "' onclick='Dialog.cancelCallback()' " + cancelButtonClass + "/>\
        </div>\
    ";
    return this._openDialog(content,parameters)
  },
  alert: function(content,parameters) {
    // Get Ajax return before
    if (content && typeof content != "string") {
      Dialog._runAjaxRequest(content,parameters,Dialog.alert);
      return
    }
    content = content || "";
    parameters = parameters || {};
    var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
    // Backward compatibility    
    parameters = Object.extend(parameters,parameters.windowParameters || {});
    parameters.windowParameters = parameters.windowParameters || {};
    parameters.className = parameters.className || "alert";
    var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'"
    var content = "\
      <div class='" + parameters.className + "_message'>" + content + "</div>\
        <div class='" + parameters.className + "_buttons'>\
          <input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()' " + okButtonClass + "/>\
        </div>";
    return this._openDialog(content,parameters)
  },
  info: function(content,parameters) {
    // Get Ajax return before
    if (content && typeof content != "string") {
      Dialog._runAjaxRequest(content,parameters,Dialog.info);
      return
    }
    content = content || "";
    // Backward compatibility
    parameters = parameters || {};
    parameters = Object.extend(parameters,parameters.windowParameters || {});
    parameters.windowParameters = parameters.windowParameters || {};
    parameters.className = parameters.className || "alert";
    var content = "<div id='modal_dialog_message' class='" + parameters.className + "_message'>" + content + "</div>";
    if (parameters.showProgress)
      content += "<div id='modal_dialog_progress' class='" + parameters.className + "_progress'>  </div>";
    parameters.ok = null;
    parameters.cancel = null;
    return this._openDialog(content,parameters)
  },
  setInfoMessage: function(message) {
    $('modal_dialog_message').update(message);
  },
  closeInfo: function() {
    Windows.close(this.dialogId);
  },
  _openDialog: function(content,parameters) {
    var className = parameters.className;
    if (!parameters.height && !parameters.width) {
      parameters.width = WindowUtilities.getPageSize(parameters.options.parent || document.body).pageWidth / 2;
    }
    if (parameters.id)
      this.dialogId = parameters.id;
    else {
      var t = new Date();
      this.dialogId = 'modal_dialog_' + t.getTime();
      parameters.id = this.dialogId;
    }
    // compute height or width if need be
    if (!parameters.height || !parameters.width) {
      var size = WindowUtilities._computeSize(content,this.dialogId,parameters.width,parameters.height,5,className)
      if (parameters.height)
        parameters.width = size + 5
      else
        parameters.height = size + 5
    }
    parameters.effectOptions = parameters.effectOptions;
    parameters.resizable = parameters.resizable || false;
    parameters.minimizable = parameters.minimizable || false;
    parameters.maximizable = parameters.maximizable || false;
    parameters.draggable = parameters.draggable || false;
    parameters.closable = parameters.closable || false;
    var win = new Window(parameters);
    win.getContent().innerHTML = content;
    win.showCenter(true,parameters.top,parameters.left);
    win.setDestroyOnClose();
    win.cancelCallback = parameters.onCancel || parameters.cancel;
    win.okCallback = parameters.onOk || parameters.ok;
    return win;
  },
  _getAjaxContent: function(originalRequest) {
    Dialog.callFunc(originalRequest.responseText,Dialog.parameters)
  },
  _runAjaxRequest: function(message,parameters,callFunc) {
    if (message.options == null)
      message.options = {}
    Dialog.onCompleteFunc = message.options.onComplete;
    Dialog.parameters = parameters;
    Dialog.callFunc = callFunc;
    message.options.onComplete = Dialog._getAjaxContent;
    new Ajax.Request(message.url,message.options);
  },
  okCallback: function() {
    var win = Windows.focusedWindow;
    if (!win.okCallback || win.okCallback(win)) {
      // Remove onclick on button
      $$("#" + win.getId() + " input").each(function(element) { element.onclick = null; })
      win.close();
    }
  },
  cancelCallback: function() {
    var win = Windows.focusedWindow;
    // Remove onclick on button
    $$("#" + win.getId() + " input").each(function(element) { element.onclick = null })
    win.close();
    if (win.cancelCallback)
      win.cancelCallback(win);
  }
}
/*
Based on Lightbox JS: Fullsize Image Overlays 
by Lokesh Dhakar - http://www.huddletogether.com
For more information on this script, visit:
http://huddletogether.com/projects/lightbox/
Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
(basically, do anything you want, just leave my name and link)
*/
if (Prototype.Browser.WebKit) {
  var array = navigator.userAgent.match(new RegExp(/AppleWebKit\/([\d\.\+]*)/));
  Prototype.Browser.WebKitVersion = parseFloat(array[1]);
}
var WindowUtilities = {
  // From dragdrop.js
  getWindowScroll: function(parent) {
    var T,L,W,H;
    parent = parent || document.body;
    if (parent != document.body) {
      T = parent.scrollTop;
      L = parent.scrollLeft;
      W = parent.scrollWidth;
      H = parent.scrollHeight;
    }
    else {
      var w = window;
      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 };
  },
  //
  // getPageSize()
  // Returns array with page width, height and window width, height
  // Core code from - quirksmode.org
  // Edit for Firefox by pHaez
  //
  getPageSize: function(parent) {
    parent = parent || document.body;
    var windowWidth,windowHeight;
    var pageHeight,pageWidth;
    if (parent != document.body) {
      windowWidth = parent.getWidth();
      windowHeight = parent.getHeight();
      pageWidth = parent.scrollWidth;
      pageHeight = parent.scrollHeight;
    }
    else {
      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;
      }
      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;
      }
    }
    return { pageWidth: pageWidth,pageHeight: pageHeight,windowWidth: windowWidth,windowHeight: windowHeight };
  },
  disableScreen: function(className,overlayId,overlayOpacity,contentId,parent) {
    WindowUtilities.initLightbox(overlayId,className,function() { this._disableScreen(className,overlayId,overlayOpacity,contentId) } .bind(this),parent || document.body);
  },
  _disableScreen: function(className,overlayId,overlayOpacity,contentId) {
    // prep objects
    var objOverlay = $(overlayId);
    var pageSize = WindowUtilities.getPageSize(objOverlay.parentNode);
    // Hide select boxes as they will 'peek' through the image in IE, store old value
    if (contentId && Prototype.Browser.IE) {
      WindowUtilities._hideSelect();
      WindowUtilities._showSelect(contentId);
    }
    // set height of Overlay to take up whole page and show
    objOverlay.style.height = (pageSize.pageHeight + 'px');
    objOverlay.style.display = 'none';
    if (overlayId == "overlay_modal" && Window.hasEffectLib && Windows.overlayShowEffectOptions) {
      objOverlay.overlayOpacity = overlayOpacity;
      new Effect.Appear(objOverlay,Object.extend({ from: 0,to: overlayOpacity },Windows.overlayShowEffectOptions));
    }
    else
      objOverlay.style.display = "block";
  },
  enableScreen: function(id) {
    id = id || 'overlay_modal';
    var objOverlay = $(id);
    if (objOverlay) {
      // hide lightbox and overlay
      if (id == "overlay_modal" && Window.hasEffectLib && Windows.overlayHideEffectOptions)
        new Effect.Fade(objOverlay,Object.extend({ from: objOverlay.overlayOpacity,to: 0 },Windows.overlayHideEffectOptions));
      else {
        objOverlay.style.display = 'none';
        objOverlay.parentNode.removeChild(objOverlay);
      }
      // make select boxes visible using old value
      if (id != "__invisible__")
        WindowUtilities._showSelect();
    }
  },
  _hideSelect: function(id) {
    if (Prototype.Browser.IE) {
      id = id == null ? "" : "#" + id + " ";
      $$(id + 'select').each(function(element) {
        if (!WindowUtilities.isDefined(element.oldVisibility)) {
          element.oldVisibility = element.style.visibility ? element.style.visibility : "visible";
          element.style.visibility = "hidden";
        }
      });
    }
  },
  _showSelect: function(id) {
    if (Prototype.Browser.IE) {
      id = id == null ? "" : "#" + id + " ";
      $$(id + 'select').each(function(element) {
        if (WindowUtilities.isDefined(element.oldVisibility)) {
          // Why?? Ask IE
          try {
            element.style.visibility = element.oldVisibility;
          } catch (e) {
            element.style.visibility = "visible";
          }
          element.oldVisibility = null;
        }
        else {
          if (element.style.visibility)
            element.style.visibility = "visible";
        }
      });
    }
  },
  isDefined: function(object) {
    return typeof (object) != "undefined" && object != null;
  },
  initLightbox: function(id,className,doneHandler,parent) {
    // Already done, just update zIndex
    if ($(id)) {
      Element.setStyle(id,{ zIndex: Windows.maxZIndex + 1 });
      Windows.maxZIndex++;
      doneHandler();
    }
    // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
    else {
      var objOverlay = document.createElement("div");
      objOverlay.setAttribute('id',id);
      objOverlay.className = className + "_overlay"
      objOverlay.style.display = 'none';
      objOverlay.style.position = 'absolute';
      objOverlay.style.top = '0';
      objOverlay.style.left = '0';
      objOverlay.style.zIndex = Windows.maxZIndex + 1;
      Windows.maxZIndex++;
      objOverlay.style.width = '100%';
      parent.insertBefore(objOverlay,parent.firstChild);
      if (Prototype.Browser.WebKit && id == "overlay_modal") {
        setTimeout(function() { doneHandler() },10);
      }
      else
        doneHandler();
    }
  },
  setCookie: function(value,parameters) {
    document.cookie = parameters[0] + "=" + escape(value) +
      ((parameters[1]) ? "; expires=" + parameters[1].toGMTString() : "") +
      ((parameters[2]) ? "; path=" + parameters[2] : "") +
      ((parameters[3]) ? "; domain=" + parameters[3] : "") +
      ((parameters[4]) ? "; secure" : "");
  },
  getCookie: function(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));
  },
  _computeSize: function(content,id,width,height,margin,className) {
    var objBody = document.body;
    var tmpObj = document.createElement("div");
    tmpObj.setAttribute('id',id);
    tmpObj.className = className + "_content";
    if (height)
      tmpObj.style.height = height + "px"
    else
      tmpObj.style.width = width + "px"
    tmpObj.style.position = 'absolute';
    tmpObj.style.top = '0';
    tmpObj.style.left = '0';
    tmpObj.style.display = 'none';
    tmpObj.innerHTML = content;
    objBody.insertBefore(tmpObj,objBody.firstChild);
    var size;
    if (height)
      size = $(tmpObj).getDimensions().width + margin;
    else
      size = $(tmpObj).getDimensions().height + margin;
    objBody.removeChild(tmpObj);
    return size;
  }
}
// window_fix.js
Window.prototype.destroy = function() {
  this._notify("onDestroy");
  Event.stopObserving(this.topbar,"mousedown",this.eventMouseDown);
  Event.stopObserving(this.bottombar,"mousedown",this.eventMouseDown);
  Event.stopObserving(this.content,"mousedown",this.eventMouseDownContent);
  Event.stopObserving(window,"load",this.eventOnLoad);
  Event.stopObserving(window,"resize",this.eventResize);
  Event.stopObserving(window,"scroll",this.eventResize);
  Event.stopObserving(this.options.parent,"scroll",this.eventResize);
  Event.stopObserving(this.content,"load",this.options.onload);
  if (this._oldParent) {
    var content = this.getContent();
    var originalContent = null;
    for (var i = 0;i < content.childNodes.length;i++) {
      originalContent = content.childNodes[i];
      if (originalContent.nodeType == 1)
        break;
      originalContent = null;
    }
    if (originalContent)
      this._oldParent.appendChild(originalContent);
    this._oldParent = null;
  }
  if (this.sizer)
    Event.stopObserving(this.sizer,"mousedown",this.eventMouseDown);
  if (this.options.url)
    this.content.src = null
  if (this.iefix)
    Element.remove(this.iefix);
  Element.remove(this.element);
  Windows.unregister(this);
}
// window_ext.js
// Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com)
WindowStore = {
  doSetCookie: false,
  cookieName: "__window_store__",
  expired: null,
  init: function(cookieName,expired) {
    WindowStore.cookieName = cookieName || WindowStore.cookieName
    if (!expired) {
      var today = new Date();
      today.setYear(today.getYear() + 1903);
      WindowStore.expired = today;
    }
    else
      WindowStore.expired = expired;
    Windows.windows.each(function(win) {
      win.setCookie(win.getId(),WindowStore.expired);
    });
    // Create observer on show/hide events
    var myObserver = {
      onShow: function(eventName,win) {
        WindowStore._saveCookie();
      },
      onClose: function(eventName,win) {
        WindowStore._saveCookie();
      },
      onHide: function(eventName,win) {
        WindowStore._saveCookie();
      }
    }
    Windows.addObserver(myObserver);
    WindowStore._restoreWindows();
    WindowStore._saveCookie();
  },
  show: function(win) {
    eval("var cookie = " + WindowUtilities.getCookie(WindowStore.cookieName));
    if (cookie != null) {
      if (cookie[win.getId()])
        win.show();
    }
    else
      win.show();
  },
  // Function to store windows show/hide status in a cookie 
  _saveCookie: function() {
    if (!doSetCookie)
      return;
    var cookieValue = "{";
    Windows.windows.each(function(win) {
      if (cookieValue != "{")
        cookieValue += ","
      cookieValue += win.getId() + ": " + win.isVisible();
    });
    cookieValue += "}"
    WindowUtilities.setCookie(cookieValue,[WindowStore.cookieName,WindowStore.expired]);
  },
  // Function to restore windows show/hide status from a cookie if exists
  _restoreWindows: function() {
    eval("var cookie = " + WindowUtilities.getCookie(WindowStore.cookieName));
    if (cookie != null) {
      doSetCookie = false;
      Windows.windows.each(function(win) {
        if (cookie[win.getId()])
          win.show();
      });
    }
    doSetCookie = true;
  }
}
// Object to set a close key an all windows
WindowCloseKey = {
  keyCode: Event.KEY_ESC,
  init: function(keyCode) {
    if (keyCode)
      WindowCloseKey.keyCode = keyCode;
    Event.observe(document,'keydown',this._closeCurrentWindow.bindAsEventListener(this));
  },
  _closeCurrentWindow: function(event) {
    var e = event || window.event
    var characterCode = e.which || e.keyCode;
    // Check if there is a top window (it means it's an URL content)
    var win = top.Windows.focusedWindow;
    if (characterCode == WindowCloseKey.keyCode && win) {
      if (win.cancelCallback)
        top.Dialog.cancelCallback();
      else if (win.okCallback)
        top.Dialog.okCallback();
      else
        top.Windows.close(top.Windows.focusedWindow.getId());
    }
  }
}
// window_effects.js
Effect.ResizeWindow = Class.create();
Object.extend(Object.extend(Effect.ResizeWindow.prototype,Effect.Base.prototype),{
  initialize: function(win,top,left,width,height) {
    this.window = win;
    this.window.resizing = true;
    var size = win.getSize();
    this.initWidth = parseFloat(size.width);
    this.initHeight = parseFloat(size.height);
    var location = win.getLocation();
    this.initTop = parseFloat(location.top);
    this.initLeft = parseFloat(location.left);
    this.width = width != null ? parseFloat(width) : this.initWidth;
    this.height = height != null ? parseFloat(height) : this.initHeight;
    this.top = top != null ? parseFloat(top) : this.initTop;
    this.left = left != null ? parseFloat(left) : this.initLeft;
    this.dx = this.left - this.initLeft;
    this.dy = this.top - this.initTop;
    this.dw = this.width - this.initWidth;
    this.dh = this.height - this.initHeight;
    this.r2 = $(this.window.getId() + "_row2");
    this.content = $(this.window.getId() + "_content");
    this.contentOverflow = this.content.getStyle("overflow") || "auto";
    this.content.setStyle({ overflow: "hidden" });
    // Wired mode
    if (this.window.options.wiredDrag) {
      this.window.currentDrag = win._createWiredElement();
      this.window.currentDrag.show();
      this.window.element.hide();
    }
    this.start(arguments[5]);
  },
  update: function(position) {
    var width = Math.floor(this.initWidth + this.dw * position);
    var height = Math.floor(this.initHeight + this.dh * position);
    var top = Math.floor(this.initTop + this.dy * position);
    var left = Math.floor(this.initLeft + this.dx * position);
    if (window.ie) {
      if (Math.floor(height) == 0)
        this.r2.hide();
      else if (Math.floor(height) > 1)
        this.r2.show();
    }
    this.r2.setStyle({ height: height });
    this.window.setSize(width,height);
    this.window.setLocation(top,left);
  },
  finish: function(position) {
    // Wired mode
    if (this.window.options.wiredDrag) {
      this.window._hideWiredElement();
      this.window.element.show();
    }
    this.window.setSize(this.width,this.height);
    this.window.setLocation(this.top,this.left);
    this.r2.setStyle({ height: null });
    this.content.setStyle({ overflow: this.contentOverflow });
    this.window.resizing = false;
  }
});
Effect.ModalSlideDown = function(element) {
  var windowScroll = WindowUtilities.getWindowScroll();
  var height = element.getStyle("height");
  element.setStyle({ top: -(parseFloat(height) - windowScroll.top) + "px" });
  element.show();
  return new Effect.Move(element,Object.extend({ x: 0,y: parseFloat(height) },arguments[1] || {}));
};
Effect.ModalSlideUp = function(element) {
  var height = element.getStyle("height");
  return new Effect.Move(element,Object.extend({ x: 0,y: -parseFloat(height) },arguments[1] || {}));
};
PopupEffect = Class.create();
PopupEffect.prototype = {
  initialize: function(htmlElement) {
    this.html = $(htmlElement);
    this.options = Object.extend({ className: "popup_effect",duration: 0.4 },arguments[1] || {});
  },
  show: function(element,options) {
    var position = Position.cumulativeOffset(this.html);
    var size = this.html.getDimensions();
    var bounds = element.win.getBounds();
    this.window = element.win;
    // Create a div
    if (!this.div) {
      this.div = document.createElement("div");
      this.div.className = this.options.className;
      this.div.style.height = size.height + "px";
      this.div.style.width = size.width + "px";
      this.div.style.top = position[1] + "px";
      this.div.style.left = position[0] + "px";
      this.div.style.position = "absolute"
      document.body.appendChild(this.div);
    }
    if (this.options.fromOpacity)
      this.div.setStyle({ opacity: this.options.fromOpacity })
    this.div.show();
    var style = "top:" + bounds.top + ";left:" + bounds.left + ";width:" + bounds.width + ";height:" + bounds.height;
    if (this.options.toOpacity)
      style += ";opacity:" + this.options.toOpacity;
    new Effect.Morph(this.div,{ style: style,duration: this.options.duration,afterFinish: this._showWindow.bind(this) });
  },
  hide: function(element,options) {
    var position = Position.cumulativeOffset(this.html);
    var size = this.html.getDimensions();
    this.window.visible = true;
    var bounds = this.window.getBounds();
    this.window.visible = false;
    this.window.element.hide();
    this.div.style.height = bounds.height;
    this.div.style.width = bounds.width;
    this.div.style.top = bounds.top;
    this.div.style.left = bounds.left;
    if (this.options.toOpacity)
      this.div.setStyle({ opacity: this.options.toOpacity })
    this.div.show();
    var style = "top:" + position[1] + "px;left:" + position[0] + "px;width:" + size.width + "px;height:" + size.height + "px";
    if (this.options.fromOpacity)
      style += ";opacity:" + this.options.fromOpacity;
    new Effect.Morph(this.div,{ style: style,duration: this.options.duration,afterFinish: this._hideDiv.bind(this) });
  },
  _showWindow: function() {
    this.div.hide();
    this.window.element.show();
  },
  _hideDiv: function() {
    this.div.hide();
  }
}
