How do I disable vertical scrolling in iOS using Hammer.js? - javascript

I'm trying to disable vertical scrolling in iOS with Hammer.js (jQuery version) in a horizontally scrolling list. I've tried this:
$(document).hammer().on('swipe,drag', 'body',
function(event)
{
if (event.direction == Hammer.DIRECTION_UP || event.direction == Hammer.DIRECTION_DOWN)
{
event.preventDefault();
}
}
);
But it doesn't work. So, how do I disable the scroll vertically while still being able to scroll horizontally?

I did it using the event.gesture.preventDefault:
$('#horizontalCarousel').hammer({ drag_lock_to_axis: true }).on("swipe drag", function(event) {
event.gesture.preventDefault();
if(event.type == "swipe"){
swipeAction(event);
} else {
dragAction(event);
}
});
Here is the given documentation
[EDIT]
My answer was only to let you know you were using the wrong event.preventDefault(). In fact you also used the wrong syntax to check the event direction. You should be able to manage it in this way, though I haven't tested it:
$(document).hammer({ drag_lock_to_axis: true }).on("swipe drag", function(event) {
if (event.gesture.direction == Hammer.DIRECTION_UP || event.gesture.direction == Hammer.DIRECTION_DOWN){
event.gesture.preventDefault();
}
});
2 things are changed: event.gesture.direction and event.gesture.preventDefault(); The event.direction was the way to do it on older versions of hammer js.
Note: if you want to do something with the swipe event, for instance: jump a bigger amount horizontally when swiping, you can combine my answers.

You can use the drag_block_vertical option to disable vertical scrolling:
$(document).hammer({drag_block_vertical: true}).on('swipe,drag', 'body', function(event){
// etc
});
Also, you're calling it on the body element, which should always exist. For that reason, you could probably simplify to:
$('body').hammer({drag_block_vertical: true}).on('swipe,drag', function(event){
// etc
});

Check out this page:
https://github.com/EightMedia/hammer.js/wiki/Event-delegation-and-how-to-stopPropagation---preventDefaults#evgesturestoppropagation
Try this assuming your $ is jQuery and you are using the jQuery version of hammer.js
$('body').hammer().on('touch', function(ev){
var $t = $(ev.target); //let's you know the exact element you touched.
if(ev.gesture.direction === 'left' || ev.gesture.direction ==='right'){
} else {
ev.gesture.preventDefault();
}
});

Hammer(document.body, { prevent_defaults: true });

Related

How can I check for two different events simultaneously [duplicate]

