jQuery Mobile cache pages in order - caching

I have a list of a tags that are hidden. I tried using the data-prefetch attribute as described in the jquery mobile docs. The only problem is it fires off an ajax request for all of them at once and there is no garentee of the order that they get loaded in.
The ordering is very important in what pages are shown next via swipe.
So I decided to try and cache the links programatically via this bit of code.
var last_cache_page = false;
function cache_next_page(){
if(last_cache_page == false){
var cache_link = $('.cache').first();
last_cache_page = cache_link;
}
else{
var cache_link = last_cache_page.nextAll('.cache');
last_cache_page = cache_link;
}
//Start Caching any other pages that we want to swip to
$.mobile.loadPage(cache_link.attr('href'), {showLoadMsg: false});
}
So on $(document).on('pageshow') I call cache_next_page(). That part works fine the real problem is that when using $.mobile.loadPage no jquery mobile page related events fire once the first cached page is interested into the dom.
I have tried pageshow, pageinit and pageload but they only fire the first time the page is loaded. Now if I load the first page which starts the caching directly. That is to say with out visiting any other pages in the application it DOES trigger all the expected events such as pageload.
It is only when you start on page_1 and then go to page_2 (which has the code to start the cache) that it fails to have a pageload event triggered when the cached page is inserted into the dom.

I found out there there is a .done on the object that is returned from .loadPage so I have modified my code as follows to allow it to cache my links in order.
var last_cache_page = false;
function start_caching(){
if(last_cache_page == false){
var cache_link = $('.cache').first();
last_cache_page = cache_link;
}
else{
var cache_link = last_cache_page.nextAll('.cache').first();
last_cache_page = cache_link;
}
if(cache_link.length == 1){
//Start Caching any other pages that we want to swipe to
new_page = $.mobile.loadPage(cache_link.attr('href'), {showLoadMsg: false});
new_page.done(function(){
start_caching();
});
}
}

Related

Load a Page Content without page refresh in Codeigniter/Bootstrap

I have created a Admin Panel in the header part with bootstrap , when i click on any nav bar option (ul->li->a) the whole page jerk and reload i want to load it smoothly with the hllp of ajax i.e, without page refresh.
How can i acheive that i have tried various material supplied in the net but it wont help.
I have limited knowledge in ajax.
Please help
Usually I think you've used jQuery. It's would be simplest. https://jquery.com
You'll need to have a back-end that should returns only part of your page (that needs to be loaded). Or use (not recommended) $.load
http://api.jquery.com/load/
If you have the back-end that returns part of your page:
var $container = $('#container'); // It's a block that will be used for content displaying
// Renderring content
function renderPage(response) {
// Wrapped content hidden by default
var $content = $('<div style="display: none">' + response + '</div>');
// Then clear current content
$container.find('*').remove();
// Then append our response and fade it to display
$content.appendTo($container).stop(true, true).fadeIn(300);
}
// Loading page
function loadPage(url, params) {
$.get(url, (params||{}), renderPage);
}
// Adding handler
function go(e) {
loadPage($(e).attr('href'));
return false;
}
And then in your items:
<ul>
<li>Page</li>
</ul>

Firefox Bootstrapped Add-On Injecting before load

