Count not updating on click - javascript

I have two multiselect menus where I'm trying to get a total of how many children are present in each multiselct on load, then update the numbers, based on a click event which will push from one to the other, or vice versa.
The onload portion is working fine. I'm getting the results I'd expect and the counts are accurate.
The problem I'm having is updating both counts once the click event triggers. My counts never change.
Here's my code along with a fiddle:
var activeUser = $('.activeUsers');
var eligibleUser = $('.eligibleUsers');
var availableUserCount = $("#availableUsers option").length;
var eligibleUserCount = $("#eligibleUsers option").length;
activeUser.html(availableUserCount);
eligibleUser.html(eligibleUserCount);
$('#availableUsers').click(function () {
return !$('#availableUsers option:selected').remove().appendTo('#eligibleUsers');
activeUser.length(function() {
return availableUserCount();
});
eligibleUser.length(function() {
return eligibleUserCount();
});
});
$('#eligibleUsers').click(function () {
return !$('#eligibleUsers option:selected').remove().appendTo('#availableUsers');
activeUser.length(function() {
return availableUserCount();
});
eligibleUser.length(function() {
return eligibleUserCount();
});
});
http://jsfiddle.net/mujaji/8gkLyfe3/3/
What am I doing wrong?

There seems to be 3 problems with your code.
You are using return in the fist line of the click event. So the following code will never be executed (Get rid of that and only return if you cannot find any options)
There is no method called length for a div element. (Use .text() instead)
When you are returning the length inside the function return availableUserCount(); it will return you the cached value. (You need to reselect the element again)
So your code should technically look like this (further refactoring can still be made)
var activeUser = $('.activeUsers');
var eligibleUser = $('.eligibleUsers');
var availableUserCount = $("#availableUsers option").length;
var eligibleUserCount = $("#eligibleUsers option").length;
activeUser.html(availableUserCount);
eligibleUser.html(eligibleUserCount);
$('#availableUsers').click(function () {
!$('#availableUsers option:selected').remove().appendTo('#eligibleUsers');
activeUser.text(function() {
return $("#availableUsers option").length;
});
eligibleUser.text(function() {
return $("#eligibleUsers option").length;
});
});
$('#eligibleUsers').click(function () {
!$('#eligibleUsers option:selected').remove().appendTo('#availableUsers');
activeUser.text(function() {
return $("#availableUsers option").length;
});
eligibleUser.text(function() {
return $("#eligibleUsers option").length;
});
});
Check Fiddle

$("#availableUsers option").length doesn't dynamically change with the number of options. Once you set it up top, it's 40 forever. This does what you want:
$('#availableUsers').click(function () {
$('#availableUsers option:selected').remove().appendTo('#eligibleUsers');
activeUser.text($("#availableUsers option").length);
eligibleUser.text($("#eligibleUsers option").length);
});
Although it's not efficient to re-query every time when you could do
availableUserCount--; eligibleUserCount++;
And keep track of it manually.

Best solution (sic) :D
/*JQUERY FUNCTIONS*/
var activeUser = $('.activeUsers');
var eligibleUser = $('.eligibleUsers');
var eligibleUserCount = function(){eligibleUser.html($("#eligibleUsers option").length)};
var availableUserCount = function(){activeUser.html($("#availableUsers option").length)};
eligibleUserCount();
availableUserCount();
$('#availableUsers').click(function () {
$('#availableUsers option:selected').remove().appendTo('#eligibleUsers');
availableUserCount();
eligibleUserCount()
});
$('#eligibleUsers').click(function () {
$('#eligibleUsers option:selected').remove().appendTo('#availableUsers');
availableUserCount();
eligibleUserCount()
});
http://jsfiddle.net/8gkLyfe3/5/

Using return in the first line of the functions prevents any other code from executing in that block.
Check out my fiddle for a functionalized way to perform this
function setUserCounts(){
availableUserCount = $("#availableUsers option").length;
eligibleUserCount = $("#eligibleUsers option").length;
activeUser.html(availableUserCount);
eligibleUser.html(eligibleUserCount);
}
http://jsfiddle.net/8gkLyfe3/6/
Essentially, we add this function and then call it from within the click handlers, while also removing the

Related

Triggering of JS functions on page load isn't working

