]> _ Git - fluidbook-html5.git/commitdiff
Refactor helpView, add proper support for interface scaling and fix numerous display...
authorStephen Cameron <stephen@cubedesigners.com>
Tue, 10 Oct 2017 16:07:29 +0000 (18:07 +0200)
committerStephen Cameron <stephen@cubedesigners.com>
Tue, 10 Oct 2017 16:07:29 +0000 (18:07 +0200)
js/libs/fluidbook/fluidbook.help.js
js/libs/fluidbook/fluidbook.resize.js
style/fluidbook.less
style/mmenu/mmenu.less

index ee4b61213d30f34727727a1ebce47673148c6488..489268ae4454bc4f6f198d32406fcdf7b1546f63 100644 (file)
@@ -43,12 +43,6 @@ FluidbookHelp.prototype = {
 \r
                // Icons\r
                help += '<div id="icons">';\r
-               // var scale = $("#horizontalNav").transform('scaleX');\r
-               // $("#horizontalNav").transform({\r
-               //      scale: [1, 1]\r
-               // }, {\r
-               //      preserve: true\r
-               // });\r
 \r
         var tooltipSelector = '#horizontalNav a[data-tooltip]';\r
 \r
@@ -203,88 +197,64 @@ FluidbookHelp.prototype = {
 \r
                // ToDo: access variables from fluidbook.resize.* if they're not passed to the function. So resize function can be called directly...\r
 \r
-               var $this = this;\r
-               var menuHeightScaled = (this.fluidbook.datas.menuHeight) * navScale;\r
+               var $this = this,\r
+                       dir = this.fluidbook.l10n.dir,\r
+                       menuHeightScaled = (this.fluidbook.datas.menuHeight) * navScale,\r
+                       arrow = $('#interface #next').get(0).getBoundingClientRect(), // Used for calculating offsets for both #next & #previous\r
+                       nextTop,\r
+                       firstTop;\r
+\r
+               // The arrow element contains both arrows in a single image\r
+               // so we calculate the top position of the labels by percentage\r
+               nextTop = Math.round(arrow.top + arrow.height * 0.35);\r
+               firstTop = Math.round(arrow.top + arrow.height * 0.71);\r
+\r
+        // Navigation arrow labels\r
+               this.view.find('.previous, .next').css({\r
+                       top: nextTop\r
+               });\r
+               this.view.find('.first, .last').css({\r
+                       top: firstTop\r
+               });\r
 \r
-               // this.view.css({\r
-               //      width: ww,\r
-               //      minHeight: hh - menuHeightScaled,\r
-               //      top: menuHeightScaled\r
-               // });\r
+               // Labels are swapped for RTL documents\r
+               var prevPosition = (dir == 'ltr') ? {left: Math.round(arrow.width)} : {right: Math.round(arrow.width)},\r
+                       nextPosition = (dir == 'ltr') ? {right: Math.round(arrow.width)} : {left: Math.round(arrow.width)};\r
 \r
+               this.view.find('.previous, .first').css(prevPosition);\r
+               this.view.find('.next, .last').css(nextPosition);\r
 \r
-        // Navigation arrows\r
-               this.interfaceTop = (hh - 100 * interfaceScale) / 2 + 30 * interfaceScale;\r
-               this.view.find('.next, .previous, .first, .last').css({\r
-                       top: this.interfaceTop\r
-               });\r
 \r
                // Slider label\r
         var positionSliderLabel = function () {\r
             var sliderHelp = $this.view.find('.slider');\r
             var sliderCursor = $('#slidercursor .visible');\r
             sliderHelp.css({\r
-                bottom: (hh - sliderCursor.offset().top) * navScale,\r
-                left: sliderCursor.offset().left + (sliderCursor.width() / 2 * navScale),\r
-                               transformOrigin: '0 0'\r
+                bottom: Math.round(hh - sliderCursor.offset().top),\r
+                left: Math.round(sliderCursor.offset().left + (sliderCursor.width() / 2)),\r
+                               transformOrigin: 'left bottom'\r
             });\r
         };\r
         positionSliderLabel(); // Run immediately\r
                setTimeout(positionSliderLabel, 250); // delay slightly to make sure co-ordinates are correct\r
 \r
                this.view.find('#icons').css({\r
-                       'top': menuHeightScaled,\r
-                       'transform': 'scale('+ navScale +')',\r
-                       'transformOrigin': '0 100%'\r
+                       top: menuHeightScaled,\r
+                       transform: 'scale('+ navScale +')'\r
                });\r
 \r
                $("#helpView #icons").css({\r
                        fontSize: (14 / navScale) * interfaceScale\r
                });\r
 \r
-               // $("#helpView .illustration").transform({\r
-               //      scale: [interfaceScale, interfaceScale],\r
-               //      origin: ['50%', '50%']\r
-               // });\r
-\r
                this.view.find('.illustration').css({\r
                        transform: 'translate(-50%, -50%) scale('+ interfaceScale +')'\r
                });\r
 \r
-               // ToDo: refactor bookmarkLabel code so that a scale transform can be applied without messing up positioning (wrap all 3 elements in a div? Handle RTL differences)\r
-\r
                $("#helpView .interface").find('> div').transform({\r
                        scale: [interfaceScale, interfaceScale]\r
                })\r
 \r
-               // ToDo: refactor this and try to move transform-origins to CSS. Make sure that .first and .last label positions factor in interfaceScale\r
-\r
-               $("#helpView .interface").find('.last').transform({\r
-                       origin: ['100%', '100%']\r
-               }, {\r
-                       preserve: true\r
-               });\r
-\r
-               $("#helpView .interface").find('.first').transform({\r
-                       origin: ['0%', '100%']\r
-               }, {\r
-                       preserve: true\r
-               });\r
-\r
-               $("#helpView .interface").find('.next').transform({\r
-                       origin: ['100%', '0%']\r
-               }, {\r
-                       preserve: true\r
-               });\r
-\r
-\r
-               $("#helpView .interface").find('.previous').transform({\r
-                       origin: ['0%', '0%']\r
-               }, {\r
-                       preserve: true\r
-               });\r
-\r
-               //this.view.find('.illustration').css('margin-top', (hh - 200 * interfaceScale) / 2);\r
        },\r
        clearTimeout: function() {\r
                clearTimeout(this.autoTimeout);\r
@@ -313,11 +283,6 @@ FluidbookHelp.prototype = {
             baseElement = $('#links .bookmark.' + side), // Original element used to provide position and sizing for overlay\r
             html = '';\r
 \r
-        // Don't show the label if there's no space for it (ie. the side doesn't exist in this view)\r
-        // if ((isFirst && side == firstMissing) || (isLast && side == lastMissing)) {\r
-        //     return '';\r
-        // }\r
-\r
         // If bookmark icon isn't present on the side we want, it means that we're on\r
         // the first/last page and that side is missing so we can't display the help\r
         if (baseElement.length == 0) {\r
@@ -326,61 +291,76 @@ FluidbookHelp.prototype = {
 \r
         // Get the offset and dimensions of the element, taking into account the scaling\r
         var box = baseElement[0].getBoundingClientRect(),\r
-            circleExtra = 20, // How much bigger the circle should be around the bookmark icon\r
+            circleExtra = 20 * this.fluidbook.resize.interfaceScale, // How much bigger the circle should be around the bookmark icon\r
             lineLength = 30; // Length of the line to the label text\r
 \r
+        // The bookmark icon sits inside a circle that is slightly bigger so in order to make the icon sit exactly\r
+        // on the corner of the page, we must offset the difference added by the larger wrapping circle.\r
+        var circleOffset = circleExtra / 2;\r
+\r
         // Build a HTML string via jQuery with all the styling\r
         // Bookmark icon:\r
-        html += $('<div/>').css({\r
-            'position': 'absolute',\r
-            'display': 'block',\r
-            'top': Math.round(box.top),\r
-            'left': Math.round(box.left),\r
-            'width': Math.round(box.width),\r
-            'height': Math.round(box.height),\r
-            'backgroundImage': baseElement.css('backgroundImage').replace('off.svg', 'on.svg'), // Show the "on" state if not already set\r
-            'backgroundSize': 'contain'\r
+        var icon = $('<div/>').css({\r
+            width: Math.round(box.width),\r
+            height: Math.round(box.height),\r
+                       margin: Math.round(circleOffset), // Centre inside circle\r
+                       backgroundSize: 'contain',\r
+                       backgroundPosition: 'center',\r
+                       backgroundRepeat: 'no-repeat',\r
+            backgroundImage: baseElement.css('backgroundImage').replace('off.svg', 'on.svg') // Show the "on" state if not already set\r
         })[0].outerHTML;\r
 \r
         // Circle around the icon - slightly bigger\r
-        html += $('<div/>').css({\r
-            'position': 'absolute',\r
-            'display': 'block',\r
-            'top': Math.round(box.top - circleExtra / 2),\r
-            'left': Math.round(box.left - circleExtra / 2),\r
-            'width': Math.round(box.width + circleExtra),\r
-            'height': Math.round(box.height + circleExtra),\r
-            'borderRadius': '50%',\r
-            'border': '1px solid'\r
+        html += $('<div>' + icon + '</div>').css({\r
+            width: Math.round(box.width + circleExtra),\r
+            height: Math.round(box.height + circleExtra),\r
+            borderRadius: '50%',\r
+            border: '1px solid'\r
         })[0].outerHTML;\r
 \r
-        // The line and text need to be positioned differently depending on which side the icon is on\r
-        var lineLeft = (side == 'left') ? Math.round(box.left + box.width + circleExtra / 2) : Math.round(box.left - circleExtra / 2 - lineLength),\r
-            labelLeft = (side == 'left') ? Math.round(box.left + box.width + circleExtra / 2 + lineLength + 10) : Math.round(box.left - circleExtra / 2 - lineLength - 10),\r
-            labelTransform = (side == 'left') ? 'translateY(-50%)' : 'translateY(-50%) translateX(-100%)'; // TranslateX -100% since we don't know how long the text is\r
-\r
         // Line to text\r
         html += $('<div/>').css({\r
-            'position': 'absolute',\r
-            'display': 'block',\r
-            'top': Math.round(box.top + box.height / 2),\r
-            'left': lineLeft,\r
-            'width': lineLength,\r
-            'height': 0,\r
-            'borderBottom': '1px solid',\r
+            width: lineLength,\r
+            height: 0,\r
+            borderBottom: '1px solid',\r
         })[0].outerHTML;\r
 \r
         // Help text label\r
         html += $('<div>'+ this.fluidbook.l10n.__('add / remove bookmark') +'</div>').css({\r
-            'position': 'absolute',\r
-            'display': 'block',\r
-            'top': Math.round(box.top + box.height / 2),\r
-            'left': labelLeft,\r
-            'transform': labelTransform,\r
-            'whiteSpace': 'nowrap'\r
+            whiteSpace: 'nowrap',\r
+                       padding: '0 0.5em' // Ensure spacing around text regardless which side the line is on\r
         })[0].outerHTML;\r
 \r
-        return html;\r
+\r
+        // Wrapper with positioning and layout switched depending on the side\r
+               var wrapperCSS = { // Shared properties\r
+                               display: 'flex',\r
+                               alignItems: 'center',\r
+                               position: 'absolute',\r
+                               top: Math.round(box.top - circleOffset)\r
+               },\r
+                       wrapperLayout;\r
+\r
+               if (side == 'left') {\r
+                       wrapperLayout = {\r
+                left: Math.round(box.left - circleOffset),\r
+                               transformOrigin: 'left top',\r
+                flexDirection: 'row' // Flexbox direction controls order of elements (icon, line, label)\r
+                       };\r
+               } else {\r
+                       wrapperLayout = {\r
+                right: Math.round(this.fluidbook.resize.ww - box.left - box.width - circleOffset),\r
+                               transformOrigin: 'right top',\r
+                flexDirection: 'row-reverse' // Reverse order of elements for right hand page\r
+                       }\r
+               }\r
+\r
+        var wrapper = $('<div class="bookmark-help">' + html + '</div>')\r
+                       .css(\r
+                               $.extend(wrapperCSS, wrapperLayout) // Merge all properties\r
+               )[0].outerHTML\r
+\r
+        return wrapper;\r
     }\r
 };\r
 \r
index c5be9aeb34b24d8c852be77cacfcc0138433e699..f5da7ab682c288877912cc8f8944c6b07c921baf 100644 (file)
@@ -164,7 +164,7 @@ FluidbookResize.prototype = {
             bottom: audioButtonPosition
         });
 
-        $("#logo,footer,#searchHints").transform({
+        $("#logo,footer,#searchHints,#menuOpener").transform({
             scale: navScale
         });
 
index 2bab7a46a1a29a7ddbdc51ee7f2bb4c84f3ba203..969f5ff78eab588186760f1baee03aa9fcf6c310 100644 (file)
@@ -1502,21 +1502,26 @@ ul.chapters.shareList a.level0 .svg-icon {
        }
 }
 
-.ltr #helpView .interface .next,
-.ltr #helpView .interface .last,
-.rtl #helpView .interface .first,
-.rtl #helpView .interface .previous {
-       text-align: right;
-       right: 40px;
-       top: 340px;
-}
+#helpView {
+       .next, .last, .previous, .first {
+               margin-top: -0.5em;
+               line-height: 1;
+       }
+
+       .next, .last {
+               transform-origin: right;
+
+               .rtl & {
+                       transform-origin: left;
+               }
+       }
 
-&.sharp {
-       .ltr #helpView .interface .next,
-       .ltr #helpView .interface .last,
-       .rtl #helpView .interface .first,
-       .rtl #helpView .interface .previous {
-               right: 53px;
+       .previous, .first {
+               transform-origin: left;
+
+               .rtl & {
+                       transform-origin: right;
+               }
        }
 }
 
@@ -1527,29 +1532,12 @@ ul.chapters.shareList a.level0 .svg-icon {
        content: '------------';
        width: 100px;
        border-bottom: 1px solid #fff;
-       margin: 0 10px;
+       margin-left: 10px;
        position: relative;
        top: -0.5em;
        color: transparent;
 }
 
-.rtl #helpView .interface .next,
-.rtl #helpView .interface .last,
-.ltr #helpView .interface .first,
-.ltr #helpView .interface .previous {
-       left: 40px;
-       top: 340px;
-}
-
-.sharp {
-       .rtl #helpView .interface .next,
-       .rtl #helpView .interface .last,
-       .ltr #helpView .interface .first,
-       .ltr #helpView .interface .previous {
-               left: 57px;
-       }
-}
-
 .rtl #helpView .interface .next:before,
 .rtl #helpView .interface .last:before,
 .ltr #helpView .interface .first:before,
@@ -1557,27 +1545,14 @@ ul.chapters.shareList a.level0 .svg-icon {
        content: '------------';
        width: 100px;
        border-bottom: 1px solid #fff;
-       margin: 0 10px;
+       margin-right: 10px;
        position: relative;
        top: -0.5em;
        color: transparent;
 }
 
-#helpView .interface .first,
-#helpView .interface .last {
-       margin-top: 43px;
-
-       .sharp & {
-               margin-top: 40px;
-       }
-}
-
-#helpView .interface .next,
-#helpView .interface .previous {
-       margin-top: -5px;
-}
 
-#helpView .interface div {
+#helpView .interface div {
        position: absolute;
        direction: ltr;
 }
index bb96c6178a426b5327198a33d405d3ba7d8a9e78..0a29f4ad52a7755728dbd385c86ee4efffcb2b28 100644 (file)
@@ -94,6 +94,10 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim] ~ #mm-blocker {
                }
        }
 
+       .mm-navbar .mm-title {
+               padding: 0 !important;
+       }
+
        //> a {
        //      vertical-align: top;
        //      display: inline-block;
@@ -102,6 +106,12 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim] ~ #mm-blocker {
 
 #menuOpener {
        display: none;
+       color: @icon-color;
+
+       // Change colour when help view is open
+       .help & {
+               color: #ccc;
+       }
 
        @media all and (max-width: @menu-breakpoint) {
                position: absolute;
@@ -110,7 +120,6 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim] ~ #mm-blocker {
                height: 100%;
                font-size: 16px;
                line-height: 1;
-               color: @icon-color;
                display: flex;
                align-items: center;
        }
@@ -120,6 +129,7 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim] ~ #mm-blocker {
                left: 9px;
                right: auto;
                flex-direction: row;
+               transform-origin: left top;
        }
 
        // Positioning for right-to-left Fluidbooks + inverted menu on LTR
@@ -127,6 +137,7 @@ html.mm-opening .mm-menu.mm-opened[class*=mm-pagedim] ~ #mm-blocker {
                right: 9px;
                left: auto;
                flex-direction: row-reverse; // Swap text and icon positions
+               transform-origin: right top;
        }
 
        .label {