How to get bold, italic styles within a div - javascript

Am working on a text editor where the content can be in the form of following
<div>some text <strong>bold text</strong> more <em>italic</em></div>
Now on some user click, I have to remove the bold and italic styling from the div.
How can I remove the strong and em tags from a div?
Thanks
Kapil

HTML
<div id="foo">
<div>some text <strong>bold text</strong> more <em>italic</em></div>
</div>
JS
var t = document.getElementById('foo').innerHTML;
t = t.replace('<strong>', '');
t = t.replace('</strong>', '');
t = t.replace('<em>', '');
t = t.replace('</em>', '');
document.getElementById('foo').innerHTML = t;

I'm not sure if you want jQuery, but it handles things like this nicely:
// To remove styles from clicked element.
$('#editor *').click(function () {
$(this).replaceWith($(this).text());
});

var element = document.getElementById('whatever');
element.innerHTML = element.innerHTML.replace(/<(strong|em)>(.*?)<\/\1>/g, '$1');
jsFiddle.
Keep in mind any events attached to any children of this div will be lost.

Don't use regular expressions or some other kind of text replacement for this. The DOM is a tree. Treat it as such and don't be scared of it. It's by far the safest and least brutal way to handle this kind of thing.
function removeElements(container) {
var elements = container.getElementsByTagName("*");
// Make an array of the strongs and ems
var strongsAndEms = [];
for (var i = 0, len = elements.length; i < len; ++i) {
if (/^(strong|em)$/i.test(elements[i].tagName)) {
strongsAndEms.push(elements[i]);
}
}
// Remove the strongs and ems
for (var j = 0, el, child; el = strongsAndEms[j++]; ) {
while ( (child = el.firstChild) ) {
el.parentNode.insertBefore(child, el);
}
el.parentNode.removeChild(el);
}
}
var div = document.getElementById("foo");
removeElements(div);

Related

What is missing in my code

Why this code is not working ?
I think i am doing some silly mistake here.
document.addEventListener("DOMContentLoaded", function() {
var text = "Planing";
document.getElementsByTagName("div").innerHTML = text;
});
<div id="demo" class="eg"></div>
getElementsByTagName returns a collection of all the matching elements(<div>s in this case) on the page/DOM, to select first element use array notation with zero index.
document.addEventListener("DOMContentLoaded", function() {
var text = "Planing";
document.getElementsByTagName("div")[0].innerHTML = text;
});
<div id="demo" class="eg"></div>
If you want to select first element, you can use document.querySelector('div');
If you want to perform some operation on all the selected elements, you need to iterate over them.
var allDivs = document.getElementsByTagName("div");
for (var i = 0; i < allDivs.length; i++) {
allDivs[i].innerHTML = 'Div ' + i;
}
getElementsByTagName, as the name suggests returns an array of elements (even if there is just one). You need to access the first one before applying the text.
document.addEventListener("DOMContentLoaded", function() {
var text = "Planing";
document.getElementsByTagName("div")[0].innerHTML = text;
});
<div id="demo" class="eg"></div>

Count how many elements in a div

