Performa Widget Random Post

Saya harus mengatakan bahwa widget random post itu sangat buruk dalam hal performa. Kerja mereka sangat lambat dan membuang-buang tenaga, karena mereka bekerja dengan cara memanggil feed posting berukuran sangat besar! Kemudian mereka hanya akan menampilkannya sebagian saja secara acak:

<script src='/feeds/posts/default?alt=json-in-script&max-results=99999&callback=randomPosts'></script>

Bagi Anda para pemakai mungkin tidak pernah tahu mengenai ini, tetapi sebenarnya setiap pemakai widget random post —termasuk juga — tanpa sadar telah menerima beban begitu besar. Ketika Anda membuka halaman tunggal dimana terdapat widget random post di dalamnya, pada saat yang bersamaan Anda juga sebenarnya sedang membuka semua posting yang telah Anda terbitkan dalam satu waktu. Mengapa? Karena parameter max-results pada feed menunjukkan angka 99999 yang artinya bahwa semua feed posting akan “diusahakan” untuk dipanggil (diusahakan, karena jumlah posting yang kita terbitkan tidak mungkin mencapai angka sebesar itu).

Mengacak Indeks Permulaan

Saya menyadari terdapat sebuah peluang untuk menciptakan widget random post yang lebih ringan dan cepat dimuat. Dibandingkan memuat semua posting dan memilah beberapa posting secara acak untuk ditampilkan, akan lebih baik jika kita mengacak nilai start-index pada feed sehingga posting yang dimuat bisa dimulai dari urutan sembarang:

function randomPosts(json) {
// Ubah JSON menjadi HTML...
}

var startIndex = Math.round(Math.random() * 9999); // Membuat angka acak
document.write('<scr' + 'ipt src="/feeds/posts/summary?alt=json-in-script&start-index=' + startIndex + '&max-results=7&callback=randomPosts"></scr' + 'ipt>');

Ada satu masalah kecil yang mungkin akan mengganggu. Jika angka acak yang tercipta nilainya lebih besar dari total posting blog Anda saat ini, maka widget random post ini tidak akan bekerja. Oleh karena itu kita harus membatasi angka acak yang tercipta, yaitu tidak boleh kurang dari 1 dan tidak boleh lebih dari “total posting dikurangi jumlah posting yang ingin ditampilkan”.

Untuk mendapatkan jumlah posting secara keseluruhan kita bisa mengambilnya melalui objek json.feed.openSearch$totalResults.$t:

// Konfigurasi
var homePage = 'http://nama_blog.blogspot.com',
maxResults = 7;

// Fungsi untuk menggenerasikan angka acak dengan batasan minimal dan maksimal
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

// Mendapatkan indeks pemulai yang aman untuk memanggil feed utama
function createRandomPostsStartIndex(json) {
// Buat angka acak dengan nilai tidak boleh kurang dari `1` dan tidak boleh lebih dari `total posting - posting yang ingin ditampilkan`
var startIndex = getRandomInt(1, (json.feed.openSearch$totalResults.$t - maxResults));
// Tampilkan pesan log
console.log('Get the post feed start from ' + startIndex + ' until ' + (startIndex + maxResults));
}

document.write('<scr' + 'ipt src="' + homePage + '/feeds/posts/summary?alt=json-in-script&max-results=0&callback=createRandomPostsStartIndex"></scr' + 'ipt>');

Muat ulang widget Anda berkali-kali. Seharusnya Anda akan melihat pesan log indeks pemanggilan posting yang berubah-ubah seperti ini:

Showing log message to indicate random number for feed start index purpose
Angka acak yang Saya tandai akan kita manfaatkan untuk memanggil indeks feed secara acak.

Kita akan menggunakan angka acak itu sebagai angka pemulai pada parameter start-index seperti ini:

function createRandomPostsStartIndex(json) {
var startIndex = getRandomInt(1, (json.feed.openSearch$totalResults.$t - maxResults));
document.write('<scr' + 'ipt src="' + homePage + '/feeds/posts/summary?alt=json-in-script&orderby=updated&start-index=' + startIndex + '&max-results=' + maxResults + '&callback=randomPosts"></scr' + 'ipt>');
}

Pada bagian akhir URL feed terdapat parameter callback=randomPosts. randomPosts di sini merupakan fungsi utama yang akan kita buat untuk mengubah JSON Blogger menjadi widget:

function randomPosts(json) {
var link, ct = document.getElementById('random-post-container'),
entry = json.feed.entry,
skeleton = "<ul>";
for (var i = 0, len = entry.length; i < len; i++) {
for (var j = 0, jen = entry[i].link.length; j < jen; j++) {
link = (entry[i].link[j].rel == "alternate") ? entry[i].link[j].href : '#';
}
skeleton += '<li><a href="' + link + '">' + entry[i].title.$t + '</a></li>';
}
ct.innerHTML = skeleton + '</ul>';
}

Sentuhan akhir, acak urutan posting yang ditampilkan menggunakan fungsi ini sehingga daftar posting yang ditampilkan nantinya akan semakin acak urutannya:

// Fungsi untuk mengacak array
function shuffleArray(arr) {
var i = arr.length, j, temp;
if (i === 0) return false;
while (--i) {
j = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
}

// Widget
function randomPosts(json) {
var link, ct = document.getElementById('random-post-container'),
entry = shuffleArray(json.feed.entry),
skeleton = "<ul>";
for (var i = 0, len = entry.length; i < len; i++) {
for (var j = 0, jen = entry[i].link.length; j < jen; j++) {
link = (entry[i].link[j].rel == "alternate") ? entry[i].link[j].href : '#';
}
skeleton += '<li><a href="' + link + '">' + entry[i].title.$t + '</a></li>';
}
ct.innerHTML = skeleton + '</ul>';
}

Hasil Akhir

<div id='random-post-container'>Memuat...</div>

<script>
//<![CDATA[
// Feed configuration
var homePage = 'http://nama_blog.blogspot.com',
maxResults = 7,
containerId = 'random-post-container';
// Function to generate random number limited from `min` to `max`
// Used to create a valid and safe random feed `start-index`
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Function to shuffle arrays
// Used to randomize order of the generated JSON feed
function shuffleArray(arr) {
var i = arr.length, j, temp;
if (i === 0) return false;
while (--i) {
j = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
}
// Get a random start index
function createRandomPostsStartIndex(json) {
var startIndex = getRandomInt(1, (json.feed.openSearch$totalResults.$t - maxResults));
// console.log('Get the post feed start from ' + startIndex + ' until ' + (startIndex + maxResults));
document.write('<scr' + 'ipt src="' + homePage + '/feeds/posts/summary?alt=json-in-script&orderby=updated&start-index=' + startIndex + '&max-results=' + maxResults + '&callback=randomPosts"></scr' + 'ipt>');
}
// Widget's main function
function randomPosts(json) {
var link, ct = document.getElementById(containerId),
entry = shuffleArray(json.feed.entry),
skeleton = "<ul>";
for (var i = 0, len = entry.length; i < len; i++) {
for (var j = 0, jen = entry[i].link.length; j < jen; j++) {
link = (entry[i].link[j].rel == "alternate") ? entry[i].link[j].href : '#';
}
skeleton += '<li><a href="' + link + '">' + entry[i].title.$t + '</a></li>';
}
ct.innerHTML = skeleton + '</ul>';
}
document.write('<scr' + 'ipt src="' + homePage + '/feeds/posts/summary?alt=json-in-script&max-results=0&callback=createRandomPostsStartIndex"></scr' + 'ipt>');
//]]>
</script>

Ketika Posting Acak Dikirim Secara Langsung oleh Server

Dalam sebuah forum Saya pernah menemukan seseorang yang mencoba menyarankan Blogger untuk menyertakakan parameter orderby baru berupa random dan popular. Saya pikir ini adalah ide yang bagus. Karena berdasarkan dokumentasi, kalau tidak salah hanya ada dua macam nilai untuk parameter orderby, yaitu published dan updated:

http://nama_blog.blogspot.com/feeds/posts/summary?orderby=published
http://nama_blog.blogspot.com/feeds/posts/summary?orderby=updated

Jika suatu saat Blogger merealisasikan masukan dari pengguna ini, maka kita tidak perlu lagi menerapkan hack semacam ini. Cukup dengan membuat widget recent post biasa, kita bisa mengubah parameter URL feed dari orderby=published menjadi orderby=random untuk menciptakan widget random post. Tapi kasus ini masih dalam tahap “seandainya”.

Widget Blogger untuk Menampilkan Daftar Posting Terbaru dalam Label-Label yang Spesifik

Screenshot of multiple recent post widget for Blogger.

Judulnya sangat panjang karena Saya sendiri tidak tahu harus memberi nama apa kepada widget ini. Pada intinya widget ini adalah widget recent post biasa, namun memiliki kemampuan untuk menggandakan diri agar bisa menampilkan daftar posting terbaru lebih dari satu buah berdasarkan label yang spesifik:

Pada awalnya Saya membuat widget ini agar bisa menampilkan posting-posting terbaru dari blog tunggal saja, namun mengingat ada juga beberapa blog yang suka menampilkan daftar posting dari blog lain, jadi sekarang widget ini tidak hanya berfungsi untuk menampilkan daftar posting dari satu feed blog, melainkan juga bisa menampilkan daftar posting dari feed blog Blogger yang lain.

Pemasangan Widget

Masuk ke halaman Tata Letak kemudian tambahkan sebuah widget HTML/JavaScript. Salin kode ini dan letakkan di dalam formulirnya:

<link rel="stylesheet" type="text/css" scoped="scoped" href="http://blogger-json-experiment.googlecode.com/svn/resources/multi-feed/multi-feed.min.css"/>
<style type="text/css" scoped="scoped">
/* Custom CSS */
.list-entries {
margin:5px;
width:270px; /* Lebar widget */
float:left;
font-size:11px;
}
</style>

<div id="feed-list-container"></div>
<div style="clear:both;"></div>

<script type="text/javascript">
var multiFeed = {
feedsUri: [
{
name: "Judul Widget 1",
url: "http://nama_blog-1.blogspot.com",
tag: "JQuery"
},
{
name: "Judul Widget 2",
url: "http://nama_blog-2.blogspot.com",
tag: "CSS"
},
{
name: "Judul Widget 1",
url: "http://nama_blog-3.blogspot.com",
tag: "Widget"
}
],
numPost: 4,
showThumbnail: true,
showSummary: true,
summaryLength: 80,
titleLength: "auto",
thumbSize: 72,
containerId: "feed-list-container",
readMore: {
text: "Selengkapnya",
endParam: "?max-results=20"
}
};
</script>
<script type="text/javascript" src="http://blogger-json-experiment.googlecode.com/svn/resources/multi-feed/multi-feed.min.js"></script>

Konfigurasi

OpsiKeterangan
feedsUriBerupa array objek dimana di dalamnya terdapat beberapa data berupa name, url dan tag: name digunakan untuk menentukan judul widget, url digunakan untuk menentukan URL feed, tag digunakan untuk menentukan tag/label posting yang ingin ditampilkan.
numPostDigunakan untuk menentukan jumlah posting yang ingin ditampilkan
showThumbnailGanti nilainya menjadi false untuk menyembunyikan gambar posting
showSummaryGanti nilainya menjadi false untuk menyembunyikan ringkasan posting
summaryLengthDigunakan untuk menentukan jumlah karakter ringkasan posting
titleLengthDigunakan untuk memotong karakter judul posting yang terlalu panjang. Ganti nilainya menjadi angka untuk memotong karakter sebanyak angka tersebut, atau set sebagai "auto" untuk membiarkan judul posting sebagai apa adanya
thumbSizeDigunakan untuk menentukan ukuran thumbnail posting
containerIdDigunakan untuk menentukan ID kontainer yang akan digunakan untuk memuat widget
readMoreTerdiri dari text dan endParam. text digunakan untuk menentukan label tautan “Baca Selengkapnya” yang terletak di bawah masing-masing widget dan endParam digunakan untuk menentukan parameter akhir tautan tersebut (abaikan jika tidak perlu).

Opsi feedsUri merupakan array objek dimana setiap objek akan mewakili masing-masing widget:

// Tiga objek = tiga widget
feedsUri: [{}, {}, {}]

Setiap objek berisi beberapa data yang digunakan untuk menentukan judul widget, sumber URL dan tag/kategori posting spesifik:

feedsUri: [
{
name: "Judul Widget 1",
url: "http://nama_blog-1.blogspot.com",
tag: "Blogger"
},
{
name: "Judul Widget 2",
url: "http://nama_blog-2.blogspot.com",
tag: "WordPress"
},
{
name: "Judul Widget 3",
url: "http://nama_blog-3.blogspot.com",
tag: "SEO"
}
]

Setelah semua konfigurasi sudah diatur dengan benar, klik Simpan Widget. Modifikasi tampilan bisa dilakukan di dalam tag <style> yang Saya tambahkan pada widget di atas.

Kode Sumber

  1. multi-feed.css
  2. multi-feed.min.css
  3. multi-feed.js
  4. multi-feed.min.js

Plugin Feed Rotator untuk Blogger

Image of Blogger Feed Rotator plugin demo

Plugin ini pada dasarnya merupakan perpaduan antara Basic JQuery Image Rotator dengan yang kemudian Saya jadikan sebagai semacam slideshow dengan konten yang akan diperbaharui secara otomatis berdasarkan posting yang sudah terbit. Saya memutuskan untuk membuat ini karena ada beberapa orang yang menanyakan melalui email mengenai bagaimana cara memadukan plugin Image Rotator dengan JSON Blogger.

Plugin JQuery Image Rotator ini juga sudah dimodifikasi hampir secara keseluruhan, khusus untuk diaplikasikan pada widget ini. Beberapa hal yang Saya tambahkan diantaranya adalah navigasi, efek animasi kontainer dan dukungan fungsi callback yang dapat dijalankan pada sesi-sesi tertentu.

Implementasi Dasar

Berikut ini adalah contoh implementasi paling mendasar yang bisa Anda lakukan untuk mengaktifkan plugin:

<link rel="stylesheet" type="text/css" href="http://blogger-json-experiment.googlecode.com/svn/resources/blogger-feed-rotator-plugin/default-style.min.css"/>
<div id="slider-rotator" class="slider-rotator loading"></div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="http://blogger-json-experiment.googlecode.com/svn/resources/blogger-feed-rotator-plugin/blogger-feed-rotator.min.js"></script>
<script type="text/javascript">
makeSlider({
url: "http://nama_blog.blogspot.com" // URL blog Anda
});
</script>

Susun file CSS dan plugin Blogger Feed Rotator sesuai dengan urutan yang Saya perlihatkan di atas. Tambahkan juga elemen HTML yang berfungsi untuk menampilkan slideshow sebelum plugin. Setelah itu aktifkan fungsi makeSlider() dengan parameter berupa objek tunggal url yang diisi dengan URL blog Anda. Salin dan tempelkan di dalam formulir elemen halaman HTML/JavaScript. Dengan ini maka Anda sudah bisa menampilkan sebuah slideshow sederhana seperti yang terlihat pada halaman demo di atas.

Daftar Opsi Konfigurasi Dasar

Konfigurasi dasar Saya batasi pada opsi-opsi yang berhubungan dengan pengaturan posting:

{
url: "http://www.dte.web.id", // Your blog URL
numPost: 5, // Number of posts to display
newTabLink: false, // `true` to automatically open link in new window tab
labelName: null, // Show posts in specific label. Specify name of the post label, or `null` to show all posts
showDetail: true, // `false` to hide the blog post title & description
summaryLength: 60, // Length of post summary
titleLength: "auto", // Length of the post title. "auto" by default, or specify number to crop the post title characters and truncate it with `...`
showThumb: true, // `false` to hide the post thumbnails
thumbWidth: 250, // Width of post thumbnail in pixels
squareThumb: true, // Thumbnail mode: Square mode or use the scaled thumbnail with original width and height ratio
noThumb: "images/grey.png", // Fallback thumbnail for no picture posts
showNav: true, // `true` to show both next/prev navigation and navigation number, "next/prev" to show next/prev navigation only, "number" to show navigation number only, `false` to hide the navigation
navText: {
prev: "&lt;", // Label of the previous navigation
next: "&gt;" // Label of the next navigation
},
containerId: "slider-rotator" // HTML element ID that is used to display the slideshow/rotator
}
OpsiKeterangan
urlIsi dengan URL halaman muka blog Anda
numPostDigunakan untuk menentukan jumlah posting yang akan ditampilkan
newTabLinkUbah nilainya menjadi true untuk membuat tautan-tautan di dalam widget ini terbuka di jendela/tab baru saat diklik
labelNameDigunakan untuk menampilkan daftar posting dengan label/kategori tertentu. Nilai null berarti menampilkan semua posting terbaru. Ganti nilainya menjadi nama label untuk menampilkan posting dengan label tertentu. Misalnya labelName:"Foto" untuk menampilkan semua posting yang memiliki label Foto - Contoh
showDetailUbah nilainya menjadi false untuk menyembunyikan judul dan ringkasan posting. Berguna untuk membuat slideshow foto/gambar tanpa tulisan - Contoh
summaryLengthDigunakan untuk membatasi panjang ringkasan posting. Akhir pemotongan ringkasan posting akan digantikan dengan simbol “…”
titleLengthDigunakan untuk membatasi panjang judul posting. Secara normal bernilai "auto". Ubah nilainya dengan angka tertentu untuk memotong panjang judul jika Anda merasa judul posting yang tampil terlalu panjang. Akhir pemotongan judul posting akan digantikan dengan simbol “…”
showThumbUbah nilainya menjadi false untuk menyembunyikan gambar posting. Berguna untuk membuat slideshow teks - Contoh
thumbWidthDigunakan untuk menentukan lebar thumbnail posting dan juga sekaligus menentukan lebar slideshow
squareThumbOpsi untuk memilih mode thumbnail. true untuk menampilkan gambar dengan resolusi /sN-c, false untuk menampilkan gambar dengan resolusi /sN
noThumbIsi dengan URL gambar. Gambar ini akan digunakan sebagai cadangan jika posting yang tampil tidak memiliki gambar
showNavOpsi untuk menampilkan atau menyembunyikan navigasi slideshow. Ubah nilainya menjadi false untuk menyembunyikan navigasi. "number" untuk menampilkan navigasi angka saja. "next/prev" untuk menampilkan navigasi next/prev saja. true untuk menampilkan keduanya
navTextOpsi untuk menentukan label navigasi Next dan Previous
containerIdDigunakan untuk menentukan di mana slideshow akan ditampilkan. Isi dengan ID elemen HTML. Dan jangan lupa untuk menyertakan elemen HTML tersebut sebelum eksekusi plugin.

Pengaturan Animasi

Pengaturan animasi Saya batasi pada opsi-opsi yang berhubungan dengan animasi plugin:

{
interval: 6000, // Slideshow interval
speed: 1000, // Slideshow animation speed
hoverPause: true, // `false` to make the slideshow/rotator keep running on mouse-over
crossFade: false, // `true` if you want to make the slide change effect occurs simultaneously between disappearance and appearance
autoHeight: false, // Animate the rotator to adjust the height of the displayed item
autoSlide: true // `false` to run the slideshow manually (with navigation)
}
OpsiKeterangan
intervalDigunakan untuk menentukan rentang waktu perpindahan setiap item slide dalam satuan milidetik
speedDigunakan untuk menentukan kecepatan animasi dalam satuan milidetik
hoverPauseJika bernilai true maka slideshow akan berhenti bergerak saat pointer mouse berada di atasnya
crossFadeDigunakan untuk menentukan apakah efek penghilangan dan pemunculan slide dilakukan secara bergantian atau bersamaan dalam waktu yang sama tanpa ada jeda
autoHeightJika bernilai true, maka tinggi slideshow akan menyesuaikan diri berdasarkan tinggi item slide yang tampil dengan efek animasi - Contoh
autoSlideUbah nilainya menjadi false untuk membuat slideshow berjalan secara manual melalui aksi klik navigasi

Konfigurasi Lanjutan

Bagian ini Saya khususkan untuk menjelaskan fungsi-fungsi callback dan implementasi lanjutan, khususnya dalam hal modifikasi:

{
onInit: function() {}, // Callback function that will be executed when slideshow is starting
onHide: function(index) {}, // Callback function that will be executed when slideshow is start hiding the slide item
onShow: function(index) {} // Callback function that will be executed after the slideshow showing the slide item
}

onInit

Fungsi ini akan dijalankan pada saat pertama kali slideshow terbentuk. Saat slideshow tampil, maka fungsi ini akan langsung dieksekusi. Contoh penerapan:

makeSlider({
url: "http://nama_blog.blogspot.com",
onInit: function() {
alert('Slideshow ready!');
}
});

Kode di atas akan menampilkan pesan “Slideshow ready!” segera setelah slideshow tampil.

onHide

Fungsi ini akan dijalankan setiap kali item slide mulai menghilang. Saat item slide menghilang, maka fungsi ini akan tereksekusi. Contoh penerapan:

makeSlider({
url: "http://nama_blog.blogspot.com",
onHide: function() {
alert('Mengganti slide...');
}
});

Kode di atas akan menampilkan pesan “Mengganti slide...” setiap kali slide mulai berganti.

onShow

Fungsi ini akan dijalankan setiap kali item slide tampil. Saat item slide tampil, maka fungsi ini akan tereksekusi. Contoh penerapan:

makeSlider({
url: "http://nama_blog.blogspot.com",
onShow: function(index) {
alert('Slide ke ' + index + ' berhasil tampil.');
}
});

Kode di atas akan menampilkan pesan “Slide ke {nomor urut slide yang tampil} berhasil tampil.” setiap kali slide ditampilkan.

Parameter `index`

Parameter index hanya berlaku untuk onHide dan onShow. Parameter ini akan menampilkan indeks slide yang aktif:

makeSlider({
url: "http://nama_blog.blogspot.com",
onInit: function() {
console.log('Slideshow dimulai...');
},
onHide: function(index) {
console.log('Menyembunyikan slide ke ' + index);
},
onShow: function(index) {
console.log('Menampilkan slide ke ' + index);
}
});

Beberapa Contoh Modifikasi Dasar

Mengubah Tampilan

Dengan mengubah ukuran lebar pada gambar dan slideshow, ukuran tinggi pada slideshow dan mengubah tampilan deskripsi/detail posting sebagai caption, maka Anda bisa semakin memperkuat status plugin ini sebagai “slideshow”:

CSS

<link rel="stylesheet" type="text/css" href="http://blogger-json-experiment.googlecode.com/svn/resources/blogger-feed-rotator-plugin/default-style.min.css"/>
<style type="text/css">

/* Custom CSS... */

.slider-rotator {
width:600px;
height:240px;
padding:0 0;
background-color:white;
font:italic normal 12px/1.4 Georgia,Serif;
color:white;
border:1px solid black;
}

.slider-rotator .slider-item {
background-color:white;
height:240px; /* Same with `.slider-rotator` height */
padding:0 0;
}

.slider-rotator h4 {margin-top:0}
.slider-rotator p {margin:2px 0 0}

/* Slider details as caption */
.slider-rotator .detail-wrapper {
position:absolute;
top:auto;
right:0;
bottom:0;
left:0;
background-color:black;
background-color:rgba(0,0,0,.9);
padding:.5em 1em;
z-index:4;
}

</style>

JavaScript

makeSlider({
url: "http://nama_blog.blogspot.com", // Your blog URL
thumbWidth: 600 // Thumbnail width in pixels (same with slideshow width)
});

Memanfaatkan Fungsi Callback untuk Menganimasikan Caption

Dengan memanfaatkan parameter index pada onHide dan onShow, Anda bisa memberikan efek animasi pada caption slide yang aktif setiap kali slide berganti:

makeSlider({
url: "http://nama_blog.blogspot.com", // Your blog URL
thumbWidth: 600, // Thumbnail width in pixels (same with slideshow width)
containerId: "slider-rotator",
// Hide all captions on initiation...
onInit: function() {
$('#' + this.containerId).find('.detail-wrapper').hide();
},
// Hide the caption with `.slideUp()` effect when the slide item hides
onHide: function() {
$('#' + this.containerId).find('.detail-wrapper').slideUp();
},
// Show the caption with `.slideDown()` effect when the slide item appears
onShow: function(index) {
$('#' + this.containerId).children().eq(index).find('.detail-wrapper').slideDown();
}
});

Menampilkan Beberapa Slideshow Sekaligus

Karena eksekusi plugin ini dilakukan di luar, maka ini memungkinkan Anda untuk menampilkan beberapa slideshow sekaligus dalam satu halaman. Pertama-tama buatlah beberapa elemen HTML yang dibutuhkan untuk memuat slideshow:

<div id="container-1" class="slider-rotator loading"></div>
<div id="container-2" class="slider-rotator loading"></div>
<div id="container-3" class="slider-rotator loading"></div>

Kemudian jalankan fungsi makeSlider() sebanyak jumlah kontainer yang dibuat. Tentukan juga konfigurasi containerId yang berbeda-beda berdasarkan ID kontainer:

makeSlider({
url: "http://nama_blog-1.blogspot.com",
containerId: "container-1"
});
makeSlider({
url: "http://nama_blog-2.blogspot.com",
containerId: "container-2"
});
makeSlider({
url: "http://nama_blog-3.blogspot.com",
containerId: "container-3"
});

Mengatur Plugin dan Melihat Demo Secara Langsung

Saya sudah menyertakan halaman konfigurasi plugin yang bisa Anda gunakan untuk melakukan pengaturan dan melihat hasilnya secara langsung di sini:

Daftar Contoh

  1. Demo 1: Basic
  2. Demo 2: Show Posts under Category “Widget”
  3. Demo 3: About Thumbnails
  4. Demo 4: Thumbnail Only
  5. Demo 5: Text Only
  6. Demo 6: Multiple Feed Loading
  7. Demo 7: Casual Slideshow
  8. Demo 8: Example Callback Function to Animate the Slideshow Caption (1)
  9. Demo 9: Example Callback Function to Animate the Slideshow Caption (2)

Modifikasi Widget Posting Populer Menjadi Berwarna-Warni

Widget Posting Populer yang Sudah Dimodifikasi

Pada konfigurasi widget Posting Populer, pastikan bahwa Anda memilih model widget berupa thumbnail dan judul. Setelah itu masuk ke editor HTML template. Salin kode CSS ini dan letakkan di atas kode ]]></b:skin> atau </style>:

