HTML5-移动开发秘籍-全-

HTML5 移动开发秘籍(全)

原文:zh.annas-archive.org/md5/56F859C9BE97C2D5085114D92EAD4841

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

我如何创建快速响应的移动网站,使其在各种平台上运行?对于开发人员来说,处理各种具有独特屏幕尺寸和性能限制的移动设备的增多是一个重要问题。本书提供了答案。您将学习如何有效地应用最新的 HTML5 移动网络功能,以适应各种移动设备。

HTML5 移动开发食谱将向您展示如何规划、构建、调试和优化移动网站。应用最新的适合移动设备的 HTML5 功能,同时发现新兴的移动网络功能,以集成到您的移动网站中。

构建坚固的默认移动 HTML 模板,并了解移动用户交互。利用基于位置的移动特性和移动丰富媒体,使您的网站快速响应。使用调试、性能优化和服务器端调优使您的移动网站完美。本书最后预览了未来移动网络技术。

本书内容

第一章, HTML5 和移动网络,介绍了 HTML5 和移动网络,以及一些仿真器和模拟器。

第二章, 移动设置和优化,讨论了各种移动设置和优化,如防止文本调整大小和优化视口宽度。

第三章, 移动事件的交互媒体,讨论了移动交互,如手势事件。

第四章, 构建快速响应的网站,讨论了使移动网站快速响应的各种方法。

第五章, 移动设备访问,讨论了基于位置的移动网络和其他 HTML5 设备特定功能。

第六章, 移动丰富媒体,讨论了可在移动浏览器上使用的 HTML5 丰富媒体元素。

第七章, 移动调试,教你如何解决移动屏幕限制并有效地调试移动网站和 Web 应用程序。

第八章, 服务器端调优,专注于移动网站的服务器端调优。

第九章, 移动性能测试,教你使用各种工具和技术来提升移动性能。

第十章, 新兴移动网络功能,讨论了 ECMAScript 5 以及为移动设备添加的特定功能,以实现更多的移动功能和提升性能。

本书所需内容

本书中大多数示例只需要一个文本编辑器。您还应该有一个移动设备,如 iPhone、Android、Blackberry 或其他适合测试的设备。虽然最好在真实设备上测试,但如果您没有,也不用担心,因为我们将介绍如何使用仿真器和模拟器进行测试,以防真实设备不可用。

本书适合对象

开发人员希望创建快速响应的 HTML5 移动网站,以适应各种移动设备。

约定

在本书中,您会发现一些文本样式,用于区分不同类型的信息。以下是一些样式的示例及其含义的解释。

文本中的代码示例如下所示:“geolocationnavigator对象上的一个新属性。”

代码块设置如下:

var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var accuracy = position.coords.accuracy;

当我们希望引起您对代码块的特定部分的注意时,相关行或项目将以粗体显示:

var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var accuracy = position.coords.accuracy;

新术语重要词汇以粗体显示。屏幕上看到的词语,比如菜单或对话框中的词语,会以这种方式出现在文本中:"在捕获选项对话框中点击开始按钮开始捕获。"

注意

警告或重要提示会以这样的方式显示在一个框中。

提示

提示和技巧会显示为这样。

第一章:HTML5 和移动网络

在本章中,我们将涵盖:

  • 准备好你的移动设备

  • 仿真器和模拟器

  • 设置移动开发环境

  • 在移动网络上使用 HTML5

  • 使 HTML5 跨浏览器渲染

  • 为移动设计

  • 确定你的目标移动设备

  • 制定内容适应策略

介绍

HTML5 和移动网络都是有前途的技术。两者的历史都相对较短。在本章中,我们将主要涵盖一些基础知识。这是为了帮助你快速开始移动开发,并付出最少的努力。

移动和 HTML5 仍在不断发展,你可能会有很多疑问。我们将解答这些疑问,让你专注于重要的事情。

移动网络发展迅速。我们现在有移动 Safari,这是 iPhone 上使用最广泛的应用之一,让开发人员能够构建高性能的网络应用,并增强用户的浏览体验。你不需要开发者账户来托管和运行移动网站,也不需要从任何应用市场获得批准来推出移动网站,而且你可以随时进行更新,而不必等待批准。这些都是移动网络开发的好处,但与此同时,也存在一些挑战,比如浏览器之间的不一致性,与原生应用相比缺少某些功能,以及安全性。我们无法解决所有问题,但我们肯定可以解决其中一些。在开发移动网站时,我们将看到如何将常规做法与最佳实践区分开来。

市面上有成千上万款智能手机;你不需要每一款都来测试你的应用。事实上,你可能只需要不到 10 款。如果这仍超出你的预算,那么两款设备就足够了。至于其他设备,你可以使用模拟器/仿真器来完成工作。本书重点关注六款 A 级移动设备,特别关注 iPhone、Android 和 Windows Phone:

  • iOS

  • Android

  • Windows Mobile

  • Blackberry v6.0 及以上版本

  • Symbian 60

  • Palm webOS

有两种与设备无关的浏览器也将在本书中介绍。它们是:

  • Opera Mobile

  • Firefox Mobile

其他浏览器不在列表中并不意味着它们不会受到我们在本书中讨论的问题和技术的影响。

确定你的目标移动设备

目标浏览器:全部

你不可能为每个移动设备制作一个移动网站。没有人有时间或精力这样做。

跨浏览器移动网络开发可能会很复杂。很难定义工作的范围,正如John Resig(jQuery Mobile 的创始人)在他的演示幻灯片中指出的那样,他提出了三个问题:(www.slideshare.net/jeresig/testing-mobile-javascript)。

  • 哪些平台和浏览器最受欢迎?

  • 哪些浏览器能够支持现代脚本?

  • 我需要哪些设备和模拟器来进行测试?

在构建移动网站时,你必须问自己类似的问题,但不是完全相同的问题,因为记住你的网站应该专门针对你的目标受众。所以你的问题应该是:

  • 访问我网站的访客最常用的平台和浏览器是哪些?

  • 有多少人从能够支持现代脚本的移动设备访问我的网站?

  • 我需要哪些设备和模拟器来进行测试?

访问我网站的访客最常用的平台和浏览器是哪些?

现在让我们回答第一个问题。在构建移动网站之前,你必须首先找出你的目标受众是谁,以及他们在访问你网站时使用的移动设备。有许多分析工具可以帮助你回答这些问题。其中之一就是 Google Analytics。你可以在www.google.com/analytics/免费注册一个 Google Analytics 账户。

做法非常简单:大多数开发人员对 Google Analytics 并不陌生。您只需从 Google Analytics 网站中包含 JavaScript 片段并嵌入到您的网页中即可。

大多数现代智能手机都可以渲染 JavaScript,因此在桌面站点和移动站点上使用它并没有真正的区别。

有多少人通过支持现代脚本的移动设备访问我的网站?

现在让我们回答第二个问题。您可能想要了解的一件事是使用移动浏览器浏览您的网站的人数。您还想了解有多少人使用根本不支持 JavaScript 的旧版移动浏览器。这是因为如果使用低端智能手机的人数比使用高端智能手机的人数更多,那么首先使用 HTML5 可能并不值得(尽管这种可能性非常低)。

因此,如果您的目标不仅是了解使用智能手机的人数,还要了解使用旧版移动电话的人数,Google Analytics for mobile 就可以派上用场。您可以从以下网址下载脚本:

code.google.com/mobile/analytics/download.html#Download_the_Google_Analytics_server_side_package

Google Analytics for mobile 服务器端包目前支持 JSP、ASPX、Perl 和 PHP。让我们看看 PHP 中的一个示例。您只需将ACCOUNT ID GOES HERE更改为您的 GA 帐户 ID。但请记住用'MO-xx'替换'UA-xx'

不幸的是,当您使用服务器端版本时,您不能在同时使用标准的 JavaScript 跟踪代码ga.js的页面上使用它。使用服务器端版本意味着您必须放弃 JavaScript 版本。这可能会很烦人,因为 JavaScript 版本提供了许多在服务器端版本中缺失的动态跟踪机制:

<?php
// Copyright 2009 Google Inc. All Rights Reserved.
$GA_ACCOUNT = "ACCOUNT ID GOES HERE";
$GA_PIXEL = "ga.php";
function googleAnalyticsGetImageUrl() {
global $GA_ACCOUNT, $GA_PIXEL;
$url = "";
$url .= $GA_PIXEL . "?";
$url .= "utmac=" . $GA_ACCOUNT;
$url .= "&utmn=" . rand(0, 0x7fffffff);
$referer = $_SERVER["HTTP_REFERER"];
$query = $_SERVER["QUERY_STRING"];
$path = $_SERVER["REQUEST_URI"];
if (empty($referer)) {
$referer = "-";
}
$url .= "&utmr=" . urlencode($referer);
if (!empty($path)) {
$url .= "&utmp=" . urlencode($path);
}
$url .= "&guid=ON";
return $url;
}
?>

Google Analytics 的替代方案

Google Analytics 并不是市场上唯一的移动分析服务。还有其他提供更专业服务的服务。例如,PercentMobile是一个托管的移动分析服务,可以清晰地展示您的移动受众和机会。您可以在以下网址了解更多关于这项服务的信息:

percentmobile.com/

Google Analytics 的准确性

移动设备报告的位置可能并不总是准确;Google Analytics 使用 IP 地址来确定地图叠加报告的用户位置。它们可能存在不准确性,因为移动 IP 来自无线运营商网关,这并不一定与移动用户位于同一位置。

服务器加载速度问题

由于服务器端处理,可能会产生一些额外的服务器负载。Google 建议您首先在您的一些页面上测试片段,以确保一切正常,然后再推广到整个网站。

设置移动开发工具

目标浏览器:全部

现在,前一个问题仍然没有得到答复:我需要哪些设备和模拟器来进行测试?我们将在这里找到答案。

如果您已经确定了要支持的主要移动设备,现在是时候看看如何设置它们了。如果您在各种移动设备上进行测试,移动开发可能会很昂贵。尽管我们有所有这些移动模拟器和仿真器可供测试,但与在真实设备上测试相比,效果并不好。现在让我们看看如何最大程度地覆盖测试并最小化成本。

准备就绪

我们在这里要做一些假设。每种情况都不同,但思路是一样的。假设您的桌面上使用的是 Windows 操作系统,但您网站的顶级访问者使用的是 iOS、Android 和 Blackberry。

如何做…

你的目标是最大程度地覆盖并最小化成本。这三种设备都有模拟器,但并非所有都支持不同的平台。

名称 兼容性
iOS 模拟器 Mac
Android 模拟器 Windows, Mac, Linux
黑莓模拟器 Windows

正如你所看到的,由于 iOS 模拟器只适用于 Mac,如果你使用的是 Windows 操作系统,最好且唯一的选择是购买 iPhone 进行测试。对于 Android 和黑莓,因为它们都有 Windows 的模拟器,为了节约预算,你可以下载模拟器。

它是如何工作的...

  1. 列出人们用来浏览你的网站的热门移动设备。

  2. 了解你用于开发的机器操作系统。

  3. 了解每个设备模拟器与您的开发环境的兼容性。

还有更多...

如果你的预算可以支持多个不同操作系统的移动设备,你可以进一步考虑屏幕尺寸和移动设备的 DPI。你可能不需要购买两台高端设备。例如,拥有 iPhone4 和 Android Thunderbolt 并非必要。你可以购买一台低端的 Android 设备来测试你的网站在低端设备上的显示效果。因此,思路是结合操作系统、移动设备和模拟器,以最大程度地覆盖各种场景。

设备模拟器/模拟器下载查询表

以下表格显示了用于移动网页设计和开发测试的流行移动设备模拟器的列表:

名称 类型 兼容性 URL
iOS 模拟器 Mac developer.apple.com/devcenter/ios/index.action#downloads
Android 模拟器 Mac, Win, Linux developer.android.com/sdk/index.html
HP webOS 虚拟机 Mac, Win, Linux developer.palm.com/index.php?option=com_content&view=article&id=1788&Itemid=55
Nokia Symbian 模拟器 Win www.forum.nokia.com/info/sw.nokia.com/id/ec866fab-4b76-49f6-b5a5-af0631419e9c/S60_All_in_One_SDKs.html
黑莓 模拟器 Win us.blackberry.com/developers/resources/simulators.jsp
Windows Mobile 7 模拟器 Win www.microsoft.com/downloads/en/details.aspx?FamilyID=04704acf-a63a-4f97-952c-8b51b34b00ce

浏览器模拟器/模拟器下载查询表

除了设备测试工具,我们还有针对平台独立浏览器的工具,特别是 Opera 和 Firefox。这些显示在下表中:

名称 类型 兼容性 URL
Opera Mobile 模拟器 Mac, Win, Linux www.opera.com/developer/tools/
Opera Mini 模拟器 Mac, Win, Linux www.opera.com/developer/tools/http://www.opera.com/mobile/demo/
Firefox for Mobile 模拟器 Mac, Win, Linux www.mozilla.com/en-US/mobile/download/

远程测试

除了模拟器和模拟器,还有一些测试框架可以让你远程访问真实设备。其中一个工具是DeviceAnywhere;一个问题是它不是免费的。

www.deviceanywhere.com/

黑莓模拟器

目标浏览器:黑莓

大多数移动设备模拟器在其网站上遵循说明进行安装和配置,但 BlackBerry 模拟器与其他移动设备模拟器的工作方式不同。对于 Blackberry 设备模拟器,除了下载模拟器外,还需要下载并安装BlackBerry Email and MDS Services Simulator以连接到互联网。

准备工作

确保您已经选择了一个要从中下载的模拟器:us.blackberry.com/developers/resources/simulators.jsp

如何做...

首先,转到页面:swdownloads.blackberry.com/Downloads/entry.do?code=A8BAA56554F96369AB93E4F3BB068C22&CPID=OTC-SOFTWAREDOWNLOADS&cp=OTC-SOFTWAREDOWNLOADS。在那里,您将看到一个类似以下截图的产品列表:

如何做...

现在选择BlackBerry Email and MDS Services Simulator Package,然后点击下一步

下载并安装软件后,您必须先启动服务模拟器,然后再启动 Blackberry 模拟器,以允许其连接到互联网。

以下是 Blackberry 模拟器的屏幕截图:

如何做...

设置移动开发环境

目标浏览器:所有

在开始移动 Web 开发之前,我们必须先设置开发环境。

准备工作

  1. 在您的机器上设置本地主机。对于 Windows、Mac 或 Linux,设置它的最简单方法是使用流行且免费的 XAMPP 软件:(www.apachefriends.org/en/index.html)。

  2. 确保您有无线连接。

  3. 您还应该随身携带一个移动设备。否则,使用移动模拟器/仿真器。

  4. 确保您的移动设备和桌面在同一个无线网络上。

如何做...

  1. 创建一个 HTML 文件,并将其命名为ch01e1.html,放在您的本地主机的根目录下:

ch01r01.html中,输入以下内容:

<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<header>
Main Navigation here
</header>
body content here
<footer>
Footer links here
</footer>
</body>
</html>

  1. 现在获取您的 IP 地址。如果您使用 Windows,可以在命令提示符中输入以下命令:
ipconfig

提示

下载本书的示例代码

您可以从您在www.PacktPub.com的帐户中下载您购买的所有 Packt 图书的示例代码文件。如果您在其他地方购买了这本书,您可以访问www.PacktPub.com/support并注册,以便将文件直接发送到您的邮箱

  1. 一旦您获得了您的 IP 地址(例如,192.168.1.16.),在您的移动浏览器 URL 地址栏中输入它。现在您应该看到页面加载,并显示文本:如何做...

它是如何工作的...

在同一个网络中,您的移动设备可以通过您的桌面 IP 地址访问您的桌面主机。

还有更多...

如果您没有移动设备,可以使用其中一个模拟器进行测试。但建议至少有一两台真实的移动设备进行测试。模拟器可以测试大多数事情,但并不是所有事情都能准确测试。

在 Safari 桌面上进行测试

如果您的主要目标受众是 iPhone 移动 Safari 用户,您也可以在桌面上进行测试以节省时间。为此,打开 Safari,转到首选项,点击高级选项卡,勾选显示开发菜单栏,如下所示:

在 Safari 桌面上进行测试

现在点击当前页面的显示菜单,选择开发 | 用户代理 | 移动 Safari 3.1.3 - iPhone:

在 Safari 桌面上进行测试

模拟器/仿真器的社区集合列表

如果您真的没有手机在手边,可以找到一份可用的模拟器和仿真器列表。您可以在 Mobile Boilerplate 项目的 wiki 上找到这个列表:

github.com/h5bp/mobile-boilerplate/wiki/Mobile-Emulators-&-Simulators

Firtman 的仿真器/模拟器收藏清单

Maximiliano Firtman,一位移动和 Web 开发者,也是一位作者,他在自己的网站上维护着仿真器的清单:

www.mobilexweb.com/emulators

在移动网络上使用 HTML5

目标浏览器:所有

现在我们将为你的移动设备创建一个简单的 HTML5 页面。如果你已经有了对旧版本 HTML 的经验,HTML5 应该很容易理解。如果你以前为桌面创建过网页,那么为移动设备创建一个网页对你来说也不难。

准备工作

创建一个新文件ch01e2.html

如何做到...

将以下代码保存在文件中:

<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
hello to the HTML5 world!
</body>
</html>

现在在你的移动浏览器中渲染这个页面,你应该看到文本的渲染效果与预期一样。

它是如何工作的...

你可以看到,HTML5 和其他 HTML 页面之间唯一的区别是我们使用的文档类型定义(DTD)<!doctype html>

你可能已经看到了<meta name="viewport" content="width=device-width, initial-scale=1.0">的代码,并想知道它的作用。它帮助 Mobile Safari 知道页面与设备一样宽。设置initial-scale=1告诉浏览器不要放大或缩小。

还有更多...

以下是 HTML5 的一点历史:HTML5 有两个草案版本,一个由 W3C 创建,另一个由 WHATWG 创建。W3C 由一个民主性质的团体管理,但在实践中进展缓慢。WHATWG 由Ian Hickson(也在 Google 工作)编辑,以及一群不公开的人组成。由于Ian做出了大部分决策,WHATWG 的版本进展更快。

HTML5 和版本号

你可能会想知道为什么 HTML5 在没有版本号的情况下使用声明如此模糊。有很多理由可以证明这一点:

  1. HTML 的版本支持对浏览器并不重要。重要的是功能支持。换句话说,如果浏览器支持你正在使用的 HTML5 功能,即使你将文档声明为 HTML4,它仍将按预期渲染 HTML5 元素。

  2. 更容易输入!

移动文档类型

你可能会问,使用 HTML5 DTD<!doctype html>是否安全。答案是 DTD 是用于验证的,而不是用于浏览器渲染。你接下来可能会问:怪癖模式呢?<!doctype html>是确保浏览器以标准模式渲染所需的最低信息。所以你可以放心使用<!doctype html>

你可能已经注意到我们使用<!doctype html>而不是<!DOCTYPE html>。原因是 HTML5 不区分大小写,但为了与其他 HTML 标签保持一致,我们将在整本书中使用小写。

学习 HTML5 的免费资源

有许多关于基本 HTML5 标签的优秀免费书籍和文章。如果你对 HTML5 不熟悉,可以查看以下内容之一:

如果你是那种真的想了解某件事的每一个细节的人,你可以阅读官方的 HTML5 规范。

规范的 W3C 版本在:

dev.w3.org/html5/spec/Overview.html

HTML Living Standard 的 WHATWG 版本在:

www.whatwg.org/specs/web-apps/current-work/multipage/

在不同浏览器中渲染 HTML5

目标浏览器:所有

有一些较旧的移动浏览器无法识别 HTML5 元素。问题在于,如果这些元素无法被识别,就无法对其进行样式设置。有许多 shim 来解决这个问题。其中一个是 Modernizr。

准备工作

  1. 其中一个不识别 HTML5 元素的移动浏览器是 Windows Mobile。如果您没有 Windows Mobile,您可以简单地使用 IE7 来测试,因为它们都是基于相同的引擎。

  2. 从网站下载 Modernizr:www.modernizr.com/。它是由Faruk Ateş, Paul IrishAlex Sexton编写的。

如何做...

  1. 创建一个 HTML 文件,并将其命名为ch01e3.html,然后在文件中输入以下代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
header, footer {display:block;}
</style>
</head>
<body>
<header>
Main Navigation here
</header>
body content here
<footer>
Footer links here
</footer>
</body>
</html>

  1. 现在创建另一个包含 Modernizr 的页面,并将其命名为ch01e4.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="img/modernizr-1.7.min.js"></script>
<style>
header, footer {display:block;}
</style>
</head>
<body>
<header>
Main Navigation here
</header>
body content here
<footer>
Footer links here
</footer>
</body>
</html>

如何做...

它是如何工作的...

记住,如果您在项目中使用 Modernizr,您应该始终在文件的头部在<head>标签的末尾之前包含它。还有其他用于类似目的的 polyfill,并且其中一些列在以下部分。

还有更多...

Modernizr 并不是唯一的脚本库助手;还有另外两个值得注意的:

  • html5shimRemy Sharp, Jonathan Neal & community编写,可用于打印,以及在:

code.google.com/p/html5shim/

  • innerShivJoe Bartlett编写,可用于 innerHTML 使用:

jdbartlett.github.com/innershiv/

HTML5 CSS 重置

您可能希望在样式表中重置一组新的 CSS HTML5 元素:

article, aside, canvas, details, figcaption, figure,footer, header,
hgroup, menu, nav, section, summary,time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit; vertical-align: baseline;
}

在较旧的 IE 中启用块级 HTML5 元素

在您的 CSS 中,您可能希望在 CSS 重置中包含一组块级 HTML5 元素。请注意,并非所有 HTML5 元素都必须显示为块级元素。

以下是一组块级 HTML5 元素的列表:

article, aside, details, figcaption, figure,footer, header, hgroup, menu, nav, section {
display: block;
}

Modernizr

Modernizr 不仅可以使 HTML5 元素在 CSS 中可样式化。它还有助于检测浏览器中用于呈现的 HTML5 功能支持。在 2.0 版本中,您将有选择自定义下载www.modernizr.com/download/的选项。

为移动设备设计

目标浏览器:所有

对于桌面设计,人们倾向于使用固定布局或流式布局。在移动设备上,几乎总是应该使用流式布局。流式布局可以使您的网站对浏览器调整大小做出响应。

准备工作

现在在您的文本编辑器中创建两个空的 HTML 文件,一个命名为ch01r06_a.html,另一个命名为ch01r06_b.html

如何做...

  1. ch01r06_a.html中,输入以下代码并保存文件:
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script src="img/modernizr-1.7.min.js"></script>
<style>
body, #main ul, #main li, h1 {
margin:0; padding:0;
}
body {
background:#FFFFA6;
}
#container {
font-family:Arial;
width:300px;
margin:0 auto;
}
header, footer {
display:block;
}
#main li{
list-style:none;
height:40px;
background:#29D9C2;
margin-bottom:0.5em;
line-height:40px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
border-radius: 15px;
}
#main li a {
color:white;
text-decoration:none;
margin-left:1em;
}
</style>
</head>
<body>
<div id="container">
<header>
<h1>Title here</h1>
</header>
<nav id="main">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Location</a></li>
<li><a href="#">Product</a></li>
<li><a href="#">About</a></li>
</ul>
</nav>
<footer>
Footer links here
</footer>
</div>
</body>
</html>

  1. ch01r06_b.html中,输入以下代码并保存文档:
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script src="img/modernizr-1.7.min.js"></script>
<style>
body, #main ul, #main li, h1 {
margin:0;
padding:0;
}
body {
background:#FFFFA6;
}
#container {
font-family:Arial;
margin:0 10px;
}
header, footer {
display:block;
}
#main li{
list-style:none;
height:40px;
background:#29D9C2;
margin-bottom:0.5em;
line-height:40px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
border-radius: 15px;
}
#main li a {
color:white;
text-decoration:none;
margin-left:1em;
}
</style>
</head>
<body>
<div id="container">
<header>
<h1>Title here</h1>
</header>
<nav id="main">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Contact Us</a></li>
<li><a href="#">Location</a></li>
<li><a href="#">Product</a></li>
<li><a href="#">About</a></li>
</ul>
</nav>
<footer>
Footer links here
</footer>
</div>
</body>
</html>

