Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IE 8 shows raw ajax response on page reloading with jQuery BBQ

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?

like image 312
sunki Avatar asked Jun 01 '11 00:06

sunki


2 Answers

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
like image 41
FewKinG Avatar answered Nov 15 '22 05:11

FewKinG


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
like image 63
Jeff Kaufman Avatar answered Nov 15 '22 03:11

Jeff Kaufman