Advertisement
  1. Code
  2. HTML & CSS

Membangun Sticky Notes yang Menetap dengan Local Storage

Scroll to top
Read Time: 12 min
This post is part of a series called HTML5 and You.
Getting Offline Access with HTML5 Application
HTML5 Apps: What, Why, and How

Indonesian (Bahasa Indonesia) translation by Ari Ana (you can also view the original English article)

Penyimpanan lokal HTML5 seperti cookie dengan steroid; ini sangat mudah digunakan namun tetap begitu kuat. Dalam tutorial ini, saya akan menunjukkan cara membuat fungsionalitas "catatan tempel", yang memungkinkan pengguna mengambil catatan yang menetap saat menjelajahi situs Anda.


Langkah 1: HTML

Karena sifat dinamis proyek ini, tidak banyak kode yang bisa dilakukan dalam markup semantik biasa. Kami hanya akan mensimulasikan halaman web dengan menyatukan beberapa konten pengisi:

1
  <!DOCTYPE html>
2
    <html>
3
    <head>
4
        <meta charset='utf-8' />
5
        <title>HTML 5 complete</title>
6
        <link rel="stylesheet" href="default.css" />
7
        <link rel="stylesheet" href="stickies/stickies.css" />
8
        <!--[if IE]>

9
        <script src="https://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

10
        <![endif]-->
11
    </head>
12
    <body>
13
        <article>
14
            <header>
15
                <h1> Sample Article Title</h1>
16
            </header>
17
            <p>Lorem ipsum dolor. . . </p>
18
            <!-- a few lorem-ipsum paragraphs later . . . -->
19
            <footer>
20
                <p>Copyright 2010 Andrew Burgess</p>
21
            </footer>
22
        </article>
23
24
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
25
        <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js"></script>
26
        <script src="json2.js"></script>
27
        <script src="stickies/stickies.js"></script>
28
        <script>
29
        </script>
30
    </body>
31
    </html>

Ada beberapa hal penting yang perlu diperhatikan di sini: kami menyertakan dua file CSS: yang pertama adalah gaya sederhana untuk halaman, yang telah kami sebut default.css. Kemudian, kami memiliki file CSS khusus untuk gaya yang terkait dengan catatan tempel kami; ini disebut stickies.css, dan seperti yang Anda lihat, ia tinggal di folder "stickies". Di bagian bawah, kami menyertakan empat skrip:

  • jQuery, dari CDN Google
  • JQuery UI, dari CDN Google
  • JSON2, dari Douglas Crockford
  • stickies.js kita sendiri, yang tinggal di direktori "stickies"

Kemudian, kami memiliki tag script kosong yang akan kami gunakan untuk menghidupkan mesin sedikit kemudian.

Dan itu untuk HTML!


Langkah 2: CSS

Konten default.css sangat sederhana:

1
   body {
2
        margin:0;
3
        padding:0;
4
        background:#ccc;
5
        font:14px/1.5 "Helvetica Neue", Helvetica, Arial, san-serif;
6
    }
7
    article, footer, header { display: block; }
8
    article {
9
        width:880px;
10
        background:#fff;
11
        margin:auto;
12
        padding:40px;
13
    }
14
    article header {
15
        color:#474747;
16
        border-bottom:1px solid #474747
17
    }
18
    article footer {
19
        font-size:90%;
20
        color:#ccc;
21
    }

Itu saja; sekarang, ada CSS dari stickies.css untuk dijaga... tapi kita belum memiliki markup itu. Jadi mari kita mulai beberapa JavaScript, dan setelah selesai, kita akan melihat CSS untuk catatan tempel.


Langkah 3: JavaScript

Inilah kerangka untuk aplikasi JavaScript kita:

1
    var STICKIES = (function () {
2
        var initStickies = function () {},
3
            openStickies = function () {},
4
            createSticky = function (data) {},
5
            deleteSticky = function (id) {},
6
            saveSticky   = function () {},
7
            markUnsaved  = function () {};
8
            
9
        return {
10
            open   : openStickies,
11
            init   : initStickies
12
        };
13
    }());

