开发者

jqueryMobile footer on nested list

开发者 https://www.devze.com 2023-03-05 08:26 出处:网络
I have a nested list in a jQuery Mobile test app.And it has开发者_运维技巧 a fixed footer. Works great until I click on an item in the list.Anything past the top level of the list has no footer.

I have a nested list in a jQuery Mobile test app. And it has开发者_运维技巧 a fixed footer.

Works great until I click on an item in the list. Anything past the top level of the list has no footer.

Is there a way to keep the footer throughout the Nested List navigation?

Thanks in advance.

Adam.

Here's the code:

    <!-- ################ Menu Page  ##################### -->  

<div data-role="page" id="home" data-theme="a">
 <div data-role="header" data-position="inline">
  <h1>Menu</h1>
 </div>
 <div data-role="content">
  <ul data-role="listview">
    <li><a href="#">List</a>
      <ul data-role="listview" data-theme="c">
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
      </ul>
    </li>
    <li><a href="#">List</a> 
      <ul data-role="listview" data-theme="c">
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
      </ul>
    </li>
    <li><a href="#">List</a>
      <ul data-role="listview" data-theme="c">
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
      </ul>
    </li>
    <li><a href="#">List</a>
      <ul data-role="listview" data-theme="c">
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
        <li><a href="index.html">List</a></li>
      </ul>
    </li>
  </ul>
 </div><!-- eof content -->
 <div data-role="footer" data-position="fixed" data-id="myfooter">
   <div data-role="navbar">
     <ul>
       <li><a data-icon="grid" data-iconpos="top" href="#home">Menu</a></li>
       <li><a data-icon="star" data-iconpos="top" href="#location">Location</a></li>
       <li><a data-icon="alert" data-iconpos="top" href="http://www.site.com" rel="external">Full Site</a></li>
       <li><a data-icon="grid" data-iconpos="top" href="#addpad">Pad</a></li>
       <li><a data-icon="info" data-iconpos="top" href="#more">More</a></li>  
     </ul>       
   </div><!-- /navbar -->  
 </div><!-- eof footer -->
</div><!-- eof page#home --> 


I've been banging my head against this problem for several days, and for once Google was no help. I finally came up with the following solution. It copies the header HTML onto a new page before the transition begins, then removes the code from the previous page once the transition completes. The header and footer will still move with the page transition, but they will persist even while navigating nested lists.

// dynamically move the header and footer between pages on load events
$('div.ui-page').live('pagebeforeshow', function(event, ui) {
    // avoid duplicating the header on the first page load
    if (ui.prevPage.length == 0) return;

    // remove the jQuery Mobile-generated header
    $('.ui-header').addClass('to-remove-now');
    $('#header').removeClass('to-remove-now');
    $('.to-remove-now').remove();

    // grab the code from the current header and footer
    header = $('#header')[0].outerHTML;
    footer = $('#footer')[0].outerHTML;

    // mark the existing header and footer for deletion
    $('#header').addClass('to-remove');
    $('#footer').addClass('to-remove');

    // prepend the header and append the footer to the generated HTML
    event.currentTarget.innerHTML = header + event.currentTarget.innerHTML + footer;
});

// remove header from previous page 
$('div.ui-page').live('pagehide', function(event, ui) {
    $('.to-remove').remove();
});

Then just add id="header" to the header div and id="footer" to the footer, and place them as you normally would in your content.


This is how I went about it, footer only though. The attribute removal is to prevent the initialization code from executing twice which results in multiple spans in the blocks. This method keeps all the class styles on the elements for styling. Another nice thing is the code only has to run once on pagecreate to append the footers.

$('div.ui-page:not(#mainPage)').live('pagecreate', function(event) {
    if ($(event.currentTarget).find('footer').length == 0)
    {

        var footer = $('#footerNavBar').html(); 

        $(event.currentTarget).append( '<footer class="footerNavBar">' +footer + '</footer>');
        $(event.currentTarget).find('.ui-navbar').removeAttr('data-id').removeAttr('data-role').removeAttr('role');
    }
});

.

<div data-role="page" id="mainPage">
            <header data-role="header" data-position="inline" id="mainHeader">
                <h1>
                    <img src="images/icon.png" alt="icon" />
                </h1>
            </header>
        <section data-role="content">

        </section>
        <footer data-role="footer" data-position="fixed" id="footerNavBar">
            <div data-role="navbar" data-id="footerNavBar">
                    <ul>
                        <li><a href="index.html" data-icon="home" data-iconpos="bottom" data-prefetch>Home</a></li>
                        <li><a href="link2.html">Link 2</a></li>

                    </ul>
                </div>
            </footer>
        </div>


I've found that putting the tabbar (footer) outside of the jqt div works great.

My DZ/jQT fork --> https://github.com/DataZombies/jQTouch

Demo --> http://web.me.com/djpinter1/iPhone/jqtouch/demos/main_tabbar/


