jQuery-Mobile: Page does not load completely when swiped to - jquery-mobile

Today I prepared some PHP pages with jQuery-Mobile. It should enable for swiping from one page to another.
In general the swiping works but there is one problem: When I've swiped to a new page swiping doesn't work on that page first. Only when I reload the page it works again. The page source before reloading is OK.
It seems to me that not all inclusions are executed when I have swiped to a new page. How can this be fixed? E.g.: Ref link
$(document).ready(function () {
var urlup, urlleft, urlright;
$('img').on('dragstart', function (event) {
event.preventDefault();
});
$('img').each(function (i) {
if (this.src.indexOf("buttonup.png") >= 0) {
urlup = this.parentNode.href;
this.id = "buttonup";
} else if (this.src.indexOf("buttonleft.png") >= 0) {
urlleft = this.parentNode.href;
this.id = "buttonleft"
} else if (this.src.indexOf("buttonright.png") >= 0) {
urlright = this.parentNode.href;
this.id = "buttonright";
} else {};
});
//$.mobile.loadPage(urlup);
//$.mobile.loadPage(urlleft);
//$.mobile.loadPage(urlright);
$(":mobile-pagecontainer").pagecontainer("load", urlup);
$(":mobile-pagecontainer").pagecontainer("load", urlleft);
$(":mobile-pagecontainer").pagecontainer("load", urlright);
$(document).on("swipeup", function () {
$.mobile.changePage(urlup);
});
$(document).on("swipeleft", function () {
$.mobile.changePage(urlright);
});
$(document).on("swiperight", function () {
$.mobile.changePage(urlleft, {
reverse: true
});
});
$("#buttonup").click(function () {
$.mobile.changePage(urlup, {
transition: "slideup"
});
});
$("#buttonleft").click(function (event) {
event.stopPropagation();
});
$("#buttonleft").click(function () {
$.mobile.changePage(urlleft, {
reverse: true
});
});
$("#buttonright").click(function () {
$.mobile.changePage(urlright);
});
});

In the meantime I was able to fix this problem: I used the document-ready-event and this one is not fired when jQuery Mobile loads a new page. Thus the javascript code that binds the swiping events was not executed. I had to use JMs pageinit event instead. After fixing some other problems swiping works fine on my pages now:
http://www.ulrichbangert.de/orchid/odm_rawdonjester.php
Best regards - Ulrich

Related

jQuery UI Tooltip delayed loading

When hovering over a link, I'd like to wait at least a second before showing a tooltip with dynamically loaded tooltip.
What I've created is the follow jQuery Code:
$(document).ready(function () {
$("div#galleries ul li:not(.active) a").tooltip({
items: "a",
show: { delay: 1000 },
content: 'Loading preview...',
open: function (event, ui) {
previewGallery(event, ui, $(this));
}
});
});
function previewGallery(event, ui, aLinkElement) {
event.preventDefault();
ui.tooltip.load("http://www.someurl.com/Preview.aspx #preview");
}
Which seemed to work pretty fine, you can see it here:
http://fotos.amon.cc/ (simply hover over the list of galleries)
But I didn't realize at the beginning, that the loading of preview text happens immediately when hovering over the link. So if you quickly hover over all the links, you'll set up several requests:
From the users point of view (without knowing that requests are fired) it looks already the way I want, but how to only start loading the preview, when tooltip is actually showing up?
Thanks,
Dominik
What I did in the end was to use window.setTimeout and window.clearTimeout:
var galleryToolTipTimer = null;
var previewElement = null;
$(document).ready(function () {
$("div#photos div a img").tooltip();
$("div#galleries ul li:not(.active) a")
.tooltip({ items: "a", content: 'Loading preview...', disabled: true, open: function (event, ui) { previewElement.appendTo(ui.tooltip.empty()); } })
.mouseover(function (e) {
if (galleryToolTipTimer != null) { window.clearTimeout(galleryToolTipTimer); }
var aLinkObject = $(this);
galleryToolTipTimer = window.setTimeout(function () { previewGallery(aLinkObject); }, 500);
}).mouseleave(function (e) {
window.clearTimeout(galleryToolTipTimer);
$(this).tooltip("option", { disabled: true });
});
});
function previewGallery(aLinkElement) {
previewElement = $("<div/>").load(aLinkElement.closest("div").data("galleryPreview") + "/" + aLinkElement.data("path") + " #preview", function () {
aLinkElement.tooltip("open");
});
}
Works at least the way I want.
To see it in action, simply navigate to http://fotos.amon.cc/ and hover over one of the gallery links on the left for a preview:

