/* <script type="text/javascript" src="../js/classes_applicator.js"></script> */

var CLASS_NUM = 'clapp_num';
var CLASS_TXT = 'clapp_txt';
var CLASS_URL = 'clapp_url';
var CLASS_RGB = 'clapp_rgb';
var CLASS_EML = 'clapp_eml';
var CLASS_COLOR_PICKER = 'clapp_cop'; // Aún no soportado.

/**
 * Verifica si el nombre de la clase está entre los soportados.
 *
 * @param class_name: Nombre de la clase.
 * @return: TRUE si la clase es soportada, FALSE en caso contrario.
 */
function is_supported_class(class_name)
{
   return ( class_name == CLASS_NUM
             || class_name == CLASS_TXT
             || class_name == CLASS_URL
             || class_name == CLASS_RGB
             || class_name == CLASS_EML
             || class_name == CLASS_COLOR_PICKER );
}

/**
 * Aplica a los objetos de clase 'num' los eventos correspondientes.
 * Se asume que todos los objetos con esta clase son de tipo 'input'.
 *
 * @param objects: (opcional) Array de objetos.
 *                 Si se lo especifica, los eventos son aplicados únicamente a los objetos indicados.
 *                 No se controla que estos objetos posean la clase 'num'.
 * @param node: (opcional) Si se lo especifica retorna sólo los objetos del DOM bajo ese nodo.
 */
function num_class_apply(objects, node)
{
   if (!objects) objects = getElementsByClassName(CLASS_NUM,'input',node);
   addObjectsEvents(objects, new Array('keyup','blur'), force_num)
}

/**
 * Aplica a los objetos de clase 'txt' los eventos correspondientes.
 * Se asume que todos los objetos con esta clase son de tipo 'input' o 'textarea'.
 *
 * @param objects: (opcional) Array de objetos.
 *                 Si se lo especifica, los eventos son aplicados únicamente a los objetos indicados.
 *                 No se controla que estos objetos posean la clase 'txt'.
 * @param node: (opcional) Si se lo especifica retorna sólo los objetos del DOM bajo ese nodo.
 */
function txt_class_apply(objects, node)
{
   if (!objects)
   {
      objects = getElementsByClassName(CLASS_TXT,'input',node);
      objects = objects.concat(getElementsByClassName(CLASS_TXT,'textarea',node));
   }
   addObjectsEvents(objects, new Array('focus'), get_txt);
   addObjectsEvents(objects, new Array('blur'), force_txt);
}

/**
 * Aplica a los objetos de clase 'url' los eventos correspondientes.
 * Se asume que todos los objetos con esta clase son de tipo 'input'.
 *
 * @param objects: (opcional) Array de objetos.
 *                 Si se lo especifica, los eventos son aplicados únicamente a los objetos indicados.
 *                 No se controla que estos objetos posean la clase 'url'.
 * @param node: (opcional) Si se lo especifica retorna sólo los objetos del DOM bajo ese nodo.
 */
function url_class_apply(objects, node)
{
   if (!objects) objects = getElementsByClassName(CLASS_URL,'input',node);
   addObjectsEvents(objects, new Array('blur'), force_url);
}

/**
 * Aplica a los objetos de clase 'rgb' los eventos correspondientes.
 * Se asume que todos los objetos con esta clase son de tipo 'input'.
 *
 * @param objects: (opcional) Array de objetos.
 *                 Si se lo especifica, los eventos son aplicados únicamente a los objetos indicados.
 *                 No se controla que estos objetos posean la clase 'rgb'.
 * @param node: (opcional) Si se lo especifica retorna sólo los objetos del DOM bajo ese nodo.
 */
function rgb_class_apply(objects, node)
{
   if (!objects) objects = getElementsByClassName(CLASS_RGB,'input',node);
   addObjectsEvents(objects, new Array('keyup','blur'), force_rgb);
}


/**
 * Aplica a los objetos de clase 'eml' los eventos correspondientes.
 * Se asume que todos los objetos con esta clase son de tipo 'input'.
 *
 * @param objects: (opcional) Array de objetos.
 *                 Si se lo especifica, los eventos son aplicados únicamente a los objetos indicados.
 *                 No se controla que estos objetos posean la clase 'eml'.
 * @param node: (opcional) Si se lo especifica retorna sólo los objetos del DOM bajo ese nodo.
 */
function eml_class_apply(objects, node)
{
   if (!objects) objects = getElementsByClassName(CLASS_EML,'input',node);
   addObjectsEvents(objects, new Array('blur'), force_eml);
}

/**
 * Aplica a los objetos con alguna de las clases soportadas los eventos correspondientes.
 *
 * @param node: (opcional) Si se lo especifica retorna sólo los objetos del DOM bajo ese nodo.
 */
function all_class_apply(node)
{
   if (!node) node = document;
   num_class_apply(null,node);
   txt_class_apply(null,node);
   url_class_apply(null,node);
   rgb_class_apply(null,node);
   eml_class_apply(null,node);
}

/* LISTENERS ******************************************************************/

/**
 * Analiza el value del objeto que provocó el evento, controlando que sea un número.
 * De no ser así, corrige el contenido.
 *
 * @param ev: Handler del evento.
 */
