.not method fails? - javascript

I have written two jQuery functions, the simplified version of which run thus:
$('button.class').not('.selected').on('click', function() {
console.log('not selected');
console.log($(this));
$(this).addClass('selected');
}
$('button.class.selected').on('click', function() {
console.log('selected');
console.log($(this));
$(this).removeClass('selected');
}
Clicking on the button always logs the following in the console:
not selected
[<button class="someClass1 someClass2 selected">Text</button>]
The Web Inspector shows this before clicking on the button:
<button class="someClass1 someClass2">Text</button>
and this after clicking on it:
<button class="someClass1 someClass2 selected">Text</button>
Clicking on it again changes nothing.
Switching addClass() to toggleClass() succeeds in toggling 'selected' on and off, but still always logs not selected, which suggests something is going on with my selectors. Why is the first function always being called even when 'selected' is clearly one of the classes associated with the button element?
I noticed in testing some solutions that hard-coding 'selected' as a class of button results in the opposite problem: only second of the functions is ever called, even though toggleClass() works as intended. Do classes added via jQuery not "count" as classes?

The CSS selector is evaluated at the time you run it. I wouldn't expect that there are any elements matching $('button.class.selected') on page load, so your second handler is never executed, because it is never bound to anything.
What you should be doing is attaching event to some base selector such as $('button.class') and then doing filtering when event is fired.
$("button.class").on("click", function()
{
if ($(this).is(".selected"))
{
console.log('selected');
console.log($(this));
$(this).removeClass('selected');
}
else
{
console.log('not selected');
console.log($(this));
$(this).addClass('selected');
}
});
Either version works, but one might be more appropriate than the other, depending on what are you actually trying to do.
If all you are looking to do is to add/remove .selected on button click then this much simpler version will do the job
$("button.class").on("click", function() { $(this).toggleClass("selected"); });

Try changing :
$('button.class').not('.selected')
To:
$('button').not('.selected')
And :
$('button.class.selected')
To:
$('button.selected')

Related

Why does jquery not respond accordingly to my conditions?

I want my tablerows to have the class 'clickable' only if edit mode is turned on. With element inspect I can see that this works. It succesfully removes the 'clickable' class if I turn off edit mode.
If a table row has the class clickable it will click it's checkbox upon clicking the table row. This works too, however when I turn off edit mode, I'm still able to click tablerows and by doing so, also check the checkbox.
If you can see something that I've overlooked please let me know.
function clickableTableRow(isClickable) {
if (isClickable) {
$(tableBody).find('tr').each(function () {
$(this).addClass("clickable");
$(this).click(function () {
$(this).find('input[type=checkbox]').click();
});
})
} else {
$(tableBody).find('tr').each(function () {
$(this).removeClass("checked").removeClass("clickable");
$(this).find('input[type=checkbox]').prop("checked", false);
})
}
}
So to clarify, in element inspect I can see that it does all as it should, so I think the problem lays in the function where I make a checkbox click upon clicking on a tablerow
Use .off()
$(this).off('click');
The off() Method in jQuery is used to remove event handlers attached
with the on() method -or the .click() method. The off() method brings a lot of consistency to
the API and it replace unbind(), die() and undelegate() methods.
The event handler was still active, using .off() turns it off. Adding this line of code tot the else statement solved the issue:
$(this).off('click');

Chaining jquery functions - Beginner

I am trying to set the name and ID of an element when a radio button is clicked on. To avoid duplicating the selector, I attempted to set it up like this:
$( "#selectOther" ).click(function() {
$( "[field=primaryInput]" ).attr('id', "modifiedId", function() {
$(this).attr('name', "modifiedName");
if ($(this).attr('visible') == "False") {
$(this).slideDown('fast');
$(this).attr("visible", "True");
}
});
});
However, it isn't working. It seems that the ID is changed, but the Name is not, nor is the rest of the function executed. Could someone help me understand how to express this correctly?
Here's a JFiddle.
EDIT: In my final case I will have a couple of buttons that reveal the field if it is hidden, and others that will hide it if it is visible. That is why I am not using .slideToggle()
See this fiddle:
$('input[type="radio"]').click(function() {
$('input[data="primaryInput"]')
.prop('id', this.id)
.prop('name', this.name)
.val(this.value)
.css('display', 'inline-block');
});
Number of points:
You didn't set an external resource (namely jQuery) in your fiddle - so you wouldn't ever get jQuery functions to execute
Use the data attribute for custom attributes. You can access them the way I have done or by selecting the $(element).data('field')
This example might help you understand how chaining works. One other piece of advise is that chaining only works if the method invoked next receives the same element the previous method returns. If it ever changes, you can use end() to get the previous state.

Jquery lag on click function

I've got a table with different columns identified with different classes.
I've also a checkbox binded to every column.
I created a function which is called on the click of any checkbox. In this function I hide/show the column which is linked to this.
It doesn't have any javascript error, and the code is the following:
$(document).ready(function(){
$('ul input').click(function(){
//alert('yooo');
if ($(this).is(':checked')) {
//alert('checked');
$("td."+replaceAll(" ","_",$(this).val())).show();
$("th."+replaceAll(" ","_",$(this).val())).show();
//alert($("td").length);
}
else{
//alert('unselected');
$("td."+replaceAll(" ","_",$(this).val())).hide();
$("th."+replaceAll(" ","_",$(this).val())).hide();
}
});
});
However, after every click, the action has a lag (after many clicks it becomes tooooooo slow, many seconds).
I tried also with .css instead of hide-show, but it doesn't make any change.
I understood that the problem was linked only to checkbox, not on callback or on jquery function. I solved the problem simply by working with radio input, adding a "true" and a "false" radio input for every checkbox that was in the page.
Instead of running the jQuery selector on every click like below:
$("td."+replaceAll(" ","_",$(this).val()))
You could set up some sort of caching like:
var cache = {} //<-- declare this outside your click handler
//add the code below inside your click handler
className = replaceAll(" ","_",$(this).val())
if(!cache[className])
cache[className ] = $("td."+className + ", th."+className); //select all the elements once and store in the cache object
$el = cache[className];
if ($(this).is(':checked'))
$el.show();
else
$el.hide();

Input:Checked jQuery vs CSS?

Unless I am mistaken. jQuery and CSS handle the :checked selector very differently. In CSS when I use :checked, styles are applied appropriately as I click around, but in jQuery it only seems to recognize what was originally in the DOM on page-load. Am I missing something?
Here is my Fiddle
In jQuery:
$('input:checked').click(function () {
$('input:checked').css('background','#FF0000');
$('input:checked+label').css('background','#ff0000');
});
In CSS:
input:checked+label {font-weight:bold;color:#5EAF1E}
UPDATE:
I should clarify that what I am looking to do is trigger behavior if a user clicks an already selected radio button.
Try setting up the handler this way:
$('body').on('click', 'input:checked', function() {
// ...
});
The way you have it, you're finding all the elements that are checked when that code runs. The above uses event bubbling so that the test is made when each "click" happens.
Inside your handler, you're updating the style for all checked elements, even though any particular click will only change one. That's not a huge deal if the number of checkboxes isn't too big.
edit — some further thought, and a helpful followup question, makes me realize that inside an event handler for a radio button "click" event, the button will always be ":checked". The value of the "checked" property is updated by the browser before the event is dispatched. (That'll be reversed if the default action of the event is prevented.)
I think it'll be necessary to add a class or use .data() to keep track of a shadow for the "checked" property. When a button is clicked, you'd see if your own flag is set; if so, that means the button was set before being clicked. If not, you set the flag. You'll also want to clear the flag of all like-named radio buttons.
You bound the event only to the inputs that were initially checked. Remove :checked from the first selector and it works as intended (but ugly.)
http://jsfiddle.net/8rDXd/19/
$('input').click(function () {
$('input:checked').css('background','#FF0000');
$('input:checked+label').css('background','#ff0000');
});
you would of course need to "undo" the css change you made with jQuery to make it go away when the input is unchecked.
$('input').click(function () {
$('input').css('background','').filter(":checked").css('background','#FF0000');
$('input+label').css('background','');
$('input:checked+label').css('background','#ff0000');
});
http://jsfiddle.net/8rDXd/20/
AFTER UPDATE
Keep track of the status of the radio buttons. For example, use .data() to keep an in-memory state of the radio buttons.
$(function () {
var $radio = $(":radio");
$radio.filter(":checked").data("checked", true);
$radio.on("click", function () {
if ($(this).data("checked")) {
alert("Already selected");
}
$radio.data("checked", false).filter(":checked").data("checked", true);
});
});
See it live here.
BEFORE UPDATE
I think you want to use .change() here.
$('input:radio').change(function () {
$('input, input+label').css('background', '');
$('input:checked, input:checked+label').css('background', '#f00');
}).change();
See it live here.

toggling between two classes jQuery = works but extra click

Sort
$(".sort").click(function (event) {
$(this).toggle(function() {
$(this).toggleClass("sortUp","sortDown");
}, function() {
$(this).toggleClass("sortDown","sortUp");
});
});
it works but I need to click once before it works.
so -
click (nothing happens), click (sortUP), click (sortDown)
I would like to remove first click.
Thank you community for the help !
Firstly, you're using toggleClass incorrectly. You appear to want to toggle sortDown and sortUp on each click. That's done with toggleClass("sortDown sortUp").
Secondly, you need your class .sort to either have sortUp or sortDown set in its class property when you load the page. e.g. <a href="#" class="sort sortDown">. This makes sure you can reason about your code (i.e. it's always true that exactly one of sortUp, sortDown are set on your div).
Thirdly, $(this).click(function() { /* code */ }) means "when somebody clicks, do /*code*/". You've wrapped your
$(this).click(function() { $(this).toggleClass("sortUp sortDown"); })
which sets up the click behaviour, in a $(".sort").click(function () { which means you are requiring an initial click on "sort" just to start the behaviour.
So the correct version is:
Sort
$(document).ready(function () {
$(".sort").click(function() {
$(this).toggleClass("sortUp sortDown");
});
});
if you dont' want to begin with a sortUp or sortDown class, do this:
Sort
$(".sort").click(function (event) {
if($(this).hasClass("sortUp") || $(this).hasClass("sortDown")){
$(this).toggleClass("sortUp sortDown");
}else{
$(this).addClass("sortUp");
}
});
It looks like you are adding the click events on the first click, also if you want to switch between sortUp and sortDown you can simply specify them both. As long as the element starts with one or the other (not both and not neither), it will swap them each time.
$(".sort").click(function() {
$(this).toggleClass('sortUp sortDown');
});
You can see this running on JSFiddle.

Categories

Resources