JQueryMobile: pagecontainershow on a particular page not working

JQueryMobile 1.4 has deprecated the pageshow event and instead recommends using pagecontainershow; however, while I'm able to get the pagecontainershow event at a document level, I can't bind a function to a particular page.
<div id="page1" data-role="page">
...
<script>
$( "#page1" ).on( "pagecontainershow", function( event, ui ) {
console.log("page1 pagecontainershow");
} );
</script>
</div>
Demonstration: http://jsbin.com/IFolanOW/22/edit?html,console,output
I also considered using the alternative form of the jQuery "on" function where we use a selector, but that would need to be a parent of the page div, and that might include other pages, so that doesn't work.
As a workaround, I've done this, but it is very inefficient:
function registerOnPageShow(pageId, func) {
var strippedPageId = pageId.replace("#", "");
var e = "pagecontainershow." + strippedPageId;
// TODO why isn't it working to use $(pageId) instead of $(document)?
$( document ).off(e).on(e, null, {page: strippedPageId, f: func}, function(e, ui) {
if ($(":mobile-pagecontainer").pagecontainer("getActivePage")[0].id == e.data.page) {
e.data.f(e, ui);
}
});
}
You can get the page ID like this.
$(document).on('pagecontainershow', function(e, ui) {
var pageId = $('body').pagecontainer('getActivePage').prop('id');
});
There is currently no way to have a show/hide event on a specific page.
Here is what I'm using (jqmobile >1.4):
$(document).on("pagecontainershow", function () {
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
var activePageId = activePage[0].id;
switch (activePageId) {
case 'loginPage':
...
break;
case 'homePage':
...
break;
case 'groupPage':
...
break;
default:
}
});
$(document).on("pagecontainershow", function(event, ui) {
var pageId = $('body').pagecontainer('getActivePage').prop('id'),
showFunc = pageId+'_show';
if (typeof MobileSite[showFunc] == 'function') {
MobileSite[showFunc]();
}
});
MobileSite is contained in an external .js file with all the show() functions.
$(document).on("pagecontainerbeforeshow", function (event, ui) {
if (typeof ui.toPage == "object") {
var crrentPage = ui.toPage.attr("id")
}
});
and you must use this code before calling Index.js !!

changing a page in jqm after a fetch - view not displaying backbone

