diff options
Diffstat (limited to 'client')
-rw-r--r-- | client/components/boards/boardBody.js | 7 | ||||
-rw-r--r-- | client/components/cards/checklists.js | 7 | ||||
-rw-r--r-- | client/components/lists/list.js | 7 | ||||
-rw-r--r-- | client/components/main/header.styl | 2 | ||||
-rw-r--r-- | client/components/mixins/perfectScrollbar.js | 18 | ||||
-rw-r--r-- | client/components/swimlanes/swimlanes.js | 7 | ||||
-rw-r--r-- | client/lib/utils.js | 46 |
7 files changed, 82 insertions, 12 deletions
diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index 68ac8b27..6ff40ca4 100644 --- a/client/components/boards/boardBody.js +++ b/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,11 @@ BlazeComponent.extendComponent({ }, }); + // ugly touch event hotfix + $('.js-swimlane:not(.placeholder)').each(function() { + enableClickOnTouch(this); + }); + function userIsMember() { return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); } diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index 519af629..7fc54f9e 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -1,4 +1,4 @@ -const { calculateIndexData } = Utils; +const { calculateIndexData, enableClickOnTouch } = Utils; function initSorting(items) { items.sortable({ @@ -36,6 +36,11 @@ function initSorting(items) { checklistItem.move(checklistId, sortIndex.base); }, }); + + // ugly touch event hotfix + $('.js-checklist-item:not(.placeholder)').each(function() { + enableClickOnTouch(this); + }); } BlazeComponent.extendComponent({ diff --git a/client/components/lists/list.js b/client/components/lists/list.js index 38a87674..3f7c6dea 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -1,4 +1,4 @@ -const { calculateIndex } = Utils; +const { calculateIndex, enableClickOnTouch } = Utils; BlazeComponent.extendComponent({ // Proxy @@ -83,6 +83,11 @@ BlazeComponent.extendComponent({ }, }); + // ugly touch event hotfix + $(itemsSelector).each(function() { + enableClickOnTouch(this); + }); + // Disable drag-dropping if the current user is not a board member or is comment only this.autorun(() => { $cards.sortable('option', 'disabled', !userIsMember()); diff --git a/client/components/main/header.styl b/client/components/main/header.styl index f9455f8e..495716e1 100644 --- a/client/components/main/header.styl +++ b/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 diff --git a/client/components/mixins/perfectScrollbar.js b/client/components/mixins/perfectScrollbar.js index f652f043..12f8a892 100644 --- a/client/components/mixins/perfectScrollbar.js +++ b/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)); + } }, }); diff --git a/client/components/swimlanes/swimlanes.js b/client/components/swimlanes/swimlanes.js index c67fe6af..2acf4a82 100644 --- a/client/components/swimlanes/swimlanes.js +++ b/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,11 @@ function initSortable(boardComponent, $listsDom) { }, }); + // ugly touch event hotfix + $('.js-list:not(.js-list-composer)').each(function() { + enableClickOnTouch(this); + }); + function userIsMember() { return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); } diff --git a/client/lib/utils.js b/client/lib/utils.js index 1f44c60d..7e2651d2 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -95,6 +95,52 @@ 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); + })(); + return isTouchable; + }, + + calculateTouchDistance(touchA, touchB) { + return Math.sqrt( + Math.pow(touchA.screenX - touchB.screenX, 2) + + Math.pow(touchA.screenY - touchB.screenY, 2) + ); + }, + + enableClickOnTouch(element) { + let touchStart = null; + let lastTouch = null; + element.addEventListener('touchstart', function(e) { + touchStart = e.touches[0]; + }, false); + element.addEventListener('touchmove', function(e) { + const touches = e.touches; + lastTouch = touches[touches.length - 1]; + }, true); + element.addEventListener('touchend', function() { + if (touchStart && lastTouch && Utils.calculateTouchDistance(touchStart, lastTouch) <= 20) { + const clickEvent = document.createEvent('MouseEvents'); + clickEvent.initEvent('click', true, true); + this.dispatchEvent(clickEvent); + } + }, false); + }, }; // A simple tracker dependency that we invalidate every time the window is |