LaravelとjQueryと使ってシンプルなTODOリスト作りました。その開発過程や使用した技術などをメモしておきます。
作ったもの
シンプルなTODOリスト
作った経緯
今日やることをサクッとメモして、優先順位をつけたりできるサービスがあればなと個人的に思ったからですね。
ごちゃごちゃたくさん機能がついているもの よりもシンプルに今日やることをリスト化できればタスクに集中しやすいと思い、作りました。
サービスのこだわり
とにかくシンプルに
最初作った時は、更新ボタンやソート確定ボタンなどごちゃごちゃしていたのですが、とにかく使いやすくするように不要な要素はできるだけそぎ落としまし た。ボタン名もつけずに直感的に使えるようにしました。
処理は非同期で行い、タスクの登録や更新はフォーカスアウトすることで確定します。タスクのソートも実行した時点で確定されます。
タスクの優先順位を簡単に変更できる
上下の矢印をクリックすることで、簡単にタスクの優先順位を変更することができます。
書けるタスクは1行
書こうと思えば長く書けてしまうタスクですが、あえて1行に制限することで、何をやるべきかを明確化することを目的としています。
使用した技術
- Laravel Webフレームワーク
- Materialize CSSフレームワーク
- MAMP ローカル環境
- MySQL データベース
- Apache Webサーバ
フロントサイド
基本的に処理はAjaxを使い非同期で行っています。
例として、削除時の処理をのせます。削除対象のタスクIDを取得して、サーバサイドで削除処理を実行します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // 削除 $('.delete_task_button').on('click', function(e) { var $task_id = $(this).attr("value"); var $delete_url = '/tasks/' + $task_id + '/delete'; // 追加メモが登録されていない場合 if( typeof $task_id === 'undefined') { $(this).parent().remove(); return; } // 2重送信防止 $('.delete_task_button').each(function(i, elm) { $(elm).prop('disabled', true).addClass('disabled'); }); $.ajax({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }, url: $delete_url, type: 'post', data: {'task_id': $task_id} }) .done(function() { $('*[name=' + $task_id + ']').parent().remove(); }) .fail(function(data) { $('.message' + $task_id).text(data.responseJSON).show(); }); // ボタン解除 $('.delete_task_button').each(function(i, elm) { $(elm).prop('disabled', false).removeClass('disabled'); }); }); |
上下に移動する処理はjquery.smoothswap.jsを使って実現しています。
使い方はいたって簡単。jQuery本体とこちらのプラグインを一緒に読み込み、入れ替えたいパネル単位に“smoothswap-panel”を指定します。
パネル内の上に動かすための要素を”smoothswap-up”、下に動かすための要素を “smoothswap-down”とクラスを指定するだけです。
1 2 3 4 5 6 7 8 9 | function setSmoothswap(){ $('.smoothswap').smoothswap({ marginHeight: 10, onswapped: function onSwapped(base, first, second) { base.children('.smoothswap-panel').each(function(index) { }); } }); } |
移動スピードを上げるには以下を追加すれば、早くなります。
1 | duration: 'fast', |
jquery.smoothswap.js - OTCHY.NET
サーバサイド
ルーティング
削除ルーティングは以下の通り。
1 | Route::post('tasks/{id}/delete', 'TasksController@delete'); |
コントローラ
POSTされた削除対象IDを取得し、サービスに投げ削除実行します。実行結果によって、Viewに返すJSONレスポンスを変えます。
削除が失敗した場合はエラーメッセージを返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * タスク削除 * * @return \Illuminate\Http\Response */ public function delete() { // 削除処理実行 $task_delete = $this->registerService->deleteTask($_POST['task_id']); if (!$task_delete) { // HTTPステータス 500 return response()->json($this->registerService->getErrorMessage(), \Illuminate\Http\Response::HTTP_INTERNAL_SERVER_ERROR); } // HTTPステータス 204 return response()->json(null, \Illuminate\Http\Response::HTTP_NO_CONTENT); } |
サービス
サービスで行ロックして削除処理を実行しています。シンプルにfindOrFail()メソッドでサクッとコントローラに書いても良いと思います。勉強もかねてコントローラとサービスに分けて処理を書きました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | /** * 削除処理 * * @param array $task_id タスクID * * @return \Illuminate\Http\Response */ public function deleteTask($task_id) { DB::beginTransaction(); try { // 行ロック $task = Task::lockForUpdate()->withTrashed()->find($task_id); if ($task === null || !empty($task->deleted_at)) throw new NotFoundException(); $task->delete(); DB::commit(); return true; } catch (NotFoundException $e) { DB::rollBack(); \Log::error($e->getMessage()); $this->error_message = 'タスクが存在しないか既に削除されています。'; return false; } catch (Exception $e) { DB::rollBack(); \Log::error($e->getMessage()); $this->error_message = '予期せぬエラーが発生しました。'; return false; } } |