

// this function is needed to work around 
  // a bug in IE related to element attributes
  function hasClass(obj) {
     var result = false;
     if (obj.getAttributeNode("class") != null) {
         result = obj.getAttributeNode("class").value;
     }
     return result;
  }   

 function stripe(id) {

    // the flag we'll use to keep track of 
    // whether the current row is odd or even
    var even = false;
  
    // if arguments are provided to specify the colours
    // of the even & odd rows, then use the them;
    // otherwise use the following defaults:
    var evenColor = arguments[1] ? arguments[1] : "#fff";
    var oddColor = arguments[2] ? arguments[2] : "#eee";
  
    // obtain a reference to the desired table
    // if no such table exists, abort
    var table = document.getElementById(id);
    if (! table) { return; }
    
    // by definition, tables can have more than one tbody
    // element, so we'll have to get the list of child
    // &lt;tbody&gt;s 
    var tbodies = table.getElementsByTagName("tbody");

    // and iterate through them...
    for (var h = 0; h < tbodies.length; h++) {
    
     // find all the &lt;tr&gt; elements... 
      var trs = tbodies[h].getElementsByTagName("tr");
      
      // ... and iterate through them
      for (var i = 0; i < trs.length; i++) {

        // avoid rows that have a class attribute
        // or backgroundColor style
        if (! hasClass(trs[i]) &&
            ! trs[i].style.backgroundColor) {
 		  
          // get all the cells in this row...
          var tds = trs[i].getElementsByTagName("td");
        
          // and iterate through them...
          for (var j = 0; j < tds.length; j++) {
        
            var mytd = tds[j];

            // avoid cells that have a class attribute
            // or backgroundColor style
            if (! hasClass(mytd) &&
                ! mytd.style.backgroundColor) {
        
              mytd.style.backgroundColor = even ? evenColor : oddColor;
            
            }
          }
        }
        // flip from odd to even, or vice-versa
        even =  ! even;
      }
    }
  }
  
  
function tableruler() {
	if (document.getElementById && document.createTextNode) {
		var tables=document.getElementsByTagName ('table');
		for (var i=0;i<tables.length;i++) {
			var clasesTable = tables[i].className.split(" ");
			if(clasesTable[0]=='ruler') {
				var trs=tables[i].getElementsByTagName('tr');
				for(var j=0;j<trs.length;j++) {
					if(trs[j].parentNode.nodeName=='TBODY' && trs[j].parentNode.nodeName!='TFOOT') {
						trs[j].onmouseover=function(){this.className='ruled';return false}
						trs[j].onmouseout=function(){this.className='';return false}
					}
				}
			}
		}
	}
}

// Copyright (c) 2006 SÃƒÂ©bastien Gruhier (http://xilinus.com, http://itseb.com)
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// VERSION 1.0

Position.windowInfo = function() {
  var windowWidth, windowHeight;
  var pageWidth, pageHeight;
  
  if (window.innerHeight && window.scrollMaxY) {  
    pageWidth = document.body.scrollWidth;
    pageHeight = window.innerHeight + window.scrollMaxY;
  } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
    pageWidth = document.body.scrollWidth;
    pageHeight = document.body.scrollHeight;
  } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
    pageWidth = document.body.offsetWidth;
    pageHeight = 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;
  } 
  var xScroll = document.documentElement.scrollLeft || document.body.scrollLeft;
  var yScroll = document.documentElement.scrollTop || document.body.scrollTop;

  // for small pages with total height less then height of the viewport
  pageHeight = Math.max(windowHeight, pageHeight);

  // for small pages with total width less then width of the viewport
  pageWidth = Math.max(windowWidth, pageWidth);
  return { width: windowWidth, height: windowHeight, pageWidth: pageWidth, pageHeight: pageHeight, xScroll: xScroll, yScroll: yScroll};
}

var TransparentMenu = Class.create();

TransparentMenu.DefaultOptions = {
  top: null,
  left: null,
  showEffect: Effect.Appear,
  showEffectOptions: {duration: 0.2}, 
  hideEffect: Effect.Fade,
  hideEffectOptions: {duration: 0.2},
  showMode: "onload",
  hideMode: "timeout",
  hideDelay: 2,
  insideElement: {id: null, width: "auto", height: "auto"},
  afterElement: null,
  fullscreen: false
}
TransparentMenu.instances = $H();

TransparentMenu.hide = function(id) {
  if (TransparentMenu.instances[id])
    TransparentMenu.instances[id].hide();
}

TransparentMenu.show = function(id) {
  if (TransparentMenu.instances[id]) 
    TransparentMenu.instances[id].show();
  else 
    new TransparentMenu(id,  arguments[1]);
}

TransparentMenu.prototype = {
	initialize: function(id) {
	  this.options  = Object.extend(Object.extend({},TransparentMenu.DefaultOptions), arguments[1] || {});   
	  this.options.insideElement =  Object.extend(Object.extend({},TransparentMenu.DefaultOptions.insideElement), this.options.insideElement || {});   
		this.id = id;

		if (this.options.displayMode == "onload")
	    Event.observe(window, "load", this._init.bindAsEventListener(this));
	  else
	    this._init(null);
	  TransparentMenu.instances[id] = this;
  },
  
  show: function() {
    new this.options.showEffect(this.element, this.options.showEffectOptions);

    // Safari bug fix
    if (navigator.appVersion.match(/Konqueror|Safari|KHTML/))
      setTimeout(this._setPostion.bindAsEventListener(this), 10)

	
    if (this.options.hideMode == "timeout") {
      setTimeout(this.hide.bindAsEventListener(this), this.options.hideDelay*1000);
    }else if (this.options.hideMode == "click" || this.options.hideMode == "mousemove") {
      this.bindEvent = this._startHideEvent.bindAsEventListener(this);
      Event.observe(this.element, this.options.hideMode, this.bindEvent);      
    }    
  },
    
  hide: function() { 
    new this.options.hideEffect(this.element, this.options.hideEffectOptions);
  },
    
  _init: function(event) {
    this.element = $(this.id);
    this._setPostion();
    
    // Get opacity from css if not specify for Fade effect
    if (Element.getOpacity(this.element) && this.options.showEffect == Effect.Appear && ! this.options.showEffectOptions.to)
      this.options.showEffectOptions.to = Element.getOpacity(this.element);
     
    this.show(); 
  },
  
  _setPostion: function() {
    var windowInfo = Position.windowInfo();
    var dim = this.element.getDimensions();

    // Inside an element
    if (this.options.insideElement.id != null) {    
      var relativeElement = $(this.options.insideElement.id);
      var position = Position.cumulativeOffset(relativeElement);
      var dimension = relativeElement.getDimensions();
      this.element.style.left = position[0] + "px";
      this.element.style.top = position[1] + "px";

      if (this.options.insideElement.width == 'auto') {
        this.element.style.width =  dimension.width + "px";
      }
      if (this.options.insideElement.height == 'auto')
        this.element.style.height = dimension.height + "px";
    }
    // Else full screen message
    else if (this.options.fullscreen) { 
      this.element.style.left = "0px";
      this.element.style.top = "0px";
      this.element.style.width = windowInfo.pageWidth + "px";
      this.element.style.height = windowInfo.pageHeight + "px";
    }
    // Relative to body or element
    else {
      var dy = 0;  		
      // Relative to an element
      if (this.options.afterElement != null) {
        var position = Position.cumulativeOffset($(this.options.afterElement));
        dy =  position[1];
      }
      // Else to body, add yScroll to have it visible from anywhere
      else
        dy = windowInfo.yScroll;
        
      // Compute left position using user options
      if (this.options.left != null)
        this.element.style.left = windowInfo.xScroll + this.options.left + "px";
      else
        this.element.style.left = windowInfo.xScroll + ((windowInfo.width - dim.width) / 2 ) + "px";
      
      // Compute top position useing user options
      if (this.options.top != null)
        this.element.style.top = dy + this.options.top + "px";
      else
        this.element.style.top = dy + ((windowInfo.height - dim.height) / 2 ) + "px";
    }
  },
  
  _startHideEvent: function() {
    var dim = this.element.getDimensions();
    Event.stopObserving(window, this.options.hideMode, this.bindEvent);      
    setTimeout(this.hide.bindAsEventListener(this), 0);
  }
}


// Copyright (c) 2006 SÃ©bastien Gruhier (http://xilinus.com, http://itseb.com)
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// VERSION 0.96.2

var Window = Class.create();
Window.prototype = {
	// Constructor
	// Available parameters : className, title, minWidth, minHeight, maxWidth, maxHeight, width, height, top, left, bottom, right, resizable, zIndex, opacity, 
	//                        hideEffect, showEffect, showEffectOptions, hideEffectOptions, effectOptions, url, draggable, closable, minimizable, maximizable, parent, onload
	initialize: function(id) {
	  if ($(id))
	    alert("Window " + id + " is already register is the DOM!!, be sure to use setDestroyOnClose()")
	    
		this.hasEffectLib = String.prototype.parseColor != null;
		this.options = Object.extend({
		  className:         "dialog",
      minWidth:          100,
      minHeight:         20,
      resizable:         true,
      closable:          true,
      minimizable:       true,
      maximizable:       true,
      draggable:         true,
      userData:          null,
      showEffect:        (this.hasEffectLib ? Effect.Appear : Element.show),
      hideEffect:        (this.hasEffectLib ? Effect.Fade : Element.hide),
      showEffectOptions: {},
      hideEffectOptions: {},
      effectOptions:     null,
      parent:            document.getElementsByTagName("body").item(0),
      title:             "&nbsp;",
      url:               null,
      onload:            Prototype.emptyFunction,
      width:             200,
      height:            300,
      opacity:           1
    }, arguments[1] || {});
    		
	  if (this.options.effectOptions) {
	    Object.extend(this.options.hideEffectOptions, this.options.effectOptions);
	    Object.extend(this.options.showEffectOptions, this.options.effectOptions);
	  }
		if (this.options.hideEffect == Element.hide)
		  this.options.hideEffect = function(){ Element.hide(this.element); if (this.destroyOnClose) this.destroy(); }.bind(this)
		  
		this.element = this._createWindow(id);
		
		// Bind event listener
    this.eventMouseDown = this._initDrag.bindAsEventListener(this);
  	this.eventMouseUp   = this._endDrag.bindAsEventListener(this);
  	this.eventMouseMove = this._updateDrag.bindAsEventListener(this);
  	this.eventKeyPress  = this._keyPress.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);
  	
		if (this.options.draggable)  {
			this.bottombar.addClassName("bottom_draggable");
			this.topbar.addClassName("top_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 (arguments[1].left != null) {
			this.element.setStyle({left: parseFloat(arguments[1].left) + 'px'});
			this.useLeft = true;
		}
		if (arguments[1].right != null) {
			this.element.setStyle({right: parseFloat(arguments[1].right) + 'px'});
			this.useLeft = false;
		}
    if (this.useLeft == null) {
	    this.element.setStyle({left: "0px"});
			this.useLeft = true;
    }
    
		if (arguments[1].top != null) {
			this.element.setStyle({top: parseFloat(arguments[1].top) + 'px'});
			this.useTop = true;
		}
		if (arguments[1].bottom != null) {
			this.element.setStyle({bottom: parseFloat(arguments[1].bottom) + 'px'});			
			this.useTop = false;
		}
    if (this.useTop == null) {
			this.element.setStyle({top: "0px"});
			this.useTop = true;
    }

    this.storedLocation = null;
    
		this.setOpacity(this.options.opacity);
		if (this.options.zIndex)
			this.setZIndex(this.options.zIndex)

		this.destroyOnClose = false;

    this._getWindowBorderSize();
    this.width = this.options.width;
    this.height = this.options.height;
    
    if (this.width && this.height)
		  this.setSize(this.options.width, this.options.height);
		this.setTitle(this.options.title)
		Windows.register(this);	    
  },
  
	// Destructor
 	destroy: function() {
		Windows.notify("onDestroy", this);
		
  	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.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 window deleagte, should have functions: "canClose(window)" 
	setDelegate: function(delegate) {
		this.delegate = delegate
	},
	
	// Gets current window delegate
	getDelegate: function() {
		return this.delegate;
	},
	
	// Gets window content
	getContent: function () {
		return this.content;
	},
	
	// Sets the content with an element id
	setContent: function(id, autoresize, autoposition) {
		var d = null;
		var p = null;

		if (autoresize) 
			d = Element.getDimensions(id);
		if (autoposition) 
			p = Position.cumulativeOffset($(id));

		var content = this.getContent()
		content.appendChild($(id));
		$(id).show();
		if (autoresize) 
			this.setSize(d.width, d.height);
		if (autoposition) 
		  this.setLocation(p[1] - this.heightN, p[0] - this.widthW);	  
	},
	
	setAjaxContent: function(url, options, showCentered, showModal) {
	  this.showFunction = showCentered ? "showCenter" : "show";
	  this.showModal = showModal || false;
	
	  if (options == null)
	    options = {}  
	  this.onComplete = options.onComplete;
	  options.onComplete = this._setAjaxContent.bind(this);
	  
	  new Ajax.Request(url, options);
	},
	
	_setAjaxContent: function(originalRequest) {
	  this.getContent().innerHTML = originalRequest.responseText;
	  if (this.onComplete)
	    this.onComplete(originalRequest);
	  this[this.showFunction](this.showModal)
	},
	
	// 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() {
	  Object.extend(this.options.hideEffectOptions, {afterFinish:  this.destroy.bind(this)});
		this.destroyOnClose = true;
	},
	
	// initDrag event
	_initDrag: function(event) {
    // Get pointer X,Y
  	this.pointer = [Event.pointerX(event), Event.pointerY(event)];

    // 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'));
			Windows.notify("onStartResize", this);
		}
    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])) 
  			return;

  		this.toFront();

  		if (! this.options.draggable) 
  		  return;
  		Windows.notify("onStartMove", this);
    }  	
  	// 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__');

    // Stop selection while dragging
    document.body.ondrag = function () { return false; };
    document.body.onselectstart = function () { return false; };
    
    Event.stop(event);
  },

  // updateDrag event
	_updateDrag: function(event) {
   	var pointer = [Event.pointerX(event), Event.pointerY(event)];    
		var dx = pointer[0] - this.pointer[0];
		var dy = pointer[1] - this.pointer[1];
		
		// Resize case, update width/height
		if (this.doResize) {
			this.setSize(this.widthOrg + dx , 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) 
				this.element.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) 
				this.element.setStyle({bottom: (this.bottomOrg -dy) + 'px'});
		}
		// Move case, update top/left
		else {
		  this.pointer = pointer;
  		
			if (this.useLeft) 
				this.element.setStyle({left: parseFloat(this.element.getStyle('left')) + dx + 'px'});
			else 
				this.element.setStyle({right: parseFloat(this.element.getStyle('right')) - dx + 'px'});
			
			if (this.useTop) 
				this.element.setStyle({top: parseFloat(this.element.getStyle('top')) + dy + 'px'});
		  else 
				this.element.setStyle({bottom: parseFloat(this.element.getStyle('bottom')) - dy + 'px'});
		}
		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)
			Windows.notify("onEndResize", this);
		else
			Windows.notify("onEndMove", this);
		
		// Release event observing
		Event.stopObserving(document, "mouseup", this.eventMouseUp,false);
    Event.stopObserving(document, "mousemove", this.eventMouseMove, false);

		// Store new location/size if need be
		this._saveCookie()

    Event.stop(event);
    
    // Restore selection
    document.body.ondrag = null;
    document.body.onselectstart = null;
  },

	_keyPress: function(event) {
		//Dialog.cancelCallback();
	},
	
	// 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 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' onmouseup='Windows.close(\""+ id +"\")'> </div>" : "";
		var minDiv = this.options.minimizable ? "<div class='"+ className + "_minimize' id='"+ id +"_minimize' onmouseup='Windows.minimize(\""+ id +"\")'> </div>" : "";
		var maxDiv = this.options.maximizable ? "<div class='"+ className + "_maximize' id='"+ id +"_maximize' onmouseup='Windows.maximize(\""+ id +"\")'> </div>" : "";
		var seAttributes = this.options.resizable ? "class='" + className + "_sizer' id='" + id + "_sizer'" : "class='"  + className + "_se'";
		
    win.innerHTML = "<div class='"+ className +"_butts_container'>"+ closeDiv + minDiv + maxDiv + "</div>\
      <table id='"+ id +"_row1' class=\"top table_window\">\
        <tr>\
          <td class='"+ className +"_nw'>&nbsp;</td>\
          <td class='"+ className +"_n'><div id='"+ id +"_top' class='"+ className +"_title title_window'>"+ this.options.title +"</div></td>\
          <td class='"+ className +"_ne'>&nbsp;</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'>&nbsp;</td>\
            <td class='"+ className +"_s'><div id='"+ id +"_bottom' class='status_bar'>&nbsp;</div></td>\
            <td " + seAttributes + ">&nbsp;</td>\
        </tr>\
      </table>\
    ";
    
		Element.hide(win);
		this.options.parent.insertBefore(win, this.options.parent.firstChild);
		Event.observe($(id + "_content"), "load", this.options.onload);
		return win;
	},
	
	// Sets window location
	setLocation: function(top, left) {
	  if (top < 0)
	    top = 0;
    if (left < 0)
      left= 0
		this.element.setStyle({top: top + 'px'});
		this.element.setStyle({left: left + 'px'});
		this.useLeft = true;
		this.useTop = true;
	},
		
	// Gets window size
	getSize: function() {
	  return {width: this.width, height: this.height};
	},
		
	// Sets window size
	setSize: function(width, height) {    
	  width = parseFloat(width);
	  height = parseFloat(height);
	  
		// Check min and max size
		if (width < this.options.minWidth)
			width = this.options.minWidth;

		if (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;

  	this.width = width;
		this.height = height;
		this.element.setStyle({width: width + this.widthW + this.widthE + "px"})
		this.element.setStyle({height: height  + this.heightN + this.heightS + "px"})

		// Update content height
		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)
	},
	
	updateWidth: function() {
    this.setSize(this.content.scrollWidth, this.height)
	},
	
	// Brings window to front
	toFront: function() {
    this.setZIndex(Windows.maxZIndex + 20);
    Windows.notify("onFocus", this);
	},
	
	// Displays window modal state or not
	show: function(modal) {
		if (modal) {
			WindowUtilities.disableScreen(this.options.className, 'overlay_modal', this.getId());
			this.modal = true;			
			this.setZIndex(Windows.maxZIndex + 20);
			Windows.unsetOverflow(this);
			Event.observe(document, "keypress", this.eventKeyPress);	      	
		}
		
		// To restore overflow if need be
		if (this.oldStyle)
		  this.getContent().setStyle({overflow: this.oldStyle});
			
		if (! this.width || !this.height) {
      var size = WindowUtilities._computeSize(this.content.innerHTML, this.content.id, this.width, this.height, 0)
  		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);		
		  
		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();
    Windows.notify("onShow", this);    
	},
	
	// 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.element.visible();
	},
	
	_center: function(top, left) {
		var windowScroll = WindowUtilities.getWindowScroll();    
		var pageSize = WindowUtilities.getPageSize();    

    if (!top)
      top = (pageSize.windowHeight - (this.height + this.heightN + this.heightS))/2;
    top += windowScroll.top
    
    if (!left)
      left = (pageSize.windowWidth - (this.width + this.widthW + this.widthE))/2;
    left += windowScroll.left 
    
    this.setLocation(top, left);
    this.toFront();
	},
	
	_recenter: function(event) {
	  if (this.modal) {
  		var pageSize = WindowUtilities.getPageSize();
  		// set height of Overlay to take up whole page and show
  		if ($('overlay_modal')) {
  		  $('overlay_modal').style.height = (pageSize.pageHeight + 'px');
  		  $('overlay_modal').style.width = (pageSize.pageWidth + 'px');
      }		
  		if (this.centered)
  		  this._center(this.centerTop, this.centerLeft);		
	  }
	},
	
	// Hides window
	hide: function() {
		if (this.modal) {
			WindowUtilities.enableScreen();
			Windows.resetOverflow();
			Event.stopObserving(document, "keypress", this.eventKeyPress);			
		}
		// 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();
		Windows.notify("onHide", this);
	},

  minimize: function() {
    var r2 = $(this.getId() + "_row2");
    var dh = r2.getDimensions().height;
    
    if (r2.visible()) {
      var h  = this.element.getHeight() - dh
      r2.hide()
  		this.element.setStyle({height: h + "px"})
  		if (! this.useTop) {
  		  var bottom = parseFloat(this.element.getStyle('bottom'));
			  this.element.setStyle({bottom: (bottom + dh) + 'px'});
		  }
    } 
    else {
      var h  = this.element.getHeight() + dh;
      this.element.setStyle({height: h + "px"})
  		if (! this.useTop) {
  		  var bottom = parseFloat(this.element.getStyle('bottom'));
			  this.element.setStyle({bottom: (bottom - dh) + 'px'});
		  }
      r2.show();
  		
      this.toFront();
    }
    Windows.notify("onMinimize", this);
		
    // Store new location/size if need be
		this._saveCookie()
  },
  
  maximize: function() {
    if (this.storedLocation != null) {
      this._restoreLocation();
      if(this.iefix) 
  			this.iefix.hide();
    }
    else {
      this._storeLocation();
      Windows.unsetOverflow(this);
      
      var windowScroll = WindowUtilities.getWindowScroll();
  		var pageSize = WindowUtilities.getPageSize();    

			this.element.setStyle(this.useLeft ? {left: windowScroll.left} : {right: windowScroll.left});
  		this.element.setStyle(this.useTop ? {top: windowScroll.top} : {bottom: windowScroll.top});

      this.setSize(pageSize.windowWidth - this.widthW - this.widthE, pageSize.windowHeight - this.heightN - this.heightS)
      this.toFront();
      if (this.iefix) 
  			this._fixIEOverlapping(); 
    }
		Windows.notify("onMaximize", this);

		// Store new location/size if need be
		this._saveCookie()
  },
  
  isMinimized: function() {
    var r2 = $(this.getId() + "_row2");
    return !r2.visible();
  },
  
  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);
  },

	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);
		// Safari size fix
		if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
		  this.setSize(this.width, this.height);
		if (this.doMaximize)
		  this.maximize();
		if (this.doMinimize)
		  this.minimize();
  },
 
  _createHiddenDiv: function(className) {
    var objBody = document.getElementsByTagName("body").item(0);
    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;
      
      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)
    }
  }
};