I am trying to change a page and display a view with JQM and backbone.
My home page loads ok but when I try and go to the second page - this is when I have a few questions. the page loads but nothing is showing
so my app has a router
var AppRouter = Backbone.Router.extend({
//define routes and mapping route to the function
routes: {
'': 'showHome', //home view
'home': 'showHome', //home view as well
'products/productList' : 'showProducts',
},
initialize:function () {
// Handle back button throughout the application
$('.back').live('click', function(event) {
window.history.back();
return false;
});
this.firstPage = true;
},
defaultAction: function(actions){
this.showHome();
},
showHome:function(actions){
// will render home view and navigate to homeView
var homeView=new HomeView();
homeView.render();
this.changePage(homeView, 'fade');
},
showProducts:function(){
var productList=new Products();
var self = this;
productList.fetch({
success:function(data) {
self.changePage(new ProductListView({collection:data}));
}
});
},
changePage:function (view, transition) {
//add the attribute 'data-role="page" ' for each view's div
if (transition != "slidefade") {
transition = "pop";
}
view.$el.attr('data-role', 'page');
$('.ui-page').attr('data-role', 'page');
//append to dom
$('body').append(view.$el);
if(!this.init){
$.mobile.changePage($(view.el), {changeHash:false, transition: transition});
}else{
this.init = false;
}
}
});
$(document).ready(function () {
console.log('App Loaded');
app = new AppRouter();
Backbone.history.start();
});
return AppRouter;
here is also my view page for product
var ProductListView = Backbone.View.extend({
template: _.template(productViewTemplate),
initialize: function () {
_.bindAll(this, "render");
this.collection.bind("reset", this.render);
},
render: function () {
var self = this;
this.collection.each(function(model) {
self.$el.append(self.template(model.toJSON()));
console.log("here");
});
}
});
return ProductListView;
So from within the homeView I can change the page and that's fine the issue what am i doing wrong on the products view for it not to return a thing.. no errors are returned.
thanks
so I have done some more work and made my show products function
showProducts:function(){
var productList=new Products();
var self = this;
var productListView =new ProductListView({collection:productList});
productList.fetch(self.changePage(productListView));
}
this works when the view is
var ProductListView = Backbone.View.extend({
template: _.template(productViewTemplate),
initialize : function () {
_.bindAll(this, "render");
this.collection.bind("reset", this.render, this);
},
render: function() {
var self = this;
this.collection.each(function(model) {
self.$el.append(self.template(model.toJSON()));
console.log("here");
});
}
});
return ProductListView;
but now jQueryMobile doesnt add on its code so it has no styling..
any suggestions?
Both Backbone.js's router and jQuery Mobile use the hashtag and don't work so well together. There are ways to get them to work but unless you have specific reason to do so I'm not sure its worth it, instead I'd recommend using jQuery-Mobile-router which is a plugin for jQuery mobile, that was created for this very reason (that is to work with Backbone.js). As a bonus the jQuery Mobile Router ties in with the special JQM Page events.

TipTip only working on second hover after ajaxpost

