I'm trying to implement panel functionality with jQuery Mobile 1.3.2. Here's my code:
<div data-role="page" id="homePage">
<section data-role="panel" class="row">
PANEL HERE..
</section>
<section data-role="header" class="row">
<div class="large-12 columns">
<h3>
Header..
</h3>
</div>
</section>
<section data-role="content" class="row">
<div class="large-12 columns">
CONTENT..
</div>
</section>
<section data-role="footer" class="row">
<div class="large-12 columns">
FOOTER..
</div>
</section>
<script type="text/javascript">
$(function ()
{
}());
</script>
</div>
When I run this is a browser, I get an error:
$.data(...) is undefined
I've traced it to line 10330 of jquery.mobile-1.3.2.js:
var $theme = $.data( page[0], "mobilePage" ).options.theme,
What am I missing?
I see that jQuery mobile panel is not compatible with jQuery 2.0.
You got the error:
TypeError: 'undefined' is not an object (evaluating
'a.data(d[0],"mobilePage").options')
Try downgrade to jQuery 1.9 it works with it.
Demo: http://jsfiddle.net/IrvinDominin/3wUts/
If you do a quick search in the jquery mobile javascript file (minified or not) for the term "mobilePage" and change it to "mobile-page" it will work. There should be only one match. I encountered this and got it working as such.
Source of the fix was: https://github.com/jquery/jquery-mobile/issues/6200
I added this code right after the script include lines in the header:
<script type="text/javascript" src="//code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
<script type="text/javascript">
var jqDataOrg = $.data;
$.data = function (a, b, c) { return jqDataOrg(a, b === "mobilePage" ? "mobile-page" : b, c); };
</script>
It allows me to continue to use jQuery 2 and CDNs for distribution. May have some side effects unknown to me so beware.
Related
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/
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).
I'm developing a mobile app using PhoneGap & jQuery Mobile. I'd like to keep my view files DRY. How do I achieve this in jQuery Mobile? Should I just put every page element in one HTML file?
Exactly, jQuery mobile is designed for that and I is the best approach to be followed.
you can have something like that:
<html>
<head>
<script src="jquerymobilelibrary.js"/>
</head>
<body>
<div data-role="page" id="page1">
<div data-theme="a" data-role="header"><h3>Header</h3></div>
<div data-role="content">
<div data-role="fieldcontain">
<label for="textinput2">Title</label>
<input name="" id="textinput2" placeholder="" value="" type="text">
</div>
<a data-role="button" href="#page2">Button</a>
</div>
</div>
<div data-role="page" id="page2">
<div data-theme="a" data-role="header"><h3>Header</h3></div>
<div data-role="content">
<!-- Content is empty -->
</div>
</div>
</body>
</html>
To switch between pages programmatically in JS you can use
<script>
$.mobile.changePage('#page2')
</script>
In jquery mobile site there is a simple but cool drag-and-drop UI builder to explore what the JQM library can do.
Hope it helps!
For app based on AngularJS, JQuery Mobile and JQuery Mobile Angular Adapter.
When i set ng-controller on tag with data-role="page", ng-model on select tag works perfectly:
<body ng-app>
<div data-role="page" id="product" ng-controller="Controller">
<div data-role="content">
<select ng-model="color" ng-options="c for c in colors"></select>
<button ng-click="Print()">print</button>
http://jsfiddle.net/ilya7u/Ddt7G/
When ng-controller present in body tag, variable associated with select tag through ng-model remains unchanged:
<body ng-app ng-controller="Controller">
<div data-role="page" id="product">
<div data-role="content">
<select ng-model="color" ng-options="c for c in colors"></select>
http://jsfiddle.net/ilya7u/qgbj2/
Why and how i can fix it? I want to use one controller in app with many pages!
including the ng-app in the html of your page will solve the problem
try
<html ng-app="myModule">
<body ng-controller="Controller">
<div id="product" >
<div data-role="content">
<select ng-model="color" ng-options="c for c in colors"></select>
<button ng-click="Print()">print</button>
</div>
</div>
</body>
</html>
and change the controller to
var myApp = angular.module('myModule',[]);
myApp.controller('Controller', function($scope) {
$scope.colors = ['red', 'black', 'white'];
$scope.color = $scope.colors[0];
$scope.Print = function () {
alert($scope.color);
};
});
updated fiddle here http://jsfiddle.net/qgbj2/2/
So it looks like there are really two scopes here. The page has its own scope, but the Print is in the parent scope. I've updated the fiddle to show that the color does indeed change, but the $scope.color in Print does not: http://jsfiddle.net/qgbj2/6/
To remedy this particular situation, I would pass in the color to Print from the DOM:
<body ng-app ng-controller="Controller">
<div data-role="page" id="product">
<div data-role="content">
<select ng-model="color" ng-options="c for c in colors"></select>
<button ng-click="Print(color)">print</button>
</div>
</div>
</body>
A general solution for this multiple scope situation does not occur to me at the moment.
My mobile website dynamically adds the header bar to reduce code redundancy.
However, I'm stuck with styling header section of a jquery mobile page.
When I see the generated HTML tags, it looks okay,
but its element is not decorated by jQuery Mobile.
After adding the content, I invoked
$(pageId).trigger('create');
Do you have any ideas?
This worked for me : http://jsfiddle.net/emBxx/2/
HTML:
<script type="text/javascript" src="js/main.js"></script>
...
<div data-role="page" data-theme="b">
<header></header>
<div data-role="content">
<div class="content-primary">
<br />
<ul data-role="listview" data-filter="true">
<li>Some</li>
<li>random</li>
<li>searchable</li>
<li>content</li>
<li>(list!)</li>
</ul>
</div><!--/content-primary -->
</div>
<footer></footer>
</div><!-- page end-->
<script>
appendJQMHeader('Injected header !');
appendJQMFooter('—Injected ftr!', 'JQM 1.3.1Beta');
</script>
JS, in js/main.js:
function appendJQMHeader(pageTitle) {
$('header').replaceWith(
'<header data-role="header" data-theme="f">'+
'<h1>'+pageTitle+'</h1>'+
'Home'+
'</header><!-- /header -->');
}
function appendJQMFooter(left, right) {
$('footer').replaceWith('<footer data-role="footer" data-theme="f" class="jqm-footer"><p>©'+left+'!</p><p class="jqm-version">—'+right+'</p></footer>');
}
Note: for JSfiddle, it require 'Framework & extension > No wrap - in <head>'
For stand alone version, it worked fine with html head calling js/main.js containing the JS. Then html body with appendJQMHeader() & appendJQMFooter(). See the fiddle :)
Instead of invoking the trigger method, I executed the below command, and it works well.
$('#pageHome').closest(":jqmData(role='page')").trigger('pagecreate');