// Windows containers, register all page windows
var Windows = {
  windows: [],
  observers: [],
  focusedWindow: null,
  maxZIndex: 0,

  addObserver: function(observer) {
    this.removeObserver(observer);
    this.observers.push(observer);
  },
  
  removeObserver: function(observer) {  
    this.observers = this.observers.reject( function(o) { return o==observer });
  },
  
  notify: function(eventName, win) {  //  onStartResize(), onEndResize(), onStartMove(), onEndMove(), onClose(), onDestroy(), onMinimize(), onMaximize(), onHide(), onShow(), onFocus()
    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;
  },

  // 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 a window with its id
  close: function(id) {
  	var win = this.getWindow(id);
  	// Asks delegate if exists
    if (win) {
	  	if (win.getDelegate() && ! win.getDelegate().canClose(win)) 
	  		return;
	      if ($(id + "_close"))
	        $(id + "_close").onclick = null;
	      if ($(id + "_minimize"))
	        $(id + "_minimize").onclick = null;	        
	      if ($(id + "_maximize"))
	        $(id + "_maximize").onclick = null;	      
	      
  			this.notify("onClose", win);
  			win.hide();
  	}
  },
  
  // Closes all windows
  closeAll: function() {  
    this.windows.each( function(w) {Windows.close(w.getId())} );
  },
  
  // Minimizes a window with its id
  minimize: function(id) {
  	var win = this.getWindow(id)
  	if (win)
  	  win.minimize();
  },
  
  // Maximizes a window with its id
  maximize: function(id) {
  	var win = this.getWindow(id)
  	if (win)
  	  win.maximize();
  },
  
  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;
    this.focusedWindow = win;
  }
};