Is it possible to add event listeners for a document before a page has been navigated to using a Bootstrapped add-on? I would like to see what page the user wants to navigate to as well as later after the page loads to inspect the DOM. I need to run code in the HTML content context.
In the past I used a toolbar XUL and included javascript within it and it would load before the HTML page loaded.
i looked into doing stuff before DOMContentLoaded sometime ago and found out there is a document inserted observer.
order of events after running research code at bottom
readystate changes to interactive (i think multiple times, not sure)
readystate changes to complete
DOMContentLoaded event fires
load event fires (Sometimes load doesnt fire, if you might have to change addEventListener with capture arugment (3rd argument) as false or true)
apparently there should be readystate loading before all of this but i can never catch it i dont know why.
after running the code in scratchpad, browser environemnt of course, then load a new page and watch the error console it will throw these reports in this order:
ready state changed! ("interactive") Scratchpad/4:18
02:28:07.873 ready state changed! ("complete") Scratchpad/4:18
02:28:07.874 DOMContentLoaded event fired! Scratchpad/4:53
02:28:07.938 Load event fired! Scratchpad/4:45
here is the research code. it adds a the listeners and observer to see whats firing.
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
var os = Cc['#mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
var LMObserver;
function myObserver() {
this.register();
}
myObserver.prototype = {
observe: function (subject, topic, data) {
//Cu.reportError(subject);
//Cu.reportError(data);
//i think subject is window element
subject.onreadystatechange = function () {
//loading
//interactive
//complete
Cu.reportError('ready state changed! ("' + subject.readyState + '")');
//var body = subject.documentElement.querySelector('body')
//you want to change title so you would do that here do something like: if (subject.readystate == 'complete') { subject.title = 'blah blah' }
//Cu.reportError('has body element: ' + body)
}
},
register: function () {
os.addObserver(this, 'document-element-inserted', false);
},
unregister: function () {
os.removeObserver(this, 'document-element-inserted', false);
}
};
//below this is the DOMContentLoaded thing i put this here so we can see what fires in what order
var pageLoad = function(event) {
var win = event.originalTarget.defaultView;
if (win && win.frameElement) {
return;
}
Cu.reportError('Load event fired!');
}
var pageDOMContentLoaded = function(event) {
var win = event.originalTarget.defaultView;
if (win && win.frameElement) {
return;
}
Cu.reportError('DOMContentLoaded event fired!');
}
LMObserver = new myObserver;
gBrowser.addEventListener("load", pageLoad, true);
gBrowser.addEventListener("DOMContentLoaded", pageDOMContentLoaded, true);
//gBrowser.removeEventListener("load", pageLoad, true);
//gBrowser.removeEventListener("DOMContentLoaded", pageDOMContentLoaded, true);
//LMObserver.unregister();
Here's some more indepth research on load events added with true or false as capture argument: https://github.com/Noitidart/event-listener-experiment-DOMC-and-load/blob/master/bootstrap.js

jQuery hashchange how to do?

I have made a jQuery thing; with will load content without refreshing the page. The code for that is:
$(document).ready(function(){
// initial
$('#content').load('content/index.php');
// handle menu clicks
$('#navBar ul li ').click(function(){
var page = $(this).children('a').attr('href');
$('#content').load('content/'+ page +'.php');
return false;
});
});
Now I want to have a sort of history thing in that, the code for that is:
(function(){
// Bind an event to window.onhashchange that, when the hash changes, gets the
// hash and adds the class "selected" to any matching nav link.
$(window).hashchange( function(){
var hash = location.hash;
// Set the page title based on the hash.
document.title = 'The hash is ' + ( hash.replace( /^#/, '' ) || 'blank' ) + '.';
// Iterate over all nav links, setting the "selected" class as-appropriate.
$('#nav a').each(function(){
var that = $(this);
that[ that.attr( 'href' ) === hash ? 'addClass' : 'removeClass' ]( 'selected' );
});
})
// Since the event is only triggered when the hash changes, we need to trigger
// the event now, to handle the hash the page may have loaded with.
$(window).hashchange();
});
Found on: http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
My Question is: how can i make the second code working with the first?
Since you haven't gotten an answer yet I will write it. You need the plugin jQuery hashchange for the code to run.
https://github.com/cowboy/jquery-hashchange
To implement a cache you could do something like
$('#content').load('content/index.php');
//create a cache object
var cache = {};
// handle menu clicks
$('#navBar ul li ').click(function(){
var page = $(this).children('a').attr('href');
//check if the page was already requested
if(cache[page] === undefined){
//if not fetch the page from the server
$.get('content/'+ page +'.php', function(data){
$('#content').html(data);
//save data in cache
cache[page] = data;
}else{
//use data from cache
$('#content').html(cache[page]);
}
return false;
});
Use History JS. It works for HTML5 pushState and also falls back to HTML 4 hashtags. Also works for keeping the state model when the page is refreshed.

jquery mobile ajax sends both GET and POST requests

Here is the problem:
By default jQuery Mobile is using GET requests for all links in the application, so I got this small script to remove it from each link.
$('a').each(function () {
$(this).attr("data-ajax", "false");
});
But I have a pager in which I actually want to use AJAX. The pager link uses HttpPost request for a controller action. So I commented the above jQuery code so that I can actually use AJAX.
The problem is that when I click on the link there are two requests sent out, one is HttpGet - which is the jQuery Mobile AJAX default (which I don't want), and the second one is the HttpPost that I actually want to work. When I have the above jQuery code working, AJAX is turned off completely and it just goes to the URL and reloads the window.
I am using asp.net MVC 3. Thank you
Instead of disabling AJAX-linking, you can hijack clicks on the links and decide whether or not to use $.post():
$(document).delegate('a', 'click', function (event) {
//prevent the default click behavior from occuring
event.preventDefault();
//cache this link and it's href attribute
var $this = $(this),
href = $this.attr('href');
//check to see if this link has the `ajax-post` class
if ($this.hasClass('ajax-post')) {
//split the href attribute by the question mark to get just the query string, then iterate over all the key => value pairs and add them to an object to be added to the `$.post` request
var data = {};
if (href.indexOf('?') > -1) {
var tmp = href.split('?')[1].split('&'),
itmp = [];
for (var i = 0, len = tmp.length; i < len; i++) {
itmp = tmp[i].split('=');
data.[itmp[0]] = itmp[1];
}
}
//send POST request and show loading message
$.mobile.showPageLoadingMsg();
$.post(href, data, function (serverResponse) {
//append the server response to the `body` element (assuming your server-side script is outputting the proper HTML to append to the `body` element)
$('body').append(serverResponse);
//now change to the newly added page and remove the loading message
$.mobile.changePage($('#page-id'));
$.mobile.hidePageLoadingMsg();
});
} else {
$.mobile.changePage(href);
}
});
The above code expects you to add the ajax-post class to any link you want to use the $.post() method.
On a general note, event.preventDefault() is useful to stop any other handling of an event so you can do what you want with the event. If you use event.preventDefault() you must declare event as an argument for the function it's in.
Also .each() isn't necessary in your code:
$('a').attr("data-ajax", "false");
will work just fine.
You can also turn off AJAX-linking globally by binding to the mobileinit event like this:
$(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false;
});
Source: http://jquerymobile.com/demos/1.0/docs/api/globalconfig.html

Loading Varying Number of files with Ajax

I have an HTML page that dynamically loads one to many HTML snippets that are used as modal forms on the page. The page comes out of a CMS, so the business users can decide "I want one form on this page" or "I want 6 forms on this page". Each of the links and it's loading info need to be a module that goes together and can be put on any page. When each of these links are chosen on the page, I'm outputting a snippet of code that will call an Ajax load script when the page loads.
Snippet Example:
<script>
$(document).ready(function()
{
load('/web_fragments/file.html', 'content_item1');
$('#item1').click(function(){
$('#rmi_item1').dialog("open");
return false;
});
$('#rmi_item1.modal').dialog({autoOpen: false, modal:true,
dialogClass:'modal', width:590});});
</script>
Request More Information
<div id="rmi_item1" class="appLvl mod modal dialog">
<div id="content_item1">
</div>
</div>
Each of the IDs and divs on the page have unique identifiers, I've just simplified them here for ease of reading. The problem is the load method. I have no idea how many of these will be on the page, so I can't really create multiple load methods. If there is only one item on the page, it all works great. Here is the load method I have now. I'm new to Ajax/jQuery, so I extend my apologies and beg you to be kind! :)
function load(url, target)
{
document.getElementById(target).innerHTML = ' Fetching data...';
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
if (req != undefined) {
req.onreadystatechange = function() {targetDiv(url, target);};
req.open("GET", url, true);
req.send("");
}
}
function targetDiv(url, target)
{
if (req.readyState == 4) { // only if req is "loaded"
if (req.status == 200) { // only if "OK"
document.getElementById(target).innerHTML = req.responseText;
}
}
}
Any suggestions or help is welcome as I am now officially about really to lose my mind over this error! Thanks!
I think your problem comes from this line
req = new XMLHttpRequest();
Here you use (and implicitly declare) a variable req. This variable is declared in the
global scope (window object)
Make this var local to the load function, like this
var req = new XMLHttpRequest();
This will prevent the second snippet to overwrite the req var and trash the first
snippet request that was just fired but not yet recieved.
Have a look to the jquery load method. This should make your code smaller and avoid
this problem.
hope this helps,

Resources