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>"'+ NOMBRE +'"</strong> está 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