var Dialog = {
  dialogId: null,
 	win: null,
  onCompleteFunc: null,
  callFunc: null, 
  parameters: null, 
    
	confirm: function(content, parameters) {
	  // Get Ajax return before
	  if (typeof content != "string") {
	    Dialog._runAjaxRequest(content, parameters, Dialog.confirm);
	    return 
	  }
	  
	  parameters = parameters || {};
		var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
		var cancelLabel = parameters.cancelLabel ? parameters.cancelLabel : "Cancel";

		var windowParam = parameters.windowParameters || {};
		windowParam.className = windowParam.className || "alert";

    okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" 
    cancelButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " cancel_button'" 
		var content = "\
			<div class='" + windowParam.className + "_message'>" + content  + "</div>\
				<div class='" + windowParam.className + "_buttons'>\
					<input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()'" + okButtonClass + "/>\
					<input type='button' value='" + cancelLabel + "' onclick='Dialog.cancelCallback()' " + cancelButtonClass + "/>\
				</div>\
		";
	  this._openDialog(content, parameters)
	  return this.win
	},
	
	alert: function(content, parameters) {
	  // Get Ajax return before
	  if (typeof content != "string") {
	    Dialog._runAjaxRequest(content, parameters, Dialog.alert);
	    return 
	  }
	  
	  parameters = parameters || {};
		var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";

		var windowParam = parameters.windowParameters || {};
		windowParam.className = windowParam.className || "alert";

    okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" 
		var content = "\
			<div class='" + windowParam.className + "_message'>" + content  + "</div>\
				<div class='" + windowParam.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 (typeof content != "string") {
	    Dialog._runAjaxRequest(content, parameters, Dialog.info);
	    return 
	  }
	   
	  parameters = parameters || {};
	  parameters.windowParameters = parameters.windowParameters || {};
	  
		var className = parameters.windowParameters.className || "alert";

		var content = "<div id='modal_dialog_message' class='" + className + "_message'>" + content  + "</div>";
		if (parameters.showProgress)
		  content += "<div id='modal_dialog_progress' class='" + className + "_progress'>	</div>";

		parameters.windowParameters.ok = null;
		parameters.windowParameters.cancel = null;
    parameters.windowParameters.className = className;
		
		return this._openDialog(content, parameters)
	},
	
	setInfoMessage: function(message) {
		$('modal_dialog_message').update(message);
	},
	
	closeInfo: function() {
		Windows.close(this.dialogId);
	},
	
	_openDialog: function(content, parameters) {
		// remove old dialog
		if (this.win) 
			this.win.destroy();

    if (! parameters.windowParameters.height && ! parameters.windowParameters.width) {
      parameters.windowParameters.width = WindowUtilities.getPageSize().pageWidth / 2;
    }
    this.dialogId = parameters.id ? parameters.id : 'modal_dialog'

    // compute height or width if need be
    if (! parameters.windowParameters.height || ! parameters.windowParameters.width) {
      var size = WindowUtilities._computeSize(content, this.dialogId, parameters.windowParameters.width, parameters.windowParameters.height)
  		if (parameters.windowParameters.height)
  		  parameters.windowParameters.width = size + 5
		  else
		    parameters.windowParameters.height = size + 5
    }
		var windowParam = parameters && parameters.windowParameters ? parameters.windowParameters : {};
		windowParam.resizable = windowParam.resizable || false;
		
		windowParam.effectOptions = windowParam.effectOptions || {duration: 1};
    windowParam.minimizable = false;
    windowParam.maximizable = false;
    windowParam.closable = false;
		this.win = new Window(this.dialogId, windowParam);
		this.win.getContent().innerHTML = content;
  	this.win.showCenter(true, parameters.top, parameters.left);	
		  
		this.win.cancelCallback = parameters.cancel;
		this.win.okCallback = parameters.ok;
		
		return this.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() {
		if (!this.win.okCallback || this.win.okCallback(this.win))
	    this.win.hide();
	},

	cancelCallback: function() {
		this.win.hide();
		if (this.win.cancelCallback)
			this.win.cancelCallback(this.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)
*/

var isIE = navigator.appVersion.match(/MSIE/) == "MSIE";

var WindowUtilities = {
  // From script.aculo.us
  getWindowScroll: function() {
    var w = window;
      var T, L, W, H;
      with (w.document) {
        if (w.document.documentElement && documentElement.scrollTop) {
          T = documentElement.scrollTop;
          L = documentElement.scrollLeft;
        } else if (w.document.body) {
          T = body.scrollTop;
          L = body.scrollLeft;
        }
        if (w.innerWidth) {
          W = w.innerWidth;
          H = w.innerHeight;
        } else if (w.document.documentElement && documentElement.clientWidth) {
          W = documentElement.clientWidth;
          H = documentElement.clientHeight;
        } else {
          W = body.offsetWidth;
          H = body.offsetHeight
        }
      }
      return { top: T, left: L, width: W, height: H };
    
  }, 
  //
  // getPageSize()
  // Returns array with page width, height and window width, height
  // Core code from - quirksmode.org
  // Edit for Firefox by pHaez
  //
  getPageSize: function(){
  	var xScroll, yScroll;

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

  	var windowWidth, windowHeight;

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

  	// 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, contentId) {
		WindowUtilities.initLightbox(overlayId, className);
		var objBody = document.getElementsByTagName("body").item(0);

		// prep objects
	 	var objOverlay = $(overlayId);

		var pageSize = WindowUtilities.getPageSize();

		// Hide select boxes as they will 'peek' through the image in IE
		if (contentId && isIE) {
      $$('select').each(function(element) {element.style.visibility = "hidden"});
	    $$('#'+contentId+' select').each(function(element) {element.style.visibility = "visible"});
		}	
	
		// set height of Overlay to take up whole page and show
		objOverlay.style.height = (pageSize.pageHeight + 'px');
		objOverlay.style.width = (pageSize.windowWidth + 'px');
		objOverlay.style.display = 'block';	
	},

 	enableScreen: function(id) {
 	  id = id || 'overlay_modal'
	 	var objOverlay =  $(id);
		if (objOverlay) {
			// hide lightbox and overlay
			objOverlay.style.display = 'none';

			// make select boxes visible
			if (isIE) {
        $$('select').each(function(element) {element.style.visibility = "visible"});
			}
			objOverlay.parentNode.removeChild(objOverlay);
		}
	},

	// initLightbox()
	// Function runs on window load, going through link tags looking for rel="lightbox".
	// These links receive onclick events that enable the lightbox display for their targets.
	// The function also inserts html markup at the top of the page which will be used as a
	// container for the overlay pattern and the inline image.
	initLightbox: function(id, className) {
		// Already done, just update zIndex
		if ($(id)) {
			Element.setStyle(id, {zIndex: Windows.maxZIndex + 10});
		}
		// create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
		else {
			var objBody = document.getElementsByTagName("body").item(0);
			var objOverlay = document.createElement("div");
			objOverlay.setAttribute('id', id);
			objOverlay.className = "overlay_" + className
			objOverlay.style.display = 'none';
			objOverlay.style.position = 'absolute';
			objOverlay.style.top = '0';
			objOverlay.style.left = '0';
			objOverlay.style.zIndex = Windows.maxZIndex + 10;
		 	objOverlay.style.width = '100%';
			objBody.insertBefore(objOverlay, objBody.firstChild);
		}
	},
	
	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) {
    if (margin == null)
      margin = 5;

    var objBody = document.getElementsByTagName("body").item(0);
  	var tmpObj = document.createElement("div");
  	tmpObj.setAttribute('id', id);
	
  	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 = $(id).getDimensions().width + margin;
    else
      size = $(id).getDimensions().height + margin;
  	objBody.removeChild(tmpObj);
    
  	return size;
  }	
}




/*
   Behaviour v1.0 by Ben Nolan, June 2005. Based largely on the work
   of Simon Willison (see comments by Simon below).

   Description:
   	
   	Uses css selectors to apply javascript behaviours to enable
   	unobtrusive javascript in html documents.
   	
   Usage:   
   
	var myrules = {
		'b.someclass' : function(element){
			element.onclick = function(){
				alert(this.innerHTML);
			}
		},
		'#someid u' : function(element){
			element.onmouseover = function(){
				this.innerHTML = "BLAH!";
			}
		}
	);
	
	Behaviour.register(myrules);
	
	// Call Behaviour.apply() to re-apply the rules (if you
	// update the dom, etc).

   License:
   
   	My stuff is BSD licensed. Not sure about Simon's.
   	
   More information:
   	
   	http://ripcord.co.nz/behaviour/
   
*/   

var Behaviour = {
	list : new Array,
	
	register : function(sheet){
		Behaviour.list.push(sheet);
	},
	
	start : function(){
		Behaviour.addLoadEvent(function(){
			Behaviour.apply();
		});
	},
	
	apply : function(){
		for (h=0;sheet=Behaviour.list[h];h++){
			for (selector in sheet){
				list = document.getElementsBySelector(selector);
				
				if (!list){
					continue;
				}

				for (i=0;element=list[i];i++){
					sheet[selector](element);
				}
			}
		}
	},
	
	addLoadEvent : function(func){
		var oldonload = window.onload;
		
		if (typeof window.onload != 'function') {
			window.onload = func;
		} else {
			window.onload = function() {
				oldonload();
				func();
			}
		}
	}
}

Behaviour.start();

/*
   The following code is Copyright (C) Simon Willison 2004.

   document.getElementsBySelector(selector)
   - returns an array of element objects from the current document
     matching the CSS selector. Selectors can contain element names, 
     class names and ids and can be nested. For example:
     
       elements = document.getElementsBySelect('div#main p a.external')
     
     Will return an array of all 'a' elements with 'external' in their 
     class attribute that are contained inside 'p' elements that are 
     contained inside the 'div' element which has id="main"

   New in version 0.4: Support for CSS2 and CSS3 attribute selectors:
   See http://www.w3.org/TR/css3-selectors/#attribute-selectors

   Version 0.4 - Simon Willison, March 25th 2003
   -- Works in Phoenix 0.5, Mozilla 1.3, Opera 7, Internet Explorer 6, Internet Explorer 5 on Windows
   -- Opera 7 fails 
*/

function getAllChildren(e) {
  // Returns all children of element. Workaround required for IE5/Windows. Ugh.
  return e.all ? e.all : e.getElementsByTagName('*');
}

document.getElementsBySelector = function(selector) {
  // Attempt to fail gracefully in lesser browsers
  if (!document.getElementsByTagName) {
    return new Array();
  }
  // Split selector in to tokens
  var tokens = selector.split(' ');
  var currentContext = new Array(document);
  for (var i = 0; i < tokens.length; i++) {
    token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
    if (token.indexOf('#') > -1) {
      // Token is an ID selector
      var bits = token.split('#');
      var tagName = bits[0];
      var id = bits[1];
      
      var element = document.getElementById(id);
      if (tagName && element.nodeName.toLowerCase() != tagName) {
        // tag with that ID not found, return false
        return new Array();
      }
      // Set currentContext to contain just this element
      currentContext = new Array(element);
      continue; // Skip to next token
    }
    if (token.indexOf('.') > -1) {
      // Token contains a class selector
      var bits = token.split('.');
      var tagName = bits[0];
      var className = bits[1];
      if (!tagName) {
        tagName = '*';
      }
      // Get elements matching tag, filter them for class selector
      var found = new Array;
      var foundCount = 0;
      for (var h = 0; h < currentContext.length; h++) {
        var elements;
        if (tagName == '*') {
            elements = getAllChildren(currentContext[h]);
        } else {
            elements = currentContext[h].getElementsByTagName(tagName);
        }
        for (var j = 0; j < elements.length; j++) {
          found[foundCount++] = elements[j];
        }
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      for (var k = 0; k < found.length; k++) {
        if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
          currentContext[currentContextIndex++] = found[k];
        }
      }
      continue; // Skip to next token
    }
    // Code to deal with attribute selectors
    if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
      var tagName = RegExp.$1;
      var attrName = RegExp.$2;
      var attrOperator = RegExp.$3;
      var attrValue = RegExp.$4;
      if (!tagName) {
        tagName = '*';
      }
      // Grab all of the tagName elements within current context
      var found = new Array;
      var foundCount = 0;
      for (var h = 0; h < currentContext.length; h++) {
        var elements;
        if (tagName == '*') {
            elements = getAllChildren(currentContext[h]);
        } else {
            elements = currentContext[h].getElementsByTagName(tagName);
        }
        for (var j = 0; j < elements.length; j++) {
          found[foundCount++] = elements[j];
        }
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      var checkFunction; // This function will be used to filter the elements
      switch (attrOperator) {
        case '=': // Equality
          checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
          break;
        case '~': // Match one of space seperated words 
          checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
          break;
        case '|': // Match start with value followed by optional hyphen
          checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
          break;
        case '^': // Match starts with value
          checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
          break;
        case '$': // Match ends with value - fails with "Warning" in Opera 7
          checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
          break;
        case '*': // Match ends with value
          checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
          break;
        default :
          // Just test for existence of attribute
          checkFunction = function(e) { return e.getAttribute(attrName); };
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      for (var k = 0; k < found.length; k++) {
        if (checkFunction(found[k])) {
          currentContext[currentContextIndex++] = found[k];
        }
      }
      // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
      continue; // Skip to next token
    }
    
    if (!currentContext[0]){
    	return;
    }
    
    // If we get here, token is JUST an element (not a class or ID selector)
    tagName = token;
    var found = new Array;
    var foundCount = 0;
    for (var h = 0; h < currentContext.length; h++) {
      var elements = currentContext[h].getElementsByTagName(tagName);
      for (var j = 0; j < elements.length; j++) {
        found[foundCount++] = elements[j];
      }
    }
    currentContext = found;
  }
  return currentContext;
}

/* That revolting regular expression explained 
/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
  \---/  \---/\-------------/    \-------/
    |      |         |               |
    |      |         |           The value
    |      |    ~,|,^,$,* or =
    |   Attribute 
   Tag
*/


/*
Copyright (c) 2005 JSON.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*
    The global object JSON contains two methods.

    JSON.stringify(value) takes a JavaScript value and produces a JSON text.
    The value must not be cyclical.

    JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
    return false if there is an error.
*/
var JSON = function () {
    var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        s = {
            'boolean': function (x) {
                return String(x);
            },
            number: function (x) {
                return isFinite(x) ? String(x) : 'null';
            },
            string: function (x) {
                if (/["\\\x00-\x1f]/.test(x)) {
                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                        var c = m[b];
                        if (c) {
                            return c;
                        }
                        c = b.charCodeAt();
                        return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
                    });
                }
                return '"' + x + '"';
            },
            object: function (x) {
                if (x) {
                    var a = [], b, f, i, l, v;
                    if (x instanceof Array) {
                        a[0] = '[';
                        l = x.length;
                        for (i = 0; i < l; i += 1) {
                            v = x[i];
                            f = s[typeof v];
                            if (f) {
                                v = f(v);
                                if (typeof v == 'string') {
                                    if (b) {
                                        a[a.length] = ',';
                                    }
                                    a[a.length] = v;
                                    b = true;
                                }
                            }
                        }
                        a[a.length] = ']';
                    } else if (x instanceof Object) {
                        a[0] = '{';
                        for (i in x) {
                            v = x[i];
                            f = s[typeof v];
                            if (f) {
                                v = f(v);
                                if (typeof v == 'string') {
                                    if (b) {
                                        a[a.length] = ',';
                                    }
                                    a.push(s.string(i), ':', v);
                                    b = true;
                                }
                            }
                        }
                        a[a.length] = '}';
                    } else {
                        return;
                    }
                    return a.join('');
                }
                return 'null';
            }
        };
    return {
        copyright: '(c)2005 JSON.org',
        license: 'http://www.JSON.org/license.html',
/*
    Stringify a JavaScript value, producing a JSON text.
*/
        stringify: function (v) {
            var f = s[typeof v];
            if (f) {
                v = f(v);
                if (typeof v == 'string') {
                    return v;
                }
            }
            return null;
        },
/*
    Parse a JSON text, producing a JavaScript value.
    It returns false if there is a syntax error.
*/
        parse: function (text) {
            try {
                return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
                        text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
                    eval('(' + text + ')');
            } catch (e) {
                return false;
            }
        }
    };
}();

// Copyright (c) 2006 SÃ©bastien Gruhier (http://xilinus.com, http://itseb.com)
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// VERSION 0.25

var Carousel = Class.create();
Carousel.prototype = {
  // Constructor
  initialize: function(carouselElemID) {
    this.carouselElemID = carouselElemID;
    
    this.options = Object.extend({
      numVisible:           4,
      scrollInc:            3,
      animParameters:      {},
      buttonStateHandler:  null,
      animHandler:         null,
      ajaxHandler:         null,
      initDoneHandler:     null,
      queue:               "carousel",
      size:                0,
      prevElementID:       "prev-arrow",
      nextElementID:       "next-arrow",
      ajaxParameters:      null,
      url:                 null
		}, arguments[1] || {});

		this.initDone = false;
		this.animRunning = "none";
    this.requestIsRunning = false;
    
		// add afterFinish options to animParameters (store old function)
		this.animAfterFinish = this.options.animParameters.afterFinish;
		Object.extend(this.options.animParameters, {afterFinish:  this._animDone.bind(this), queue: { position:'end', scope: this.options.queue }});
	  
		// Event bindings
		this.prevScroll = this._prevScroll.bindAsEventListener(this);
		this.nextScroll = this._nextScroll.bindAsEventListener(this);
		this.onComplete = this._onComplete.bindAsEventListener(this);
		this.onFailure  = this._onFailure.bindAsEventListener(this);

		Event.observe(this.options.prevElementID, "click", this.prevScroll);
		Event.observe(this.options.nextElementID, "click", this.nextScroll);
		
		// Get DOM UL element
		var carouselListClass = "carousel-list";
		this.carouselList = document.getElementsByClassName(carouselListClass, $(carouselElemID))[0]
		
		// Init data
		this._init();
  },
  
  // Destructor
 	destroy: function() {
  	Event.stopObserving(this.options.prevElementID, "click", this.prevScroll);
  	Event.stopObserving(this.options.nextElementID, "click", this.nextScroll);
	},
	
	scrollTo: function(newStart) {
		var old_inc = this.options.scrollInc;
		this.ignoreNoMoreImages = true;
		if(newStart > this.currentIndex) {
			this.options.scrollInc = newStart - this.currentIndex;
			this._nextScroll(this);
		} else {
			this.options.scrollInc = this.currentIndex - newStart;
			this._prevScroll(this);
		}
    this.options.scrollInc = old_inc;
	},
	
  /* "Private" functions */
  _init: function() {
    this.currentIndex = 0;
    
      
    // Ajax content
    if (this.options.url)
  	  this._request(this.currentIndex, this.options.numVisible);
	  // Static content
  	else {
  	  this._getLiElementSize();
  		this._updateButtonStateHandler(this.options.prevElementID, false);
  		this._updateButtonStateHandler(this.options.nextElementID, this.options.size > this.options.numVisible);
  	}
  },
  
  _prevScroll: function(event) {
    if (this.animRunning != "none" || this.currentIndex == 0)
      return;

    var inc = this.options.scrollInc;

    if (this.currentIndex - inc < 0)
      inc = this.currentIndex;

    this._scroll(inc)		  
	  return false;
  },
  
  _nextScroll: function(event) {    
    if (this.animRunning != "none")
      return false;
            
    // Check if there are enough elements in cache
    if (this.currentIndex + this.options.numVisible + this.options.scrollInc <= this.options.size) 
      this._scroll(-this.options.scrollInc);
    else {
      // Compute how many are in the cache
      this.nbInCache = this.options.size - (this.currentIndex + this.options.numVisible);
      if (this.options.url && this.noMoreImages == false) 
		    this._request(this.currentIndex + this.options.numVisible + this.nbInCache, this.options.scrollInc - this.nbInCache);
	    else  {
	      if (this.nbInCache > 0)
          this._scroll(-this.nbInCache);
        }
	  }
	  return false;
  },
  
  _request: function(start, nb) {
    if (this.options.url && ! this.requestIsRunning) {
      this.requestIsRunning = true;
      
      if (this.options.ajaxHandler)
        this.options.ajaxHandler(this, "before");
      
      var params = "start=" + start + "&nb=" + nb;
      if (this.options.ajaxParameters != null)
        params += "&" + this.options.ajaxParameters
      
  		new Ajax.Request(this.options.url, {parameters: params, onComplete: this.onComplete, onFailure: this.onFailure});
		}
  },
  
  _onComplete: function(originalRequest){
    this.requestIsRunning = false;
    this.carouselList.innerHTML += originalRequest.responseText;
    // Compute how many new elements we have
    var size = this.options.size;
    this.options.size = this.carouselList.getElementsByTagName("li").length;
    var inc = this.options.size - size;
    
		// First run, compute li size
		if (this.initDone == false) {
  		this._getLiElementSize()
  		this.currentIndex = 0;
  		this.initDone = true;
      if (this.options.initDoneHandler) 
        this.options.initDoneHandler(this);
         
  		// Update button states
		  this._updateButtonStateHandler(this.options.prevElementID, false);
		  this._updateButtonStateHandler(this.options.nextElementID, this.options.size == this.options.numVisible);
		  this.noMoreImages = this.options.size < this.options.numVisible
		}
		// Add images
		else {
		  if (!this.ignoreNoMoreImages)
		    this.noMoreImages = inc != this.options.scrollInc;
		  else
		    this.ignoreNoMoreImages = false;
		  // Add images
		  if (inc > 0) {
        this._scroll(-inc, this.noMoreImages)
      }
      // No more images, disable next button
		  else {
		    if (this.nbInCache >0)
          this._scroll(-this.nbInCache, true);
		    
		    this._updateButtonStateHandler(this.options.nextElementID, false);
	    }
		}
		if (this.options.ajaxHandler)
      this.options.ajaxHandler(this, "after");
  },
  
  _onFailure: function(originalRequest){    
    this.requestIsRunning = false;
  },

  _animDone: function(event){   
    if (this.options.animHandler)
      this.options.animHandler(this.carouselElemID, "after", this.animRunning);
     
    this.animRunning = "none";
    // Call animAfterFinish if exists
    if (this.animAfterFinish)
      this.animAfterFinish(event);
  },
  
  _updateButtonStateHandler: function(button, state) {
		if (this.options.buttonStateHandler) 
		    this.options.buttonStateHandler(button, state)
   },
  
  _scroll: function(delta, forceDisableNext) {      
    this.animRunning = delta > 0 ? "prev" : "next";
    
    if (this.options.animHandler)
      this.options.animHandler(this.carouselElemID, "before", this.animRunning);

    new Effect.MoveBy(this.carouselList, 0, delta * this.elementSize, this.options.animParameters);
    this.currentIndex -= delta;
    this._updateButtonStateHandler(this.options.prevElementID, this.currentIndex != 0);
    
    if (this.options.url && this.noMoreImages == false)
      enable = true;
    else
      enable = (this.currentIndex + this.options.numVisible < this.options.size);
    this._updateButtonStateHandler(this.options.nextElementID, (forceDisableNext ? false : enable));
  },
  
  _getLiElementSize: function() {
    var li = $(this.carouselList.getElementsByTagName("li")[0]);
		this.elementSize = li.getDimensions().width + parseFloat(li.getStyle("margin-left")) + + parseFloat(li.getStyle("margin-right"));
  }
}
	





/****************************************************
 * Funciones de submit
 ****************************************************/

function FormSubmitter(formName, formCbs)
{
	this.formName = formName;
	this.form = document[formName];
	this.formCbs = formCbs;
}

function bloqueaWindow(){
	Dialog.info("Enviando datos, por favor espere ...",
               {windowParameters: {className:"alphacube",width:250, height:100}, showProgress: true});
}
/**
 * Comproba los datos antes de ejecutar la acción.
 * Se suele utilizar para modificar un registro desde la ficha.
 */
FormSubmitter.prototype.valida_busca = function(accion)
{
	
	this.form.accion.value = accion;
	this.form.issearch.value = 1;
	oFormCallbacks.validateInServerForm();
	return false;
	
	if (this.formCbs.isValidAlert() && this.formCbs.isCompleteAlert()) {
		this.form.accion.value = accion;
		this.form.issearch.value = 1;
		this.formCbs.submit();
		this.form.submit();
		//return true;
	}
	return false;
}

/**
 * Comproba los datos antes de ejecutar la acción.
 * Se suele utilizar para modificar un registro desde la ficha.
 */
FormSubmitter.prototype.valida_ejecuta = function(accion)
{
	bloqueaWindow();
	this.form.accion.value = accion;
	oFormCallbacks.validateInServerForm();
	return false;
}

/**
 * Comproba los datos antes de ejecutar la acción.
 * Se suele utilizar para modificar un registro desde la ficha.
 */
FormSubmitter.prototype.valida_ejecuta_tab = function(accion,regMatch)
{
	this.form.accion.value = accion;
	oFormCallbacks.validateInServerForm(regMatch);
	return false;
}


/**
 * Ejecuta la acción sin confirmación ni comprobación.
 * Sin pasar el id: se suele utilizar para volver al listado.
 * Pasando el id: Se suele utilizar para ir del listado a una ficha.
 */
FormSubmitter.prototype.ejecuta = function(accion, id)
{
	this.form.accion.value = accion;
	this.form.id.value = id;
	this.form.submit();
}

FormSubmitter.prototype.ejecutaInNewWindow = function(accion, id)
{
	var odlAccion = this.form.accion.value;
	var oldId = this.form.id.value;

	this.form.target = "_blank";
	this.form.accion.value = accion;
	this.form.id.value = id;
	this.form.submit();
	this.form.target = "_self";

	this.form.accion.value = odlAccion;
	this.form.id.value = oldId;
	
}


FormSubmitter.prototype.ejecutaInNewWindowNewDest = function(accionNew, id, newUrl)
{
	var odlAccion = this.form.accion.value;
	var oldId = this.form.id.value;
	
	this.form.action = newUrl;
	this.form.target = "_blank";
	this.form.accion.value = accionNew;
	this.form.id.value = id;
	this.form.submit();
	this.form.target = "_self";
	this.form.action = '';
	
	this.form.accion.value = odlAccion;
	this.form.id.value = oldId;
	
}

/**
 * Cambia el target del form.
 */
FormSubmitter.prototype.setTarget = function(dest)
{
	this.form.action = dest;
	
}

/**
 * Pide una confirmación antes de ejecutar la acción.
 * Sin pasar id: Se suele utilizar para eliminar un registro desde la ficha.
 * Pasando un id: Se suele utilizar para eliminar un registro desde el listado.
 */
FormSubmitter.prototype.confirma = function(accion, id)
{
	var accionTest = accion;
	if (accion.indexOf('.') > 0) {
		accionTest = accion.split('.');
		accionTest = accionTest[1];
	}
	
	if (accionTest.substr(0,3) == "del") {
		//"Confirme que desea eliminar el registro.";
		msg = MENSAJES['confirmDel'];
	}
	
	if (accionTest.substr(0,4) == "send") {
		//"Confirme que desea enviar el registro";
		msg = MENSAJES['confirmSend'];
	}
	
	Dialog.confirm(msg, 
		{windowParameters: {className:"alphacube",width:300}, okLabel: "OK", 
		buttonClass: "myButtonClass",
		id: "msgAlert",
		cancel:function(win) {return false;},
		ok:function(win) {s.ejecuta(accion, id); return true;}
		});
	return false;
	
	/*
	if ( confirm(msg) ) {
		this.ejecuta(accion, id);
		return true;
	} else {
		return false;
	}
	*/
}


FormSubmitter.prototype.autoSave = function(accion, id)
{

	msg = MENSAJES['confirmAutoSave'];
	
	Dialog.confirm(msg, 
		{windowParameters: {className:"alphacube",width:300}, okLabel: "OK", 
		buttonClass: "myButtonClass",
		id: "msgAlert",
		cancel:function(win) {return false;},
		ok:function(win) {s.valida_ejecuta(accion, id); return true;}
		});
	return false;
	/*
	if ( confirm(msg) ) {
		this.valida_ejecuta(accion, id);
		return true;
	} else {
		return false;
	}
	*/
}


/**
 * Pide una confirmación antes de eliminar una foto.
 */
FormSubmitter.prototype.eliminar_foto = function(memname)
{
	if ( confirm(MENSAJES['confirmDelFile']) ) {
		this.form.accion.value = "delfoto:" + memname;
		this.form.submit();
	}
}

FormSubmitter.prototype.eliminar_fotoAjax = function(memname)
{
	var msg = MENSAJES['confirmDelFile'];
	var formu = this.form;
	Dialog.confirm(msg, 
		{windowParameters: {className:"alphacube",width:300}, okLabel: "OK", 
		buttonClass: "myButtonClass",
		id: "msgAlert",
		cancel:function(win) {return false;},
		ok:function(win) {
				formu.accion.value = "ajaxDelfoto:" + memname;
				var valsForm = ''; //Form.serialize(document.f);
				valsForm = 'accion=' + "ajaxDelfoto:" + memname;
				valsForm += '&id=' + formu.id.value;
				valsForm += '&' + memname + '=' + formu.elements[memname].value;
				
				var opt = {
						// Use POST
						method: 'post',
						asynchronous:true,
						// Send this lovely data
						postBody: valsForm,
						// Handle successful response
						onSuccess: function(t) {
							document.f.elements[memname].value = 0;
							new Effect.BlindUp('contenedor_' + memname, {duration:0.3});
							new Insertion.Bottom(document.body,t.responseText);
							}
					};
				new Ajax.Request(formu.action, opt);
				return true;
			}
		});
	return false;
}

/**
 * Pide una confirmación antes de eliminar una foto.
 */
FormSubmitter.prototype.eliminar_file = function(memname)
{
	if ( confirm(MENSAJES['confirmDelFile']) ) {
		this.form.accion.value = "delfile:" + memname;
		this.form.submit();
	}
}

FormSubmitter.prototype.eliminar_fileAjax = function(memname)
{
	var msg = MENSAJES['confirmDelFile'];
	var formu = this.form;
	Dialog.confirm(msg, 
		{windowParameters: {className:"alphacube",width:300}, okLabel: "OK", 
		buttonClass: "myButtonClass",
		id: "msgAlert",
		cancel:function(win) {return false;},
		ok:function(win) {
				var oldAccion = formu.accion.value;
				formu.accion.value = "ajaxDelfile:" + memname;
				var valsForm = Form.serialize(document.f);
				valsForm = valsForm.split('accion_').join('boton_');
				//var valsForm = ''; //Form.serialize(document.f);
				//valsForm = 'accion=' + "ajaxDelfile:" + memname;
				//valsForm += '&id=' + this.form.id.value;
				//valsForm += '&' + memname + '=' + this.form.elements[memname].value;
				formu.accion.value = oldAccion;
				//alert(valsForm);
				var opt = {
						// Use POST
						method: 'post',
						asynchronous:true,
						// Send this lovely data
						postBody: valsForm,
						// Handle successful response
						onSuccess: function(t) {
							//alert(t.responseText);
							document.f.elements['F_' + memname].value = '';
							new Effect.BlindUp('contenedor_' + memname);
							// $('contenedor_' + memname).style.display = 'none';
							
						}
					};
				new Ajax.Request(formu.action, opt);
				return true;
			}
		});
	return false;
}

/**
 * Recarga la página ajustando el orden de la columna 'by'.
 */
FormSubmitter.prototype.paginate = function(by)
{
	var currBy = this.form.orderBy.value;
	if (currBy == by) {
		this.form.orderDir.value =
			(this.form.orderDir.value == 'DESC') ? 'ASC' : 'DESC';
	} else {
		this.form.orderDir.value = 'ASC';
	}
	this.form.orderBy.value = by;
	
	this.form.submit();
}

// pone a 0 el formulario dejando los hidden sin resetear
function resetForm(objForm)
{
	for(var i = 0;i < objForm.elements.length;i ++){
		var obj = objForm.elements[i];
		switch(obj.type){
			case "select-one":
				if(obj.name != 'regsPerPage'){
					obj.selectedIndex = 0;
				}
				break;
			case "select-multiple":
				obj.selectedIndex = -1;
				break;
			case "checkbox":
				obj.checked = false;
				break;
			case "text":
			case "file":
			case "textarea":
				obj.value = "";
				break;
		}
		
	}
	//return true;
}

/****************************************************
 * ChangeCallbacks
 ****************************************************/

/**
 * Colección de callback de cambios en la página
 */
function ChangeCallbacks()
{
	this.cbChange = new Array();
}

/**
 * Adición de un callback de cambio
 *
 * El callback se añade a la colección. Se llamará cada vez
 * que cambia un elemento, aunque no tenga nada que ver con
 * este callback. El callback es el encargado de hacer la
 * diferencia.
 *
 * @param Function un callback definido en la página
 * @param HtmlFormElement 
 */
ChangeCallbacks.prototype.addChangeCallback = function(callback)
{
	var pos = this.cbChange.length;
	this.cbChange[pos] = callback;
}
// Crea un objeto global
var oChangeCallbacks = new ChangeCallbacks();

/**
 * Callback de cambio general
 *
 * Esta función se registra para ser llamada cada vez 
 * que se cambia un elemento del formulario.
 */
function __formHasChanged(el) 
{ 
	if(document.f && document.f.is_modified) { 
		document.f.is_modified.value = 'cambiado'; 
	} 
}
// Registra el callback
oChangeCallbacks.addChangeCallback(__formHasChanged);

/*
function __autoCheck(el)
{
	oFormCallbacks.autoCheck(el.name);
}
oChangeCallbacks.addChangeCallback(__autoCheck);
*/

/**
 * Event Handler para los cambios
 *
 * Se añade a cada elemento del formulario con el código:
 * <input ... onchanged='changed(this)' />
 */
function changed(el)
{
	el = $(el);
	
	var arr = el.name.split("[");
	var	formElementName = arr[0];
	formElementName = formElementName.replace('Out','In');
	if(oFormCallbacks.configMembers[formElementName]){
		oFormCallbacks.configMembers[formElementName].validateInServer();
	}
}

function multiselSelect(elName,onOff)
{
	if(!onOff) onOff = true;
	var selFrom = document.f[elName + "[]"];
	var optFrom = selFrom.options;
	for(var f=0; f<optFrom.length; f++) {
		optFrom[f].selected = onOff;
	}
}


// Associated functions

/**
 * Change checkbox state when clicking on its label
 *
 * @param string name of the checkbox
 * @todo add the function in the 'onclick' of the label of the corresponding checkbox
 */
function toggleCheckboxOld(elName) {
	thisCheckbox = document.f[elName];
	thisCheckbox.checked = !(thisCheckbox.checked);
	changed(thisCheckbox);
}

function toggleCheckbox(elName,idDl) {
	if(idDl){
		var thisCheckbox = document.f[elName +'['+idDl+']'];
	}else{
		var thisCheckbox = document.f[elName];
	}
	if(checkIt('applewebkit')){
		thisCheckbox.checked = !(thisCheckbox.checked);
	}
	changed(thisCheckbox);
}
/**
 * Change radio button state when clicking on its label
 *
 * @param string name of the radio button group
 * @param string value of this particular radio button
 */
function setSelectedRadioButton(elName, radioValue) {
	radioArray = document.f[elName];
	if(!radioArray.length) {
		radioArray.checked = true;
		changed(radioArray);
		return;	
	}
	for (i = 0; i < radioArray.length; i++) {
		if (radioArray[i].value == radioValue) {
			radioArray[i].checked = true;
			break;
		}
	}
	changed(radioArray[i]);
}

/**
 * Shows a popup window with a calendar in flash
 *
 * @param string name of the form
 * @param string name of the field to receive the selected date
 */
function showCalendar(form,campo)
{
	var f = (document.forms[form].elements[campo].value);
	fecha = f.split("-");
	d = fecha[0];
	m = fecha[1]-1;
	y = fecha[2];
	win = newWindow('../inc/base/miniCal.php?y='+y+'&m='+m+'&d='+d+'&form='+form+'&campo='+campo,'Calendario',150,150,'');
}

/**
 * Fills the field with a given date
 *
 * @param string name of the form
 * @param string name of the field to receive the date
 * @param mixed date to put into field
 */
function setDate(form,campo,fecha)
{
	elInput = (document.forms[form].elements[campo]);
	
	fecha = fecha.split("-");
	var d = eval(fecha[0]);
	var m = eval(fecha[1]);
	var y = fecha[2];
	if(d<10) d = '0'+d;
	if(m<10) m = '0'+m;
 	elInput.value = d + '-' + m + '-' + y;
	elInput.focus();
	//campo = campo.substring(1,500);
	/*
	assignLabel(campo,"completed");
	
	var spanError = $('err_' + campo);
	if(spanError){
			new Effect.BlindUp(spanError,
    		{ duration: 0.2, afterFinish: function(element){ Element.remove(spanError); } });
		}
	*/
	if(elInput.onchange){
		elInput.onchange();
	}
}

function getFormValues()
{
	valsForm = {};
	objForm = document.f;
	for(var i = 0;i < objForm.elements.length;i ++){
		var obj = objForm.elements[i];
		switch(obj.type){
			case "select-one":
				val = obj.selectedIndex;
				break;
			case "radio":
				if(obj.checked == true){
					val = obj.value;
				}
				break;
			case "text":
			case "file":
			case "textarea":
				val = obj.value;
				break;
			case "select-multiple":
				numOptions = (obj.options.length);
				valArr = new Array;
				for (z = 0; z < numOptions; z++) {
					valArr[z] = obj.options[z].text;
				}
				val = valArr;
				break;
			default:
				val = null;
				break;
		}
		
		if(val != null){
			valsForm[obj.name] = val;
		}
	}
	return valsForm;
}

function checkFormChanges()
{
	newValuesForm = getFormValues();
	var formChanges = new Array;
	for (var i in oldValuesForm){
		if(oldValuesForm[i] != newValuesForm[i]){
			if(typeof oldValuesForm[i] == 'object'){
				valsOld = new Array;
				valsNew = new Array;
				cambiado = false;
				for (var h in oldValuesForm[i]){
					if(oldValuesForm[i][h] != newValuesForm[i][h]){
						valsOld[valsOld.length] = oldValuesForm[i][h];
						valsNew[valsNew.length] = newValuesForm[i][h];
						cambiado = true;
					}
				}
				if(cambiado ==true){
					formChanges[formChanges.length] = i + '\n  old:'+ valsOld +'\n  new:' + valsNew;
				}
			}else{
				formChanges[formChanges.length] = i + '\n  old:'+oldValuesForm[i] +'\n  new:' + newValuesForm[i];
			}
		}
	}
	//alert(formChanges.join('\n'));
}




var MemberDedoLib = Class.create();
MemberDedoLib.prototype = {
   initialize: function(formElementName, pTipo, pFormat, pRequired, pErrorMsg, pEnabled, pExtraParam) {
		this.a_name = this.getMemberName(formElementName);
		
		this.element = $(this.a_name);
		this.a_tipo = pTipo;
		this.a_format = pFormat;
		this.a_required = pRequired;
		this.a_errorMsg = pErrorMsg;
		this.a_title = pErrorMsg;
		this.a_enabled = false;
		
		this.a_accesibleVal = '';
		if(Element.hasClassName(this.element,'accesibleVal')){
			this.a_accesibleVal = this.element.value;
		}
		if(pEnabled == '1') this.a_enabled = true;
	
		var paramsExtra = '0';
		if(pExtraParam) paramsExtra = pExtraParam;
		this.a_params = paramsExtra;
		
		
		this.hasError = false;
		// extras
		this.setLabel(this.a_name);
		//this.setSpanError(this.a_name);
		this.setElToInsert(this.a_name);
   },
   
   getMemberName: function(formElementName) {
		var arr = formElementName.split("[");
		formElementName = arr[0];
		formElementName = formElementName.replace('Out','In');
		return formElementName;
   },
   
   setLabel: function(nameMember) {
		this.label = $('L__' + nameMember);
   },
   
   setSpanError: function(nameMember) {
		this.spanError = $('err_' + nameMember);
   },
   getSpanError: function(nameMember) {
   		var idSpanError = 'err_' + nameMember;
		if((this.a_tipo == 'password')) idSpanError = 'err_' + this.elToInsert.id;
		
		if(!$(idSpanError)){
			var spanError = '<span id="' + idSpanError + '" class="errorField" style="display:none;"><\/span>';
			
			if(oFormCallbacks.config.errorPosition == 'after'){
				var anchoLabel = 0;
				if(this.label && this.a_tipo != 'foto' && this.a_tipo != 'check'){
					anchoLabel = Element.getDimensions(this.label).width;
				}
				spanError = '<div id="' + idSpanError + '" class="errorField" style="clear:left;display:none;padding-left:'+ anchoLabel + 'px;"><\/div>';
				new Insertion.After(this.elToInsert, spanError);
			}
			
			if(oFormCallbacks.config.errorPosition == 'before'){
				new Insertion.Before(this.elToInsert, spanError);
			}
			if(oFormCallbacks.config.errorPosition == 'top'){
				new Insertion.Top(this.elToInsert, spanError);
			}
			if(oFormCallbacks.config.errorPosition == 'bottom'){
				new Insertion.Bottom(this.label, spanError);
			}
		}
		
		this.spanError = $(idSpanError);
   },
   
   setElToInsert: function(member) {
		this.elToInsert = this.element;
		
		if(this.a_tipo == 'date'){
			this.elToInsert = $('cal_icon_' + member);
		}
		if(this.a_tipo == 'daterange'){
			this.elToInsert = $('H_' + member + '_1');
		}
		if(this.a_format == 'radio' || this.a_format == 'checks'){
			this.elToInsert = $('ul_' + member);
		}
		if(this.a_format == 'select' && (this.a_tipo == 'multienum' || this.a_tipo == 'multiforkey')){
			this.elToInsert = $('ins_' + member);
			this.setLabel(member.substr(0,member.length-2));
		}
		if(this.a_tipo == 'foto' || this.a_tipo == 'file'){
			this.elToInsert = $('ins_' + member);
		}
		if(this.a_format == 'autocomplete'){
			this.elToInsert = $('auto_' + member);
		}
		if(this.a_tipo == 'check'){
			this.elToInsert = $('L__' + member);
		}
		if(this.a_tipo == 'text' && this.a_format == 'FCK'){
			if($(member + '___Frame')){
				this.elToInsert = $(member + '___Frame');
			}
		}
		
		if((this.a_tipo == 'password')){
		
			var isRepassw = (this.a_name.substr(0,3) == 're_');
			if(isRepassw){
				this.elToInsert = this.element;
				this.label = $('L__' + this.a_name.substr(3,100));
			}else{
				var haveRepassw = $('re_'+this.a_name);
				if(haveRepassw){
					this.elToInsert = $('re_' + this.a_name);
				}else{
					this.elToInsert = this.element;
				}
			}
			// var spanError = $('err_' + elToInsert.id);
		}
   },
   
   onSubmitMember: function() {
		var valSerialize = '';
		var member = this.a_name;
		if(this.a_accesibleVal && $(member).value == this.a_accesibleVal){
			$(member).value = '';
		}
		if((this.a_tipo=='multienum' || this.a_tipo=='multiforkey') && this.a_format == 'select'){
			multiselSelect(member);
		}		
		if((this.a_tipo == 'foto' || this.a_tipo == 'file')){
			valSerialize = '&valSer_' + member + '=' + (this.element.value);
		}
		
		if((this.a_tipo=='text') && this.a_format == 'RTE'){
			// puede que este asi definido pero el navegador no soporte el RTE
			if($('hdn' + member)){
				updateRTE(member);
				var textoRte = $('hdn' + member).value;
				valSerialize += '&valSer_' + member + '=' + (textoRte);
			}
		}
		
		if((this.a_tipo=='text') && this.a_format == 'FCK'){
			// puede que este asi definido pero el navegador no soporte el RTE
			if(!(isSafari)){ 
					if(FCKeditorAPI.GetInstance(member).GetXHTML() != ''){
						this.element.value = 'OK';
						var textoRte = $(member).value;
					}
				}else{
					var textoRte = document.f.elements[member].value;
				}
			
			valSerialize += '&valSer_' + member + '=' + (textoRte);
			
		}
		
		return valSerialize;
   },
   
   validateInServer: function() {
   		if(this.a_enabled == false) return;
   		var member = this.a_name;
		var valSerialize = this.onSubmitMember();
		
		var valsForm = Form.serialize(document.f);
		
		var accesibleVal = '&a_accesibleVal=' + (this.a_accesibleVal);
		
		
		var opt = {
				// Use POST
				method: 'post',
				asynchronous:true,
				// Send this lovely data
				postBody: 'accionJS=validaMember&member='+member+'&a_format='+this.a_format+''+valSerialize+accesibleVal+'&a_tipo='+this.a_tipo+'&a_title='+this.a_title+'&a_required='+this.a_required + '&' + valsForm,
				// Handle successful response
				onSuccess: function(t) {
					//oFormCallbacks.configMembers[member].showResponse(t.responseText);
					this.showResponse(t.responseText);
					
				}.bind(this)
			};
		new Ajax.Request('../utilidades/validator.php', opt);	
   },
   
    showResponse: function(responseText) {
    	
		this.hasError = false;
		if(responseText == 'OKY'){
			if(this.spanError){
				new Effect.BlindUp(this.spanError,
				{ duration: 0.2, afterFinish: function(element){ Element.remove($(this.spanError.id));this.spanError = null;}.bind(this) });
			}
		}else{
			// alert(this.a_name);
			this.hasError = true;
			if(oFormCallbacks.config.showErrorsText){
				
				
				if(oFormCallbacks.config.errorPosition == 'alert'){
					alert(responseText.stripTags());
				}else{
					
					this.getSpanError(this.a_name);
					
					this.spanError.innerHTML = ' ' + responseText;
					
					new Effect.Appear(this.spanError);
				}		
			}
			
		}
		
		// falta asignar el label
		this.assignLabel();
   },
   
   assignLabel: function() {
   		var tipoLabel = (this.hasError == false) ? 'completed' : 'problem';
		Element.removeClassName(this.label,'completed');
		Element.removeClassName(this.label,'problem');
		Element.removeClassName(this.label,'optional');
		Element.addClassName(this.label,tipoLabel);
   }
};

/****************************************************
 * FormCallbacks
 ****************************************************/

/**
 * FormCallbacks
 * 
 * @param string nombre del formulario
 */
var FormCallbacks = Class.create();

// definimos la clase
FormCallbacks.prototype = {

   initialize: function(formName) {
		this.formName = formName;
		this.configMembers = {};
		this.config = {};
   },

   setConfig: function(pShowErrorsText,pErrorPosition) {
		this.config.showErrorsText = false;
		if(pShowErrorsText == '1') this.config.showErrorsText = true;
		this.config.errorPosition = pErrorPosition;
   },
   
   addValidateCallback: function(formElementName, pTipo, pFormat, pRequired, pErrorMsg, pEnabled, pExtraParam) {
		this.configMembers[formElementName] = new MemberDedoLib(formElementName, pTipo, pFormat, pRequired, pErrorMsg, pEnabled, pExtraParam);
   },
   
   enable: function(formElementName) {
		this.configMembers[formElementName].a_enabled = true;
   },
   
   disable: function(formElementName) {
		this.configMembers[formElementName].a_enabled = false;
   },
   
   observeForm: function() {
		var els = Form.getElements(document[this.formName]);
		for(var i = 0; i < els.length; i++)
		{
			
			if(els[i].type == 'hidden') continue;
			
			if(els[i].type == 'radio' || els[i].type == 'checkbox'){
				//Event.observe(els[i], "click", changed, false);
				els[i].onclick = function(){changed(this);};
			}else{
				if(els[i].type == 'select-multiple'){
					// en los multiples el changed se aplicara al mover de uno a otro en el script moveSelectBox.js
					continue;
				}
				
				//Event.observe(els[i], "change", changed, false);
				
				els[i].onchange = function(){changed(this);};
			}
		}
		
		/*
		// las etiquetas de los radio y checks
		var radiosChecks = document.getElementsByClassName("checkRadioInput");
		radiosChecks.each(function(value, index){
			// var elLabel = radiosChecks[index].nextSibling;
			
			var arr = (radiosChecks[index].id).split("__");
			var nombre = arr[0];
			var idDl = '';
			if(arr[1]){
				idDl = arr[1];
			}
			
			var els = document.getElementsByAttribute('for',(radiosChecks[index].id));
			var elLabel = els[0];
			
			if(radiosChecks[index].type == 'radio'){
				//Event.observe(elLabel, "click", function() { setSelectedRadioButton(nombre,idDl); }, false);
				elLabel.onclick = function(){setSelectedRadioButton(nombre,idDl);};
			}else{
				Event.observe(elLabel, "click", function() { toggleCheckbox(nombre,idDl);return false; }, false);
			}
			
		});
		*/
		
   },
   validateInServerForm: function(regMatch) {
		var valSerialize = '';
		var serStr = '';
		var isTab = false;
		if(regMatch){
			var re = new RegExp(regMatch,"gm");
			isTab = true;
		}
		var serStr = '';
		for(var i in this.configMembers){
			if(isTab){
				if (!(i.match(re))) continue;
			}
			
			member = this.configMembers[i];
			if(!member.a_enabled) continue;
			
			valSerialize += member.onSubmitMember();
			serStr += i +'##';
			
    		['a_tipo','a_format','a_required','a_errorMsg','a_accesibleVal'].each( function(k) {
      			serStr += k +'|' + this.configMembers[i][k] + '||';
    		}.bind(this));
			
			serStr += '##';
			
		}
		
		var valsForm = Form.serialize(document.f);
			
		var opt = {
					// Use POST
					method: 'post',
					asynchronous:true,
					// Send this lovely data
					postBody: 'accionJS=validaForm&config='+serStr + valSerialize + '&' + valsForm,
					// Handle successful response
					onSuccess: function(t) {
						this.showResponseForm(t.responseText);
					}.bind(this)
				};
						

		new Ajax.Request('../utilidades/validator.php', opt);	
   },
   
   showResponseForm: function (res){
		var hasError = false;
		var partes = res.split("||");
		var focusFirst = '';
		for(var i = 0; i < partes.length; i++){
			if(partes[i] == '') continue;
			var campoValor = partes[i].split("|");
			
			if(campoValor[0] == '') continue;
			
			if(this.configMembers[campoValor[0]]){
				if(this.configMembers[campoValor[0]].a_format == 'radio'){
					var el = document.f.elements[campoValor[0]][0];
				}else{
					var el = document.f.elements[campoValor[0]];
				}
				
			}else{
				continue;
				alert(campoValor[0] + ' no esta en la config');
			}
			
			this.configMembers[campoValor[0]].showResponse(campoValor[1]);
			
			if(campoValor[1] != 'OKY'){
				if(focusFirst == '') focusFirst = el;
				hasError = true;
			}
		}
		
		if(hasError){
			//Field.focus(focusFirst);
			//Field.select(focusFirst); //focusFirst.focus();
			Dialog.closeInfo();
			var msg = MENSAJES['error_form'];
			Dialog.alert(msg, 
				 {windowParameters: {className:"alphacube",width:300, height:100}, okLabel: "OK", 
				  ok:function(win) { return true;}});
			//alert(MENSAJES['error_form']);
		}else{
			if(typeof(updateRTEs) == 'function') updateRTEs();
			s.form.submit();
		}
	},

   submit: function() {
		var oForm = document[this.formName];
		for(i in this.cbOnSubmit) {
			if (this.enabled[i])
				var msg = this.cbOnSubmit[i](i, oForm);
		}
   }
};	

// creamos el objeto
var oFormCallbacks = new FormCallbacks('f');


var isSafari = (/Konqueror|Safari|KHTML/.test(navigator.userAgent));
/****************************************************
 * MISC
 ****************************************************/

/**
 * Gets the value of the specified parameter in the cookie.
 *
 * @param string name of the desired parameter.
 * @return string value of that parameter or null if cookie does not exist.
 */
function getCookie(name)
{
    var dc = document.cookie;
    var prefix = name + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1)
    {
        begin = dc.indexOf(prefix);
        if (begin != 0) return null;
    }
    else
    {
        begin += 2;
    }
    var end = document.cookie.indexOf(";", begin);
    if (end == -1)
    {
        end = dc.length;
    }
    return unescape(dc.substring(begin + prefix.length, end));
}



function newWindow(mypage, myname, w, h, scroll) {
     var winLeft = (screen.width - w) / 2;
     var winTop = (screen.height - h) / 2;
     winProps = "height=" + h + ",width=" + w + ",top=" + winTop + ",left=" + winLeft + "," + scroll;
     win = window.open(mypage, myname, winProps);
     if (parseInt(navigator.appVersion) >= 4) { win.window.focus(); } 
     return win;    
}

var posicX =0;
var posicY =0;

Event.observe(document, 'mousemove', get_mouse_xy);

function get_mouse_xy(e) {
	posicX = Event.pointerX(e) + 10;
	posicY = Event.pointerY(e) + 12;
	return true;
}

function showToolTip(text){
	idToolTip = "toolTip";
	w = Math.min((text.length * 5),250);
	//w = 300;
	if(!document.getElementById(idToolTip)){
		divholder = document.createElement("div");
		divholder.id = idToolTip;
		divholder.style.display = 'none';
		divholder.style.width = w + 'px';
		divholder.style.height = "auto";
		divholder.style.border = "1px solid #CCCCCC";
		divholder.style.backgroundColor = "#FCFCBD";
		divholder.style.position = "absolute";
		divholder.style.color = "#222222";
		divholder.style.padding = "2px";
		divholder.style.fontSize = "10px";
		divholder.style.zIndex = "200";
		document.body.appendChild(divholder);
	}else{
		divholder = document.getElementById(idToolTip);
		divholder.style.width = w + 'px';
	}
	x = posicX;
	y = posicY;
	if(document.body.offsetWidth < posicX+w+20){
		x = document.body.offsetWidth - (w+20);
	}
	
	divholder.style.left = x+"px";
	divholder.style.top = y+"px";
	document.getElementById(idToolTip).innerHTML = ""+text+"";
	document.getElementById(idToolTip).style.visibility = "visible";
	document.getElementById(idToolTip).style.display = "";
}


function hideToolTip(){
	document.getElementById("toolTip").style.visibility = "hidden";
}

function showToolTipNew(text,w){
	idToolTip = "toolTipNew";
	var w = 250;
	//w = 300;
	if(!document.getElementById(idToolTip)){
		divholder = document.createElement("div");
		divholder.id = idToolTip;
		divholder.style.display = 'none';
		divholder.style.width = w + 'px';
		divholder.style.height = "auto";
		divholder.style.position = "absolute";
		divholder.style.zIndex = "200";
		document.body.appendChild(divholder);
	}else{
		divholder = document.getElementById(idToolTip);
		divholder.style.width = w + 'px';
	}
	x = posicX;
	y = posicY;
	if(document.body.offsetWidth < posicX+w+20){
		x = document.body.offsetWidth - (w+20);
	}
	
	divholder.style.left = x+"px";
	divholder.style.top = y+"px";
	document.getElementById(idToolTip).innerHTML = ""+text+"";
	//new Effect.Appear($(idToolTip), {duration:0.3,limit:1});
	document.getElementById(idToolTip).style.visibility = "visible";
	document.getElementById(idToolTip).style.display = "";
}


function hideToolTipNew(){
	document.getElementById("toolTipNew").style.display = "none";
}

function showDivDateChoose(form,campo){
	idDiv = "DateChoose";
	w = 300;
	if(!document.getElementById(idDiv)){
		divholder = document.createElement("div");
		divholder.id = idDiv;
		divholder.style.width = "auto";
		divholder.style.height = "auto";
		divholder.style.position = "absolute";
		divholder.style.zIndex = "200";
		document.body.appendChild(divholder);
	}else{
		divholder = document.getElementById(idDiv);
	}

	arr = Position.cumulativeOffset(document.f.elements[campo]);
	x = arr[0] + 110;
	y = arr[1] - 40;
	divholder.style.left = x+"px";
	divholder.style.top = y+"px";

	var texts = getTextsDateChooser();
 	content = 	"<div id='dateChooseContent'>";
 	content += 	"<ul>";
	content += 	"<li class='sigue hand'><a href='javascript:showCalendar(\""+form+"\",\""+campo+"\");javascript:hideDivDateChoose();'>"+texts[0]+"</a></li>";
	content += 	"<li class='sigue hand'><a href='javascript:hideDivDateChoose();'>"+texts[1]+"</a></li>";
	content += 	"</ul>";
	
	content += 	"<ul>";
	content += 	"<li class='sign'><a href='javascript:addDayToDate(-1,\""+form+"\",\""+campo+"\");'><b>-</b></a></li>";
	content += 	"<li><a href='javascript:calculateDate(0,\""+form+"\",\""+campo+"\");javascript:hideDivDateChoose();'>"+texts[2]+"</a></li>";
	content += 	"<li class='sign'><a href='javascript:addDayToDate(1,\""+form+"\",\""+campo+"\");'><b>+</b></a></li>";
	content += 	"</ul>";
	
	content += 	"<ul>";
	content += 	"<li class='sign'><a href='javascript:addDayToDate(-7,\""+form+"\",\""+campo+"\");'><b>-</b></a></li>";
	content += 	"<li class='semana'>"+texts[3]+"</li>";
	content += 	"<li class='sign'><a href='javascript:addDayToDate(7,\""+form+"\",\""+campo+"\");'><b>+</b></a></li>";
	content += 	"</ul>";
	content += 	"<div style='clear:both;'></div>";
	content += 	"</div>";
	content += 	"";
	document.getElementById(idDiv).innerHTML = ""+content+"";
	if(Effect){
		Effect.Appear(idDiv);
	}else{
		document.getElementById(idDiv).style.visibility = "visible";
	}
}

function getTextsDateChooser(){
	var lang = getCookie('lang');
	if (lang == '' || lang == undefined){
		lang = 'es';
	}
	if (lang == 'es'){
		texts = new Array('Elegir','Cerrar','Hoy','Semana');
	}else if (lang == 'eu'){
		texts = new Array('Aukeratu','Itxi','Gaur','Astea');
	}else if (lang == 'en'){
		texts = new Array('Choose','Close','Today','Week');
	}else {
		texts = new Array('Choose','Close','Today','Week');
	}
	return texts;
}


function hideDivDateChoose(){
	if(Effect){
		Effect.DropOut("DateChoose");
	}else{
		document.getElementById("DateChoose").style.visibility = "hidden";
	}
}

function calculateDate(dif,form,campo){
	MINUTE = 60 * 1000;
 	HOUR = MINUTE * 60;
 	DAY = HOUR * 24;

	
	today = (new Date()).getTime();
 	newFecha = new Date(today + (DAY * (dif)));
 	newFechaFormat = newFecha.getDate() + '-' + (newFecha.getMonth()+1) + '-' + (newFecha.getFullYear());
 	
	setDate(form,campo,newFechaFormat);
}

function addDayToDate(dif,form,campo){
	MINUTE = 60 * 1000;
 	HOUR = MINUTE * 60;
 	DAY = HOUR * 24;

	elInputVal = eval("document." + form + "['" + campo + "'].value");
	if (elInputVal == ''){
		today = (new Date()).getTime();
	}else{
		fecha = elInputVal.split("-");
		d = fecha[0];
		m = fecha[1]-1;
		y = fecha[2];
		today = (new Date(y,m,d)).getTime();
	}
 	newFecha = new Date(today + (DAY * (dif)));
 	newFechaFormat = newFecha.getDate() + '-' + (newFecha.getMonth()+1) + '-' + (newFecha.getFullYear());
 	
	setDate(form,campo,newFechaFormat);
}

function setPointer(theRow, thePointerColor)
{
    if (thePointerColor == '' || typeof(theRow.style) == 'undefined') {
        return false;
    }
	
	var theCells = null;
    if (typeof(document.getElementsByTagName) != 'undefined') {
        theCells = theRow.getElementsByTagName('td');
    }else if (typeof(theRow.cells) != 'undefined') {
        theCells = theRow.cells;
    }else {
        return false;
    }

    var rowCellsCnt  = theCells.length;
    for (var c = 0; c < rowCellsCnt; c++) {
        theCells[c].style.backgroundColor = thePointerColor;
    }

    return true;
} // end of the 'setPointer()' function

function changeHeightTextArea(elName,inc)
{
	if(document.getElementById(elName +'___Frame')){
		var oEditor = FCKeditorAPI.GetInstance(elName).EditorWindow.parent;
		
		var actualHeight = oEditor.innerHeight;		
		
		document.getElementById(elName + '___Frame').style.height = actualHeight + inc +'px';
		return;
		
	}else{
		var tArea = document.getElementById(elName);
		var actualHeight = parseInt(tArea.style.height);
	
		if(actualHeight <= 60 && inc < 0) return;
		if((actualHeight + inc) < 60) inc = 60 - actualHeight;
		if(Effect){
			// cual es el porcentaje de los pixeles a mover?
			var porcentaje = 100 + ((inc * 100) / (Math.max(50,actualHeight)));
			
			var test = new Effect.Scale(tArea, porcentaje, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'contents'}, {duration:0.2}));
		}else{
			tArea.style.height = actualHeight + inc +'px';
		}
	}
	
	
}

