I am supposed to have the same HTML code segment repeated multiple times on the same page. I have an external JavaScript file whose functionality is meant to be invoked whenever a user interacts with one of the repeated segments. However, only the first of the three code segments is impacted upon interaction. When interacting with the other two, nothing happens, meaning, the JavaScript does not get invoked.
I would assume that if all HTML code segments have the same IDs and classes (aside from the fact that unique IDs should be assigned), then at the least the content in all 3 HTML segments would change if changes are made in any of the other instances of these segments.
Here is an example of this issue:
<input id="my-id" type="text" />
<input id="my-id" type="text" />
<input id="my-id" type="text" />
<script>
var textbox = document.getElementById("my-id");
textbox.onkeyup = function() {
alert("ok");
}
</script>
Here, only interaction with the first instance of my-id creates the alert box, the other 2, don't. How can I make my code so that it applies to all 3 textboxes?
you should not use same id for multiple elements. The selector will return only first matched element in case of multiple elements with same id. It would be better if you use class instead of id. something like this will work:
<input class="my-id" type="text" />
<input class="my-id" type="text" />
<input class="my-id" type="text" />
<script>
var textboxes = document.getElementsByClassName("my-id");
for (var i = 0; i < textboxes.length; i++) {
textboxes[i].onkeyup = function(){
alert("ok");
};
}
</script>
You cannot have same id to all div's, ID's should be unique. Please change the ID to class in order to work.
Calling Javascript functions on a specific ID when there are multiple instances of the ID (which is a big no-no) will only work on the first instance in the DOM. Try calling your function on either the inputs or assign a class to each input and call it on the class.
You cannot use ID names in multiple times.. Change ID to CLASS.. It will work....
ID's must be unique!
In order to use the same javacsript functions for multiple div, assign a common class for all the divs and invoke the js function for the class!
Ids have to be unique, see: Can multiple different HTML elements have the same ID if they're different elements?. beside that getElementById returns only one element. Take a look at Adding event listeners to multiple elements
var textboxes = document.getElementsByClassName("my-class");
function keyUpListener() {
console.log("ok");
}
for (var i = 0; i < textboxes.length; i++) {
textboxes[i].addEventListener('keyup', keyUpListener, false);
}
<input class="my-class" type="text" />
<input class="my-class" type="text" />
<input class="my-class" type="text" />
Or use event delegation:
function keyUpListener(event) {
if( event.target.getAttribute('class').split(' ').indexOf('my-class') !== -1 ) {
console.log( 'ok' );
}
}
document.addEventListener('keyup', keyUpListener, false);
<input class="my-class" type="text" />
<input class="my-class" type="text" />
<input class="my-class" type="text" />
Because element ID must be unique, this attribute cannot be utilized to bind click event.
HTML5 support CSS Selector, a powerful mechanism to identify element that has similar characteristic.
Your code can be re-written with CSS Selector like below:
<input type="text" data-item="Text box 1"/>
<input type="text" data-item="Text box 2"/>
<input type="text" data-item="Text box 3"/>
<script>
function keyUpListener() {
var itemId = this.getAttribute('data-item');
alert(itemId);
}
var textboxes = document.querySelectorAll('input');
for (var i = 0; i < textboxes.length; i++) {
textboxes[i].addEventListener('keydown', keyUpListener, false);
}
</script>
Related
I need to get the value of all elements with a certain attribute.
I have a lot elements like this one
<input data-ini="3" class="form-control" type="time">
The attribute is day_of_week_ini, where i'm going to receive a day of the week in a function like this one
function createNewPeriod(day_of_week){
//i should have all values inside an array
}
//EDIT
I need to do that with jquery
/*input[data-ini] is the css selector. second parameter of jQuery map function is DOM element, so we retrieved the attr value using jquery. $(element) convert the DOM element to jQuery object.*/
var a = $('input[data-ini]').map((index,element)=> $(element).attr('data-ini'));
console.log(a);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<!-- A series of html time controls with data attribute data-ini -->
<input data-ini="3" class="form-control" type="time" value="18:00">
<input data-ini="4" class="form-control" type="time" value="16:00">
<input data-ini="5" class="form-control" type="time" value="02:00">
<input data-ini="6" class="form-control" type="time" value="03:00">
</body>
You should use data attribute for cases like this as developer said and set value attribute for your elements as it is edited now.
Then you can use below jQuery code.
var allElements = jQuery("[data-ini]");
var myArray = [];
for(var i = 0; i < allElements.length; i++) {
myArray.push(allElements[i].val());
}
I have a list of text-field + button that gets rendered dynamically. The user hits the button and I want to control the input field when a button is clicked.
I figure you could do something like:
<input id="1"><button onclick="doSomething(1)">Something</button>
<input id="2"><button onclick="doSomething(2)">Something</button>
<!--...-->
<input id="3"><button onclick="doSomething(3)">Something</button>
But wonder if there's a different and more sophisticated solution because the code I'm modifying passes an an anonymous function to onclick and I can't pass a unique ID like the method above.
This is very easy to achieve in vanilla Javascript (as most things). No jQuery overhead required here.
let buttons = [...document.getElementsByClassName('inputbutton')]
function doSomething(i) {
console.log(i);
}
for (const button of buttons) {
button.addEventListener('click', (e) => {
const i = e.target.previousSibling.id
doSomething(i);
})
}
<input id="1"><button class="inputbutton" type="button">Something</button>
<input id="2"><button class="inputbutton" type="button">Something</button>
<!--...-->
<input id="3"><button class="inputbutton" type="button">Something</button>
If you modify your dynamic HTML like the following and add this jQuery, you will be able to access the value of the previous input field.
var buttons = $(".inputs-and-buttons #button-after-input-field");
buttons.click(function() {
console.log($(this).prev("input").val());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inputs-and-buttons">
<input id="1" value="1"><button id="button-after-input-field">Something</button>
<input id="2" value="2"><button id="button-after-input-field">Something</button>
<!--...-->
<input id="3" value="3"><button id="button-after-input-field">Something</button>
</div>
You can generate dynamic Id for both input field and button with index or row number or you can add custom attribute for row number as below.
You can generate dynamic related control with specific Id for textbox and button as well. e.g. txtFirstName_1, txtLastName_1, btnAdd_1. here textbox and button distinguished by its id and number after Underscore "_" .
$(function(){
// Register click on button
//here you can pass specific class name for button if all are have same functionality
$("button").click(function(e){
console.log(this);
var btnId=$(this).attr("id");
//console.log(btnId);
// Way 1
//Split btnId with "_" e.g btn_1 will splited with ["btn","1"]
var rowIndex=btnId.split("_")[1];
console.log(btnId.split("_"),rowIndex);
$("#txt_"+rowIndex).val("Upate value by btn"+rowIndex); // Or fetch value
// Way 2
// You can directly use custom attribute data-row and do your work
var rowIndex1=$(this).attr("data-row");//$(e).prop("data-row");
console.log(rowIndex1);
//$("#txt_"+rowIndex1).val("Upate value"); // Or fetch value
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input id="txt_1" data-row="1"><button id="btn_1" data-row="1">Something</button>
<input id="txt_2" data-row="2"><button id="btn_2" data-row="2">Something</button>
<input id="txt_3" data-row="3"> <button id="btn_3" data-row="3">Something</button>
how to find element html with Jquery .
in this example element html is "input"
jsfiddle
$("#her").click(function() {
var $t = $('#mee');
console.log($t.filter());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="mee">
<input type="submit" value="click ici" id="her">
$(this).prev().prop('nodeName');
I believe this was the JSFiddle link - http://jsfiddle.net/sr2o412y/
<input type="text" id="mee">
<input type="submit" value="click ici" id="her" >
If you want to select a element using jquery you can use (#)id attribute or (.) class attribute or (input) html tagname.
In this case if you want to take the data from text element which has id => "#mee" on click if id => "#her". You can use the below code
$('#her').on('click', function(){
var textvalue = $('#mee').val();
console.log(textvalue);
});
Provide readable id and class names to identify elements properly.
Your selectors looks fine to me. In short, you can use any valid CSS selector, so both $('#her') and $('#mee') should be working in your example, as you have HTML elements with those ids:
$('#her').click(function() {
var $t = $('#mee');
console.log($t.val());
});
<input type="text" id="mee" />
<input type="submit" id="her" value="SUBMIT" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
If you want to select an element based on its type (tag) instead, then just remove the #. For example, to select any input element on the page you would just do:
$('input')
Or, to get just the first one:
$('input').first()
Or also:
$('input').eq(0)
You can also select elements based on type plus attribute to select specific inputs:
$('input[type="text"]')
Please forgive me if I repeat the question.
I have HTML that all elements inside a div tag has different id, suppose I have already get the reference to the div, is there any simple way to get the element by its id without iterate all elements with that div?
here is my sample html:
<div id="div1" >
<input type="text" id="edit1" />
<input type="text" id="edit2" />
</div>
<div id="div2" >
<input type="text" id="edit1" />
<input type="text" id="edit2" />
</div>
You may try something like this.
Sample Markup.
<div id="div1" >
<input type="text" id="edit1" />
<input type="text" id="edit2" />
</div>
<div id="div2" >
<input type="text" id="edit3" />
<input type="text" id="edit4" />
</div>
JavaScript
function GetElementInsideContainer(containerID, childID) {
var elm = {};
var elms = document.getElementById(containerID).getElementsByTagName("*");
for (var i = 0; i < elms.length; i++) {
if (elms[i].id === childID) {
elm = elms[i];
break;
}
}
return elm;
}
Demo: http://jsfiddle.net/naveen/H8j2A/
A better method as suggested by nnnnnn
function GetElementInsideContainer(containerID, childID) {
var elm = document.getElementById(childID);
var parent = elm ? elm.parentNode : {};
return (parent.id && parent.id === containerID) ? elm : {};
}
Demo: http://jsfiddle.net/naveen/4JMgF/
Call it like
var e = GetElementInsideContainer("div1", "edit1");
var x = document.getElementById("parent").querySelector("#child");
// don't forget a #
or
var x = document.querySelector("#parent").querySelector("#child");
or
var x = document.querySelector("#parent #child");
or
var x = document.querySelector("#parent");
var y = x.querySelector("#child");
eg.
var x = document.querySelector("#div1").querySelector("#edit2");
You don't want to do this. It is invalid HTML to have more than one element with the same id. Browsers won't treat that well, and you will have undefined behavior, meaning you have no idea what the browser will give you when you select an element by that id, it could be unpredictable.
You should be using a class, or just iterating through the inputs and keeping track of an index.
Try something like this:
var div2 = document.getElementById('div2');
for(i = j = 0; i < div2.childNodes.length; i++)
if(div2.childNodes[i].nodeName == 'INPUT'){
j++;
var input = div2.childNodes[i];
alert('This is edit'+j+': '+input);
}
JSFiddle
A given ID can be only used once in a page. It's invalid HTML to have multiple objects with the same ID, even if they are in different parts of the page.
You could change your HTML to this:
<div id="div1" >
<input type="text" class="edit1" />
<input type="text" class="edit2" />
</div>
<div id="div2" >
<input type="text" class="edit1" />
<input type="text" class="edit2" />
</div>
Then, you could get the first item in div1 with a CSS selector like this:
#div1 .edit1
On in jQuery:
$("#div1 .edit1")
Or, if you want to iterate the items in one of your divs, you can do it like this:
$("#div1 input").each(function(index) {
// do something with one of the input objects
});
If I couldn't use a framework like jQuery or YUI, I'd go get Sizzle and include that for it's selector logic (it's the same selector engine as is inside of jQuery) because DOM manipulation is massively easier with a good selector library.
If I couldn't use even Sizzle (which would be a massive drop in developer productivity), you could use plain DOM functions to traverse the children of a given element.
You would use DOM functions like childNodes or firstChild and nextSibling and you'd have to check the nodeType to make sure you only got the kind of elements you wanted. I never write code that way because it's so much less productive than using a selector library.
A simple way to do what OP desires in core JS.
document.getElementById(parent.id).children[child.id];
In HTML ids should be unique. I suggest you change your code to something like this:
<div id="div1" >
<input type="text" name="edit1" id="edit1" />
<input type="text" name="edit2" id="edit2" />
</div>
<div id="div2" >
<input type="text" name="edit1" id="edit3" />
<input type="text" name="edit2" id="edit4" />
</div>
Sample Html code
<div id="temp">
F1 <input type="text" value="111"/><br/>
F2 <input type="text" value="222"/><br/>
F3 <input type="text" value="333"/><br/>
Type <select>
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
</select>
<input type="button" value="Go" onclick="getVal()">
</div>
Javascript
function getVal()
{
var test = document.getElementById("temp").getElementsByTagName("input");
alert("Number of Input Elements "+test.length);
for(var i=0;i<test.length;i++)
{
if(test[i].type=="text")
{
alert(test[i].value);
}
}
test = document.getElementById("temp").getElementsByTagName("select");
alert("Select box "+test[0].options[test[0].selectedIndex].text);
}
By providing different tag names we can get all the values from the div.
Unfortunately this is invalid HTML. An ID has to be unique in the whole HTML file.
When you use Javascript's document.getElementById() it depends on the browser, which element it will return, mostly it's the first with a given ID.
You will have no other chance as to re-assign your IDs, or alternatively using the class attribute.
Using jQuery, what's the best way to find the next form element on the page, starting from an arbitrary element? When I say form element I mean <input>, <select>, <button> or <textarea>.
In the following examples, the element with the id "this" is the arbitrary starting point, and the element with the id "next" is the one I want to find. The same answer should work for all examples.
Example 1:
<ul>
<li><input type="text" /></li>
<li><input id="this" type="text" /></li>
</ul>
<ul>
<li><input id="next" type="text" /></li>
</ul>
<button></button>
Example 2:
<ul>
<li><input id="this" type="text" /></li>
</ul>
<button id="next"></button>
Example 3:
<input id="this" type="text" />
<input id="next" type="text" />
Example 4:
<div>
<input id="this" type="text" />
<input type="hidden" />
<div>
<table>
<tr><td></td><td><input id="next" type="text" /></td></tr>
</table>
</div>
<button></button>
</div>
EDIT: The two answers provided so far both require writing a sequence number to all input elements on the page. As I mentioned in the comments of one of them, this is kind of what I'm already doing and I would much prefer have a read-only solution since this will be happening inside a plugin.
kudos,
What about using .index?
e.g $(':input:eq(' + ($(':input').index(this) + 1) + ')');
redsquare is absolutely right, and a great solution also, which I also used in one of my project.
I just wanted to point out that he is missing some parentheses, since the current solution concatenates the index with 1, instead of adding them together.
So the corrected solution would look like:
$(":input:eq(" + ($(":input").index(this) + 1) + ")");
Sorry about the double-post, but I couldn't find a way to comment his post...
This solution does not require indexes, and also plays nicely with tabindex - in other words, it gives you the exact element that the browser would give you on tab, every time, without any extra work.
function nextOnTabIndex(element) {
var fields = $($('form')
.find('a[href], button, input, select, textarea')
.filter(':visible').filter('a, :enabled')
.toArray()
.sort(function(a, b) {
return ((a.tabIndex > 0) ? a.tabIndex : 1000) - ((b.tabIndex > 0) ? b.tabIndex : 1000);
}));
return fields.eq((fields.index(element) + 1) % fields.length);
}
It works by grabbing all tabbable fields in the form (as allowed by http://www.w3.org/TR/html5/editing.html#focus-management), and then sorting the fields based on (http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute) to work out the next element to tab to. Once it has that, it looks at where the passed in field is in that array, and returns the next element.
A few things to note:
jQuery appears to support sort() on a jQuery object, but I can't find
it explicitly in the documentation, hence calling toArray() and then
rewrapping the array in a jQuery object.
There are other fields that
it is okay to tab to, but I left them out as they aren't standard
form fields.
The code I used to test this was (using jQuery 1.7):
<script>
$(function() {
$('a[href], button, input, select, textarea').click(function() {
console.log(nextOnTabIndex($(this)).attr('name'));
})
});
</script>
<form>
<input type='text' name='a'/>
<input type='text' name='b' tabindex='1' />
<a>Hello</a>
<input type='text' name='c'/>
<textarea name='d' tabindex='2'></textarea>
<input id='submit' type='submit' name='e' tabindex='1' />
</form>
After trying every code I could find (and having issues between browsers), I found one that works in the top browsers. Couldn't use the previous routines because of some weird issues.
$(document.body).keydown(function(event) {
if(event.keyCode == 13 ) {
$(":input")[$(":input").index(document.activeElement) + 1].focus();
return false;
}
});
Hope this helps someone else. Enjoy.
You can do this to take a complete list of the form elements you are looking for:
var yourFormFields = $("yourForm").find('button,input,textarea,select');
Then, should be easy find the next element:
var index = yourFormFields.index( this ); // the index of your current element in the list. if the current element is not in the list, index = -1
if ( index > -1 && ( index + 1 ) < yourFormFields.length ) {
var nextElement = yourFormFields.eq( index + 1 );
}
You could give each form item an id (or unique class name) that identified it as a form element and also gave it an index. For example:
<div>
<input id="FormElement_0" type="text" />
<input id="FormElement_1" type="text" />
<div>
Then, if you want to traverse from the first element to the second you can do something like this:
//I'm assuming "this" is referring to the first input
//grab the id
var id = $(this).attr('id');
//get the index from the id and increment it
var index = parseInt(id.split('_')[0], 10);
index++;
//grab the element witht that index
var next = $('#FormElement_' + index);
The benefit of this is that you can tag any element to be next, regardless of location or type. You can also control the order of your traversal. So, if for any reason you want to skip an element and come back to it later, you can do that too.
Or you could use the html attribute 'tabindex' which is for when a user tabs around a form, it goes to tabindex="i" to tabindex="i+1". You can use jQuery to get the attribute very easily. Would make for a nice fall back to users without javascript enabled, also.
I came up with a function that does the job without explicitly defining indexes:
function nextInput(form, id) {
var aInputs = $('#' + form).find(':input[type!=hidden]');
for (var i in aInputs) {
if ($(aInputs[i]).attr('id') == id) {
if (typeof(aInputs[parseInt(i) + 1]) != 'undefined') {
return aInputs[parseInt(i) + 1];
}
}
}
}
And here's a working example. The form tags are for consistency. All you really need is a common parent and could even just use the body tag as the parent (with a slight modification to the function).
Paste this into a file and open with firefox / firebug and you'll see it returns the correct element for all your examples:
<html>
<head>
<script src="http://www.google.com/jsapi"></script>
<script>
function nextInput(form, id) {
var aInputs = $('#' + form).find(':input[type!=hidden]');
for (var i in aInputs) {
if ($(aInputs[i]).attr('id') == id) {
if (typeof(aInputs[parseInt(i) + 1]) != 'undefined') {
return aInputs[parseInt(i) + 1];
}
}
}
}
google.load("jquery", "1.2.6");
google.setOnLoadCallback(function() {
console.log(nextInput('myform1', 'this1'));
console.log(nextInput('myform2', 'this2'));
console.log(nextInput('myform3', 'this3'));
console.log(nextInput('myform4', 'this4'));
});
</script>
</head>
<body>
<form id="myform1">
<ul>
<li><input type="text" /></li>
<li><input id="this1" type="text" /></li>
</ul>
<ul>
<li><input id="next1" type="text" /></li>
</ul>
</form>
<form id="myform2">
<ul>
<li><input type="text" /></li>
<li><input id="this2" type="text" /></li>
</ul>
<ul>
<li><input id="next2" type="text" /></li>
</ul>
</form>
<form id="myform3">
<input id="this3" type="text" />
<input id="next3" type="text" />
</form>
<form id="myform4">
<div>
<input id="this4" type="text" />
<input type="hidden" />
<div>
<table>
<tr><td></td><td><input id="next4" type="text" /></td></tr>
</table>
</div>
<button></button>
</div>
</form>
</body>
</html>
You can use jQuery field plugin which allows you to do that.
var elementSelector = "input:visible,textarea:visible";
var nextSibling = $(elementSelector )[$(elementSelector ).index() + 1];
//$(nextSibling).focus(); possible action
I just think above solution is simpler, or you can just add it all in one line if you want :-)
var nextSibling = $("input:visible,textarea:visible")[$("input:visible,textarea:visible").index() + 1];
This worked well for me, and it correctly skips over hidden inputs:
input_el.nextAll( 'input:visible:first' ).focus();
All solutions using index (or nextAll) will only work where all the form inputs are siblings, e.g. within the same <div> block. The following gets round that by creating an array of ids of all visible, non-readonly inputs on the page and picks out the first one after the current control, wrapping round if the current control is the last one on the page.
ids = $(":input:visible:not([readonly])").map(function () { return this.id });
nextId = ids[($.inArray($(this).attr("id"), ids) + 1) % ids.length];
$("#" + nextId).focus();
Using the map function makes it a little more succinct than solutions involving iterators.