I currently have a dialog that allows you to download a file, and another link (the one in question) to transfer the user to another page which links you to an external API.
When I pop up the dialog, I can click on close and the dialog closes properly. When I follow the external link the page loads correctly and everything like that.
However if I hit the back button, it keeps the #ui-dialog has in the URL and nothing is loaded into the page.
I have tried to set the changehash value to false, but when I do that and if I close the dialog, it takes me too far back in my browsers history.
$(document).ready(function () {
VaultManager.GetFolderConent(VaultManager.UserRootFolderGuid, "My Vault");
$.mobile.changePage.defaults.changeHash = false;
});
function PopDialog() {
$.mobile.changePage( 'MobileFileOptions.htm', { reverse:false, transition:'pop', role:'dialog' });
}
Instead of PopDialog(), I also tried this:
<a href="MobileFileOptions.htm" data-rel="dialog" data-transition="pop">
Here is MobileFileOptions.htm:
<div data-role="page">//I have tried data-role="dialog" as well
<div data-role="header" data-theme="e">
<h1 id="popupHeader">File</h1>
</div><!-- /header -->
<div data-role="content">
<div id="divFileName"></div>
<div id="divFileSize"></div>
<div id="divFileCreated"></div>
<ul data-role="listview" data-inset="true">
<li>Download</li>
<li>
<a href="BoxManager.aspx" data-rel="external" id="boxLink">
Send to Box.NET
</a>
</li>
</ul>
</div><!-- /content -->
</div>
Am I missing something somewhere?
I am fairly new with jQuery Mobile, so, I may have done some mistakes and I can't figure out to get much help from the docs.
Related
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>
I'm trying to get a function to run everytime jquery mobile loads a new page into the application, but currently, the code only gets run once on the first instance of a page loading.
HTML:
<div id="pageID" data-role="page" class="content_page">
<div data-role="header" data-id="bestHeader" data-position="fixed">
<h1>Header</h1>
</div><!-- end header -->
<section data-role="content">
<h2>Header2</h2>
<p>Content goes here</p>
</section>
<div class="bottomAd" data-role="footer" data-position="fixed">
<img src="ad2.jpg" width="100%">
</div>
<div data-role="footer" data-id="bestFooter" data-position="fixed">
<nav data-role="navbar">
<!-- navBar here -->
</nav>
</div><!-- end footer -->
</div><!-- end page -->
<div id="pageID2" data-role="page" class="content_page">
<div data-role="header" data-id="bestHeader" data-position="fixed">
<h1>Header</h1>
</div><!-- end header -->
<section data-role="content">
<h2>Header2</h2>
<p>Content goes here</p>
</section>
<div class="bottomAd" data-role="footer" data-position="fixed">
<img src="ad2.jpg" width="100%">
</div>
<div data-role="footer" data-id="bestFooter" data-position="fixed">
<nav data-role="navbar">
<!-- navBar here -->
</nav>
</div><!-- end footer -->
</div><!-- end page -->
Javascript
$(".content_page").live('pageinit', function(event) {
if ($(".bottomAd img[src*=ad]").length >= 1) {
console.log($(".bottomAd img[src*=ad]").length);
$(".bottomAd").remove();
}
No matter how many times you click back and forth between the two pages, the console.log only gets called once, and the .bottomAd class gets removed document wide on the first instance of the page getting clicked on. I'd like to have the function run everytime the page is called, so each time the "page" is checked for having an image with a src that contains "ad" in the bottomAd div on that specific page, and then removed if so.
If you want to do work on something each time a page is shown (either the first time or subsequent visits) then I suggest using pageshow, pageinit only fires the first time a page is shown and jQuery Mobile will keep pages in the DOM sometimes. If you want to run some code only the first time a user goes to a page then use pageinit but bind your delegated event handler to the document element.
I would also make your selector more specific (to the current page) so you don't work on elements on pages not being viewed like so:
...
//`this` refers to the `<data-role="page">` pseudo-page element being bound to
$(this).find(".bottomAd").remove();
..
Your delegated event handler should bind to an element always in the DOM, for example document:
$(".content_page").live('pageinit', function(event) {
should be
$(document).on('pageinit', '.content_page', function () {...});
Note that .live() was depreciated in jQuery 1.7 and that .on() is the new flavor.
You probably want to use the pageshow event, you also might want to use .on instead of .live as .live is depreciated,
For example
$(document).on('pageshow','.content_page' function(event) {
if ($(".bottomAd img[src*=ad]").length >= 1) {
console.log($(".bottomAd img[src*=ad]").length);
$(".bottomAd").remove();
}
There is also a pageload event but that is fired when an external page is attached to the DOM.
pageload Event
"Triggered after the page is successfully loaded and inserted into the DOM. Callbacks bound to this event will be passed a data object as its 2nd arg. "
http://jquerymobile.com/test/docs/api/events.html
I'm building a mobile app with Cordova, Backbone for the MVC structure and jQuery Mobile for UI.
This works well except for the user experience while loading a new page. Actually a new page is created dynamically, and when it's ready, jquery mobile handles the page transition to this page. In a mobile browser this transition is slower than in a classic browser, so while page is loading the user sees a blank white screen and then appears the new page.
The matter is about my header/footer bar. I'd like it to keep showing while the content is loading, so the user will see the header/footer and only a blank/white content during the transition.
So this is a classic page structure:
<div data-role="page">
<div data-role="header"></div>
<div data-role="content"></div>
<div data-role="footer"></div>
</div>
For me the easiest way to go is like that:
<div data-role="header"></div>
<div data-role="page">
<div data-role="content"></div>
</div>
<div data-role="footer"></div>
And fix the content with CSS positioning.
But I'd like to find something smarter.
What do you think of having a single JQM page, with Backbone just updating the <div data-role="content"> for each route? What about JQM rendering? And what about transitions?
Documentation: http://jquerymobile.com/demos/1.1.0/docs/toolbars/footer-persist-d.html
Basically you put a data-role="footer" element in each page like this:
<div data-role="footer" data-id="foo-footer" data-position="fixed">
<div data-role="navbar">
<ul>
<li>Friends</li>
<li>Albums</li>
<li>Emails</li>
<li><a href="d.html" >Info</a></li>
</ul>
</div><!-- /navbar -->
</div><!-- /footer -->
Notice the data-id, it must be the same on all data-role="footer" elements to take advantage of the persistent toolbar option. The data-role="footer" element also must have the data-position="fixed" attribute.
Here is a demo: http://jsfiddle.net/SpRAA/
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>
I have couple of pages on my mobile web site. One page lets user log in and the other show user their date and lets user log out. However, when user is logged out and redirected to the login page they can click on back button and get back to the page where they supposedly authenticated.
I just have one html page divided into multiple divs ("pages") and using $.mobile.changePage to navigate from one page to another.
How can I make it so that when user does click on back button they don't see their data?
When I browse back my 'pageinit' doesn't get executed. If it was I would be able to check if the user is logged in...
Example:
http://jsfiddle.net/GF8np/5/
JS
var $secure_token = true;
$('div').live('pageshow',function(event, ui) {
// Check for secure token here
if($secure_token != true) {
$.mobile.changePage("#login", { transition: "slideup"} );
}
});
// Act if user has logged out
$('#secure2').live('pageshow',function(event, ui) {
$secure_token = false;
});
HTML
<div data-role="page" id="login">
<div data-role="content">
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="f">
<li data-role="list-divider">Redirect</li>
<li>Secure Page 1</li>
<li>Secure Page 2</li>
</ul>
</div>
</div>
<div data-role="page" id="secure1">
<div data-role="content">
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="f">
<li data-role="list-divider">Secure Page 1</li>
<li>Secure Page 2</li>
</ul>
</div>
</div>
<div data-role="page" id="secure2">
<div data-role="content">
<p>Please hit the browser back button or right click and back</p>
</div>
</div>
I think it's normal behaviour, as any browser saves the previous webpage it rendered. I just tested with my own webpage, and it indeed shows the info, but whenever you try and change something, the system redirects to the login view.
I mean, they will see the previous data, but it will be stale, and they won't be able to change it without login in first.