Setting an id on an element created from a template element - javascript

I have a template element that I use to create <li>-Elements on my page. I can set the textContent attributes of the inner elements of that template. However I can not set the id for the parent element inside the template.
<template id="list-item">
<li class="list-group-item">
<div class="media-body">
<strong class="list-item-text"></strong>
<p class="list-item-text"></p>
</div>
</li>
</template>
<div id="output"></div>
And this is the required js to demonstrate the issue.
var template = document.querySelector('#list-item');
var listItem = document.importNode(template.content, true);
var lines = listItem.querySelectorAll('.list-item-text');
lines[0].textContent = 'title';
lines[1].textContent = 'description';
listItem.id = 5;
document.querySelector('#output').appendChild(listItem);
Text contents will be set correctly, however the id won't be set at all (the js attribute gets created but it does not appear in the DOM.
I also created a jsfiddle for this.
How can I set the id of the newly appended element? My current approach is to avoid templates in general and use strings in order to construct the element, which makes me feel dirty.

The problem is that you are trying to handle a document-fragment (listItem) as an DOM element. Instead, you should first get/query the element from the document-fragment as follows:
var docFragment = document.importNode(template.content, true);
var listItem = docFragment.querySelector('li');
See working JSFiddle
Also, see documentation about DocumentFragment here.

You need to use listItem.querySelector() on the document-fragment and change the id then:
listItem.querySelector("li").id = 5;
var template = document.querySelector('#list-item');
var listItem = document.importNode(template.content, true);
var lines = listItem.querySelectorAll('.list-item-text');
lines[0].textContent = 'title';
lines[1].textContent = 'description';
listItem.querySelector("li").id = 5;
document.querySelector('#output').appendChild(listItem);

Related

make a DOM element's content be the one of a document fragment

