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.
$(document).on("pagecreate", "#example", function () { /* validation code */ });data-role="page"bits. I'm not really sure this is the issue. Also I have disabled the normal AJAX submitting of the form.pagecreateandpageinitbefore 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.