I don’t want to be the equivalent of a cooking show, saying “And here’s one I prepared earlier!”. And, I think that more value is gained from seeing it done poorly, and improving on it from there.
Also, TDD techniques have you solve it quickly with bad code, giving you green tests and letting you then improve the code while maintaining things in the green.
As a result, it’s time to do things poorly, for now.
First of all, we need to hide the existing options.
Hide alignment options
I don’t think that this part will change throughout the improvements. What we need to do is to get the different options, and hide each of them.
function showAlignmentOptions(widthSelect, alignments) {
var options = alignments.querySelectorAll(".dd-option");
options.forEach(function (option) {
option.classList.add("hide");
});
}
We are now in a good place to show relevant options, poorly at first.
A poor way to show alignment options, but it works
An initial start is to get the text of the chosen width, and use that to decide which options to show.
var widthOption = widthSelect.options[widthSelect.selectedIndex];
var widthChoice = widthOption.text;
if (widthChoice === "100%") {
options[1].classList.remove("hide");
}
if (widthChoice === "50%") {
options[3].classList.remove("hide");
options[4].classList.remove("hide");
}
if (widthChoice === "33%") {
options[6].classList.remove("hide");
options[7].classList.remove("hide");
options[8].classList.remove("hide");
}
if (widthChoice === "25%") {
options[10].classList.remove("hide");
options[11].classList.remove("hide");
options[12].classList.remove("hide");
options[13].classList.remove("hide");
}
That works (and desperately need improving), but the currently selected option doesn’t update. We can use the ddSlick select method, to select an option.
I tried by having it select the first available option each time, but most of those are just Left and don’t provide much visual feedback.
Instead, I selected the option heading, which gives much better “50% Options” feedback each time.
Fixing remaining issues
A few other problems are noticed, such as that the second dropdown is fully populated before a selection is made. We need to hide those selections on page load, as well as when changes are made.
We should move that hiding code to a separate function, so that we can call it from different places.
It is important that we know that the hide function is only relevant to hiding ddslick options, so I’ve included that in the function name.
function hideDDSlickOptions(select) {
var options = alignments.querySelectorAll(".dd-option");
options.forEach(function (option) {
option.classList.add("hide");
});
}
function showAlignmentOptions(widthSelect, alignments) {
// var options = alignments.querySelectorAll(".dd-option");
// options.forEach(function (option) {
// option.classList.add("hide");
// });
hideDDSlickOptions(alignments);
var options = alignments.querySelectorAll(".dd-option");
...
}
...
var alignments = d.querySelector("#alignments");
hideDDSlickOptions(alignments);
That second call to hideDDSlickOptions ensures that they are hidden on page load too, which has revealed two new problems, one in the code and one on the page.
Having only one alignment assignment
The code problem is that alignments is being assigned twice, once on pageload and also in the event handler. That alignments variable should be moved up to the top of the code, so that it’s available to all of the code beneath. We should also do that with the width select one too.
(function(d) {
"use strict";
var widths = d.querySelector("#width");
var alignments = d.querySelector("#alignments");
...
function widthChangeHandler(evt) {
var widthChoice = evt.target;
// var alignments = d.querySelector("#alignments");
showAlignmentOptions(widthChoice, alignments);
}
// var orientation = d.querySelector("#width");
// orientation.addEventListener("change", widthChangeHandler);
widths.addEventListener("change", widthChangeHandler);
// var alignments = d.querySelector("#alignments");
hideDDSlickOptions(alignments);
Doing that lets us see that the assignment of widths and alignments are inconsistent, so I’ll make them singular instead.
<select id="width">
...
<select id="alignment">
// $('#alignments').ddslick({
$('#alignment').ddslick({
});
...
var widths = d.querySelector("#width");
var alignments = d.querySelector("#alignment");
Showing a suitable message on page load
The other problem that occurs on the page, is that on pageload the second select doesn’t have an appropriate message. It really should have a message that says: “Please select a Width”.
The ddSlick code does have a selectText message, but that only seems to work when you give it the options as a JSON data set.
So instead, we can do the usual trick of having the first option be the message.
<select id="alignment">
<option value="" disabled>Please select a Width</option>
And at the end of the JavaScript code where the options are hidden, have it select that first option to be shown.
hideDDSlickOptions(alignments);
$(alignments).ddslick('select', {index: 0});
}(document));
But, adding that option changes all of the option indexes, so we have to go back and update them all. I’ve also moved the option heading selection before showing the options, so that the numbered indexes remain in appropriate order.
if (widthChoice === "100%") {
$(alignments).ddslick('select', {index: 1});
options[2].classList.remove("hide");
}
if (widthChoice === "50%") {
$(alignments).ddslick('select', {index: 3});
options[4].classList.remove("hide");
options[5].classList.remove("hide");
}
if (widthChoice === "33%") {
$(alignments).ddslick('select', {index: 6});
options[7].classList.remove("hide");
options[8].classList.remove("hide");
options[9].classList.remove("hide");
}
if (widthChoice === "25%") {
$(alignments).ddslick('select', {index: 10});
options[11].classList.remove("hide");
options[12].classList.remove("hide");
options[13].classList.remove("hide");
options[14].classList.remove("hide");
}
This is just some of the pain that comes from doing things poorly. Despite that though it has allowed us to fix many other problems, and we now have useful information about what needs to be improved from here, which will occur in my next post.