-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow marker thumbnails outside of edit mode
Previously, the only way to see thumbnails of an existing marker was to enter edit mode. With this change, a thumbnail toggle is added to existing markers' options, which, like edit mode, will show/hide the thumbnails for that marker. Core changes: * Split out the logic that handles marker edit thumbnail previews and the preview toggle into its own class to be shared by other components. * Use said class to add static thumbnails to existing marker rows, initially collapsed, but toggled via the new image icon. * Dynamically adjust the width of static thumbnails when the window resizes to avoid horizontal scrolling as much as possible. * Generalize longpress handling to allow anyone to set up a longpress listener. * Using the generalized longpress handling, allow a long press to show/hide all static thumbnails in a marker table. * Similarly, Ctrl+Click to show/hide all thumbnails in the table, and Ctrl+Shift+Click to show/hide thumbnails in all unhidden marker rows. Minor changes: * Add window resize listeners to marker rows to adjust more elements. * Before entering an edit session, make sure any static thumbnails are hidden. * Adjust TableElements.timeData to account for potential thumbnail elements. * Adjust options column width based on whether thumbnails are enabled. * Adjust how display height is caculated/set, including removing the DisplayHeight attribute, as everything can be calculated based on the thumbnail's naturalWidth/Height. Tangential changes: * When animating images, use the height attribute directly if the style height. isn't set. Also use the height attribute when resetting after animating. * Allow additional events to be set on buttons. * Export _buildNode's event attachment logic so it can be shared with ButtonCreator's attribute parser. * Refactor result row window resize listeners to ensure all relevant elements get notified as expected. * Make sure smallScreenCached is set correctly on load. * Don't launch purge overlay if the click target was the marker info icon. * Adjust padding of topAlignedPlainText * More flex tweaks to keep marker info on a single row in season results.
- Loading branch information
Showing
22 changed files
with
977 additions
and
317 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
|
||
/** @typedef {!import('./Common').CustomEventCallback} CustomEventCallback */ | ||
|
||
/** | ||
* Data to keep track of touch events. | ||
*/ | ||
class TouchData { | ||
/** @type {EventTarget} */ | ||
target = null; | ||
/** The screen x/y during the first touch */ | ||
startCoords = { x : 0, y : 0 }; | ||
/** The current touch coordinates, updated after every touchmove. */ | ||
currentCoords = { x : 0, y : 0 }; | ||
/** Timer set after a touchstart */ | ||
timer = 0; | ||
/** Clear out any existing touch data. */ | ||
clear() { | ||
this.target = null; | ||
this.startCoords = { x : 0, y : 0 }; | ||
this.currentCoords = { x : 0, y : 0 }; | ||
if (this.timer) { | ||
clearTimeout(this.timer); | ||
} | ||
} | ||
} | ||
|
||
/** List of events we want to listen to. */ | ||
const events = [ 'touchstart', 'touchmove', 'touchend' ]; | ||
|
||
/** | ||
* Handles a single element's "longpress" listener, triggering a callback if | ||
* the user has a single press for one second. | ||
*/ | ||
class LongPressHandler { | ||
/** @type {TouchData} */ | ||
#touches; | ||
|
||
/** @type {CustomEventCallback} */ | ||
#callback; | ||
|
||
/** | ||
* @param {HTMLElement} element | ||
* @param {CustomEventCallback} callback */ | ||
constructor(element, callback) { | ||
this.#callback = callback; | ||
this.#touches = new TouchData(); | ||
for (const event of events) { | ||
element.addEventListener(event, this.#handleTouch.bind(this), { passive : true }); | ||
} | ||
} | ||
|
||
/** | ||
* @param {TouchEvent} e */ | ||
#handleTouch(e) { | ||
switch (e.type) { | ||
default: | ||
return; | ||
case 'touchstart': | ||
if (e.touches.length !== 1) { | ||
this.#touches.clear(); | ||
return; | ||
} | ||
|
||
this.#touches.target = e.target; | ||
this.#touches.startCoords = { x : e.touches[0].clientX, y : e.touches[0].clientY }; | ||
this.#touches.currentCoords = { x : e.touches[0].clientX, y : e.touches[0].clientY }; | ||
this.#touches.timer = setTimeout(this.#checkCurrentTouch.bind(this), 1000); | ||
break; | ||
case 'touchmove': | ||
if (!this.#touches.timer || e.touches.length !== 1) { | ||
this.#touches.clear(); | ||
return; | ||
} | ||
|
||
this.#touches.currentCoords = { x : e.touches[0].clientX, y : e.touches[0].clientY }; | ||
break; | ||
case 'touchend': | ||
this.#touches.clear(); | ||
break; | ||
} | ||
} | ||
|
||
/** | ||
* Triggered one second after the first touch, if touchend hasn't been fired. | ||
* If our final touch point isn't too far away from the initial point, trigger the callback. */ | ||
#checkCurrentTouch() { | ||
const diffX = Math.abs(this.#touches.currentCoords.x - this.#touches.startCoords.x); | ||
const diffY = Math.abs(this.#touches.currentCoords.y - this.#touches.startCoords.y); | ||
|
||
// Allow a bit more horizontal leeway than vertical. | ||
if (diffX < 20 && diffY < 10) { | ||
this.#callback(this.#touches.target); | ||
} | ||
|
||
this.#touches.clear(); | ||
} | ||
} | ||
|
||
/** | ||
* Add a "longpress" listener to the given element, triggering the callback if a | ||
* single touch lasts for one second and hasn't moved from the original touch point. | ||
* @param {HTMLElement} element | ||
* @param {CustomEventCallback} callback */ | ||
export function addLongPressListener(element, callback) { | ||
new LongPressHandler(element, callback); | ||
} |
Oops, something went wrong.