From 292e43466e1db0dafc58d5d6f6cef51879c5c6a9 Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Mon, 25 Oct 2021 11:26:02 +0200 Subject: [PATCH 1/4] Card drag/drop scrolls now the list at top/bottom --- .meteor/packages | 1 - .meteor/versions | 3 +-- client/components/lists/list.js | 16 ++++++++++++++++ client/lib/jquery-ui.js | 17 +++++++++++++++++ package-lock.json | 13 +++++++++++++ package.json | 2 ++ 6 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 client/lib/jquery-ui.js diff --git a/.meteor/packages b/.meteor/packages index e6911f08e..10d89875e 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -60,7 +60,6 @@ reactive-var@1.0.11 fortawesome:fontawesome mousetrap:mousetrap mquandalle:jquery-textcomplete -mquandalle:jquery-ui-drag-drop-sort mquandalle:mousetrap-bindglobal peerlibrary:blaze-components@=0.15.1 templates:tabs diff --git a/.meteor/versions b/.meteor/versions index 76647b8a0..0f1be0e1d 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -76,6 +76,7 @@ matb33:collection-hooks@0.9.1 matteodem:easy-search@1.6.4 mdg:validation-error@0.5.1 meteor@1.9.3 +meteor-autosize@5.0.1 meteor-base@1.4.0 meteor-platform@1.2.6 meteorhacks:aggregate@1.3.0 @@ -106,7 +107,6 @@ mquandalle:collection-mutations@0.1.0 mquandalle:jade@0.4.9 mquandalle:jade-compiler@0.4.5 mquandalle:jquery-textcomplete@0.8.0_1 -mquandalle:jquery-ui-drag-drop-sort@0.2.0 mquandalle:moment@1.0.1 mquandalle:mousetrap-bindglobal@0.0.1 msavin:usercache@1.8.0 @@ -219,7 +219,6 @@ url@1.3.2 useraccounts:core@1.14.2 useraccounts:flow-routing@1.14.2 useraccounts:unstyled@1.14.2 -meteor-autosize@5.0.1 webapp@1.10.1 webapp-hashing@1.1.0 wekan-accounts-cas@0.1.0 diff --git a/client/components/lists/list.js b/client/components/lists/list.js index b5f829f25..f4819c9f7 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -1,3 +1,5 @@ +require('/client/lib/jquery-ui.js') + const { calculateIndex } = Utils; BlazeComponent.extendComponent({ @@ -114,6 +116,20 @@ BlazeComponent.extendComponent({ } boardComponent.setIsDragging(false); }, + sort(event, ui) { + const $boardCanvas = $('.board-canvas'); + const boardCanvas = $boardCanvas[0]; + + if (event.pageX < 10) + { // scroll to the left + boardCanvas.scrollLeft -= 15; + ui.helper[0].offsetLeft -= 15; + } + if (event.pageX > boardCanvas.offsetWidth - 10) + { // scroll to the right + boardCanvas.scrollLeft += 15; + } + }, }); this.autorun(() => { diff --git a/client/lib/jquery-ui.js b/client/lib/jquery-ui.js new file mode 100644 index 000000000..91f7b38aa --- /dev/null +++ b/client/lib/jquery-ui.js @@ -0,0 +1,17 @@ +// https://bugs.jqueryui.com/ticket/15020 +// required for sortable +require('jquery-ui/ui/widget') +require('jquery-ui/ui/scroll-parent') +require('jquery-ui/ui/data') +require('jquery-ui/ui/widgets/mouse') +require('jquery-ui/ui/ie') +require('jquery-ui/ui/widgets/sortable') + +// required for draggable +require('jquery-ui/ui/plugin') +require('jquery-ui/ui/safe-active-element') +require('jquery-ui/ui/safe-blur') +require('jquery-ui/ui/widgets/draggable') + +// everything already required for droppable +require('jquery-ui/ui/widgets/droppable') diff --git a/package-lock.json b/package-lock.json index aa323f882..63fb378c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1802,6 +1802,19 @@ "semver": "^6.3.0" } }, + "jquery": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", + "integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI=" + }, + "jquery-ui": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.0.tgz", + "integrity": "sha512-Osf7ECXNTYHtKBkn9xzbIf9kifNrBhfywFEKxOeB/OVctVmLlouV9mfc2qXCp6uyO4Pn72PXKOnj09qXetopCw==", + "requires": { + "jquery": ">=1.8.0 <4.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index 0ea0e6779..c849a4d7a 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,8 @@ "exceljs": "^4.2.1", "fibers": "^5.0.0", "gridfs-stream": "https://github.com/wekan/gridfs-stream/tarball/master", + "jquery": "^2.2.4", + "jquery-ui": "^1.13.0", "jszip": "^3.7.1", "ldapjs": "^2.3.1", "markdown-it": "^12.2.0", From c9071a74bc810d5d8786503d43bb8066c949b42a Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Sat, 13 Nov 2021 23:50:33 +0100 Subject: [PATCH 2/4] jquery-ui works now with touch devices - the "old" implementation at wekan source code didn't work anymore with jquery-ui@1.13.0, so it's necessary to use another package to get it work again --- client/components/boards/boardsList.js | 6 +-- client/components/cards/labels.js | 1 - client/lib/jquery-ui.js | 3 ++ client/lib/tests/Utils.tests.js | 12 ----- client/lib/utils.js | 61 -------------------------- package-lock.json | 5 +++ package.json | 1 + 7 files changed, 10 insertions(+), 79 deletions(-) diff --git a/client/components/boards/boardsList.js b/client/components/boards/boardsList.js index fc8331b8c..290b45c32 100644 --- a/client/components/boards/boardsList.js +++ b/client/components/boards/boardsList.js @@ -1,5 +1,4 @@ const subManager = new SubsManager(); -const { calculateIndex, enableClickOnTouch } = Utils; Template.boardListHeaderBar.events({ 'click .js-open-archived-board'() { @@ -56,7 +55,7 @@ BlazeComponent.extendComponent({ // of the previous and the following card -- if any. const prevBoardDom = ui.item.prev('.js-board').get(0); const nextBoardBom = ui.item.next('.js-board').get(0); - const sortIndex = calculateIndex(prevBoardDom, nextBoardBom, 1); + const sortIndex = Utils.calculateIndex(prevBoardDom, nextBoardBom, 1); const boardDomElement = ui.item.get(0); const board = Blaze.getData(boardDomElement); @@ -73,9 +72,6 @@ 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(() => { if (Utils.isMiniScreenOrShowDesktopDragHandles()) { diff --git a/client/components/cards/labels.js b/client/components/cards/labels.js index 2b599aa66..fc48f75f4 100644 --- a/client/components/cards/labels.js +++ b/client/components/cards/labels.js @@ -73,7 +73,6 @@ BlazeComponent.extendComponent({ card.board().setNewLabelOrder(newLabelOrderOnlyIds); }, }); - Utils.enableClickOnTouch(itemsSelector); // Disable drag-dropping if the current user is not a board member or is comment only this.autorun(() => { diff --git a/client/lib/jquery-ui.js b/client/lib/jquery-ui.js index 91f7b38aa..6bdcf2f5a 100644 --- a/client/lib/jquery-ui.js +++ b/client/lib/jquery-ui.js @@ -15,3 +15,6 @@ require('jquery-ui/ui/widgets/draggable') // everything already required for droppable require('jquery-ui/ui/widgets/droppable') + +// enable touch on mobile +require('jquery-ui-touch-punch') diff --git a/client/lib/tests/Utils.tests.js b/client/lib/tests/Utils.tests.js index 5a368876c..1ffcd8105 100644 --- a/client/lib/tests/Utils.tests.js +++ b/client/lib/tests/Utils.tests.js @@ -163,18 +163,6 @@ describe('Utils', function() { it('has no tests yet'); }); - describe(Utils.isTouchDevice.name, function() { - it('has no tests yet'); - }); - - describe(Utils.calculateTouchDistance.name, function() { - it('has no tests yet'); - }); - - describe(Utils.enableClickOnTouch.name, function() { - it('has no tests yet'); - }); - describe(Utils.manageCustomUI.name, function() { it('has no tests yet'); }); diff --git a/client/lib/utils.js b/client/lib/utils.js index 6395fe741..fba13c74d 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -364,67 +364,6 @@ Utils = { }; }, - // 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); - } - }); - }, - manageCustomUI() { Meteor.call('getCustomUI', (err, data) => { if (err && err.error[0] === 'var-not-exist') { diff --git a/package-lock.json b/package-lock.json index 63fb378c5..88f497d66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1815,6 +1815,11 @@ "jquery": ">=1.8.0 <4.0.0" } }, + "jquery-ui-touch-punch": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/jquery-ui-touch-punch/-/jquery-ui-touch-punch-0.2.3.tgz", + "integrity": "sha1-7tgiQnM7okP0az6HwYQbMIGR2mg=" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index c849a4d7a..68d6b3356 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "gridfs-stream": "https://github.com/wekan/gridfs-stream/tarball/master", "jquery": "^2.2.4", "jquery-ui": "^1.13.0", + "jquery-ui-touch-punch": "^0.2.3", "jszip": "^3.7.1", "ldapjs": "^2.3.1", "markdown-it": "^12.2.0", From 126c9ab853baa1f8e4597a49f0ed78af0389ba90 Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Sat, 13 Nov 2021 14:43:31 +0100 Subject: [PATCH 3/4] The Minicard dragging scrolls now the board at screen outside --- client/components/lists/list.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/components/lists/list.js b/client/components/lists/list.js index f4819c9f7..59825eb00 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -129,6 +129,15 @@ BlazeComponent.extendComponent({ { // scroll to the right boardCanvas.scrollLeft += 15; } + if (event.pageY > boardCanvas.offsetHeight - 10) + { // scroll to the bottom + boardCanvas.scrollTop += 15; + } + if (event.pageY < 10) + { // scroll to the top + boardCanvas.scrollTop -= 15; + } + }, }, }); From 3c7ca87625968fd0933df458e86cbae84ec3c713 Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Sat, 13 Nov 2021 14:48:22 +0100 Subject: [PATCH 4/4] Don't scroll the screen more than the scrollbar would scroll --- client/components/lists/list.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/client/components/lists/list.js b/client/components/lists/list.js index 59825eb00..3a0f9d66f 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -125,11 +125,17 @@ BlazeComponent.extendComponent({ boardCanvas.scrollLeft -= 15; ui.helper[0].offsetLeft -= 15; } - if (event.pageX > boardCanvas.offsetWidth - 10) + if ( + event.pageX > boardCanvas.offsetWidth - 10 && + boardCanvas.scrollLeft < $boardCanvas.data('scrollLeftMax') // don't scroll more than possible + ) { // scroll to the right boardCanvas.scrollLeft += 15; } - if (event.pageY > boardCanvas.offsetHeight - 10) + if ( + event.pageY > boardCanvas.offsetHeight - 10 && + boardCanvas.scrollTop < $boardCanvas.data('scrollTopMax') // don't scroll more than possible + ) { // scroll to the bottom boardCanvas.scrollTop += 15; } @@ -138,6 +144,14 @@ BlazeComponent.extendComponent({ boardCanvas.scrollTop -= 15; } }, + activate(event, ui) { + const $boardCanvas = $('.board-canvas'); + const boardCanvas = $boardCanvas[0]; + // scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax) + // https://stackoverflow.com/questions/12965296/how-to-get-maximum-document-scrolltop-value/12965383#12965383 + $boardCanvas.data('scrollTopMax', $(document).height() - $(window).height()); + // https://stackoverflow.com/questions/5138373/how-do-i-get-the-max-value-of-scrollleft/5704386#5704386 + $boardCanvas.data('scrollLeftMax', boardCanvas.scrollWidth - boardCanvas.clientWidth); }, });