Kita punya beberapa teknik menarik yang terjadi di sini. Pertama adalah fungsi yang memanggil dirinya sendiri: mungkin terlihat seperti kita menugaskan fungsi ke variabel STICKIES, tapi jika Anda melihat dari dekat fungsi ini, Anda akan melihat bahwa kita menjalankannya dengan segera. Sebagai petunjuk—untuk mengingatkan kita bahwa ini bukan fungsi normal—kita membungkus keseluruhan fungsi dalam tanda kurung. Jadi, STICKIES bukanlah fungsi, itu adalah nilai yang dikembalikan dari fungsi itu, yang merupakan objek, dalam kasus ini.

Itu membawa kita ke teknik berikutnya: penutupan. Perhatikan bahwa dari enam fungsi yang kita buat, hanya dua di antaranya yang terpapar pada pengguna (sebenarnya hanya satu yang diperlukan untuk penggunaan yang kami rencanakan; jika kita ingin membangun dukungan untuk membuat catatan ke situs web Anda, kita dapat mengekspos createSticky dan deleteSticky). Meskipun fungsi yang memanggil dirinya sendiri selesai dijalankan sebelum kita menggunakan metode ini, kita akan dapat menggunakan fungsi lain yang telah kita definisikan.

Oke, mari beralih ke isi dari fungsi ini.


initStickies

Kita akan mulai dengan melihat fungsi initStickies:

1
    var initStickies = function initStickies() {
2
        $("<div />", { 
3
            text : "+", 
4
            "class" : "add-sticky",
5
            click : function () { createSticky(); }
6
        }).prependTo(document.body);
7
        initStickies = null;
8
    },

Ini sangat sederhana. Kita akan menggunakan jQuery dengan cukup sedikit untuk membuat elemen, dan kita menggunakan beberapa sintaks khusus dalam v. 1.4: yang mengirimkan sebuah objek literal dengan spesifikasi elemen sebagai parameter kedua pada fungsi jQuery. Di sini, kita menciptakan sebuah tombol untuk membuat catatan baru. Itu berarti kita membutuhkan div baru; kita menetapkan teksnya ke "+" dan memberinya kelas "add-sticky"; kemudian, kita menetapkan handler klik untuk memanggil metode createSticky (penting untuk memanggil createSticky dari dalam sebuah fungsi, dan tidak ada handler klik yang langsung memanggil createSticky; ini karena createSticky dapat mengambil satu parameter saja, dan kita tidak ingin itu menjadi objek event). Akhirnya, kita menambahkan div ini ke body. Kita akhiri dengan mengatur initStickies menjadi null; ya, pada dasarnya kita menyingkirkan fungsi yang kita jalankan. Ini meyakinkan kita bahwa fungsi ini hanya akan dijalankan sekali; kami tidak ingin pengguna API kami secara tidak sengaja menambahkan beberapa tombol "add note" ke halaman.

openStickies

Mari beralih ke metode selanjutnya, openStickies:

1
    openStickies = function openStickies() {
2
        initStickies && initStickies();
3
        for (var i = 0; i < localStorage.length; i++) {
4
            createSticky(JSON.parse(localStorage.getItem(localStorage.key(i))));
5
        }
6
    },

Kita mulai dengan menjalankan initStickies... tapi ada apa dengan sintaksnya? Nah, Anda mungkin akrab dengan operator &&: operator AND boolean. Anda biasanya menggunakannya untuk memeriksa beberapa kondisi dalam pernyataan if. Inilah yang sebenarnya terjadi: ia mengevaluasi ekspresi pertama, dan jika itu true, ia akan terus mengevaluasi ekspresi kedua. Dalam kasus ini, jika initStickies belum diset ke null, kita akan menjalankan fungsinya. Hal ini untuk menghindari kesalahan yang akan datang dari mencoba menjalankan variabel null sebagai fungsi.

Selanjutnya, kita mengulangi setiap item di localStorage. Inilah yang kami lakukan dalam for-loop itu (dari dalam ke luar):

  • localStorage.key() adalah fungsi hebat yang mengembalikan nama kunci dari nilai localStorage; dibutuhkan angka sebagai parameter. Ini adalah cara yang bagus untuk mengulang setiap item di localStorage.
  • Begitu kita memiliki kunci untuk barang yang tersimpan, kita bisa mengirimkannya ke localStorage.getItem() untuk mendapatkan nilainya.
  • Kemudian, kita menyampaikan nilai itu ke JSON.parse(); ini berasal dari perpustakaan Crockford. Karena kita menyimpan beberapa nilai untuk setiap catatan, kita menggunakan JSON.stringify() di ujung yang lain untuk mengubah objek menjadi string JSON, yang kita simpan. Di sini, kita mengubahnya dari string kembali menjadi objek.
  • Akhirnya, kita mengirimkan objek itu ke createSticky(), yang mengubahnya menjadi catatan tempel.