function setActiveStyleSheet(title) {
  var i, a, main;
  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
    if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
      a.disabled = true;
      if(a.getAttribute("title") == title) a.disabled = false;
    }
  }
}

var detect = navigator.userAgent.toLowerCase();

function checkIt(string)
{
	place = detect.indexOf(string) + 1;
	return place;
}

function clickDiaCalMini(idTd){
	s.ejecuta('agenda');
}
function clickDiaCalSearch(idTd){
	document.f.fechaCal.value = idTd;
	s.ejecuta('buscarPublic');
}


var idEnRoll = -1;
var classEnRoll = '';

function rollOverDiaCalMini(idTd){
	return;
}


var isExplorer=checkIt('msie');
function validaMouseOut(elem){
		if(isExplorer){
			if (!e) var e = window.event;
			if (e.target) tg = e.target;
			else if (e.srcElement) tg = e.srcElement;
			var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
			if(!reltg) return false;					
			while (reltg.className != elem.className && reltg.nodeName != 'BODY'){
					if(reltg.parentNode==null) return false;
					reltg= reltg.parentNode;
			}
			if (reltg.className == elem.className) return false;		
		}
		return true;
}

///////////////////////////////////////////////////////////////////////////
// MOVESELECTBOX
///////////////////////////////////////////////////////////////////////////
function moveFromTo(fbox,tbox){
	for(var i=0; i<fbox.options.length; i++) {
		if(fbox.options[i].selected && fbox.options[i].value != "") {
			var no = new Option();
			no.value = fbox.options[i].value;
			// alert(no.value);
			no.text = fbox.options[i].text;
			tbox.options[tbox.options.length] = no;
			fbox.options[i].value = "";
			fbox.options[i].text = "";
   		}
	}
	BumpUp(fbox);
	SortD(tbox);
	if(fbox.name.substr(fbox.name.length-5,100) == 'Out[]'){
		changed(tbox);
	}else{
		changed(fbox);
	}
}

