find DOM elements that have no attributes? - javascript

I'm trying to find all span tags that have no attributes -- no class, no styling, no nothing. I've been doing this:
function hasAttributes(span) {
if (span.outerHTML.slice(0,6) === '<span>') return true;
return false;
}
Is there a better (faster) way to check if a particular element qualifies?

You can use querySelectorAll() to select all spans and then use for loop to filter spans by attributes property. If span doesn't have any attributes it will return empty array.
var spans = document.querySelectorAll('span');
for (var i = 0; i < spans.length; i++) {
if (spans[i].attributes.length == 0) spans[i].style.color = 'blue';
}
<span>one</span>
<span class="two">Two</span>

Check attributes property of element for length
function hasAttributes(span){
return span.attributes.length;
}

Related

Events and selectors in native javascript

How can this jQuery-dependent code
$('.myElement').click(function () {
drawMode = !drawMode;
$icon = $(this).children('i');
if (drawMode) {
$icon.removeClass('a').addClass('b');
} else {
$icon.removeClass('b').addClass('a');
}
});
be rewritten into native javascript?
I have tried
var element = document.getElementsByClassName('myElement')[0];
element.addEventListener('click', function (e) {
drawMode = !drawMode;
var icon = this.children()[0];
if (drawMode) {
icon.classList.remove('a').add('b');
} else {
icon.classList.remove('b').add('a');
}
});
but I cannot find the children element correctly.
jQuery's children allows you to filter by selector, something that isn't in the DOM API (you can find all descendants matching a given CSS selector, but you can't [for now] limit it to just children).
If it doesn't matter whether it's a child or just any descendant, then:
var icon = this.querySelector("i");
That finds the first descendant within the element that's an i element. I suspect that would work just fine for you. The only time it might not would be if you had this:
<div class="myElement">
<span>
<i>You DON'T want this one</i>
</span>
<i>You do want this one</i>
</div>
If that's the case and you need to only look at children, not all descendants, you'll need a loop:
var icon = null;
var n;
for (n = 0; n < !icon && this.children.length; ++n) {
if (this.children[n].tagName.toLowerCase() === "i") {
icon = this.children[n];
}
}
In ES2015+ (you can transpile to use it today), that's so much tidier:
let icon = Array.from(this.children)
.find(child => child.tagName.toLowerCase() === "i");
A few notes:
The add and remove functions of the classList do not return the classList object, so you can't concatenate them (e.add().remove(), like you are used to do in jQuery).
In your code you only go over the first element, while when using jQuery the changes are made for all elements that you selected.
I used the querySelectorAll and filtered out elements that are not direct childs, (checked for the parentElement since you used the children() function of jQuery).
Here is an example:
drawMode = true;
var elements = document.getElementsByClassName('myElement');
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', function() {
var that = this;
drawMode = !drawMode;
var icons = this.querySelectorAll('i');
for (var j = 0; j < icons.length; j++) {
var icon = icons[j];
if (icon.parentElement != that) {
continue;
}
if (drawMode) {
icon.classList.remove('a');
icon.classList.add('b');
} else {
icon.classList.remove('b')
icon.classList.add('a');
}
}
});
}
i.a {
background: red;
}
i.b {
background: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="myElement">
<i>asd</i><br />
<i>fgh</i><br />
<span><i>This element will not change because he isn't a direct child</i></span><br />
</div>
Generally, document.querySelectorAll is very useful when converting jQuery to vanilla javascript.
Returns a list of the elements within the document (using depth-first pre-order traversal of the document's nodes) that match the specified group of selectors. The object returned is a NodeList.
// get a NodeList of elements which match CSS Selector '.myElement'
var elements = document.querySelectorAll('.myElement');
for (var i = 0; i < elements.length; i++ ) {
// loop through every element with class 'myElement'
var element = elements[i];
element.addEventListener('click', function(event) {
drawMode = !drawMode;
var icon = element.querySelector('i');
if (drawMode) {
icon.classList.remove('a');
icon.classList.add('b');
} else {
icon.classList.remove('b');
icon.classList.add('a');
}
});
}
Note I've also used element.querySelector to match descendants of the currently processed element.

JavaScript get textContent excluding children

First, I'm creating a library for JavaScript and I can not use jQuery. I'm trying to get the text content of an HTML element without the text contents of its children.
Both attributes innerText and textContent don't give me what needed, please help.
You can solve using DOM API as childNodes and nodeType.
var elChildNode = document.querySelector("#hello").childNodes;
var sChildTextSum = "";
elChildNode.forEach(function(value){
if(value.nodeType === Node.TEXT_NODE) {
console.log("Current textNode value is : ", value.nodeValue.trim());
sChildTextSum += value.nodeValue;
}
});
console.log("All text value of firstChild : ", sChildTextSum);
I created a sample code as above.
https://jsfiddle.net/nigayo/p7t9bdc3/
To get Author's Name from the following element, excluding <span>...:
<div class="details__instructor">
Author's Name<span ng-show="job_title">, Entrepreneur</span>
</div>
use childNodes[0]. For example:
document.querySelector('div.details__instructor').childNodes[0].textContent
Using only JavaScript (you specified you cannot use jQuery), and given that you have provided and know the id for the parent element:
document.getElementById('parent_element_id').childNodes[0].nodeValue;
You can also use .trim() to remove any trailing space characters left behind from the removal of any child element text:
document.getElementById('parent_element_id').childNodes[0].nodeValue.trim();
var mydiv = getElementByID("id");
function Get_text(element) {
var selected = element.cloneNode(true);
var text;
while (selected.firstChild) {
if (selected.firstChild.nodeType == 3) text = selected.firstChild.nodeValue;
selected.removeChild(selected.firstChild);
}
return text;
}
Get_text(mydiv);
I know many good solutions here exist, but none of them actually achieved what I needed (get the textContent of a single node, none of its children), so sharing this for future searchers.
var html = document.getElementsByTagName("*");
for (var i = 0; i < html.length; i++) {
var el = html[i];
for (var j = 0; j < el.children.length; j++) {
var child = el.children[j],
childTextContent = child.innerHTML;
// Remove all children tags, leaving only the actual text of the node.
childTextContent = childTextContent.replace(/\<.*\>.*\<\/.*\>/gmi, "");
// Also remove <img /> type tags.
childTextContent = childTextContent.replace(/\<.*\ \/\>/gmi, "");
console.log(childTextContent);
// Now you can do any type of text matching (regex) on the result.
}
});

how to iterate through a particular attribute using js?

I am using ckeditor inline on a webpage that i have built.I can save the data to a database but the major problem is that ckeditor applies its own classes and other attributes to all the elements on which contenteditable is set to true.Also it removes some classes on elements. This is affecting the styling of my webpage. I wish to remove the classes and other attributes set by ckeditor before printing it on the browser.For this I need to loop through all the elements having content editable set to true. How can we do this using js?
Plain JS:
var el = document.getElementsByTagName("*");
for(var i = 0, l = el.length; i < l; i++)
{
if (el[i].contentEditable)
{
// Do here what you want
}
}
jQuery:
as dandavis said:
$("*[contentEditable]").each(function()
{
//
});
Edit:
As far as the .contentEditable does not return boolean,
you must check whether the element has the contentEditable attribute like this:
var el = document.getElementsByTagName("*");
for(var i = 0, l = el.length; i < l; i++)
{
if (el[i].contentEditable === "true" || el[i].contentEditable === "")
{
// Do here what you want
}
}
In order to remove the contentEditable attribute:
In jQuery you can do it like this:
$("*[contentEditable]").each(function()
{
this.prop("contentEditable", false);
});
Plain js:
el[i].contentEditable = "false";

Access dynamic generated div id

I have some div ids that are generated dynamicly via php
<div id='a<?php echo $gid?>>
How can I access them in JavaScript? All these divs start with "A" followed by a number.
Is there some kind of search function
getElementById(a*)?
Thanks for any help
No generic JavaScript function for this (at least not something cross browser), but you can use the .getElementsByTagName and iterate the result:
var arrDivs = document.getElementsByTagName("div");
for (var i = 0; i < arrDivs.length; i++) {
var oDiv = arrDivs[i];
if (oDiv.id && oDiv.id.substr(0, 1) == "a") {
//found a matching div!
}
}
This is the most low level you can get so you won't have to worry about old browsers, new browsers or future browsers.
To wrap this into a neater function, you can have:
function GetElementsStartingWith(tagName, subString) {
var elements = document.getElementsByTagName(tagName);
var result = [];
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (element.id && element.id.substr(0, subString.length) == subString) {
result.push(element);
}
}
return result;
}
The usage example would be:
window.onload = function() {
var arrDivs = GetElementsStartingWith("div", "a");
for (var i = 0; i < arrDivs.length; i++) {
arrDivs[i].style.backgroundColor = "red";
}
};
Live test case.
In case you choose to use jQuery at some point (not worth for this thing alone) all the above code turns to single line:
$(document).ready(function() {
$('div[id^="a"]').css("background-color", "blue");
});
Updated fiddle, with jQuery.
No, you need a fixed id value for getElementById to work. However, there are other ways to search the DOM for elements (e.g. by CSS classes).
You can use querySelectorAll to get all divs that have an ID starting with a. Then check each one to see if it contains a number.
var aDivs = document.querySelectorAll('div[id^="a"]');
for(var index = 0, len = aDivs.length; index < len; index++){
var aDiv = aDivs[index];
if(aDiv.id.match(/a\d+/)){
// aDiv is a matching div
}
}​
DEMO: http://jsfiddle.net/NTICompass/VaTMe/2/
Well, I question myself why you would need to select/get an element, that has a random ID. I would assume, you want to do something with every div that has a random ID (like arranging or resizing them).
In that case -> give your elements a class like "myGeneratedDivs" with the random ID (if you need it for something).
And then select all with javascript
var filteredResults=document.querySelectorAll(".myGeneratedDivs").filter(function(elem){
....
return true;
});
or use jQuery/Zepto/YourWeaponOfChoice
var filteredResults=$(".myGeneratedDivs").filter(function(index){
var elem=this;
....
return true;
});
If you plan to use jQuery, you can use following jQuery selectors
div[id^="a"]
or
$('div[id^="id"]').each(function(){
// your stuff here
});
You will have to target the parent div and when someone click on child div inside a parent div then you can catch the child div.
<div id="target">
<div id="tag1" >tag1</div>
<div id="tag1" >tag2</div>
<div id="tag1" >tag3</div>
</div>
$("#target").on("click", "div", function() {
var showid = $(this).attr('id');
alert(showid)
});
getElementById() will return the exact element specified. There are many javascript frameworks including jQuery that allow much more powerful selection capabilities. eg:
Select an element by id: $("#theId")
Select a group of elements by class: $(".class")
Select subelements: $("ul a.action")
For your specific problem you could easily construct the appropriate selector.

