jQuery Mobile - pageinit handler not called on subsequent changePage calls - jquery-mobile

I have two jquery mobile "pages" (divs designated as pages) on the html page. I want to call methods every time I go to a page. I hook up methods to fire on 'pageinit' event. However, it only gets called once and doesn't get called on subsequent changePage calls.
Here is a jsFiddle to demonstrate. ( time stamp should change on pageinit )
Here is my code in entirety https://gist.github.com/dev-e-loper/5356942
My pages:
<div id="page1" data-role="page">
<h1>One</h1>
<a id="page1_link" data-role="button">go to page 2</a>
<div id="page1_output"></div>
</div>
<div id="page2" data-role="page">
<h1>Two</h1>
<a id="page2_link" data-role="button">go to page 1</a>
<div id="page2_output"></div>
</div>
Code to hook up pageinit handlers:
$("#page1").live('pageinit', function () {
$("#page1_output").append('<br/> page 1 initialized. time - ' + new Date());
});
$("#page2").live('pageinit', function () {
$("#page2_output").append('<br/> page 2 initialized time - ' + new Date());
});
$("#page1_link").live('click', function () {
$.mobile.changePage($("#page2"));
});
$("#page2_link").live('click', function () {
$.mobile.changePage($("#page1"));
});

pageinit will fire when your page first loads. Both of your pages are cached within the DOM so that event will only fire once. Try pageshow which will fire each time the page is shown.
Also, live() is depreciated. You should use bind() or on().
http://www.elijahmanor.com/2012/02/differences-between-jquery-bind-vs-live.html
$("#page1").bind('pageshow', function () {
$("#page1_output").append('<br/> page 1 initialized. time - ' + new Date());
});
$("#page2").bind('pageshow', function () {
$("#page2_output").append('<br/> page 2 initialized time - ' + new Date());
});

Related

jquery-ui tag "a" inside tooltip click event

