SOLVED

Re: Customizing Forms 2.0 with Jquery - late loading

Go to solution
Brennan_McAdam2
Level 4
I have been experimenting with creating dynamic sections of a landing page based on the selection of from a select menu.  I finally figured out that I was having problems between when Jquery was ready and when the form actually loaded.  In the end, I ended up explicitly adding the Form2.js in the top of my html block to get the MktoForms2.whenReady to properly call.  However, I am wondering if anyone solved this differently as a hate loading a script in twice.
Brennan McAdams
Tags (1)
1 ACCEPTED SOLUTION
Brennan_McAdam2
Level 4
Found an even better solution.

Jquery is loading first as it is declared in the header.  As the Forms2.js is placed inline (after the header), I modifed the call to first check jQuery is ready, then check that the form is loaded to begin processing. 

//Attach change of select to display
    $(document).ready(function() {  //switched this to the top
        MktoForms2.whenReady(function (form){  //once jquery is ready, wait for the form
            $("#repurpose8").change( function(){
                changeLoc($(this).children('option:selected').index());
         });
        });
    });
Brennan McAdams

View solution in original post

11 REPLIES 11
SanfordWhiteman
Level 10 - Community Moderator
That last way can actually be less efficient.   By delaying attaching whenReady until after DOMReady you may introduce a delay (whether this delay is perceptible to humans depends of course on the complexity of your page) if you were also doing other stuff in whenReady that didn't care about the rest of the DOM.

May you're not totally getting what $(document).ready() (a.k.a. DOMready) means? It doesn't mean that "jQuery is ready" (in fact, it can't mean that, since $() is a jQuery function that will not work unless the jQuery library is loaded in-scope).  

DOMReady is fired when the entire initial DOM has loaded, that is, the "scaffolding" of the page but not necessarily all of the displayable content.  DOMReady isn't he same as the Marketo whenReady() nor is it a prerequisite for whenReady() to fire.  

One usually waits for DOMReady before adding event listeners, but that's not definitive.  You can add an event listener to a SELECT element before any more of the page is drawn and it will still work fine... of course, if the event listener code expects to find other elements in the page that aren't drawn yet, that will be a problem, but that's a separate concern.   

Bottom line is there is no one-size-fits all dependency pattern when dealing with jQuery's DOMReady and Marketo's whenReady and I would take care to not introduce dependencies without knowing why they are necessary.

 
Brennan_McAdam2
Level 4
Found an even better solution.

Jquery is loading first as it is declared in the header.  As the Forms2.js is placed inline (after the header), I modifed the call to first check jQuery is ready, then check that the form is loaded to begin processing. 

//Attach change of select to display
    $(document).ready(function() {  //switched this to the top
        MktoForms2.whenReady(function (form){  //once jquery is ready, wait for the form
            $("#repurpose8").change( function(){
                changeLoc($(this).children('option:selected').index());
         });
        });
    });
Brennan McAdams
Brennan_McAdam2
Level 4
Yes, I didn't realize that forms2.js was place inline and not at the header.
Brennan McAdams
SanfordWhiteman
Level 10 - Community Moderator
An inline SCRIPT tag is fine but MktoForms2 needs to be in-scope when you first call it...
Brennan_McAdam2
Level 4
I found it.  It was the forms2.js is placed below in my page and inline (not in the header).  So in my case it is late.  Thanks for helping.
Brennan McAdams
SanfordWhiteman
Level 10 - Community Moderator
@Brennan M There's no such line in my landing page; there's only the built-in forms2.min.js include that the LP adds to support the form widget.  

I do have a feeling there's something else in your page b/c I kept it as basic as possible.
Brennan_McAdam2
Level 4
Yes, the code works.  If you scan the javascripts that get loaded, In the code, i had to import the forms2.js into the block to get the MktoForms2.whenReady to work.  My question is has any else experienced late loading of forms? 

In your example, try removing the <script type="text/JavaScript" src="http://info.purestorage.com/js/forms2/js/forms2.min.js" ></script>.  Does it still work?  When testing this I found the forms2.js was loading in well after Jquery called ready.  Hence my second declarition in my script.  Perhaps it is something else in my page. 


BTW, I appreciate looking at this and burning the midnight oil.
Brennan McAdams
SanfordWhiteman
Level 10 - Community Moderator
OK, I threw together a landing page and reduced your code to the apparent problem area, but I don't see a problem. http://pages.vaneck.com/jq-whenready.html listens for the MktoForms2.whenReady event and then adds an Element.onChange event listener to the `Email` field, using jQ syntax for the native event.

There's nothing special about the Landing Page.  I added jQuery in the HEAD (using standard LP Actions >> Edit Page Meta Tags).  Then an HTML Element to hold the SCRIPT tag.
SanfordWhiteman
Level 10 - Community Moderator
How about a URL where that code is running, so I don't have to make my own landing page?
Brennan_McAdam2
Level 4
Here is the code.

<script type="text/JavaScript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js" ></script>
//This line here is required or the ReferenceError: MktoForms2 is not defined
<script type="text/JavaScript" src="http://info.purestorage.com/js/forms2/js/forms2.min.js" ></script>
    
<script type="application/javascript">
    var $ = jQuery.noConflict();

    var Locations = ["<b>San Francisco</b><br /> What a foggy city!","<b>New York</b><br /> It's the Big Apple, need we say more!", "<b>London</b><br /> It's a foggy city too, ever heard of London Fog?"];

    function changeLoc(i) {
        i = i - 1;
        $("#Location-Tag").html(Locations[i]);
    }


//requires a second inline load of forms2.min.js to be available.  See http://developers.marketo.com/documentation/websites/forms-2-0/    
MktoForms2.whenReady(function (form){
    //Attach change of select to display
    $(document).ready(function() {
//This is the failing element in that Jquery calls ready before form is loaded.
        $("#repurpose8").change( function(){
            changeLoc($(this).children('option:selected').index());
        });
    });
});

</script>
Brennan McAdams
SanfordWhiteman
Level 10 - Community Moderator
The goal isn't entirely clear (sorry!) without example code/URL.

Try to create an example of code that triggers the failure (rather than code you fixed with a workaround) and post the URL.