createSticky

Sekarang, mari kita lihat metode createSticky itu.

1
    createSticky = function createSticky(data) {
2
        data = data || { id : +new Date(), top : "40px", left : "40px", text : "Note Here" }
3
        
4
        return $("<div />", { 
5
            "class" : "sticky",
6
            'id' : data.id
7
             })
8
            .prepend($("<div />", { "class" : "sticky-header"} )
9
                .append($("<span />", { 
10
                    "class" : "status-sticky", 
11
                    click : saveSticky 
12
                }))
13
                .append($("<span />", { 
14
                    "class" : "close-sticky", 
15
                    text : "trash", 
16
                    click : function () { deleteSticky($(this).parents(".sticky").attr("id")); }
17
                }))
18
            )
19
            .append($("<div />", { 
20
                html : data.text, 
21
                contentEditable : true, 
22
                "class" : "sticky-content", 
23
                keypress : markUnsaved
24
            }))
25
        .draggable({ 
26
            handle : "div.sticky-header", 
27
            stack : ".sticky",
28
            start : markUnsaved,
29
            stop  : saveSticky  
30
         })
31
        .css({
32
            position: "absolute",
33
            "top" : data.top,
34
            "left": data.left
35
        })
36
        .focusout(saveSticky)
37
        .appendTo(document.body);
38
    },

Ya, sudah lama, tapi tidak akan terlalu sulit. Pertama, perhatikan bahwa fungsi ini mengambil objek data; seperti yang baru saja kita lihat di openStickies, kita meneruskan data yang tersimpan ke fungsi ini. Namun, jika kami tidak menyampaikan data apa pun (yaitu, kami membuat catatan baru), kami akan membuat objek catatan default. Karena semua catatan harus dibuat pada satu titik, semua catatan akan dimulai dengan konfigurasi ini. Perhatikan bahwa untuk id catatan, kami menggunakan +new Date(); yang ditambah operator plus unary yang mengubah tanggal yang kami dapatkan dari tanggal baru ke angka, jadi pernyataan ini menghasilkan angka yang mewakili jumlah milidetik sejak 1 Januari 1970. Jelas, nomor ini akan terus berubah, jadi ini adalah cara yang bagus untuk mengidentifikasi setiap catatan secara unik.

Sisa dari fungsi adalah string panjang metode berantai jQuery. Sebelum kita melalui ini, perhatikan bahwa kita mengembalikan hasilnya. Jika kita mengekspos metode ini kepada pengembang menggunakan mirco-API kita, itu akan mengembalikan referensi ke elemen div catatan tempel.

Jadi, inilah yang terjadi:

  • Pertama, kita membuat div yang merupakan tempurung dari catatan tempel. Dengan menggunakan sintaks jQuery 1.4 yang bermanfaat, kami memberikan kelas "sticky" dan id dari objek data.

  • Kemudian, kita menambahkan div ke sana; div ini mendapat kelas "sticky-header". div.sticky-header kemudian mendapat dua span ditambahkan ke sana. Yang pertama, span.sticky-status, mendapat handler klik yang memanggil fungsi saveSticky. Namun, itu sebenarnya fitur tersembunyi: span ini akan menampilkan status yang sticky: tersimpan atau belum disimpan. Akan ada beberapa cara sticky menyimpan datanya ke localStorage; mungkin pengguna akan berpikir bahwa mengklik 'unsaved' akan menyimpan catatan, jadi kami akan memberi mereka fungsi itu. Span kedua, span.close-sticky, akan menjadi tombol hapus: saat pengguna mengkliknya, kami akan menghapus sticky dari localStorage, melalui metode deleteSticky. Kami melewatkan metode itu id catatan.

  • Selanjutnya, kita menambahkan div lain ke div.sticky utama; perhatikan bahwa kita mengatur properti html ke data.text; saat kita menyimpan teks catatan, kita menggunakan metode html() dari jQuery, karena menggunakan text() menghilangkan jeda baris. Kita juga mengatur contentEditable:true di div ini, karena ini adalah isi dari catatan. Dengan demikian, itu juga mendapat kelas sticky-content. Akhirnya, ketika tombol ditekan pada div ini (artinya pengguna mengubah konten), kami ingin menandainya sebagai tidak tersimpan, jadi kita akan memanggil fungsi itu (yang akan segera kita lakukan).

  • Sekarang, kami menggunakan fitur jQuery UI draggable untuk membuat catatan tempel kita dapat dipindah-pindahkan. Di objek parameter kita, kita menggunakan properti handle agar catatan kita hanya dapat dipindahkan dari bilah header. Properti stack adalah pemilih untuk elemen yang dapat diseret yang ingin di-"stack"; dengan pengaturan ini, catatan yang saat ini terseret akan selalu berada di atas. Akhirnya, ketika kita mulai menyeret catatan, kita ingin menandainya sebagai "belum disimpan" (karena kita juga harus menyimpan koordinatnya), dan ketika kita berhenti menyeret, kita akan menyimpan sticky itu.

  • Selanjutnya, kita menetapkan beberapa gaya untuk div.sticky kita; kita memposisikannya secara absolute, dan kemudian menetapkan nilai atas dan kiri ke nilai pada objek data. Dengan cara ini, catatan akan tetap mempertahankan posisinya dan juga isinya saat kita me-refresh halaman.

  • Akhirnya, kita akan mengatur event handler saat kita focusout sticky (intinya, klik di luarnya setelah mengkliknya): kita ingin menyimpan sticky. Terakhir, kami akan menambahkannya ke body. Sebagai rujukan, inilah struktur html yang seharusnya kita hasilkan:

1
<div class="sticky ui-draggable" id="1281194825332" style="position: absolute; top: 40px; left: 40px;">
2
    <div class="sticky-header">
3
            <span class="sticky-status"></span>
4
            <span class="close-sticky">trash</span>
5
    </div>
6
    <div contenteditable="true" class="sticky-content">
7
        Note Here
8
    </div>
9
</div>

Dan itulah fungsi createSticky kita.

deleteSticky

Sekarang kita memiliki fungsi deleteSticky; ini sangat sederhana:

1
    deleteSticky = function deleteSticky(id) {
2
        localStorage.removeItem("sticky-" + id);
3
        $("#" + id).fadeOut(200, function () { $(this).remove(); });
4
    },

Seperti yang Anda ingat, fungsi deleteSticky mengambil id dari sebuah catatan sebagai parameternya. localStorage.removeItem() adalah metode jamnya: kita menyampaikan ke nilai yang tersimpan secara lokal untuk menghapus pasangan kunci-nilai tersebut (Perhatikan bahwa ketika kita menyimpan data catatan, kita menambahkan "sticky-" ke id). Kemudian, kita menemukan elemen dengan id yang diberikan, memudarkannya, dan menghapusnya. Catatan dihapus!

saveSticky

Kedua-sampai-terakhir mungkin metode yang paling penting hari ini: saveSticky: ini adalah lem yang membuat semuanya bekerja.

1
    saveSticky = function saveSticky() {
2
        var that = $(this),  sticky = (that.hasClass("sticky-status") || that.hasClass("sticky-content")) ? that.parents('div.sticky'): that,
3
        obj = {
4
            id  : sticky.attr("id"),
5
            top : sticky.css("top"),
6
            left: sticky.css("left"),
7
            text: sticky.children(".sticky-content").html()               
8
        }
9
        localStorage.setItem("sticky-" + obj.id, JSON.stringify(obj));    
10
        sticky.find(".sticky-status").text("saved");
11
    },

Baris pertama adalah sedikit resolusi: ada tiga elemen yang berbeda yang bisa kita panggil fungsi ini darinya. Pertama, kita akan "men-jQuery-kan" this ke that; jika elemennya memiliki kelas "sticky-status" atau "sticky-content", kita akan mendapatkan induk div.sticky; jika tidak memiliki salah satu dari kelas tersebut, maka itu adalah div.sticky itu sendiri, jadi kita akan langsung menggunakannya.

Kemudian, kita perlu mendapatkan nilai yang ingin kita simpan. Seperti yang bisa Anda lihat, kita mendapatkan id, offset dari atas dan kiri, dan html dari anak .sticky-content; ingat, kita menggunakan html() bukannya text() karena kita ingin menyimpan jeda baris. Kemudian, kita menggunakan localStorage.setItem untuk menyimpan datanya. Ingat, dibutuhkan dua parameter: kunci dan nilai untuk disimpan. Karena localStorage hanya menyimpan string, kita menggunakan JSON.stringify() untuk mengubah objek menjadi string.

