Can I attach any event handlers to HTML hidden input fields? Basically I want to run a function when a hidden input field value changes.
Events are only triggered when the user performs the event in the browser, so if it's <input type="hidden"> or an <input> hidden by CSS, the user won't be able to trigger events to your input.
The only way you would get onchange to work is if you manually trigger onchange in Javascript. A quick example of this:
<form name="f" onsubmit="document.f.h.value='1';
document.f.h.onchange();
return false;"
>
<input type="hidden" name="h" value="0" onchange="alert(document.f.h.value);" />
<input type="submit" />
</form>
Yes, certain browsers (such as Firefox) will fire an onclick or onfocus event on hidden elements when they're activated via an accesskey attribute (meant to provide a keyboard hotkey to jump to an input).
Open the below in firefox, focus the frame, then strike Alt+Shift+x (Windows and Linux) or Ctrl+Alt+x (Mac).
<input type="hidden" accesskey="x" onclick="alert('clicked!');" />
JavaScript has focus events for the elements. There are three focus events: focus, focusin, and focusout.
I discovered focusout will trigger when an element display state is change for both block and none, while focusin only triggered for display state of block.
document.getElementById('element_id').addEventListener('focusout',function(e){
if (this.style.display === "none") {
// perform operations when the element is hidden, like clear fields, etc.
} else {
// perform operations when the element is displayed, like populate fields
}
});
Facing the problem I needed to react on change of hidden inputs which were modified by code which was out of my control, I got inspired by JS onchange hack for input[type=hidden] and created following solution for my problem using MutationObserver
Request:
I want to have function FAM.processFields run whenever any of selected subset of form fields (expressionFields) changes its value.
Problem:
Some of the form fields are of type="hidden", so change event is never fired for them.
Solution:
var index, elementId, element;
var elementIdPrefix = g_form.getTableName() + ".";
var expressionFields = this.getExpressionFieldNames();
// As trigger either Event or MutationRecord is passed, depends on input type
var processFieldsCallback = (function(trigger) {
// Relies on instance of - FAM object - added in onLoad script
FAM.processFields();
});
var changeOfValueConfig = {attributeFilter: ["value"]};
var processFieldsObserver = new MutationObserver(processFieldsCallback);
if (this.debug) {
console.log("addChangeEventListeners to expressionFields");
console.log(expressionFields);
}
for (index = 0; index < expressionFields.length; index++) {
elementId = elementIdPrefix + expressionFields[index];
element = document.getElementById(elementId);
// In case of hidden input (e.g. glideList, fieldList, checkbox) we need to register an observer to it
if (element.getAttribute("type") && element.getAttribute("type").toLowerCase() == "hidden") {
processFieldsObserver.observe(element, changeOfValueConfig);
if (this.debug) {
console.log("register processFieldsObserver of changeOfValueConfig on elementId " + elementId);
console.log(element);
}
}
else {
element.addEventListener("change", processFields);
if (this.debug) {
console.log("addChangeEventListeners on elementId " + elementId);
console.log(element);
}
}
}
Facing the problem I needed to react on change of hidden inputs which were modified by code which was out of my control, I got inspired by JS onchange hack for input[type=hidden] and created following solution for my problem using MutationObserver
Request:
I want to have function FAM.processFields run whenever any of selected subset of form fields (expressionFields) changes its value.
Problem:
Some of the form fields are of type="hidden", so change event is never fired for them.
Solution:
var index, elementId, element;
var elementIdPrefix = g_form.getTableName() + ".";
var expressionFields = this.getExpressionFieldNames();
// As trigger either Event or MutationRecord is passed, depends on input type
var processFieldsCallback = (function(trigger) {
// Relies on instance of - FAM object - added in onLoad script
FAM.processFields();
});
var changeOfValueConfig = {attributeFilter: ["value"]};
var processFieldsObserver = new MutationObserver(processFieldsCallback);
if (this.debug) {
console.log("addChangeEventListeners to expressionFields");
console.log(expressionFields);
}
for (index = 0; index < expressionFields.length; index++) {
elementId = elementIdPrefix + expressionFields[index];
element = document.getElementById(elementId);
// In case of hidden input (e.g. glideList, fieldList, checkbox) we need to register an observer to it
if (element.getAttribute("type") && element.getAttribute("type").toLowerCase() == "hidden") {
processFieldsObserver.observe(element, changeOfValueConfig);
if (this.debug) {
console.log("register processFieldsObserver of changeOfValueConfig on elementId " + elementId);
console.log(element);
}
}
else {
element.addEventListener("change", processFields);
if (this.debug) {
console.log("addChangeEventListeners on elementId " + elementId);
console.log(element);
}
}
}
You can still trigger events on hidden input using labels
The accepted answer claims that: "The user won't be able to trigger events to your input.", but this is not true.
A label connected to an input element can also trigger an input, so even though the input element itself is hidden, if properly connected to a label the user can trigger the input by its label:
There are two ways to connect an input to a label,
Use the id of the input element in the for attribute:
<label for="checkbox">Label</label><input type="checkbox" id="checkbox"/>
Or simply wrap the input inside a label:
<label><input type="checkbox"/>Label</label>
See a working code example here in fiddle or below:
const onChange = (event) => {
console.log(event);
const checkbox = event.target;
alert("checkbox value is: " + checkbox.checked);
}
document.getElementById('checkbox').addEventListener('change', onChange);
input[type="checkbox"] {
visibility: hidden;
}
label {
font-weight: bold;
}
<label>
<input id="checkbox" type="checkbox"/>
label for hidden checkbox
</label>
Related
I'm trying to fire a function whenever the value of an input field changes. The input field is in a lightbox so I have to delegate the event:
var validateDonation = function(elem) {
var msg,
value = elem.value;
if (value == '') { msg = 'Please enter an amount'; }
else if(parseInt(value, 10) < 1) { msg = 'Please enter an amount greater than 1'; }
else if(parseInt(value, 10) > 100) { msg = 'Please enter an amount less than 100'; }
else { msg = ''; }
if(msg != '') {
console.log(msg);
}
}
and
$('body').delegate('#donation_amount', 'change', function(event) {
validateDonation(this);
});
If I use keyup instead of change the console log works just fine. But not on change. Why?
https://msdn.microsoft.com/en-us/library/ms536912(v=vs.85).aspx
onchange: This event is fired when the contents are committed and not while the value is changing. For example, on a text box, this event is not fired while the user is typing, but rather when the user commits the change by leaving the text box that has focus. In addition, this event is executed before the code specified by onblur when the control is also losing the focus.
If you want the change to be instantly updated then you would want to use the oninput event
oninput: The DOM input event is fired synchronously when the value of an <input> or <textarea> element is changed. Additionally, it fires on contenteditable editors when its contents are changed.
For IE less than IE9 i believe you need to use the onpropertychange event as well as oninput to accommodate modern browsers.
Here is a fiddle to show you the event fires immediately
http://jsfiddle.net/SeanWessell/9jfkcapp/
Try this...
$('body').delegate('#donation_amount', 'input propertychange', function (event) {
validateDonation(this);
});
I've created a function to focus the next input with the enter key and disabled the submit on the form. It works fine but when I add an input field with the appendTo function it will reactivate the submit function on my form. I want to focus the input fields with the enter key and not with tab key.
Here is my function:
$('input').keydown(function (e) {
if (e.which === 13) {
var index = $('input').index(this) + 1;
$('input').eq(index).focus().val("");
return false;
}
});
And my appendTo function
var inputs = $('<input type="text" name="inputBasic[]" value="" class="form-control" />');
inputs.appendTo($("#dc_step_inputs"));
How can I remove the submit function when I add dynamical input field?
Thanks you for an answer!
You are binding your keydown event handler to a static set of elements (which does not include any elements added dynamically after your event handler has been attached), use delegation to bind to any elements that show up under your form:
$('#parent-form-id').on('keydown', 'input', function(e){
if (e.which === 13) {
var index = $('input').index(this) + 1;
$('input').eq(index).focus().val("");
return false;
}
});
$('input') only affects the elements that exist at the time this function runs.
You need to run the same script on the inserted element(s) too:
var inputs = $('<input type="text" name="inputBasic[]" value="" class="form-control" />');
inputs.appendTo($("#dc_step_inputs"));
inputs.keydown(function (e) {
if (e.which === 13) {
var index = $('input').index(this) + 1;
$('input').eq(index).focus().val("");
return false;
}
});
you can name your key down function
$('input').keydown(keydown);
function keydown(){
if (e.which === 13) {
var index = $('input').index(this) + 1;
$('input').eq(index).focus().val("");
return false;
}
and when you create a new input, give it an id, like this:
var inputs = $('<input id="newInput" type="text" name="inputBasic[]" value="" class="form-control" />');
inputs.appendTo($("#dc_step_inputs"));
and then
$('#newInput').keyDown(keyDown);
As has already been mentioned, when you add an event listener to a DOM element in JavaScript, you set it again the element itself, rather than a selector, or a given collection of elements.
One way around this, is to add an event listener to a common parent of all the elements for which you wish your event to be triggered against. This process is called Event Delegation. Fortunately, in jQuery this is very simple, using the following syntax:
$(<parent_selector>).on(<event>, <child_selector>, <fn>);
From the example you provided this might look something like (presuming you only want to target inputs within #dc_step_inputs):
$("#dc_step_inputs").on("keydown", ":input", function(e) {
if (e.which === 13) {
var index = $('input').index(this) + 1;
$('input').eq(index).focus().val("");
e.preventDefault(); // Note, this is preferred to return False
}
});
I am handling the content inside a textarea using binding a function to the event "input propertychange"
Like this:
$('#textarea').bind('input propertychange', function () {
var textarea = document.getElementById('textarea');
window.lastLineWriting = textarea.value.substr(0, textarea.value.length).split("\n").length;
var writingOnLine = textarea.value.substr(0, textarea.selectionStart).split("\n").length;
if (writingOnLine < window.lastLineWriting) {
//dont write on textarea
}
});
I don't know how to prevent the char typed by the user's keyboard to appear on the textarea... Inside that if I want to prevent the text to be inserted on textarea..
How can I do this?
you could easily stop the user from typing with this code, using jQuery:
$('textarea').bind('keypress', function (e) {
e.preventDefault();
return false;
});
NOTE:
this code will prevent the user from typing in all the textareas, to bind it specifically to one or some selected elements, you must change the selector to the desired elements.
var editable = false // Your Condition
if(editable != "true"){
$("#textarea" ).attr("disabled",true);
}
How to add multiple event listeners in the same initialization?
For example:
<input type="text" id="text">
<button id="button_click">Search</button>
JavaScript:
var myElement = document.getElementById('button_click');
myElement.addEventListener('click', myFunc());
This is working correctly however I would like to have another event listener for this input filed in the same call if that is possible, so when user clicks enter or presses the button it triggers the same event listener.
Just one note. User needs to be focused on the input field to trigger an "enter" event.
Just bind your function to 2 listeners, each one of the wished element:
document.getElementById('button_click').addEventListener('click', myFunc);
document.getElementById('text').addEventListener('keyup', keyupFunc);
where the new function test if the user pressed enter and then execute the other function :
function keyupFunc(evt) {
if(evt.keyCode === 13) // keycode for return
myFunc();
}
Working jsFiddle : http://jsfiddle.net/cG7HW/
Try this:
function addMultipleEvents(elements, events){
var tokens = events.split(" ");
if(tokens.length == elements.length){
for(var i = 0; i< tokens.length; i++){
elements[i].addEventListener(tokens[i], (e.which == 13 || e.which == 48)?myFunc:); //not myFunc()
}
}
}
var textObj = document.getElementById("textId");
var btnObj = document.getElementById("btnId");
addMultipleEvents([textObj,btnObj], 'click keyup');
UPDATE:
function addMultipleEvents(elements, events) {
var tokens = events.split(" ");
if (tokens.length == elements.length) {
for (var i = 0; i < tokens.length; i++) {
elements[i].addEventListener(tokens[i], myFunc); //not myFunc()
}
}
}
var textObj = document.getElementById("textId");
var btnObj = document.getElementById("btnId");
addMultipleEvents([btnObj, textObj], 'click keyup');
function myFunc(e) {
if (e.which == 13 || e.which == 1) {
alert("hello");
}
}
Working Fiddle
I think the best way to do this is by using for loops.
const events = ["click", "mouseover"]
for (i in events) {
document.getElementById("button_click").addEventListener(events[i], () => myFunc())
}
The code above loops through every events inside an array and adds it to the button.
Yeah this is a good question and can apply to other scenarios. You have a form and a user will have input text field, a radio box, a select option. So now you want the submit button to go from disabled to enabled. You decide to add an event listener to check if fieldA and fieldB and fieldC is first to enable submit button.
If you use event listener on Keyup", and all your fields are valid, the submit button will become enabled only if the last field is a text field because the event will only be triggered when you let go the key. This means it will not trigger if the radio box or select option is selected with your mouse. We must not rely in the order the fields are filled for the logic to work. Again, If you use "click", it sucks, because user will have to click somewhere on page in order for the event listener to fire and run the logic. So i think we'll need an event lister on mouseup, keyup and change for this example below. I assume you made all your validations and variables for the form fields already. We need a function with parameters of multiple events names as a string, the element we want to target (document, or button or form), and a custom function that contains our logic.
// Create function that takes parameters of multiple event listeners, an element to target, and a function to execute logic
function enableTheSubmitButton(element, eventNamesString, customFunction) {
eventNamesString.split(' ').forEach(e => element.addEventListener(e, listener, false));
}
// Call the above function and loop through the three event names inside the string, then invoke each event name to your customFunction, you can add more events or change the event names maybe mousedown, keyup etc.
enableSubmitButton(document, 'keyup mouseup change', function(){
// The logic inside your customFunction
if (isNameValid && isLocationValid && isProjectValid){
publishButton.disabled = false;
} else {
publishButton.disabled = true;
// Do more stuff like: "Hey your fields are not valid."
}
});
// The isNameValid isLocationValid, isProjectValid are coming from your previous validation Javascript for perhaps a select field, radio buttons, and text fields. I am adding it as an example, they have to be equal to true.
// The publishButton is a variable to target the form submit button of which you want enabled or disabled based one weather the form fields are valid or not.
// For example: const publishButton = document.getElementById("publish");
Can I attach any event handlers to HTML hidden input fields? Basically I want to run a function when a hidden input field value changes.
Events are only triggered when the user performs the event in the browser, so if it's <input type="hidden"> or an <input> hidden by CSS, the user won't be able to trigger events to your input.
The only way you would get onchange to work is if you manually trigger onchange in Javascript. A quick example of this:
<form name="f" onsubmit="document.f.h.value='1';
document.f.h.onchange();
return false;"
>
<input type="hidden" name="h" value="0" onchange="alert(document.f.h.value);" />
<input type="submit" />
</form>
Yes, certain browsers (such as Firefox) will fire an onclick or onfocus event on hidden elements when they're activated via an accesskey attribute (meant to provide a keyboard hotkey to jump to an input).
Open the below in firefox, focus the frame, then strike Alt+Shift+x (Windows and Linux) or Ctrl+Alt+x (Mac).
<input type="hidden" accesskey="x" onclick="alert('clicked!');" />
JavaScript has focus events for the elements. There are three focus events: focus, focusin, and focusout.
I discovered focusout will trigger when an element display state is change for both block and none, while focusin only triggered for display state of block.
document.getElementById('element_id').addEventListener('focusout',function(e){
if (this.style.display === "none") {
// perform operations when the element is hidden, like clear fields, etc.
} else {
// perform operations when the element is displayed, like populate fields
}
});
Facing the problem I needed to react on change of hidden inputs which were modified by code which was out of my control, I got inspired by JS onchange hack for input[type=hidden] and created following solution for my problem using MutationObserver
Request:
I want to have function FAM.processFields run whenever any of selected subset of form fields (expressionFields) changes its value.
Problem:
Some of the form fields are of type="hidden", so change event is never fired for them.
Solution:
var index, elementId, element;
var elementIdPrefix = g_form.getTableName() + ".";
var expressionFields = this.getExpressionFieldNames();
// As trigger either Event or MutationRecord is passed, depends on input type
var processFieldsCallback = (function(trigger) {
// Relies on instance of - FAM object - added in onLoad script
FAM.processFields();
});
var changeOfValueConfig = {attributeFilter: ["value"]};
var processFieldsObserver = new MutationObserver(processFieldsCallback);
if (this.debug) {
console.log("addChangeEventListeners to expressionFields");
console.log(expressionFields);
}
for (index = 0; index < expressionFields.length; index++) {
elementId = elementIdPrefix + expressionFields[index];
element = document.getElementById(elementId);
// In case of hidden input (e.g. glideList, fieldList, checkbox) we need to register an observer to it
if (element.getAttribute("type") && element.getAttribute("type").toLowerCase() == "hidden") {
processFieldsObserver.observe(element, changeOfValueConfig);
if (this.debug) {
console.log("register processFieldsObserver of changeOfValueConfig on elementId " + elementId);
console.log(element);
}
}
else {
element.addEventListener("change", processFields);
if (this.debug) {
console.log("addChangeEventListeners on elementId " + elementId);
console.log(element);
}
}
}
Facing the problem I needed to react on change of hidden inputs which were modified by code which was out of my control, I got inspired by JS onchange hack for input[type=hidden] and created following solution for my problem using MutationObserver
Request:
I want to have function FAM.processFields run whenever any of selected subset of form fields (expressionFields) changes its value.
Problem:
Some of the form fields are of type="hidden", so change event is never fired for them.
Solution:
var index, elementId, element;
var elementIdPrefix = g_form.getTableName() + ".";
var expressionFields = this.getExpressionFieldNames();
// As trigger either Event or MutationRecord is passed, depends on input type
var processFieldsCallback = (function(trigger) {
// Relies on instance of - FAM object - added in onLoad script
FAM.processFields();
});
var changeOfValueConfig = {attributeFilter: ["value"]};
var processFieldsObserver = new MutationObserver(processFieldsCallback);
if (this.debug) {
console.log("addChangeEventListeners to expressionFields");
console.log(expressionFields);
}
for (index = 0; index < expressionFields.length; index++) {
elementId = elementIdPrefix + expressionFields[index];
element = document.getElementById(elementId);
// In case of hidden input (e.g. glideList, fieldList, checkbox) we need to register an observer to it
if (element.getAttribute("type") && element.getAttribute("type").toLowerCase() == "hidden") {
processFieldsObserver.observe(element, changeOfValueConfig);
if (this.debug) {
console.log("register processFieldsObserver of changeOfValueConfig on elementId " + elementId);
console.log(element);
}
}
else {
element.addEventListener("change", processFields);
if (this.debug) {
console.log("addChangeEventListeners on elementId " + elementId);
console.log(element);
}
}
}
You can still trigger events on hidden input using labels
The accepted answer claims that: "The user won't be able to trigger events to your input.", but this is not true.
A label connected to an input element can also trigger an input, so even though the input element itself is hidden, if properly connected to a label the user can trigger the input by its label:
There are two ways to connect an input to a label,
Use the id of the input element in the for attribute:
<label for="checkbox">Label</label><input type="checkbox" id="checkbox"/>
Or simply wrap the input inside a label:
<label><input type="checkbox"/>Label</label>
See a working code example here in fiddle or below:
const onChange = (event) => {
console.log(event);
const checkbox = event.target;
alert("checkbox value is: " + checkbox.checked);
}
document.getElementById('checkbox').addEventListener('change', onChange);
input[type="checkbox"] {
visibility: hidden;
}
label {
font-weight: bold;
}
<label>
<input id="checkbox" type="checkbox"/>
label for hidden checkbox
</label>