Select all 'a' elements from a page? - javascript

I want to select a link with some text then I put:
$("a[text='some text']")
But didn't work, then I want to test selecting all links from a page.
$("a")
But this jquery select instruction only gave me the first or maybe the most important link of the page.
Why?
An example is here:
Thanks in advance.

Coding Horror does not make use of jQuery: there is no reference to the library in the source. If you tried jQuery('a') instead, you would receive an error stating that jQuery is not defined or it is not a function.
The reason $('a') works anyway, but only returns the first element, is because $ is defined within Chrome's developer console, but as an alias of document.querySelector. This native method only returns the first matching element if any, unlike document.querySelectorAll which returns all matching elements.
There is a different command aliased to document.querySelectorAll and that is $$. Calling either one will yield all (256) elements matching the selector string:
> $$('a')
NodeList[256]
> document.querySelectorAll('a')
NodeList[256]
Both $ and $$ are documented here.

the page doesnt actually have jQuery on it. Type $ or window.$ into the console. by typing $('a') you are using the chrome Command Line API. https://developers.google.com/chrome-developer-tools/docs/commandline-api

Related

Why does the jquery selector ("id,id") selects all elements with duplicate IDs

I came across some year old code written by a good developer (yes, I knew him personally) to access all elements having the same id.
$("#choice,#choice")
It returns all elements having the id. But if we use the below
$("#choice")
It returns only the first match, as expected.
After searching for some time, I'm unable to figure out any official links pointing to his technique, as to how it selected all elements with duplicate id.
Can anyone please explain how is this working ?
UPDATE
Please see the question is not about what alternative to use. I'm aware of classSelectors and attributeSelectors and know having duplicate IDs is not recommended, but sometimes you just have to live with years old code the way it is (if you know what I mean).
http://jsbin.com/zodeyexigo/1/edit?html,js,output
If you look at the code of sizzle.js that jQuery uses for selecting elements based on selector you will understand why this happens. It uses following regex to match simple ID, TAG or class selector:
// Easily-parseable/retrievable ID or TAG or CLASS selectors
rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
but as the selector in question is $("#ID,#ID") it does not match with the selector and uses querySelectorAll (line no 270 in ref link), which replaces selector to "[id='" + nid + "'] " (line no 297 in ref link) which selects all the elements with matching ID.
However, I agree with the other people in this thread, that it is not good idea to have same ID for multiple elements.
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 tag selector, like this:
$('span[id="a"]');
Having duplicated id on the page making your html not valid . ID is unique identifier for one element on the page (spec). Using classes, that are classify similar elements that's your case and $('.choice') will return set of elements
So in JS Fiddle i have shown an example of what jQuery is doing.
https://jsfiddle.net/akp3a7La/
When you have a
$('#choice,#choice');
It is actually getting all the instances of the objects #choice twice, and then filtering out any duplicates.
in my example i show you how it does that also when you have something like this
$("#choice,li");
Where items are actually your #choice items.
In the Jquery Documentation
https://api.jquery.com/multiple-selector/
it talks about multiple Selectors, which is what i think is happening here, your developer friend is selecting the same ID twice, and it would be returning it twice. as you can only have one input with the same ID once on a page (good html syntax)

JavaScript: addEventListener not running

