How to inject the same panel into multiple pages using jquery mobile - jquery-mobile

jQuery Mobile 1.3.1 has a very nice sliding panel feature, but the panel code must be placed within the same page it's used on.
I'm working on an app that needs to have the same panel on many pages. Instead of replicating code is there a way to dynamically inject the panel into these pages so that it will still retain the jqm panel functionality?

jQuery Mobile >= 1.4
Solution one:
Use an External panel that can be accessed from any page, this is in case you want to have the same panel contents in all pages.
Append panel to $.mobile.pageContainer once only on pagebeforecreate and then enhance the panel using $(".selector").panel().
var panel = '<div data-role="panel" id="mypanel" data-position="right" data-display="push"><h1>Panel</h1><p>stuff</p></div>';
$(document).one('pagebeforecreate', function () {
$.mobile.pageContainer.prepend(panel);
$("#mypanel").panel();
});
Add button to open the panel in each header (or wherever you want).
Note: When using External Panel data-theme should be added to panel div, as it doesn't inherit any styles/theme.
Demo
Solution two:
If you wish to do changes to panel before appending it, based on number of pages in DOM, add panel to each one with a different ID and a button to open that panel.
Note that you don't need to call any kind of enhancement, because you're adding panels on pagebeforecreate. Hence, panels will be auto-initialized once page is created.
var p = 1,
b = 1;
$(document).one('pagebeforecreate', function () {
$.mobile.pageContainer.find("[data-role=page]").each(function () {
var panel = '<div data-role="panel" id="mypanel' + p + '" data-position="right" data-display="push"><h1>Panel</h1><p>stuff</p></div>';
$(this).prepend(panel);
p++;
});
$.mobile.pageContainer.find("[data-role=header]").each(function () {
var panelBtn = ''
$(this).append(panelBtn);
b++;
});
});
Demo
Note: Make sure you use .one() not .on(), if you use the latter, panels will be added whenever a page is created.
jQuery Mobile <= 1.3
You can do it this way, using pagebeforecreate event and by checking if there is no Panel added already. Keeping in mind that panels markup should always be placed before [data-role=header] that's why I used .before().
There is no need to call any enhancement method since panels are added on pagebeforecreate. They will be initialized during that event.
Demo
Your panel
var panel = '<div data-role="panel" id="mypanel" data-position="right" data-display="push"><h1>Panel</h1><p>stuff</p></div>';
Add panels dynamically
$(document).on('pagebeforecreate', '[data-role=page]', function () {
if ($(this).find('[data-role=panel]').length === 0) {
$('[data-role=header]').before(panel);
}
});
Update
There are two alternative methods to inject "External Panel" dynamically.

For some one coming across this issue, there is something called External Panels in JQuery Mobile 1.4+, which can make our life easier.
http://demos.jquerymobile.com/1.4.0/panel-external/
You can do something like this.
<div data-role="panel" id="mainPanel">
<!-- .... -->
</div>
<div data-role="page" id="page1" >
<!-- .... -->
</div>
<div data-role="page" id="page2" >
<!-- .... -->
</div>

You can also do one thing create a panel at the end or start of all pages and open that by Id and script code mentioned below.....its working fine for me.
$(function(){
$("#navigation").enhanceWithin().panel();
});
<div data-role="page" id="page1">
<div data-role="main" class="ui-content ui-body-a ui-responsive">
<div data-role="header">
<div data-role="navbar">
<ul>
<li class="">
</li>
</li>
</ul>
</div>
</div>
</div>
</div>
<div data-role="page" id="page2">
<div data-role="main" class="ui-content ui-body-a ui-responsive">
<div data-role="header">
<div data-role="navbar">
<ul>
<li class="">
</li>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="ui-panel ui-panel-position-left ui-panel-display-reveal ui-body-b ui-panel-animate ui-panel-open" data-role="panel" id="navigation" data-position="left" data-display="overlay" data-theme="b" data-dismissible="true" data-swipe-close="true">
<div class="ui-panel-inner">
<ul class="">
</ul>
</div>
</div>

In order for hashcoder his response to work you need to initialize the external panel. Also add .enhanceWithin() to make listviews etc render properly within the panel.
Als add a data-rel=... attribute to the link via which you want to open the external panel.
<script>
$(function () {
$("div[data-role='panel']").panel().enhanceWithin();
});
</script>
<div data-role="panel" id="mainMenu">
<!-- .... -->
</div>
<div data-role="page" id="page1" >
Open main menu panel
<!-- .... -->
</div>
<div data-role="page" id="page2" >
Open main menu panel
<!-- .... -->
</div>

Related

How to prevent adding duplicate id on a page in a multi-page html document?