/* Custom CSS for Blogger Popular Post Widget */
.PopularPosts ul,
.PopularPosts li,
.PopularPosts li img,
.PopularPosts li a,
.PopularPosts li a img {
margin:0 0;
padding:0 0;
list-style:none;
border:none;
background:none;
outline:none;
}

.PopularPosts ul {
margin:.5em 0;
list-style:none;
font:normal normal 13px/1.4 "Arial Narrow",Arial,Sans-Serif;
color:black;
counter-reset:num;
}

.PopularPosts ul li img {
display:block;
margin:0 .5em 0 0;
width:50px;
height:50px;
float:left;
}

.PopularPosts ul li {
background-color:#eee;
margin:0 10% .4em 0;
padding:.5em 1.5em .5em .5em;
counter-increment:num;
position:relative;
}

.PopularPosts ul li:before,
.PopularPosts ul li .item-title a {
font-weight:bold;
font-size:120%;
color:inherit;
text-decoration:none;
}

.PopularPosts ul li:before {
content:counter(num);
display:block;
position:absolute;
background-color:black;
color:white;
width:30px;
height:30px;
line-height:30px;
text-align:center;
top:50%;
right:-10px;
margin-top:-15px;
-webkit-border-radius:30px;
-moz-border-radius:30px;
border-radius:30px;
}