I have two functions that are triggered whilst the user is inputting data. They essentially add up the values of the options they choose, and output them.
On this form, in particular, the options are already pre-populated. Because of this, the functions have not been triggered, leaving their calculation as null.
The functions are shown just above </body>
Functions:
$(calculateScore);
function calculateScore () {
var fields = $('.form-group #input').change(calculate);
function calculate () {
var score = 0;
fields.each(function () {
score += +$(this).val();
});
$('#score').html(score.toFixed(0));
}
}
$(calculateHiddenScore);
function calculateHiddenScore () {
var fields = $('.form-group #input').change(calculate);
function calculate () {
var score = 0;
fields.each(function () {
score += +$(this).val();
});
$('#hidden_score').val(score.toFixed(0));
}
}
Code placed underneath the functions to try and trigger them:
$(function () {
calculateHiddenScore();
calculateScore();
});
and I have also tried:
window.onload = function () {
calculateScore();
calculateHiddenScore();
};
How can I trigger these two functions when the page has loaded please? Many thanks.
DOM ready will not trigger an onchange event even if your items are pre-populated.
Therefore you have to modify a bit your script like:
function calculateScore() {
var fields = $('.form-group #input'); // Cache only!
function calculate() {
var score = 0;
fields.each(function() {
score += +$(this).val();
});
$('#score').html(score.toFixed(0));
$('#hidden_score').val(score.toFixed(0));
}
calculate(); // Calculate ASAP (on DOM ready)
fields.on("change", calculate); // and also on change
}
jQuery(function($) { // DOM is ready and $ alias secured
calculateScore(); // Trigger
// other jQuery code here
});
P.S: BTW even if the above is a bit improved, it makes not much sense to loop using each over a single ID #input element - I'll leave that to you...

Javascript Dynamically invoke shortcut keys combination function to shortcutjs plugin

Am getting key Combination from the server. Based on that am assigning key Combination to function dynamically. The below code is working for last iteration in loop. how below code is work for all iterations.
In my page i have two buttons save and cancel the below code is working for last iteration in for loop, It means btnCanel button triggers if i press key for save function.Any suggestions. hope understand my question.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
shortcut.add(String(keyCombination[k]), function () {
var btnAdd = document.getElementById(String(k));
btnAdd.focus();
btnAdd.click();
});
}
}
});
if i give like this means it is working
shortcut.add("Alt+S", function () {
var btnAdd = document.getElementById('btnAdd ');
btnAdd .focus();
btnAdd .click();
});
shortcut.add("Alt+C", function () {
var btnCancel = document.getElementById('btnCancel');
btnCancel.focus();
btnCancel.click();
});
but if i try to add dynamically its overriding help me this issue.
Thanks in Advance.
I created a separate function outside the document.ready function like this now its working fine.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
Set_KeyCombinations(k, keyCombination);
}
}
});
function Set_KeyCombinations(k, keyCombination) {
shortcut.add(String(keyCombination[k]), function () {
var eleId = document.getElementById(String(k));
if (eleId) {
if ($('#' + String(k).trim()).css('display') !== 'none' && eleId.getAttribute("disabled") !== "disabled") {
eleId.click();
eleId.focus();
}
}
});
}
Try this:
var keyCombinations = [ "Ctrl+Shift+X" , "Ctrl+Shift+Y" ];
for(var i=0; i<keyCombinations.length; i++){
(function(shorcutCombination){
shortcut.add(shorcutCombination,function() {
alert("i am " + shorcutCombination);
});
})(keyCombinations[i]);
}
The idea is that you need to preserve the value of keyCombinations[i]
as i increases in the loop. Tested this here: Openjs

if statement within function breaks javascript

