Firefox OS용 Todo앱 만들기, 1회

Firefox OS의 Todo 앱 만들기 시리즈 총2회 중 첫번째 입니다. HTML5, CSS3, JavaScript, jQuery/Zepto 와 Backbone.js 에 대해 이미 알고 있다고 가정하겠습니다. 이번 회에서는 모바일 UI를 만들기 위한 최선의 방법을 사용하여 적절한 구조와 직관적인 UI를 만들려고 합니다.  소스는 GitHub에 올려져 있습니다.

환경설정하기

패키지 관리 및 빌드도구로 volo를 사용할 겁니다.

첫번째 단계

volo를 사용하기 위해 Node.js를 설치합니다. 윈도우와 맥 사용자는 여기에서 다운받으세요. 리눅스 사용자는 패키지관리자를 사용해서 설치하세요 : 패키지관리자를 사용해서 설치하는 방법

두번째 단계

volo 설치하기

npm install -g volo

*nix 환경에서는 명령을 사용하기 전에 sudo를 앞에 붙여야 합니다.

세번째 단계

‘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/ )을 읽어보길 권합니다.

네번째 단계

Firefox 최신버전을 사용하세요. 그리고나서 시뮬레이터 (https://addons.mozilla.org/en-US/firefox/addon/firefox-os-simulator/)   를 설치하세요. 이 글의 마지막에서 시뮬레이터에서 앱 UI를 테스트할 겁니다.

다섯번째 단계

MozTT 폰트 (https://github.com/mozilla-b2g/moztt/tree/master/MozTT)를 받아서 설치하세요. MozTT는 Firefox OS에서 사용할 폰트입니다. 여기는 그냥 지나가도 되지만 여러분이 Firefox OS 시뮬레이터와 실제 폰에서 일관된 화면을 얻길 원하면 이 폰트를 사용하는 것이 더 좋습니다.

Todo 화면

header에는 제목,  footer에는 있는 추가/삭제 버튼이 있고  할일 목록이 있는 첫번째 UI를 빌드할 겁니다. 이 화면은 할일을 보고, 수정하고, 완료 표시를 하고, 삭제할 때 사용할 겁니다.

Todo View - Firefox OS

Todo화면을 만들기 위해 ‘body’에 role="application" 을 추가하고 다음에 나오는 HTML을 추가하세요.

<section id="view-todos" role="region">
  <header>
    <h1>Todos</h1>
  </header>

  <article class="view-content">
    <ul id="todo-list" class="todo-list reset-list" role="list">
      <li role="listitem">
        <label>
          <input type="checkbox">
          <span>My task 1</span>
        </label>

        <input type="text" aria-hidden="true">
        <button class="btn edit"><span>Edit</span></button>
      </li>

      <li role="listitem">
        <label>
          <input type="checkbox" checked>
          <span>My task 2</span>
        </label>

        <input type="text" aria-hidden="true">
        <button class="btn edit"><span>Edit</span></button>
      </li>
    </ul>
  </article>

  <footer>
    <menu role="toolbar">
      <button role="menuitem" class="btn add"><span>Add</span></button>
      <button role="menuitem" class="btn del" disabled><span>Delete</span></button>
    </menu>
  </footer>
</section><!--end view-todos-->

각 화면은 role="region"가 지정되어 있습니다.  화면(view)에 여러분은 header, footer와 화면의 콘텐츠를 담고 있는 view-content 클래스를 가진 컨테이너를 넣을 수 있습니다.

이전 화면의 내용에서 우리는 사용자가 입력한 할일을 표시할 ul[role=list]를 사용했습니다. 테스트를 위해 나는 두 개의 할일을 넣었으며 여러분이 목록의  구조(`li[role=listitem]`)를 이해하기 쉽게 했습니다. 각 항목에서 우리는 <input type="checkbox"> 를 가진 label과 할일의 내용을 가진 span 을 사용했습니다. 항목에서 사용한 두번째 요소는 aria-hidden="true"를 사용하여 숨겨진 <input type="text"> 입니다. 마지막으로 세번째 요소는 .btn.edit(수정버튼)입니다.

참고사항:물론 이것은 마술이 아닙니다. 우리는 모든 요소를 CSS로 만들었습니다. 여러분이 WAI-ARIA가 생소하다면 ARIA and Progressive Enhancement 를 참고하세요.

항목에서 label 을 사용한 목적은 할일의 내용과 내용을 수정할 때 사용되어 질 input[type=text] (기본적으로 숨겨져 있는)를 보여주는 것입니다.
footer에는 추가/삭제 버튼을 가진 menu[role=toolbar]를 위치시켰습니다. 이후에 CSS를 사용하여 버튼을 만들어 우리는 배경에 svg 아이콘을 보여주고 inner span을 숨길 것입니다.

추가 화면

우리의 앱의 두번째이자 마지막 화면은 할일 목록에 할일을 추가하는 화면입니다.

Add View

이 화면에서 할일을 목록을 넣기 위한 텍스트박스와 웹 액티비티를 사용하여 연락처 번호를 추가할 연락처 링크를 위치시켰습니다.

<section id="view-add" role="region">
  <header>
    <h1>[+] Todo</h1>
  </header>

  <section class="view-content">
    <div class="wrapper">
      <menu class="options">
        <ul id="activities" class="reset-list" role="list">
          <li role="listitem"><a href="#"><label for="task">[Insert Contact]</label></a></li>
        </ul>
      </menu>

      <form aria-owns="btn-add-done">
        <input type="text" name="task" id="task" required>
      </form>
    </div>
  </section>

  <footer>
    <menu role="toolbar">
      <button id="btn-add-done" role="menuitem" class="btn done" disabled><span>Done</span></button>
      <button role="menuitem" class="btn del"><span>Cancel</span></button>
    </menu>
  </footer>
</section><!--end view-add-->

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 <a href="http://snook.ca/archives/html_and_css/font-size-with-rem">this</a> 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;
}

애니메이션

화면을 동적으로 보이기 위해 몇가지 애니메이션 효과를 사용할 겁니다.  JavaScript를 사용한 CSS-3 애니메이션 런타임 라이브러리인 Zepto.js 을 사용할 겁니다. 개인적으로 CSS3를 사용해서 애니메이션을 표현하고 CSS 클래스를 적용/제거함으로써 이것을 변경하는 걸 즐깁니다.

Zepto는 jQuery API와 호환되는 Javascript 라이브러리 입니다. 여러분이 jQuery를 사용하고 있다면 벌써 Zepto를 사용하는 방법을 아는 것입니다. – zeptojs.com

CSS3 애니메이션을 더 많이 이해하기 위해서 CSS 애니메이션 사용하기 (http://css3.bradshawenterprises.com/animations/) 소개를 참고하세요.

.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"
}

지금은 app icon을 추가하지 않겠지만 그 점은 염려하지 않아도 됩니다. manifest 파일안에서 찾지 못한다면 Firefox OS가 기본 아이콘을 표시해줄 것입니다. 지금 시뮬레이터(개발자도구 > Firefox OS Simulator) 를 실행시켜 봅시다. 그리고 나서 Add Directory 를 누르고 manifest 파일을 선택하세요. 시뮬레이터에 우리의 앱이 추가될 겁니다.

첫 회의 마지막

여러분은 Todo 앱의 시작점에 왔고 몇가지 단계를 지나왔습니다. 다음 회에서는 앱에 JavaScript (Backbone/Zepto)를 사용해서 생명을 불어 넣을 것입니다. Todo 모델, 콜렉션과 뷰를 생성하고 간단하게 todo 콜렉션을 IndexedDB 에 저장할 것입니다.  또한 할일 내용에 있는 연락처를 입력하기 위해 웹 액티비티를 사용할 것입니다.

작성자: LAWN

설수웅(SwooWoong, Seol) / Software & Data Engineer / I love technology to improve people's lives, and harmonious architecture with nature​.(LAWN) / 인간의 삶을 향상시키는 기술, 자연과 조화로운 아키텍쳐를 사랑합니다.

LAWN가 작성한 문서들…


댓글이 없습니다.

댓글 쓰기