This question already has answers here:
Can I change an HTML element's type?
(9 answers)
Closed 4 years ago.
I want to know how can I change a tag with pure javascript like that
<span>some text</span>
I want to change it to that
<div>some text</div>
I have no idea how to do it.
You can't change the type of an element like that, instead you have to create a new element and move the contents into it. Example:
var e = document.getElementsByTagName('span')[0];
var d = document.createElement('div');
d.innerHTML = e.innerHTML;
e.parentNode.replaceChild(d, e);
Demo: http://jsfiddle.net/Guffa/bhnWR/
Just written a jQuery plugin for this.
(function( $ ) {
$.fn.replaceTag = function(newTag) {
var originalElement = this[0]
, originalTag = originalElement.tagName
, startRX = new RegExp('^<'+originalTag, 'i')
, endRX = new RegExp(originalTag+'>$', 'i')
, startSubst = '<'+newTag
, endSubst = newTag+'>'
, newHTML = originalElement.outerHTML
.replace(startRX, startSubst)
.replace(endRX, endSubst);
this.replaceWith(newHTML);
};
})(jQuery);
Usage:
$('div#toChange').replaceTag('span')
The biggest advantage of this method is that id preserves all the attributes of the original element.
If jquery is acceptable use replaceWith.
$('span').each(function() {
$(this).replaceWith($('<div>' + this.innerHTML + '</div>'));
});
Here is a JSFIDDLE working DEMO
If using jquery
Var spantxt = $('span').text();
$('body').append('<div>'+spantext+'</div');
Note this would only work if there was only one span, use an id selector otherwise
You can't do it.
What you want to do is to take content of your span,
then delete it and create new div and fill it with previous content.
Assumption: The span you want to replace is wrapped in a div with id "foo"
In pure javascript you could do something like:
var original_html = document.getElementById('foo').innerHTML;
original_html = original_html.replace("<span>", "<div>");
original_html = original_html.replace(new RegExp("</span>"+$), "</div">)
document.getElementById('foo').innerHTML=original_html;
If however you can not necessarily expect the span to be tightly wrapped by an element you can consistently get (by id or otherwise), the javascript becomes fairly complex. In either case, the real answer here is: use jQuery.
Related
I need to pass (using javascript) text inside span to href
<div class='tableCell'><span>information</span></div>
<div class='tableCell'><span>contact</span></div>
<div class='tableCell'><span>about</span></div>
for example when i click to about link must be example.com/tag/about/
Here is my Answer. I'm using Javascript to manipulate the DOM to add a new element with the href equal to the inner text within the span element.
I hope you find this answer helpful.
Thanks.
var spans = document.getElementsByTagName('span')
var baseUrl = 'http://example.com/tag/'
for(var i=0; i<spans.length; i++)
{
var curElement = spans[i];
var parent = curElement.parentElement;
var newAElement = document.createElement('a');
var path = baseUrl+curElement.innerHTML;
newAElement.setAttribute('href', path);
newAElement.appendChild(curElement);
parent.appendChild(newAElement)
}
DEMO
The simplest way:
$( "span" ).click(function() {
var link = 'http://yousite.com/tag/'+ $(this).text().replace(/ /, "-")+"/";
window.location.href= link.toLowerCase();
});
DEMO
http://codepen.io/tuga/pen/yNyYPM
$(".tableCell span").click(function() {
var link = $(this).text(), // will provide "about"
href = "http://example.com/tag/"+link; // append to source url
window.location.href=href; // navigate to the page
});
You can try the above code
You do not have links but span in your html. However, you can get build the href you want and assign it to an existing link:
$('div.tableCell').click(function(){
var href = 'example.com/tag/' + $(this).find('span').text();
})
Lets work with pure javascript, I know you want to use jQuery but I am really sure too many people can't do this without looking in to web with pure javascript. So here is a good way.
You can follow it from jsFiddle
var objectList = document.getElementsByClassName("tableCell");
for(var x = 0; x < objectList.length; x++){
objectList[x].addEventListener('click', function(){
top.location.href = "example.com/tag/" + this.childNodes[0].innerHTML;
});
}
Lets work on the code,
var objectList = document.getElementsByClassName("tableCell");
now we have all element with the class tableCell. This is better than $(".tableCell") in too many cases.
Now objectList[x].addEventListener('click', function(){}); using this method we added events to each object.
top.location.href = "example.com/tag/" + this.childNodes[0].innerHTML; with this line if somebody clicks to our element with class: We will change the link to his first child node's text.
I hope it is useful, try to work with pure js if you want to improve your self.
Your Method
If you always are going to have the url start with something you can do something like this. The way it is set up is...
prefix + THE SPANS TEXT + suffix
spaces in THE SPANS TEXT will be converted to -
var prefix = 'http://example.com/tag/',
suffix = '/';
$('span').click(function () {
window.location.href = prefix + $(this).text().replace(' ', '-').trim().toLowerCase() + suffix;
//An example is: "http://example.com/tag/about-us/"
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='tableCell'><span>Information</span></div>
<div class='tableCell'><span>Contact</span></div>
<div class='tableCell'><span>About</span></div>
You can adjust this easily so if you want it to end in .html instead of /, you can change the suffix. This method will also allow you to make the spans have capitalized words and spaces.
JSBIN
I have a string where I want to remove all figure tags. I have tried the following:
var s = '<html><body>report content<figure id="fig2" data-contenttype="chart"><img src="chart.jpg"/><div>chart 1</div></figure><div>body content</div><figure id="fig2"><img src="chart2.jpg"/><div>chart 2</div></figure></body></html>';
var result = $(s).find('figure').remove();
The reason this does not work is that find does not find the figure elements because they have children. Does anyone know how I can remove all figure nodes (and everything inside them) and leave the rest of the html in tact?
Note the html is not in the DOM I need to do this via string manipulation. I don't want to touch the DOM.
You can wrap your string in a jQuery object and do some sort of a manipulation like this:
var removeElements = function(text, selector) {
var wrapped = $("<div>" + text + "</div>");
wrapped.find(selector).remove();
return wrapped.html();
}
USAGE
var removedString = removeElements('<html><body>report content<figure id="fig2" data-contenttype="chart"><img src="chart.jpg"/><div>chart 1</div></figure><div>body content</div><figure id="fig2"><img src="chart2.jpg"/><div>chart 2</div></figure></body></html>','figure');
The beauty of this approach is that you can specify a jquery selector which to remove.
Another approach for keeping html and body tag:
var s = '<html><body>report content<figure id="fig2" data-contenttype="chart"><img src="chart.jpg"/><div>chart 1</div></figure><div>body content</div><figure id="fig2"><img src="chart2.jpg"/><div>chart 2</div></figure></body></html>';
var $s = s.replace(/<figure>(.*)<\/figure>/g, "");
console.log($s)
How to surround element with div tag in dojo?
<button>Testing</button>
:
<div>
<button>Testing</button>
</div>
<div>Testing <span>something</span></div>
:
<div>
<div>Testing <span>something</span></div>
</div>
Finally I found answer
Surrounding
var node = domConstruct.create("div");
dojo.addClass(node,"container");
var refNode = dom.byId("refNode");
var tagName = refNode.tagName.toLowerCase();
node.innerHTML="<"+tagName+">"+refNode.innerHTML+"</"+tagName+">";
domConstruct.place(node, refNode,"before");
domConstruct.destroy(refNode);
Its pretty simple
require(["dojo/dom-construct"], function(domConstruct){
var n = domConstruct.create("div", { innerHTML: "Testing <span>something</span>" });
});
read all about it here
How about this :
var refNode = dom.byId("refNode");
// make the new div, with the correct class, directly after the node to be wrapped
var node = domConstruct.create("div", {"class":"container"}, refNode, "after");
// move the refNode inside our wrapping node
domContruct.place(refNode, node);
A quick and dirty approach looks like this:
element.outerHTML = '<div>' + element.outerHTML + '</div>';
No need for any libraries. Note, this will create a new object under the hood, so you have to retrieve element again to get the surrounding element, in case you need it afterwards.
Overall, it's handy, because you do not have to remove the old element and insert the new one.
I also came up with a similar approach to replace the tag name and preserve attributes, which might be interesting for one or another.
I don't know how it was in 2013, but these days, dojo's NodeList-manipulate functionality allows you to do it quite easily.
Given:
<b>one</b>
<b>two</b>
Use:
require(["dojo/query", "dojo/NodeList-manipulate"], function(query){
query("b").wrap("<div><span></span></div>");
});
Output:
<div><span><b>one</b></span></div>
<div><span><b>two</b></span></div>
This example is take from the documentation here.
I would like to retrieve a certain tag element with its attributes from the DOM. For example, from
<a href="#" class="class">
link text
</a>
I want to get , optionally with a closing , either as a string or some other object.
In my opinion, this would be similar to retrieving the .outerHTML without the .innerHTML.
Finally, I need this to wrap some other elements via jQuery. I tried
var elem = $('#some-element').get(0);
$('#some-other-element').wrap(elem);
but .get() returns the DOM element including its content. Also
var elem = $('#some-element').get(0);
$('#some-other-element').wrap(elem.tagName).parent().attr(elem.attributes);
fails as elem.attributes returns a NamedNodeMap which does not work with jQuery's attr() and I was not able to convert it.
Admitted that the above examples are not very senseful as they copy also the element's no-longer-unique ID. But is there any easy way? Thanks alot.
There is a way to do this without jQuery.
This also works with <br> tags, <meta> tags, and other empty tags:
tag = elem.innerHTML ? elem.outerHTML.slice(0,elem.outerHTML.indexOf(elem.innerHTML)) : elem.outerHTML;
Because innerHTML would be empty in self-closing tags, and indexOf('') always returns 0, the above modification checks for the presence of innerHTML first.
var wrapper = $('.class').clone().attr('id','').empty();
You might want to change the selector to more exactly match the <a> element you're looking for.
clone() creates a new copy of the matched element(s), optionally copying event handlers too.
I used attr to clear the element's ID so that we don't duplicate IDs.
empty() removes all child nodes (the 'innerHTML').
Here is my solution:
opentag=elem.outerHTML.slice(0, elem.outerHTML.length-elem.innerHTML.length-elem.tagName.length-3);
I suppose, that close tag is of the form: "</"+elem.tagName+">".
Unfortunately, #AaronGillion's answer isn't reliable as I said in my comment. Thank #sus. I recommend his/her way with a little change to support <self-closing tags />:
function getOpenTag(element: HTMLElement): string {
const outerHtml = element.outerHTML;
const len = outerHtml.length;
const openTagLength = outerHtml[len - 2] === '/' ? // Is self-closing tag?
len :
len - element.innerHTML.length - (element.tagName.length + 3);
// As #sus said, (element.tagName.length + 3) is the length of closing tag. It's always `</${tagName}>`. Correct?
return outerHtml.slice(0, openTagLength);
}
The code is in TypeScript. Remove types (HTMLElement and number) if you want JavaScript.
If someone is not using jQuery . . .
elem.outerHTML
"<a href="#" class="class">
link text
</a>"
elem.cloneNode().outerHTML
""
If you want to be safe for Firefox etc. released before mid-2014, use cloneNode(false) to avoid getting inner stuff.
Reference: https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode
Here's a solution I've used:
const wrap = document.createElement('div')
wrap.appendChild(target.cloneNode(true))
const openingTag = wrap.innerHTML.split('>')[0] + '>'
This can be done without any String manipulation.
Instead, you can use the element's internals and build the string yourself from there:
function getTagHTML(el) {
if (!el instanceof HTMLElement) return null;
let result = `<${el.tagName.toLowerCase()}`;
for (const attribute in el.attributes) {
if (el.attributes[attribute].nodeValue)
result += ` ${el.attributes[attribute].name}="${el.attributes[attribute].nodeValue.replace(/"/g, """)}"`
}
result += `></${el.tagName.toLowerCase()}>`;
return result;
}
console.log(getTagHTML(document.getElementById('outer')));
<div id="outer" class='i-want-"this"'>
<span>I do not want this</span>
</div>
Please note that for self-closing elements like <img /> this would give you an unwanted and incorrect closing tag. Feel free to adjust the code accordingly.
+1 for cloneNode answer above
create HTML without content
Looping over attributes
optional end tag
optional self-closing tag
function getTagHTML(el, includeClosingTag=true , selfClosing = false) {
//return el.cloneNode(false).outerHTML;
if (el.attributes)
return `<${el.localName}` +
[...el.attributes].map(
attr => ` ${attr.name}="${attr.nodeValue.replace(/"/g, """)}"`
).join`` +
`${selfClosing ? "/" : ""}>` +
(!selfClosing && includeClosingTag ? `</${el.localName}>` : "");
else
return null;
}
document.body.querySelectorAll("*:not(script)").forEach(el=>{
console.log(getTagHTML(el));
console.log(getTagHTML(el,false));
console.log(getTagHTML(el,false,true))
});
<div id="ONE" class='CLASSNAMES' attr1='"string"'>
INNERHTML
</div>
<img id="TWO" src="https://svgshare.com/i/Uhq.svg"/>
My solution using Reg Exp to replace all possible closing tags inside element attributes:
const outerHTML = div.outerHTML;
const content = outerHTML.slice(0, outerHTML.length - div.innerHTML.length);
const dummy = content.replace(/'.*?'|".*?"/g, x => 'x'.repeat(x.length));
return content.slice(0, 1 + dummy.indexOf('>'));
How can I replace a specific text with HTML objects?
example:
var text = "some text to replace here.... text text text";
var element = $('<img src="image">').event().something...
function ReplaceWithObject(textSource, textToReplace, objectToReplace);
So I want to get this:
"some text to replace < img src...etc >.... text text text"
And I would like manipulate the object element without call again $() method.
UPDATE:
I solved.
thanx #kasdega, i made a new script based in your script, because in your script i can't modify the "element" after replace.
This is the script:
$(document).ready(function() {
var text = "some text to replace here.... text text text";
var element = $('<img />');
text = text.split('here');
$('.result').append(text[0],element,text[1]);
$(element).attr('src','http://bit.ly/mtUXZZ');
$(element).width(100);
});
I didnt know that append method accept multiples elements.
That is the idea, only need to automate for multiple replacements
thanx to all, and here the jsfiddle
do a split on the text you want to replace then use the array indexes 0 and 1...something like:
function ReplaceWithObject(textSource, textToReplace, objectToReplace) {
var strings = textSource.split(textToReplace);
if(strings.length >= 2) {
return strings[0] + objectToReplace.outerHTML() + strings[1];
}
return "";
}
UPDATE: I found another SO post Get selected element's outer HTML that pointed me to a tiny jquery plugin that helps here.
I believe this jsfiddle has what you want. outerHTML is the tiny jquery plugin I included in the JSFiddle.
You can also use replace which will reduce some code: http://jsfiddle.net/kasdega/MxRma/1/
function ReplaceWithObject(textSource, textToReplace, objectToReplace) {
return textSource.replace(textToReplace, objectToReplace.outerHTML());
}
function textToObj (text,obj,$src){
var className = "placeholder-"+text;
$src.html($src.html().replace(text,"<div class='"+className+"'></div>"));
$("."+className).replace(obj);
}
you can use $(selector).outerHtml to get the html string of an element
You can replace the html directly: http://jsfiddle.net/rkw79/qNFKF/
$(selector).html(function(i,o) {
return o.replace('old_html','new_html');
})