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).
Related
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.
I have a Kendo MVC DatePicker as belowed, it will render as a textbox with a button (with calendar icon) within it which can trigger the date picker UI.
In my scenario, I need to insert a button to clear the value of the textbox, just on the left of the calendar button.
What my problem is that, is it possible (and how can I) insert another custom button inside the textbox rendered?
<div class="col-md-2 ">
#(Html.Kendo().DatePicker()
.Name("InspecitonDate")
.Value(DateTime.Now.AddMonths(-3)).Format("dd/MM/yyyy")
.HtmlAttributes(new { style = "width: 100%" })
)
</div>
Kendo date picker adds attribute data-role so select all the controls through jQuery on page with attribute data-role = datepicker
<script>
$(document).ready(function () {
var dt = $("[data-role='datepicker']");
//For each control insert an icon button calling js function clearDate to clear date input
$.each(dt,
function (i, d) {
$("#" + d.id).before("<span class='fa fa-times' onclick=\"clearDate('" + d.id + "')\"></span>");
});
});
function clearDate(inputId) {
$("#"+inputId).data("kendoDatePicker").value(null);
}
I would suggest to write this code in some common js file so that all kendo date controls in every page can be changed. You may add some style too to move icon to right
.k-picker-wrap > span.fa-times {
position: absolute;
right: 35px;
top: 8px;
color:#01ace4;
cursor: pointer;
}
There is no such built-in option, so you need to do it yourself. So you need to append the needed extra button on document.ready
I'm trying to use panel on each different HTML pages.
And I got this sample panel JS code on JQM website.
/* panel */
$( document ).on( "pageinit", "#demo-page", function() {
$( document ).on( "swipeleft swiperight", "#demo-page", function( e ) {
// We check if there is no open panel on the page because otherwise
// a swipe to close the left panel would also open the right panel (and v.v.).
// We do this by checking the data that the framework stores on the page element (panel: open).
if ( $.mobile.activePage.jqmData( "panel" ) !== "open" ) {
if ( e.type === "swipeleft" ) {
$( "#right-panel" ).panel( "open" );
} else if ( e.type === "swiperight" ) {
$( "#left-panel" ).panel( "open" );
}
}
});
});
The problem is if I want to put panel on each different HTML pages, How do I have to set the page ID ?
For example, I have HTML pages such as.....
main.html page ID is "#pageMain" , about.html page ID is "#pageAbout", and gallery.html page ID is "#gallery"
How do I have to fix JS code ? Please help~
The code you have is for adding the ability to open panels via swipe gestures. It won't add the panel into the DOM alongside your page content. To do that you'll need to adapt the following code.
/* Creates the functionality to open the left side panel with a swipe */
$(document).one("pagebeforecreate", function () {
$.get('left-panel.html', function(data){
//$(data).prependTo($.mobile.pageContainer); //or .prependTo("body");
$.mobile.pageContainer.prepend(data);
$("[data-role=panel]").panel().enhanceWithin(); // initialize panel
}, "html");
In my PhoneGap app I have a form page in which there is a contacts button. When the user clicks it the contacts page appears to select a contact and then returns to the form to submit it. In the JSFiddle when returning to the form the entered data still in the form, but in my app when I return to the form all the entered data has been removed so the user needs to fill the form again.
How can I keep the entered form data in the fields when returning to it from the contacts page?
When the user clicks the done button in the contacts page I use this code to pass the selected data to the formPage.
JSFiddle
$('#Done').on('click', function(){
$.mobile.changePage('FormPage.html', {
dataUrl: 'FormPage.html?paremeter=' + selectedContact + ' ',
data: {
'paremeter': '' + selectedContact + ''
},
reloadPage: false,
changeHash: false
});
});
You can use a popup instead of a separate page.
Here is your updated FIDDLE
Your page 2 is now a popup within the first page. It includes a DIV that is scrollable and a listview which is dynamically populated with 100 items:
<div data-role="popup" id="page2" data-position-to="window">
<div id="scrollDiv">
<ul data-role="listview" id="contactsList">
</ul>
<div>
</div>
#scrollDiv{
max-height: 450px;
width: 300px;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
On pageinit I add 100 contacts and then creat a click handler for the contacts that writes the selected contact id back to a field in the form and closes the popup:
$(document).on("pageinit", "#FormPage", function(){
var contactsList;
for (var i = 0; i< 100; i++){
contactsList += '<li>contact ' + i + '</li>';
}
$("#contactsList").append($(contactsList));
$("#contactsList").listview("refresh");
$(".contactLink").on("click", function(){
var msg = 'you selected contact: id = ';
msg += $(this).data("contactid");
$("#selContact").val(msg);
$("#page2").popup( "close" )
});
});
I am new to jQuery and I am working with the droppable API.
I want to have a group of divs that can all hold one and only one droppable item. I've set the class of my droppable divs to inv. I can drop items into the divs but I can find a way to reject a drop once in the drop function.
I want to be able to detect that my div already has a child and if it does revert the dopped element.
my code currently looks like this
$( "div.inv" ).droppable(
{
drop: function( event, ui )
{
childCount = $(this).children().length;
if (childCount !=0)
{
//revert droppable to initial position
return;
}
//if there is a child revert and return
$( this )
.addClass( "ui-state-highlight" )
.append($(ui.draggable))
}
});
What about disabling the droppable area after receiving an item ?
You can do something like this :
$( "div.inv" ).droppable(
{
drop: function( event, ui ) {
$(this).droppable('disable');
}
});