function BumpUp(box){
	for(var i=0; i<box.options.length; i++) {
		if(box.options[i].value == "")  {
			break;
   		}
	}

	for(var j=i; j<box.options.length-1; j++)  {
		box.options[j].value = box.options[j+1].value;
		box.options[j].text = box.options[j+1].text;
	}

	if(i < box.options.length)  {
		box.options.length -= 1;
		BumpUp(box);
	}
}

function SortD(box)  {
	var temp_opts = new Array();
	var temp = new Object();
	for(var i=0; i<box.options.length; i++)  {
		temp_opts[i] = box.options[i];
	}
	for(var x=0; x<temp_opts.length-1; x++)  {
		for(var y=(x+1); y<temp_opts.length; y++)  {
			if(temp_opts[x].text > temp_opts[y].text)  {
				temp = temp_opts[x].text;
				temp_opts[x].text = temp_opts[y].text;
				temp_opts[y].text = temp;
				
				temp = temp_opts[x].value;
				temp_opts[x].value = temp_opts[y].value;
				temp_opts[y].value = temp;
			}
		}
	}
	for(var i=0; i<box.options.length; i++)  {
		box.options[i].value = temp_opts[i].value;
		box.options[i].text = temp_opts[i].text;
	}
}

///////////////////////////////////////////////////////////////////////////
// END MOVESELECTBOX
///////////////////////////////////////////////////////////////////////////

