changing attribute of element - why is onchange event not fireing? - javascript

For demonstration of the problem described below see JSFiddle
HTML:
<input type="range" id="slider_length" min="10" max="200" value="0" step="10" onchange="changeValue1();" />
<span id="slider_length_span">10 mm</span>
</br>
<input type="range" id="slider_length2" min="5" max="15" value="0" step="10" onchange="changeValue2();" />
<span id="slider_length2_span">5 mm</span>
JS:
window.changeValue1 = function()
{
var slider = document.getElementById("slider_length");
var span = document.getElementById("slider_length_span");
span.innerHTML = slider.value + " mm";
var slider2 = document.getElementById("slider_length2");
slider2.setAttribute("max", slider.value - 5);
}
window.changeValue2 = function()
{
var slider = document.getElementById("slider_length2");
var span = document.getElementById("slider_length2_span");
span.innerHTML = slider.value + " mm";
}
I have one range element where the user can select a value between 10 and 200 with steps of 10.
There is a second range element with values between 5 and 15 with steps of 10.
If the user changes the first range element, the onchange event gets fired (successfully), in which the "max" attribute of the second range element gets changed (by value of first element -5). So far this works fine.
Steps to reproduce the problem:
select any number on first range element (e.g. 150)
select highest possible number on second range element (e.g. 145)
reduce selected number on first range element (e.g. 150 -> 110)
Expected behaviour:
When the onchange Event of the first range element gets fired the "max" attribute of the second range element changes to 105. The value of the second range element still is at 145 and should go to 105 (highest possible value). Because the second range element changes, the onchange event gets fired, updating a span element which shows its value.
Actual behaviour:
When the "max" Attribute of the second range element gets changed the onchange event doesn't seem to fire.
Question: Why is the onchange event not fireing? If onchange event is not the correct event to use in this case, which event am I supposed to use?

I have made a trick on your function like;
window.changeValue1 = function()
{
var slider = document.getElementById("slider_length");
var span = document.getElementById("slider_length_span");
span.innerHTML = slider.value + " mm";
var slider2 = document.getElementById("slider_length2");
if ((slider.value - 5) < slider2.value) {
slider2.value = 0;
slider2.setAttribute("max", slider.value - 5);
slider2.value = slider.value - 5;
var span = document.getElementById("slider_length2_span");
span.innerHTML = slider2.value + " mm";
} else {
slider2.setAttribute("max", slider.value - 5);
}
}
In order to set max value of second range in your case, I have set second range to zero, set max range of slide2 and set slide2 value to possible max value. You can see working example here: http://jsfiddle.net/wtq6H/7/

Onchange only checks if the value of an input changes not if any of it's other attributes change. In addition only after specific user actions like a textfield loosing focus will the browser check if a change has happend to begin with.
Why do you want to use the second event anyway? It seems like you should be able to do everything you want to do in the second event from within the first.

Related

How to create a minus and plus button to update a field?

I am trying to create a products page with a forum that shows the price of the item, the name of the item and also the quantity with buttons to add or subtract from the quantity field.
I have no idea where to begin, I thought I'd do some looking into different types of buttons and form input types but none of them seem to have what I need.
I was wondering if anyone can point me to the right direction so I can figure out how these buttons are changing the quantity field and how I can make a plus and minus button which appears next to the quantity.
Here is a picture of what I mean:
Use JavaScript to increase and decrease the input value:
const minusButton = document.getElementById('minus');
const plusButton = document.getElementById('plus');
const inputField = document.getElementById('input');
minusButton.addEventListener('click', event => {
event.preventDefault();
const currentValue = Number(inputField.value) || 0;
inputField.value = currentValue - 1;
});
plusButton.addEventListener('click', event => {
event.preventDefault();
const currentValue = Number(inputField.value) || 0;
inputField.value = currentValue + 1;
});
<button id="minus">−</button>
<input type="number" value="0" id="input"/>
<button id="plus">+</button>
Here what happens in the JS code. First it gets references to the HTML elements using the id HTML attribute and the document.getElementById JS function. Then it adds functions which are executed when one of the buttons is clicked. Inside the functions, the default button browser action (submitting the form) is cancelled, the input value is read, increased/decreased and put back to the input.

