Dynamic listview not loading until refresh - jquery-mobile

I'm using JS render to create dynamic pages in Jquery Mobile for my Phonegap app. The problem however is that the listview isn't loaded until the page is refreshed. Clearly that's not what I want and in another app I used the exact same technique and the listview is loaded immediately. Thing is that there's no difference between the two, so I have no idea why it isn't working in this one.
Here's my script for loading the pages:
<script src="jquery/jsrender.min.js"></script>
<script type="text/javascript">
$(document).on('pageinit', '#kunstwerken_exp1', function (event, ui) {
var $page = $(event.target);
$.ajax({
dataType:"json",
url:"json/exp1_index.js",
success:function(data, textStatus, jqHXR){
for( var x = 0; x < data.length; x++){
//create valid unique IDs for each page.
data[x].id = data[x].link.replace("?","").replace("=","").replace("#","");
}
console.log("success:");
console.log(data);
$("#templateDropPoint").html($("#template").render(data));
$("#templateDropPoint").listview("refresh");
$("body").append($("#pagetemplate").render(data));
},
error:function(jqXHR, textStatus, errorThrown ){
console.log(textStatus+ " "+ errorThrown);
}
});
});
</script>
This is the HTML:
<div data-role="page" id="kunstwerken_exp1" data-url="kunstwerken_exp1">
<div data-role="content">
<ul data-role="listview" id="templateDropPoint"></ul>
</div><!-- /content -->
</div>
<script id="template" type="text/x-jsrender">
<li>
<a href="#{{>id}}">
<img src={{>img}} />
<h5><b>{{>naam}}</b></h5>
<h6>{{>kunstwerk}}</h6>
</a>
</li>
</script>
<script type="text/x-jsrender" id="pagetemplate">
<div data-role="page" id="{{>id}}">
{{if pagina}}
<div data-role="content">
<h1>{{>naam}} ({{:pagina.nationaliteit}})</h1>
<h2>{{:pagina.kunstwerk}}</h2>
<em>{{:pagina.onderschrift}}</em>
<div class="ui-grid-a my-breakpoint">
<div class="ui-block-a">
<div class="koloma">
<div class="callbacks_container">
<ul class="rslides">
<li id="callbacks1_s0">
<img src="{{:pagina.afbeelding1}}" alt=""><p class="caption">{{:pagina.onderschrift1}}</p>
</li>
</ul>
</div>
{{if pagina.videooff}}
<ul class="tabs">
<li><img src="images/video.png"/></li><br>
</ul>
{{/if}}
</div>
</div>
<div class="ui-block-b">
<div class="kolomb">{{:pagina.tekst}}</div>
</div>
</div>
</div>
{{/if}}
</div>
</script>

To understand this situation you need to understand how jQuery Mobile works. It uses AJAX to load other pages.
First page is loaded normally. Its HEAD and BODY is loaded into the DOM, and they are there to await other content. When second page is loaded, only its BODY content is loaded into the DOM. To be more precise, even BODY is not fully loaded. Only first div with an attribute data-role="page" will be loaded, everything else is going to be discarded. Even if you have more pages inside a BODY only first one is going to be loaded. This rule only applies to subsequent pages, if you have more pages in an initial HTML all of them will be loaded.
That's why your listview is show successfully only after a page refresh.
Here's an official documentation: http://jquerymobile.com/demos/1.2.0/docs/pages/page-links.html
Unfortunately you are not going to find this described in their documentation. Ether they think this is a common knowledge or they forgot to describe this like my other topics. (jQuery Mobile documentation is big but lacking many things).
I have another ANSWER that discusses this problem. Solutions and working examples can be found there.

Related

Jquery Mobile - $(document).ready(function() {});

I am new to jquery mobile.
I need help understanding the equivalent of document.ready() for jquery mobile.
I have 2 jsp pages as follow:
page1.jsp
<head>
<script type="text/javascript">
$(document).on('pagebeforeshow', '#page1', function(event){
alert("page 1");
});
</script>
</head>
<body>
<div data-role="page" id="page1">
<header data-role="header">
</header>
<article data-role="content">
page 1
</article>
<footer data-role="footer" data-position="fixed">
<nav data-role="navbar">
<ul>
<li>Page 2</li>
</ul>
</div>
</body>
page2.jsp
<head>
<script type="text/javascript">
$(document).on('pagebeforeshow', '#page2', function(event){
alert("page 2");
});
</script>
</head>
<body>
<div data-role="page" id="page2">
<header data-role="header">
</header>
<article data-role="content">
page 2
</article>
<footer data-role="footer" data-position="fixed">
<nav data-role="navbar">
<ul>
<li>Page 1</li>
</ul>
</div>
</body>
So when I initially load page 1, I will get an alert "page 1". But when I navigate to page 2, I do not get the alert "page 2"
But on page 2, I navigate back to page 1, I get an alert "page 1"
So why don't I get "page 2" alert when I load page 2 via navigation?
I am trying to learn jquery mobile so please an explanation and any code example would help to me understand it a lot.
I tried to read through jquery mobile documentation but not understanding it.
Thank you!
Your script isn't running because it technically isn't being loaded. jQuery Mobile follows links by intercepting their normal functionality (which is to navigate to a new page) and instead loads the page's content via an AJAX request. If successful, it then takes the [data-role=page] element and adds it to your existing page. The result is that the new page is loaded, but you never really leave the page that you started from.
Anything not within a [data-type=page] element is not loaded during this, including your scripts. You can fix this by by moving your <script> tag inside of page2's [data-role=page] element. If you do this, keep in mind that any code loaded this will will remain as other pages are loaded, and you might have things start interacting in ways you never intended.
Another option is to simply force jQuery Mobile to actually navigate to new pages when links are clicked. Check out their documentation for how to do that.

