I have created a javascript web component where one element is completely replaced with a set of html elements.
To do that I use replaceWith. My problem is that I need to keep track of the new created element. How can I do that? I use vanilla js ES6, not jQuery.
let element = document.querySelector('div');
let another = document.querySelector('h2');
element.replaceWith(another);
<div>
Replace this content
</div>
<h2>Heading 1</h2>
<h2>Heading 2</h2>
<h2>Heading 3</h2>
https://jsfiddle.net/n9q0x86a/1/
I have created a javascript web component where one element is completely replaced with a set of html elements
your statement is wrong, if you want to move all the desired elements in place of <div>. In such case you need to use the querySelectorAll()MDN method. Which in turn will give you I believe exactly what you expect: a collection of all our targeted selectors:
const element = document.querySelector('#replaceMe');
const another = document.querySelectorAll('.moveMe');
element.replaceWith(...another);
console.log("Replaced #%s with %i elements", element.id, another.length);
// let's try to manipulate our stored elements:
[...another].forEach(el => el.style.color = 'red');
<div data-info="This DIV should stay">
<div id="replaceMe" data-info="this DIV should be replaced">
Replace this content
</div>
</div>
<h1 class="moveMe">Heading 1</h2>
<h2 class="moveMe">Heading 2</h2>
<p class="moveMe">Paragraph</p>
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
Related
i want to detect the parent of element that has "_" character in it
that could be achieved using jquery and css3 selcetor ":contain" like the following
$('.class a:contains("_")').parent()
but im trying to avoid using jquery too much , so is there any way to do this using native js
There is no CSS to check if it contains text. Only way you can do text matching is if that text happened to be in an attribute on the element. So you are going to have to select all the parent elements and loop over them looping at the text/children's text.
To do that you can select all the elements and use filter to check the text. If you only care there is an underscore you can just text the text content of the element.
const elemsWithUnderscore = [...document.querySelectorAll('.yourClass')].filter(el => el.textContent.includes('_'));
console.log(elemsWithUnderscore);
<div class="yourClass"><a>a</a></div>
<div class="yourClass"><a>b_</a></div>
<div class="yourClass"><a>c</a></div>
<div class="yourClass"><a>d_</a></div>
<div class="yourClass"><a>e</a></div>
If it only can be in the anchor tag and there is one you can selector the anchor tag.
const elemsWithUnderscore = [...document.querySelectorAll('.yourClass')].filter(el => [...el.querySelectorAll('a')].some(a => a.textContent.includes('_')));
console.log(elemsWithUnderscore);
<div class="yourClass">_<a>a</a></div>
<div class="yourClass"><a>b</a><a>b_</a></div>
<div class="yourClass"><a>c</a></div>
<div class="yourClass"><a>d_</a></div>
<div class="yourClass"><a>e</a></div>
If there is more than one anchor as children then you need to use some to see if one of them has an underscore.
const elemsWithUnderscore = [...document.querySelectorAll('.yourClass')].filter(el => el.querySelector('a')?.textContent.includes('_'));
console.log(elemsWithUnderscore);
<div class="yourClass">_<a>a</a></div>
<div class="yourClass"><a>b_</a></div>
<div class="yourClass"><a>c</a></div>
<div class="yourClass"><a>d_</a></div>
<div class="yourClass"><a>e</a></div>
You can use document.querySelectorAll and check the textContent of the children.
[...document.querySelectorAll('.class')].filter(el =>
[...el.querySelectorAll('a')].some(a => a.textContent.includes('_')))
.forEach(el => console.log(el.outerHTML));
<div class="class"><a>_</a></div>
<div class="class">
<div><a>abc_def</a><span>123</span></div>
</div>
<div><a>nothing to see</a></div>
I have created a div with Javascript, this displays correctly, however it is not in the place where I want, I would like to put it inside a container as the first element. I'm not very good, I'm trying to learn, so sorry for the triviality of the question.
How do I put the div I created inside an already existing container as the first element?
Beyond that I would like to understand the logic of the operation, for example, how can I move the new div as the last element? Or as a second element ?
This is the Js code
// Add New Element
var newEl = document.createElement("div");
var text = document.createTextNode("Hello");
newEl.appendChild(text);
var element = document.getElementById("main_container");
element.appendChild(newEl);
This is what I am trying to achieve
<div id="main_container" class="something">
<div class="new_element">Hello</div>
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three</div>
</div>
This is what I got for now
<div id="main_container" class="something">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three</div>
</div>
<div>Hello</div>
This should work:
element.insertBefore(newEl, element.firstChild)
const parent;
const newFirstChild;
parent.insertBefore(newFirstChild, parent.firstChild);
In your case:
element.insertBefore(newEl, element.firstChild)
If you want to insert at a different index you can do it like this:
parent.insertBefore(newEl, parent.children[2])
Codepen
I am trying to use AngularJS to grab the element by tag name.
For example,
angular.element(document.querySelector('h1')).css('color', 'green');
element in HTML:
<div>
<h1>Title 1</h1>
</div>
<div>
<h1>Title 2</h1>
</div>
It works only for the first element but not the second one. I am not sure the reason for it. Can anyone help me about it? Thanks a lot!
As #Tushar mentioned, the best way to handle this is with ng-class. Let Angular do the DOM manipulation for you
Your CSS
.someclass{
color: green
}
Your HTML
<div ng-class="{'someclass': obj.value == 'somevalue'}">
<h1>Title 1</h1>
</div>
<div>
<h1>Title 2</h1>
</div>
After 'someclass', in your controller, you can insert whatever expression makes the most sense. When your expression evaluates to true, the 'someclass' will be applied to your Div.
The querySelector() method returns the first element that matches a specified CSS selector(s) in the document.
The querySelectorAll() method returns all elements in the document that matches a specified CSS selector(s), as a static NodeList object.
Updated
The code I have come up with is:
<section id="Test">
<header>Welcome</header>
<p>This is a test</p>
<div>Nothing here</div>
</section>
var element = document.getElementById("Test");
var elements = <HTMLCollection>element.getElementsByTagName("*");
I want the collection to include <section>, <header>, <p>, and <div> the above code only has <header>, <p>, and <div>. Is there anyway I can add the <section> itself to the collection?
The problem is that I want to include the element itself into the elements collection. I know I can use outerHTML and put it in a temp container and then get all the element inside from that but i'm looking for a cleaner way.
You can use a comma-separated list with querySelectorAll, where the first item is the element itself.
This Snippet uses your HTML to retrieve section Test and its children: header, p, and div:
var elements= document.querySelectorAll('#Test, #Test *');
console.log(elements.length); //4
<section id="Test">
<header>Welcome</header>
<p>This is a test</p>
<div>Nothing here</div>
</section>
I have following HTML
Html
<aside>
<section class="links"></section>
<section class="downloads"></section>
<section class="news"></section>
<section class="contact"></section>
<aside>
I'm trying to insert </aside><aside>before section.news (effectively splitting the aside container tag in 2 aside containers with 2 sections in each)
jQuery
I use:
$("aside section.news").before("</aside><aside>");
Problem
Jquery always prints <aside></aside> instead of </aside><aside> like I want.
DOM elements are not strings, you can't add elements in that way using JavaScript, DOM elements are JavaScript objects, jQuery behind the scenes calls createElement() method of the document object which creates a DOM HTMLElement object, it doesn't add strings to the document.
Here is the "proper" way of doing it:
Create an aside element
Insert it after the existing aside element
Move desired elements inside it
var $aside1 = $("aside:first");
var $aside2 = $("<aside><\/aside>").insertAfter($aside1);
$(".news").nextAll().addBack().appendTo($aside2);
Demo here
$('</aside><aside>').insertBefore('.news');
As
<aside>
<section class="links"></section>
<section class="downloads"></section>
</aside><aside>
<section class="news"></section>
<section class="contact"></section>
<aside>
Reference about .insertBefore
$(document).ready(function(){
var one = $('aside').children().eq(0).clone().wrap('<p>').parent().html() + $('aside').children().eq(1).clone().wrap('<p>').parent().html()
var two = $('aside').children().eq(2).clone().wrap('<p>').parent().html() + $('aside').children().eq(3).clone().wrap('<p>').parent().html()
$('aside').before('<aside>'+one+'</aside');
$('aside').eq(1).html(two);
console.log(one)
console.log(two)
});