0

Introduction


I'm trying to mimic a server-side include like process but on the client-side instead. I have a header and panel navigation that I will reuse on every page of my Web app and I want to centralize it for easier more efficient maintenance.

My question is when is the best time in the page load event process to call upon my HTML "include" so that it can still get enhanced and a click/tap event can be bound to an image that will open the navigation panel?


The code


HTML - About Us Page (NOTES: single page template in use; left out the <head> code for simplicity)

    <div data-role="page" id="aboutUs" title="About Us">

        <div data-role="content"> 

            <p>My unique to the page content here</p>

        </div><!-- /content -->

    </div>
    <!-- /page About Us -->

HTML - Include Content

        <div id="headerContainer" data-role="header">
            <div class="companyLogoHeader"><img class="imgCompanyLogo" src="imgHeaderLogo.jpg" width="847" height="27" /></div>             
            <img id="imgPanelNavButton" src="icon-panel-bars.png" />
            <h2></h2>
        </div><!-- /header -->


        <div data-role="panel" data-position="left" data-display="reveal" id="nav-panel" data-theme="a">

                <ul data-role="listview" data-theme="a" data-divider-theme="a" style="margin-top:-16px;" class="nav-search">
                    <li data-icon="false" data-theme="g">
                        <a href="#" data-rel="back" data-direction="reverse"><img src="icon-panel-arrow-left.png" class="ui-li-icon ui-corner-none" /> Back</a>
                        <a href="#" data-rel="close" data-icon="delete" data-iconpos="notext" data-theme="h" style="margin-top:-1px;">Close Menu</a>
                    </li>
                    <li><a href="index.html"><img src="icon-panel-home.png" class="ui-li-icon ui-corner-none" /> Home</a></li>
                    <li><a href="scheduling.html"><img src="icon-panel-calendar.png" class="ui-li-icon ui-corner-none" /> Schedule</a></li>
                    <li><a href="services/services.html"><img src="icon-panel-list-bullets.png" class="ui-li-icon ui-corner-none" /> Services</a></li>
                    <li><a href="contact.html"><img src="icon-panel-phone.png" class="ui-li-icon ui-corner-none" /> Contact Us</a></li>
                </ul>

        </div>

JavaScript: (my understanding is the enhancement process happens just after the pagecreate event

$(document).on('pagebeforecreate', '#aboutUs', function()
{

$.ajax({
    url: 'assets/includes/SSI-Header-NavPanel.html',
    success: function(html) {
        $('[data-role="content"]').before(html); //Put the "include" code before the content container
        $('[data-role="header"]').find('h2').text($('[data-role="page"]').attr('title')).trigger('create'); // Once the "include" code is in the DOM, get the page title and insert it in the 'H2' tag for a page heading, then trigger a create for enhancement
        $('[data-role="page"]').trigger('create'); // adding this seem to help with the enhancements but didn't do the full job.  Don't even know if this is right?
        $('#imgPanelNavButton').on('click', function() { // now that the icon-panel-bars.png image is loaded into the DOM, bind a click event to it so it can open the panel on tap.
            $('#nav-panel').panel('open');
        });

    }
});


});

Some Observations:


  • The data-role="header" doesn't seem to get getting any of the enhanced classes, and additional data- attributes that the other pages on my site are getting where I haven't implemented this approach yet

  • The page seems to load somewhat when I refresh the About Us page including getting some of the enhancements, but then I try click a link from the homepage nothing is enhanced. For this page I'm wanting to do a data-prefetch from the homepage for other reasons as well.

  • Lastly, if I navigate away from the page after the content has been included then come back to it, I get a double insertion of the "include" content. For this should I wrap the AJAX request in and IF statement checking for the content? Or something more clever then that?


Please help and Thank You for taking the time.

WizzyBoom
  • 920
  • 1
  • 8
  • 18
  • [Please check out this excellent post by gajotres too](http://stackoverflow.com/questions/14550396/jquery-mobile-markup-enhancement-of-dynamically-added-content) – Ross Aug 06 '13 at 21:12

1 Answers1

1

Give this a try (separate from your code above) -

$('#aboutUs').one('pagebeforeshow', function(){
    $(this).trigger('pagecreate');
});

To answer your last question about only appending the ajax response once, you can use jQuery's one method for this. Like below -

$('#aboutUs').one('pagebeforecreate', function() {
    $.ajax({
        url: 'assets/includes/SSI-Header-NavPanel.html',
        success: function(html) {
            $('#aboutUs [data-role="content"]').before(html); //Put the "include" code before the content container
            $('#aboutUs [data-role="header"] h2').text($('#aboutUs [data-role="page"]').attr('title'));
            $('#aboutUs #imgPanelNavButton').on('click', function() { // now that the icon-panel-bars.png image is loaded into the DOM, bind a click event to it so it can open the panel on tap.
                $('#aboutUs #nav-panel').panel('open');
            });

        }
    });
});

Also, instead of $(document).on('pagebeforecreate', '#aboutUs', function() you can simply do $('#aboutUs').on('pagebeforecreate', function()

Here is a jsFiddle Demo that appends dynamic content to a page once and then triggers the pagecreate in the pagebeforeshow event

/Update

When you use $('[data-role="content"]'), $('[data-role="header"]'), and $('[data-role="page"]') as your selectors when appending content you are appending to the first instance of every content, header, and page within your jQM index page. To resolve this you need to refine your selector to $('#abousUs [data-role="content"]'), $('#aboutUs [data-role="header"]'), and $('#aboutUs [data-role="page"]')

Personally, I would do your ajax inside of a single pagebeforeshow because pagebeforechange triggers twice on each transition. Here is how I would do this -

$('#aboutUs').one('pagebeforeshow', function() {
    $.ajax({
        url: 'assets/includes/SSI-Header-NavPanel.html',
        success: function(html) {
            $('#aboutUs [data-role="content"]').before(html); //Put the "include" code before the content container
            $('#aboutUs [data-role="header"] h2').text($('#aboutUs [data-role="page"]').attr('title'));
            $('#aboutUs #imgPanelNavButton').on('click', function() { // now that the icon-panel-bars.png image is loaded into the DOM, bind a click event to it so it can open the panel on tap.
                $('#aboutUs #nav-panel').panel('open');
            });
            $('#aboutUs').trigger('pagecreate');
        }
    });
});

Notice I am using jQuery one for this pagebeforeshow. You can have additional pagebeforeshow for the aboutUs page still too.

Ross
  • 3,335
  • 1
  • 19
  • 18
  • I moved onto another part of the app I'm writing while I waited for a response to this one. Thank you. I'm just finishing up and will circle back around to this in the next day or two. Thank you and I'll let you know! – WizzyBoom Aug 08 '13 at 21:17