/* PROTOTYPE EXTENDS */

Object.extend(Ajax.Autocompleter.prototype, {
  initialize: function(element, update, url, options) {
    this.baseInitialize(element, update, options);
    this.options.asynchronous  = true;
    this.options.onComplete    = this.onComplete.bind(this);
    this.options.defaultParams = this.options.parameters || null;
    this.url                   = url;
  	this.options.onNoresults = this.options.onNoresults || function(element, update){ return; };
  },

  onObserverEvent: function() {
    this.changed = false;

    if(this.getToken().length>=this.options.minChars) {
      this.startIndicator();
      this.getUpdatedChoices();
    } else {
      //this.options.onNoResults(this.element,this.update);
      this.active = false;
      this.hide();
    }
  },

  updateChoices: function(choices) {
    if(!choices || choices == '' || choices.indexOf('no_results') != -1) this.options.onNoresults(this.element,this.update);
  	if(!this.changed && this.hasFocus) {
      this.update.innerHTML = choices;
      Element.cleanWhitespace(this.update);
      Element.cleanWhitespace(this.update.firstChild);

      if(this.update.firstChild && this.update.firstChild.childNodes) {
        this.entryCount =
          this.update.firstChild.childNodes.length;
        for (var i = 0; i < this.entryCount; i++) {
          var entry = this.getEntry(i);
          entry.autocompleteIndex = i;
          this.addObservers(entry);
        }
      } else {
        this.entryCount = 0;
      }


      this.stopIndicator();

      this.index = 0;
      this.render();
    }
  },

  onComplete: function(request) {
    //alert(request.responseText);
    this.updateChoices(request.responseText);
  }
});



document.getElementsByAttribute = function(attribute, value, tagName, parentElement) {
	var children = ($(parentElement) || document.body).getElementsByTagName((tagName || '*'));
	return $A(children).inject([], function(elements, child) {
		var attributeValue = child.getAttribute(attribute);
		if(attributeValue != null) {
			if(!value || attributeValue == value) {
				elements.push(child);
			}
		}
		return elements;
	});
}

function procesaAccesibleValuesForm()
{
	var els = $$('accesibleVal');
	els.each(function(value, index) {
      var element = els[index];
      element.startValue = element.value;
      Element.addClassName(element,'accesibleValFocus');
		element.onfocus = function(){
			if (element.value == element.startValue){
				element.value = "";
				//element.style.color='#000000';
				Element.removeClassName(element,'accesibleValFocus');
			}
		};
		element.onblur = function(){
			if (element.value == ''){
				element.value = element.startValue;
				//element.style.color='#747373';
				Element.addClassName(element,'accesibleValFocus');
			}
		};
    });
}

function initMap(lat, lon, dirOverlay, mapId,showScala,showTipoMapa)
{
	if (GBrowserIsCompatible()) {
		var map = new GMap2(document.getElementById(mapId));
	
		map.setCenter(new GLatLng(lat, lon), 14);
		if(showScala){
			map.addControl(new GLargeMapControl());
		}else{
			map.addControl(new GSmallMapControl());
		}
		if(showTipoMapa){
			map.addControl(new GMapTypeControl());
		}
		
		var point = new GLatLng(lat, lon);
	
		var marker = new GMarker(point);
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml(dirOverlay);
		});
		map.addOverlay(marker);
		marker.openInfoWindowHtml(dirOverlay);
	}
}

var Reflection = {
	defaultHeight : 0.5,
	defaultOpacity: 0.5,
	
	add: function(image, options) {
		Reflection.remove(image);
		
		doptions = { "height" : Reflection.defaultHeight, "opacity" : Reflection.defaultOpacity }
		if (options) {
			for (var i in doptions) {
				if (!options[i]) {
					options[i] = doptions[i];
				}
			}
		} else {
			options = doptions;
		}
	
		try {
			var d = document.createElement('div');
			var p = image;
			
			var classes = p.className.split(' ');
			var newClasses = '';
			for (j=0;j<classes.length;j++) {
				if (classes[j] != "reflect") {
					if (newClasses) {
						newClasses += ' '
					}
					
					newClasses += classes[j];
				}
			}

			var reflectionHeight = Math.floor(p.height*options['height']);
			var divHeight = Math.floor(p.height*(1+options['height']));
			
			var reflectionWidth = p.width;
	
			/* Copy original image's classes & styles to div */
			d.className = newClasses;
			p.className = 'reflected';
			
			d.style.cssText = p.style.cssText;
			p.style.cssText = ' ';
			
			if (document.all && !window.opera) {
				var reflection = document.createElement('img');
				reflection.src = p.src;
				reflection.style.width = reflectionWidth+'px';
				
				reflection.style.marginBottom = "-"+(p.height-reflectionHeight)+'px';
				reflection.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity='+(options['opacity']*100)+', style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy='+(options['height']*100)+')';
				
				d.style.width = reflectionWidth+'px';
				d.style.height = divHeight+'px';
				p.parentNode.replaceChild(d, p);
				
				d.appendChild(p);
				d.appendChild(reflection);
			} else {
				var canvas = document.createElement('canvas');
				var context = canvas.getContext("2d");
			
				canvas.style.height = reflectionHeight+'px';
				canvas.style.width = reflectionWidth+'px';
				canvas.height = reflectionHeight;
				canvas.width = reflectionWidth;
				
				d.style.width = reflectionWidth+'px';
				d.style.height = divHeight+'px';
				p.parentNode.replaceChild(d, p);
				
				d.appendChild(p);
				d.appendChild(canvas);
				
				context.save();
				
				context.translate(0,image.height-1);
				context.scale(1,-1);
				
				context.drawImage(image, 0, 0, reflectionWidth, image.height);

				context.restore();
				
				context.globalCompositeOperation = "destination-out";
				var gradient = context.createLinearGradient(0, 0, 0, reflectionHeight);
				
				gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
				gradient.addColorStop(0, "rgba(255, 255, 255, "+(1-options['opacity'])+")");
	
				context.fillStyle = gradient;
				if (navigator.appVersion.indexOf('WebKit') != -1) {
					context.fill();
				} else {
					context.fillRect(0, 0, reflectionWidth, reflectionHeight*2);
				}
			}
		} catch (e) {
	    }
	},
	
	remove : function(image) {
		if (image.className == "reflected") {
			image.className = image.parentNode.className;
			image.parentNode.parentNode.replaceChild(image, image.parentNode);
		}
	}
}

function addReflections() {
	var rimages = document.getElementsByClassName('reflect');
	for (i=0;i<rimages.length;i++) {
		var rheight = null;
		var ropacity = null;
		var classes = rimages[i].className.split(' ');
		for (j=0;j<classes.length;j++) {
			if (classes[j].indexOf("rheight") == 0) {
				var rheight = classes[j].substring(7)/100;
			} else if (classes[j].indexOf("ropacity") == 0) {
				var ropacity = classes[j].substring(8)/100;
			}
		}
		
		Reflection.add(rimages[i], { height: rheight, opacity : ropacity});
	}
}

Behaviour.addLoadEvent(function() { addReflections();procesaAccesibleValuesForm();});


// Cross-Browser Rich Text Editor
// http://www.kevinroth.com/rte/demo.htm
// Written by Kevin Roth (kevin@NOSPAMkevinroth.com - remove NOSPAM)

//init variables
var isRichText = false;
var rng;
var currentRTE;
var allRTEs = "";

var isIE;
var isGecko;
var isSafari;
var isKonqueror;

var imagesPath;
var includesPath;
var cssFile;


function initRTE(imgPath, incPath, css) {
	//set browser vars
	var ua = navigator.userAgent.toLowerCase();
	isIE = ((ua.indexOf("msie") != -1) && (ua.indexOf("opera") == -1) && (ua.indexOf("webtv") == -1)); 
	isGecko = (ua.indexOf("gecko") != -1);
	isSafari = (ua.indexOf("safari") != -1);
	isKonqueror = (ua.indexOf("konqueror") != -1);
	
	//check to see if designMode mode is available
	if (document.getElementById && document.designMode && !isSafari && !isKonqueror) {
		isRichText = true;
	}
	
	if (!isIE) document.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT | Event.MOUSEDOWN | Event.MOUSEUP);
	document.onmouseover = raiseButton;
	document.onmouseout  = normalButton;
	document.onmousedown = lowerButton;
	document.onmouseup   = raiseButton;
	
	//set paths vars
	imagesPath = imgPath;
	includesPath = incPath;
	cssFile = css;
	
	if (isRichText) document.writeln('<style type="text/css">@import "' + includesPath + 'rte.css";</style>');
	
	//for testing standard textarea, uncomment the following line
	//isRichText = false;
}

function writeRichText(rte, html, width, height, buttons, readOnly) {
	if (isRichText) {
		if (allRTEs.length > 0) allRTEs += ";";
		allRTEs += rte;
		writeRTE(rte, html, width, height, buttons, readOnly);
	} else {
		writeDefault(rte, html, width, height, buttons, readOnly);
	}
}

function writeDefault(rte, html, width, height, buttons, readOnly) {
	if (!readOnly) {
		document.writeln('<textarea name="' + rte + '" id="' + rte + '" style="width: ' + width + 'px; height: ' + height + 'px;" onchange="changed(this);">' + html + '</textarea>');
	} else {
		document.writeln('<textarea name="' + rte + '" id="' + rte + '" style="width: ' + width + 'px; height: ' + height + 'px;" readonly="readonly">' + html + '</textarea>');
	}
}

function raiseButton(e) {
	if (isIE) {
		var el = window.event.srcElement;
	} else {
		var el= e.target;
	}
	
	className = el.className;
	if (className == 'rteImage' || className == 'rteImageLowered') {
		el.className = 'rteImageRaised';
	}
}

function normalButton(e) {
	if (isIE) {
		var el = window.event.srcElement;
	} else {
		var el= e.target;
	}
	
	className = el.className;
	if (className == 'rteImageRaised' || className == 'rteImageLowered') {
		el.className = 'rteImage';
	}
}

