function initializeAutoedits()
{
  // busco todos los elementos de la clase autoedit
  var allElem = document.all?document.all:document.getElementsByTagName("*");
  var autoedits = new Array();

  for(var h=0,j=allElem.length; h < j; h++)
  {
 	  if (allElem[h].getAttribute("autoedit"))
    {
      // tienen que tener id, si no les asigno uno random
      allElem[h].id = allElem[h].id == ""?Math.random():allElem[h].id;
      
      // como voy a estar moviendo los elementos del DOM 
      // y eso trae problemas para iterar, en lugar de iterar creo un array de ID's
      autoedits.push(allElem[h].id);
    }
  }
  // itero con los ID's, que no trae problemas
  for(i=0;i<autoedits.length;i++)
  {
    initializeAutoedit(autoedits[i]);
  }
}

function initializeAutoedit(initThis)
{
  // inicializo un solo elemento autoedit
  // util para cuando los demás ya están inicializados 
  // y acabamos de insertar uno nuevo dinamicamente
  
  var span = $(initThis);
  span.id = span.id == ""?Math.random():span.id;
  var parent = span.parentNode?span.parentNode:span.parentElement;
  var nextSibling = span.nextSibling;

  // autoEdit es el span contenedor del control que voy a dejar inserto aqui.
  var autoEdit = document.createElement('span');
  autoEdit.id = span.id + "_autoedit";

  // creo el campo de edicion
  if (span.getAttribute("mode") == "wysiwyg"){
    var editBox = document.createElement('textarea');
    // aqui habría que convertir el textarea en wysiwyg.
  } else if (span.getAttribute("mode") == "textarea"){
    var editBox = document.createElement('textarea');
  } else {
    var editBox = document.createElement('input');
    editBox.type = "text";
  }
  editBox.setAttribute("mode", span.getAttribute("mode"));

  //editBox.style.border = "none";
  editBox.style.borderStyle = "Dashed";
  editBox.style.borderWidth = "1px";

  // le asigno un ID y una CLASS similares a los del span, para que 
  // se le pueda dar un estilo a través de la hoja de estilos
  editBox.id = span.id + "_editbox";
  editBox.className = span.className + "_editbox"; 

  editBox.style.display = "none";
  addEvent(editBox,"keypress",function(){pressed_(autoEdit.id, arguments[0])});

  // creo el span de elemento vacio
  var empty = document.createElement(span.tagName);
  empty.innerHTML = span.getAttribute("emptyTxt")?span.getAttribute("emptyTxt"):"&lt;Click here to edit&gt;";
  empty.id = span.id + "_empty";
  empty.className = span.className + "_empty";
  if (span.innerHTML == "") {empty.style.display = ""} else {empty.style.display = "none"};
  addEvent(empty,"click",startEdit_);
   
  // creo el boton de submit
  var editBoxSubmit = document.createElement('img');
  editBoxSubmit.setAttribute("src", '/js/autoedit/AutoeditSave20.gif');
  editBoxSubmit.setAttribute("alt", '[Save]');
  editBoxSubmit.setAttribute("valign", 'center');
  editBoxSubmit.id = span.id + "_submit"; // le asigno un ID similar al de su parent
  editBoxSubmit.style.display = "none";
  addEvent(editBoxSubmit,"click",submit_);

  // creo la imagen de espera
  var wait = document.createElement("img");
  wait.id = span.id + "_wait"; // le asigno un ID similar al de su parent
  wait.setAttribute("src", '/js/autoedit/AutoeditWait20.gif');
  wait.setAttribute("alt", ' [Saving...] ');
  wait.style.display = "none";

  // quito del documento el span que estamos editando
  // y lo meto dentro del control autoedit
  parent.removeChild(span);
  autoEdit.appendChild(span);
 
  // inserto el campo, el boton y el gif oculto de espera en el div principal autoEdit
  autoEdit.appendChild(empty);
  autoEdit.appendChild(editBox);
  autoEdit.appendChild(editBoxSubmit);
  autoEdit.appendChild(wait);
  
  // el control autoedit debe saber de un modo facil los ID's de sus controles internos
  autoEdit.setAttribute('submitId', editBoxSubmit.id);
  autoEdit.setAttribute('editBoxId', editBox.id);
  autoEdit.setAttribute('waitId', wait.id);
  autoEdit.setAttribute('spanId', span.id);
  autoEdit.setAttribute('emptyId', empty.id);

  // creo el metodo edit dentro del span
  span.edit = startEdit_;
  
  // creo el metodo submit dentro de editBoxSubmit 
  // para que this valga lo correcto cuando se la llame
  editBoxSubmit.submit = submit_;  
  span.submit = function() { return editBoxSubmit.submit(); };

  span.getMode = function() { return editBox.getAttribute("mode"); };  
  editBox.getMode = function() { return span.getMode(); };  

  span.setMode = function(mode) { span.setAttribute("mode", mode); editBox.setAttribute("mode", mode); };  
  editBox.setMode = function(mode) { span.setMode(mode); };  

  span.getValue = function() { return editBox.value; };
  span.setValue = function() { editBox.value = arguments[0]; };
  
  addEvent(span,"click",startEdit_);
  if (span.innerHTML == "") {span.style.display = "none"} else {span.style.display = ""};
  span.style.cursor = "pointer";
  empty.style.cursor = "pointer";

  // muestro el control autoedit
  parent.insertBefore(autoEdit, nextSibling);    
}

