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

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.

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:

Why do I have an extra empty page when I add jquery mobile 1.3.2?

When I load the jquery mobile I have an extra empty page that messes with the app (changes to a white page) when I use the options tag in html, for example.
But only when I have data-native-menu="false"
This is the extra page:
<div data-role="page" data-url="/" tabindex="0" class="ui-page ui-body-c" style="min-height: 629px;">
Someone can explain to me how to use the jquery mobile without the extra page?
Code:
main:
require(['app', 'jquery', 'backbone', './router'], function (App, $, Backbone, Router) {
'use strict';
$( document ).on( "mobileinit",
// Set up the "mobileinit" handler before requiring jQuery Mobile's module
function() {
// Prevents all anchor click handling including the addition of active button state and alternate link bluring.
$.mobile.linkBindingEnabled = false;
// Disabling this will prevent jQuery Mobile from handling hash changes
$.mobile.hashListeningEnabled = false;
// $.mobile.selectmenu.prototype.options.nativeMenu = false;
$.mobile.ajaxEnabled = false;
$.mobile.pushStateEnabled = false;
$('div[data-role="page"]').live('pagehide', function (event, ui) {
$(event.currentTarget).remove();
});
}
)
require( ['jquery-mobile-bower'], function() {
// Instantiates a new Backbone.js Mobile Router
var router = new Router();
Backbone.history.start();
});
});
Router:
define([ "jquery", "backbone", './views/views'], function($, Backbone, views) {
var changeView = function(view){
view.render([{}]);
$(view.el).attr('data-role', 'page');
$('body').append(view.el)
var el = view.el;
$.mobile.changePage($(view.el));
}
// Extends Backbone.Router
var CategoryRouter = Backbone.Router.extend( {
// The Router constructor
initialize: function() {
// Tells Backbone to start watching for hashchange events
$('.back').live('click', function(event) {
window.history.back();
return false;
});
},
// Backbone.js Routes
routes: {
"": "index",
"aa": "aa"
},
// Home method
index: function(){
var view = new views.Index();
changeView(view);
view.on('changePage', function(pageName){
})
},
aa: function(){
var view = new views.A();
changeView(view);
}
} );
// Returns the Router class
return CategoryRouter;
} );
Thanks

events not firing when creating single instance of a view, but works when mutliple instance are created

I'm a complete newbie to Backbone and am trying to get my head round few things. Im trying to build something using jQuery mobile and Backbone. Please find my code below
var WelcomePage = Backbone.View.extend({
initialize:function () {
this.template = _.template($("#welcome_template").html());
},
render:function (eventName) {
$(this.el).html(this.template());
return this;
},
events:{
"click .btn_continue" : function(){
appRouter.navigate('login',{trigger: true});
}
}
});
var Login = Backbone.View.extend({
initialize:function () {
this.template = _.template($("#login_template").html());
},
render:function (eventName) {
$(this.el).html(this.template());
return this;
},
events:{
"click .btn_login" : function(){
appRouter.navigate('dashboard',{trigger: true});
}
}
});
var Dashboard = Backbone.View.extend({
initialize:function () {
this.template = _.template($("#dashboard_template").html());
},
render:function (eventName) {
$(this.el).html(this.template());
return this;
},
events:{
"click .btn_loadImages" : function(){
console.log('load Images');
}
}
});
var Router = Backbone.Router.extend({
routes:{
"":"welcome",
"login":"login",
"dashboard":"dashboard",
},
initialize:function () {
},
welcome:function () {
this.changePage(new WelcomePage());
},
login:function () {
this.changePage(new Login());
},
dashboard:function(){
this.changePage(new Dashboard());
},
changePage:function (page) {
$(page.el).attr('data-role', 'page');
page.render();
$('body').append($(page.el));
$.mobile.changePage($(page.el), {changeHash:false, transition: 'slide'});
}
});
var appRouter = new Router();
Backbone.history.start();
Now while I go back and forth through the screens using the BACK key the events fire OK using the code above. Then I tried replacing the code for the Router with the code below
var Router = Backbone.Router.extend({
routes:{
"":"welcome",
"login":"login",
"dashboard":"dashboard",
},
initialize:function () {
},
welcome:function () {
this.changePage(v_WelcomePage);
},
login:function () {
this.changePage(v_Login);
},
dashboard:function(){
this.changePage(v_Dashboard);
},
changePage:function (page) {
$(page.el).attr('data-role', 'page');
page.render();
$('body').append($(page.el));
$.mobile.changePage($(page.el), {changeHash:false, transition: 'slide'});
}
});
var v_WelcomePage = new WelcomePage();
var v_Login = new Login();
var v_Dashboard = new Dashboard();
var appRouter = new Router();
Backbone.history.start();
I noticed when I go back to the previous screens the events stop firing. Instead of creating the instance of the view in the action of the router I have created it outside and call it each time.I hope im making some sense.
Any advice much appreciated.
Events are hooked up using jQuery when the view is instantiated, not rendered (in the Backbone View constructor function). jQuery disconnects those events when the html is removed from the page (probably in $.mobile.changePage).
So, the second time you render the page, the events will not be hooked back up. You could try calling page.delegateEvents() to manually hook up the events again, or you could re-create the view each time.

knockout observable array bounded listview doesnt get rendered in JQM

JQM listview get populated as with the data with no issue as expected, but i cant get it rendered with JQM styles. could any one can help me with this issue.
I have tried with listview(), listview("refresh"), trigger("create") none of them did work
var ProfessionsModel = function() {
var self = this;
self.professionDetails = ko.observableArray([]);
self.getProfessionDetails=function(){
var rest = new RestService('${pageContext.request.contextPath}/rest/profession/designations');
rest.findAll(function(data) {
$.each(data, function(index, value){
self.professionDetails.push(value);
});
});
};
self.removeProfessionDetails= function(){
self.professionDetails.removeAll();
};
};
var pm = new ProfessionsModel();
$('#profession').live('pagecreate', function(event) {
ko.applyBindings(pm, this);
});
$('#profession').live('pagebeforeshow', function(event) {
pm.removeProfessionDetails();
});
$('#profession').live('pageshow', function(event) {
pm.getProfessionDetails();
$('#profession').find("ul").listview();
$('#profession').find("ul").listview("refresh");
});
You are doing it in a wrong moment. You want believe how jQM is picky about a right moment.
var ProfessionsModel = function() {
var self = this;
self.professionDetails = ko.observableArray([]);
self.getProfessionDetails=function(){
var rest = new RestService('${pageContext.request.contextPath}/rest/profession/designations');
rest.findAll(function(data) {
$.each(data, function(index, value){
self.professionDetails.push(value);
});
$('#profession').find("ul").listview();
$('#profession').find("ul").listview("refresh");
});
};
self.removeProfessionDetails= function(){
self.professionDetails.removeAll();
};
};
jQM trigger refresh will brake if not executed after content has been appended, hence refresh after $.each part.

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.

Resources