UPDATE
Refactored code - see edit section below.
I am practicing using the Prototype pattern and to do so, I am building a simple CRUD app that allows me to view, add, and delete customers.
Here is a JsFiddle for you to see what I've got so far: http://jsfiddle.net/phillipkregg/cfafr/146/
I will post the code here as well, for quick review:
// Create customer 'class' and store state here
var Customer = function(el) {
this.el = document.getElementById(el);
this.first_name = $("#input_first_name").val();
this.last_name = $("#input_last_name").val();
this.name = ""
}
var customers = [];
// In the Customer prototype store methods
Customer.prototype = {
// utility to log customer array
logCustomers: function() {
console.log(customers);
},
fullName: function() {
this.name = this.first_name + " " + this.last_name;
return this.name;
},
addCustomer: function() {
// clear out the current html to make room for the append later
this.el.innerHTML = "";
// create new customer instance
var cust = new Customer();
// add customer to the array
customers.push(cust);
// iterate through the array and add each customer to a row in the table
$.each(customers, function() {
$("#el").append("<tr><td>" + this.fullName() + "</td><td><a id='btn_remove_cust' class='btn btn-mini btn-danger'>delete</a></td></tr>");
})
// Clear out the text boxes
$("#input_first_name").val("");
$("#input_last_name").val("");
},
// Remove customer from array and hide the row that contained them
removeCustomer: function(e) {
$(e.target).closest('tr').hide();
customers.splice(e.target, 1);
}
}
// Default customer object has to be created in order for unobtrusive calls to work
var cust = new Customer("el");
// unobtrusive jQuery event handling below
$("#btn_add_customer").click(function() {
cust.addCustomer();
});
$("#btn_remove_cust").live("click", cust.removeCustomer);
$("#btn_log_customers_array").click(cust.logCustomers)
There are a few things that I'm concerned about:
1) I'm using jQuery to handle events and I'm trying to make everything as unobtrusive as possible. In doing so, I wasn't exactly sure where I needed to place the event-handling code so I created a separate block below the prototype code to contain the button click events. I'm not sure if this is the best way to go.
2) The events are being passed a function from the prototype - so in order for anything to work I have to new-up an instance of the 'Customer' before the user actually creates a new customer. Seems like there might be a better way - but since I'm using a constructor function, I'm not sure if there is any other way around that. If I change the constructor to an object literal, than I've just got a singleton.
3) Am I handling the removal of 'customers' from the array properly? I created a simple utility function that is wired up to a button so that I could check and make sure that objects were being removed - as well as hidden in the DOM.
Advice is greatly appreciated!
EDIT
Ok, after playing with my app above, I realized that the delete functionality was totally jacked-up to say the least.
I refactored my code to make it so that each new 'Customer' instance would get a unique identifier (to simulate objects coming from a server).
I then took this unique identifier and hid it inside of a span tag and passed that id into the customers
array element to get the proper customer to destroy.
Here is the new fiddle: http://jsfiddle.net/phillipkregg/cfafr/217/
And the JavaScript code itself:
// Create customer 'class' and store state here
var Customer = function(el) {
// added the id field to simulate id from server
this.id = 0;
this.el = document.getElementById(el);
this.first_name = $("#input_first_name").val();
this.last_name = $("#input_last_name").val();
this.name = ""
}
var customers = [];
// In the Customer prototype store methods
Customer.prototype = {
// utility to log customer array
logCustomers: function() {
console.log(customers);
},
fullName: function() {
this.name = this.first_name + " " + this.last_name;
return this.name;
},
addCustomer: function() {
// clear out the current html to make room for the append later
this.el.innerHTML = "";
// create new customer instance
var cust = new Customer("el");
// increment and create unique id for customer
var cust_id = this.id++;
cust.id = cust_id;
// add customer to the array
customers.push(cust);
// iterate through the array and add each customer to a row in the table
//$.each(customers, function() {
for (var i = 0; i < customers.length; i++) {
$("#el").append('<tr><td>' + customers[i].fullName() + '</td><td><a id="btn_remove_cust" class="btn btn-mini btn-danger">delete</a><span class="hidden_id">' + customers[i].id + '</span></td></tr>');
}
//})
// Clear out the text boxes
$("#input_first_name").val("");
$("#input_last_name").val("");
},
// Remove customer from array and hide the row that contained them
removeCustomer: function(e) {
// hide the row
$(e.target).closest('tr').hide();
// get the value of the hidden span
var target_id = ($(e.target).next('span').text());
// remove the array element with the unique id
customers.splice(target_id, 1);
}
}
// Default customer object has to be created in order for unobtrusive calls to work
var cust = new Customer("el");
// unobtrusive jQuery event handling below
$("#btn_add_customer").click(function() {
cust.addCustomer();
});
$("#btn_remove_cust").live("click", cust.removeCustomer);
$("#btn_log_customers_array").click(cust.logCustomers);
$("#input_first_name").bind('keypress', function(e) {
var cust = new Customer("el");
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
cust.addCustomer();
}
});
Please let me know if I'm overcomplicating this - or if I've jacked up something else.
Thanks! :)