Do not close tooltip when input has focus after click - jquery-ui

How can I make tooltip do not be closed if input has focus? It works when it gets focus with tab, but if I use mouse to focus on input, tooltip will be closed on mouseout even if input has focus.
I can do
$('input').tooltip().off("mouseover mouseout");
But this will dissable tooltip on hover and I just need to dissable mouseout when input has focus.
http://jsfiddle.net/3dX6d/2/
http://jsfiddle.net/3dX6d/3/

Try this:
Working Example
$("input").tooltip({
close: function (event, ui) { //when the tooltip is supposed to close
if ($('input').is(':focus')) { // check to see if input is focused
$('input').tooltip('open'); // if so stay open
}
}
});
New and Improved Method:
Better Working Example
$("input").tooltip({
hide: {
effect: 'explode'// added for visibility
}
}).mouseleave(function () { // on mouse leave
if ($('input').is(':focus')) { // if input is focused
ui.tooltip.preventDefault(); //prevent the tooltip's default behavior
$('input').tooltip('open'); // leave the tooltip open
}
}).focusout(function () { // on focus out
$('input').tooltip('close'); // close the tooltip
});
API documentation:
:focus
event.preventDefault()
.focusout()
open method
close event

Instead of adding all these other listeners, I looked into the actual and decided the most effective way is to just inherit the widget and add an extra flag
http://code.jquery.com/ui/1.10.3/jquery-ui.js
Here's a demo
http://jsfiddle.net/3dX6d/7/
(function ($) {
$.widget("custom.tooltipX", $.ui.tooltip, {
options: {
focusPreventClose: false
},
close: function (event, target, content) {
if (this.options.focusPreventClose && $(this.element).is(":focus")) {
// Don't call the parent's close() call but therefore have to add event on focus out
this._on({ focusout:this.close });
} else {
this._superApply(arguments);
}
}
});
}(jQuery));
$('input').tooltipX({
focusPreventClose: true
});
Compared to the other solution, this doesn't require us to do more work with the extra open calls (which actually does several other calls within it). We simply prevent the tooltip to close when we have the focus on the element, as requested by original post.

The only thing you need to do to fix the ui error is just pass it in as a parameter per documentation.
http://api.jqueryui.com/tooltip/#event-close
$(document).tooltip({ selector: "[title]" }).mouseleave(function(event, ui) {
if ($('input').is(':focus')) {
ui.tooltip.preventDefault();
$('input').tooltip('open');
}
});

Related

Can't get events to work on images with Highmaps

I'm trying to get the click and mouseOver handlers to work with Highmaps. I've checked the docs and tried to follow their examples. I inserted the event handler configs just about everywhere where I think it makes sense.
The wanted result is that the click and mouseOver handlers get called when hovering and clicking on the labels (pin icons) in the map.
Fiddle with my non-working code:
http://jsfiddle.net/fyp86hct/1/
One of the Highmaps examples shows that you should be able to do this:
point:
{
events:
{
click: function ()
{
alert("this doesn't work"); // <-- non working event handler
},
mouseOver: function()
{
alert("this doesn't work"); // <-- non working event handler
}
}
}
Unfortunately it is not supported, but you can add shape by renderer and then attach click event.

Wijmo grid - Prevent row selection when clicking on a specific column

I have a Wijmo Grid which allows row selection, whenever a user click on any column.
And I added a column to display a tooltip with additional info of the specific record.
The problem is when this column is clicked, Wijmo automatically selects the current row.
I've read the documentation, there is no event before selecting a row or clicking on a row. The selectionChanged event is not useful in this case, because it is fired after selecting a row.
I cannot add a tr click event handler and make e.preventDefault, because in this case the tooltip would not appear.
How could I prevent row selection, depending on the column clicked?
There is no native way to do this. What you could do is, handle the currentCellChanging event and set the 'selectionMode' option to none based on the clicked cell.
var isLoaded = false;
$("#gridview2").wijgrid({
loading: function (e, args) {
isLoaded = false;
},
loaded: function (e, args) {
isLoaded = true;
},
currentCellChanging: function (e, args) {
if (isLoaded) {
if (args.cellIndex == 5) {
$(this).wijgrid({ selectionMode: 'none' });
}
else {
$(this).wijgrid({ selectionMode: 'singleRow' });
}
}
}
});
use selectionMode="none" work fine
which not select anything by default

