In the end, I have decided that this isn't a problem that I particularly need to fix, however it bothers me that I don't understand why it is happening.
Basically, I have some checkboxes, and I only want the users to be able to select a certain number of them. I'm using the code below to achieve that effect.
$j( function () {
$j('input[type=checkbox].vote_item').click( function() {
var numLeft = (+$j('#vote_num').text());
console.log(numLeft);
if ( numLeft == 0 && this.checked ) {
alert('I\'m sorry, you have already voted for the number of items that you are allowed to vote for.');
return false;
} else {
if ( this.checked == true ) {
$j('#vote_num').html(numLeft-1);
} else {
$j('#vote_num').html(numLeft+1);
}
}
});
});
And when I was testing it, I noticed that if I used:
$j('input[type=checkbox]').each( function () {
this.click()
});
The JavaScript reacted as I would expect, however when used with:
$j('input[type=checkbox]').each( function () {
$j(this).click()
});
It would actually make the counter count UP.
I do realize that it isn't the most secure way to keep count using the counter, however I do have server side error-checking that prevents more than the requisite amount from being entered in the database, that being the reason that I have decided that it doesn't actually need fixing.
Edit: The $j is due to the fact that I have to use jQuery in noConflict mode...
$(this) contains a jQuery wrapper (with lots of functions) whereas this is solely the DOM object.
The fact that counter is going up gave me the clue that there is a link between checked attribute, which you are using, and firing the click event manually.
I searched Google for 'jquery checkbox click event raise' and found this link, where author faces the exact same problem and the workaround he used.
http://www.bennadel.com/blog/1525-jQuery-s-Event-Triggering-Order-Of-Default-Behavior-And-triggerHandler-.htm
On a side note, I think you can simplify your code further:
$j('input[type=checkbox].vote_item').click(
function()
{
var maxNumberOfChoices = 5;
//get number of checked checkboxes.
var currentCheckedCount = $j('input[type=checkbox].vote_item :checked');
if(currentCheckedCount > maxNumberOfChoices)
{
//It's useful if you show how many choices user can make. :)
alert('You can only select maximum ' + maxNumberOfChoices + ' checkboxes.');
return false;
}
return true;
});
this.click() calls the browser DOM method click().
$(this).click() calls the jQuery method click(), which does more than just call the browser method: see the implementation of the function trigger for details.
Related
For several years I've used the waitForKeyElements() function to track changes in webpages from a userscript. However, sometimes I've found it doesn't trigger as expected and have worked around out. I've run into another example of this problem, and so am now trying to figure out what the problem is. The following is the barest example I can create.
Given a simple HTML page that looks like this:
<span class="e1">blah</span>
And some Javascript:
// function defined here https://gist.github.com/BrockA/2625891
waitForKeyElements('.e1', handle_e1, false);
function handle_e1(node) {
console.log(node.text());
alert(node.text());
}
setInterval(function() {
$('.e1').text("updated: "+Math.random());
}, 5000);
I would expect this code to trigger an alert() and a console.log() every 5 seconds. However, it only triggers once. Any ideas?
Here's a codepen that demonstrates this.
By design and default, waitForKeyElements processes a node just once. To tell it to keep checking, return true from the callback function.
You'll also want to compare the string (or whatever) to see if it has changed.
So, in this case, handle_e1() would be something like:
function handle_e1 (jNode) {
var newTxt = jNode.text ();
if (typeof this.lastTxt === "undefined" || this.lastTxt !== newTxt) {
console.log (newTxt);
this.lastTxt = newTxt;
}
return true; // Allow repeat firings for this node.
}
With the constant string comparisons though, performance might be an issue if you have a lot of this on one page. In that scenario, switching to a MutationObserver approach might be best.
This is a simple password checking function I messed around with for a little bit. I've tried a lot of different methods (including, but not limited to: .css(), .on('click'), .click(), .animate(), .show(), .hide(), .preventDefault() on the submit), put selectors into variables, moved around all sorts of IDs and $('input[name="s"]') and all sorts of selectors. Not sure if the function won't work, or maybe something else within the script. I've taken the function out of the $(document).ready() tree, and moved it all around inside of it. I'm sure that isn't the problem now, but I'm starting to not be sure about anything at this point.
I'm trying to get the function to hide the password textbox and submit(or is button better?) and show a textarea for news input, with a button to append the update.The appendedTo and .append() section works, but I can't seem to get the passwordcheck function to work. Sometimes it will alert me if it's wrong, but when it's right the if methods don't seem to work. Then I'll change it a few times and the alert will no longer show, nor will the if work any longer.
Any help would be appreciated, and I can provide any code snippets or chunks at request.
Function in question:
function passwordcheck() {
var $newspass = $('#newspass');
var $submitpass = $('#submitpass'); // <--- variables were at one point selectors
var $newssubmit = $('#newssubmit'); // written out, I've changed this a lot
if ($newspass.val() === 'comecorrecT') {
$submitpass.css('display', 'hidden');
$newspass.css('display', 'hidden');
$('#newsinput').css('display', 'block');
$newssubmit.css('display', 'static');
} else {
alert("Try again, please.");
}
};
Rest of the script, for reference:
$(document).ready(function(){
// billboard functions
var $billboard = $('.billboard');
$billboard.mouseenter(function(){
$(this).fadeTo('slow', 0.98);
});
$billboard.mouseleave(function(){
$(this).fadeTo('slow', 0.72);
});
var $learn = $('#learn-more');
$learn.hover(function(){
$(this).fadeTo('slow', 1);
},
function() {
$(this).fadeTo('slow', 0.6);
});
// news and updates/appendedTo
var $submitpass = $('#submitpass');
var $newssubmit = $('#newssubmit');
$submitpass.click(passwordcheck());
$newssubmit.click(function(){
$('#appendedTo').append('<div class="update">'+$('#newsinput').val()+'</div>');
// passwordcheck();
});
});
I've been working with it for a little while now, and I know you guys will have a profound explanation or two.
The way you are doing it now, you are simply passing "undefined" instead of a function (which would be what the passwordcheck function returns) as you are calling the function instead of passing a reference to it in this line:
$submitpass.click(passwordcheck());
Which should be
$submitpass.click(passwordcheck);
In the last block of your code, after
// news and updates/appendedTo
This being said, don't use client side JavaScript for authentication, the password you are checking against is visible for anyone using the site.
Try this:
function passwordcheck() {
var newspass = $('#newspass').val();
var submitpass = $('#submitpass').val();
var newssubmit = $('#newssubmit').val();
if (newspass == 'comecorrecT') {
$('#submitpass').hide();
$('#newspass').hide();
$('#newsinput').show();
} else {
alert("Try again, please.");
}
}
I have a native <select>-element based on which I'm initializing a select2-dropdown-menu.
I bound a change-event via select2 which is called whenever the select2/select-option is changed. However, I need to fire the event even if the currently selected option is selected again.
function onSelectChange(){
alert('changed');
};
$("#select").select2().bind('change', onSelectChange);
I prepared a http://jsfiddle.net/rb6pH/1/ - if "Alaska" is currently selected and then selected again via the select2-dropdown, onSelectChange() should fire again, triggering the alert.
I have a hard time expressing myself, please ask if something isn't clear enough.
Motivated by the absolutely valid remarks by #FritsvanCampen, I sat my ass down and figured out a way myself: What I really needed was a way to access the currently selected val, even if it hadn't changed. By using select2's undocumented close-event instead of change, I can access just that like so:
function onSelectChange(event){
alert( $("#select").select2("val") );
};
$("#select").select2().bind('close', onSelectChange);
Find an updated jsFiddle at http://jsfiddle.net/rb6pH/42/
A similar question was asked here. I have made a fiddle for your question based on the code in the link.
http://jsfiddle.net/rb6pH/55/
function onSelectChange(){
alert('changed');
};
var select2 = $("#select").select2().data('select2');
select2.onSelect = (function(fn) {
return function(data, options) {
var target;
if (options != null) {
target = $(options.target);
}
if (target) {
onSelectChange();
return fn.apply(this, arguments);
}
}
})(select2.onSelect);
I think you might refer to this link, i stuck once in same situation,
Change event is not fired when the selection is changed using Select2's val() method.
The event object contains the following custom properties:
val
the current selection (taking into account the result of the change) - id or array of ids.
added
the added element, if any - the full element object, not just the id
removed
the removed element, if any - the full element object, not just the id
For more information you might refer to this.
Thanks!
I read the question and it's so close to my problem so I decided not to post another question. What I want to do is after select2 closed, a simple text input become focused but it doesn't work. please check
function onSelectChange(){
alert('closed');
$('#hey').focus();
};
$("#select").select2().bind('close', onSelectChange);
$('#hey').on('focusin)', function(){alert('in');}
http://jsfiddle.net/sobhanattar/x49F2/5/
I tried to make sure that the input become focused and it showed that the input become focused but I don't know why it doesn't show the curser
a little old question but i spent a few hours last week to find a solution.
I am using Select2 version: 4.0.5.
My working solution is this one:
$("#exampleId").on("select2:open", function() {
var checkExist = setInterval(function() {
var $selectedChoiceInsideSelect2Dropdown = $("li.select2-results__option[id^='select2-" + exampleId + "-result'][aria-selected=true]");
if ($selectedChoiceInsideSelect2Dropdown.length) {
$selectedChoiceInsideSelect2Dropdown.on("mouseup", function() {
$(this).trigger("change");
});
clearInterval(checkExist);
}
}, 100); // check every 100ms
});
It's very important to use the interval!
var prev_val = $('#select2').val();
$('#select2').blur( function() {
if( $(this).val() == prev_val )
// not changed
else {
// changed
prev_val = $(this).val();
}
});
I'm making a web application for a class which contains a jsp file that uses jquery. I want the app to trigger an alert right before submitting. This works some of the time in my real program, and other times the alert is never triggered. I can't seem to peg down an instance where it always works or never works. My error console is silent on the matter, unless I add Firebug breakpoints. Then it gives me
Error: attempt to run compile-and-go script on a cleared scope
Source File: http://code.jquery.com/jquery-1.7.2.min.js
Line: 2
But I have no idea what that means. As far as Firebug goes, I can't understand why the evaulation stops before the alert message.
I tried to make an sscce documenting the problem, but I guess it was too different from my real program, because submit never worked. I'll show some code from my real program. (Sorry about the lack of SSCCE.)
$(document).ready(function() {
$("#questionDisplay").submit(function() {
var correctAnswer = $(".correctAnswer").attr("value");
var answer = "";
if ($(".multipleChoice").length > 0) {
answers = $("input:checked");
for (var obj in answers) {
answer += obj.attr("value") + "#";
}
} else if ($(".fillBlank").length > 0) {
for (var answerNo = 1; $(".answer" + answerNo).length > 0; ++answerNo) {
answer += $(".answer" + answerNo).attr("value") + "#";
}
} else {
answer = $(".answer1").attr("value");
}
if (answer == correctAnswer) {
alert("Yes! Correct!");
} else {
alert("Sorry, incorrect.");
}
});
});
The jsp is a huge mess (we have to use scriplets :( ), but if you'd like to see it just lemme know.
How do I get my submit handler to work every time?
In your example, answers is a jQuery collection of elements. Looping through it using for(var obj in answers) { } is actually looping through the properties of answers, not the elements themselves. Therefore, calling .attr() on a property is not going to work.
In general, if I see my debugger state that jQuery has an error, it's 99.9% of the time me calling a jQuery method on a non-jquery selected object. In this case, I saw the error in Chrome's JavaScript console, and sometimes results may vary with different consoles.
A good practice is to prefix variables that store jQuery elements with $ to indicate that they are jQuery objects. For instance, $answers makes it easier to keep track of what it contains.
Use:
answers.each(function() {
answer += $(this).attr("value") + "#";
});
Instead of this:
for (var obj in answers) {
answer += obj.attr("value") + "#";
}
I have two select menus (#id1 and #id2) that, when validated as containing a user error, should instigate some DOM changes (remove error notice) when either one of them gets interacted with.
Again:
var Heat_Check = jQuery('#id1' or '#id2').change(function() { ... });
PS. I know there's no return value from that chain.
May be you wanted to check if change is triggered from either of those select. Try below,
var Heat_Check = false;
jQuery('#id1, #id2').change(function() { Heat_Check = true; });
function heatCheck () {
if(Heat_Check) {
//Do your stuff
console.log('It is hot');
}
}
The comment from #Vega is right, but for completeness you can also do this:
heatChangeHandler = function() {
// ....
};
$('#id1').change(heatChangeHandler);
$('#id2').change(heatChangeHandler);
In general it is better to put multiple selectors in one $(), but it's worth knowing that functions can be addressed as variables, and thus referenced many times.