From 05b18fdc3455142279a614877409fe6462a66734 Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Mon, 25 Mar 2019 15:29:00 +0100 Subject: [PATCH] wip #2636 0.5 --- js/libs/fluidbook/fluidbook.help.js | 39 ++-- js/libs/fluidbook/fluidbook.input.js | 14 +- js/libs/jquery/jquery.pep.min.js | 210 +++++++++++++++++++ style/help.less | 292 ++++++++++++++------------- 4 files changed, 387 insertions(+), 168 deletions(-) create mode 100644 js/libs/jquery/jquery.pep.min.js diff --git a/js/libs/fluidbook/fluidbook.help.js b/js/libs/fluidbook/fluidbook.help.js index e88c131c..2b80b5c7 100644 --- a/js/libs/fluidbook/fluidbook.help.js +++ b/js/libs/fluidbook/fluidbook.help.js @@ -20,23 +20,24 @@ FluidbookHelp.prototype = { ext = 'png'; } - var name = ''; + var width = 400; + var height = 200; + var zoom = 2; + var name = 'fingers'; + var text = this.fluidbook.l10n.__("tap twice or spread your fingers to zoom in"); + + help += '
' + this.fluidbook.loader.getImage('data/images/help-' + name + '.' + ext, width * zoom, height * zoom); + help += '

' + text + '

'; + help += '
'; + + var width = 100; var height = 200; - var text; var zoom = 1; - if (this.fluidbook.support.isMobile) { - width = 400; - height = 200; - zoom = 2; - name = 'fingers'; - text = this.fluidbook.l10n.__("tap twice or spread your fingers to zoom in"); - } else { - name = 'mouse'; - text = this.fluidbook.l10n.__('click once to zoom in, click again to zoom out') + '
' + this.fluidbook.l10n.__('roll the mouse wheel to zoom in/out'); - } + name = 'mouse'; + text = this.fluidbook.l10n.__('click once to zoom in, click again to zoom out') + '
' + this.fluidbook.l10n.__('roll the mouse wheel to zoom in/out'); - help += '
' + this.fluidbook.loader.getImage('data/images/help-' + name + '.' + ext, width * zoom, height * zoom); + help += '
' + this.fluidbook.loader.getImage('data/images/help-' + name + '.' + ext, width * zoom, height * zoom); help += '

' + text + '

