+1-888-365-2779
Try Now
More in this section

Forums / Ecommerce / Possible to force acceptance of Terms and Conditions before adding a product type to cart?

Possible to force acceptance of Terms and Conditions before adding a product type to cart?

8 posts, 0 answered
  1. SteveV
    SteveV avatar
    178 posts
    Registered:
    06 Nov 2011
    23 Jan 2012
    Link to this post
    Hi,

    I have a product type that requires the acceptance for terms and conditions before it is added to the cart.  I can modify the single item template and add a check box control and javascript validation but how would I go about showing the control for only one specific product type?

    Thanks--Steve
  2. Jochem Bökkers
    Jochem Bökkers avatar
    787 posts
    Registered:
    13 Aug 2007
    23 Jan 2012
    Link to this post
    Hey Steve,

    There are 2 ways to go about this - the client proof and the developer proof :)

    Developer proof
    On the product list widget, near the bottom of the single item setting you'll find a radio button for Detail templates. Checking the 'Different' option allows you to select a different product detail template for each product type.

    Naturally if a client drags a new product list widget somewhere or alters the radio button you're out of luck...

    Client proof
    Set the 'accept terms' bits to hidden by default and 'checked' by default. This will make sure that it passes validation and allows all product types to be accepted without the end user realizing it.

    Add some javascript at the top of the template to check for the specific type where end users have to explicitly accept the terms. If the product displayed is of that type, make the div containing the checkbox and terms visible and set the checkbox to unchecked. Now the validation javascript will not allow the user to add to cart unless checkbox is checked first.

    This way you could use only 1 product detail template and be assured that the client will allways have the validation in place...

    Jochem.
  3. Jochem Bökkers
    Jochem Bökkers avatar
    787 posts
    Registered:
    13 Aug 2007
    23 Jan 2012
    Link to this post
    I've just glanced at the product properties and it doesn't seem possible to simply display/extract the product type with JavaScript.

    You could always go with the code behind and mapping an external option but if you want to keep it simple perhaps it's easier when creating a custom product-type to add an dynamic Boolean field "Should accept terms" and have the JavaScript check the value of that field.

    J.
  4. SteveV
    SteveV avatar
    178 posts
    Registered:
    06 Nov 2011
    24 Jan 2012
    Link to this post

    Hi Jochem,

    Thanks for the suggestions.  I tried mapping the the single item template to an external custom control using the info in
    Josh's blog. I originally tried option 1 but SF kept restoring the TemplateKey Guid and rather than fight it went with the less friendly option 2. From codebehind I can get the product type and hide/unhide the "I accept the terms" checkbox. So far so good.

    From here I have 2 options in terms of forcing the user to accept the terms before they can add an item to the cart:

    A. Hook into the ValidationGroup (addToCart) using a CustomValidator and handle the OnServerValidate event and set the args.IsValid property to true or false depending on the checkbox checked state.
    B. Set the Add to cart button's enabled state based on the checked state of the checkbox.

    I'd prefer to use option A as option B is far less user friendly in my opinion.

    So, far I have been unable to catch any of the validation using any validator controls. I tried adding a dummy textbox and a RequiredFieldValidator to the template control and setting its ControlToValidate property to the id of the dummy textbox and setting its ValidationGroup to match that of the "addToCartButton" and the "quantity" controls but SF seems to ignore any validator controls other than those that are part of the "AddToCartWidget".

    Thinking I might get better control over validation, I created a custom control that inherits from "AddToCartWidget". Unfortunately, I'm now running into the following error:

    "Microsoft JScript runtime error: Object doesn't support property or method 'fancybox'"

    I have tried including the Telerik.Sitefinity.Resources.Themes.Basic.Styles.fancybox.css and JQueryFancyBox JavaScriptLibrary resources a number of different ways all to no avail.

    After a day of trying to get this to work I've made little measureable progress--pretty frustrating for something that should be pretty easy to do.

    --Steve

  5. Jochem Bökkers
    Jochem Bökkers avatar
    787 posts
    Registered:
    13 Aug 2007
    24 Jan 2012
    Link to this post
    Hey Steve,

    Sorry to hear you lost a full day, unfortunately I know how it feels...

    Since I replied to the other post regarding custom fields/labels I can understand why you're opting for an external custom control. Personally I try to avoid them as much as possible because even if things work smoothly during after an upgrade, they always mean extra time spent on testing. So that's why I didn't suggest it in this post...

    But since you already put some hefty time into it...
    (replying as I am reading - so I haven't tested it myself ok, but I'm sure Telerik will reply if I'm seeing things wrong)

    I'm pretty sure Sitefinty wrapped their validation tight, so even after you solved the 'fancybox' issue, I'm pretty sure you'll run into other issues.

    First thing you could try is assign a different ValidationGroup, perhaps that'll invoke it properly instead of the validation being ignored. As an alternative why not invoke a clientValidationfunction instead of OnServerValidate? Yes I don't like mixing server and client validation either, but since we merely need to verify a checkbox, I'd just avoid further headaches.

    ---
    A few days ago I posted a sample for Erick with an 'accept terms' checkbox, completely from the standard template editor although it didn't have a product type verification. I'd still go with that approach (with the addition from my previous post) since it is a 15 minute implementation and is a more flexible approach.

    (if the client decides later on he'd like more product types to be validated, it would mean just adding a custom field to a product type instead of opening up your code)

    ---
    But since we're here to help each other instead of trying to persuade each other to do what someone else thinks is easier, feel free to send me the code if the validationgroup trick doesn't work (jbokkers at live dot nl).

    I'm not the smartest kid in the class when it comes to coding, but I've got spare time :)

    J.
  6. SteveV
    SteveV avatar
    178 posts
    Registered:
    06 Nov 2011
    26 Jan 2012
    Link to this post
    Hi Jochem,

    Sorry for the late reply.  I spent some more time on this today and decided to scrap the custom control.  I ended creating a new template based on Product Detail Template.  I took your advice  and was able to get client validation working properly without having to resort to disabling the Add to Cart button.  Overall it works well but there are a couple of downsides worth noting:

    As you noted, there doesn't appear to be a way to determine the product type using client side scripting.  This is a pain because my product types have Custom Fields.  Normally, I'd let SF deal with displaying the Custom Field values on its own but there's a bug in the current version that results in the custom field values being displayed without their associated labels.  So to get that working I need to use Eval statements to grab the custom fiels data. Ugly things happen when you try to get custom fields that don't exist in a particular product type.  So in the end I wound up using the "Different template for each product type..." option.

    Here's the code just in case someone else needs to do something similar:
    <%@ Control Language="C#" %>
    <%@ Import Namespace="System.ComponentModel" %>
    <%@ Import Namespace="Telerik.Sitefinity.Ecommerce.Catalog.Model" %>
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Orders.Web.UI" TagPrefix="sfOrders" %>
    <%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Catalog.Web.UI.Fields" TagPrefix="sfCatalog" %>
    <%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.ContentUI" Assembly="Telerik.Sitefinity" %>
    <%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
    <%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit" Assembly="Telerik.Sitefinity" %>
    <%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
    <%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Modules.Ecommerce.Catalog.Web.UI" Assembly="Telerik.Sitefinity" %>
    <%@ Register Assembly="SitefinityWebApp" Namespace="SitefinityWebApp.CustomControls" TagPrefix="nlg" %>
    <sf:resourcelinks id="resourcesLinks" runat="server">
          <sf:ResourceFile JavaScriptLibrary="JQueryFancyBox"/>
        </sf:resourcelinks>
    <sf:resourcelinks id="resourcesLinks2" runat="server" useembeddedthemes="true" theme="Default">
          <sf:ResourceFile Name="Telerik.Sitefinity.Resources.Themes.Basic.Styles.fancybox.css" Static="true" />
        </sf:resourcelinks>
    <div id="widgetStatus" runat="server" visible="false" class="sfErrorSummary sfTopMsg">
        <asp:Label ID="widgetStatusMessage" runat="server" />
    </div>
    <sf:conditionaltemplatecontainer id="conditionalTemplate" runat="server">
            <Templates>
                <sf:ConditionalTemplate Left="IsActive" Operator="Equal" Right="false" runat="server">
                    <asp:Literal ID="Literal1" runat="server" Text="<%$Resources:OrdersResources, ProductNotAvailable %>" />
                </sf:ConditionalTemplate>
     
                <sf:ConditionalTemplate Left="IsActive" Operator="Equal" Right="true" runat="server">
                    <telerik:RadListView ID="SingleItemContainer" ItemPlaceholderID="ItemContainer" AllowPaging="False" runat="server" EnableEmbeddedSkins="false" EnableEmbeddedBaseStylesheet="false">
                        <LayoutTemplate>
                            <div class="sfproductDetails sfClearfix">
                                <asp:PlaceHolder ID="ItemContainer" runat="server" />
                            </div>
                        </LayoutTemplate>
                        <ItemTemplate>
                            <div class="sfproductImgsWrp">
                                <div class="sfproductMainImgWrp">
                                    <%-- This is so that we can have the rel="fancybox" without resorting to an Attributes.Add() call --%>
                                    <a href='<%# Eval("PrimaryImageUrl") %>' rel="fancybox">
                                        <img src='<%# Eval("Thumbnail.Url") %>' alt='<%# Eval("ThumbnailAlternativeText") %>' />
                                    </a>
                                </div>
     
                                <div class="sfproductImgsListWrp">
                                    <ul class="sfproductImgsList">
                                        <asp:Repeater ID="Repeater1" runat="server" DataSource='<%# new BindingList<ProductImage>(((IEnumerable<ProductImage>)Eval("Images")).Skip(1).ToList()) %>'>
                                            <ItemTemplate>
                                                <li class="sfproductImgWrp">
                                                    <a href='<%# DataBinder.Eval(Container.DataItem, "Url") %>' rel="fancybox" class="sfproductImgLnk">
                                                        <asp:Image ID="Image1" CssClass="sfproductImg" runat="server" ImageUrl='<%# DataBinder.Eval(Container.DataItem, "ThumbnailUrl") %>' Width='<%# (int)DataBinder.Eval(Container.DataItem, "ThumbnailWidth") %>' Height='<%# (int)DataBinder.Eval(Container.DataItem, "ThumbnailHeight") %>' />
                                                    </a>
                                                </li>
                                            </ItemTemplate>
                                        </asp:Repeater>
                                    </ul>
                                </div>
                            </div>
                            <div class="sfproductInfoWrp">
                                <div class="sfproductTitle">
                                    <%# Eval("Title") %>
                                </div>
                                <div class="sfproductPrice">
                                    <sfCatalog:DisplayPriceField ID="DisplayPriceField1" runat="server" ObjectType="Product" ObjectId='<%# Eval("Id") %>' />
                                </div>
                                <div class="sfproductDescription">
                                    <%# Eval("Description") %>
                                </div>
                                 
                                <!-- Begin Custom Fields from Video-On-Demand Product Type.  Workaround for SF showing the Custom Field value and skipping the label -->
                                <div class="nlgProductsCustomItemWrp">
                                    <div class="nlgProductsCustomItemWrp runningTime">
                                        Running Time: <sitefinity:TextField ID="TextField1" runat="server" DisplayMode="Read" Value='<%# Eval("Length")%>' CssClass="nlgProductsCustomItem" />
                                    </div>
                                    <div class="nlgProductsCustomItemWrp ceuCredits">
                                        CEUs: <sitefinity:TextField ID="TextField2" runat="server" DisplayMode="Read" Value='<%# Eval("CEUs")%>' CssClass="nlgProductsCustomItem" />
                                    </div>
                                </div>
                                <!-- End Custom Fields from Video-On-Demand Product Type -->
     
                                <div class="sfproductOptions">
                                    <sf:ProductOptionsControl id="productOptionsControl" ProductItem='<%# Page.GetDataItem() %>' runat="server" />
                                </div>
                                <div class="nlgTermsAndConditions">
             
                                    <asp:Label ID="TermsOfUseCaption" runat="server" Text="Label" CssClass="nlgTermsOfUseCaption">
                                        On-line Content Terms of Use:
                                    </asp:Label>
             
                                    <asp:Label ID="TermsOfUse" runat="server" Text="Label" CssClass="nlgTermsOfUse">
                                        All content and information is provided for informational purposes only and a professional should be consulted prior to relying on subject matter of this site.
                                    </asp:Label>
     
                                    <asp:CheckBox ID="TermsChkBox" runat="server" ClientIDMode="Static" CssClass="nlgTermsChkBox" Text="  I Agree" TextAlign="Right" />
                                    <asp:customvalidator id="TermsValidator" runat="server" clientvalidationfunction="ValidateTermsOfUse" enableclientscript="True" ValidationGroup="addToCart" Display="Dynamic">
                                        <span class="sfError">
                                            <asp:Literal runat="server" ID="TermsValidationMsg" Text="You must accept the On-line Content Terms of Use before this item can be added to your cart." />
                                        </span>
                                    </asp:customvalidator>
     
                                </div>
                                <sfOrders:AddToCartWidget ID="addToCartWidget" ProductId='<%# Eval("Id") %>' runat="server" />
                            </div>
                        </ItemTemplate>
                    </telerik:RadListView>
                </sf:ConditionalTemplate>
            </Templates>
        </sf:conditionaltemplatecontainer>
     
    <script language="javascript" type="text/javascript">
     
        function ValidateTermsOfUse( sender, args )
        {
            var chkBox = document.getElementById( 'TermsChkBox' );
     
            if ( !chkBox.checked )
                args.IsValid = false;
     
            else
                args.IsValid = true;
        }
     
    </script>


    Thanks again for all your help--as always, very much appreciated!

    Steve
  7. Jochem Bökkers
    Jochem Bökkers avatar
    787 posts
    Registered:
    13 Aug 2007
    27 Jan 2012
    Link to this post
    @Steve,

    Guess what?

    After 2hrs of adding labels in 'admin-settings-catalog-catalogproductsfrontend-views-productsfrontenddetail-label', adding 'CatalogResources' labels and trying to figure out stuff that's going wrong in 'catalog.config' I was ready to give before I decided to take 1 more look at the database...

    45mins later I was halfway through the tables and found the table [sf_meta_fields] and (insert annoying windows95 sound here) the [title_] field isn't populated for the custom fields.

    Nothing fancy or not implemented or anything, just a bug that doesn't save the [title_] field properly... (PS: Recycle app pool after adding the titles in the db)

    ---
    Now before you go and change all the custom templates back to a default one with proper labels, give me time this weekend to come up with a blond hack for the other issue (limiting quantity) as well ok?

    Jochem.
  8. SteveV
    SteveV avatar
    178 posts
    Registered:
    06 Nov 2011
    28 Jan 2012
    Link to this post
    Hi Jochem,

    Nice find--that did indead fix the problem.  Silly little problem to have made it through QC but those are the ones that alway seem to be the easiest to miss.

    Thanks--Steve

    PS: Love the book title
8 posts, 0 answered