I am trying to insert into a DOM element the content of a document fragment (in pure javascript). The working principle is this:
var a = document.getElementById("a"),
b = document.getElementById("b");
now i place the content of "a" into a document fragment, using a template element
var content = document.createElement("template");
content.innerHTML = a.innerHTML;
content = content.content.cloneNode(true);
now i would like to replace the content of b with the content of content. I tried with a simple b.innerHTML = content.innerHTML;, but it seems like if document fragments doesn't have innerHTML property.
Is this possible to do?
Note: i know this is totally an ineffective way to do the task of making b.innerHTML = a.innerHTML, but obviously this is just a simplification of a bigger task i am managing to do.
You need to create "clones" and by using the template content property you can then use the innerHTML of a and b into your fragments.
Example:
const a = document.getElementById("a"),
b = document.getElementById("b");
// note template will only be parsed, to render it use js...
function initTemplate() {
const container = document.getElementById("container");
const template = document.getElementById("t");
// create a first clone with the innerHTML of a...
const firstClone = template.content.cloneNode(true);
firstClone.textContent = a.innerHTML;
// create a second clone with the innerHTML of b...
const secondClone = template.content.cloneNode(true);
secondClone.textContent = b.innerHTML;
// append to the document
container.appendChild(firstClone);
container.appendChild(secondClone);
}
<p id="a">Paragraph A</p>
<p id="b">Paragraph B</p>
<button onclick="initTemplate()">Init Template</button>
<br>
<div id="container"></div>
<template id="t">
</template>
If you want to check if your browser supports the HTML template element, do something like this:
if ("content" in document.createElement("template") {
// clone the elements as above and append them to the document
}
Mozilla Docs and Mozilla Docs

How to insert multi values to data-tag

I made a jquery filter function, that filtering the results by data-tags. like this:
<div class="resultblock" data-tag="ios">
<img src="images/osx.jpg" class="itemimg">
<div class="desc">
<div class="desc_text">
lorem ipsum
</div>
</div>
i just want to insert in the data-tag another tags to filter. like this:
data-tag="ios,android,windows"
How can i do that?
I am not sure I fully understand the question you are asking, but I think you could accomplish this via JS.
In your html add a script tag and then you just write some JS to edit or add html tags. Here is an example:
<script>
var para = document.createElement("p");
var node = document.createTextNode("This is new.");
para.appendChild(node);
var element = document.getElementById("div1");
element.appendChild(para);
</script>
Now to sort the data-tag:
just add this code to your HTML file.
<div id="div1">
</div>
<script>
var tag ="ios,android,windows"; //initialize variable
var data = tag.split(","); //this makes an array of ios,andrid,windows
var i = 0;
while (i < 3){
alert(i);
var para = document.createElement("p");
var node = document.createTextNode(data[i]);
para.appendChild(node);
var element = document.getElementById("div1");
element.appendChild(para);
i++;
}
</script>
The best way doing this is to use classes. Adding classes and removing them is much easier than other attributes. The classes should not overlap with other classes used for CSS for example. Adding a prefix to them is even better. Like this:
$(".filter-ios").hide(); // hide all ios elements
$("something").addClass("filter-windows"); // add the class windows to an element
$(".filter-ios").addClass("filter-apple"): // add the apple filter class to the ios filter class elements
$("something").hasClass("filter-samsung"); // check if an element has the filter class samsung
// ...
The classes .filter-* should be used for filtering only, they must not have any CSS attached to them, if there is already classes like that, then just change the prefix filter to something else!
I've just created a little object with two methods .add and .remove. It works like classList DOM method for adding and removing classes. If you add one value twice, it's added only once, also if you remove some not existing class, any error will occure. Hope you'll find it helpful.
var el = document.getElementById('myElem');
multiValues = {
add: function(elem,val){
if(elem.constructor.toString().search('HTML')===-1) return;
if(typeof val !=='string') return;
if(!elem.attributes['data-tag']) elem.setAttribute('data-tag');
var attr = elem.attributes['data-tag'];
var parsed = attr.value.split(',');
var isExist = parsed.some(function(a){
return a === val;
});
if(!isExist) parsed.push(val);
elem.setAttribute('data-tag',parsed.join(','));
},
remove: function(elem,val){
if(elem.constructor.toString().search('HTML')===-1) return;
if(typeof val !=='string') return;
if(!elem.attributes['data-tag']) return;
var attr = elem.attributes['data-tag'];
var parsed = attr.value.split(',');
parsed.some(function(a,b){
if(a===val){
parsed.splice(b,1);
}
elem.setAttribute('data-tag',parsed.join(','));
});
}
};
multiValues.add(el,'window');
multiValues.add(el,'window');
multiValues.add(el,'window');
multiValues.add(el,'android');
multiValues.remove(el,'a');
multiValues.remove(el,'b');
multiValues.add(el,'something');
console.log(el.attributes['data-tag'].value);
<div class="resultblock" data-tag="ios" id="myElem"></div>

How can I get an element's attribute from the parent's parent element's ID using JavaScript?

So I have the following HTML...
HTML:
<div id="col1">
<img src="1.jpg">
</div>
And I am implementing a HTML5 drag and drop feature where the inner html of col1 is changed for the dragged element's inner html - so basically the columns change their content.
I have another div (let's call that swap-text) where I want to change its text content depending on what image is presently inside col1.
This is why I want to figure out how I can obtain col1's img element's src attribute value through JavaScript so I can then write an if statement to change the content of the swap-text depending on which image is in col1.
I could add ID's to the img elements but then I still don't know how I would write the condition to check if say, img-id1 parent is col1.
Attempt(s):
var doc = document.getElementById("col1");
var children = null;
var imgEle;
//gets img node, but also got 1/2 text object(s)?
for (var i = 0; i < doc.childNodes.length; i++) {
children = doc.childNodes[i];
console.log(children);
}
//document.getElementById("img")
//children[1].getAttribute('src'); - cannot call method 'getAttribute' of undefined
//imgEle = doc.childNodes[0].getElementById('img'); - Object #<Text> has no method 'getElementById'
console.log(imgEle);
console.log(children);
This work fine pure javascript:
document.getElementById("col1").getElementsByTagName("img")[0].getAttribute("src");
var doc = document.getElementById("col1");
var img = document.getElementsByTagName('img')[0];
var imgParent = img.parentElement;
This is how you determine the elements parent/
I suggest you to use JQuery so you can simply use:
$("img").attr("id"); //Return the id of the img element
Check this:
var column = document.getElementById("col1");
var imgSrc = column.getElementsByTagName("img")[0].getAttribute("src");
Or just use the jQuery - it's simpler:
$('#col1 img').attr('src');
as you will only have one child node in col1 (the img), change the for loop.
var doc = document.getElementById("col1");
var children = null;
var imgEle;
//gets img node, but also got 1/2 text object(s)?
//for (var i = 0; i < doc.childNodes.length; i++) {
// children = doc.childNodes[i];
// console.log(children);
//}
childen = doc.childNodes[0];
// or children = doc.firstChild;
console.log(children);
//document.getElementById("img")
console.log(children.getAttribute('src')); - children is single object
//imgEle = doc.childNodes[0].getElementById('img'); - Object #<Text> has no method 'getElementById'
console.log(imgEle);
console.log(children);

`getElementById` doesn’t find elements inside `<template>` tag

I want to add <li> to <ul> tag via JavaScript:
const newLI = document.createElement("LI");
const ul = document.getElementById("tag_list");
ul.appendChild(newLI);
newLI.innerHTML = "" + json + "";
<template id="box#add-feeds">
<ul class="search-ac" id="tag_list" name="tag_list"></ul>
</template>
When I remove the <template> tag, this code works well, but with this tag I have this error:
TypeError: Cannot call method 'appendChild' of null
I can’t remove the <template> tag so I have to change the JavaScript code. Any idea about why getElementById doesn’t find an element if it’s in a <template> tag?
The <template tag is not a custom tag; it's a new HTML5 feature.
The whole point of <template> tags is that they aren't actually in the document.
That includes IDs.
You can examine or manipulate the contents of the template using the content property of the <template> tag's DOM element.
Templates are there for you to CLONE them.
Given this HTML code:
<template id="add-feeds">
<ul class="search-ac" id="tag_list" name="tag_list"></ul>
</template>
if you try something like this, it will NOT work (will return null):
var ul = document.getElementById('tag_list'); // ul is *null*
THE WAY TO GO IS:
clone the template (think about it of instantiating a class).
Let me add a div to your base html:
<template id="add-feeds">
<ul class="search-ac" id="tag_list" name="tag_list"></ul>
</template>
<div id="show_list"></div> //div used as DOM-entry-point for our new created list
Now clone the template:
var template= document.querySelector("#add-feeds");
my_template_clone = template.content.cloneNode(true); // clone the template
var my_ul = my_template_clone.getElementById('tag_list'); //now you can find the *ul*
var newLI = document.createElement("LI"); //create random stuff
newLI.innerHTML="hello";
my_ul.appendChild(newLI); //append it to the ul
var div = document.getElementById('show_list');
div.appendChild(my_ul); //now add it into the DOM
Here you have a working jsfiddle

navigating the dom javascript specific tag

Here it is DOM structure:
<div id="some">
NOTHIS
NOTHIS
<h3 class="myclass">HELLO</h3>
</div>
How can I get the value of HELLO in javascript?
EDIT: Forgot, I have other anchor tags inside 'some', so I want strictly the anchor tag inside the h3's
EDIT2: Got it:
var n = document.getElementById('some').getElementsByTagName('h3')[0].getElementsByTagName('a')[0].innerHTML;
Thanks all!
var linkText = document.getElementById('some').getElementsByTagName('a')[0].innerHTML;
or if you have jQuery
var linkText = $('#some').find('a').html();
var anchor = document.getElementById('some').getElementsByTagName('a')[0],
yourText = anchor.innerText || anchor.textContent;
It's cross-browser, too. http://www.quirksmode.org/dom/w3c_html.html
Propagate down the DOM from your ID.
var s = document.getElementById('some').getElementsByTagName('h3')[0].getElementsByTagName('a')[0].innerHTML;
I would put an ID on the a myself.
var shouldEqualHello = document.getElementById('some').getElementsByTagName('h3')[0].getElementsByTagName('a')[0].innerHTML;
edit: fixed
to get to a single dom element with javascript, you need a way to uniquely identify it. the ideal approach is to give your element a unique id.
<a id="myAnchor" href="#" style="color:red;">HELLO</a>
then you can directly obtain a reference in script.
var myAnchor = document.getElementById('myAnchor');
or if you are guaranteed that your element is the only anchor element within the "some" id you can do
var someDiv = document.getElementById('some');
var anchors = someDiv.getElementsByTagName('a'); // returns a list of anchor elements
var myAnchor = anchors[0]; // get the first element in the list
but since that's not the case you'll have to pick your way down through the dom some more.
var someDiv = document.getElementById('some');
var headers = someDiv.getElementsByTagName('h3');
var myH3 = headers[0];
var anchors = myH3 .getElementsByTagName('a'); // returns a list of anchor elements
var myAnchor = anchors[0]; // get the first element in the list
from there you can see the stuff between the tags with
alert(myAnchor.innerHTML);
or
alert(myAnchor.firstChild.nodeValue);
or some other method already mentioned here.
You could simply use query selector,
let result = document.querySelector('#some h3 a').innerText;
console.log(result);

Categories

Resources