﻿/*
AJAX plugin for jQuery
Copyright (c) 2009 Rafael Assis (crystaldevelop.com)
Version: 1.1.1 (09/09/2009 10:50:00)
	
O único parâmetro obrigatório é a url
	
Como utilizar:
Método 1(sem retornar nada para a tela){
$().execAjaxPlugin({
url: 'ajax.ajax'
});
}
	
Método 2(escrevendo os dados retornados na página){
$('[selectors]').execAjaxPlugin({
url: 'ajax.ajax'
});
		
* O [selectors] é o selector do elemento que receberá o retorno
}
*/
(function($) {
   $.fn.execAjaxPlugin = function(options) {
      var defaults = {
         url: '',
         method: 'post',
         data: null,
         output: null,
         displayReturn: true,
         execOnComplete: null,
         execOnLoading: null,
         debug: false
      }
      var loadingMsgDefaults = {
         displayMessage: true,
         displayOnParent: false,
         displayOn: null,
         message: 'Carregando...',
         width: '100%'
      }
      var errorHandlerDefaults = {
         execOnError: null,
         onBadRequest_errorCode: 400,
         onBadRequest_displayMessage: true,
         onBadRequest_displayMessageType: 1, //0 - screen | 1 - alert
         onBadRequest_message: 'A requisição foi recusada devido a um problema de sintaxe.',
         onBadRequest_fn: null,

         onUnauthorized_errorCode: 401,
         onUnauthorized_displayMessage: true,
         onUnauthorized_displayMessageType: 1, //0 - screen | 1 - alert
         onUnauthorized_message: 'Você não permissão para acessar a página solicitada!',
         onUnauthorized_fn: null,

         onForbidden_errorCode: 403,
         onForbidden_displayMessage: true,
         onForbidden_displayMessageType: 1, //0 - screen | 1 - alert
         onForbidden_message: 'Você não permissão para acessar a página solicitada!',
         onForbidden_fn: null,

         onNotFound_errorCode: 404,
         onNotFound_displayMessage: true,
         onNotFound_displayMessageType: 1, //0 - screen | 1 - alert
         onNotFound_message: 'Página não encontrada!',
         onNotFound_fn: null,

         onRequestTimeout_errorCode: 408,
         onRequestTimeout_displayMessage: true,
         onRequestTimeout_displayMessageType: 1, //0 - screen | 1 - alert
         onRequestTimeout_message: 'A requisição atingiu o tempo limite.',
         onRequestTimeout_fn: null,

         onServerError_errorCode: 500,
         onServerError_displayMessage: true,
         onServerError_displayMessageType: 1, //0 - screen | 1 - alert
         onServerError_message: 'Ocorreu um erro inesperado no servidor, tente novamente mais tarde.',
         onServerError_fn: null,

         onServiceUnavailable_errorCode: 503,
         onServiceUnavailable_displayMessage: true,
         onServiceUnavailable_displayMessageType: 1, //0 - screen | 1 - alert
         onServiceUnavailable_message: 'O servidor está sobre carregado ou está em manutenção, tente novamente mais tarde.',
         onServiceUnavailable_fn: null,

         onGeneric_errorCode: 0,
         onGeneric_displayMessage: true,
         onGeneric_displayMessageType: 1, //0 - screen | 1 - alert
         onGeneric_message: 'Ocorreu um erro na sua requisição.',
         onGeneric_fn: null
      }

      var opts = $.extend(defaults, options);
      var error = $.extend(errorHandlerDefaults, opts.errorHandler);
      var loading = $.extend(loadingMsgDefaults, opts.loadingMsg);

      return this.each(function() {
         var obj = $(this);
         var hasObj = obj.attr('id') ? true : false;
         var objType = hasObj ? this.nodeName.toLowerCase() : '';
         var displayOnType = loading.displayOn != undefined ? (loading.displayOn != null ? $(loading.displayOn).get(0).nodeName.toLowerCase() : '') : '';

         if (opts.url == '' || opts.url == null) {
            alert('Defina uma url!!');
            return false;
         }
         if (opts.method == '' || opts.method == null) {
            alert('Defina um método!!');
            return false;
         }
         //Exibindo mensagem enquanto carrega o ajax
         if (opts.execOnLoading) execFunction(opts.execOnLoading);
         if (loading.displayMessage && hasObj) {
            if ((objType != 'input' && objType != 'textarea' && objType != 'select') || loading.displayOnParent ||
					(displayOnType != 'input' && displayOnType != 'textarea' && displayOnType != 'select' && displayOnType != '')) {
               loading.message = '<div class="ajaxLoading" style="width: ' + loading.width + '">' + loading.message + '</div>';
            } else if (objType == 'select') {
               loading.message = '<option value="">' + loading.message + '</option>';
            }
            if (loading.displayOn != undefined && loading.displayOn != null) {
               $(loading.displayOn).html(loading.message)
            } else if (loading.displayOnParent) {
               $(obj).parent().append(loading.message);
            } else {
               showMessage(this, objType, loading.message);
            }
         }
         //Executar procedimentos AJAX
         $.ajax({
            type: opts.method,
            url: opts.url,
            data: opts.data,
            success: function(html) {
               //Exibindo retorno do AJAX
               if (opts.displayReturn && hasObj) {
                  showMessage(obj, objType, html);
                  $('.ajaxLoading').remove();
               }
               if (opts.execOnComplete) execFunction(opts.execOnComplete);
               return;
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
               //alert(XMLHttpRequest.status+"|"+textStatus+"|"+errorThrown);
               ajaxErrorManager(XMLHttpRequest, textStatus, errorThrown, opts.debug);
            }
         });
         //Fim AJAX
      });

      function ajaxErrorManager(XMLHttpRequest, textStatus, errorThrown, debug) {
         switch (parseInt(XMLHttpRequest.status)) {
            case error.onBadRequest_errorCode:
               if (error.onBadRequest_displayMessage) {
                  error.onBadRequest_message = 'Erro ' + error.onBadRequest_errorCode + ': ' + error.onBadRequest_message
                  if (error.onBadRequest_displayMessageType == 0) {
                     showMessage(this, objType, error.onBadRequest_message);
                  } else {
                     if (debug) {
                        alert(opts.url + '\n' + XMLHttpRequest.responseText + '\n' + error.onBadRequest_message);
                     } else {
                        alert(error.onBadRequest_message);
                     }
                  }
               }
               execFunction(error.onBadRequest_fn);
               return;
            case error.onUnauthorized_errorCode:
               if (error.onUnauthorized_displayMessage) {
                  error.onUnauthorized_message = 'Erro ' + error.onUnauthorized_errorCode + ': ' + error.onUnauthorized_message
                  if (error.onUnauthorized_displayMessageType == 0) {
                     showMessage(this, objType, error.onUnauthorized_message);
                  } else {
                     if (debug) {
                        alert(opts.url + '\n' + XMLHttpRequest.responseText + '\n' + error.onUnauthorized_message);
                     } else {
                        alert(error.onUnauthorized_message);
                     }
                  }
               }
               execFunction(error.onUnauthorized_fn);
               return;
            case error.onForbidden_errorCode:
               if (error.onForbidden_displayMessage) {
                  error.onForbidden_message = 'Erro ' + error.onForbidden_errorCode + ': ' + error.onForbidden_message
                  if (error.onForbidden_displayMessageType == 0) {
                     showMessage(this, objType, error.onForbidden_message);
                  } else {
                     if (debug) {
                        alert(opts.url + '\n' + XMLHttpRequest.responseText + '\n' + error.onForbidden_message);
                     } else {
                        alert(error.onForbidden_message);
                     }
                  }
               }
               execFunction(error.onForbidden_fn);
               return;
            case error.onNotFound_errorCode:
               if (error.onNotFound_displayMessage) {
                  error.onNotFound_message = 'Erro ' + error.onNotFound_errorCode + ': ' + error.onNotFound_message
                  if (error.onNotFound_displayMessageType == 0) {
                     showMessage(this, objType, error.onNotFound_message);
                  } else {
                     if (debug) {
                        alert(opts.url + '\n' + XMLHttpRequest.responseText + '\n' + error.onNotFound_message);
                     } else {
                        alert(error.onNotFound_message);
                     }
                  }
               }
               execFunction(error.onNotFound_fn);
               return;
            case error.onRequestTimeout_errorCode:
               if (error.onRequestTimeout_displayMessage) {
                  error.onRequestTimeout_message = 'Erro ' + error.onRequestTimeout_errorCode + ': ' + error.onRequestTimeout_message
                  if (error.onBadRequest_displayMessageType == 0) {
                     showMessage(this, objType, error.onRequestTimeout_message);
                  } else {
                     if (debug) {
                        alert(opts.url + '\n' + XMLHttpRequest.responseText + '\n' + error.onRequestTimeout_message);
                     } else {
                        alert(error.onRequestTimeout_message);
                     }
                  }
               }
               execFunction(error.onNotFound_fn);
               return;
            case error.onServerError_errorCode:
               if (error.onServerError_displayMessage) {
                  error.onServerError_message = 'Erro ' + error.onServerError_errorCode + ': ' + error.onServerError_message
                  if (error.onServerError_displayMessageType == 0) {
                     showMessage(this, objType, error.onServerError_message);
                  } else {
                     if (debug) {
                        alert(opts.url + '\n' + XMLHttpRequest.responseText + '\n' + error.onServerError_message);
                     } else {
                        alert(error.onServerError_message);
                     }
                  }
               }
               execFunction(error.onServerError_fn);
               return;
            case error.onServiceUnavailable_errorCode:
               if (error.onServiceUnavailable_displayMessage) {
                  error.onServiceUnavailable_message = 'Erro ' + error.onServiceUnavailable_errorCode + ': ' + error.onServiceUnavailable_message
                  if (error.onServiceUnavailable_displayMessageType == 0) {
                     showMessage(this, objType, error.onServiceUnavailable_message);
                  } else {
                     if (debug) {
                        alert(opts.url + '\n' + XMLHttpRequest.responseText + '\n' + error.onServiceUnavailable_message);
                     } else {
                        alert(error.onServiceUnavailable_message);
                     }
                  }
               }
               execFunction(error.onServiceUnavailable_fn);
               return;
            default:
               if (error.onGeneric_displayMessage) {
                  error.onGeneric_message = 'Erro ' + error.onGeneric_errorCode + ': ' + error.onGeneric_message
                  if (error.onGeneric_displayMessageType == 0) {
                     showMessage(this, objType, error.onGeneric_message);
                  } else {
                     if (debug) {
                        alert(opts.url + '\n' + XMLHttpRequest.responseText + '\n' + error.onGeneric_message);
                     } else {
                        alert(error.onGeneric_message);
                     }
                  }
               }
               execFunction(error.onGeneric_fn);
               return;
         }
         if (error.execOnError) execFunction(error.execOnError);
      }

      function showMessage(obj, objType, message) {
         if (objType == 'input' || objType == 'textarea') {
            $(obj).val(message);
         } else {
            $(obj).html(message);
         }
      }

      function execFunction(f) {
         if (typeof (f) == 'string') {
            eval(f);
         } else if (typeof (f) == 'function') {
            f(opts.output);
         }
      }
   }
})(jQuery);