What's the appropriate way to attach button click events in jQuery Mobile for different pages? - jquery-mobile

I tried this solution but apparently, I still get ghost clicks with it.
For example, I'm using the following code inside page1.html:
<script type="text/javascript">
$(document).on('pageinit', '.ui-page',function(){
$("#someButtonForPage1").click(function(){
$.mobile.changePage("page2.html");
});
});
</script>
Then on page 2, I have the following:
<script type="text/javascript">
$(document).on('pageinit', '.ui-page',function(){
$("#someButtonForPage2").click(function(){
$.mobile.changePage("page1.html");
});
});
</script>
As for the pages, they merely contain a header, a content body (with the button element inside) and a footer. What happens is clicking on the buttons will make the page transition to each other at least a couple of times. Meaning I still get ghost clicks.
What will absolutely fix this?

This is a common jQuery mobile problem. Before you bind a event on anything you need to check if that event is already bind to that element. For example, button with the 2 click/tap events on it will execute wanted action 2 times.
Here you will find my answer to same question.
My first example uses Event filter, and you can find it here, example is here.

Related

How to obtain an always fixed header in jQuery Mobile?

I have implemented a fixed header in jQuery Mobile, and it's working great for the most part. When I scroll, the toolbar remains visible. When I tap the screen, the header does not disappear. Great. The only annoyance I see is that when you tap into an input field that's towards the bottom of the page, the header then reverts to position:static so it disappears. You can see that by scrolling back up to the top. Once you unfocus the input box (hit done on the keyboard), then it goes back to position:fixed. I would like it to always be visible no matter what.
<div data-role="header" data-position="fixed">
I'm using jQM 1.4.0 RC1 and in the change log it states:
- Fixed Toolbars are now an extension on the toolbar widget
Sounds relevant, but I'm not sure what exactly that means.
Thanks. :)
This actually a fix for many issues raised on fixedtoolbar widget.
Issue #4410
Issue #4724
jQM hides fixed toolbars once focus is triggered on select, textarea and select; to give more working place when screen width less than 1025.
I have tried the below solution but the results were ugly.
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
$(document).on("mobileinit", function() {
$.mobile.toolbar.prototype.options.hideDuringFocus = "";
});
</script>
<script src="http://code.jquery.com/mobile/1.4.0-rc.1/jquery.mobile-1.4.0-rc.1.min.js"></script>
For more details, check fixedToolbar.js widget on GitHub, go to line 243.
Demo (1)
(1) To be tested on Mobile browsers, not desktop.

jQuery Mobile - preventDefault() on button (link)

