I have the below HTML structure.
<div class="SomeClassName">
<a href="https://abc.xyz">
<span>
<img id="SomeImgID1" />
</span>
</a>
<a href="https://xyz.abc">
<span>
<img id="SomeImgID2" />
</span>
</a>
</div>
I want to append <div> tag before each <img> tag, how do I do it with pure javascript?
Something like
let divElement=document.querySelection('div.someClass');
Array.from(divElement.querySelectionAll('img'))
.forEach(el=>divElement.insertBefore(document.createElement('div'),el));
Again, if you want to wrap img then you can use next snippet:
let divElement=document.querySelection('div.someClass');
Array.from(divElement.querySelectionAll('img'))
.forEach(el=>{
let div=document.createElement('div');
divElement.insertBefore(div,el));
div.appendChild(el);
});
For more information see Element.insertBefore on MDN
iaMsUPerNOva finally i got you and i am here with solution .
<a class="image" href="https://abc.xyz"> <!--note this-->
$(function() {
var node = $("a.image"); // This will copy your a tag so that img tag will also get copied.
$(".SomeClassName").append('<div>hello</div>');//This will create a new div containing hello text
$("a.image").remove(); // This will remove a tag which is already copied to node.
$("SomeClassName").append(node); //Finally we are going to add newly created div to SomeClassName.
});
Okay, so what we want to do here involves two steps:
Find each IMG element inside your DIV with class SomeClassName.
For each of these IMG elements, create a new DIV and insert it before the element.
Here is how you do that.
/* document.querySelectorAll returns a NodeList.
The spread operator "..." converts it into an array,
so that we can call the forEach method on it. */
[...document.querySelectorAll("div.SomeClassName img")].forEach(x => {
// Here we create the new DIV
let div = document.createElement("div");
// Just some sample text to show
div.textContent = "Hello!";
// x.parentNode finds the parent of the IMG element.
// The frst parameter of node.InsertBefore is the
// element we want to insert as its child, and the
// the second parameter is the reference element
// before which this new element will be inserted
x.parentNode.insertBefore(div, x);
});
Thank you, everyone, for your responses. I forgot to mention before that I had another parent <div> and the final structure was like this.
<div class="ParentClassName">
<div class="ChildClassName">Some Content</div>
<div class="ChildClassName">Some Content2</div>
<div class="ChildClassName">
<a href="https://abc.xyz">
<span>
<img id="SomeImgID1" />
</span>
</a>
<a href="https://xyz.abc">
<span>
<img id="SomeImgID2" />
</span>
</a>
</div>
</div>
I could able to wrap all <img> tags inside <div> by doing the below step.
Note: If your classname is dynamic you can remove it from the query selectors and you can put only the selector element like document.querySelector("div");
let divElement = document.querySelector("div.ParentClassName");
Array.from(divElement.querySelectorAll("div.ChildClassName img")).forEach(
(el) => {
let div = document.createElement("div");
el.parentElement.insertBefore(div, el);
div.appendChild(el);
}
);
and my final output was
<div class="ParentClassName">
<div class="ChildClassName">Some Content</div>
<div class="ChildClassName">Some Content2</div>
<div class="ChildClassName">
<a href="https://abc.xyz">
<span>
<div>
<img id="SomeImgID1" />
</div>
</span>
</a>
<a href="https://xyz.abc">
<span>
<div>
<img id="SomeImgID2" />
</div>
</span>
</a>
</div>
</div>
Related
I have a tool that is used for cleaning up crappy HTML in order to make sense of the underlying structure. Having stripped class, style attributes and various Angular attributes, often the resulting markup is a series of nested <div> or <span> elements that have no attributes. What I would like to do is provide option to do a second pass where a <div> or <span> with no attributes can be removed, to flatten the structure more.
Is there a way in JavaScript to confirm that an HTML element has no attributes of any kind?
And if that is possible, how might I approach this stripping of an element?
For example, assuming I have this:
<div>
<div>
<div id="blah">
<div>
<div>
<span dir="auto">
<span>Joe Bloggs</span>
</span>
</div>
</div>
</div>
</div>
</div>
That should end up as:
<div id="blah">
<span dir="auto">
Joe Bloggs
</span>
</div>
Which I would then format to:
<div id="blah">
<span dir="auto">
Joe Bloggs
</span>
</div>
So I'd need a function that can walk the DOM and remove a div (or span) that has no attributes while leaving the inner contents intact (unless of course any of those inner elements can also be stripped for same reason).
Any pointers before I go ahead and construct a shoddy (but working) script would be appreciated!
The attributes property will tell you how many attributes an element has.
const countAttributes = element => console.log({
count: element.attributes.length,
list: [...element.attributes].map(attribute => attribute.name)
});
const divs = document.querySelectorAll('div');
divs.forEach(countAttributes);
<div></div>
<div class="one attribute"></div>
<div class="two attributes" id="second attribute"></div>
Do note that an element without attributes might still be used for something (e.g. a stylesheet might reference it in relation to other elements).
Here's how I did it.
I created a demo element, to get the elements, then I checked the number of elements, I checked if the element should be stripped.
I replaced the element with its children, and if it didn't have any, I used its text
function strip(startElement, toStrip) {
const test = document.createElement('div');
test.innerHTML = startElement.outerHTML;
[...test.querySelectorAll('*')].forEach(elem => {
if (!elem.attributes.length && toStrip.includes(elem.tagName.toLowerCase())) {
if (elem.children.length) elem.replaceWith(...elem.children);
else elem.replaceWith(elem.innerText);
} ;
});
return test.innerHTML;
}
console.log(strip(document.querySelector('div'), ['span', 'div']));
<div>
<div>
<div id="blah">
<div>
<div>
<span dir="auto">
<span>Joe Bloggs</span>
</span>
</div>
</div>
</div>
</div>
</div>
Updated Code
Here you go.
document.querySelectorAll("div").forEach((ele) => {
if (ele.attributes.length === 0) {
var fragment = document.createDocumentFragment();
while (ele.firstChild) {
fragment.appendChild(ele.firstChild);
}
ele.parentNode.replaceChild(fragment, ele);
}
});
<div>
<div>
<div id="blah">
<div>
<div>
<span dir="auto">
<span>Joe Bloggs</span>
</span>
</div>
</div>
</div>
</div>
</div>
So final output would be
<div id="blah">
<span dir="auto">
<span>Joe Bloggs</span>
</span>
</div>
I need a dynamic jquery or javascript code, which hides all <div> elements, if the data-event-id="" is a repeating one on the <a> element, so there are no multiple elements with the same attribute, only the first one.
The parents should be invisible like result of CSS display:none; but they can also be "deleted" on the code, doesn't really matter.
since my knowledge is limited on css and html, i'm completely lost.
<div>
<a data-event-id="87" href="https://google.com">1</a>
</div>
<div>
<a data-event-id="48" href="https://google.com">2</a>
</div>
<div>
<a data-event-id="87" href="https://google.com">3</a>
</div>
<div>
<a data-event-id="20" href="https://google.com">4</a>
</div>
<div>
<a data-event-id="48" href="https://google.com">5</a>
</div>
On this example, it should only show following links:
1
2
4
Does anyone know how to do this?
With jQuery you can query for all a-elements and iterate over them. You can keep track of known event-ids with an array where you add newly discovered event-ids. If the id is already in that array, simply hide the parent-element.
let events = [];
$('a').each(function(){
let event_id = $(this).attr('data-event-id');
if (!events.includes(event_id)) {
events.push(event_id);
} else {
$(this).parent().hide();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<a data-event-id="87" href="https://google.com">1</a>
</div>
<div>
<a data-event-id="48" href="https://google.com">2</a>
</div>
<div>
<a data-event-id="87" href="https://google.com">3</a>
</div>
<div>
<a data-event-id="20" href="https://google.com">4</a>
</div>
<div>
<a data-event-id="48" href="https://google.com">5</a>
</div>
That's quite simple: you can iterate through your element collection, and check if its dataset.eventId is present in a unique set—this can be done by leveraging on ES6's Set(), which stores unique values (so it kind of serves as a dictionary). For each iteration, you:
check if the eventId is in the set. If it is, remove the node
store the eventId into your unique set for future comparison.
const elements = Array.from(document.querySelectorAll('a'));
const eventIds = new Set();
elements.forEach(element => {
const eventId = element.dataset.eventId;
if (eventIds.has(eventId)) {
element.parentNode.remove();
}
eventIds.add(element.dataset.eventId);
});
<div>
<a data-event-id="87" href="https://google.com">1</a>
</div>
<div>
<a data-event-id="48" href="https://google.com">2</a>
</div>
<div>
<a data-event-id="87" href="https://google.com">3</a>
</div>
<div>
<a data-event-id="20" href="https://google.com">4</a>
</div>
<div>
<a data-event-id="48" href="https://google.com">5</a>
</div>
You can also use :not(:first)").remove();
var i;
for (i = 0; i < 10; i++) {
$("[data-event-id$='" + i + "']:not(:first)").remove();
}
See fiddle
I want to run a function anytime one of a series of elements are clicked and want to target these elements using a partial ID. Currently, only the first element responds when clicked upon. What have I done wrong? My code:
HTML:
<div>
<a id="selector-0">Zero</a>
</div>
<div>
<a id="selector-1">One</a>
</div>
<div>
<a id="selector-2">Two</a>
</div>
JS:
document.querySelector('[id^="selector-"]').onclick = function(){
var id_selector = this.getAttribute('id');
alert('ID: ' + id_selector);
}
I have attempted changing the querySelector to include 'a[id^="selector-"]', but only the first element ever wants to respond on click.
Use *= selector with id as attribute and document.querySelectorAll.
Then add the onclick to all the elements of the given array of retrieved elements.
const els = Array.from(document.querySelectorAll('[id*=selector-]'));
console.log(els.length);
els.forEach(el => el.onclick = () => console.log('Clicked el:', el));
<div>
<a id="selector-0">Zero</a>
</div>
<div>
<a id="selector-1">One</a>
</div>
<div>
<a id="selector-2">Two</a>
</div>
I have several pictures in the same class, and when the class is clicked I get the ID of the picture using this.id. I want to take that ID and use it to move the picture that has been clicked. I am trying to append it to the span with the ID "yours."
$(".characters img").on("click",function(){
console.log(this.id);
$(this.id).prependTo("#yours");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class= "characters">
<img src="assets/images/luke.jpg" id="luke">
<img src="assets/images/rey.jpg" id="rey">
<img src="assets/images/kylo.jpg" id="kylo">
<img src="assets/images/snoke.jpg"id="snoke">
</div>
<div class = "text">
<h1> Your Character </h1>
<span id="yours"> </span>
<h1>Enemies Available to Attack</h1>
<span id="enemies"></span>
<h1> Defender</h1>
<span id="defender"></span>
</div>
Instantiate a new jQuery object with the image (this), and not this.id:
Change:
$(this.id).prependTo("#yours");
To:
$(this).prependTo("#yours");
While clicking on an img, target #yours element, empty it ( if desired ), then clone the clicked img and pass it to the html method since it accepts a jQuery object.
$(".characters img").on("click",function(){
// Empty "yours" and add the cloned clicked image
$("#yours").empty().html($(this).clone());
});
What I want is to call the showPopup('text goes here'); function and the below block of code to be shown with my text in it.
How can I achieve this?
function showPopup(data) {
}
<a class="fragment" href="#">
<span id='close' onclick='this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); return false;'>x</span>
<div class="content">
// I WANT TO PUT MY TEXT HERE
</div>
</a>
JSFiddle example: http://jsfiddle.net/tb5musm6/
function showPopup(data) {
var elem = document.getElementsByClassName('content');
elem[0].innerHTML = data;
}
showPopup('asdf');
document.getElementsByClassName will return an array of elements with the given classname
innerHTML variable holds all content between tags
Add an id to you div so you can find it easier.
Then, use innerHTML to modify the content of the div.
<a class="fragment" href="#">
<span id='close' onclick='this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); return false;'>x</span>
<div class="content" id="content">
// I WANT TO PUT MY TEXT HERE
</div>
</a>
<script>
function showPopup(data) {
document.getElementById('content').innerHTML(data);
}
showPopup('my text');
</script>