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;
Kemudian, dari induk tersebut Saya akan menyingkirkan elemen itu sendiri:
var a = document.getElementById('foo');
var parent = a.parentNode;
parent.removeChild(a);
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:
1code-line:4-12code-line:4-23code-line:4-34code-line:4-45code-line:4-5elem.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'),
inner = elem.getElementsByTagName('ol')[0],
loading = elem.getElementsByTagName('span')[0];
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;
loading.style.display = "none";
} else {
loading.className += ' the-end';
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);
}
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);
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) {
updateScript(i, 25);
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) {
start++;
updateScript(start*25, 25);
loading.style.display = "block";
}
};
Produk Final
HTML
1code-line:12-12code-line:12-23code-line:12-34code-line:12-4<div id="result-container">
<ol></ol>
<span class="loading">Memuat...</span>
</div>
CSS
1code-line:13-12code-line:13-23code-line:13-34code-line:13-45code-line:13-56code-line:13-67code-line:13-78code-line:13-89code-line:13-910code-line:13-1011code-line:13-1112code-line:13-1213code-line:13-1314code-line:13-1415code-line:13-1516code-line:13-1617code-line:13-1718code-line:13-1819code-line:13-1920code-line:13-2021code-line:13-2122code-line:13-2223code-line:13-2324code-line:13-2425code-line:13-2526code-line:13-2627code-line:13-2728code-line:13-2829code-line:13-2930code-line:13-3031code-line:13-3132code-line:13-3233code-line:13-3334code-line:13-3435code-line:13-3536code-line:13-3637code-line:13-3738code-line:13-3839code-line:13-3940code-line:13-4041code-line:13-4142code-line:13-4243code-line:13-4344code-line:13-4445code-line:13-4546code-line:13-4647code-line:13-47#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
1code-line:14-12code-line:14-23code-line:14-34code-line:14-45code-line:14-56code-line:14-67code-line:14-78code-line:14-89code-line:14-910code-line:14-1011code-line:14-1112code-line:14-1213code-line:14-1314code-line:14-1415code-line:14-1516code-line:14-1617code-line:14-1718code-line:14-1819code-line:14-1920code-line:14-2021code-line:14-2122code-line:14-2223code-line:14-2324code-line:14-2425code-line:14-2526code-line:14-2627code-line:14-2728code-line:14-2829code-line:14-2930code-line:14-3031code-line:14-3132code-line:14-3233code-line:14-3334code-line:14-3435code-line:14-3536code-line:14-3637code-line:14-3738code-line:14-3839code-line:14-3940code-line:14-4041code-line:14-4142code-line:14-4243code-line:14-4344code-line:14-4445code-line:14-4546code-line:14-4647code-line:14-4748code-line:14-4849code-line:14-4950code-line:14-5051code-line:14-5152code-line:14-5253code-line:14-5354code-line:14-5455code-line:14-5556code-line:14-5657code-line:14-5758code-line:14-5859code-line:14-5960code-line:14-6061code-line:14-6162code-line:14-6263code-line:14-6364code-line:14-6465code-line:14-6566code-line:14-6667code-line:14-67var widget_config = {
home_page: 'http://nama_blog.blogspot.com',
container_id: 'result-container',
script_id: 'load-on-scroll-end-script',
max_result: 25,
end_text: 'Habis'
};
var elem = document.getElementById(widget_config.container_id),
inner = elem.getElementsByTagName('ol')[0],
loading = elem.getElementsByTagName('span')[0],
start = 0,
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;
loading.style.display = "none";
} else {
loading.className += ' the-end';
loading.textContent = widget_config.end_text;
}
}
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 (document.getElementById(widget_config.script_id)) {
var oldScript = document.getElementById(widget_config.script_id);
oldScript.parentNode.removeChild(oldScript);
}
head.appendChild(script);
}
updateScript(1, max);
elem.onscroll = function() {
if ((this.scrollTop + this.offsetHeight) == inner.offsetHeight) {
start++;
updateScript(start*max, max);
loading.style.display = "block";
}
};