它是如何工作的...

当您在纵向模式下查看这两个网站时,它们看起来几乎一样:

它是如何工作的...

现在尝试旋转您的屏幕,看看会发生什么。

正如您现在所看到的,在横向模式下,第一个例子在左右两侧有空白,而第二个例子覆盖了屏幕的大部分空间:

它是如何工作的...

第二个例子显示了不同的结果:

它是如何工作的...

这个网站页面在固定布局中看起来非常尴尬,但在流式布局中看起来正常。因此,当您为移动设备设计时,始终记住您的网站应该具有这种灵活性。原因是:

  • 移动设备既有纵向模式又有横向模式

  • 移动设备的空间非常有限,因此您应该利用屏幕上的每个像素

还有更多...

CSS 媒体查询也是响应式设计的重要组成部分。它帮助您灵活设计移动设备。

<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script src="img/modernizr-1.7.min.js"></script>
<style>
body {
margin:0;
padding:0;
background:#FFFFA6;
}
#main section {
display:block;
border:5px solid #29D9C2;
width:60%;
height:120px;
margin:5% auto;
}
@media screen and (min-width: 480px) {
#main {
width:90%;
margin:0 auto;
}
#main > section:first-child {
margin-right:5%;
}
#main section {
float:left;
width:45%;
}
}
</style>
</head>
<body>
<div id="container">
<div id="main">
<section id="top-news"></section>
<section id="sports"></section>
</div>
</div>
</body>
</html>

在较窄的屏幕上呈现时,这两个部分将垂直布局,而在较宽的屏幕上呈现时,这两个部分将水平布局。我们用来实现这一点的技术是使用 CSS 媒体查询。就像在这个例子中,我们使用了@media screen and (min-width: 480px) {..},所以它的意思是页面在最小宽度为480px的页面上呈现时,其中的样式将被应用:

还有更多...

现在让我们在方向模式下看一下,如下所示。这两个框现在是相邻的。

还有更多...

首先桌面站点

除了构建纯粹的移动端或桌面端网站的想法,还有其他方式。其中之一是首先构建桌面站点,然后使其在移动端上优雅地降级。

首先移动端站点

另一种方法是首先构建移动端,然后使其在桌面上优雅地呈现。

其中一种方法在 CSS 中使用以下内容:

@media only screen and (min-width: 320px) {
/* Styles */
}
@media only screen and (min-width: 640px) {
/* Styles */
}
@media only screen and (min-width: 800px) {
/* Styles */
}
@media only screen and (min-width: 1024px) {
/* Styles */
}

一个网站的方法

第三种方法是拥有一个“一个网站”版本,而不是专注于移动端或桌面端,而是同时专注于两者。

定义内容策略

目标浏览器:全部

使用分析工具收集的数据,您可以制定您想要构建的策略。如果您已经有了网站的桌面版本,这将特别有用。

准备就绪

确保您的网站上已经嵌入了 JavaScript。

如何做...

  1. 转到您的分析工具,然后点击左侧导航下的访客 | 移动设备如何做...

  2. 现在,如果您点击移动设备,您可以看到人们用来浏览您网站的最常用设备:如何做...

它是如何工作的...

Google Analytics 可以帮助您找出访问您网站的最常用的移动设备,并找出您网站最受欢迎的部分。

还有更多...

您还可以确定您的移动站点上最有用的页面是什么。人们对待移动浏览与桌面浏览不同。例如,如果您经营一家销售产品的本地商店,大多数人倾向于在移动设备上浏览联系我们、位置服务等页面。相反,在桌面上,人们倾向于搜索产品目录、关于产品描述。Google Analytics 可以帮助您找出您网站上访问量最高的部分/页面。除了 Google Analytics,您还可以使用 PercentMobile,就像我们之前看到的那样。

还有更多...

浏览器等级

使用分析服务是决定要支持哪些设备的一种方式。另一种方式是使用浏览器等级来了解您应该针对哪个类别。jQuery Mobile 在jquerymobile.com/gbs/.上有一个出色的网格支持图表。还有一个关于移动浏览器 Web 开发的整体策略的 jQuery Mobile 幻灯片,网址是www.slideshare.net/jeresig/testing-mobile-javascript

移动矩阵

我一直在与Jonathan Neal和许多其他人合作,共同制定智能手机前端矩阵。您可以查看:

github.com/h5bp/mobile-boilerplate/wiki/Mobile-Matrices

它包含了市场上大多数智能手机的信息,它们的屏幕尺寸、DPI 和操作系统。

第二章:移动设置和优化

在本章中,我们将涵盖:

  • 添加主屏幕按钮图标

  • 防止文本调整大小

  • 优化视口宽度

  • 修复移动 Safari 屏幕缩放

  • 从浏览器启动特定于手机的程序

  • 启用 iPhone 全屏模式的开始屏幕

  • 防止 iOS 在焦点上缩放

  • 禁用或限制 WebKit 功能

介绍

虽然有许多操作系统(OS)以及设备制造商,但不可避免地可能会出现跨浏览器问题,这会给我们带来很多头疼。但另一方面,我们开发人员喜欢挑战,并着手解决这些问题!

在本章中,我们首先将关注跨浏览器/特定于浏览器的设置和优化,然后继续查看您可能希望在移动开发开始时添加的一些通用/特定于浏览器的功能。

添加主屏幕按钮图标

目标设备:iOS、Android、Symbian

在现代智能手机上,屏幕大多是触摸式的。iPhone 通过使设备上的一切都成为“应用程序”而改变了我们对移动设备的看法;即使是短信和电话拨号也像带有主屏幕图标的应用程序一样。对于 HTML 网络应用程序,情况有所不同;用户必须首先进入浏览器应用程序,输入地址,然后启动您的网站。从用户的角度来看,这可能是太麻烦了,因此在某些智能手机上,用户可以将主屏幕图标添加到特定的网络应用程序,以便他们可以直接从主屏幕上的图标启动该特定的网络应用程序网站。

听起来很酷,对吧?是的,但它也存在一些问题。当涉及到触摸图标时,并非所有浏览器的行为都是相同的。在这个教程中,我们将研究每个浏览器的行为以及如何使主屏幕图标尽可能地适用于尽可能多的移动浏览器。

准备就绪

首先,您必须从章节代码文件夹中下载图标集。如果您打开文件夹,您应该能够看到以下内容:

apple-touch-icon.png
apple-touch-icon-57x57-precomposed.png
apple-touch-icon-72x72-precomposed.png
apple-touch-icon-114x114-precomposed.png
apple-touch-icon-precomposed.png

这些图像将用于不同的设备。

创建一个 HTML 文档,并将其命名为ch02r01.html

如何做...

在您的 HTML 文档中,使用以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://icons/apple-touch-icon-114x114-precomposed.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://icons/apple-touch-icon-72x72-precomposed.png">
<link rel="apple-touch-icon-precomposed" href="http://icons/apple-touch-icon-precomposed.png">
<link rel="shortcut icon" href="http://icons/apple-touch-icon.png">
</head>
<body>
</body>
</html>

它是如何工作的...

现在让我们来分解代码:

从 iOS 4.2.1 开始,可以使用sizes属性为不同的设备分辨率指定多个图标。

<link rel="apple-touch-icon-precomposed" sizes="114x114" href="http://apple-touch-icon-114x114-precomposed.png">

对于 iPhone 4 的高分辨率 retina 显示屏,使用 114 x 114 的图标。

<link rel="apple-touch-icon-precomposed" sizes="72x72" href="http://apple-touch-icon-72x72-precomposed.png">

对于 iPad,可以使用 72 x 72 的图标。对于非 retina iPhone、Android 2.1+设备,使用 57 x 57 的低分辨率图标。

<link rel="apple-touch-icon-precomposed" href="http://apple-touch-icon-precomposed.png">

对于诺基亚 Symbian 60 设备,使用shortcut icon在链接关系中告诉设备有关快捷图标的信息。

<link rel="shortcut icon" href="img/l/apple-touch-icon.png">

这是 Android 上书签的样子:

它是如何工作的...

还有更多...

在看到上一个例子后,您的脑海中一定有一些问题:

  • rel属性中定义多个值不是可能的吗?那么我们能否将最后两行合并成以下内容?
<link rel="shortcut icon apple-touch-icon-precomposed" href="http://apple-touch-icon-precomposed.png">

已经测试过,但不知何故移动浏览器无法识别该值。

您可能已经看到人们使用:

<link rel="apple-touch-icon-precomposed" media="screen and (min-resolution: 150dpi)" href="http://apple-touch-icon-114x114-precomposed.png">

Paul IrishDivya Manian一起,我们一直在致力于 Mobile Boilerplate (www.h5bp.com/mobile),为前端移动开发提供了一个坚实的默认设置。在 Mobile Boilerplate 中,我们已经涵盖了所有当前的情景和可能的未来情景:

github.com/h5bp/mobile-boilerplate/blob/master/index.html#L21

Everything you always wanted to know about touch icons

这个主题上提出的大多数想法都源自Mathias Bynens。他的原始文章Everything you always wanted to know about touch icons可以在以下网址找到:mathiasbynens.be/notes/touch-icons

关于苹果触摸图标的官方文档

有一个官方文档列表,您可以在其中找到有关每个特定设备和浏览器的触摸图标的更多信息:

  • 苹果触摸图标:
http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html

  • 来自 WHATWG 的官方信息:
http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#rel-icon

苹果自定义图标和图像创建指南

关于如何创建触摸图标的指南和文章可以在以下文章中找到:

  • 苹果 - 自定义图标和图像创建指南:
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/IconsImages/IconsImages.html#//apple_ref/doc/uid/TP40006556-CH14-SW11

另请参阅

在 iPhone 上启用全屏模式的开始屏幕 - 在这个示例中,我们将看到如何在从主屏幕触摸图标启动时添加全屏模式的开始屏幕。

防止文本调整大小

目标设备:iOS,Windows Mobile

在像 iPhone 和 Windows Mobile 这样的某些移动设备上,当您将设备从纵向模式旋转到横向模式时,浏览器文本可能会调整大小。这可能会对网页开发人员造成问题,因为我们希望完全控制网站的设计和呈现。

准备就绪

创建一个新的 HTML 文件,并将其命名为ch02r02.html。输入以下代码:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<style>
figure, figcaption, header {
display:block;
margin:0 auto;
text-align:center;
}
</style>
</head>
<body>
<header>
HTML5 Logo
</header>
<figure>
<img src="img/HTML5_Badge_128.png" alt="HTML5 Badge" />
<figcaption>
It stands strong and true, resilient and universal as the markup you write.
It shines as bright and as bold as the forward-thinking, dedicated web developers you are.
It's the standard's standard, a pennant for progress.
And it certainly doesn't use tables for layout.
</figcaption>
</figure>
</body>
</html>

现在在 iPhone 上以纵向模式呈现此页面,如您所见,它将正常呈现如下:

准备就绪

现在,如果您将其呈现为横向模式,字体大小将突然增加。正如我们所看到的,当页面更改为横向模式时,文本将被调整大小。这不是期望的行为。以下显示了它的外观:

准备就绪

如何做...

您可以按照以下步骤来解决这个问题:

  1. 您可以将以下行添加到 CSS 中,然后再次以横向方式呈现页面:
html {
-webkit-text-size-adjust: none;
}

  1. 如您所见,文本现在看起来正常:如何做...

它是如何工作的...

要解决这个问题,您必须在 WebKit 中添加一个名为text-size-adjust的 CSS 属性,并将值分配为none以防止自动调整。

text-size-adjust设置为 none 可以解决移动特定网站的问题,但如果我们在桌面屏幕或其他非移动浏览器上呈现此内容,桌面浏览器的文本缩放功能将被禁用。为了防止这种无障碍问题,我们可以将text-size-adjust设置为100%,而不是none

因此,我们可以调整此示例以:

html {
-webkit-text-size-adjust: 100%;
}

还有更多...

除了 iPhone 之外,其他设备也有添加文本大小调整属性的方法。

Windows Mobile

Windows Mobile IE 使用不同的前缀。他们最初添加了 WebKit 前缀。其目的是添加对 WebKit 特定属性的支持,以使网页开发人员的生活变得更加轻松,而不必在页面中添加另一个供应商前缀的 CSS 属性来控制文本的缩放方式。更具体地说,他们直觉到这个属性的最常见用例是将其明确设置为none,以告诉浏览器不要缩放文本的特定部分。

在听取社区对这个问题的反馈后(以及在意识到实施其他浏览器供应商的 CSS 属性的更广泛影响时摔了几个跤),他们决定最好只实现-ms-前缀版本,而不是-webkit-版本。

因此,为了使前面的示例更完整,您可以添加:

html {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}

使其具有未来的保障

为了使事情更具未来性,您可以添加一行没有任何前缀的内容,如下所示:

html {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
text-size-adjust: 100%;
}

px em,哪个更好?

关于在移动设备上使用 px 与 em 的常见争论在移动设备上不再是一个问题。最初,Yahoo!用户界面使用 ems 的原因是 IE6 不支持像素的页面缩放。在移动设备上,没有这样的问题,即使我们希望页面在桌面浏览器上呈现良好,使用 IE6 的可能性也越来越低,因此在大多数情况下,您可以避免使用 ems 和所有计算的麻烦,而选择使用像素。

优化视口宽度

目标设备:跨浏览器

不同的移动设备有不同的默认移动视口宽度。请参考附录 X,了解所有移动设备的默认视口宽度列表。如果你将其保持未设置,在大多数情况下,会导致意外的结果。例如,在 iPhone 上,如果视口宽度保持未设置,它将被渲染为 980 像素。

准备就绪

让我们创建一个 HTML 文档并将其命名为ch02r03.html

如何做...

以下是我们可以优化视口宽度的方法:

  1. 将以下代码添加到ch02r03.html并在你的移动浏览器中渲染它:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<header>
HTML5 Logo
</header>
<div id="main">
<h1>Lorem ipsum</h1>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</body>
</html>

这是默认的渲染方式:

如何做...

  1. 如果我们渲染这个例子,我们会发现一切都变得非常小。现在,让我们将视口宽度设置为设备宽度:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<header>
HTML5 Logo
</header>
<div id="main">
<h1>Lorem ipsum</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
viewport widthviewport widthoptimizing</body>
</html>

现在内容宽度使用屏幕宽度,文本变得可读:

如何做...

它是如何工作的...

当我们将视口宽度设置为设备宽度时,它会告诉浏览器不要缩放页面以适应设备区域。因此,对于 iPhone,device-width在纵向模式下是 320 像素,在横向模式下是 480 像素。

还有更多...

对于一些非常老旧的移动浏览器,meta属性是不被识别的。为了处理这些浏览器,你需要使用:

<meta name="HandheldFriendly" content="true">

这被旧版本的 Palm OS、AvantGo 和 Blackberry 使用。

<meta name="MobileOptimized" content="320">

对于 Microsoft PocketPC,引入了一个MobileOptimized属性。

因此,最完整的代码应该是:

<meta name="HandheldFriendly" content="true">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width">

IE for Windows Phone 视口博客文章

在 IE for Windows Phone 团队博客上,有一篇关于IE Mobile Viewport on Windows Phone 7的文章。在其中,作者解释了 Windows Phone 7 如何实现“device-width”,以及其他很有用的一般信息。你可以在这里阅读这篇文章:blogs.msdn.com/b/iemobile/archive/2010/11/22/the-ie-mobile-viewport-on-windows-phone-7.aspx

Safari 文档

Safari 在开发者文库中有一个参考:developer.apple.com/library/safari/#documentation/appleapplications/reference/SafariHTMLRef/Articles/MetaTags.html

黑莓文档

有一个黑莓浏览器内容设计指南文档。它解释了黑莓对视口宽度的使用:docs.blackberry.com/en/developers/deliverables/4305/BlackBerry_Browser-4.6.0-US.pdf

修复移动 Safari 屏幕重新流动比例

目标设备:iOS

移动 Safari 有一个恼人的屏幕重新流动 bug:当你将移动浏览器从纵向模式旋转到横向模式时,文本会突然跳到更大的尺寸。

在我致力于构建 Mobile Boilerplate 的时候,Jeremy Keith和我就这个问题进行了长时间的讨论。

修复这个问题的传统方法是向meta视口添加以下缩放属性:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">

这个解决方案首先被纳入了 Mobile Boilerplate。Jeremy指出这解决了比例跳跃的问题,但同时也导致了另一个可访问性问题:当你设置如上所示的值时,你就不能再放大页面了。对于视力有问题的人来说,放大页面的能力是至关重要的。但如果我们让缩放发生,文本跳跃将会让大多数用户感到恼火。因此,很长一段时间里,这是一个可访问性与可用性的辩论。

我发现了一种可以解决这个问题的方法,我们将在下面讨论。

准备就绪

首先,让我们创建一个 HTML 文档并将其命名为ch02r04.html,在其中输入以下代码:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>
<h1>Lorem ipsum</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</body>
</html>

这个页面在纵向模式下渲染得非常好:

准备就绪

但在横向模式下显示时,情况就不同了:

准备就绪

如何做...

我们需要做的就是在用户放大页面时动态重置比例因子为默认值。现在将以下代码放入 HTML 文档中:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>
<h1>Lorem ipsum</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<script>
var metas = document.getElementsByTagName('meta');
var i;
if (navigator.userAgent.match(/iPhone/i)) {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
}
}
document.addEventListener("gesturestart", gestureStart, false);
}
function gestureStart() {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
}
}
}
</script>
</body>
</html>

现在,如果我们将屏幕从纵向旋转到横向,问题应该不复存在,如果我们放大页面,它将如预期般反应:

如何做...

它是如何工作的...

让我们来看看代码是如何工作的。

  1. 我们需要知道默认的最小比例和最大比例值。在 iPhone 的官方文档中,它指出最小比例值为 0.25,最大比例值为 1.6。因此,为了替换默认值,我们需要设置:
function gestureStart() {
var metas = document.getElementsByTagName('meta');
var i;
for (i=0; i if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum- scale=0.25, maximum-scale=1.6";
}
}

  1. 接下来,我们需要知道何时设置这个。这很容易:iPhone 有一个手势事件监听器,我们可以用来定位文档主体。以下是如何做到这一点:
document.addEventListener("gesturestart", gestureStart, false);

  1. 最后,我们需要确保这仅发生在 iPhone 上。同样,这可以很容易地通过以下方式完成:
if (navigator.userAgent.match(/iPhone/i)) {
document.addEventListener("gesturestart", gestureStart, false);
}

还有更多...

如果您对 Jeremy 和我的整个故事和讨论感兴趣,您可以在www.blog.highub.com/mobile-2/a-fix-for-iphone-viewport-scale-bug/阅读。

尽管这为问题提供了一个解决方案,但一些人会遇到一些问题:

  • 一旦用户在文档上做出手势,缩放就会再次启用。因此,如果在那之后更改设备方向,缩放错误仍然会发生。

  • 在 iOS4 上报告说,用户只能在开始第二个手势后有效地开始缩放。

稍微改进的版本

Mathias Bynens有一个智能编码的修订版本。您可以在这里看到代码

gist.github.com/901295

一个更好的版本

John-David Dalton有一个更新更好的版本,代码更智能更精简

gist.github.com/903131

给 jQuery Mobile 的一句话

Scott Jehl来自 jQuery Mobile 提到它可能会在将来的 jQuery Mobile 中实现。目前,您可以在gist.github.com/1183357看到他的要点。

从浏览器启动特定于手机的程序

目标设备:跨浏览器

可以从移动浏览器启动特定于手机的程序,例如地图、呼叫和短信可以从某些移动设备启动。程序是否可以启动取决于特定设备上本机应用程序的可用性。

准备好了

创建一个 HTML 文档,并将其命名为ch02r05.html.

如何做...

以下是我们如何启动特定于手机的程序:

  1. 让我们将以下代码添加到 HTML 文档中:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<header>
HTML5 Logo
</header>
<div>
<h1>Lorem ipsum</h1>
<a href="http://maps.google.com/maps?q=cupertino"> Directions</a>
</div>
</body>
</html>

  1. 现在在 Palm OS 浏览器中运行此代码,点击地址链接。您将被提示在手机上启动地图应用程序:如何做...

它是如何工作的...

与一些方案不同,地图 URL 不以“maps”方案标识符开头。相反,地图链接被指定为常规 HTTP 链接,但是针对 Google 地图服务器。设备浏览器将能够判断它是否是地图,并使用解析的信息启动程序。

还有更多...

您可以做的不仅仅是启动一个应用程序。以下示例显示了您将用于在旧金山和库比蒂诺之间提供驾驶路线的字符串:

<a href="http://maps.google.com/maps?daddr=San+Francisco,+CA&saddr=cupertino">Directions</a>

那么,如果浏览器无法启动特定的程序怎么办?没关系!在这种情况下,它将像普通链接一样打开:

还有更多...

移动 Safari URL 方案

可以在这里找到所有与 Mobile Safari 相关的 URL 方案列表:developer.apple.com/library/safari/#featuredarticles/iPhoneURLScheme_Reference/Introduction/Introduction.html

黑莓 URL 方案

所有与黑莓相关的 URL 方案列表可以在以下网址找到:docs.blackberry.com/en/developers/deliverables/18169/

索尼爱立信开发者指南

索尼爱立信开发者可以从 Developer World 网站下载Web 浏览开发者指南developer.sonyericsson.com/wportal/devworld/search-downloads?cat=%5B1.706817%2C+1.716594%2C+1.716688%5D&cc=gb&lc=en

启用 iPhone 全屏模式的启动屏幕

目标设备:iOS

为了使 Web 应用更像本机应用,iPhone 有一些独特的功能供开发者在 Web 应用上添加。您可以在全屏模式下添加启动屏幕,并为应用定义预加载屏幕。

准备工作

下载提供的源代码中的图像,创建一个 HTML 文档,并将其命名为ch02r06.html

如何做到的...

以下是我们如何使启动屏幕进入全屏模式:

  1. 输入以下 HTML 代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-startup-image" href="img/l/splash.png">
</head>
<body>
<header>
HTML5 Logo
</header>
<div>
Lorem ipsum
</div>
</body>
</html>

  1. 如果您将该页面添加到书签并从应用图标在浏览器中打开,它将显示为全屏应用。

它是如何工作的...

让我们来看一下代码:

<meta name="apple-mobile-web-app-capable" content="yes">

这使得网页在从主屏幕图标启动时以全屏模式运行,隐藏了浏览器顶部和底部的地址栏和组件栏。

<meta name="apple-mobile-web-app-status-bar-style" content="black">

这个代码是为了给浏览器顶部的状态栏添加样式。

<link rel="apple-touch-startup-image" href="img/l/splash.png">

您还可以在应用启动时添加一个启动屏幕,这是在页面仍在加载时显示的预加载屏幕。

还有更多...

iPad 和 iPhone 有不同的启动屏幕尺寸,所以如果我们希望网站动态更改启动屏幕,这取决于用于渲染的浏览器。我们可以使用以下 JavaScript 函数来实现:

var filename = navigator.platform === 'iPad' ? 'h/' : 'l/'; document.write('<link rel="apple-touch-startup-image" href="/img/' + filename + 'splash.png" />' );