Okay so I can detect a mouseover using .on('mouseover')
and I can detect keypresses using
$(document).keypress(function(e) {
console.log(e.which);
}
but how do I detect which image my mouse is hovering over when I press a certain button?
the idea is to be able to delete an image by pressing d while hovering over it. any ideas ?
You can just toggle a class or data-attribute that shows you which one is currently being hovered
$('img').hover(function(){
$(this).toggleClass('active'); // if hovered then it has class active
});
$(document).keypress(function(e) {
if(e.which == 100){
$('.active').remove(); // if d is pressed then remove active image
}
});
FIDDLE
I'v added a better example with jsFiddle:
http://jsfiddle.net/cUCGX/ (Hover over one of the boxes and press enter.)
Give each image an on('mouseover') and set a variable based on that image.
So
var activeImage = null;
myImage.on('mouseover', function() {
activeImage = 'myImage';
});
myImage2.on('mouseover', function() {
activeImage = 'myImage2';
});
$(document).keypress(function(e) {
if (e.which == 'certainKeyPress' && activeImage) {
//do something with activeImage
console.log('The cursor was over image: ' + activeImage + ' when the key was pressed');
}
});
Maybe also add an onmouseout to each image as well to clear activeImage if you want the key press to only work WHEN being hovered.
You should use a mousemove event to permanently store the x & y position in a global variable.
Then, in the keypress handler, grab the element at the last-known mouse position with the document.elementFromPoint(x, y) method.
See https://developer.mozilla.org/en-US/docs/Web/API/document.elementFromPoint
I'm going to go ahead and necro this as I was playing around with this and found I liked my quick solution more. It may not be the best, but it worked better for my needs where I needed a namespace type solution in that the handler would be removed when the dom was in a certain state (sortable):
// Create handler for binding keyup/down based on keyCode
// (ctrl in this example) with namespace to change the cursor
var setCursorBindings = function() {
$(document).on('keydown.sortable', function(event) {
if (event.keyCode === 17) {
$('body').css('cursor', 'pointer');
}
}).on('keyup.sortable', function(event) {
if (event.keyCode === 17) {
$('body').css('cursor', 'inherit');
}
});
};
// Create a handler for reverting the cursor
// and remove the keydown and keyup bindings.
var clearCursorBindings = function() {
$('body').css('cursor', 'inherit');
$(document).off('keydown.sortable').off('keyup.sortable');
};
// Use the jQuery hover in/out to set and clear the cursor handlers
$('.myElementSelector').hover(function() {
setCursorBindings();
}, function() {
clearCursorBindings();
});
Tested in Chrome v41
Use this to test whether the mouse is over the image with id img:
$('#img').is(":hover")

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.

Jquery: How to check if input is focused

I am building a mobile web app where the page is set to responsive through screen width and height. I am facing one issue here. In a mobile, if I click any input field, the screen size changes due to mobile keypad in some browsers. In this case I don't want the screen to resize. Where as the screen has to resize when we rotate screen. Your help will be greatly appreciated. Below is the part of code I am using for that.
function pageresponsive() {
$('body').css('width', window.screen.width);
$('body').css('height', window.screen.height);
}
pageresponsive();
var input_click_status = 0;
$("input").click(function() {
input_click_status = 1;
});
$( "input" ).focus(function() {
input_click_status = 1;
});
//This might not work as resize event will be set at the time of page load
if(input_click_status == 0) {
$(window).resize(function() {
pageresponsive(true);
});
}
Try this solution
var isFocused = $("input").is(":focus")
for version 1.6+ of jquery
$("selector").is(":focus")
:Focus
you can check by two way:
you can bind an event on input.
var is_focused = false;
jQuery('input').bind('focus', function(){
is_focused = true;
/* you can write code what ever you want to do on focus.*/
});
or
there is one more function:
var is_focused = jQuery("input").is(":focus")

Disable scrolling on `<input type=number>`

Is it possible to disable the scroll wheel changing the number in an input number field?
I've messed with webkit-specific CSS to remove the spinner but I'd like to get rid of this behavior altogether. I like using type=number since it brings up a nice keyboard on iOS.
Prevent the default behavior of the mousewheel event on input-number elements like suggested by others (calling "blur()" would normally not be the preferred way to do it, because that wouldn't be, what the user wants).
BUT. I would avoid listening for the mousewheel event on all input-number elements all the time and only do it, when the element is in focus (that's when the problem exists). Otherwise the user cannot scroll the page when the mouse pointer is anywhere over a input-number element.
Solution for jQuery:
// disable mousewheel on a input number field when in focus
// (to prevent Chromium browsers change the value when scrolling)
$('form').on('focus', 'input[type=number]', function (e) {
$(this).on('wheel.disableScroll', function (e) {
e.preventDefault()
})
})
$('form').on('blur', 'input[type=number]', function (e) {
$(this).off('wheel.disableScroll')
})
(Delegate focus events to the surrounding form element - to avoid to many event listeners, which are bad for performance.)
One event listener to rule them all
This is similar to #Simon Perepelitsa's answer in pure js, but a bit simpler, as it puts one event listener on the document element for all inputs and checks if the focused element is a number input tpye:
document.addEventListener("wheel", function(event){
if(document.activeElement.type === "number"){
document.activeElement.blur();
}
});
If you want to turn off the value scrolling behaviour on some fields by class/id, but not others just add && and the corresponding document selector instead:
document.addEventListener("wheel", function(event){
if(document.activeElement.type === "number" &&
document.activeElement.classList.contains("noscroll"))
{
document.activeElement.blur();
}
});
with this:
<input type="number" class="noscroll"/>
If an input has the noscroll class it wont change on scroll, otherwise everything stays the same.
Test here with JSFiddle
$(document).on("wheel", "input[type=number]", function (e) {
$(this).blur();
});
You can simply use the HTML onwheel attribute.
This option have no effects on scrolling over other elements of the page.
And add a listener for all inputs don't work in inputs dynamically created posteriorly.
Aditionaly, you can remove the input arrows with CSS.
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
<input type="number" onwheel="this.blur()" />
I have an alternative suggestion. The problem I see with most of the common recommendation of firing a blur event is that it has unexpected side-effects. It's not always a good thing to remove a focus state unexpectedly.
Why not this instead?
<input type="number" onwheel="return false;" />
It's very simple and straight-forward, easy to implement, and no side-effects that I can think of.
input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(event){ this.blur() })
http://jsfiddle.net/bQbDm/2/
For jQuery example and a cross-browser solution see related question:
HTML5 event listener for number input scroll - Chrome only
#Semyon Perepelitsa
There is a better solution for this. Blur removes the focus from the input and that is a side affect that you do not want. You should use evt.preventDefault instead. This prevents the default behavior of the input when the user scrolls. Here is the code:
input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(evt){ evt.preventDefault(); })
For anyone working with React and looking for solution. I’ve found out that easiest way is to use onWheelCapture prop in Input component like this:
onWheelCapture={e => {
e.target.blur()
}}
ReactJS Solution
For those needing a React solution, here's an onWheel handler for your type="number" input to prevent the number from changing and prevent the page from scrolling while the user tries to wheel over the input. Finally, it'll refocus on the input so the user can keep editing as intended:
const numberInputOnWheelPreventChange = (e) => {
// Prevent the input value change
e.target.blur()
// Prevent the page/container scrolling
e.stopPropagation()
// Refocus immediately, on the next tick (after the current function is done)
setTimeout(() => {
e.target.focus()
}, 0)
}
return <input type="number" onWheel={numberInputOnWheelPreventChange}/>
First you must stop the mousewheel event by either:
Disabling it with mousewheel.disableScroll
Intercepting it with e.preventDefault();
By removing focus from the element el.blur();
The first two approaches both stop the window from scrolling and the last removes focus from the element; both of which are undesirable outcomes.
One workaround is to use el.blur() and refocus the element after a delay:
$('input[type=number]').on('mousewheel', function(){
var el = $(this);
el.blur();
setTimeout(function(){
el.focus();
}, 10);
});
Easiest solution is to add onWheel={ event => event.currentTarget.blur() }} on input itself.
Typescript Variation
Typescript needs to know that you're working with an HTMLElement for type safety, else you'll see lots of Property 'type' does not exist on type 'Element' type of errors.
document.addEventListener("wheel", function(event){
const numberInput = (<HTMLInputElement>document.activeElement);
if (numberInput.type === "number") {
numberInput.blur();
}
});
The provided answers do not work in Firefox (Quantum). The event listener needs to be changed from mousewheel to wheel:
$(':input[type=number]').on('wheel',function(e){ $(this).blur(); });
This code works on Firefox Quantum and Chrome.
If you want a solution that doesn’t need JavaScript, combining some HTML functionality with a CSS pseudo-element does the trick:
span {
position: relative;
display: inline-block; /* Fit around contents */
}
span::after {
content: "";
position: absolute;
top: 0; right: 0; bottom: 0; left: 0; /* Stretch over containing block */
cursor: text; /* restore I-beam cursor */
}
/* Restore context menu while editing */
input:focus {
position: relative;
z-index: 1;
}
<label>How many javascripts can u fit in u mouth?
<span><input type="number" min="0" max="99" value="1"></span>
</label>
This works because clicking on the contents of a <label> that’s associated with a form field will focus the field. However, the “windowpane” of the pseudo-element over the field will block mousewheel events from reaching it.
The drawback is that the up/down spinner buttons no longer work, but you said you had removed those anyway.
In theory, one could restore the context menu without requiring the input to be focused first: :hover styles shouldn’t fire when the user scrolls, since browsers avoid recalculating them during scrolling for performance reasons, but I haven’t thoroughly cross-browser/device tested it.
In my case, I needed to maintain focus and still apply the scroll. None of the solutions above can handle that and doing blur/focus feels a bit hacky to me.
This maintains existing focus and also keeps the scroll. You know... like the browser should. Only minimally tested in chrome and only supports Y-axis.
// you could make this target a specific input instead of document
document.addEventListener('wheel', event => {
if (!event.target) return;
const isNumberInput = event.target.nodeName === 'INPUT' && event.target.type === 'number';
const isFocused = event.target === document.activeElement;
if (isNumberInput && isFocused) {
// prevent stupid input change
event.preventDefault();
// since we're taking over scrolling, we want to make sure
// nothing else gets the event
event.stopPropagation();
// finally we reapply the scroll
applyScroll(event);
}
}, { passive: false });
// this walks up the tree for event.target to find the first
// scrollable parent. this is probably good enough for most situations.
const applyScroll = event => {
try {
// console.debug('attempting to reapply scroll. searching for scrollable container...');
let scrollContainer = event.target;
while (scrollContainer && scrollContainer !== document.body && !elementIsScrollable(scrollContainer)) {
scrollContainer = scrollContainer.parentElement;
// console.debug('\t-> container was not scrollable. checking parent', scrollContainer);
}
if (scrollContainer) {
// console.debug('scrollContainer container found. applying scroll', scrollContainer, event.deltaY);
scrollContainer.scrollBy({ top: event.deltaY });
}
else {
// console.debug('no scrollContainer found');
}
}
catch (err) {
console.info('failed to reapply scroll', err, event);
}
};
const elementIsScrollable = element => {
const { scrollHeight = 0, offsetHeight = 0 } = element;
const scrollable = style.overflowY === 'auto' || style.overflowY === 'scroll';
return scrollable && scrollHeight > 0 && offsetHeight > 0 && element.scrollHeight > element.offsetHeight;
};
Non-JS solution
I like using type=number since it brings up a nice keyboard on iOS.
The keyboard is nice indeed. But we can get the same behaviour with:
<input inputmode="numeric" pattern="[0-9]*" />
Taken from gov.uk which was linked in the MUI docs. Works nicely for our product.
Grain of salt
Please check browser support for inputmode. Most mobile browsers are supported, and to me inputmode is mostly about the mobile experience. But YMMV.
While trying to solve this for myself, I noticed that it's actually possible to retain the scrolling of the page and focus of the input while disabling number changes by attempting to re-fire the caught event on the parent element of the <input type="number"/> on which it was caught, simply like this:
e.target.parentElement.dispatchEvent(e);
However, this causes an error in browser console, and is probably not guaranteed to work everywhere (I only tested on Firefox), since it is intentionally invalid code.
Another solution which works nicely at least on Firefox and Chromium is to temporarily make the <input> element readOnly, like this:
function handleScroll(e) {
if (e.target.tagName.toLowerCase() === 'input'
&& (e.target.type === 'number')
&& (e.target === document.activeElement)
&& !e.target.readOnly
) {
e.target.readOnly = true;
setTimeout(function(el){ el.readOnly = false; }, 0, e.target);
}
}
document.addEventListener('wheel', function(e){ handleScroll(e); });
One side effect that I've noticed is that it may cause the field to flicker for a split-second if you have different styling for readOnly fields, but for my case at least, this doesn't seem to be an issue.
Similarly, (as explained in James' answer) instead of modifying the readOnly property, you can blur() the field and then focus() it back, but again, depending on styles in use, some flickering might occur.
Alternatively, as mentioned in other comments here, you can just call preventDefault() on the event instead. Assuming that you only handle wheel events on number inputs which are in focus and under the mouse cursor (that's what the three conditions above signify), negative impact on user experience would be close to none.
function fixNumericScrolling() {
$$( "input[type=number]" ).addEvent( "mousewheel", function(e) {
stopAll(e);
} );
}
function stopAll(e) {
if( typeof( e.preventDefault ) != "undefined" ) e.preventDefault();
if( typeof( e.stopImmediatePropagation ) != "undefined" ) e.stopImmediatePropagation();
if( typeof( event ) != "undefined" ) {
if( typeof( event.preventDefault ) != "undefined" ) event.preventDefault();
if( typeof( event.stopImmediatePropagation ) != "undefined" ) event.stopImmediatePropagation();
}
return false;
}
Most answers blur the number element even if the cursor isn't hovering over it; the below does not
document.addEventListener("wheel", function(event) {
if (document.activeElement.type === "number" &&
document.elementFromPoint(event.x, event.y) == document.activeElement) {
document.activeElement.blur();
}
});
https://jsfiddle.net/s06puv3j/1/
I was struggling with the solution. So, This and other posts help me to do this. We need to change some stuff regarding the best answer here. So in order to disable scrolling, we must add the following:
<script>
$(document).ready(function() {
$('input[type=number]').on('wheel',function(e){ $(this).blur(); });
});
</script>
Instead of using "onwheel" we use "wheel" :)
Antd / React + Typescript answer
const myComponent = () => {
const inputRef: React.RefObject<HTMLInputElement> = createRef();
return <Input
ref={inputRef}
type="number"
onWheel={(e) => {
if (inputRef && inputRef.current && inputRef.current.blur) {
inputRef.current.blur();
}
e.preventDefault();
}}
/>
}
Angular solution. One directive to rule them all!
In contrast to other solutions, with this solution the user
does not loose focus on the input
and still able to scroll!
See it on StackBlitz
import { Directive, ElementRef, NgZone, OnDestroy } from '#angular/core';
import { fromEvent, Subscription, takeUntil } from 'rxjs';
import { tap, switchMap } from 'rxjs/operators';
#Directive({
selector: 'input[type=number]',
})
export class FixNumberInputScrollDirective implements OnDestroy {
private subs = new Subscription();
constructor(elRef: ElementRef<HTMLInputElement>, zone: NgZone) {
const el = elRef.nativeElement;
const focus$ = fromEvent(el, 'focus');
const blur$ = fromEvent(el, 'blur');
// when input is focused, start listening to the scroll of element. On this event blur and
// re-focus on the next tick. This allows for the page scroll to still happen, but the unwanted
// input number change is prevented.
// Stop listening to the scroll when focus is lost
const preventWheel$ = focus$.pipe(
switchMap(() => {
return fromEvent(el, 'wheel', { passive: false }).pipe(
tap(() => {
zone.runOutsideAngular(() => {
el.blur();
setTimeout(() => {
el.focus();
}, 0);
})
}),
takeUntil(blur$)
);
})
);
this.subs.add(preventWheel$.subscribe());
}
ngOnDestroy() {
this.subs.unsubscribe();
}
}

