Mass replace of elements [duplicate] - javascript

This question already has answers here:
Recursively change element type with jQuery, why it's partially working?
(2 answers)
Closed 7 years ago.
I'm trying to replace all the child elements in a certain element to DIVs.
I have the following structure:
<div id="wrapper">
<span>
<span>
<span>
<span></span>
<span></span>
</span>
</span>
</span>
</div>
I've tried replaceElements($('#wrapper')):
function replaceElements($element){
var children = $element.find("*");
var current;
for(var i=0; i<children.length; i++){
current = $(children[i]);
current.replaceWith("<div>" + current.html() + "</div>");
}
}
However this doesn't work because when it tries to change the N+1 element it all ready doesn't exist because it was replaced when doing the Nth element. N+1 is a descendant of N and thus is being changed when changing the .html() of N. Preserving element attributes is not an issue here.
How can I change all the child SPANs into DIVs, please?

You should not use the html content in the replaced element, instead need to add the dom elements to it
function replaceElements($element) {
$element.find("*").replaceWith(function() {
return $('<div></div>', {
html: this.childNodes
});
})
}
replaceElements($('#wrapper'))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="wrapper">
<span>1
<span>2
<span>3
<span>4</span>
<span>5</span>
</span>
</span>
</span>
</div>
Note: No attributes of the elements will be copied

Related

How to get HTML elements by their inner text using queryselectors?

I need to get all the HTML divs that contains many HTML elements which has the innerText = ' * ' and store it in an array, How can I achieve that using typescript?. If I find a span containing the innerText= ' * ', I need to put the div inside an array. Here, in my code, there are 2 divs contains span elements with innerText= ' * ' and I need to put only that 2 divs inside an array. I don't need the 3rd div in the array, because it does not contains any HTML elements with innerText="*".
<div class="div">
<label>
<span> Subject </span>
<span> * </span>
</label>
</div>
<br>
<div class="div">
<label> Yes/No </label>
<span> * </span>
</div>
<br>
<div class="div">
<label> Email Id </label>
<span> hello </span>
</div>
There is currently no standard API to get elements by their content, so you would have to loop over them manually:
const myElements = Array.from(document.querySelectorAll('*'))
.filter(() => this.children.length === 0 && this.textContent === ' * ');
The '*' passed here to querySelectorAll is not related to the text you are looking for, it's just the universal selector to select all elements on the page. As this might be expensive, you'd better use some other selector to limit the scope.

Remove spans from html with a class but keep the text [duplicate]