iOS 4.3 的全屏问题

iOS 4.3 引入了一个他们称之为 JavaScript Nitro Engine 的新功能。这段新代码允许默认的 Safari 浏览器加载页面的速度提高了一倍。然而,这个功能似乎不支持全屏 Web 应用。虽然一些人质疑为什么苹果没有将新的 Safari 功能与其 Web 应用整合在一起,但也有人指出证据表明这可能只是一个 bug。

Safari 关于 Web 应用的文档

官方文档可以在 Safari 上访问以下网站:

developer.apple.com/library/safari/#documentation/appleapplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html

Safari 启动图像和触摸图标指南

有关启动图像和触摸图标指南,您可以访问官方 Safari 网站上的自定义图标和图像创建指南:

http://developer.apple.com/library/safari/#documentation/UserExperience/Conceptual/MobileHIG/IconsImages/IconsImages.html#//apple_ref/doc/uid/TP40006556-CH14

防止 iOS 在焦点上缩放

目标设备:iOS

在 JavaScript 事件 API 中,有一个form onfocus事件。当您在 iOS 中点击表单元素时,元素将放大显示在设备屏幕上。对于未设计为响应式或移动特定的网站,这种默认缩放可能有所帮助,但对于移动优化的网站来说,这可能没有那么有用,甚至可能很烦人。为了禁用这种默认行为,我们可以更改 meta viewport 值onfocusonblur

准备工作

创建一个 HTML 文档,并将其命名为ch02r06_b.html

如何做到的...

以下是我们如何启动一个特定于手机的程序:

  1. 让我们将以下代码添加到 HTML 文档中:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<form>
<label>First name:</label> <input type="text" name="fname" /><br />
<label>Last name:</label> <input type="text" name="lname" />
</form>
<script>
var $viewportMeta = $('meta[name="viewport"]');
$('input, select, textarea').bind('focus blur', function(event) {
$viewportMeta.attr('content', 'width=device-width,initial-scale=1,maximum-scale=' + (event.type == 'blur' ? 10 : 1));
});
</script>
</body>
</html>

  1. 现在,在 iOS 设备中渲染页面,触摸聚焦表单输入字段,您会发现现在输入字段不会放大。

它是如何工作的...

现在让我们提取出 JavaScript 部分:

<script>
var $viewportMeta = $('meta[name="viewport"]');
$('input, select, textarea').bind('focus blur', function(event) {
$viewportMeta.attr('content', 'width=device-width,initial-scale=1,maximum-scale=' + (event.type == 'blur' ? 10 : 1));
});
</script>

脚本的作用是检测到onfocus事件时,我们将最大缩放比例设置为 1,当检测到onblur时,我们将其设置为 10。

还有更多...

您可以阅读有关原始博客帖子讨论的更多信息:

nerd.vasilis.nl/prevent-ios-from-zooming-onfocus/

此代码片段已添加到 Mobile Boilerplate:

github.com/h5bp/mobile-boilerplate/blob/master/js/mylibs/helper.js

禁用或限制 WebKit 功能

目标设备:WebKit 移动浏览器(Android,iOS)

移动浏览器中存在许多特定设备的问题。通过一些不太为人知的 CSS 技术,我们可以轻松解决这些问题。让我们看看一些问题以及我们如何神奇地解决它们。

准备工作

创建一个 HTML 文档并将其命名为ch02r07.html

如何做到...

以下是限制 WebKit 功能的示例:

  1. 将以下代码添加到 HTML 文档中:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<style>
.nocallout {-webkit-touch-callout: none;}
#targetarea {width:200px; height:120px; padding-top:80px; background:#ccc; text-align:center; font-size:20px;}
</style>
</head>
<body>
<div id="targetarea" class="nocallout">
<a href="http://www.google.com" target="_blank">Google</a>
</div>
WebKit featuresWebKit featureslimiting</body>
</html>

如何做到...

  1. 现在,将附加代码输入到 HTML 文档中,
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<style>
.nocallout {-webkit-touch-callout: none;}
#targetarea {width:200px; height:120px; padding-top:80px; background:#ccc; text-align:center; font-size:20px;}
</style>
WebKit featuresWebKit featureslimiting</head>
<body>
<div id="targetarea" class="nocallout">
<a href="http://www.google.com" target="_blank">Google</a>
</div>
</body>
</html>

如何做到...

它是如何工作的...

如果不设置webkit-touch-callout,当您在设备上点击并按住链接时,将会出现提示,询问您是否要在当前页面中打开它,在新页面中打开它或复制,如第一个示例所示。

如果要禁用此功能,可以通过将webkit-touch-callout值设置为none来实现,如第二个示例所示。

还有更多...

您可能还想限制的另一个功能是复制和粘贴。这个功能在网页上是有意义的,但对于大多数应用程序的界面元素来说是不需要的。

<style type="text/css">
.oncopy {
-webkit-user-select: text;
}
</style>

更改点击颜色

您可以使用以下规则更改点击颜色:

<style type="text/css">
* {
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
</style>

使文本区域内容可编辑

如果要将元素设置为contenteditable,可以使用以下 CSS:

textarea.contenteditable {
-webkit-appearance: none;
}

窄屏幕的省略号

在移动浏览器上,屏幕要窄得多,因此在显示菜单标题列表时,可能会发生文本溢出。如果发生这种情况,CSS 技巧可以帮助您使用省略号修复文本溢出:

.ellipsis {
text-overflow: ellipsis;
overflow: hidden;
white-space:
white-space:

第三章:使用移动事件的交互媒体

在本章中,我们将涵盖:

  • 使用触摸事件移动元素

  • 检测和处理方向事件

  • 使用手势事件旋转 HTML 元素

  • 使用滑动事件制作轮播图

  • 使用手势事件操作图像缩放

介绍

移动和桌面之间最大的区别之一是我们与屏幕交互的方式。在桌面屏幕上,我们使用鼠标移动和点击事件来控制交互。在移动屏幕上,交互来自触摸和手势事件。在本章中,我们将看到一些触摸屏独有的事件(例如,双指事件),以及您如何利用这些功能来为移动构建独特的东西。

使用触摸事件移动元素

目标设备:跨浏览器

在移动屏幕上,我们使用触摸事件与元素进行交互。因此,我们可以用手指在屏幕上移动 HTML 元素。

准备工作

在这个例子中,我们将使用 jQuery。首先,让我们创建一个新的 HTML 文件,并将其命名为ch03r01.html

如何做...

在您的 HTML 文档中,使用以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#square {
width: 100px;
height: 100px;
background:#ccc;
position:absolute;
}
</style>
</head>
<body>
<div id="main">
<div id="square">
</div>
</div>
<script src="img/jquery-1.5.2.min.js"></script>
<script src="img/jquery. mobile-1.0a4.1.min.js"></script>
<script>
$('#square').bind('touchmove',function(e){
e.preventDefault();
var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
var elm = $(this).offset();
var x = touch.pageX - elm.left/2;
var y = touch.pageY - elm.top/2;
$(this).css('left', x+'px');
$(this).css('top', y+'px');
});
</script>
</body>
</html>

  • 现在让我们看看它在 Opera 中的渲染:如何做...

它是如何工作的...

首先,我们注册一个带有touchmove事件的正方形div

您可以检测相对于页面的触摸位置,即在我们的例子中是touch.pageXtouch.pageY。我们使用手指位置减去正方形div元素宽度和高度的一半,这样就感觉像我们是以div中心作为注册点移动。

var x = touch.pageX - elm.left/2;
var y = touch.pageY - elm.top/2;

我们使用 CSS 位置将 x 和 y 值应用于正方形元素。这就是'移动'动作。

$(this).css('left', x+'px');
$(this).css('top', y+'px');

还有更多...

您可能已经意识到,在这个例子的顶部,有一行如下:

var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];

现在你可能想知道它是做什么的。移动 Safari 不允许将e.touchese.changedTouches属性复制到另一个对象上的事件对象。您可以通过使用e.originalEvent来解决这个问题。您可以在这里阅读更多关于它的信息:

www.the-xavi.com/articles/trouble-with-touch-events-jquery

jQuery 移动事件

jQuery 移动是一组组件。如果您想深入了解所有与移动相关的事件,您可以在这里找到它们:

github.com/shichuan/jquery-mobile/blob/master/js/jquery.mobile.event.js

Zepto

Zepto 是一个比 jQuery 更轻量级的替代品,如果您的主要目标是基于 WebKit 的浏览器,您可以考虑使用它。您可以在这里了解更多信息:

github.com/madrobby/zepto

Safari 关于移动事件处理的指南

官方参考资料,请访问 Safari 的在线指南:

developer.apple.com/library/safari/#documentation/appleapplications/reference/safariwebcontent/HandlingEvents/HandlingEvents.html

另请参阅

  • 使用方向事件重绘画布

  • 使用手势事件旋转 HTML 元素

  • 使用滑动事件制作轮播图

  • 使用手势事件操作图像缩放

检测和处理方向事件

目标设备:跨浏览器

在移动浏览器上,如果您的网站是基于流体布局构建的,它不应受方向变化的影响。但对于一个高度互动的网站,有时您可能希望以特殊的方式处理方向变化。

准备工作

创建一个新的 HTML 文件,并将其命名为ch03r02.html

如何做...

现在让我们开始创建 HTML 和脚本来检测和处理方向事件。

  1. 输入以下代码:
<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html, body {
padding: none;
margin: none;
}
</style>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
<script src="img/jquery-1.6.4.min.js"></script>
<script src="img/jquery.mobile-1.0.min.js"></script>
</head>
<body>
<div id="a">
</div>
<script>
var metas = document.getElementsByTagName('meta');
var i;
if (navigator.userAgent.match(/iPhone/i)) {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
}
}
document.addEventListener("gesturestart", gestureStart, false);
}
function gestureStart() {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
}
}
}
</script>
<script>
$(window).bind('orientationchange',function(event){
updateOrientation(event.orientation);
})
function updateOrientation(orientation) {
$("#a").html("<p>"+orientation.toUpperCase()+"</p>");
}
</script>
</body>
</html>

  1. 现在,在您的移动浏览器中渲染此代码,并旋转屏幕以在纵向和横向模式下查看。在纵向模式下,文本输出将是'PORTAIT'。如何做...

  2. 当我们将屏幕旋转到横向模式时,文本将显示为'LANDSCAPE'。如何做...

它是如何工作的...

通过监听window.onorientationchange事件,我们可以在发生时获取orientationchange事件;我们将event.orientation传递给函数以输出结果。

还有更多...

有时,您可能希望锁定屏幕的方向,比如在构建游戏时。对于原生应用程序来说,这很容易,但对于 Web 应用程序来说,这可能有点难以实现。

让我们创建一个只能锁定在横向模式的单页面屏幕。请注意,这只是一个概念验证,要创建真正复杂的应用程序或游戏需要更多的计算和处理。

创建一个文档,并将其命名为ch03r02_b.html,然后输入以下代码

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
<style>
body {
font-family: 'Kranky', serif;
font-size: 36px;
font-style: normal;
font-weight: 400;
word-spacing: 0em;
line-height: 1.2;
}
html {
background:#F1F2CE;
}
html, body, #screen {
padding:0;
margin:0;
}
#screen {
text-align:center;
-moz-transform:rotate(90deg);
-webkit-transform:rotate(90deg);
-o-transform:rotate(90deg);
-ms-transform:rotate(90deg);
}
#screen div {
padding-top:130px;
}
@media screen and (min-width: 321px){
#screen {
text-align:center;
-moz-transform:rotate(0deg);
-webkit-transform:rotate(0deg);
-o-transform:rotate(0deg);
-ms-transform:rotate(0deg);
}
#screen div {
padding-top:70px;
}
}
</style>
</head>
<body>
<div id="screen">
<div id="loader">enter the game</div>
</div>
<script>
var metas = document.getElementsByTagName('meta');
var i;
if (navigator.userAgent.match(/iPhone/i)) {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
}
}
document.addEventListener("gesturestart", gestureStart, false);
}
function gestureStart() {
for (i=0; i<metas.length; i++) {
if (metas[i].name == "viewport") {
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
}
}
}
window.onorientationchange = function() {
update();
}
function update() {
switch(window.orientation) {
case 0: // Portrait
case 180: // Upside-down Portrait
var cWidth = window.innerWidth;
var cHeight = window.innerHeight;
document.getElementById("screen").style.width = cHeight-36+'px';
document.getElementById("screen").style.height = cWidth+'px';
break;
case -90: // Landscape: turned 90 degrees counter-clockwise
case 90: // Landscape: turned 90 degrees clockwise
var cWidth = window.innerWidth;
var cHeight = window.innerHeight;
document.getElementById("screen").style.width = "100%";
document.getElementById("screen").style.height = "auto";
break;
}
}
update();
</script>
</body>
</html>

现在,如果您在浏览器中呈现页面,您将看到以下屏幕。在纵向模式下,它建议用户游戏/应用程序是设计为横向模式查看的:

还有更多...

当您将屏幕从纵向旋转到横向时,它看起来很正常:

还有更多...

在这个例子中,我们使用 CSS3 的transform:rotate将屏幕旋转 90 度,以便在纵向模式下查看:

#screen {
text-align:center;
-moz-transform:rotate(90deg);
-webkit-transform:rotate(90deg);
-o-transform:rotate(90deg);
-ms-transform:rotate(90deg);
}

用户所处的模式可以通过window.orientation确定。有四个值:-90、0、90、180。当度数为-90 和 90 时,设备处于横向模式。当度数为 0 和 180 时,设备处于纵向模式。

switch(window.orientation) {
case 0: // Portrait
case 180: // Upside-down Portrait
//...
break;
case -90: // Landscape: turned 90 degrees counter-clockwise
case 90: // Landscape: turned 90 degrees clockwise
//...
break;
}

通过这种方式,您可以确定屏幕的方向。

Safari 的原生支持

有关官方参考,请访问 Safari 的在线指南:

developer.apple.com/library/safari/#documentation/appleapplications/reference/safariwebcontent/HandlingEvents/HandlingEvents.html

Web 与原生

尽管移动 Web 正在迎头赶上,但如果您正在开发高度交互式的应用程序,请始终记住,即使是最慢的原生应用程序的性能也比 HTML 应用程序更快。如果您决定使用 HTML5 构建应用程序,还必须牢记所有的黑客和浏览器不一致性。

另请参阅

  • 使用触摸事件移动元素

  • 使用手势事件旋转 HTML 元素

  • 使用滑动事件创建旋转木马

  • 使用手势事件缩放图像

使用手势事件旋转 HTML 元素

目标设备:iOS,Android,Symbian

在移动 Safari 上,当人们用两根手指在屏幕上进行旋转时,你可以检测旋转的角度。因此,我们可以使用手指在屏幕上旋转一个元素!

准备工作

让我们创建一个 HTML 文档,并将其命名为ch03r03.html

如何做...

  1. 将以下代码添加到ch03r03.html中,并在您的移动浏览器中呈现它:
<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<style>
#main {
text-align:center;
}
#someElm {
margin-top:50px;
margin-left:50px;
width: 200px;
height: 200px;
background:#ccc;
position:absolute;
}
</style>
</head>
<body>
<div id="main">
<div id="someElm">
</div>
</div>
<script>
var rotation =0 ;
var node = document.getElementById('someElm');
node.ongesturechange = function(e){
var node = e.target;
//alert(e.rotation);
// scale and rotation are relative values,
// so we wait to change our variables until the gesture ends
node.style.webkitTransform = "rotate(" + ((rotation + e.rotation) % 360) + "deg)";
//alert("rotate(" + ((rotation + e.rotation) % 360) + "deg)");
}
node.ongestureend = function(e){
// Update the values for the next time a gesture happens
rotation = (rotation + e.rotation) % 360;
}
</script>
</body>
</html>

  1. 现在用两根手指旋转框,你会看到类似这样的东西:如何做...

它是如何工作的...

在这个例子中,当触发ongesturechange事件时,我们旋转元素。我们通过以下值获取旋转角度:

e.target.rotation

还有更多...

您可能已经注意到,我们还监听ongestureend事件,因为如果用户之前已经旋转过,此脚本将记住上次旋转的角度,并继续从那里旋转。

Safari 事件处理

有关官方参考,请访问 Safari 的在线指南:

developer.apple.com/library/safari/#documentation/appleapplications/reference/safariwebcontent/HandlingEvents/HandlingEvents.html

CSS3 转换

在这个例子中,我们使用了 CSS3 的转换功能。您可以在 WebKit 的博客上找到有关 WebKit 和 CSS 转换的更多信息:

www.webkit.org/blog/130/css-transforms/.

缩放错误修复的缺点

在这个例子中,我们使用了maximum-scale=1.0来防止在使用手势事件时进行缩放。这会导致一些无法访问的缺点,因此只有在构建高度交互式的 Web 应用程序时才使用旋转事件。在构建移动网站时尽量避免使用它。

另请参阅

  • 使用触摸事件移动元素

  • 使用方向事件重绘画布

  • 使用手势事件旋转 HTML 元素

  • 使用手势事件缩放图像

使用滑动事件制作一个旋转木马

移动设备的一个常见功能是滑动。当你在照片库中浏览照片时,你可以向左和向右滑动以从一张图片导航到另一张图片。在 Android 设备上,你可以向下滑动解锁手机。在移动浏览器上,你也可以使用滑动。

准备工作

首先,让我们创建一个 HTML 文档并命名为ch03r04.html

如何做...

  1. 输入以下代码:
<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html, body {
padding:0;
margin:10px auto;
}
#checkbox {
border:5px solid #ccc;
width:30px;
height:30px;
}
#wrapper {
width:210px;
height:100px;
position:relative;
overflow:hidden;
margin:0 auto;
}
#inner {
position:absolute;
width:630px;
}
#inner div {
width:200px;
height:100px;
margin:0 5px;
background:#ccc;
float:left;
}
.full-circle {
background-color: #ccc;
height: 10px;
-moz-border-radius:5px;
-webkit-border-radius: 5px;
width: 10px;
float:left;
margin:5px;
}
.cur {
background-color: #555;
}
#btns {
width:60px;
margin:0 auto;
}
</style>
</head>
<body>
<div id="main">
<div id="wrapper">
<div id="inner">
<div></div>
<div></div>
<div></div>
</div>
</div>
<div id="btns">
<div class="full-circle cur"></div>
<div class="full-circle"></div>
<div class="full-circle"></div>
</div>
</div>
<script src="img/jquery-1.5.2.min.js"></script>
<script src="img/jquery.mobile-1.0a4.1.min.js"></script>
<script>
var curNum = 0;
$('#wrapper').swipeleft(function () {
$('#inner').animate({
left: '-=210'
}, 500, function() {
// Animation complete.
curNum +=1;
$('.full-circle').removeClass('cur');
$('.full-circle').eq(curNum).addClass('cur');
});
});
$('#wrapper').swiperight(function () {
$('#inner').animate({
left: '+=210'
}, 500, function() {
// Animation complete.
curNum -=1;
$('.full-circle').removeClass('cur');
$('.full-circle').eq(curNum).addClass('cur');
});
});
</script>
</body>
</html>

  1. 一旦你在页面中输入了代码,左右滑动查看区域,你就可以看到盒子在水平滚动:How to do it...

它是如何工作的...

我们在这个例子中使用了一些 HTML5 技术。首先,我们使用 jQuery Mobile 来检测滑动事件。当我们用手指向左或向右滑动页面时,会分配一个事件监听器:

$('#wrapper').swipeleft(function () {
});
$('#wrapper').swiperight(function () {
});

当检测到滑动事件时,使用 jQuery 动画.animate()来创建移动效果:

$('#inner').animate({
left: '+=210'
}, 500, function() {
// Animation complete.
curNum -=1;
$('.full-circle').removeClass('cur');
$('.full-circle').eq(curNum).addClass('cur');
});

还有更多...

在这个例子中,我们使用了 CSS3 技术来制作圆形按钮。你可以只用纯 CSS3 画出一个完整的圆:

.full-circle {
background-color: #ccc;
height: 10px;
-moz-border-radius:5px;
-webkit-border-radius: 5px;
border-radius: 5px;
width: 10px;
}

在这个例子中,我们定义文档的宽度和高度为 10 像素,边框半径为 5 像素。现在你可以用几行 CSS 代码画出一个完美的圆!

Zepto 框架和滑动事件

你可以使用 Zepto 框架做类似的事情。它有事件,如swipe, swipeLeft, swipeRight, swipeUp, swipeDown

YUI 和手势事件

YUI 有手势事件,你可以使用它们来创建滑动事件。你可以在这里阅读更多关于这个的信息:支持向左滑动手势:

yuiblog.com/sandbox/yui/3.3.0pr3/examples/event/ swipe-gesture.html

深入源码

jQuery 移动中的事件是以模块化方式构建的。想要了解 jQuery 如何创建滑动事件的人可以访问:

github.com/jquery/jquery-mobile/blob/master/js/jquery.mobile.event.js。与滑动事件相关的部分在:

$.event.special.swipe = {...}

垂直、水平和距离阈值被用于事件计算。

另请参阅

  • 使用触摸事件移动元素

  • 使用方向事件重绘画布

  • 使用手势事件旋转 HTML 元素

  • 使用手势事件缩放图像

使用手势事件缩放图像

在 iPhone 上,你可以根据缩放检测调整元素的大小。在手势改变时,你可以获得缩放因子的值,并根据它来缩放 HTML 元素。

准备工作

创建一个 HTML 文档并命名为ch03r05.html

如何做...

输入以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<style>
#frame {
width:100px;
height:100px;
background:#ccc;
}
</style>
</head>
<body>
<div id="main">
<div id="frame"></div>
</div>
<script src="img/jquery-1.5.2.min.js"></script>
<script src="img/jquery.mobile-1.0a4.1.min.js"></script>
<script>
var width = 100, height = 100;
var node = document.getElementById('frame');
node.ongesturechange = function(e){
var node = e.target;
// scale and rotation are relative values,
// so we wait to change our variables until the gesture ends
node.style.width = (width * e.scale) + "px";
node.style.height = (height * e.scale) + "px";
}
node.ongestureend = function(e){
// Update the values for the next time a gesture happens
width *= e.scale;
height *= e.scale;
}
</script>
</body>
</html>

它是如何工作的...

在这个例子中,我们使用ongesturechange事件来分配我们想要缩放的元素。缩放因子由e.target.scale:确定。

width *= e.scale;
height *= e.scale;

还有更多...

手势事件可能很棘手,因此正确使用它们非常重要。对于双指多点触摸手势,事件发生的顺序如下:

  1. touchstart 用于第一根手指。当第一根手指触摸表面时发送。

  2. gesturestart。当第二根手指触摸表面时发送。

  3. touchstart 用于第二根手指。在第二根手指触摸表面后立即发送gesturestart

  4. gesturechange 用于当前手势。当两根手指仍然触摸表面时移动时发送。

  5. gestureend。当第二根手指从表面抬起时发送。

  6. touchend 用于第二根手指。在第二根手指从表面抬起后立即发送gestureend

  7. touchend 用于第一根手指。当第一根手指从表面抬起时发送。

官方 iOS Safari 手势事件指南

有一个官方的 iPhone Safari 指南,详细解释了 Safari 上的GestureEvent类的细节:

developer.apple.com/library/safari/#documentation/UserExperience/Reference/GestureEventClassReference/GestureEvent/GestureEvent.html.

YUI 手势事件

来自 Yahoo!的 YUI 具有跨浏览器的手势事件解决方案,但只支持单指事件。您可以在以下网址找到更多信息:

developer.yahoo.com/yui/3/event/#gestures.

Google 地图和手势事件

一个依赖于双指手势事件的网站的例子是移动 Safari 上的 Google 地图:

