Skip to content

Commit 92ef9ed

Browse files
Merge pull request #322 from desmosinc/mike/check-is-user-selecting
add mq.isUserSelecting() method to check if a mouse selection is active
2 parents 5266451 + 6ad81a3 commit 92ef9ed

File tree

6 files changed

+48
-0
lines changed

6 files changed

+48
-0
lines changed

docs/Api_Methods.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,18 @@ If a timeout (in ms) is supplied, and the math field has keyboard focus when the
289289

290290
Returns the suffix to be appended to the [ARIA label][`aria-label`], after the math content of the field. If no ARIA post-label has been specified, `''` (empty string) is returned.
291291

292+
## .isUserSelecting()
293+
294+
Returns `true` if the user is currently selecting text with the mouse, `false` otherwise. This can be useful for preventing certain actions (like setting the cursor position) while the user is actively dragging to select text. The method tracks mouse selection from the moment the user presses the mouse button down to start selecting until they release it or the selection is cancelled due to an edit operation.
295+
296+
```javascript
297+
if (!mathField.isUserSelecting()) {
298+
// Safe to programmatically change cursor position
299+
mathField.moveToLeftEnd();
300+
}
301+
```
302+
303+
292304
[`aria-label`]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute
293305

294306
## .config(new_config)

src/controller.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class ControllerBase {
2626
editable: boolean | undefined;
2727
_ariaAlertTimeout: number;
2828
KIND_OF_MQ: KIND_OF_MQ;
29+
isMouseSelecting: boolean = false;
2930

3031
textarea: HTMLElement | undefined;
3132
private textareaEventListeners: Partial<{

src/mathquill.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ declare namespace MathQuill {
6464
setAriaPostLabel: (str: string, timeout?: number) => EditableMathQuill;
6565
ignoreNextMousedown: (func: () => boolean) => EditableMathQuill;
6666
clickAt: (x: number, y: number, el: HTMLElement) => EditableMathQuill;
67+
isUserSelecting: () => boolean;
6768
}
6869

6970
interface API {

src/publicapi.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,9 @@ function getInterface(v: number): MathQuill.v3.API | MathQuill.v1.API {
490490
this.__controller.cursor.options.ignoreNextMousedown = fn;
491491
return this;
492492
}
493+
isUserSelecting() {
494+
return this.__controller.isMouseSelecting;
495+
}
493496
}
494497

495498
var APIClasses: APIClasses = {

src/services/mouse.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class Controller_mouse extends Controller_latex {
8484
ownerDocument?.removeEventListener('mousemove', onDocumentMouseMove);
8585
ownerDocument?.removeEventListener('mouseup', onDocumentMouseUp);
8686
cancelSelectionOnEdit = undefined;
87+
ctrlr.isMouseSelecting = false;
8788
}
8889

8990
function updateCursor() {
@@ -125,6 +126,7 @@ class Controller_mouse extends Controller_latex {
125126
}
126127

127128
cursor.blink = noop;
129+
ctrlr.isMouseSelecting = true;
128130
ctrlr
129131
.seek(e.target as HTMLElement | null, e.clientX, e.clientY)
130132
.cursor.startSelection();

test/unit/publicapi.test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,35 @@ suite('Public API', function () {
253253
assert.equal(mq.getAriaPostLabel(), '');
254254
});
255255

256+
test('.isUserSelecting()', function () {
257+
mq.latex('x+y');
258+
259+
// Initially should not be selecting
260+
assert.equal(mq.isUserSelecting(), false);
261+
262+
// Simulate mouse down event to start selection
263+
var mouseDownEvent = new MouseEvent('mousedown', {
264+
clientX: 10,
265+
clientY: 10,
266+
bubbles: true
267+
});
268+
mq.el().dispatchEvent(mouseDownEvent);
269+
270+
// Should be selecting during mouse down
271+
assert.equal(mq.isUserSelecting(), true);
272+
273+
// Simulate mouse up event to end selection
274+
var mouseUpEvent = new MouseEvent('mouseup', {
275+
clientX: 20,
276+
clientY: 10,
277+
bubbles: true
278+
});
279+
document.dispatchEvent(mouseUpEvent);
280+
281+
// Should not be selecting after mouse up
282+
assert.equal(mq.isUserSelecting(), false);
283+
});
284+
256285
test('.mathspeak()', function () {
257286
function assertMathSpeakEqual(a, b) {
258287
assert.equal(normalize(a), normalize(b));

0 commit comments

Comments
 (0)