2

I have a page that is using jQuery 1.11.1, the jQuery Validation plugin 1.12.1, jQuery Mobile 1.4.2, and ColdFusion 9.0.1. (I think the ColdFusion part is irrelevant to my issue though.) On this page I have a form that submits to itself for server-side validation. Initially, on the first load of the page, the form and validation all work as I expect. If the form is submitted with valid input it also works as I expect. If, however, the form is submitted with invalid input then I attempt to expand the collapsed collapsible in order to show the validation error message. This part does not work - the collapsible is not expanded and the following JavaScript error is thrown:

cannot call methods on collapsible prior to initialization; attempted to call method 'expand'

Once I receive this error then other features stop working as well. For example, the Cancel button can no longer collapse the collapsible. The validation messages no longer have my custom UI and fall-back to defaults, etc. I'm assuming the I need to somehow bind/delay my attempt to expand the collapsible to something when the page reloads but what?

Below is a self-contained example of my issue (written in CFML). Notice on the first load that you can expand the collapsible and collapse the collapsible using the Cancel button. Also notice the UI if you attempt to submit the form without entering any text. Then enter some text and submit the form. Upon reload you will see that the collapsible is not expanded initially. You will also see that the Cancel button no longer collapses the collapsible and that the UI of the validation messages has fallen back to defaults.