I was able to solve this problem with the following approach. It was made possible by Mikkel's response so thank you for sharing that!

/*  */

function prepareHeaderFooterForULDiving(pageName) {
    // dynamically move the header and footer between pages on load events
    $(document).bind('pagebeforeshow', function(event, ui) {
        // If the previous page length is zero then we couldn't possibly be drilling into a nested list this very moment
        if (ui.prevPage.length == 0) return;

        var pathname = window.location.pathname;
        var fullPath = $(location).attr('href');
        //alert (pathname +" versus1 "+fullPath);

        // Don't add an extra header and footer to a page that doesn't need it
        // The pathname must end with the page name and the fullPath must NOT end with .php (all nested list pages will have extra pieces)
        var regex = new RegExp(pageName+"$");
        if (pathname.match(regex) && !fullPath.match(/.php$/)) {
            $headerObj = $('[id^=header]:last');
            $footerObj = $('[id^=footer]:last');
            // Since we find the latest header and footer (and since that latest one might be the one we want to display
            var beginningState = event.currentTarget.innerHTML;
            var beginningHeader = $headerObj[0].outerHTML;
            var beginningFooter = $footerObj[0].outerHTML;
            // Before we copy the header and footer, find out if we are copying a copy or not; if we are, 
            // make sure we add special handling to get rid of the first copy when we hide the current page
            var alreadyHadClass = $headerObj.hasClass('to-remove');
            // copy the code from the current header and footer but before you clone it, add the to-remove class to it; that way
            // we only end up removing the footers and headers that we have dynamically added!
            // Get the latest header and footer; there's a possibility the header would be grabbed from a prior loaded page that isn't presently visible (and with a misleading phrase)
            // Multiple layers of ULs could end up causing the wrong footer to be removed
            $headerObj.addClass('to-remove');
            $footerObj.addClass('to-remove');
            var header = $headerObj[0].outerHTML;
            var footer = $footerObj[0].outerHTML;

            // Now that we know that we are going to be drawing on this particular branch of the contactUs.php UL leaf, mark every previous 
            // leaf (if applicable in higher or lower part of the tree) for immediate removal once the page is hidden
            // Do NOT do this before we clone
            if (alreadyHadClass) {
                $('.to-remove').addClass('removeOncePageHidden');
            }
            // Remove the temporary designation; this way we don't accidentally remove contactUs.php's header when we return
            $headerObj.removeClass('to-remove');
            $footerObj.removeClass('to-remove');

            // Optionally, you could remove the auto-generated header (with the next ul's content); but I kinda like it
            // remove the jQuery Mobile-generated header
            //$('.ui-header').addClass('to-remove-now');
            //$('.to-remove-now').remove();

            // For some crazy reason this pagebeforeshow can be fired TWICE! Ridiculous I know; only update the screen if it doesn't 
            // already look like that. Otherwise, you'll end up with a flashing of an instant where the first-added header and footer
            // display and then get removed during the pagehide
            if ( beginningState.indexOf(beginningHeader) != -1 || beginningState.indexOf(footer) != -1 ) {
                // this script has just been fired twice and the header that we copied we don't need any more; the page is fine except that we just removed the class that needs to stay there
                console.log("Didn't do it!");
                $headerObj.removeClass('removeOncePageHidden');
                $footerObj.removeClass('removeOncePageHidden');
            } else if ( beginningState.indexOf(header) == -1 &&  beginningState.indexOf(footer) == -1 ) {
                // prepend the header and append the footer to the generated HTML
                console.log("weird: "+header+"\nbut the kicker: "+beginningState);
                event.currentTarget.innerHTML = header + event.currentTarget.innerHTML + footer;
            } else {
                // We didn't just create a new one so undo the addition of the 'remove it now' Class; we'll 
                // go ahead and keep it since this code has been fired twice now for one page load
                console.log("whoah");
                $headerObj.removeClass('removeOncePageHidden');
                $footerObj.removeClass('removeOncePageHidden');

            }
        }
    });

    $(document).bind('pagehide', function(event, ui) {
        $('.removeOncePageHidden').remove();
        var fullPath = $(location).attr('href');
        //alert ("Should we remove anything here: "+fullPath);
        // We only need to run this code when we're navigating into a page that is a top-level page (nested-list-generated pages have 'fun' characters appended beyond the .php)
        if (fullPath.match(/.php$/)) {
            //alert("Removing all to-removers");
            $('.to-remove').remove();
        }
    });
}

This is my first foray into jquerymobile scripting so there could be some problematic aspect I'm not aware of but all my navigation attempts have succeeded at generating the behavior I was in search of. One curious thing was that the script appeared to keep firing even after I left my contactUs page. My if statements kept it from misbehaving but perhaps it's something others will need to be wary about.

My footer is not fixed position which seems like might have different behavior or response to this but perhaps this will help you as well.

0

精彩评论

暂无评论...
验证码 换一张
取 消