function startEdit_()
{
  var autoEdit = this.parentNode?this.parentNode:this.parentElement;
  var editBox = $(autoEdit.getAttribute('editBoxId'));
  var editBoxSubmit = $(autoEdit.getAttribute('submitId'));
  var span = $(autoEdit.getAttribute('spanId'));
  var empty = $(autoEdit.getAttribute('emptyId'));
  
  if(editBox.style.width == "")
  { 
    var width = getWidth(span);
    //editBox.style.width = width < 300 ? 300 : width;
  }

  if(editBox.style.height == "" && (span.getAttribute("mode") == "textarea" || span.getAttribute("mode") == "wysiwyg"))
  {
    var height = getHeight(span);
    editBox.style.height = height < 200 ? 200 : height;
  }
  
  editBox.value = span.innerHTML;
  
  // oculto el span y muestro el editbox
  span.style.display = "none";
  empty.style.display = "none";
  editBox.style.display = "";
  editBoxSubmit.style.display = "";
  
  //y le doy el foco para que el usuario lo edite
  editBox.focus();
}

function pressed_(autoEditId, e)
{
  var evt = (e)?e:(window.event)?window.event:null; 
  if(evt)
  { 
    var key=(evt.charCode)?evt.charCode: ((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
	if(key=="13") 
	{
	  // se presiono ENTER (13) o Ctrl+ENTER (10 en IE, 13 en los demás)
      var ctrlPressed = evt.modifiers?(evt.modifiers & Event.CONTROL_MASK):evt.ctrlKey;
	  if(ctrlPressed) 
	  {
	    submit_(autoEditId);  // Ctrl+ENTER
	  } else { // ENTER solo
        // hay que averiguar si estamos en un INPUT TYPE TEXT o en un TEXTAREA
        var mode = $($(autoEditId).getAttribute("editBoxId")).getAttribute("mode");
        mode = mode ? mode.toLowerCase(): "";

        if (mode!="textarea" && mode!="wysiwyg") submit_(autoEditId);  // ENTER en un INPUT TYPE TEXT
	  }
	}
    if(key=="10") submit_(autoEditId); // Ctrl+ENTER según IE7
	if(key=="27") cancel_(autoEditId);
  } 
}

function cancel_(autoEditId)
{
  var autoEdit = $(autoEditId);
  var editBox = $(autoEdit.getAttribute('editBoxId'));
  var editBoxSubmit = $(autoEdit.getAttribute('submitId'));
  var span = $(autoEdit.getAttribute("spanId"));
  var wait = $(autoEdit.getAttribute("waitId"));
  var empty = $(autoEdit.getAttribute("emptyId"));

  try {editBox.blur();} catch(e) {}; //necesario en Opera
 
  span.style.cursor = "pointer";
  empty.style.cursor = "pointer";
  
  wait.style.display = "none";
  editBox.style.display = "none";
  editBoxSubmit.style.display = "none";
  
  if (span.innerHTML == "") {empty.style.display = "";} else {span.style.display = "";}
    
  editBox.value = span.innerHTML;
  
  if(Fat) { Fat.fade_element(span.id,60,600, "#FF0000"); }
}

function submit_(autoEditId)
{
  // si autoEditId no es nada es porque "this" es el boton de submit
  if (typeof autoEditId == "string") {
    var autoEdit = $(autoEditId);
    var editBoxSubmit = $(autoEdit.getAttribute('submitId'));
  } else {
    var autoEdit = this.parentNode?this.parentNode:this.parentElement;
    var editBoxSubmit = this;
  }
  var editBox = $(autoEdit.getAttribute('editBoxId'));
  var span = $(autoEdit.getAttribute('spanId'));
  try {editBox.focus();editBox.blur();} catch(e) {}; //necesario en Opera
   
  // obtenemos el action (default: mismo URL) y el method (default: get)
  var action = span.getAttribute("action")?span.getAttribute("action"):window.location.href;
  var method = span.getAttribute("method")?span.getAttribute("method"):"get";
  var name = span.getAttribute("autoedit")?span.getAttribute("autoedit"):"value";
  var extraParams = span.getAttribute("parameters");
  
  /* Inicio procesamiento de la validación (onSubmit) */
    // si hay una funcion de validacion la ejecutamos, si da falso se anula el submit y salimos.
  var onsubmit = span.getAttribute("onsubmit")?"var _fun = function() {" + span.getAttribute("onsubmit")+"}":"var _fun = function() {return true;}";
  try {
    eval(onsubmit); // evaluamos la cadena y se crea la funcion _fun
    var returnValue = _fun(); // la ejecutamos
  } catch (e) {}
  if(!returnValue){  // si dio false cancelamos todo
    return false;
  } // sino continuamos
  /* Fin procesamiento de la validación (onSubmit) */


  // inserto la imagen de espera en lugar del diskette
  wait = $(autoEdit.getAttribute("waitId"));
  wait.style.display = "";
  editBoxSubmit.style.display = "none";
    
  var params = name + "=" + encodeURIComponent(editBox.value);
  params = extraParams == "" ? params + "&" + extraParams : params;
  
  var success_ = function() { success__(autoEdit.id, arguments[0]); };
  var failure_ = function() { failure__(autoEdit.id, arguments[0]); };
  
  var myAjax = new Ajax.Request(
  action, 
  {
    method: method, 
    parameters: params, 
    onSuccess: success_,
    onFailure: failure_
  });
}

function success__(autoEditId, XMLHttp) {
  var autoEdit = $(autoEditId);
  var span = $(autoEdit.getAttribute("spanId"));
  var wait = $(autoEdit.getAttribute("waitId"));
  var editBox = $(autoEdit.getAttribute("editBoxId"));
  var empty = $(autoEdit.getAttribute("emptyId"));
  
  span.innerHTML = editBox.value;
  span.style.cursor = "pointer";
  
  // muestro el contenido modificado y llamo al Yellow Fade
  wait.style.display = "none";
  editBox.style.display = "none";

  if (span.innerHTML == "") {empty.style.display = "";} else {span.style.display = "";}

   /* Inicio del onSuccess */
  var onsuccess = span.getAttribute("onsuccess")?"var _fun = function() {" + span.getAttribute("onsuccess")+"}":"var _fun = function() {return true;}";
  try {
    eval(onsuccess); // evaluamos la cadena y se crea la funcion _fun
    var returnValue = _fun(); // la ejecutamos
  } catch (e) {}
  /* Fin del onSuccess */
  
  if(returnValue && Fat) Fat.fade_element(span.id,60,600);
  
  return returnValue;
}

function failure__(autoEditId, XMLHttp) {
  var autoEdit = $(autoEditId);
  var span = $(autoEdit.getAttribute("spanId"));
  var wait = $(autoEdit.getAttribute("waitId"));
  var editBox = $(autoEdit.getAttribute("editBoxId"));
  
  editBox.value = span.innerHTML;
  span.style.cursor = "pointer";
  
  // muestro el contenido original y llamo al Yellow Fade con color rojo
  wait.style.display = "none";
  editBox.style.display = "none";
  span.style.display = "";
  
   /* Inicio del onFailure */
  var onfailure = span.getAttribute("onfailure")?"var _fun = function() {" + span.getAttribute("onfailure")+"}":"var _fun = function() {return true;}";
  try { 
    eval(onfailure); // evaluamos la cadena y se crea la funcion _fun
    var returnValue = _fun(); // la ejecutamos
  } catch (e) {}
  /* Fin del onFailure */
  
  if(returnValue && Fat) Fat.fade_element(span.id,60,600,"#FF0000");
  
  return returnValue;
}

addLoadListener(initializeAutoedits);