I have a header.jsp that I am including on all the pages to display header and logo of my project. It has a link that opens up panel.
//header.jsp
<div data-role="header">
Menu
<div data-role="panel" id="menuPanel" data-position-fixed="true" data-display="overlay" >My menu</div>
</div>
Now I am using a multi page html document. The header will be included on all the div's with data-role=page.
<div data-role="page" id="page1">
//include header
</div>
<div data-role="page" id="page2">
//include header here
</div>
My doubt is my header.jsp has a panel with id="menuPanel". Two div with the same id will be included twice on my html page. Even on clicking the link we might get unepected results.How can I resolve this and save my project from including two div with the same id in DOM. I want to keep header as a separate file.
Can my panel be opened in some other way apart from using id. Please suggest some solution
Change your header to use class and not id, and link to #:
<div data-role="header">
Menu
<div data-role="panel" class="menuPanel" data-position-fixed="true" data-display="overlay" >My menu</div>
</div>
And add some JavaScript to open/close the menu panel relative to current page:
$(document).on("click", ".menuButton", function(event)
{
var pageID = $(this).closest("[data-role=page]").attr("id");
$("#" + pageID + " .menuPanel").panel("toggle");
});
JSFiddle

Data-transition effects does not work with tab navigation jquery mobile

I try to bring some effects to my tabs navigation on my jquery-mobile page but it looks like that the data-transitions argument does not work combined with a tabs navigation.
My code looks like this:
<div data-role="header" data-theme="a" id="header">
<h1>Mainpage</h1>
</div>
<div data-role="main" class="ui-content">
<div data-role="tabs" id="tabs" >
<div data-role="navbar" data-iconpos="left">
<ul>
<li><a id="lblTab1" href="#location" data-ajax="false" class="ui-btn-active" data-icon="search" data-transition="pop">search</a></li>
<li><a id="lblTab2" href="#product" data-ajax="false" data-icon="location" data-transition="pop">product</a></li>
</ul>
</div>
<div id="location" class="ui-body-d ui-content" > content </div>
<div id="product" class="ui-body-d ui-content" > content2 </div>
</div>
</div>
</div>
so how is it possible to bring some effects to the navigation bar?
I use jquery-mobile 1.4.0
Page transitions don't work on tabs as transition classes are activated when hiding/showing pages. You can create your own transitions, use third party CSS transitions or use jQM default ones.
First, you need to listen to tabbeforeactivate event. This event omits a ui object containing data of previous (ui.oldPanel) and next panel (ui.newPanel). All you need is to add animation classes to ui-newPanel and remove them once animation ends by binding Animation End one time only using .one().
$("#tabs").on("tabbeforeactivate", function (e, ui) {
$(ui.newPanel)
.addClass("animation")
.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () {
$(this).removeClass("animation");
});
});
Demo - Custom animation by Daneden
Demo - jQM default transitions

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).

jQuery Mobile: Content doesn't load properly after changePage

My application has a button (on app.html) that leads to a new page with a navbar (app2.html). The Navigation has an internal link (Toolbar 2) that should show the internal div "page2".
When coming from the button with changePage() it is not able to display the content when clicking on the navigation. It seems like the reloadPage is not working.
app.html looks like this:
<body>
<!-- Home -->
<div data-role="page" id="page3">
<div data-role="content">
<a id="asdf" data-role="button" name="asdf">
Button
</a>
</div>
</div>
<script>
$('#asdf').click(function(){
$.mobile.changePage('app2.html', {transition: "slidedown", reloadPage: true, changeHash: true });
});
</script>
</body>
This is my app2.html:
<body>
<!-- Home -->
<div data-role="page" id="page1">
<div data-role="content">
<div id="navigation" data-role="navbar" data-iconpos="right">
<ul>
<li>
<a href="app.html" data-theme="" data-icon="">
Toolbar1
</a>
</li>
<li>
<a href="#page2" data-theme="" data-icon="check">
toolbar 2
</a>
</li>
<li>
<a href="app.html" data-theme="" data-icon="">
Toolbar 3
</a>
</li>
</ul>
</div>
</div>
</div>
<div data-role="page" id="page2">
<div data-role="content">
<div data-role="header">
<h3>asdfasd</h3>
</div>
</div>
</div>
</body>
Where's the problem? I'm using jQuerymobile 1.1.1 with jQuery 1.7.1.
Here are the files:
app.html
app2.html
You cannot have two jQuery Mobile pages in the second page. When you click on the link in app.html, it will do an ajax request to app2.html to get the data-role="page" and it expects only in the html file. You should read up on the difference between a single page template and a multi-page template.
You can find more in the docs, look for "Linking within a multi-page document".
tl;dr: You either need to put all the pages in one HTML file and link to the id or put all the pages in separate HTML files and link to the file.

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