Terakhir, mengubah status sticky menjadi "saved."

markUnsaved

Kita punya satu fungsi terakhir, yang hanya fungsi helper:

1
    markUnsaved = function markUnsaved() {
2
        var that = $(this), sticky = that.hasClass("sticky-content") ? that.parents("div.sticky") : that;
3
        sticky.find(".sticky-status").text("unsaved");
4
    }

Sekali lagi, kita harus mulai dengan menyelesaikan referensi ke div.sticky; begitu kita melakukannya, kita bisa menemukan span status dan mengatur teksnya menjadi "unsaved."

Percaya atau tidak, itu saja JavaScript-nya.


Langkah 4: CSS, Kunjungan Ulang

Sekarang kita tahu apa markup catatan tempel kita, kita bisa memberinya gaya. Ini sangat sederhana; tapi lihat saja, dan saya akan membuat beberapa komentar di akhir:

1
   :focus {
2
        outline:0;
3
    }
4
    .add-sticky {
5
        cursor: default;
6
        position:absolute;
7
        top:1px;
8
        left:1px;
9
        font-size:200%;
10
        background:#000;
11
        color:#fff;
12
        border:2px solid #fff;
13
        border-radius:40px;
14
        -webkit-border-radius:40px;
15
        -moz-border-radius:40px;
16
        text-align:center;
17
        line-height:25px;
18
        width:30px;
19
        height:30px;
20
    }
21
    .add-sticky:hover {
22
        background: #474747;
23
    }
24
    .sticky {
25
        width:300px;
26
        background:#fdfdbe;
27
        box-shadow:3px 3px 10px rgba(0,0,0,0.45);
28
        -webkit-box-shadow:3px 3px 10px rgba(0,0,0,0.45);
29
        -moz-box-shadow:3px 3px 10px rgba(0,0,0,0.45);
30
    }
31
    .sticky-content {
32
        min-height:150px;
33
        border-left:3px double rgba(238, 150, 122, .75);
34
        margin-left:30px;
35
        padding:5px;
36
    }
37
    .sticky-header {
38
        padding:5px;
39
        background:#f3f3f3;
40
        border-bottom:2px solid #fefefe;
41
        box-shadow:0 3px 5px rgba(0,0,0,0.25);
42
        -webkit-box-shadow:0 3px 5px rgba(0,0,0,0.25);
43
        -moz-box-shadow:0 3px 5px rgba(0,0,0,0.25);
44
    }
45
    .sticky-status {
46
        color:#ccc;
47
        padding:5px;
48
    }
49
    .close-sticky {
50
        background:#474747;
51
        float:right;
52
        cursor:default;
53
        color:#ececec;
54
        padding:1px 5px;
55
        border-radius:20px;
56
        -webkit-border-radius:20px;
57
        -moz-border-radius:20px;
58
    }

Ada beberapa hal menarik di sini:

  • Beberapa browser menempatkan garis tepi di seputar elemen dengan contenteditable=true saat Anda mengedit konten. Kita tidak menginginkan itu, jadi kita menyingkirkannya dengan deklarasi :focus kita.
  • Tombol "Add Sticky" diposisikan di sudut kiri atas; tampilannya samar-samar mirip dengan "Add Dashboard Widget" di Mac OS X.
  • Kita menggunakan properti CSS3 border-radius dan box-shadow (dan inkarnasi prefiks vendor yang sesuai).
  • Kami juga menggunakan rgba() untuk warna bayangan kami. Dibutuhkan empat parameter: warna merah, hijau, dan biru, dan nilai alpha (transparansi).

Selain itu, itu hanya CSS standar Anda. Seperti inilah tampilan catatan yang diberi gaya:

Note

Langkah 5: Memulai Stickies

Sekarang setelah kita membuat API kita, saatnya memulainya; kita bisa melakukan itu dari tag script tambahan kosong di file index.html kita:

1
    STICKIES.open();

Kesimpulan: Produk Akhir

Kita sudah selesai! Inilah produk akhir yang beraksi:

Hanya itu yang saya miliki hari ini; bagaimana Anda berencana untuk menggunakan penyimpanan lokal HTML5 untuk membumbui proyek web Anda? Beri tahu saya di komentar!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.