moonorongo
3/16/2015 - 1:35 PM

Pequeño ejemplo de modulo JS utilizando el patron Module y la libreria Backbone

Pequeño ejemplo de modulo JS utilizando el patron Module y la libreria Backbone

// inicializacion modulo.
MyModule = (function(){
	
    // private section
	// Se guardan las referencias a las instancias (generalmente Views) para poder destruirlas despues
    var _instances = {};
    
    // este nombre se utilizara en el Controller, con sufijo <_appName>Controller.java
    // idem para templates, con el sufijo <_appName>EditTemplate en edicion y <_appName>Template en la app 
    var _appName = "responsables";  
    
	var _appContainer = _appName + "Container";
	var _appTitle= "Responsables";
    
    // interno guarda el ultimo id seleccionado
	var _lastIdSelected = null;
    
	var _listaProcesos = null;
	
	
	// bind sidebar button ----------------------------------------------
    // cuando se inicializa la app agrega el comportamiento al boton del menu para que se cree el popup y 
    // se inicie... ver si corresponde asi... o que el menu se encargue de inicializa
    $('#'+ _appName +'Button').click(function(){
        // borra basura anterior
        $('#mainPopupContainer').html('');
        
        // pone menu seleccionado
        $(this).addClass('treeButtonSelected');
        $('#mainPopupContainer').dialog({
            height: 437,
            width: 712,
            title: _appTitle,
            resizable: false,
            modal: true
        });
    
        // agrega el container del modulo en el menu
        $('#mainPopupContainer').html('<div id="'+ _appContainer +'"></div>');
        
        // obtiene la lista que mostrara en el abm
        $.ajax({
            url : 'procesos?method=listHandler',
            success : function(response) {
                _listaProcesos = response;
            }
        });
        
        // inicializa el modulo
        _instances.app = new App();
    });

    
    // Vista modulo principal
    var App = Backbone.View.extend({
            
            initialize: function() {
                var _this = this;
                
                this.$el = $('#'+ _appContainer);
                this.el = this.$el[0];
                _lastIdSelected = null;
                this.render();
                this.initDatatable();
            },  
            
            events: {
                "click #modificar" : "modificar",
                "click #agregar" : "agregar",
                "click #eliminar" : "eliminar",
                "click #cancelar" : "cancelar"
            },
            
            
            agregar: function() {
            	var _this=this;
                _this.model = new Model();
                _this.modificarModel(true);
            },
            
            
            modificar: function() {
                var _this = this;
                this.model = new Model();
                this.model.id = parseInt(_lastIdSelected);
                this.model.fetch({
                    success: function(response){
                        _this.modificarModel(false);
                    }
                });
            },
            
            
            
            modificarModel: function(isNew) {
                var _this = this;
                
                $('#editPopup').dialog({
                    height: 157,
                    width: 450,
                    title: _appTitle,
                    resizable: false,
                    modal: true
                });         
                
                _instances.view = new View({
                    model : _this.model
                }); 
            },
            
            
    
            eliminar: function() {
                var _this = this; 
                jConfirm(mainApp.alertaBorrar, function(){
                    var m = new Model();
                    m.id = _lastIdSelected;
                    
                    m.destroy({
                       success: function(model, response) {
                       	    if(response.success) {
                                _this.oTable.fnStandingRedraw()
                                _lastIdSelected = null;
                                $('.enableDisable').prop({disabled: true});
                            } else {
                                jAlert(mainApp.alertaErrorBorrado, {width: 250, height: 130, title: 'Se encontraron errores'})
                            }
                       } // success
                    });
                }); // jConfirm
            },    
            
            
            
            cancelar: function(e) {
                
                if(!_.isUndefined(e)) e.preventDefault(); 
    
                this.undelegateEvents();
                $(this.el).removeData().unbind();
                this.unbind();
                delete _instances.app;
                
                $('.treeButton').removeClass('treeButtonSelected');
                $('#'+ _appContainer).empty();
                $('#mainPopupContainer').dialog("destroy");
                
                return false;                
            },
            
            
    
            updateDT : function() {
                this.oTable.fnPageChange(0);
            },
            
            
            // inicializa DT 
            initDatatable : function() {
            	
            	var cantidadLineas = 12; //Math.floor(($('#'+ _appContainer).height() - 50) / 22); 
            	
                var view = this;
                var DTConfig = clone(ventasDatatableDefaults);
                
                DTConfig.sAjaxSource = _appName +"?method=listPagedHandler";
                var id = "#datatableContainer";
    
                DTConfig.aoColumnDefs = [
                                { "sClass": "left", "aTargets": [ 0 ], "sWidth" : "100%" }
                            ];
                    
                DTConfig.fnPreDrawCallback = function(oSettings) {
                    _lastIdSelected = null;
                }
                
                
                DTConfig.fnDrawCallback = function(oSettings){
                    _lastIdSelected = null;

                    if(oSettings._iRecordsTotal != 0) {
                        $("tr", oSettings.nTable).click( function() {
                            if ( $(this).hasClass('rowSelected') ) {
                                $(this).removeClass('rowSelected');
                                _lastIdSelected = null;
                                $('.enableDisable').prop({disabled: true});
                            } else {
                                $('tr.rowSelected', view.$el).removeClass('rowSelected');
                                $(this).addClass('rowSelected');
                                _lastIdSelected = this.id;
                                $('.enableDisable').prop({disabled: false});
                            }
                        });
                    } // if
            
                    if(_.isNull(_lastIdSelected) || !_.isNumber(parseInt(_lastIdSelected))) {
                        $('.enableDisable').prop({disabled: true});
                    } else {
                        $('.enableDisable').prop({disabled: false});
                    }
                    
                } // end fnDrawCallback
                  
                
                DTConfig.fnRowCallback = function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
                    if(!_.isNull(_lastIdSelected)) {
                        if(aData.DT_RowId == _lastIdSelected) {
                            $(nRow).addClass('rowSelected');
                        } else {
                            $(nRow).removeClass('rowSelected');
                        }
                    }
                } // end fnRowCallback

                
                DTConfig.iDisplayLength = cantidadLineas;
                view.oTable = $(id,view.$el).dataTable(DTConfig).fnSetFilteringDelay();
                
            }, // initDatatable        
            
            
            
            
            render: function() {
            	var _this = this;
                var html = _.template($('#'+ _appName +'Template').html());
                this.$el.html(html);
                return this;        
            }
    });
    
    
    
    
    
    
    
    // ----------------------------------------------------------------------
    // modelo de datos
    var Model = Backbone.Model.extend({
        idAttribute : "CODIGO" ,
      
        defaults : {
            "NOMBRE" : ""
        },
        
        url : function() {
            var base = _appName +"?method=RESTHandler";
            if(!_.isUndefined(this.iSortCol_0)) base += '&iSortCol_0='+ this.iSortCol_0;
            if(!_.isUndefined(this.sSortDir_0)) base += '&sSortDir_0='+ this.sSortDir_0;
            if(!_.isUndefined(this.iDisplayLength)) base += '&iDisplayLength='+ this.iDisplayLength;
            
            if (this.isNew()) return base;
            return base + "&CODIGO=" + this.id;
        }
    });
    
    
    
    
    
    
    // ----------------------------------------------------------------------
    // vista de edicion de datos
    var View = Backbone.View.extend({
    
            initialize: function() {
                this.$el = $('#editContainer');
                this.el = this.$el[0];
                
                this.render();
                var _this = this;
                this.$('.focusThis').focus();
                
                // este bloque de codigo modifica el elemento que tiene la clase lastTabIndex para que, si detecta la pulsacion de tecla
                // TAB, mande al primer field del formulario
                $(this.$el).on('keydown', '.lastTabIndex', function(e) {
                    var keyCode = e.keyCode || e.which; 
                    if (keyCode == 9) {
                        e.preventDefault();
                        _this.$('.focusThis').focus();
                    }
                });                
            },
    
            
            events: {
                "click #cancelar" : "cancelar",
                "click #actualizar" : "actualizar"
            },
            
            
            cancelar: function(e) {
              
                if(!_.isUndefined(e)) e.preventDefault(); 
    
                this.undelegateEvents();
                $(this.el).removeData().unbind();
                this.unbind();
                delete _instances.view;
    
                $('#editContainer').empty();
                $('#editPopup').dialog("destroy");
                
                return false;           
            },
            
            
            actualizar: function(e) {
                
                e.preventDefault(); // corta la propagacion de eventos.
                var _this = this;
                var ok = true;
                
                // fn en global.js, checkea formulario en base a la informacion provista en el template
                // a cada field erroneo le agrega .errorField
                checkFields(); 
                
                var hasError = this.$('.errorField').size();
                if(hasError != 0) {
                    var erroresEncontrados = showErrors(); // en global.js: resalta los .errorField marcados por checkFields(), y devuelve un msg, detallando los errores
                    jAlert(erroresEncontrados, {width: 250, height: 130, title: 'Se encontraron errores'});
                } else {
                    _this.saveModel();
                }
            
                return false;
            },
            
            
            saveModel : function() {
                var _this = this;
                
                // seteo los fields a guardar
                var NOMBRE = this.$('#NOMBRE').val();
                var CODPROCESO = this.$('#CODPROCESO').val();
                
                this.model.set({"NOMBRE" : NOMBRE, "CODPROCESO" : CODPROCESO});

                // informacion para determinar tipo de ordenamiento, a fin de poder mostrar en que pagina cae el registro.
                _this.model.iSortCol_0 = _instances.app.oTable.fnSettings().aaSorting[0][0]; 
                _this.model.sSortDir_0 = _instances.app.oTable.fnSettings().aaSorting[0][1];
                _this.model.iDisplayLength = _instances.app.oTable.fnSettings()._iDisplayLength; 
    
                _this.model.save({}, {
                   success: function(response) {
                        if(response.get("success")) {
                            _lastIdSelected = null;
                            _instances.app.oTable.fnPageChange(response.get("iPageNumber"));
                            _this.cancelar();
                        } else {
                        	var sErrorMsg = '';
                        	if(response.get("nombreEnUso")) sErrorMsg += 'El Nombre <strong>&quot;'+ NOMBRE +'&quot;</strong> est&aacute; repetido';
                            jAlert(sErrorMsg, {width: 250, height: 130, title: 'Se encontraron errores'});                       
                        } // if response.success
                   } // success
                });
                
                
                
            },
            
            
            render: function() {
            	var _this = this;
                var html = _.template($('#'+ _appName +'EditTemplate').html(), this.model.toJSON());
                this.$el.html(html);
                
                var selected = "";
                _.each(_listaProcesos, function(p){
                    selected = (p.CODIGO == _this.model.get("CODPROCESO"))? " selected " : "";
                    _this.$('#CODPROCESO').append('<option value="'+ p.CODIGO +'" '+ selected +'>'+ p.NOMBRE +'</option>');
                });
                
                return this;    
            }
    });


    

    
    
    
    
    // public section
    // aqui quiza deberia estar algo para inicializar el modulo, otro para destruirlo... etc... ver
    return {
        instances : _instances 
    }
    
    
})(); // end Modulo