]> _ Git - fluidbook-html5.git/commitdiff
wip #2636 0.5
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Mon, 25 Mar 2019 14:29:00 +0000 (15:29 +0100)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Mon, 25 Mar 2019 14:29:00 +0000 (15:29 +0100)
js/libs/fluidbook/fluidbook.help.js
js/libs/fluidbook/fluidbook.input.js
js/libs/jquery/jquery.pep.min.js [new file with mode: 0644]
style/help.less

index e88c131cbd7c1cff40bfae6a842878ec1641bf12..2b80b5c75a311ac71d86c9f340785b5287f5010f 100644 (file)
@@ -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 += '<div class="illustration touch">' + this.fluidbook.loader.getImage('data/images/help-' + name + '.' + ext, width * zoom, height * zoom);
+        help += '<p>' + text + '</p>';
+        help += '</div>';
+
+
         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') + '<br />' + 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') + '<br />' + this.fluidbook.l10n.__('roll the mouse wheel to zoom in/out');
 
-        help += '<div class="illustration">' + this.fluidbook.loader.getImage('data/images/help-' + name + '.' + ext, width * zoom, height * zoom);
+        help += '<div class="illustration mouse">' + this.fluidbook.loader.getImage('data/images/help-' + name + '.' + ext, width * zoom, height * zoom);
         help += '<p>' + text + '</p>';
         help += '</div>';
 
