HammerJS clicking on Pan - javascript

ready = ->
onPan = (ev) ->
console.log(ev)
# ev.target.dataset.object
createHammer = (v) ->
mc = new Hammer.Manager(v, {})
mc.add new Hammer.Pan(
direction: Hammer.DIRECTION_HORIZONTAL
threshold: 20
)
mc.on 'panleft', onPan
mc.on 'panright', onPan
selector = '.foo a'
createHammer(v) for v in document.querySelectorAll(selector)
$(document).ready(ready)
$(document).on('page:load', ready)
I don't know what I'm doing wrong, here... the objects all get a handler, and when I drag 's (mind you, with my mouse on my computer) if I stop on the element, it clicks. The last hammer event's srcEvent.type is mousemove, so it's not hammer firing the event. I tried calling ev.preventDefault(), but didn't seem to have any effect.
I still want to be able to click the ... just not after a drag. What am I missing?
I tried preventDefault: true as an option on the manager...
I tried ev.preventDefault() on the action...

I had the same problem, fixed it by temporarily (200ms) disabling click-handling on the target element. This was done in the panend event by setting a flag and starting a timer to remove that flag

As stated in this comment:
https://github.com/hammerjs/hammer.js/issues/240#issuecomment-16583814
"It's not a Hammer issue really, but rather just the way client events propagate. Hammer isn't replacing all default events but rather augmenting it, so default stuff like Click still fires."
And you can filter such click with a regular flag. E.g. in Angular 7:
#HostListener('click', ['$event'])
onClickBtn(){
if (!this.filterGhostClick) {
this.regularClickHandler();
}
this.filterGhostClick = false;
}
#HostListener('pan', ['$event'])
onPanStart(e){
this.panHandler(e);
}
private filterGhostClick = false;
panHandler(e: Event) {
...
if (e.isFinal) {
this.filterGhostClick = true;
}
}
...

Related

Is there an event for any kind of interaction (click, mousedown, keydown etc) [duplicate]

