Add multiple items with one click using checkboxes

drwagner13drwagner13 Member
in Help edited November 2008
We have a store with many items (>50) presented at once (seed packets), each with a max quantity set to 1. It makes for slow shopping to "add item to cart" for each item. We would like to implement checkboxes instead, adding all checked items to the cart at one.

I have begun an implementation, but currently I can't get only checked items to show up in the cart—all items show up.

Here's what I've done in ModX.
1. each item is a separate content item.
2. The parent item has the following code:

<form action="https://cssa.foxycart.com/cart"; class="foxycart" method="post">
<div class="clr"> </div>
[!Ditto? &parents=`[*id*]` &display=`all` &tpl=`seedso` &sortDir=`ASC`!]
<input type="submit" class="button" value="Add Seeds to Cart" />
</form>

3. each items is processed by the ditto statement using the following template:

<div class="seeds">
<input type="checkbox" name="[+ditto_iteration+]:checkbox" value="">
[+content+]
<input type="hidden" name="[+ditto_iteration+]:name" value="[+pagetitle+]" />
<input type="hidden" name="[+ditto_iteration+]:price" value="Personalize? &yesChunk=`seeds_price_members` &noChunk=`seeds_price`" />
<input type="hidden" name="[+ditto_iteration+]:content" value="[+longtitle+]" />
<input type="hidden" name="[+ditto_iteration+]:quantity_max" value="1" />
<input type="text" name="[+ditto_iteration+]:quantity" value="0" size="1" />
</div>
<div class="clr"> </div>

[+Ditto_Iteration+] makes the various values for each item uniquely named.

What I'd like is that the quantity be set to 1 when the checkbox is checked, zero when unchecked. This would seem to require an onclick evnet for the button, but I don't yet know how to write the script.

Then I'd like to hide the quantity input, so I can put a div around it and hide that later.

Using what I have so far, I can input the quantities manually and add multiple items to the cart, but when I "continue shopping", I'd like all the quantities to be reset to zero. But how? Can I force the page to reload when I "continue shopping"?

