How to make jQuery UI Tooltip stay on, on hover - jquery-ui

Does anybody know how can I make jQuery UI tooltip to stay visible on hover. That is- I want it to stay visible when I move mouse from p element to tooltip.
Have tried on fiddle, but it seems there's a problem with :hover.
$("p").tooltip({
hide: {
effect: 'explode'
}
}).mouseleave(function () {
if ($('p').is(':hover')) {
ui.tooltip.preventDefault();
$('p').tooltip('open');
}
}).focusout(function () {
$('p').tooltip('close');
});
jsFiddle

That was a little tricky...
This script extends the standard jQuery UI 1.12.1, so that you get two extra options, allowing you to keep the tooltip open, while hover (the mouse stays on) it.
(function($) {
var uiTooltipTmp = {
options: {
hoverTimeout: 200,
tooltipHover: false // to have a regular behaviour by default. Use true to keep the tooltip while hovering it
},
// This function will check every "hoverTimeout" if the original object or it's tooltip is hovered. If not, it will continue the standard tooltip closure procedure.
timeoutHover: function (event,target,tooltipData,obj){
var TO;
var hov=false, hov2=false;
if(target !== undefined) {
if(target.is(":hover")){
hov=true;}
}
if(tooltipData !== undefined) {
if($(tooltipData.tooltip).is(":hover")){
hov=true;}
}
if(target !== undefined || tooltipData !== undefined) {hov2=true;}
if(hov) {
TO = setTimeout(obj.timeoutHover,obj.options.hoverTimeout,event,target,tooltipData,obj);
}else{
target.data('hoverFinished',1);
clearTimeout(TO);
if(hov2){
obj.closing = false;
obj.close(event,true);}
}
},
// Changed standard procedure
close: function(event) {
var tooltip,
that = this,
target = $( event ? event.currentTarget : this.element ),
tooltipData = this._find( target );
if(that.options.tooltipHover && (target.data('hoverFinished')===undefined || target.data('hoverFinished') === 0)){
target.data('hoverFinished',0);
setTimeout(that.timeoutHover, that.options.hoverTimeout,event, target, tooltipData, that);
}
else
{
if(that.options.tooltipHover){
target.data('hoverFinished',0);}
// The rest part of standard code is unchanged
if ( !tooltipData ) {
target.removeData( "ui-tooltip-open" );
return;
}
tooltip = tooltipData.tooltip;
if ( tooltipData.closing ) {
return;
}
clearInterval( this.delayedShow );
if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
target.attr( "title", target.data( "ui-tooltip-title" ) );
}
this._removeDescribedBy( target );
tooltipData.hiding = true;
tooltip.stop( true );
this._hide( tooltip, this.options.hide, function() {
that._removeTooltip( $( this ) );
} );
target.removeData( "ui-tooltip-open" );
this._off( target, "mouseleave focusout keyup" );
if ( target[ 0 ] !== this.element[ 0 ] ) {
this._off( target, "remove" );
}
this._off( this.document, "mousemove" );
if ( event && event.type === "mouseleave" ) {
$.each( this.parents, function( id, parent ) {
$( parent.element ).attr( "title", parent.title );
delete that.parents[ id ];
} );
}
tooltipData.closing = true;
this._trigger( "close", event, { tooltip: tooltip } );
if ( !tooltipData.hiding ) {
tooltipData.closing = false;
}
}
}
};
// Extending ui.tooltip. Changing "close" function and adding two new parameters.
$.widget( "ui.tooltip", $.ui.tooltip, uiTooltipTmp);
})(jQuery);
jQuery(document).ready(function($) {
$("h3").tooltip({hoverTimeout: 250, tooltipHover: true});
});
body {
background-color: #f3f3f3;
}
h3 {
display: inline-block;
margin: 1em 0 0 1em;
padding: 1em;
background-color: #FF7E6B;
color: #fff;
}
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<div>
<h3 title="I'll be here while you are hovering me or my creator.">
Hover me</h3>
</div>

$('[data-toggle="popover"]').popover({ trigger: "manual" }).on(
{
mouseenter: function () {
var $this = $(this);
$this.popover("show");
$(".popover").on("mouseleave", function () {
$this.popover('hide');
});
},
mouseleave: function () {
var $this = $(this);
setTimeout(function () {
if (!$(".popover:hover").length) {
$this.popover("hide");
}
}, 350);
}
});
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span type="button" role="button" class="glyphicon glyphicon-question-sign" data-toggle="popover" data-trigger="hover" data-placement="auto" data-html="true" data-content="For instance enter a link here <a href='https://google.com' target='_blank'>Almost know everything</a>"></span>

Related

Use clone helper only when button pressed

