Saya tidak tahu apakah cara ini bisa mempercepat kerja animasi atau tidak (Saya malas mengetesnya). Tapi Saya pikir cara ini bisa mempermudah kita di dalam membangun deret animasi berlebih-lebihan tanpa harus mendeklarasikan JQuery .animate() secara berlebihan. Selain itu, dengan cara mempopulasikan properti animasi di dalam array, maka ini memungkinkan kita untuk menciptakan gerak animasi yang berbeda-beda pada elemen yang berbeda dengan cara meletakkan array animasi ke dalam atribut elemen. Misalnya seperti ini:
Setelah itu, cukup gunakan method manipulasi atribut untuk mendapatkan nilai atribut pada masing-masing elemen. Konversi nilainya agar menjadi array (bukan string) dengan eval():
$('div').each(function() { var anim = eval($(this).data('animation')), // Mengambil nilai atribut `data-animation` dari elemen $div = $(this); $.each(anim, function(i) { $div.animate(anim[i], 1000); }); });
Fungsi ini digunakan untuk mengubah deret angka menjadi pola mata uang dimana setiap tiga deret angka akan ditambahi sebuah titik atau koma setelahnya/sebelumnya, dimulai dari belakang:
Kode ini memungkinkan kita untuk mengambil node komentar HTML yang kemudian bisa kita gunakan sebagai elemen HTML biasa. Sehingga jika komentar HTML adalah berupa elemen HTML yang mengandung permintaan HTTP, maka kita bisa memuat elemen tersebut secara tidak langsung dengan cara menuliskannya sebagai komentar HTML terlebih dahulu:
#fake-elem-container adalah elemen yang akan dijadikan sebagai penampung komentar HTML, sedangkan #container akan menjadi penampung node komentar yang sudah berubah menjadi elemen HTML:
<b:if cond='data:post.allowComments'> adalah kondisional template yang berfungsi untuk menyatakan bahwa pemilik blog mengizinkan pengunjung untuk menuliskan komentar. Anda biasanya akan melihat kode ini membungkus semua elemen di dalam seksi komentar sehingga jika administrator mengeset opsi pengaturan untuk tidak mengizinkan pengunjung lain menuliskan komentar baru melalui panel pengaturan utama (bukan opsi pada pengaturan posting), maka seluruh komentar yang telah masuk akan ikut menghilang (disembunyikan):
<!-- Seluruh konten di bagian ini akan menghilang jika Administrator mengeset opsi pengaturan untuk tidak mengizinkan pengunjung menuliskan komentar baru. -->
</b:if> </div>
Biasanya hal ini akan merugikan blog-blog bertipe diskusi yang ramai pengunjung, terutama jika komentar-komentar yang diterbitkan berguna untuk pembaca lain sebagai referensi tambahan.
Suatu saat mungkin Anda akan mengalami masa-masa sibuk atau katakanlah “sedang tidak mampu untuk membalas komentar-komentar yang masuk”. Saat Anda mengalami itu biasanya hal yang akan Anda lakukan adalah menutup komentar posting secara temporer dengan cara menyembunyikannya seperti ini:
Menonaktifkan sekaligus menyembunyikan komentar pada semua posting.
Untuk menjaga agar komentar-komentar lama tidak hilang, Anda bisa memindahkan/memperbaharui wilayah kondisional <b:if cond='data:post.allowComments'> menjadi lebih sempit. Cukup hilangkan formulir komentarnya saja dan biarkan komentar-komentar yang sudah ada tetap pada tempatnya. Caranya adalah hapus kode <b:if cond='data:post.allowComments'> ... </b:if> yang mengelilingi elemen <div class='comments' id='comment'> sehingga akan tersisa seperti ini:
Masing-masing kode biasanya akan ditemukan dua buah, termasuk juga untuk seksi komentarnya. Dimana salah satu adalah elemen komentar yang akan aktif pada blog versi biasa dan satunya lagi aktif pada blog tampilan seluler.
Alat ini digunakan untuk menggenerasikan kode-kode karakter spesial HTML yang bisa Anda gunakan untuk menghiasi tulisan atau untuk keperluan-keperluan lain seperti penambahan ikon pada menu tanpa gambar dan sebagainya. Cukup tentukan angka awal dan banyak karakter yang akan ditampilkan kemudian tekan tombol Show the Code List untuk menampilkan deret karakter beserta kodenya.
Anda juga bisa menggenerasikan kueri URL berdasarkan deretan simbol yang ditampilkan. URL ini bisa Anda gunakan sebagai URL berbagi atau URL bookmark untuk karakter-karakter favorit Anda:
Saya hanya akan menjelaskan konsep ini secara cepat dan nyaris nonverbal, jadi perhatikan dan jangan lupa untuk membaca komentar-komentar di dalam kode CSS dan HTML yang Saya tuliskan. Pada dasarnya kita hanya akan membuat menu biasa, yang kemudian kita lengkapi dengan ikon sebagai tombol penampil menu. Secara normal, ikon tersebut akan disembunyikan dan menu navigasi akan ditampilkan pada perangkat desktop/device berukuran besar, sampai ketika kita berada pada perangkat yang lebih kecil, maka CSS akan melakukan hal sebaliknya, yaitu akan menyembunyikan menu dan menampilkan ikon/navicon.
Kita membutuhkan enam buah elemen HTML yaitu <nav>, <ul>, <li>, <input type="checkbox">, <label> dan <a>
Tag HTML
Keperluan
<nav>, <ul>, <li>
Semantik. Semua navigasi standar dibangun dengan elemen ini
<a>
Setiap navigasi juga memiliki tautan-tautan yang berfungsi untuk mengarahkan pengunjung menuju sebuah tempat tertentu saat tautan-tautan tersebut diklik
<input type="checkbox">
Elemen ini digunakan untuk menampilkan dan menyembunyikan menu pada tampilan mobile. Dengan CSS3 :checked, kita bisa membuat efek toggle menggunakan elemen checkbox (baca di sini)
<label>
Elemen ini digunakan untuk keperluan visual saja. Lebih tepatnya, elemen ini akan menjadi ikon yang akan tampak sebagai tombol, padahal tombol menu yang sebenarnya adalah elemen checkbox yang disembunyikan dengan opacity:0.
Pertama-tama kita set dasar dimensi menu dengan mengatur tampilan elemen <nav> meliputi tipe font, warna latar dan huruf:
/* navigasi: tentukan font, warna huruf dan latar */ nav { font:normal bold 11px Arial,Sans-Serif; color:gray; background-color:black; height:30px; }
Kemudian set layout daftar menu menjadi horizontal. Hapus margin, padding dan bullet bawaan dari User Agent Style Sheet:
/* daftar menu: hilangkan margin, padding dan bullet */ nav ul, nav li { margin:0 0; padding:0 0; list-style:none; }
/* set tinggi menu */ nav ul {height:30px}
/* set layout menu menjadi berjajar/horizontal */ nav li { float:left; display:inline; }
Ubah semua tautan di dalam navigasi menjadi elemen blok agar lebih mudah dalam pengaturan tinggi, padding dan hal-hal lain yang kebanyakan bisa dilakukan oleh elemen blok:
/* tautan */ nav a { display:block; line-height:30px; padding:0 14px; text-decoration:none; color:white; }
Ganti juga warna item menu jika pointer mouse berada di atasnya:
/* sikap hover item menu */ nav a:hover {background-color:#39f}
Ikon Menu (Navicon)
Bentuknya seperti ini: `≡`. Simbol disamping Saya buat dengan entitas HTML ≡. Kita akan meletakkan simbol itu di dalam elemen <label> seperti ini:
<label>≡</label>
Sebenarnya ada beberapa bentuk lain yang biasa dijadikan sebagai simbol untuk menyatakan menu (baca di sini), tapi bentuk yang paling mudah dibuat dan yang paling umum digunakan adalah bentuk yang Saya tuliskan di atas.
Kali ini kita akan mengerjakan CSS elemen checkbox dan label. Secara normal tampilannya akan disembunyikan:
nav input {display:none} nav label {display:none}
Kemudian set beberapa pengaturan. Sembunyikan wujud elemen checkbox dengan mendeklarasikan opacity:0, dan atur dimensinya dengan tinggi dan lebar yang (disarankan) sama dengan tinggi menu:
/* checkbox: sebagai tombol menu pada tampian mobile */ nav input { display:none; margin:0 0; padding:0 0; width:30px; height:30px; opacity:0; /* sembunyikan wujud */ cursor:pointer; }
/* elemen label: sebagai ikon */ nav label { display:none; font-size:200%; width:30px; height:30px; /* teks berada di tengah secara vertikal dan horizontal */ line-height:30px; text-align:center; }
Media Queries
Hanya membutuhkan satu media query untuk menyatakan bahwa kita sedang berada pada perangkat mobile. Misalnya berada pada ukuran layar maksimal 767px
@media (max-width:767px) { ... }
Saat kita berada pada ukuran layar maksimal 767 piksel, set tampilan menu sebagai menu vertikal. Tampilkan ikon dan sembunyikan semua menu:
@media (max-width:767px) { nav { /* kita akan mengeset posisi menu dan ikon sebagai elemen absolut terhadap navigasi, jadi kita memerlukan deklarasi ini */ position:relative; } nav ul { background-color:#200; position:absolute; top:100%; right:0; left:0; height:auto; display:none; /* sembunyikan menu */ } /* set tampilan menu agar bersusun secara vertikal */ nav li { display:block; float:none; width:auto; } nav input, nav label { position:absolute; top:0; right:0; display:block; /* tampilkan elemen checkbox dan label */ } nav input {z-index:4} /* selalu pastikan bahwa checkbox berada di atas label */ }
Kemudian buat efek toggle dengan CSS :checked. Ubah warna ikon saat tombol menu diklik, dan tampilkan menu yang tersembunyi:
@media (max-width:767px) { ... ... /* ubah warna ikon saat tombol menu diklik, dan tampilkan menu yang tersembunyi saat checkbox dicek */ nav input:checked + label {color:white} nav input:checked ~ ul {display:block} }
/* horizontal navigation: define the navigation font and basic background */ nav { background-color:black; font:normal bold 11px Arial,Sans-Serif; color:gray; height:30px; }
/* lists: remove the nested list margin, padding & bullets */ nav ul, nav li { margin:0 0; padding:0 0; list-style:none; }
/* navigation height */ nav ul {height:30px}
/* inline layout menu */ nav li { float:left; display:inline; }
/* the anchor */ nav a { display:block; line-height:30px; padding:0 14px; text-decoration:none; color:white; }
/* hover state menu */ nav a:hover {background-color:#39f}
/* checkbox element: for mobile navigation button */ nav input { display:none; margin:0 0; padding:0 0; width:30px; height:30px; opacity:0; cursor:pointer; }
/* for visual purpose */ nav label { display:none; font-size:200%; width:30px; height:30px; /* center vertically and horizontally */ line-height:30px; text-align:center; }
/* MOBILE NAVIGATION */
@media (max-width:767px) {
nav { /* we want to absolute positioning the menu, checkbox and label element to its parent, so this is needed */ position:relative; }
nav ul { background-color:#200; position:absolute; top:100%; right:0; left:0; height:auto; display:none; /* hide the menu */ }
/* set the menu as a block list item */ nav li { display:block; float:none; width:auto; }
/* now show the checkbox and label element in mobile device */ nav input, nav label { position:absolute; top:0; right:0; display:block; /* show the menu icon */ }
nav input {z-index:4} /* always place the checkbox above the label element */
/* highlight the label element and show the menu if the checkbox is checked */ nav input:checked + label {color:white} nav input:checked ~ ul {display:block}
Untuk indentasi karakter yang akurat, kode hendaknya dituliskan di dalam elemen <pre> atau elemen blok apapun yang dikenai deklarasi white-space:pre dan bertipe font Monospace:
<!-- Dengan tag `PRE` --> <pre> Teks dan unikode di sini ... </pre>
<!-- Dengan tag HTML biasa --> <div style="white-space:pre;word-wrap:break-word;font-family:Monospace;"> Teks dan unikode di sini ... </div>
Demo
A ├─── AA │ └─── AAA ├─── AB │ ├─── ABA │ ├─── ABB │ └─── ABC └─── AC
A ├─── AA │ └─── AAA ├─── AB │ ├─── ABA │ ├─── ABB │ └─── ABC └─── AC
Ini adalah plugin JQuery yang Saya buat berdasarkan konsep selectbox kustom yang pernah Saya temukan dan Saya catat di sini. Fungsinya adalah untuk mengubah tampilan selectbox biasa menjadi selectbox yang mudah dimodifikasi tampilannya. Saya suka dengan metodenya yang sangat sederhana untuk mengubah tampilan selectbox asli tanpa harus menghilangkan elemen aslinya dan hanya membungkusnya dengan elemen baru, sehingga kita bisa menyesuaikan dimensi selectbox palsu berdasarkan dimensi selectbox yang asli tanpa menggunakan perhitungan JavaScript yang rumit. Di sini Saya hanya memanfaatkan dimensi selectbox asli untuk mengubah ukuran lebar elemen inline-block:
Letakkan CSS sebelum JQuery dan plugin setelah JQuery, kemudian aktifkan .customSelectBox() pada elemen <select> yang dikehendaki. Setelah itu Anda bisa menjalankan perintah-perintah lain yang diperlukan terhadap elemen selectbox asli melalui event .change():
<link rel="stylesheet" href="css/style.css" type="text/css"> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/jquery.custom.selectbox.min.js"></script> <script type="text/javascript"> $(document).ready(function() { $('select').customSelectBox().change(function() { // Lakukan sesuatu di sini seperti halnya saat kita melakukan sesuatu ... // ... dengan event `change` JQuery pada elemen selectbox }); }); </script>
Itu saja.
Konfigurasi Lanjutan
Konfigurasi lanjutan ini hanya berputar di sekitar modifikasi kelas. Tidak ada efek-efek khusus tambahan pada plugin ini:
Itu adalah dasarnya. Jika Anda ingin menciptakan efek animasi yang sedikit unik, Anda bisa mencoba untuk memindahkan deklarasi CSS transisi atau membuat perbedaan durasi transisi antara keadaan normal dan saat disentuh pointer. Sebagai contoh, jika Anda memindahkan deklarasi transisi dari selektor utama ke selektor keadaan :hover, maka efek transisi hanya akan terjadi saat pointer berada di atas elemen. Namun saat pointer keluar dari elemen tersebut, efek transisi akan menghilang dan menyisakan efek tersentak seperti biasa:
Efek di atas tampak sedikit berbeda dari efek yang pertama karena transisi hanya terjadi saat pointer berada di atas elemen. Sedangkan saat pointer meninggalkannya, efek transisi tidak terjadi.
Untuk membuat efek transisi yang merupakan kebalikan dari efek di atas (yaitu efek transisi terjadi pada saat pointer keluar dari elemen, namun tidak terjadi pada saat pointer berada di atasnya), Anda bisa menggunakan cara seperti ini:
Pertama-tama, set efek transisi pada selektor utama dengan durasi tertentu:
Mendapatkan warna secara acak berdasarkan barisan warna yang sudah terdaftar:
// Deret warna var colors = ["#345", "#292222", "#990000", "black", "#ffa500", "#fff3db"]; // Mengambil warna secara acak dari array `colors` // dan memasukkan hasilnya ke dalam variabel `a` var a = colors[Math.floor(Math.random()*colors.length)];
Pembaharuan
Yang ini sedikit panjang, tapi hasilnya lebih stabil dibandingkan dengan yang pertama, serta bisa menghasilkan urutan warna yang lebih indah. Dalam beberapa kesempatan, Saya melihat kode pengacak warna yang pertama menghasilkan warna yang tidak valid (pengacak warna hanya menggenerasikan lima digit kode saja, bukannya enam digit seperti yang seharusnya):
function getRandomColor() { var letters = '0123456789ABCDEF'.split(''), color = '#'; for (var i = 0; i < 6; ++i) { color += letters[Math.round(Math.random() * 15)]; } return color; }
Beberapa waktu yang lalu Saya pernah menuliskan cara menampilkan hasil penelusuran dengan JSON Blogger tanpa harus berpindah dari halaman awal menuju halaman hasil penelusuran dengan JavaScript (Anda bisa membacanya di sini).
Melalui JQuery $.ajax() kita bisa meniadakan penyisipan script callback dan langsung memanggil JSON dengan cara seperti ini:
Pertama-tama kita tangkap beberapa elemen penting yaitu formulir pencarian dan elemen input kata kunci pencarian:
var $form = $('#ajax-search-form'), // Mendapatkan elemen formulir $input = $form.find(':text'); // Mendapatkan elemen input bertipe teks (penampung kata kunci pencarian)
Sisipkan sebuah elemen HTML secara tidak langsung sebagai kontainer hasil pencaran:
$form.append('<div id="search-result"></div>'); var $result_container = $('#search-result');
Setelah itu kita berlakukan event .submit() atau .on("submit") pada formulir untuk kemudian kita bisa langsung memproses data JSON yang akan ditransfer pada saat yang bersamaan ketika kita menekan tombol Enter pada papan ketik atau mengeklik tombol penelusuran di dalam formulir:
$form.on("submit", function() { $.ajax(url, type, dataType, success, error); // Dapatkan data dan proses data di sini... return false; // <= Ini digunakan untuk mencegah formulir membawa kita menuju halaman hasil penelusuran saat kita men-submit kata kunci pencarian });
Pengambilan data JSON dilakukan oleh JQuery $.ajax(), sehingga kita tidak perlu menyisipkan script callback ke dalam area <head> seperti dalam metode JavaScript mentah pada umumnya:
var $form = $('#ajax-search-form'), $input = $form.find(':text');
// Append a search result container to the search form $form.append('<div id="search-result"></div>'); var $result_container = $('#search-result');
// When the keyword is submitted... $form.on("submit", function() {
// Get the input value var keyword = $input.val();
// Show the search result container and insert a `Loading...` text $result_container.show().html('Loading...');
// Get the blog JSON via $.ajax() to show the search result // The URL format: http://blog_name.blogspot.com/feeds/posts/summary?alt=json-in-script&q={THE_KEYWORD}&max-results=9999 $.ajax({ url: 'http://nama_blog.blogspot.com/feeds/posts/summary?alt=json-in-script&q=' + keyword + '&max-results=9999', type: 'get', dataType: 'jsonp',
// If success, grab the search result list... success: function(json) { var entry = json.feed.entry, link, skeleton = ""; if (entry !== undefined) { skeleton = '<h4>Search results for keyword "' + keyword + '"</h4>'; skeleton += '<a class="close" href="/">×</a><ol>'; for (var i = 0; i < entry.length; i++) { for (var j = 0; j < entry[i].link.length; j++) { if (entry[i].link[j].rel == "alternate") { link = entry[i].link[j].href; } } skeleton += '<li><a href="' + link + '">' + entry[i].title.$t + '</a></li>'; } skeleton += '</ol>'; $result_container.html(skeleton); } else { // If the JSON is empty ... (entry === undefined) // Show the `not found` or `no result` message $result_container.html('<a class="close" href="/">×</a><strong>No result!</strong>'); } }, error: function() {
// If error, show an error message $result_container.html('<a class="close" href="/">×</a><strong>Error loading feed.</strong>'); } }); return false; });
// Fade out the search result container if the close button is clicked $form.on("click", ".close", function() { $result_container.fadeOut(); return false; });
})(jQuery); </script>
Ganti kode yang Saya beri tanda dengan URL blog Anda kemudian klik Simpan Widget.
Ini adalah sebuah plugin awal yang menjadi dasar dari JQuery Masonry. Plugin ini ditulis oleh Desandro di dalam gist GitHub dan Saya pikir ini cukup bermanfaat untuk sekedar menata layout seperti halnya saat kita menggunakan plugin Masonry yang sesungguhnya (yang sudah disempurnakan). Jadi Saya mencatat ulang kodenya di sini.
Saya sudah mengeditnya sedikit untuk beberapa keperluan:
(function($) { // Finding min and max values in array Array.prototype.min = function() {return Math.min.apply({},this);}; Array.prototype.max = function() {return Math.max.apply({},this);}; $.fn.masonry = function() { this.each(function() { var wall = $(this); if (wall.children().length > 0) { // Check if the element has anything in it if (wall.children('.masonry-wrap').length === 0) { // checks if the `.masonry-wrap` div is already there wall.wrapInner('<div class="masonry-wrap"></div>'); } var m_w = wall.children('.masonry-wrap'), brick = m_w.children(), b_w = brick.outerWidth(true), c_c = Math.floor(m_w.width() / b_w), c_h = [], this_col, i; for (i = 0; i < c_c; i++) { c_h[i] = 0; } m_w.css('position', 'relative'); brick.css({ 'float':'none', 'position':'absolute', 'display':'block' }).each(function() { for (i = c_c - 1; i > -1; i--) { if (c_h[i] == c_h.min()) { this_col = i; } } $(this).css({ 'top':c_h[this_col], 'left':b_w * this_col }); c_h[this_col] += $(this).outerHeight(true); }); m_w.height(c_h.max()).parent().addClass('start-transition'); } return this; }); }; })(jQuery);
Penggunaan
Sebenarnya plugin ini cukup diterapkan dengan cara seperti ini:
$('#container').masonry();
Tapi Saya sarankan untuk memicu plugin ini di dalam event .resize():
Saat kita mengetik tulisan di dalam <textarea>, kita tidak bisa menekan tombol tab untuk menyisipkan karakter tab karena saat kita melakukan itu, fokus kursor akan berpindah ke item formulir lain begitu saja. JavaScript ini bisa digunakan untuk menonaktifkan perpindahan formulir instan menggunakan tombol tab dan akan mengizinkan pengguna untuk menyisipkan karakter tab di dalam <textarea> dengan sekali tekan tombol tab:
function enableTab(id) { var el = document.getElementById(id); el.onkeydown = function(e) { if (e.keyCode === 9) { // tab was pressed
// get caret position/selection var val = this.value, start = this.selectionStart, end = this.selectionEnd;
// set textarea value to: text before caret + tab + text after caret this.value = val.substring(0, start) + '\t' + val.substring(end);
// put caret at right position again this.selectionStart = this.selectionEnd = start + 1;
Sebuah kumpulan data dalam daftar akan menampilkan indikator sedang memuat dan akan memulai pemuatan data baru saat jarak gulungan telah mencapai titik maksimal
Metode ini masih sama dengan metode-metode penundaan pemuatan JSON yang biasa Saya lakukan untuk widget-widget Saya yaitu dengan cara menyisipkan script callback secara tidak langsung ke dalam area <head> dengan ID tertentu. Kemudian, jika Saya ingin memperbaharui muatan JSON yang sudah ada, Saya tinggal menyingkirkan script callback yang lama kemudian menggantinya dengan duplikat baru dengan parameter yang sudah diperbaharui.
Bayangkan saja bahwa sudah terdapat sebuah script callback dengan ID foo di dalam area <head> seperti ini:
Kemudian Saya akan menyingkirkannya dengan cara menangkap ID elemen tersebut sebagai awalan untuk menyeleksi node induknya:
var a = document.getElementById('foo'); var parent = a.parentNode; // Mendapatkan elemen induk dari `foo`
Kemudian, dari induk tersebut Saya akan menyingkirkan elemen itu sendiri:
var a = document.getElementById('foo'); var parent = a.parentNode; // Mendapatkan elemen induk dari `foo` parent.removeChild(a); // Singkirkan `foo` dari `parent`
Di sini, kita akan melakukan pekerjaan di atas berdasarkan event onscroll dengan batasan akhir berupa jarak gulungan maksimal kontainer. Kode di bawah ini akan menjalankan fungsi bernama myFunction() berdasarkan event onscroll dengan syarat jarak gulungan telah mencapai titk maksimal:
Elemen #result-container digunakan sebagai area scroll, elemen ol digunakan sebagai kontainer data yang nantinya akan dihasilkan dari JSON, dan elemen span.loading digunakan sebagai indikator sedang memuat.
Membangun JavaScript
Pertama-tama kita buat script untuk memparse data JSON menjadi elemen HTML. Sederhana, seperti script recent post biasa yang Saya beri nama grabList(), dan hanya akan menghasilkan elemen <li> dengan tautan dan judul posting di dalamnya:
var elem = document.getElementById('result-container'), // Mendapatkan elemen `#result-container` inner = elem.getElementsByTagName('ol')[0], // Mendapatkan elemen `ol` pertama loading = elem.getElementsByTagName('span')[0]; // Mendapatkan elemen `span` pertama (dalam hal ini adalah elemen indikator sedang memuat)
// Bangun sebuah script untuk menampilkan daftar posting function grabList(json) {
var list = json.feed.entry, link, skeleton = "";
// Jalankan loop hanya jika data JSON masih ada/dapat didefinisikan if (list !== undefined) { for (var i = 0; i < list.length; i++) { for (var j = 0; j < list[i].link.length; j++) { if (list[i].link[j].rel == "alternate") { link = list[i].link[j].href; // Mendapatkan URL posting } }
// Bangun beberapa elemen `<li>` yang berisi tautan dan judul posting... skeleton += '<li><a href="' + link + '">' + list[i].title.$t + '</a></li>';
}
// ... kemudian sisipkan elemen tersebut ke dalam elemen `<ol>` inner.innerHTML += skeleton;
// dan sembunyikan indikator sedang memuat. loading.style.display = "none";
} else {
// Jika data JSON sudah tidak ada (list == undefined), tambahkan kelas baru kepada elemen indikator sedang memuat dengan nilai `the-end` loading.className += ' the-end';
// kemudian ganti teks indikator sedang memuat dengan kata `Habis` loading.textContent = 'Habis';
} }
Setelah itu buat sebuah fungsi untuk memuat script callback secara tidak langsung. Tambahkan dua buah parameter untuk menangani start-index dan max-results:
function updateScript(i, max) { var head = document.getElementsByTagName('head')[0], script = document.createElement('script'); script.type = 'text/javascript'; script.id = 'load-on-scroll-end'; script.src = 'http://nama_blog.blogspot.com/feeds/posts/summary?alt=json-in-script&start-index=' + i + '&max-results=' + max + '&callback=grabList'; head.appendChild(script); }
// Jalankan fungsi! updateScript(1, 25);
Fungsi di atas akan menyisipkan sebuah script callback JSON Blogger dengan nilai parameter start-index berupa 1 dan max-results berupa 25, sehingga sebuah elemen <script> dengan parameter yang sudah diatur akan disipkan ke dalam area <head> secara tidak langsung seperti ini:
Memperbaharui JSON Berdasarkan Jarak Maksimal Gulungan Area
Setelah itu kita tambahkan sebuah kondisional untuk menyingkirkan script callback lama jika script tersebut ada. Tidak perlu membuat fungsi baru, cukup gunakan fungsi tadi agar kita bisa menggunakannya untuk dua hal sekaligus, yaitu menyisipkan script baru dan/atau menyingkirkan script lama (jika ada):
function updateScript(i, max) { var head = document.getElementsByTagName('head')[0], script = document.createElement('script'); script.type = 'text/javascript'; script.id = 'load-on-scroll-end'; script.src = 'http://nama_blog.blogspot.com/feeds/posts/summary?alt=json-in-script&start-index=' + i + '&max-results=' + max + '&callback=grabList'; if (document.getElementById('load-on-scroll-end')) { var oldScript = document.getElementById('load-on-scroll-end'); oldScript.parentNode.removeScript(oldScript); } head.appendChild(script); }
updateScript(1, 25); // Jalankan fungsi!
Karena kita juga akan menjalankan fungsi updateScript() berdasarkan event onscroll, maka kita juga harus memasukkan updateScript() ke dalam event yang Saya tuliskan pertama kali:
elem.onscroll = function() { if ((this.scrollTop + this.offsetHeight) == inner.offsetHeight) { // Muat ulang JSON Blogger dengan `start-index` yang baru melalui parameter `i` updateScript(i, 25); // Kemudian tampilkan indikator sedang memuat loading.style.display = "block"; } };
Parameter i haru dinamis, dan harus bisa bertambah setiap kali gulungan kontainer berakhir. Untuk membuatnya menjadi dinamis, kita akan menggunakan variabel awalan dengan nilai 0, kemudian kita tingkatkan nilainya di dalam event onscroll setiap kali jarak gulungan telah mencapai titik maksimal:
var start = 0; elem.onscroll = function() { if ((this.scrollTop + this.offsetHeight) == inner.offsetHeight) {
// Tingkatkan nilai `start` dengan 1 (dari `start = 0` menjadi `start = 1`, `start = 2`, dst...) start++;
// Muat ulang JSON Blogger dengan `start-index` yang telah diperbaharui... // ... melalui `start` yang nilainya dikalikan dengan 25 updateScript(start*25, 25); // => dari `(1, 25)` menjadi `(25, 25)`, `(50, 25)`, `(75, 25)`, dst...
// Kemudian tampilkan indikator sedang memuat loading.style.display = "block";
var widget_config = { home_page: 'http://nama_blog.blogspot.com', // Your blog homepage container_id: 'result-container', // ID of the result container script_id: 'load-on-scroll-end-script', // ID of the asynchronous script max_result: 25, // Max result post at once script loading end_text: 'Habis' // End text if all posts has been loaded };
var elem = document.getElementById(widget_config.container_id), inner = elem.getElementsByTagName('ol')[0], loading = elem.getElementsByTagName('span')[0], start = 0, // Dynamic start-index max = widget_config.max_result;
function grabList(json) { var list = json.feed.entry, link, skeleton = ""; if (list !== undefined) { for (var i = 0; i < list.length; i++) { for (var j = 0; j < list[i].link.length; j++) { if (list[i].link[j].rel == "alternate") { link = list[i].link[j].href; } } skeleton += '<li><a href="' + link + '">' + list[i].title.$t + '</a></li>'; } inner.innerHTML += skeleton; // Insert the list to the container loading.style.display = "none"; // Hide the loading indicator } else { // If the JSON is empty (list == undefined), // add a new class to the loading indicator called `the-end` loading.className += ' the-end'; // Replace the loading indicator text into `fully loaded!` for the example loading.textContent = widget_config.end_text; } }
// Make an indirect script loader with two parameters: start-index and max-result post function updateScript(a, b) { var head = document.getElementsByTagName('head')[0], script = document.createElement('script'); script.type = 'text/javascript'; script.id = widget_config.script_id; script.src = widget_config.home_page + '/feeds/posts/summary?alt=json-in-script&start-index=' + a + '&max-results=' + b + '&callback=grabList'; // If there is an old script in the document... if (document.getElementById(widget_config.script_id)) { var oldScript = document.getElementById(widget_config.script_id); // Remove the old script, and replace with the new one that has an updated start-index value oldScript.parentNode.removeChild(oldScript); } head.appendChild(script); }
// Start loading the callback script with start-index of 1 updateScript(1, max);
// When the container is being scrolled... elem.onscroll = function() { // ... check the scroll distance if ((this.scrollTop + this.offsetHeight) == inner.offsetHeight) { // If the distance equal to the height of the inner container... start++; // Increase the start value by one // then load the new script with an updated start-index updateScript(start*max, max); // and show the loading indicator loading.style.display = "block"; } };
Kode ini digunakan untuk mengecek apakah pengguna telah mencapai bagian akhir halaman atau tidak saat mereka sedang menggulung layar. Jika ya, lakukan sesuatu:
JavaScript
window.onscroll = function() { if (navigator.userAgent.toLowerCase().indexOf("chrome") > -1 || navigator.userAgent.toLowerCase().indexOf("safari") > -1) { if (document.documentElement.scrollHeight == (document.body.scrollTop + document.documentElement.clientHeight)) { alert("End of the page!"); // for demonstration } } else { if (document.documentElement.scrollHeight == (document.documentElement.scrollTop + document.documentElement.clientHeight)) { alert("End of the page!"); // for demonstration } } };
Demo
Catatan: Deklarasi <!DOCTYPE html> pada dokumen HTML harus dinyatakan.
Pembaharuan 22 April 2013: Mengintegrasikan widget dengan cookies, menambahkan opsi summary dan menyingkirkan opsi tt_id.
Widget ini bukan widget recent comment biasa yang biasanya Anda temukan di blog-blog lain, karena widget ini memiliki kemampuan untuk memberitahu kepada administrator bahwa terdapat komentar baru yang telah masuk.
Demonya bisa Anda lihat di sini, namun efeknya hanya akan terlihat apabila terdapat (paling tidak) satu komentar baru yang masuk di blog ini:
Ganti kode yang Saya beri tanda dengan URL blog Anda kemudian klik Simpan. Hasil maksimal akan terlihat saat terdapat komentar baru yang masuk.
Konfigurasi Widget Lanjutan
Ada beberapa hal yang harus Anda ketahui mengenai konfigurasi lanjutan widget ini:
Opsi
Keterangan
home_page
Ganti nilainya dengan URL halaman muka blog Anda
max_result
Digunakan untuk menentukan jumlah komentar yang akan ditampilkan pada widget ini
t_w
Digunakan untuk menentukan lebar avatar
t_h
Digunakan untuk menentukan tinggi avatar
summary
Digunakan untuk menentukan jumlah karakter komentar yang ditampilkan
new_tab_link
Jika bernilai true, seluruh tautan yang ada di dalam widget ini akan terbuka di tab/jendela baru saat diklik
tt_id
ID kontainer total komentar (abaikan jika tidak perlu)
ct_id
ID kontainer daftar komentar (abaikan jika tidak perlu)
new_cm
Label teks yang akan muncul setelah jumlah komentar (Misalnya: 2 Komentar Baru!)
interval
Lihat deskripsi di bawah
alert
Lihat deskripsi di bawah
Opsi: interval
Digunakan untuk menentukan interval penyegaran feed komentar. Menggunakan satuan milidetik. Nilai 30000 artinya bahwa feed komentar akan disegarkan selama setengah menit sekali untuk memeriksa apakah terdapat komentar baru yang masuk atau tudak. Jika terdapat komentar baru yang masuk, maka widget ini akan menampilkan pesan bahwa komentar baru telah masuk.
Opsi: alert
Ini cuma opsi untuk menentukan gaya pemberitahuan pesan. Jika bernilai false, widget ini akan menampilkan pesan masuknya komentar baru pada title bar peramban seperti gambar 1. Sebaliknya, jika bernilai true, notifikasi akan muncul pada kotak peringatan seperti terlihat pada gambar 2:
Model Notifikasi 1: alert: falseModel Notifikasi 2: alert: true
Pembaharuan
Sekarang Anda bisa menampilkan teks notifikasi pada elemen HTML tertentu dengan cara mengubah nilai opsi alert menjadi sebuah fungsi seperti ini:
var cm_config = { ... alert: function(total, label) { // Lakukan sesuatu dengan `total` dan `label` } };
total berfungsi untuk menampilkan total komentar baru, sedangkan label berfungsi untuk menampilkan nilai pada opsi new_cm. Sebagai contoh, buat sebuah elemen HTML seperti ini. Elemen ini akan digunakan sebagai penampil/kontainer teks total komentar:
<div id="show-total"></div>
Setelah itu, sisipkan teks total komentar ke dalam elemen tersebut dengan JavaScript innerHTML melalui fungsi di atas:
Sebuah seksi merupakan elemen <b:section>, sedangkan widget adalah elemen <b:widget>. <b:widget> harus berada di dalam <b:section>, dan <b:section> harus berada di dalam tag <body>
<b:section> dan <b:widget> selalu dilengkapi oleh beberapa atribut. Beberapa merupakan atribut wajib dan beberapa merupakan pilihan. Namun, untuk mengaktifkan sebuah <b:section>, minimal kita hanya membutuhkan atribut id dengan nilai yang spesifik:
<b:section id='widget-area'/>
Elemen di atas nantinya akan ditampilkan sebagai bagian terpenting dalam halaman Tata Letak, yaitu berupa tab pengeditan, penambahan & penghapusan widget seperti ini:
Contoh tampilan <b:section> di halaman Tata Letak
Dan saat ditampilkan sebagai elemen HTML, <b:section> akan tampil sebagai elemen ini:
<div class='section' id='widget-area'></div>
Daftar Atribut yang Biasa Muncul di dalam Elemen <b:section>
Atribut
Nilai/Contoh Nilai
Keterangan
id
section-1
Atribut wajib. Seperti ID dalam elemen HTML. Berupa huruf atau angka, dan harus spesifik.
class
header
Atribut opsional. Seperti kelas dalam elemen HTML. Tidak harus spesifik. Kelas-kelas standar dalam sebuah template blogspot adalah navbar, header, main, sidebar dan footer. Kelas-kelas standar tersebut sangat berguna bagi Blogger untuk mempermudah dalam menentukan tipe widget yang sesuai yang biasanya akan disisipkan/ditata ulang secara otomatis saat Anda mengunggah/mengganti template.
maxwidgets
1
Atribut opsional. Berupa jumlah. Atribut ini berguna untuk menentukan seberapa banyak widget yang bisa ditambahkan pada seksi terkait. Anda biasanya akan melihat atribut ini pada seksi header berupa maxwidgets='1', yang akan membatasi penambahan widget sebanyak satu buah. Setelah sebuah elemen halaman ditambahkan, elemen halaman baru tidak diizinkan untuk masuk ke dalam seksi tersebut. Ciri khususnya adalah, sebuah tombol penambahan widget akan tampil saat seksi tersebut masih mengandung jumlah widget kurang dari nilai maksimal, dan akan menghilang saat jumlahnya telah mencapai nilai maksimal.
showaddelement
yes (default)
Atribut opsional. Jika bernilai yes, tombol penambahan widget akan ditampilkan. Jika bernilai no, tombol penambahan widget akan menghilang (pemilik blog tidak diizinkan untuk menambahkan elemen halaman).
no
growth
vertical (default)
Atribut opsional. Digunakan untuk menentukan apakah widget-widget halaman akan disusun secara menyamping atau bertumpukan.
horizontal
Sebuah <b:widget> merupakan bagian dari <b:section> dan memiliki beberapa atribut wajib, yang akan terisi secara otomatis saat kita menambahkan elemen halaman/widget baru:
Daftar Atribut yang Biasa Muncul di dalam Elemen <b:widget>
Atribut
Nilai/Contoh Nilai
Keterangan
id
BlogArchive1
Atribut wajib. Seperti ID dalam elemen HTML. Berupa huruf atau angka, dan harus spesifik.
type
BlogArchive
Atribut wajib. Nilai terdaftar[1] dan tidak bisa ditentukan sesuka hati. Digunakan untuk menentukan tipe widget.
locked
true
Atribut opsional. Digunakan untuk menentukan apakah widget bisa digeser-geser (diatur ulang susunannya) dan dihapus atau tidak. Ciri khusus tampak pada bagian bilah di samping item widget seperti ini
false
title
Blog Archive
Atribut opsional. Digunakan untuk menentukan judul widget.
pageType
all
Atribut opsional. Digunakan untuk membuat widget tampil pada halaman spesifik (???)
archive
main
item
mobile
yes
Atribut opsional. Jika yes, widget akan ditampilkan saat berada pada tampilan blog mobile. Jika no, widget tidak akan tampil saat berada pada tampilan blog mobile. Jika only, widget akan ditampilkan hanya pada tampilan blog mobile.