jquery_ui menu ui parameter for dynamic sub-menu - jquery-ui

I am trying to create a dynamic sub-menu. For example, the top-level items are load and edit. Whenever the menu is focused, a get JSON is called and the result used to populate the possible items to load under the load menu item. However, the ui parameter for the select event handler no longer seems to correspond to the item clicked and calling ui.item.text() will instead return the entire text to the sub-menu.
HTML:
...
<ul id="menu">
<li><div>load</div><ul id="load"></ul></li>
<li><div>edit</div></li>
</ul>
...
javascript:
var load_populate = function ( json ) {
var ul = $( "#load" );
ul.empty();
for ( let item of json ) {
ul.append ( $( "<li>" ).append ( $( "<div>" ).text ( item.name ) ) );
}
};
var menu_focus = function ( event, ui ) {
$.getJSON ( load_options_url )
.done ( load_populate );
};
var menu_select = function ( event, ui ) {
console.log ( ui.item.text() );
};
$( "#menu" ).menu ({
"focus" : menu_focus,
"select" : menu_select
});
Clicking an item in the load sub-menu logs
loaditem1item2item3, etc.
Refreshing the menu did not work.
How do I go about this?

Here is an example based on your code.
Example Fiddle
This uses POST just to simulate the AJAX activity
https://jsfiddle.net/Twisty/qpky9ht1/53/
HTML
<ul id="menu">
<li>
<div>load</div>
<ul id="load">
</ul>
</li>
<li>
<div>edit</div>
</li>
</ul>
JavaScript
Adjusted to be more similar to your code.
$(function() {
function makeListItem(o, n) {
$(o).append("<li><div>" + n + "</div></li>");
}
$("#menu").menu({
focus: function(e, ui) {
console.log("FOCUS", e, ui.item);
if (ui.item.parent().is("#menu")) {
$.getJSON (load_options_url,
function(json) {
console.log("LOAD");
$("#load").empty();
$.each(json, function(i, m) {
console.log("ITEM", i, m);
makeListItem("#load", m.name);
});
$("#menu").menu("refresh");
});
}
},
select: function(e, ui) {
console.log("SELECT", ui.item);
}
});
});
This will gather the list data in focus and append them. Once this is done, refresh method is executed on the Menu. This will assimilate all the new list items into the menu. Since focus can be executed on all menu items, you want to ensure you are not rebuilding the menu while focusing on sub-menu items. Hence the if statement.

Related

jquery mobile data-lastval

