Fire events on more than one element in html - javascript

I have a jquery code
$(function() {
$("input").on("mouseover", function() {
var a = $('input').attr('name');
populate(a);
});
});
I have three input elements.
Computer Language: <br>
<div>
<datalist id="language"></datalist>
<input type="text" list="language" name= "language" id="search"/>
</div>
<br>
Country: <br>
<div>
<datalist id="country"></datalist>
<input type="text" list="country" name= "country" id="search" />
</div>
<br>
Degree: <br>
<div>
<datalist id="degree"></datalist>
<input type="text" list="degree" name= "degree" id="search"/>
</div>
Now, mouseover event only fires that have name language (or the top input element). Why mouseover event is not being fired for 2nd and 3rd input elements?

Note: The ids are not meant to be duplicated. You have used id="search" many times.
You need to use the context-sensitive this keyword:
$(function() {
$("input").on("mouseover", function() {
var a = $(this).attr('name');
populate(a);
});
});
To answer your question:
The reason being, you are executing the .attr() (which is one of many functions that processes only one element) on the first matched element.

You could use the parameter of your handler:
$("input").on("mouseover", function(e) {
var a = $(e.target).attr('name');
populate(a);
});
e.target is exatcly the element you are looking for.
You can use directly javascript instead to transform the element into a jQuery object:
$("input").on("mouseover", function(e) {
var a = e.target.getAttribute('name');
populate(a);
});

You need to refer to the current element which is done using $(this) ,
this refer to the element that invokes the event. $(this) will return the object. While
$('input').attr('name') will refer to the first input element
var a = $(this).attr('name');
JSFIDDLE

In JQuery code you always get "language" input, because it is first input in dom, as your code search first input.
Change your jQuery code as below:
$(function () {
$("input").on("mouseover", function () {
var a = $(this).attr('name');
populate(a);
});
});

Related

Use "this.id" when addEventListener in JavaScript

I want to get the id of an element create in javascript when we click on him.
For example:
var input_check = document.createElement("INPUT");
input_check.id = 1;
input_check.type = "checkbox";
input_check.addEventListener("click", test);
//Come here when s1 click on the checkbox
function test(id){
console.log(id);
}
Obviously with this example I can't print "ID" cause I need to "generate" with javascript something like this :
<input id="1" type="checkbox" onClick="test(this.id)">
With the previous example I have something like this :
<input id="1" type="checkbox" onClick="test()">
Do exactly what you did when writing the onclick function as an attribute value.
input_check.addEventListener("click", function () {
test(this.id);
});
Or just write test to expect to be called as an event listener in the first place:
input_check.addEventListener("click", test);
function test(event) {
console.log(this.id);
}
To generate the input in HTML, you must add the input you created to the body, like this:
document.body.appendChild(input_check);

jQuery-Events: How To Unbind Keyup Event If One Input Detected?

