Reputation: 7563
I have an <img>
tag followed by a <span>
tag which I am saving in a variable named $contents
. However, I want to replace the <span>
tag with a a <figcaption>
before using add()
to add it to the image tag. I can't seem to get it to do that. Here's what I have so far:
First the HTML
<img src="whatever.jpg" />
<span>Copyright Stackoverflow</span>
With this Jquery code:
$elem.find("img, img + span").each(function(innerIndex) {
var $contents = $(this).add($(this).next('span'));
});
What I end up with:
<img src="whatever.jpg" /> <span>Copyright Stackoverflow</span>
What I want to happen is more like this (if it worked which it doesn't):
$elem.find("img, img + span").each(function(innerIndex) {
// first replace the span with a figcaption
var $figcaption = $(this).next('span').unwrap().wrap('<figcaption/>');
// add the new element to the img tag to make the new contents
var $contents = $(this).add($figcaption);
});
So I can end up with this instead:
<img src="whatever.jpg" /> <figcaption>Copyright Stackoverflow</figcaption>
When I output $contents
to the page, I get an empty <span>
instead of one wrapped in <figcaption>
tags. How am I supposed to do this?
UPDATE: To clarify, I need to get the finished HTML into a variable because it gets used in different places later on. So all this <img src="whatever.jpg" /><figcaption>Copyright</figcaption>
must be inside a var.
Upvotes: 1
Views: 583
Reputation: 34196
This is pretty simple really. Wrap the span inner with our new tag, then remove the span with unwrap of that new tag then create a clone of both of those (myclone
now holds your "new" elements):
$('span').wrapInner('<figcaption/>').find('figcaption').unwrap();
var myclone = $('img').add('figcaption').clone();
Same thing with one chain:
var myclonea = $('span').wrapInner('<figcaption/>').find('figcaption').unwrap().add('img').clone();
NOTE With regard to event handlers on the original wrapper that might need to be moved etc. to the new wrapper, you can reference this post if needed: jQuery find events handlers registered with an object
Upvotes: 0
Reputation: 32354
Try something similar:
$elem.find("img").each(function(innerIndex) {
var span = $(this).next('span');//gets the next span from the img
var $contents = span.text();//gets the content
span.remove();//removes the span
//adds the figcaption after the img tag
$(this).after('<figcaption>'+$contents+'</figcaption>');
});
jsfiddle: https://jsfiddle.net/t5dLcw12/
Upvotes: 1
Reputation: 253396
To turn:
<img src="whatever.jpg" />
<span>Copyright Stackoverflow</span>
Into:
<img src="whatever.jpg" />
<figcaption>Copyright Stackoverflow</figcaption>
I'd suggest:
// selecting the relevant elements,
// using the replaceWith() method to
// replace those found elements:
$('img + span').replaceWith(function(){
// returning a string comprised of the HTML tags,
// surrounding the text from the 'this' (the current
// <span> element of the jQuery collection) node:
return '<figcaption>' + this.textContent + '</figcaption>'
});
$('img + span').replaceWith(function(i, el) {
return '<figcaption>' + this.textContent + '</figcaption>'
});
span {
color: limegreen;
}
figcaption {
color: #f90;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="whatever.jpg" />
<span>Copyright Stackoverflow</span>
Or, in order to retain event-handlers on any child elements:
// a simple function bound to the click event
// on the <span> element within a parent <span>
// element:
$('span > span').click(function () {
console.log('woo');
})
// finding the relevant <span> elements:
$('img + span').replaceWith(function () {
// returning a created <figcaption> element,
// after appending the contents of the
// found <span> element(s):
return $('<figcaption>').append($(this).contents());
});
$('span > span').click(function() {
console.log('woo');
})
$('img + span').replaceWith(function() {
return $('<figcaption>').append($(this).contents());
});
span {
color: limegreen;
}
figcaption {
color: #f90;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="whatever.jpg" />
<span><span>Copyright</span> Stackoverflow</span>
Alternatively, in native JavaScript:
// creating a named function, and its arguments:
function replaceWith(original, tag) {
// tag: String, the element-type to be created,
// here we remove any '<' or '>' characters, to
// ensure that '<fieldset>' becomes 'fieldset':
tag = tag.replace(/<|>/g, '');
// creating a new element of that type:
var newEl = document.createElement(tag);
// setting the innerHTML of the created element
// that of the original element:
newEl.innerHTML = original.innerHTML;
// replacing the original child with the new element:
original.parentNode.replaceChild(newEl, original);
}
// finding the relevant elements:
var elements = document.querySelectorAll('img + span'),
// converting the collection of elements into an
// an Array:
elementArray = Array.prototype.slice.call(elements, 0);
// iterating over the Array using Array.prototype.forEach():
elementArray.forEach(function (elem) {
// calling the function, passing in the current array-element
// of the array over which we're iterating:
replaceWith(elem, '<figcaption>')
});
function replaceWith(original, tag) {
tag = tag.replace(/<|>/g, '');
var newEl = document.createElement(tag);
newEl.innerHTML = original.innerHTML;
original.parentNode.replaceChild(newEl, original);
}
var elements = document.querySelectorAll('img + span'),
elementArray = Array.prototype.slice.call(elements, 0);
elementArray.forEach(function(elem) {
replaceWith(elem, '<figcaption>')
});
span {
color: limegreen;
}
figcaption {
color: #f90;
}
<img src="whatever.jpg" />
<span>Copyright Stackoverflow</span>
Further, if you wish to retain event-handlers on child elements – using native JavaScript:
// finding the <span> elements with a <span> parent:
document
.querySelector('span > span')
// adding a simple anonymous function as the
// handler for the click event:
.addEventListener('click', function () {
// logging a simple message to the console:
console.log('woo')
});
function replaceWith(original, tag) {
tag = tag.replace(/<|>/g, '');
var newEl = document.createElement(tag);
// this is the only change, while the
// original element contains a firstChild node
// we append that child-node to the newly
// created-element:
while (original.firstChild) {
// using Node.appendChild to move the firstChild
// of the original node into the created-element:
newEl.appendChild(original.firstChild)
}
original.parentNode.replaceChild(newEl, original);
}
var elements = document.querySelectorAll('img + span'),
elementArray = Array.prototype.slice.call(elements, 0);
elementArray.forEach(function (elem) {
replaceWith(elem, '<figcaption>')
});
document.querySelector('span > span').addEventListener('click', function() {
console.log('woo')
});
function replaceWith(original, tag) {
tag = tag.replace(/<|>/g, '');
var newEl = document.createElement(tag);
while (original.firstChild) {
newEl.appendChild(original.firstChild)
}
original.parentNode.replaceChild(newEl, original);
}
var elements = document.querySelectorAll('img + span'),
elementArray = Array.prototype.slice.call(elements, 0);
elementArray.forEach(function(elem) {
replaceWith(elem, '<figcaption>')
});
span {
color: limegreen;
}
figcaption {
color: #f90;
}
<img src="whatever.jpg" />
<span><span>Copyright</span> Stackoverflow</span>
References:
Upvotes: 3
Reputation: 1763
$(function() {
//create figcaption empty
var figcaption = $('<figcaption/>');
//get span
var span = $('span:first');
//replacement behind the scenes
figcaption.html(span.html());
//replace in dom
span.replaceWith(figcaption);
//verify
alert($('body').html());
});
https://jsfiddle.net/rodrigo/Lfvotuze/
Upvotes: 2