I'd like to accomplish the following code using a wildcard (that I don't think exists?)
myObject.element = document.getElementsByClassName('js-myObject');
myObject.element.addEventListener('click', myObject.click);
myObject.element.addEventListener('mouseover', myObject.mouseover);
//etc..
So far, I have the following
myObject.controller = function(e){
if( (e.type in myObject) && (typeof myObject[e.type] ==='function') ){
myObject[e.type](e);
}
};
//but the listeners still have to be assigned as such
myObject.element = document.getElementsByClassName('js-myObject');
myObject.element.addEventListener('click', myObject.controller);
myObject.element.addEventListener('mouseover', myObject.controller);
//etc...
// but I want to do (and it doesn't work)
myObject.element.addEventListener('*', myObject.controller);
Any suggestions on methods other than an array of events and a foreach statement?
Edit, my current solution
I've accepted an answer below (there's no wildcard available, and it's a bad idea to parse potentially hundreds of events)
For those looking for a similar function, I've settled on the following approach, at least for now.
for(var prop in myObject){
if (!myObject.hasOwnProperty(prop){continue;}
if (typeof myObject[prop] !== 'function'){continue;}
myObject.element.addEventListener(prop, myObject[prop]);
}
The upside is a handler for custom events that I don't have to go back and add listeners for. The downside is that I have to ensure this function is called after every myObject.someEvent() is defined. I call it in myObject.init(); which works for me just fine. Note that this solution wouldn't fit my previous specs, because it uses a for/each loop -- but it accomplishes what i really wanted to accomplish and a big thanks to #torazaburo for clearly defining the technical limitations and lack of wisdom in my initial plan.
How to implement addEventListener('*') yourself
For all native events, we can retrieve a list of supported events by iterating over the target.onevent properties and installing our listener for all of them.
for (const key in target) {
if(/^on/.test(key)) {
const eventType = key.substr(2);
target.addEventListener(eventType, listener);
}
}
The only other way that events are emitted which I know of is via EventTarget.dispatchEvent, which every Node and thefore every Element inherits.
To listen for all these manually triggered events, we can proxy the dispatchEvent method globally and install our listener just-in-time for the event whose name we just saw ✨ ^^
const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
EventTarget.prototype.dispatchEvent = function (event) {
if (!alreadyListenedEventTypes.has(event.type)) {
target.addEventListener(event.type, listener, ...otherArguments);
alreadyListenedEventTypes.add(event.type);
}
dispatchEvent_original.apply(this, arguments);
};
🔥 function snippet 🔥
function addEventListenerAll(target, listener, ...otherArguments) {
// install listeners for all natively triggered events
for (const key in target) {
if (/^on/.test(key)) {
const eventType = key.substr(2);
target.addEventListener(eventType, listener, ...otherArguments);
}
}
// dynamically install listeners for all manually triggered events, just-in-time before they're dispatched ;D
const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
function dispatchEvent(event) {
target.addEventListener(event.type, listener, ...otherArguments); // multiple identical listeners are automatically discarded
dispatchEvent_original.apply(this, arguments);
}
EventTarget.prototype.dispatchEvent = dispatchEvent;
if (EventTarget.prototype.dispatchEvent !== dispatchEvent) throw new Error(`Browser is smarter than you think!`);
}
// usage example
function addEventListenerAll(target, listener, ...otherArguments) {
// install listeners for all natively triggered events
for (const key in target) {
if (/^on/.test(key)) {
const eventType = key.substr(2);
target.addEventListener(eventType, listener, ...otherArguments);
}
}
// dynamically install listeners for all manually triggered events, just-in-time before they're dispatched ;D
const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
function dispatchEvent(event) {
target.addEventListener(event.type, listener, ...otherArguments); // multiple identical listeners are automatically discarded
dispatchEvent_original.apply(this, arguments);
}
EventTarget.prototype.dispatchEvent = dispatchEvent;
if (EventTarget.prototype.dispatchEvent !== dispatchEvent) throw new Error(`Browser is smarter than you think!`);
}
// usage example
addEventListenerAll(window, (evt) => {
console.log(evt.type);
});
document.body.click();
document.body.dispatchEvent(new Event('omg!', { bubbles: true }));
// usage example with `useCapture`
// (also receives `bubbles: false` events, but in reverse order)
addEventListenerAll(
window,
(evt) => { console.log(evt.type); },
true
);
document.body.dispatchEvent(new Event('omfggg!', { bubbles: false }));
There's no wild card, but using jQuery you can have 1 long event listener line, rather than multiple.
How do you log all events fired by an element in jQuery?
Like so:
('body').on("click mousedown mouseup focus blur keydown change dblclick mousemove mouseover mouseout mousewheel keydown keyup keypress textInput touchstart touchmove touchend touchcancel resize scroll zoom select change submit reset",function(e){
console.log(e);
});
A little late to the party, but here's how I add all event listeners & log them to the console:
Object.keys(window).forEach(key => {
if(/./.test(key)){
window.addEventListener(key.slice(2), event => {
console.log(key, event)
})
}
})
There is no feature to add a * listener, and I doubt if you want hundreds of events on an element being listened for anyway.
By the way, instead of your roll-your-own architecture for a generic event handler in the form of your myObject.controller, you should use the under-appreciated approach involving the EventListener interface and the handleEvent method it defines.
I'm not a 100% if this is what you're looking for, but I think this is what you're looking for.
the document which is what we usually tag into for our events doesn't contain the events. It's actually the grandparent class.
document -> HTMLDocument -> Document (where you could find the onclick* events)
as you could see we can then do this. just trim the on at the start of the events
Object.keys(document.__proto__.__proto__).reduce((arr, event)=> {
if(event.startsWith('on')) return [...arr, event.substr(2)];
return arr;
}, [])
which would return something like:
["readystatechange", "pointerlockchange", "pointerlockerror", "beforecopy", "beforecut", "beforepaste", "freeze", "resume", "search", "securitypolicyviolation", "visibilitychange", "copy", "cut", "paste", "abort", "blur", "cancel", "canplay", "canplaythrough", "change", "click", "close", "contextmenu", "cuechange", "dblclick", "drag", "dragend", "dragenter", "dragleave", "dragover", "dragstart", "drop", "durationchange", "emptied", "ended", "error", "focus", "formdata", "input", "invalid", "keydown", "keypress", "keyup", "load", "loadeddata", "loadedmetadata", "loadstart", "mousedown", "mouseenter", "mouseleave", "mousemove", "mouseout", "mouseover", "mouseup", "mousewheel", "pause", "play", "playing", "progress", "ratechange", "reset", "resize", "scroll", "seeked", "seeking", "select", "stalled", "submit", "suspend", "timeupdate", "toggle", "volumechange", "waiting", "webkitanimationend", "webkitanimationiteration", "webkitanimationstart", "webkittransitionend", "wheel", "auxclick", "gotpointercapture", "lostpointercapture", "pointerdown", "pointermove", "pointerup", "pointercancel", "pointerover", "pointerout", "pointerenter", "pointerleave", "selectstart", "selectionchange", "animationend", "animationiteration", "animationstart", "transitionend", "fullscreenchange", "fullscreenerror", "webkitfullscreenchange", "webkitfullscreenerror", "pointerrawupdate"]
this is just something quick I came up with and I'm sure there are better answers from smarter folks. you might also want to check out https://developer.mozilla.org/en-US/docs/Web/Events which contains what you just might need.
getElementsByClassName already returns an array (or more specifically, an HTMLCollection), not a single element. Just do it in a loop.
myObject.element = document.getElementsByClassName('js-myObject');
for(var i=0; i<myObject.element.length; i++){
myObject.element[i].addEventListener('click', myObject.controller);
myObject.element[i].addEventListener('mouseover', myObject.controller);
}
Edit... after clarification.. loops and arrays are still useful
var e = ['click', 'hover', 'focus', 'mouseover', 'mouseout'];
myObject.element = document.getElementsByClassName('js-myObject');
for(var i=0; i<myObject.element.length; i++){
for(var n=0; n<e.length; n++)
myObject.element[i].addEventListener(e[n], myObject.controller);
}
To find all event listeners on the page
getEventListeners(document)
Reference
To list them a little nicer
for (const [key, value] of Object.entries(getEventListeners(document))) {
console.log(`${key}`)
}
I will leave it up to you to actually do something with each, but now you can at least see all that exist on the page, you can open DevTools and try it out on this page and see for yourself it does work.
Something like this ?
document.addEventListener('click', function (event) {
if (event.target.closest('.scroll')) {
// Do something...
}
if (event.target.matches('[data-some-attribute]')) {
// Do something else...
}
if (event.target.matches('#my-form')) {
// Do another t hing...
}
}, false)

Combing "click" and "hover" permanently?

I want to have the click and drag functionality that Raphael.js provides, an example here: https://qiao.github.io/PathFinding.js/visual/.
The way you add and remove obstacles is great, it's essentially combining mousedown event and hover. But how on earth is that done? Any help please?
The closest I have is: https://codepen.io/ProgrammingKea/pen/ZowWJx
The salient bit is
div.addEventListener("mousedown", function(ev){
this.classList.add("obstacle");
});
div.addEventListener("mousemove", function(ev){
this.classList.add("obstacle");
});
div.addEventListener("mouseup", function(ev){
this.classList.add("obstacle");
});
If you press large, then hover over the grid, that's the closest I've got.
But my issue is that its only hover here, I don't have the click functionality the above link does
Please post answers containing only vanilla JS
It maybe feels a bit clunky putting a handler on every element. I'd be tempted to put a handler on the main container and then check from there...
Maybe first add a bit of code to check if mouse is down.
var main = document.getElementById('main')
var mouseDown = 0;
main.onmousedown = function() {
mouseDown=1;
}
main.onmouseup = function() {
mouseDown=0;
}
Then we can check if a mouse is down or over event...
main.addEventListener('mouseover', mousecheck)
main.addEventListener('mousedown', mousecheck)
Then we preventDefault (stop a drag).
If the mouse is down, and the element being acted on is a box, then we'll change it's colour.
function mousecheck( ev ) {
ev.preventDefault();
if( mouseDown && ev.target.className.startsWith( 'box') ) {
ev.target.style.backgroundColor = ev.target.style.backgroundColor == "red" ? 'white' : 'red';
}
}
Codepen
You can use something like:
["mousedown", "mousemove", "mouseup"]
.forEach(function (eve) {
div.addEventListener(eve, function(ev){
this.classList.add("obstacle");
});
});

How can I add an event listener for all events in javascript without listing them individually?

I'd like to accomplish the following code using a wildcard (that I don't think exists?)
myObject.element = document.getElementsByClassName('js-myObject');
myObject.element.addEventListener('click', myObject.click);
myObject.element.addEventListener('mouseover', myObject.mouseover);
//etc..
So far, I have the following
myObject.controller = function(e){
if( (e.type in myObject) && (typeof myObject[e.type] ==='function') ){
myObject[e.type](e);
}
};
//but the listeners still have to be assigned as such
myObject.element = document.getElementsByClassName('js-myObject');
myObject.element.addEventListener('click', myObject.controller);
myObject.element.addEventListener('mouseover', myObject.controller);
//etc...
// but I want to do (and it doesn't work)
myObject.element.addEventListener('*', myObject.controller);
Any suggestions on methods other than an array of events and a foreach statement?
Edit, my current solution
I've accepted an answer below (there's no wildcard available, and it's a bad idea to parse potentially hundreds of events)
For those looking for a similar function, I've settled on the following approach, at least for now.
for(var prop in myObject){
if (!myObject.hasOwnProperty(prop){continue;}
if (typeof myObject[prop] !== 'function'){continue;}
myObject.element.addEventListener(prop, myObject[prop]);
}
The upside is a handler for custom events that I don't have to go back and add listeners for. The downside is that I have to ensure this function is called after every myObject.someEvent() is defined. I call it in myObject.init(); which works for me just fine. Note that this solution wouldn't fit my previous specs, because it uses a for/each loop -- but it accomplishes what i really wanted to accomplish and a big thanks to #torazaburo for clearly defining the technical limitations and lack of wisdom in my initial plan.
How to implement addEventListener('*') yourself
For all native events, we can retrieve a list of supported events by iterating over the target.onevent properties and installing our listener for all of them.
for (const key in target) {
if(/^on/.test(key)) {
const eventType = key.substr(2);
target.addEventListener(eventType, listener);
}
}
The only other way that events are emitted which I know of is via EventTarget.dispatchEvent, which every Node and thefore every Element inherits.
To listen for all these manually triggered events, we can proxy the dispatchEvent method globally and install our listener just-in-time for the event whose name we just saw ✨ ^^
const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
EventTarget.prototype.dispatchEvent = function (event) {
if (!alreadyListenedEventTypes.has(event.type)) {
target.addEventListener(event.type, listener, ...otherArguments);
alreadyListenedEventTypes.add(event.type);
}
dispatchEvent_original.apply(this, arguments);
};
🔥 function snippet 🔥
function addEventListenerAll(target, listener, ...otherArguments) {
// install listeners for all natively triggered events
for (const key in target) {
if (/^on/.test(key)) {
const eventType = key.substr(2);
target.addEventListener(eventType, listener, ...otherArguments);
}
}
// dynamically install listeners for all manually triggered events, just-in-time before they're dispatched ;D
const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
function dispatchEvent(event) {
target.addEventListener(event.type, listener, ...otherArguments); // multiple identical listeners are automatically discarded
dispatchEvent_original.apply(this, arguments);
}
EventTarget.prototype.dispatchEvent = dispatchEvent;
if (EventTarget.prototype.dispatchEvent !== dispatchEvent) throw new Error(`Browser is smarter than you think!`);
}
// usage example
function addEventListenerAll(target, listener, ...otherArguments) {
// install listeners for all natively triggered events
for (const key in target) {
if (/^on/.test(key)) {
const eventType = key.substr(2);
target.addEventListener(eventType, listener, ...otherArguments);
}
}
// dynamically install listeners for all manually triggered events, just-in-time before they're dispatched ;D
const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
function dispatchEvent(event) {
target.addEventListener(event.type, listener, ...otherArguments); // multiple identical listeners are automatically discarded
dispatchEvent_original.apply(this, arguments);
}
EventTarget.prototype.dispatchEvent = dispatchEvent;
if (EventTarget.prototype.dispatchEvent !== dispatchEvent) throw new Error(`Browser is smarter than you think!`);
}
// usage example
addEventListenerAll(window, (evt) => {
console.log(evt.type);
});
document.body.click();
document.body.dispatchEvent(new Event('omg!', { bubbles: true }));
// usage example with `useCapture`
// (also receives `bubbles: false` events, but in reverse order)
addEventListenerAll(
window,
(evt) => { console.log(evt.type); },
true
);
document.body.dispatchEvent(new Event('omfggg!', { bubbles: false }));
There's no wild card, but using jQuery you can have 1 long event listener line, rather than multiple.
How do you log all events fired by an element in jQuery?
Like so:
('body').on("click mousedown mouseup focus blur keydown change dblclick mousemove mouseover mouseout mousewheel keydown keyup keypress textInput touchstart touchmove touchend touchcancel resize scroll zoom select change submit reset",function(e){
console.log(e);
});
A little late to the party, but here's how I add all event listeners & log them to the console:
Object.keys(window).forEach(key => {
if(/./.test(key)){
window.addEventListener(key.slice(2), event => {
console.log(key, event)
})
}
})
There is no feature to add a * listener, and I doubt if you want hundreds of events on an element being listened for anyway.
By the way, instead of your roll-your-own architecture for a generic event handler in the form of your myObject.controller, you should use the under-appreciated approach involving the EventListener interface and the handleEvent method it defines.
I'm not a 100% if this is what you're looking for, but I think this is what you're looking for.
the document which is what we usually tag into for our events doesn't contain the events. It's actually the grandparent class.
document -> HTMLDocument -> Document (where you could find the onclick* events)
as you could see we can then do this. just trim the on at the start of the events
Object.keys(document.__proto__.__proto__).reduce((arr, event)=> {
if(event.startsWith('on')) return [...arr, event.substr(2)];
return arr;
}, [])
which would return something like:
["readystatechange", "pointerlockchange", "pointerlockerror", "beforecopy", "beforecut", "beforepaste", "freeze", "resume", "search", "securitypolicyviolation", "visibilitychange", "copy", "cut", "paste", "abort", "blur", "cancel", "canplay", "canplaythrough", "change", "click", "close", "contextmenu", "cuechange", "dblclick", "drag", "dragend", "dragenter", "dragleave", "dragover", "dragstart", "drop", "durationchange", "emptied", "ended", "error", "focus", "formdata", "input", "invalid", "keydown", "keypress", "keyup", "load", "loadeddata", "loadedmetadata", "loadstart", "mousedown", "mouseenter", "mouseleave", "mousemove", "mouseout", "mouseover", "mouseup", "mousewheel", "pause", "play", "playing", "progress", "ratechange", "reset", "resize", "scroll", "seeked", "seeking", "select", "stalled", "submit", "suspend", "timeupdate", "toggle", "volumechange", "waiting", "webkitanimationend", "webkitanimationiteration", "webkitanimationstart", "webkittransitionend", "wheel", "auxclick", "gotpointercapture", "lostpointercapture", "pointerdown", "pointermove", "pointerup", "pointercancel", "pointerover", "pointerout", "pointerenter", "pointerleave", "selectstart", "selectionchange", "animationend", "animationiteration", "animationstart", "transitionend", "fullscreenchange", "fullscreenerror", "webkitfullscreenchange", "webkitfullscreenerror", "pointerrawupdate"]
this is just something quick I came up with and I'm sure there are better answers from smarter folks. you might also want to check out https://developer.mozilla.org/en-US/docs/Web/Events which contains what you just might need.
getElementsByClassName already returns an array (or more specifically, an HTMLCollection), not a single element. Just do it in a loop.
myObject.element = document.getElementsByClassName('js-myObject');
for(var i=0; i<myObject.element.length; i++){
myObject.element[i].addEventListener('click', myObject.controller);
myObject.element[i].addEventListener('mouseover', myObject.controller);
}
Edit... after clarification.. loops and arrays are still useful
var e = ['click', 'hover', 'focus', 'mouseover', 'mouseout'];
myObject.element = document.getElementsByClassName('js-myObject');
for(var i=0; i<myObject.element.length; i++){
for(var n=0; n<e.length; n++)
myObject.element[i].addEventListener(e[n], myObject.controller);
}
To find all event listeners on the page
getEventListeners(document)
Reference
To list them a little nicer
for (const [key, value] of Object.entries(getEventListeners(document))) {
console.log(`${key}`)
}
I will leave it up to you to actually do something with each, but now you can at least see all that exist on the page, you can open DevTools and try it out on this page and see for yourself it does work.
Something like this ?
document.addEventListener('click', function (event) {
if (event.target.closest('.scroll')) {
// Do something...
}
if (event.target.matches('[data-some-attribute]')) {
// Do something else...
}
if (event.target.matches('#my-form')) {
// Do another t hing...
}
}, false)

Equivalent of "hold" and "release" in hammer.js 2.0

In hammer.js 1.1.3 version I was able to use the following code perfectly:
var button = Hammer(element, {
hold: true,
release: true
});
button .on('hold', function() {
//Do something when the hold event starts
});
button .on('release', function() {
//Do something when the hold event stops
});
But in hammer.js 2.0 I'm struggling to find an equivalent:
var button = new Hammer.Manager(element);
button.add(new Hammer.Press({
event: 'press',
pointer: 1,
threshold: 5,
time: 500
}));
button.on('press', function(event) {
//Do something when the the element is pressed after 500ms
});
//Possible handler when the element is released?
According to the documentation (http://hammerjs.github.io/getting-started.html) for the new hammer.js 2.0, there are 5 recognizers:
Pan, Pinch, Press, Rotate, Swipe, Tap
I couldn't find a appropriate recognizer that would allow release type functionality. Any thoughts, suggestions or ideas are appreciated. Cheers for reading!
This will be supported in the next release, 2.0.1!
https://github.com/hammerjs/hammer.js/commit/a764fde2e89c3af2575ae02d3af41d7787a60dc5
Managed to achieve this functionality using 'press' (hold) and 'pressup' (release)
var hammer = new Hammer(this);
hammer.on("press pressup", function (ev) {
// Hold gesture start (press)
if (ev.type == "press") {
console.log("Hold active");
}
// Hold gesture stop (pressup)
if (ev.type == "pressup") {
console.log("Hold inactive");
}
});
Tested on Hammer.JS v2.0.8
Using
$(button).on('touchend',function(e){});
Works on jQuery.

Differentiate between focus event triggered by keyboard/mouse

I'm using jquery ui autocomplete and want to decipher between focus events triggered by keyboard interaction and mouse interaction. How would I go about this?
$('input').autocomplete({
source: function(request, response) {
...
},
focus: function(event, ui) {
// If focus triggered by keyboard interaction
alert('do something');
// If focus event triggered by mouse interaction
alert('do something else');
}
});
Thanks
The only way I can think of doing this is to have a handler listen in on the keypress and click events, and toggle a boolean flag on/off. Then on the focus handler of your input, you can just check what the value of your flag is, and go from there.
Probably something like
var isClick;
$(document).bind('click', function() { isClick = true; })
.bind('keypress', function() { isClick = false; })
;
var focusHandler = function () {
if (isClick) {
// clicky!
} else {
// tabby!
}
}
$('input').focus(function() {
// we set a small timeout to let the click / keypress event to trigger
// and update our boolean
setTimeout(focusHandler,100);
});
Whipped up a small working prototype on jsFiddle (don't you just love this site?). Check it out if you want.
Of course, this is all running off a focus event on an <input>, but the focus handler on the autocomplete works in the same way.
The setTimeout will introduce a bit of lag, but at 100ms, it might be negligible, based on your needs.
You should actually be able to determine this from the event-Object that is passed into the focus-event. Depending on your code structure this might be different, but there is usually a property called originalEvent in there, which might be nested to some depth. Examine the event-object more closely to determine the correct syntax. Then test on mousenter or keydown via regular expression. Something like this:
focus: function(event, ui){
if(/^key/.test(event.originalEvent.originalEvent.type)){
//code for keydown
}else{
//code for mouseenter and any other event
}
}
The easiest and most elegant way I've found of achieving this is to use the "What Input?" library. It's tiny (~2K minified), and gives you access to the event type both in scripts:
if (whatInput.ask() === 'mouse') {
// do something
}
...and also (via a single data attribute that it adds to the document body) styles:
[data-whatinput="mouse"] :focus,
[data-whatinput="touch"] :focus {
// focus styles for mouse and touch only
}
I particularly like the fact that where you just want a different visual behaviour for mouse / keyboard it makes it possible to do that in the stylesheet (where it really belongs) rather than via some hacky bit of event-checking Javascript (though of course if you do need to do something that's not just purely visual, the former approach lets you handle it in Javascript instead).
The first thing that comes to mind is that you can find the position of the mouse and check to see if its within the position of the element
Use this to store the position of the element:
var input = $('#your_autocompleted_element_id'),
offset = input.offset(),
input_x = offset.top,
input_y = offset.left,
input_w = input.outerWidth(),
input_h = input.outerHeight();
Then use this to find absolute position of the mouse within the window:
var cur_mx, cur_my;
$(document).mousemove(function(e){
cur_mx = e.pageX;
cur_my = e.pageY;
});
Then in your autcomplete setup:
focus: function(event, ui) {
// mouse is doing the focus when...
// mouse x is greater than input x and less than input x + input width
// and y is greater than input y and less than input y + input height
if (cur_mx >= input_x && cur_mx <= input_x + input_w && cur_my >= input_y && cur_my <= input_y + input_h) {
// do your silly mouse focus witchcraft here
} else {
// keyboard time!
}
}
This can be handled using mousedown event, see my example below.
this.focusFrom = 'keyboard' =>
onFocus = () => {
if (this.focusFrom === 'keyboard') {
// do something when focus from keyboard
}
}
handleMouseDown = () => {
this.focusFrom = 'mouse';
}
handleOnClick = () => {
this.focusFrom = 'keyboard';
}

Categories

Resources