Can't fire click event on the elements with same id - javascript

Could you help me to understand - where I made the mistake. I have the following html code:
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
and the following js code (using jQuery):
$('#getInfo').click(function(){
alert('test!');
});
example here
"Click" event fired only on first link element. But not on others.
I know that each ID in html page should be used only one time (but CLASS can be used a lot of times) - but it only should (not must) as I know. Is it the root of my problem?
TIA!
upd: Big thx to all for explanation!:)

Use a class for this (and return false in your handler, not inline):
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
$('.getInfo').click(function(){
alert('test!');
return false;
});
http://jsfiddle.net/Xde7K/2/
The reason you're having this problem is that elements are retrieved by ID using document.getElementById(), which can only return one element. So you only get one, whichever the browser decides to give you.

While you must, according to the W3 specifications, have only one element with a given id within any document, you can bypass this rule, and the issues arising from the consequences if document.getElementById(), if you're using jQuery, by using:
$('a[id="getInfo"]').click(function() {
alert('test!');
return false;
});
JS Fiddle demo.
But, please, don't. Respect the specs, they make everybody's life easier when they're followed. The above is a possibility, but using html correctly is much, much better for us all. And reduces the impact of any future changes within the browser engines, jQuery or JavaScript itself.

It must only be used once or it will be invalid so use a class instead, return false can also be added to your jQuery code as so: -
$('.getInfo').click(function(){
alert('test!');
return false;
});
<a href="#info-mail.net" **class**="getInfo" ....

First id's are for one element only, you should have same id for several divs.
you can make it class instead.
your example changed:
<div class="container">
<a href="#info-mail.ru" class="getInfo" >Info mail.ru</a>
</div>
<div class="container">
<a href="#info-mail.com" class="getInfo" >Info mail.com</a>
</div>
<div class="container">
<a href="#info-mail.net" class="getInfo" >Info mail.net</a>
</div>
$('.getInfo').click(function(ev){
ev.preventDefault(); //this is for canceling your code : onClick="return false;"
alert('test!');
});