I've currently this function here:
let input = [];
input.push(jQuery("#test1"));
input.push(jQuery("#test2"));
input[0].add(input[1] ).one( "keyup", function () {
console.log("Keyup!");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="test1"/>
<input id="test2"/>
It works but I've a bit of a problem. I need to unbind the keyup event if one of the two inputs are detected so that the other one don't works anymore. How can I do this?
As result, only one log Keyup! should be visible.
u can unbind with jquery-off -method (https://api.jquery.com/off/) like so:
let input = [];
input.push(jQuery("#test1"));
input.push(jQuery("#test2"));
input[0].add(input[1] ).one( "keyup", function () {
$(input).each(function() {
$(this).off("keyup");
});
console.log("Keyup!");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="test1"/>
<input id="test2"/>
So, this was my solution:
let input = [];
input.push(jQuery("#test1"));
input.push(jQuery("#test2"));
input[0].add(input[1]).one("keyup", function() {
console.log('keyup!');
for(i=0; i<input.length; i++){
if(input[i].attr('id') != event.target.id){
input[i].unbind();
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="test1" />
<input id="test2" />
Don't know if you'll like it, but I find useful to know which element triggered the event in order to use this info after.
Moreover, you'll be able to add more elements to input array and automatically unbind the event from them too.
To achieve that you can add an extra data attribute and check against that:
<input id="test1" data-disabled="false"/>
<input id="test2" data-disabled="false"/>
Then your js would look like this:
input[0].add(input[1] ).one( "keyup", function () {
if ($(this).attr("data-disabled")==="true") {
return false;
}
$(this).siblings().attr("data-disabled","true");
console.log("Keyup!");
});

How to apply validation to cloned elements in Jquery?

There is a textbox with label; having validation of isnumeric.
Money: <input type="text" id="dollar" name="dollar" data-require-numeric="true" value="">
//Textbox with id dollar0
At run time, I have created clone of above; by clicking on button named add; and this created another textbox with different id and other attributes same; say.
Money: <input type="text" id="dollar1" name="dollar1" data-require-numeric="true" value="">
//Cloned textbox; cloned by clicking on a button named clone
On both textboxes data-require-numeric is true.
Issue: For default textbox the JQuery validation is getting executed. But for new clone; JQuery is not running.
Following is jquery:
var economy= {
init: function () {
$('input[type="text"][data-require-numeric]').on("change keyup paste", function () {
check isnumeric; if yes then border red
});
}};
$(economy.init);
How to resolve this?
Try this : You need to register click event handler using .on() in following way where registering the click handler for document which will delegate the event to 'input[type="text"][data-require-numeric]'. This way you can handle events for dynamically added elements.
var economy= {
init: function () {
$(document).on("change keyup paste",'input[type="text"][data-require-numeric]',
function () {
check isnumeric; if yes then border red
});
}};
$(economy.init);
to bind change event on dynamic dom elements . use class reference instead of id . And bind the event to its parent like,
$(document).ready(function(){
$(".parent").on("keyup",".dynamicdom",function(e){
value = $(e.target).val()
//then do your validation here. and you can attach multiple events to it
})
})
<div class="parent">
<input type="text" class="dynamicdom" >
<input type="text" class="dynamicdom" >
</div>

Copy value from input 1 to input 2 onclick

Looking for a script that copies input value 1 to input 2 on button click and add +1 to sets text box.
b = document.getElementById('tussenstand').value;
var theTotal1 = b;
$(document).on("click", "#button1", function(){
theTotal1 = Number(theTotal2)
$('#eindstand').val(theTotal2);
});
$('#eindstand').val(theTotal2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id="tussenstand"></input>
<input id="eindstand"></input>
<input id="sets"></input>
<button id="button1">click</button>
Thanks in advance.
I think this will do it.
$(document).on("click", "#button1", function(){
var total = document.getElementById('tussenstand').value;
$('#eindstand').val(total);
var sets = parseInt($('#sets').val());
$('#sets').val( (sets || 0) + 1);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id="tussenstand"></input>
<input id="eindstand"></input>
<input id="sets"></input>
<button id="button1" onclick="">click</button>
$('#button1').click(function(){
$('#eindstand').val($('#tussenstand').val());
$('#sets').val(Number($('#sets').val())+1);
});
check here : jsfiddle
Edited as you commented
The code below should work. There are several issues that will help you in the future. In the HTML the function that is triggered via the onclick will interfere with the jQuery onclick. You may want to remove it.
onclick="bereken();
The way that you have your code the b variable is not declared.
b=document.getElementById('tussenstand').value;
The way that the jQuery onclick is written should have a narrower scope (not the document). The way that it is now every time you click any were in the document it fires. I changed this:
$(document).on("click", "#button1", function(){
to this:
$("#button1").on("click", function() {
The full edited code is here.
var count = 0;
$("#button1").on("click", function(){
if ( typeof b === 'number') {
count++;
$("#eindstand").val(b);
$("#sets").val(count);
}
});
Look at the JQuery API Documentation for the .on() method. The function doesn't take the target as a parameter, but as the caller object! EDIT: well, it would actually still work the other way around, but that makes event delegation. Only do that if you know what you're doing. I prefer changing this:
$(document).on("click", "#button1", function(){ ... });
into this:
$("#button1").on("click", function() { ... });
Which in vanilla JS would be:
document.getElementById("button1").addEventListener("click", function() { ... });
Next, you shouldn't need to define variables outside of your function, and naming variables with numbers in them is a bad practice. Try to make the names as clear as possible.
Now that this is clear, here's how I'd write it:
$("#button1").on("click", function() {
$("#eindstand").val($("#tussenstand").val());
$("#sets").val(parseInt($("#sets").val())+1);
});
To achieve that use:
$(function() { //on DOM ready
$('#button1').click(function(){ //Attach event
//Get value safe - can use parseFloat() too:
val1 = parseInt($('#tussenstand').val());
val2 = parseInt($('#eindstand').val());
sets = parseInt($('#sets').val());
//Make sure we are using integers:
if (isNaN(val1) || isNaN(val2) || isNaN(sets)) return;
//Add
$('#eindstand').val(val1 + val2);
//Increment:
$('#sets').val(sets+1);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="tussenstand" type='number' />
<input id="eindstand" value='0' type='number' />
<input id="sets" value='0' type='number' />
<button id="button1">click</button>

How to refactor this simple code

I have a following script:
$(document).ready(function() {
$('#q1_6').on("click", function(event){
$('#q1-f').slideToggle(350);
});
$('#q1_7').on("click", function(event){
$('#q1-m').slideToggle(350);
});
$('#q1_15').on("click", function(event){
$('#q1-o').slideToggle(350);
});
$('#q2_6').on("click", function(event){
$('#q2-f').slideToggle(350);
});
$('#q2_7').on("click", function(event){
$('#q2-m').slideToggle(250);
});
$('#q2_15').on("click", function(event){
$('#q2-o').slideToggle(350);
});
$('#q3_13').on("click", function(event){
$('#q3-o').slideToggle(350);
});
});
Are these calls proper, or maybe I should somehow refactor the script to avoid duplication?
Edit:
I am creating a survey with about 20 questions displayed on one page. Answers are in checkboxes. Some answers have additional options (sub-answers), which should be shown when user clicks parental answer. Here is HTML markup for better understanding
<div>
<input type="checkbox" id="q1_5"/><label for="q1_5">Answer 5</label>
</div>
<div>
<input type="checkbox" id="q1_6"/><label for="q1_6">Answer 6</label>
</div>
<div id="q1-f">
<div>
<input type="checkbox" id="q1_6_1"/><label for="q1_6_1">Answer 6-1</label>
</div>
<div>
<input type="checkbox" id="q1_6_2"/><label for="q1_6_2">Answer 6-2</label>
</div>
<div>
<input type="checkbox" id="q1_6_3"/><label for="q1_6_3">Answer 6-3</label>
</div>
</div>
Current script works well, but I am wondering if I can avoid repeats of the same code snippets.
If you have access to the HTML and can influence the structure of the elements which when clicked initiate the toggle, then I'd add a class and data attribute:
<a href='#' id='q1_6' class='toggle' data-toggle-id='q1-f'>blah</a>
$(document).ready(function() {
$('a.toggle').on('click', function(){
var $el = $(this),
toggleID = '#' + $el.attr('data-toggle-id'),
toggleValue = 350;
$(toggleID).slideToggle(toggleValue);
});
});
given no idea on how IDs are correlated in your example.
function toggle(id, id2, value){
$(id).on("click", function(event){
$(id2).slideToggle(value);
});
}
toggle('#q1_15', '#q1-0', 350);
You could do :
$('[id^="q"]').on("click", function(e){
//get the id of the clicked button
var id = e.target.id;
switch(id){
//do all cases based on id
}
});
This could be done in an even cleaner way if there is some element to which we could delegate the event handling, but you didn't show us your markup. It would be something like
$('body').on("click",'[id^="q"]', function(e){
//get the id of the clicked button
var id = e.target.id;
switch(id){
//do all cases based on id
}
});
This second option use only one event handler (good) but it has to wait until the event is bubbled up the DOM (might be bad)
Why don't you create a javascript object where keys denote the id of element that accepts clicks and corresponding value is the id of element to show. Something like:
var clickHanders = {
"q1_6": "q1-f",
"q1_7": "q1-m"
// ...
};
Then all you need is:
$(document).ready(function() {
$("div[id^=q]").on("click", function(event) {
var srcId = this.id;
var dstId = clickHanders[srcId];
if (dstId) {
$("#" + dstId).slideToggle(350);
}
});
});
Edit
I now see that the slide duration can be different as well. You can still use the above approach:
var clickHanders = {
"q1_6": {
"elementId": "q1-f",
"duration": "350"
},
"q2_7": {
"elementId": "q2-m",
"duration": "250"
}
//...
};
$(document).ready(function() {
$("div[id^=q]").on("click", function(event) {
var srcId = this.id;
var dstData = clickHanders[srcId];
if (dstData) {
$("#" + dstData.elementId).slideToggle(dstData.duration);
}
});
});
This code looks longer than your original code but perhaps more sensible.
There are some things to ask when you refactor:
Are you having speed problems?
Are you having memory problems?
Does the code look ugly?
You should not be refactoring code just to refactor it and optimize something where it is not needed. If the code is not too slow and does not have a too high memory consumption (all in the eye of the beholder) and is readable, you have good code.
My idea would be to serialize the event trigger, event target and slideToggle amount, so you could iterate through some kind of Collection and bind it. But would that be worth it?
Well, each handler does the very same thing, so here's what you should do:
Refactor your HTML, for example:
<div id="q1-6" data-to="q1-f"></div>
for each object (you can use other HTML attributes). Then you can define handlers:
$('#q1-6,#q1-7,#someother_id,#watman,#foo').click(function() {
var id = $(this).attr('data-to');
$('#'+id).slideToggle(350);
});
There is no way to shorten your code, because there is nothing exactly the same, so your code is ok.

Categories

Resources