/* Set color & level */
.PopularPosts ul li:nth-child(1) {background-color:#E11E28;margin-right:1%}
.PopularPosts ul li:nth-child(2) {background-color:#FD3C03;margin-right:2%}
.PopularPosts ul li:nth-child(3) {background-color:#FECB09;margin-right:3%}
.PopularPosts ul li:nth-child(4) {background-color:#6EBE27;margin-right:4%}
.PopularPosts ul li:nth-child(5) {background-color:#149A48;margin-right:5%}
.PopularPosts ul li:nth-child(6) {background-color:#5BBFF1;margin-right:6%}
.PopularPosts ul li:nth-child(7) {background-color:#61469C;margin-right:7%}
.PopularPosts ul li:nth-child(8) {background-color:#863E86;margin-right:8%}
.PopularPosts ul li:nth-child(9) {background-color:#863E62;margin-right:9%}
.PopularPosts ul li:nth-child(10) {background-color:#815540;margin-right:10%}

Klik Simpan Template. Begitu saja.

Kotak Penelusuran Blogger dengan Ajax JQuery

Ajax Search Form with JQuery
Kotak Penelusuran Blogger dengan Ajax JQuery

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:

$('#search-form').on("submit", function() {
$.ajax({
url: '../feeds/posts/summary?alt=json-in-script&q=KATA_KUNCI',
type: 'get',
dataType: 'jsonp',
success: function(json) {
...
}
});
});

Sehingga jika dijabarkan akan menjadi seperti ini:

HTML Formulir

<form action="/search" id="ajax-search-form">
<input type="text" name="q">
<input type="submit" value="Search">
</form>

JQuery

(function($) {
var $form = $('#ajax-search-form'),
$input = $form.find(':text');
$form.append('<div id="search-result"></div>');
var $result_container = $('#search-result');
$form.on("submit", function() {
var keyword = $input.val();
$result_container.show().html('Loading...');
$.ajax({
url: 'http://nama_blog.blogspot.com/feeds/posts/summary?alt=json-in-script&q=' + keyword + '&max-results=9999',
type: 'get',
dataType: 'jsonp',
success: function(json) {
var entry = json.feed.entry,
link, skeleton = "";
if (entry !== undefined) {
skeleton = '<h4>Search results for keyword &quot;' + keyword + '&quot;</h4>';
skeleton += '<a class="close" href="/">&times;</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 {
$result_container.html('<a class="close" href="/">&times;</a><strong>No result!</strong>');
}
},
error: function() {
$result_container.html('<a class="close" href="/">&times;</a><strong>Error loading feed.</strong>');
}
});
return false;
});
$form.on("click", ".close", function() {
$result_container.fadeOut();
return false;
});
})(jQuery);

Cara Kerja

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:

$.ajax({
url: 'http://nama_blog.blogspot.com/feeds/posts/summary?alt=json-in-script&q=' + keyword + '&max-results=9999',
type: 'get',
dataType: 'jsonp',
success: function(json) {
var entry = json.feed.entry,
link, skeleton = "";
if (entry !== undefined) {
skeleton = '<h4>Search results for keyword &quot;' + keyword + '&quot;</h4>';
skeleton += '<a class="close" href="/">&times;</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 {
$result_container.html('<a class="close" href="/">&times;</a><strong>No result!</strong>');
}
},
error: function() {
$result_container.html('<a class="close" href="/">&times;</a><strong>Error loading feed.</strong>');
}
});

keyword adalah variabel. Nilainya diambil dari elemen input teks:

var keyword = $input.val();
// `../feeds/posts/summary?alt=json-in-script&q=keyword&max-results=9999`

Integrasi Widget ke Blogger

Widget ini hanya akan bekerja jika blog Anda sudah dilengkapi dengan JQuery.

Pertama-tama masuk ke halaman Tata Letak, kemudian tambahkan sebuah elemen halaman HTML/JavaScript. Salin kode ini dan letakkan di dalam formulirnya:

<style type="text/css" scoped="scoped">
#ajax-search-form {
position:relative;
font:normal normal 13px/normal Arial,Sans-Serif;
}
#ajax-search-form a {
color:#741F27;
text-decoration:none;
}
#ajax-search-form input {
border:1px solid #ccc;
border-top-color:#999;
background-color:white;
font:inherit;
color:black;
margin:0 0;
padding:5px 5px;
width:180px;
}
#ajax-search-form input::-moz-focus-inner {
margin:0;
padding:0;
border:none;
outline:none;
}
#ajax-search-form input[type="submit"] {
width:auto;
background-color:#084670;
border-color:transparent;
color:#B4D8F0;
font-weight:bold;
cursor:pointer;
padding-left:7px;
padding-right:7px;
}
#ajax-search-form input[type="submit"]:hover,
#ajax-search-form input[type="submit"]:focus {background-color:#083E5F}
#search-result {
border:1px solid #bbb;
background-color:white;
padding:10px 15px;
margin:2px 0;
width:auto;
height:auto;
position:absolute;
top:100%;
left:0;
z-index:99;
-webkit-box-shadow:0 1px 3px rgba(0,0,0,.4);
-moz-box-shadow:0 1px 3px rgba(0,0,0,.4);
box-shadow:0 1px 3px rgba(0,0,0,.4);
display:none;
}
#search-result ol,
#search-result li,
#search-result h4 {
margin:0;
padding:0;
}
#search-result h4,
#search-result strong {
display:block;
margin:0 30px 10px 0;
}
#search-result ol {margin:0 0 10px 28px}
#search-result ol a:hover {text-decoration:underline}
#search-result .close {
display:block;
position:absolute;
top:6px;
right:10px;
line-height:normal;
color:#17950F;
}
#search-result strong {color:#B75252}
</style>
<form action="/search" id="ajax-search-form">
<input type="text" name="q" />
<input type="submit" value="Search" />
</form>
<script type="text/javascript">
(function($) {

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 &quot;' + keyword + '&quot;</h4>';
skeleton += '<a class="close" href="/">&times;</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="/">&times;</a><strong>No result!</strong>');
}
},
error: function() {

// If error, show an error message
$result_container.html('<a class="close" href="/">&times;</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.

Memperbaharui Pemuatan JSON berdasarkan Event Scroll

Sebuah kumpulan data dalam daftar akan menampilkan indikator sedang memuat dan akan memulai pemuatan data baru saat jarak gulungan telah mencapai titik maksimal
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:

...
...
<script id="foo" src="../feeds/posts/summary?alt=json-in-script&callback=functionName" type="text/javascript"></script>
</head>

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:

elem.onscroll = function() {
if ((this.scrollTop + this.offsetHeight) == inner.offsetHeight) {
myFunction();
}
};

Dimana elem adalah objek berupa kontainer.

Memulai Pekerjaan

Markup HTML

Kita mulai dengan pembuatan markup HTML sederhana seperti ini:

<div id="result-container" style="width:400px;height:400px;overflow:auto;">
<ol></ol>
<span class="loading">Memuat...</span>
</div>

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:

...
...
...
<script id="load-on-scroll-end" src="http://nama_blog.blogspot.com/feeds/posts/summary?alt=json-in-script&start-index=1&max-results=25&callback=grabList" type="text/javascript"></script>
</head>

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";

}
};