This question already has answers here:
Remove a HTML tag but keep the innerHtml
(7 answers)
Closed 4 years ago.
If I had the following html:
<div id="main">
This <span class="class-two">is</span> a <span class="class-one">string</span> and I want <span class="class-one">to remove</span> spans <span>with the</span> class class-one.
</div>
How would I remove all spans that have the class class-one?
The expected output from the above html would be:
<div id="main">
This <span class="class-two">is</span> a string and I want to remove spans <span>with a</span> class
</div>
The class-two and the span without a class haven't been removed.
I also need to save the new html string into a variable which is the part I am struggling with.
Something like this:
var html = $('#main').$('.class-one').replaceWith((i, txt) => txt);
Select #main, and find .class-one. Use .replaceWith() with a function to replace with the text. Then use .end() to return to .main and get the .html():
const result = $('#main')
.find('.class-one')
.replaceWith((i, txt) => txt)
.end()
.html();
console.log(result);
.class-one {
color: red;
}
.class-two {
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
This <span class="class-two">is</span> a <span class="class-one">string</span> and I want <span class="class-one">to remove</span> spans <span>with the</span> class class-one.
</div>

Only fire one onmouseover when hovering over multiple elements

I'd like to have basic code like the following:
<span onmouseover="alert('hi')">Hello, <span onmouseover="alert('hello')">this</span> is a test</span>
However, I'd like to keep it from firing both of these events if both are being hovered over; e.g. if I hover over "this" it should fire only its event and alert "hello." How can I do this?
Thank you in advance!
$(".container").hover(function(){
alert($(this).attr("id"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="container" id="hi">
Hello,
</span>
<span class="container" id="hello">
this
</span>
<span class="container" id="hi">
is a test
</span>
I am going to assume that the overlapping elements are not the same size. I.e one is bigger than the other.
HTML and inline js:
<span class="container" id="hi">
Hello,
</span>
<span class="container " id="hello">
this </span>
<script>
var hello =
document.getElementById("hello");
var this =
document.getElementById
("this");
hello.addEventListener("click
",pop("hello"));
this.addEventListener("click",pop(" hi");
function pop(string) {
window.alert(string);
}
<\script>
That being said very little is mentioned about the nature of the elements this and hello. Op plz show your CSS and update ques
Here's the relevant portion of what I ended up using. I used JQuery.
var mouseHovered = function(element) {
//get all hovered spans
var hoveredElements = $("span:hover");
//get the element with the smallest text
var smallestElement;
for(var i=0; i<hoveredElements.length; i++) if(!smallestElement || hoveredElements[i].textContent.length < smallestElement.textContent.length) smallestElement = hoveredElements[i];
//if this is the smallest text in the elements
if(element == smallestElement) {
//log the text
console.log(element.textContent);
}
}
You need to prevent Event bubbling when you hover/click on inner span.
This can be done using event.stopPropagation().
Look at two solutions provided at this JSFiddle.
Solution 1 - Use of e.stopPropagation() in the handler function innerSpan().
Solution 2 - Use of event.stopPropagation() in inline onclick event.
<span onclick="alert('Outer span');">
Outer
<span onclick="event.stopPropagation(); alert('Inner span');">
Inner
</span>
</span>

Get the selector string from DOM element with native Javascript [duplicate]

This question already has answers here:
How to generate unique css selector for DOM element?
(7 answers)
Closed 6 years ago.
Usually, we use querySelectorAll('html:eq(0) > body:eq(0) > div.row:eq(0) > div.span4:eq(2) > p.p3:eq(2)') to get the DOM ELEMENT.
If I want to use the ELEMENT <p class="p3">target</p> with native javascript to get the selector string, what should I do?
For example:
<div class="row">
<div class="span4">
<p class="p1">p1_1<p>
<br>
<p class="p1">p1_2<p>
<p class="p1">p1_3<p>
</div>
<br>
<div class="span4">
<p class="p2">p2_1<p>
<p class="p2">p2_2<p>
<br>
<p class="p2">p2_3<p>
</div>
<p>stranger</p>
<div class="span4">
<p class="p3">p3_1<p>
<br>
<p class="p3">p3_2<p>
<br>
<p class="p3">target<p>
</div>
<div>
<div class="row">
<div class="span3">
<p class="p3">p1<p>
<br>
<p class="p3">p2<p>
<p class="p3">p3<p>
</div>
<div>
<br>
<div class="row">
<p>stranger</p>
<div>
Thses are what I think:
Taking advantage of those attributes of the element <p class="p3">target</p>, I found these are useful:
attributes
nextElementSibling
previousElementSibling
parentElement
Attribute => attributes: I can use it generate the string like div.className#idName, this is not hard to do.
Attribute => nextElementSibling, previousElementSibling: I can use it generate the string like :eq(0).
What I met as a problem is the Step3, because if there are BR between two DIV, then this two ElementSibling will return BR, it means the BR is treated as a brother of this two div who has the same class, but that is not i want.
So I tried to consider use Step3.1:
3.1. Attribute => parentElement: Use element's parent to get the eq, who it is ? 0, 1, 2.....
But I find i cannot specify targeting element is which one, because he has so many same brothers have the same tagName, and className....
I would like to know if you guys have any good ideas?
If you are trying to find the element based on the html, in this case "target", you can do this:
var elms = document.querySelectorAll('p');
var targetElm;
for (var i = 0; i < elms.length; i++) {
if (elms[i].innerHTML === 'target') {
targetElm = elms[i];
}
}

Get div children ids [duplicate]

This question already has answers here:
JavaScript next sibling?
(2 answers)
Closed 9 years ago.
I have a div which contains other divs like this:
<div id="main_div">
<div id="div_1">
<div id="some_id"></div>
</div>
<div id="div_2">
<div id="some_id"></div>
</div>
<div id="div_3">
<div id="some_id"></div>
</div>
</div>
How can programatically get the next div id when a particular div is clicked?
div_1 is clicked -> alert div_2
div_2 is clicked -> alert div_3
Thanks
If you can use jQuery, you should do it like this.
Using the next function
$("#main_div > div").on("click", function(){
alert($(this).next("div").attr("id"));
});
You coud use Node.nextSibling
Returns the node immediately following the specified one in its parent's childNodes list, or null if the specified node is the last node in that list.
var div = document.getElementById('main_div');
for (var i=0, len=div.children.length; i<len; i++) {
div.children[i].addEventListener('click', function(e) {
var nextSib = e.target.nextSibling;
if (nextSib) alert(nextSib.id);
}, false);
}

Categories