fellows! I'm doing some frontend work using doT.js for generating content and jquery-ui for displaying tooltips.
{{##def.defboardtooltip:
<div class='tooltip'>
<!-- some html code -->
<a id='bdetails' href='#'>Click for details</a></div>
</div>
#}}
And how it is used:
<div class="participant" title="{{#def.defboardtooltip}}">
I'm trying to add the event to the a element with jquery as such ():
$(document).ready(function () {
// ...enter code here
$('#bdetails').click(function (e) {
// some code
console.log('fired');
});
});
And I never see the "fired". I'm confused.
jQuery Event delegates are your friend here.
Try:
$(function()
{
$(document).on('click', '#bdetails', function(e)
{
var a = $(this);
});
});
This will filter the event to just your #bdetails element, you can use any valid jQuery seletor here also; e.g., 'a' to delegate all anchor tag clicks.

Jquerymobile buttons are shown only first apperance of the page

I have a problem with jquery mobile code. I am using the code above to append a dynamic html code for my application.
$("#tab3").click(function() {
$('#HaberIcerik').html(" <img src='img/izto_header.png' height=auto width=100% class='img2' > ");
$('#HaberIcerik').append(" <div class='zoomTab'><a href='#' data-role='button' class='plus'>+</a><a href='#' data-role='button' class='minus'>-</a></div>");
});
When the page loads first, everything works perfectly. However when I move to the main page and click my tab3 page again buttons are shown only as links,not with button styles.
Can you help me to solve this problem?
In your code you're not refreshing your button's styles. So, you must add it after append()
$(document).on("click", "#tab3", function (e) {
e.preventDefault();
$('#HaberIcerik').html("<img src='http://www.ndaccess.com/Sample/Images/Image1.jpg' height=auto width=100% class='img2' > ");
$('#HaberIcerik').append("<div class='zoomTab'><a href='#' data-role='button' class='plus'>+</a><a href='#' data-role='button' class='minus'>-</a></div>").promise().done(function () {
//wait till everything is appended
$(this).find("a").buttonMarkup("refresh");
});
});
For more info see docs : http://api.jquerymobile.com/button/#method-refresh
And here's a demo : http://jsfiddle.net/hungerpain/cTdkN/

Initializing knockoutjs content in child jquery mobile page

I know there are a lot of questions that cover jquery mobile / knockoutjs integration, however I couldn't find a thread that solved my issue. I have a master view model which contains child view models, and so I initialize this on page load, as that event is only fired on application load:
var viewModel = null;
$(function () {
console.debug("running init");
viewModel = new ViewModel();
ko.applyBindings(viewModel);
});
This works great on the first page of my app, however when I go to a child page, the knockoutjs content doesn't show up because jquery mobile has loaded the html dynamically and knockout doesn't know to update the binded content. I'm trying to tell it to update dynamically by using the $(document).delegate function, however I'm struggling with how it's supposed to be implemented.
<ul id="speeding" data-role="listview" data-bind="foreach: speeding.items">
<li>
<h3 class="ui-li-heading" data-bind="text: Address"></h3>
<p class="ui-li-desc" data-bind="text: Address2"></p>
<p class="ui-li-desc" data-bind="text: PrettyDate"></p>
<p class="ui-li-aside" data-bind="text: SpeedMph"></p>
</li>
<script type="text/javascript">
var loaded = false;
$(document).delegate("#page-speeding", "pagebeforecreate", function () {
if (!loaded) {
loaded = true;
ko.applyBindings(viewModel);
}
else {
$("#speeding").trigger("refresh");
}
});
</script>
</ul>
I'm putting the delegate function within the page it's being called on, as apparently that's a requirement of using delegate. Then on first load of this child page I call ko.applyBindings (I only wanted to call this on application load but I couldn't get trigger("create") to work. On subsequent calls it would call trigger("refresh") (which doesn't work for me.) The issue though is that the delegate function gets added each time I go to the child page. So on first load of the child page, it will call the delegate callback function once. If I go back to the main page, then back to the child page, it will call the delegate callback twice, and so on.
Can someone please provide guidance of the recommended approach to refreshing the knockoutjs bindings on child pages?
This is what ended up working for me. I have no idea if there's a better way or not...
var viewModel = null;
$(function () {
console.debug("running init");
viewModel = new ViewModel();
ko.applyBindings(viewModel);
var pages = [
"scorecard", "speeding", "leaderboard"
];
_.each(pages, function (page) {
$(document).on("pagebeforecreate", "#page-" + page, function () {
console.debug("applying " + page + " bindings");
ko.applyBindings(viewModel, $("#page-" + page)[0]);
});
});
});

Adding a reload button to an Ajax page with jQuery Mobile

In a jQuery Mobile application, I'm using Ajax to load a page with dynamic content. Now, I want to add a "reload" button to that page.
Consider index.html:
<div data-role="page" id="home">
<div data-role="header"><h1>Home</h1></div>
<div data-role="content">Time</div>
</div>
And time.php:
<div data-role="page" data-add-back-btn="true" id="time">
<div data-role="header"><h1>Time</h1></div>
<div data-role="content">
<p><?= date(DATE_RFC822)?></p>
Reload
</div>
</div>
I can now navigate back and forth between the "home" and "time" pages, and the time will be updated when arriving on the "time" page, but I would like the "Reload" button to reload the "time" page. That is: it should do an Ajax request for time.php, and recreate the "time" page from the response (and meanwhile show the "page loading" indicator).
How can I do that?
After looking at the code of changePage and loadPage I came up with a simpler solution:
$('.reload').live('click', function(e) {
$.mobile.changePage($.mobile.activePage.jqmData('url'), {
reloadPage: true,
changeHash: false,
transition: 'none'
});
e.preventDefault();
});
Note that JQM will still transition between the old version of the page and the new version; it is best not to use a transition that has a stronge sense of direction (like 'slide').
The preventDefault does not seem strictly necessary, but I added it for good measure.
This does not seem to be possible when using the hijax-style links. You can however use a multi-page HTML document and load the dynamic page content yourself in the pagebeforechange event.
So in index.html, I already add the "time" page with empty content:
<div data-role="page" id="home">
<div data-role="header"><h1>Home</h1></div>
<div data-role="content">Time</div>
</div>
<div data-role="page" data-add-back-btn="true" id="time">
<div data-role="header">
<h1>Time</h1>
Reload
</div>
<div data-role="content"></div>
</div>
Next, I intercept the pagebeforechange event: in case of the "time" page, we will load the page content from URL time.php.
$(document).bind('pagebeforechange', function(e, data) {
if(typeof data.toPage == 'string') {
var u = $.mobile.path.parseUrl(data.toPage);
if(u.hash == "#time") {
loadPageContent($('#time'), 'time.php', data.options);
e.preventDefault();
}
}
});
Since I want to wait for the Ajax request to come back before changing the page, I prevent the page change; loadPageContent will have to do this.
I can do a similar loadPageContent for the "Reload" button:
$(document).ready(function() {
$('#time .reload').bind('click', function(e) {
loadPageContent($('#time'), 'time.php', undefined, $(e.target).closest(".ui-btn"));
});
});
This is the code of loadPageContent:
function loadPageContent(page, url, options, button) {
if(typeof button != "undefined")
button.addClass($.mobile.activeBtnClass);
$.mobile.showPageLoadingMsg($.mobile.loadingMessageTheme, $.mobile.loadingMessage, $.mobile.loadingMessageTextVisible);
var content = page.children(':jqmData(role=content)');
content.load(url, function(response, status, xhr) {
if(status == "success") {
page.page();
content.trigger('create');
$.mobile.hidePageLoadingMsg();
if(typeof button != "undefined")
button.removeClass($.mobile.activeBtnClass);
$.mobile.changePage(page, options);
} else {
$.mobile.hidePageLoadingMsg();
$.mobile.showPageLoadingMsg($.mobile.pageLoadErrorMessageTheme, $.mobile.pageLoadErrorMessage, true);
setTimeout(function() {
$.mobile.hidePageLoadingMsg();
if(typeof button != "undefined")
button.removeClass($.mobile.activeBtnClass);
}, 1000);
}
});
}
This is already quite an elaborate version: it will display the page loading message, and it will display an error message for 1s when the request fails. At the end of a successful request, it will enhance the content with the create trigger, and it will do the page change. If the reload button is passed along, it will mark this button as active while the operation is in progress.

Prevent default on a click within a JQuery tabs in Google Chrome

I would like to prevent the default behaviour of a click on a link. I tried the return false; also javascript:void(0); in the href attribute but it doesn’t seem to work. It works fine in Firefox, but not in Chrome and IE.
I have a single tab that loads via AJAX the content which is a simple link.
<script type="text/javascript">
$(function() {
$("#tabs").tabs({
ajaxOptions: {
error: function(xhr, status, index, anchor) {
$(anchor.hash).html("Couldn't load this tab. We'll try to fix this as soon as possible. If this wouldn't be a demo.");
},
success: function() {
alert('hello');
$('#lk').click(function(event) {
alert('Click Me');
event.preventDefault();
return false;
});
}
},
load: function(event, ui) {
$('a', ui.panel).click(function(event) {
$(ui.panel).load(this.href);
event.preventDefault();
return false;
});
}
});
});
</script>
<body>
<div id="tabs">
<ul>
<li>Link</li>
</ul>
</div>
</body>
The content of linkChild.htm is
Click Me
So basically when the tab content is loaded with success, a click event is attached to the link “lk”. When I click on the link, the alert is displayed but then link disappears. I check the HTML and the element is actually removed from the DOM.
$('#selector').click(function(event) {
event.preventDefault();
});
The event object is passed to your click handler by default - you have to have something there to receive it. Once you have the event, you can use jQuery's .preventDefault() method to cancel the link's behavior.
Edit:
Here's the fragment of your code, corrected:
$('a', ui.panel).click(function(event) {
$(ui.panel).load(this.href);
event.preventDefault();
return false;
});
Notice the addition of the word 'event' when creating the anon function (or you could use just e, or anything else - the name is unimportant, the fact there's a var there is.

Resources