Produk Final

HTML

<div id="result-container">
<ol></ol>
<span class="loading">Memuat...</span>
</div>

CSS

#result-container {
height:400px;
width:400px;
overflow:auto;
margin:50px auto;
font:normal normal 12px 'Trebuchet MS',Trebuchet,Geneva,Arial,Sans-Serif;
}

#result-container ol {
margin:0 0;
padding:0 0;
background-color:#B5D68C;
}

#result-container li {
margin:0 0;
padding:0 0;
list-style:none;
}

#result-container li:nth-child(even) {background-color:#A2C179}

#result-container li a {
display:block;
padding:5px 10px;
font-weight:bold;
color:#396B18;
text-decoration:none;
}

#result-container li a:hover {
background-color:#396B18;
color:white;
text-decoration:none;
}

#result-container .loading {
display:block;
height:26px;
font:normal bold 11px/26px Arial,Sans-Serif;
color:white;
text-align:center;
background-color:#B75A6F;
border-top:2px solid #222;
}

#result-container .loading.the-end {background-color:#666}

JavaScript

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";
}
};

Widget Recent Comment dengan Sistem Notifikasi

Pembaharuan 22 April 2013: Mengintegrasikan widget dengan cookies, menambahkan opsi summary dan menyingkirkan opsi tt_id.

