I have created a Backgrid table to manage users. One of the functions of that table is to allow paswords to be changed by an administrator. This is achieved by adding a button cell column to the backgrid table that launches a modal change password dialog. On entering the passwords and clicking change, the new password is passed back to the backgrid cell and inserted to the backbone model in the callback.
The problem is passing the callback, because the change password dialog is a compiled client side Jade template, so I can't pass a function in the options when the html is rendered, I can only pass a function name.
Here is what I have so far (showing only the Jade and the Backgrid PasswordCell definition).
The client side Jade template:
#user-passwd-dialog.modal
.modal-dialog
.modal-content
.modal-header.bg-warning
button.close(type="button" data-dismiss="modal" aria-label="Close")
span(aria-hidden="true") ×
h4.modal-title
span.glyphicon.glyphicon-log-in
span Set User Password
.modal-body
if message.length > 0
// show any messages that come back with authentication
.alert.alert-info #{message}
// LOGIN FORM
form
.form-group
label(for="user-password") Password
input.form-control#user-password(type="password" placeholder="New Password")
.form-group
label(for="user-confirm") Confirm Password
input.form-control#user-confirm(type="password" disabled="disabled" placeholder="Confirm Password")
.modal-footer
button.btn.btn-warning.btn-lg#user-change-password(type="button" disabled="disabled") Change Password
button.btn.btn-warning.btn-lg(type="button" data-dismiss='modal') Cancel
script(type="text/javascript").
function checkMatch() {
var password = $("#user-password").val();
var confirmPassword = $("#user-confirm").val();
if (password !== confirmPassword) {
$("#user-confirm").removeClass("alert alert-success").addClass("alert alert-danger");
$("#user-change-password").prop("disabled", true);
return false;
} else {
$("#user-confirm").removeClass("alert alert-danger").addClass("alert alert-success");
$("#user-change-password").prop("disabled", false);
return true;
}
}
$("#user-password").keyup(function() {
var password = $("#user-password").val();
if (password.length >= #{ minLen }) {
$("#user-confirm").prop("disabled", false);
checkMatch();
} else {
$("#user-confirm").prop("disabled", true);
}
});
$("#user-confirm").keyup(function() {
var password = $("#user-password").val();
if (password.length >= #{ minLen }) {
checkMatch();
}
});
$("#user-change-password").click(function() {
var password = $("#user-password").val();
#{result}(password);
$('#user-passwd-dialog').modal('hide');
});
The Backgrid cell is defined as (the compiled Jade template is Templates.set_password(opts)):
var PasswordCell = Backgrid.Cell.extend({
className: "button-cell",
template: function () {
return '<button class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-lock"></span></button>';
},
events: {
"click": "setPassword"
},
setPassword: function (e) {
e.preventDefault();
// XXX binding to global variable so modal can set password
// must be more elegant way to do this
mycallbackwiththelongname = (function(password) {
this.model.set({ password : password});
}).bind(this);
var opts = {
message:"The password must be at least 8 characters long",
minLen: 8,
result: "mycallbackwiththelongname"
};
$("#dialog-wrapper").html(Templates.set_password(opts));
$("#user-passwd-dialog").modal({ keyboard: true });
},
render: function () {
this.$el.html(this.template());
this.delegateEvents();
return this;
}
});
The question is in the code: Is there a more elegant way to pass the callback such that a global function is not needed. A local function would be preferable, but I am not sure how to specify the name.
I have a simplified jsfiddle working using the global function.
I figured out a way to use a function local to the PasswordCell 'click' handler by passing it using the jQuery data API. I attach the callback function to the parent element and then pass the name of the parent element to the function that renders the Jade template.
In the PasswordCell change setPasswd to:
setPassword: function (e) {
e.preventDefault();
var passwordResult = (function(password) {
this.model.set({ password : password});
}).bind(this);
var opts = {
name: "change-password-modal",
message:"The password must be at least 8 characters long",
minLen: 8,
parent: "dialog-wrapper"
};
$("#dialog-wrapper").html(Templates.set_password(opts));
$("#dialog-wrapper").data("onChange", passwordResult);
$("#user-passwd-dialog").modal({ keyboard: true });
},
In the Jade template change the button click event handler:
$("#user-change-password").click(function() {
var password = $("#user-password").val();
$("##{ parent }").data("onChange")(password);
$('#user-passwd-dialog').modal('hide');
});
The jsfiddle has been updated.