You can use the same id for several element (although the page won't validate), but then you can't use the id to find the elements.
The document.getElementById method only returns a single element for the given id, so if you would want to find the other elements you would have to loop through all elements and check their id.
The Sizzle engine that jQuery uses to find the elements for a selector uses the getElementById method to find the element when given a selector like #getInfo.

I know this is an old question and as everyone suggested, there should not be elements with duplicate IDs. But sometimes it cannot be helped as someone else may have written the HTML code.
For those cases, you can just expand the selector used to force jQuery to use querySelectorAll internally instead of getElementById. Here is a sample code to do so:
$('body #getInfo').click(function(){
alert('test!');
});
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<div id="container">
Info mail.ru
</div>
<div id="container">
Info mail.com
</div>
<div id="container">
Info mail.net
</div>
</body>
However as David Thomas said in his answer
But, please, don't. Respect the specs, they make everybody's life easier when they're followed. The above is a possibility, but using html correctly is much, much better for us all. And reduces the impact of any future changes within the browser engines, jQuery or JavaScript itself.

Related

Understanding the usage of get() in my sorting script

I recently found a code snippet that I would really like to understand:
var buttons = $('#fruit,#vegetable,#meat').click(function() {
$(this).toggleClass('active');
var classes = buttons.filter('.active').map(function() {
return this.id;
}).get().join(',.');
$('div.fruit,div.vegetable,div.meat').hide().
filter('.' + (classes || 'none')).show();
});
The HTML code :
<div style="float:right; padding:25px;">
<button id="fruit" class="active"><span>fruit</span></button>
<button id="vegetable" class="active">vegetable</button>
<button id="meat" class="active">meat</button>
</div>
<div>
<p>Trying to use buttons as an "or" case rather than "and." When choosing fuit or vegetable, I want to see tomato as part of each list, <em>not just</em> when both are selected.</p>
<div class="fruit">
<p>apple</p>
</div>
<div class="vegetable">
<p>pumpkin</p>
</div>
<div class="vegetable">
<p>okra</p>
</div>
<div class="fruit">
<p>orange</p>
</div>
<div class="meat">
<p>beef</p>
</div>
<div class="fruit vegetable">
<p>tomato</p>
</div>
</div>
The fiddle is here.
I do understand how all the methods work in jQuery like toggleclass, filter and map, I also understand how join works in JS, but in this particular example, I am not able to figure out how get() is working or rather what is it's usage in the script is.
I went through the jQuery documentation for get() and I came across this method for the first time; to me, it seems it's very much similar to eq() in jQuery, but I am still not able to figure out why exactly get is being used in my example.
Can somebody explain this to me ?
.get is used here, because .map returns a jquery style object which contains some functions and information about the contained data. But in this scenario only the values stored within the object (the class names of the active buttons) are wanted. .get is used to get an array containing the raw values and with .join(",.") the values from the array get concatenated to a string. This string then get's used to show all div's that should be active according to the selected buttons.

Storing object ID in HTML document: id vs data-id vs?

I would like to have an opinion on storing RESTful object IDs in document for accessing it later from JavaScript.
Theoretically speaking using id for addressing elements in HTML doesn't cut it anymore. Same element can be repeated twice on the page say in "Recent" and "Most Popular" queries which breaks the main point of using id.
HAML even has this nice syntax sugar:
%div[object]
becomes:
<div class="object" id="object_1">
But like I said, seems that it is not a good approach. So I am wondering what is the best way to store objects id in DOM?
Is this the current proper approach?
<div data-id="object_1">
An ID is intended to uniquely identify an element, so if you have a case where you want to identify two or more elements by some common identifier, you can use ID but it may not be the best option in your case.
You can use IDs like:
<div id="d0">Original Div</div>
<div id="d0-0">Copy of original div</div>
<div id="d1">Another original Div</div>
<div id="d1-0">Another copy of original div</div>
<div id="d1-1">Another copy of original div</div>
and get all the d1 elements using:
document.querySelectorAll('[id^=d1]');
or just d1 divs:
document.querySelectorAll('div[id^=d1]')
You could also use a class:
<div id="d0" class="d0">Original Div</div>
<div id="..." class="d0">Copy of original div</div>
<div id="d1" class="d1">Another original Div</div>
<div id="..." class="d1">Another copy of original div</div>
<div id="..." class="d1">Another copy of original div</div>
and:
document.querySelectorAll('.d1')
Or use data- attributes the same way. Whatever suits.
You can also have a kind of MVC architecture where an object stores element relationships through references based on ID or whatever. Just think outside the box a bit.
The purpose why data-selectors where introduces is because the users neednt want to use class or anyother attributes to store value.Kindly use data-selectors itself. In order to make it easy to access them use attributes selector i.e. [attribute='value']. PFB the fiddle for the same and also the example
jsfiddle
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-git2.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body onload="call()">
<div id="1" data-check='1'></div>
<div id="2" data-check='1'>sdf</div>
<div data-check='1'>sdf</div>
<div data-check='1'>sdf</div>
<div data-check='1'>sdf</div>
</body>
</html>
function call()
{
$("#1").html($('[data-check="1"]').length);
$("#2").html( document.querySelectorAll('[data-check="1"]').length);
}
Output: 5 5 sdf sdf sdf
#RobG is right by using 'class' you can get array of elements in JavaScript as-
var divs=document.getElelementsByClassName("className");
\\And you can loop through it(`divs[i]`).
AND according to #RobG and #Barmar data-* attribute is also a good option.
But here is some point(just point, not negative or positive, its totally depends on your application need) I want to discuss:
1] data-* element is HTML5's new attribute. Documentation
2] To retrieve elements in javascript, You need to use jQuery or more bit of JavaScript, coz all direct function available have specific browser support:
Like document.querySelector("CSS selector"); IE8+
document.getElementsByClassName("className"). IE9+
document.querySelectorAll("CSS selector"); etc.
So, basically for this point you need to choose according to your app need and browser compatibility.
3] Performance issue is also there on selecting by data-* attribute... Source
But, generally and if we go for latest application and selecting HTML5, data-* attribute + jQuery is a good option.
I was wondering about this too. Here's my POV using an example component.
CSS - styling across all buttons
Elements should not be referenced in JS using CSS classes because if you have multiple buttons that need to function differently, adding unique CSS classes for each component will get messy.
<div class="my-component">
JS - Grab the component when it can only appear once on a page
While browsers may handle multiple id okay, it would harm maintenance since this would be unexpected behavior from an id.
<div id="my-component">
const myComponent = document.querySelector('#my-component')
JS - Grab the component when it can appear multiple times on a page
ref or data-id could both work. ref has been popularized by React and Vue, so it may be more familiar to developers.
<div ref="my-component">
const myComponents = document.querySelectorAll('[ref="my-component"]')
or
<div data-id="my-component">
const myComponents = document.querySelectorAll('[data-id="my-component"]')

Extract all classes from body element of AJAX-ed page and replace current page's body classes