Recent Comments Widget for Blogger with Notification System

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:

Untuk memasang widget ini, pertama-tama tambahkan sebuah elemen halaman HTML/JavaScript. Salin kode ini kemudian letakkan di dalam formulirnya:

<style type="text/css" scoped="scoped">
.cm-outer {
margin:0 auto;
padding:0 0;
font:normal normal 11px Arial,Sans-Serif;
border:1px solid;
border-top:none;
}
.cm-outer li {
margin:0 0;
padding:7px 10px 12px;
list-style:none;
clear:both;
border-top:1px solid;
}
.cm-outer .cm-header {margin:0 0 5px}
.cm-outer .cm-content {overflow:hidden}
.cm-outer img {
display:block;
float:left;
margin:2px 10px 2px 0;
border:4px solid black;
background:#8fa2cb url('http://img1.blogblog.com/img/anon36.png') no-repeat 50% 50%;
overflow:hidden;
}
</style>
<div id="comments-container">Loading&hellip;</div>
<script type="text/javascript">
var cm_config = {
home_page: "http://nama_blog.blogspot.com",
max_result: 7,
t_w: 32,
t_h: 32,
summary: 9999,
new_tab_link: true,
ct_id: "comments-container",
new_cm: " Komentar Baru!",
interval: 30000,
alert: true
};
</script>
<script type="text/javascript" src="http://reader-download.googlecode.com/svn/trunk/recent-comments-script-with-notification.js"></script>

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:

OpsiKeterangan
home_pageGanti nilainya dengan URL halaman muka blog Anda
max_resultDigunakan untuk menentukan jumlah komentar yang akan ditampilkan pada widget ini
t_wDigunakan untuk menentukan lebar avatar
t_hDigunakan untuk menentukan tinggi avatar
summaryDigunakan untuk menentukan jumlah karakter komentar yang ditampilkan
new_tab_linkJika bernilai true, seluruh tautan yang ada di dalam widget ini akan terbuka di tab/jendela baru saat diklik
tt_idID kontainer total komentar (abaikan jika tidak perlu)
ct_idID kontainer daftar komentar (abaikan jika tidak perlu)
new_cmLabel teks yang akan muncul setelah jumlah komentar (Misalnya: 2 Komentar Baru!)
intervalLihat deskripsi di bawah
alertLihat 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
Model Notifikasi 1: alert: false
Model Notifikasi 2
Model 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:

var cm_config = {
...
alert: function(total, label) {
document.getElementById('show-total').innerHTML = '<strong>'+total+' '+label+'</strong>';
}
};

Jika terdapat notifikasi baru, maka teks notifikasi tersebut akan muncul di dalam elemen #show-total dan akan menghasilkan markup HTML seperti ini:

<div id="show-total">
<strong>1 Komentar Baru!</strong>
</div>

Sebaiknya tambahkan juga atribut title dengan pesan tertentu dan satu buah fungsi kecil pada elemen di atas seperti ini:

<div id="show-total" title="Abaikan!" onclick="this.innerHTML='';"></div>

Fungsinya untuk menghilangkan teks total komentar apabila pengguna mengeklik elemen tersebut.

XHTML Blogger, Item Kontrol

Tombol Edit Cepat Posting

Biasanya berbentuk gambar/ikon pensil dan terletak di dalam footer posting:

<b:includable id='postQuickEdit' var='post'>
<b:if cond='data:post.editUrl'>
<span expr:class='&quot;item-control &quot; + data:post.adminClass'>
<a expr:href='data:post.editUrl' expr:title='data:top.editPostMsg'>
<img alt='' class='icon-action' height='18' src='http://img2.blogblog.com/img/icon18_edit_allbkg.gif' width='18'/>
</a>
</span>
</b:if>
</b:includable>
DataKeteranganTampilan/Contoh Tampilan
data:post.editUrlElemen ini akan menghasilkan URL pengeditan postinghttp://www.blogger.com/post-edit.g?blogID=489094982896596XXXX&postID=622513084927827XXXX&from=pencil
data:top.editPostMsgElemen ini akan menghasilkan deskripsi/pesan tautan pengeditan postingEdit Entri
data:post.adminClassElemen ini akan menghasilkan kelas khusus administrator (???)blog-admin pid-251761511

Tombol Edit Cepat Widget

Berbentuk gambar/ikon kunci inggris dan terletak pada bagian bawah widget:

<b:include name='quickedit'/>

http://img1.blogblog.com/img/icon18_wrench_allbkg.png

Tombol Penghapusan Komentar

Lihat pada XHTML Blogger, Ikon Penghapusan Komentar

Widget Daftar Isi Tabulasi untuk Blogger

Pembaharuan 29 Maret 2013: Menambahkan opsi thumbSize, noThumb, sortAlphabetically, showNew dan newText

Widget Daftar Isi Tabulasi untuk Bogger

Berikut ini adalah sebuah widget daftar isi blog berbentuk tabulasi. Terdiri dari dua sisi berupa daftar kategori dan daftar posting. Setiap nama kategori akan menjadi tab, sedangkan daftar posting akan menjadi konten tab yang akan muncul setiap kali tab diklik:

Integrasi Widget ke Blogger

Pertama-tama klik menu Laman pada sidebar. Kemudian, pada menu Laman Baru pilihlah Laman Kosong:

Blogger Post Editor
Menambahkan halaman statis baru

Setelah itu Anda akan melihat formulir halaman statis seperti ini. Klik mode HTML:

Blogger Post Editor
Pilih mode HTML

Salin kode di bawah ini kemudian letakkan di dalam formulirnya:

<link rel="stylesheet" href="http://reader-download.googlecode.com/svn/trunk/tabbed-toc-skin.css" type="text/css" media="screen" />
<div id="tabbed-toc"><span class="loading">Memuat...</span></div>
<a style="display:block;text-align:right;font:normal bold 8px Arial,Sans-Serif;text-decoration:none;margin:10px;" href="http://hompimpaalaihumgambreng.blogspot.com/2012/10/widget-daftar-isi-tabulasi-untuk-bogger.html" title="Tabbed TOC">DTE :]</a>
<script type="text/javascript">
var tabbedTOC = {
blogUrl: "http://nama_blog.blogspot.com", // Blog URL
containerId: "tabbed-toc", // Container ID
activeTab: 1, // The default active tab index (default: the first tab)
showDates: false, // `true` to show the post date
showSummaries: false, // `true` to show the posts summaries
numChars: 200, // Number of summary chars
showThumbnails: false, // `true` to show the posts thumbnails (Not recommended)
thumbSize: 40, // Thumbnail size
noThumb: "http://3.bp.blogspot.com/-vpCFysMEZys/UOEhSGjkfnI/AAAAAAAAFwY/h1wuA5kfEhg/s72-c/grey.png", // A "no thumbnail" URL
monthNames: [ // Array of month names
"Januari",
"Februari",
"Maret",
"April",
"Mei",
"Juni",
"Juli",
"Agustus",
"September",
"Oktober",
"November",
"Desember"
],
newTabLink: true, // Open link in new window?
maxResults: 99999, // Maximum post results
preload: 0, // Load the feed after 0 seconds (option => time in milliseconds || "onload")
sortAlphabetically: true, // `false` to sort posts by published date
showNew: 7, // `false` to hide the "New!" mark in most recent posts, or define how many recent posts are to be marked
newText: " - <em style='color:red;'>New!</em>" // HTML for the "New!" text
};
</script>
<script type="text/javascript" src="http://reader-download.googlecode.com/svn/trunk/tabbed-toc.js"></script>

Ganti URL yang Saya beri tanda dengan alamat blog Anda kemudian klik Publikasikan.

Pengaturan Lanjutan

OpsiKeterangan
blogUrlGanti nilainya dengan alamat blog Anda.
containerIdID elemen yang akan digunakan sebagai penampung JSON yang sudah diproses (abaikan jika tidak perlu).
activeTabDigunakan untuk menentukan nomor urut tab yang aktif (nilai 1 akan membuat tab di urutan pertama menjadi aktif, begitu pula konten tab pertama juga akan terbuka saat pertama kali halaman diakses).
showDatesGanti nilainya menjadi true untuk menampilkan waktu terbit posting.
showSummariesGanti nilainya menjadi true untuk menampilkan ringkasan posting.
showThumbnailsGanti nilainya menjadi true untuk menampilkan thumbnail posting (tidak direkomendasikan karena akan membuat halaman lama termuat).
thumbSizeDigunakan untuk menentukan ukuran thumbnail.
noThumbURL gambar cadangan untuk posting yang tidak memiliki gambar di dalamnya.
monthNamesDigunakan untuk menentukan nama-nama bulan sesuai dengan sistem penanggalan di negara tempat Anda tinggal.
newTabLinkJika bernilai true, semua tautan akan membuka di tab/jendela baru saat diklik.
maxResultsJumlah maksimal posting yang akan ditampilkan.
preloadDigunakan untuk menentukan waktu penundaan pemuatan JSON. Gunakan satuan milidetik atau cukup tuliskan "onload" agar widget ini memuat setelah keseluruhan halaman telah selesai termuat.
sortAlphabeticallyfalse untuk menyortir posting secara normal berdasarkan bulan terbit, true untuk menyortir posting berdasarkan alfabet.
showNewfalse untuk menyembunyikan tanda New!. Ganti dengan angka untuk menentukan berapa banyak posting terbaru yang ingin ditandai dengan label New!.
newTextMarkup HTML bebas untuk membuat label New! pada posting-posting terbaru.

Membangun Aplikasi Quick Search dengan JSON Blogger

Membangun Aplikasi Quick Search dengan JSON Blogger
Membangun Aplikasi Quick Search dengan JSON Blogger

Selain melalui halaman pencarian biasa, Blogger juga mengizinkan kita untuk mengakses posting-posting acak di dalam feed yang dapat disortir berdasarkan kata kunci. Ini bisa dilakukan melalui parameter q.

Format dasar URL feed untuk memanggil data posting dengan sortir berdasarkan kata kunci adalah seperti ini:

http://nama_blog.blogspot.com/feeds/posts/summary?q=Kata Kunci

Yang jika diakses akan menghasilkan halaman berisi daftar posting tersortir berdasarkan kata kunci dari parameter q seperti ini ⇒ Daftar posting dengan kata kunci ‘css’

Dengan memanfaatkan kerangka dasar widget Blogger, event onsubmit pada formulir dan juga penargetan elemen kontainer yang tepat, maka parameter ini memungkinkan kita untuk menciptakan aplikasi quick search. Yaitu sebuah aplikasi yang bisa digunakan untuk mencari artikel/posting dalam sebuah blog tanpa harus berpindah dari halaman asal. Seluruh hasil penelusuran akan tampil pada tempat yang sama!

Pada prinsipnya, hal pertama yang Saya buat adalah sebuah fungsi yang akan menyisipkan elemen <script> secara tidak langsung ke dalam area <head> saat fungsi tersebut dieksekusi. JavaScript yang Saya bangun adalah callback widget Blogger biasa dengan pola sumber yang umum. Saya hanya menambahkan parameter kata kunci pencarian sebagai penyortir posting yang akan dikirim nantinya:

http://nama_blog.blogspot.com/feeds/posts/summary?alt=json-in-script&q=Kata Kunci&callback=functionName

Nilai parameter sumber diambil dari sebuah elemen <input> yang Saya letakkan di dalam formulir. Logikanya seperti ini:

Menyisipkan Nilai Elemen Input ke dalam Parameter 'q'
Menyisipkan Nilai Elemen Input ke dalam Parameter q pada URL Feed
function insertScript() {
// Membangun elemen <script> untuk disisipkan ke dalam area <head> ...
// ... dengan parameter kueri yang ditentukan oleh nilai elemen 'feed-q-input'
var query = document.getElementById('feed-q-input').value,
s = document.createElement('script');
s.type = "text/javascript";
s.src = "http://nama_blog.blogspot.com/feeds/posts/summary?q="+query+"&alt=json-in-script&callback=functionName";
document.getElementsByTagName('head')[0].appendChild(s);
}
<form onsubmit="insertScript();return false;"> ... </form>

Kode aslinya lebih panjang, tapi pada intinya inilah dasar yang Saya gunakan untuk membangun aplikasi pencarian cepat. Anda bisa mengunduh JavaScript dan melihat demonya melalui tombol-tombol ini:


Integrasi Widget ke Blogger

Pertama-tama masuk ke halaman editor HTML template Anda, kemudian salin kode CSS ini dan letakkan di atas kode ]]></b:skin> atau </style>:

#search-form-feed {
width:200px; /* lebar kotak penelusuran */
position:relative;
margin:0 0 10px;
padding:0 0;
font:normal normal 11px Arial,Sans-Serif;
color:#333;
}

