I have a CSS selector #menu li {background-color: red;}.
I want to access its attributes in JavaScript. It's important that I need to access both #menu and li since #menu alone has different attributes. It seems like getElementById(menu li), QuerySelector and getComputedStyle are not working in this case.
Is there any other way to achieve that or am I missing something here?
You should use jQuery for this, here the easy code example
//html
<div id="menu" data-number="123" >
</div>
//jquery
var menu = $('#menu').attr('data-number');
console.log(menu);
//print 123
jquery version
https://jsfiddle.net/pn52uvw1/
$(".button_1").click(function(){
alert($("#menu").attr("data-item-id"));
})
$(".button_2").click(function(){
alert($("#menu li").attr("data-item-id"));
})
non jquery version
https://jsfiddle.net/pn52uvw1/2/
window.firstFunction = function(){
var target = document.getElementById("menu");
alert(target.getAttribute('data-item-id'));
}
window.secondFunction = function(){
var target = document.getElementById("menu").children[0];
alert(target.getAttribute('data-item-id'));
}
but you will need to get rid of that [0] index probably, and use a for or something for multiple li items
If you want to get that css rule's property, you can do like this:
function getStyleFromSelector(selector, styleName) {
// Get all style elements
var styles = document.styleSheets;
var styleIndex = 0, styleCount = styles.length;
var rules, ruleCount, ruleIndex;
// Iterate though styles
for (styleIndex = 0; styleIndex < styleCount; ++styleIndex) {
// Get the css rules under the style.
rules = styles[styleIndex].rules;
ruleCount = rules.length;
for (ruleIndex = 0; ruleIndex < ruleCount; ++ruleIndex) {
// Check if the selector match the one we want
if (rules[ruleIndex].selectorText === selector) {
return styleName ?
rules[ruleIndex].style.getPropertyValue(styleName) : rules[ruleIndex];
}
}
}
}
var div = document.getElementById("results");
var result = getStyleFromSelector('#menu li');
console.log(result);
div.innerHTML = 'background-color is : ' + result.style.backgroundColor;
console.log(getStyleFromSelector('#menu li', 'background-color'));
#menu li {background-color: red;}
<div id="results"></div>
You can try it without additional Libraries with the following
var len = document.querySelectorAll("#menu li").length;
for(i = 0; i<len; i++)
document.querySelectorAll("#menu li")[i].style.backgroundColor="blue";
I also made you (a not very beautiful) jsfiddle
https://jsfiddle.net/gmeewsmz/
Related
I'm stuck on how to get number of all elements that has inline style.
var galleryElements = document.getElementsByClassName("popup-gallery")[0].children;
$('.myButton').click(function() {
var totalItems = galleryElements.length;
var itemsWithStyle = ($(galleryElements).css('display') == 'inline').length;
if (totalItems == itemsWithStyle){
/* do something */
}
});
Say I have a NodeList of the children of some div, i.e.
const div = document.querySelector('#target');
const children = div.children;
If I want to get the number of children with the display attribute set to inline, then I can iterate through children and increment a counter each time I encounter a child element with the display attribute set to inline.
For example:
let count = 0;
for (let child of children) {
if (child.style.display === 'inline') count++;
}
Where count represents the number of child elements of the parent div that have a display attribute set to inline.
this is without jquery
You can check this out for starters:
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
basic
<h1 id="hello">index.html</h1>
<-- css -->
#hello {display: inline;}
// js
const title = document.getElementById('hello');
let res = window.getComputedStyle(title)
let count = 0;
if(res.getPropertyValue('display') === 'inline') {
console.log('yes')
count ++;
console.log(count)
// 1
}
what I learned:
" The object from getComputedStyle is read-only, and should be used to inspect the element's style — including those set by a element or an external stylesheet.
The element.style object should be used to set styles on that element, or inspect styles directly added to it from JavaScript manipulation or the global style attribute."
You are in fact checking if all gallery elements are display: inline, so you can simplify your code a bit:
const $galleryElements = $('.popup-gallery').first().children();
$('.myButton').click(function() {
const areAllInline = $galleryElements.filter(function () {
$(this).css('display') !== 'inline';
}).length === 0;
if (areAllInline) {
/* do something */
}
});
If there are no elements with display different than inline, you're good to go.
This will give you a tally of both inline (including inline-block) and other. If there is a class associated with the element, it will report back that as well.
$('.myButton').click(function() {
let inline = [], block = []
$('.popup-gallery *').each(function() {
let tg = $(this).prop('tagName').toLowerCase()
if ($(this).attr('class')) tg += "." + $(this).attr('class');
if (['inline','inline-block'].includes($(this).css('display'))) inline.push(tg)
else block.push(tg)
})
console.log('inline',inline)
console.log('not-inline',block)
console.log('inline/total',inline.length + "/" + (inline.length + block.length))
console.log('has inline elements?',inline.length>0)
});
.special{
display:inline;
}
.special-ib{
display:inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='popup-gallery'>
<div>A div
<ul>
<li>li list - <i>italics...</i></li>
</ul>
</div>
<div class='special'>inline div</div>
<div class='special-ib'>inline-block div</div>
<p>paragraph</p>
<span>span, <dd>dd</dd></span>
</div>
<button class='myButton'>Click me </button>
These answers are good, however I feel it is even easier than how others are solving this problem.
console.log(
[...document.querySelectorAll(".popup-gallery")]
.filter(element =>
"inline" ==
window.getComputedStyle(element)
.getPropertyValue("display")
).length
);
I have several polymer elements.
<ps-el-one/>
<ps-el-two/>
<ps-el-three/>
<ps-el-four/>
I want to be able to query all of the elements which begin with "ps-" with either a CSS selector or javaScript.
I whipped up the following solution, but I am wondering if there is anything more efficient?
var allElementsOnPage = document.querySelectorAll('*');
var res = [];
for (var index in allElementsOnPage) {
var el = allElementsOnPage[index];
if (el && el.tagName && el.tagName.substr(0, 3) == 'PS-') {
res.push(el);
}
}
This solution seems very inefficient.
I'm not aware of any element selector, but it is possible with CSS3 attribute and class substring-matching selectors (which are supported in IE7+):
[class^="tocolor-"], [attr*=" tocolor-"] {
color:red
}
Not sure if this is what you want, but probably gives you another way of achieving the same.
Check this here
<input name="man-news">
<input name="milkman">
<input name="letterman2">
<input name="newmilk">
<script>
$( "input[name*='man']" ).val( "has man in it!" );
</script>
You can use something like this instead of querySelectorAll
function myFunction() {
var x = document.getElementsByTagName("*");
var res = [];
for(var i = 0; i < x.length; i++) {
if(x[i].tagName.indexOf('PS-') == 0) {
res.push(x[i]);
}
}
}
Just give a class to all the elements common in nature. and do:
HTML
<ps-el-one class="ps"/>
<ps-el-two class="ps"/>
<ps-el-three class="ps"/>
<ps-el-four class="ps"/>
CSS
// for all elements together
.ps { /* css for all elements together */ }
// for individual elements
.ps:nth-of-type(1) { /* css for 1st ele */ }
.ps:nth-of-type(2) { /* css for 2nd ele */ }
.ps:nth-of-type(3) { /* css for 3rd ele */ }
.ps:nth-of-type(4) { /* css for 4th ele */ }
JS
// for all elements together
var ps = document.querySelectorAll('.ps');
// for individual elements
var ps1 = document.querySelectorAll('.ps')[0];
var ps2 = document.querySelectorAll('.ps')[1];
var ps3 = document.querySelectorAll('.ps')[2];
var ps4 = document.querySelectorAll('.ps')[3];
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.
I have a page full of links and they're paired. What I would like to do is once I've clicked a question mark (for help) the first 2 pairs are selected, then the next 2 and so on. The problem is that the links are created randomly on the page. I have the following code which selects the first link and its pair.
$(".main .container a:first").css("color", "#0c0");
var valid = $(".main .container a:first").attr("class").split(" ");
var links = $(".main .container a");
for (i = 0; i < links.length; i ++) {
var attributes = $(links[i]).attr("class").split(" ");
if (attributes[1] == valid[1]) {
$(links[i]).eq(0).css("color", "#0c0");
}
}
EDIT:
$(".help a").on("click", function()
{
var unchecked = $(".main .container a:not(.selected)");
var valid = unchecked.eq(0).attr("class").split(" ");
var links = $(".main .container a");
unchecked.eq(0).addClass("selected");
for (i = 0; i < links.length; i ++) {
var attributes = $(links[i]).attr("class").split(" ");
if (attributes[1] == valid[1]) {
$(links[i]).eq(0).addClass("selected");
}
}
});
Looks like you can simply manage that by adding a CSS class to the elements that were already "selected".
Check this simple test I did at JSFiddle: http://jsfiddle.net/L4rUM/1/
// When you click the "?"
$('button#btnHelp').on('click', function(){
// Gathers the list of ALL <a> elements that were not "selected" yet
var uncheckeds = $('.main .container > a:not(.selected)');
// If you have at least 2 available elements
if(uncheckeds.size() > 1){
// Adds the .selected CSS class to first 2 non-selected elements
uncheckeds.eq(0).addClass('selected');
uncheckeds.eq(1).addClass('selected');
}
});
And the CSS manipulation you are doing is now controlled by just adding the CSS class:
.selected { color: #0c0; }
I hope this helps and solve your problem :)
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.