I use Ben Almans's jQuery BBQ and jQuery hashchange plugins on pagination links. Both work as expected in Opera and Firefox but do not in IE 8 (surprised, huh?). IE also works good with ajax, back button and hashchange, but fails when I clicking the reload button and shows raw ajax response instead of running it in previously loaded page.
So here is my ugly code and some explanations about features that Im trying to implement in my pagination:
1) Search engines friendly links (server responds html or js depending on javascript availability on client side).
2) Dynamically changeable url when JS is turned on (using the '#' symbol).
3) History and back button support.
4) Minimizing double requests (do not make ajax request if same content was loaded with html page).
JS:
$(function ($) {
if (ajax_init) {
$('.pagination a').live("click", function () {
$.bbq.pushState({page: $.deparam.querystring($(this).attr('href')).page});
return false;
});
$(window).bind("hashchange", function(e) {
var anchor = $.deparam.fragment().page;
var query = $.deparam.querystring().page;
if (ajax_load(anchor, query)) {
$(ajax_div).css('opacity', '0.4');
$(ajax_div + '-processing').removeClass('hidden');
$.ajax({
type: 'GET',
url: $.param.querystring('', {page: anchor}),
dataType: 'script',
cache: false
});
}
});
$(window).trigger('hashchange');
}
});
function ajax_load(anchor, query) {
if ((anchor && anchor !== query && !(!query && anchor == 1)) || $('#noscript').length < 1) {
return true;
}
else {
return false;
}
}
Template (Rails view):
<div id="products-container" >
<div id="products-processing" class="hidden">
<%= image_tag "spinner.gif" %>
</div>
<div id="products">
<div id="noscript">
<%= render "products_list.erb" %>
</div>
<script type="text/javascript">
var ajax_init = true;
var ajax_div = '#products';
var anchor = $.deparam.fragment().page;
var query = $.deparam.querystring().page;
if (!ajax_load(anchor, query)) {
url = anchor ? anchor : (query ? query : 1);
$.bbq.pushState({page: url});
}
else {
$('#noscript').hide();
$('#products-processing').removeClass('hidden');
}
</script>
</div>
<div id="products-min-height"></div>
</div>
AJAX template (Rails js view):
$('#products').html('<%= escape_javascript(render "products_list") %>').css('opacity', '1');
UPD: IE doesnt send request type header (or Rails cant determine it) while refreshing. So Rails generates JS view instead of HTML. Solved by:
respond_to do |format|
request.format.js? ? (format.js {render :index}) : (format.html {render :index})
end
Is there a better solution?
I had the same issue with IE8. My controller was serving JS as well as HTML responses. For me ensuring the html format block is noted first in the code solved the issue:
This doesn't work because rails responds with the js template:
respond_to do |format|
format.js
format.html
end
This however works just fine:
respond_to do |format|
format.html
format.js
end
IE appears to ask for "*/*" on refresh, and rails seems to think javascript is a better response than html. Because refreshing should only happen for html, telling rails that "*/*" means html fixes this issue:
before_filter :set_request_type
...
protected
def set_request_type
request.format = :html if request.format == "*/*"
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With