]> _ Git - fluidbook-html5.git/commitdiff
WIP #807 @6.5
authorStephen Cameron <stephen@cubedesigners.com>
Thu, 22 Jun 2017 18:01:55 +0000 (20:01 +0200)
committerStephen Cameron <stephen@cubedesigners.com>
Thu, 22 Jun 2017 18:01:55 +0000 (20:01 +0200)
js/libs/fluidbook/fluidbook.desktop.js
js/libs/fluidbook/fluidbook.js
js/libs/fluidbook/fluidbook.menu.js
js/libs/fluidbook/fluidbook.nav.js
js/main.js
style/mmenu/mmenu.less

index 14c7e48f5509186f971549ca0b1173fa5990b9b0..60fed437a57479c53991e62e8ff9a06eff9c6570 100644 (file)
@@ -46,7 +46,8 @@ FluidbookDesktop.prototype = {
         return false;
     },
     wheelZoom: function (delta) {
-        if ($("body").hasClass('view')) {
+        // Disable scroll zoom when either a view or the menu is open...
+        if ($("body").is('.view, .menu-open')) {
             return;
         }
         this.fluidbook.zoom.setZoom(this.fluidbook.zoom.zoom + delta / 3, delta > 0 ? 1 : -1);
index 59d982ea51c94b4210b964c88af1d5270b7fe9a1..360ce80b13eb96c8e72c6c2be138000d0ac83df1 100644 (file)
@@ -32,6 +32,7 @@ Fluidbook.prototype = {
         this.service = new FluidbookService(this, datas.id);
         this.support = new FluidbookSupport(this);
         this.loader = new FluidbookLoader(this);
+        this.index = new FluidbookIndex(this);
         this.search = new FluidbookSearch(this);
         this.pad = new FluidbookPad(this);
         this.links = new FluidbookLinks(this);
@@ -723,6 +724,9 @@ Fluidbook.prototype = {
         $('#menuList > ul > li').not(exception).fadeIn(300);
     },
 
+    initSearchResults: function () {
+        this.menuSearchResults = $('#menuSearchResults');
+    },
 
     initSearchHints: function () {
 
@@ -730,6 +734,9 @@ Fluidbook.prototype = {
         this.hideMenuItems('#menuSearch'); // Hide everything except the search form so we can have space for the hints
 
         this.menuSearchHints.fadeIn(300);
+
+        this.initSearchResults();
+
         // if (this.menuSearchHints.hasClass('mm-hidden')) {
         //     this.nav.menuAPI.openPanel(this.menuSearchHints, false);
         // }
@@ -770,8 +777,25 @@ Fluidbook.prototype = {
         // $("#searchHints").html('');
         // $("#searchHints").hide();
         this.menuSearchHints.html('').hide(); // Clear and hide all hints
-        this.showMenuItems('#menuSearch'); // Show menu items that were hidden previously
     },
+
+    hideSearchResults: function () {
+        this.menuSearchResults.html('').hide();
+    },
+
+    // Check if a search is active in the interface
+    isSearchActive: function () {
+        return ($('#q').val().length > 0);
+    },
+
+    // Clear search query and close search related menu items
+    closeSearch: function () {
+        $('#q').val(''); // Clear search field
+        this.hideSearchHints();
+        this.hideSearchResults();
+        this.showMenuItems(); // Show menu items that were hidden previously
+    },
+
     getLocationToShare: function () {
         if (this.datas.phonegap) {
             return this.datas.offlineLink;
index 53fde9b43a2c07761941f60645cacee78367b9bb..aec4e8e40d383bdc9bdb402707244f4b87a60293 100644 (file)
@@ -5,7 +5,6 @@ function FluidbookMenu(fluidbook) {
 
 FluidbookMenu.prototype = {
     init: function () {
-        this.index = new FluidbookIndex(this.fluidbook);
         var $this = this;
 
         $(document).on('click', ".mview .back", function () {
@@ -374,7 +373,7 @@ FluidbookMenu.prototype = {
     openIndex: function (title, group, closeAll, callback) {
         var c = !closeAll ? ' one' : '';
         var index = '<div class="caption">' + this.closeButton(c) + '<h2>' + title + '</h2></div>';
-        index += this.index.getView(group);
+        index += this.fluidbook.index.getView(group);
         $("#view").append('<div class="mview" data-menu="index">' + index + '</div>');
         this.fluidbook.bookmarks.updateBookmarks();
         if (callback != undefined) {
index 88c5c460c5e35307b03fdf70f1689b2337125dbb..a5244acdfa37a9c67a65819089a8eca32a2cc3df 100644 (file)
@@ -56,10 +56,12 @@ FluidbookNav.prototype = {
 
         // Bind API hooks (see http://mmenu.frebsite.nl/documentation/core/off-canvas.html#h4)
         this.menuAPI.bind("open:finish", function () {
+            $('body').addClass('menu-open');
             $this.menuIsOpen = true;
         });
 
         this.menuAPI.bind("close:finish", function () {
+            $('body').removeClass('menu-open');
             $this.menuIsOpen = false;
         });
 
@@ -337,8 +339,18 @@ FluidbookNav.prototype = {
 
         // Click handler to close menu
         $(document).on('click', '#' + buttonID, function(e) {
+
             e.preventDefault();
-            $this.menuAPI.close();
+
+            // If the search is active, the close button should clear the search
+            // and return the user to the main menu instead of closing the menu
+            if ($this.fluidbook.isSearchActive()) {
+                $this.fluidbook.closeSearch();
+            } else {
+                $this.menuAPI.close();
+            }
+
+
         });
 
         return '<a href="#" id="'+ buttonID +'">'+ getSpriteIcon('interface-close') +'</a>';
@@ -364,15 +376,94 @@ FluidbookNav.prototype = {
         // Search form handler
         $(document).on('submit', '#searchForm', function () {
             var q = $("#q").val();
+
             if (q == '') {
                 return false;
             }
 
             $this.fluidbook.search.find(q, function (results) {
-                // Todo: see FluidbookMenu displayResults function...
+
+                // Handle empty result set
+                if (results.total <= 0) {
+                    fluidbook.menuSearchResults.html(this.fluidbook.l10n.__('no result found'));
+                    return false;
+                }
+
+                var hits = [];
+
+                // Create a list of all pages so we can record which ones have a hit on the search term
+                for (var i = 0; i <= $this.fluidbook.datas.pages; i++) {
+                    hits[i] = 0;
+                }
+                // Map result hits to pages
+                $.each(results.results, function (k, v) {
+                    hits[k] += v;
+                });
+
+                // ToDo: check the purpose of the group variable? Also check tracking
                 //$this.displayResults(r, group, cb);
-                console.log('Search results...');
-                console.log(results);
+                //console.log('Search results...');
+                //console.log(results);
+
+                // Display results
+                //res += $this.fluidbook.l10n.__('search results for') + ' &laquo; ' + q + " &raquo;"
+
+                // Use the index of all pages as a starting point to filter results thumbnails
+                fluidbook.menuSearchResults.html($this.fluidbook.index.getView()).hide();
+
+                // Process each spread of pages to collect the ones with results
+                fluidbook.menuSearchResults.find('.doubleThumb').each(function() {
+
+                    var currentPages = $(this).data('pages').toString().split(','),
+                        totalHits = 0,
+                        pagesWithHits = [];
+
+                    // Get total number of hits for pages in this spread
+                    for (var i in currentPages) {
+                        var pageNum = parseInt(currentPages[i]);
+                        if (hits[pageNum] > 0) {
+                            totalHits += hits[pageNum];
+                            pagesWithHits.push(currentPages[i]);
+                        }
+                    }
+
+
+                    // If there's already a .hits element, this spread has already been processed
+                    if ($(this).find('.hits').length > 0) {
+                        return;
+                    }
+
+                    if (totalHits == 0) {
+                        // Should pages with no results still be shown?
+                        if (fluidbook.datas.searchShowNoResultsPages) {
+                            $(this).append('<div class="overlay"></div>');
+                            $(this).append('<div class="hits no">' + $this.fluidbook.l10n.__('no result found') + '</div>');
+                        } else {
+                            $(this).remove();
+                            return;
+                        }
+                    } else {
+                        // Add the
+                        $(this).append('<div class="hits yes">' + totalHits + ' ' + fluidbook.l10n.__('hit(s)') + '</div>');
+                        if (fluidbook.pad.enabled) {
+                            if (pagesWithHits.length == 1) {
+                                $(this).find('a').attr('href', '#/page/' + pagesWithHits[0]);
+                            } else {
+                                $(this).find('a').attr('href', '#/search/' + e + '/' + $(this).attr('page'));
+                            }
+                        } else {
+                            $(this).find('a').attr('href', '#/page/' + $(this).attr('page'));
+                        }
+                    }
+
+                });
+
+                // Todo: handle results.terms here... Highlighting?
+
+
+                fluidbook.hideSearchHints();
+                fluidbook.menuSearchResults.fadeIn(300);
+
             });
 
             // window.location.hash = '/search/' + q;
@@ -385,7 +476,10 @@ FluidbookNav.prototype = {
         });
 
         //$("#q").keyup(searchHints);
-        $(document).on('keyup', '#q', searchHints);
+        $(document).on('keyup', '#q', function(key) {
+            if (13 == key.which) return; // Ignore enter key otherwise hints are re-displayed after form is submitted
+            searchHints();
+        });
 
         $(document).on('click', ".hint", function () {
             var e = $("#q").val().split(' ');
index 592a97691cf5888699cb83aa695d44a78e46d555..fd562bf97e85f96c6ec5febd5c7fd65eaf567e35 100644 (file)
@@ -505,6 +505,8 @@ function searchHints() {
     } else {
         try {
             fluidbook.hideSearchHints();
+            fluidbook.hideSearchResults();
+            fluidbook.showMenuItems(); // Show main menu items that were hidden previously
         } catch (err) {
 
         }
index 64a601a0d2deab6c758cc2c013abcb30e3022d0b..f7995bb17a5061e7a4c8a66e4b0014e5366dbd80 100644 (file)
@@ -89,6 +89,8 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim]~#mm-blocker {
 
 // Main menu with icons
 #menuList {
+  padding-top: 60px; // Offset for the fixed search box...
+
   &:before {
     height: 0; // Fix spacing with search box
   }
@@ -115,7 +117,9 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim]~#mm-blocker {
 
 
 #searchForm {
-  position: relative;
+  position: fixed;
+  top: 0;
+  left: 0;
   padding: 0;
   text-align: left;
 }
@@ -141,5 +145,25 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim]~#mm-blocker {
   .svg-icon {
     width: 20px;
     height: 20px;
+    margin-top: 1px; // Fixes weird clipping of top of icon
+  }
+}
+
+#menuSearchResults, #menuSearchHints {
+  display: none; // Hidden by default, displayed via JS
+}
+
+#menuSearchResults {
+  max-height: ~"calc(100vh - 60px)";
+  overflow-y: auto;
+  padding-top: 20px;
+
+  .doubleThumb {
+    display: block !important;
+    margin: 10px auto 40px auto !important;
+  }
+
+  .padding {
+    display: none !important;
   }
 }
\ No newline at end of file