I am trying to make it so that my draggable element is only cloned when I press the Control button and drag it. My options for the draggable() function are:
var pressedKeys = {};
window.onkeyup = function(e) { pressedKeys[e.keyCode] = false; }
window.onkeydown = function(e) { pressedKeys[e.keyCode] = true; }
var draggable_options = {
snap: '.slot',
snapMode: 'inner',
scroll: false,
start: function(event,ui){
if (pressedKeys[17]){
$(ui.helper).draggable('option','helper','clone');
}
},
}
Is this even possible? I've tried ui.element and also this and neither have worked. I'm not sure if you can change options at runtime for the jquery functions.
Consider the following.
$(function() {
var pressedKeys = {
17: false
};
$(window).on({
keyup: function(e) {
pressedKeys[e.keyCode] = false;
$("#draggable").draggable("option", "helper", "original");
},
keydown: function(e) {
console.log("Key Pressed: " + e.keyCode);
pressedKeys[e.keyCode] = true;
$("#draggable").draggable("option", "helper", "clone");
}
})
$("#draggable").draggable({
snap: '.slot',
snapMode: 'inner',
scroll: false
});
});
#draggable {
width: 150px;
height: 150px;
padding: 0.5em;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.js"></script>
<div id="draggable" class="ui-widget-content">
<p>Drag me around</p>
</div>
An alternative solution. I would advise this solution personally.
$(function() {
var pressedKeys = {
17: false
};
$(window).on({
keyup: function(e) {
pressedKeys[e.keyCode] = false;
},
keydown: function(e) {
console.log("Key Pressed: " + e.keyCode);
pressedKeys[e.keyCode] = true;
}
})
$("#draggable").draggable({
snap: '.slot',
snapMode: 'inner',
scroll: false,
helper: function() {
return (pressedKeys[17] ? $(this).clone().removeAttr("id") : $(this));
}
});
});
#draggable, .ui-draggable {
width: 150px;
height: 150px;
padding: 0.5em;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.js"></script>
<div id="draggable" class="ui-widget-content">
<p>Drag me around</p>
</div>
See more: https://api.jqueryui.com/draggable/#option-helper
The start callback is triggered too late to generate a Clone. This is why helper option offers a Function to dynamically create the the helper as needed.
Here is the _createHelper code from the library:
var o = this.options,
helperIsFunction = typeof o.helper === "function",
helper = helperIsFunction ? $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : ( o.helper === "clone" ? this.element.clone().removeAttr( "id" ) : this.element );
Simply perform a similar activity to replicate the code. Conditionally, it will return the original or a clone.

Add widgets to existing jQuery-UI lib