@@ -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',
index 0c4145d1cc8ece3d1811031a86c193994314b8a2..b12bb2aedaad05fcf415a88ccd2dbf1aaec86b87 100644 (file)
@@ -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 (file)
index 0000000..ac49fbc
--- /dev/null
@@ -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<m.length;e++)d=m[e],c[d]=b[d]||n[e];c.buttons=b.buttons||0;
+// Spec requires that pointers without pressure specified use 0.5 for down
+// state and 0 for up state.
+    var f=0;
+// add x/y properties aliased to clientX/Y
+// define the properties of the PointerEvent interface
+    return f=b.pressure&&c.buttons?b.pressure:c.buttons?.5:0,c.x=c.clientX,c.y=c.clientY,c.pointerId=b.pointerId||0,c.width=b.width||0,c.height=b.height||0,c.pressure=f,c.tiltX=b.tiltX||0,c.tiltY=b.tiltY||0,c.twist=b.twist||0,c.tangentialPressure=b.tangentialPressure||0,c.pointerType=b.pointerType||"",c.hwTimestamp=b.hwTimestamp||0,c.isPrimary=b.isPrimary||!1,c}function b(){this.array=[],this.size=0}function c(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),A&&(this.observer=new A(this.mutationWatcher.bind(this)))}function d(a){return"body /shadow-deep/ "+e(a)}function e(a){return'[touch-action="'+a+'"]'}function f(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; }"}function g(){if(F){D.forEach(function(a){String(a)===a?(E+=e(a)+f(a)+"\n",G&&(E+=d(a)+f(a)+"\n")):(E+=a.selectors.map(e)+f(a.rule)+"\n",G&&(E+=a.selectors.map(d)+f(a.rule)+"\n"))});var a=document.createElement("style");a.textContent=E,document.head.appendChild(a)}}function h(){
+// only activate if this platform does not have pointer events
+    if(!window.PointerEvent){if(window.PointerEvent=a,window.navigator.msPointerEnabled){var b=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:b,enumerable:!0}),u.registerSource("ms",_)}else Object.defineProperty(window.navigator,"maxTouchPoints",{value:0,enumerable:!0}),u.registerSource("mouse",N),void 0!==window.ontouchstart&&u.registerSource("touch",V);u.register(document)}}function i(a){if(!u.pointermap.has(a)){var b=new Error("InvalidPointerId");throw b.name="InvalidPointerId",b}}function j(a){for(var b=a.parentNode;b&&b!==a.ownerDocument;)b=b.parentNode;if(!b){var c=new Error("InvalidStateError");throw c.name="InvalidStateError",c}}function k(a){var b=u.pointermap.get(a);return 0!==b.buttons}function l(){window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:W},releasePointerCapture:{value:X},hasPointerCapture:{value:Y}})}/**
+ * This is the constructor for new PointerEvents.
+ *
+ * New Pointer Events must be given a type, and an optional dictionary of
+ * initialization properties.
+ *
+ * Due to certain platform requirements, events returned from the constructor
+ * identify as MouseEvents.
+ *
+ * @constructor
+ * @param {String} inType The type of the event to create.
+ * @param {Object} [inDict] An optional dictionary of initial event properties.
+ * @return {Event} A new PointerEvent of type `inType`, initialized with properties from `inDict`.
+ */
+var m=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","pageX","pageY"],n=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0],o=window.Map&&window.Map.prototype.forEach,p=o?Map:b;b.prototype={set:function(a,b){return void 0===b?this["delete"](a):(this.has(a)||this.size++,void(this.array[a]=b))},has:function(a){return void 0!==this.array[a]},"delete":function(a){this.has(a)&&(delete this.array[a],this.size--)},get:function(a){return this.array[a]},clear:function(){this.array.length=0,this.size=0},
+// return value, key, map
+    forEach:function(a,b){return this.array.forEach(function(c,d){a.call(b,c,d,this)},this)}};var q=[
+// MouseEvent
+    "bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget",
+// DOM Level 3
+    "buttons",
+// PointerEvent
+    "pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary",
+// event instance
+    "type","target","currentTarget","which","pageX","pageY","timeStamp"],r=[
+// MouseEvent
+    !1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,
+// DOM Level 3
+    0,
+// PointerEvent
+    0,0,0,0,0,0,"",0,!1,
+// event instance
+    "",null,null,0,0,0,0],s={pointerover:1,pointerout:1,pointerenter:1,pointerleave:1},t="undefined"!=typeof SVGElementInstance,u={pointermap:new p,eventMap:Object.create(null),captureInfo:Object.create(null),
+// Scope objects for native events.
+// This exists for ease of testing.
+    eventSources:Object.create(null),eventSourceList:[],/**
+     * Add a new event source that will generate pointer events.
+     *
+     * `inSource` must contain an array of event names named `events`, and
+     * functions with the names specified in the `events` array.
+     * @param {string} name A name for the event source
+     * @param {Object} source A new source of platform events.
+     */
+    registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
+// call eventsource register
+        b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
+// call eventsource register
+        b.unregister.call(b,a)},contains:/*scope.external.contains || */function(a,b){try{return a.contains(b)}catch(c){
+// most likely: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
+        return!1}},
+// EVENTS
+    down:function(a){a.bubbles=!0,this.fireEvent("pointerdown",a)},move:function(a){a.bubbles=!0,this.fireEvent("pointermove",a)},up:function(a){a.bubbles=!0,this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){a.bubbles=!0,this.fireEvent("pointercancel",a)},leaveOut:function(a){this.out(a),this.propagate(a,this.leave,!1)},enterOver:function(a){this.over(a),this.propagate(a,this.enter,!0)},
+// LISTENER LOGIC
+    eventHandler:function(a){
+// This is used to prevent multiple dispatch of pointerevents from
+// platform events. This can happen when two elements in different scopes
+// are set up to create pointer events, which is relevant to Shadow DOM.
+        if(!a._handledByPE){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),a._handledByPE=!0}},
+// set up event listeners
+    listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},
+// remove event listeners
+    unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:/*scope.external.addEvent || */function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:/*scope.external.removeEvent || */function(a,b){a.removeEventListener(b,this.boundHandler)},
+// EVENT CREATION AND TRACKING
+    /**
+     * Creates a new Event of type `inType`, based on the information in
+     * `inEvent`.
+     *
+     * @param {string} inType A string representing the type of event to create
+     * @param {Event} inEvent A platform event with a target
+     * @return {Event} A PointerEvent of type `inType`
+     */
+    makeEvent:function(b,c){
+// relatedTarget must be null if pointer is captured
+        this.captureInfo[c.pointerId]&&(c.relatedTarget=null);var d=new a(b,c);return c.preventDefault&&(d.preventDefault=c.preventDefault),d._target=d._target||c.target,d},
+// make and dispatch an event in one call
+    fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},/**
+     * Returns a snapshot of inEvent, with writable properties.
+     *
+     * @param {Event} inEvent An event that contains properties to copy.
+     * @return {Object} An object containing shallow copies of `inEvent`'s
+     *    properties.
+     */
+    cloneEvent:function(a){for(var b,c=Object.create(null),d=0;d<q.length;d++)b=q[d],c[b]=a[b]||r[d],
+// Work around SVGInstanceElement shadow tree
+// Return the <use> 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<g&&(b=c[f]);f++){
+// simulated mouse events will be swallowed near a primary touchend
+            var h=Math.abs(d-b.x),i=Math.abs(e-b.y);if(h<=I&&i<=I)return!0}},prepareEvent:function(a){var b=u.cloneEvent(a),c=b.preventDefault;return b.preventDefault=function(){a.preventDefault(),c()},b.pointerId=this.POINTER_ID,b.isPrimary=!0,b.pointerType=this.POINTER_TYPE,b},prepareButtonsForMove:function(a,b){var c=H.get(this.POINTER_ID);
+// Update buttons state after possible out-of-document mouseup.
+            0!==b.which&&c?a.buttons=c.buttons:a.buttons=0,b.buttons=a.buttons},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=H.get(this.POINTER_ID),c=this.prepareEvent(a);K||(c.buttons=J[c.button],b&&(c.buttons|=b.buttons),a.buttons=c.buttons),H.set(this.POINTER_ID,a),b&&0!==b.buttons?u.move(c):u.down(c)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,H.set(this.POINTER_ID,a),u.move(b)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=H.get(this.POINTER_ID),c=this.prepareEvent(a);if(!K){var d=J[c.button];
+// Produces wrong state of buttons in Browsers without `buttons` support
+// when a mouse button that was pressed outside the document is released
+// inside and other buttons are still pressed down.
+            c.buttons=b?b.buttons&~d:0,a.buttons=c.buttons}H.set(this.POINTER_ID,a),
+// Support: Firefox <=44 only
+// FF Ubuntu includes the lifted button in the `buttons` property on
+// mouseup.
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1223366
+            c.buttons&=~J[c.button],0===c.buttons?u.up(c):u.move(c)}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,H.set(this.POINTER_ID,a),u.enterOver(b)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,u.leaveOut(b)}},cancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.deactivateMouse()},deactivateMouse:function(){H["delete"](this.POINTER_ID)}},O=u.captureInfo,P=v.findTarget.bind(v),Q=v.allShadows.bind(v),R=u.pointermap,S=2500,T=200,U="touch-action",V={events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){M.enableOnSubtree(a)},unregister:function(){},elementAdded:function(a){var b=a.getAttribute(U),c=this.touchActionToScrollType(b);c&&(a._scrollType=c,u.listen(a,this.events),
+// set touch-action on shadows as well
+            Q(a).forEach(function(a){a._scrollType=c,u.listen(a,this.events)},this))},elementRemoved:function(a){a._scrollType=void 0,u.unlisten(a,this.events),
+// remove touch-action from shadow
+            Q(a).forEach(function(a){a._scrollType=void 0,u.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(U),d=this.touchActionToScrollType(c),e=this.touchActionToScrollType(b);
+// simply update scrollType if listeners are already established
+            d&&e?(a._scrollType=d,Q(a).forEach(function(a){a._scrollType=d},this)):e?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){
+// set primary touch if there no pointers, or the only pointer is the mouse
+            (0===R.size||1===R.size&&R.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,T)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},typeToButtons:function(a){var b=0;return"touchstart"!==a&&"touchmove"!==a||(b=1),b},touchToPointer:function(a){var b=this.currentTouchEvent,c=u.cloneEvent(a),d=c.pointerId=a.identifier+2;c.target=O[d]||P(c),c.bubbles=!0,c.cancelable=!0,c.detail=this.clickCount,c.button=0,c.buttons=this.typeToButtons(b.type),c.width=2*(a.radiusX||a.webkitRadiusX||0),c.height=2*(a.radiusY||a.webkitRadiusY||0),c.pressure=a.force||a.webkitForce||.5,c.isPrimary=this.isPrimaryTouch(a),c.pointerType=this.POINTER_TYPE,
+// forward modifier keys
+            c.altKey=b.altKey,c.ctrlKey=b.ctrlKey,c.metaKey=b.metaKey,c.shiftKey=b.shiftKey;
+// forward touch preventDefaults
+            var e=this;return c.preventDefault=function(){e.scrolling=!1,e.firstXY=null,b.preventDefault()},c},processTouches:function(a,b){var c=a.changedTouches;this.currentTouchEvent=a;for(var d,e=0;e<c.length;e++)d=c[e],b.call(this,this.touchToPointer(d))},
+// For single axis scrollers, determines whether the element should emit
+// pointer events or behave as a scroller
+        shouldScroll:function(a){if(this.firstXY){var b,c=a.currentTarget._scrollType;if("none"===c)
+// this element is a touch-action: none, should never scroll
+            b=!1;else if("XY"===c)
+// this element should always scroll
+            b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);
+// if delta in the scroll axis > 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<e&&(c=a[d]);d++)if(c.identifier===b)return!0},
+// In some instances, a touchstart can happen without a touchend. This
+// leaves the pointermap in a broken state.
+// Therefore, on every touchstart, we remove the touches that did not fire a
+// touchend event.
+// To keep state globally consistent, we fire a
+// pointercancel for this "abandoned" touch
+        vacuumTouches:function(a){var b=a.touches;
+// pointermap.size should be < tl.length here, as the touchstart has not
+// been processed yet.
+            if(R.size>=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
index e3965d22c79c57c423aeb8985c1d277e851d6439..a8f2abafbe35405261dbc80dbb95cd8f7903ff78 100644 (file)
 /* 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