I need help with an Intel XDK project.
After research I was succesfull to create an autocomplete form.
However, if the user do not select the value from filter list,
and enter the value manually, it is not saved to the variable.
It would be possible to select the value in "data-lastval".
Here is the code that appears in DOM. But with all the research I do, I cannot understand, how to fetch this content of data-lastval and put in into a variable. On selection of the list item it goes saved to a hidden input field and can be stored to localstorage. I need help in building this javascript or jquery mobile selector, like var xstreet = ...
"If"-logic will decide, that the hidden field was empty, and then put "xstreet" instead in this.
<div class="ui-input-search ui-shadow-inset ui-input-has-clear ui-body-e ui-corner-all">
<input data-type="search" placeholder="street" data-lastval="2323">
Clear text</div>
Code in src:
<div class="widget uib_w_15 form1widths labelwhite form1forms streetfield" data-uib="jquery_mobile/input" data-ver="0" id="streetfield"><input type="hidden" id="xd">
<ul class="autocomplete" data-role="listview" data-inset="true" data-filter="true"
data-filter-placeholder="street" data-filter-theme="e"></ul>
</div>
Code in the head:
<script>
$('#streetfield ul').listview();
var gcity = window.localStorage.getItem("city");
$(document).on( "pageinit", "#form", function() {
$(".autocomplete").on("listviewbeforefilter", function(e, data ) {
var $ul=$(this);
var value = $( data.input ).val();
var dropdownContent = "" ;
$ul.html("") ;
if ( value && value.length > 2 ) {
var response = ['data1','data2','data3'];
$('.autocomplete').show();
$ul.html( "<li><div class='ui-loader'><span class='ui-icon ui-icon-loading' ></span></div></li>" );
$ul.listview( "refresh" );
$.each(response, function( index, val ) {
dropdownContent += "<li>" + val + "</li>";
$ul.html( dropdownContent );
$ul.listview( "refresh" );
$ul.trigger( "updatelayout");
});
}
});
});
$(document).on( "click", ".autocomplete li", function() {
var selectedItem = $(this).html();
$(this).parent().parent().find('input').val(selectedItem);
$('.autocomplete').hide();
});
</script>
Well, nobody helped. I think, this may be the solution.
I found it in an other case.
var x = $(#id).attr('data-lastval')
maybe it can help somebody.

JQuery multiple select filter bug

I have a multiple select with a filter. Filtering works properly, but when you select a filtered item it does not change to the selected state (there is no tick in the box of the selected item).
I followed the instructions of the offical JQuery Mobile page. The only difference is that they do not use a multiple select. Is there a workaround to have the filter functionality with multiple select boxes?
JQuery Mobile filterable select
My select:
<form>
<div class="ui-field-contain">
<label for="title-filter-menu">Placeholder:</label>
<select id="title-filter-menu" multi data-native-menu="false" class="filterable-select">
<option>Select fruit...</option>
<option value="orange">Orange</option>
<option value="apple">Apple</option>
<option value="peach">Peach</option>
<option value="lemon">Lemon</option>
</select>
</div>
</form>
JS
( function( $ ) {
function pageIsSelectmenuDialog( page ) {
var isDialog = false,
id = page && page.attr( "id" );
$( ".filterable-select" ).each( function() {
if ( $( this ).attr( "id" ) + "-dialog" === id ) {
isDialog = true;
return false;
}
});
return isDialog;
}
$.mobile.document
// Upon creation of the select menu, we want to make use of the fact that the ID of the
// listview it generates starts with the ID of the select menu itself, plus the suffix "-menu".
// We retrieve the listview and insert a search input before it.
.on( "selectmenucreate", ".filterable-select", function( event ) {
var input,
selectmenu = $( event.target ),
list = $( "#" + selectmenu.attr( "id" ) + "-menu" ),
form = list.jqmData( "filter-form" );
// We store the generated form in a variable attached to the popup so we avoid creating a
// second form/input field when the listview is destroyed/rebuilt during a refresh.
if ( !form ) {
input = $( "<input data-type='search'></input>" );
form = $( "<form></form>" ).append( input );
input.textinput();
list
.before( form )
.jqmData( "filter-form", form ) ;
form.jqmData( "listview", list );
}
// Instantiate a filterable widget on the newly created selectmenu widget and indicate that
// the generated input form element is to be used for the filtering.
selectmenu
.filterable({
input: input,
children: "> option[value]"
})
// Rebuild the custom select menu's list items to reflect the results of the filtering
// done on the select menu.
.on( "filterablefilter", function() {
selectmenu.selectmenu( "refresh" );
});
})
// The custom select list may show up as either a popup or a dialog, depending on how much
// vertical room there is on the screen. If it shows up as a dialog, then the form containing
// the filter input field must be transferred to the dialog so that the user can continue to
// use it for filtering list items.
.on( "pagecontainerbeforeshow", function( event, data ) {
var listview, form;
// We only handle the appearance of a dialog generated by a filterable selectmenu
if ( !pageIsSelectmenuDialog( data.toPage ) ) {
return;
}
listview = data.toPage.find( "ul" );
form = listview.jqmData( "filter-form" );
// Attach a reference to the listview as a data item to the dialog, because during the
// pagecontainerhide handler below the selectmenu widget will already have returned the
// listview to the popup, so we won't be able to find it inside the dialog with a selector.
data.toPage.jqmData( "listview", listview );
// Place the form before the listview in the dialog.
listview.before( form );
})
// After the dialog is closed, the form containing the filter input is returned to the popup.
.on( "pagecontainerhide", function( event, data ) {
var listview, form;
// We only handle the disappearance of a dialog generated by a filterable selectmenu
if ( !pageIsSelectmenuDialog( data.prevPage ) ) {
return;
}
listview = data.prevPage.jqmData( "listview" ),
form = listview.jqmData( "filter-form" );
// Put the form back in the popup. It goes ahead of the listview.
listview.before( form );
});
})( jQuery );
CSS
.ui-selectmenu.ui-popup .ui-input-search {
margin-left: .5em;
margin-right: .5em;
}
.ui-selectmenu.ui-dialog .ui-content {
padding-top: 0;
}
.ui-selectmenu.ui-dialog .ui-selectmenu-list {
margin-top: 0;
}
.ui-selectmenu.ui-popup .ui-selectmenu-list li.ui-first-child .ui-btn {
border-top-width: 1px;
-webkit-border-radius: 0;
border-radius: 0;
}
.ui-selectmenu.ui-dialog .ui-header {
border-bottom-width: 1px;
}
I found out, that the right option is selected, but the shown selected state in the filtered list is wrong.
If you have the options
a1
b1
c2
d2
with an filter "1" you get
a1
b1
you can correctly select each of them.
If you filter "2"
you get
c2
d2
if you select c2 (which is the first option of the selected list and the third of the original list) jquerymobile tries to show selected state on the !third! option of the !filtered list". thats the bug.
However, with the basic filtered select example ist works (first one in http://view.jquerymobile.com/master/demos/selectmenu-custom-filter/)
Problem here: The filter bar (search input) is above the select Header (Closing icon + Label).

jQuery mobile autocomplete is not updating itself

I'm new to jQuery and jQuery mobile.
I'm trying to get an autocomplete field working. What I have so far is pretty much ripped right from the demo at http://demos.jquerymobile.com/1.4.5/listview-autocomplete-remote/
$( document ).on( "pagecreate", "#foo", function() {
$( "#autocomplete" ).on( "filterablebeforefilter", function ( e, data ) {
var $ul = $( this ),
$input = $( data.input ),
value = $input.val(),
html = "";
$ul.html( "" );
if ( value && value.length > 2 ) {
$ul.html( "<li><div class=\'ui-loader\'><span class=\'ui-icon ui-icon-loading\'></span></div></li>" );
$ul.listview( "refresh" );
$.ajax({
url: "/cgi/perl_script.pl",
data: \'search=\' + value,
dataType: "json",
traditional: true
})
.then( function ( response ) {
$.each( response, function ( i, val ) {
alert(JSON.stringify(val));
html += "<li>Just a test</li>";
});
$ul.html( html );
$ul.listview( "refresh" );
$ul.trigger( "updatelayout");
});
}
});
});
I have confirmed that json data is getting returned with the js alert. That's all working perferctly. If my perl script returns 3 json records, I get three alerts with the stringified JSON.
However, the records never get displayed by the widget even if I use a the simple "Just a test" string as shown here in my code as I try to debug the problem.
Here is the relevant html code:
<div role="main" class="ui-content">
<form class="ui-filterable">
<input id="autocomplete-input" data-type="search" placeholder="Last name">
</form>
<ul id="autocomplete" data-role="listview" data-inset="true" data-filter="true" data-input="#autocomplete-input"></ul>
See comments to the original post for the answer.

jQueryUI tooltip Widget to show tooltip on Click

How the new jQueryUI's tooltip widget can be modified to open the tooltip on click event on certain element's on document, while the others are still showing their tootip on mouseover event. In click-open case the tooltip should be closed by clicking somewhere else on the document.
Is this possible at all?
Using jqueryui:
HTML:
<div id="tt" >Test</div>
JS:
$('#tt').on({
"click": function() {
$(this).tooltip({ items: "#tt", content: "Displaying on click"});
$(this).tooltip("open");
},
"mouseout": function() {
$(this).tooltip("disable");
}
});
You can check it using
http://jsfiddle.net/adamovic/A44EB/
Thanks Piradian for helping improve the code.
This code creates a tooltip that stays open until you click outside the tooltip. It works even after you dismiss the tooltip. It's an elaboration of Mladen Adamovic's answer.
Fiddle: http://jsfiddle.net/c6wa4un8/57/
Code:
var id = "#tt";
var $elem = $(id);
$elem.on("mouseenter", function (e) {
e.stopImmediatePropagation();
});
$elem.tooltip({ items: id, content: "Displaying on click"});
$elem.on("click", function (e) {
$elem.tooltip("open");
});
$elem.on("mouseleave", function (e) {
e.stopImmediatePropagation();
});
$(document).mouseup(function (e) {
var container = $(".ui-tooltip");
if (! container.is(e.target) &&
container.has(e.target).length === 0)
{
$elem.tooltip("close");
}
});
This answer is based on working with different classes. When the click event takes place on an element with class 'trigger' the class is changed to 'trigger on' and the mouseenter event is triggered in order to pass it on to jquery ui.
The Mouseout is cancelled in this example to make everything based on click events.
HTML
<p>
<input id="input_box1" />
<button id="trigger1" class="trigger" data-tooltip-id="1" title="bla bla 1">
?</button>
</p>
<p>
<input id="input_box2" />
<button id="trigger2" class="trigger" data-tooltip-id="2" title="bla bla 2">
?</button>
</p>
jQuery
$(document).ready(function(){
$(function () {
//show
$(document).on('click', '.trigger', function () {
$(this).addClass("on");
$(this).tooltip({
items: '.trigger.on',
position: {
my: "left+15 center",
at: "right center",
collision: "flip"
}
});
$(this).trigger('mouseenter');
});
//hide
$(document).on('click', '.trigger.on', function () {
$(this).tooltip('close');
$(this).removeClass("on")
});
//prevent mouseout and other related events from firing their handlers
$(".trigger").on('mouseout', function (e) {
e.stopImmediatePropagation();
});
})
})
http://jsfiddle.net/AK7pv/111/
I have been playing with this issue today, I figured I would share my results...
Using the example from jQueryUI tooltip, custom styling and custom content
I wanted to have a hybrid of these two. I wanted to be able to have a popover and not a tooltip, and the content needed to be custom HTML. So no hover state, but instead a click state.
My JS is like this:
$(function() {
$( document ).tooltip({
items: "input",
content: function() {
return $('.myPopover').html();
},
position: {
my: "center bottom-20",
at: "center top",
using: function( position, feedback ) {
$( this ).css( position );
$( "<div>" )
.addClass( "arrow" )
.addClass( feedback.vertical )
.addClass( feedback.horizontal )
.appendTo( this );
}
}
});
$('.fireTip').click(function () {
if(!$(this).hasClass('open')) {
$('#age').trigger('mouseover');
$(this).addClass('open');
} else {
$('#age').trigger('mouseout');
$(this).removeClass('open');
}
})
});
The first part is more or less a direct copy of the code example from UI site with the addition of items and content in the tooltip block.
My HTML:
<p>
<input class='hidden' id="age" />
Click me ya bastard
</p>
<div class="myPopover hidden">
<h3>Hi Sten this is the div</h3>
</div>
Bacially we trick the hover state when we click the anchor tag (fireTip class), the input tag that holds the tooltip has a mouseover state invoked, thus firing the tooltip and keeping it up as long as we wish... The CSS is on the fiddle...
Anyways, here is a fiddle to see the interaction a bit better:
http://jsfiddle.net/AK7pv/
This version ensures the tooltip stays visible long enough for user to move mouse over tooltip and stays visible until mouseout. Handy for allowing the user to select some text from tooltip.
$(document).on("click", ".tooltip", function() {
$(this).tooltip(
{
items: ".tooltip",
content: function(){
return $(this).data('description');
},
close: function( event, ui ) {
var me = this;
ui.tooltip.hover(
function () {
$(this).stop(true).fadeTo(400, 1);
},
function () {
$(this).fadeOut("400", function(){
$(this).remove();
});
}
);
ui.tooltip.on("remove", function(){
$(me).tooltip("destroy");
});
},
}
);
$(this).tooltip("open");
});
HTML
Test
Sample: http://jsfiddle.net/A44EB/123/
Update Mladen Adamovic answer has one drawback. It work only once. Then tooltip is disabled. To make it work each time the code should be supplement with enabling tool tip on click.
$('#tt').on({
"click": function() {
$(this).tooltip({ items: "#tt", content: "Displaying on click"});
$(this).tooltip("enable"); // this line added
$(this).tooltip("open");
},
"mouseout": function() {
$(this).tooltip("disable");
}
});
jsfiddle
http://jsfiddle.net/bh4ctmuj/225/
This may help.
<!-- HTML -->
Click me to see Tooltip
<!-- Jquery code-->
$('a').tooltip({
disabled: true,
close: function( event, ui ) { $(this).tooltip('disable'); }
});
$('a').on('click', function () {
$(this).tooltip('enable').tooltip('open');
});

JQuery UI selectable : Preselecting list item

I am trying to implement the click of the first item of the selectable list.I can add the CSS
but unable to get the click event working when i try to pre select the first item (I need the click since ,onclick event has an ajax call to populate related information on another div..)
I even tried to use the the trigger method , but couldnt get this working on the fist item on the list. The code is standard stuff.
<ol id="selectable">
<li class="ui-widget-content">Item 1</li>
<li class="ui-widget-content">Item 2</li>
<li class="ui-widget-content">Item 3</li>
<li class="ui-widget-content">Item 4</li>
<li class="ui-widget-content">Item 5</li>
<li class="ui-widget-content">Item 6</li>
<ol>
Jquery function
$(function() {
$( "#selectable" ).bind("mousedown", function (e) {
e.metaKey = false;
}).selectable({
selected: function(event, ui) {
alert("selected");
},
stop: function() {
var result = $( "#select-result" ).empty();
$( ".ui-selected", this ).each(function() {
var index = $( "#selectable li" ).index( this );
result.append( " #" + ( index + 1 ) );
});
}
});
});
I can apply the css to the first list item like this
$('li:first-child').select().addClass("ui-selected");
But i cant get the click function to work (The click would invoke the 'selected' anonymous call back.) Any pointers would be helpful/.
After some trying i managed to get it working.Posting the solution as it may be useful.
I want to simulate the mouse click on the first item on the selectable list.For that we first need to bind
$( "#selectable" ).bind( "selectableselected", function(event, ui) {
$( ".ui-selected", this ).each(function() {
var index = $( "#selectable li" ).index( this );
alert("test");
});
});
Once you do that we need to fire the click.I put this in the create callback which is called as soon as the selectable is formed.
create: function(event, ui) {
setTimeout( function() {
$('li:firstchild').addClass("uiselected").trigger('selectableselected');
}, 100 );
the great thing about Jquery is that its so intutive.

Resources