(function ($) {

$.fn.characterCounter = function(){
  return this.each(function(){
    var $input = $(this);
    var $counterElement = $input.parent().find('span[class="character-counter"]');

    // character counter has already been added appended to the parent container
    if ($counterElement.length) {
      return;
    }

    var itHasLengthAttribute = $input.attr('length') !== undefined;

    if(itHasLengthAttribute){
      $input.on('input', updateCounter);
      $input.on('focus', updateCounter);
      $input.on('blur', removeCounterElement);

      addCounterElement($input);
    }

  });
};

function updateCounter(){
  var maxLength     = +$(this).attr('length'),
  actualLength      = +$(this).val().length,
  isValidLength     = actualLength <= maxLength;

  $(this).parent().find('span[class="character-counter"]')
                  .html( actualLength + '/' + maxLength);

  addInputStyle(isValidLength, $(this));
}

function addCounterElement($input) {
  var $counterElement = $input.parent().find('span[class="character-counter"]');

  if ($counterElement.length) {
    return;
  }

  $counterElement = $('<span/>')
                      .addClass('character-counter')
                      .css('float','right')
                      .css('font-size','12px')
                      .css('height', 1);

  $input.parent().append($counterElement);
}

function removeCounterElement(){
  $(this).parent().find('span[class="character-counter"]').html('');
}

function addInputStyle(isValidLength, $input){
  var inputHasInvalidClass = $input.hasClass('invalid');
  if (isValidLength && inputHasInvalidClass) {
    $input.removeClass('invalid');
  }
  else if(!isValidLength && !inputHasInvalidClass){
    $input.removeClass('valid');
    $input.addClass('invalid');
  }
}

$(document).ready(function(){
  $('input, textarea').characterCounter();
});

}( jQuery ));