I have a div with span inside of it. Is there a way of counting how many elements in a div then give it out as a value. For Example there were 5 span in a div then it would count it and alert five. In Javascript please.
Thank you.
If you want the number of descendants, you can use
var element = document.getElementById("theElementId");
var numberOfChildren = element.getElementsByTagName('*').length
But if you want the number of immediate children, use
element.childElementCount
See browser support here: http://help.dottoro.com/ljsfamht.php
or
element.children.length
See browser support here: https://developer.mozilla.org/en-US/docs/DOM/Element.children#Browser_compatibility
You can use this function, it will avoid counting TextNodes.
You can choose to count the children of the children (i.e. recursive)
function getCount(parent, getChildrensChildren){
var relevantChildren = 0;
var children = parent.childNodes.length;
for(var i=0; i < children; i++){
if(parent.childNodes[i].nodeType != 3){
if(getChildrensChildren)
relevantChildren += getCount(parent.childNodes[i],true);
relevantChildren++;
}
}
return relevantChildren;
}
Usage:
var element = document.getElementById("someElement");
alert(getCount(element, false)); // Simply one level
alert(getCount(element, true)); // Get all child node count
Try it out here:
JS Fiddle
Without jQuery:
var element = document.getElementById("theElementId");
var numberOfChildren = element.children.length
With jQuery:
var $element = $(cssSelectocr);
var numberOfChildren = $element.children().length;
Both of this return only immediate children.
i might add just stupid and easy one answer
<div>this is div no. 1</div>
<div>this is div no. 2</div>
<div>this is div no. 3</div>
you can get how many divs in your doc with:
const divs = document.querySelectorAll('div');
console.log(divs.length) // 3
With jQuery; checks only for spans inside a div:
JSFiddle
$(function(){
var numberOfSpans = $('#myDiv').children('span').length;
alert(numberOfSpans);
})();​
With jQuery you can do like this:
var count = $('div').children().length;
alert( count );​​​
Here's a Fiddle: http://jsfiddle.net/dryYq/1/
To count all descendant elements including nested elements in plain javascript, there are several options:
The simplest is probably this:
var count = parentElement.getElementsByTagName("*").length;
If you wanted the freedom to add more logic around what you count, you can recurse through the local tree like this:
function countDescendantElements(parent) {
var node = parent.firstChild, cnt = 0;
while (node) {
if (node.nodeType === 1) {
cnt++;
cnt += countDescendantElements(node);
}
node = node.nextSibling;
}
return(cnt);
}
Working Demo: http://jsfiddle.net/jfriend00/kD73F/
If you just wanted to count direct children (not deeper levels) and only wanted to count element nodes (not text or comment nodes) and wanted wide browser support, you could do this:
function countChildElements(parent) {
var children = parent.childNodes, cnt = 0;
for (var i = 0, len = children.length; i < len; i++) {
if (children[i].nodeType === 1) {
++cnt;
}
}
return(cnt);
}
The easiest way is to select all the span inside the div which will return a nodelist with all the span inside of it...
Then you can alert the length like the example below.
alert(document.querySelectorAll("div span").length)
<div>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>

how to add a wrapper div to an inner div