<cftry>
<html>
    <head>
        <title>Test</title>
        <link rel="stylesheet" type="text/css" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css" />
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>
        <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.12.0/jquery.validate.min.js"></script>
    </head>
    <body>
        <div id="example" data-role="page" data-theme="b">
            <div id="head" data-role="header" data-position="fixed">
                <h1 align="center">Example Header</h1>
            </div>
            <div role="main" class="ui-content">
                <div data-role="collapsible" data-content-theme="c" data-collapsed="false" data-collapsed-icon="arrow-r" data-expanded-icon="arrow-d">
                    <h3>Show Info Here</h3>
                    <p>Some additional information here...</p>
                    <cfif IsDefined("form.subcc")>
                        <p>CC form submitted. Form text = [<cfoutput>#form.ccname#</cfoutput>]</p>
                    </cfif>
                    <cfif IsDefined("form.subeft")>
                        <p>EFT form submitted. Form text = [<cfoutput>#form.eftname#</cfoutput>]</p>
                    </cfif>
                    <p>Choose one of the payment methods below.</p>
                </div>
                <div data-role="collapsible-set" data-content-theme="c" data-collapsed-icon="arrow-r" data-expanded-icon="arrow-d">
                    <div id="cc-payment" data-role="collapsible">
                        <h3>Credit Card Payment</h3>
                        <p>cc info here</p>
                        <div class="payment-form">
                            <form data-ajax="false" id="frmpaycc" method="post" action="">
                                <div class="ui-field-contain"><label for="ccname" class="ui-hidden-accessible">Text: </label> <input class="txtdata" type="text" id="ccname" name="ccname" size="20" maxlength="60" alphanumericwithbasicpunc="true" required="required" placeholder="Enter Text for CC" /></div>
                                <p align="center">
                                    <input type="submit" id="subcc" name="subcc" value="Make Payment" data-inline="true" data-mini="true" data-theme="b" />
                                    <a id="cancc" href="#" data-role="button" data-inline="true" data-mini="true">Cancel</a>
                                </p>
                            </form>
                        </div>
                    </div>
                    <div id="eft-payment" data-role="collapsible">
                        <h3>EFT Payment</h3>
                        <p>eft info here</p>
                        <div class="payment-form">
                            <form data-ajax="false" id="frmpayeft" method="post" action="">
                                <div class="ui-field-contain"><label for="eftname" class="ui-hidden-accessible">Text: </label> <input class="txtdata" type="text" id="eftname" name="eftname" size="20" maxlength="60" alphanumericwithbasicpunc="true" required="required" placeholder="Enter Text for EFT" /></div>
                                <p align="center">
                                    <input type="submit" id="subeft" name="subeft" value="Make Payment" data-inline="true" data-mini="true" data-theme="b" />
                                    <a id="caneft" href="#" data-role="button" data-inline="true" data-mini="true">Cancel</a>
                                </p>
                            </form>
                        </div>
                    </div>
                </div>
                <script type="text/javascript">
                    <cfif IsDefined("form.subcc")>
                        $("#cc-payment").collapsible("expand");
                    </cfif>
                    $("#cancc").click(function(){
                        $("#cc-payment").collapsible("collapse");
                    });
                    $("#frmpaycc").validate({
                        errorElement: "div",
                        submitHandler: function(form) {
                            $('#subcc').attr('disabled', 'disabled');
                            $('#frmpaycc,#frmpayeft').hide();
                            $("#msg-pay-proc").popup("open");
                            form.submit();
                        }
                    });

                    <cfif IsDefined("form.subeft")>
                        $("#eft-payment").collapsible("expand");
                    </cfif>
                    $("#caneft").click(function(){
                        $("#eft-payment").collapsible("collapse");
                    });
                    $("#frmpayeft").validate({
                        errorElement: "div",
                        submitHandler: function(form) {
                            $('#subeft').attr('disabled', 'disabled');
                            $('#frmpaycc,#frmpayeft').hide();
                            $("#msg-pay-proc").popup("open");
                            form.submit();
                        }
                    });
                </script>
                <div id="msg-pay-proc" class="ui-content" data-role="popup" data-theme="e">
                    <a href="#" data-rel="back" data-role="button" data-theme="a" data-icon="delete" data-iconpos="notext" class="ui-btn-right">Close</a>
                    <p>Processing your payment. Please be patient and do not navigate away from this page until a message is returned.</p>
                </div>
            </div>
            <div id="foot" data-role="footer" data-position="fixed" data-mini="true">
                <h1 align="center">Example Footer</h1>
            </div>
        </div>
    </body>
</html>
<cfcatch type="any">
    <cfdump var="#cfcatch#" />
</cfcatch>
</cftry>

I believe the issue is that the page is reloading itself via jQuery Mobile and perhaps the existing ID's are conflicting with each other in the DOM. The error message is explicit but I'm not sure how to delay or bind my attempt to expand the collapsible to get passed it.

8
  • IDs are conflicting with each other? IDs should always be unique in your code. Commented Aug 14, 2014 at 15:33
  • wrap your js code in $(document).on("pagecreate", "#example", function () { /* validation code */ }); Commented Aug 14, 2014 at 16:47
  • @Blazemonger - I'm thinking the IDs might be conflicting because the same document is being reloaded via the form submission. As I understand it, jQuery mobile does not really load an entire document but only brings in the data-role="page" bits. I'm not really sure this is the issue. Also I have disabled the normal AJAX submitting of the form. Commented Aug 14, 2014 at 17:58
  • 1
    @Omar - I think you got it! I tried using pagecreate and pageinit before posting my question but I obviously had something wrong. Your example seems to be working for me. Thanks so much! If you post an answer I can accept it. Commented Aug 14, 2014 at 18:12
  • Since you have Ajax disabled, DOM will be wiped and a fresh page will be loaded. Commented Aug 14, 2014 at 18:17

2 Answers 2

1

Any JS/jQuery code should be wrapped in pagecreate event. It is equivalent to .ready(), however, it is emitted on page fragments upon creating them and only once per page.

Moreover, this event can be delegated to be bound to specific pages based on their id or any other selector.

$(document).on("pagecreate", ".selector", function () {
  /* code */
});
Sign up to request clarification or add additional context in comments.

1 Comment

@Miguel-F you're welcome. To understand page events, pls check this and this.
0

I do not know coldfusion, but if a JQM page is "reloaded", even partially I believe (which it sounds like it is as you are not using JQ client side validation and there is a form POST with data-ajax="false", I could be wrong like I said I do not know CF), then you just have to manually initialize the widgets on pageinit or the appropriate event (add a ID or class to allow for JQ selection of the element) before you can call their respective methods.

So add in a script tag on the page:

$( document ).on( "pageinit", "#example", function( event ) {
    $("#yourCollapsibleElemnt").collapsible();
});

3 Comments

Actually I am using jQuery validation on the client side but I am also validating on the server side. When the page reloads after server side validation I see the issue. You and @Omar both have basically the same answer (his came first). Funny thing is I tried wrapping the JS in pageinit and pagecreate before asking here but it still did not work. I must have had the syntax wrong or something.
Glad you got it sorted :D
For future reference, I found that the pageinit event has been deprecated in jQuery Mobile 1.4.0 in favor of the pagecreate event. See documentation here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.