How to get all elements inside "div" that starts with a known text

I have a div element in an HTML document.
I would like to extract all elements inside this div with id attributes starting with a known string (e.g. "q17_").
How can I achieve this using JavaScript ?
If needed, for simplicity, I can assume that all elements inside the div are of type input or select.
var matches = [];
var searchEles = document.getElementById("myDiv").children;
for(var i = 0; i < searchEles.length; i++) {
if(searchEles[i].tagName == 'SELECT' || searchEles.tagName == 'INPUT') {
if(searchEles[i].id.indexOf('q1_') == 0) {
matches.push(searchEles[i]);
}
}
}
Once again, I strongly suggest jQuery for such tasks:
$("#myDiv :input").hide(); // :input matches all input elements, including selects
Option 1: Likely fastest (but not supported by some browsers if used on Document or SVGElement) :
var elements = document.getElementById('parentContainer').children;
Option 2: Likely slowest :
var elements = document.getElementById('parentContainer').getElementsByTagName('*');
Option 3: Requires change to code (wrap a form instead of a div around it) :
// Since what you're doing looks like it should be in a form...
var elements = document.forms['parentContainer'].elements;
var matches = [];
for (var i = 0; i < elements.length; i++)
if (elements[i].value.indexOf('q17_') == 0)
matches.push(elements[i]);
With modern browsers, this is easy without jQuery:
document.getElementById('yourParentDiv').querySelectorAll('[id^="q17_"]');
The querySelectorAll takes a selector (as per CSS selectors) and uses it to search children of the 'yourParentDiv' element recursively. The selector uses ^= which means "starts with".
Note that all browsers released since June 2009 support this.
Presuming every new branch in your tree is a div, I have implemented this solution with 2 functions:
function fillArray(vector1,vector2){
for (var i = 0; i < vector1.length; i++){
if (vector1[i].id.indexOf('q17_') == 0)
vector2.push(vector1[i]);
if(vector1[i].tagName == 'DIV')
fillArray (document.getElementById(vector1[i].id).children,vector2);
}
}
function selectAllElementsInsideDiv(divId){
var matches = new Array();
var searchEles = document.getElementById(divId).children;
fillArray(searchEles,matches);
return matches;
}
Now presuming your div's id is 'myDiv', all you have to do is create an array element and set its value to the function's return:
var ElementsInsideMyDiv = new Array();
ElementsInsideMyDiv = selectAllElementsInsideDiv('myDiv')
I have tested it and it worked for me. I hope it helps you.
var $list = $('#divname input[id^="q17_"]'); // get all input controls with id q17_
// once you have $list you can do whatever you want
var ControlCnt = $list.length;
// Now loop through list of controls
$list.each( function() {
var id = $(this).prop("id"); // get id
var cbx = '';
if ($(this).is(':checkbox') || $(this).is(':radio')) {
// Need to see if this control is checked
}
else {
// Nope, not a checked control - so do something else
}
});
i have tested a sample and i would like to share this sample and i am sure it's quite help full.
I have done all thing in body, first creating an structure there on click of button you will call a
function selectallelement(); on mouse click which will pass the id of that div about which you want to know the childrens.
I have given alerts here on different level so u can test where r u now in the coding .
<body>
<h1>javascript to count the number of children of given child</h1>
<div id="count">
<span>a</span>
<span>s</span>
<span>d</span>
<span>ff</span>
<div>fsds</div>
<p>fffff</p>
</div>
<button type="button" onclick="selectallelement('count')">click</button>
<p>total element no.</p>
<p id="sho">here</p>
<script>
function selectallelement(divid)
{
alert(divid);
var ele = document.getElementById(divid).children;
var match = new Array();
var i = fillArray(ele,match);
alert(i);
document.getElementById('sho').innerHTML = i;
}
function fillArray(e1,a1)
{
alert("we are here");
for(var i =0;i<e1.length;i++)
{
if(e1[i].id.indexOf('count') == 0)
a1.push(e1[i]);
}
return i;
}
</script>
</body>
USE THIS I AM SURE U WILL GET YOUR ANSWER ...THANKS

Categories