Skip to content

Commit

Permalink
Merge pull request #80 from drag-drop-touch-js/issue-79
Browse files Browse the repository at this point in the history
Add debug code using the `DEBUG` label
  • Loading branch information
Pomax authored Jul 30, 2024
2 parents 3353db4 + 94f1e0f commit 1fc302b
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 24 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
dist/drag-drop-touch.debug.esm.js
node_modules
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
demo/*
dist/drag-drop-touch.debug.esm.js
node_modules/*
tests/*
ts/*
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,28 @@ polyfill works:
## License

[MIT License](./LICENSE)

## For developers

If you wish to work on this library, fork and clone the repository, then run
`npm install` to install all the dependency, followed by a one-time
`npm run dev:setup`, which will install the necessary components for running
the integration tests.

### Running tests

This repository uses the standard `npm test` command to run build and
integration tests. Build testing consists of linting the source code using `tsc`,
auto-formatting it using `prettier`, and compiling it into three bundles (debug, normal, and minified) using `esbuild`. Integration tests are found in the
`tests/touch.spec.js` file, using Playwright as test runner.

### Manual testing

To manually test in the browser, you can run `npm start` and then open the
URL that is printed to the console once the initial build tasks have finished.
This runs a local server that lets you run the demo page, but with the
`drag-drop-touch.esm.min.js` replaced by a `drag-drop-touch.debug.esm.js`
instead, which preserves all debug statements used in the TypeScript source.

To add your own debug statements, use the `DEBUG:` label followed by either
a normal statement, or multiple statements wrapped in a new block.
5 changes: 0 additions & 5 deletions dist/drag-drop-touch.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,6 @@ var DragDropTouch = class {
_img;
_imgCustom;
_imgOffset;
// Note that this typing is _not_ true for Node, because it does not follow
// the official JS Timers specification. However, Node does not have native
// support for typescript, and so by the time this code runs there is no
// problem. Similarly, native-typescript engines like Deno or Bun *do* follow
// the spec and so the following typing is correct when running in those.
_pressHoldIntervalId;
configuration;
/**
Expand Down
8 changes: 8 additions & 0 deletions dist/drag-drop-touch.esm.min.js

Large diffs are not rendered by default.

27 changes: 23 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
"main": "dist/drag-drop-touch.esm.js",
"scripts": {
"build:base": "esbuild --bundle --format=esm ./ts/drag-drop-touch.ts",
"build:esm": "npm run build:base -- --outfile=dist/drag-drop-touch.esm.js",
"build:min": "npm run build:base -- --minify --outfile=dist/drag-drop-touch.esm.min.js",
"build": "npm run lint && npm run build:esm && npm run build:min",
"lint": "prettier -w ts/*.ts",
"build:esm:debug": "npm run build:base -- --outfile=dist/drag-drop-touch.debug.esm.js",
"build:esm": "npm run build:base -- --drop-labels=DEBUG --outfile=dist/drag-drop-touch.esm.js",
"build:min": "npm run build:base -- --drop-labels=DEBUG --minify --outfile=dist/drag-drop-touch.esm.min.js",
"build": "npm run lint && npm run format && npm run build:esm:debug && npm run build:esm && npm run build:min",
"dev:setup": "playwright install",
"format": "prettier -w ts/*.ts",
"lint": "tsc --noEmit --target esnext --module esnext ts/drag-drop-touch.ts",
"server": "node server.js",
"start": "npm run build && npm run server",
"test:integration": "playwright test tests --workers=1 --timeout 5000 --global-timeout 15000",
"dev:setup": "playwright install",
"test": "npm run start -- -- --test && rm -rf test-results"
},
"repository": {
Expand Down Expand Up @@ -42,6 +44,7 @@
"esbuild": "^0.23.0",
"express": "^4.19.2",
"playwright": "^1.45.2",
"prettier": "^3.3.3"
"prettier": "^3.3.3",
"typescript": "^5.5.4"
}
}
12 changes: 11 additions & 1 deletion server.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,17 @@ app.use((req, res, next) => {
});

// static routes
app.get(`/`, (req, res) => res.redirect(`/demo`));
app.use(`/`, (req, res, next) => {
const { url } = req;
if (url === `/`) {
return res.redirect(`/demo`);
}
const testing = process.argv.includes(`--test`);
if (url === `/dist/drag-drop-touch.esm.min.js?autoload` && !testing) {
return res.redirect(`/dist/drag-drop-touch.debug.esm.js?autoload`);
}
next();
});
app.use(`/`, express.static(`.`));
app.use((req, res) => {
if (req.query.preview) {
Expand Down
34 changes: 26 additions & 8 deletions ts/drag-drop-touch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,7 @@ class DragDropTouch {
private _img: HTMLElement | null;
private _imgCustom: HTMLElement | null;
private _imgOffset: Point;

// Note that this typing is _not_ true for Node, because it does not follow
// the official JS Timers specification. However, Node does not have native
// support for typescript, and so by the time this code runs there is no
// problem. Similarly, native-typescript engines like Deno or Bun *do* follow
// the spec and so the following typing is correct when running in those.
private _pressHoldIntervalId?: number | undefined;
private _pressHoldIntervalId?: ReturnType<typeof setTimeout> | undefined;

private readonly configuration: DragDropTouchConfiguration;

Expand Down Expand Up @@ -207,7 +201,9 @@ class DragDropTouch {
* @param e
*/
_touchstart(e: TouchEvent) {
DEBUG: console.log(`touchstart`);
if (this._shouldHandle(e)) {
DEBUG: console.log(`handling touch start, resetting state`);
this._reset();
let src = this._closestDraggable(e.target as HTMLElement);
if (src) {
Expand All @@ -223,6 +219,7 @@ class DragDropTouch {
this._lastTouch = e;

// show context menu if the user hasn't started dragging after a while
DEBUG: console.log(`setting a contextmenu timeout`);
setTimeout(() => {
if (this._dragSource === src && this._img === null) {
if (this._dispatchEvent(e, `contextmenu`, src)) {
Expand All @@ -232,6 +229,7 @@ class DragDropTouch {
}, this.configuration.contextMenuDelayMS);

if (this.configuration.isPressHoldMode) {
DEBUG: console.log(`setting a press-hold timeout`);
this._pressHoldIntervalId = setTimeout(() => {
this._isDragEnabled = true;
this._touchmove(e);
Expand All @@ -243,6 +241,7 @@ class DragDropTouch {
// been turned into click events by the browser.
else if (!e.isTrusted) {
if (e.target !== this._lastTarget) {
DEBUG: console.log(`synthetic touch start: saving _lastTarget`);
this._lastTarget = e.target;
}
}
Expand All @@ -257,25 +256,33 @@ class DragDropTouch {
* @returns
*/
_touchmove(e: TouchEvent) {
DEBUG: console.log(`touchmove`);

if (this._shouldCancelPressHoldMove(e)) {
DEBUG: console.log(`cancel press-hold move`);
this._reset();
return;
}

if (this._shouldHandleMove(e) || this._shouldHandlePressHoldMove(e)) {
DEBUG: console.log(`handling touch move`);

// see if target wants to handle move
let target = this._getTarget(e)!;
if (this._dispatchEvent(e, `mousemove`, target)) {
DEBUG: console.log(`target handled mousemove, returning early.`);
this._lastTouch = e;
e.preventDefault();
return;
}

// start dragging
if (this._dragSource && !this._img && this._shouldStartDragging(e)) {
DEBUG: console.log(`should start dragging`);
if (
this._dispatchEvent(this._lastTouch!, `dragstart`, this._dragSource)
) {
// target canceled the drag event
DEBUG: console.log(`target canceled drag event, returning early.`);
this._dragSource = null;
return;
}
Expand All @@ -285,6 +292,7 @@ class DragDropTouch {

// continue dragging
if (this._img && this._dragSource) {
DEBUG: console.log(`continue dragging`);
this._lastTouch = e;
e.preventDefault();

Expand All @@ -300,6 +308,7 @@ class DragDropTouch {

// Allow scrolling if the screen edges were marked as "hot regions".
if (this.configuration.allowDragScroll) {
DEBUG: console.log(`synthetic scroll allowed`);
const delta = this._getHotRegionDelta(e);
globalThis.scrollBy(delta.x, delta.y);
}
Expand All @@ -313,27 +322,36 @@ class DragDropTouch {
* @returns
*/
_touchend(e: TouchEvent) {
DEBUG: console.log(`touchend`);

if (!(this._lastTouch && e.target && this._lastTarget)) {
DEBUG: console.log(`no lastTouch for touchend, resetting state.`);
this._reset();
return;
}

if (this._shouldHandle(e)) {
DEBUG: console.log(`handling touch end`);

if (this._dispatchEvent(this._lastTouch, `mouseup`, e.target)) {
DEBUG: console.log(`target handled mouseup, returning early.`);
e.preventDefault();
return;
}

// user clicked the element but didn't drag, so clear the source and simulate a click
if (!this._img) {
DEBUG: console.log(`click rather than drag.`);
this._dragSource = null;
this._dispatchEvent(this._lastTouch, `click`, e.target);
}

// finish dragging
this._destroyImage();
if (this._dragSource) {
DEBUG: console.log(`handling drop.`);
if (e.type.indexOf(`cancel`) < 0 && this._isDropZone) {
DEBUG: console.log(`drop was canceled.`);
this._dispatchEvent(this._lastTouch, `drop`, this._lastTarget);
}
this._dispatchEvent(this._lastTouch, `dragend`, this._dragSource);
Expand Down

0 comments on commit 1fc302b

Please sign in to comment.