function lowerButton(e) {
	if (isIE) {
		var el = window.event.srcElement;
	} else {
		var el= e.target;
	}
	
	className = el.className;
	if (className == 'rteImage' || className == 'rteImageRaised') {
		el.className = 'rteImageLowered';
	}
}

function writeRTE(rte, html, width, height, buttons, readOnly) {
	if (readOnly) buttons = false;
	
	//adjust minimum table widths
	if (isIE) {
		if (buttons && (width < 600)) width = 600;
		var tablewidth = width;
	} else {
		if (buttons && (width < 500)) width = 500;
		var tablewidth = width + 4;
	}
	
	if (buttons == true) {
//		document.writeln('<table class="rteBack" cellpadding=2 cellspacing=0 id="Buttons1_' + rte + '" width="' + tablewidth + '">');
//		document.writeln('	<tr>');
		
//		document.writeln('		<td width="100%">');
//		document.writeln('		</td>');
//		document.writeln('	</tr>');
//		document.writeln('</table>');
		document.writeln('<div class="rteDiv">');
		document.writeln('<table class="rteBack" border="1" cellpadding="0" cellspacing="0" id="Buttons2_' + rte + '" width="' + tablewidth + '">');
		document.writeln('	<tr>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'bold.gif" width="18" height="18" alt="Bold" title="Bold" onClick="FormatText(\'' + rte + '\', \'bold\', \'\')"></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'italic.gif" width="18" height="18" alt="Italic" title="Italic" onClick="FormatText(\'' + rte + '\', \'italic\', \'\')"></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'underline.gif" width="18" height="18" alt="Underline" title="Underline" onClick="FormatText(\'' + rte + '\', \'underline\', \'\')"></td>');
		document.writeln('		<td><img class="rteVertSep" src="' + imagesPath + 'blackdot.gif" width="1" height="20" border="0" alt=""></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'left_just.gif" width="18" height="18" alt="Align Left" title="Align Left" onClick="FormatText(\'' + rte + '\', \'justifyleft\', \'\')"></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'centre.gif" width="18" height="18" alt="Center" title="Center" onClick="FormatText(\'' + rte + '\', \'justifycenter\', \'\')"></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'right_just.gif" width="18" height="18" alt="Align Right" title="Align Right" onClick="FormatText(\'' + rte + '\', \'justifyright\', \'\')"></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'justifyfull.gif" width="18" height="18" alt="Justify Full" title="Justify Full" onclick="FormatText(\'' + rte + '\', \'justifyfull\', \'\')"></td>');
		document.writeln('		<td><img class="rteVertSep" src="' + imagesPath + 'blackdot.gif" width="1" height="20" border="0" alt=""></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'hr.gif" width="18" height="18" alt="Horizontal Rule" title="Horizontal Rule" onClick="FormatText(\'' + rte + '\', \'inserthorizontalrule\', \'\')"></td>');
		document.writeln('		<td><img class="rteVertSep" src="' + imagesPath + 'blackdot.gif" width="1" height="20" border="0" alt=""></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'numbered_list.gif" width="18" height="18" alt="Ordered List" title="Ordered List" onClick="FormatText(\'' + rte + '\', \'insertorderedlist\', \'\')"></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'list.gif" width="18" height="18" alt="Unordered List" title="Unordered List" onClick="FormatText(\'' + rte + '\', \'insertunorderedlist\', \'\')"></td>');
		document.writeln('		<td><img class="rteVertSep" src="' + imagesPath + 'blackdot.gif" width="1" height="20" border="0" alt=""></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'outdent.gif" width="18" height="18" alt="Outdent" title="Outdent" onClick="FormatText(\'' + rte + '\', \'outdent\', \'\')"></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'indent.gif" width="18" height="18" alt="Indent" title="Indent" onClick="FormatText(\'' + rte + '\', \'indent\', \'\')"></td>');
		document.writeln('		<td><div id="forecolor_' + rte + '"><img class="rteImage" src="' + imagesPath + 'textcolor.gif" width="18" height="18" alt="Text Color" title="Text Color" onClick="FormatText(\'' + rte + '\', \'forecolor\', \'\')"></div></td>');
		document.writeln('		<td><img class="rteVertSep" src="' + imagesPath + 'blackdot.gif" width="1" height="20" border="0" alt=""></td>');
		document.writeln('		<td><img class="rteImage" src="' + imagesPath + 'hyperlink.gif" width="18" height="18" alt="Insert Link" title="Insert Link" onClick="FormatText(\'' + rte + '\', \'createlink\')"></td>');
		document.writeln('		<td><img class="rteVertSep" src="' + imagesPath + 'blackdot.gif" width="1" height="20" border="0" alt=""></td>');
		document.writeln('		<td>');
		document.writeln('			<select unselectable="on" id="fontsize_' + rte + '" onchange="Select(\'' + rte + '\', this.id);">');
		document.writeln('				<option value="Size">[Size]</option>');
		document.writeln('				<option value="1">1</option>');
		document.writeln('				<option value="2">2</option>');
		document.writeln('				<option value="3">3</option>');
		document.writeln('				<option value="4">4</option>');
		document.writeln('				<option value="5">5</option>');
		document.writeln('				<option value="6">6</option>');
		document.writeln('				<option value="7">7</option>');
		document.writeln('			</select>');
		document.writeln('		</td>');
		document.writeln('		<td width="100%"></td>');
		document.writeln('	</tr>');
		document.writeln('</table>');
	}
	document.writeln('<iframe id="' + rte + '" name="' + rte + '" style="width:' + width + 'px;height:' + height + 'px;border: 2px outset #415E93;"></iframe>');
	//if (!readOnly) document.writeln('<br /><input type="checkbox" id="chkSrc' + rte + '" onclick="toggleHTMLSrc(\'' + rte + '\');" />&nbsp;View Source');
	document.writeln('<iframe width="154" height="104" id="cp' + rte + '" src="' + includesPath + 'palette.htm" marginwidth="0" marginheight="0" scrolling="no" style="visibility:hidden; display: none; position: absolute;"></iframe>');
	document.writeln('<input type="hidden" id="hdn' + rte + '" name="' + rte + '" value="">');
	document.writeln('</div>');
	
	document.getElementById('hdn' + rte).value = html;

	enableDesignMode(rte, html, readOnly);
}

function enableDesignMode(rte, html, readOnly) {
	var frameHtml = "<html id=\"" + rte + "\">\n";
	frameHtml += "<head>\n";
	//to reference your stylesheet, set href property below to your stylesheet path and uncomment
	if (cssFile.length > 0) {
		frameHtml += "<link media=\"all\" type=\"text/css\" href=\"" + includesPath + cssFile + "\" rel=\"stylesheet\">\n";
	} else {
		frameHtml += "<style>\n";
		frameHtml += "body {\n";
		frameHtml += "	background: #FFFFFF;\n";
		frameHtml += "	margin: 0px;\n";
		frameHtml += "	padding: 0px;\n";
		frameHtml += "}\n";
		frameHtml += "</style>\n";
	}
	frameHtml += "</head>\n";
	frameHtml += "<body class='bodyRte'>\n";
	frameHtml += html + "\n";
	frameHtml += "</body>\n";
	frameHtml += "</html>";
	
	if (document.all) {
		var oRTE = frames[rte].document;
		oRTE.open();
		oRTE.write(frameHtml);
		oRTE.close();
		if (!readOnly) oRTE.designMode = "On";
	} else {
		try {
			if (!readOnly) document.getElementById(rte).contentDocument.designMode = "on";
			try {
				var oRTE = document.getElementById(rte).contentWindow.document;
				oRTE.open();
				oRTE.write(frameHtml);
				oRTE.close();
				if (isGecko && !readOnly) {
					//attach a keyboard handler for gecko browsers to make keyboard shortcuts work
					oRTE.addEventListener("keypress", kb_handler, true);
					oRTE.addEventListener("blur", function() { checkRequiredRTE(rte); }, true);
				}
			} catch (e) {
				alert("Error preloading content.");
			}
		} catch (e) {
			//gecko may take some time to enable design mode.
			//Keep looping until able to set.
			if (isGecko) {
				setTimeout("enableDesignMode('" + rte + "', '" + html + "', " + readOnly + ");", 10);
			} else {
				return false;
			}
		}
	}
}

function updateRTEs() {
	var vRTEs = allRTEs.split(";");
	for (var i = 0; i < vRTEs.length; i++) {
		updateRTE(vRTEs[i]);
	}
}

function updateRTE(rte) {
	if (!isRichText) return;
	
	//set message value
	var oHdnMessage = document.getElementById('hdn' + rte);
	var oRTE = document.getElementById(rte);
	var readOnly = false;
	
	//check for readOnly mode
	if (document.all) {
		if (frames[rte].document.designMode != "On") readOnly = true;
	} else {
		if (document.getElementById(rte).contentDocument.designMode != "on") readOnly = true;
	}
	
	if (isRichText && !readOnly) {
		//if viewing source, switch back to design view
		if (document.getElementById("chkSrc" + rte) && document.getElementById("chkSrc" + rte).checked) {
			document.getElementById("chkSrc" + rte).checked = false;
			toggleHTMLSrc(rte);
		}
		
		if (oHdnMessage.value == null) oHdnMessage.value = "";
		if (document.all) {
			oHdnMessage.value = frames[rte].document.body.innerHTML;
		} else {
			oHdnMessage.value = oRTE.contentWindow.document.body.innerHTML;
		}
		
		//if there is no content (other than formatting) set value to nothing
		if (stripHTML(oHdnMessage.value.replace("&nbsp;", " ")) == "" 
			&& oHdnMessage.value.toLowerCase().search("<hr") == -1
			&& oHdnMessage.value.toLowerCase().search("<img") == -1) oHdnMessage.value = "";
		//fix for gecko
		if (escape(oHdnMessage.value) == "%3Cbr%3E%0D%0A%0D%0A%0D%0A") oHdnMessage.value = "";
	}
}

function toggleHTMLSrc(rte) {
	//contributed by Bob Hutzel (thanks Bob!)
	var oRTE;
	if (document.all) {
		oRTE = frames[rte].document;
	} else {
		oRTE = document.getElementById(rte).contentWindow.document;
	}
	
	if (document.getElementById("chkSrc" + rte) && document.getElementById("chkSrc" + rte).checked) {
		//document.getElementById("Buttons1_" + rte).style.visibility = "hidden";
		document.getElementById("Buttons2_" + rte).style.visibility = "hidden";
		if (document.all) {
			oRTE.body.innerText = oRTE.body.innerHTML;
		} else {
			var htmlSrc = oRTE.createTextNode(oRTE.body.innerHTML);
			oRTE.body.innerHTML = "";
			oRTE.body.appendChild(htmlSrc);
		}
	} else {
		//document.getElementById("Buttons1_" + rte).style.visibility = "visible";
		document.getElementById("Buttons2_" + rte).style.visibility = "visible";
		if (document.all) {
			//fix for IE
			var output = escape(oRTE.body.innerText);
			output = output.replace("%3CP%3E%0D%0A%3CHR%3E", "%3CHR%3E");
			output = output.replace("%3CHR%3E%0D%0A%3C/P%3E", "%3CHR%3E");
			
			oRTE.body.innerHTML = unescape(output);
		} else {
			var htmlSrc = oRTE.body.ownerDocument.createRange();
			htmlSrc.selectNodeContents(oRTE.body);
			oRTE.body.innerHTML = htmlSrc.toString();
		}
	}
}

//Function to format text in the text box
function FormatText(rte, command, option) {
	var oRTE;
	if (document.all) {
		oRTE = frames[rte];
		
		//get current selected range
		var selection = oRTE.document.selection; 
		if (selection != null) {
			rng = selection.createRange();
		}
	} else {
		oRTE = document.getElementById(rte).contentWindow;
		
		//get currently selected range
		var selection = oRTE.getSelection();
		rng = selection.getRangeAt(selection.rangeCount - 1).cloneRange();
	}
	
	try {
		if ((command == "forecolor") || (command == "hilitecolor")) {
			//save current values
			parent.command = command;
			currentRTE = rte;
			
			//position and show color palette
			buttonElement = document.getElementById(command + '_' + rte);
			// Ernst de Moor: Fix the amount of digging parents up, in case the RTE editor itself is displayed in a div.
			document.getElementById('cp' + rte).style.left = getOffsetLeft(buttonElement, 4) + "px";
			document.getElementById('cp' + rte).style.top = (getOffsetTop(buttonElement, 4) + buttonElement.offsetHeight + 4) + "px";
			if (document.getElementById('cp' + rte).style.visibility == "hidden") {
				document.getElementById('cp' + rte).style.visibility = "visible";
				document.getElementById('cp' + rte).style.display = "inline";
			} else {
				document.getElementById('cp' + rte).style.visibility = "hidden";
				document.getElementById('cp' + rte).style.display = "none";
			}
		} else if (command == "createlink") {
			var szURL = prompt("Enter a URL:", "");
			try {
				//ignore error for blank urls
				oRTE.document.execCommand("Unlink", false, null);
				oRTE.document.execCommand("CreateLink", false, szURL);
			} catch (e) {
				//do nothing
			}
		} else {
			oRTE.focus();
		  	oRTE.document.execCommand(command, false, option);
			oRTE.focus();
		}
	} catch (e) {
		alert(e);
	}
}

//Function to set color
function setColor(color) {
	var rte = currentRTE;
	var oRTE;
	if (document.all) {
		oRTE = frames[rte];
	} else {
		oRTE = document.getElementById(rte).contentWindow;
	}
	
	var parentCommand = parent.command;
	if (document.all) {
		//retrieve selected range
		var sel = oRTE.document.selection; 
		if (parentCommand == "hilitecolor") parentCommand = "backcolor";
		if (sel != null) {
			var newRng = sel.createRange();
			newRng = rng;
			newRng.select();
		}
	}
	oRTE.focus();
	oRTE.document.execCommand(parentCommand, false, color);
	oRTE.focus();
	document.getElementById('cp' + rte).style.visibility = "hidden";
	document.getElementById('cp' + rte).style.display = "none";
}

//Function to add image
function AddImage(rte) {
	var oRTE;
	if (document.all) {
		oRTE = frames[rte];
		
		//get current selected range
		var selection = oRTE.document.selection; 
		if (selection != null) {
			rng = selection.createRange();
		}
	} else {
		oRTE = document.getElementById(rte).contentWindow;
		
		//get currently selected range
		var selection = oRTE.getSelection();
		rng = selection.getRangeAt(selection.rangeCount - 1).cloneRange();
	}
	
	imagePath = prompt('Enter Image URL:', 'http://');				
	if ((imagePath != null) && (imagePath != "")) {
		oRTE.focus();
		oRTE.document.execCommand('InsertImage', false, imagePath);
		oRTE.focus();
	}
}

//function to perform spell check
function checkspell() {
	try {
		var tmpis = new ActiveXObject("ieSpell.ieSpellExtension");
		tmpis.CheckAllLinkedDocuments(document);
	}
	catch(exception) {
		if(exception.number==-2146827859) {
			if (confirm("ieSpell not detected.  Click Ok to go to download page."))
				window.open("http://www.iespell.com/download.php","DownLoad");
		} else {
			alert("Error Loading ieSpell: Exception " + exception.number);
		}
	}
}

// Ernst de Moor: Fix the amount of digging parents up, in case the RTE editor itself is displayed in a div.
function getOffsetTop(elm, parents_up) {
	var mOffsetTop = elm.offsetTop;
	var mOffsetParent = elm.offsetParent;
	
	if(!parents_up) {
		parents_up = 10000; // arbitrary big number
	}
	while(parents_up>0 && mOffsetParent) {
		mOffsetTop += mOffsetParent.offsetTop;
		mOffsetParent = mOffsetParent.offsetParent;
		parents_up--;
	}
	
	return mOffsetTop;
}

// Ernst de Moor: Fix the amount of digging parents up, in case the RTE editor itself is displayed in a div.
function getOffsetLeft(elm, parents_up) {
	var mOffsetLeft = elm.offsetLeft;
	var mOffsetParent = elm.offsetParent;
	
	if(!parents_up) {
		parents_up = 10000; // arbitrary big number
	}
	while(parents_up>0 && mOffsetParent) {
		mOffsetLeft += mOffsetParent.offsetLeft;
		mOffsetParent = mOffsetParent.offsetParent;
		parents_up--;
	}
	
	return mOffsetLeft;
}

function Select(rte, selectname) {
	var oRTE;
	if (document.all) {
		oRTE = frames[rte];
		
		//get current selected range
		var selection = oRTE.document.selection; 
		if (selection != null) {
			rng = selection.createRange();
		}
	} else {
		oRTE = document.getElementById(rte).contentWindow;
		
		//get currently selected range
		var selection = oRTE.getSelection();
		rng = selection.getRangeAt(selection.rangeCount - 1).cloneRange();
	}
	
	var idx = document.getElementById(selectname).selectedIndex;
	// First one is always a label
	if (idx != 0) {
		var selected = document.getElementById(selectname).options[idx].value;
		var cmd = selectname.replace('_' + rte, '');
		oRTE.focus();
		oRTE.document.execCommand(cmd, false, selected);
		oRTE.focus();
		document.getElementById(selectname).selectedIndex = 0;
	}
}

function kb_handler(evt) {
	var rte = evt.target.id;
	
	//contributed by Anti Veeranna (thanks Anti!)
	if (evt.ctrlKey) {
		var key = String.fromCharCode(evt.charCode).toLowerCase();
		var cmd = '';
		switch (key) {
			case 'b': cmd = "bold"; break;
			case 'i': cmd = "italic"; break;
			case 'u': cmd = "underline"; break;
		};

		if (cmd) {
			FormatText(rte, cmd, true);
			//evt.target.ownerDocument.execCommand(cmd, false, true);
			// stop the event bubble
			evt.preventDefault();
			evt.stopPropagation();
		}
 	}
}

function checkRequiredRTE(rte){
	changed(document.getElementById(rte));
}




function stripHTML(oldString) {
	var newString = oldString.replace(/(<([^>]+)>)/ig,"");
	
	//replace carriage returns and line feeds
   newString = newString.replace(/\r\n/g," ");
   newString = newString.replace(/\n/g," ");
   newString = newString.replace(/\r/g," ");
	
	//trim string
	newString = trim(newString);
	
	return newString;
}

function trim(inputString) {
   // Removes leading and trailing spaces from the passed string. Also removes
   // consecutive spaces and replaces it with one space. If something besides
   // a string is passed in (null, custom object, etc.) then return the input.
   if (typeof inputString != "string") return inputString;
   var retValue = inputString;
   var ch = retValue.substring(0, 1);
	
   while (ch == " ") { // Check for spaces at the beginning of the string
      retValue = retValue.substring(1, retValue.length);
      ch = retValue.substring(0, 1);
   }
   ch = retValue.substring(retValue.length-1, retValue.length);
	
   while (ch == " ") { // Check for spaces at the end of the string
      retValue = retValue.substring(0, retValue.length-1);
      ch = retValue.substring(retValue.length-1, retValue.length);
   }
	
	// Note that there are two spaces in the string - look for multiple spaces within the string
   while (retValue.indexOf("  ") != -1) {
		// Again, there are two spaces in each of the strings
      retValue = retValue.substring(0, retValue.indexOf("  ")) + retValue.substring(retValue.indexOf("  ")+1, retValue.length);
   }
   return retValue; // Return the trimmed string back to the user
}


// -----------------------------------------------------------------------------------
//
//	Lightbox v2.04
//	by Lokesh Dhakar - http://www.lokeshdhakar.com
//	Last Modification: 2/9/08
//
//	For more information, visit:
//	http://lokeshdhakar.com/projects/lightbox2/
//
//	Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
//  	- Free for use in both personal and commercial projects
//		- Attribution requires leaving author name, author link, and the license info intact.
//	
//  Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets.
//  		Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous.
//
// -----------------------------------------------------------------------------------
/*

    Table of Contents
    -----------------
    Configuration

    Lightbox Class Declaration
    - initialize()
    - updateImageList()
    - start()
    - changeImage()
    - resizeImageContainer()
    - showImage()
    - updateDetails()
    - updateNav()
    - enableKeyboardNav()
    - disableKeyboardNav()
    - keyboardAction()
    - preloadNeighborImages()
    - end()
    
    Function Calls
    - document.observe()
   
*/
// -----------------------------------------------------------------------------------

//
//  Configurationl
//

var idiomaJs = getCookie('lang');

LightboxOptions = Object.extend({
    fileLoadingImage:        '../images/lightbox/loading.gif',     
    fileBottomNavCloseImage: '../images/lightbox/closelabel_'+ idiomaJs +'.gif',

    overlayOpacity: 0.8,   // controls transparency of shadow overlay

    animate: true,         // toggles resizing animations
    resizeSpeed: 7,        // controls the speed of the image resizing animations (1=slowest and 10=fastest)

    borderSize: 10,         //if you adjust the padding in the CSS, you will need to update this variable

	// When grouping images this is used to write: Image # of #.
	// Change it for non-english localization
	labelImage: "",
	labelOf: "-"
}, window.LightboxOptions || {});

// -----------------------------------------------------------------------------------

var Lightbox = Class.create();
Lightbox.prototype = {
    imageArray: [],
    activeImage: undefined,
    
    // initialize()
    // Constructor runs on completion of the DOM loading. Calls updateImageList and then
    // the function inserts html at the bottom of the page which is used to display the shadow 
    // overlay and the image container.
    //
    initialize: function() {    
        
        this.updateImageList();
        
        this.keyboardAction = this.keyboardAction.bindAsEventListener(this);

        if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10;
        if (LightboxOptions.resizeSpeed < 1)  LightboxOptions.resizeSpeed = 1;

	    this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0;
	    this.overlayDuration = LightboxOptions.animate ? 0.2 : 0;  // shadow fade in/out duration

        // When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
        // If animations are turned off, it will be hidden as to prevent a flicker of a
        // white 250 by 250 box.
        var size = (LightboxOptions.animate ? 250 : 1) + 'px';
        
		var pos = Element.getStyle($$('.salto')[0], 'top');
		this.estilosActivados = pos ? true : false;
		this.estilosActivados = true;
		if(!this.estilosActivados){
			LightboxOptions.fileLoadingImage = '../images/lightbox/spacer.gif';
			LightboxOptions.fileBottomNavCloseImage = '../images/lightbox/spacer.gif';
		}
		
        // Code inserts html at the bottom of the page that looks similar to this:
        //
        //  <div id="overlay"></div>
        //  <div id="lightbox">
        //      <div id="outerImageContainer">
        //          <div id="imageContainer">
        //              <img id="lightboxImage">
        //              <div style="" id="hoverNav">
        //                  <a href="#" id="prevLink"></a>
        //                  <a href="#" id="nextLink"></a>
        //              </div>
        //              <div id="loading">
        //                  <a href="#" id="loadingLink">
        //                      <img src="js/images/lightbox/loading.gif">
        //                  </a>
        //              </div>
        //          </div>
        //      </div>
        //      <div id="imageDataContainer">
        //          <div id="imageData">
        //              <div id="imageDetails">
        //                  <span id="caption"></span>
        //                  <span id="numberDisplay"></span>
        //              </div>
        //              <div id="bottomNav">
        //                  <a href="#" id="bottomNavClose">
        //                      <img src="js/images/lightbox/close.gif">
        //                  </a>
        //              </div>
        //          </div>
        //      </div>
        //  </div>
		
		
        var objBody = $$('body')[0];

		objBody.appendChild(Builder.node('div',{id:'overlay'}));
	
        objBody.appendChild(Builder.node('div',{id:'lightbox'}, [
            Builder.node('div',{id:'outerImageContainer'}, 
                Builder.node('div',{id:'imageContainer'}, [
                    Builder.node('img',{id:'lightboxImage'}), 
                    Builder.node('div',{id:'hoverNav',className:'lang_'+idiomaJs}, [
                        Builder.node('a',{id:'prevLink', href: '#' }),
                        Builder.node('a',{id:'nextLink', href: '#' })
                    ]),
                    Builder.node('div',{id:'loading'}, 
                        Builder.node('a',{id:'loadingLink', href: '#' }, 
                            Builder.node('img', {src: LightboxOptions.fileLoadingImage})
                        )
                    )
                ])
            ),
            Builder.node('div', {id:'imageDataContainer'},
                Builder.node('div',{id:'imageData'}, [
                    Builder.node('div',{id:'imageDetails'}, [
                        Builder.node('span',{id:'caption'}),
                        Builder.node('span',{id:'numberDisplay'})
                    ]),
                    Builder.node('div',{id:'bottomNav'},
                        Builder.node('a',{id:'bottomNavClose', href: '#' },
                            Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage })
                        )
                    )
                ])
            )
        ]));


		$('overlay').hide().observe('click', (function() { this.end(); }).bind(this));
		$('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this));
		$('outerImageContainer').setStyle({ width: size, height: size });
		$('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this));
		$('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this));
		$('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
		$('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
		
		//$('prevLink').setStyle({ backgroundImage: 'url(../images/lightbox/prevlabel_'+ idiomaJs +'.gif)' });
		//$('nextLink').setStyle({ backgroundImage: 'url(../images/lightbox/nextlabel_'+ idiomaJs +'.gif)' });

        var th = this;
        (function(){
            var ids = 
                'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' + 
                'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose';   
            $w(ids).each(function(id){ th[id] = $(id); });
        }).defer();
    },

    //
    // updateImageList()
    // Loops through anchor tags looking for 'lightbox' references and applies onclick
    // events to appropriate links. You can rerun after dynamically adding images w/ajax.
    //
    updateImageList: function() {   
        this.updateImageList = Prototype.emptyFunction;

        document.observe('click', (function(event){
            var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]');
            if (target) {
                event.stop();
                this.start(target);
            }
        }).bind(this));
    },
    
    //
    //  start()
    //  Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
    //
    start: function(imageLink) {    

        $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });

        // stretch overlay to fill page and fade in
        var arrayPageSize = this.getPageSize();
        $('overlay').setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' });

        new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity });

        this.imageArray = [];
        var imageNum = 0;       

        if ((imageLink.rel == 'lightbox')){
            // if image is NOT part of a set, add single image to imageArray
            this.imageArray.push([imageLink.href, imageLink.title]);         
        } else {
            // if image is part of a set..
            this.imageArray = 
                $$(imageLink.tagName + '[href][rel="' + imageLink.rel + '"]').
                collect(function(anchor){ return [anchor.href, anchor.title]; }).
                uniq();
            
            while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; }
        }

        // calculate top and left offset for the lightbox 
        var arrayPageScroll = document.viewport.getScrollOffsets();
        var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10);
        var lightboxLeft = arrayPageScroll[0];
        this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show();
        
        this.changeImage(imageNum);
    },

    //
    //  changeImage()
    //  Hide most elements and preload image in preparation for resizing image container.
    //
    changeImage: function(imageNum) {   
        
        this.activeImage = imageNum; // update global var

        // hide elements during transition
        if (LightboxOptions.animate) this.loading.show();
        this.lightboxImage.hide();
        this.hoverNav.hide();
        this.prevLink.hide();
        this.nextLink.hide();
		// HACK: Opera9 does not currently support scriptaculous opacity and appear fx
        this.imageDataContainer.setStyle({opacity: .0001});
        this.numberDisplay.hide();      
        
        var imgPreloader = new Image();
        
        // once image is preloaded, resize image container


        imgPreloader.onload = (function(){
            this.lightboxImage.src = this.imageArray[this.activeImage][0];
            this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
        }).bind(this);
        imgPreloader.src = this.imageArray[this.activeImage][0];
    },

    //
    //  resizeImageContainer()
    //
    resizeImageContainer: function(imgWidth, imgHeight) {

        // get current width and height
        var widthCurrent  = this.outerImageContainer.getWidth();
        var heightCurrent = this.outerImageContainer.getHeight();

        // get new width and height
        var widthNew  = (imgWidth  + LightboxOptions.borderSize * 2);
        var heightNew = (imgHeight + LightboxOptions.borderSize * 2);

        // scalars based on change from old to new
        var xScale = (widthNew  / widthCurrent)  * 100;
        var yScale = (heightNew / heightCurrent) * 100;

        // calculate size difference between new and old image, and resize if necessary
        var wDiff = widthCurrent - widthNew;
        var hDiff = heightCurrent - heightNew;

        if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'}); 
        if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration}); 

        // if new and old image are same size and no scaling transition is necessary, 
        // do a quick pause to prevent image flicker.
        var timeout = 0;
        if ((hDiff == 0) && (wDiff == 0)){
            timeout = 100;
            if (Prototype.Browser.IE) timeout = 250;   
        }

        (function(){
            this.prevLink.setStyle({ height: imgHeight + 'px' });
            this.nextLink.setStyle({ height: imgHeight + 'px' });
            this.imageDataContainer.setStyle({ width: widthNew + 'px' });

            this.showImage();
        }).bind(this).delay(timeout / 1000);
    },
    
    //
    //  showImage()
    //  Display image and begin preloading neighbors.
    //
    showImage: function(){
        this.loading.hide();
        new Effect.Appear(this.lightboxImage, { 
            duration: this.resizeDuration, 
            queue: 'end', 
            afterFinish: (function(){ this.updateDetails(); }).bind(this) 
        });
        this.preloadNeighborImages();
    },

    //
    //  updateDetails()
    //  Display caption, image number, and bottom nav.
    //
    updateDetails: function() {
    
        // if caption is not null
        if (this.imageArray[this.activeImage][1] != ""){
            this.caption.update(this.imageArray[this.activeImage][1]).show();
        }
        
        // if image is part of set display 'Image x of x' 
        if (this.imageArray.length > 1){
            this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + '  ' + this.imageArray.length).show();
        }

        new Effect.Parallel(
            [ 
                new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }), 
                new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration }) 
            ], 
            { 
                duration: this.resizeDuration, 
                afterFinish: (function() {
	                // update overlay size and update nav
	                var arrayPageSize = this.getPageSize();
	                this.overlay.setStyle({ height: arrayPageSize[1] + 'px' });
	                this.updateNav();
                }).bind(this)
            } 
        );
    },

    //
    //  updateNav()
    //  Display appropriate previous and next hover navigation.
    //
    updateNav: function() {

        this.hoverNav.show();               

        // if not first image in set, display prev image button
        if (this.activeImage > 0) this.prevLink.show();

        // if not last image in set, display next image button
        if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show();
        
        this.enableKeyboardNav();
    },

    //
    //  enableKeyboardNav()
    //
    enableKeyboardNav: function() {
        document.observe('keydown', this.keyboardAction); 
    },

    //
    //  disableKeyboardNav()
    //
    disableKeyboardNav: function() {
        document.stopObserving('keydown', this.keyboardAction); 
    },

    //
    //  keyboardAction()
    //
    keyboardAction: function(event) {
        var keycode = event.keyCode;

        var escapeKey;
        if (event.DOM_VK_ESCAPE) {  // mozilla
            escapeKey = event.DOM_VK_ESCAPE;
        } else { // ie
            escapeKey = 27;
        }

        var key = String.fromCharCode(keycode).toLowerCase();
        
        if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox
            this.end();
        } else if ((key == 'p') || (keycode == 37)){ // display previous image
            if (this.activeImage != 0){
                this.disableKeyboardNav();
                this.changeImage(this.activeImage - 1);
            }
        } else if ((key == 'n') || (keycode == 39)){ // display next image
            if (this.activeImage != (this.imageArray.length - 1)){
                this.disableKeyboardNav();
                this.changeImage(this.activeImage + 1);
            }
        }
    },

    //
    //  preloadNeighborImages()
    //  Preload previous and next images.
    //
    preloadNeighborImages: function(){
        var preloadNextImage, preloadPrevImage;
        if (this.imageArray.length > this.activeImage + 1){
            preloadNextImage = new Image();
            preloadNextImage.src = this.imageArray[this.activeImage + 1][0];
        }
        if (this.activeImage > 0){
            preloadPrevImage = new Image();
            preloadPrevImage.src = this.imageArray[this.activeImage - 1][0];
        }
    
    },

    //
    //  end()
    //
    end: function() {
        this.disableKeyboardNav();
        this.lightbox.hide();
        new Effect.Fade(this.overlay, { duration: this.overlayDuration });
        $$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' });
    },

    //
    //  getPageSize()
    //
    getPageSize: function() {
	        
	     var xScroll, yScroll;
		
		if (window.innerHeight && window.scrollMaxY) {	
			xScroll = window.innerWidth + window.scrollMaxX;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}
		
		var windowWidth, windowHeight;
		
		if (self.innerHeight) {	// all except Explorer
			if(document.documentElement.clientWidth){
				windowWidth = document.documentElement.clientWidth; 
			} else {
				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 = xScroll;		
		} else {
			pageWidth = windowWidth;
		}

		return [pageWidth,pageHeight];
	}
}




document.observe('dom:loaded', function () { new Lightbox(); });