Google 地图和手势事件

另请参阅

  • 使用触摸事件移动元素

  • 使用方向事件重绘画布

  • 使用手势事件旋转 HTML 元素

  • 制作一个旋转木马

第四章:构建快速响应的网站

在本章中,我们将涵盖:

  • 使用基本的 HTML5 标记构建页面

  • 使用 CSS3 功能进行渐进增强

  • 应用响应式设计与媒体查询

  • 使用动态加载

  • 应用用户代理检测

  • 在主页上添加移动书签气泡

  • 使用文本区域和自动增长表单构建联系页面

  • 制作具有即时响应的按钮

  • 隐藏 WebKit chrome

  • 构建移动站点地图

介绍

在移动设备上,带宽并不总是像在台式电脑上那样好。如果您在一个慢速的 3G 网络上,加载速度可能比在 Wi-Fi 热点上慢得多。即使对于 Wi-Fi 连接,许多移动浏览器的处理速度也比台式电脑慢。因此,当我们创建移动站点时,它们必须快速且响应迅速。

从本章开始,我们还将开始介绍 HTML5 功能。HTML5 是一组技术,包括语义、新的 CSS 规则和属性,以及新的 JavaScript API,可用于构建结构更好的网页和功能强大的 Web 应用程序。以下是八个主要的 HTML5 功能:

  • 语义

  • 离线和存储

  • 设备访问

  • 连接

  • 多媒体

  • 3D、图形和效果

  • 性能和集成

  • CSS3

并非所有这些功能都是专门针对移动设备的;有些与移动 Web 更相关,而有些则更适用于移动和桌面 Web。我们将讨论每个功能,并看看它们如何最好地帮助我们的移动开发。

基于使用新的语义标记和 CSS3 创建的示例,我们将讨论充分利用移动浏览器提供的内容以及如何使用这些独特功能构建网站的许多方法。

使用 HTML5 语义构建页面

目标设备:跨浏览器

HTML5 引入了更丰富的标签集;这些标签赋予结构以含义。语义是 HTML5 的一个基本方面。

我们不会在这里介绍所有标签,但会涵盖一些最常用的标签。

准备工作

首先,让我们创建一个新的 HTML 文件,并将其命名为ch04r01.html。让我们创建一个关于音乐的虚构网站。

如何做...

在我们的 HTML 文档中,输入以下代码:

<!doctype html>
<html>
<head>
<title>first.fm</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
</style>
</head>
<body>
<header>
<h1>first.fm</h1>
</header>
<div id="main">
<h2>Pages</h2>
<nav>
<ul>
<li class="list"><a href="http://music.html">Music</a></li>
<li><a href="radio.html">Radio</a></li>
<li><a href="http://events.html">Events</a></li>
<li><a href="http://charts.html">Charts</a></li>
<li><a href="community.html">Community</a></li>
<li><a href="help.html">Help</a></li>
<li><a href="http://about.html">About</a></li>
</ul>
</nav>
</div>
<footer>
<small>&copy; 2011 first.fm</small>
</footer>
</body>
</html>

它是如何工作的...

header元素通常用于h1h6元素;它可以出现在整个页面的头部或任何块级元素的头部。它通常包含标题、副标题或标语。

<header>元素:

<header>
</header>

nav元素表示文档的导航。nav元素是一个包含指向其他文档或当前文档内部部分的链接的部分。

页面上并非所有链接组都需要在nav元素中。只有主要或次要导航链接的组。特别是,页脚通常会有指向站点各个关键部分的链接列表,但在这种情况下,页脚元素更合适。

<nav>元素:

<nav>
<ul class="list">
<li class="list"><a href="http://music.html">Music</a></li>
</ul>
</nav>

footer元素表示文档或文档部分的“页脚”。页脚元素通常包含有关其封闭部分的元数据,例如谁写的、相关文档的链接、版权数据等。页脚中给出的部分的联系信息应使用地址元素进行标记。

<footer>元素:

<footer>
<small>&copy; 2011 first.fm</small>
</footer>

small元素可用于小字体。它不打算呈现页面的主要焦点。small元素不应用于长段落或文本部分。它只用于版权信息等短文本。

<small>元素:

<small>&copy; 2011 first.fm</small>

还有更多...

语义不仅仅是更丰富的标签集。我们需要的不仅仅是更有意义的标签。为了扩展标签之外,我们还可以添加机器可读的额外语义;浏览器、脚本或机器人可以理解的数据,为程序和用户提供更有用的、数据驱动的 Web。这些语义是:RDFa(属性中的资源描述框架)、MicrodataMicroformats

RDFa

RDFa 提供了一组可机器读取的 HTML 属性。通过使用 RDFa,作者可以将现有的可读信息转换为可机器读取的数据,而无需重复内容。最新的规范可以在此处找到:

www.w3.org/TR/rdfa-in-html/

微数据

微数据使用属性来定义数据的名称-值对组。您可以在此处了解更多信息:html5doctor.com/microdata/

您可以通过阅读 W3C 工作草案来深入了解微数据:www.w3.org/TR/microdata/

您还可以阅读 W3C 编辑草案:dev.w3.org/html5/md/

微格式

微格式首先设计为人类,其次为机器。目前有 34 个微格式规范,其中一些已发布,一些是草案。您可以在此处了解更多信息:html5doctor.com/microformats/

另请参阅

  • 在移动 Web 上使用 HTML5在第一章中,HTML5 和移动 Web

  • 在第一章中使 HTML5 跨浏览器呈现HTML5 和移动 Web

使用 CSS3 功能进行渐进增强

目标设备:跨浏览器

CSS3 通过各种样式和效果增强 Web 应用程序和网站。使用 CSS3,可以创建一组无图像的丰富 UI。在移动设备上,更少的图像意味着更快的加载,这是提高性能的一种方式。由于大多数现代智能手机浏览器都广泛支持 CSS3,并且有用于回退的 polyfills(polyfills 用作回退,使 HTML5 功能在不支持 HTML5 的浏览器上工作),因此开始使用 CSS3 不仅安全而且必要!

使用 CSS3 功能进行渐进增强

准备就绪

让我们设计前面示例中创建的页面。首先复制ch04r01.html,并将其重命名为ch04r02.html

如何做...

添加以下样式规则:

<style>
body {
margin:0;
padding:0;
font-family:Arial;
background:#ccc;
}
header {
text-shadow: 0 1px #000;
background: #ff3019; /* Old browsers */
background: -moz-linear-gradient(top, #ff3019 0%, #cf0404 20%, #ff3019 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ff3019), color-stop(20%,#cf0404), color-stop(100%,#ff3019)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #ff3019 0%,#cf0404 20%,#ff3019 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #ff3019 0%,#cf0404 20%,#ff3019 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #ff3019 0%,#cf0404 20%,#ff3019 100%); /* IE10+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ff3019', endColorstr='#ff3019',GradientType=0 ); /* IE6-9 */
background: linear-gradient(top, #ff3019 0%,#cf0404 20%,#ff3019 100%); /* W3C */
}
h1 {
padding:0.5em 0.2em;
margin:0;
font-size: 18px;
color:white;
}
h2 {
text-shadow: 0 1px #FFFFFF;
background: #eeeeee; /* Old browsers */
background: -moz-linear-gradient(top, #eeeeee 0%, #cccccc 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#eeeeee), color-stop(100%,#cccccc)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #eeeeee 0%,#cccccc 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #eeeeee 0%,#cccccc 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #eeeeee 0%,#cccccc 100%); /* IE10+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#cccccc',GradientType=0 ); /* IE6-9 */
background: linear-gradient(top, #eeeeee 0%,#cccccc 100%); /* W3C */
padding:0.5em 0.2em;
margin:0;
font-size: 16px;
color:#000;
}
nav ul {
border-top:1px solid #fff;
list-style-type: none;
padding:0;
margin:0;
}
nav li {
padding:0.5em 0.2em;
margin:0;
background:#AFAFAF;
border-bottom:1px solid #fff;
}
nav li a {
height:20px;
display:block;
text-decoration:none;
color:white;
}
</style>

通过在浏览器中运行此代码,我们可以看到:

如何做...

它是如何工作的...

在此示例中,我们使用 CSS3 渐变来设计标题元素。传统上,要创建像前面的示例一样的渐变,人们必须使用 Photoshop 或 Illustrator,但现在您可以纯粹使用 CSS 来创建它!

background: #eeeeee; /* Old browsers */
background: -moz-linear-gradient(top, #eeeeee 0%, #cccccc 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#eeeeee), color-stop(100%,#cccccc)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #eeeeee 0%,#cccccc 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #eeeeee 0%,#cccccc 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #eeeeee 0%,#cccccc 100%); /* IE10+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#cccccc',GradientType=0 ); /* IE6-9 */
background: linear-gradient(top, #eeeeee 0%,#cccccc 100%); /* W3C */

通过查看上述每条规则,我们可以看到不同的浏览器使用不同的 CSS 规则来处理渐变。为了确保跨浏览器兼容性,有六种不同的变体。您可能会想:“哦,天哪,照顾每个浏览器真的很耗时。”别担心,这条规则不是手动输入的。终极 CSS 渐变生成器来拯救!ColorZilla 的强大类似于 Photoshop 的 CSS 渐变编辑器可以帮助您轻松创建 CSS3 渐变:

www.colorzilla.com/gradient-editor/

它是如何工作的...

还有更多...

如果考虑 IE9 及以下版本,可以使用 CSS3 PIE(css3pie.com/)来提供支持。

下载PIE.htc后,将其包含在 CSS 中:

-pie-background: linear-gradient(top, #eeeeee 0%,#cccccc 100%); /*PIE*/
behavior: url(PIE.htc);

支持的功能包括:

  • 边框半径

  • 盒阴影

  • 边框图像

  • CSS3 背景(-pie-background

  • 渐变

  • RGBA 颜色值

  • PIE 自定义属性

了解 CSS3 渐变

Jeffrey Way,nettuts 的编辑,有一篇关于 CSS3 渐变的优秀文章。您可以在此处查看:net.tutsplus.com/tutorials/html-css-techniques/quick-tip-understanding-css3-gradients/.

CSS3,请!

CSS3 Please!,由Paul Irish编写,提供了有关渐变和许多其他 CSS3 功能的最新语法:css3please.com/

另请参阅

  • 在移动 Web 上使用 HTML5在第一章中

应用响应式设计

目标设备:跨浏览器

响应式设计是近期移动开发中最重要的概念之一。它强调浏览器应该对屏幕/浏览器调整大小做出不同的渲染。移动优先的响应式设计可以使页面在桌面浏览器上优雅地降级。

那么为什么我们需要响应式网页设计呢?

当我们在桌面网页上应用固定布局时,根据浏览器屏幕尺寸,屏幕左侧或右侧通常会出现空白。移动浏览器也有不同的尺寸,并且视口空间有限,每个像素都很重要,因此利用屏幕上的每个像素非常重要,因此需要使用响应式设计来消除页面左侧或右侧的不必要的空白。

媒体查询如何帮助响应式设计?

媒体查询用于根据屏幕尺寸更新样式内容,因此对于相同的 HTML 元素,可以应用两个单独的规则。渲染哪一个取决于浏览器视口的大小。

准备工作

在本示例中,我们将使用名为respond.js的 HTML5 填充。它是由Scott Jehl(来自 jQuery Mobile 团队)创建的。它位于源代码的ch04_code/js中。

操作步骤...

首先,让我们创建一个名为ch04r03.html的 HTML 文档。

在 HTML 中输入以下代码:

<!doctype html>
<html>
<head>
<title>first.fm</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css?v=1">
<script>Modernizr.mq('(min-width:0)') || document.write("<script src='js/respond.min.js'>\x3C/script>")</script>
</head>
<body>
<header>
<h1>first.fm</h1>
</header>
<div id="main">
<h2>Pages</h2>
<nav>
<ul class="list clearfix">
<li class="list"><a href="http://music.html">Music</a></li>
<li class="list"><a href="radio.html">Radio</a></li>
<li class="list"><a href="http://events.html">Events</a></li>
<li class="list"><a href="http://charts.html">Charts</a></li>
<li class="list"><a href="community.html">Community</a></li>
<li class="list"><a href="help.html">Help</a></li>
<li class="list"><a href="http://about.html">About</a></li>
</ul>
</nav>
</div>
<footer>
<small>&copy; 2011 first.fm</small>
</footer>
</body>
</html>

如果您在移动设备上渲染页面,这个页面看起来会和前面的示例一模一样。但是如果您在桌面浏览器上渲染它,它会看起来和下面的类似:

操作步骤...

工作原理...

在文件顶部,我们使用Modernizr首先检测当前浏览器是否支持媒体查询。如果不支持,我们将加载respond.min.js

<script>Modernizr.mq('(min-width:0)') || document.write("<script src='js/respond.min.js'>\x3C/script>")</script>

在撰写本文时,您需要在规则的末尾添加/*/mediaquery*/注释才能使其工作。这在respond.js的未来版本中可能会得到改进:

@media only screen and (min-width: 800px) {
}/*/mediaquery*/

还有更多...

在 Mobile Boilerplate 网站上,我进一步解释了媒体查询,并且您可以在以下网址找到幻灯片:html5boilerplate.com/mobile/

Andy Clarke创建了基于响应式设计理念的320 and up。您可以在以下网址下载:stuffandnonsense.co.uk/projects/320andup/

优化填充脚本加载

目标设备:跨浏览器

脚本加载对于任何浏览器都很重要,但对于移动设备来说更重要,因为带宽较低。Modernizr 带有一个动态加载解决方案。

准备工作

首先,让我们创建一个 HTML 文档,命名为ch03r04.html

操作步骤...

在代码编辑器中输入以下代码,并运行它。

<!doctype html>
<html>
<head>
<title>first.fm</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="img/modernizr.custom.54685.js"></script>
<style>
</style>
</head>
<body>
<header>
<h1>Your Location</h1>
</header>
<div id="main">
Your Geo Location is: <span id="geo"></span>
</div>
<script src="img/jquery.js"></script>
<script>
yepnope({
test : Modernizr.geolocation,
nope : ['js/geolocation.js'],
complete: function () { navigator.geolocation.getCurrentPosition(function(position) {
document.getElementById('geo').innerHTML = position.coords.latitude+", "+position.coords.longitude;
});
}
});
</script>
</body>
</html>

工作原理...

在撰写本文时,Modernizr 2.0 预览版处于 Beta 1 阶段。在这个测试版中,有两个很棒的新功能。一个是您可以选择自定义要检测的功能。另一个很棒的功能是您可以使用yepnope.js(也被称为Alex SextonRalph HolzmannModernizr.load)。Yepnope.js提供了一个动态 JavaScript 加载器,您可以在本章的还有更多部分了解更多信息。

工作原理...

使用 Modernizr,我们可以首先检测当前用户代理中是否已存在某个功能:

test : Modernizr.geolocation

如果不存在,我们将使用yepnope加载shim geolocation.js。加载完成后,我们可以附加纬度和经度:

yepnope({
test : Modernizr.geolocation,
nope : ['js/geolocation.js'],
complete: function () {
...
});

还有更多...

有一些可选资源对开发人员很有帮助。Modernizr 测试套件就是其中之一。它有助于开发人员一目了然地了解某个设备支持哪些功能。您可以在以下网址了解更多信息:

modernizr.github.com/Modernizr/test/index.html

yepnope

yepnope 是一个异步条件资源加载器,速度超快,允许您仅加载用户需要的脚本。要了解更多信息,请访问:yepnopejs.com/

另请参阅

  • 使用 CSS3 功能进行渐进增强

应用用户代理检测

目标设备:跨浏览器

在开发移动站点时,具有用户代理检测是很有用的。这可以帮助您编写重定向脚本,或者帮助您确定是否要基于用户代理加载/不加载某些内容。

准备工作

首先,让我们看看如何根据用户代理检测告诉用户是否可以从一个站点重定向到另一个站点。有几种方法可以做到这一点:您可以在服务器配置中执行此操作,也可以在服务器端编程语言中执行此操作,或者可以从前端 JavaScript 中执行此操作。

如何做...

您可以从以下位置下载重定向脚本:detectmobilebrowser.com/。它带有许多不同版本。在本示例中,让我们使用 Apache 配置.htaccess

它是如何工作的...

下载文件并打开后,您会看到以下脚本:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} android|avantgo|blackberry|blazer|compal|
....
|up\.(browser|link)|vodafone|wap|windows\ (ce|phone)|xda|xiino [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^(1207|6310|6590|
....
|your|zeto|zte\-) [NC]
RewriteRule ^$ http://example.com/mobile [R,L]

要将桌面站点重定向到移动站点,可以将http://example.com/mobile更改为您的站点地址。

还有更多...

用户代理检测不仅在重定向站点时有用,还在尝试确定是否应基于用户代理加载某些内容时有用。

在构建 Mobile Boilerplate 站点时,我使用了检测脚本的 JavaScript 版本来确定站点是否应根据用户代理(移动或桌面)呈现嵌入内容:

if(!jQuery.browser.mobile) {
...
}

使用此桌面浏览器脚本,幻灯片将被加载并显示如下:

还有更多...

在移动版本中,它不会显示:

还有更多...

移动浏览器检测方法

移动 tuts 上的一篇文章解释了移动浏览器检测的不同方法:mobile.tutsplus.com/tutorials/mobile-web-apps/mobile-browser-detection/

将移动书签气泡添加到主页

目标设备:iOS

在前几章中,我们已经谈到了在某些移动设备上为您的站点添加书签的能力。尽管这是一个非常酷的功能,使 Web 应用程序更接近本机应用程序,但它也存在一个问题:没有 API 可以用来调用书签操作,因此许多用户根本不知道手机上有这样一个功能。为了解决这个问题,一些框架使用 CSS 和 JavaScript 提供了书签气泡。该脚本将在 Web 应用程序页面底部添加一个促销气泡,要求用户将 Web 应用程序添加到其设备的主屏幕上。

准备工作

如前所述,许多框架提供了此功能,但为了简单起见,让我们使用一个独立的框架。Google 发布了一个名为The Mobile Bookmark Bubble的开源库来完成这项任务。首先,让我们在以下位置下载它:code.google.com/p/mobile-bookmark-bubble/

如何做...

该库附带一个sample.js。只需在创建的任何网页中包含bookmark_bubble.jssample.js,然后您会看到以下内容:

如何做...

它是如何工作的...

该库使用 HTML5 本地存储来跟踪促销是否已经显示,以避免不断地纠缠用户。该库的当前实现专门针对 Mobile Safari,这是 iPhone 和 iPad 设备上使用的 Web 浏览器。

另请参阅

在第二章中启用 iPhone 全屏模式

构建带有文本区域和自动增长表单的联系人页面

目标设备:跨浏览器

在像短信这样的原生应用中,文本区域会自动增长。在移动 Web 上,如果创建一个文本区域,您会意识到它是固定大小的。当您输入的文本行数超过文本区域的高度时,很难看到文本。在这个例子中,我们将看到如何创建一个在您输入更多行时自动增长的文本区域。

准备工作

首先,让我们创建一个名为ch04r05.html的 HTML 文档。在这个例子中,我们将在 Mobile Boilerplate 中使用helper.jsgithub.com/h5bp/mobile-boilerplate

如何做...

在文件中输入以下代码:

<!doctype html>
<html>
<head>
<title>first.fm</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#contact {width:220px; height:40px;}
</style>
</head>
<body>
<header>
<h1>Contact Form</h1>
</header>
<div id="main">
<p>Type the message to see it autogrow</p>
<textarea id="contact">
</textarea>
</div>
<script src="img/jquery.js"></script>
<script src="img/helper.js"></script>
<script>
var contact = document.getElementById("contact");
MBP.autogrow(contact);
</script>
</body>
</html>

以下是 Palm webOS 中呈现方式的屏幕截图:

如何做...

它是如何工作的...

在脚本中,我们有一个键盘事件监听器。这将检测文本区域的高度是否已更改。我们测量内容的高度,如果已更改,我们将更改文本区域的 CSS 样式以增加高度。

还有更多...

这个原始概念来自 Google 的 Code 博客。您可以在这里阅读更多关于它的信息:googlecode.blogspot.com/2009/07/gmail-for-mobile-html5-series.html

参见

  • 使用即时响应制作按钮

使用即时响应制作按钮

目标设备:iOS,Android

在移动设备浏览器上,按钮响应可能会比原生应用稍慢。在移动浏览器上,有一个touchstart事件。通过检测这个事件而不是点击事件,可以使点击更快。

准备工作

在这个例子中,我们将使用 Mobile Boilerplate 中的一个函数。创建一个名为ch04r06.html的文件。

如何做...

以下代码将创建一个带有提交按钮的表单:

<!doctype html>
<html>
<head>
<title>first.fm</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#contact {
width:220px; height:40px;
}
</style>
</head>
<body>
<header>
<h1>Contact Form</h1>
</header>
<div id="main">
<textarea id="contact"></textarea><br />
<button id="btn">INSTANT button!!!</button><br />
<span id="result"></span>
</div>
<footer>
<small>&copy; 2011 first.fm</small>
</footer>
<script src="img/jquery.js"></script>
<script src="img/helper.js"></script>
<script>
var btn = document.getElementById("btn");
MBP.fastButton(btn,showForm);
function showForm() {
$("#result").html("Thank you for submitting, we will get back to you shortly!");
}
</script>
</body>
</html>

它是如何工作的...

以下是快速按钮函数的摘录,我们将在这里看到函数是如何工作的。

在顶部,我们定义了主要函数。只有在支持addEventListener的情况下才会使用它,它监听touchstartclick事件:

MBP.fastButton = function (element, handler) {
this.element = element;
this.handler = handler;
if (element.addEventListener) {
element.addEventListener('touchstart', this, false);
element.addEventListener('click', this, false);
}
};
MBP.fastButton.prototype.handleEvent = function(event) {
switch (event.type) {
case 'touchstart': this.onTouchStart(event); break;
case 'touchmove': this.onTouchMove(event); break;
case 'touchend': this.onClick(event); break;
case 'click': this.onClick(event); break;
}
};

onTouchStart方法用于监听touchmovetouchend事件。stopPropagation用于停止事件在监听器中的传播,以便它停止冒泡:

MBP.fastButton.prototype.onTouchStart = function(event) {
event.stopPropagation();
this.element.addEventListener('touchend', this, false);
document.body.addEventListener('touchmove', this, false);
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
this.element.style.backgroundColor = "rgba(0,0,0,.7)";
};

touchmove用于测试用户是否在拖动。如果用户拖动超过 10 像素,我们将重置它:

MBP.fastButton.prototype.onTouchMove = function(event) {
if(Math.abs(event.touches[0].clientX - this.startX) > 10 || Math.abs(event.touches[0].clientY - this.startY) > 10) {
this.reset();
}
};

以下代码防止幽灵点击并调用实际的点击处理程序:

MBP.fastButton.prototype.onClick = function(event) {
event.stopPropagation();
this.reset();
this.handler(event);
if(event.type == 'touchend') {
MBP.preventGhostClick(this.startX, this.startY);
}
this.element.style.backgroundColor = "";
};
MBP.fastButton.prototype.reset = function() {
this.element.removeEventListener('touchend', this, false);
document.body.removeEventListener('touchmove', this, false);
this.element.style.backgroundColor = "";
};

还有更多...

您可以在 Google 的博客上阅读有关快速按钮的更多信息。它详细解释了这个想法背后的背景和理论:code.google.com/mobile/articles/fast_buttons.html

参见

使用文本区域和自动增长表单构建联系页面

隐藏 WebKit chrome

目标设备:iOS,Android

iOS 和 Android 上移动 Safari 的 URL 栏使用了大量空间。许多开发人员会在页面加载时隐藏它,因为移动房地产有限。每个像素都很重要,通过隐藏 URL 栏,可以帮助您利用屏幕上的每个像素,最大化显示区域。

准备工作

首先,让我们创建一个名为ch04r07.html的 HTML 文档。

如何做...

输入以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html,body,header,footer{
padding:0;
margin:0;
}
header{
height:40px;
background:#BFB840;
display:block;
}
#main{
height:350px;
background:#F2CB67;
}
footer{
height:40px;
background:#DB5E31;
display:block;
}
</style>
</head>
<body>
<header>
header
</header>
<div id="main">
main
</div>
<footer>
footer
</footer>
<script src="img/jquery.js"></script>
<script src="img/helper.js"></script>
<script>
//MBP.hideUrlBar();
</script>
</body>
</html>

现在,如果您在浏览器中呈现它,它将看起来像这样:

如何做...

现在取消以下行的注释:

MBP.hideUrlBar();

再次呈现内容,您会看到 chrome 现在被隐藏,允许页脚显示:

如何做...

它是如何工作的...

以下是 Boilerplate 中的脚本:

MBP.hideUrlBar = function () {
var win = window,
doc = win.document;
// If there's a hash, or addEventListener is undefined, stop here
if( !location.hash || !win.addEventListener ){
//scroll to 1
window.scrollTo( 0, 1 );
var scrollTop = 1,
//reset to 0 on bodyready, if needed
bodycheck = setInterval(function(){
if( doc.body ){
clearInterval( bodycheck );
scrollTop = "scrollTop" in doc.body ? doc.body.scrollTop : 1;
win.scrollTo( 0, scrollTop === 1 ? 0 : 1 );
}
}, 15 );
win.addEventListener( "load", function(){
setTimeout(function(){
//reset to hide addr bar at onload
win.scrollTo( 0, scrollTop === 1 ? 0 : 1 );
}, 0);
}, false );
}
};

它检测 URL 中是否有任何哈希。如果有,我们将停止运行脚本,因为这意味着有一个内联锚点。如果没有任何哈希,我们将等待一秒,如果没有滚动,Android 使用 1 像素的 y 位置进行隐藏,而在 iOS 中为 0。脚本对两者进行了规范化。它是由Scott Jehl制作的:gist.github.com/1183357

它也包含在 Mobile Boilerplate 中:github.com/h5bp/mobile-boilerplate/blob/master/js/mylibs/helper.js

另请参阅

使用文本区域和自动增长表单构建联系页面

构建移动站点地图

目标设备:跨浏览器

许多开发人员熟悉 Google 站点地图。作为最大的搜索引擎,确保它获取我们的内容非常重要。为了移动 SEO 目的,Google 提出了移动站点地图。Google 建议人们将其移动站点地图更新为下面描述的格式。

准备工作

首先,让我们创建一个 XML 文档并将其命名为sitemap.xml

如何做...

我们可以将以下代码添加到 XML 文档中。对于您拥有的特定网站,URL 应该是您页面的 URL:

<?xml version="1.0" encoding="UTF-8" ?>
<urlset 
>
<url>
<loc>http://mobile.example.com/article100.html</loc>
<mobile:mobile/>
</url>
</urlset>

所有 URL 都包含在<loc></loc>中。

确保您已包含<mobile:mobile/>。否则,站点将无法被正确爬取。

它是如何工作的...

站点地图遵循特定的模式;上述 XML 模式用于告诉 Google 搜索引擎移动网页的位置。通常,如果网站使用 CMS 系统构建,应该有一种自动生成 URL 的方法,并且它们都应该在<loc></loc>中列出。

还有更多...

移动站点地图不能包含仅限桌面的 URL。但是,它可以包含桌面和移动内容。

对于具有专用移动内容和专用 URL 的网站,您可以将用户从example.com重定向到m.example.com。在这种情况下,对用户和 Googlebot-Mobile 都使用 301 重定向。

如果您从example.com提供所有类型的内容,则 Google 不认为这是欺骗。

Google 和移动友好的站点构建

在 Google 网站管理员网站上,有一篇关于如何使网站移动友好的博客文章:googlewebmastercentral.blogspot.com/2011/02/making-websites-mobile-friendly.html

Google 和移动站点索引

Google 网站管理员网站上还有另一篇博客,讨论如何帮助 Google 索引您的移动站点:googlewebmastercentral.blogspot.com/2009/

第五章:移动设备访问

在本章中,我们将涵盖:

  • 获取您的位置

  • 处理跨浏览器地理位置

  • 根据您的地理位置显示地图

  • 实时定位

  • DeviceOrientation事件

  • 使用 foursquare 的地理位置

介绍

在所有 HTML5 类中,与移动开发最相关的类之一必须是设备访问。

这是 W3C HTML5 Movement 网站上设备访问的官方描述(www.w3.org/html/logo/):

从地理位置 API 开始,Web 应用程序可以呈现丰富的、设备感知的功能和体验。令人难以置信的设备访问创新正在被开发和实施,从音频/视频输入访问到麦克风和摄像头,再到诸如联系人和事件之类的本地数据,甚至倾斜方向。

您可以在以下网址找到描述和徽标:www.w3.org/html/logo/ #the-technology

基于位置的社交网络,如 foursquare,对业务运作方式和人们的动员方式产生了深远影响。如果 Groupon 发布了基于位置的新优惠,可能会从根本上改变消费者行为和零售业的运作方式。Google 地图使用实时地理位置和 GPRS 来帮助人们和车辆导航。将会有越来越多基于这种设备访问技术构建的令人兴奋的创新。

在本章中,我们将研究地理位置 API 和 DeviceOrientation API,解决跨浏览器问题,并看看我们如何将设备访问与流行的基于位置的服务一起使用。

获取您的位置

目标浏览器:Android、iOS、webOS、Opera、Firefox

使用地理位置 API,我们可以返回当前位置的纬度、经度和精度等值:

  • 纬度和经度:这些属性是地理坐标,以十进制度数指定

  • 精度:表示纬度和经度坐标的精度级别,以米为单位指定

准备就绪

让我们创建一个 HTML 文档,并获取纬度和经度以及精度。首先,让我们创建一个新的 HTML 文件,并将其命名为ch05r01.html

如何做...

将以下代码输入到 HTML 文档中:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main">
<div id="someElm">
</div>
</div>
<script src="img/jquery-1.5.2.min.js"></script>
<script>
function getLocation() {
navigator.geolocation.getCurrentPosition(showInfo);
}
function showInfo(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var accuracy = position.coords.accuracy;
$('#someElm').html('latitude: '+latitude+'<br />longitude: '+longitude+'<br />accuracy: '+accuracy);
}
getLocation();
</script>
</body>
</html>

当您首次渲染它时,您将收到以下消息提示:

如何做...

地理位置支持是可选的。没有浏览器会自动将设备的物理位置发送到服务器。相反,它会在执行发送设备位置的程序之前征求您的许可。浏览器可以记住您的偏好,以防止它再次从同一网站弹出。

现在按下允许分享位置的按钮。然后,您将在屏幕上看到显示的位置数据如下:

如何做...

它是如何工作的...

navigator是 JavaScript 程序员所熟悉的对象。它通常用于用户代理检测:navigator.userAgent

geolocationnavigator对象上的一个新属性:navigator.geolocation

getCurrentPositionnavigator.geolocation的一个方法。在这个例子中,我们将函数showInfo作为第一个参数执行:

navigator.geolocation.getCurrentPosition(showInfo);

showInfo函数中,我们从position参数返回三个值,即纬度、经度精度

var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var accuracy = position.coords.accuracy;

还有更多...

那么,前面提到的属性是地理位置 API 可能返回的全部吗?从理论上讲,可以返回更多的信息,但实际上,只有选定的浏览器会返回额外的信息。

处理跨浏览器地理位置

目标浏览器:跨浏览器

地理位置在所有移动浏览器上都不起作用,即使对于支持它的浏览器,它们的 API 也可能与标准不同。iOS 和 Android 使用标准。已知具有不同 API 的浏览器包括 Blackberry、Nokia 和 Palm。幸运的是,我们有一个移动中心的地理位置填充——geo-location-javascript。它具有非标准的 Blackberry 和 webOS 技巧,以帮助规范不同的 API 行为。

准备工作

下载本章附带的资源,并创建一个js文件夹。将geo.js放入js文件夹中。现在创建一个名为ch05r02.html的 HTML 文档。

如何做...

将以下代码输入 HTML 文档中:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="img/gears_init.js" type="text/javascript" charset="utf-8"></script>
<script src="img/geo.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="main">
<div id="someElm">
</div>
</div>
<script src="img/jquery-1.5.2.min.js"></script>
<script>
if(geo_position_js.init()){
geo_position_js.getCurrentPosition(success_callback,error_callback,{enableHighAccuracy:true,options:5000});
}
else{
$('#someElm').html("Functionality not available");
}
function success_callback(p)
{
$('#someElm').html('latitude: '+p.coords.latitude+'<br />longitude: '+p.coords.longitude+'<br />accuracy: '+p.coords.accuracy);
}
function error_callback(p)
{
$('#someElm').html('error='+p.message);
}
</script>
</body>
</html>

在 Opera 中进行测试,您应该能够看到以下结果:

如何做...

它是如何工作的...

在 HTML 文档的顶部,我们链接到gears_init.js。如果浏览器没有默认支持的地理位置 API,但安装了 Gears,则 Gears API 可能会返回地理位置数据。对于具有地理位置 API 但使用不同方法的浏览器,将使用第二个脚本geo.js来规范化 API。

如果geo_position_js.init()返回 true,则意味着我们以某种方式能够获取地理位置数据。在这种情况下,我们将继续下一步。我们使用geo_position_js.getCurrentPosition作为方法,而不是使用navigator.geolocation.getCurrentPosition

geo_position_js.getCurrentPosition(showInfo,error_callback,{enableHighAccuracy:true,options:5000});

还有更多...

这是一个额外的资源,可以帮助您获取地理位置信息。

YQL Geo 库

YQL Geo 库提供了一种替代方法,即基于 IP 地址的地理位置。这是一个轻量级库,与 Yahoo 服务相关联。它可以:

  • 从文本中获取地理位置

  • 从纬度/经度获取位置信息

  • 从特定 URL 获取所有地理位置

  • 从 IP 号码获取地点

根据您的地理位置显示地图

目标浏览器:跨浏览器

Google Maps API V3 已经设计成在移动设备上快速加载并在移动设备上运行良好。特别是,我们专注于为 iPhone 和运行 Android 操作系统的手机等先进移动设备开发。移动设备的屏幕尺寸比桌面上的典型浏览器小。此外,它们通常具有特定于这些设备的特定行为,例如 iPhone 上的“捏合缩放”。

准备工作

让我们创建一个在您的移动设备上显示的地图。首先,让我们创建一个名为ch05r03.html的 HTML 文档。

如何做...

输入以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="img/js?sensor=true"></script>
<script src="img/gears_init.js"></script>
<script src="img/geo.js"></script>
<style>
html {
height: auto;
}
body {
height: auto;
margin: 0;
padding: 0;
}
#map_canvas {
height: auto;
position: absolute;
bottom:0;
left:0;
right:0;
top:0;
}
</style>
</head>
<body>
<div id="map_canvas"></div>
<script src="img/jquery-1.5.2.min.js"></script>
<script>
var initialLocation;
var siberia = new google.maps.LatLng(60, 105);
var newyork = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
var browserSupportFlag = new Boolean();
var map;
var infowindow = new google.maps.InfoWindow();
function initialize() {
var myOptions = {
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
if(geo_position_js.init()){
browserSupportFlag = true;
geo_position_js.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
contentString = "you are here";
map.setCenter(initialLocation);
infowindow.setContent(contentString);
infowindow.setPosition(initialLocation);
infowindow.open(map);
});
}
}
function detectBrowser() {
var useragent = navigator.userAgent;
var mapdiv = document.getElementById("map_canvas");
if (useragent.indexOf('iPhone') != -1 || useragent.indexOf('Android') != -1) {
mapdiv.style.width = '100%';
mapdiv.style.height = '100%';
} else {
mapdiv.style.width = '600px';
mapdiv.style.height = '800px';
}
}
detectBrowser();
initialize();
</script>
</body>
</html>

在您的移动浏览器中呈现如下:

如何做...

它是如何工作的...

现在让我们来分解代码,看看每个部分的作用:

  1. iPhone 具有捏合缩放功能,Google Maps API V3 对此事件有特殊处理。因此,您可以设置以下元标记,以确保用户无法调整 iPhone 的大小。运行软件版本 1.5(杯子蛋糕)的 Android 设备也支持这些参数:
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />

  1. 将包含地图的<div>设置为 100%的宽度和高度属性:
mapdiv.style.width = '100%';
mapdiv.style.height = '100%';

  1. 您可以通过检查 DOM 中的navigator.userAgent属性来检测 iPhone 和 Android 设备:
function detectBrowser() {
var useragent = navigator.userAgent;
var mapdiv = document.getElementById("map_canvas");
if (useragent.indexOf('iPhone') != -1 || useragent.indexOf('Android') != -1 ) {
mapdiv.style.width = '100%';
mapdiv.style.height = '100%';
} else {
mapdiv.style.width = '600px';
mapdiv.style.height = '800px';
}
}

  1. 指定传感器参数,使用传感器确定用户位置的应用程序在加载 Maps API JavaScript 时必须传递sensor=true
<script type="text/javascript" src="img/js?sensor=true"></script>

使用 Google Maps API 需要指示您的应用程序是否使用传感器(例如 GPS 定位器)来确定用户的位置。这对于移动设备尤为重要。在包含 Maps API JavaScript 代码时,应用程序必须将所需的传感器参数传递给<script>标记,指示您的应用程序是否使用传感器设备。

提示

请注意,即使我们针对的设备不使用传感器设备,我们仍然必须传递此参数,并将其值设置为false

  1. 我们将地理位置坐标解析到地图 API 的LatLng方法中:
initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);

还有更多...

您可以在官方文档页面了解更多关于 Google Maps JavaScript API V3 的信息:

code.google.com/apis/maps/documentation/javascript/

HTML5 地理位置教程

Mobile tuts 有一篇关于移动地理位置的优秀文章,名为HTML5 Apps: Positioning with Geolocation。您可以在以下链接阅读:

HTML5 Apps: Positioning with Geolocation

mobile.tutsplus.com/tutorials/mobile-web-apps/html5-geolocation/

实时显示位置

目标浏览器:跨浏览器

除了getCurrentPosition,地理位置 API 还有另一个名为watchPosition的方法。当调用时,它执行两个重要的操作:

  1. 它返回一个标识监视操作的值。

  2. 它异步地开始监视操作。

准备工作

让我们创建一个名为ch05r04.html的 HTML 文档。

如何做...

将以下代码输入文档中:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style>
html {
height: auto;
}
body {
height: auto;
margin: 0;
padding: 0;
}
#map_canvas {
height: auto;
position: absolute;
bottom:0;
left:0;
right:0;
top:0;
}
</style>
</head>
<body>
<div id="map_canvas"></div>
<script type="text/javascript" src="img/js?sensor=true"></script>
<script src="img/jquery-1.5.2.min.js"></script>
<script>
var watchProcess = null;
var initialLocation;
var map;
var infowindow = new google.maps.InfoWindow();
var myOptions = {
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
navigator.geolocation.getCurrentPosition(function(position) {
updatePos(position.coords.latitude,position.coords.longitude,position.coords.accuracy);
});
initiate_watchlocation();
function initiate_watchlocation() {
if (watchProcess == null) {
watchProcess = navigator.geolocation.watchPosition(handle_geolocation_query, handle_errors);
}
}
function stop_watchlocation() {
if (watchProcess != null)
{
navigator.geolocation.clearWatch(watchProcess);
watchProcess = null;
}
}
locationdisplaying, in real timefunction handle_errors(error)
{
switch(error.code)
{
case error.PERMISSION_DENIED: alert("user did not share geolocation data");
break;
case error.POSITION_UNAVAILABLE: alert("could not detect current position");
break;
case error.TIMEOUT: alert("retrieving position timedout");
break;
default: alert("unknown error");
break;
}
}
function handle_geolocation_query(position) {
updatePos(position.coords.latitude,position.coords.longitude,position.coords.accuracy);
}
function updatePos(lat,long,acc) {
var text = "Latitude: " + lat + "<br/>" + "Longitude: " + long + "<br/>" + "Accuracy: " + acc + "m<br/>";
initialLocation = new google.maps.LatLng(lat,long);
contentString = text;
map.setCenter(initialLocation);
infowindow.setContent(contentString);
infowindow.setPosition(initialLocation);
infowindow.open(map);
}
</script>
</body>
</html>

这是它将如何呈现的:

如何做...

它是如何工作的...

以下函数将启动位置监视:

function initiate_watchlocation() {
if (watchProcess == null) {
watchProcess = navigator.geolocation.watchPosition(handle_geolocation_query, handle_errors);
}
}

navigator.geolocation.watchPosition将在执行时返回成功或错误。在成功函数中,您可以解析纬度和经度:

navigator.geolocation.watchPosition(handle_geolocation_query, handle_errors);

当位置正在被监视时,handle_geolocation_query用于获取当前位置并解析到更新位置函数中:

function handle_geolocation_query(position) {
updatePos(position.coords.latitude,position.coords.longitude,position.coords.accuracy);
}

使用 DeviceOrientation 事件

目标浏览器:iOS

DeviceOrientation事件是设备访问的重要方面。它包括设备运动事件和设备方向事件。不幸的是,这些事件目前只在 iOS 中受支持。

准备工作

创建一个名为ch05r05.html的 HTML 文档。

如何做...

将以下代码输入文档中:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="img/js?sensor=true"></script>
<style>
#no {
display: none;
}
#ball {
width: 20px;
height: 20px;
border-radius: 10px;
background-color: red;
position:absolute;
top: 0px;
left: 0px;
}
</style>
</head>
<body>
<div id="content">
<h1>Move the Ball</h1>
<div id="yes">
<p>Move your device to move the ball.</p>
<div id="ball"></div>
</div>
<div id="no">
Your browser does not support Device Orientation and Motion API. Try this sample with iPhone, iPod or iPad with iOS 4.2+.</div>
</div>
<script>
// Position Variables
var x = 0;
var y = 0;
// Speed - Velocity
var vx = 0;
var vy = 0;
// Acceleration
var ax = 0;
var ay = 0;
var delay = 10;
var vMultiplier = 0.01;
if (window.DeviceMotionEvent==undefined) {
document.getElementById("no").style.display="block";
document.getElementById("yes").style.display="none";
} else {
window.ondevicemotion = function(event) {
ax = event.accelerationIncludingGravity.x;
ay = event.accelerationIncludingGravity.y;
}
setInterval(function() {
DeviceOrientation eventusingvy = vy + -(ay);
vx = vx + ax;
var ball = document.getElementById("ball");
y = parseInt(y + vy * vMultiplier);
x = parseInt(x + vx * vMultiplier);
if (x<0) { x = 0; vx = 0; }
if (y<0) { y = 0; vy = 0; }
if (x>document.documentElement.clientWidth-20) { x = document.documentElement.clientWidth-20; vx = 0; }
if (x>document.documentElement.clientWidth-20) { x = document.documentElement.clientWidth-20; vx = 0; }
if (y>document.documentElement.clientHeight-20) { y = document.documentElement.clientHeight-20; vy = 0; }
ball.style.top = y + "px";
ball.style.left = x + "px";
}, delay);
}
</script>
</body>
</html>

它是如何工作的...

这段代码是由Maximiliano Firtman制作的(www.mobilexweb.com/blog/safari-ios-accelerometer-websockets-html5)。在示例中,我们使用了accelerationIncludingGravity。它返回设备的总加速度值,包括用户加速度和重力。

三个值 x,y,z 分别代表每个轴上的加速度(以 m/s² 为单位):

window.ondevicemotion = function(event) {
event.accelerationIncludingGravity.x
event.accelerationIncludingGravity.y
event.accelerationIncludingGravity.z
}

它是如何工作的...

还有更多...

这是一个显示当前对DeviceOrientationEventDeviceMotionEvent支持的表格:

属性 描述 返回值 支持
acceleration 用户给设备的加速度。 x,y,z(以 m/s² 为单位) DeviceMotion Event iPhone 4 / iPod Touch 4G
acceleration IncludingGravity 设备的总加速度,包括用户加速度和重力。 x,y,z(以 m/s² 为单位) DeviceMotion Event iPhone3 / iPod Touch 3G
interval 自上次设备运动事件以来的毫秒间隔。 毫秒 DeviceMotion Event iPhone3 / iPod Touch 3G
rotationRate 设备的旋转速率。 alpha,beta 和 gamma(值在 0 到 360 之间) DeviceMotionEvent iPhone 4 / iPod Touch 4G
alpha 设备框架绕其 z 轴旋转的角度。 值在 0 到 360 之间。 DeviceOrientation Event iPhone 4 / iPod Touch 4G
beta 设备框架绕其 x 轴旋转的角度。 值在-180 到 180 之间。 DeviceOrientation Event iPhone 4 / iPod Touch 4G
gamma 设备框架绕其 y 轴旋转的角度。 值在-90 到 90 之间。 DeviceOrientation Event iPhone 4 / iPod Touch 4G

设备方向事件规范

dev.w3.org/geo/api/spec-source-orientation.html

Safari 官方指南

DeviceOrientation事件规范:

developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/DeviceMotionEventClassRef/DeviceMotionEvent/DeviceMotionEvent.html

DeviceOrientationEvent类参考:

developer.apple.com/library/safari/#documentation/SafariDOMAdditions/Reference/DeviceOrientationEventClassRef/DeviceOrientationEvent/DeviceOrientationEvent.html

使用 foursquare 的地理位置

目标浏览器:跨浏览器

近年来,基于地理位置的社交网络网站 foursquare 变得越来越受欢迎。它影响了许多企业的工作方式和消费者的行为。用户使用移动网站、移动应用程序或短信在各个地方“签到”。

准备工作

第三方开发人员已发布了许多用于从各种编程语言访问 foursquare API 的库。其中之一是 Marelle。它基于 jQuery,用 coffeescript 编写。别担心,那只是 JavaScript。

如何做...

转到 Marelle 的 GitHub 页面(praized.github.com/marelle/)并下载最新版本。有两个示例,一个是登录,另一个是签到。

这是登录脚本的样子:

// Supply your foursquare client id
var FSQUARE_CLIENT_ID = 'FOURSQUARE_CLIENT_ID';
// on DOM ready...
$(function() {
// setup with your key and a callback function which
// receives the Marelle Object ( "M" in this example )
$.Marelle( FSQUARE_CLIENT_ID ).done( function( M ){
// grab an authentication promise
var authpromise = M.authenticateVisitor();
// handle logged-in visitor
var authsuccess = function(visitor){
M.signoutButton( document.body );
console.log(visitor)
/*
I think the single entry point is through the visitor
*/
venuepromise = visitor.getVenues()
// venuepromise.then etc..etc...
};
// handle non visitor
var authfailure = function() {
M.signinButton( document.body );
};
// wait for promise to resolve
authpromise.then(authsuccess,authfailure)
}).fail(function(){
consoloe.log('Marelle could not be loaded.')
});
});

它是如何工作的...

它是如何工作的:

  1. 首先触发 Marelle 初始化$.Marelle(clientID),它会返回一个承诺:
$.Marelle( FSQUARE_CLIENT_ID )

  1. 然后我们使用$.Marelle.authenticateVisitor()获取认证承诺:
$.Marelle( FSQUARE_CLIENT_ID ).done( function( M ){
var authpromise = M.authenticateVisitor();
});

  1. 根据认证的结果,authpromise.then()用于执行authsuccessauthfailure
authpromise.then(authsuccess,authfailure)

  1. 如果认证成功,它会将“断开连接”按钮附加到提供的选择器:
M.signoutButton( document.body );

  1. 可以返回推荐场所的列表,添加或搜索场所:
venuepromise = visitor.getVenues()

  1. 如果认证失败,它会将“连接”按钮附加到提供的选择器:
M.signinButton( document.body );

还有更多..

可以在以下网址找到 foursquare API 的列表:

developer.foursquare.com/docs/libraries.html

第六章:移动丰富媒体

在本章中,我们将涵盖:

  • 从移动浏览器播放音频

  • 在移动设备上流式传输视频

  • 使用 Appcache 进行离线查看

  • 使用 Web Storage 进行 Feed 或电子邮件应用程序

  • 使用 web workers 进行大量计算工作

  • 创建类似 Flash 的导航,使用会话和历史 API

介绍

使用 HTML5,您可以构建丰富的媒体应用程序以在移动设备上显示。使用 HTML5 的方式有无限种,唯一的限制是想象力。

在之前的章节中,我们已经涵盖了 HTML5 的语义命名、CSS3 和设备访问类别。在本章中,我们将介绍另外三个类别:

  • 多媒体—越来越多的人在移动设备上播放视频和音频,我们将看到如何在移动设备上嵌入这些元素。

  • 离线和存储—离线是移动设备的重要功能,因为连接在移动设备上并不一直稳定。存储对于移动设备存储数据以减少用户每次访问页面时的获取是有用的。

  • 性能和集成—在 iOS 和 Blackberry 上支持 web workers,我们可以在移动浏览器上获得更好的性能。

在移动设备上播放音频

目标浏览器:iOS、Android、Blackberry、webOS、Opera Mobile、Firefox Mobile

多媒体包括音频和视频。在移动设备上播放音频可能会有些棘手。在移动浏览器上有一些支持的音频格式—Ogg Vorbis、MP3 和 WAV。这些格式的问题之一是并非所有浏览器都支持它们。

准备工作

创建一个 HTML 文档并将其命名为ch06r01.html

如何做...

在文档中输入以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main">
<audio src="img/snake_charmer.mp3" controls preload="auto" autobuffer>
</audio>
</div>
</body>
</html>

现在在浏览器中渲染时,您将看到一个音乐播放器显示如下,当您按下播放时,音乐应该会流式传输:

如何做...

它是如何工作的...

使用音频标签非常简单。音频被包含在<audio></audio>标签中。

controls 告诉音频元素显示可视控件,如暂停、播放等。

autobuffer让浏览器处理缓冲和流式传输。autobuffer属性具有布尔值。如果它在音频标签中;音频将自动缓冲。preload=auto使流式传输在播放之前甚至预加载。

在移动设备上音频流式传输的一个问题是格式支持。下表显示了支持比较:

浏览器 Ogg Vorbis MP3 WAV
Android WebKit Yes Yes
Opera Mobile Yes
Firefox Mobile Yes Yes
iOS Safari Yes Yes

如表所示,支持一直不够一致。这对于跨浏览器音频流式传输可能会很麻烦。您可以使用多个轨道来解决这个问题。如果浏览器无法识别第一个源标签中的轨道,它将尝试下一个。正如我们从前面的表中所看到的,最广泛支持的格式是 MP3。

它在大多数移动浏览器中都受支持,除了 Firefox。对于 Firefox,我们可以使用 Ogg,因此以下代码更适用于跨移动浏览器:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main">
<audio controls preload="auto" autobuffer>
<source src="img/snake_charmer.mp3" />
<source src="img/snake_charmer.ogg" />
</audio>
</div>
</body>
</html>

还有更多...

您可能会问,'那些不支持 HTML5 音频标签的浏览器怎么办?' 有音频 polyfills,但一般来说,我不认为在移动音频中使用 polyfills 有意义。一个原因是因为这些 polyfills 是使用 Flash 制作的,而 Flash Lite 只支持有限的移动设备,如塞班。一个解决方案是在音频标签之前简单地包含一个链接。它不会被支持音频标签的浏览器渲染,但会显示在不支持音频标签的浏览器上。您可以通过在音频标签关闭之前添加一个下载链接来实现:

<div id="main">
<audio controls preload="auto" autobuffer>
<a href="http://resources/snake_charmer.mp3">play or download here</a>
</audio>
</div>

现在,如果您在 Windows Phone 上渲染此内容,将显示如下:

还有更多...

如果您点击链接,它将简单地由系统的默认音乐播放器打开:

还有更多...

W3C 音频工作组

当前的音频元素缺乏客户端 API。W3C 音频工作组(www.w3.org/2011/audio/)成立以解决这个问题。该 API 将支持高级交互应用程序所需的功能,包括在脚本中直接处理和合成音频流的能力。您可以订阅参与讨论:<public-audio-request@w3.org>

在移动设备上流媒体视频

目标浏览器:iOS、Android、Blackberry、webOS、Opera Mobile、Firefox Mobile

从桌面平台访问最多的网站之一是视频网站,如www.youtube.comwww.vimeo.com。它们有为移动设备优化的版本。视频流是移动设备的重要组成部分。人们喜欢在移动设备上观看视频,尤其是 YouTube 上的短视频。它们需要更少的时间来缓冲,观看完也不需要花费太多时间。那么视频在移动设备上是如何工作的呢?让我们首先创建一个示例。

准备工作

创建一个名为ch06r02.html的 HTML 文档。

如何做...

将以下代码输入 HTML 文档中:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main">
<video id="movie" width="320" height="240" preload controls>
<source src="img/test.mp4" />
<source src="img/pr6.webm" type='video/webm; codecs="vp8, vorbis"' />
<source src="img/pr6.ogv" type='video/ogg; codecs="theora, vorbis"' />
<object width="320" height="240" type="application/x-shockwave-flash"data=" http://releases.flowplayer.org/swf/flowplayer-3.2.1.swfflowplayer-3.2.1.swf"> data="flowplayer-3.2.1.swf">
<param name="movie" value=" http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf" />
<param name="allowfullscreen" value="true" />
<param name="flashvars" value='config={"clip": {"url":http://diveintohtml5.info/i//test.mp4", "autoPlay":false, "autoBuffering":true}}' />
<p>Download video as <a href=" http://diveintohtml5.info/i/pr6.mp4">MP4</a>, <a href=" http://diveintohtml5.info/i/pr6.webm">WebM</a>, or <a href=" http://diveintohtml5.info/i/pr6.ogv">Ogg</a>.</p>
</object>
</video>
<p>Try this page in Safari 4! Or you can <a href=" http://diveintohtml5.info/i//test.mp4">download the video</a> instead.</p>
</div>
</body>
</html>

现在,如果您在移动浏览器中打开它,您应该看到视频播放器已呈现。

如何做...

它是如何工作的...

代码的一部分取自Mark Pilgrim 的 Dive into HTML5。您一定会想,这是一项非常艰巨的工作来让视频工作!在这里,让我们看看每个部分的作用。iOS 和 Android 都支持 H.264(mp4)格式,添加webmogv版本以确保它也可以在其他桌面和移动设备上呈现。

如果您有多个<source>元素,iOS 只会识别第一个。由于 iOS 设备只支持 H.264+AAC+MP4,您必须始终首先列出您的 MP4。这个错误在 iOS 4.0 中已经修复。因此,在这个例子中,我们将test.mp4列为第一个。

<source src="img/test.mp4" />
<source src="img/pr6.webm" type='video/webm; codecs="vp8, vorbis"' />
<source src="img/pr6.ogv" type='video/ogg; codecs="theora, vorbis"' />

以下是添加的 Flash 回退,以确保不支持 HTML5 视频的站点可以播放视频:

<object width="320" height="240" type="application/x-shockwave-flash"data=" http://releases.flowplayer.org/swf/flowplayer-3.2.1.swfflowplayer-3.2.1.swf"> data="flowplayer-3.2.1.swf">
<param name="movie" value=" http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf" />
<param name="allowfullscreen" value="true" />
<param name="flashvars" value='config={"clip": {"url": "resources http://diveintohtml5.info/i//test.mp4", "autoPlay":false, "autoBuffering":true}}' />
<p>Download video as <a href="test.mp4">MP4</a>, <a href="test.webm">WebM</a>, or <a href="test.ogv">Ogg</a>.</p>
</object>

还有更多...

Mark Pilgrim 的 Dive into HTML5详细介绍了在不同浏览器上呈现视频时遇到的问题。您可以在以下网址阅读:diveintohtml5.info/video.html

Android 2.3 之前的版本在 HTML5 视频方面存在一些问题。<source>元素上的 type 属性让早期版本的 Android 感到困惑。让它识别视频源的唯一方法是讽刺的是完全省略 type 属性,并确保您的 H.264+AAC+MP4 视频文件的名称以.mp4扩展名结尾。您仍然可以在其他视频源上包括 type 属性,因为 H.264 是 Android 2.2 支持的唯一视频格式。这个错误在 Android 2.3 中已经修复。

controls属性不受支持。包括它不会产生任何不良影响,但 Android 不会为视频显示任何用户界面控件。您需要提供自己的用户界面控件。至少,您应该提供一个脚本,当用户点击时开始播放视频。这个错误在 Android 2.3 中也已经修复。

使用离线缓存

目标浏览器:iOS、Android、Opera Mobile、webOS、Firefox Mobile

除了设备访问之外,离线缓存是移动设备最重要的功能之一。桌面浏览和移动浏览之间最大的区别之一是移动用户总是在行动。与通常使用单一稳定连接的桌面浏览不同,移动浏览可能在移动中进行,在 3G 和 WiFi 之间切换,并在隧道等地方完全离线。离线缓存可以帮助解决因与互联网断开连接而引起的问题。

设备 支持
iOS 是的(3.2+)
Android 是的(2.1+)
Windows Mobile
Blackberry v6.0 及以上
Symbian 60
Palm webOS 是的
Opera Mobile 是的
Firefox Mobile 是的

准备工作

让我们创建一个文本文件并将其命名为default.appcache

如何做...

在我们刚刚创建的default.appcache文件中,输入以下内容:

CACHE MANIFEST
# version 1
img/apple-touch-icon.png
#img/splash.png
NETWORK:
#http://example.com/api/
FALLBACK:

现在创建一个 HTML 文档并将其命名为ch06r03.html:

<!doctype html>
<html manifest="default.appcache">
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<img src="img/apple-touch-icon.png" alt="Apple Touch Icon" />
</body>
</html>

现在如果你加载页面,禁用互联网连接并重新加载页面。你会发现页面仍然加载。

它是如何工作的...

CACHE MANIFEST下的任何内容都包括了将被缓存以供离线查看的文件。包含缓存清单文件的文件将自动包含在内,这意味着:

CACHE MANIFEST
# version 1
img/apple-touch-icon.png
#img/splash.png

NETWORK部分列出了所有你不希望被缓存的 URL。这些是每次重新加载页面时应该加载的文件。这类文件的一个例子是 API 调用。你不希望浏览器缓存动态 API 返回。如果你所有的 API 调用都来自同一个前缀,你不必把它们都包括进来。相反,你只需要包括前缀。例如,如果你有以下 URL 列表:

http://example.com/api/?loc=paris
http://example.com/api/?loc=london

不要一次添加到列表中,你可以只添加一个:

NETWORK:
http://example.com/api/

FALLBACK部分是用于列出页面 URL 替换的网络 URL,当浏览器离线或远程服务器不可用时使用。

还有更多...

你可能会问为什么我们使用.appcache而不是.manifest作为扩展名?这是因为.appcache是由 WHATWG 推荐的。由于它是一个标准,并且没有浏览器支持的问题,最好使用.appcache

你可能还想知道的一件事是这些扩展是否被浏览器识别。不用担心,以下的AddType将帮助.appcache.manifest以正确的 MIME 类型呈现。将以下内容添加到.htaccess文件中:

AddType text/cache-manifest appcache manifest

Appcache facts

要了解更多关于 Appcache 的信息,可以访问Appcache Facts网站(appcachefacts.info/)。它有关于 Appcache 的许多有用和宝贵的信息。它还维护了一个链接列表,链接到探索 Appcache 的网站:

WHATWG 的官方描述

如果你想深入了解规范,可以阅读 HTML Living Standard 的官方描述:

www.whatwg.org/specs/web-apps/current-work/multipage/ offline.html

在移动设备上使用 Web 存储

目标浏览器:跨浏览器

Web 存储对离线应用非常有用,特别是新闻订阅或电子邮件 Web 应用。当人们谈论 Web 存储时,他们通常指的是localStorage部分。它是一个键/值持久性系统。除了 Web 存储,还有两个 HTML5 存储功能;它们是索引数据库 APIWeb SQL 数据库

让我们来看看 Web 存储、索引数据库和 Web SQL 数据库的优缺点。

存储类型 优点 缺点
Web Storage 简单易用的 API**受主要浏览器支持 没有数据隐私
索引数据库 没有类似 SQL 的结构化存储 大多数移动浏览器尚不支持**没有 SQL(显然)
Web SQL Database 快速功能丰富的 SQL 实现受主要新移动浏览器支持 W3C 工作组已经将其暂停了标准

从移动浏览器支持的角度来看,Web Storage 得到了最广泛的支持,其次是 Web SQL 数据库。

Web SQL 数据库具有比 Web Storage 更好的功能集。因此,在这个示例中,我们将专注于 Web Storage 和 Web SQL 数据库,而不是索引数据库(至少目前是这样)。

准备工作

创建一个 HTML 文档并将其命名为ch06r04.html

如何做...

首先,输入以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="img/modernizr.custom.54685.js"></script>
</head>
<body>
<section>
<p>Values are stored on <code>keyup</code></p>
<p>Content loaded from previous sessions:</p>
<div id="previous"></div>
</section>
<section>
<div>
<label for="local">localStorage:</label>
<input type="text" name="local" value="" id="local" />
</div>

现在我们要添加 JavaScript 部分:

<script>
var addEvent = (function () {
if (document.addEventListener) {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.addEventListener(type, fn, false);
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
} else {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.attachEvent('on' + type, function () { return fn.call(el, window.event); });
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
}
})();
function getStorage(type) {
var storage = window[type + 'Storage'],
delta = 0,
li = document.createElement('li');
if (!window[type + 'Storage']) return;
if (storage.getItem('value')) {
delta = ((new Date()).getTime() - (new Date()).setTime(storage.getItem('timestamp'))) / 1000;
li.innerHTML = type + 'Storage: ' + storage.getItem('value') + ' (last updated: ' + delta + 's ago)';
} else {
li.innerHTML = type + 'Storage is empty';
}
document.querySelector('#previous').appendChild(li);
}
getStorage('local');
addEvent(document.querySelector('#local'), 'keyup', function () {
localStorage.setItem('value', this.value);
localStorage.setItem('timestamp', (new Date()).getTime());
});
</script>

现在在文件的末尾,让我们关闭 HTML 文档:

</section>
</body>
</html>

localStorage甚至可以在 Dolphin 中使用,这是三星使用的浏览器,可以安装在任何安卓设备上。在 Dolphin 浏览器中渲染页面时,您可以输入任何单词。在这种情况下,如果您输入"hullo world",一旦您点击刷新,它将显示这些信息:

如何做...

它是如何工作的...

正如前面提到的,它真的就是值/键对,您可以使用setget方法存储数据。

要设置数据,您可以使用setItem方法:

localStorage.setItem('value', this.value);

要获取数据,您可以使用:

storage.getItem('value')

寻找一个 polyfill?jQuery Offline 是一个不错的离线存储插件。它使用 HTML5 的localStorage API 进行持久化。您可以在不支持localStorage的浏览器上使用相同的 API。jQuery Offline 将简单地回退到每次向服务器发出请求。您可以在github.com/wycats/jquery-offline了解更多信息。

还有更多...

Web SQL 数据库是localStorage的替代方案,受到使用 SQL 的人的喜爱。Remy Sharp在 github 上有一个非常好的演示,展示了如何使用 Web SQL 数据库。您可以在html5demos.com/database了解更多信息。

Web Storage 可移植层

Web Storage 可移植层库允许您轻松为支持 HTML5 数据库或 Gears 的浏览器编写离线存储代码。

Gears 是由 Google 开发的早期离线存储系统。它在 IE6 和 IE Mobile 4.0.1 等浏览器上受到支持,但已不再开发。

您可以在以下网址了解更多关于这个库的信息:google-opensource.blogspot.com/2009/05/web-storage-portability-layer-common.html

HTML5 存储之争

您可以在以下网址了解更多关于 localStorage vs. IndexedDB vs. Web SQL 的信息:csimms.botonomy.com/2011/05/html5-storage-wars-localstorage-vs-indexeddb-vs-web-sql.html

使用 Web Workers

目标浏览器:Opera Mobile,Firefox Mobile,iOS5,黑莓

大多数具有 Java/Python/.NET 背景的程序员应该熟悉多线程或并发编程。曾经有人嘲笑 JavaScript 缺乏高级线程,但随着 HTML5 的出现,其 API 已经扩展以允许并发,大大增加了其有效能力!JavaScript 不再只是一种脚本语言。随着越来越多使用 JavaScript 创建的复杂任务,它在处理繁重的前端计算时必须表现得更好。

设备 支持
iOS 是(5.0+)
安卓
Windows Mobile
黑莓 是(6.0+)
塞班
Palm webOS
Opera Mobile
Firefox Mobile

准备工作

让我们创建一个 JavaScript 文件并将其命名为math.js

如何做...

将以下代码输入到文档中:

/* math.js */
function addNumbers(x,y) {
return x + y;
}
function minNumbers(x,y) {
return x - y;
}
/*
Add an eventlistener to the worker, this will
be called when the worker receives a message
from the main page.
*/
this.onmessage = function (event) {
var data = event.data;
switch(data.op) {
case 'mult':
postMessage(minNumbers(data.x, data.y));
break;
case 'add':
postMessage(addNumbers(data.x, data.y));
break;
default:
postMessage("Wrong operation specified");
}
};

现在,让我们创建一个 HTML 文档并将其命名为ch06r05.html。将以下代码输入到 HTML 文件中:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="img/modernizr.custom.54685.js"></script>
</head>
<body onload="loadDeals()">
<input type="text" id="x" value="6" />
<br />
<input type="text" id="y" value="3" />
<br />
<input type="text" id="output" />
<br />
<input type="button" id="minusButton" value="Subtract" />
<input type="button" id="addButton" value="Add" />
<script>
if (Modernizr.webworkers){
alert('hi');
}
/* Create a new worker */
arithmeticWorker = new Worker("js/math.js");
/*
Add an event listener to the worker, this will
be called whenever the worker posts any message.
*/
arithmeticWorker.onmessage = function (event) {
document.getElementById("output").value = event.data;
};
/* Register events for buttons */
document.getElementById("minusButton").onclick = function() {
/* Get the values to do operation on */
x = parseFloat(document.getElementById("x").value);
y = parseFloat(document.getElementById("y").value);
message = {
'op' : 'min',
'x' : x,
'y' : y
};
arithmeticWorker.postMessage(message);
}
document.getElementById("addButton").onclick = function() {
/* Get the values to do operation on */
x = parseFloat(document.getElementById("x").value);
y = parseFloat(document.getElementById("y").value);
message = {
'op' : 'add',
'x' : x,
'y' : y
};
arithmeticWorker.postMessage(message);
}
</script>
</body>
</html>

在移动浏览器中呈现此页面时,我们可以看到三个字段和两个用于计算的按钮。在以下示例截图中,我输入了 6 和 3,然后按下添加按钮,看到 9 显示为结果:

如何做...

它是如何工作的...

我们可以将math.js分为三个部分:

  • 实际的数学函数

  • 从主文件(HTML 文档)获取事件

  • 将信息发送到主文件(HTML 文档)

实际的数学函数相当容易理解,addNumbers是一个用于加法的函数,minNumbers用于减法:

/* math.js */
function addNumbers(x,y) {
return x + y;
}
function minNumbers(x,y) {
return x - y;
}

接下来是onmessage。这是math.js从 HTML 文档获取的信息:

this.onmessage = function (event) {
var data = event.data;
...
};

一旦math.js工作程序从主文件(HTML 文档)获取信息,它将开始进行数学计算,并通过使用postMessage将结果发送回主文件:

switch(data.op) {
case 'mult':
postMessage(minNumbers(data.x, data.y));
break;
case 'add':
postMessage(addNumbers(data.x, data.y));
break;
default:
postMessage("Wrong operation specified");
}

在 HTML 文档中也有三个部分,如下所示:

  • 创建工作程序

  • 将信息发送到工作程序进行数学计算

  • 通过工作程序完成数学计算

创建工作程序相当容易。通过调用new Worker("math.js")来创建:

/* Create a new worker */
arithmeticWorker = new Worker("js/math.js");

要向工作程序发送信息,可以使用与math.js中解释的相同的postMessage方法。消息本身可以是具有名称/值对的对象:

message = {
'op' : 'min',
'x' : x,
'y' : y
};
arithmeticWorker.postMessage(message);

完成工作程序完成数学计算后,我们使用与math.js中解释的相同的onmessage方法获取信息:

arithmeticWorker.onmessage = function (event) {
document.getElementById("output").value = event.data;
};

使用会话和历史 API 创建类似 Flash 的导航

目标浏览器:跨浏览器

过去,人们不得不使用哈希标签来伪造 URL,以在 SEO 和平滑的页面转换之间进行妥协。现在,有了历史 API,就不再需要这种黑客行为。使用历史 API 和 Ajax 调用,可以动态更新 URL。

设备平台 支持
iOS 是(4.2+)
Android 是(2.2+)
Windows Mobile
Blackberry
Symbian 是(5.2+)
Palm webOS
Opera Mobile
Firefox Mobile

准备就绪

让我们创建一个 HTML 文档并将其命名为ch06r06.html

如何做...

在 HTML 文档中输入以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="img/modernizr.custom.54685.js"></script>
<style>
section {width:300px; background:#ccc; padding:5px; margin:20px auto;}
html, body, figure {padding:0; margin:0;}
figcaption {display:block;}
</style>
</head>
<body>
<section id="gallery">
<p class="photonav"><a id="photoprev" href="http://ch06r06_b.html">&lt; Previous</a> <a id="photonext" href="http://ch06r06_a.html">Next ></a></p>
<figure id="photo">
<img id="photoimg" src="img/300" alt="Fer" width="300" height="300"><br />
<figcaption>Adagio, 1982</figcaption>
</figure>
</section>
<script src="img/nav.js"></script>
</body>
</html>

现在让我们创建另一个文档并将其命名为ch06r06_a.html。将以下代码输入其中:

<p class="photonav"><a id="photoprev" href="http://ch06r06_b.html">&lt; Previous</a> <a id="photonext" href="http://ch06r06_b.html">Next ></a></p>
<figure id="photo">
<img id="photoimg" src="img/301" alt="Fer" width="300" height="300">
<figcaption>Aida, 1990</figcaption>
</figure>

现在让我们创建另一个文档并将其命名为ch06r06_b.html。将以下代码输入文档:

<p class="photonav"><a id="photoprev" href="http://ch06r06_a.html">&lt; Previous</a> <a id="photonext" href="http://ch06r06_a.html">Next ></a></p>
<figure id="photo">
<img id="photoimg" src="img/299" alt="Fer" width="300" height="300">
<figcaption>Air Cat, 2001</figcaption>
</figure>

现在让我们创建一个 JavaScript 文件并输入以下代码。将以下代码中的 URL 替换为您自己的 URL:

function supports_history_api() {
return !!(window.history && history.pushState);
}
function swapPhoto(href) {
var req = new XMLHttpRequest();
req.open("GET",
"http://localhost /work/packt/ch06_code/" +
href.split("/").pop(),
false);
req.send(null);
if (req.status == 200) {
document.getElementById("gallery").innerHTML = req.responseText;
setupHistoryClicks();
return true;
}
return false;
}
function addClicker(link) {
link.addEventListener("click", function(e) {
if (swapPhoto(link.href)) {
history.pushState(null, null, link.href);
e.preventDefault();
}
}, true);
}
function setupHistoryClicks() {
addClicker(document.getElementById("photonext"));
addClicker(document.getElementById("photoprev"));
}
window.onload = function() {
if (!supports_history_api()) { return; }
setupHistoryClicks();
window.setTimeout(function() {
window.addEventListener("popstate", function(e) {
swapPhoto(location.pathname);
}, false);
}, 1);
}

现在让我们在移动浏览器中呈现页面。当您单击上一页下一页按钮时,页面不会刷新。但是,如果您查看 URL,它们已更新:

如何做...

它是如何工作的...

history.pushState用于将新的 URL 推送到浏览器地址栏:

history.pushState(null, null, link.href);

实际的页面导航是对服务器的 Ajax 请求,因此页面永远不会重新加载。但是 URL 将使用以下函数进行更新:

function swapPhoto(href) {
var req = new XMLHttpRequest();
req.open("GET",
"http://192.168.1.11:8080/work/packt/ch06_code/" +
href.split("/").pop(),
false);
req.send(null);
if (req.status == 200) {
document.getElementById("gallery").innerHTML = req.responseText;
setupHistoryClicks();
return true;
}
return false;
}

还有更多...

要了解有关历史 API 的更多信息,您可以深入研究规范:www.whatwg.org/specs/web-apps/current-work/multipage/history.html

Mark PilgrimDive into HTML5中有一个很好的详细解释:diveintohtml5.info/history.html

您还可以在Mozilla's MDC Docs中了解更多信息:developer.mozilla.org/en/DOM/Manipulating_the_browser_history

放置小猫

想知道小猫图片来自哪里吗?它来自一个名为placekitten.com/的网站。这是一个快速简单的服务,用于获取小猫图片,以便在设计或代码中使用它们作为占位符。

第七章:移动调试

在本章中,我们将涵盖:

  • 使用 Opera Dragonfly 进行远程调试

  • 使用 weinre 进行远程调试

  • 在移动设备上使用 Firebug

  • 使用 JS 控制台进行远程调试

  • 设置移动 Safari 调试

介绍

尽管调试可能需要大量时间,但它是网页开发的重要方面,无论是桌面还是移动。在本章中,我们将介绍一些用于使前端调试更容易,更快速,并使网页开发更高效的移动调试工具。

使用 Opera Dragonfly 进行远程调试

目标浏览器:Opera Mobile

由于移动屏幕相对较小,移动调试与桌面调试不同。

准备工作

  1. 确保您连接到 WiFi 网络。

  2. www.opera.com/下载最新版本的 Opera 桌面浏览器。

  3. 在您的移动设备上下载 Opera Mobile。

如何做...

  1. 在撰写本文时,Opera 的版本为 11.50。一些说明可能会在您阅读本书时发生变化。

  2. 在您的桌面上打开 Opera,并从下拉菜单中选择页面 | 开发者工具 | Opera Dragonfly

  3. 您应该会看到一个调试工具出现在页面底部。点击远程调试配置,如下截图所示:如何做...

  4. 一旦我们点击远程调试配置按钮,将会出现一个弹出面板。

  5. 在面板上,您可以看到一个文本字段来指定端口号和一个应用按钮。默认号码应该是未使用的,并且应该可以正常工作。点击应用:如何做...

  6. 现在打开您的桌面控制台并输入ipconfig作为命令。IPv4 地址就是您的 IP 地址。

  7. 在移动设备上打开 Opera Mobile,输入opera:debug在 URL 地址栏中,我们将到达一个如下的页面:如何做...

  8. 输入您从桌面控制台获取的 IP 地址,然后点击连接。现在移动浏览器应该连接到 Dragonfly:如何做...

它是如何工作的...

在 Opera Mobile 上打开一个新标签,访问 Yahoo.com,现在切换到桌面,点击选择调试上下文,这是右上角的第四个按钮。从下拉菜单中选择Yahoo!开始检查页面!

它是如何工作的...

另请参阅

  • 使用 weinre 进行远程调试

  • 使用 JS 控制台进行远程调试

使用 weinre 进行远程调试

目标浏览器:iOS,Android,Blackberry,webOS

在上一个步骤中,我们看到了如何远程调试 Opera 移动页面。在这个步骤中,我们将看到如何在其他移动设备上进行远程调试。Weinre是一个Web Inspector Remote

支持的操作系统包括:

  • Android 2.2 浏览器应用

  • Android 2.2 w/PhoneGap 0.9.2iOS 4.2.x

  • 移动 Safari 应用

  • BlackBerry v6.x 模拟器

  • webOS 2.x(未指定版本)

准备工作

首先,我们必须从官方网站下载 weinre;有两个版本可用,一个是 PC 版,一个是 Mac 版:

github.com/phonegap/weinre/archives/master

如何做...

  1. 首先,在控制台中运行ipconfig获取您的 IP 地址。

  2. 创建一个名为ch07r01.html的 HTML 文档。将192.168.1.11替换为您自己的 IP 地址:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<header>
<h1>Mobile Cookbook</h1>
</header>
<div id="main">
</div>
<script src="img/target-script-min.js"></script>
</body>
</html>

  1. 首先,找到下载的weinre.jar文件。在我的情况下,路径是C:\xampp\htdocs\dev\weinre.jar。其次,获取 IP 地址,在我的情况下是http://192.168.1.11

  2. 现在打开控制台并输入以下行:

java -jar path/to/weinre.jar -httpPort 8081 -boundHost http://192.168.1.11

  1. 要测试是否有效,请访问 URL 地址http://192.168.1.11:8081/,应该会出现接近以下截图的页面:如何做...

它是如何工作的...

现在使用您的移动设备访问创建的示例页面:

它是如何工作的...

现在,回到桌面,点击调试客户端用户界面。不要在标签中打开,而是在新窗口中打开。

你应该能够看到类似以下截图的东西:

它是如何工作的...

点击元素,现在你可以检查元素(如下图所示):

它是如何工作的...

在移动设备上使用 Firebug

目标浏览器:跨浏览器

许多人在 Firefox 和 Chrome 上使用 Firebug,但 Firebug Lite 可以在支持 JavaScript 的任何浏览器上使用。在这个教程中,我们将看到如何使用 Firebug 进行调试。

准备工作

创建一个 HTML 文档并将其命名为ch07r02.html

如何操作...

  1. 在 HTML 中输入以下代码:
<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main">
</div>
<script type="text/javascript" src="img/firebug-lite.js"></script>
</body>
</html>

  1. 在移动浏览器中渲染它:如何操作...

它是如何工作的...

Firebug Lite 是 Firebug 的 JavaScript 版本。以下代码将加载托管在 Firebug 网站上的 Firebug Lite 脚本:

<script type="text/javascript" src="img/firebug-lite.js"></script>

你也可以下载脚本并将其添加为本地版本。

你可以访问 HTML、CSS 和 JavaScript,并查看 DOM。控制台可用于 JavaScript 输入。

Firebug Lite 有四个发布渠道:

  • 稳定通道

  • 调试通道

  • Beta 通道

  • 开发者通道

我们一直在使用的是稳定通道。其他通道在还有更多部分下有解释。

还有更多...

除了实时和本地版本,你还可以添加书签。它可能无法在所有浏览器上运行。以下是如何操作的。

  1. 点击页面右侧的链接:getfirebug.com/firebuglite还有更多...

  2. 这将在移动浏览器的 URL 末尾添加哈希#javascript:(function..

  3. 在 Safari 上收藏该页面。

  4. 编辑书签的名称为书签的名称,Firebug Lite,Firebug Lite 调试或 Firebug Lite beta。

  5. 保存书签后,打开书签菜单,选择Firebug Lite,然后点击编辑。删除 URL 和#,只保留以javascript:(function开头的部分。

  6. 现在,如果你打开任何网页并点击Firebug Lite 书签,一个 Firebug 控制台将出现在页面的右下角。

调试通道

调试通道使用与稳定通道相同的版本,但具有不同的预配置,使得调试 Firebug Lite 本身变得更容易。

Beta 通道

Beta 通道是新功能和修复的地方。它应该是相当稳定的(没有已知的回归),但可能会包含一些错误,一些功能可能不完整。

开发者通道

开发者通道是创意和测试的地方。一旦它直接绑定到我们的代码存储库,你将获得可能的最新代码,并且将比其他渠道更频繁地接收更新。但需要注意的是,开发者通道有时可能非常不稳定,初始加载可能会较慢。

使用 JS 控制台进行远程 JavaScript 调试

目标浏览器:跨浏览器

如果你只是寻找远程 JavaScript 调试,Remy Sharp有一个名为 JavaScript 控制台的很棒的工具。它对于移动调试非常有效。

准备工作

访问jsconsole.com/,你会看到下面显示的页面:

准备工作

如何操作...

  1. 在网站上输入:listen,你应该看到以下信息消息返回:

创建连接...

连接到"65C1F9F1-6A57-46C0-96BB-35C5B515331F"

  1. 接下来将是一行类似于 JavaScript 的代码:
<script src="img/remote.js?65C1F9F1-6A57-46C0-96BB-35C5B515331F"></script>

如何操作...

  1. 创建一个 HTML 页面并将其命名为ch07r04.html。将以下代码输入到文档中,用你从 jsconsole.com 得到的<script>...</script>替换:
<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
>
<div id="main">
</div>
<script src="img/remote.js?04926BFB-44AB-4979-BAE9-F4A4FA7CE22C"></script>
<script>
for (var i=0; i<10; i++) {
console.log('testing '+i);
}
</script>
</body>
</html>

  1. 现在,如果我们在移动设备上渲染页面,我们会看到桌面屏幕网页上出现日志消息:如何操作...

它是如何工作的...

在以下循环中,我们使用console.log输出一串消息:

<script>
for (var i=0; i<10; i++) {
console.log('testing '+i);
}
</script>

从您的 Web 应用程序中对console.log的任何调用都将在监听您的密钥的 jsconsole 会话中显示结果。同样,如果您在 jsconsole 会话中运行命令,代码将被注入到您的 Web 应用程序中,并将结果返回给 jsconsole。

还有更多...

整个 JavaScript 控制台 Web 应用程序是开源的;如果您想了解更多关于它是如何制作的,请访问:github.com/remy/jsconsole

JS 控制台 iOS 应用

JS Console for iOS,也是由Remy Sharp制作的,是一个 JavaScript 控制台,用于测试和检查 JavaScript 的结果,而无需在线或在浏览器中。

简单的 iOS 模拟器示例

这段由Remy Sharp制作的视频展示了如何在 iOS 上使用 jsconsole.com 进行远程调试 JavaScript。它展示了如何接收日志并发送任意命令:

www.youtube.com/watch?v=Y219Ziuipvc&feature=player_embedded

在任何设备上远程调试 JavaScript

在以下视频中,Remy Sharp录制了如何使用 jsconsole.com 远程调试任何设备上的任何浏览器的操作步骤:

www.youtube.com/watch?v=DSH392Gxaho&feature=player_embedded

设置移动 Safari 调试

目标浏览器:iOS

在 iOS 移动 Safari 上,有一个用于调试的内置调试器。

准备就绪

拿起 iPhone 并导航到主屏幕。

如何做...

  1. 找到并打开设置应用程序:如何做...

  2. 选择Safari如何做...

  3. 向下滚动以找到底部的开发人员选项:如何做...

  4. 默认情况下,调试控制台关闭的:如何做...

  5. 现在我们可以将调试控制台切换到打开如何做...

  6. 在 Safari 中,查找页面顶部 URL 栏下方的调试控制台摘要信息:如何做...

  7. 点击摘要信息以查看页面上的错误的详细报告。

  8. 现在,让我们创建一个 HTML 文档并将其命名为ch07r05.html。将以下代码输入到页面中:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main">
</div>
<script>
for (var i=0; i<3; i++) {
console.log('testing '+i);
}
</script>
</body>
</html>

  1. 在渲染时,我们可以看到:如何做...

它是如何工作的...

一旦点击调试控制台,它将带您到消息屏幕:

它是如何工作的...

以下脚本用于创建调试消息:

<script>
for (var i=0; i<3; i++) {
console.log('testing '+i);
}
</script>

第八章:服务器端调优

在本章中,我们将涵盖:

  • 防止移动转码

  • 添加移动 MIME 类型

  • 使缓存清单正确显示

  • 设置远期过期标头

  • Gzip 压缩

  • 实体标签移除

介绍

服务器端性能直接影响页面加载速度。适当的服务器配置可以极大地提高客户端加载速度。

在本章中,我们将介绍一些用于使移动网站和应用程序性能更好更快的服务器端配置。一些概念是移动中心的;一些也适用于桌面网络。

有许多服务器最佳实践指南,但有些可能不够全面。在本章中,我们将结合最佳实践,看看如何最大化网站的性能。

防止移动转码

目标浏览器:跨浏览器

许多移动运营商使用代理或适配引擎来更改您要提供的网页内容。在许多移动设备上,内置或安装的浏览器使用移动转码器来重新格式化和压缩页面内容。这被称为移动转码。如果您不希望内容被更改,必须添加 HTTP 头部以防止移动转码。

准备工作

.htaccess文件用于在文件目录级别配置 Apache 服务器。配置也可以通过编辑httpd.conf来完成。因为许多服务器托管公司不允许访问安装了 Apache 的根目录,所以在这个例子中,我们使用.htaccess。这使得在目录级别进行服务器配置更容易,因为与主httpd.conf不同,它不需要服务器重新启动。创建或打开一个.htaccess文件。

如何做...

将以下代码添加到.htaccess文件中:

<FilesMatch "\.(php|cgi|pl)$">
Header append Cache-Control "no-transform"
Header append Vary "User-Agent, Accept"
</FilesMatch>

.htaccess文件上传到要应用规则的文件夹中。

通过这样做,我们已经防止了移动转码的发生。

它是如何工作的...

FilesMatch用于仅过滤 CGI 和 PHP 脚本,因为我们不希望将此规则应用于其他文件类型。

<FilesMatch "\.(php|cgi|pl)$">

假设启用了 Apache 模块mod_headers,我们可以在FilesMatch部分中添加头部Cache-Control "no-transform"

Header append Cache-Control "no-transform"

还有更多...

以下资源可能有助于了解更多关于移动转码的信息。

Microsoft Internet Information Server (IIS)

如果您正在使用Microsoft Internet Information Server (IIS),可以使用软件界面进行配置。有关如何执行此操作的详细信息可以在以下位置找到:

mobiforge.com/developing/story/setting-http-headers-advise-transcoding-proxies

负责任的重新格式化

以下文章提供了一些关于网络运营商进行的内容转码的影响的见解:

mobiforge.com/developing/blog/responsible-reformatting

MBP — Mobile Boilerplate

本章中使用的代码片段也包含在 Mobile Boilerplate 中:

github.com/h5bp/mobile-boilerplate/blob/master/.htaccess

添加移动 MIME 类型

目标浏览器:黑莓,塞班

黑莓和诺基亚浏览器支持许多移动专属内容类型。在本主题中,我们将看一些这些移动浏览器使用的 MIME 类型。由于服务器可能默认不识别它们,因此在服务器配置中正确添加它们非常重要。

准备工作

.htaccess文件用于在文件目录级别配置 Apache 服务器。它使得在目录级别进行服务器配置变得容易。创建或打开一个.htaccess文件。

如何做...

将以下代码添加到.htaccess文件中:

AddType application/x-bb-appworld bbaw
AddType text/vnd.rim.location.xloc xloc
AddType text/x-vcard vcf
AddType application/octet-stream sisx
AddType application/vnd.symbian.install sis

.htaccess文件上传到要应用规则的文件夹中。

它是如何工作的...

我们使用AddType:使移动 MIME 类型可识别:

代码 描述
AddType application/x-bb-appworld bbaw 包含在 BlackBerry App World™商店中找到的应用程序的应用程序 ID 的文本文件。
AddType text/vnd.rim.location.xloc xloc BlackBerry 地图位置文档。
AddType text/x-vcard vcf 一个 vCard 文件,一种用于电子名片的标准文件格式。
AddType application/octet-stream sisx 诺基亚类型
AddType application/vnd.symbian.install sis 诺基亚类型

还有更多...

有关 BlackBerry 支持的更多移动文件类型,请访问:

docs.blackberry.com/en/developers/deliverables/18169/index.jsp?name=Feature+and+Technical+Overview+-+BlackBerry+Browser6.0&language=English&userType=21&category=BlackBerry+Browser&subCategory=

使缓存清单正确显示

目标浏览器:跨浏览器

如第六章中所解释的,移动富媒体,缓存清单用于离线 Web 应用程序。服务器可能无法识别此文件的扩展名。让我们看看如何添加正确的 MIME 类型。

准备工作

创建或打开一个.htaccess文件。

如何做...

添加以下代码:

AddType text/cache-manifest appcache manifest

上传.htaccess文件到您希望应用规则的文件夹。

它是如何工作的...

缓存清单可以使用.appcache.manifest作为其扩展名。通过将这两种类型都添加为text/cache-manifest,我们确保无论使用哪种类型,它们都可以正确呈现。

MBP 移动样板

.htaccess规则包含在移动样板中:

github.com/h5bp/mobile-boilerplate/blob/master/.htaccess#L75

设置远期过期标头

目标浏览器:跨浏览器

为文件设置远期过期标头可通过减少不必要的 HTTP 请求来提高站点性能。对于需要加载许多资源的富媒体站点,这可以提高整体性能。有不同的文件类型,根据文件的使用,我们选择不同的过期时间。

准备工作

创建或打开一个.htaccess文件。

如何做...

添加以下代码:

<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
ExpiresByType text/cache-manifest "access plus 0 seconds"
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType image/x-icon "access plus 1 week"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType video/ogg "access plus 1 month"
ExpiresByType audio/ogg "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
ExpiresByType text/x-component "access plus 1 month"
ExpiresByType font/truetype "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
<IfModule mod_headers.c>
Header append Cache-Control "public"
</IfModule>
</IfModule>

上传.htaccess文件到您希望应用规则的文件夹。

它是如何工作的...

以下是代码的分解,我们将看到它是如何工作的:

  1. 白名单过期规则:
ExpiresDefault "access plus 1 month"

  1. cache.appcache在 FF 3.6 中需要重新请求:
ExpiresByType text/cache-manifest "access plus 0 seconds"

  1. 您的文档 HTML 不应该被缓存:
ExpiresByType text/html "access plus 0 seconds"

  1. 数据不应该被缓存,因为它总是需要被拉取的:
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"

  1. RSS 订阅更新频率低于正常 API 数据:
ExpiresByType application/rss+xml "access plus 1 hour"

  1. Favicon 不能被重命名,所以最好的方法是将其设置为一周后:
ExpiresByType image/x-icon "access plus 1 week"

  1. 对于诸如图像、视频和音频之类的大型媒体资源,我们可以将日期设置得更久远:
ExpiresByType image/gif "access plus 1 month"
...
ExpiresByType video/webm "access plus 1 month"

  1. HTC 文件,如果您使用 HTML5 polyfill - CSS3PIE 会很有用:
ExpiresByType text/x-component "access plus 1 month"

  1. 安全地将 Webfonts 缓存一个月:
ExpiresByType font/truetype "access plus 1 month"
...
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"

  1. 对于 CSS 和 JavaScript,我们可以将过期日期设置为一年后:
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"

还有更多...

这些都是相当远期的过期标头。它们假定您使用缓存破坏查询参数来控制版本:

<script src="img/script_034543.js" ></script>

此外,考虑到过时的代理可能会错误缓存:

www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/

添加一个 Expires 或 Cache-Control 标头

在 Yahoo!开发者网络中,有关过期规则的解释非常好:

developer.yahoo.com/performance/rules.html#expires

MBP 移动样板中的规则

这些规则包含在 Mobile Boilerplate 的.htacess 文件中:

github.com/h5bp/mobile-boilerplate/blob/master/.htaccess#L142

使用 Gzip 压缩文件

目标浏览器:跨浏览器

前端开发人员在决定如何减少在网络上传输 HTTP 请求和响应所需的时间方面发挥着重要作用。Gzip 压缩可通过减小 HTTP 响应的大小来减少响应时间。

Gzip 可以大大减小响应大小,通常可减小 70%。Gzip 在现代浏览器中得到广泛支持。

大多数服务器默认只压缩某些文件类型,因此最好定义支持广泛的文本文件的规则,包括 HTML、XML 和 JSON。

准备工作

创建或打开一个 .htaccess 文件。

如何做...

将以下代码添加到 .htaccess 中:

<IfModule mod_deflate.c>
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s,?\s(gzip|deflate)?|X{4,13}|~{4,13}|-{4,13})$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
<IfModule filter_module>
FilterDeclare COMPRESS
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/css
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/javascript
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/plain
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $text/x-component
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/javascript
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/json
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-javascript
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xhtml+xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/rss+xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/atom+xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/vnd.ms-fontobject
FilterProvider COMPRESS DEFLATE resp=Content-Type $image/svg+xml
FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-font-ttf
FilterProvider COMPRESS DEFLATE resp=Content-Type $font/opentype
FilterChain COMPRESS
FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
</IfModule>
<IfModule !mod_filter.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
AddOutputFilterByType DEFLATE image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype
</IfModule>
</IfModule>

.htaccess 文件上传到要应用规则的文件夹中。

它是如何工作的...

以下代码强制对损坏的标头进行通缩,以便检测损坏的模式,mod_setenvif 用于执行正则表达式匹配并设置一个环境变量,指示损坏的 Accept-Encoding 标头存在:

SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s,?\s(gzip|deflate)?|X{4,13}|~{4,13}|-{4,13})$ HAVE_Accept-Encoding

强制请求标头支持压缩很简单:

RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding

压缩 HTML、TXT、CSS、JavaScript、JSON、XML、HTC:

<IfModule filter_module>
FilterDeclare COMPRESS
...
FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
</IfModule>

对于 Apache 2.1 之前的旧版本:

<IfModule !mod_filter.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
AddOutputFilterByType DEFLATE image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype
</IfModule>

还有更多...

需要注意的是,图像和 PDF 文件不需要进行 Gzip 压缩,因为它们已经默认进行了压缩。对它们进行 Gzip 压缩将浪费 CPU 使用率,甚至会增加文件大小。

超越 Gzip

Marcel Duran 在 Yahoo! Network 上的一篇关于 Gzip 的文章谈到了最近的研究和服务器端方法:

developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/

移除 ETags

目标浏览器:跨浏览器

ETags 代表 实体标签。实体是诸如 CSS 或 JavaScript 文件、图像等组件。实体标签的作用是标识组件的特定版本。您可以在 Yahoo! Developer Network, 高性能网站:规则 13 配置 ETags (developer.yahoo.com/blogs/ydn/posts/2007/07/high_performanc_11/) 中找到更多详细信息。

如果您的网站由多个服务器托管,例如在内容交付网络上,ETag 的验证机制可能会导致额外的重新获取。验证模型中几乎没有优势,所以最佳实践是只需移除 ETag。

准备工作

创建或打开一个 .htaccess 文件。

如何做...

添加以下代码:

<IfModule mod_headers.c>
Header unset Etag
</IfModule>
FileETag None

.htaccess 文件上传到要应用规则的文件夹中。

它是如何工作的...

首先,我们取消当前已配置文件的 ETag:

<IfModule mod_headers.c>
Header unset Etag
</IfModule>

其次,我们使用 FileTag None 来确保文件的 ETag 被移除:

FileETag None

还有更多...

以下部分提供了有关 ETags 的更多信息供您参考。

在 IIS 服务器上同步 ETag 值

如果您正在运行 IIS 服务器,为了解决问题,您必须同步运行 IIS 5.0 的所有 Web 服务器上的 ETag 值。为此,请使用 Mdutil.exe 工具从其中一个 Web 服务器检索 ETag 值。然后,在所有其他 Web 服务器上设置相同的 ETag 值。

更详细的说明可以在以下 Microsoft 支持文章中找到:

support.microsoft.com/?id=922733

高性能网站

Steve Souders 在他的 高性能网站 系列中解释了配置规则:

高性能网站:规则 13配置 ETags:

developer.yahoo.com/blogs/ydn/posts/2007/07/high_performanc_11/

David Walsh 博客

David Walsh的博客网站包含了 Eric Wendelin 的一篇文章 - 使用.htaccess 改善您的 YSlow 等级,其中也提到了这个配方中解决的问题:

davidwalsh.name/yslow-htaccess

MBP - 移动样板

实体标签的移除也包含在移动样板中:

github.com/h5bp/mobile-boilerplate/blob/master/.htaccess#L211-L218

第九章:移动性能测试

在本章中,我们将介绍:

  • 使用 Blaze 测试您的移动设备

  • 在线分析移动页面速度

  • PCAP Web 性能分析仪

  • HTTP 存档移动版

  • 使用 Jdrop 存储性能数据

介绍

在本章中,我们将介绍一些最热门的移动性能测试工具。

像移动调试一样,移动性能测试可能并不像桌面测试那样直接。但是每朵云都有一线阳光。许多开发人员已经找到了解决这些问题的创造性方法。

使用 Blaze 测试您的设备的速度

目标浏览器:跨浏览器

如果您想节省时间并快速测试移动站点的性能,了解加载时间和页面资源信息,那么 Blaze 是一个不错的选择。Mobitest 性能工具用于了解移动 Web 性能。它提供以下测试结果:

  • 总加载时间

  • 单个页面资源的分解

  • 渲染视频

  • 原始 HTTP 存档(HAR)文件

准备就绪

您只需登录www.blaze.io/mobile/

如何做...

如何做...

在页面上,您可以看到以下表单,允许您输入 URL。让我们测试yahoo.com

在结果页面的顶部,我们可以从屏幕截图中看到平均加载时间、页面大小和站点的速度排名:

如何做...

以下图表显示了站点的瀑布图:

如何做...

它是如何工作的...

使用的设备

您可能想知道后端使用了什么设备,它们是否是仿真器或模拟器。测试是在使用自定义构建的代理的真实移动设备上运行的。

加载时间百分位数

使用内部索引来计算加载时间百分位数。它使用数百个网站来获取站点速度与其他站点的比较。

测试运行的位置

测试运行位置在加拿大渥太华。代理通过 WiFi 连接到互联网。撰写时使用的设备有:iPhone、Nexus 和三星 Galaxy S。

要了解更多,请访问:

www.blaze.io/mobile/methodology/

还有更多...

可以在以下位置找到一些有用的页面测试工具列表:

www.blaze.io/learn/feo-resources/

Blaze 博客

除了提供的测试工具,Blaze 还有一个博客,其中有很多关于移动优化的文章,网址是:

www.blaze.io/blog/

Web 性能优化最佳实践

有关 Web 性能最佳实践的良好提示,请访问 Blaze 优化页面:

www.blaze.io/overview/optimizations/

在线分析移动页面速度

目标浏览器:跨浏览器

如果您熟悉 Google Page Speed,您会知道有一个 Chrome 扩展程序,用于测试桌面浏览器的加载时间。但是还有一个 Google Page Speed 的 Web 版本,可以用于分析移动性能。

准备就绪

访问 Google Page Speed Online:

pagespeed.googlelabs.com/

如何做...

在此示例中,我们将测试 Google 的移动主页:

  1. 输入您想要分析的 URL,在我们的例子中,让我们使用m.google.com:如何做...

  2. 单击输入框旁边的下拉列表,并从下拉菜单中选择获取移动建议如何做...

  3. 一旦点击分析移动性能,我们将进入以下页面:如何做...

它是如何工作的...

页面速度得分表示页面可以快多少。对于我们的例子,数字是 100 中的 62。

以下是分析的细节。细节已经分解如下:

  • 高优先级:这些建议代表了最大潜在的性能优胜者,而开发工作最少。您应该首先解决这些问题。

  • 中等优先级:这些建议可能代表着较小的收益或者更多的工作来实施。

  • 低优先级:这些建议代表最小的收益。

  • 实验性规则:这些建议是实验性的,但不会影响整体页面速度得分。

  • 没有建议的规则:对于这些规则没有建议,因为此页面已经遵循了这些最佳实践。但您仍然可以通过展开左侧可折叠菜单来检查规则。

还有更多...

要查看移动性能工具列表,请访问:

github.com/h5bp/mobile-boilerplate/wiki/Mobile-Performance-Tools

需要速度

麻省理工技术评论显示了一些关于速度有多重要以及它如何影响您网站访问者的图表和统计数据。文章提到,即使轻微的在线减速也会让人感到沮丧,并给公司带来损失:

www.technologyreview.com/files/54902/GoogleSpeed_charts.pdf

当时间很重要

Gomez Inc 进行了一项关于网站和移动性能期望的全国消费者调查:

www.gomez.com/wp-content/downloads/GomezWebSpeedSurvey.pdf

使用 PCAP Web 性能分析器分析移动性能

目标浏览器:跨浏览器

PCAP Web 性能分析器允许您更好地控制数据分析。您可以与移动网站/应用程序进行交互,并更准确地获取性能数据。它是由Bryan McQuadeLibo Song创建的。

准备工作

在使用 PCAP Web 性能分析器之前,我们需要先为移动设备捕获 PCAP 文件。我们通过设置一个私人 WiFi 网络,连接移动设备到网络,捕获,然后分析流量来实现。以下是如何做到这一点:

  1. 打开控制面板 | 网络和互联网 | 网络和共享中心

  2. 选择设置新的连接或网络的链接。

  3. 选择设置无线自组网(计算机对计算机)网络

  4. 接下来,给网络取一个名字(例如 hot1),并勾选保存此网络

  5. 返回网络和共享中心,点击左侧的更改适配器设置链接。

  6. 找到您的局域网,右键单击并打开属性 | 共享选项卡

  7. 启用共享。

现在我们需要下载 Wireshark,我们可以使用它来选择要捕获的网络流量。我们可以通过以下步骤生成 HAR 文件并将其保存在本地机器上:

  1. 从以下网址下载 Wireshark:www.wireshark.org/download.html

  2. 打开 WireShark。

  3. 点击菜单捕获 | 选项

  4. 选项对话框中,选择您的无线接口,然后点击捕获过滤器

  5. 捕获过滤器对话框中,创建一个新的过滤器(如果您还没有这样做),名称为TCP 和 UDP 端口 53(DNS),过滤字符串为tcp 或 udp 端口 53

  6. 选择过滤器,然后关闭对话框。

  7. 捕获选项对话框中点击开始按钮开始捕获。

  8. 完成后保存捕获。

要将移动设备连接到热点,请在移动设备上连接到指定的 WiFi 热点(在我们的示例中为“hot1”)。现在,您在移动设备上访问的任何网站都应该被tcpdump捕获。

如何做...

性能分析器页面上,选择您保存的 HAR 文件,然后点击上传。文件将被处理,并将显示带有瀑布的详细分析:

如何做...

它是如何工作的...

它使用开放文件格式 PCAP 和 HAR,以及开源工具 pcap2har、HAR 查看器和页面速度。

还有更多...

Stoyan Stefanov维护了一个非常有用的关于 Web 和移动性能的网站。

calendar.perfplanet.com/2010/mobile-performance-analysis-using-pcapperf/

HAR 查看器

正如官方描述所说,HAR Viewer 是一个基于 HTTP 存档格式(HAR)的 HTTP 跟踪日志的可视化 Web 应用程序(PHP + JavaScript)。该项目托管在 Google Code 上;您可以在以下网址查看:code.google.com/p/harviewer/

使用 Page Speed 优化您的移动网站

有一个关于使用 Google 的 Page Speed 的视频。该视频是在 Google I/O 2011 期间拍摄的,由 PACPPERF 的创作者呈现,您可以在以下网址找到:

www.google.com/events/io/2011/sessions/use-page-speed-to-optimize-your-web-site-for-mobile.html

pcap2har

要了解有关 pcap2har 的更多信息,您可以访问 Github 上托管的项目页面:

github.com/andrewf/pcap2har

使用 HTTP 存档移动版

目标浏览器:跨浏览器

HTTP 存档移动版跟踪 Web 的构建方式。它提供:

  • Web 技术趋势:加载时间,下载大小,性能得分

  • 有趣的统计数据:流行的脚本,图像格式,错误,重定向

  • 网站性能:特定 URL 截图,瀑布图,HTTP 头

准备工作

登录到mobile.httparchive.org/

如何做...

点击趋势,您可以查看诸如 HTML,JavaScript,CSS,图像和 Flash 的传输大小和请求等趋势。以下是 HTML 传输大小和 HTML 请求的图表:

如何做...

点击统计,您可以获得许多有趣的统计数据,从最常见的图像格式到最常见的服务器;从具有最多 CSS 的页面到具有最多图像的页面。

以下是显示最受欢迎的 JS 库的图表:

如何做...

点击网站,您将获得与特定网站相关的所有性能信息,包括 Filmstrip,瀑布图,页面速度,请求,趋势和 HAR 文件的下载。

它是如何工作的...

列出的网站是由 Alexa,财富,全球 500 和 Quancast10K 排名最高的网站。

URL 列表提供给WebPagetest.org

使用 JavaScript 从 HAR 文件生成 HTTP 瀑布图。

还有更多...

因此,您可能会问为什么我们需要记录这些数据。我们这样做是因为归档并从 Web 性能历史中学习是很重要的。正如Steve Souders所说,“HTTP 存档提供了这一记录。它是网页性能信息的永久存储库,如页面大小,失败的请求和使用的技术。”(在www.stevesouders.com/blog/2011/03/30/announcing-the-http-archive/))。