Submit jQuery UI dialog on <Enter>

I have a jQuery UI dialog box with a form. I would like to simulate a click on one of the dialog's buttons so you don't have to use the mouse or tab over to it. In other words, I want it to act like a regular GUI dialog box where simulates hitting the "OK" button.
I assume this might be a simple option with the dialog, but I can't find it in the jQuery UI documentation. I could bind each form input with keyup() but didn't know if there was a simpler/cleaner way. Thanks.
I don't know if there's an option in the jQuery UI widget, but you could simply bind the keypress event to the div that contains your dialog...
$('#DialogTag').keypress(function(e) {
if (e.keyCode == $.ui.keyCode.ENTER) {
//Close dialog and/or submit here...
}
});
This'll run no matter what element has the focus in your dialog, which may or may not be a good thing depending on what you want.
If you want to make this the default functionality, you can add this piece of code:
// jqueryui defaults
$.extend($.ui.dialog.prototype.options, {
create: function() {
var $this = $(this);
// focus first button and bind enter to it
$this.parent().find('.ui-dialog-buttonpane button:first').focus();
$this.keypress(function(e) {
if( e.keyCode == $.ui.keyCode.ENTER ) {
$this.parent().find('.ui-dialog-buttonpane button:first').click();
return false;
}
});
}
});
Here's a more detailed view of what it would look like:
$( "#dialog-form" ).dialog({
buttons: { … },
open: function() {
$("#dialog-form").keypress(function(e) {
if (e.keyCode == $.ui.keyCode.ENTER) {
$(this).parent().find("button:eq(0)").trigger("click");
}
});
};
});
I have summed up the answers above & added important stuff
$(document).delegate('.ui-dialog', 'keyup', function(e) {
var target = e.target;
var tagName = target.tagName.toLowerCase();
tagName = (tagName === 'input' && target.type === 'button')
? 'button'
: tagName;
isClickableTag = tagName !== 'textarea' &&
tagName !== 'select' &&
tagName !== 'button';
if (e.which === $.ui.keyCode.ENTER && isClickableTag) {
$(this).find('.ui-dialog-buttonset button').eq(0).trigger('click');
return false;
}
});
Advantages:
Disallow enter key on non compatible elements like textarea , select , button or inputs with type button , imagine user clicking enter on textarea and get the form submitted instead of getting new line!
The binding is done once , avoid using the dialog 'open' callback to bind enter key to avoid binding the same function again and again each time the dialog is 'open'ed
Avoid changing existing code as some answers above suggest
Use 'delegate' instead of the deprecated 'live' & avoid using the new 'on' method to allow working with older versions of jquery
Because we use delegate , that mean the code above can be written even before initializing dialog. you can also put it in head tag even without $(document).ready
Also delegate will bind only one handler to document and will not bind handler to each dialog as in some code above , for more efficiency
Works even with dynamically generated dialogs like $('<div><input type="text"/></div>').dialog({buttons: .});
Worked with ie 7/8/9!
Avoid using the slow selector :first
Avoid using hacks like in answers here to make a hidden submit button
Disadvantages:
Run the first button as the default one , you can choose another button with eq() or call a function inside the if statement
All of dialogs will have same behavior you can filter it by making your selector more specific ie '#dialog' instead of '.ui-dialog'
I know the question is old but I have had the same need, so, I shared the solution I've used.
$('#dialogBox').dialog('open');
$('.ui-dialog-buttonpane > button:last').focus();
It works beautifully with the latest version of JQuery UI (1.8.1).
You may also use :first instead of :last depending on which button you want to set as the default.
This solution, compared to the selected one above, has the advantage of showing which button is the default one for the user. The user can also TAB between buttons and pressing ENTER will click the button currently under focus.
Cheers.
Ben Clayton's is the neatest and shortest and it can be placed at the top of your index page before any jquery dialogs have been initialized. However, i'd like to point out that ".live" has been deprecated. The preferred action is now ".on". If you want ".on" to function like ".live", you'll have to use delegated events to attach the event handler. Also, a few other things...
I prefer to use the ui.keycode.ENTER method to test for the enter
key since you don't have to remember the actual key code.
Using "$('.ui-dialog-buttonpane button:first', $(this))" for the
click selector makes the whole method generic.
You want to add "return false;" to prevent default and stop
propagation.
In this case...
$('body').on('keypress', '.ui-dialog', function(event) {
if (event.keyCode === $.ui.keyCode.ENTER) {
$('.ui-dialog-buttonpane button:first', $(this)).click();
return false;
}
});
A crude but effective way to make this work more generically:
$.fn.dlg = function(options) {
return this.each(function() {
$(this).dialog(options);
$(this).keyup(function(e){
if (e.keyCode == 13) {
$('.ui-dialog').find('button:first').trigger('click');
}
});
});
}
Then when you create a new dialog you can do this:
$('#a-dialog').mydlg({...options...})
And use it like a normal jquery dialog thereafter:
$('#a-dialog').dialog('close')
There are ways to improve that to make it work in more special cases. With the above code it will automatically pick the first button in the dialog as the button to trigger when enter is hit. Also it assumes that there is only one active dialog at any given time which may not be the case. But you get the idea.
Note: As mentioned above, the button that is pressed on enter is dependent on your setup. So, in some cases you would want to use the :first selector in .find method and in others you may want to use the :last selector.
Rather than listening for key codes like in this answer (which I couldn't get to work) you can bind to the submit event of the form within the dialog and then do this:
$("#my_form").parents('.ui-dialog').first().find('.ui-button').first().click();
So, the whole thing would look like this
$("#my_form").dialog({
open: function(){
//Clear out any old bindings
$("#my_form").unbind('submit');
$("#my_form").submit(function(){
//simulate click on create button
$("#my_form").parents('.ui-dialog').first().find('.ui-button').first().click();
return false;
});
},
buttons: {
'Create': function() {
//Do something
},
'Cancel': function() {
$(this).dialog('close');
}
}
});
Note that different browsers handle the enter key differently, and some do not always do a submit on enter.
I don't know about simpler, but ordinarily you would track which button has the current focus. If the focus is changed to a different control, then the "button focus" would remain on the button that had focus last. Ordinarily, the "button focus" would start on your default button. Tabbing to a different button would change the "button focus". You'd have to decide if navigating to a different form element would reset the "button focus" to the default button again. You'll also probably need some visual indicator other than the browser default to indicate the focused button as it loses the real focus in the window.
Once you have the button focus logic down and implemented, then I would probably add a key handler to the dialog itself and have it invoke the action associated with the currently "focused" button.
EDIT: I'm making the assumption that you want to be able hit enter anytime you are filling out form elements and have the "current" button action take precedence. If you only want this behavior when the button is actually focused, my answer is too complicated.
I found this solution, it work's on IE8, Chrome 23.0 and Firefox 16.0
It's based on Robert Schmidt comment.
$("#id_dialog").dialog({
buttons: [{
text: "Accept",
click: function() {
// My function
},
id: 'dialog_accept_button'
}]
}).keyup(function(e) {
if (e.keyCode == $.ui.keyCode.ENTER)
$('#dialog_accept_button').click();
});
I hope it help anyone.
Sometimes we forget the fundamental of what the browser already supports:
<input type="submit" style="visibility:hidden" />
This will cause the ENTER key to submit the form.
I did such way... ;) Hope it will helpful for somebody..
$(window).keypress(function(e) {
if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
$(".ui-dialog:visible").find('.ui-dialog-buttonpane').find('button:first').click();
return false;
}
});
This should work to trigger the click of the button's click handler. this example assumes you have already set up the form in the dialog to use the jquery.validate plugin. but could be easily adapted.
open: function(e,ui) {
$(this).keyup(function(e) {
if (e.keyCode == 13) {
$('.ui-dialog-buttonpane button:last').trigger('click');
}
});
},
buttons: {
"Submit Form" : function() {
var isValid = $('#yourFormsID').valid();
// if valid do ajax call
if(isValid){
//do your ajax call here. with serialize form or something...
}
}
I realise there are a lot of answers already, but I reckon naturally that my solution is the neatest, and possibly the shortest. It has the advantage that it works on any dialogs created any time in the future.
$(".ui-dialog").live("keyup", function(e) {
if (e.keyCode === 13) {
$('.ok-button', $(this) ).first().click();
}
});
Here is what I did:
myForm.dialog({
"ok": function(){
...blah...
}
Cancel: function(){
...blah...
}
}).keyup(function(e){
if( e.keyCode == 13 ){
$(this).parent().find('button:nth-child(1)').trigger("click");
}
});
In this case, myForm is a jQuery object containing the form's html (note, there aren't any "form" tags in there... if you put those in the whole screen will refresh when you press "enter").
Whenever the user presses "enter" from within the form it will be the equivalent of clicking the "ok" button.
This also avoids the issue of having the form open with the "ok" button already highlighted. While that would be good for forms with no fields, if you need the user to fill in stuff, then you probably want the first field to be highlighted.
done and done
$('#login input').keyup(function(e) {
if (e.keyCode == 13) {
$('#login form').submit();
}
}
if you know the button element selector :
$('#dialogBox').dialog('open');
$('#okButton').focus();
Should do the trick for you. This will focus the ok button, and enter will 'click' it, as you would expect. This is the same technique used in native UI dialogs.
$("#LogOn").dialog({
modal: true,
autoOpen: false,
title: 'Please Log On',
width: 370,
height: 260,
buttons: { "Log On": function () { alert('Hello world'); } },
open: function() { $(this).parents('.ui-dialog-buttonpane button:eq(0)').focus();}
});
I found a quite simple solution for this problem:
var d = $('<div title="My dialog form"><input /></div>').dialog(
buttons: [{
text: "Ok",
click: function(){
// do something
alert('it works');
},
className: 'dialog_default_button'
}]
});
$(d).find('input').keypress(function(e){
if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
e.preventDefault();
$('.dialog_default_button').click();
}
});
$('#DialogID').dialog("option", "buttons")["TheButton"].apply()
This worked great for me..
None of these solutions seemed to work for me in IE9. I ended up with this..
$('#my-dialog').dialog({
...
open: function () {
$(this).parent()
.find("button:eq(0)")
.focus()
.keyup(function (e) {
if (e.keyCode == $.ui.keyCode.ENTER) {
$(this).trigger("click");
};
});
}
});
Below body is used because dialog DIV added on body,so body now listen the keyboard event. It tested on IE8,9,10, Mojila, Chrome.
open: function() {
$('body').keypress(function (e) {
if (e.keyCode == 13) {
$(this).parent().find(".ui-dialog-buttonpane button:eq(0)").trigger("click");
return false;
}
});
}
Because I don't have enough reputation to post comments.
$(document).delegate('.ui-dialog', 'keyup', function(e) {
var tagName = e.target.tagName.toLowerCase();
tagName = (tagName === 'input' && e.target.type === 'button') ? 'button' : tagName;
if (e.which === $.ui.keyCode.ENTER && tagName !== 'textarea' && tagName !== 'select' && tagName !== 'button') {
$(this).find('.ui-dialog-buttonset button').eq(0).trigger('click');
return false;
} else if (e.which === $.ui.keyCode.ESCAPE) {
$(this).close();
}
});
Modified answer by Basemm #35 too add in Escape to close the dialog.
It works fine Thank You!!!
open: function () {
debugger;
$("#dialogDiv").keypress(function (e) {
if (e.keyCode == 13) {
$(this).parent().find("#btnLoginSubmit").trigger("click");
}
});
},
Give your buttons classes and select them the usual way:
$('#DialogTag').dialog({
closeOnEscape: true,
buttons: [
{
text: 'Cancel',
class: 'myCancelButton',
click: function() {
// Close dialog fct
}
},
{
text: 'Ok',
class: 'myOKButton',
click: function() {
// OK fct
}
}
],
open: function() {
$(document).keyup(function(event) {
if (event.keyCode === 13) {
$('.myOKButton').click();
}
});
}
});

Categories

Resources