jQuery Mobile pagecontainerremove never fires - jquery-mobile

In my multipage jqm document there is a page with the id #internal. At some point I do
$('#internal').remove();
The page is removed but
$('body').on('pagecontainerremove',function(e,ui){console.log(ui.toPage);console.log('page removed');})
does not fire. Googling for pagecontainerremove and experimenting with various ways of removing the page has not yielded anything useful.

The remove events pageremove and its' "successor" pagecontainerremove are fired on external pages in Single Page Model. jQuery Mobile removes external pages from DOM upon navigating away off them. By default, jQuery Mobile doesn't cache external pages and binds bindRemove to remove them. However, if an external page is cached data-dom-cache="true", the remove event won't be attached to it to remove it from DOM.
Although pageremove is replaced by pagecontainerremove, the latter doesn't fire and it is definitely a bug in jQuery Mobile 1.4.
/* doesn't fire */
$(document).on("pagecontainerremove", function (e) {
console.log("pagecontainer event: " + e.type);
});
/* does fire */
$(document).on("pageremove", function (e) {
console.log("page event: " + e.type);
});
Demo
Nevertheless, it is possible to use bindRemove in Multi-Page Model to let jQuery Mobile removes it once hidden. First, add data-external-page="true" to page div that you want to be removed by jQuery Mobile, and then flag it for removal $("#pageID").page("bindRemove").
<div data-role="page" id="pageID" data-external-page="true">
$(document).on("pagecreate", "#pageID", function (e) {
$(e.target).page("bindRemove");
});
Demo

Related

Jquery mobile, init bind page events only once

I'm using jquery mobile v1.3.2
For some reasons I want to set an global pagechange event to prepare all of my pages :
var Front = {
initDom : function($dom) {
// here i can bind some events in my page
$(".someButton",$dom).bind("tap",function(){
alert("some actions");
});
// etc.....
});
}
$(document).on("pagechange", function(event, data) {
Front.initDom($(data.toPage));
});
This works well. But it is triggered at each page change. And some times it will init the same event twice and that will lead to some bugs.
Now i have tested to do it with the event pageinit or pagecreate but both are triggered before the page is ready and $("ui-page-active"); is empty.
I have though about some setTimeout, but that's definitively a bad idea.
I have also though to init everything at the first pageinit and unbind it. But ajax called page wont be bound.
It there some good workarround ?
You can use pageinit and then get the id of the page from the event target object:
$(document).on("pageinit", function(e){
alert(e.target.id);
});
DEMO

Jquery mobile How to tap the screen to no avail

I tested on the Apple device, and when I click on the screen when there is no effect. This is my code. Click on the events of this writing there are questions?
<script>
$(function() {
$('#test').tap(function() {
$('#menuNum').text('1');
})
})
</script>
You need to change few things.
Do not use $(function() { or classic document ready to check for a correct state, they can cause problems with jQuery Mobile. Instead use jQuery Mobile alternative called page events.
Then don't bind tap event like that, use proper modern way of doing that. In your case element must be loaded into the DOM for that kind of binding to work. And because of $(function() { sometimes it can happen that element is still loading when binding is executed. So use it like this:
$(document).on('tap','#test',function() {
$('#menuNum').text('1');
});
This method don't care if element exist or not, it will even work if element is loaded into the DOM after binding process.
Working example: http://jsfiddle.net/Gajotres/SQ7DF/
In the end you want something like this:
$(document).on('pagebeforeshow', '#index', function(){
$(document).on('tap','#test',function() {
alert('Tap');
});
});

jQuery does not work in IE9 in first attemp; on pressing F5 (refresh) it works

(I have already asked this question; here I am adding more details)
I have return a jQuery which returns the text entered in input element on change event. This jQuery works fine in FireFox but fails in Internet Explorer (IE9).
<script>
$(document).ready(function () {
$("#UserName").change(function () {
alert("Text Entered Is :"+$("#UserName").val());
});
});
</script>
1) I am using ASP.NET MVC; to reach the page having above jquery I am using Html.ActionLink
2) On IE when I reach on the page of above jQuery it does not work; but when I press F5 and refresh the page it works.
3) On Firefox I do not need to refresh the page; it works on very first attempt.
Please help...
The $(document).ready() event depends on an event called DOMContentLoaded (in Chrome, not really sure about firefox, but it is there by some name).
This event is fired as soon as the HTML has been loaded and all the relevant files have been brought in (the CSS and the JS files).. Chrome, Safari (WebKit) and Firefox(Gecko) are pretty predictable at firing this particular event. It bubbles up the stack like clockwork and once caught, you can play fiddle with it, for all anyone cares.
However, as far as IE is concerned, up till version 7 (I think) they never implemented this event. Given that, the implementation in the recent versions is not so efficient as well.
I have faced this problem time and again.
One workaround for this that has worked everytime is to fire the event manually at the end of the HTML:
<script type="text/javascript">
try{jQuery.ready();}catch(e){}
</script>
Hope this helps
Edit
A great way of seeing whether the event gets fired is to add somekind of action in the code. SOmething like:
<script>
$(document).ready(function () {
alert("Loaded");
$("#UserName").change(function () {
alert("Text Entered Is :"+$("#UserName").val());
});
});
</script>
alert blocks the execution of the code, due the single threaded nature of Javascript. Therefore, you can use this to get a pseudo-stacktrace of your code.

What page is being loaded by Jquery Mobile