I am in the process of AJAX-ing a WordPress theme with a persistent music player. Wordpress uses dynamic classes on the <body> tag. The basic structure is as follows:
<html>
<head>
</head>
<body class="unique-class-1 unique-class-2 unique-class-3">
<div id="site-container">
<nav class="nav-primary">
Other Page 01
Other Page 02
</nav>
<div class="site-inner">
<p>Site Content Here</p>
</div>
</div>
<div id="music-player"></div>
</body>
</html>
I am currently successfully loading the content of /other-page-01/, /other-page-02/, etc, using load('/other-page-01/ #site-container'). However, I need to extract all <body> classes from the AJAX loaded page and replace the current page's <body> classes with them dynamically.
Note: Replacing the entire <body> element is not an option due to the persistent <div id="music-player">. I've tried jQuery.get(), but couldn't get it to work.
How do I extract the <body> classes from the AJAX requested page and replace the current page's <body> classes with them?
I am not very familiar with jQuery or Javascript, so the exact code would be extremely helpful. Any help is greatly appreciated.
Thanks,
Aaron
My typical solution would have been to tell you to throw the AJAX code in to a jQuery object and then read it out like normal:
$(ajaxResult).attr('class');
Interestingly though, it appears you can't do this with a <body> element.
I'd say the easiest solution (if you have control over the resulting HTML) is to just use some good ol' regex:
var matches = ajaxResult.match(/<body.*class=["']([^"']*)["'].*>/),
classes = matches && matches[1];
I say "if you have control over the resulting HTML", because this relies on the HTML being reasonably well formed.
The other method would involve parsing it as a DOMDocument and then extracting what you need, but this would take a lot more and is usually overkill in simple cases like this.
Convert the body within your returned html to a div with a specific ID, then target that id to get the classes of the body (which is now a div.)
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("#re_body").attr("class");
Of course, if the body has an id, this will conflict with it, so an arbitrary data attribute might be less likely to break.
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class");
http://jsfiddle.net/N68St/
Of course, to use this method, you'll have to switch to using $.get instead.
$.get("/other-page-01/",function(ajaxResult){
var modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
alert($(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class"));
// the following line replicates what `.load` was doing.
$(someElement).append( $("<div>").html(ajaxResult).find("#site-container") );
});

Get onClick element to return to the main element?

I'm awful with javascript and I'm having a problem with this one.
I'm using this code
<script>
function changeNavigation(id){
document.getElementById('members')
.innerHTML=document.getElementById(id).innerHTML
}
</script>
and HTML
`<span onClick="changeNavigation('members')" >MEMBERS</span>
<span onClick="changeNavigation('help')" >HELP</span>`
<div id="members>...</div>
<div id="help" style="display: none;>...</div>
But I can't get <span onClick="changeNavigation('members')" >MEMBERS</span> to actually go to an element "members" without duplicating everything inside of it in another id.
Is there a way to do this?
This can be done using only standard javascript, but personally I'd recommend going ahead and getting used to using jQuery. Here's an example jsfiddle using jQuery: http://jsfiddle.net/JnvCR/2/
Don't forget to include jQuery in your website:
<script src="http://code.jquery.com/jquery.js"></script>
You need to correct your syntax errors. Use onclick instead of onClick (pedantic). Make sure you close your attributes properly, you are missing a few closing " marks.
updated html
<span onclick="changeNavigation('members')" >MEMBERS</span>
<span onclick="changeNavigation('help')" >HELP</span>`
<div id="members">...</div>
<div id="help" style="display: none;">...</div>
There is also an error with your logic as you are simply replacing the contents of div#members with itself.
Updated JS without syntax errors, but still with dodgy logic
function changeNavigation(id){
document.getElementById('members').innerHTML=document.getElementById(id).innerHTML;
}
Demo fiddle
http://jsfiddle.net/ADGCV/
As far as your actual question goes, can you explain what you would like to happen a bit better??
Here's a possible solution http://jsfiddle.net/ADGCV/1/

How to select an object in JQuery?

I'm beginner in JQuery, how could I select an object using JQuery ?
This is the code:
<script type="text/javascript" language="javascript">
function Hide(senderID) {
$("#" + senderID).hide(200);
// this exception is thrown // Microsoft JScript runtime error: Object expected
}
</script>
<div id="div1" onclick="javascript:Hide(this.id)"
Any help!
Don't:
get an id from an element
pass that id to a function
use the id to get the element.
Do: Just pass the element.
Don't stick javascript: at the front of an intrinsic event attribute, it doesn't mean what you think it means.
Don't use intrinsic event attributes for that matter (although I didn't fix this in this example). Use unobtrusive JS.
Avoid triggering events based on clicks on a div. This can't be targeted with a focus based navigation device (such as using the tab key on the keyboard and numerous devices used by people with disabilities) without using new features introduced in HTML 5 that don't see widespread support yet. Use an element that is designed as an interaction control (such as a button). (Also not fixed in the example below)
Example:
function Hide(sender) {
$(sender).hide(200);
}
<div id="div1" onclick="Hide(this)"
Code is exactly the same as yours, I added the correct tags, and the call to include the jquery library:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script>
function Hide(senderID) {
$("#" + senderID).hide();
}
</script>
<div id="div1" onclick="javascript:Hide(this.id)">Click Me</div>
function Hide(sender) {
$(sender).hide(200);
}
<div id="div1" onclick="javascript:Hide(this)"></div>
hope it helps
I can't resist. Why not use jQuery's full power?
HTML:
<div class="hideable-div">Click me and get rid of me.</div>
jQuery:
$('.hideable-div').click(function () {
$(this).hide(200);
});
you misplaced those "" in
<div id="div1" class=""hideable-div>Click me and get rid of me.</div>
Should be like
<div id="div1" class="hideable-div">Click me and get rid of me.</div>

Categories