I’m wondering if I am going in the right direction for this challenge. Below is what I have so far. When I move the slider on the form I can get the value to log to console but I’m not sure where to go from here or if this is even the right approach?? Any help would be appreciated! Thank you!
Created the rangehandler.js file in the scripts directory. The rangehandler.js file is below
(function (window){
‘use strict’;
var App = window.App || {};
var $ = window.jQuery;
function RnageHandler(selector){
if(!selector){
throw new Error('No selector provided');
}
this.$formElement = $(selector);
if(this.$formElement.length === 0){
throw new Error('Could not find element with selector: ' + selector);
}
}
RangeHandler.prototype.addRangeHandler = function(){
//console.log('Setting slider handler for form');
this.$formElement.on('change', function(event){
event.preventDefault();
**console.log(this.value);**
var data = this.value;
//console.log(data);
});
};
(function(windows){
‘use strict’;
var FORM_SELECTOR = ‘[data-coffee-order=“form”]’;
var RANGE_SELECTOR = ‘[data-coffee-order=“strenghtRange”]’;
var App = window.App;
var Truck = App.Truck;
var DataStore = App.DataStore;
var FormHandler = App.FormHandler;
var RangeHandler = App.RangeHandler;
var myTruck = new Truck('ncc-1701', new DataStore());
window.myTruck = myTruck;
var formHandler = new FormHandler(FORM_SELECTOR);
var rangeHandler = new RangeHandler(RANGE_SELECTOR);
UPDATE: I got it working but still not sure if this is what the question was asking.
in the main.js I changed
(function(windows){
‘use strict’;
var FORM_SELECTOR = ‘[data-coffee-order=“form”]’;
var RANGE_SELECTOR = ‘[data-coffee-order=“strenghtRange”]’; var RANGE_VALUE = ‘[data-coffee-order=“strengthValue”]’;
var App = window.App;
var Truck = App.Truck;
var DataStore = App.DataStore;
var FormHandler = App.FormHandler;
var RangeHandler = App.RangeHandler;
var myTruck = new Truck(‘ncc-1701’, new DataStore());
window.myTruck = myTruck;
var formHandler = new FormHandler(FORM_SELECTOR);
var rangeHandler = new RangeHandler(RANGE_SELECTOR);
You need to add a min and max and below you add a span element where the value will display. As you see, I have it at 50.
Now in main.js outside you IIFE you create a function and work with jQuery to manipulate the html elements you’re going to work with:
var rangeSlider = function() {
var slider = $('.range-slider');
var range = $('.range-slider__range');
var value = $('.range-slider__value');
slider.each(function() {
value.each(function() {
var value = $(this).prev().attr('value');
$(this).html(value);
});
range.on('input', function() {
$(this).next(value).html(this.value);
});
});
};
rangeSlider();
This should show the numbers. I’m still trying to figure out a way of changing the colours. I thought about giving it a nice gradient effect to the bar and a background to the element but I will do that later on when I finish the entire project. Hope this works for you!Preformatted text
I got a gradient background for the bar instead of the numbers as the book suggests and it looks awful but it will look better later on (i hope). Here’s what I did:
In you css file:
and then at the end of the FormHandler(selector) function:
// update strengthOutput when slider changes and add color
var slider = document.getElementById("strengthLevel");
var sliderOutput = document.getElementById("strengthOutput");
var sliderLabel = document.getElementById('strengthLabel');
// set initial color
sliderOutput.style.color = "green";
sliderLabel.style.color = "green";
slider.addEventListener("input", function() { // using change only shows
// number after letting go of slider
// both value and textContent seem to work
// can't find any discussion online about which to use
// sliderOutput.textContent = slider.value;
sliderOutput.value = slider.value
// change the color of the label and number based on intensity
var intensityColor;
if (slider.value < 34) {
intensityColor = "green";
}
else if (slider.value < 68) {
intensityColor = "#aaaa00";
}
else {
intensityColor = "red";
}
sliderOutput.style.color = intensityColor;
sliderLabel.style.color = intensityColor;
});
As pointed out in the comments, I am not sure which is more appropriate to use between value and textContent (or even something else). I am also using getElementById and ids as oppose to data- attributes and querySelector. One of the hardest part about javascript so far is understanding which method to use when several options seem to get the job done. I do find some good help from discussions online, but not always.
Does resetting the form work properly for you? In my case only the slider itself is reset, but the color and value of the span remain untouched until you start moving the slider again.
Hi @ballgeier, MDN uses .value so I’d go with that since you’re using the new <output> tag.
Your approach works great! Here are some things you could do to improve it a bit: first, instead of updating the look with inline styles (sliderOutput.style.color), use the .classList API to update a class, then add some CSS to style the particular class. For example:
var intensity = slider.value;
var intensityClass;
if (intensity < 34) {
intensityClass = "low";
}
else if (intensity < 68) {
intensityClass = "medium";
}
else {
intensityClass = "high";
}
sliderOutput.classList.remove('low', 'medium', 'high');
sliderOutput.classList.add(intensityClass);
#strengthOutput.high {
color: red;
}
/* ... */
This will help separate your logic from the styling.
I added a span element and set an id attribute to it in this line <span id="strenghtLevelNumber">30</span>.
Then I added a handler to the slider in the formhandler.js file:
...
};
FormHandler.prototype.addSliderHandler = function () {
this.$formElement.on('input', function () {
var caffeineRate = $(this).val();
$(this).next().html(caffeineRate);
});
};
App.FormHandler = FormHandler;
...
What I did here was to add a listener to the input attribute and return the numerical value of the slider. I tested this on the console like this:
var fh = new App.FormHandler('[id="strengthLevel"]');
fh.addSliderHandler();
When I moved the slider the code works, but the problem that I have is that the $(this).next()method doesn’t seem quite well to make the code reusable. Plus, when I submit or reset the form, the value that was sent to the <span> element remains with the new value and won’t go back to 30. I solve it by adding a line to the addSubmitHandler function after submitting the form:
This solution also doesn’t seem to be reusable. It actually seems like a bad practice and the same problem is happening with the reset button (I haven’t solved that yet). What would be a better approach?
Hi @skrial, way to go taking the challenge for a spin! Here are some ideas to tidy up your solution:
First, instead of hardwiring the behavior for when the slider changes, your addSliderHandler function could take in a callback. e.g.
FormHandler.prototype.addSliderHandler = function (callback) {
this.$formElement.on('input', function () {
var caffeineRate = $(this).val();
callback(caffeineRate);
});
};
Then you could pass in that callback like this:
var fh = new App.FormHandler('[id="strengthLevel"]');
fh.addSliderHandler(function(caffeineRate) {
// do the caffeine dance
});
A couple more tips that may help: right now, the $(this).next().html(caffeineRate); line is a bit ill performant and has a security issue. First off, you could calculate $(this).next() once (outside the event handler) and put it in a local variable. Next, when you use the .html() helper, you are setting the innerHTML property of that node. So if the caffeineRate happened to be:
var caffeineRate = "<script>alert('muahaha')</script>"
…much chaos would ensue. So instead, use the .text() helper which will do what you want and not allow raw HTML to be injected