In a future implementation I'd like to remove, replace, or diable the checkboxes for items already in the cart, so perhaps a reload is ideal. But faster would be???...
«1
Comments
  • Just using this like a blog, I suppose. Progress I've made:

    I've written a script to update a quantiy field, but I can't get it to work, because the getElementById function always returns null.

    <script type="text/JavaScript">

    //a script to change the quantity of a text input when a checkbox is toggled.

    function changeQuantity(boxID,quanID) {
    var myBox = document.getElementById("boxID")
    var myQuan = document.getElementById("quanID")
    if ( myBox.checked && myQuan.value == "0") {
    if ( !myBox.checked && myQuan.value == "1") {
    myQuan.value = "0" }
    }
    </script>

    But at least now I know I can push multiple independent items into the cart by setting the quantities.

    My remaining challenges:
    1. If the script above works, will it work when the quantity form field is hidden?
    2. On reload of the pages, can we get the checkboxes and quantities ot return to the default state (right now they are not).

    So much to learn!
  • brettbrett FoxyCart Team
    Hi drwagner13.

    Sounds like fun. The ditto_iteration placeholder can be SUPER useful, as in this case. Nice approach.

    A few notes, not in order.

    Removing the quantity input: Just change it from type="text" to type="hidden" and you'll be fine.

    The short answer to the rest of your questions is "javascript". The long answer gets into coding the actual javascript. Do you have any javascript or jQuery experience to work with?
  • brettbrett FoxyCart Team
    Oops, it took me so long to actually post my answer that you posted again.

    As far as the reload of pages, check the wiki for the fc_BuildFoxyCart() function, which gets called after the thickbox closes.

    As far as selecting elements go, it'd probably be VERY beneficial for you to give jQuery a look. The foxycart_includes.js file includes jQuery, but it's set to no-conflict mode at $j() instead of the standard $() syntax. You can select by just about anything, including siblings and such, which would likely be very easy for you to manage changing the quantity input value based on the preceding checkbox input.
  • drwagner13drwagner13 Member
    edited November 2008
    An update on setting quantities using checkbox:

    It is impossible to use getElementById in a function called inline in the body of the html. I have not yet tried it in the head, in an external file, or using a javascript statement like myElement.onclick, but I will try these things.

    What does work is to include the javascript code directly in the onlick tag, thusly:

    <input type="checkbox" id="2:checkbox" name="2:checkbox" UNCHECKED onclick="var myQuan = document.getElementById('2:quantity');
    if ( this.checked && myQuan.value == '0') {myQuan.value = '1'; }
    if ( !this.checked && myQuan.value == '1') {myQuan.value = '0'; }" />

    Note: everywhere you see a 2 in this script, this is gernerated using [+ditto_iteration+], so each checkbox and quantity input has a unique id tag.

    This seems rather bulky to me, since we will include this dozens of times in a page. But it works.

    I do not have experience with jQuery yet. I will explore that later. For now I'm excited to get somethign working. This seems like a lot of work for a pretty simple bit of functionality.
  • brettbrett FoxyCart Team
    Here's some jQuery that'd be unobtrusive and should work pretty well:
    $j(document).ready(function(){
    	$j('input[@type=checkbox]').change(function(){
    		if ($j(this).is(':checked')) {
    			$j(this).siblings('input[@name$=quantity]').val(1);
    		} else{
    			$j(this).siblings('input[@name$=quantity]').val(0);
    		}
    	});
    });
    

    It basically attaches an onchange event to every checkbox on the page. If (onchange) the checkbox is checked, the next input (actually, all sibling inputs, but there's only be one sibling for each checkbox) with name ending with "quantity" (the $= means "ends with") gets set to 1. If the checkbox is unchecked, the quantity input gets set to 0.

    I haven't tested that but it should work. If it doesn't, throw it in Firebug and see where it's erroring. Make sure you stick that code inside <script> tags and that it comes after your foxycart_includes.js file, which is where the jQuery file is being loaded.
  • drwagner13drwagner13 Member
    edited November 2008
    Thanks for the jquery script. I will study it. In the meantime, to get the checkbox functionality I wanted, I struggled over writing the following javascripts:

    To increment/decrement the (hidden) quantity field of max quantity=1, I came up with this:
    <input type="checkbox" id="[+ditto_iteration+]:checkbox" name="seedCheckbox" UNCHECKED  onclick="{{CheckboxQuantScript}}" />
    

    where {{CheckboxQuantScript}}=
    var myQuan = document.getElementById('[+ditto_iteration+]:quantity');
    if ( this.checked && myQuan.value == '0') {myQuan.value = '1'; }
    if ( !this.checked && myQuan.value  == '1') {myQuan.value = '0'; }
    

    Because I'm using this.value in the script, I couldn't make use of a called javascript. I'm sure it is possible and desirable to do this differently, as now I have three lines of script attached to every checkbox!

    Moving on—

    To include a "Select/Deselect All" checkbox I worked out this:
    function SetAllCheckboxes(FormName, FieldName, clickState) {
            if(!document.forms[FormName])
    		return;
    	var objCheckBoxes = document.forms[FormName].elements[FieldName];
    	if(!objCheckBoxes)
    		return;
    	var countCheckBoxes = objCheckBoxes.length;
    	if(!countCheckBoxes)
    		objCheckBoxes.checked = clickState;
    	else
    	   for(var i = 0; i < objCheckBoxes.length; i++) 
    
            if (objCheckBoxes[i].checked != clickState)
            objCheckBoxes[i].click();
    }
    

    called thusly:
    <input type="checkbox" name="selectAll" id="selectAll1" value="" onclick="SetAllCheckboxes('seedForm', 'seedCheckbox', selectAll1.checked);SetAllCheckboxes('seedForm', 'selectAll', selectAll1.checked)" /><label for="selectAll1"> Select/Deselect All Items</label>
    

    Note that there are two such checkboxes, one above and one below the list of items, so I have to call the script twice in the onclick event to cover the "itemCheckbox"es and the "selectAll" checkboxes (so those stay in synch with eachother).

    Notice the click method, which preserves the onclick event functionality. if you just set the value of the checkbox, the onclick event does not get triggered.

    I struggled for awhile on how to pass the value into the script using this.value. And the first script I wrote toggled all the checkboxes, which was not the desired behavior! The above script does what I want.
  • lukeluke FoxyCart Team
    Hey drwagner. It sounds like you're moving into some details a bit beyond our general level of support here on the forums. Your questions might be better suited for a JQuery forum.

    Can we recommend some developers for hire you could get in touch with?
  • I didn't ask for support in my post guys> I'm following up on a post to show that I solved the problem. Foxycart has a flaw, in that there is no documented way to add multiple items to the cart using checkboxes. This cannot be an uncommon feature. I am providing a solution here, so your comment above makes little sense to me. (Incidentally, it's the third smarmy response I've gotten from you guys on this forum. I'm a total beginner at this, so why dis me? I didn't choose your product, but I'm trying to work with it, OK?).
  • lukeluke FoxyCart Team
    I'm sorry, drwagner, I misunderstood your post. We really do appreciate you providing solutions for the rest of the community. If you're referring to my reply to your other post mentioning virtumart, it was an attempt at humor that obviously failed. I had to look up "smarmy" to fully understand what you're saying.

    We're here to help and since we built this thing, I guess we can come off a little smug. That's definitely not our intention. We can't build our business by dissing our customers.

    As to a flaw in FoxyCart, I'd probably have to see an example page to better understand what you're trying to do.
  • Hey drwagner

    Just a note to say that I, as a complete novice, really appreciated your posts above.

    To put it in perspective, the FoxyCart team are used to people like myself who use this forum more for cries for help. That therefore informs their mindset when reading any thread on this board. To be fair to them, I find Brett, Luke and Fred here extremely helpful and keen to assist. This was a large factor in my choosing FoxyCart over alternatives - I knew I would need help! :-)

    Just my tuppenyworth

    Lee
  • You can view my first attempt at implementing this feature here:

    http://shop.cssainc.org/seed-depot-f-g.html

    You can quickly find two problems.

    1. If you submit an order with no items checked you get an error. I need to learn how to do some error checking prior to the submit.
    2. If there are many items (try this on the M page), and you select all and the submit, you get an error because the URL was too long. Would be nice ot know if a workaround there.
  • brettbrett FoxyCart Team
    1. That'd be the fc_PreProcess() function, described briefly here:
    http://wiki.foxycart.com/docs:json

    Using jQuery you can make quick work of that:
    function fc_PreProcess() {
        if ($j('#seedTable input[@type=checkbox]:checked').length > 0) {
            return true;
        } else {
            alert('Please select some seeds.');
            return false;
        }
    }
    

    2. That's an interesting issue that's never come up before. The limit on GET requests varies per browser, but is sufficiently large as to not cause problems normally. We'll take a look at this and see what we can figure out a workaround for you. (Even though your form is method="post", the foxycart_includes.js serializes it and converts it to GET. There are reasons for this, but we'll see if there's a good workaround for you.)
  • brettbrett FoxyCart Team
    Also, something like this might be really interesting for your customers:
    - http://plugins.jquery.com/project/uiTableFilter (example at http://gregweber.info/projects/demo/flavorzoom.html)
    - http://rikrikrik.com/jquery/quicksearch/

    I could imagine that being a very useful and usable way to quickly and easily search through your seeds.
  • Wow, Brett, that was easy. Thanks for the handy script. However, suddenly I cannot post any items to the cart on certain pages. I thought that before it was working if you only selected some items, but not all. But perhaps every item is being sent, with a quantity of zero for those not selected. I don't know how to view the url being sent to see what exactly is happening. But I guess I've basically rolled out something that doesn't work. Oops! So much for testing!

    Having read up a little now on post vs. get, I can see why the conversion to a get causes trouble in this case. A workaround would be great. I could also divide up my selections into smaller bits, but I'd need some way to predict how much is too much for any given page, and perhaps this is a variable I can't access readily.
  • brettbrett FoxyCart Team
    The "how much is too much" depends on the browser. I think it's at least 2000 characters, but you could probably get some accurate numbers on Google.

    As far as posting any items... ok, on certain pages. Yeah, so the M page works, but the F-G page definitely doesn't (at least, not in FF3 on OSX). The issue is definitely that _everything_ is being passed, regardless of quantity. You could work around this to copy the checked items to a hidden form and submit that instead of the massive form you have now, but the underlying issue is still there, which we'd need to find a workaround for (or you could pare down your pages)... http://www.boutell.com/newfaq/misc/urllength.html should give you an idea. Looks like we're (yet again) limited by IE, at 2083 characters.

    You can see exactly what it's sending by using Firebug to inspect the HTML and view the iframe src attribute. One thing I'm seeing would be to remove the "category=Seed Depot" value, and just have everything use the default category. That'd end up saving a lot of characters. (If you have multiple categories, then that might not work, but if you can get away with making the Seed Depot your default category then I'd go for it.)

    If you're willing to split up the pages to get them having less products per page that'd definitely work. We'll try to find a workaround for the POST -> GET conversion otherwise, but let us know if you'd like for us to look at that. We're neck deep in some other major new functionality on our end so if you're able to work around the limitation for the time being we'd be thrilled (and we could continue on supertax, supersubscriptions, and some other nifty stuff).
  • I'm not willing to split up the pages further... in a future implementation I'd like to put more items on each page! Removing the category seems to work for now, although that's not an ideal solution, as I have five categories, each handled by a different person fulfilling orders.

    So idealy a workaround for the post-get conversion would be ideal.

    As for passing the checked values to another form, interesting idea. But I can't begin to imagine how that would work/look.
  • brettbrett FoxyCart Team
    Passing the checked values to another form would be really easy with just a little jQuery we could help you out with, but you'd still run into the same issue if a user selected all of them, so I'm not sure it's worth pursuing.

    In a future implementation I think it'd be really amazing to use the find-as-you-type scripts I linked to above, though you'd still likely run into the same issue, so we do need to work on a get/post fix.

    Are you ok for the time being, though? We're slaving away on some other pieces of functionality, so if you have things working at least for the time being, we'll come back to this as we're able (or once it does become an issue for you again). Let me know.
  • OK, new problems. Even with removing the category from each item I can't post the items for one of my pages in Firefox, and I'm getting reports that you can post items using Internet Explorer (users a re reporting a blank or grayed-out cart with only continue shopping and close buttons available).

    http://shop.cssainc.org/seed-depot-e.html

    So actually, I do need a solution sooner than later, if you guys wouldn't mind helping me out... Wouldn't a post be better in this case? Is there a way to make this work?
  • brettbrett FoxyCart Team
    Yes, a post would be better. We're just really slammed at the moment with some other things so we were hoping you'd be able to work around it in the meantime. I've assigned a ticket on our end to see what we can figure out. Is this an asap issue for you or do we have some time to work with?
  • Honestly it is ASAP, since I have a non-working store (in some important browsers). And I think your product will be improved if it is possible to post large orders anyway.

    The workarounds are to go back to placing single item orders. But out of a list of 500 items, imagine trying to order 100 of them (not uncommon for us!) using the one at a time method and foxycart. It would be (is) a nightmare.

    I am willling to explore other options.
  • brettbrett FoxyCart Team
    Yeah, in your situation it's certainly an issue. Ok, I'll see what we can figure out. Realistically it might take a few days to get to it, not because we don't love you but because we're in the middle of a few other super high priority issues. If you want a status update please bump this thread though. Thanks for your patience and willingness to work through the issues.
  • lukeluke FoxyCart Team
    Just to clarify, this change would be rather significant and isn't something we can roll out until a future release (which won't be happening in a few days). We may be able to get a custom FoxyCart include file for you that would would do a post rather than a get... but that's a maybe until we look into it some more.

    Thanks for keeping us up-to-date with your needs.
  • drwagner13drwagner13 Member
    edited November 2008
    Yes, well currently, because I didn't get enough help with testing, I have a non-working store under IE. That custom FoxyCart include file that would do a post rather than a get would be great. What can I do to help expedite that? My business manager is getting upset with me...

    In exchange for your herculean efforts, I will promise to write up a detailed Wiki article on how to set up a once-click, multiple-item order.

    Incidentally, I now have a modified version of your jquery script setting the quantity of each item item using using checkboxes. Great stuff!
  • lukeluke FoxyCart Team
    Hey wagner, we didn't forget about you. We've been playing with this a bit and it looks like the only way to deal with this would be to remove "foxycart" from the class on your forms and just load the cart page as a complete webpage in the full browser window. You'll loose the thickbox functionality, but at least it will work. Thickbox is called by passing a URL and I'm not sure there's away around that. We tried a couple different JQuery ajax tricks, but ran into security issues:

    [Exception... "'Permission denied to call method XMLHttpRequest.open' when calling method: [nsIDOMEventListener::handleEvent]" nsresult: "0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)" location: "<unknown>" data: no]

    Wish I had better news for you. Creating your own cart page seems like the only option at this point.
  • drwagner13drwagner13 Member
    edited November 2008
    Well, perhaps in the meantime loading the cart as a web page will be faster. I find that the current implementation becomes excruciatingly slow if once you get a few dozen items in the cart.

    Two useful approaches come to mind:

    1. I could load the cart into a separate page, like you say. But how can I do this? And just for this category/these items on this page (I'm using a submit button)?

    2. I could simply display a dialog ("x items have been added to cart") and force the mini cart to display the new total (this would be great). But again, I'm not sure how do do these things.
  • lukeluke FoxyCart Team
    1) As mentioned in my last post, just remove the "foxycart" class on your form. That will bypass all the custom javascript and it will be just a normal form submit to the cart page on the FoxyCart server. You'll probably have to run your whole store like this since we don't currently support multiple template sets (vote for it here: http://requests.foxycart.com/pages/general/suggestions/38758). If you really wanted some products to open in the modal and some not too, then you'd have to get fancy with the cart JSON object and dynamical add or remove the "foxycart" class on the form as well as dynamically adjusting the cart template to be a full page or not based on the JSON object on page load.

    2) That is possible and we have add customers pull it off using their own javascript with some JQuery posts to the cart, but it's probably not something we could get into here in the forums as it can be pretty detailed. The one store I can think of off the top of my head that did implement it (http://www.getcellranger.com/) ended up going back to the modal cart anyway. Brett has more experience with this and may be able to chime in when he gets a chance.
  • Great. I feel like we are almost there. If I remove the foxycart class, I get the cart loaded into a new page, sans template. This is almost workable, except there's no "Continue shopping button" (wah!). I don't want to lose the focybox functionality in the rest of my store, so I need another option.

    So, I'd like to just submit the form ajax-style, and I've been looking at the jquery form plugin, but I haven't gotten it to work yet.

    It would be great if you guys could provide a wiki page or tutorial on how to handle form submission without displaying the cart. In the meantime, can you drop me a hint?

    This has really got me stuck and seems like a serious limitation of your product.
  • I'd really like to see some code that moves the items to a seperate form. I'm pretty good with JQuery, and I can see right away how to add the checked items to the form, but getting them out on un-check seems a little problematic.
  • tvainisitvainisi Member
    edited November 2009
    Actually, since I don't need to move between pages (or ajax calls) I can just add a submit button which will wipe out the inputs in the hidden form and add only whats checked.

    Just an aside, I think the customer service on this thread was both humble and outstanding. I'd never expect the kinds of things this user was asking for - jquery scripting support, custom includes just for him, etc. It seems to me that foxy cart is built perfect and that the problems pertained to his implementation of catalog pages.
Sign In or Register to comment.