3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Indexed Database APIを使ってスタンドアロンな付箋アプリを作ってみる

Posted at

記事の趣旨

せっかくIndexed Database APIについて勉強したので,それを使ってブラウザアプリを作ってみた.

1. 作ったアプリと技術要素

ブラウザにスティッキー(付箋紙)っぽいメモを残していけるツール.本当はカンバン方式の管理ツールを作りたかったんだけれど,力尽きたのでいったん保留.画面キャプチャは以下のとおり.

kanban01.png

使用した技術要素は以下のとおり.Vue.jsは初めて触るので,書籍と睨めっこしながらの対応.

  • HTML
  • CSS
  • Vue.js
  • Indexed Database API(敢えてライブラリ未使用)

ソースコードはGithubのリポジトリに置いているのでご自由にどうぞ.動作は「Chrome 79.0.3945.117」で確認.Edgeでも動作するがレイアウトが若干崩れる.

2. 操作方法

直感で扱えるレベルだと思うけれど,とりあえず以下のとおり.

  1. cloneなりzip downloadなりでローカルに落としてきたらkanban.htmlを開く.
  2. 付箋紙を新たに作りたいときは左下のプラスマークをクリック.
  3. 付箋紙はドラッグ&ドロップで自由に移動可能.
  4. 付箋紙をダブルクリックすると編集ウィンドウ(後述)が開く.
  5. 編集ウィンドウでURLを登録しておけば,付箋紙左下の「URL」ボタンクリックでその画面に新タブで遷移可能.

kanban02.png

3. 苦戦したポイント

スキル低いので,初歩的だったり,間抜けなものばかりだが,恥を忍んで書いていく.

3.1 Promise

以下の処理は,「DBへのコネクションを確立する」->「チケットを全件取得する」->「グローバル変数にチケット情報を詰め込む」という意図のコードになる.このうち,createConnection()およびgetAllTickets()は,Promiseオブジェクトを返却する関数である.先日の記事でも述べたとおり,Indexed Database APIは非同期処理であるため,Promiseを活用することで同期を図っている.

    created: function() {
        createConnection().then(
            getAllTickets()
        ).then(
            (allTickets) => {
                allTickets.forEach(
                    ticket =>
                    {
                        tickets.push({
                            id: ticket.id,
                            text: ticket.text,
                            url: ticket.url,
                            categoryId: ticket.categoryId,
                            left: ticket.left,
                            top: ticket.top,
                            zIndex: ticket.zIndex,
                            deleted: false
                        })
                    }
                )
            }
        ).catch(
            (reason) => alert(reason)
        )
    }

さて,上記コードは一部が不正で,これだと同期処理にならない.どこかわかるだろうか.

答えは3行目.getAllTicket()と書いているが,ここはgetAllTicketと,関数オブジェクトを指定しないといけない.

promise.prototype.then()は,あくまでメソッドであり,その引数指定するのはコールバック関数.ものすごく間抜けなミスだが,うっかりif/elseの構文と同じような感覚で記述してしまい,上記のミスに至ってしまった.

3.2 Bubbling

今回の付箋紙オブジェクトは,複数のレイヤで構成されているので,Bubblingを意識してイベントをハンドリングしないといけない.が,そもそもその辺りを全然理解しておらず,序盤はかなり意図しない挙動に苛まれた.たぶん今も多少バグは残っていると思われる.

Bubblingについては,こちらのページの説明がとてもわかりやすいと思う.定義を引用させていただくと以下のとおり.

要素上でイベントが起きると、最初にその上のハンドラが実行され、次にその親のハンドラが実行され、他の祖先に到達するまでそれらが行われます。

今回でいうと,例えば「URL」ボタンをクリックすると,続けて付箋紙自体にセットされたマウスダウンイベントが処理されることになる.後者は付箋紙の移動に関わる処理なので,付箋紙がワープするなどの謎挙動が頻発していた.

Bubblingを防ぎたい場合は,event.stopPropagation()を呼び出すことで,それ以降の親オブジェクトへの伝播を抑制することができる.

4. ペンディングしている事項

  • 付箋紙の色の変更機能
    • categoryIdという死にパラメータがその名残
  • ファイルサーバやローカルへのショートカットボタン
    • エクスプローラの直接操作は無理そうなので,パスをクリップボードにコピーする処理を想定
  • ゴミ箱アイコンへのドロップによる付箋紙削除処理
    • 面倒臭くなって今は削除ボタンで代替
  • カンバンボード化と,付箋紙へのステータス(ToDo,WIP,Done)導入
    • そもそもそれを目指したアプリだったので
  • 複数タブ対応
    • 現在は複数タブでこのアプリを開いたら何が起きるか不明
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?