数据的准确性如何?

如果您想了解数据的准确性,请阅读:mobile.httparchive.org/about.php#accuracy关于测量的信息,特别是时间测量。

测试方法的限制

尽管测试结果在很大程度上是有用的,但用户需要注意一些限制。有关需要考虑的事项清单,请访问:

mobile.httparchive.org/about.php#limitations

使用 Jdrop 存储性能数据

目标浏览器:跨浏览器

Jdrop用于存储移动设备性能数据。JSON 数据存储在云中。

移动设备的屏幕空间较小,这使得分析大量信息变得困难。为了解决这个问题,Jdrop 允许您在大屏幕上分析从移动设备收集的数据。

准备工作

登录到 Jdrop jdrop.org/

如何做...

在您的移动设备上:

  1. 登录到 Jdrop。

  2. 安装任何使用 Jdrop 的应用程序。

  3. 运行应用程序并将数据保存到 Jdrop。

在您的台式机或笔记本电脑上:

  1. 登录 Jdrop。

  2. 查看您生成的 JSON 数据。

在移动设备上,开始的最简单方法是将jdrop-example.js的内容(可以在jdrop.org/jdrop-example.js)找到)嵌入到您的书签脚本中。此外,您还必须添加一个“保存到 Jdrop”的链接到您的书签,以调用您的函数。您可以在jdrop.org/devdocs找到带有解释的代码。

