Selasa, 11 Juni 2013
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 widget artikel terkait— 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:

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”.
Label: JavaScript, Pemecahan Masalah, Posting, Tingkat Lanjut, Widget
Senin, 16 April 2012
Recent Post dan Recent Comment pada Drop Down Menu??

Seringkali Saya melihat beberapa orang mencoba menuliskan semua kategori posting pada drop down menu. Mereka melakukannya secara manual. Saya pikir, seandainya Saya bisa menggunakan JSON untuk ini, maka mereka tidak perlu lagi repot-repot memperbaharui menu setiap kali label baru ditambahkan.
Tapi setelah Saya coba ternyata hasilnya proses muat halaman menjadi sangat lambat. Jadi Saya mencoba menggunakan alternatif menarik lainnya, yaitu widget recent post dan recent comment yang Saya letakkan pada menu-menu sekunder. Kita tahu bahwa kebanyakan widget semacam ini dibangun oleh elemen-elemen daftar, oleh karena itulah kita bisa menaruhnya dengan sangat pas ke dalam menu (yang juga dibangun oleh elemen-elemen daftar).
Masih sama. Halaman menjadi sedikit lebih lambat. Ya, itu terjadi karena widget-widget ini harus memanggil feed posting untuk menampilkan isi widget tersebut. Terlebih lagi, menu navigasi secara umum diletakan di bagian atas, sehingga jika proses pemuatan menu navigasi lebih lambat dari biasanya, maka peramban akan terlambat pula saat membaca elemen-elemen di bawahnya, karena peramban membaca seperti manusia, dari kiri atas menuju ke kanan bawah (Kesimpulan: Proses muat halaman menjadi lambat).
Solusi Saya adalah dengan cara meletakkan menu navigasi ini pada bagian paling bawah, tepatnya di atas </body> sehingga kita harap widget ini akan memulai proses pemuatan posting saat elemen-elemen di atasnya sudah cukup siap. Dan untuk mengangkat menu navigasi yang berada di bawah menuju ke atas, Saya menggunakan posisi absolute dengan nilai top sebesar 0:
Masuklah ke menu Template kemudian klik Edit HTML dan klik Lanjutkan:
Temukan kode ini:
</head>
Salin kode ini dan letakkan di atasnya:
<style type='text/css'>
#autonav {
position:absolute;
top:0px;
right:0px;
left:0px;
z-index:9999;
margin:0px 0px;
padding:0px 0px;
font:normal 11px Arial,Sans-Serif;
color:white;
border-bottom:2px solid #333;
-webkit-box-shadow:0px 1px 7px rgba(0,0,0,.4);
-moz-box-shadow:0px 1px 7px rgba(0,0,0,.4);
box-shadow:0px 1px 7px rgba(0,0,0,.4);
}
#autonav ul {
margin:0px 0px;
padding:0px 0px;
height:30px;
background-color:#0F5079;
}
#autonav ul li {
list-style:none;
display:inline;
float:left;
margin:0px 0px;
padding:0px 0px;
position:relative;
}
#autonav ul li a {
display:block;
line-height:30px;
height:30px;
overflow:hidden;
margin:0px 0px;
padding:0px 15px;
border-left:1px solid #155F90;
border-right:1px solid #082E46;
text-decoration:none;
text-shadow:0px -1px 0px rgba(0,0,0,.4);
color:white;
font-weight:bold;
}
#autonav ul li a:hover {
background-color:#0F486C;
}
#autonav ul ul {
position:absolute;
width:220px;
height:auto;
top:100%;
left:0px;
z-index:99;
background-color:#111;
-webkit-box-shadow:0px 1px 3px rgba(0,0,0,.7);
-moz-box-shadow:0px 1px 3px rgba(0,0,0,.7);
box-shadow:0px 1px 3px rgba(0,0,0,.7);
overflow:visible !important;
display:none;
}
#autonav ul ul:before {
content:"";
width:0px;
height:0px;
border:7px solid transparent;
border-bottom-color:#111;
position:absolute;
top:-14px;
left:24px;
}
#autonav ul ul li {
display:block;
float:none;
}
#autonav ul ul li a {
border:none;
color:#999;
}
#autonav ul ul ul {
top:0px;
left:100%;
}
#autonav li:hover > ul {
display:block;
}
/* Khusus JSON */
#autonav ul.json-dropdown {
overflow:hidden;
}
#autonav ul.json-dropdown li {
cursor:pointer;
display:block;
padding:7px 10px;
margin:0px 0px;
overflow:hidden;
}
#autonav ul.json-dropdown li a {
line-height:14px;
height:auto !important;
padding:0px 0px;
}
#autonav ul.json-dropdown li a:hover {
text-decoration:underline;
background:transparent;
}
#autonav li ul li a:hover,
#autonav li ul.json-dropdown li:hover {
background-color:#222;
}
#autonav ul.json-dropdown img.rp-thumb {
padding:0px 0px;
outline:none;
border:2px solid #333;
background-color:#02406C;
display:block;
float:left;
margin:0px 10px 0px 0px;
width:40px;
height:40px;
}
#autonav .subposts span,
#autonav .subcomments span {
font-family:Verdana,Arial,Sans-Serif;
color:#666;
font-size:9px;
}
/* Drop down menu untuk ukuran yang cukup lebar */
#autonav .wide {
width:400px;
}
</style>
<script type='text/javascript'>
//<![CDATA[
var numposts = 7,
cmtext = "Komentar",
pBlank = "http://reader-download.googlecode.com/svn/trunk/images/no-image-72x72.png",
numcomment = 7,
cmsumm = 100;
//]]>
</script>
<script src='http://reader-download.googlecode.com/svn/trunk/json-dropdown.js' type='text/javascript'></script>Setelah itu temukan kode ini:
</body>
Salin kerangka menu ini dan letakkan di atasnya:
<nav id='autonav'>
<ul>
<li><a href='/'>Beranda</a></li>
<li><a href='#'>Profil</a></li>
<li><a href='#'>Terbaru</a>
<ul class='json-dropdown subposts wide'>
<script src='http://hompimpaalaihumgambreng.blogspot.com/feeds/posts/default/?alt=json-in-script&callback=dropdownposts'></script>
</ul>
</li>
<li><a href='#'>Komentar Terakhir</a>
<ul class='json-dropdown subcomments'>
<script src='http://hompimpaalaihumgambreng.blogspot.com/feeds/comments/default?alt=json-in-script&callback=dropdowncomment'></script>
</ul>
</li>
<li><a href='#'>Kontak</a>
<ul>
<li><a href='#'>Lorem Ipsum</a></li>
<li><a href='#'>Dolor Sit Amet</a></li>
</ul>
</li>
</ul>
</nav>- Tentukan jumlah posting menu recent post pada variabel
numposts - Tentukan jumlah posting recent comment pada variabel
numcomment - Tentukan label komentar pada variabel
cmtext(misal: 17 Komentar) pBlankdigunakan untuk menampilkan gambar cadangan pada recent post yang tidak memiliki gambar mini- Tentukan jumah ringkasan komentar pada variabel
cmsumm - Ganti URL yang Saya beri tanda dengan URL blogmu.
Label: JavaScript, JSON, JSON Blogger, Menengah, Menu, Navigasi, Pemecahan Masalah, Widget
Rabu, 15 Juni 2011
Membuat Recent Post/Posting Terbaru dengan Script untuk Mengatasi Masalah Desain dan Bahasa
Pernah melihat model recent post seperti ini? Ya, itu adalah recent post bawaan dari Blogger.com. Jika dilihat-lihat, tampilannya memang terasa sedikit memaksa dengan template blog kita. Komposisi warna dan model huruf yang tidak bisa disesuaikan terkadang juga membuat recent post ini menjadi tampak seperti "tempelan" saja, bukannya menjadi salah satu bagian dari tubuh blog kita. Selain itu, salah satu bagian kecil berupa tautan bertuliskan continue >> juga mungkin akan sedikit mengganggu bagi para anak bangsa yang cinta bahasa tanah air. Nah, untuk mengatasi semua masalah itu, kamu bisa menggunakan baris script yang Saya peroleh dari salah seorang tetangga Saya yang baik hatinya. Namanya mas Hoctro (hehe..)Salin saja semua kode ini, kemudian letakkan di dalam sebuah elemen halaman HTML/JavaScript:
<script type='text/javascript'>
//<![CDATA[
//kredit kepada HOCTRO
function rp(json) {
document.write('<ul>');
for (var i = 0; i < numposts; i++) {
document.write('<li>');
var entry = json.feed.entry[i];
var posttitle = entry.title.$t;
var posturl;
if (i == json.feed.entry.length) break;
for (var k = 0; k < entry.link.length; k++) {
if (entry.link[k].rel == 'alternate') {
posturl = entry.link[k].href;
break;
}
}
posttitle = posttitle.link(posturl);
readmorelink = readmorelink.link(posturl);
var postdate = entry.published.$t;
var cdyear = postdate.substring(0,4);
var cdmonth = postdate.substring(5,7);
var cdday = postdate.substring(8,10);
var monthnames = new Array();
monthnames[1] = "Jan";
monthnames[2] = "Feb";
monthnames[3] = "Mar";
monthnames[4] = "Apr";
monthnames[5] = "Mei";
monthnames[6] = "Jun";
monthnames[7] = "Jul";
monthnames[8] = "Agt";
monthnames[9] = "Sep";
monthnames[10] = "Okt";
monthnames[11] = "Nov";
monthnames[12] = "Des";
if ("content" in entry) {
var postcontent = entry.content.$t;
} else if ("summary" in entry) {
var postcontent = entry.summary.$t;
} else
var postcontent = "";
var re = /<\S[^>]*>/g;
postcontent = postcontent.replace(re, "");
document.write(posttitle);
if (showpostdate == true) document.write(' - ' + monthnames[parseInt(cdmonth,10)] + ' ' + cdday);
if (showpostsummary == true) {
if (postcontent.length < numchars) {
document.write(postcontent);
} else {
postcontent = postcontent.substring(0, numchars);
var quoteEnd = postcontent.lastIndexOf(" ");
postcontent = postcontent.substring(0,quoteEnd);
document.write(' ' + postcontent + '...' + readmorelink);
}
}
document.write('</li>');
}
document.write('</ul>');
}
//]]>
</script>
<script type='text/javascript'>
var numposts = 7;
var showpostdate = true;
var showpostsummary = true;
var numchars = 100;
var readmorelink = "(lagi)";
</script>
<script src="http://hompimpaalaihumgambreng.blogspot.com/feeds/posts/default?orderby=published&alt=json-in-script&callback=rp">
</script>Simpan elemen halamanmu. Sekarang kita tinggal melakukan beberapa penyesuaian.
Sedikit Penyesuaian:
- Gantilah http://hompimpaalaihumgambreng.blogspot.com dengan alamat blogmu.
- Semua kode yang Saya beri warna merah adalah variabel yang bisa kamu utak-atik sesuai dengan bahasamu.
var numpostsadalah variabel untuk menentukan jumlah posting yang tampil (dalam hal ini 7).var numcharsadalah variabel untuk menentukan jumlah teks konten posting yang diringkas/dipotong.- Di situ juga terdapat nilai-nilai
truedanfalse. Cobalah untuk mengganti nilaitruedenganfalseatau sebaliknya dan lihat sendiri perbedaannya.
Nah, sekarang kita sudah bisa memiliki model recent post/posting terbaru dengan tampilan dan bahasa yang bisa menyesuaikan diri dengan pemodel template kita seperti ini:
Label: Pemecahan Masalah, Posting, Widget

