Selaa lähdekoodia

Merge pull request #1757 from Haocen/mobile-hotfix

Mobile hotfix
Lauri Ojansivu 7 vuotta sitten
vanhempi
sitoutus
efb083aabf

+ 4 - 1
client/components/boards/boardBody.js

@@ -1,5 +1,5 @@
 const subManager = new SubsManager();
-const { calculateIndex } = Utils;
+const { calculateIndex, enableClickOnTouch } = Utils;
 
 BlazeComponent.extendComponent({
   onCreated() {
@@ -74,6 +74,9 @@ BlazeComponent.extendComponent({
       },
     });
 
+    // ugly touch event hotfix
+    enableClickOnTouch('.js-swimlane:not(.placeholder)');
+
     function userIsMember() {
       return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
     }

+ 7 - 1
client/components/cards/cardDetails.js

@@ -1,5 +1,5 @@
 const subManager = new SubsManager();
-const { calculateIndexData } = Utils;
+const { calculateIndexData, enableClickOnTouch } = Utils;
 
 BlazeComponent.extendComponent({
   mixins() {
@@ -132,6 +132,9 @@ BlazeComponent.extendComponent({
       },
     });
 
+    // ugly touch event hotfix
+    enableClickOnTouch('.card-checklist-items .js-checklist');
+
     const $subtasksDom = this.$('.card-subtasks-items');
 
     $subtasksDom.sortable({
@@ -167,6 +170,9 @@ BlazeComponent.extendComponent({
       },
     });
 
+    // ugly touch event hotfix
+    enableClickOnTouch('.card-subtasks-items .js-subtasks');
+
     function userIsMember() {
       return Meteor.user() && Meteor.user().isBoardMember();
     }

+ 4 - 1
client/components/cards/checklists.js

@@ -1,4 +1,4 @@
-const { calculateIndexData } = Utils;
+const { calculateIndexData, enableClickOnTouch } = Utils;
 
 function initSorting(items) {
   items.sortable({
@@ -36,6 +36,9 @@ function initSorting(items) {
       checklistItem.move(checklistId, sortIndex.base);
     },
   });
+
+  // ugly touch event hotfix
+  enableClickOnTouch('.js-checklist-item:not(.placeholder)');
 }
 
 BlazeComponent.extendComponent({

+ 4 - 1
client/components/lists/list.js

@@ -1,4 +1,4 @@
-const { calculateIndex } = Utils;
+const { calculateIndex, enableClickOnTouch } = Utils;
 
 BlazeComponent.extendComponent({
   // Proxy
@@ -83,6 +83,9 @@ BlazeComponent.extendComponent({
       },
     });
 
+    // ugly touch event hotfix
+    enableClickOnTouch(itemsSelector);
+
     // Disable drag-dropping if the current user is not a board member or is comment only
     this.autorun(() => {
       $cards.sortable('option', 'disabled', !userIsMember());

+ 1 - 1
client/components/main/header.styl

@@ -218,7 +218,7 @@
       position: absolute
       right: 0px
       padding: 10px
-      margin: -10px
+      margin: -10px 0 -10px -10px
 
 .announcement,
 .offline-warning

+ 11 - 7
client/components/mixins/perfectScrollbar.js

@@ -1,12 +1,16 @@
+const { isTouchDevice } = Utils;
+
 Mixins.PerfectScrollbar = BlazeComponent.extendComponent({
   onRendered() {
-    const component = this.mixinParent();
-    const domElement = component.find('.js-perfect-scrollbar');
-    Ps.initialize(domElement);
+    if (!isTouchDevice()) {
+      const component = this.mixinParent();
+      const domElement = component.find('.js-perfect-scrollbar');
+      Ps.initialize(domElement);
 
-    // XXX We should create an event map to be consistent with other components
-    // but since BlazeComponent doesn't merge Mixins events transparently I
-    // prefered to use a jQuery event (which is what an event map ends up doing)
-    component.$(domElement).on('mouseenter', () => Ps.update(domElement));
+      // XXX We should create an event map to be consistent with other components
+      // but since BlazeComponent doesn't merge Mixins events transparently I
+      // prefered to use a jQuery event (which is what an event map ends up doing)
+      component.$(domElement).on('mouseenter', () => Ps.update(domElement));
+    }
   },
 });

+ 4 - 1
client/components/swimlanes/swimlanes.js

@@ -1,4 +1,4 @@
-const { calculateIndex } = Utils;
+const { calculateIndex, enableClickOnTouch } = Utils;
 
 function currentCardIsInThisList(listId, swimlaneId) {
   const currentCard = Cards.findOne(Session.get('currentCard'));
@@ -66,6 +66,9 @@ function initSortable(boardComponent, $listsDom) {
     },
   });
 
+  // ugly touch event hotfix
+  enableClickOnTouch('.js-list:not(.js-list-composer)');
+
   function userIsMember() {
     return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
   }

+ 49 - 0
client/lib/utils.js

@@ -95,6 +95,55 @@ Utils = {
       increment,
     };
   },
+
+  // Detect touch device
+  isTouchDevice() {
+    const isTouchable = (() => {
+      const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
+      const mq = function(query) {
+        return window.matchMedia(query).matches;
+      };
+
+      if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
+        return true;
+      }
+
+      // include the 'heartz' as a way to have a non matching MQ to help terminate the join
+      // https://git.io/vznFH
+      const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
+      return mq(query);
+    })();
+    Utils.isTouchDevice = () => isTouchable;
+    return isTouchable;
+  },
+
+  calculateTouchDistance(touchA, touchB) {
+    return Math.sqrt(
+      Math.pow(touchA.screenX - touchB.screenX, 2) +
+      Math.pow(touchA.screenY - touchB.screenY, 2)
+    );
+  },
+
+  enableClickOnTouch(selector) {
+    let touchStart = null;
+    let lastTouch = null;
+
+    $(document).on('touchstart', selector, function(e) {
+      touchStart = e.originalEvent.touches[0];
+    });
+    $(document).on('touchmove', selector, function(e) {
+      const touches = e.originalEvent.touches;
+      lastTouch = touches[touches.length - 1];
+    });
+    $(document).on('touchend', selector, function(e) {
+      if (touchStart && lastTouch && Utils.calculateTouchDistance(touchStart, lastTouch) <= 20) {
+        e.preventDefault();
+        const clickEvent = document.createEvent('MouseEvents');
+        clickEvent.initEvent('click', true, true);
+        e.target.dispatchEvent(clickEvent);
+      }
+    });
+  },
 };
 
 // A simple tracker dependency that we invalidate every time the window is