保存到 Jdrop:

以下是您需要添加“保存到 Jdrop”链接到您的书签的代码。

<a href="javascript:SaveToJdrop('MY APP NAME', myDataObj, '1.1.3', '1.8 secs')">Save to Jdrop</a>

注册您的应用程序:

目前,注册您的应用程序需要一些手动操作;您必须在 Jdrop 讨论列表(groups.google.com/group/jdrop/topics)上发布请求。

这是注册您的应用程序所需的信息:

  • 应用程序名称(必填)

  • 脚本 URL(必填)

  • 回调函数(可选)

  • 格式(可选)

  • 格式密钥(可选)

一些信息可能在您阅读此文时发生变化,您可以登录jdrop.org/devdocs检查是否有任何更新。

它是如何工作的...

当通过 Google 帐户连接时,您可能想知道为什么 Jdrop 要求访问您的 Google 联系人。这是因为 OAuth 到 Google 需要提到一个要进行身份验证的服务。Jdrop 实际上并不访问您的任何联系人。创建者正在考虑使用 OpenID 而不是 OAuth 来绕过这一步。

还有更多...

Jdrop 是由Steve SoudersJames Pearce创建的。

Steve Souders对大多数开发者来说并不陌生;要查看他创造的所有奇迹,请访问:

stevesouders.com/