'; help += '
'; @@ -221,13 +222,12 @@ FluidbookHelp.prototype = { }); // Labels are swapped for RTL documents - var prevPosition = (dir == 'ltr') ? {left: Math.round(arrow.width)} : {right: Math.round(arrow.width)}, - nextPosition = (dir == 'ltr') ? {right: Math.round(arrow.width)} : {left: Math.round(arrow.width)}; + var prevPosition = (dir === 'ltr') ? {left: Math.round(arrow.width)} : {right: Math.round(arrow.width)}, + nextPosition = (dir === 'ltr') ? {right: Math.round(arrow.width)} : {left: Math.round(arrow.width)}; this.view.find('.previous, .first').css(prevPosition); this.view.find('.next, .last').css(nextPosition); - // Slider label var positionSliderLabel = function () { var sliderHelp = $this.view.find('.slider'); @@ -262,6 +262,7 @@ FluidbookHelp.prototype = { clearTimeout: function () { clearTimeout(this.autoTimeout); }, + displayAtStartup: function () { if (this.fluidbook.datas.helpStartup) { this.show(parseInt(this.fluidbook.datas.helpStartupTime)); @@ -282,13 +283,13 @@ FluidbookHelp.prototype = { var dir = this.fluidbook.l10n.dir, inverted = this.fluidbook.datas.invertMenuPosition, - side = ((dir == 'ltr' && inverted) || (dir == 'rtl' && !inverted)) ? 'left' : 'right', + side = ((dir === 'ltr' && inverted) || (dir === 'rtl' && !inverted)) ? 'left' : 'right', baseElement = $('#links .bookmark.' + side), // Original element used to provide position and sizing for overlay html = ''; // If bookmark icon isn't present on the side we want, it means that we're on // the first/last page and that side is missing so we can't display the help - if (baseElement.length == 0) { + if (baseElement.length === 0) { return ''; } @@ -344,7 +345,7 @@ FluidbookHelp.prototype = { }, wrapperLayout; - if (side == 'left') { + if (side === 'left') { wrapperLayout = { left: Math.round(box.left - circleOffset), transformOrigin: 'left top', diff --git a/js/libs/fluidbook/fluidbook.input.js b/js/libs/fluidbook/fluidbook.input.js index 0c4145d1..b12bb2ae 100644 --- a/js/libs/fluidbook/fluidbook.input.js +++ b/js/libs/fluidbook/fluidbook.input.js @@ -30,13 +30,13 @@ FluidbookInput.prototype = { this.forceTouch = this.forceMouse = false; - $(document).on('mousemove', function () { - $this.useMouse(); - return true; - }); - - $(document).on('touchstart touchmove touchend', function () { - $this.useTouch(); + $(document).on("pointermove", function (e) { + if (e.pointerType === 'mouse') { + $this.useMouse(); + } else { + // touch or pencil + $this.useTouch(); + } return true; }); }, diff --git a/js/libs/jquery/jquery.pep.min.js b/js/libs/jquery/jquery.pep.min.js new file mode 100644 index 00000000..ac49fbc6 --- /dev/null +++ b/js/libs/jquery/jquery.pep.min.js @@ -0,0 +1,210 @@ +/*! + * PEP v0.4.3 | https://github.com/jquery/PEP + * Copyright jQuery Foundation and other contributors | http://jquery.org/license + */ +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.PointerEventsPolyfill=b()}(this,function(){"use strict";function a(a,b){b=b||Object.create(null);var c=document.createEvent("Event");c.initEvent(a,b.bubbles||!1,b.cancelable||!1); +// define inherited MouseEvent properties +// skip bubbles and cancelable since they're set above in initEvent() + for(var d,e=2;e element that is represented by the instance for Safari, Chrome, IE. +// This is the behavior implemented by Firefox. + !t||"target"!==b&&"relatedTarget"!==b||c[b]instanceof SVGElementInstance&&(c[b]=c[b].correspondingUseElement); +// keep the semantics of preventDefault + return a.preventDefault&&(c.preventDefault=function(){a.preventDefault()}),c},getTarget:function(a){var b=this.captureInfo[a.pointerId];return b?a._target!==b&&a.type in s?void 0:b:a._target},propagate:function(a,b,c){ +// Order of conditions due to document.contains() missing in IE. + for(var d=a.target,e=[];d!==document&&!d.contains(a.relatedTarget);) +// Touch: Do not propagate if node is detached. + if(e.push(d),d=d.parentNode,!d)return;c&&e.reverse(),e.forEach(function(c){a.target=c,b.call(this,a)},this)},setCapture:function(b,c,d){this.captureInfo[b]&&this.releaseCapture(b,d),this.captureInfo[b]=c,this.implicitRelease=this.releaseCapture.bind(this,b,d),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease);var e=new a("gotpointercapture");e.pointerId=b,e._target=c,d||this.asyncDispatchEvent(e)},releaseCapture:function(b,c){var d=this.captureInfo[b];if(d){this.captureInfo[b]=void 0,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease);var e=new a("lostpointercapture");e.pointerId=b,e._target=d,c||this.asyncDispatchEvent(e)}},/** + * Dispatches the event to its target. + * + * @param {Event} inEvent The event to be dispatched. + * @return {Boolean} True if an event handler returns true, false otherwise. + */ + dispatchEvent:/*scope.external.dispatchEvent || */function(a){var b=this.getTarget(a);if(b)return b.dispatchEvent(a)},asyncDispatchEvent:function(a){requestAnimationFrame(this.dispatchEvent.bind(this,a))}};u.boundHandler=u.eventHandler.bind(u);var v={shadow:function(a){if(a)return a.shadowRoot||a.webkitShadowRoot},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);if(this.canTarget(b))return b},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for( +// is element a shadow host? + e=this.targetingShadow(f);e;){if( +// find the the element inside the shadow root + d=e.elementFromPoint(b,c)){ +// shadowed element may contain a shadow root + var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d} +// check for older shadows + e=this.olderShadow(e)} +// light dom element is the target + return f}},owner:function(a){ +// walk up until you hit the shadow root or document + for(var b=a;b.parentNode;)b=b.parentNode; +// the owner element is expected to be a Document or ShadowRoot + return b.nodeType!==Node.DOCUMENT_NODE&&b.nodeType!==Node.DOCUMENT_FRAGMENT_NODE&&(b=document),b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target); +// if x, y is not in this root, fall back to document search + return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}},w=Array.prototype.forEach.call.bind(Array.prototype.forEach),x=Array.prototype.map.call.bind(Array.prototype.map),y=Array.prototype.slice.call.bind(Array.prototype.slice),z=Array.prototype.filter.call.bind(Array.prototype.filter),A=window.MutationObserver||window.WebKitMutationObserver,B="[touch-action]",C={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};c.prototype={watchSubtree:function(a){ +// Only watch scopes that can target find, as these are top-level. +// Otherwise we can see duplicate additions and removals that add noise. +// +// TODO(dfreedman): For some instances with ShadowDOMPolyfill, we can see +// a removal without an insertion when a node is redistributed among +// shadows. Since it all ends up correct in the document, watching only +// the document will yield the correct mutations to watch. + this.observer&&v.canTarget(a)&&this.observer.observe(a,C)},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){w(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(B):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(y(b))}, +// register all touch-action = none nodes on document load + installOnLoad:function(){document.addEventListener("readystatechange",function(){"complete"===document.readyState&&this.installNewSubtree(document)}.bind(this))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){ +// find children with touch-action + var b=x(a,this.findElements,this); +// flatten the list +// make sure the added nodes are accounted for + return b.push(z(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}};var D=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],E="",F=window.PointerEvent||window.MSPointerEvent,G=!window.ShadowDOMPolyfill&&document.head.createShadowRoot,H=u.pointermap,I=25,J=[1,4,2,8,16],K=!1;try{K=1===new MouseEvent("test",{buttons:1}).buttons}catch(L){} +// handler block for native mouse events + var M,N={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},lastTouches:[], +// collide with the global mouse listener + isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,d=a.clientX,e=a.clientY,f=0,g=c.length;f delta other axis, scroll instead of +// making events + b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;d=b.length){var c=[];R.forEach(function(a,d){ +// Never remove pointerId == 1, which is mouse. +// Touch identifiers are 2 smaller than their pointerId, which is the +// index in pointermap. + if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(e)}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){R.set(a.pointerId,{target:a.target,out:a,outTarget:a.target}),u.enterOver(a),u.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,c=R.get(b.pointerId); +// a finger drifted off the screen, ignore it + if(c){var d=c.out,e=c.outTarget;u.move(b),d&&e!==b.target&&(d.relatedTarget=b.target,b.relatedTarget=e, +// recover from retargeting by shadow + d.target=e,b.target?(u.leaveOut(d),u.enterOver(b)):( +// clean up case when finger leaves the screen + b.target=e,b.relatedTarget=null,this.cancelOut(b))),c.out=b,c.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(u.up(a),u.leaveOut(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){u.cancel(a),u.leaveOut(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){R["delete"](a.pointerId),this.removePrimaryPointer(a)}, +// prevent synth mouse events from creating pointer events + dedupSynthMouse:function(a){var b=N.lastTouches,c=a.changedTouches[0]; +// only the primary finger will synth mouse events + if(this.isPrimaryTouch(c)){ +// remember x/y of last touch + var d={x:c.clientX,y:c.clientY};b.push(d);var e=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,b,d);setTimeout(e,S)}}};M=new c(V.elementAdded,V.elementRemoved,V.elementChanged,V);var W,X,Y,Z=u.pointermap,$=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,_={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var b=a;return $&&(b=u.cloneEvent(a),b.pointerType=this.POINTER_TYPES[a.pointerType]),b},cleanup:function(a){Z["delete"](a)},MSPointerDown:function(a){Z.set(a.pointerId,a);var b=this.prepareEvent(a);u.down(b)},MSPointerMove:function(a){var b=this.prepareEvent(a);u.move(b)},MSPointerUp:function(a){var b=this.prepareEvent(a);u.up(b),this.cleanup(a.pointerId)},MSPointerOut:function(a){var b=this.prepareEvent(a);u.leaveOut(b)},MSPointerOver:function(a){var b=this.prepareEvent(a);u.enterOver(b)},MSPointerCancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var b=u.makeEvent("lostpointercapture",a);u.dispatchEvent(b)},MSGotPointerCapture:function(a){var b=u.makeEvent("gotpointercapture",a);u.dispatchEvent(b)}},aa=window.navigator;aa.msPointerEnabled?(W=function(a){i(a),j(this),k(a)&&(u.setCapture(a,this,!0),this.msSetPointerCapture(a))},X=function(a){i(a),u.releaseCapture(a,!0),this.msReleasePointerCapture(a)}):(W=function(a){i(a),j(this),k(a)&&u.setCapture(a,this)},X=function(a){i(a),u.releaseCapture(a)}),Y=function(a){return!!u.captureInfo[a]},g(),h(),l();var ba={dispatcher:u,Installer:c,PointerEvent:a,PointerMap:p,targetFinding:v};return ba}); \ No newline at end of file diff --git a/style/help.less b/style/help.less index e3965d22..a8f2abaf 100644 --- a/style/help.less +++ b/style/help.less @@ -1,187 +1,195 @@ /* Help */ #helpViewOverlay { - display: none; - z-index: 30; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: transparent; + display: none; + z-index: 30; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: transparent; } #helpView { - background-color: rgba(0, 0, 0, 0.7); - position: absolute; - top: 0; - height: 100%; - width: 100%; - z-index: 20; - display: none; - color: #ffffff; - overflow: hidden; - - .illustration { - position: absolute; - top: 50%; - left: 50%; - //transform: translate(-50%, -50%); // Transform handled via fluidbook.help.js so dynamic scaling can be done - text-align: center; - font-size: 20px; - - img { - max-width: 100%; - height: auto; - } - - p { - position: static; - } - - } - - #icons { - position: absolute; - - @media all and (max-width: @menu-breakpoint) { - display: none; - } - } - - .portrait & .icon.afterSearch { - display: none; - } - - .icon { - position: absolute; - top: 0px; - display: inline-block; - white-space: nowrap; - padding: 0 0.5em; - border-color: #fff; - border-style: solid; - border-width: 0 0 0 1px; // Left border - - // When in RTL default or LTR with menu inverted, the labels need to be on the other side of the line - .rtl.menu-default &, .ltr.menu-inverted & { - border-width: 0 1px 0 0; // Right border - transform: translateX(-100%); // Flip position back to where it would be if it was based on a left border line - } - } - - .icon span { - position: relative; - bottom: -0.25em; - - & .rtl { - position: absolute; - right: 1em; - margin-top: -1em; - } - } + background-color: rgba(0, 0, 0, 0.7); + position: absolute; + top: 0; + height: 100%; + width: 100%; + z-index: 20; + display: none; + color: #ffffff; + overflow: hidden; + + .illustration { + + .no-using-touch &.touch{ + display: none; + } + .no-using-mouse &.mouse{ + display: none; + } + + position: absolute; + top: 50%; + left: 50%; + //transform: translate(-50%, -50%); // Transform handled via fluidbook.help.js so dynamic scaling can be done + text-align: center; + font-size: 20px; + + img { + max-width: 100%; + height: auto; + } + + p { + position: static; + } + + } + + #icons { + position: absolute; + + @media all and (max-width: @menu-breakpoint) { + display: none; + } + } + + .portrait & .icon.afterSearch { + display: none; + } + + .icon { + position: absolute; + top: 0px; + display: inline-block; + white-space: nowrap; + padding: 0 0.5em; + border-color: #fff; + border-style: solid; + border-width: 0 0 0 1px; // Left border + + // When in RTL default or LTR with menu inverted, the labels need to be on the other side of the line + .rtl.menu-default &, .ltr.menu-inverted & { + border-width: 0 1px 0 0; // Right border + transform: translateX(-100%); // Flip position back to where it would be if it was based on a left border line + } + } + + .icon span { + position: relative; + bottom: -0.25em; + + & .rtl { + position: absolute; + right: 1em; + margin-top: -1em; + } + } } #helpView .interface hr { - width: 30px; - height: 0px; - border: 0; - border-top: 1px solid #ffffff; - display: inline-block; - margin: 0 10px; - vertical-align: middle; + width: 30px; + height: 0px; + border: 0; + border-top: 1px solid #ffffff; + display: inline-block; + margin: 0 10px; + vertical-align: middle; } #helpView .down { - position: absolute; - right: 62px; - bottom: 20px; + position: absolute; + right: 62px; + bottom: 20px; } #helpView .down hr { - width: 30px; - height: 0px; - border: 0; - border-top: 1px solid #ffffff; - display: inline-block; - margin: 0 10px; - vertical-align: middle; + width: 30px; + height: 0px; + border: 0; + border-top: 1px solid #ffffff; + display: inline-block; + margin: 0 10px; + vertical-align: middle; } #helpView .interface .slider { - position: absolute; - display: inline-block; - border-left: 1px solid #fff; - padding: 0 0 20px 0.5em; - white-space: nowrap; - - span { - position: relative; - top: -0.5em; - } + position: absolute; + display: inline-block; + border-left: 1px solid #fff; + padding: 0 0 20px 0.5em; + white-space: nowrap; + + span { + position: relative; + top: -0.5em; + } } #helpView { - .next, .last, .previous, .first { - margin-top: -0.5em; - line-height: 1; - } - - .next, .last { - transform-origin: right; - - .rtl & { - transform-origin: left; - } - } - - .previous, .first { - transform-origin: left; - - .rtl & { - transform-origin: right; - } - } + .next, .last, .previous, .first { + margin-top: -0.5em; + line-height: 1; + } + + .next, .last { + transform-origin: right; + + .rtl & { + transform-origin: left; + } + } + + .previous, .first { + transform-origin: left; + + .rtl & { + transform-origin: right; + } + } } .ltr #helpView .interface .next:after, .ltr #helpView .interface .last:after, .rtl #helpView .interface .first:after, .rtl #helpView .interface .previous:after { - content: '------------'; - width: 100px; - border-bottom: 1px solid #fff; - margin-left: 10px; - position: relative; - top: -0.5em; - color: transparent; + content: '------------'; + width: 100px; + border-bottom: 1px solid #fff; + margin-left: 10px; + position: relative; + top: -0.5em; + color: transparent; } .rtl #helpView .interface .next:before, .rtl #helpView .interface .last:before, .ltr #helpView .interface .first:before, .ltr #helpView .interface .previous:before { - content: '------------'; - width: 100px; - border-bottom: 1px solid #fff; - margin-right: 10px; - position: relative; - top: -0.5em; - color: transparent; + content: '------------'; + width: 100px; + border-bottom: 1px solid #fff; + margin-right: 10px; + position: relative; + top: -0.5em; + color: transparent; } #helpView .interface > div { - position: absolute; - direction: ltr; + position: absolute; + direction: ltr; } .portrait #helpView .interface { - display: none; + display: none; } .pad.portrait #helpView .interface { - display: block; + display: block; } .pad #helpView .illustration { - display: none; + display: none; } \ No newline at end of file -- 2.39.5