function force_num(ev)
{
   var obj = getEventTarget(ev);
   if (obj != null)
   {
      if (ev.type == 'blur' || obj.value.length > 0)
      {
         var ch;
         var txt = obj.value;
         var ok = true;
         var num = 0;
         for (var i = 0; (i < txt.length) && (ok); i++)
         {
            ch = txt.charAt(i);
            if (ch >= '0' && ch <= '9') num = (ch - 0) + num * 10;
            else ok = false;
         }
         obj.value = num;
      }
   }
}

/**
 * Analiza el value del objeto que provocó el evento, controlando que sea un texto (string no vacío).
 * De no ser así, corrige el contenido asignándole el último texto ingresado.
 *
 * @param ev: Handler del evento.
 */
function force_txt(ev)
{
   var obj = getEventTarget(ev);
   if (obj != null && obj.value.length == 0)
   {
      var ind = !obj.id ? obj.name : obj.id;
      obj.value = txtValues[ind];
   }
}

/**
 * Almacena el value del objeto que provocó el evento en txtValues[objeto.id]
 * Si el objeto no posee id, lo alamacena en objeto.name.
 *
 * @param ev: Handler del evento.
 */
function get_txt(ev)
{
   var obj = getEventTarget(ev);
   if (obj != null)
   {
      var ind = !obj.id ? obj.name : obj.id;
      txtValues[ind] = obj.value;
   }
}
var txtValues = new Array();

/**
 * Analiza el value del objeto que provocó el evento, controlando que sea una url (comienza por 'http://').
 * De no ser así, corrige el contenido.
 *
 * @param ev: Handler del evento.
 */
function force_url(ev)
{
   var obj = getEventTarget(ev);
   if (obj != null && obj.value.indexOf('http://') != 0)
   {
      obj.value = 'http://' + obj.value;
   }
}

/**
 * Analiza el value del objeto que provocó el evento, controlando que sea un color ('#rrggbb').
 * De no ser así, corrige el contenido.
 *
 * @param ev: Handler del evento.
 */
function force_rgb(ev)
{
   var obj = getEventTarget(ev);
   if (obj != null)
   {
      var txt = obj.value;
      var color = '#';

      for (var i = 1; i < txt.length; i++)
      {
         ch = txt.charAt(i);
         if ((ch>='0' && ch<='9') || (ch>='a' && ch<='f') || (ch>='A' && ch<='F'))
            color += ch;
      }

      if (ev.type == 'blur' && color.length != 7)
      {
         if (color.length > 7) color = color.substring(0,7);
         else
         {
            if (color.length == 0) color = '#';
            while (color.length < 7) color += '0';
         }
      }

      obj.value = color;
   }
}

/**
 * Analiza el value del objeto que provocó el evento, controlando que sea un email.
 * De no ser así, vacía el contenido.
 *
 * @param ev: Handler del evento.
 */
function force_eml(ev)
{
   var obj = getEventTarget(ev);
   if (obj != null)
   {
      var er = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
      if (!obj.value.match(er))
      {
         obj.value = "";
         obj.focus();
      }
   }
}

/* FUNCIONES DOM **************************************************************/

/**
 * Obtiene todos los objetos del DOM cuya clase es la indicada.
 *
 * @param class_name: Nombre de la clase buscada.
 * @param tag: Si se lo especifica retorna sólo objetos del DOM con ese tagname.
 * @param node: Si se lo especifica retorna sólo los objetos del DOM bajo ese nodo.
 * @return: Array con los objetos requeridos.
 */
function getElementsByClassName(class_name, tag, node)
{
   if (!node) node = document;
   if (!tag) tag = '*';

   var class_name = ' ' + class_name + ' ';
   var objects = new Array();

   var item_classes;
   var items = node.getElementsByTagName(tag);

   for (var i=0; i < items.length; i++)
   {
      item_classes = ' ' + items[i].className + ' ';
      if (item_classes.indexOf(class_name) != -1)
         objects.push(items[i]);
   }
   return objects;
}

/**
 * Asigna a un objeto, un listener para determinado evento.
 *
 * @param object: Objeto.
 * @param event: Tipo de evento ('focus', 'mouseover', 'keyup', etc).
 * @param method: Referencia al listener por asociar al objeto.
 */
function addObjectEvent(object, event, method)
{
   //alert(object.id + ' --> ' + event + ' = ' + method);
   if (object.addEventListener) object.addEventListener(event,method,true);
   else if (object.attachEvent) object.attachEvent("on"+event,method);
   else object['on'+event] = method;
}

/**
 * Asigna a un grupo de objetos, un listener para determinados eventos.
 *
 * @param objects: Array con los objetos requeridos.
 * @param events: Array con los eventos a los que asociará el listener
 *               ('focus', 'mouseover', 'keyup', etc).
 * @param method: Referencia al listener por asociar a cada objeto.
 */
function addObjectsEvents(objects, events, method)
{
   for (var i = 0; i < objects.length; i++) for (var j = 0; j < events.length; j++)
      addObjectEvent(objects[i], events[j], method);
}

/**
 * Dado un evento, retorna el objeto que lo provocó.
 *
 * @param event: Handler del evento.
 * @return: Objeto que provocó el evento, NULL en caso de error.
 */
function getEventTarget(event)
{
   var target = null;

	if (event && event.target)
		target = event.target;
	else if (window.event && window.event.srcElement)
		target = window.event.srcElement;

	return target;
}

/* FUNCIONES DE TESTING *******************************************************/

function testGEC(class_name, tag, node)
{
   var inputs = getElementsByClassName(class_name,tag,node);
   for (var i=0; i < inputs.length; i++)
   {
      alert(inputs[i].id);
   }
}
