FastClick interfering with jQuery UI Selectmenu on touch - jquery-ui

I'm trying to implement a jQuery UI Selectmenu while using FastClick. Tapping one of the entries of the selecmenu's dropdown list is not registering on touch, closing the list without actually selecting the tapped list item. To remedy this, I'm using bind() to add the class .needsclick to the jQuery UI elements when they are created (as recommended in this answer). This is supposed to ensure that FastClick is not applied to the problematic elements.
Unfortunately, the class is only added once I've opened and closed the menu once, so it only works on the second attempt to select a list item, even though the elements are inserted the moment the page is loaded. How can I ensure it's added the moment the element is inserted by jQuery UI?
Here's a working CodePen that demonstrates the issue: http://codepen.io/dahdah/pen/qbePZK
JavaScript:
$(document).ready(function() {
/* global FastClick */
$(function() {
FastClick.attach(document.body);
});
$('#filetype').selectmenu({
width: '100%'
});
// Fix for FastClick breaking jQuery UI on mobile
$('body').bind('DOMNodeInserted', function() {
$(this).find('.ui-menu-item').addClass('needsclick');
});
});
HTML:
<select id="filetype">
<option selected=**strong text**"">Filetype</option>
<option value="doc">DOC</option>
<option value="pdf">PDF</option>
<option value="html">HTML</option>
</select>

So after some more research, it turns out that "jQuery does not get involved with node insertion events". A suggestion would be to try DOM MutationOberserver, but that's opening a whole can of worms for something that should be quick and simple.
I've solved my problem by listening for clicks on the element that jQuery UI creates to replace native elements like <select> and then adding .needsclick to the inserted list items:
$('.ui-widget').on('click', function(e) {
$('.ui-menu-item').addClass('needsclick');
});
It needs to be done this way because the list items are only created after .ui-widget has been clicked.

Related

Always Display jQuery UI Date Picker on Input

I need to set up two jQuery UI date pickers to always be displayed. I know there's an easy way to do this with DIVs, but I can't find anything on how to do it for inputs. I've tried the "show" method in the jQuery UI documentation, but that just acts as a click on the input on page load, which isn't what I'm looking for.
I just tested the code below and it always remains on the page. You will need to handle the selection/click events by passing options the datepicker in the javascript. I added the JS for when the user selects a date... that should give you enough to go off of.
HTML:
<div id="test"></div>
<input type="text" id="date_input">
Javascript:
$('#test').datepicker({
onSelect: function(date, obj){
$('#date_input').val(date); //Updates value of of your input
}
});

jQuery live() and Tablesorter - does not work for 1st click

Here's the thing: file a.php contains jQuery Tablesorter table.
This is the Tablesorter code:
$("#feedsTable thead").live("click", function() {
$("#feedsTable").tablesorter({
widthFixed : true,
dateFormat : "uk",
}).tablesorterPager({
container : $("#pager"),
positionFixed : false
});
});
Slightly stripped table HTML code:
<div id="tablica">
<article class="module width_full">
<div id="pager">
<form>
[snip]tablesort pager stuff...
</form>
</div>
<table id="feedsTable" class="tablesorter" cellspacing="0">
<thead>
<tr>
[snip]table header row...
</tr>
</thead>
<tbody> ... PHP printed table data
Also, file a.php contains refresh link, which, when clicked, calls b.php file which contains following code: $("#tablica").load("a.php #tablica"); (basically, b.php prints table with new elements and then replaces the old table with the new one using the load function).
Of course, I must use either jQuery live or delegate (having some kind of problems with this one, just can't get Tablesorter to work, so I'm using live instead) function instead of (document).ready because once the load code is executed, Tablesorter will not work with the new table data.
But the problem is that when I use jQuery live() function, I need to click twice to be able to use the Tablesorter plugin. It's like the first click only "activates" the plugin, and then, when table header is clicked for 2nd time, table is sorted and it works great.
In a.php, I can add this code
$(document).ready(function() {
$("#feedsTable thead").click();
});
and it will "activate" the plugin and first user's click on the table header will sort the table. But if I add $("#feedsTable thead").click(); to the b.php file and click refresh link, this "hack" does not work, and again two clicks are needed to be able to use Tablesorter plugin after the table with new data is loaded.
Basically, the question is: I would like Tablesorter to work on first click when using jQuery live, and not only on second. How to fix that?
Any help would be much appreciated!
Thanks.
"of course, I must use either jQuery live or delegate"
http://api.jquery.com/live/:
As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().
Try on() and see if it makes much of a difference. If it doesn't then something else is at play.
So, delegate won't work because it is targeting the table inside of #tablica which has all of its contents completely replaced by the load function. Delegate needs an "anchor" element to detect a bubbling event whereas live uses the document, I think. So, the way it is written, when the user clicks anywhere in the thead, tablesorter will initialize. Now a second click will actually sort the column because tablesorter is active.
Anyway, the solution would be to initialize tablesorter within the load callback function. So remove the live function completely and try just this:
$("#tablica").load("a.php #tablica", function(){
$("#feedsTable").tablesorter({
widthFixed : true,
dateFormat : "uk",
}).tablesorterPager({
container : $("#pager"),
positionFixed : false
});
});
Now when the user clicks on the table header it will sort because tablesorter is initialized immediately after the content is loaded.

