Extending the Prototype
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeFrom now on, we'll pretty much be adding everything to the prototype
key. But, it does get a little bit annoying to always need to say Helper.prototype.something =
for every method:
// ... lines 1 - 2 | |
(function(window, $) { | |
// ... lines 4 - 65 | |
Helper.prototype.calculateTotalWeight = function() { | |
// ... lines 67 - 72 | |
}; | |
})(window, jQuery); |
No worries! We can shorten this with a shortcut that's similar to PHP's array_merge()
function. Use $.extend()
and pass it Helper.prototype
and then a second object containing all of the properties you want to merge into that object. In other words, move our calculateTotalWeight()
function into this and update it to be calculateTotalWeight: function
:
// ... lines 1 - 2 | |
(function(window, $) { | |
// ... lines 4 - 60 | |
$.extend(Helper.prototype, { | |
calculateTotalWeight: function() { | |
var totalWeight = 0; | |
this.$wrapper.find('tbody tr').each(function () { | |
totalWeight += $(this).data('weight'); | |
}); | |
return totalWeight; | |
} | |
}); | |
})(window, jQuery); |
At the bottom, we don't need the semicolon anymore. If we had more properties, we'd add them right below calculateTotalWeight
: no need to worry about writing prototype
every time.
There's nothing special about $.extend
, it's just a handy array_merge
-esque function that we happen to have handy. You may see other functions from other libraries that do the same thing.
Making RepLogApp an Instantiatable Object
With this trick, it's super easy to make RepLogApp
an instantiatable object. First, set RepLogApp
itself to the former initialize()
function. I'll un-indent everything and finish it with a semicolon:
// ... lines 1 - 2 | |
(function(window, $) { | |
window.RepLogApp = function ($wrapper) { | |
this.$wrapper = $wrapper; | |
this.helper = new Helper(this.$wrapper); | |
this.$wrapper.find('.js-delete-rep-log').on( | |
'click', | |
this.handleRepLogDelete.bind(this) | |
); | |
this.$wrapper.find('tbody tr').on( | |
'click', | |
this.handleRowClick.bind(this) | |
); | |
}; | |
// ... lines 17 - 72 | |
})(window, jQuery); |
Constructor done!
Next, add $.extend()
with window.RepLogApp.prototype
and {
. The existing keys fit right into this perfectly! Winning! At the end, add an extra )
:
// ... lines 1 - 2 | |
(function(window, $) { | |
// ... lines 4 - 17 | |
$.extend(window.RepLogApp.prototype, { | |
updateTotalWeightLifted: function () { | |
this.$wrapper.find('.js-total-weight').html( | |
this.helper.calculateTotalWeight() | |
); | |
}, | |
handleRepLogDelete: function (e) { | |
e.preventDefault(); | |
var $link = $(e.currentTarget); | |
$link.addClass('text-danger'); | |
$link.find('.fa') | |
.removeClass('fa-trash') | |
.addClass('fa-spinner') | |
.addClass('fa-spin'); | |
var deleteUrl = $link.data('url'); | |
var $row = $link.closest('tr'); | |
var self = this; | |
$.ajax({ | |
url: deleteUrl, | |
method: 'DELETE', | |
success: function () { | |
$row.fadeOut('normal', function () { | |
$(this).remove(); | |
self.updateTotalWeightLifted(); | |
}); | |
} | |
}); | |
}, | |
handleRowClick: function () { | |
console.log('row clicked!'); | |
} | |
}); | |
// ... lines 55 - 72 | |
})(window, jQuery); |
Yes! In our template, we won't use RepLogApp
like this anymore. Instead, say var repLogApp = new RepLogApp($table)
:
// ... lines 1 - 64 | |
{% block javascripts %} | |
// ... lines 66 - 69 | |
<script> | |
$(document).ready(function() { | |
var $table = $('.js-rep-log-table'); | |
var repLogApp = new RepLogApp($table); | |
}); | |
</script> | |
{% endblock %} |
We won't call any methods on that new repLogApp
variable, but we could if we wanted to. We could also create multiple RepLogApp
objects if we had multiple tables on the page, or if we loaded a table via AJAX. Our JavaScript is starting to be awesome!
As touched upon at the end of the video, if you want to instantiate RepLogApp for multiple tables, assuming they've got the same class, you can do so as follows: