为 Firefox OS 构建待办事项应用,第一部分

这是包含两个部分的教程系列的第一部分,我们将从头开始为 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 将在标题中显示一个标题,在页脚中显示“添加/删除”按钮,以及一个待办事项列表。此视图将用于查看、编辑、标记为已完成和删除任务。

Todo View - Firefox OS

role="application" 属性添加到 `body` 元素,并为待办事项视图编写以下 HTML。

Todos

每个视图都分配了一个 role="region"。在视图内,您可以拥有 headerfooter 和任何具有 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。

添加视图

应用程序中第二个也是最后一个视图将用于向待办事项列表添加任务。

Add View

在此视图中,我们有一个用于输入任务文本的文本框,以及一个插入联系人链接,该链接将使用 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 Simulator

您可以非常轻松地使用 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 产品。

更多 Fawad Hassan 的文章…

关于 Robert Nyman [荣誉编辑]

Mozilla Hacks 的技术布道师和编辑。发表关于 HTML5、JavaScript 和开放 Web 的演讲和博客。Robert 坚定地相信 HTML5 和开放 Web,自 1999 年以来一直从事 Web 前端开发工作 - 在瑞典和纽约市。他还在 http://robertnyman.com 定期发表博客,并且热爱旅行和结识新朋友。

更多 Robert Nyman [荣誉编辑] 的文章…


18 条评论

  1. jay

    有趣的是,当 Mozilla 拥有自己的 JavaScript 引擎 (rhino、spidermonkey) 时,您却必须依赖 Node.js。

    2013 年 6 月 4 日 11:01

    1. Andre Garzia

      Jay,

      使用 Nodejs 的原因超出了它是一个 JavaScript 引擎的事实。NodeJS 拥有一个充满活力的库和工具生态系统 (npmjs.org),可以提高您的生产力。本教程中使用的 volo 包管理器构建在 Nodejs/npm 之上,这就是本文使用它的原因。如果 rhino 或独立的 spidermonkey 支持 npm 库,那么您可以使用它。并不是说 Mozilla 的 JavaScript 引擎无法满足像 Node 这样的执行 js 的需求,只是 Node 拥有大量库和非常好的生态系统,Mozilla 在一些演示和工具中采用了它。Node 很好,spidermonkey 也很好。

      2013 年 6 月 4 日 15:34

    2. Fawad Hassan

      看起来有些混乱。我既没有在本教程中使用 Node.js,将来也不会在后续部分使用。我唯一使用需要 Node.js 的是 volo,它也是 Mozilla 员工(James Burke)开发的工具。他也是开发 require.js 的人 :)

      2013 年 6 月 5 日 01:06

  2. Tojo Chacko

    哇...期待第二部分 :)

    2013 年 6 月 4 日 21:20

    1. Robert Nyman [编辑]

      很高兴你喜欢它!

      2013 年 6 月 5 日 01:47

  3. Alexandre Girard

    很棒的开始,期待第二部分!

    感谢外部工具和字体!

    2013 年 6 月 5 日 04:00

    1. Fawad Hassan

      不客气 :)

      2013 年 6 月 5 日 04:08

  4. Raphael Martinez

    这太棒了。感谢您提供详细的教程/演示。迫不及待地等待第二部分 :)

    2013 年 6 月 5 日 15:14

  5. AmirolAhmad

    你好,

    我在 .php 中构建了自己的 Firefox OS,但在 Firefox OS 模拟器中运行时崩溃了。它是否只能运行 html?

    请查看我的:https://github.com/AmirolAhmad/Firefox-OS-KFC-MY-locator/tree/gh-pages

    2013 年 6 月 9 日 10:27

    1. Fawad Hassan

      我通过创建一个具有 php 扩展名的 HTML 文件并在 manifest.webapp 文件中相应地设置 launch_path 来测试它。它不起作用。Firefox OS 模拟器提供了“另存为...”选项来下载该 php 文件,而不是执行其中的 HTML 代码。

      2013 年 6 月 10 日 01:42

    2. Robert Nyman [编辑]

      这取决于您的设置方式。如果您设置了本地或远程 Web 服务器来运行 PHP,它将像任何网站一样在您的应用程序中运行它。它不会直接在自身中运行 PHP,因为平台/应用程序环境仅支持本地 HTML。

      基本上,就像这个博客。您可以输入 https://hacks.mozilla.ac.cn/,它将在应用程序中运行此网站,但您无法获取此处的源代码并直接运行它。

      但是,如果您无法在 Firefox OS 模拟器中指向以 .php 结尾的服务器上的 URL,那么这是一个错误:请 将其作为问题提交

      2013 年 6 月 10 日 02:06

      1. Fawad Hassan

        是的,我理解 PHP 代码不会在 Firefox OS 中直接运行。我在 php 文件中添加了纯 HTML 并尝试了它。我认为这是一个错误。我将提交它。

        2013 年 6 月 13 日 01:10

  6. 工作

    您没有解释将代码放在哪里。

    我把 html 代码放在 www/index.html 中,CSS 代码放在
    www/css/foo.css 中,并在 index.html 的 部分添加了一个 。

    但我只看到第二个屏幕“待办事项”,而不是第一个“待办事项”

    我假设在第二部分中,您计划将所有这些整合在一起?也许是一些 JavaScript 来控制各个部分的可见性?

    我注释掉了view-add部分,发现选中复选框会导致该项目被添加删除线。这是如何实现的?

    谢谢
    Worik

    2013年6月27日 16:02

    1. Fawad Hassan

      所有CSS都放在一个文件中。如果您对任何内容感到困惑,可以将其与GitHub上的源代码进行比较。这是app.css文件

      https://github.com/iFadey/fos-todo-app/blob/master/www/css/app.css

      删除线效果完全使用CSS完成。查看“待办事项列表模块”的CSS。

      /***
      这个选择器很有意思。它创建了一个删除线,并且
      在选中复选框时降低span中文字的透明度
      ***/
      .todo-list input[type=checkbox]:checked + span {
      text-decoration: line-through;
      opacity: .4;
      }

      是的,第二部分完全是关于JavaScript的。

      2013年6月27日 22:45

  7. Worik

    那应该是我拼写错误的名字!

    Worik

    2013年6月27日 16:03

  8. uokesita

    第二部分在哪里? :(

    2013年6月28日 22:03

    1. Fawad Hassan

      第二部分在上周就完成了,但由于排队需要发布的文章太多而被延迟。因此,第二部分将于7月2日(星期二)发布。

      2013年6月29日 02:59

    2. Robert Nyman [编辑]

      它将于明天,7月2日发布。

      2013年7月1日 03:02

本文的评论已关闭。