📜 ⬆️ ⬇️

iPhone version of the ROR site

No matter how you feel about the iPhone, you cannot deny that this phone has captured a good piece of the mobile device market. And, in my opinion, it was he who gave the opportunity to normally use the Internet from the phone. But although the built-in safari is complete (thanks, Webkit ), many people want to make a special version of the iPhone site that looks like a real iPhone app (for example, iweather.yandex.ru ).
iweatheriphone.livecookbook.ru
One of the most popular libraries for creating an adapted version of the site is iUI .

Cooking


First you need to make a special mime type by writing it in initializers / mime_types.rb:
Mime::Type.register_alias "text/html", :iphone

Now the erb-templates for the site will be called as * .iphone.erb (for example, index.iphone.erb).
You also need to write a before filter in ApplicationController, which will switch the site versions:
before_filter :adjust_format

def adjust_format
request.format = :iphone if iphone_request?
end

def iphone_request?
request.subdomains.first == "iphone"
end

There is one subtle point - you need to decide when you want to display the iphone version of the site. I chose to switch to the domain for myself, but no one bothers you to determine the iPhone by the HTTP_USER_AGENT header and not bother with the domains.

IUI basics


We are done with preparations, we are starting to create an iphone version of the site. On the website iUI download the latest version of the library. Unfortunately, the documentation on iUI is rather scanty, in fact limited to a couple of examples of sites - open source has its drawbacks :-).

Installing iUI consists of copying scripts, styles (iui * or iuix * files - the minimized version) and images into the corresponding directories of the site.
Making a new erb template (applitation.iphone.erb):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta id="viewport" name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<title>@page_title</title>
<%= stylesheet_link_tag 'iui' %>
<%= javascript_include_tag 'iui' %>
</head>
<body>
<div class="toolbar">
<h1 id="pageTitle"></h1>
<a id="backButton" class="button" href="#"></a>
</div>
<%= yield %>
</body>
</html>

In iUI, an unusual approach to navigation is that a page can be divided into several “screens” (physically, the screen is the root div or ul), the one who contains the selected parameter is considered active, and only that one is displayed. It looks like this:
<ul title="" selected="true">
<li><%= link_to " ", shoplist_path(current_user.shoplist), :target => "_self" %></li>
<li><%= link_to " ", "#recipes" %></li>
</ul>
<ul id="recipes" name="recipes">
<li><%= link_to "", recipes_path(:order => "date"), :target => "_self" %></li>
<li><%= link_to "", recipes_path(:order => "quality"), :target => "_self" %></li>
<li><%= link_to "", recipes_path(:order => "popular"), :target => "_self" %></li>
</ul>

When loading, the first list will be displayed, by clicking on the “all recipes” link, the screen will be changed to the second list (corporate iPhone scrolling). In order for the external link to work correctly, the target attribute needs to be set to "_self".
')

Form implementation


Now login page (app / views / sessions / new.iphone.erb):
<% form_tag sessions_path, :id => "auth", :name => "auth", :class => "panel", :selected => "true", :title => "", :target => "_self" do -%>
<script>
function toggleSession() {
document.auth.foreign_computer.value = (document.auth.foreign_computer.value == "1") ? "0" : "1";
}
</script>
<fieldset>
<div class="row">
<label> :</label>
<%= text_field_tag 'login' %>
</div>
<div class="row">
<label>:</label>
<%= password_field_tag 'password' %>
</div>
<div class="row">
<label> iPhone?</label>
<div class="toggle" onclick="toggleSession()" toggled="true">
<span class="thumb"></span>
<span class="toggleOff"></span>
<span class="toggleOn"></span>
</div>
<input type="hidden" name="foreign_computer" id="foreign_computer" value="0" />
</div>
</fieldset>
<%= submit_tag '' %>
<% end -%>

A normal checkbox does not steer, whether to remember a session is done with a proprietary switch (see fiction with div.toggle and javascript: toggleSession ()) :-). By the way, pay attention, the class “panel” makes the background of the page as in the settings of our mobile phone.

Link Customization - ajax screen update


Anyone who has not yet closed the browser, will tell you more about the links. Links in iUI are made quite cleverly, complete with target = "_ replace", which allows you to create a loadable list ( working example ). But, as is often the case, there are not enough standard tools - I wanted to make a transition from the list to a specific object without loading a new page, so that I could go back to the list, and it was in its original state. For these purposes, I modified the clicker in iui.js, adding a new target:
addEventListener("click", function(event) {
...
else if (link.target == "_custom_replace")
{
link.setAttribute("selected", "progress"); //
// ajax
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 4) {
//
var frag = $(link.getAttribute("target_elem"));
frag.innerHTML = req.responseText;
//
setTimeout(unselect, 1000, true);
//
iui.showPageById(link.getAttribute("target_elem"));
}
};
req.open(link.getAttribute("target_method") || "GET", link.href, true);
req.send(null);
}
...
}

I made the list of objects as follows:
<% if @first_page? %>
<ul title="" selected="true">
<% end %>

<% @recipes.each do |recipe| %>
<li>
<%= link_to recipe.name, recipe_path(recipe), :target => "_custom_replace", :target_elem => "recipe" %>
</li>
<% end %>
<% if @page < @recipes.total_pages %>
<li><%= link_to " ...", params.merge(:page => @page+1), :target => "_replace" %></li>
<% end %>

<% if @first_page? %>
</ul>
<% end %>

<% if @first_page? %>
<div id="recipe" name="recipe" class="panel"/>
<% end %>

This list is loadable, “digg-styled”, and the return from the page of the object to the list works, and works correctly , i.e. returning the user sees the list in the state in which it was left.

Conclusion


iUI is a handy tool for developing an iPhone version of the site, allowing you not to be distracted by the layout, and at the same time it is easily customized to the needs of the developer. In fact, this is a js + css + pack of pictures, so you can use it regardless of the language and framework of the system being developed.

The results of my work can be viewed on iphone.livecookbook.ru (authorization form, list of objects, “shopping list”), the described list of recipes is available without authorization. Modified iui.js is also easily available .

Source: https://habr.com/ru/post/42589/


All Articles