I'm stumped with this one and would really appreciate someone's help.
I'm customizing highslide for integration with wordpress. Via the following code within the highslide.config.js file I'm adding a class name to certain elements and passing different attributes through an onClick call depending on certain conditions.
Everything works until I add the following code:
if(hsGroupByWpGallery){
slideshowGroup: this.parentNode.parentNode.parentNode.id
};
When the above code is present, not only does that one statement not execute, but the whole thing stops working. Even if the if statement is something like if(1=1){}; it still breaks.
If I have instead simply slideshowGroup: this.parentNode.parentNode.parentNode.id or nothing (the two options I'm looking for), both do what I would expect. I just need an if statement to switch between them.
Here's the relevant code:
jQuery(document).ready(function() {
var hsCustomGalleryGroupClass = 'fbbHighslide_GalleryGroup';
var hsCustomGalleryGroupChecker = 0;
var hsGroupByWpGallery = true;
jQuery('.' + hsCustomGalleryGroupClass).each(function(){
hsCustomGalleryGroupChecker++;
return false;
});
if (hsCustomGalleryGroupChecker > 0){
jQuery('.' + hsCustomGalleryGroupClass).each(function(i, $item) {
var grpID = $item.id;
jQuery('#' + grpID + ' .gallery-item a').addClass('highslide').each(function() {
this.onclick = function() {
return hs.expand(this, {
slideshowGroup: grpID
});
};
});
});
} else {
jQuery('.gallery-item a').addClass('highslide').each(function() {
this.onclick = function() {
return hs.expand(this, {
// This is the problem if statement
if(hsGroupByWpGallery){
slideshowGroup: this.parentNode.parentNode.parentNode.id
};
});
};
});
};
});
Thanks in advance.
The problem is you are trying to assign a conditional property.. you can't have a if condition inside a object definition like that
jQuery('.gallery-item a').addClass('highslide').each(function () {
this.onclick = function () {
var obj = {};
//assign the property only if the condition is tru
if (hsGroupByWpGallery) {
obj.slideshowGroup = this.parentNode.parentNode.parentNode.id;
}
return hs.expand(this, obj);
};
});
Another way to do the same is
jQuery('.gallery-item a').addClass('highslide').each(function () {
this.onclick = function () {
//if the flag is true sent an object with the property else an empty object
return hs.expand(this, hsGroupByWpGallery ? {
slideshowGroup: this.parentNode.parentNode.parentNode.id
} : {});
};
});
I think you might want this, based on the other code:
jQuery('.gallery-item a').addClass('highslide').each(function() {
this.onclick = function() {
if(hsGroupByWpGallery){
return hs.expand(this, {
slideshowGroup: this.parentNode.parentNode.parentNode.id
});
}
};
});

.slideToggle nested ajax repeater

I have a function that writes out to a cooke the value of the DIV that holds that data that I want to show, the cookie code works, the toggle code works but when the page refreshses, I can get the list of repeater elements, itterate through them, determine if the section should be hidden or not but I can't use visible, I can't use .show() or .hide(), I know this has to be easy but what am I over looking???
This is my working code for the slidetoggle that works and writes the true or false to the cooke based on the repeater title attribute:
$(document).ready(function () {
$("a.toggle").click(function () {
var inObj = $(this).parent().find('div#fader');
var inTitle = inObj.attr('title');
inObj.slideToggle('fast', function () {
docCookies.setItem(inTitle, inObj.is(':visible').toString());
});
});
});
This is the code block that I have the problem with, specifically, the .show() and the .hide() are not known methods, so I have the object in inObj[] collection, I am not sure how to cast this or deal with this in javascript.....
$(window).load(function () {
var inObj = $('div#fader');
for (var i = 0; i < inObj.length; i++) {
var objTitle = inObj[i].title;
var item = docCookies.getItem(objTitle);
if (item == "true") {
inObj[i].show();
}
else {
inObj[i].hide();
}
}
});
Use $(inObj[i]).show() and $(inObj[i]).hide().

knockout dirty flag code not working

Just started with knockout and need to implement page change warning. Following is the code snippet. I just need an alert pop up as warning if any change is made on the page.
function parseViewModel() {
var viewModel = JSON.parse(getState());
viewModel.checking = ko.observable(false);
viewModel.Slider = new ko.observable(100 - viewModel.Slider);
viewModel.CausalsList = buildHierarchy(viewModel.Causals);
viewModel.Causals["-1"] = "Total Marketing Budget";
viewModel.GeographiesList = ko.observableArray(gl);
viewModel.Geographies["0"] = "All Geographies";
viewModel.ProductsList = ko.observableArray(pl);
viewModel.Products["0"] = "All Products";
.
.
.
return viewModel;
}
function bindModel() {
model = parseViewModel();
ko.dirtyFlag = function (root, isInitiallyDirty) {
var result = function () { },
_initialState = ko.observable(ko.toJSON(root)),
_isInitiallyDirty = ko.observable(isInitiallyDirty);
result.isDirty = ko.computed(function () {
return _isInitiallyDirty() || _initialState() !== ko.toJSON(root);
});
result.reset = function () {
_initialState(ko.toJSON(root));
_isInitiallyDirty(false);
};
return result;
};
model.dirtyFlag = new ko.dirtyFlag(model);
model.isDirty.subscribe(function () {
alert("Page change warning!");
});
ko.applyBindings(model, $('#const').get(0));
ko.applyBindings(model, $('#buttonDiv').get(0));
}
Referred Ryan Niemeyer's blog. Unfortunately, it's not working anymore. Any insights please?
You would want to subscribe to model.dirtyFlag.isDirty in your case rather than model.isDirty.
One way to do is by using customBinding. I'm not that familiar with KO either but this might be something you're interested on.
Basically you would do is :-
ko.bindingHandlers.myFunction = {
update : function(){
//do something
}
}
http://knockoutjs.com/documentation/custom-bindings.html
And call it on your element using :-
<h1 data-bind="myFunction:{}"></h1>
Also, a jsfiddle to show how it works. (If you change the value of the First Name and focus out of it then the customBinding gets triggered. )
http://jsfiddle.net/3vuTk
Not sure if it's the best practice though.

Categories