Bekerja Dengan IndexedDB - Bagian 2
Indonesian (Bahasa Indonesia) translation by Shylchemist (you can also view the original English article)
Selamat datang di bagian kedua artikel IndexedDB saya. Saya sangat merekomendasikan membaca artikel pertama dalam seri ini, karena saya akan menganggap Anda sudah familiar dengan semua konsep yang tercakup sejauh ini. Dalam artikel ini, kita akan menyelesaikan aspek CRUD yang tidak kita selesaikan sebelumnya (secara khusus memperbarui dan menghapus konten), dan kemudian menunjukkan aplikasi dunia nyata yang akan kita gunakan untuk mendemonstrasikan konsep lain dalam artikel terakhir.
Memperbarui Records
Mari kita mulai dengan membahas cara memperbarui catatan dengan IndexedDB. Jika Anda ingat, menambahkan data cukup sederhana:
//Define a person var person = { name:name, email:email, created:new Date() } //Perform the add var request = store.add(person);
Memperbarui record hanya sederhana. Dengan asumsi bahwa Anda telah mendefinisikan properti yang disebut id
sebagai kunci untuk penyimpanan objek Anda, Anda dapat menggunakan metode put
daripada add
.
var person = { name:name, email:email, created:new Date(), id:someId } //Perform the update var request = store.put(person);
Seperti metode add
, Anda dapat menetapkan metode untuk menangani hasil operasi asynchronous.
Menghapus Records
Menghapus records dilakukan melalui delete method. (Kejutan besar di sana.) Anda cukup meneruskan pengenal unik dari rekaman yang ingin Anda hapus. Berikut ini contoh sederhana:
var t = db.transaction(["people"], "readwrite"); var request = t.objectStore("people").delete(thisId);
Dan seperti setiap aspek lain dari IndexedDB, Anda dapat menambahkan pegangan Anda untuk hasil asynchronous.
Jadi, seperti saya katakan, tidak sangat menarik, mungkin baik. Anda ingin API Anda sederhana, membosankan, dan tidak mengejutkan. Sekarang mari kita mengambil apa yang telah kita pelajari dan menyatukannya untuk menciptakan aplikasi yang nyata, if simple.
Note App
Ok, akhirnya kita memiliki semua (baik, sebagian) dari bagian-bagian yang kita butuhkan untuk membangun aplikasi nyata. Karena belum pernah dilakukan sebelumnya (ahem), kita akan membuat aplikasi pencatatan sederhana. Mari kita lihat beberapa cuplikan layar dan kemudian saya akan menunjukkan kode di belakangnya. Saat diluncurkan, aplikasi menginisialisasi IndexedDB untuk aplikasi dan membuat tabel kosong. Awalnya, yang bisa Anda lakukan dengan aplikasi ini adalah menambahkan catatan baru. (Kita bisa membuat ini lebih ramah pengguna.)



Mengeklik tombol Add Note membuka formulir:



Setelah memasukkan beberapa data dalam formulir, Anda kemudian dapat menyimpan catatan:



Seperti yang Anda lihat, Anda memiliki opsi untuk mengedit dan menghapus catatan. Akhirnya, jika Anda mengklik baris itu sendiri, Anda dapat membaca catatan:



Jadi bukan ilmu roket, tapi contoh lengkap dari spesifikasi IndexedDB. Catatan yang ditulis di sini akan tetap ada. Anda dapat menutup browser Anda, menghidupkan ulang mesin Anda, mengambil beberapa tahun untuk merenungkan kehidupan dan puisi, dan ketika Anda membuka browser lagi data Anda akan tetap ada. Mari kita lihat kode sekarang.
Pertama - disclaimer. Aplikasi ini akan menjadi kandidat yang sempurna untuk salah satu dari banyak JavaScript framework. Saya yakin Anda yang menggunakan Backbone atau Sudut sudah bisa membayangkan bagaimana Anda akan mengatur ini. Namun - saya membuat keputusan yang berani di sini untuk tidak menggunakan framework. Saya khawatir baik tentang orang-orang yang mungkin menggunakan kerangka kerja yang berbeda dan mereka yang tidak menggunakan. Saya ingin fokus kami di sini untuk berada di aspek IndexedDB saja. Saya sepenuhnya berharap beberapa orang tidak setuju dengan keputusan itu, tetapi mari kita hilangkan dalam komentar.
Template pertama kami adalah file HTML. Kami hanya punya satu dan sebagian besar adalah Bootstrap boilerplate:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Note Database</title> <link href="bootstrap/css/bootstrap.css" rel="stylesheet"> <link href="css/app.css" rel="stylesheet"> </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">Note Database</a> </div> </div> </div> <div class="container"> <div id="noteList"></div> <div class="pull-right"><button id="addNoteButton" class="btn btn-success">Add Note</button></div> <div id="noteDetail"></div> <div id="noteForm"> <h2>Edit Note</h2> <form role="form" class="form-horizontal"> <input type="hidden" id="key"> <div class="form-group"> <label for="title" class="col-lg-2 control-label">Title</label> <div class="col-lg-10"> <input type="text" id="title" required class="form-control"> </div> </div> <div class="form-group"> <label for="body" class="col-lg-2 control-label">Body</label> <div class="col-lg-10"> <textarea id="body" required class="form-control"></textarea> </div> </div> <div class="form-group"> <div class="col-lg-offset-2 col-lg-10"> <button id="saveNoteButton" class="btn btn-default">Save Note</button> </div> </div> </form> </div> </div> <script src="js/jquery-2.0.0.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script> <script src="js/app.js"></script> </body> </html>
Seperti disebutkan di atas, sebagian ukuran file ini adalah kode template untuk Bootstrap. Bagian yang kita pedulikan adalah noteList
div, noteDetail
div, dan noteForm
. Anda mungkin bisa menebak bahwa ini adalah DIV yang akan kami perbarui saat pengguna mengklik di dalam aplikasi.
Coding File Core Aplikasi
Sekarang mari kita lihat app.js
, file inti yang menangani logika untuk aplikasi kita.
/* global console,$,document,window,alert */ var db; function dtFormat(input) { if(!input) return ""; var res = (input.getMonth()+1) + "/" + input.getDate() + "/" + input.getFullYear() + " "; var hour = input.getHours(); var ampm = "AM"; if(hour === 12) ampm = "PM"; if(hour > 12){ hour-=12; ampm = "PM"; } var minute = input.getMinutes()+1; if(minute < 10) minute = "0" + minute; res += hour + ":" + minute + " " + ampm; return res; }
Anda dapat mengabaikan fungsi pertama karena ini hanyalah utilitas format untuk tanggal. Mari kita langsung beralih ke jQuery document ready block
Memeriksa dukungan Browser
$(document).ready(function() { if(!("indexedDB" in window)) { alert("IndexedDB support required for this demo!"); return; } var $noteDetail = $("#noteDetail"); var $noteForm = $("#noteForm"); var openRequest = window.indexedDB.open("nettuts_notes_1",1); openRequest.onerror = function(e) { console.log("Error opening db"); console.dir(e); }; openRequest.onupgradeneeded = function(e) { var thisDb = e.target.result; var objectStore; //Create Note OS if(!thisDb.objectStoreNames.contains("note")) { console.log("I need to make the note objectstore"); objectStore = thisDb.createObjectStore("note", { keyPath: "id", autoIncrement:true }); } }; openRequest.onsuccess = function(e) { db = e.target.result; db.onerror = function(event) { // Generic error handler for all errors targeted at this database's // requests! alert("Database error: " + event.target.errorCode); console.dir(event.target); }; displayNotes(); };
Tindakan pertama kami adalah memeriksa dukungan IndexedDB. Jika browser pengguna tidak kompatibel, kami menggunakan peringatan dan membatalkan fungsi. Mungkin akan lebih baik untuk memindahkan mereka ke halaman yang sepenuhnya menjelaskan mengapa mereka tidak dapat menggunakan aplikasi. (Dan untuk lebih jelasnya, kita juga bisa membuat aplikasi yang menggunakan WebSQL sebagai cadangan. Tetapi sekali lagi - fokus saya di sini adalah pada kesederhanaan.)
Setelah melakukan cache beberapa pemilih jQuery, yang akan kami gunakan di seluruh aplikasi, kami kemudian membuka database IndexedDB kami. Basis data cukup sederhana. Dalam handler onupgradeneeded
Anda dapat melihat satu toko objek yang disebut notes
sedang dibuat. Setelah semuanya selesai, handler yang onsuccess
akan mengaktifkan panggilan untuk displayNotes
.
DisplayNotes
Function
function displayNotes() { var transaction = db.transaction(["note"], "readonly"); var content="<table class='table table-bordered table-striped'><thead><tr><th>Title</th><th>Updated</th><th>&nbsp;</td></thead><tbody>"; transaction.oncomplete = function(event) { $("#noteList").html(content); }; var handleResult = function(event) { var cursor = event.target.result; if (cursor) { content += "<tr data-key=\""+cursor.key+"\"><td class=\"notetitle\">"+cursor.value.title+"</td>"; content += "<td>"+dtFormat(cursor.value.updated)+"</td>"; content += "<td><a class=\"btn btn-primary edit\">Edit</a> <a class=\"btn btn-danger delete\">Delete</a></td>"; content +="</tr>"; cursor.continue(); } else { content += "</tbody></table>"; } }; var objectStore = transaction.objectStore("note"); objectStore.openCursor().onsuccess = handleResult; }
Fungsi displayNotes
melakukan apa yang Anda harapkan - dapatkan semua data dan menampilkannya. Kami membahas cara mendapatkan semua baris data di entri sebelumnya, tetapi saya ingin menunjukkan sesuatu yang sedikit berbeda tentang contoh ini. Perhatikan bahwa kami memiliki pengendali event baru, oncomplete
, bahwa kami telah terikat dengan transaksi itu sendiri. Sebelumnya, kami telah menggunakan acara hanya dalam tindakan, di dalam transaksi, tetapi IndexedDB memungkinkan kami melakukannya di level teratas juga. Ini menjadi sangat berguna dalam kasus seperti ini. Kami memiliki string raksasa, tabel HTML kami, yang kami bangun di atas setiap iterasi data kami. Kita dapat menggunakan penangan oncomplete
transaksi untuk membungkus bagian tampilan dan menuliskannya menggunakan jQuery call sederhana.
Delete
, Edit
, dan Add
fungsi
$("#noteList").on("click", "a.delete", function(e) { var thisId = $(this).parent().parent().data("key"); var t = db.transaction(["note"], "readwrite"); var request = t.objectStore("note").delete(thisId); t.oncomplete = function(event) { displayNotes(); $noteDetail.hide(); $noteForm.hide(); }; return false; }); $("#noteList").on("click", "a.edit", function(e) { var thisId = $(this).parent().parent().data("key"); var request = db.transaction(["note"], "readwrite") .objectStore("note") .get(thisId); request.onsuccess = function(event) { var note = request.result; $("#key").val(note.id); $("#title").val(note.title); $("#body").val(note.body); $noteDetail.hide(); $noteForm.show(); }; return false; }); $("#noteList").on("click", "td", function() { var thisId = $(this).parent().data("key"); var transaction = db.transaction(["note"]); var objectStore = transaction.objectStore("note"); var request = objectStore.get(thisId); request.onsuccess = function(event) { var note = request.result; $noteDetail.html("<h2>"+note.title+"</h2><p>"+note.body+"</p>").show(); $noteForm.hide(); }; }); $("#addNoteButton").on("click", function(e) { $("#title").val(""); $("#body").val(""); $("#key").val(""); $noteDetail.hide(); $noteForm.show(); });
Dua metode kami berikutnya (delete
dan edit
) adalah contoh lain dari prinsip yang sama ini. Karena tidak ada panggilan IndexedDB di sini yang baru, kami tidak akan repot-repot memikirkannya. Sebagian besar "meat" di sini berakhir dengan manipulasi DOM yang sederhana untuk menangani tindakan-tindakan tertentu. Pawang untuk mengklik tombol tambah adalah persis seperti itu, jadi kita akan melewatkannya juga.
Save
Function
$("#saveNoteButton").on("click",function() { var title = $("#title").val(); var body = $("#body").val(); var key = $("#key").val(); var t = db.transaction(["note"], "readwrite"); if(key === "") { t.objectStore("note") .add({title:title,body:body,updated:new Date()}); } else { t.objectStore("note") .put({title:title,body:body,updated:new Date(),id:Number(key)}); } t.oncomplete = function(event) { $("#key").val(""); $("#title").val(""); $("#body").val(""); displayNotes(); $noteForm.hide(); }; return false; }); });
Berita gembira berikutnya yang menarik adalah metode save
. Itu harus menggunakan sedikit logika untuk menentukan apakah kita menambahkan atau memperbarui, tetapi bahkan itu agak sederhana. Dan itu dia! Lengkap, if simple, aplikasi IndexedDB. Anda dapat bermain-main dengan demo ini sendiri dengan mengunduh source code.
Kesimpulannya
Itu untuk bagian dua! Artikel ketiga akan mengambil aplikasi ini dan mulai menambahkan fitur tambahan termasuk properti berbasis search dan array.