Search code examples
jqueryjquery-mobilemenuslidingdrawer

How to implement a ResideMenu on jQuery Mobile?


I would like to implement a ResideMenu just like the image, here is the link:

http://d13yacurqjgara.cloudfront.net/users/107759/screenshots/1114754/social_feed_ios7.gif

Please, any help or component?

Thanks.


Solution

  • To achieve this, you need to setup the following:

    1. Transition CSS3 classes transform3d, scale3d and transition.
    2. Create a div with contents any place in body outside page div.
    3. Apply changes on active page pre-animation and revert all defaults post-animation.

    1. ResideMenu content div and related styles:

      Create a div and place it in body. Make sure position: absolute; and low z-index: -9999;, as that div shouldn't be visible/clickable even if its hidden.

      HTML

      <div id="content">
        <!-- content -->
      </div>
      

      CSS

      #content {
        height: 100%;
        width: 50%;
        position: absolute;
        top: 5px;
        left: 5px;
        z-index: -9999;
      }
      
    2. Transformation and animation:

      Create three classes; showing, hiding and animating the aforementioned steps.

      Animation class - you can play with animation speed 500ms.

      .panel-animate {
          -webkit-transition: all 500ms ease;
          -moz-transition: all 500ms ease;
          -ms-transition: all 500ms ease;
          -o-transition: all 500ms ease;
          transition: all 500ms ease;
      }
      

      Menu showing/revealing class - page is moved 60% on X-Axis and scaled down by 60% of its' width and height. You can play with those values as well.

      .panel-open {
          -webkit-transform: translate3d(60%, 0, 0) scale3d(0.6, 0.6, 1);
          -moz-transform: translate3d(60%, 0, 0) scale3d(0.6, 0.6, 1);
          -ms-transform: translate3d(60%, 0, 0) scale3d(0.6, 0.6, 1);
          -o-transform: translate3d(60%, 0, 0) scale3d(0.6, 0.6, 1);
          transform: translate3d(60%, 0, 0) scale3d(0.6, 0.6, 1);
      }
      

      Menu hiding class.

      .panel-close {
          -webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
          -moz-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
          -ms-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
          -o-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
          transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
      }
      
    3. Code to show/hide menu:

      First step, if ResideMenu contains any jQuery Mobile widgets, they should be initialized manually since the reside outside page div. To manually initialize/create jQM widget, call .enhanceWithin() on parent div, then hide ResideMenu div.

      $("#content").enhanceWithin().hide();
      

      Showing ResideMenu - consists of four steps.

      1) Hide Y-Axis overflow on body to avoid scroll once menu is shown. 2) Update page's height according to viewport's height. If toolbars (header/footer) are used in that page, 88px (top & bottom padding) should be subtracted from viewport's height. If either header or footer is used, subtract 44px. 3) Apply animation classes to show the menu. 4) Unhide menu div.

      $(".panel").on("click", function () {
         $("body").css({ "overflow-y": "hidden" });
         $(".ui-page-active").height($(window).height() - 88);
         $(".ui-page-active").addClass("panel-animate panel-open");
         $("#content").show();
      });
      

      Hiding ResideMenu - simple step, just remove opening class and add closing class. However, note that menu's z-index should be changed again to low value. Because when it's shown, z-index is set to high value, explanation will come in next setp.

      $(".panel-close-btn").on("click", function () {
         $(".ui-page-active").addClass("panel-close").removeClass("panel-open");
         $("#content").css("z-index", "-9999");
      });
      

      Changes to be made in between the previous two steps. These changes should be applied after animation/transition is done by listening to transitionend event.

      1) If menu is revealed, its' z-index should be set to high value in order to become clickable/touchable. 2) If menu is closed/hidden, it should be hidden after transition is done. 3) Remove ALL custom CSS applied to both body and active page. 4) Add back header/footer 88px padding to active page and remove closing & animating classes. 5) Since active page's height is modified prior to revealing the menu, it should be returned as it was before by calling $.mobile.resetActivePageHeight().

      $(document).on("webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd", ".panel-open, .panel-close", function (e) {
          if ($(this).hasClass("panel-open")) {
              $("#content").css("z-index", "9999");
          }
          if ($(this).hasClass("panel-close")) {
              $("#content").hide();
              $("body, .ui-page-active").removeAttr("style");
              $(this).removeClass("panel-animate panel-close").css({ padding: "44px 0" });
              $.mobile.resetActivePageHeight();
          }
      });
      

    Demo (1)

    (1) Tested on Safari & Chrome for Mobile - iPhone 5 and iPad 2.