What would be the shortest way to do the following :
var div = document.createElement('div');
div.className = 'divClass';
div.innerHTML = 'Div Content';
... without any external libraries
class Div {
constructor(className, innerHTML) {
let div = document.createElement("div");
div.className = className;
div.innerHTML = innerHTML;
return div;
}
}
let innerHTML = "LOL"
new Div(divClass, innerHTML);
This would be the shortest way to doing it again and again while still having some order inside your code, IMO.
Write a function to do it in one line:
function tag(tagNameAndClass, innerHTML) {
var parts = (tagNameAndClass || 'div').split(/\./g);
var elem = document.createElement(parts.shift());
elem.className = parts.join(' ');
if (innerHTML) elem.innerHTML = innerHTML;
return elem;
}
Examples of uses:
tag('div.divClass', 'Div Content') // <div class="divClass">Div Content</div>
tag('.class-one.class-two', 'Content') // <div class="class-one class-two">Content</div>
tag('h1.super', 'My Super Heading') // <h1 class="super">My Super Heading</h1>
What would be the shortest way to do the following [...]
We can imagine a situation in which the div already exists in the DOM while the CSS style rule display:none ensures it remains absent from the visible document flow.
The following single line in javascript will make the element reappear into the visible document flow:
document.getElementsByClassName('divClass')[0].style.display = 'block';
Probably the best solution I have came up with so far :
var el = function(type,props,appends){
var el = document.createElement(type);
if(props) for(var x in props) el[x] = props[x];
if(appends) for(var x in appends) el.appendChild(appends[x]);
return el;
}
and then when using it (creating a popup with header and body example) :
$title = el('div',{className:'title',innerHTML:'Item Title'});
$remove = el('div',{className:'remove',innerHTML:'X'});
$header = el('div',{className:'header'},[$title,$remove,el('div',{className:'clear'})]);
$body = el('div',{className:'body',innerHTML:'body'});
$el = el('div',{className:'item'},[$header,$body]);
Related
I want to wrap all the nodes within the #slidesContainer div with JavaScript. I know it is easily done in jQuery, but I am interested in knowing how to do it with pure JS.
Here is the code:
<div id="slidesContainer">
<div class="slide">slide 1</div>
<div class="slide">slide 2</div>
<div class="slide">slide 3</div>
<div class="slide">slide 4</div>
</div>
I want to wrap the divs with a class of "slide" collectively within another div with id="slideInner".
If your "slide"s are always in slidesContainer you could do this
org_html = document.getElementById("slidesContainer").innerHTML;
new_html = "<div id='slidesInner'>" + org_html + "</div>";
document.getElementById("slidesContainer").innerHTML = new_html;
Like BosWorth99, I also like to manipulate the dom elements directly, this helps maintain all of the node's attributes. However, I wanted to maintain the position of the element in the dom and not just append the end incase there were siblings. Here is what I did.
var wrap = function (toWrap, wrapper) {
wrapper = wrapper || document.createElement('div');
toWrap.parentNode.appendChild(wrapper);
return wrapper.appendChild(toWrap);
};
How to "wrap content" and "preserve bound events"?
// element that will be wrapped
var el = document.querySelector('div.wrap_me');
// create wrapper container
var wrapper = document.createElement('div');
// insert wrapper before el in the DOM tree
el.parentNode.insertBefore(wrapper, el);
// move el into wrapper
wrapper.appendChild(el);
or
function wrap(el, wrapper) {
el.parentNode.insertBefore(wrapper, el);
wrapper.appendChild(el);
}
// example: wrapping an anchor with class "wrap_me" into a new div element
wrap(document.querySelector('div.wrap_me'), document.createElement('div'));
ref
https://plainjs.com/javascript/manipulation/wrap-an-html-structure-around-an-element-28
If you patch up document.getElementsByClassName for IE, you can do something like:
var addedToDocument = false;
var wrapper = document.createElement("div");
wrapper.id = "slideInner";
var nodesToWrap = document.getElementsByClassName("slide");
for (var index = 0; index < nodesToWrap.length; index++) {
var node = nodesToWrap[index];
if (! addedToDocument) {
node.parentNode.insertBefore(wrapper, node);
addedToDocument = true;
}
node.parentNode.removeChild(node);
wrapper.appendChild(node);
}
Example: http://jsfiddle.net/GkEVm/2/
A general good tip for trying to do something you'd normally do with jQuery, without jQuery, is to look at the jQuery source. What do they do? Well, they grab all the children, append them to a a new node, then append that node inside the parent.
Here's a simple little method to do precisely that:
const wrapAll = (target, wrapper = document.createElement('div')) => {
;[ ...target.childNodes ].forEach(child => wrapper.appendChild(child))
target.appendChild(wrapper)
return wrapper
}
And here's how you use it:
// wraps everything in a div named 'wrapper'
const wrapper = wrapAll(document.body)
// wraps all the children of #some-list in a new ul tag
const newList = wrapAll(document.getElementById('some-list'), document.createElement('ul'))
I like to manipulate dom elements directly - createElement, appendChild, removeChild etc. as opposed to the injection of strings as element.innerHTML. That strategy does work, but I think the native browser methods are more direct. Additionally, they returns a new node's value, saving you from another unnecessary getElementById call.
This is really simple, and would need to be attached to some type of event to make any use of.
wrap();
function wrap() {
var newDiv = document.createElement('div');
newDiv.setAttribute("id", "slideInner");
document.getElementById('wrapper').appendChild(newDiv);
newDiv.appendChild(document.getElementById('slides'));
}
jsFiddle
Maybe that helps your understanding of this issue with vanilla js.
To simply wrap a div without the need of the parent:
<div id="original">ORIGINAL</div>
<script>
document.getElementById('original').outerHTML
=
'<div id="wrap">'+
document.getElementById('original').outerHTML
+'</div>'
</script>
Working Example: https://jsfiddle.net/0v5eLo29/
More Practical Way:
const origEle = document.getElementById('original');
origEle.outerHTML = '<div id="wrap">' + origEle.outerHTML + '</div>';
Or by using only nodes:
let original = document.getElementById('original');
let wrapper = document.createElement('div');
wrapper.classList.add('wrapper');
wrapper.append(original.cloneNode(true));
original.replaceWith(wrapper);
Working Example: https://jsfiddle.net/wfhqak2t/
A simple way to do this would be:
let el = document.getElementById('slidesContainer');
el.innerHTML = `<div id='slideInner'>${el.innerHTML}</div>`;
Note - below answers the title of the question but is not specific to the OP's requirements (which are over a decade old)
Using the range API is making wrapping easy, by creating a Range which selects only the node wished to be wrapped, and then use the surroundContents API to wrap it.
Below code wraps the first (text) node with a <mark> element and the last node with a <u> element:
const wrapNode = (nodeToWrap, wrapWith) => {
const range = document.createRange();
range.selectNode(nodeToWrap);
range.surroundContents(wrapWith);
}
wrapNode(document.querySelector('p').firstChild, document.createElement('mark'))
wrapNode(document.querySelector('p').lastChild, document.createElement('u'))
<p>
first node
<span>second node</span>
third node
</p>
From what I understand #Michal 's answer is vulnerable to XXS attacks (using innerHTML is a security vulnerability) Here is another link on this.
There are many ways to do this, one that I found and liked is:
function wrap_single(el, wrapper) {
el.parentNode.insertBefore(wrapper, el);
wrapper.appendChild(el);
}
let divWrapper;
let elementToWrap;
elementToWrap = document.querySelector('selector');
// wrapping the event form in a row
divWrapper = document.createElement('div');
divWrapper.className = 'row';
wrap_single(elementToWrap, divWrapper);
This works well. However for me, I sometimes want to just wrap parts of an element. So I modified the function to this:
function wrap_some_children(el, wrapper, counter) {
el.parentNode.insertBefore(wrapper, el);
if ( ! counter ) {
counter = el.childNodes.length;
}
for(i = 0; i < counter; i++) {
wrapper.appendChild( el.childNodes[0] );
}
}
// wrapping parts of the event form into columns
let divCol1;
let divCol2;
// the elements to wrap
elementToWrap = document.querySelector('selector');
// creating elements to wrap with
divCol1 = document.createElement('div');
divCol1.className = 'col-sm-6';
divCol2 = document.createElement('div');
divCol2.className = 'col-sm-6';
// for the first column
wrap_some_children(elementToWrap, divCol1, 13); // only wraps the first 13 child nodes
// for the second column
wrap_some_children(elementToWrap, divCol2);
I hope this helps.
wrapInner multiple tag content
function wilWrapInner(el, wrapInner) {
var _el = [].slice.call(el.children);
var fragment = document.createDocumentFragment();
el.insertAdjacentHTML('afterbegin', wrapInner);
var _wrap = el.children[0];
for (var i = 0, len = _el.length; i < len; i++) {
fragment.appendChild(_el[i]);
}
_wrap.appendChild(fragment);
}
Link Demo Jsbin
I need to append some html to an existing element using pure javaScript:
function create(htmlStr) {
var frag = document.createDocumentFragment(),
temp = document.createElement('div');
temp.innerHTML = htmlStr;
while (temp.firstChild) {
frag.appendChild(temp.firstChild);
}
return frag;
}
var target = document.querySelectorAll(".container-right");
var fragment = create(
'<div class="freetext"><p>Some text that should be appended...</p></div>'
);
document.body.insertBefore(fragment, document.body.childNodes[0]);
It's kind of working, but I have two questions:
How can I make sure that the html fragment is appended to the div with the class container-right and not just the body? Changing the last line to document.body.insertBefore(fragment, target); doesn't work.
How can I insert the html after the content in the target element - after the existing content - like jQuery's append()?
Any help is much appreciated.
JsFiddle here.
Well, I know this works:
let elem = document.querySelector ( 'css-selector (id or class)' )
That should give you your element. Then you do this:
elem.innerHTML = elem.innerHTML + myNewStuff;
That'll append your html to the innerHTML of the element. I tried it quickly, it works.
var target = document.querySelector(".container-right");
var p = document.createElement('p');
p.innerHTML = "Some text that should be appended...";
var div = document.createElement('div');
div.appendChild(p);
var fragment = document.createDocumentFragment();
fragment.appendChild(div);
target.appendChild(fragment);
JSFiddle
Try this:
var target = document.querySelector(".container-right");
target.innerHTML += '<div class="freetext"><p>Some text that should be appended...</p></div>';
Based on this answer to a similar question, I have found that insertAdjacentHTML is a good fit for this kind of problems.
I haven't tested it on a Node List, but with a single node it works perfectly.
insertAdjacentHTML has a great browser compatibility (back to IE4), plus it lets you decide where you want to insert the HTML (see here).
var target = document.querySelector(".container-right");
var newContent = '<div class="freetext"><p>Some text that should be appended...</p></div>';
target.insertAdjacentHTML('beforeend', newContent);
document.querySelectorAll('.container-right').forEach(elm=>{
elm.innerHTML += '<div class="freetext"><p>Some text that should be appended...</p></div>';
});
Consider this my value:
var value = "<br><br><div class="test">-- Thanks, <br><div><br></div></div>";
I want to remove test class div tag i.e <div class="test1"> and related to closing tag </div>.
Expecting results will be:
"<br><br>-- Thanks, <br><div><br></div>"
I am trying with regular expression:
value = value.replace(/(<div class="test">|<\/div>)/g, '');
but it's removing adjacent div tag:
<br><br><div class="test">-- Thanks, <br><div><br>
not the exactly with the closing tag.
How to do this?
Your best bet here is to use the HTML parser built into the browser. For instance:
var div, divToRemove, node, sibling;
div = document.createElement('div');
div.innerHTML = value;
divToRemove = div.querySelector('.test');
for (node = divToRemove.firstChild, sibling = node.nextSibling;
node;
node = sibling, sibling = node && node.nextSibling) {
divToRemove.parentNode.insertBefore(node, divToRemove);
}
divToRemove.parentNode.removeChild(divToRemove);
value = div.innerHTML;
Live Example:
var value = '<br><br><div class="test">-- Thanks, <br><div><br></div></div>';
snippet.log("Before: " + value);
var div, divToRemove, node, sibling;
div = document.createElement('div');
div.innerHTML = value;
divToRemove = div.querySelector('.test');
for (node = divToRemove.firstChild, sibling = node.nextSibling; node; node = sibling, sibling = node && node.nextSibling) {
divToRemove.parentNode.insertBefore(node, divToRemove);
}
divToRemove.parentNode.removeChild(divToRemove);
value = div.innerHTML;
snippet.log("After: " + value);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
You need to first save parent div's html in a variable
var html = document.getElementByClassName('test1').innerHtml;
Then remove the div:
document.getElementByClassName('test1').remove();
Then append the html to the parent of the div
var bodyHtml = document.getElementByTagName('body');
bodyHtml = bodyHtml + html;
Use the DOM to get it right
var html = '<br><br><div class="test">-- Thanks, <br><div><br></div></div>';
var frag = document.createElement('div');
frag.innerHTML = html;
var tgt = frag.querySelector('.test');
var par = tgt.parentNode;
while(tgt.firstChild) {
par.insertBefore(tgt.firstChild, tgt);
};
tgt.remove();
console.log(frag.innerHTML);
I want to wrap all the nodes within the #slidesContainer div with JavaScript. I know it is easily done in jQuery, but I am interested in knowing how to do it with pure JS.
Here is the code:
<div id="slidesContainer">
<div class="slide">slide 1</div>
<div class="slide">slide 2</div>
<div class="slide">slide 3</div>
<div class="slide">slide 4</div>
</div>
I want to wrap the divs with a class of "slide" collectively within another div with id="slideInner".
If your "slide"s are always in slidesContainer you could do this
org_html = document.getElementById("slidesContainer").innerHTML;
new_html = "<div id='slidesInner'>" + org_html + "</div>";
document.getElementById("slidesContainer").innerHTML = new_html;
Like BosWorth99, I also like to manipulate the dom elements directly, this helps maintain all of the node's attributes. However, I wanted to maintain the position of the element in the dom and not just append the end incase there were siblings. Here is what I did.
var wrap = function (toWrap, wrapper) {
wrapper = wrapper || document.createElement('div');
toWrap.parentNode.appendChild(wrapper);
return wrapper.appendChild(toWrap);
};
How to "wrap content" and "preserve bound events"?
// element that will be wrapped
var el = document.querySelector('div.wrap_me');
// create wrapper container
var wrapper = document.createElement('div');
// insert wrapper before el in the DOM tree
el.parentNode.insertBefore(wrapper, el);
// move el into wrapper
wrapper.appendChild(el);
or
function wrap(el, wrapper) {
el.parentNode.insertBefore(wrapper, el);
wrapper.appendChild(el);
}
// example: wrapping an anchor with class "wrap_me" into a new div element
wrap(document.querySelector('div.wrap_me'), document.createElement('div'));
ref
https://plainjs.com/javascript/manipulation/wrap-an-html-structure-around-an-element-28
If you patch up document.getElementsByClassName for IE, you can do something like:
var addedToDocument = false;
var wrapper = document.createElement("div");
wrapper.id = "slideInner";
var nodesToWrap = document.getElementsByClassName("slide");
for (var index = 0; index < nodesToWrap.length; index++) {
var node = nodesToWrap[index];
if (! addedToDocument) {
node.parentNode.insertBefore(wrapper, node);
addedToDocument = true;
}
node.parentNode.removeChild(node);
wrapper.appendChild(node);
}
Example: http://jsfiddle.net/GkEVm/2/
A general good tip for trying to do something you'd normally do with jQuery, without jQuery, is to look at the jQuery source. What do they do? Well, they grab all the children, append them to a a new node, then append that node inside the parent.
Here's a simple little method to do precisely that:
const wrapAll = (target, wrapper = document.createElement('div')) => {
;[ ...target.childNodes ].forEach(child => wrapper.appendChild(child))
target.appendChild(wrapper)
return wrapper
}
And here's how you use it:
// wraps everything in a div named 'wrapper'
const wrapper = wrapAll(document.body)
// wraps all the children of #some-list in a new ul tag
const newList = wrapAll(document.getElementById('some-list'), document.createElement('ul'))
I like to manipulate dom elements directly - createElement, appendChild, removeChild etc. as opposed to the injection of strings as element.innerHTML. That strategy does work, but I think the native browser methods are more direct. Additionally, they returns a new node's value, saving you from another unnecessary getElementById call.
This is really simple, and would need to be attached to some type of event to make any use of.
wrap();
function wrap() {
var newDiv = document.createElement('div');
newDiv.setAttribute("id", "slideInner");
document.getElementById('wrapper').appendChild(newDiv);
newDiv.appendChild(document.getElementById('slides'));
}
jsFiddle
Maybe that helps your understanding of this issue with vanilla js.
To simply wrap a div without the need of the parent:
<div id="original">ORIGINAL</div>
<script>
document.getElementById('original').outerHTML
=
'<div id="wrap">'+
document.getElementById('original').outerHTML
+'</div>'
</script>
Working Example: https://jsfiddle.net/0v5eLo29/
More Practical Way:
const origEle = document.getElementById('original');
origEle.outerHTML = '<div id="wrap">' + origEle.outerHTML + '</div>';
Or by using only nodes:
let original = document.getElementById('original');
let wrapper = document.createElement('div');
wrapper.classList.add('wrapper');
wrapper.append(original.cloneNode(true));
original.replaceWith(wrapper);
Working Example: https://jsfiddle.net/wfhqak2t/
A simple way to do this would be:
let el = document.getElementById('slidesContainer');
el.innerHTML = `<div id='slideInner'>${el.innerHTML}</div>`;
Note - below answers the title of the question but is not specific to the OP's requirements (which are over a decade old)
Using the range API is making wrapping easy, by creating a Range which selects only the node wished to be wrapped, and then use the surroundContents API to wrap it.
Below code wraps the first (text) node with a <mark> element and the last node with a <u> element:
const wrapNode = (nodeToWrap, wrapWith) => {
const range = document.createRange();
range.selectNode(nodeToWrap);
range.surroundContents(wrapWith);
}
wrapNode(document.querySelector('p').firstChild, document.createElement('mark'))
wrapNode(document.querySelector('p').lastChild, document.createElement('u'))
<p>
first node
<span>second node</span>
third node
</p>
From what I understand #Michal 's answer is vulnerable to XXS attacks (using innerHTML is a security vulnerability) Here is another link on this.
There are many ways to do this, one that I found and liked is:
function wrap_single(el, wrapper) {
el.parentNode.insertBefore(wrapper, el);
wrapper.appendChild(el);
}
let divWrapper;
let elementToWrap;
elementToWrap = document.querySelector('selector');
// wrapping the event form in a row
divWrapper = document.createElement('div');
divWrapper.className = 'row';
wrap_single(elementToWrap, divWrapper);
This works well. However for me, I sometimes want to just wrap parts of an element. So I modified the function to this:
function wrap_some_children(el, wrapper, counter) {
el.parentNode.insertBefore(wrapper, el);
if ( ! counter ) {
counter = el.childNodes.length;
}
for(i = 0; i < counter; i++) {
wrapper.appendChild( el.childNodes[0] );
}
}
// wrapping parts of the event form into columns
let divCol1;
let divCol2;
// the elements to wrap
elementToWrap = document.querySelector('selector');
// creating elements to wrap with
divCol1 = document.createElement('div');
divCol1.className = 'col-sm-6';
divCol2 = document.createElement('div');
divCol2.className = 'col-sm-6';
// for the first column
wrap_some_children(elementToWrap, divCol1, 13); // only wraps the first 13 child nodes
// for the second column
wrap_some_children(elementToWrap, divCol2);
I hope this helps.
wrapInner multiple tag content
function wilWrapInner(el, wrapInner) {
var _el = [].slice.call(el.children);
var fragment = document.createDocumentFragment();
el.insertAdjacentHTML('afterbegin', wrapInner);
var _wrap = el.children[0];
for (var i = 0, len = _el.length; i < len; i++) {
fragment.appendChild(_el[i]);
}
_wrap.appendChild(fragment);
}
Link Demo Jsbin
if i have a string like
<p>this is some content</p><script>alert('hello');</script>
i want to get the string without any scripts, but with the formatting, how do i do it?
<p>this is some content</p>
i tried
var html = "<p>etc</p><script>alert('hello world');</script>".replace("<script*</script>", "p");
but that gave me something like
".replace("", "p"); $('#blogDescription').html(html); }); });
You can do this without using regex, by using some DOM manipulation you can run through each of the elements in the DOM fragment created from the string and remove the script tags.
var html = "<p>etc</p><script>alert('hello world');</script>";
var container = document.createElement('div');
container.innerHTML = html;
function stripScript(parent){
var elements = parent.children;
for(var i = 0; i < elements.length; i++){
if(elements[i].nodeName === 'SCRIPT'){
parent.removeChild(elements[i]);
} else if(elements[i].children.length > 0){
stripScript(elements[i]);
}
}
}
stripScript(container);
console.log(container.innerHTML);
Or with jQuery
var html = "<p>etc</p><script>alert('hello world');</script>";
container = document.createElement('div');
container.innerHTML = html;
$(container).find('script').remove();
console.log(container.innerHTML);
try using this
/<script\b[^>]*>(.*?)<\/script>/i
var html = "<p>etc</p><script>alert('hello world');</script>".replace("<script>").replace("</script>");