JQM 1.4 beta persistent navbar not keeping active state class for links

I'm facing an issue with the latest beta release of jQuery Mobile. I'm trying to implement a fixed persistent footer navbar, the persistent part is working but whenever I click a link and navigate to another page the ui-btn-active class is lost and no link appears selected.
Here's a demo fiddle that reproduces the issue: http://jsfiddle.net/koala_dev/DgdMg/2/
And here's the complete markup:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0-beta.1/jquery.mobile.structure-1.4.0-beta.1.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.0-beta.1/jquery.mobile-1.4.0-beta.1.min.js"></script>
<script>
$(function() {
$("[data-role='header'],[data-role='footer']").toolbar();
$.mobile.window.triggerHandler("throttledresize");
});
</script>
</head>
<body>
<div data-role="header" data-position="fixed" data-id="header">
<h1>My fixed header</h1>
</div>
<div data-role="page" id="page-1">
<div data-role="content">
<p>Page 1 content goes here.</p>
</div>
</div>
<!-- /page -->
<div data-role="page" id="page-2">
<div data-role="content">
<p>Page 2 content goes here.</p>
</div>
</div>
<!-- /page -->
<div data-role="footer" data-position="fixed" data-id="footer">
<div data-role="navbar">
<ul>
<li>Page 1
</li>
<li>Page 2
</li>
</ul>
</div>
</div>
</body>
</html>
I followed the instruction from the demos in the docs (which don't seem to be complete) and placed the footer outside the page container. I tried adding .ui-state-persist to the first link and to both links but it didn't produce any effect and since even the demos are not working correctly I'm not sure how to proceed.
I would appreciate any insight on how to keep the ui-btn-active class for the clicked link.
Well, I found this on jQM updated demo page. Adding .ui-btn-active for external fixed toolbars depends on data-role=page's data-title attribute.
<div data-role="page" id="page-1" data-title="Page 1">
Navbar buttons text, should match data-title in order to determine which button should be updated with .ui-btn-active, as well as updating data-role=header title.
Demo
$(document).on("pageinit", function () {
$("[data-role='navbar']").navbar();
$("[data-role='header'], [data-role='footer']").toolbar();
});
// Update the contents of the toolbars
$(document).on("pageshow", "[data-role='page']", function () {
// Each of the four pages in this demo has a data-title attribute
// which value is equal to the text of the nav button
// For example, on first page: <div data-role="page" data-title="Info">
var current = $(this).jqmData("title");
// Change the heading
$("[data-role='header'] h1").text(current);
// Remove active class from nav buttons
$("[data-role='navbar'] a.ui-btn-active").removeClass("ui-btn-active");
// Add active class to current nav button
$("[data-role='navbar'] a").each(function () {
if ($(this).text() === current) {
$(this).addClass("ui-btn-active");
}
});
});
Source: http://view.jquerymobile.com/1.4.0-rc.1/dist/demos/toolbar-fixed-persistent/
I had this same issue for links in the navbar. It was very frustrating. I fired up firebug and debugged jqm. I ended up patching the jquery mobile code like so:
In jquery.mobile-1.4.0.js
From:
$navbtns.removeClass( $.mobile.activeBtnClass );
activeBtn.addClass( $.mobile.activeBtnClass );
To:
if ( !($navbtns.filter( ".ui-state-persist" ) ) ) {
$navbtns.removeClass( $.mobile.activeBtnClass );
activeBtn.addClass( $.mobile.activeBtnClass );
}
I minified jqm here: http://jscompress.com/

Use external panel from dynamically injected page

A new thing in version 1.4.0 alpha 2 of jQuery-Mobile is that panels no longer have to be inside the page that uses them. Instead, external panels can be siblings to the pages.
This works fine with static pages:
<div id="panel" data-role="panel" data-theme="b" data-position="left"
data-display="push">
<h3>This is a panel</h3>
</div>
<div data-role="page" id="staticPage">
<div data-role="header" data-position="fixed">
Panel
<h1>Static page</h1>
</div>
<div data-role="content">
<div class="content-primary">
Go to dynamic page
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$('#panel').panel();
});
</script>
However, when I generate and inject a page dynamically, the link to the panel no longer works as it is supposed to:
<script type="text/x-template" id="dynamicPageTemplate">
<div data-role="page" id="staticPage">
<div data-role="header" data-position="fixed">
Panel
<h1>Dynamic page</h1>
</div>
<div data-role="content">
<div class="content-primary">
<a href="#staticPage" data-role="button" data-inline="true">
Go to static page
</a>
</div>
</div>
</div>
</script>
<script type="text/javascript">
$(document).bind("pagebeforechange", function (e, data) {
if (typeof data.toPage === "string") {
var url = $.mobile.path.parseUrl(data.toPage);
if (url.hash.search(/^#dynamicPage$/) !== -1) {
$('#dynamicPage').remove();
var template = $("#dynamicPageTemplate").html();
var $page = $(template);
$page.attr('id', 'dynamicPage');
$('body').append($page);
$page.page();
$.mobile.changePage($page, {changeHash: false});
e.preventDefault();
}
}
});
</script>
When I click the "Panel" button in header of the dynamic page, the URL changes to …#panel and nothing is shown. I suspect that jQuery-Mobile tries to show the panel as a page rather than a panel. Am I doing something wrong, or is this a bug?
Fiddle with complete example
jQuery Mobile 1.4 panel (and a lot of other widgets) implementation still don't work correctly. Several new components are not even implemented yet. Not to mention, demo site was not updated since they announced alpha version 1.
Let me get back to pane implementation. It is still under heavy development. Any panel inner content (except buttons) is not properly styled. Just add a listview and see a final result.
Only thing you can do is wait for RC1 versions, or maybe just maybe first beta version (but I wouldn't hold my breath for the beta release).

Collapisble Set, jQuery Mobile, inject AJAX content

Given a basic jQuery Mobile Collapisible Set, how can I get AJAX content before the toggle event fires? I am using jQM to create the following:
<div id="test" data-role="collapsible-set" data-inset="false">
<div data-role="collapsible" data-collapsed="true" data-mini="true">
<h2>Title #1</h2>
<ul data-role="listview"></ul>
</div>
<div data-role="collapsible" data-collapsed="true" data-mini="true">
<h2>Title #2</h2>
<ul data-role="listview"></ul>
</div>
</div>
I want to be able to when a user clicks on the "toggle" fire of an AJAX call to get content from the server and place it in the correct ul. I can figure out how to do everything except intercept the "click". I have tried binding on both click and expand on the div's, h2's and even ul's.
I am looking for something like:
$('#test h2').live('click',function() {
// do my AJAX call here to get li's to put in correct ul (assuming none exist)
});
Surely I am missing something super simple.
Ok...Here is a working example (minus the AJAX). The biggest drawback is that this only "fires" on expand. But by then it has already expanded and thus currently shows a blank space. What is really needed is a "before expanding" or "click" event so that you can inject the content you want and then the default can happen (changing icons, showing, etc). Not sure how to go about proposing that...
http://jsfiddle.net/mfumm/
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css"/>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<div data-role="page" id="page">
<div id="set" data-role="collapsible-set" data-inset="false"></div>
</div>
$("#set div:jqmData(role='collapsible')").each(function () {
$(this).bind('expand', function() {
if($(this).find('li').length < 1) {
// do ajax call here to get data
$(this).find('ul').append(items).listview('refresh');
}
});
});
$('#page #set li').live('click',function () {
alert('Go to item');
});

How to get alert to only appear once in jQuery Mobile multiple page html

I have a multipage html (using "div data-role="page") that displays 4 pages of a document that can be swiped left or right to move between the pages back and forth.
I have an alert that I want to pop-up only when the page first loads (telling the user they can swipe to move back and forth between pages).
My problem is that it keeps popping up again every time a swipe to a new page is made and I only want it to alert them once when the page loads.
I've tried moving the script from the head to inside the element, and I've tried binding it to all the different pagecreate, pagebeforecreate, pageinit, etc. events and can't seem to figure it out.
I appreciate any advice or direction.
Here's the alert code that is currently showing on every page when swiped:
<script type="text/javascript">
$('div').live("pagecreate",function(event){
alert('Swipe left and right to move between the 5 pages of this lead sheet');
});
</script>
You can bind to the id for the page DIV (ex: div#home).
<script type="text/javascript">
$('div#home').live("pagecreate", function (event) {
alert('Swipe left and right to move between the 5 pages of this lead sheet');
});
</script>
...
<div data-role="page" id="home">
Live Example:
http://jsfiddle.net/FcjNR/1/
JS
var $alerted = false;
$('div').live('pageshow',function(event, ui) {
// Check for secure token here
if($alerted == false) {
$alerted = true;
alert('Can you see me now?');
}
});
HTML
<div data-role="page" id="home">
<div data-role="content">
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="f">
<li data-role="list-divider">Alert once</li>
<li>Alert Page</li>
</ul>
</div>
</div>
<div data-role="page" id="alert">
<div data-role="content">
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="f">
<li data-role="list-divider">The Alert</li>
<li>Home</li>
</ul>
</div>
</div>

Resources