I have a template that I will be adding to the body multiple times. Each one will be the same, except the text in one of the elements will be different:
<template id="template">
<div class="activity">
<p class="activityName"> <!-- to be changed -->
</p>
<button type="button" class="btn btn-primary">
Edit
</button>
</div>
</template>
When I insert this template, I wants to edit the .activityName element. I could use Node.firstChild, but that means that if I change the HTML in the future, this setup might break if that element is no longer the first child. Is it possible to retrieve it by class from that specific node? Something like this:
var template = document.getElementById("template");
var clon = template.content.cloneNode(true);
clon.getElementsByClassName("activityName")[0].innerHTML = "text"; //this line needs changing
document.body.append(clon);
what about using:
clon.querySelector(".activityName").innerHTML = "text";
The querySelector function finds the first element that matches with the specified selector, in this case, our selector is .activityName this means that the function will find the first element with the class activityName
Now, if you want to get all the nodes with the same class, you have to use the querySelectorAll function
I see that you used template.content but there is not a property called content in template element, maybe you mean something like var clon = template.querySelector('.activity')
Related
I am trying to identify a button press in JavaScript that is coming from a list within a list.
In basic terms I am thinking of it like a 2x2 table - e.g. if the top-right button is pressed it's index should be 0-1. If bottom-right is pressed it's index should be 1-1. If top-left is pressed index should be 0-0, bottom left 1-0 etc.
The child lists make up the parent list's rows, and are comprised of a series of pre-defined templates. Each child list's ID is generated using the index id of the parent list.
I'd like to know best practice for this. I am using Crestron's ch5 library but am hoping I can apply generic principles to my problem.
I have simplified the HTML:
<template id="template-0">
<button id="post-1">Item 1</button>
</template>
<template id="template-1">
<button id="post-2">Item 2</button>
</template>
<ch5-list
class="verticalList"
size="2"
indexid="idy"
id="parent-list"
orientation="vertical">
<template>
<ch5-list
class="horizontalList"
id="child-list{{idy}}"
size="2"
indexid="idx"
orientation="horizontal">
<template>
<ch5-template templateid="template-{{idx}}">
</ch5-template>
</template>
</ch5-list>
</template>
</ch5-list>
I am new to HTML so apologies if this is a stupid question.
Any help would be much appreciated!
Thank you
Accessing elements in your HTML can be done with several DOM methods: getElementById, getElementsByTagName, getElementsByClassName, and querySelectorAll.
NOTE: In all of the methods which return a collection of resulting elements, the elements will be sorted in the order which they appear on the page (in the HTML), so the button order would be as follows:
let order = [
"top-left button", "top-right button",
"bottom-left button", "bottom-right button"
];
getElementById
If the resulting button elements from the template are placed, they'll just have id values of post-1 for template-0 and post-2 for template-1. With two columns and two rows of buttons, this means that there will only be two unique IDs between four buttons, so selecting elements this way may not work well. The HTML code could probably be modified to be sure that the buttons have unique ID attributes. If that problem can be solved, the following code will select one button at a time:
let buttonElement = document.getElementById("post-1");
// or if ID can be resolved to be post-0-1:
let firstButtonElement = document.getElementById("post-0-1");
getElementsByTagName
Using this method would work fine as it will return a list of button elements as an HTMLCollection. It may return other buttons on the page, but it's a minor inconvenience that can be handled.
let buttonsCollection = document.getElementsByTagName("button");
getElementsByClassName
If you use a class for the buttons instead of IDs, the buttons can all be assigned to the same class and this is one of the ways it will select all of the buttons as intended and none of the buttons you didn't intend.
<template id="template-0">
<button id="post-1" class="postButtons">Item 1</button>
</template>
<template id="template-1">
<button id="post-2" class="postButtons">Item 2</button>
</template>
let postButtons = document.getElementsByClassName("postButtons");
console.log(postButtons);
querySelectorAll
This method combines multiple selection types into one (using CSS selectors):
Description
Method call
Tag names
document.querySelectorAll("button");
Class names
document.querySelectorAll(".postButtons");
Id
document.querySelectorAll("#post-1");
Since you can use CSS Selectors, you could select buttons with id values that start with post- like so:
let postButtons = document.querySelectorAll("button[id^=post-]");
I'm not entirely sure how the elements will be created as for the CH5 library, but these steps provided above should help you get started.
Code Snippet showing all of the above examples in one:
let buttonElementPostOne = document.getElementById('post-1');
console.log("getElementById:".padStart(23, " "), buttonElementPostOne);
let buttonsCollection = document.getElementsByTagName('button');
console.log("getElementsByTagName:".padStart(23, " "), buttonsCollection[0]);
let postButtons = document.getElementsByClassName('postButtons');
console.log("getElementsByClassName:".padStart(23, " "), postButtons[0]);
let postButtonsQueried = document.querySelectorAll('button[id^=post-');
console.log("querySelectorAll:".padStart(23, " "), postButtonsQueried[0]);
<div>
<button id="post-1" class="postButtons">post-1</button>
<button id="post-2" class="postButtons">post-2</button>
</div>
<div>
<button id="post-3" class="postButtons">post-3</button>
<button id="post-4" class="postButtons">post-4</button>
</div>
I have an HTML like this
<div class="this">
EXP
</div>
I want to add id to <a>. But do not know what to do.
First select your element using something like .getElementsByClassName(). Keep in mind that .getElementsByClassName() returns a NodeList collection of elements, so you'll want to access the first index (or loop over them). You can then simply set the ID with .id, as the ID is merely a property of an element.
This can be seen in the following:
const element = document.getElementsByClassName('this')[0];
element.id = 'element';
console.log(element);
<div class="this">
EXP
</div>
If you want to add this with Javascript, you'll need to use a selector to target your <a> tag and then set the id attribute on it. You can do this by using the querySelector() function or as seen below:
// Find an <a> tag that occurs below a class called "this" and set its id attribute
document.querySelector('.this > a').id = "some-id";
There are many other available functions to handle this through native Javascript and other frameworks, so your milage may vary depending on what you are using.
Example
In this example, we have provided some CSS that should only apply to an element with an id of "test" and we'll run the necessary code to show that the id is being added to the element (as it will be red):
document.querySelector('.this > a').id = 'test';
#test { color: red; }
<div class="this">
EXP
</div>
Add the id attribute to the <a> tag. See the differences of the middle line:
<div class="this">
<a id="expid" href="exp.com">EXP</a>
</div>
I know how to append an element inside another element, but how do I specify which class I want to append it to?
For example:
<div class="main" id="11">
<div class="somethingelse>
<div class="moreThings">
/*How to append to this class?*/
</div>
<div class="extraThings">
</div>
</div>
</div>
What I have is something like this:
var x = document.createElement("IMG");
x.setAttribute("src", "../truck.png");
document.getElementById(order_id).appendChild(x);
document.getElementById("btn_transport_"+order_id).style.display = "none";
There could be hundreds of classes with same name which is why I need to define them by id.
At the moment I am appending the img under everything other divs, but I would like to append it inside "morethings". How would I do that?
You could do something like this:
document.getElementById(order_id).getElementsByClassName("moreThings")[0].appendChild(x);
Make sure getElementsByClassName("moreThings") returns at least one element.
You can find out more about getElementsByClassName(...) from HERE. The gist of it is:
Returns an array-like object of all child elements which have all of the given class names
You could use document.querySelector. It allows CSS-like selectors. In your case it could look like
const myElementToAppendTo = document.querySelector('#myID .morethings');
myElementToAppendTo.appendChild(x);
I'm trying (in native Javascript, so without jQuery or anything) to get content before and after occurence of a div.
HTML:
<div id="thisIsWhatIWant">
<span>foo</span>
<div id="helloWorld">hello world</div>
<p>bar</p>
</div>
So I want to get <span>foo</span> and <p>bar</p> in separate vars.
JS:
var beforeElement_helloWorld = ...do something to get <span>foo</span>...
var afterElement_helloWorld = ...do something to get <p>bar</p>...
note:
There may be many more divs, spans etc in the HTML example.
You need this:
var previous = document.getElementById("helloWorld").previousElementSibling;
var next = document.getElementById("helloWorld").nextElementSibling;
Also read this,
The difference between previousSibling and previousElementSibling, is that previousSibling returns the previous sibling node as an element node, a text node or a comment node, while previousElementSibling returns the previous sibling node as an element node (ignores text and comment nodes).
Could you please lend a hand as I am having some trouble getting the text of a heading and the source of an image element in order to create a list of the item clicked. But I will explain better with some code:
Firstly I have a div element that goes like this:
<div class="main_page_entry">
<div class="main_item_desc">
<img class="main_item_pic" src="blah.jpg" />
<h6>Item Title</h6>
<span class="icon"> <img src="icon.png" /></span><br />
<span class="address">Some address</span>
<p class="item_desc">More blahs and links for description </p>
</div>
<div class="item_controls">
...
<a href="#" class="add_to_list">
<img src="add_icon.gif" />Add to List
</a>
...
</div>
</div>
It consists with a big div containing two smaller. What I want to do is the following: When I click on 'Add to List' link, I would like to get just the text inside and the main_item_pic source in order to create a list item with those two.
So here is my written code so far:
$('a.add_to_list').live('click', function() {
var name = $(this).closest('h6').text();
var source = $(this).closest('.main_item_pic').src;
$('<li class="hide list_entry"><span class="entry_title">'+
name+'</span><button class="remove_entry"></button>'+
'<img class="list_entry" src="'+source+'" /></li>')
.appendTo('#favs_list ul')
.show('slow');
});
Obviously this doesn't work! I've tried different solutions that I read around here like:
var name = $(this).closest('h6').html();
var source = $(this).closest('.main_item_pic').attr('src');
but oh well...no luck so far. Any ideas? Thanks in advance!
Try going back to the top and coming down again along the right DOM branch:
var src = $(this).closest('.main_page_entry') // Back to the top
.find('.main_item_desc .main_item_pic') // And down again.
.attr('src');
The closest method goes up the DOM tree through your ancestors:
Get the first ancestor element that matches the selector, beginning at the current element and progressing up through the DOM tree.
So it won't cross over to any of the sibling branches. Then, once you're at the appropriate ancestor, you use find to come back down, find is just like $() but uses the specified element rather than document as the root:
Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
The closest method only finds the closest ancestor that matches the selector you pass it. Because the h6 and img you are looking for are not ancestors of the element you are calling it on, it won't find them. What you need is to find the closest element that contains both the element you are searching from and the elements you are trying to find, and use it as an intermediate step in the search:
var name = $(this).closest('.main_page_entry').find('h6').text();
var source = $(this).closest('.main_page_entry').find('.main_item_pic').attr('src');
First off, if this content isn't added dynamically or in a live manner (in other words, if the content is loaded with the original HTML load) then you do not have to use the .live() function.
Also, why are you using .closest()? Couldn't you just do:
<img class="main_item_pic" ref='pic1' src="blah.jpg" />
<a ref='pic1' href="#" class="add_to_list">
<img src="add_icon.gif" />Add to List
</a>
$('a.add_to_list').click(function(){
var ref = $(this).attr('ref');
var src = $("img[ref='" + ref + "']").attr('src');
var name = $('h6 a').text();
});
The method closest() looks for ancestors. Your h6 and img are not ancestors of your link.
Also, I guess you don't want $('h6').html() but $('h6 a').html()