Learning Javscript and trying to trigger a click event.
I'm not sure what I'm doing wrong but the following doesn't seem to work.
JSFiddle
http://jsfiddle.net/73e7H/1/
HTML
<ul>
<li id="nav-item-39">
Visit
</li>
<ul>
JS
var $visit = document.getElementById('nav-item-39').firstChild;
$visit.addEventListener('click', function() {
print('hello');
});
The firstChild is a text node containing the whitespace after the end of the li start tag and the beginning of the link. You need the first child that's an element.
On many browsers, that's firstElementChild, but if you need support for older browsers you may need a loop.
Fiddle (using alert rather than print)
Another option is to use querySelector, which is available on all modern browsers (even IE8 — but of course, IE8 doesn't have addEventListener):
var $visit = document.querySelector('#nav-item-39 a');
$visit.addEventListener('click', function() {
print('hello');
});
That finds the first a element that's a descendant of #nav-item-39. If you want to require that it's a direct child instead, use the selector string "#nav-item-39 > a" instead.
Fiddle
(Just for completeness: querySelector finds the first matching element and returns it [or null if no match]. There's also querySelectorAll which finds all matching elements and returns a static NodeList.)
Side note: print, unless you override it (and I don't think you do in the fiddle), is window.print which opens the browser's Print dialog.
Try Using firstElementChild instead of firstChild.
firstElementChild will defenitely return element, when firstChild can return text node also.

jQuery: Refreshing an element

I'm using this accordion-like script:
jQuery(document).ready(function () {
jQuery(".content").hide();
jQuery(".heading").click(function () {
jQuery(this).next(".content").slideToggle(500)
});
});
But then I add this line in order to reload the element after the content div toggles...
document.getElementsByClassName(transition current).reload();
and as a result, the accordion no longer works... The content class is always being displayed.
Why is this line affecting the behavior of the accordion?
I'm trying to refresh the element while retaining the accordion style divs...
Any ideas?
You need to use event delegation since the elements are created dynamically
jQuery(function ($) {
$(".content").hide();
$(document).on('click', ".heading", function () {
$(this).next(".content").stop(true, true).slideToggle(500)
});
});
Still you might have a problem of all content element getting displayed once the element is reloaded, for hiding those elements you need to use any load callback system provided by the reloader you are using
You've got a syntax error here:
document.getElementsByClassName(transition current).reload();
getElementsByClassName expects a string to be passed (not to mention that the above isn't syntactically correct even if it did expect two arguments). You're trying to pass two variables (which you haven't defined). Pass a string:
document.getElementsByClassName('transition current').reload();
Blast. That doesn't work either! Reading the docs informs us that getElementsByClassName returns an HTMLCollection, which doesn't have the method reload(), resulting in another error. Are you even looking at the console?
You may be assuming that getElementsByClassName returns a jQuery object, in which case you can replace the above with $('.transistion, .current').reload();
Again, let's note that reload() isn't a native jQuery method either. I'm assuming you're bringing it in via a plugin. If I'm wrong, comment below and I'll update the answer.
I was using the isotype jQuery plugin, so the issue was resolved by adding this one line as a callback to "relayout" any changes that were loaded into the DOM.
$('#blog-list').isotope('reLayout');

How to click and navigate on a new page programatically using javascript

I want to click on link on a page and navigate to a new page. I used following code for it :
document.getElementsByClassName('classname').click();
I used classname as it dont have id. document.getElementsByClassName('classname') works fine. But use of click() returns :
TypeError: document.getElementsByClassName(...).click is not a function
Why I am getting this error? I read in couple of answers in stackoverflow that click() works fine. I am using this code in firebug console of firefox.
If click() won't work, what other options I have?
document.getElementsByClassName returns an array of elements, so you have to specify the index:
document.getElementsByClassName('classname')[0].click();
As a side note, programatically clicking an element doesn't run the native behavior, it runs the assigned click handlers for said element.
Use
document.getElementsByClassName('classname')[0].click();
Returns a set of elements which have all the given class names. When called on the document object, the complete document is searched, including the root node. You may also call getElementsByClassName on any element; it will return only elements which are descendants of the specified root element with the given class names.
Reference

Prototype.js get text from an element

I'm new to Protoype.JS and just testing it a bit because I heard it was good, but I'm stuck quite quickly.
As easy as this is with jQuery, it seems to be the end of the world to get the text in an element. I've tried innerHTML in multiple ways but the only thing I can get is "undefined".
alert($$('.mnu_item').innerHTML);
alert($('content').innerHTML);
None of these work.
Content is a div with id "content" and .mnu_item is an anchor tag with class ".mnu_item".
I don't get what the problem is, probably something stupid but it would be great if somebody could point me in the right direction!
EDIT: I've found that it isn't the innerHTML that doesn't work but it's the class selector. The second line in the code above does work. How can I select an element by its class in the latest Prototype version if this isn't the correct way?
Has the DOM loaded when you run your script? If you're not running this code in a window.onload or by placing it at the end of the body, then the elements by not exist when it runs.
Try placing your script just inside the closing </body> tag.
<body>
<!-- my content -->
<script type="text/javascript">
alert($('content').innerHTML);
</script>
</body>
Also, your first line is selecting correctly, but will return an Array of elements, so innerHTML will be undefined.
To iterate the Array, you can do this:
$$('.mnu_item').each(function(val,i) {
alert(val.innerHTML);
});
or if you want to end up with an Array of the innerHTML values, do this:
var values = $$('.mnu_item').map(function(val,i) {
return val.innerHTML;
});
Make sure the DOM is loaded before you run these tests:
$(document).on('dom:loaded', function () {
/* code to execute after dom has loaded */
})
The first line of code $$('.mne_item') doesn't work because $$ gives back an array of all elements matching the css rule. So $$('.mne_item') gives an array of all dom elements which has the class mne_item. You can ask the first one by using the first method or iterate over all items like this:
$$('.mne_item').each(function(elem) {
// elem is the li elements extended by all Element methods of prototype
});
If you use $ in jQuery, it actually uses a similar pattern but hides the each construct. It just applies the chained method to all elements or just the first.
The second line of code $('content').innerHTML should work. $ is a shortcut for document.getElementById so it should give you a DOM node back. The reason why this doesn't work is there is no node where id = content, probably because the dom isn't loaded yet.
For more info about the methods of prototype look at the api: http://api.prototypejs.org/
Also check the default DOM methods: http://quirksmode.org/dom/w3c_core.html
$('content').innerHTML should work. Check your HTML, ensure the ID is unique.
var text = $$('label[for="display_on_amazon"]').first().textContent;
Above code worked for me.
Regarding, $$('.mnu_item').innerHTML
When you are trying to fetch with class selector, prototype returns array of multiple elments, by using [0] or first() method system will point at the first element in that array, after that you can use innerHtml (to get html inside the element) or textContent (to get text content of that element, native javascript method)

Categories