I've built an app with multiple internal pages such as this:
<div id="states" data-role="page">
<div data-role="header"> Back
<h1>My List</h1>
</div>
<!-- /header -->
<div data-role="content"></div>
<!-- /content -->
<div data-role="footer" data-position="fixed" data-id="myfooter">
<div data-role="navbar">
<ul>
<li>Option</li>
<li>Home</li>
<li>Search</li>
</ul>
</div>
<!-- /navbar -->
</div>
<!-- /footer -->
</div>
<!-- /page -->
When the page is initialized, I load an XML file and populate the pages dynamically. This works fine. If I refresh the screen on the default internal page, it reloads without an issue. I can go 1 or two pages deep, hit the back button... and that works as well. I am using this code to maintain my hash history (I'm a noob).
$(document).bind( "pagebeforechange", function( e, info ) {
if ( typeof info.toPage === "string" ) {
var u = $.mobile.path.parseUrl( info.toPage ),
re = /^#.../;
if ( u.hash.search(re) !== -1 ) {
buildLists( u, info.options );
e.preventDefault();
}
}
});
The problem appears when I go to another page and hit refresh, my data comes back as undefined and all of my data.find(...) calls are void, throwing errors.
Has anyone had this problem? How can I make sure my data is either a) retained or b)reloaded. Is there something I am missing?
I've looked into this code but this isn't as dynamic as I require. All of my listviews are populated via the XML.
You're listening to the wrong event. pagebeforechange is triggered when you change the hash. You want to change it when the hash has changed, as in, when the browser sets it. Listen for 'hashchange.' I'd suggest learning how to do these things without jQuery because libraries just HIDE the actual technology.
If that doesn't work, abandon jQuery (I hate it an never use it and all my sites work on all devices). There's plenty of other ways of doing this. Here's one: http://www.davidpirek.com/blog/on-hash-change-javascript-listener
Related
I see many websites such as gitHub changing it's html content and URL without refreshing pages.
I find one possible way to do this in HTML Histroy API.
Here is the code.
HTML
<div class="container">
<div class="row">
<ul class="nav navbar-nav">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
<div class="row">
<div class="col-md-6">
<div class="well">
Click on Links above to see history API usage using <code>pushState</code> method.
</div>
</div>
<div class="row">
<div class="jumbotron" id="contentHolder">
<h1>Home!</h1>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
</div>
</div>
</div>
</div>
home.html
This is home page
about.html
This is about page
contact.html
That one is content page
JAVASCRIPT
<script type="text/javascript">
jQuery('document').ready(function(){
jQuery('.historyAPI').on('click', function(e){
e.preventDefault();
var href = $(this).attr('href');
// Getting Content
getContent(href, true);
jQuery('.historyAPI').removeClass('active');
$(this).addClass('active');
});
});
// Adding popstate event listener to handle browser back button
window.addEventListener("popstate", function(e) {
// Get State value using e.state
getContent(location.pathname, false);
});
function getContent(url, addEntry) {
$.get(url)
.done(function( data ) {
// Updating Content on Page
$('#contentHolder').html(data);
if(addEntry == true) {
// Add History Entry using pushState
history.pushState(null, null, url);
}
});
}
</script>
This code is working fine even you go back or forward in browser.
But the problem is that when you refresh page it only shows the file which is being refreshed. For example, if you refresh the about.html then only the following will show: This is the about page.
Unlike the gitHub it can't show the complete page. As you see in gitHub, even you refresh a page it will show the page same as how it was before refreshing.
How can I do that?
Thanks...
You may use Routie or Director to do the routing. And within their callback functions write the code to update the part of your HTML page, for this you may use Fragment.js.
You can change DOM anytime you want without loading the page.
Use fundamental XMLHTTPRequest or Ajax to contact the server without refreshing the browser.
There are many frameworks which offer convenient url routing which can change content automatically without page refreshes. Angular JS is my favorite such framework which offers great routing capability among many other things.
You have to check/set the value of your variable on the event onload of the page.
Your code does not work - when you click on a particular link the page does refresh. correct me if i am wrong.
Consider the following page layout:
<div id="page-container" class="">
<div id="scroller">
<!-- This page should be removed -->
<div id="page_1" class="pagina"></div>
<!-- These pages should be kept -->
<div id="page_2" class="pagina"></div>
<div id="page_3" class="pagina"></div>
<!-- This is the current page -->
<div id="page_4" class="pagina"></div>
<!-- These pages should be kept -->
<div id="page_5" class="pagina"></div>
<div id="page_6" class="pagina"></div>
<!-- These pages AND everything that follows should be removed -->
<div id="page_7" class="pagina"></div>
<div id="page_8" class="pagina"></div>
</div>
</div>
I have a function loadPage(pageNr) which loads a specific page and scrolls it into view.
I also have a function that load's two more pages on top, or below the current page depending on the scroll direction.
What I want to achieve now, is that when my loadPage() function is called, I want to keep 2 pages below and before the current page. All other pages should be removed. This is for speed purposes as my app has 748 pages in total.
What I have tried:
//Determine which pages on top of current page should be kept
var firstPageToKeep = (pageNr - 2);
//Delete every page on top that should not be kept in memory
for(x=0;x<firstPageToKeep;x++) {
console.log('x: '+x);
$('#page_'+x).remove();
}
//=================================
//Determine which pages below current page should be kept
var lastPageToKeep = (pageNr + 2);
//Delete every page below current page that should not be kept in memory
for(y=0;y<lastPageToKeep;y++) {
$('#page_'+y).remove();
}
This does remove every page except the current page. I believe I have set the limits of which pages should be deleted and which not. Why is everything deleted except the current page?
Try this code:
$('.pagina').each(function(i, page) {
if ((i < pageNr - 3) || (i > pageNr + 1)) {
$(page).remove();
}
});
http://jsfiddle.net/6NCmR/
Try This:
$("#scroller").children().not("#id1 #id2 ...").each(function(){//Your code});
My quick guess is, that your last for-loop deletes all pages up to lastPageToKeep, keeping only the last pages. You should iterate beginning from lastPageToKeep+1 up to the maximum number of pages.
Nevertheless I'd recommend to you the :lt and :gt selectors from jQuery!
I made a quick fiddle for you demonstrating the use:
http://jsfiddle.net/d6tZ6/
Note: As a side effect this will also remove the neccessity for having an ID for each page.
I have divided html page into :
<body>
<div class="menu_container">
<!-- added menu here -->
</div>
<div class="content">
<!-- body content here -->
</div>
</body>
I want to change the content of "content" div when I select menu item.
ie depending on menu item selection div content should change, like what happens in Tabviews.
How can I do so?
The latest versions of YUI include the concept of Pjax which uses History and Ajax to update the page. It's really easy to set up and it'll keep your URLs working. Check out the User Guide: http://yuilibrary.com/yui/docs/pjax/.
You only need to add the yui3-pjax class to each menu that updates the page, apply the Menu plugin, plug the Pjax plugin and have your server return the right HTML content.
<div id="menu-1" class="yui3-menu">
<div class="yui3-menu-content">
<ul>
<li class="yui3-menuitem">
<a class="yui3-menuitem-content yui3-pjax" href="/some-page.html">Some page</a>
</li>
</ul>
</div>
</div>
<div id="content">
<!-- here goes the page content -->
</div>
<script type="text/javascript">
YUI().use('node-menunav', 'pjax-plugin', function (Y) {
Y.one('#menu-1').plug(Y.Plugin.NodeMenuNav);
Y.one('#content').plug(Y.Plugin.Pjax);
});
</script>
This should do the trick:
Y.one('.menu_container').on('click', function(e) {
Y.one('.content').setHTML("<h1>Hello, <em>World</em>!</h1>");
});
Depending on the selector used instead of menu_container, you can update the content accordingly.
EDIT: In fact, delegate is probably better for your needs:
Y.one('.menu_container').delegate('click', onClick, '.menu-item');
http://jsfiddle.net/olan/w2jfh/
We have a single page application with two views (essentially, a list of items and a details page for the selected item). Both views are in separate html files, and we’re using sammy.js to transition/navigate between the pages. Everything was working great until we tried to add jQuery Mobile to the mix. Now, when we navigate to the second page (the details page), jQuery Mobile is not styling the page.
Our working app is not set up as described by jQuery Mobile’s multi-page template (i.e., having all page divs in the same html file and use their navigation system to load linked pages into the DOM via AJAX). But, is it possible to have separate pages, use something other than jQuery Mobile’s navigation, and still have jQuery Mobile style the second page? Or, is there a way to force jQuery Mobile to style the second page?
Here’s some code snippets that’ll hopefully help show what we’re doing. (Note: We’re also using ASP.NET razor views.)
index.cshtml
<body>
#RenderPage("Views/items.cshtml")
#RenderPage("Views/item.cshtml")
#Scripts.Render("~/bundles/jquery")
<script>
$(document).bind("mobileinit", function () {
$.mobile.ajaxEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.pushStateEnabled = false;
$.mobile.loader.prototype.options.text = "loading. please wait...";
$.mobile.loader.prototype.options.textVisible = true;
});
</script>
#Scripts.Render("~/bundles/jquerymobile", ...)
</body>
items.cshtml (this page gets loaded and rendered correctly)
<section id="items-view" class="view" data-role="page">
<section data-role="header">
....
</section>
<section data-role="content">
(navbars, ULs, LIs, etc. are here, with each LI a link to go to the details page)
</section>
<section data-role="footer">
....
</section>
</section>
item.cshtml (this page gets loaded but NOT rendered correctly, there is no jQuery Mobile styling)
<section id="item-view" class="view" data-role="page">
<section data-role="header">
....
</section>
<section data-role="content">
(ULs, LIs, listboxes, textboxes, etc. are here)
</section>
<section data-role="footer">
....
</section>
</section>
router.js (used to route between pages)
....
navigateTo = function (url) {
sammy.setLocation(url); // url = #/items or #/item/1234
},
....
In the js file for the item page, we’ve tried:
var $page = $("#item-view");
//$page.trigger("create");
//$page.listview("refresh");
//$page.page(); (this one kind of work but doesn’t style every object)
//$page.page("refresh", true);
but haven’t got any thing to work correctly and completely.
So, again, given our situation, is there a way to have a jQuery Mobile multi-page app with actual separate physical files and have all pages get style correctly? Or is there a programmatic way to force jQuery Mobile to style all pages correctly?
Thanks.
jquery mobile does NOT load everything from your second page.
when you require a new page with JQM (or it's ajax method), it loads parts of your page's DOMs and get all things under
<div data-role="page" id="yourPageID"></div>
so your could simply try put your stylesheet under "data-role", like this:
<div data-role="page" id="yourPageID">
<link rel="stylesheet" href="yourStyleSheetLink.css" />
</div>
then, when JQM requires a new page, your stylesheets will be loaded.
as a non-English speaker, i hope you can understand my words :)
I'm pretty sure there is a very simple solution here but I can't seem to think of the best approach. I'm using History.js which utilizes History API. Lets say I start with the following page:
<div ="header">
Header
</div>
<div id="content">
Content
</div>
<div id="footer">
Footer
</div>
The way I have been handling my AJAX calls is to replace the content of #content with the new html. So for example I load in text that says "content 2". This all works great until the user navigates back to the first page they hit on my site because it tries to load in the full first page (which includes #header and #footer so I end up with:
<div ="header">
Header
</div>
<div id="content">
<div ="header">
Header
</div>
<div id="content">
Content
</div>
<div id="footer">
Footer
</div>
</div>
<div id="footer">
Footer
</div>
I know there is a better way to structure my page to avoid this issue but I can't seem to figure out what it is. Here is the code I'm using:
(function(window,undefined){
var
History = window.History,
State = History.getState();
History.Adapter.bind(window,'statechange',function(){
var State = History.getState();
$.ajax({
url: History.getState().url,
cache: false
}).done(function( html ) {
$("#content").html(html);
});
});
})(window);
Any ideas on the proper way to handle this?
<?php
$is_ajax = isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && ( $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' );
if ( $is_ajax ) {
// Give the content
} else {
// Give a full page
}
?>