server.php
1 2 |
<?php echo print_r($_POST); |
post.php
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 |
<!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script> <meta charset="UTF-8"> </head> <body> <button type="button" class="btn">submit</button> <script> $(function(){ $(document).on('click','.btn',function(){ if(confirm()){ var id = 'key'; $.post( 'server.php', //リクエストURL {id: id}, //送信データ //上記でPostされる値はid:keyになっているのでid側は変数にしても展開されない。 //id側はクォーテーションの有無は関係ないっぽい。 function(rs){ //通信成功時のコールバック alert(rs); } ); } }); }); </script> </body> </html> |
index.php
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
<?php require_once('config.php'); require_once('functions.php'); $db = con(); $tasks = array(); $sql = "select * from tasks where type != 'deleted' order by seq"; foreach($db->query($sql) as $row){ array_push($tasks, $row); } ?> <!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script> <meta charset="UTF-8"> <title>Todo</title> <style> .delete, .drag, .edit{ cursor: pointer; color: blue; } .done{ text-decoration: line-through; color: gray; } </style> </head> <body> <p> <input type="text" id="title"> <input type="button" id="addTask" value="追加"> </p> <ul id="tasks"><!-- jQueryUIのsortableを使うためのID --> <?php foreach ($tasks as $task): ?> <li id="task_<?php echo h($task['id']); ?>" data-id="<?php echo h($task['id']); ?>"> <!-- チェックボックス --> <input type="checkbox" class="check" <?php if($task['type'] == "done"){echo "checked";} ?>> <!-- 本文 --> <span class="<?php echo h($task['type']); ?>"><?php echo h($task['title']); ?></span> <!-- 編集 --> <span <?php if($task['type'] == "notyet"){ echo 'class="edit"'; } ?>>[編集]</span> <span class="delete">[削除]</span> <span class="drag">[drag]</span> </li> <?php endforeach; ?> </ul> <script> //postがエラーの時の反応が必要。 //削除されたときの反応が必要。 $(function(){ $('#title').focus(); $('#addTask').click(function(){ var title = $('#title').val(); $.post('_ajax_add_task.php',{title: title},function(rs){ var e = $( '<li id="task_'+rs+'" data-id="'+rs+'">'+ '<input type="checkbox" class="check">'+ '<span></span>'+ '<span class="edit">[編集]</span>'+ '<span class="delete">[削除]</span>'+ '<span class="drag">[drag]</span>'+ '</li>' ); $('#tasks').append(e).find('li:last span:eq(0)').text(title); $('#title').val('').focus(); }); }); $(document).on('click', '.edit', function(){ var id = $(this).parent().data('id'); var title = $(this).prev().text(); $('#task_'+id) .empty() .append($('<input type="text">').attr('value',title)) .append('<input type="button" value="更新" class="update">'); $('#task_'+id+' input:eq(0)').focus(); }); $(document).on('click', '.update', function(){ var id = $(this).parent().data('id'); var title = $(this).prev().val(); $.post('_ajax_update_task.php', {id: id, title: title}, function(rs){ var e = $( '<input type="checkbox" class="check">'+ '<span></span>'+ '<span class="edit">[編集]</span>'+ '<span class="delete">[削除]</span>'+ '<span class="drag">[drag]</span>' ); $('#task_'+id).empty().append(e).find('span:eq(0)').text(title); }); }); $('#tasks').sortable({ axis: 'y', //ドラッグできる方向 opacity: 0.2, //ドラッグ中の透明度 handle: '.drag', //ドラッグの対象 update: function(){ //ドラッグ後のコールバック $.post('_ajax_sort_task.php',{task: $(this).sortable('serialize')}); //どの要素が何番目かの文字列 //li要素のidが文字列 + _ + 数字になっている必要がある。 } }); $(document).on('click', '.check', function(){ var id = $(this).parent().data('id'); //dataはプロパティを取得。 //.checkはinput要素で親はli要素。dataプロパティはHTMLのdata-*を取得する仕様らしい。 var title = $(this).next(); // <!-- 本文 -->の部分のエレメントを取得している。 $.post('_ajax_check_task.php',{id: id},function(rs){ if(title.hasClass('done')){ title.removeClass('done').next().addClass('edit'); }else{ title.addClass('done').next().removeClass('edit'); } }); }); $(document).on('click','.delete',function(){ if(confirm('本当に削除しますか?')){ var id = $(this).parent().data('id'); //thisは<span>を指す。ここではdata-idを利用している。 $.post('_ajax_delete_task.php',{id: id},function(rs){ $('#task_'+id).fadeOut(800); }); } }); }); </script> </body> </html> |
functions.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php function con(){ try{ return new PDO(DSN, DB_USER, DB_PASSWORD); }catch(PDOException $e){ echo $e->getMessage(); exit; } } function h($s){ return htmlspecialchars($s, ENT_QUOTES, "UTF-8"); } |
config.php
1 2 3 4 5 6 |
<?php error_reporting(E_ALL & ~E_NOTICE); define('DSN','mysql:host=localhost;dbname=todo_app;charset=utf8'); define('DB_USER','user'); define('DB_PASSWORD','1234'); |
commands.sql
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
create database todo_app; grant all on todo_app.* to user@'localhost' identified by '1234'; use todo_app create table tasks( id int not null auto_increment primary key, seq int not null, type enum('notyet','done','deleted') default 'notyet', title text, created datetime, modified datetime, key type(type), key seq(seq) ); insert into tasks (seq,type,title,created,modified) values (1,'notyet','牛乳買う',now(),now()); |
_ajax_update_task.php
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php require_once('config.php'); require_once('functions.php'); $db = con(); $sql = "update tasks set title = :title, modified = now() where id = :id"; $st = $db->prepare($sql); $st->execute(array( ":id" => (int)$_POST['id'], ":title" => $_POST['title'] )); |
_ajax_sort_task.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php require_once('config.php'); require_once('functions.php'); $db = con(); //var_dump($_POST['task']); //ドラッグ後にDevToolsのネットワークタブからこのファイルを選択するとファイルの出力が見られる。 parse_str($_POST['task']); //$taskが使えるようになる。 print_r($task); foreach ($task as $key => $val ){ $sql = "update tasks set seq = :seq where id = :id"; $st = $db->prepare($sql); $st->execute(array( ":seq" => $key, ":id" => $val )); } |
_ajax_delete_task.php
1 2 3 4 5 6 7 8 9 |
<?php require_once('config.php'); require_once('functions.php'); $db = con(); $sql = "update tasks set type = 'deleted', modified = now() where id = :id"; $st = $db->prepare($sql); $st->execute(array(":id" => (int)$_POST['id'])); |
_ajax_check_task.php
1 2 3 4 5 6 7 8 9 |
<?php require_once('config.php'); require_once('functions.php'); $db = con(); $sql = "update tasks set type = if(type='done', 'notyet','done'), modified = now() where id = :id"; $st = $db->prepare($sql); $st->execute(array(":id" => (int)$_POST['id'])); |
_ajax_add_task.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php require_once('config.php'); require_once('functions.php'); $db = con(); $sql = "select max(seq)+1 from tasks where type != 'deleted'"; $seq = $db->query($sql)->fetchColumn(); $sql = "insert into tasks (seq, title, created, modified) values (:seq, :title, now(), now())"; $st = $db->prepare($sql); $st->execute(array( ":seq" => $seq, ":title" => $_POST['title'] )); echo $db->lastInsertId(); //コールバックのrsで受取っている。 |