I have a an html code like this
<div>
<p> blah blah </p>
<div class = foo>
//some code
</div>
//some text
</div>
What i want to do by javascript is to add a wrapper div to the inner div with class foo. So that the code becomes something like
<div>
<p> blah blah </p>
<div id = temp>
<div class = foo>
//some code
</div>
</div>
//some text
</div>
Please tell me how to do something like this. Non jquery solutions would be more helpful.. :)
Using POJS is pretty simple:
function divWrapper(el, id) {
var d = document.createElement('div');
d.id = id;
d.appendChild(el);
return d;
}
Make sure you pass it something that can be wrapped in a div (e.g. don't give it a TR or TD or such).
You'll need some helper functions, I'm not going to post a getElementsByClassName function here, there are plenty on the web to choose from, a good one should first try qSA, then DOM method, then custom function.
Assuming you have one, consider something like:
function wrappByClass(className) {
var el, elements = getElementsByClassName(className);
for (var i = elements.length; i--;) {
el = elements[i];
el.parentNode.replaceChild(divWrapper(el, 'foo' + i), el);
}
}
Edit
On reflection, I prefer the following method. It inserts the wrapper div into the DOM first, then moves the element to be wrapped into it. The above seems to move the element out of the DOM, then wants to use its position in the DOM to insert the new node. It might work, but seems prone to error to me. So here's a better solution, tested in Safari:
// Quick implementation of getElementsByClassName, just for prototypeing
function getByClassName(className, root) {
var root = root || document;
var elements = root.getElementsByTagName('*');
var result = [];
var classRe = new RegExp('(^|\\s)' + className + '(\\s|$)');
for (var i=0, iLen=elements.length; i<iLen; i++) {
if (classRe.test(elements[i].className)) {
result.push(elements[i]);
}
}
return result;
}
var divWrapper = (function() {
var div = document.createElement('div');
return function(el, id) {
var oDiv = div.cloneNode(false);
oDiv.id = id;
el.parentNode.insertBefore(oDiv, el);
oDiv.appendChild(el);
}
}());
function wrapByClassName(className) {
var els = getByClassName(className);
var i = els.length;
while (i--) {
divWrapper(els[i], 'foo' + i)
}
}
var wrapper = document.createelement('div');
var myDiv = document.getelementById('myDiv');
wrapper.appendChild(myDiv.cloneNode(true));
myDiv.parentNode.replaceChild(wrapper, myDiv);
$('.foo').wrap('<div id="temp"/>');
See $.wrap()
Note that if there are more elements than 1 wrapped, you got more elements with the ID "temp"

JavaScript: how to get img and div elements using getElementsByTagName

I have a tree structure as follows:
<ul id="theul275">
<li>
<div id="red"></div>
<img id="green" />
<script></script>
<div id="blue"></div>
</li>
</ul>
There are multiple UL's likes this on my page each with a different id. I am getting each UL by doing this:
var child = document.getElementById('theul' + id).getElementsByTagName('*');
the problem is, I only want to get the children of each ul which are either div's or img's.
Is there a way to get elements by multiple tag names?
I really appreciate any help because I am kind of new to JavaScript! Thanks!
Depending on what browsers you may to support, you could use the CSS selector interface.
document.getElementById('theul275').querySelectorAll('div, img');
Or use a library. There are plenty of options out there. I am familiar with two,
MooTools
$('theul275').getElements('div, img');
jQuery
$('#theul275').find('div, img');
Or get a reference to the li node, and loop through each node and check if the nodeName is DIV or IMG.
for (var i = 0, l = child.length; i < l; i++)
{
if (child[i].nodeName == 'DIV' || child[i].nodeName == 'IMG')
{
//...
}
}
You could use a iterative method for this.
var elemArray = document.getElementById('theul' + id).childNodes,
getChildByNodeName = function (elem, pattern) {
var childCollection = [],
re = new RegExp(pattern, 'g'),
getChild = function (elements) {
var childs = elements.childNodes,
i = 0;
if (childs) {
getChild(childs);
for (i = 0; i < childs.length; i += 1) {
if (childs[i].nodeName.match(pattern)) {
childCollection.push(childs[i]);
}
}
}
};
getChild(elem);
return childCollection;
}
var childs2 = getChildByNodeName(elemArray, '^(DIV|IMG)$'); // array of match elements
And just change the pattern ('^(DIV|IMG)$') to suite your needs.
If you can use jQuery, try
var child = $("#theul" + id).find("div,img");
Otherwise, see JavaScript NodeList.

jQuery/javascript replace tag type

Is there an easy way to loop through all td tags and change them to th? (etc).
My current approach would be to wrap them with the th and then remove the td, but then I lose other properties etc.
jQuery.replaceTagName
The following is a jQuery plugin to replace the tag name of DOM elements.
Source
(function($) {
$.fn.replaceTagName = function(replaceWith) {
var tags = [],
i = this.length;
while (i--) {
var newElement = document.createElement(replaceWith),
thisi = this[i],
thisia = thisi.attributes;
for (var a = thisia.length - 1; a >= 0; a--) {
var attrib = thisia[a];
newElement.setAttribute(attrib.name, attrib.value);
};
newElement.innerHTML = thisi.innerHTML;
$(thisi).after(newElement).remove();
tags[i] = newElement;
}
return $(tags);
};
})(window.jQuery);
Minified Source
(function(e){e.fn.replaceTagName=function(t){var n=[],r=this.length;while(r--){var i=document.createElement(t),s=this[r],o=s.attributes;for(var u=o.length-1;u>=0;u--){var a=o[u];i.setAttribute(a.name,a.value)}i.innerHTML=s.innerHTML;e(s).after(i).remove();n[r]=i}return e(n)}})(window.jQuery);
Usage
Include the above minified source in your javascript after jQuery.
Then you can use the plugin like this:
$('div').replaceTagName('span'); // replace all divs with spans
Or in your case this:
$('td').replaceTagName('th');
jQuery selectors work as expected
$('.replace_us').replaceTagName('span'); // replace all elements with "replace_us" class with spans
$('#replace_me').replaceTagName('div'); // replace the element with the id "replace_me"
More resources
jsFiddle with Qunit tests
Completely untested, but giving this a whirl:
$("td").each(function(index) {
var thisTD = this;
var newElement = $("<th></th>");
$.each(this.attributes, function(index) {
$(newElement).attr(thisTD.attributes[index].name, thisTD.attributes[index].value);
});
$(this).after(newElement).remove();
});
I'm looking and looking at it, and I can't think of a reason why it wouldn't work!
1) loop through each td element
2) create a new th element
3) for each of those td's, loop over each of its attributes
4) add that attribute and value to the new th element
5) once all attributes are in place, add the element to the DOM right after the td, and remove the td
Edit: works fine: http://jsbin.com/uqofu3/edit
$("td").each(function() {
var tmp = $('<div/>').append($(this).clone(true)).html().replace(/td/i,'th');
$(this).after(tmp).remove();
});
or pure DOM
function replaceElm(oldTagName, newTagName, targetElm) {
var target = targetElm || window.document;
var allFound = target.getElementsByTagName(oldTagName);
for (var i=0; i<allFound.length; i++) {
var tmp = document.createElement(newTagName);
for (var k=0; k<allFound[i].attributes.length; k++) {
var name = allFound[i].attributes[k].name;
var val = allFound[i].attributes[k].value;
tmp.setAttribute(name,val);
}
tmp.innerHTML = allFound[i].innerHTML;
allFound[i].parentNode.insertBefore(tmp, allFound[i]);
allFound[i].parentNode.removeChild(allFound[i]);
}
}
replaceElm('td','th',document.getElementsByTagName('table')[0]);
DOM is always faster: http://jsperf.com/replace-tag-names
This might work, but I haven't tested it extensively:
var tds = document.getElementsByTagName("td");
while(tds[0]){
var t = document.createElement("th");
var a = tds[0].attributes;
for(var i=0;i<a.length;i++) t.setAttribute(a[i].nodeName,a[i].nodeValue);
t.innerHTML = tds[0].innerHTML;
tds[0].parentNode.insertBefore(t,tds[0]);
tds[0].parentNode.removeChild(tds[0]);
}
I hope it helps in some way.
Slight addition to #GlenCrawford answer, to also preserve inner text with the line:
newElement.text($(value).text());
All together now:
$("td").each(function(index) {
var thisTD = this;
var newElement = $("<th></th>");
newElement.text($(value).text());
$.each(this.attributes, function(index) {
$(newElement).attr(thisTD.attributes[index].name, thisTD.attributes[index].value);
});
$(this).after(newElement).remove();
});
Well this question is pretty old but this could help anyway: the only jQuery plugin that actually works as expected (you can't reuse the returned object in the other one, to add attributes for example):
jQuery.fn.extend({
replaceTagName: function(replaceWith) {
var tags=[];
this.each(function(i,oldTag) {
var $oldTag=$(oldTag);
var $newTag=$($("<div />").append($oldTag.clone(true)).html().replace(new RegExp("^<"+$oldTag.prop("tagName"),"i"),"<"+replaceWith));
$oldTag.after($newTag).remove();
tags.push($newTag.get(0));
});
return $(tags);
}
});
Besides the basic $("td").replaceTagName("th"); you can also chain calls like $("td").replaceTagName("th").attr("title","test");
Minified version:
jQuery.fn.extend({replaceTagName:function(a){var b=[];this.each(function(d,c){var e=$(c);var f=$($("<div />").append(e.clone(true)).html().replace(new RegExp("^<"+e.prop("tagName"),"i"),"<"+a));e.after(f).remove();b.push(f.get(0))});return $(b)}});
This is a bit cleaner than #GlenCrawford's answer and additionally copies the children of the replaced element.
$('td').each(function(){
var newElem = $('<th></th>', {html: $(this).html()});
$.each(this.attributes, function() {
newElem.attr(this.name, this.value);
});
$(this).replaceWith(newElem);
});

Categories

Resources