How to show end of the text in input after programmatically adding text?

I want to programmatically add words in input and always see the end of the text. But the problem is that when I'm adding word (like input.value += 'word') when length of text is almost the same as length of input, text inside input doesn't move, so I can see only begining of the text and ending is become hidden.
I think if I could put cursor to the end of input it will help, but none of tricks with cursor not working in Chrome, such as
input.value = input.value
or
input.setSelectionRange(input.value.length, input.value.length);
Seems to work well enough:
let input = document.getElementById('auto');
let sentence = 'Courage is the magic that turns dreams into reality.';
let index = 0;
setTimeout(function typing() {
let letter = sentence.charAt(index++);
input.blur();
input.value += letter;
input.focus();
input.setSelectionRange(index, index);
if (index < sentence.length) {
let ms = Math.floor(75 + Math.random() * 150);
setTimeout(typing, ms);
}
}, 1000);
<input id="auto" type="text">
If the input does not have focus, then Chrome will show it "scrolled" all the way to the left, showing the beginning of your input value.
If the element has focus, then you can set the selection range to move the cursor:
window.onload = function(){
var input = document.getElementById('foobar');
input.value += ' bazbat';
input.focus();
input.setSelectionRange( input.value.length - 1 );
}
<input id="foobar" value="foobar" size="6">
But it would be a very confusing and frustrating UX if the cursor is moving around while the user is attempting to type a value.
Other options to consider:
Change the width of your input to match the value. make html text input field grow as I type?
Toggle between an input and a span (edit mode vs read mode). With a span, you'd have a lot more control over how text is displayed. Jquery: Toggle between input and text on click
Use an indicator of some sort to alert the user that one of their input values was modified. This would be useful even if they can see the entire value, as they might not notice that the value was updated.

jQuery: changed input value is not used for new addition

I have a hidden input field, wich has the value 0:
<input type="hidden" class="test" value="0" />
Now I added a button with some JS to add 0.5 to the value each time the button is clicked:
<a class="addition-input">Click me</a>
Here is the JS part:
$('a.addition-input').click(function(event) {
event.preventDefault();
var currentValue = parseInt($('input.test').val());
var step = 0.5;
var newValue = currentValue + step;
$('input.test').val(newValue);
});
So, the first time i click the link/button, the value gets from "0" to "0.5".
But then, when I click the link/button the second time, it won't change, it just stays "0.5".
I think that jQuery doesn't get the new input value by the second time click, it probably thinks the value is "0".
How can I fix that?
Update:
Here's the fiddle: https://jsfiddle.net/m7pvjrve/1/
Use
var currentValue = parseFloat($('input.test').val());
instead of
var currentValue = parseInt($('input.test').val());
parseInt() converts 0.5 to 0 everytime and the value you get is 0.5 which is actually the step value
Demo: http://jsfiddle.net/GCu2D/657/

Is there a way to assign unique IDs to createElement objects?

