I’m a few years late to the party but I really liked this book and found this challenge really nice for consolidating the stuff taught in the chapter. Here is my solution:
I decided I’d stick with the book’s ways of modularizing code (as opposed to newer import/export). Mainly to learn how and when to use this
(which I was struggling with)
First a new module, achievementhandler.js
(function(window) {
'use strict';
const App = window.App || {};
const $ = window.jQuery;
function AchievementHandler() {
console.log('Initializing AchievementHandler');
this._arrayOfAchievers = [];
this._pendingAchiever = undefined;
this.$noButton = $('#modalNo');
this.$yesButton = $('#modalYes');
this.$emailInput = $('#emailInput');
this.$achieverOptions = $('#achieverOptions');
this.$resetAndSubmitButtons = $('[type="reset"], [type="submit"]');
}
AchievementHandler.prototype.addAchiever = function(email) {
console.log('Adding superuser - invoking addAchiever');
this._arrayOfAchievers.push(email);
console.log('Updated list of superusers:');
console.log(this._arrayOfAchievers);
};
AchievementHandler.prototype.getAchievers = function() {
return this._arrayOfAchievers;
};
AchievementHandler.prototype.handleModal = function(email) {
this._pendingAchiever = email;
const isAlreadyAchiever = this._arrayOfAchievers.some(function(el) {
return el === this._pendingAchiever;
}.bind(this));
if (!isAlreadyAchiever) {
$('#achievementModal').modal('show');
}
};
AchievementHandler.prototype.addModalButtonHandler = function() {
console.log('Initializing modal button handler');
this.$yesButton.on('click', function(event) {
event.preventDefault();
console.log('yes clicked - pending superuser added to array');
this._arrayOfAchievers.push(this._pendingAchiever);
this._pendingAchiever = undefined;
console.log('Updated list of superusers: ');
console.log(this._arrayOfAchievers);
$('#achievementModal').modal('hide');
}.bind(this));
this.$noButton.on('click', function(event) {
event.preventDefault();
console.log('no clicked - purging pendning superuser');
this._pendingAchiever = undefined;
$('#achievementModal').modal('hide');
}.bind(this));
this.$resetAndSubmitButtons.on('click', function() {
$(this.$achieverOptions).css("display", "none");
}.bind(this));
};
AchievementHandler.prototype.addEmailInputHandler = function() {
this.$emailInput.on('input', function(event) {
console.log($(this.$emailInput).val());
this._arrayOfAchievers.forEach(function(email) {
if ($(this.$emailInput).val() === email) {
console.log('Achiever Detected!');
$(this.$achieverOptions).css("display", "block");
}
}.bind(this))
}.bind(this));
};
App.AchievementHandler = AchievementHandler;
window.App = App;
})(window);
And these lines added to main.js:
const AchievementHandler = App.AchievementHandler;
const achievementHandler = new AchievementHandler();
achievementHandler.addModalButtonHandler();
achievementHandler.addEmailInputHandler();
/* update the call to addSubmitHandler with a second callback function */
formHandler.addSubmitHandler(truckOne.createOrder.bind(truckOne), achievementHandler.handleModal.bind(achievementHandler));
Then inside index.html I added the following just before the buttons:
<fieldset id="achieverOptions" style="display: none;">
<legend class="col-form-label col-12 pt-0">Superuser options:</legend>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="methylphenidate" name="methylphenidate" value="yes">
<label class="form-check-label" for="methylphenidate">Methylphenidate</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="lsd" name="lsd" value="yes">
<label class="form-check-label" for="lsd">LSD</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="alcohol" name="alcohol" value="yes">
<label class="form-check-label" for="alcohol">Alcohol (20%)</label>
</fieldset>
and also in index.html a section with the code for the modal:
<section>
<div class="modal fade" id="achievementModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalCenterTitle">Achievement Unlocked!</h5>
</div>
<div class="modal-body">
<h6>Achievement: <strong>Sleep is overrated</strong></h6>
<p>Do you want to unlock this achievement and add your email to our list of superusers? This unlocks extra options for your next order.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" id="modalNo">No</button>
<button type="button" class="btn btn-primary" id="modalYes">Yes</button>
</div>
</div>
</div>
</div>
</section>
Also used script tags to import the new achievement handler.js and the bootstrap js file.
And lastly, in formhandler.js I updated addSubmitHandler (I had four sizes from the previous challenge)
FormHandler.prototype.addSubmitHandler = function(callback, passEmailToAchievementHandler) {
console.log('Initializing submit handler for form.');
this.$formElement.on('submit', function(event) {
event.preventDefault();
const data = {};
$(this).serializeArray().forEach(function(item) {
data[item.name] = item.value;
console.log(item.name + ' is: ' + item.value);
});
console.log(data);
if (data['size'] === 'extremo' && data['strength'] === '100') {
console.log('Superuser detected - email: ' + data['emailAddress']);
// Pass email to achievemnthandler
passEmailToAchievementHandler(data['emailAddress']);
}
callback(data);
this.reset();
this.elements[0].focus();
});
};