#feed-q-input {
display:block;
width:100%;
border:2px solid #bbb;
background-color:white;
padding:5px 5px;
font:normal bold 13px Tahoma,Arial,Sans-Serif;
color:#ccc;
margin:0 0;
-webkit-border-radius:4px;
-moz-border-radius:4px;
border-radius:4px;
-webkit-box-shadow:inset 0 1px 5px rgba(0,0,0,.2);
-moz-box-shadow:inset 0 1px 5px rgba(0,0,0,.2);
box-shadow:inset 0 1px 5px rgba(0,0,0,.2);
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}

#feed-q-input:focus {
border-color:#0D6786;
color:#333;
outline:none;
-webkit-box-shadow:0 0 5px #153E95,0 0 7px #153E95;
-moz-box-shadow:0 0 5px #153E95,0 0 7px #153E95;
box-shadow:0 0 5px #153E95,0 0 7px #153E95;
}

#search-result-container {
width:400px;
height:300px;
overflow:auto;
position:absolute;
top:100%;
right:0;
z-index:999;
background-color:#E5EDF7;
border:2px solid white;
padding:10px 10px 0;
margin:10px 0 0;
-webkit-box-shadow:0 1px 2px rgba(0,0,0,.4),0 7px 7px -4px rgba(0,0,0,.4);
-moz-box-shadow:0 1px 2px rgba(0,0,0,.4),0 7px 7px -4px rgba(0,0,0,.4);
box-shadow:0 1px 2px rgba(0,0,0,.4),0 7px 7px -4px rgba(0,0,0,.4);
-webkit-border-radius:5px;
-moz-border-radius:5px;
border-radius:5px;
display:none;
}

#search-result-container mark {
background-color:yellow;
color:black;
}

#search-result-container a {
text-decoration:none;
color:#0D3E71;
font-weight:bold;
font-size:12px;
display:block;
}

#search-result-container a:hover {
color:#052748;
}

#search-result-container h4 {
margin:0 0 10px;
font:normal bold 12px 'Trebuchet MS',Arial,Sans-Serif;
color:#B50001;
}

#search-result-container ol {
background:transparent;
border:none;
margin:0 0 10px;
padding:0 0;
}

#search-result-container li {
margin:0 0 1px;
padding:7px 8px;
list-style:none;
border:1px solid #B7C1CE;
background-color:white;
overflow:hidden;
word-wrap:break-word;
}

#search-result-container li img {
display:block;
float:left;
margin:0 10px 4px 0;
border:1px solid #B7C1CE;
background-color:#F5F5F5;
padding:2px 2px;
}

#search-result-loader {
position:absolute;
top:100%;
left:5px;
z-index:999;
background-color:#0D6786;
color:white;
padding:3px 5px;
margin:-2px 0 0;
font:normal bold 10px Arial,Sans-Serif;
-webkit-border-radius:0 0 3px 3px;
-moz-border-radius:0 0 3px 3px;
border-radius:0 0 3px 3px;
display:none;
}

Setelah itu masuk ke halaman Tata Letak, kemudian tambahkan sebuah elemen halaman HTML/JavaScript. Salin kode ini dan letakkan di dalam formulirnya:

<div id="search-form-feed">
<form action="/search" onsubmit="return updateScript();">
<input name="q" type="text" value="Telusuri..." id="feed-q-input" onkeyup="resetField();" onfocus="this.value='';"/>
</form>
<div id="search-result-container"></div>
<div id="search-result-loader">Loading...</div>
</div>
<script type="text/javascript">
//<![CDATA[
var searchFormConfig = {
url: "http://nama_blog.blogspot.com", // URL Blog
numPost: 9999, // Jumlah maksimal temuan
summaryPost: true, // 'true' jika ingin menampilkan deskripsi posting
summaryLength: 400, // Jumlah karakter ringkasan posting
resultTitle: "Hasil penelusuran untuk kata kunci", // Judul hasil pencarian
noResult: "No result", // Deskripsi 'tak ditemukan'
resultThumbnail: true, // 'true' untuk menampilkan thumbnail posting
thumbSize: 40, // Ukuran & resolusi thumbnail
fallbackThumb: "http://reader-download.googlecode.com/svn/trunk/images/no-image-72x72.png" // Fallback thumbnail untuk posting tak bergambar
};
//]]>
</script>
<script type="text/javascript" src="http://reader-download.googlecode.com/svn/trunk/blogger-quick-search.js"></script>

Klik Simpan Widget.

Konfigurasi Widget

Semua opsi sangat umum. Saya yakin Anda bisa dengan cepat mempelajarinya:

OpsiKeterangan
urlURL blog Anda
numPostJumlah posting yang akan ditampilkan dalam hasil pencarian. Nilai 9999 maksudnya adalah Anda mencoba untuk menampilkan semua posting yang ditemukan
summaryPostPilihan untuk menampilkan atau menyembunyikan ringkasan posting dalam hasil pencarian
summaryLengthDigunakan untuk menentukan jumlah karakter ringkasan hasil pencarian
resultTitleJudul hasil pencarian
noResultPeringatan yang menunjukkan bahwa posting tidak ditemukan
resultThumbnailPilihan untuk menampilkan atau menyembunyikan thumbnail posting dalam hasil pencarian
thumbSizeDigunakan untuk menentukan ukuran dan resolusi thumbnail hasil pencarian
fallbackThumbGambar cadangan untuk posting tak bergambar.

CSS untuk Tema Minimalis (Layout Dasar)

Digunakan sebagai pengganti kode CSS di atas demi kemudahan dalam hal penyesuaian tema:

#search-form-feed {
width:200px; /* lebar kotak penelusuran */
position:relative;
margin:0 0 10px;
padding:0;
font:normal normal 11px/normal Arial,Sans-Serif;
color:#333;
}

#feed-q-input {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
display:block;
width:100%;
border:1px solid #bbb;
background-color:white;
padding:5px 5px;
font:inherit;
font-size:13px;
margin:0;
}

#search-result-container {
width:400px;
height:300px;
overflow:auto;
position:absolute;
top:100%;
left:0; /* ganti menjadi `right:0` untuk mendorong kontainer ke kanan */
z-index:9999;
border:1px solid #ccc;
padding:10px 10px 0;
margin:10px 0 0;
-webkit-box-shadow:0 3px 5px rgba(0,0,0,.2);
-moz-box-shadow:0 3px 5px rgba(0,0,0,.2);
box-shadow:0 3px 5px rgba(0,0,0,.2);
display:none;
}

#search-result-container mark {
font:inherit;
display:inline;
background-color:#ff0;
color:black;
}

#search-result-container a {
text-decoration:none;
font-weight:bold;
font-size:110%;
display:block;
}

#search-result-container h4 {
margin:0 0 10px;
font:inherit;
font-weight:bold;
color:#B50001;
}

#search-result-container ol {
background:none;
border:none;
margin:0 0 10px;
padding:0;
}

#search-result-container li {
margin:0 0 15px;
list-style:none;
overflow:hidden;
word-wrap:break-word;
padding-left:65px;
}

#search-result-container li img {
display:block;
float:left;
margin:0 0 2px -55px;
border:1px solid #ccc;
padding:2px;
}

#search-result-loader {
position:absolute;
top:100%;
left:5px;
z-index:9999;
margin-top:4px;
font-size:10px;
display:none;
}