I have to extend an existing project which uses version 1.10.4, and this jQuery-UI version is build without any widgets.
Now I want to use the widgets "Spinner" and "Selectmenu".
For the "Spinner"-widget: this is available for jQuery version 1.10.4.
The "Selectmenu"-widget is available from versoin 1.11.4.
Unfortunately, I can't update the current versoin of jQuery-UI, so I want to know how/if it's possible to enhance the current version with these two widgets.
Using the $.widget() you can extend or create your own custom widgets. I gathered this code from https://code.jquery.com/ui/1.11.4/jquery-ui.js and since $.ui.menu exists in 1.10.4, this mostly works. Some adjustments must be made.
I gathered the styleing from https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css
$(function() {
$.widget("custom.selectmenu", {
version: "1.11.4",
defaultElement: "<select>",
options: {
appendTo: null,
disabled: null,
icons: {
button: "ui-icon-triangle-1-s"
},
position: {
my: "left top",
at: "left bottom",
collision: "none"
},
width: null,
// callbacks
change: null,
close: null,
focus: null,
open: null,
select: null
},
_create: function() {
var selectmenuId = this.element.uniqueId().attr("id");
this.ids = {
element: selectmenuId,
button: selectmenuId + "-button",
menu: selectmenuId + "-menu"
};
this._drawButton();
this._drawMenu();
if (this.options.disabled) {
this.disable();
}
},
_drawButton: function() {
var that = this;
// Associate existing label with the new button
this.label = $("label[for='" + this.ids.element + "']").attr("for", this.ids.button);
this._on(this.label, {
click: function(event) {
this.button.focus();
event.preventDefault();
}
});
// Hide original select element
this.element.hide();
// Create button
this.button = $("<span>", {
"class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
tabindex: this.options.disabled ? -1 : 0,
id: this.ids.button,
role: "combobox",
"aria-expanded": "false",
"aria-autocomplete": "list",
"aria-owns": this.ids.menu,
"aria-haspopup": "true"
})
.insertAfter(this.element);
$("<span>", {
"class": "ui-icon " + this.options.icons.button
})
.prependTo(this.button);
this.buttonText = $("<span>", {
"class": "ui-selectmenu-text"
})
.appendTo(this.button);
this._setText(this.buttonText, this.element.find("option:selected").text());
this._resizeButton();
this._on(this.button, this._buttonEvents);
this.button.one("focusin", function() {
// Delay rendering the menu items until the button receives focus.
// The menu may have already been rendered via a programmatic open.
if (!that.menuItems) {
that._refreshMenu();
}
});
this._hoverable(this.button);
this._focusable(this.button);
},
_drawMenu: function() {
var that = this;
// Create menu
this.menu = $("<ul>", {
"aria-hidden": "true",
"aria-labelledby": this.ids.button,
id: this.ids.menu
});
// Wrap menu
this.menuWrap = $("<div>", {
"class": "ui-selectmenu-menu ui-front"
})
.append(this.menu)
.appendTo(this._appendTo());
// Initialize menu widget
this.menuInstance = this.menu
.menu({
role: "listbox",
select: function(event, ui) {
event.preventDefault();
// support: IE8
// If the item was selected via a click, the text selection
// will be destroyed in IE
that._setSelection();
that._select(ui.item.data("ui-selectmenu-item"), event);
},
focus: function(event, ui) {
var item = ui.item.data("ui-selectmenu-item");
// Prevent inital focus from firing and check if its a newly focused item
if (that.focusIndex != null && item.index !== that.focusIndex) {
that._trigger("focus", event, {
item: item
});
if (!that.isOpen) {
that._select(item, event);
}
}
that.focusIndex = item.index;
that.button.attr("aria-activedescendant",
that.menuItems.eq(item.index).attr("id"));
}
})
.data("ui-menu");
// Adjust menu styles to dropdown
this.menu
.addClass("ui-corner-bottom")
.removeClass("ui-corner-all");
// Don't close the menu on mouseleave
this.menuInstance._off(this.menu, "mouseleave");
// Cancel the menu's collapseAll on document click
this.menuInstance._closeOnDocumentClick = function() {
return false;
};
// Selects often contain empty items, but never contain dividers
this.menuInstance._isDivider = function() {
return false;
};
},
refresh: function() {
this._refreshMenu();
this._setText(this.buttonText, this._getSelectedItem().text());
if (!this.options.width) {
this._resizeButton();
}
},
_refreshMenu: function() {
this.menu.empty();
var item,
options = this.element.find("option");
if (!options.length) {
return;
}
this._parseOptions(options);
this._renderMenu(this.menu, this.items);
this.menuInstance.refresh();
this.menuItems = this.menu.find("li").not(".ui-selectmenu-optgroup");
item = this._getSelectedItem();
// Update the menu to have the correct item focused
this.menuInstance.focus(null, item);
this._setAria(item.data("ui-selectmenu-item"));
// Set disabled state
this._setOption("disabled", this.element.prop("disabled"));
},
open: function(event) {
if (this.options.disabled) {
return;
}
// If this is the first time the menu is being opened, render the items
if (!this.menuItems) {
this._refreshMenu();
} else {
// Menu clears focus on close, reset focus to selected item
this.menu.find(".ui-state-focus").removeClass("ui-state-focus");
this.menuInstance.focus(null, this._getSelectedItem());
}
this.isOpen = true;
this._toggleAttr();
this._resizeMenu();
this._position();
this._on(this.document, this._documentClick);
this._trigger("open", event);
},
_position: function() {
this.menuWrap.position($.extend({ of: this.button
}, this.options.position));
},
close: function(event) {
if (!this.isOpen) {
return;
}
this.isOpen = false;
this._toggleAttr();
this.range = null;
this._off(this.document);
this._trigger("close", event);
},
widget: function() {
return this.button;
},
menuWidget: function() {
return this.menu;
},
_renderMenu: function(ul, items) {
var that = this,
currentOptgroup = "";
$.each(items, function(index, item) {
if (item.optgroup !== currentOptgroup) {
$("<li>", {
"class": "ui-selectmenu-optgroup ui-menu-divider" +
(item.element.parent("optgroup").prop("disabled") ?
" ui-state-disabled" :
""),
text: item.optgroup
})
.appendTo(ul);
currentOptgroup = item.optgroup;
}
that._renderItemData(ul, item);
});
},
_renderItemData: function(ul, item) {
return this._renderItem(ul, item).data("ui-selectmenu-item", item);
},
_renderItem: function(ul, item) {
var li = $("<li>");
if (item.disabled) {
li.addClass("ui-state-disabled");
}
this._setText(li, item.label);
return li.appendTo(ul);
},
_setText: function(element, value) {
if (value) {
element.text(value);
} else {
element.html(" ");
}
},
_move: function(direction, event) {
var item, next,
filter = ".ui-menu-item";
if (this.isOpen) {
item = this.menuItems.eq(this.focusIndex);
} else {
item = this.menuItems.eq(this.element[0].selectedIndex);
filter += ":not(.ui-state-disabled)";
}
if (direction === "first" || direction === "last") {
next = item[direction === "first" ? "prevAll" : "nextAll"](filter).eq(-1);
} else {
next = item[direction + "All"](filter).eq(0);
}
if (next.length) {
this.menuInstance.focus(event, next);
}
},
_getSelectedItem: function() {
return this.menuItems.eq(this.element[0].selectedIndex);
},
_toggle: function(event) {
this[this.isOpen ? "close" : "open"](event);
},
_setSelection: function() {
var selection;
if (!this.range) {
return;
}
if (window.getSelection) {
selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(this.range);
// support: IE8
} else {
this.range.select();
}
// support: IE
// Setting the text selection kills the button focus in IE, but
// restoring the focus doesn't kill the selection.
this.button.focus();
},
_documentClick: {
mousedown: function(event) {
if (!this.isOpen) {
return;
}
if (!$(event.target).closest(".ui-selectmenu-menu, #" + this.ids.button).length) {
this.close(event);
}
}
},
_buttonEvents: {
// Prevent text selection from being reset when interacting with the selectmenu (#10144)
mousedown: function() {
var selection;
if (window.getSelection) {
selection = window.getSelection();
if (selection.rangeCount) {
this.range = selection.getRangeAt(0);
}
// support: IE8
} else {
this.range = document.selection.createRange();
}
},
click: function(event) {
this._setSelection();
this._toggle(event);
},
keydown: function(event) {
var preventDefault = true;
switch (event.keyCode) {
case $.ui.keyCode.TAB:
case $.ui.keyCode.ESCAPE:
this.close(event);
preventDefault = false;
break;
case $.ui.keyCode.ENTER:
if (this.isOpen) {
this._selectFocusedItem(event);
}
break;
case $.ui.keyCode.UP:
if (event.altKey) {
this._toggle(event);
} else {
this._move("prev", event);
}
break;
case $.ui.keyCode.DOWN:
if (event.altKey) {
this._toggle(event);
} else {
this._move("next", event);
}
break;
case $.ui.keyCode.SPACE:
if (this.isOpen) {
this._selectFocusedItem(event);
} else {
this._toggle(event);
}
break;
case $.ui.keyCode.LEFT:
this._move("prev", event);
break;
case $.ui.keyCode.RIGHT:
this._move("next", event);
break;
case $.ui.keyCode.HOME:
case $.ui.keyCode.PAGE_UP:
this._move("first", event);
break;
case $.ui.keyCode.END:
case $.ui.keyCode.PAGE_DOWN:
this._move("last", event);
break;
default:
this.menu.trigger(event);
preventDefault = false;
}
if (preventDefault) {
event.preventDefault();
}
}
},
_selectFocusedItem: function(event) {
var item = this.menuItems.eq(this.focusIndex);
if (!item.hasClass("ui-state-disabled")) {
this._select(item.data("ui-selectmenu-item"), event);
}
},
_select: function(item, event) {
var oldIndex = this.element[0].selectedIndex;
// Change native select element
this.element[0].selectedIndex = item.index;
this._setText(this.buttonText, item.label);
this._setAria(item);
this._trigger("select", event, {
item: item
});
if (item.index !== oldIndex) {
this._trigger("change", event, {
item: item
});
}
this.close(event);
},
_setAria: function(item) {
var id = this.menuItems.eq(item.index).attr("id");
this.button.attr({
"aria-labelledby": id,
"aria-activedescendant": id
});
this.menu.attr("aria-activedescendant", id);
},
_setOption: function(key, value) {
if (key === "icons") {
this.button.find("span.ui-icon")
.removeClass(this.options.icons.button)
.addClass(value.button);
}
this._super(key, value);
if (key === "appendTo") {
this.menuWrap.appendTo(this._appendTo());
}
if (key === "disabled") {
this.menuInstance.option("disabled", value);
this.button
.toggleClass("ui-state-disabled", value)
.attr("aria-disabled", value);
this.element.prop("disabled", value);
if (value) {
this.button.attr("tabindex", -1);
this.close();
} else {
this.button.attr("tabindex", 0);
}
}
if (key === "width") {
this._resizeButton();
}
},
_appendTo: function() {
var element = this.options.appendTo;
if (element) {
element = element.jquery || element.nodeType ?
$(element) :
this.document.find(element).eq(0);
}
if (!element || !element[0]) {
element = this.element.closest(".ui-front");
}
if (!element.length) {
element = this.document[0].body;
}
return element;
},
_toggleAttr: function() {
this.button
.toggleClass("ui-corner-top", this.isOpen)
.toggleClass("ui-corner-all", !this.isOpen)
.attr("aria-expanded", this.isOpen);
this.menuWrap.toggleClass("ui-selectmenu-open", this.isOpen);
this.menu.attr("aria-hidden", !this.isOpen);
},
_resizeButton: function() {
var width = this.options.width;
if (!width) {
width = this.element.show().outerWidth();
this.element.hide();
}
this.button.outerWidth(width);
},
_resizeMenu: function() {
this.menu.outerWidth(Math.max(
this.button.outerWidth(),
// support: IE10
// IE10 wraps long text (possibly a rounding bug)
// so we add 1px to avoid the wrapping
this.menu.width("").outerWidth() + 1
));
},
_getCreateOptions: function() {
return {
disabled: this.element.prop("disabled")
};
},
_parseOptions: function(options) {
var data = [];
options.each(function(index, item) {
var option = $(item),
optgroup = option.parent("optgroup");
data.push({
element: option,
index: index,
value: option.val(),
label: option.text(),
optgroup: optgroup.attr("label") || "",
disabled: optgroup.prop("disabled") || option.prop("disabled")
});
});
this.items = data;
},
_destroy: function() {
this.menuWrap.remove();
this.button.remove();
this.element.show();
this.element.removeUniqueId();
this.label.attr("for", this.ids.element);
}
});
$("#spinner").spinner();
$("#speed").selectmenu();
});
.ui-selectmenu-menu {
padding: 0;
margin: 0;
position: absolute;
top: 0;
left: 0;
display: none;
}
.ui-selectmenu-menu .ui-menu {
overflow: auto;
/* Support: IE7 */
overflow-x: hidden;
padding-bottom: 1px;
}
.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
font-size: 1em;
font-weight: bold;
line-height: 1.5;
padding: 2px 0.4em;
margin: 0.5em 0 0 0;
height: auto;
border: 0;
}
.ui-selectmenu-open {
display: block;
}
.ui-selectmenu-button {
display: inline-block;
overflow: hidden;
position: relative;
text-decoration: none;
cursor: pointer;
}
.ui-selectmenu-button span.ui-icon {
right: 0.5em;
left: auto;
margin-top: -8px;
position: absolute;
top: 50%;
}
.ui-selectmenu-button span.ui-selectmenu-text {
text-align: left;
padding: 0.4em 2.1em 0.4em 1em;
display: block;
line-height: 1.4;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js" integrity="sha256-tp8VZ4Y9dg702r7D6ynzSavKSwB9zjariSZ4Snurvmw=" crossorigin="anonymous"></script>
<p>
<label for="spinner">Select a value:</label>
<input id="spinner" name="value">
</p>
<label for="speed">Select a speed</label>
<select name="speed" id="speed">
<option>Slower</option>
<option>Slow</option>
<option selected="selected">Medium</option>
<option>Fast</option>
<option>Faster</option>
</select>
The first issue, 1.11.4 makes use of .menu('instance') which is not available to 1.10.4. In the code above, this was used on Line 145, and can be reverted to .data("ui-menu"); to compensate.
Second, when selecting an item, it triggered an error as item was undefined. This is alsos related to the above issue. Need to work on it more. Work in progress.

asp.net mvc 4 bootstrap jquery combobox autocomplete

I'm having problems with the rendering of combobox in my project.
The autocomplete functionality works correctly. But you can not click to select the items in the combobox. Also the items are badly formed, and a descriptive label appears at the bottom.
Print:
http://tinypic.com/r/2jebtau/8
View:
<div class="col-lg-10">
#Html.DropDownList("IdProcedimento", (IEnumerable<SelectListItem>)ViewBag.PriorityID, new { #class = "form-control", id = "combobox" })
</div>
Script:
(function ($) {
$.widget("custom.combobox", {
_create: function () {
this.wrapper = $("<span>")
.addClass("custom-combobox")
.insertAfter(this.element);
this.element.hide();
this._createAutocomplete();
this._createShowAllButton();
},
_createAutocomplete: function () {
var selected = this.element.children(":selected"),
value = selected.val() ? selected.text() : "";
this.input = $("<input>")
.appendTo(this.wrapper)
.val(value)
.attr("title", "")
.addClass("custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left")
.autocomplete({
delay: 0,
minLength: 0,
source: $.proxy(this, "_source")
})
.tooltip({
tooltipClass: "ui-state-highlight"
});
this._on(this.input, {
autocompleteselect: function (event, ui) {
ui.item.option.selected = true;
this._trigger("select", event, {
item: ui.item.option
});
},
autocompletechange: "_removeIfInvalid"
});
},
_createShowAllButton: function () {
var input = this.input,
wasOpen = false;
$("<a>")
.attr("tabIndex", -1)
.tooltip()
.appendTo(this.wrapper)
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass("ui-corner-all")
.addClass("custom-combobox-toggle ui-corner-right")
.mousedown(function () {
wasOpen = input.autocomplete("widget").is(":visible");
})
.click(function () {
input.focus();
// Close if already visible
if (wasOpen) {
return;
}
// Pass empty string as value to search for, displaying all results
input.autocomplete("search", "");
});
},
_source: function (request, response) {
var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
response(this.element.children("option").map(function () {
var text = $(this).text();
if (this.value && (!request.term || matcher.test(text)))
return {
label: text,
value: text,
option: this
};
}));
},
_removeIfInvalid: function (event, ui) {
// Selected an item, nothing to do
if (ui.item) {
return;
}
// Search for a match (case-insensitive)
var value = this.input.val(),
valueLowerCase = value.toLowerCase(),
valid = false;
this.element.children("option").each(function () {
if ($(this).text().toLowerCase() === valueLowerCase) {
this.selected = valid = true;
return false;
}
});
// Found a match, nothing to do
if (valid) {
return;
}
// Remove invalid value
this.input
.val("")
this.element.val("");
this._delay(function () {
this.input.tooltip("close").attr("title", "");
}, 2500);
this.input.data("ui-autocomplete").term = "";
},
_destroy: function () {
this.wrapper.remove();
this.element.show();
}
});
})(jQuery);
$(function () {
$("#combobox").combobox();
});
Try to add these files:
jquery-ui.css // this is for styling
jquery-1.10.2.js
jquery-ui.js"
And the following css classes are also required:
.custom-combobox {
position: relative;
display: inline-block;
}
.custom-combobox-toggle {
position: absolute;
top: 0;
bottom: 0;
margin-left: -1px;
padding: 0;
/* support: IE7 */
*height: 1.7em;
*top: 0.1em;
}
.custom-combobox-input {
margin: 0;
padding: 0.3em;
}
And check if "form-control" class is having efects.
You have downloaded this from here
Have you changed the paths of images(icons) which are being used by the plugins in CSS.

CKEditor not working after opening jQuery UI Dialog

I have a jQuery UI Dialog that has a CKEditor instance on it. I can open the dialog and interact fine with the editor. But if I open another jQuery UI dialog from the original dialog the text in the editor disappears when the second dialog opens and the editor can't be used until you reload the entire page.
This works fine if the CKEditor instance is not in a dialog. I can open up the child dialog, use it, close it, and still interact with editor.
Any ideas what is going on and how to make it work?
Sample program below or http://jsfiddle.net/3EyM4/1/
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ckeditor/4.3.2/ckeditor.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ckeditor/4.3.2/adapters/jquery.js"></script>
</head>
<body>
<script>
$(document).ready(
function()
{
$('textarea').ckeditor( { toolbar: [] } );
$( "#childDialog" ).dialog(
{
autoOpen: false
} );
$( "#parentDialog" ).dialog(
{
autoOpen: false
} );
});
</script>
<div>
Main page
<button onclick="$('#parentDialog').dialog( 'open' );">Open Parent</button>
</div>
<div id="parentDialog" title="Parent Dialog">
<button onclick="$('#childDialog').dialog( 'open' );">Open Child</button>
<textarea name="editorTextArea"></textarea>
</div>
<div id="childDialog" title="Child Dialog">
Child
</div>
</body>
</html>
You need to instantiate the CKEDITOR on the open event of the dialog
open: CKEDITOR.replace('editor1', {
height: 145,
width: 500,
allowedContent: true,
}),
Then is will allow text. Something to do with the Iframe that CKEDITOR uses
This will work fine
Check CKEditor intances than destroy it when dialog is closed. Enjoy your code
function DestryoCKEditorInstances(textarea_name)
{
if (CKEDITOR.instances[textarea_name])
{
CKEDITOR.instances[textarea_name].destroy();
}
}
$( "#add-task" ).dialog({
modal: true,
minHeight: 600,
minWidth: 600,
position: [0,28],
create: function (event) { $(event.target).parent().css('position', 'fixed');},
open: CKEDITOR.replace('textarea_name',{language: 'tr',height: 150,width: 550, allowedContent: true}),
close: function (){
DestryoCKEditorInstances('textarea_name');
form[ 0 ].reset();
},
buttons: {
"Add Task": function() {
Add();
form[ 0 ].reset();
$( this ).dialog( "close" );
},
"Keep Going To Add Task": function() {
Add();
form[ 0 ].reset();
},
Cancel: function() {
form[ 0 ].reset();
$( this ).dialog( "close" );
}
}
});
I found a workaround at least. If I save the contents of the editor and destroy the instance before opening the dialog, and then recreate the editor instance after opening the dialog, it all works fine.
var editor = $('textarea').ckeditorGet();
editor.updateElement();
editor.destroy();
$('#childDialog').dialog( 'open' );
$('textarea').ckeditor( { toolbar: [] } );
I had a similar problem loading text into ckeditor while it was inside a jquery ui dialog. I had 2 instances of ckeditor and an ajax post to get the data so my workaround was:
(...)
success: function(data, textStatus, jqXHR) {
for (name in CKEDITOR.instances) {
CKEDITOR.instances[name].destroy()
}
$('#newForm').dialog('open');
$("#dialog").focus();
$('#txtDescription').ckeditor({ toolbar: 'Basic' });
$('#txtDescriptionFr').ckeditor({ toolbar: 'Basic' });
CKEDITOR.instances['txtDescription'].setData(data.Description.NameEn);
CKEDITOR.instances['txtDescriptionFr'].setData(data.Description.NameFr);
}
To get around the Problems when having a CKEDITOR in a Jquery ui-dialog I did the following:
Problem 1:
Dropdowns like font-size etc. arent visible in ckeditor.
Solution:
config.baseFloatZIndex=9999999;
Problem 2:
Input Fileds in CKEDITOR Dialog arent "active".
Solution:
Close ui-dialog when ckeditor dialog opens and vice-versa
Problem 3:
Ckeditor dialog input fields arent "active" when ckeditor switches to fullscreen mode
Solution:
Close jquery ui-dialog when ckeditor is going to fullscreen, reopen when leaving fullscreen mode
My CKEDITOR jquery adapter now looks like this, works fine for me:
/*
Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.md or http://ckeditor.com/license
*/
(function(a) {
if ("undefined" == typeof a) throw Error("jQuery should be loaded before CKEditor jQuery adapter.");
if ("undefined" == typeof CKEDITOR) throw Error("CKEditor should be loaded before CKEditor jQuery adapter.");
console.error("CKEDITOR jQuery Team-pro adapter v0.4a");
CKEDITOR.config.jqueryOverrideVal = "undefined" == typeof CKEDITOR.config.jqueryOverrideVal ? !0 : CKEDITOR.config.jqueryOverrideVal;
a.extend(a.fn, {
ckeditorGet: function() {
var a = this.eq(0).data("ckeditorInstance");
if (!a) throw "CKEditor is not initialized yet, use ckeditor() with a callback.";
return a
},
ckeditor: function(g, d) {
if (!CKEDITOR.env.isCompatible) throw Error("The environment is incompatible.");
if (!a.isFunction(g)) {
var m = d;
d = g;
g = m
}
var k = [];
d = d || {};
this.each(function() {
var b = a(this),
c = b.data("ckeditorInstance"),
f = b.data("_ckeditorInstanceLock"),
h = this,
l = new a.Deferred;
k.push(l.promise());
if (c && !f) g && g.apply(c, [this]), l.resolve();
else if (f) c.once("instanceReady", function() {
setTimeout(function() {
c.element ? (c.element.$ == h && g && g.apply(c, [h]), l.resolve()) : setTimeout(arguments.callee, 100)
}, 0)
},
null, null, 9999);
else {
if (d.autoUpdateElement || "undefined" == typeof d.autoUpdateElement && CKEDITOR.config.autoUpdateElement) d.autoUpdateElementJquery = !0;
d.autoUpdateElement = !1;
b.data("_ckeditorInstanceLock", !0);
c = a(this).is("textarea") ? CKEDITOR.replace(h, d) : CKEDITOR.inline(h, d);
b.data("ckeditorInstance", c);
c.on("instanceReady", function(d) {
var e = d.editor;
e.config.baseFloatZIndex=9999999;
setTimeout(function() {
if (e.element) {
d.removeListener();
e.on("dataReady", function() {
b.trigger("dataReady.ckeditor", [e])
});
e.on("setData", function(a) {
b.trigger("setData.ckeditor", [e, a.data])
});
e.on("getData", function(a) {
b.trigger("getData.ckeditor", [e, a.data])
}, 999);
e.on("destroy", function() {
b.trigger("destroy.ckeditor", [e])
});
e.on("save", function() {
a(h.form).submit();
return !1
}, null, null, 20);
if (e.config.autoUpdateElementJquery && b.is("textarea") && a(h.form).length) {
var c = function() {
b.ckeditor(function() {
e.updateElement()
})
};
a(h.form).submit(c);
a(h.form).bind("form-pre-serialize", c);
b.bind("destroy.ckeditor", function() {
a(h.form).unbind("submit", c);
a(h.form).unbind("form-pre-serialize",
c)
})
}
e.on("destroy", function() {
b.removeData("ckeditorInstance")
});
/*
e.on("maximize", function (e) {
// console.log('---------------------------- MAXIMIZE ----------------------------');
// console.debug(e.data);
switch(parseInt(e.data)){
case(1)://Gehe in Fullscreen, SCHLIESSE Jquery ui Dialoge
console.log('CKEDITOR [maximize:true] jQuery adapter: schliesse ui-dialog');
$('.ui-dialog-content').dialog('close');
break;
case(2)://Gehe in Fullscreen, OFFNE Jquery ui Dialoge
console.log('CKEDITOR [maximize:false] jQuery adapter: öffne ui-dialog');
$('.ui-dialog-content').dialog('open');
break;
}
});
*/
b.removeData("_ckeditorInstanceLock");
b.trigger("instanceReady.ckeditor", [e]);
g && g.apply(e, [h]);
l.resolve()
} else setTimeout(arguments.callee, 100)
}, 0)
}, null, null, 9999)
}
});
var f = new a.Deferred;
this.promise = f.promise();
a.when.apply(this, k).then(function() {
f.resolve();
CKEDITOR.on("dialogDefinition", function (e) {
var dialogName = e.data.name;
var dialog = e.data.definition.dialog;
dialog.on('show', function () {
console.log('CKEDITOR [dialogdefinition:true] jQuery adapter: schliesse ui-dialog');
$('.ui-dialog-content').dialog('close');
});
dialog.on('hide', function () {
console.log('CKEDITOR [dialogdefinition:false] jQuery adapter: öffne ui-dialog');
$('.ui-dialog-content').dialog('open');
});
});
});
this.editor = this.eq(0).data("ckeditorInstance");
return this
}
});
CKEDITOR.config.jqueryOverrideVal && (a.fn.val = CKEDITOR.tools.override(a.fn.val, function(g) {
return function(d) {
if (arguments.length) {
var m =
this,
k = [],
f = this.each(function() {
var b = a(this),
c = b.data("ckeditorInstance");
if (b.is("textarea") && c) {
var f = new a.Deferred;
c.setData(d, function() {
f.resolve()
});
k.push(f.promise());
return !0
}
return g.call(b, d)
});
if (k.length) {
var b = new a.Deferred;
a.when.apply(this, k).done(function() {
b.resolveWith(m)
});
return b.promise()
}
return f
}
var f = a(this).eq(0),
c = f.data("ckeditorInstance");
return f.is("textarea") && c ? c.getData() : g.call(f)
}
}))
})(window.jQuery);
Also found this solution:
https://forum.jquery.com/topic/can-t-edit-fields-of-ckeditor-in-jquery-ui-modal-dialog

jQuery UI Sortable: no changing order of items while sorting

By default, while sorting, items are replaced (for example, if I take the third element and move it to the first, than the first and the second elements will move down)
I do not need this behaviour. I'd like elements not to change order while I finish sorting (release mouse).
I need this because I want to ask user if he want to change element or to re-order?
P.S. option tolerance have only 2 options, and they don't help in this situation.
I meant something like this (sortable list with option of replacing elements):
$(function() {
var
/**
* Sortable List, that can insert or replace elements
*/
SortableList = (function() {
var
// Configuration of Sortable list
// css classes of separator and sortable elements
// jQuery UI droppable and sortable init configuration
CONFIG = {
'confirm-message': 'Insert? Element will be removed',
'separator-class': 'sortable-separator',
'sortable-class': 'sortable-elem',
// Initialization of jQuery UI Droppable
'separators-droppable-init': {
drop: function(e, ui) {
// Insertation
var drag = ui.draggable,
drop = $(this),
a = drop.prev(),
b = drop.next();
Separators.clean();
Elements.insert(a, b, drag);
Separators.init();
},
over: function(e, ui) {
$(this).css({
'background-color': 'lightgreen'
});
},
out: function(e, ui) {
$(this).css({
'background-color': 'white'
});
}
},
'sortable-droppable-init': {
drop: function(e, ui) {
// Replace
var drag = ui.draggable,
drop = $(this);
if (Elements.replace(drop, drag)) {
Separators.init();
}
}
},
'sortable-draggable-init': {
revert: true,
start: function(e, ui) {
$(this).css({
'z-index': '999',
'cursor': 'move'
});
},
stop: function(e, ui) {
$(this).css({
'z-index': '1',
'cursor': 'default'
});
}
}
},
getSeparators = function() {
return $('.' + CONFIG['separator-class']);
},
getSortables = function() {
return $('.' + CONFIG['sortable-class']);
},
/**
* Separators Handler
*/
Separators = (function() {
var
// create separator html element
_create = function() {
return $('<div />').addClass(CONFIG['separator-class']);
},
// create all separators and insert them
createAll = function() {
getSortables().each(function() {
$(this).before(_create());
}).last().after(_create());
return Separators;
},
// remove all separators
clean = function() {
var s = getSeparators();
if (s.length) {
s.remove();
}
return Separators;
},
// init jQuery UI Droppable interface
initDroppable = function() {
getSeparators().droppable(CONFIG['separators-droppable-init']);
return Separators;
},
// Initialization of separators
init = function() {
if (getSeparators().length) {
Separators.clean();
}
return Separators.createAll().initDroppable();
};
// Return result
Separators = {
clean: clean,
createAll: createAll,
init: init,
initDroppable: initDroppable
};
return Separators;
}()),
Elements = (function() {
var
init = function() {
getSortables().droppable(CONFIG['sortable-droppable-init']).draggable(CONFIG['sortable-draggable-init']);
return Elements;
},
// replaces element A with element B
replace = function(A, B) {
if (!confirm(CONFIG['confirm-message'])) {
return false;
}
B.draggable("option", "revert", false).css({
top: 0,
left: 0
});
A.replaceWith(B);
return Elements;
},
// insert element C between elements A and B
insert = function(A, B, C) {
C.draggable("option", "revert", false).css({
top: 0,
left: 0
});
if (!A.length) {
B.before(C);
} else {
A.after(C);
}
return Elements;
},
// result to return
Elements = {
init: init,
replace: replace,
insert: insert
};
return Elements;
}()),
init = function() {
Separators.init();
Elements.init();
};
return {
init: init
};
}());
SortableList.init();
});
.sortable-elem {
width: 32px;
height: 32px;
background-color: darkred;
border: 1px solid brown;
color: white;
}
.sortable-separator {
width: 100px;
height: 16px;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<link href="//code.jquery.com/ui/1.8.16/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="//code.jquery.com/ui/1.8.16/jquery-ui.min.js"></script>
<div class="sortable-elem" data-order="1">1</div>
<div class="sortable-elem" data-order="2">2</div>
<div class="sortable-elem" data-order="3">3</div>
<div class="sortable-elem" data-order="4">4</div>
<div class="sortable-elem" data-order="5">5</div>
<div class="sortable-elem" data-order="6">6</div>
<div class="sortable-elem" data-order="7">7</div>
<div class="sortable-elem" data-order="8">8</div>
<div class="sortable-elem" data-order="9">9</div>
<div class="sortable-elem" data-order="10">10</div>
View on JSFiddle

Resources