Getting all selectors and printing its value to console - javascript

I am on the following site : Betway and want to extract via a query all the values from the selector collectionitem with the class oneLineEventItem.
I can partially get this with the following:
document.querySelectorAll("div[collectionitem] ~ .oneLineEventItem").forEach((result) => {
console.log(result)
})
However I have noticed the following issues with this:
It selects n-1 such that the first is not selected.
It prints the node tree and not just the values.
How do I correctly select all and print the values out?

Using the General sibling combinator (~) is not the good approach. To select all div elements having the attribute collectionitem and the class oneLineEventItem you should use the following selector :
div[collectionitem].oneLineEventItem
Then, as I said in my comment, you can get the value of the collectionitem attribute using the getAttribute() method :
document.querySelectorAll("div[collectionitem].oneLineEventItem").forEach((result) => {
console.log(result.getAttribute("collectionitem"));
})
<div collectionitem="test1" class="oneLineEventItem">foo</div>
<div collectionitem="test2" class="oneLineEventItem">bar</div>

Related

Find css class on div and get values

I'm trying to find a class on a div (where the value will always end in 0bg), given a partial string, and then get its background style value.
For example:
.xx-color-100bg{
background-color: #323334;
}
<div class="heading xx-color-100bg"></div>
document.querySelectorAll(".heading").classList.contains("0bg").style.background
The solution above errors with Cannot read properties of undefined (reading 'contains')
How can I find the necessary class and grab it's background-color value?
querySelectorAll() returns a NodeList, so you can't use classList. You need to loop over the DOMElements in the list or just assume the first one is what you need:
document.querySelectorAll(".heading").forEach(e => {
// do something with e.classList
});
// OR
document.querySelectorAll(".heading")[0].classList // the first element
Figured out the solution right after posting the question:
window.getComputedStyle(document.querySelector(".heading[class*='0bg'")).backgroundColor;

Why does jQuery return more than one element when selecting by type and ID? [duplicate]

I fetch data from Google's AdWords website which has multiple elements with the same id.
Could you please explain why the following 3 queries doesn't result with the same answer (2)?
Live Demo
HTML:
<div>
<span id="a">1</span>
<span id="a">2</span>
<span>3</span>
</div>
JS:
$(function() {
var w = $("div");
console.log($("#a").length); // 1 - Why?
console.log($("body #a").length); // 2
console.log($("#a", w).length); // 2
});
Having 2 elements with the same ID is not valid html according to the W3C specification.
When your CSS selector only has an ID selector (and is not used on a specific context), jQuery uses the native document.getElementById method, which returns only the first element with that ID.
However, in the other two instances, jQuery relies on the Sizzle selector engine (or querySelectorAll, if available), which apparently selects both elements. Results may vary on a per browser basis.
However, you should never have two elements on the same page with the same ID. If you need it for your CSS, use a class instead.
If you absolutely must select by duplicate ID, use an attribute selector:
$('[id="a"]');
Take a look at the fiddle: http://jsfiddle.net/P2j3f/2/
Note: if possible, you should qualify that selector with a type selector, like this:
$('span[id="a"]');
The reason for this is because a type selector is much more efficient than an attribute selector. If you qualify your attribute selector with a type selector, jQuery will first use the type selector to find the elements of that type, and then only run the attribute selector on those elements. This is simply much more efficient.
There should only be one element with a given id. If you're stuck with that situation, see the 2nd half of my answer for options.
How a browser behaves when you have multiple elements with the same id (illegal HTML) is not defined by specification. You could test all the browsers and find out how they behave, but it's unwise to use this configuration or rely on any particular behavior.
Use classes if you want multiple objects to have the same identifier.
<div>
<span class="a">1</span>
<span class="a">2</span>
<span>3</span>
</div>
$(function() {
var w = $("div");
console.log($(".a").length); // 2
console.log($("body .a").length); // 2
console.log($(".a", w).length); // 2
});
If you want to reliably look at elements with IDs that are the same because you can't fix the document, then you will have to do your own iteration as you cannot rely on any of the built in DOM functions.
You could do so like this:
function findMultiID(id) {
var results = [];
var children = $("div").get(0).children;
for (var i = 0; i < children.length; i++) {
if (children[i].id == id) {
results.push(children[i]);
}
}
return(results);
}
Or, using jQuery:
$("div *").filter(function() {return(this.id == "a");});
jQuery working example: http://jsfiddle.net/jfriend00/XY2tX/.
As to Why you get different results, that would have to do with the internal implementation of whatever piece of code was carrying out the actual selector operation. In jQuery, you could study the code to find out what any given version was doing, but since this is illegal HTML, there is no guarantee that it will stay the same over time. From what I've seen in jQuery, it first checks to see if the selector is a simple id like #a and if so, just used document.getElementById("a"). If the selector is more complex than that and querySelectorAll() exists, jQuery will often pass the selector off to the built in browser function which will have an implementation specific to that browser. If querySelectorAll() does not exist, then it will use the Sizzle selector engine to manually find the selector which will have it's own implementation. So, you can have at least three different implementations all in the same browser family depending upon the exact selector and how new the browser is. Then, individual browsers will all have their own querySelectorAll() implementations. If you want to reliably deal with this situation, you will probably have to use your own iteration code as I've illustrated above.
jQuery's id selector only returns one result. The descendant and multiple selectors in the second and third statements are designed to select multiple elements. It's similar to:
Statement 1
var length = document.getElementById('a').length;
...Yields one result.
Statement 2
var length = 0;
for (i=0; i<document.body.childNodes.length; i++) {
if (document.body.childNodes.item(i).id == 'a') {
length++;
}
}
...Yields two results.
Statement 3
var length = document.getElementById('a').length + document.getElementsByTagName('div').length;
...Also yields two results.
What we do to get the elements we need when we have a stupid page that has more than one element with same ID? If we use '#duplicatedId' we get the first element only. To achieve selecting the other elements you can do something like this:
$("[id=duplicatedId]")
You will get a collection with all elements with id=duplicatedId.
From the id Selector jQuery page:
Each id value must be used only once within a document. If more than one element has been assigned the same ID, queries that use that ID will only select the first matched element in the DOM. This behavior should not be relied on, however; a document with more than one element using the same ID is invalid.
Naughty Google. But they don't even close their <html> and <body> tags I hear. The question is though, why Misha's 2nd and 3rd queries return 2 and not 1 as well.
If you have multiple elements with same id or same name, just assign same class to those multiple elements and access them by index & perform your required operation.
<div>
<span id="a" class="demo">1</span>
<span id="a" class="demo">2</span>
<span>3</span>
</div>
JQ:
$($(".demo")[0]).val("First span");
$($(".demo")[1]).val("Second span");
Access individual item
<div id='a' data-options='{"url","www.google.com"}'>Google</div>
<div id='a' data-options='{"url","www.facebook.com"}'>Facebook</div>
<div id='a' data-options='{"url","www.twitter.com"}'>Twitter</div>
$( "div[id='a']" ).on('click', function() {
$(location).attr('href', $(this).data('options').url);
});
you can simply write $('span#a').length to get the length.
Here is the Solution for your code:
console.log($('span#a').length);
try JSfiddle:
https://jsfiddle.net/vickyfor2007/wcc0ab5g/2/

