Rails 3 Handling Javascript for Mobile Users
I have a mobile version of my site that I'm developing. I'm using the technique described in Ryan Bates' Railscast episode to do the mobile detection. In a nut, you have to w开发者_运维百科rite a controller action that detects whether this is a mobile browser, and if so, set the request format to "mobile". So you can have views with the name format "file.mobile.erb" alongside "file.html.erb".
This works great. But I have a remote script execution to support, and I'd consequently like to have it serve up a mobile version of the Javascript as well.
Here's the form declaration in the view:
<%= form_for :humanity, :url=>{:action=>"human"}, :remote=>true do |h| %>
On the desktop version, it calls the controller action properly. In the log:
Processing by CardsController#human as JS
But when I call it from the mobile version, the log doesn't pick it out as JS:
Processing by CardsController#human as */*
So I first have to figure out how to get the form to tell the controller that it wants Javascript. Assuming I can do that, then I think this modification to @rbates' code should lock me in (as suggested by a commenter on that Railscast post). This is in application_controller.rb, in the prepare_for_mobile method:
if mobile_device?
if request.format == :js
request.format = :mobilejs
else
request.format = :mobile
end
end
So I have a "human.mobilejs.erb" file ready to fire, except it can't until the controller rightfully acknowledges that it's getting a JS request!
Looking forward to your generous assistance!
Aaron
Add !request.xhr? in the following function in your application_controller.rb
def prepare_for_mobile
session[:mobile_param] = params[:mobile] if params[:mobile]
request.format = :mobile if mobile_device? && !request.xhr?
end
It will respond to .js request with format.js
Also, as genkilabs suggested, use mobile_fu. It is awesome.
Aaron, you're actually on the right track. However, instead of checking for something like request.format == :js
(or worse, request.xhr?
which will kill you if you use a framework like jQuery Mobile), you will want to check for a mime type. Here what I did basically:
if mobile_device? and request.format.to_s == "text/html"
request.format = :mobile
elsif mobile_device? and request.format.to_s == "text/javascript"
request.format = :mobilejs
end
Then you can include a format.mobilejs {}
block and do pretty much what you would do with a regular js block (render out a Javascript template, etc.)
I got it working, but it feels like a nasty, hacky solution.
Following a hint on another SO post, I overrode the rendering in the controller action, like so:
if mobile_device?
render :file => "#{RAILS_ROOT}/app/views/cards/human.mobilejs.erb"
end
I had already registered "mobilejs" as a javascript mime type in /config/initializers/mime_types.rb:
Mime::Type.register_alias "text/javascript", :mobilejs
So it started hitting my mobile-only script. Hooray! But thereafter, every partial that I was trying to add in my script failed out, because it was also expecting a mobilejs format. So I created a new copy of each of those partials with a mobilejs extension, and it's working. Yucky, but it works.
I'm not sure I totally understand your question, but perhaps you could use something like mobile-fu for detection.
https://github.com/brendanlim/mobile-fu
This gives you methods like, is_mobile_device? # => Returns true or false depending on the device
Then just set the JS file you want to use by yielding from your layout. ie. in your layout put:
<!DOCTYPE html>
<html>
<head>
<title>sweet app</title>
<%= stylesheet_link_tag "jquery", :media => :screen %>
<%= stylesheet_link_tag "main", :media => :screen %>
<%= javascript_include_tag :defaults %>
<%= yield :script_includes %>
<%= csrf_meta_tag %>
</head>
Then in the view you are rendering you can choose which js tag to put there. So in some_view.html.erb or some_view.mobile.erb
<% content_for :script_includes do %>
<% if is_mobile_device? %>
<%= javascript_include_tag "jquery-mobile.js" %>
<% else %>
<%= javascript_include_tag "jquery-unmovable.js" %>
<% end %>
<% end %>
精彩评论