这是包含两个部分的教程系列的第一部分,我们将从头开始为 Firefox OS 构建一个待办事项应用。我假设您对 HTML5、CSS3、JavaScript、jQuery/Zepto 和 Backbone.js 有一定了解。在本部分中,我们将使用为移动设备设计 UI 的最佳实践,手工制作一个结构良好且语义化的待办事项应用 UI。
待办事项应用的源代码可在 GitHub 上获取。
设置环境
我们将使用 volo 作为我们的包管理器和构建工具。
步骤 1
首先,您需要安装 Node.js,因为 volo 依赖于它。Windows 和 Mac 用户可以从 此处 下载。但对于 Linux 用户,我建议您使用包管理器:不同发行版上使用包管理器安装的说明。
步骤 2
使用以下命令安装 volo。
npm install -g volo
确保在 *nix 环境中,在上述命令前使用 `sudo`。
步骤 3
使用 `volo create` 命令创建一个空白项目 fos-todo-app
。
volo create fos-todo-app
这将创建一个名为 fos-todo-app
的文件夹,并从 GitHub 复制必要的 volo 项目文件。
**请记住** 我们只会处理 fos-todo-app/www
目录中的文件。如果您以前从未使用过 volo,建议您阅读 [使用 Volo 简化您的流程](http://net.tutsplus.com/tutorials/javascript-ajax/streamline-your-process-with-volo/)。
步骤 4
确保您安装了最新稳定版本的 Firefox。然后 [安装 Firefox OS 模拟器加载项](https://addons.mozilla.org/en-US/firefox/addon/firefox-os-simulator/)。在本文章的结尾,我们将在该模拟器中测试应用程序的 UI。
步骤 5
获取 [MozTT 字体](https://github.com/mozilla-b2g/moztt/tree/master/MozTT) 并安装它。MozTT 是 Firefox OS 中使用的字体。这是一个可选步骤,但最好在您的系统上安装此字体,以便您可以在 Firefox OS 模拟器和真实的手机上获得一致的外观和感觉。
待办事项视图
我们将构建的第一个 UI 将在标题中显示一个标题,在页脚中显示“添加/删除”按钮,以及一个待办事项列表。此视图将用于查看、编辑、标记为已完成和删除任务。
将 role="application"
属性添加到 `body` 元素,并为待办事项视图编写以下 HTML。
Todos
-
-
每个视图都分配了一个 role="region"
。在视图内,您可以拥有 header
、footer
和任何具有 view-content
类的容器元素,该元素将包含视图的内容。
在上述视图的内容中,我们有 ul[role=list]
,它包含用户输入的任务。出于测试目的,我添加了两个虚拟任务,以便您可以理解每个列表项 (`li[role=listitem]`) 的结构。在每个列表项中,我们都有一个 label
元素,其中包含一个 <input type="checkbox">
和一个包含任务文本的 span
元素。列表项中的第二个元素包含一个 <input type="text">
元素,该元素最初使用属性 aria-hidden="true"
隐藏。最后,第三个元素是 .btn.edit
(编辑按钮)。
**注意:** 当然这不是魔术。我们将为所有这些属性编写 CSS。如果您不熟悉 WAI-ARIA,请查看 ARIA 和渐进增强。
将 label
放置在列表项中的目的是显示每个任务的文本,而 input[type=text]
(最初隐藏)将用于编辑该文本。当用户 点击
.btn.edit
(编辑按钮)时,任何任务都可以进入编辑模式。类似地,当用户点击 label
时,任务会被“标记为已完成”。
在 footer
中,我们有 menu[role=toolbar]
,其中包含“添加/删除”按钮。稍后,我们将使用这些按钮的 CSS 在背景中显示一个 svg 图标,并隐藏其中的内部 span。
添加视图
应用程序中第二个也是最后一个视图将用于向待办事项列表添加任务。
在此视图中,我们有一个用于输入任务文本的文本框,以及一个插入联系人链接,该链接将使用 Web Activities 添加联系号码。以下是“添加”视图的 HTML。
[+] Todo
请注意,section.view-content
中的内容使用 div.wrapper
包裹,以便我们可以限制其 max-width
并右对齐 menu.options
。
第二个需要注意的是 form
元素上的 aria-owns
属性。此属性与 btn-add-done
关联的 form
相关。
元素样式
让我们为 HTML 元素编写 CSS。每个选择器上方的注释中都给出了解释。
/* Stretch vertically */
html, body { height: 100%; }
body {
background: radial-gradient(ellipse at center, rgba(231,76,60,1) 0%,rgba(192,57,43,1) 100%);
color: #fff;
font-family: MozTT, sans-serif;
/* Reset base size */
font-size: 16px;
/* Set font size relative to base size */
/* Check this article on rem usage */
font-size: 1.4rem;
font-weight: 300;
/* Remove spacing */
margin: 0;
}
h1, h2, h3, h4, h5, h6 { font-weight: 300; }
h1 { font-size: 3rem; }
a {
color: #FFA49E;
text-decoration: none;
text-shadow: 0px 1px 1px rgba(0,0,0,.3);
}
a:hover { color: #fff; }
input, button, select, textarea {
border-radius: 0;
box-shadow: none;
}
input[type=text], textarea, select {
border: none;
font-family: MozTT, sans-serif;
font-size: 1.3rem;
font-weight: 300;
padding: .7rem .8rem;
}
视图特定样式
#view-todos > .view-content {
margin-left: 0;
margin-right: 0;
}
#view-add > .view-content {
margin-top: 2rem;
}
#view-add > .view-content > .wrapper {
overflow: hidden;
margin: 0 auto;
max-width: 800px;
width: 100%;
}
#view-add input[name=task] {
width: 100%;
}
#view-add .options {
margin: 0 0 .5rem 0;
text-align: right;
}
#view-add .options [role=listitem] {
margin: .5rem 0;
}
#view-add .options a {
padding: .4rem;
}
模块样式
视图模块
/* All views have region role so selecting them with attribute selector */
[role=region] {
background: radial-gradient(ellipse at center, rgba(231,76,60,1) 0%,rgba(192,57,43,1) 100%);
/* Stretch both vertically/horizontally */
top: 0; right: 0; bottom: 0; left: 0;
position: fixed;
overflow-x: hidden;
}
[role=region] > header {
margin: .5rem 0 1rem 0;
text-align: center;
}
[role=region] > header > h1 {
margin: 0;
text-shadow: 0px 1px 1px rgba(0,0,0,.4);
}
[role=region] > .view-content {
margin: 0 1rem 4rem 1rem;
}
[role=region] > footer {
background: rgba(0,0,0,.2);
right: 0; bottom: 0; left: 0;
position: fixed;
text-align: center;
}
[role=region] > footer > menu[role=toolbar] {
margin: 0;
padding: 0;
}
按钮模块
.btn {
border: none;
width: 3.5rem;
height: 3.5rem;
}
.btn > span {
display: none;
}
.btn:disabled {
opacity: .2;
}
.btn.done {
background: url(../img/check.svg) no-repeat center center;
}
.btn.add {
background: url(../img/add.svg) no-repeat center center;
}
.btn.del {
background: url(../img/del.svg) no-repeat center center;
}
.btn.edit {
background: url(../img/edit.svg) no-repeat center center;
}
.btn:hover {
background-color: rgba(255,255,255,.1);
}
待办事项列表模块
.todo-list > li {
border-bottom: 1px solid rgba(255,255,255,.1);
position: relative;
}
.todo-list > li > .btn {
top: 0; right: 0;
position: absolute;
height: 3.9rem;
}
.todo-list label {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
display: block;
padding: 1rem 2.8rem 1rem 1rem;
}
.todo-list > li:last-child,
.todo-list > li:last-child > label {
border-bottom: none;
}
.todo-list label > span {
transition: all .5s;
}
/***
This selector is interesting. It creates a line-through and
decrease opacity of text in span when checkbox is checked
***/
.todo-list input[type=checkbox]:checked + span {
text-decoration: line-through;
opacity: .4;
}
.todo-list > li > input[type=text] {
margin: .4rem;
/* removing input padding and margin from 100% */
width: calc(100% - 2.3rem);
}
实用程序样式
.reset-list {
list-style: none;
margin: 0;
padding: 0;
}
[aria-hidden=true] {
display: none !important;
}
动画
以下是我们将用于为视图设置动画的一些动画效果。尽管我们将使用 Zepto.js,它在运行时使用 JavaScript 生成 CSS3 动画,但我更喜欢使用 CSS3 编写自己的动画,并通过在 DOM 元素上应用/移除 CSS 类来利用它。
Zepto 是一个适用于现代浏览器的极简主义 JavaScript 库,它拥有一个与 jQuery 大致兼容的 API。如果您使用 jQuery,那么您已经知道如何使用 Zepto。‐ zeptojs.com
查看 如何使用 CSS 动画 教程,以更好地了解 CSS3 动画。
.slide-up-in {
animation-name: slide-up-in;
animation-duration: .6s;
transform: translateY(0%);
opacity: 1;
}
@keyframes slide-up-in {
0% { transform: translateY(30%); opacity: 0; }
100% { transform: translateY(0%); opacity: 1; }
}
.slide-down-out {
animation-name: slide-down-out;
animation-duration: .6s;
transform: translateY(30%);
opacity: 0;
}
@keyframes slide-down-out {
0% { transform: translateY(0%); opacity: 1; }
100% { transform: translateY(30%); opacity: 0; }
}
.slide-right-in {
animation-name: slide-right-in;
animation-duration: .6s;
transform: translateX(0%);
}
@keyframes slide-right-in {
0% { transform: translateX(-100%); }
100% { transform: translateX(0%); }
}
.slide-left-out {
animation-name: slide-left-out;
animation-duration: .6s;
transform: translateX(-100%);
}
@keyframes slide-left-out {
0% { transform: translateX(0%); }
100% { transform: translateX(-100%); }
}
在 Firefox OS 模拟器中测试
您可以非常轻松地使用 Firefox OS 模拟器测试我们开发的 UI。您只需要在根目录 (fos-todo-app/www) 中有一个 manifest.webapp
文件。在其中添加以下 json。
{
"version": "0.1",
"name": "Todos",
"description": "Awesome todo app by iFadey",
"launch_path": "/index.html",
"icons": {
"16": "/img/icons/icon-16.png",
"48": "/img/icons/icon-48.png",
"128": "/img/icons/icon-128.png"
},
"developer": {
"name": "Fawad Hassan",
"url": "http://ifadey.com"
},
"installs_allowed_from": ["*"],
"appcache_path": "/cache.manifest",
"default_locale": "en"
}
目前我还没有添加应用程序图标,但不用担心。如果在清单文件中找不到应用程序图标,Firefox OS 会添加一个默认的应用程序图标。现在从 `工具 > Web 开发 > Firefox OS 模拟器` 中打开模拟器选项卡。然后点击“添加目录”按钮,并从我们的应用程序目录中选择清单文件。这将在模拟器中添加我们的应用程序。
第一部分结束
现在您已经开始使用待办事项应用程序,并通过几个简单的步骤开始了。在下一部分中,我们将使用 JavaScript (Backbone/Zepto) 为我们的应用程序注入活力。我们将创建待办事项模型、集合和视图,并且为了简单起见,我们只会将待办事项集合存储在 IndexedDB 中。我们还将使用 Web Activities 将联系人号码注入待办事项任务的文本中。
关于 Fawad Hassan
我是一名 JavaScript 开发人员,我喜欢处理单页应用程序、Firefox OS、基于 PhoneGap 的移动应用程序以及 Node.js/Express.js 后端。目前我在 PLUMgrid(SDN 相关的初创公司)工作,并且正在开发基于 HTML5 的网络操作系统 GUI。除此之外,我还是 Mozilla 社区的一员,在我的空闲时间里,我会推广 Mozilla 产品。
关于 Robert Nyman [荣誉编辑]
Mozilla Hacks 的技术布道师和编辑。发表关于 HTML5、JavaScript 和开放 Web 的演讲和博客。Robert 坚定地相信 HTML5 和开放 Web,自 1999 年以来一直从事 Web 前端开发工作 - 在瑞典和纽约市。他还在 http://robertnyman.com 定期发表博客,并且热爱旅行和结识新朋友。
18 条评论