Select all the elements within an element having an attribute set to a specific value

I have the followings defined :
var excludedFiltersPanel = $("#excludedFiltersPanel");
var includedfiltersPanel = $("#includedfiltersPanel");
where *Panel is just a div.
in excludedFiltersPanel there are some div's with attribute data-iscorefilter="true" e.g. :
<div id="filterPanel-LastName" class="filterPanel" data-iscorefilter="true">
<Some Stuff here!>
</div>
I am trying to get them and move them to includedfiltersPanel:
It seems neither of these is a correct syntax:
excludedFiltersPanel.('[data-iscorefilter="true"]')
excludedFiltersPanel.$('[data-iscorefilter="true"]')
1.What is the correct syntax?
2.How do I append them to includedfiltersPanel? (I know how to append a single item, but not sure what is the common good practice here, e.g. using for loop or some JQuery magic)
Since excludedFiltersPanel there are some div's with attribute data-iscorefilter="true"
Use .find()
Description: Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
It would look like :
excludedFiltersPanel.find('[data-iscorefilter="true"]')

How to using ng-repeat select all element, but without some class

How can I use ng-repeat to select all elements but exclude all of them which have a class bookmaker-disabled.
Screen shot
I am using: element.all(by.repeater('bookmaker in vm.bookmakers'))
What needs to be added here to get a result without elements with class bookmaker-disabled?
From looking at your screenshot, you add class 'bookmaker-disabled' when bookmaker.disabled is true. Well as per your code, you could add an ng-if="!bookmaker.disabled" to show only when not disabled, and remove elements which has disabled. In which case you needn't add the class.
Alternatively you could filter out those results which has bookmaker disabled, eg:
<div ng-repeat='bookmaker in vm.bookmakers | filter: {disabled: false}'>
Or you could use map reduce inside your controller if that was what you were looking for.
If you are using protractor, This might work:
element.all(by.repeater('bookmaker in vm.bookmakers')).filter(function(elem, index) {
return elem.getAttribute('class').then(function(classes) {
return classes.indexOf('bookmaker-disabled') === -1;
});
})

jQuery Advance Selector Using Wildcards

I have an input element which id looks like:
Les_Site_1381400656_43306_input
The ID format will always be Les_Site_ANYTHING_INPUT
My current selector is: $(element).find('[id^=Les_Site_input]')
How do I i make a selector which says i want this at the start anything in the middle and this at the end?
Thanks
// starts with "Les_Site_" , ends with "_input" :
$(element).find('[id^=Les_Site_][id$=_input]')
Note that such filtering rules are slow, you want to call them on as few elements as possible :
$(element).find('input').filter('[id^=Les_Site_][id$=_input]')
The way you seem to be using ids : you would have a better time adding a class to this input, and select it using that class
<input class="siteInput" id="Les_Site_1381400656_43306_input" />
$(element).find('input.siteInput')

Categories