How can I access a dynamically created element using jQuery? Suppose I have the following code:
for (var i = 0; i < count; i++)
{
var div = document.createElement("div");
div.setAttribute("id", "divHour" + i);
var button = document.createElement("button");
button.setAttribute("id", "btnHour" + i);
div.appendChild(button);
document.getElementById("divHours").appendChild(div);
}
How can I access the buttons using jQuery?
To select the button inside your original loop...
for (var i = 0; i < count; i++)
{
var div = document.createElement("div");
div.setAttribute("id", "divHour" + i);
var button = document.createElement("button");
button.setAttribute("id", "btnHour" + i);
div.appendChild(button);
document.getElementById("divHours").appendChild(div);
// moved after the button has been added to the DOM
// do something with the button in jQuery
$("#btnHour" + i).css({width:100})
}
As long as you know the HTML ID of the element. All you need to do is this:
$("#html_id")
jQuery uses CSS selectors.
Give the buttons a class:
div.setAttribute("class", "myButton");
Then you can get all of the buttons with
$('.myButton') ...
For example, to loop over them:
$('.myButton').each(function(){
console.log($(this).attr("id"));
});
If you want to identify each button, parse the number out of the class or give it a data-mynumber attribute and use $(this).data('mynumber')
var $button0 = $('#btnHour0')
var $button1 = $('#btnHour1')
// ... etc ...
Once you have cached the jQuery object, use it as you wish...
$button0.css({width: 400}).animate({width: 200})
EDIT
To access all buttons in a loop...
// assuming `count` is the same as the code used to create the buttons
for (var i = 0; i < count; i++){
var $button = $('#btnHour'+i)
// do stuff with $button here
}
EDIT
Alternatively, to access all button elements that have an ID that starts with btnHour
var $buttons = $('button[id^="btnHour"]')
// do stuff to all buttons here
$buttons.css({width:300})
var buttons=$('button[id^="btnHour"]');
Will give you the whole collection of buttons
Your question is extremely vague, I suspect you want to access a specific button contained within a div that user interacts with. More details are required as to what you want.
EDIT: following is how you can access the index of a button within a click handler.
var buttons=$('button[id^="btnHour"]').click(function(){
var buttonIndex= buttons.index(this);
var div=$('#divHour'+ buttonIndex)
/* can now interact with corresponding div*/
});
Another simpler way to find the parent div is :
$('button[id^="btnHour"]').click(function(){
var $parentDiv=$(this).parent()
})
To target a specific button use eq() method
var thirdButton=$('button[id^="btnHour"]').eq(2);/* indexing is zero based*/
Related
I'm working on a JavaScript project where a user can click a button to create a text element. However, I also want a feature where I can click a different button and the element that was created most recently will be removed, so In other words, I want to be able to click a button to create an element and click a different button to undo that action.
The problem I was having was that I created the element, then I would remove the element using:
element.parentNode.removeChild(element); , but it would clear all of the elements that were created under the same variable.
var elem = document.createElement("div");
elem.innerText = "Text";
document.body.appendChild(elem);
This code allows an element to be created with a button click. All elemente that would be created are under the "elem" variable. so when I remove the element "elem", all element are cleared.
Is there a simple way to remove on element at a time that were all created procedurally?
Thanks for any help
When you create the elements, give the a class. When you want to remove an element, just get the last element by the className and remove it.
The below snippet demonstrates it -
for(let i = 0; i<5; i++){
var elem = document.createElement("div");
elem.innerText = "Text " + i;
elem.className = "added";
document.body.appendChild(elem);
}
setTimeout(function(){
var allDivs = document.getElementsByClassName("added");
var lastDiv = allDivs.length-1;
document.body.removeChild(allDivs[lastDiv]);
}, 3000);
I would probably use querySelectors to grab the last element:
// optional
// this is not needed it's just a random string added as
// content so we can see that the last one is removed
function uid() {
return Math.random().toString(36).slice(2);
}
document.querySelector('#add')
.addEventListener('click', (e) => {
const elem = document.createElement('div');
elem.textContent = `Text #${uid()}`;
document.querySelector('#container').appendChild(elem);
// optional - if there are elements to remove,
// enable the undo button
document.querySelector('#undo').removeAttribute('disabled');
});
document.querySelector('#undo')
.addEventListener('click', (e) => {
// grab the last child and remove
document.querySelector('#container > div:last-child').remove();
// optional - if there are no more divs we disable the undo button
if (document.querySelectorAll('#container > div').length === 0) {
document.querySelector('#undo').setAttribute('disabled', '');
}
});
<button id="add">Add</button>
<button id="undo" disabled>Undo</button>
<div id="container"></div>
I'm new to JS and jQuery but I've been trying to use the addClass() and removeClass with some Javascript variables and don't know what I'm doing wrong.
I have this 1–5 star rating system.
I want it to change classes when hovering and save rating when I click.
The HTML looks like this:
<span class="icon-rating-empty" id="blob1"></span>
and so on for blobs 2–5.
The JS I currently have is
var blob1 = document.getElementById('blob1');
var blob2 = document.getElementById('blob2');
var blob3 = document.getElementById('blob3');
var blob4 = document.getElementById('blob4');
var blob5 = document.getElementById('blob5');
var rating = 0;
blob1.addEventListener('hover', function() {
$(blob1).addClass("icon-rating-full").addClass("green-blob").removeClass("icon-rating-empty")
},
function() {
$(blob1).addClass("icon-rating-empty").removeClass("green-blob").removeClass("icon-rating-full")
});
blob1.addEventListener('click', function() {
rating = 1;
});
This doesn't work—I'm sure I don't know how to handle variables with the jQuery, but can't find any article on what I'm supposed to do.
I've tested it and if I use $("#blob1") instead of $(blob1) it works, but I'd like to use the variables because I have more in plan.
You're not far off. You will need to set up two sets of event listeners: one for when the user clicks on a star, and one for when the user hovers over a star.
I suggest saving the "rating" as a variable. When the user clicks a star, you adjust the rating. I used a data attribute to keep track of the value of each star. After adjusting the rating, you loop through the elements and add or remove classes accordingly.
Hovering adds a layer of complexity. Every time there is mouseover, you will need to loop over the star elements and update the classes as though that was the new rating. When you mouseout, you will update the classes again according to the rating that you saved.
var rating = 0;
var stars = $('li');
// Set up listeners
$('li').on('click', function(){
rating = parseInt($(this).data('val'));
drawStars(rating);
});
$('li').hover(
function(){
tempRating = parseInt($(this).data('val'));
drawStars(tempRating);
},
function(){
drawStars(rating);
}
);
// This function loops through the "star" elements and adds and removes a 'selected' class
function drawStars(numStars){
// Reset the colour by removing the selected class from all elements
for(var i = 0; i < stars.length; i++){
$(stars[i]).removeClass('selected');
}
// Add a selected class to some of the elements
for(var i = 0; i < numStars; i++){
$(stars[i]).addClass('selected');
}
}
See this jsfiddle: https://jsfiddle.net/ffz5y9fm/5/
Untested:
<span class="rating">
<span data-star="0">STAR</span>
<span data-star="1">STAR</span>
<span data-star="2">STAR</span>
<span data-star="3">STAR</span>
<span data-star="4">STAR</span>
<span data-star="5">STAR</span>
</span>
<script>
try{
var elements = document.querySelectorAll('.rating'),
listener = function(e){
var a = this, parent = a.parentNode, value = parseInt( a.getAttribute('data-star') );
// reset
parent.classList = 'rating';
// add class
parent.classList.add( 'star-'+value );
};
// get all elements and attach listener
for( var i = 0; i < elements.length; ++i ){
var current = elements[i], childs = current.children;
for( var ii = 0; ii < childs.length; ++ii ){
childs[ii].addEventlistener('mouseenter',listener,false);
}
}
} catch(e){ console.log('error',e); }
</script>
If something doesn't work just report here.
I am adding a simple toggle button through Javascript. Then I want to add three span tags inside it.
So, I am creating variable of span and trying to append it inside our very own basic FOR loop. Iteration count is 3 times.
Here's my basic code below. Please let me know what has been missing or misplaced that my span tag refuses to append more than once. I checked this in the inspect mode.
Then, I brought up console tab and the value of i was 3. Append is meant to append and NOT replace the element. Right ?
var $navbar_header = $('<div class="navbar-header"></div>');
var $button = $("<button></button>");
var $span = $('<span class="icon-bar"></span>');
for (var i = 0; i < 3; i++) {
$button.append($span);
}
$button.addClass('navbar-toggle');
$navbar_header.append($button);
$("#menu").append($navbar_header);
Here's a link to fiddle.
The DOM is a tree, where any element points to its parent (see parentNode). An element can have only one location. So when you append an element, you're removing it from its precedent location.
The solution here is either to clone the element:
$button.append($span.clone());
or just to create it in the loop:
for (var i = 0; i < 3; i++) {
$button.append('<span class="icon-bar"></span>');
}
Is this possible? Or is there a way to tack on and ID to an existing div?
This is my code. I can't get the code to work using classes, but I found when I used getElementById and changed the div to an ID, that it did. But I have a ton of already posted stuff so it would take forever to go through all those posts and change it manually to an ID.
Can I incorperate JQuery in this and still have it work? I tried that with something I stumbled across but it didn't work so I removed it. I don't remember what it is now though. :S
<div id="imdb" class="imdb">tt2382396</div>
<script>
function imdbdiv() {
var imdbmain = "http://www.imdb.com/title/";
var end = "/#overview-top";
var idnum = document.getElementsByClassName("imdb");
var newdiv = document.createElement("div");
var done = "<a href='" + imdbmain + idnum + end + "'>IMDB</a>";
newdiv.innerHTML = done;
document.body.appendChild(newdiv);
}
window.onload = imdbdiv();
</script>
Can anyone help. I cannot for the life of me figure this out.
JsFiddle
Your problem was, you were appending the collection returned by document.getElementsByClassName instead of looping through the elements in the collection. You can verify this by looking at the href property of the link in your jsFiddle. You must loop through the values, then access the data in their innerHTML property.
You can use document.querySelectorAll to get a list of all elements matching a certain CSS selector, in your case .imdb. This is more flexible, in case you want to select elements with more than one class. I've pasted the code from the updated jsFiddle below.
function imdbdiv() {
var imdbMain = "http://www.imdb.com/title/",
end = "/#overview-top",
imdbValueDivs = document.querySelectorAll('.imdb'),
length = imdbValueDivs.length,
// Iterator values
i,
newDiv,
newLink;
// Loop over all of your link value containers
for (i = 0; i < length; i++) {
// Create the container
newDiv = document.createElement('div');
// Create the new link
newLink = document.createElement('a');
newLink.href = imdbMain + imdbValueDivs[i].innerHTML + end;
newLink.innerHTML = "My favorite film";
// Add the link to the container,
// and add the container to the body
newDiv.appendChild(newLink);
document.body.appendChild(newDiv);
}
}
window.onload = imdbdiv();
If you have many such divs on your page, then it could be like this:
<div class="imdb">tt2382396</div>
<div class="imdb">tt2382396</div>
<div class="imdb">tt2382396</div>
<script>
function imdbdiv() {
var imdbmain = "http://www.imdb.com/title/";
var end = "/#overview-top";
var idnums = document.getElementsByClassName("imdb");
for (var i =0; i < idnums.length; i++) {
var newdiv = document.createElement("div");
var done = "<a href='" + imdbmain + idnums[i].innerText + end + "'>IMDB</a>";
newdiv.innerHTML = done;
document.body.appendChild(newdiv);
}
}
window.onload = imdbdiv();
</script>
See jsfiddle
UPDATE:
The following string was incorrect:
window.onload = imdbdiv;
Okay, so your question is a little bit unclear.
The way I understood your question is that you have a whole bunch of div elements with class attribute and what you want is to simply copy the class value to the id attribute of the div elements.
If that's correct then try something like this with jquery:
<script>
$(document).ready(function(){
$(".imdb").each(function(imdbDiv){
var classValue = imdbDiv.attr("class");
imdbDiv.attr("id", classValue);
});
});
</script>
I have a button that is defined as follows :
<button type="button" id="ext-gen26" class=" x-btn-text">button text here</button>
And I'm trying to grab it based on the text value. Hhowever, none of its attributes contain the text value. It's generated in a pretty custom way by the look of it.
Does anyone know of a way to find this value programmatically, besides just going through the HTML text? Other than attributes?
Forgot one other thing, the id for this button changes regularly and using jQuery to grab it results in breaking the page for some reason. If you need any background on why I need this, let me know.
This is the JavaScript I am trying to grab it with:
var all = document.getElementsByTagName('*');
for (var i=0, max=all.length; i < max; i++)
{
var elem = all[i];
if(elem.getAttribute("id") == 'ext-gen26'){
if(elem.attributes != null){
for (var x = 0; x < elem.attributes.length; x++) {
var attrib = elem.attributes[x];
alert(attrib.name + " = " + attrib.value);
}
}
}
};
It only comes back with the three attributes that are defined in the code.
innerHTML, text, and textContent - all come back as null.
You can do that through the textContent/innerText properties (browser-dependant). Here's an example that will work no matter which property the browser uses:
var elem = document.getElementById('ext-gen26');
var txt = elem.textContent || elem.innerText;
alert(txt);
http://jsfiddle.net/ThiefMaster/EcMRT/
You could also do it using jQuery:
alert($('#ext-gen26').text());
If you're trying to locate the button entirely by its text content, I'd grab a list of all buttons and loop through them to find this one:
function findButtonbyTextContent(text) {
var buttons = document.querySelectorAll('button');
for (var i=0, l=buttons.length; i<l; i++) {
if (buttons[i].firstChild.nodeValue == text)
return buttons[i];
}
}
Of course, if the content of this button changes even a little your code will need to be updated.
One liner for finding a button based on it's text.
const findButtonByText = text =>
[...document.querySelectorAll('button')]
.find(btn => btn.textContent.includes(text))