]> _ Git - fluidbook-html5.git/commitdiff
Refactoring MMenu for better mobile experience. WIP #1630 @5
authorStephen Cameron <stephen@cubedesigners.com>
Fri, 1 Sep 2017 16:36:27 +0000 (18:36 +0200)
committerStephen Cameron <stephen@cubedesigners.com>
Fri, 1 Sep 2017 16:36:27 +0000 (18:36 +0200)
js/libs/fluidbook/fluidbook.js
js/libs/fluidbook/fluidbook.nav.js
style/mmenu/mmenu.less

index 905921d2d853bf08ca1aea410c50b00db952d134..7efcc1d8847272d6dc937b9833298bb5da2d05fa 100644 (file)
@@ -726,23 +726,21 @@ Fluidbook.prototype = {
         return i + 1;
     },
 
-    hideMenuItems: function (exception) {
-        exception = exception || '';
-        $('#menuList > ul > li').not(exception).fadeOut(100);
+    hideMenuItems: function () {
+        $('#menuList > ul > li, #shareLinks').fadeOut(100);
     },
 
-    showMenuItems: function (exception) {
-        exception = exception || '';
-        $('#menuList > ul > li').not(exception).fadeIn(300);
+    showMenuItems: function () {
+        $('#menuList > ul > li, #shareLinks').fadeIn(300);
     },
 
     initSearchResults: function () {
         this.menuSearchResults = $('#menuSearchResults');
-        this.resizeSearchResults();
+        this.resizeMenu();
         this.menuSearchResults.hide();
     },
 
-    resizeSearchResults: function () {
+    resizeMenu: function () {
 
         //console.warn('calling resizeSR');
         //console.log('menu open?', this.nav.menuIsOpen);
@@ -751,8 +749,9 @@ Fluidbook.prototype = {
 
         var wh = $(window).height(),
             formHeight = $('#searchForm').height();
-            marginTop = marginBottom = 50,
-            maxHeight = wh - formHeight - marginTop - marginBottom;
+            marginTop = marginBottom = Math.min(Math.round(wh * 0.075), 50); // Relative margins with a max of 50
+            searchResultsMaxHeight = wh - formHeight - marginTop - marginBottom,
+            mainMenuMaxHeight = wh - $('#menuSearch').height() - $('#shareLinks').outerHeight();
 
         // Search results element may not exist when resize is called
         if (fluidbook.menuSearchResults == undefined) {
@@ -760,15 +759,27 @@ Fluidbook.prototype = {
             return false; // initSearchResults will call this resize function anyway
         }
 
+        // Max-height for the top level of the main menu so it can scroll between the search box and sharing bar
+        $('#menuList > ul').css('maxHeight', mainMenuMaxHeight);
+
         // Set max-height for search results section (using CSS vh units was unreliable)
-        fluidbook.menuSearchResults.css('maxHeight', maxHeight);
-        fluidbook.menuSearchResults.perfectScrollbar('update');
+        if (fluidbook.menuSearchResults !== undefined) {
+            fluidbook.menuSearchResults.css('maxHeight', searchResultsMaxHeight);
+            fluidbook.menuSearchResults.css('marginTop', marginTop);
+            fluidbook.menuSearchResults.perfectScrollbar('update');
+        }
+
+        // Also set same max-height for search hints
+        if (fluidbook.menuSearchHints !== undefined) {
+            fluidbook.menuSearchHints.css('maxHeight', wh - formHeight);
+            fluidbook.menuSearchHints.perfectScrollbar('update');
+        }
     },
 
     initSearchHints: function () {
 
         this.menuSearchHints = $('#menuSearchHints');
-        this.hideMenuItems('#menuSearch'); // Hide everything except the search form so we can have space for the hints
+        this.hideMenuItems(); // Hide menu items to give space for hints div
 
         this.menuSearchHints.fadeIn(300);
 
@@ -804,6 +815,12 @@ Fluidbook.prototype = {
         if (this.l10n.dir == 'rtl') {
             left = -1 * ($(window).width() - left - $("#q").outerWidth());
         }
+
+        this.menuSearchHints.perfectScrollbar({
+            suppressScrollX: true,
+            minScrollbarLength: 40
+        });
+
         $("#searchHints").css({top: top, left: left}).show();
     },
     killLastSearchHint: function () {
index 35965a3e5d1599419eb065b582b9b80eeb9c0b3a..0bd0ac78be4feb6293ade592ab3d5fedda12e8f7 100644 (file)
@@ -3,6 +3,8 @@ function FluidbookNav(fluidbook) {
     this._dimensions = this.fluidbook.datas.iconsDimensions;
     this.menuIsOpen = false;
     this.chaptersMenuHTML = '';
+    this.searchHTML = '';
+    this.shareLinksHTML = '';
     this.menu = $("#menu"); // Renamed from #nav because mmenu animations weren't working (probably due to some other script interference)
     this.horizontalNav = $("#horizontalNav");
     this._inited = {};
@@ -44,7 +46,9 @@ FluidbookNav.prototype = {
             $('body').addClass('menu-open');
             $this.menuIsOpen = true;
 
-            $('#q').focus();
+            setInterval($this.fluidbook.resizeMenu, 500);
+
+            //$('#q').focus(); // Disabled for now because it triggers the keyboard to open on some mobile devices
         });
 
         this.menuAPI.bind("close:finish", function () {
@@ -64,7 +68,7 @@ FluidbookNav.prototype = {
         });
 
         // Recalculate available size for menu search results
-        $(window).on('fluidbookresize', fluidbook.resizeSearchResults);
+        $(window).on('fluidbookresize', fluidbook.resizeMenu);
 
         // Handle swipe to close (it's only really practical to have this because swipe to open would interfere with main Fluidbook swipes)
         // We are not using MMenu's "Drag" add-on because it doesn't close the main menu, only submenus on swipe.
@@ -85,6 +89,15 @@ FluidbookNav.prototype = {
 
 
 
+        // Add search and share links to main menu panel
+        $('#menuList').append(this.searchHTML + this.shareLinksHTML);
+
+        // Add scrollbar to main menu
+        $('#menuList > ul, #chapterList').perfectScrollbar({
+            suppressScrollX: true,
+            minScrollbarLength: 40,
+            //maxScrollbarLength: 60
+        });
     },
     // getIcon: function (name) {
     //     var src = 'data/images/' + name + '.';
@@ -218,7 +231,7 @@ FluidbookNav.prototype = {
 
             // Add Search form, or if disabled, add "Menu" label in its place
             var searchElement = (this.fluidbook.datas.search) ? this.getSearch() : '<span>' + this.fluidbook.l10n.__('Menu') + '</span>';
-            $('#menuList').prepend('<li id="menuSearch">' + searchElement + '</li>');
+            this.searchHTML = '<div id="menuSearch">' + searchElement + '</div>'; // Save for later so it can be injected after MMenu is rendered
 
         // Horizontal icon nav
         } else if (navType == 'horizontalNav') {
@@ -340,8 +353,8 @@ FluidbookNav.prototype = {
                         }
                     }
 
-                    // Append to menu
-                    this.menu.find('ul').append('<li id="shareLinks"><div class="mm-nopanel share-icons">' + shareHTML + '</div></li>');
+                    // Save HTML so it can be added to menu once MMenu is initialised
+                    this.shareLinksHTML = '<div id="shareLinks"><div class="share-icons">' + shareHTML + '</div></div>';
                 }
 
 
@@ -463,6 +476,8 @@ FluidbookNav.prototype = {
                 $this.menuAPI.closeAllPanels(); // Make sure we're on the main panel with the search box
             }
             $this.menuAPI.open();
+
+            $('#q').focus(); // Put cursor in the search field
         });
 
         // Full screen toggle
@@ -671,6 +686,12 @@ FluidbookNav.prototype = {
                 fluidbook.hideSearchHints();
                 fluidbook.menuSearchResults.fadeIn(300);
 
+                // On some phones, the height of the search results is miscalculated due to the
+                // keyboard being open and reducing the available window height. We need to wait until
+                // the keyboard closes before trying to resize again...
+                setTimeout(fluidbook.resizeMenu, 500);
+
+
                 // Initialise scrollbar after populating so bars appear immediately
                 fluidbook.menuSearchResults.perfectScrollbar({
                     suppressScrollX: true,
index 4e9d8a439f966eb0a0b0521941950f4f08c045a2..592a7fdc9375c12aec1df76fe6bff180b82990cf 100644 (file)
@@ -6,6 +6,7 @@
 .mm-menu {
   &.mm-offcanvas {
     max-width: 320px;
+    width: 100%; // Max-width will limit overall width but this allows it to take up more space on very narrow screens
   }
 
   .mm-navbar {
@@ -111,7 +112,10 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim]~#mm-blocker {
 }
 
 #menuSearch {
-  margin-bottom: 23px; // Spacing between search panel and first menu item
+  position: fixed; // So we can scroll the other items below...
+  top: 0;
+  left: 0;
+  width: 100%;
 
   &:after {
     border: none;
@@ -121,12 +125,20 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim]~#mm-blocker {
 // Main menu with icons
 #menuList {
   overflow: hidden;
-  //padding-top: 80px; // Offset for the fixed search box plus some extra padding
+  position: relative;
+  height: 100%;
 
   &:before {
     height: 0; // Fix spacing with search box
   }
 
+  > ul {
+    margin-top: 60px; // Spacing for search box
+    margin-bottom: 0;
+    padding-top: 20px;
+    padding-bottom: 20px;
+  }
+
   .svg-icon {
     width: 26px;
     height: 26px;
@@ -295,6 +307,7 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim]~#mm-blocker {
 
   .share-icons {
     padding-left: 29px;
+    white-space: nowrap;
   }
 
   a {