I'm developing jQuery Mobile (jQm) app.
I wanna utilize taphold event to some crucial elements, such as remove button, to assure, that this element is secured from unwanted trigger.
I created Remove button on jQm popup and aded some JS to it, but I cannot force default action to quit, not with event.preventDefault() and event.stopImmediatePropagation(), nor with return false.
I prepared jsFiddle as duplicate of my code. The popup there contains simple progress bar as indicator of holded tap. You can try it here: jsFiddle (note: HTML5 data tag taphold="true" is not jQm default)
As a workaround, I'm currently replacing <a href="#" data-role="button"...></a> with <div>styled like button. This works well, since it doesn't have any default action, but I'm curious why the "proper" solution doesn't work?
$("a:jqmData(taphold='true')").bind("vmousedown vmouseup", function(event) {
event.preventDefault();
event.stopImmediatePropagation();
The event.preventDefault(); and event.stopImmediatePropagation(); used in the above piece of code, refer to the vmousedown and vmouseup events and not to every event which is bound to the selected element(s).
This means that the default behaviour for the click event still exists. So when you click the remove button, the click event is triggered and that's why the pop up closes immediately.
I hope this helps.

jQuery Mobile - scroll to specific div on pageload

I would like to automatically scroll to a particular div when the page loads. However, I seem to get into some conflict with JQM's scroll to top functionality.
I am using the following code:
$.mobile.silentScroll($("#myElementId").offset().top);
which does not scroll correctly when wrapped like this:
$('[data-role=page]').bind("pageshow", function() {
$.mobile.silentScroll($("#myElementId").offset().top);
});
but works correctly with a little timeout like this:
$('[data-role=page]').bind("pageshow", function() {
setTimeout(function(){$.mobile.silentScroll($("#myElementId").offset().top);},100);
});
the problem with the last piece of code is that it causes a flicker, with a jump to the top and then a jump down the page. Any ideas how to avoid this?
Your setTimeout works because the jQuery Mobile framework remembers where you were scrolled-to if you are returning to a page you've been to before and you have to wait for their scroll to complete before running your own. You can essentially disable this feature by changing the minScrollBack option inside the mobileinit event handler to something really big:
<script src="[jQuery Core]"></script>
<script>
$(document).bind("mobileinit", function(){
$.mobile.minScrollBack = 90000;
});
</script>
<script src="[jQuery Mobile]"></script>
That should disable the auto-scroll that the jQuery Mobile framework does when you visit a page on a subsequent visit.
Docs: http://jquerymobile.com/demos/1.0.1/docs/api/globalconfig.html
First post on StackOverflow!
Thanks for this, I have been working on a project that uses quite a bit of custom animation for the transitions and while it took a while to get here, Jasper's answer set me in the right direction, it was just missing a bit of code:
<script src="[jQuery]"></script>
<script>
$(document).bind("mobileinit", function(){
$.extend($.mobile, {
minScrollBack: 90000 // turn off scrolling to position on last page
});
});
</script>
<script src="[jQuery mobile]"></script>
This seemed to do the trick!
Ref: http://jquerymobile.com/test/docs/api/globalconfig.html
You guys ever tried the answer???
It does not work unless you set $.mobile.defaultHomeScroll to your wanted scroll as well.
That is, two steps.
1. set $.mobile.minScrollBack to a large enough value.
2. at page load, set the defaultHomeScroll to desired value.
Then it works.
I did not have to do much ... I got it working with the following on the section.
<script>$(function() {$.mobile.defaultHomeScroll = $(window).scrollTop();});</script>

How to navigate back one page using $.mobile.changePage

All of the JQuery Mobile documentation I can find about navigating backwards assumes I am going to do this using an anchor tag and suggest I add data-rel="back" to the tag.
I'm not navigating from a tag, I'm mixing with PhoneGap which means I'm calling javascript functions like PhoneGap.something(goForwardOnSuccess,goBackwardsOnFailure);
where
function goFowardOnSuccess()
{
$.mobile.changePage('#next', { transition: 'pop' });
}
function goBackwardOnFailure()
{
$.mobile.changePage(/* I HAVE NO IDEA WHAT GOES HERE */);
}
One of the main things I'm using this sort of thing for is putting up a "Busy Doing Something In Native Code Don't Touch Me..." click shield screen with the "loading" stuff and then closing it in the completion functions.
However, I find when I try that from a button on a screen I "popped" into place, I find myself back at the home page (goes back two levels).
The documentation is maddeningly vague about how to navigate backwards from pure javascript. Any clues would be very nice.
Notice also that I tend to pop these busy screens from everywhere so explicitly coding a transition back to the screen I want isn't really an option.
It's definitely not clear in the documentation, but there are small allusions to it.
Try using:
$.mobile.back();
it makes sense to use data-rel="back" for something like that:
<a href="#" data-rel="back" ...
but it is better to use history.back(); inside javascript code blog i.e
.....
.....
var cId = $(this).val();
// do something with control ID then
.....
.....
goBackParent();
}
function goBackParent(){
history.back();
}
Why not just use data-rel="back" as an attribute to your back button, this will take the user back 1 page.
Also equivalent to history.back()
You are going back "two levels" because if you fire changePage programmatically via
$.mobile.changePage('#next', { transition: 'pop' });
and omit all the other options, you are triggering two functions:
changePage
hashChange
Normally on a regular transition, the hashChange is blocked, while on backwards transitions, the changePage should be blocked (not sure here...). So in your case you have your (wanted) hashChange and an unwanted (changePage) transition.
Check the JQM docs for the options you can pass along in your changePage call or look in the 1.0 source code #3140 for all available options. I would try also passing changeHash:false or fromHashChange:true along in your function call and see what happens.
If you want to dig deeper you will have to look for ignoreNextHashChange and how its value changes though JQM.
A call to history.back() will do that.
Add changeHash: true from where you are redirecting.
And then use 'history.back()' or 'history.go(-1)' from your current page. It will only take you 1 page back.
$.mobile.changePage("yourpage.html",{ transition: "flip", changeHash: true});

jQuery accordion w/input, how do you get the input to not close the accordion & still be able to control it?

This is more of a proof of concept for myself, to fool around and learn what I can and can't do with jQuery, and I have had partial success.
I created an accordion that contains two spans, which serve as name and description, as well as a button that is independently click-able (ie, it does not open or close the accordion.)
Taking that concept, I decided to try and make the name and description editable by turning the name and description spans into text inputs / text areas, which worked fairly well.
The problem however is that when I take the same technique I used on the button and use it on the input and textarea, clicking it does not allow you to move the cursor to different positions. There does not seem to be a way for me to get around this behavior.
I tried event.preventDefault(), which does not work at all.
I tried event.stopPropagation(), which gives the partially working behavior.
and I tried return false, which worked the same way as stopPropagation.
I was wondering if anyone could provide any insight on this issue.
I included the jQuery javascript below, but for a much more concise example I will provide a jsfiddle link here (http://jsfiddle.net/Rakshasas/xFhN3/) which gives you a much more clear example of what I am doing. Note that when you click the accordion to expand it, the spans are hidden and inputs are shown. Clicking the inputs does not close the accordion, but it also does not allow you to position the cursor.
Also, if you do attempt to change the text in the inputs, closing the accordion does indeed update the spans which is the intended result. This is why I am saying my concept partially works.
Thank you.
$(function() {
$(".accordion").accordion({
header: 'h3',
collapsible: true,
active: false,
change: function(event, ui) {
var id = ui.newHeader.find('input:last').val();
$("#status").text(id);
ui.newHeader.find('div.headerContainer input.name').val(ui.newHeader.find('div.headerContainer span.name').text());
ui.newHeader.find('div.headerContainer textarea.desc').val(ui.newHeader.find('div.headerContainer span.desc').text());
ui.oldHeader.find('div.headerContainer span.name').text(ui.oldHeader.find('div.headerContainer input.name').val());
ui.oldHeader.find('div.headerContainer span.desc').text(ui.oldHeader.find('div.headerContainer textarea.desc').val());
ui.newHeader.find('div.headerContainer span').hide();
ui.newHeader.find('div.headerContainer input, div.headerContainer textarea').show();
ui.oldHeader.find('div.headerContainer span').show();
ui.oldHeader.find('div.headerContainer input, div.headerContainer textarea').hide();
}
});
$('input.name, textarea.desc').click(function(event){
event.stopPropagation();
});
$(".delButton").button({
icons: {primary: 'ui-icon-trash'},
text: false
}).click(function(event) {
//Display user friendly text
return false;
});
});
If someone is facing this issue, this is a little trick that worked for me.
PROBLEM: nested jquery accordions with input/textareas elements, cannot gain focus with normal click in Firefox (if you use jquery accordions with NO nested accordions on it, everything works fine). Confirmed by above users.
The sympton relates only to normal click (left click). If you try optional click (right click), the element (input/textarea) WILL gain focus. Weird.
SOLUTION: Just declare this in your document ready function
$(function() {
//some code ...
$("input, textarea").click( function(){
$("input, textarea").blur();
$(this).focus();
});
//more code ...
});
Confirmed (by me) working on IExplorer, Firefox and Chrome.
Seems to work fine in Chrome. This might be browser dependent.
"Clicking the inputs does not close the accordion, but it also does not allow you to position the cursor"
Also fine in Chrome.

Resources