Situation:
My tooltips show up on my page. Opening my fancybox works. Doing the ajax post from that fancybox works.
But my tooltips don't work in that fancybox. And they don't work after my ajax post.
I tried to reinitialize TipTip with the callbacks of fancybox.
EDIT
Title changes
So I found a way to let it run on the second hover after post but not on first hover.
I also found some explanations here but it still didn't fix my problem. Probably doing it wrong.
EDIT 2
Tootip in fancybox working use afterShow only.
Changes
added this in $(function () { so that it calls this function instead of initTipTip.
$(".tooltip").live('mouseover', function () {
$(this).tipTip();
});
Code of my function that does the post thing and closes my fancybox.
var reservation = MakeReservation();
var oldDateSplit = $("#resDate").val().split('/');
var newDateSplit = $("#dateEditReservation").val().split('/');
var oldDate = new Date(oldDateSplit[2], oldDateSplit[1] - 1, oldDateSplit[0]);
var newDate = new Date(newDateSplit[2], newDateSplit[1] - 1, newDateSplit[0]);
var time = $("#txtTime");
$.ajax({
url: ResolveUrl('~/Reservation/CheckSettings'),
data: "JSONString=" + reservation + "&hasJavaScriptMethod=" + true
}).done(function (data) {
if (data.length == 0 || oldDate.getTime() == newDate.getTime()) {
$.fancybox.close();
var id = $("#reservationId").val();
$("#reservationList").load(ResolveUrl('~/Reservation/reservationList',
function () { initTipTip(); }));
$("#reservationDetail").load(ResolveUrl('~/Reservation/DetailInfo',
function () { initTipTip(); }), { reservationId: id });
$("#reservationList").on("hover", " .tooltip", function () { $(this).tipTip(); });
}
else {
$(".errorDiv").removeClass("hidden");
$(".errorDiv").html(data);
$(".btnReservations").removeAttr('disabled');
}
});
NEW
$(".tooltip").live('mouseover', function () {
$(this).tipTip();
});
}
Still the same as before the edit.
Code initialization for TipTip
function initTipTip () {
$(".tooltip").tipTip();
}
Code of fancybox
function openFancy() {
$("a.inline").fancybox({
'type': 'ajax',
'afterShow': function () {
return initTipTip();
}
});
$("a.inlineBlockedDate").fancybox({
'type': 'ajax',
'ajax': { cache: false },
'afterShow': function () {
return initTipTip();
}
});
}
I found the solution for this.
So I used my .live in $(function(){ like in my question but I did not use ".tooltip" here but the table itself. I also use initTipTip here instead of $(this).tipTip();
So this solves the Tooltip from TipTip.
Explanation: This is because the tooltip.live only gets triggered on first hover and not when the table 'refreshes'. So now you add that event on that refresh of the table
Correct me if I'm wrong here.
So no need for any other .tiptip stuff or InitTipTip then in $(function(){
$("#reservationList").live('mouseover', function () {
initTipTip();
});
I hope your problem gets solved with this question.

Changing link destination with the pagebeforechange event and keeping it out of the history?

I am working on a PhoneGap application that uses jQuery Mobile (jQM). This application has areas that will require the user to be authenticated. So I'm using jQM's pagebeforechange to determine if the user needs to authenticate before viewing the page they have requested. If so, I send them to a login page.
I want to keep the login page out of jQM's history tracking. That is, if the user is presented with the login page, but decides to press "cancel," I want the application to go back to the previous page and not have a "next" page in the history; the "previous page" would be at the top of the history stack.
Here's how I am handling the login page redirection:
$(document).bind('pagebeforechange', function(e, data) {
if (typeof data.toPage !== 'string') {
return;
}
if (data.toPage.match(/someRestrictedPage/)) {
data.options.transition = "pop";
data.options.changeHash = false;
data.toPage = "myLogin.html";
}
});
For the cancel button of my login page I am doing:
$loginCancelButton.bind('click', function() {
var prevPage = $.mobile.urlHistory.getPrev();
if (typeof prevPage !== 'undefined') {
$.mobile.changePage(prevPage.url, {
changeHash: false,
reverse: true,
transition: "pop"
});
}
});
However, when I do this, I end up with a $.mobile.urlHistory.stack with three elements:
[ {"index"}, {"login"}, {"index"} ]
How do I manage intercepting page changes to redirect to a login form when necessary, but not create an "invalid" navigation history?
looking at the jquery docs it mentions that pagebeforeload event needs to be stopped. and then call the data.deferred (resolve or reject).
try changing it to:
$(document).bind('pagebeforechange', function(e, data) {
if (typeof data.toPage !== 'string') {
return;
}
if (data.toPage.match(/someRestrictedPage/)) {
e.preventDefault()
data.options.transition = "pop";
data.options.changeHash = false;
data.toPage = "myLogin.html";
}
data.deferred.resolve(/* url */, data.options)
});
A solution for the initial problem could be something like:
$(document).bind('pagebeforechange', function(e, data) {
if (typeof data.toPage !== 'string') {
return;
}
if (data.toPage.match(/ your regex /gi))
{
if (!check_login())
{
e.preventDefault();
data.options.transition = "pop";
data.options.changeHash = false;
data.toPage = "#SignIn";
$.mobile.changePage("#SignIn");
}
//data.deferred.resolve('#SignIn', data.options);
}
});
That worked for me just fine.
VeXii's solution seemed to work for me. By simply removing
data.deferred.resolve('#SignIn', data.options);
and
e.preventDefault();
On jquery mobile 1.3...
$(document).bind('pagebeforechange', function(e, data) {
if (typeof data.toPage !== 'string') {
return;
}
if (data.toPage.match(/index/)) {
data.options.transition = "pop";
data.options.changeHash = false;
data.toPage = "#login";
}
});

Resources