jQuery Mobile breaks my site

I load jQuery Mobile on my site when I am only on a mobile touchscreen device. When I do though. It messes up everything. For example, select menus don't work quite right, as well, the words "loading, loading, undefined" appear at the bottom of the page. I know I am missing something but do not know what.
Any ideas on what I could be missing?
Thanks
EDIT: Okay, So I took out all scripts that I am running except for jQuery and jQuery Mobile. I call jQuery first, then jQuery Mobile. It still breaks aspects of the site.
What it breaks:
- I cannot navigate to any other page via the navbar, if I click on a nav item, and look in the url, the correct url appears (with a # in it) like: /#/about-us/ Then, it just redirects to the home page and the page goes white
Select menus have weird results. It prints out whatever is in the select right beside it. And if you in landscape mode on the ipad and you click on the select, it sends you to the bottom of the page (weird).
it prints out 'loading' twice and 'undefined' once at the bottom of the page
All I have for scripts are jQuery and jQuery Mobile. I should also mention that I am using wordpress so it might have enqueued some other scripts (I have deregistered Wordpress' version of jquery and enqueued my own)
Anyone else experiencing these problems?
jQueryMobile replace your normal links with Ajax one, so every page can be loaded by the ajax, text on docs page:
(..) Ajax is used to load the contents of each page into the DOM as you navigate, and the DOM ready handler only executes for the first page. To execute code whenever a new page is loaded and created, you can bind to the pageinit event. This event is explained in detail at the bottom of this page.
If you want to disable single link to be loaded by the ajax you should write something like this:
<a href="/some_page" data-ajax="false" >link</a>
or do it globally:
$(document).bind("mobileinit", function() {
$.mobile.ajaxEnabled = false;
});
jm also does replacement on other elements so you should try using data-role attribute, for example:
<select id="test" data-role="none">
to disable replacing this element.
For those like me where
$.mobile.ajaxEnabled = false;
did not work and the whole page layout seems still broken:
For me this one works (- set it inline before loading the jquery mobile file):
<script>
// Preload configuration
$( document ).on( "mobileinit", function() {
$.mobile.autoInitializePage = false; // This one does the job
});
</script>
Furthermore if you want to disable jQuery mobile automatic link and form handling via ajax, set (as dvk3 said) ajaxEnabled to false and pushStateEnabled to false as recommended:
$.mobile.ajaxEnabled = false;
$.mobile.pushStateEnabled = false; // Recommended is false, when ajax is disabled
For further information see: http://api.jquerymobile.com/global-config/
I'm using v1.4.5
Same happened to me by mixing mobile with other frameworks. Fixed issue but getting custom build of jQuery.mobile. My case was that I needed swipe for touch devices only so used custom min file and nothing was broken after that.
It really depends if you need jQuery.mobile or you need just a certain functionality, Widgets, events? Use custom version that you can build yourself.
You can make and download yours here : http://jquerymobile.com/download-builder/
I hope it worked for you too guys!

Controlling the DOM location of a jquery UI dialog

I'm trying to create a jQueryUI Dialog and have it insert itself into the dom within a specific element. We have a content section that is the parent of a number of styles so items within the dialog are not styled since jqueryUI does an append to body. Is there a way to tell jqueryUI to append to a selector of my choosing?
What it does
<section id="content">
</section>
<div class="dialog"> the dialog </div>
what I want
<section id="content">
<div class="dialog"> the dialog </div>
</section>
I know this question is a little old but I wanted to make sure any new comers were pointed in the right direction. The option "appendTo" was added in version 1.10.0.
$( ".selector" ).dialog({ appendTo: "#someElem" });
You can read about it here
From Custom CSS scope and jQuery UI dialog themes
// Create the dialog, but don't open it yet
var d = $('#myDialogContents').dialog({
autoOpen: false
// other dialog options
});
// Take whole dialog and put it back into the custom scope
d.parent('.ui-dialog').appendTo('.myCustomScope');
// Open the dialog (if you want autoOpen)
d.dialog('open');
This link maybe of some use.
But the thing you'd like to achieve seems to me a bit against the model of jQuery UI library. You can style the dialog using the CSS classes specified in the Theme tab on this page.
If you can transfer the id of the element, you want to make into a dialog, to a class, you can use the following code
$( ".dialog" ).dialog({ dialogClass: 'content' });
and you should update your CSS to reflect the change. Thus you do not introduce duplicate id-s (which may lead to problems in future work and is semantically incorrect), if you duplicate the #content tag inside the dialog content
You can use jquery's append method.
$('#content').append('<div class="dialog"> the dialog </div>');

not understanding event-delegation with jquery ui tabs

I'm just not getting event delegation with jquery ui tabs, or at all!
I got the code for jquery ui tabs and loading the pages with ajax working perfectly. However I'm having trouble understanding event-delegation. I load 4 tabs with external content, depending on the tab which is opened. Inside those tabs I would like to attach the same widgets to the input buttons and links. So far my code looks like this
JS for rest of page already loaded
$("button, input:submit, a", ".create_button").button();
$("a.edit_button").button({
icons: {primary: 'ui-icon-pencil'}
});
$("a.delete_button").button({
icons: {primary: 'ui-icon-circle-close'}
});
$("a.active_button").button({
icons: {primary: 'ui-icon-lightbulb'}
});
JS For Tabs:
<script type="text/javascript">
$(document).ready(function() {
$("#tabs").tabs({
ajaxOptions: {error: function(xhr, status, index, anchor)
{$(anchor.hash).html("Could not load");}},
selected: 0})
});
</script>
HTML
<div id="tabs">
<ul>
<li>Pass Information</li>
<li>Entries</li>
<li>Event Administration</li>
<li>Profile</li>
</ul>
</div>
I've learned here on stack overflow that I have to attach a click event to my #tabs div with live(). Best guess anyway.
however I cannot find any examples that work for me and my limited understanding of event delegation.
Any help is appreciated.
Rick
Right now, you have "error" being handled, but nothing else. You need to handle "success" or "complete"... actually, why are you using AJAX at all? You don't appear to be requesting any data from off of the page?
It seems like the key to your question is this:
Inside those tabs I would like to attach the same widgets to the input buttons and links.
Sounds like you want to use the "show" method of the tabs widget:
$(document).ready(function() {
$("#tabs").tabs({
ajaxOptions: {error: function(xhr, status, index, anchor)
{$(anchor.hash).html("Could not load");}},
selected: 0,
show: function() {
$([selectors for buttons or jQuery UI widgets in your tabs]).button();
}
})
});
FWIW, this question is not really about event delegation. That article is useful in understanding the concept.
Turns out that .live() only works on events. So though I could bind something to the links, it would not actually take affect until the link has an event take place, i.e. click or hover.
A workaround would be to dynamically add events to the links with the loaded content, but that is quite tricky and adds a lot of overhead to the application. Instead I chose to style things within loaded content in a different way. In the process of learning about this, I did end up using live() for form submission and a reload of the content after the submission takes place.
Thanks guys for your help. RwL. You ended up not actually answering the question, but your prodding sent me in the right direction and I learned a lot. I was ultimately able to solve the problem myself. You know, give a man fish or teach him to fish, yadi yadi yadi...
Thanks!

Resources