Easy Form

Éste módulo sirve para validaciones de formularios, personalizar checkbox y selects.

Para empezar, definimos los módulos que requerimos, en éste caso validateExt, alphanumeric y probablemente datepicker en caso que nuestro formulario requiera de campos del tipo date.

define([
  /*'datepicker',*/
  'validateExt',
  'alphanumeric'
], function() {

A continuación, la función setupEasyForm

function setupEasyForm() {
    var $form = $('form');

    // Inicializamos el jQuery Validate
    $form.validate({
      errorClass: 'ElementForm-label--error'
    });

    // En esta parte, con la función $.each recorreremos  
    // nuestro formulario y buscaremos inputs que tengan el  
    // atributo date.  
    $.each($('input[date]'), function(index) {  
      // Para cada uno de éstos inputs, obtendremos el 
      // valor mínimo y máximo que puede recibir.
      var minValue = $(this).attr('data-rule-mindate').split('/'),
        maxValue = $(this).attr('data-rule-maxdate').split('/'),

        // Luego de que sepamos los valores de fecha mínimos y máximos,  
        // generamos dos variables del tipo Date, con los valores anteriores  
        xMinDate = new Date(minValue[2], minValue[1] - 1, minValue[0]),
        xMaxDate = new Date(maxValue[2], maxValue[1] - 1, maxValue[0]);


      // Inicializamos cada input del tipo date con datepicker.  
      // Es importante mencionar que aquí se definen los valores  
      // antes asignados, es decir, el valor mínimo y máximo.  
      $(this).datepicker({
        dateFormat: 'dd/mm/yy',
        minDate: xMinDate,
        maxDate: xMaxDate
      });
    });

    // A continuación volvemos a usars la función $.each para recorrer  
    // todos los inputs del tipo password. 
    $.each($('input[type="password"]'), function() {
      // Seleccionamos el input y luego obtenemos el valor que almacena  
      // en su atributo data-reference-confirm.
      var $this = $(this),
        $reference_confirm = $($this.attr('data-reference-confirm')) || '';

      // data-reference confirm nos sirve para apuntar mediante el ID  
      // a otro input que deba ser la confirmación de éste password.  
      // Previo a ello validamos que existe una confirmación, de lo  
      // contrario no haremos nada.
      if ($reference_confirm.length > 0) {        
        // Usamos equalTo de jQuery Validate para hacer confirmaciones.
        $reference_confirm.rules("add", {
          equalTo: '#' + $(this).attr('id')
        });
      }
    });

    // Refresca la imagen del captcha al hacer click en el boton
    $('.ElementForm-captchaRefreshContent').on('click', refreshCaptcha);

    // Se define el evento "change" para todos los elementos "select"
    setTimeout(function() {
      $('select').on('change', changeValSelect);
    }, 500);


    // A todos los input que contengan el atributo number, le asignamos  
    // numeric para validar de que sean sólo números.  
    $('input[number]').numeric();

    // A todos los input que contengan el atributo date, le asignamos  
    // numeric para validar de que sean sólo números, pero le permitimos  
    // que se ingrese el caracter '/' (slash)
    $('input[date]').numeric({
      allow: '/'
    });

    // Cuando un select cambia de valor, se ejecuta la función  
    // changeValSelect
    $('select').on('change', changeValSelect);

    // A cada input del tipo checkbox se le personalizará con la función  
    // customCheckBox
    $('input[type="checkbox"]').each(function() {
      var $this = $(this);
      customCheckBox($this);
    });

    // Hacemos que luego de 500 milisegundos se dispare  
    // el evento change.
    setTimeout(function() {
      $('select').each(function() {
        var $this = $(this);
        $this.trigger('change');
      });
    }, 500);

    $form.each(function() {
      var $this = $(this),
        $submit_button = $this.find('button[type="submit"]');
      if(!$this.data('custom-form')) {
        if ($submit_button.length > 0) {
          $submit_button.on("click", {
              form: $this
            },
            onSubmitRegisterForm
          );
        }
      }
    });
  };

/**
* Valida los campos del formulario y submitea la data vía POST(soporta envío por Ajax)
*/
function onSubmitRegisterForm(e) {
  // Evitamos que se ejecute el evento por defecto con  
  // preventDefault();
  e.preventDefault();

  // Obtenemos algunos valores importantes:
  var $form = e.data.form,
    isAjax = $form.data('is-ajax') || false, // Definimos si nuestro formulario es Ajax o no

    // Definimos la categoría del tracking que se efectuará  
    // al submitear el formulario.  
    tracking_category = $form.data('tracking-category'),

    // Definimos el action del tracking que se efectuará  
    // al submitear el formulario.
    tracking_action = $form.data('tracking-action'),

    // Definimos el label del tracking que se efectuará  
    // al submitear el formulario.
    tracking_label = $form.data('tracking-label');

  if ($form.valid()) {
    // Si nuestro formulario ha cumplido con todas las
    // validaciones, entonces se ejecuta lo siguiente:

    // Si es ajax se cumple lo siguiente
    if (isAjax) {
      // Se efectúa el AJAX por método POST.  
      $.post(
        $form.attr('action'),
        $form.serialize()
      ).done(function(data) {
        // Si el response devuelve status_code diferente de 0  
        // entonces mostramos los errores con parseErros.  
        if (data.status_code != 0) {
          parseErrors(data);
        } else {
          // Si todo está bien, efectuamos el tracking.
          trackEventSubmitForm(tracking_category, tracking_action, tracking_label);

        }

      }).fail(function() {

      });

    } else {
      // Si no es Ajax, entonces solo ejecutamos el tracking  
      if (tracking_category) {
        trackEventSubmitForm(
          tracking_category,
          tracking_action,
          tracking_label
        );
      }
      $form.submit();
    }
  }
}

/**
* Trackea el submit exitoso de un formulario
* @param {String} category
* @param {String} action
* @param {String} label
*/
function trackEventSubmitForm(category, action, label) {
  ga('send', 'event', category, action, label);
};

/**
* Cambia el texto de la mascara del select personalizado 
* por la opción seleccionada
*/
function changeValSelect() {
  var _self = $(this);
  _self.parent().find('.ElementForm-selectText').html(_self.find('option:selected').html());
};

/**
* Vincula el evento click del label con el checkbox personalizado
* @param {Object} el - Elemento checkbox
*/  
function setupEventsToCheckbox(el) {
  // Selecciona el parent del elemento  
  var parent = el.parents('.ElementForm');
  // Una vez que tenemos el parent, buscamos dentro el checkbox y el label  
  // En caso se haga click en el checkbox, se efectuará la función changeStateCheckbox  
  parent.find('.ElementForm-contentCheckBox').on('click', changeStateCheckbox);
  // En caso se haga click en el label del checkbox, se efectuará la función changeStateCheckbox  
  parent.find('label').on('click', changeStateContentCheckbox);
}

/**
* Agrega clases de estado al contenedor del checkbox  
*/
function changeStateContentCheckbox() {
  var $this = $(this),
      content = $this.parents('.ElementForm'), // Seleccionamos el parent del input          
      input = content.find('input'), // Buscamos el input  
      subContent = content.find('.ElementForm-contentCheckBox');

  // Asignamos la clase is-checked si es que el input está marcado,  
  // de lo contrario la removemos.  
  if (content.hasClass('is-checked')) {
    content.removeClass('is-checked');
    subContent.removeClass('is-checked');
    input.removeAttr('checked');
  } else {
    content.addClass('is-checked');
    subContent.addClass('is-checked');
    input.attr('checked', true);
  }
  input.trigger('click');
}

/**
* Agrega clases de estado al checkbox
*/
function changeStateCheckbox(e) {
  var $this = $(this),
    content = $this.parents('.ElementForm'),
    input = $this.find('input');

  if ($this.hasClass('is-checked')) {
    content.find('.ElementForm-contentCheckBox').removeClass('is-checked');
    content.removeClass('is-checked');
    input.removeAttr('checked');
  } else {
    content.find('.ElementForm-contentCheckBox').addClass('is-checked');
    content.addClass('is-checked');
    input.attr('checked', true);
  }
}

Easy Modal

Este módulo nos permite crear lightbox con contenidos dinámicos o estaticos.

define([
  'datepicker',
  'validateExt'
], function () {
 var EasyModal,
      defaults;

  defaults = {
    'padding': 0,
    'width': 450,
    'height': 320,
    'isFixed': false,
    'content': "This is a content example",
    'onClose': null,
    'onAfterShow': null,
  };

  function EasyModal(options) {      
      this.options = $.extend(defaults,  options);      
      this.init();
  }

  EasyModal.prototype = {
    constructor : EasyModal,
    init: function() {
      $('body').prepend(
        $('<div class="Overlay"></div>'),
        $('<div class="Modal"></div>')
      );      
      this.$modal = $('.Modal');
      this.$overlay = $('.Overlay');
      this.setContent(this.options.content);
      this._setupEventCloseModal();
    },
    setContent: function (content) {     
      this.$modal.html(content);

    },
    getContent : function () {
      return this.$modal.html();
    },
    _setupEventCloseModal: function() {
      var $body = $('body');

      $body.on('click', this.$modal.find('.Modal-close').selector, { obj: this }, this.close);
      this.$overlay.on('click', { obj: this }, this.close);
      $(document).on('keydown', { obj: this }, function(e) {        
        if (e.keyCode == 27) {
          e.data.obj.close(e);
        }
      });
    },
    close: function(e) {
      var onClose,
          data,
          self;

      if (e) {
        data = e.data;
        self = data.obj;  
      } else {
        self = this;
      }

      onClose = self.options.onClose;
      self.$overlay.fadeOut(200);
      self.$modal.fadeOut(200);
      self.$modal.removeClass('is-show');
      if (onClose) {
        onClose();
      }

      if (self.options.isFixed) {
        $('body').removeClass('u-noScroll')
      }
    },
    show: function() {
      var $body,
          $calculatedPositionLeft,
          $calculatedPositionTop,
          $topScrollbar;

      this.$overlay.show();
      $body = $('body');
      calculatedPositionLeft = parseInt(($body.width() - this.options.width) / 2);
      calculatedPositionTop = parseInt(($body.height() - this.options.height) / 2);
      topScrollbar = $(document).scrollTop();

      this.$modal.removeClass('is-show');
      if (this.options.isFixed) {
        $body.addClass('u-noScroll');
        this.$modal.css({
          'top': calculatedPositionTop + 'px',
          "padding": this.options.padding + "px",
          "width": this.options.width + "px",
          "height": this.options.height + "px",
          "left": calculatedPositionLeft + 'px'
        });
      } else {
        this.$modal.css({
          'top': (topScrollbar + 150) + 'px',
          "padding": this.options.padding + "px",
          "width": this.options.width + "px",
          "height": this.options.height + "px",
          "left": calculatedPositionLeft + 'px'
        });
      }
      this.$modal.fadeIn(600);
      var onAfterShow = this.options.onAfterShow;

      if (onAfterShow) {

        onAfterShow();
      }

    }
  }
  return EasyModal;
});

Register Form

Éste módulo cuenta con pocas funciones, entre ellas loadProv y loadDist

// Al iniciar, se ejecuta la función setupRegisterForm,  
function setupRegisterForm() {
  var dpt = $('#cod_dpto'),
    prov = $('#cod_prov'),
    dist = $('#cod_dist');

  if (prov.length > 0) {
    // Si es que existe el input #cod_prov, al efectuar un cambio  
    // en Departamento o Provincia, se ejecutará la función loadProv  
    // o loadDist respectivamente.  
    dpt.on('change', loadProv);
    prov.on('change', loadDist);
  }   
  // Dispara el evento "change" del select "dept" para que quede seleccionado
  // el departamento por defecto.
  setTimeout(function() {
    dpt.trigger('change');
  }, 500); 
};

// La función loadProv nos sirve para cargar las provincias en base a  
// al departamento seleccionado.

function loadProv() {
  var $this = $(this),
    selectedVal = $this.val(),
    $el = $('#cod_prov'),
    $sub_el = $('#cod_dist'),
    html = '<option class="ElementForm-selectOption" value="">Selecciona</option>',
    item;

  if (selectedVal === '') {
    $el.html(html)
      .attr('disabled')
      .parent().addClass('is-disabled')
  } else {

    $el.html(html);
    $el.removeAttr('disabled');
    $el.parent().removeClass('is-disabled');
    $el.trigger('change');
    $sub_el.html(html).attr('disabled', 'disabled');
    $sub_el.parent().addClass('is-disabled');
    $sub_el.trigger('change');

    $.get($el.attr('data-source'), {
      'cod_dpto': selectedVal 
    }).done(function(data) {
      for (item in data) {
        html += '<option class="ElementForm-selectOption" value="' + data[item].code + '">' + data[item].name + '</option>';
      }
      $el.html(html);
      $el.trigger('change');
    });
  }
};

// La función loadDist nos sirve para cargar las provincias en base a  
// al departamento y provincia seleccionado.
function loadDist() {
  var $el = $('#cod_dist'),
    $dept = $('#cod_dpto'),
    $this = $(this),
    html = '<option class="ElementForm-selectOption" value="">Selecciona</option>',
    selectedVal = $this.val(),
    item;

  if (selectedVal === '') {
    $el.html(html);
    $el.attr('disabled', 'disabled');
    $el.parent().addClass('is-disabled');
    $el.trigger('change');
  } else {
    $el.removeAttr('disabled');
    $el.parent().removeClass('is-disabled');
    $el.trigger('change');
    $.get($el.attr('data-source'), {
      'cod_prov': $this.val(),
      'cod_dpto': $dept.val(),
    }).done(function(data) {
      for (item in data) {
        html += '<option class="ElementForm-selectOption" value="' + data[item].code + '">' + data[item].name + '</option>';
      }
      $el.html(html);
      $el.trigger('change');
    });
  }
};