I'm tasked to execute specific page javascript on pagechange in Jquery Mobile (Such as geolocate the user on one page or show a Google map on another page)
Its really not clear how to execute javascript after a pagechange but i'm almost there, i was able to use
$(document).bind('pageinit', function(event){
loadGmaps();
geolocate();
});
But the problem is that this code executes on each page change/page init and if i'm not on a page that has a #map tag, it just executes code for nothing. Worst? Jquery keeps pages loaded in memory but hides them. So if i change page, it can reload the map 16 times in a row for nothing.
I'm really confused as to how you are supposed to bind specific page javascript in a jquery mobile loaded page. I'm lurked all around the web and i'm sure i'm not the only one looking for that specific trick...
Thanks
EDIT
I changed my code to reflect Jasper's solution, and it works fine except for the geolocation:
$(document).on('pageinit', '#wp-post-id-70', function(event){
geolocate();
});
$(document).on('pageinit', '.wp-post-type-spa', function(event){
loadGmaps();
});
The maps load fine on each page i visit that is a spa, but when i load a spa page from a fresh load, if i click on the logo to go back to the home page, it loads the home page and then fires the "geolocate" function but nothing happens in terms of geolocation:
function geolocate()
{
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position){
$('#near_spa').load('?latitude='+position.coords.latitude.toString()+'& longitude='+position.coords.longitude.toString()+' #near_spa > *');
}
);
}else{
alert('Votre navigateur ne supporte pas la géolocalisation ou refuse l\'accès aux données de localisation');
}
}
The code really goes up to the navigator.geolocation.getCurrentPosition, it gets called but then pffff, nothing. If i reload the home page manually with F5, i now get the geolocation request...
EDIT
Never mind that "map" loads fine on each page, it doesn't anymore, probably me and my brain being too tired...
Therefore, the
$(document).on('pageinit', '.wp-post-type-spa', function(event){
loadGmaps();
});
Doesn't load the maps anymore at all and yes, i verified, the pages do feature a wp-post-type-spa class...
If you have code that only runs once per pseudo-page, then use the pageinit event, which only runs once every time a pseudo-page is added to the DOM.
You can also target specific pseudo-pages in your bind call:
$(document).on('pageinit', '#some-map-page', function(event){
loadGmaps();
geolocate();
});
This will only run when the pageinit event fires on an element with the ID of some-map-page. You could for example add a class to each pseudo-page element where you want to run the map code:
<div data-role="page" id="some-map-page" class="map-page">...</div>
Which would work with the following event binding:
$(document).on('pageinit', '.map-page', function(event){
loadGmaps();
geolocate();
});
Notice that I'm using .on() as a delegated event handler, which is very useful when using jQuery Mobile as you can't ever be sure when a pseudo-page exists in the DOM.

jQuery / jQuery UI - $("a").live("click", ...) not working for tabs

So I have some jQuery UI tabs. The source code is as follows:
HTML:
<div class="tabs">
<ul>
<li>Ranges</li>
<li>Collections</li>
<li>Designs</li>
</ul>
<div id="ranges"></div>
<div id="collections"></div>
<div id="designs"></div>
</div>
jQuery:
$(document).ready(function() {
$(".tabs").tabs();
});
My problem is that I am trying to make each tab load a page into the content panel on click of the relevant link. To start with I am just trying to set the html of all the panels on clicking a link. From the code below, if I use method 1, it works for all links. However if I use method 2 it doesn't - but only for the links in the tabs (i.e. the labels you click to select a tab).
Method 1 (works for all links all the time, but would not be applied to links which are added after this is called):
$("a").click(function () {
$("#ranges, #collections, #designs").html("clicked");
});
Method 2 (works for all links which are not "tabified"):
$("a").live("click", function () {
$("#ranges, #collections, #designs").html("clicked");
});
Does anyone know why it is behaving like this? I would really like to get method 2 working properly as there may well be links which I need to add click events to which are added after the page is originally loaded.
Thanks in advance,
Richard
PS yes the function calls for .live and .click are both in the $(document).ready() function, before anyone says that that may be the problem - otherwise it wouldn't work at all..
Edit:
The solution I came up with involves an extra attribute in the anchors (data-url) and the following code (which outputs a 404 not found error if the page cannot be loaded). I aim to expand this over the next few weeks / months to be a lot more powerful.
$(".tabs").tabs({
select: function (event, ui) {
$(ui.panel).load($(ui.tab).attr("data-url"), function (responseText, textStatus, XMLHttpRequest) {
switch (XMLHttpRequest.status) {
case 200: break;
case 404:
$(ui.panel).html("<p>The requested page (" + $(ui.tab).attr("data-url") + ") could not be found.</p>");
break;
default:
$(ui.panel).html("<p title='Status: " + XMLHttpRequest.status + "; " + XMLHttpRequest.statusText + "'>An unknown error has occurred.</p>");
break;
};
});
}
});
I don't know if I understand what you are going for but basically you want to do something once a tab is clicked?
Here's the docs for setting up a callback function for selecting a tab.
EDIT: Don't know if that link is working correctly, you want to look at select under Events. But basically it is:
$("#tabs").tabs({
select: function(event, ui) { ... }
});
Where ui has information on the tab that was clicked.
jQuery UI tabs has an outstanding issue where return false; is used instead of event.preventDefault();. This effectively prevents event bubbling which live depends on. This is scheduled to be fixed with jQuery UI 1.9 but in the meantime the best approach is use the built in select event as suggested by #rolfwaffle.
Maybe the tabs() plugin that you are using is calling event.preventDefault(); (Reference) once it has created it's tabs.
Then it captures the click event and the bubbling stops, so it doesn't invoke your click-function. In jQuery this is done with
$(element).click(function(){
// Do stuff, then
return false; // Cancels the event
});
You'd have to alter the tabs() plugin code and remove this return false; statement, OR if you are lucky, the plugin might have an option to disable that behavior.
EDIT: Now I see you're using jQuery UI. Then you should check the documentation there, since it is an awesome plugin, it will do anything you want if you do the html right and pass it the right options.

Resources