jQuery UI – draggable 'snap' event

I'm looking a way to binding the snap event.
When I'm dragging an element over my surface and the draggable element is snapped to a declared snap position I want to trigger an event.
Something like this:
$(".drag").draggable({
snap: ".grid",
snaped: function( event, ui ) {}
});
Bonus point: with a reference to the .grid element where the draggable element was snapped.
The draggable widget does not expose such an event out of the box (yet). You could modify it and maintain your custom version or, better, derive a new widget from it and implement the new event there. There is, however, a third way.
From this question, we know the widget stores an array of the potentially "snappable" elements in its snapElements property. In turn, each element in this array exposes a snapping property that is true if the draggable helper is currently snapped to this element and false otherwise (the helper can snap to several elements at the same time).
The snapElements array is updated for every drag event, so it is always up-to-date in drag handlers. From there, we only have to obtain the draggable widget instance from the associated element with data(), and call its _trigger() method to raise our own snapped event (actually dragsnapped under the hood). In passing, we can $.extend() the ui object with a jQuery object wrapping the snapped element:
$(".drag").draggable({
drag: function(event, ui) {
var draggable = $(this).data("draggable");
$.each(draggable.snapElements, function(index, element) {
if (element.snapping) {
draggable._trigger("snapped", event, $.extend({}, ui, {
snapElement: $(element.item)
}));
}
});
},
snap: ".grid",
snapped: function(event, ui) {
// Do something with 'ui.snapElement'...
}
});
The code above, however, can still be improved. As it stands, a snapped event will be triggered for every drag event (which occurs a lot) as long as the draggable helper remains snapped to an element. In addition, no event is triggered when snapping ends, which is not very practical, and detracts from the convention for such events to occur in pairs (snapped-in, snapped-out).
Luckily, the snapElements array is persistent, so we can use it to store state. We can add a snappingKnown property to each array element in order to track that we already have triggered a snapped event for that element. Moreover, we can use it to detect that an element has been snapped out since the last call and react accordingly.
Note that rather than introducing another snapped-out event, the code below chooses to pass an additional snapping property (reflecting the element's current state) in the ui object (which is, of course, only a matter of preference):
$(".drag").draggable({
drag: function(event, ui) {
var draggable = $(this).data("draggable");
$.each(draggable.snapElements, function(index, element) {
ui = $.extend({}, ui, {
snapElement: $(element.item),
snapping: element.snapping
});
if (element.snapping) {
if (!element.snappingKnown) {
element.snappingKnown = true;
draggable._trigger("snapped", event, ui);
}
} else if (element.snappingKnown) {
element.snappingKnown = false;
draggable._trigger("snapped", event, ui);
}
});
},
snap: ".grid",
snapped: function(event, ui) {
// Do something with 'ui.snapElement' and 'ui.snapping'...
var snapper = ui.snapElement.attr("id"),snapperPos = ui.snapElement.position(),
snappee = ui.helper.attr("id"), snappeePos = ui.helper.position(),
snapping = ui.snapping;
// ...
}
});
You can test this solution here.
In closing, another improvement might be to make the snapped event cancelable, as the drag event is. To achieve that, we would have to return false from our drag handler if one of the calls to _trigger() returns false. You may want to think twice before implementing this, though, as canceling a drag operation on snap-in or snap-out does not look like a very user-friendly feature in the general case.
Update: From jQuery UI 1.9 onwards, the data() key becomes the widget's fully qualified name, with dots replaced by dashes. Accordingly, the code used above to obtain the widget instance becomes:
var draggable = $(this).data("ui-draggable");
Instead of:
var draggable = $(this).data("draggable");
Using the unqualified name is still supported in 1.9 but is deprecated, and support will be dropped in 1.10.
In jquery-ui 1.10.0, the above code doesn't work. The drag function is instead:
drag: function(event, ui) {
var draggable = $(this).data("ui-draggable")
$.each(draggable.snapElements, function(index, element) {
if(element.snapping) {
draggable._trigger("snapped", event, $.extend({}, ui, {
snapElement: $(element.item)
}));
}
});
}

Click and keydown at same time for draggable jQuery event?

I'm trying to have a jQuery UI event fire only if it meets the criteria of being clicked while the shift key is in the keydown state ( to mimic being held), and if not disable the event.
This example uses jQuery UI's .draggable to drag a container div only if the user clicks and holds shift.
http://jsfiddle.net/zEfyC/
Non working code, not sure if this is the best way to do this or what's wrong.
$(document).click(function(e) {
$('.container').keydown(function() {
if (e.shiftKey) {
$('.container').draggable();
} else {
$('.container').draggable({
disabled: true
});
}
});
});​
I see lots of errors with that code. Firstly, you only add the key listener after there's been a click on the document. Second you are adding keydown to the container div, rather than the whole document. Then, you also need to listen to keyup, since releasing the shift key should disable draggability, then you also need to pass disabled: false to the case where shift is down. And your handler is missing the e parameter. Try this:
$(function(e) {
var handler = function(e) {
if (e.shiftKey) {
$('.container').draggable({
disabled: false
});
} else {
$('.container').draggable({
disabled: true
});
}
};
$(document).keydown(handler);
$(document).keyup(handler);
});

jqueryUI Sortable: handling .disableSelection() on form inputs

example: i have an un-ordered list containing a bunch of form inputs.
after making the ul .sortable(), I call .disableSelection() on the sortable (ul) to prevent text-selection when dragging an li item.
..all fine but I need to re/enable text-selection on the form inputs.. or the form is basically un-editable ..
i found a partial solution # http://forum.jquery.com/topic/jquery-ui-sortable-disableselection-firefox-issue-with-inputs
enableSelection, disableSelection seem still to be un-documented: http://wiki.jqueryui.com/Core
any thoughts?
solved . bit of hack but works! .. any comments how i can do this better?
apply .sortable() and then enable text-selection on input fields :
$("#list").sortable({
stop: function () {
// enable text select on inputs
$("#list").find("input")
.bind('mousedown.ui-disableSelection selectstart.ui-disableSelection', function(e) {
e.stopImmediatePropagation();
});
}
}).disableSelection();
// enable text select on inputs
$("#list").find("input")
.bind('mousedown.ui-disableSelection selectstart.ui-disableSelection', function(e) {
e.stopImmediatePropagation();
});
A little improvement from post of Zack - jQuery Plugin
$.fn.extend({
preventDisableSelection: function(){
return this.each(function(i) {
$(this).bind('mousedown.ui-disableSelection selectstart.ui-disableSelection', function(e) {
e.stopImmediatePropagation();
});
});
}
});
And full solution is:
$("#list").sortable({
stop: function () {
// enable text select on inputs
$("#list").find("input").preventDisableSelection();
}
}).disableSelection();
// enable text select on inputs
$("#list").find("input").preventDisableSelection();
jQuery UI 1.9
$("#list").sortable();
$("#list selector").bind('click.sortable mousedown.sortable',function(e){
e.stopImmediatePropagation();
});
selector = input, table, li....
I had the same problem. Solution is quite simple:
$("#list").sortable().disableSelection();
$("#list").find("input").enableSelect();
The following will disable selection for the entire document, but input and select elements will still be functional...
function disableSelection(o) {
var $o = $(o);
if ($o.find('input,select').length) {
$o.children(':not(input,select)').each(function(x,e) {disableSelection(e);});
} else {
$o.disableSelection();
}
}
disableSelection(document);
But note that .disableSelection has been deprecated by jquery-ui and will someday go away.
EASY! just do:
$( "#sortable_container_id input").click(function() { $(this).focus(); });
and replace "sortable_container_id" with the id of the element that is the container of all "sortable" elements.
Quite old, but here is another way:
$('#my-sortable-component').sortable({
// ...
// Add all non draggable parts by class name or id, like search input texts and google maps for example
cancel: '#my-input-text, div.map',
//...
}).disableSelection();

Resources