詹姆斯·皮尔斯(James Pearce)是 Sencha Inc.的开发者关系总监。您可以在他的网站上找到有关移动设备的有趣想法和有用信息:

tripleodeon.com/

第十章:新兴移动 Web 功能

在本章中,我们将涵盖:

  • window.onerror

  • 使用 ECMAScript 5 方法

  • 新的 HTML5 输入类型

  • 内联 SVG

  • position:fixed

  • overflow:scroll

介绍

iOS 5 上的移动 Safari 引入了一系列改进,使移动 Safari 成为最先进的移动浏览器之一。添加了许多尖端的 HTML5 功能——ECMAScript 5 以及移动特定功能——以允许在移动设备上实现更多功能并提高性能:

  • Web forms已经被引入,以帮助改善 Web 的用户界面,使界面原型设计更快速、更容易。

  • 内联 SVG在移动浏览器上具有更大的可扩展性;这对于响应式设计可能非常有用。

  • ES5允许更好地控制创建的对象,并且可以在纯 JavaScript 中构建大型和复杂的功能。

  • 添加了移动特定属性,如滚动 CSS。在移动 Safari 上,实现原生滚动曾经很痛苦,但现在添加了移动特定属性,使得 Web 开发人员能够开发具有与原生应用相同性能的 Web 应用变得轻松。

window.onerror

目标浏览器:iOS 5

在 iOS 5 中,新增了一个事件处理程序:window.onerror。此事件处理程序用于发送到窗口的错误事件。

语法如下:

window.onerror = funcA;

准备工作

创建一个 HTML 文档并将其命名为ch10r01.html

操作步骤...

输入以下代码并在浏览器中进行测试:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<style>
</style>
</head>
<body>
<script>
window.onerror=function(){
alert('An error has occurred!')
}
</script>
<script>
document.write('hello world'
</script>
</body>
</html>

您应该看到一个弹出警报,显示发生了错误。

它是如何工作的...

出现错误是因为我们没有在document.write:中关闭括号:

<script>
document.write('hello world'
</script>

如果关闭括号并重试,错误将消失:

<script>
document.write('hello world');
</script>

还有更多...

默认窗口行为是阻止显示错误对话框。它覆盖了默认行为:

window.onerror = null;

浏览器对象模型

浏览器对象模型 (BOM)是一组对象,让您可以访问浏览器和计算机屏幕。这些对象可以通过全局对象窗口和window.screen访问。要了解更多关于 BOM 的信息,请访问:

javascript.about.com/od/browserobjectmodel/Browser_Object_Model.htm

使用 ECMAScript 5 方法

目标浏览器:iOS 5

ECMAScript 5正在取代 ECMAScript 3.1。ECMAScript 5 为对象交互提供了很大的增强。从 iOS 4 开始,Safari 引入了许多新的 ECMAScript 5 功能;iOS 5 为 ECMAScript 5 提供了更大的支持。

以下是新引入的Object方法:

Object.seal/Object.isSealed
Object.freeze/Object.isFrozen
Object.preventExtensions/Object.isExtensible
Function.prototype.bind

准备工作

创建一个 HTML 文档并将其命名为ch10r02.html

操作步骤...

输入以下代码并在浏览器中进行测试:

/*** freeze ***/
var dog = {
eat: function () {},
hair: "black"
};
var o = Object.freeze(dog);
// test if dog is frozen
assert(Object.isFrozen(dog) === true);
// can't alter the property
dog.hair = "yellow";
// can't remove property
delete dog.hair;
// can't add new property
dog.height = "0.5m";
/*** seal ***/
var human = {
eat: function () {},
hair: "black"
};
human.hair = "blonde";
var o = Object.seal(obj);
// changing property works
human.hair = "grey";
// can't convert
Object.defineProperty(obj, "hair", { get: function() { return "green"; } });
// silently doesn't add the property
human.height = "1.80m";
// silently doesn't delete the property
delete human.hair;
// detect if an object is sealed
assert(Object.isSealed(human) === true);
/*** preventExtensions ***/
ECMAScript 5ECMAScript 5testingvar nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // throws a TypeError
assert(Object.isExtensible(nonExtensible) === true);
/*** bind ***/
var x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var getX = module.getX;
getX(); // 9, because in this case, "this" refers to the global object
// create a new function with 'this' bound to module
var boundGetX = getX.bind(module);
boundGetX(); // 81

它是如何工作的...

Freeze

如其名称所示,freeze冻结一个对象。不能向freeze添加或删除任何内容;甚至不能修改内容。它使对象不可变并返回一个冻结的对象:

// can't alter the property
dog.hair = "yellow";
// can't remove property
delete dog.hair;
// can't add new property
dog.height = "0.5m";

要测试对象是否被冻结,请使用isFrozen:

// test if dog is frozen
assert(Object.isFrozen(dog) === true);
// silently doesn't add the property
human.height = "1.80m";
// silently doesn't delete the property
ECMAScript 5ECMAScript 5object, freezingdelete human.hair;

Seal

如果您seal一个对象,则无法再添加或删除对象属性。您可能会问,freezeseal之间有什么区别?区别在于对于seal,您仍然可以更改当前属性的值:

// changing property works
human.hair = "grey";

要测试对象是否被封闭,请使用isSealed:

// detect if an object is sealed
assert(Object.isSealed(human) === true);

preventExtensions

默认情况下,对象是可扩展的,但是通过preventExtensions,我们可以阻止对象扩展。这意味着不能再向对象中添加新属性。

/*** preventExtensions ***/
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // throws a TypeError
assert(Object.isExtensible(nonExtensible) === true);

Function.prototype.bind

另一个非常有用的功能是bind。它允许更好地控制this值。在我们的示例中,无论如何调用函数,它都会以特定的this值调用。

从示例中,我们可以看到有一个全局变量x,并且它的值在module对象中被修改:

var x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81

当从对象中提取方法getX,然后调用该函数并期望它使用原始对象作为this,但此时对象是全局的,因此它返回9

var getX = module.getX;
getX(); // 9, because in this case, "this" refers to the global object

通过使用bind,我们创建了一个this绑定到module:的新函数

// create a new function with 'this' bound to module
var boundGetX = getX.bind(module);
boundGetX(); // 81

还有更多...

默认窗口行为是防止错误对话框显示。它覆盖了默认行为:

window.onerror = null;

MDN 上的文档

Object.freeze/Object.isFrozen:

Object.seal/Object.isSealed:

preventExtensions/isExtensible:

Function.prototype.bind:

新的 HTML5 输入类型

目标浏览器:iOS 5

新的输入类型对于 Web 表单是有用的功能。iOS 5 现在支持:date, datetime, month, time, range等等。

准备工作

创建一个 HTML 文档并将其命名为ch10r03.html

如何做...

输入以下代码并在浏览器中测试:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
</head>
<body>
<input type="date">
<input type="datetime">
<input type="month">
<input type="time">
<input type="range">
</body>
</html>

它是如何工作的...

在 iOS 5 上,datedatetime将被渲染如下:

它是如何工作的...

在 iOS Safari 上渲染后,monthtime输入类型将如下截图所示:

它是如何工作的...

slider输入类型将如下截图所示:

它是如何工作的...

还有更多...

有许多 polyfill 用于使 Web 表单在各种浏览器中工作。html5slider是 Firefox 4 及以上版本的 HTML5<input type="range">的 JavaScript 实现。您可以在以下网址了解更多信息:

github.com/fryn/html5slider

文本/HTML 中的内联 SVG

目标浏览器:iOS 5

可伸缩矢量图形(SVG)可以在支持内联 SVG 的 HTML 文档中使用。

准备工作

创建一个 HTML 文档并将其命名为ch10r04.html

如何做...

输入以下代码并在浏览器中测试:

<svg width="500" height="220"  version="1.1">
<rect x="2" y="2" width="496" height="216" stroke="#000" stroke-width="2px" fill="transparent"></rect>
</svg>

它是如何工作的...

HTML 内联 SVG 必须以 MIME 类型Content-Type: text/xml呈现。您可以通过以.xml而不是.html结尾来创建这个。

还有更多...

有几种在 HTML 页面中嵌入 SVG 的方法:<object>, <embed>, <iframe>

要了解不同浏览器中对 SVG 的支持,请访问(在直接将 SVG 代码嵌入 HTML部分下):

www.w3schools.com/svg/svg_inhtml.asp

HTML 中的 SVG

Mozilla MDN 有很多关于前端网页和相关信息的有用文章:

developer.mozilla.org/en/SVG_In_HTML_Introduction

position:fixed

目标浏览器:iOS 5

position:fixed现在在 iOS 5 中得到支持。现在更容易为 Web 应用创建固定定位的工具栏。

准备工作

创建一个 HTML 文档并将其命名为ch10r05.html

如何做...

在 iOS 5 之前,position:fixed在移动 Safari 中无法工作。如果我们想要创建一个工具栏或固定定位的页眉或页脚,就需要类似以下的 hack:

<div id="fixedDiv">
</div>
<script>
window.onscroll = function() {
document.getElementById('fixedDiv').style.top =
(window.pageYOffset + window.innerHeight - 25) + 'px';
};
</script>

随着 iOS 5 的发布,不再需要这种 hack,我们可以简单地使用 CSS 样式,就像我们通常在其他浏览器中使用的那样:

<style>
#fixedDiv { position:fixed; }
</style>
<div id="fixedDiv">
</div>

它是如何工作的...

我们将onscroll事件注册到window对象上,当滚动事件发生时,div将始终位于页面底部。

developer.mozilla.org/en/SVG_In_HTML_Introduction

overflow:scroll

目标浏览器:iOS 5

移动设备和桌面设备之间的一个重要区别是人们与浏览器的交互方式。在桌面浏览器上,可以通过鼠标滚轮或滚动条来进行滚动操作。在移动浏览器上,没有滚动条或鼠标滚轮,因此整个滚动交互都是通过手指操作完成的。很长一段时间内,iOS 不支持overflow:scroll,但现在 iOS 5 已经支持了!

准备工作

创建一个名为ch10r06.html的 HTML 文档。

如何做...

现在,如果您想要使一个区域可滚动,请使用以下代码:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
div {
width:200px;
height:200px;
margin:0 auto;
border:1px solid black;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
</style>
</head>
<body>
<div>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
<p>Lorem Ipsum</p>
</div>
</body>
</html>

它是如何工作的...

通过将overflow定义为scroll,并将-webkit-overflow-scrolling定义为touch,可以在移动 Safari 页面上滚动内容,而无需任何额外的代码。

还有更多...

在过去的几年中,有许多 hack 用于模拟原生滚动行为。从未发布的苹果网页框架PastryKit启发了许多框架这样做。一些著名的框架包括:

有一句古话是“假装直到你成功”,现在苹果终于让这成为可能。就性能而言,它非常稳定,可能比以前的任何框架都要好。

浏览器碎片化

对于某些企业来说,可能会担心移动浏览器的碎片化。一种方法是支持当前浏览器版本之前的两个版本。另一种方法是

posted @ 2024-05-24 11:10  绝不原创的飞龙  阅读(4)  评论(0编辑  收藏  举报