JQuery select children based on more than one class from parent element
I have just started with JQuery and I need to change the css class of two elements and remove their onclick event handlers.
When any of the three elements in the div with class upDown is clicked, a popup appears. When a button in that popup is clicked, vote_click() is called.
I need to disable the elements with classes "up" and "down", but no others.
<div class="upDown">
<div class="up" id="ctl04_btnUp" onclick="lastClick=this;" ></div>
<div class="com" id="ctl04_btnCom" onclick="lastClick=this;"></div>
<div class="down" id="ctl04_btnDown" onclick="lastClick=this;"></div>
</div>
Here is my attempt
var lastClick; //will be set to either the "up" or "down"
function vote_click() {
if (lastClick && lastClick.className != "com") {
$("#"+lastClick.parentElement.id + " > .up .down").each(
function(index, e) {
alert('disabled ' + this.id);
this.onclick = null;
this.className += '-ya';
}
);
开发者_C百科 lastClick = null;
}
}
I clearly have no idea what I'm doing so any general observations about my approach would be appreciated.
I hope the following code does what you intend:
(function($) {
var lastClick = null;
$('div.upDown .up, div.upDown.com, div.upDown.down').bind('click', function(e) {
lastClick = this;
});
function vote_click() {
if (lastClick && (lastClick.hasClass('up') || lastClick.hasClass('down')) {
$('div.upDown .up, div.upDown.down').each( function() {
var $this = $(this);
$this.unbind('click');
var c = $this.attr('class');
$this.removeClass(c).addClass(c + '-ya');
});
}
}
})(jQuery);
Note:
- The code gets rid of the
onclick
attributes in the HTML tags so that your JS is purely unobtrusive. - Because everything is wrapped in an anonymous function that is executed right away, it introduces no global variables, which is good for interoperability. Previously, the
lastClick
variable was global. - In your code,
$("#"+lastClick.parentElement.id + " > .up .down")
would select all elements with classdown
that are descendants of an element with classup
that is a child of the element with idlastClick.parentElement.id
. That is not what you want. You could write what you want more easily as$(lastClick).parent().find('.up, .down')
.
EDIT
A word on why onclick
is often undesirable: Personally, I don't like globals in JavaScript because all the JS code running in the page (possibly from several developers who don't communicate) share one global namespace. Event handlers declared by means of onclick
etc. often refer to globals (as in your case), so this is one reason for me to avoid them.
The second is that the code specified in an onclick
attribute runs in a special scope (or scope chain, to be precise). It does not run in the global namespace directly, but in a scope chain consisting of
- The element that triggered the event handler (here, the div element)
- The
document
object - Maybe anything in between (this is not specified)
- Finally, of course, the global object (
window
)
This can lead to unintended misunderstandings, like you call open()
and mean window.open()
, but what you get is document.open()
. In short, I prefer knowing exactly what my event handlers can and cannot see, and I think in bigger projects, strict separation of code parts and avoidance of global variables pays off. For smaller pieces of code and as long as you don't write novels in the onclick
attributes, using onclick
etc. is fine.
P.S.: Yes, it is shamefully obvious that I am using an example from Flanagan's "JavaScript - The Definitive Guide".
精彩评论