I have a button when pressed creates new input bars and I would like those input bars to have unique ids, for example - textBar1, textBar2, textBar3 and so on.
I tried creating a variable outside of the function that has the value 0 and then inside the function add the value with +1 for each time the function runs but that doesn't work but instead it assigns the id textBar0 to every element that is created.
Does anyone have any suggestions on how to solve this?
Thanks in advance!
HTML
<label for='ingredient'></label>
<input id="textBar" class="textBar" type="name" name="ingredient">
<div id="textBarPosition"></div>
<div id="addRemoveContainer">
<input id="addBar" type="button" value="Add Ingredient">
JavaScript/jQuery
var counter = 0;
function createSector() {
var input = document.createElement('input');
input.setAttribute("id", 'textBar' + counter +1);
input.type = 'text';
input.name = 'name[]';
return input;
counter = 1;
}
var form = document.getElementById('textBarPosition');
document.getElementById('addBar').addEventListener('click', function(e) {
// step 1: create element and set opacity to 0.
var selector = $(createSector());
selector.fadeIn();
// step 2: append it to its parent.
$(form).append(selector);
$('#removeBar').click(function(){
$("input:last-child").remove(".textBar");
});
});
That is becaus you're not reassinging the changed value to counter.
Use counter+=1 instead or just counter++
input.setAttribute("id", 'textBar' + counter++); // now it should work
What you were doing before was always add 1 to 0
Best way is to use _.uniqueId.
Generate a globally-unique id for client-side models or DOM elements that need one. If prefix is passed, the id will be appended to it.
_.uniqueId('contact_');
=> 'contact_104'
You can use Math.random like this:
input.setAttribute("id", 'textBar_' + Math.random().toString(36));
It is my understanding that when you first call Math.random it generates a sequence of unique random numbers between 0 and 1 using the current time in milliseconds as a seed then returns the first one. Subsequent calls will move through the generated sequence of numbers, returning them one at a time, giving you the ability to generate random unique strings for element IDs.
jQuery Code -
var counter = 0;
function createSector() {
var input = document.createElement('input');
input.setAttribute("id", 'textBar' + counter);
input.type = 'text';
input.name = 'name[]';
return input;
}
var form = document.getElementById('textBarPosition');
document.getElementById('addBar').addEventListener('click', function(e) {
// step 1: create element and set opacity to 0.
var selector = $(createSector());
counter++;
selector.fadeIn();
// step 2: append it to its parent.
$(form).append(selector);
$('#removeBar').click(function(){
$("input:last-child").remove(".textBar");
});
});
Working JSFiddle - http://jsfiddle.net/Ashish_developer/mtafre04/

How can I undo input value by rolling back the previous valid value in Kendo UI

I have an input component as the following:
<input type="number" value="0" name="weight" format="0" min="50" max="100">
What I expect:
input a number between 50 and 100, for example 70;
focus other component then focus back on this input;
input a number which is lower than 50 or greater than 100, for example 20;
focus other component
I expect the box rolling back to 70 instead of populating 50, the min attribute.
Thank you for your help
You can do something like:
var ntb = $("#num").kendoNumericTextBox({
min : 50,
max : 100
}).data("kendoNumericTextBox");
var oldvalue = undefined;
$("#num").on("focusin", function(e) {
oldvalue = $("#num").val();
});
$("#num").on("focusout", function(e) {
var value = $("#num").val();
if (value < ntb.options.min || value > ntb.options.max) {
$("#num").val(oldvalue);
}
});
Basically you intercept the focusin event and save previous value and in focusout you check that are inside the limits, if not, you restore the old saved value.
EDIT If you need to do the same for many input fields in the page, what you can do is:
// Save old value in the numeric text box by adding an oldvalue property to it
$("[data-role='numerictextbox']").on("focusin", function(e) {
var me = $(this).data("kendoNumericTextBox");
me.oldvalue = $(this).val();
});
// Restore saved old value if value is not in range
$("[data-role='numerictextbox']").on("focusout", function(e) {
var value = $(this).val();
var me = $(this).data("kendoNumericTextBox");
if (value < me.options.min || value > me.options.max) {
$(this).val(me.oldvalue);
}
});
See it running here : http://jsfiddle.net/OnaBai/yYX7m
There is a field named "_old" in the KendoNumericTextBox object; this is useful for this purpose, at least when handling a NumericTextBoxSpinEvent, viz.:
function spinEventHandler(e) {
alert("delta from spin is: " + (+e.sender._value - e.sender._old));
}

Categories

Resources