Jquery automatically select next X checkboxes - javascript

I'm working on a website for a theater where a customer can reserve tickets.
Choosing a chair works as follows:
You select how many chairs you want in the dropdown menu (we will call this X).
You tick the checkboxes where you want to sit (maximum of X).
Upon having chosen all X checkboxes, the other checkboxes turn grey (unclickable).
There are ofcourse also chairs that have already been reserved. These simply don't have a checkbox. The value of the checkbox is the same as the chair's unique ID.
This works fine except I want the system to automatically tick the next checkboxes (next 3 if the customer has chosen 4).
I have updated my code to this:
var _X = $('#PlaatsenDropdown').val() - 1;
var _id = $(this).id;
var _counter = _id + _X;
for(var i = _id; i <= _counter; i++) {
if($(this).nextAll().is('disabled')) {
alert('No seats available');
} else {
alert('Chairs available');
}
}
The id is also the chair number, so I just take that and do some calculations with it to use in the for loop.
This however, doesn't show me anything. I think there might be something wrong with the calculations but I can't figure out what :S.

You can create an array of ID strings similar to what you've done already. Then loop through the array with the 'disabled' test.
Pseudo code:
val = selected_chair_ID
for (i=0; i < desired_number_chairs; i++) {
search_right.push('#' + val + i);
search_left.push(('#' + val - i);
}
found = true;
for (j = 0; j < search_right.length; j++) { // Check chairs to the right
$(search_right[j]).....// Disabled check
if (disabled...) {
found=false;
}
if (!found) {
check chairs to the left
}
if (!found) // out of luck

Related

Optimization of a large multiselect list

I have three MultiselectLists
Countries which has 22 values
Cities which has ~800 values
Sites which has ~1700 values
I am using the jquery bootstrap-multiselect library
It is fast enough for what I am trying to do that the user doesn't notice any overhead except in one case when the user selects USA 600 Cities and 1200-1300 sites get checked/selected this takes about 30 seconds in IE, and about 6 seconds in Firefox which is enough for a reasonable person to believe that something is wrong with the page.
I don't want to change the UI of the website at all since this works beautifully in every other case, including when the user hits a "select-all" or "deselect-all" and just wants to run a full report
these are the two functions that take about 90-95% of the time to execute
getInputByValue: function(value) {
var checkboxes = $('li input', this.$ul);
var valueToCompare = value.toString();
for (var i = 0; i < checkboxes.length; i = i + 1) {
var checkbox = checkboxes[i];
if (checkbox.value === valueToCompare) {
return $(checkbox);
}
}
}
getOptionByValue: function(value) {
var options = $('option', this.$select);
var valueToCompare = value.toString();
for (var i = 0; i < options.length; i = i + 1) {
var option = options[i];
if (option.value === valueToCompare) {
return $(option);
}
}
}
and this is the code I use to select all of the options, I have a Dictionary>>(); that I pass from my controller into my view that governs the relationship between the Countries/Cities/ and sites
onChange: function (option, checked, select) {
try{
if (checked == true) {
var t0 = performance.now();
$('#Cities').multiselect('select', Object.keys(CountryCitySite[$(option).text()]),'triggeronChange');
var t1 = performance.now();
list = Object.keys(CountryCitySite[$(option).text()])
var t2 = performance.now();
for(var i = 0; i<list.length; i++)
{
$('#Sites').multiselect('select', CitySite[list[i]])
}
var t3 = performance.now();
}
else if (checked == false) {
$('#Cities').multiselect('deselect', Object.keys(CountryCitySite[$(option).text()]), 'triggeronChange');
list = Object.keys(CountryCitySite[$(option).text()])
for(var i = 0; i<list.length; i++)
{
$('#Sites').multiselect('deselect', CitySite[list[i]], 'triggeronChange')
}
}
}
Some thoughts:
1. maybe in the case of USA I could do an Ajax, and post everything to the server and then return three new selectlists with the appropriate options checked? the problem with this is that I don't see this taking less than like 7 or 8 seconds if not more which is still much too long
var options = $('option', this.$select);
this Jquery selection is several orders of magnitude slower than just using native javascript Document.getelementsbytagname, since I know that all of the checkboxes have unique values maybe I could replace this Jquery selection with native javascript and get all of the checkboxes that way
as a 'hack' I could send two invisible multiselectlists at the very beginning with all of the boxes for USA checked, these invisible multiselects behave exactly the same as the visible ones in most respects but if the user selects USA, these are shown instead of the originals. This actually does work, it makes the website a little slower but since the selection of every other option is so quick it doesn't really matter, it seems like a sub-par solution but this is currently the best I have
if anyone thinks of anything else or can give any advice on this I would be very appreciative
Sincerely Josh

How can I count only checked checkboxes in a PDF form?

There are a few check boxes in an Adobe PDF I have open in Acrobat. I want to count the checkboxes that have been checked and output the number in another textbox. How can I do that with JavaScript? Or other methods?
One possibility would be to set up a counter, enumerate all fields, check whether the field is a checkbox, and then whether its value is not "Off"; in that case increment the counter. A function doing that would look like this:
function countCheckedBoxes() {
var cntr = 0;
for (var i = 0; i < this.numFields; i++) {
var mf = this.getField(this.getNthFieldName(i));
if (mf.type == "checkbox") {
if (mf.value != "Off") {
cntr++;
}
}
}
if (cntr > 0) {
app.alert("The form has " + cntr + " checked boxes")
} else {
app.alert("The form has no checked boxes")
}
}
and that should do it.
As the number of checked boxes should go into another field, you would replace the evaluation of cntr with the following code:
if (cntr > 0) {
this.getField("boxCount").value = cntr + " boxes checked";
} else {
this.getField("boxCount").value = "no boxes checked";
}
...or simply enter the value of cntr.
I just was able to achieve this with a very simple script thanks to a script by George Johnson back in 2008.
What I did was create a text field, set it to read-only, and set it to be a custom computed value and put this in the script field:
// Initialize counter variable
var sum = 0;
// Loop through the fields
for (var i = 1; i < 180; i += 1) {
// Add one if check box is not Off
if (getField("CheckBox" + i).value !== "Off") {sum += 1;}
}
// Set this field's value to the sum
event.value = sum;
Important note: I have "CheckBox" + i and i < 180 in my for loop because all my checkboxes are named "CheckBox1", "CheckBox2", etc. through "Checkbox180".
If your checkboxes all have unique names, you'll need to put those names in an array and loop through it in your code. And if you only have, say, 15 checkboxes, then change the 180 in the script to 15.

JavaScript validation, prevent duplicate input fields

I have a form with 10 Select Lists all have the same items. The items are populated from a PHP/MySQL array. The user needs to select one item per select list. I need to prevent the user from selecting the same item twice before submitting the form.
function checkDropdowns(){
var iDropdowns = 10;
var sValue;
var aValues = new Array();
var iKey = 0;
for(var i = 1; i <= iDropdowns; ++i){
sValue = document.getElementById('test' + i).value;
if ( !inArray(sValue, aValues) ){
aValues[iKey++] = sValue;
}else{
alert('Duplicate!');
return false;
}
}
return true;
}
Use javascript to add an event listener on the value change of the selects. That function would then loop through the selects taking the values into memory after having compared it to the values it had already. If the loop finds that the current select has an option that is already selected, put it back to default value and display a little message...
Or, still on a change event, take the value of the just selected item and remove all the items of this value in the 10 selects. So at the end the user will only have 1 choice, since he only sees the options he can choose. But be careful, if the user changes his mind on one select, make sure you add back the option you removed in the first place.
Option 2 is to be prefered as a user point of view, you will cause less frustration.
EDIT:
The code you are providing already does quite a lot... All you need now is something to revert the change if it is invalid:
var defaultValues = [];
function onLoadSelect(){//Please execute this on document load, or any event when the select are made available.
var iDropdowns = 10;
var iKey = 0;
for(var i = 1; i <= iDropdowns; ++i){
var sValue = document.getElementById('test' + i).value;
defaultValues['test' + i] = sValue;
}
}
Then, in your function's else, reset the value according to the defaults we have gathered:
else{
alert('Duplicate!');
document.getElementById('test' + i).value = defaultValues['test' + i];
return false;
}
I have written code, i think it can be improved but it works as you asked.
Put it in inside script tag under body so it loads after document.
Put id names of select/dropdown elements in id array.
Take a look: //took me 3 hours O_O
http://jsfiddle.net/techsin/TK9aX/15/
i think i need better strategy to approach programming.

Changing If - Else function to return multiple values?

So the JavaScript code below is what I am using to pull data from our automated marketing software Eloqua. This works for single-select drop downs. What I want it to do is work for multi-select drop downs.
I know that the ProductValue variable works. So with that said I am positive that it is in the if(ProductValue == ProductList[i].value) specifically the " .value " since this is calling the value on in the drop-downs. Is there a way to make this multiple? This has been driving me nuts for days.
function CustomerInformation()
{
var ProductValue = "<span class=eloquaemail>MarketingCustomerInformation1</span>"; //Field Merge...Field merge is working
var ProductList = document.getElementById('C_Marketing_Customer_Information1').options; //Calling the contact record field
for(var i=0; i< ProductList.length; i++)
{
if(ProductValue == ProductList[i].value)
{
document.getElementById('C_Marketing_Customer_Information1').value = ProductValue;
break;
}
else
{
document.getElementById('C_Marketing_Customer_Information1').value = "Select";
}
}
}
you could use multiple for loops:
var ProductValue = "<span class=eloquaemail>MarketingCustomerInformation1</span>"; //Field Merge...Field merge is working
var ProductList = document.getElementById('C_Marketing_Customer_Information1').options; //Calling the contact record field
for(var i=0; i< ProductList.length; i++)
{
for(var j=0;j<ProductValue.length;j++)
{
if(ProductValue[j] == ProductList[i].value)
{
document.getElementById('C_Marketing_Customer_Information1').option[i].selected="selected";
}
}
}
Could also add a boolean var to select a default for when nothing gets selected.
BASIC IDEA
The first loop will go through all the values in the multi-select list.
The second loop will go through all the values you pass it (meaning ProductValue will need to be an array of all the values you want selected).
IF the current item in the first array (ProductList[i]) is equal to (==) the current item in the second array (ProductValue[j]) THEN you will mark the option as selected.
Some useful tools for your JS needs:
google
W3Schools.com
Firebug (Firefox addon, though most browsers have something tied to F12 that can help, use it to see your variables and step through the functions)

Javascript Logic Issue in IE

First I'll explain a little bit about my system here. It's a form to allow children to book onto a series of day courses that run in the school easter and summer breaks. The form allows registration of two children simultaneously, and if the dates for both children are the same, the sibling has a £5 discount for their dates.
On the form, there is a date section which is a series of checkboxes. As you check the checkboxes a total price is calculated at the bottom of the page.
The single child price is £29 and the sibling rate (for those dates that match up to the first child) is £24. There is an additional £16.50 charge for booking onto the horseriding course - but this logic error only extends to the date selection.
For some reason, which I cannot fathom, in Internet Explorer the price for registering 2 children appears £5 less that it should. Here is my code for calculating the dates (the function below is fired onclick of the date checkbox):
function processDates(){
//contentsA and contentsB are used for outputting on the email confirmation
valsA = [], dates_A = document.forms['registerForm']['childADates[]'];
for(var iA=0,elmA;elmA = dates_A[iA];iA++) {
if(elmA.checked) {
valsA.push(elmA.value);
}
}
contentsA = valsA.join(', ');
//this generates a string based on what dates were selected i.e. April 18th, April 19th etc.
var valsB = [], dates_B = document.forms['registerForm']['childBDates[]'];
for(var iB=0,elmB;elmB = dates_B[iB];iB++) {
if(elmB.checked) {
valsB.push(elmB.value);
}
}
contentsB = valsB.join(', ');
//same as contentA but for the second child.
//get the total dates for both children
//fullDates is the number of dates selected (number of checkboxes checked)
fullDates = (valsA.length + valsB.length);
siblingDates=0;
//this detects if entries are matching in the two arrays valsA and valsB
for(var i in valsA) {
for(var j in valsB) {
if(valsA[i]==valsB[j]){
//if there are matching dates, increment a siblingDates value to get a total number of matching dates in the siblingDates variable
siblingDates=siblingDates+1;
}
}
}
//get the amount of dates to be charged at £29
fullDates = fullDates - siblingDates;
fullPrice = fullDates*29;
siblingPrice = siblingDates*24;
totalPrice = fullPrice + siblingPrice;
calcTotal();
}
function calcTotal(){
var horseA = parseInt(document.getElementById("horseridingA").value);
var horseB = parseInt(document.getElementById("horseridingB").value);
var horse = parseInt(horseA+horseB);
//Add the horseriding price
overall = parseFloat(horse*16.5)+totalPrice;
//output the overall total to the form
document.getElementById("totalPrice").innerHTML = overall;
}
UPDATE: This process is run when the user selects one of the checkboxes that correspond to each date. April 18th [], April 19th [] etc. These checkboxes are duplicated for the 2nd child. Upon clicking one of the checkboxes the above functions are run that calculate a total price at the bottom of the screen. In internet explorer, clicking a date for ChildA yields £24 not £29, but only on the FIRST date clicked, all other dates both childA and childB are calculated correctly. The first date choice is £5 less than it should be.
I just used IE to select the first date on the main child side and it gave £24, then unselected the same checkbox which gave £-5
UPDATE 2: Okay! I've narrowed down the problem to the below statement:
fullDates = (valsA.length + valsB.length);
siblingDates=0;
for(var i in valsA) {
alert(valsA[i]);
for(var j in valsB) {
if(valsA[i]==valsB[j]){
alert("does equal");
siblingDates=siblingDates+1;
}else{
alert("does not equal");
}
}
}
Upon clicking the April 18th checkbox, the first alert (valsA[i]) reads April 18th
The second alert reads "does not equal" as expected.
In Internet Explorer the above happens normally as expected but I get an additional set of alerts:
After the above 2 alerts I get a bizarre function alert that alerts of a string length error, it's about four lines of minified code so very difficult to decipher.
Then the same alert appears again.
Then I get "does equal"
Try changing your loop to this:
for (var i=0; i < valsA.length; i++) {
for (var j=0; j < valsB.length; j++) {
if(valsA[i]==valsB[j]){
alert("does equal");
siblingDates=siblingDates+1;
}else{
alert("does not equal");
}
}
}
first up, these lines look wrong, is this how they appear in your code?
for(var iA=0,elmA;elmA = dates_A[iA];iA++)
for(var iB=0,elmB;elmB = dates_B[iB];iB++)
try something like this
for(var iA=0;iA < dates_A.length;iA++){
var elmA = dates_A[iA];
...
}

Categories

Resources