Tampilkan postingan dengan label jquery. Tampilkan semua postingan
Tampilkan postingan dengan label jquery. Tampilkan semua postingan

Minggu, 10 April 2016

Bagaimana Sebenarnya jQuery Bekerja

Ketika orang-orang sudah cukup puas dengan markup dan style sheet language, pada akhirnya mereka memutuskan untuk tertarik dengan dunia pemrograman setelah mereka dipertemukan dengan bahasa pemrograman yang luar biasa dahsyat yang mereka kenal sebagai jQuery. Mereka jatuh cinta karena efek animasi yang diberikan; mereka jatuh cinta kepada slideshow, kepada efek dropdown menu, kepada efek gambar kabur, dan lain sebagainya; sebegitu jatuh cintanya mereka hingga mereka sanggup untuk duduk berlama-lama di depan komputer, ketagihan menggoyang-goyangkan pointer mouse mereka di permukaan menu navigasi dropdown berkali-kali hanya demi melihat efek slide-up dan slide-down yang begitu indah…

Sabtu, 29 November 2014

Beberapa Tip untuk Para Pengguna JQuery Tingkat Lanjut

Idea

Berikut ini adalah beberapa tip penggunaan JQuery tingkat lanjut untuk Anda yang menginginkan performa web yang lebih baik, entah itu dari segi lama/cepatnya waktu eksekusi skrip ataupun dari segi panjang/pendeknya penulisan kode. Semoga bermanfaat!

Kode Pintasan untuk ‘DOM Ready’

// Sebelum
$(document).ready(function() {

});

// Sesudah
$(function() {

});

Metode Berantai

Jika memang masih bisa dikaitkan, maka Anda sebenarnya tidak perlu menuliskan selektor JQuery berulang-ulang dan kemudian menerapkan metode pada selektor tersebut:

// Sebelum
$('button').click(function() {
$(this).toggleClass('active');
$(this).html('Clicked!');
$(this).css('opacity', .5);
});
$('button').css('color', 'red');

// Sesudah
$('button').click(function() {
$(this).toggleClass('active').html('Clicked!').css('opacity', .5);
}).css('color', 'red');

Menyeleksi Elemen <body> dan <html>

Selektor ini akan memberikan performa yang lebih baik:

// Sebelum
var $root = $('html'),
$base = $('body');

// Sesudah
var $root = $(document.documentElement),
$base = $(document.body);

Mengambil/Mengeset Atribut Elemen dengan JavaScript Mentah

Dalam kondisi tertentu, metode ini terbukti jauh lebih efisien jika dibandingkan dengan metode .attr():

// Sebelum
$('div').each(function(i) {
$(this).attr({
'class': 'foo',
'id': 'bar-' + i
});
});

// Sesudah
$('div').each(function(i) {
this.className = 'foo';
this.id = 'bar-' + i;
});
// Sebelum
$('a').click(function() {
alert($(this).attr('href'));
});

// Sesudah
$('a').click(function() {
alert(this.href);
});

Menerapkan Metode JavaScript Mentah kepada Selektor JQuery

Anda bisa menggunakan JQuery .get() untuk mengembalikan status selektor JQuery menjadi selektor JavaScript, atau gunakan indeks array yang ada untuk menyeleksi elemen pada urutan tertentu:

// Tidak valid
$('div').innerHTML = 'test';

// Valid
$('div').get(0).innerHTML = 'test';
$('div')[0].innerHTML = 'test';
// Tidak valid
$('#my-button').onclick = function() {
alert('test!');
};

// Valid
$('#my-button').get(0).onclick = function() {
alert('test!');
};
$('#my-button')[0].onclick = function() {
alert('test!');
};

Fungsi Anonim untuk Menggantikan .each()

// Sebelum
$('div').each(function(i) {
$(this).html('Element: ' + i);
});

// Sesudah
$('div').html(function(i) {
return 'Element: ' + i;
});

Mengeset Event dan Mengeksekusinya Secara Bersamaan

// Sebelum
function windowSizeCheck() {
$('#result').html('Width: ' + $(window).width() + '<br>Height: ' + $(window).height());
} windowSizeCheck();
$(window).resize(windowSizeCheck);

// Sesudah
$(window).resize(function() {
$('#result').html('Width: ' + $(this).width() + '<br>Height: ' + $(this).height());
}).trigger("resize");

Jalan Pintas untuk Efek Toggle

Setiap metode dalam JQuery pada umumnya adalah berupa objek, sehingga Anda bisa menganggap $(document).ready() dan $(document)['ready']() sebagai dua hal yang sama:

// Tidak efisien
$('a').mouseenter(function() {
$(this).addClass('hover');
});
$('a').mouseleave(function() {
$(this).removeClass('hover');
});

// Lebih efisien
$('a').mouseenter(function() {
$(this).addClass('hover');
}).mouseleave(function() {
$(this).removeClass('hover');
});

// Lebih efisien lagi
$('a').hover(function() {
$(this).addClass('hover');
}, function() {
$(this).removeClass('hover');
});

// Paling efisien
$('a').on("mouseenter mouseleave", function(e) {
$(this)[e.type == "mouseenter" ? 'addClass' : 'removeClass']('hover');
});

Efek Tabulasi

Gunakan .siblings() untuk menyeleksi semua elemen yang sejenis dengan X di dalam induk yang sama tanpa menyeleksi elemen X itu sendiri:


/**
* <div class="my-tab-buttons">
* <a href="#tab-1">Tab 1</a>
* <a href="#tab-2">Tab 2</a>
* <a href="#tab-3">Tab 3</a>
* <a href="#tab-4">Tab 4</a>
* </div>
*/

// Sebelum
$('.my-tab-buttons a').click(function() {
$(this).parent().find('a').removeClass('active');
$(this).addClass('active');
return false;
});
$('.my-tab-buttons a:first').addClass('active');

// Sesudah
$('.my-tab-buttons a').click(function() {
$(this).addClass('active').siblings().removeClass('active');
return false;
}).first().trigger("click");

Efek Animasi Beruntun

Sebelumnya Saya sudah pernah menjelaskan tentang ini…

// Sebelum
$('div')
.animate({'font-size':10}, 400)
.animate({'font-size':50}, 400)
.animate({'font-size':100}, 400)
.animate({'margin-top':200}, 400);

// Sesudah
var anim = [
{'font-size':10},
{'font-size':50},
{'font-size':100},
{'margin-top':200}
];
$.each(anim, function(i) {
$('div').animate(anim[i], 400);
});
// Sebelum
$('div')
.animate({'font-size':10}, 400)
.animate({'font-size':50}, 1000)
.animate({'font-size':100}, 200)
.animate({'margin-top':200}, 300);

// Sesudah
var anim = [
[{'font-size':10}, 400],
[{'font-size':50}, 1000],
[{'font-size':100}, 200],
[{'margin-top':200}, 300]
];
$.each(anim, function(i) {
$('div').animate(anim[i][0], anim[i][1]);
});

Efek Berdenyut

function pulsate() {
var $div = $('div');
$div.animate({
fontSize: $div.css('font-size') == '50px' ? '100px' : '50px'
}, 800, pulsate);
} pulsate();

Minggu, 01 Juni 2014

Memasang Back To Top Button Pada Blog

Back To Top Button
Memasang back to top button sangat penting agar memudahkan pengunjung, bila sebelumnya Saya share tentang Membuat Back To Top Unik Dengan Cacing. Kali ini saya share back to top button sederhana. Pada versi ada agak sedikit berbeda, yaitu ada penambahan efek smoothing.

Cara Memasang Back To Top

1. Template Anda harus sudah terpasang jQuery Libary, jika belum pasang jQuery ini diatas kode </head>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
2. Simpan kode ini diatas kode ]]></b:skin> atau </style>

/*Back To Top*/
#top{background-color:#444;margin:0;padding:10px;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px;position:fixed;bottom:10px;right:10px;cursor:pointer;display:none;}
#top:hover{background-color:#E73138}
3. Kemudian simpan kode ini diatas kode </body>

<a href='#' id='top'><img alt='Back To Top' src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioWYvLwg1rH-xplqHIHse660sPu2fEjh5wfwPh2J-2oKh1iiJIavRMqtbfEfVhvYx3yQCN-PJyY5b_L-0gTJ0DLaXMkck2GB2qMK1Jr6RfBTQp2Rdqy9YR_uIPalPl7FPaIwUEXw_xzZaC/s1600/btp.png'/></a>
<script type='text/javascript'>
//<![CDATA[
//Scroll Top
(function(a){a(window).scroll(function(){if(a(this).scrollTop()>280){a("#top").removeAttr("href");a("#top").fadeIn()}else{a("#top").fadeOut()}});a(function(){a("#top").click(function(){a("html, body").animate({scrollTop:0},"slow");return false})})})(jQuery);
//]]>
</script>

Minggu, 27 April 2014

Membuat Back To Top Unik Dengan Cacing

Back To Top Button
Back to top adalah suatu tombol untuk kembali ke atas website tanpa harus menggunakan scrollbar. Back to top ini fungsinya untuk memudahkan pengunjung untuk kembali ke kepala suatu website dengan cepat. Kita sering menjumpai tampilan back to top yang biasa saja, namun berbeda dengan yang satu ini.

Back To Top yang satu ini seolah - olah kita sedang memancing, jadi saat scrollbar digulung kebawah otomatis kail dengan cacing turun kebawah, saat scrollbar digulung ke atas kail naik lagi ke atas. Lalu saat kail dengan cacing di klik, scrollbar menggulung otomatis ke atas. Artikel ini pernah ditulis oleh +Beben Koben pada Make Attractive Back to Top Cacing Theme, oleh karena itu Saya tulis ulang di blog ini.

Cara Memasang Back To Top

1. Template Anda harus sudah terpasang jQuery Libary, jika belum pasang jQuery ini diatas kode </head>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
2. Simpan kode ini diatas kode ]]></b:skin> atau </style>

.cacing{background-image:url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcudgxubcFLXRSYaOKA1Gzl4CBMuhvumNvh8k6nfp-UU1RuNxqkefk4oVeZJFF74DtqAVW5JcDn-rlfw6krLZlWUr3ic2V6EMZwKHBHzEFfqn5tSOLK-FUi898G5xfnenV6MEhrvlVgsuT/s1600/Cacing.png);background-repeat:no-repeat;position:relative}
#cacing{cursor:pointer;width:30px;height:530px;background-size:41px;position:fixed;top:-550px;left:7%;transition:all .7s ease-in-out;-webkit-transition:all .7s ease-in-out;z-index:21}
#cacing-bubble{background:#fff;border-radius:50px;color:#06f;display:block;font-size:12px;line-height:14px;opacity:0;overflow:visible;padding:5px;position:absolute;top:445px;left:20px;text-align:center;transition:all .3s ease-in-out;-webkit-transition:all .3s ease-in-out;visibility:hidden;width:60px;height:auto;z-index:99}
#cacing:hover > #cacing-bubble,#cacing:hover > #cacing-bubble:after{opacity:1;transition:all .3s ease-in-out;-webkit-transition:all .3s ease-in-out;visibility:visible}
#cacing-bubble:after{border-bottom:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #fff;border-left:5px solid #fff;content:"";display:block;position:absolute;top:96%;left:10px;width:0;height:0;z-index:98}
3. Kemudian simpan kode ini diatas kode </body>

<script type='text/javascript'>
//<![CDATA[
jQuery(document).ready(function($) {
$(window).on('scroll', false, function() {
var windowTop = $(window).scrollTop();
if (windowTop > 550) {
$('#cacing').css('top', '0');
} else {
$('#cacing').css('top', windowTop - 550 + 'px');
}
});
$('#cacing').unbind('click').click(function() {
$('html,body').animate({
scrollTop: $("#cacingTOP").offset().top
}, 'slow');
});
});

//]]>
</script>
4. Lalu simpan kode ini dibawah kode <body>

<div class="cacing" id="cacing">
<div id="cacing-bubble">Kembali ke atas!</div>
</div>
<div id="cacingTOP"></div>
Silakan Anda ganti tulisan yang Saya tandai sesuai dengan keinginan. Bagaimana unik bukan tentunya beda dari yang lain ;)

Minggu, 30 Maret 2014

Emoticon Wordpress Untuk Blogger

Setelah membahas tentang SEO kali ini Saya akan mencoba berbagi tutorial kecil yaitu Emoticon Wordpress Untuk Blogger. Emoticon ini Saya gunakan pada blog ini, emoticon ini memiliki kelebihan yaitu lebih ramah terhadap loading blog, karena Saya merubah gambar ke base64. Emoticon ini Saya ambil dari sini http://codex.wordpress.org/Using_Smilies.

Langkah Pertama : Memasang CSS

Lalu silakan Anda simpan kode CSS ini berada di atas kode ]]></b:skin> atau </style>.

.emoWrap{margin:0 auto;text-align:center}
.emo,.emoKey{display:inline-block;*display:inline;vertical-align:middle}
.emoKey{width:auto;border:1px solid #ccc;background-color:white;font:normal bold 11px/normal Arial,Sans-Serif;padding:2px;margin:0 0 0 2px;color:black}

Langkah Kedua : Memasang jQuery

Agar emoticon ini berkeja pakai jQuery versi dibawah ini, dan simpan diatas kode </head>
<script async='async' src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js' type='text/javascript'></script>
Silakan Anda simpan jQuery ini diatas kode </body>.

<script type='text/javascript'>
//<![CDATA[
// Automatic Emoticons by Taufik Nurrohman
// http://gplus.to/tovic - http://dte.web.id
// Modification - Wordpress Emoticon For Blogger by Kang Mousir
// http://gplus.to/mousir - http://kang-mousir.blogspot.com

var emoRange = ".comment_reply_form,.div.comment-form,#comments p, div.post-body, div.emoWrap",
emoMessage = "Untuk menyisipkan emoticon setidaknya Anda harus menambahkan satu spasi di awal simbol.";
(function ($) {
$(document).ready(function () {
function emo(emo, imgRep, emoKey) {
$(emoRange).html(function () {
return $(this).html().replace(/<br ?\/?>(:|;|=|\^)/ig, "<br> $1").replace(emo, " <img src='" + imgRep + "' class='emo delayLoad' alt='" + emoKey + "' />")
})
}
emo(/\s:\)/g, "data:image/gif;base64,R0lGODlhDwAPALMOAP/qAEVFRQAAAP/OAP/JAP+0AP6dAP/+k//9E///////xzMzM///6//lAAAAAAAAACH5BAEAAA4ALAAAAAAPAA8AAARb0EkZap3YVabOGRcWcAgCnIMRTEEnCCfwpqt2mHEOagoOnz+CKnADxoKFyiHHBBCSAdOiCVg8KwPZa7sVrgJZQWI8FhB2msGgwTXTWGqCXP4WBQr4wjDDstQmEQA7", ":)");
emo(/\s:D/g, "data:image/gif;base64,R0lGODlhDwAPALMNAEVFRf/qAAAAAP/////OAP/JAP+0AP6dAP/+k//9E///x///6//lAAAAAAAAAAAAACH5BAEAAA0ALAAAAAAPAA8AAARZsEkJap241aUQIhcGcEkSnMQBTEBnnnC6aogpwHcAasqbB7mCCoD4wXCGSlHAbDqTANtgSh0IClACsEq9qjRaAfe6AxMYTvKXQiAU3m9ZpmKoG4YZlmU2iQAAOw==", ":D");
emo(/\s:\(/g, "data:image/gif;base64,R0lGODlhDwAPALMMAP/qAEVFRQAAAP/OAP/JAP6dAP+0AP/+k//9E///x//lAP//6wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAPAA8AAARYkEkZap2Y1ZXOGRcWcAgCnEMRTEEnnLCQrtrxwjGoJSZw+yeCKnDo/W4EQ+WAawKSlZ4zqAwMpieFcGU9Cb7fp04zGPwACpmKVSa43bNMxUA3DDMsC20SAQA7", ":(");
emo(/\s:\-\o/ig, "data:image/gif;base64,R0lGODlhDwAPALMNAP/qAEVFRQAAAP/////OAP/JAP6dAP+0AP/+k//9E///x//lAP//6wAAAAAAAAAAACH5BAEAAA0ALAAAAAAPAA8AAARbsEkZap24VaYQIhcWcEkCnIQRTEEnCCfwpquGmHEOagoOn7+CKnADxoKHCiLHBBSSAZzs9To9KwTgYLsVLISrQFbA7RZ2GgJhQTbTWOoC9azKVA74wzDDstQmEQA7", ":-o");
emo(/\s@@,/g, "data:image/gif;base64,R0lGODlhDwAPALMNAP///wAAAP/qAEVFRf/OAP/JAP+0AP6dAP/lAP/9E//+k///6///xwAAAAAAAAAAACH5BAEAAA0ALAAAAAAPAA8AAARXsEk5ap241cWUIhcWjEkinGMwBUAbnALrNnILvLUr77Gr264eMDCovVA24iCRgqFGhgrBSUUUDgPN9HksgCgEAsJpJWAng3BhvTZnMRWD3IB9ZzQWuyQCADs=", "@@,");
emo(/\s\:s/g, "data:image/gif;base64,R0lGODlhDwAPALMMAP/qAEVFRQAAAP/OAP/JAP6dAP+0AP/+k//9E///x//lAP//6wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAPAA8AAARYkEkZap2Y1ZXOGRcWcAgCnEMRTEEnCCfwpqt2mHEOagkOnz+CKnADxoKGyiHHBBCSAVzz9KwMpieFcBW4/mQvwk4zGCheMC2NVSa43WtRwEA3DDMsS20SAQA7", ":s");
emo(/\s:-d/ig, "data:image/gif;base64,R0lGODlhFwASALMMAEVFRf/qAP/////OAP/JAP6dAP/9E/+0AP/+k///x///6//lAP///wAAAAAAAAAAACH5BAEAAAwALAAAAAAXABIAAASDkMlJqwQY2F2xEBgnAt+nddlJkaXKYEqCIEM4seYdG0bgDwUVDnSR9XxI4AlnAyAMGCTgl2oVob5pQEsIglIa5xFJJhwypa+TzA6YPelvT8sGvOEtwGDb3nbBKS97dFkENSBxSwMDC2CGXkNEF4sElZVKJoArAAedB0FVaTabGaSBDBEAOw==", ":-d");
emo(/\s:wow:/ig, "data:image/gif;base64,R0lGODlhDwAPALMKAEVFRf/qAP/MAP////+pAP/+qP/9EzExMf///p4AAP///wAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFDAAKACwAAAAADwAPAAAETFBJCWqdWFVUurgYwBlGYAoEMAFdab6oqhXuC6tsWb17nAc7Uy/FshkDvtoRSRQsYSmNUxgUfChWKgAZW1k/FWs0BCCYzaCMxiKbRAAAIfkEBQwACgAsAwAEAAkABAAABBBQAaDqlGNQkOc527dRFhUBACH5BAUMAAoALAIAAwALAAkAAAQeUCkA5KwSjFE1n4PEhQqniWfZbeuXYZclz3QtJ3MEACH5BAUMAAoALAEAAgANAAgAAAQgUEkApKJ2jlHBrprEDWJHWmfpZanCXedYWt5bgzSOSREAIfkEBQwACgAsAQACAA0ACAAABCVQyWKkCsJOAMLl2SZ1wJgVpZWOBKqtCkB8Y5AC4dfpnhb0F2AEACH5BAUMAAoALAEAAgANAAgAAAQgUEkApKJ2jlHBrprEDWJHWmfpZanCXedYWt5bgzSOSREAIfkEBQwACgAsAQACAA0ACAAABCVQyWKkCsJOAMLl2SZ1wJgVpZWOBKqtCkB8Y5AC4dfpnhb0F2AEACH5BAUMAAoALAEAAgANAAgAAAQgUEkApKJ2jlHBrprEDWJHWmfpZanCXedYWt5bgzSOSREAIfkEBQwACgAsAQACAA0ACAAABCVQyWKkCsJOAMLl2SZ1wJgVpZWOBKqtCkB8Y5AC4dfpnhb0F2AEACH5BAUMAAoALAIAAwALAAkAAAQfUCkTpApVGgBq4NUmdcAoiAppXiDbWRicWXRt32MdAQAh+QQFDAAKACwDAAQACQAEAAAEC9CESSkAFoebqw8RADs=", ":wow:");
emo(/\s8\)/g, "data:image/gif;base64,R0lGODlhDwAPALMNAP/qAEVFRQAAAP/OAP/JAP6dAP+0AP/+k//9E///x//////lAP//6wAAAAAAAAAAACH5BAEAAA0ALAAAAAAPAA8AAARZsEkZap24VZbOGRcWcAgCnEMRTEFnnnC6ascLx2sr7DvA76rAgacQ+HZFQ+VwNJ54BGXAdoNFK4PqbUFQabJOmIAAogwGi99YxjoT3m+2KGCoG4IZlmU2iQAAOw==", "8)");
emo(/\s:x/ig, "data:image/gif;base64,R0lGODlhDwAPALMNAP/qAEVFRQAAAP/OAP/JAP+0AP6dAP/+k//9E///////x///6//lAAAAAAAAAAAAACH5BAEAAA0ALAAAAAAPAA8AAARbsEkZap241aXOGRcWcAgCnIMRTEEnnLCQrtphvicOaooJ/wCCKmADCHDGF6FQOcSeQWbAB4QtK4PY8QhgCFeBrCBBJgsIO81gsG3PWGuCXP4WBQr4wjDDstAmEQA7", ":x");
emo(/\s:P/ig, "data:image/gif;base64,R0lGODlhDwAPALMOAP/qAEVFRQAAAP/OAP8AAP/JAP+0AP6dAP/9E//+k///x///6zMzM//lAAAAAAAAACH5BAEAAA4ALAAAAAAPAA8AAARd0EkZap3Y1aVSGhcWcAgCnMMRTEEnCCfwpquWmHEOagoOn7+CKnADxoKGSiLHBBSSAROjCWA8KwPZa7sVrgJZAWE8FhR2msGgESAHziqWutB+0zIVg94wzLAsNRMRADs=", ":P");
emo(/\s:\|/g, "data:image/gif;base64,R0lGODlhDwAPALMMAP/qAEVFRQAAAP/OAP/JAP6dAP+0AP/+k//9E///x//lAP//6wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAPAA8AAARYkEkZap2Y1ZXOGRcWcAgCnEMRTEEnnKcgpKt2vHAOaokJ4L8TQRU4+IA4gqFyyDkByorvKVwGBtSTYri6/mRgAWGnGQwUuS2NZSa43WtRwEA3EDMsS20SAQA7", ":|");
emo(/\s;\)/g, "data:image/gif;base64,R0lGODlhDwAPALMMAP/qAEVFRQAAAP/OAP/JAP6dAP+0AP/+k//9E///x//lAP//6wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAPAA8AAARXkEkZap2Y1ZXOGRcWcAgCnEMRTEEnnDCQrtrxxjCoJSZw+y+CKnDo/WAEQ+WAwyUrvWZQGRg0TwKFcFX1xYI6zWCgEJizhBlrTGi31aKAYW4YZlgW2iQCADs=", ";)");
emo(/\s:lol:/ig, "data:image/gif;base64,R0lGODlhDwAPALMNAEVFRf/qAAAAAP/////OAP/JAP+0AP6dAP/9E//+k///x///6//lAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFFAANACwAAAAADwAPAAAEWrBJCWqduNWlUiIXBiyCgARBeQAToJhonK5UcgoxHoCacuspXGEFsMmOBUMlATymlABEaUotQQmpgXY7EAxZAKyA2y3wNAQCo2qmUdKFeJzgbgEMeAMxY7dkIgAh+QQFFAANACwCAAIACwAHAAAEE7BJJFuoOOvNq+if8GGiNAzZ2UQAIfkEBQoADQAsBQAHAAUAAgAABAVQSDlqjQAh+QQFCgANACwFAAcABQACAAAEBTBIKWqNACH5BAUKAA0ALAUABwAFAAIAAAQFUEg5ao0AIfkEBRQADQAsBQAHAAUAAgAABAUwSClqjQA7", ":lol:");
emo(/\s:oops:/ig, "data:image/gif;base64,R0lGODlhDwAPAMQfAPqzAP3KAOBsAPeOW//3zftoaP62dfecAP/Sh/ykaf+3t/6YmOdzSkVFRf/k5P/69f/MzP/qAPiAgP/86frXAP7jAPmmpv/8E/7Lg//+k+NfX9lINgAAAP/lmfrBewAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFFAAfACwAAAAADwAPAAAFZuAnik1ZjuhXTkSWBSfasNcV3cHRjE3L3UBObqfK/IBBmIpgixydOF0jY+M8rZEAoJSpUCrIiFdbugAAFGTlfC6dDwHwjQI42HcNQCBt5XjhRA0BcWqDOjyDiYmHMnlsUik8JkQjIQAh+QQFCgAfACwBAAEADQANAAAFUeAnfs9EEMY4ll2HvMYwmt9rf7FI1PadTi4ETwgbEFyiW82QIHgMmB7imUggBgyrzYMdVBmbQc8AZsgGA49QhEl4RQZoDxOXweP4ukpUrdpFIQAh+QQFMgAfACwBAAEADQANAAAFSOAnik65jKgDQUq7FGP5tfT3kjNdn2qbK7lXT1SbLSQOi0XXUh4VEs1CZ4lKrpqPhJotwK7LkeIlES2mzDPMfG6rUaLrdS0KAQAh+QQFCgAfACwBAAEADQANAAAFUOAnihNBGGM6dR3iGsNYfm79wSJB1za6ujvEDkZoiWw0Q4LgMWB4iGYigRgwqDWPdTBlfAY8g5cRGww8QhEmwRUZnDzMO+Z+2+cp0XRKF4UAACH5BAUKAB8ALAEAAQANAA0AAAVR4Cd+E5FlwTiW1xW9wTGa32t/sZjV9p0SrghPCDtkXKJbLQDIUAKVXuTJjBwEgB7legAABIJDLwA+yAAHilBUQQNEAWivEpfB4/i6SuT12kUhADs=", ":oops:");
emo(/\s:cry:/ig, "data:image/gif;base64,R0lGODlhDwAPAMQQAP/qAEVFRQAAAP/OAP/JAP6dAP+0AP/+k//9E///////x///6//lAACM2IG71l5eXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFHgAQACwAAAAADwAPAAAFXCAkikFZjihULspxDCcasAgC3EMRjEEr3EBBbqc6/IBBmEphQyIJusDBJjgCqgCCoXRwOrWlpvcGDgzGNwZ0Z75V31mlajB4IBmPIY9O6Pf1MgEGgwZRKTwmRCMhACH5BAUUABAALAQABQAHAAcAAAURICRA5EieZNKcTYK+MGyeQggAIfkEBQoAEAAsBAAIAAcAAQAABQZg4kCkk4QAIfkEBQoAEAAsBAAHAAcAAwAABQogII5AkoymiSYhACH5BAUKABAALAQACAAHAAMAAAULIABApEieZIJCSQgAIfkEBQoAEAAsBAAHAAcABAAABQ1g0gBkk5BoqgJC2wIhACH5BAUKABAALAQACAAHAAEAAAUGYOJApJOEACH5BAUKABAALAQABwAHAAMAAAUKICCOQJKMpokmIQAh+QQFCgAQACwEAAUABwAGAAAFDyAEQORInmgKmCKLJmkSAgA7", ":cry:");
emo(/\s:evil:/ig, "data:image/gif;base64,R0lGODlhDwAPAMQQAEVFRf/qAAAAAP/OAP/JAP6dAP/9E/+0AP8AAP/+k///x/4qAP5tA5aWlv/lAP//6wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAAPAA8AAAVpIABApGiSkLmYj5IkgyoyhaEYRqAPQ8GINUBORwT0AA1AwiAg6pqx5C0gaD6bhIJoKUBUqV0B4bClIhDEs5gsvBK/Y9HASXdkR8ZrFRsr8aw6DgJHKEYDBIiIhCgpAAePB1ojjIUmkyghADs=", ":evil:");
emo(/\s:twisted:/ig, "data:image/gif;base64,R0lGODlhDwAPAMQRAEVFRf/qAAAAAP/OAP6dAP/9E/+0AP8AAP/////+k//JAP//x/4qAJaWljMzM/5tA///6wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABEALAAAAAAPAA8AAAVrIABEpGiSkcmY0JIkgyo+RLEURaAPA/GINUBORwT0AA1AoiAg6pqx5C0gaD6bCoJoKThUqV2BwrClHg7Es5gsvBK/Y9Eg4HASHdmRscrvx0o8AgiDgwJHKEYxfEZaKCUABpEGWiOOiCaVKCEAOw==", ":twisted:");
emo(/\s:roll:/ig, "data:image/gif;base64,R0lGODlhDwAPALMNAEVFRf/qAAAAAP/OAP/JAP////6dAP+0AP/+k///x//9E//lAP//6wAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgANACwAAAAADwAPAAAEXrBJCWqduFWWEBoXBnCKEpyDAUxAJwhn8KarhghFAeM6qCW8XFCnAtx0uGTyUEHIXjsogQkwPWOvwLQyiHlPC4JK0/2eCD7yYAGAAtBjymBAqNdpmcphfyhmWBY1ExEAIfkEBQoADQAsBAAFAAgAAwAABAqwiFnkvFbYoGcEACH5BAUKAA0ALAQABAAHAAQAAAQLsIlG5ayz1Kb5LhEAIfkEBTIADQAsBAAEAAgAAwAABApQtNkkLbThgiePACH5BAUUAA0ALAkACgACAAIAAAQEsAnRIgAh+QQFCgANACwEAAQABwAEAAAEDbCURmUBtIErMOhahkUAIfkEBQAADQAsAgACAAsABwAABB2wSSEbrTJUXVX4zQcqQikEpkBMTdFaWFnJGxdyEQAh+QQFAAANACwCAAIACwAGAAAEFrBJJVuoOFehG7dBCIrKJwQmMV6hGAEAIfkEBQAADQAsAgACAAsABgAABBawSSEbrThLpVuYQmiFlFBIhYmW5ChGADs=", ":roll:");
emo(/\s:!:/ig, "data:image/gif;base64,R0lGODlhDwAPAMQdAP/qAEVFRf/OAP/JAP/9E/+0AP6dAP/+k///x391AP/lAAAAAL+vAP//68W1Bi8vL9LBBfPfBHFvV3JwWL+wAEpHKbGiAgMDA21rUxQUFOnXBvvnAFNPJgAAAAAAAAAAACH5BAEAAB0ALAAAAAAPAA8AAAVpYCeKQVmOaFc2yHEIJxqwBAHcghGMQWsnCwZORzrYAEAhbtc7Ii+UG2CgCxillox0Wigdto7KdtANOAEOzrgs2G4gUgWV2b5JHpPbAEYSCBQAGhgRcjk7fQIDioqGKSUFkAVVKTwmhyMhADs=", ":!:");
emo(/\s:\?\:/ig, "data:image/gif;base64,R0lGODlhDwAPAMQaAEVFRf/qAP/OAP/JAP6dAP+0AP/9E//+k+/bAH91AAAAAN/NAP//x8++AA8OAL+vAP/lAC8rAJ+SAP//6x8cAF9XAN+wAO+8AL+XAG9mAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABoALAAAAAAPAA8AAAV1oCaKQFmOqFZOzHEIJwqwhhHcAgGMQGsskooEEcjtVAcDwkFJUBSL4q5nS0ADy0xgoAMksY1bQ5HYFkqHm7rhiBAHZ4BNHWgTzSUB/aF43CBcU3piCVFbMCQCAhABVg+ARjyKAxYYFwORMgAFnAVdKTwmRyMhADs=", ":?:");
emo(/\s:idea:/ig, "data:image/gif;base64,R0lGODlhDwAPALMNAEVFRf/qAAAAAP/////OAP/JAP+0AP/9E/6dAP/+k///x//lAP//6wAAAAAAAAAAACH5BAEAAA0ALAAAAAAPAA8AAARdsEkJap24VaZSIhcGcMcRnAQCTEBnCjCqUsk73AK6tvaNBwUVoBYQ4H4FQyVxMg6cuWTF1Hw+T1IA4dSMBRbB3babA4IoBMKiCAOnVmhCoSCYvzMVg94gzLAscBMRADs=", ":idea:");
emo(/\s:arrow:/ig, "data:image/gif;base64,R0lGODlhDwAPALMMAP/qAEVFRQAAAP/OAP/JAP/9E/6dAP+0AP/+k///x//lAP//6wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAPAA8AAARXkEkZap2Y1ZUQGhcWcEUBnIMRTEFnnnC6asgLCEK8tvaJnwRVoHbDGXOEQwXhOxqTlZfzBw0MYLCfIri7ZnMAAogyGCiwWxmrTGi31aLAYX4QZliW2SQCADs=", ":arrow:");
emo(/\s:mrgreen:/ig, "data:image/gif;base64,R0lGODlhDwAPANUAAAAAAP///wDywwDuvwDsvgDqvADktwDitgDgtADcsQDarwDYrgDWrADSqQDOpgDKogDIoQDGnwDEngC+mQC8lwC4lAC0kQCyjwCujACqiQCohwCmhQCggQCcfQCafACWeQCOcgCKbwCGbACCaQB+ZQB8ZAB4YP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACcALAAAAAAPAA8AAAZ6wJNQCCgWh8hTcQJpKAxHJEBzoTQVh4IAMAR0NkWJY1EcbIkeAKYCeAASBwCBCwB9OBkLJeJgJBAGUAAhRoWFCUUiAAEBi4yOAA1FI5CMjY8QRSWVj48TdCSLjpcAF1xKJqGjRRsap6iqRh4dr0QAJSMiISBRSUqFSUEAOw==", ":mrgreen:");
var one = 0;
$(document.body).on("click", function () {
$('.emoKey').remove()
});
$('.emo').css('cursor', 'pointer').live("click", function (e) {
$('.emoKey').remove();
$(this).after('<input class="emoKey" type="text" size="6" value=" ' + this.alt + '" />');
$('.emoKey').trigger("select");
if (emoMessage && one === 0) {
alert(emoMessage);
one = 1
}
e.stopPropagation()
})
})
})(jQuery);
//]]>
</script>

Langkah Ketiga : Memasang Emoticon

Sebenarnya emoticon ini bisa simpan di mana saja, namun disini Saya akan menjelasakan emoticon ini di simpan di pesan komentar. Pertama masuk ke Setelan blogger Anda seperti gambar dibawah ini.
Setelan Komentar Blogger
Kemudian pada Pos dan Komentar isi dengan kode dibawah ini tepat di Pesan Formulir Komentar lalu Simpan.
 :) :D :( :-o @@, :s :wow: 8) :x :P :| ;) :lol: :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :arrow: :mrgreen: :-d 

Data Emoticon Wordpress Untuk Blogger

IconTeks
:) :)
:D :D
:( :(
:-o :-o
@@, @@,
:s :s
:wow: :wow:
8) :D
:x :x
:P :)
:| :|
;) ;)
:lol: :lol:
:oops: :oops:
:cry: :cry:
:evil: :evil:
:twisted: :twisted:
:roll: :roll:
:!: :!:
:?: :?:
:idea: :idea:
:arrow: :arrow:
:mrgreen: :mrgreen:
:-d :-d

Sabtu, 03 Agustus 2013

JQuery Find and Highlight Text

HTML, CSS & JQuery

<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="utf-8">
<title>JQuery Find and Highlight Text</title>
<style>
body {
background-color:white;
padding:40px 10px 10px;
font:normal normal 13px/1.4 Arial,Sans-Serif;
color:black;
}
.text-finder {
position:fixed;
top:0;
right:0;
left:0;
z-index:999;
background-color:white;
border-bottom:1px solid gray;
padding:5px 6px;
box-shadow:0 1px 2px rgba(0,0,0,.4);
}
.highlight {
background-color:yellow; /* highlight color */
font-weight:bold;
}
</style>
<script src="http://code.jquery.com/jquery-2.0.2.js"></script>
<script>
/*!
highlight v4
Highlights arbitrary terms.
<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
MIT license.
Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>
*/
(function($) {
$.fn.highlight = function(pat) {
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
} else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
return this.length && pat && pat.length ? this.each(function() {
innerHighlight(this, pat.toUpperCase());
}) : this;
};
$.fn.removeHighlight = function() {
return this.find("span.highlight").each(function() {
this.parentNode.firstChild.nodeName;
with (this.parentNode) {
replaceChild(this.firstChild, this);
normalize();
}
}).end();
};
})(jQuery);

// Text finder form function
(function($) {
$(document).ready(function() {
var $finder = $('#text-finder'),
$field = $finder.children().first(),
$clear = $field.next(),
$area = $(document.body),
$viewport = $('html, body');
$field.on("keyup", function() {
$area.removeHighlight().highlight(this.value); // Highlight text inside `$area` on keyup
$viewport.scrollTop($area.find('span.highlight').first().offset().top - 50); // Jump the viewport to the first highlighted term
});
$clear.on("click", function() {
$area.removeHighlight(); // Remove all highlight inside `$area`
$field.val('').trigger("focus"); // Clear the search field
$viewport.scrollTop(0); // Jump the viewport to the top
return false;
});
});
})(jQuery);
</script>
</head>
<body>

<form id="text-finder" class="text-finder" action="javascript:;">
<input type="text" placeholder="Find...">
<input type="reset" value="&times;">
</form>

Content goes here...

</body>
</html>

Selasa, 09 Juli 2013

JavaScript/JQuery - Cek Jika Latar Gambar Telah Termuat

Lakukan sesuatu jika latar gambar pada elemen #test-bg telah termuat.

Tidak ada fungsi bawaan khusus yang bisa digunakan untuk mengecek bahwa sebuah latar gambar telah termuat. Tetapi Anda bisa melakukan itu dengan cara mengambil URL latar gambar pada elemen yang Anda inginkan untuk Anda sisipkan ke dalam atribut src gambar palsu yang Anda buat melalui JavaScript. Mengapa gambar? Karena kita bisa mendeteksi event onload pada gambar:

JavaScript Mentah

function getBgUrl(el) {
var bg = "";
if (el.currentStyle) { // IE
bg = el.currentStyle.backgroundImage;
} else if (document.defaultView && document.defaultView.getComputedStyle) { // Firefox
bg = document.defaultView.getComputedStyle(el, "").backgroundImage;
} else { // try and get inline style
bg = el.style.backgroundImage;
}
return bg.replace(/url\(['"]?(.*?)['"]?\)/i, "$1");
}

var image = document.createElement('img');
image.src = getBgUrl(document.getElementById('test-bg'));
image.onload = function() {
alert('Loaded!'); // Test!
};

JQuery

var bg = $('#test-bg').css('background-image').replace(/url\(['"]?(.*?)['"]?\)/i, "$1");
$('<img />').attr('src', bg).on("load", function() {
alert('Loaded!'); // Test!
});

Minggu, 16 Juni 2013

Cross Browser HTML5 Placeholder

JQuery

$('[placeholder]').each(function() {
var plc = $(this).attr('placeholder');
$(this).addClass('blur').removeAttr('placeholder').val(plc).on("focus blur", function(e) {
// Add a `blur` class to fade the text color for the default placeholder text
$(this)[(e.type == "blur" && (this.value === "" || this.value == plc)) ? "addClass" : "removeClass"]('blur');
// Set the value to `plc` on blur if the element value is empty
if (e.type == "blur" && this.value === "") $(this).val(plc);
// Set the value to empty on focus if the element value is same with the default placeholder text
if (e.type == "focus" && this.value == plc) $(this).val("");
});
});

CSS

input.blur,
textarea.blur {color:#bbb}

Rabu, 29 Mei 2013

Aksesibilitas pada Soal Pilihan Ganda Online

Example of Accessible QA Form

Berbicara mengenai elemen formulir, umumnya elemen radio dan checkbox akan menjadi jenis elemen yang cukup sulit untuk ditangani oleh pihak pengguna karena ukurannya yang sangat kecil. Contoh sederhana:

<input type="radio" name="o"> Pilihan 1
<br>
<input type="radio" name="o"> Pilihan 2

Formulir di atas memang bekerja, tetapi tidak cukup nyaman untuk digunakan. Area yang bisa diklik hanya terfokus pada elemen radio saja yang ukurannya sangat kecil:

Aksesibilitas elemen radio yang kurang baik tanpa adanya elemen label.
Area pengecekan hanya terbatas pada elemen radio yang berukuran sangat kecil.

Mungkin tidak masalah jika orang yang mengisi formulir tersebut adalah orang-orang yang masih muda. Tetapi bagaimana jika yang mengisi formulir tersebut adalah para orangtua dan lanjut usia? Karena bagi mereka, mengarahkan mouse saja sudah kewalahan, apalagi mengeklik elemen radio yang ukurannya kecil seperti itu!

Selalu Ingat untuk Menambahkan Elemen Label

Untuk memperluas area pengecekan, kita bisa membungkus setiap opsi formulir dengan elemen label seperti ini:

<label><input type="radio" name="o"> Pilihan 1</label>
<br>
<label><input type="radio" name="o"> Pilihan 2</label>

Cara ini memungkinkan teks (atau elemen apa saja) yang berada di dalam elemen label tersebut untuk bisa bekerja sebagai pemicu perubahan kondisi radio yang merupakan anak dari label tersebut:

Aksesibilitas elemen radio yang lebih baik dengan penambahan elemen label.
Area pengecekan menjadi lebih luas, meliputi radio dan teks di sampingnya.

Kursor

Berikan elemen label dan semua jenis tombol dengan kursor jari telunjuk untuk meningkatkan kenyamanan:

input[type="button"],
input[type="submit"],
input[type="reset"],
button,
label {cursor:pointer}

Efek Timbal Balik

Perubahan warna saat opsi disentuh dan saat opsi terseleksi, semua itu akan memberikan rasa keyakinan kepada setiap pengguna yang sedang mengisi formulir Anda:

label:hover {background-color:whitesmoke}
label:active {background:none}
label.selected {background-color:forestgreen} /* Kelas `.selected` akan diciptakan oleh JavaScript */

Demonstrasi

Berikut ini adalah sebuah demonstrasi soal pilihan ganda online dengan akses jawaban yang mudah untuk kenyamanan pengguna:

HTML

<form class="qa-form" id="qa-form" action="...">
<ol>
<li>
<p>Uraian pertanyaan di sini ...</p>
<label><input type="radio" name="a-1"> Jawaban 1</label>
<label><input type="radio" name="a-1"> Jawaban 2</label>
<label><input type="radio" name="a-1"> Jawaban 3</label>
...
</li>
<li> ... </li>
</ol>
</form>

CSS

.qa-form {padding:1em 1em 2em}

.qa-form ol,
.qa-form li,
.qa-form p,
.qa-form input,
.qa-form label {
margin:0;
padding:0;
}

.qa-form ol {
list-style:decimal outside;
margin:0 0 2em 3em;
}

.qa-form p {
margin:1em 0;
clear:both;
}

.qa-form label {
display:block;
width:300px;
cursor:pointer;
overflow:hidden;
padding:5px 10px 5px 6px;
margin:0 0 2px;
line-height:100%;
border-radius:20px;
}

.qa-form label input {
outline:none;
vertical-align:top;
cursor:inherit;
}

.qa-form button {cursor:pointer}
.qa-form label:hover {background-color:whitesmoke}
.qa-form label:active {background:none}

.qa-form label.selected {
background-color:forestgreen;
color:white;
}

JQuery

// Fungsi ini digunakan untuk menambahkan/menyingkirkan
// kelas `.selected` pada elemen `<label>`
// berdasarkan kondisi radio di dalamnya
$(document).ready(function() {
$('#qa-form :radio').on("change", function() {
$(this).parent()[this.checked ? "addClass" : "removeClass"]('selected').siblings().removeClass('selected');
});
$('#qa-form :reset').on("click", function() {
$(this).closest('form').find('label').removeClass('selected').children().prop('checked', false);
});
});

Kesimpulan

Selalu pastikan bahwa pengguna bisa merasa nyaman dengan apa yang Anda berikan untuk mereka gunakan. Berikan efek timbal balik yang tegas kepada pengguna agar mereka yakin dengan apa yang telah mereka putuskan, sehingga hal-hal seperti kegagalan tes karena kesalahan antarmuka pengguna tidak akan terjadi.

Jumat, 03 Mei 2013

Jalan Pintas untuk Menangani Perintah-Perintah JQuery di dalam Peraturan Kondisi

Dalam sebuah forum Saya pernah sekali diajari mengenai cara tersingkat untuk menangani perintah-perintah JQuery di dalam peraturan kondisi yang biasa dituliskan seperti ini:

if (statement) {
$(selector).method1();
} else {
$(selector).method2();
}

Kode di bawah ini adalah jalan pintas untuk kondisional di atas:

$(selector)[statement ? "method1" : "method2"]();

Pada awalnya Saya merasa bingung dengan sudut pandang yang orang tersebut berikan, sampai kemudian Saya menyadari bahwa pada dasarnya ini hanyalah sebuah jalan pintas peraturan if/else untuk memanggil item objek yang berbeda berdasarkan kondisi tertentu.

JQuery, pada dasarnya hanyalah sekumpulan fungsi yang dinyatakan di dalam objek. Kurang lebihnya seperti ini (memang tidak sama persis seperti ini, tapi setidaknya lumayan mirip):

var foo = {
addClass: function(param) { ... },
removeClass: function(param) { ... },
toggleClass: function(param) { ... },
hasClass: function(param) { ... }
...
}

Sehingga setiap fungsi bisa dipanggil dengan cara seperti ini:

foo.addClass('bar');
foo.removeClass('bar');

Atau seperti ini:

foo["addClass"]('bar');
foo["removeClass"]('bar');

Katakanlah kita ingin memanggil fungsi tertentu di dalam foo hanya jika suatu kondisi terpenuhi. Jika kondisi tidak terpenuhi, maka fungsi cadangan yang lain akan dijalankan:

if (abc === true) {
foo["removeClass"]('bar');
} else {
foo["addClass"]('bar');
}

Yang mana jika diubah ke pernyataan kondisional ringkas akan menjadi seperti ini:

var x = (abc === true) ? "removeClass" : "addClass";
foo[x]('bar');

Sehingga kita bisa menyimpulkannya menjadi seperti ini:

foo[abc === true ? "removeClass" : "addClass"]('bar');

Contoh Penerapan

Berikut ini adalah contoh penerapan kondisional jalan pintas untuk menangani perintah .slideDown() dan .fadeOut() berdasarkan visibilitas panel:

Sebelum

$('h2').click(function() {
$(this).toggleClass('active');
if ($(this).next().is(':hidden')) {
$(this).next().slideDown();
} else {
$(this).next().fadeOut();
}
});

Sesudah

$('h2').click(function() {
$(this).toggleClass('active')
.next()[$(this).next().is(':hidden') ? "slideDown" : "fadeOut"]();
});

Senin, 22 April 2013

Membuat Navigasi Halaman AJAX pada Blogger

Prinsipnya sederhana. Di sini Saya menggunakan navigasi Posting Lebih Lama sebagai navigasi AJAX dan menggunakan JQuery $.get() untuk memanggil URL pada navigasi tersebut:

// Menyingkirkan navigasi posting lebih baru (Navigasi ini tidak diperlukan)
$('#blog-pager').find('#blog-pager-newer-link').remove();

// Dasar AJAX navigasi
$('#blog-pager').on("click", "#blog-pager-older-link a", function() {
$.get(this.href, {}, function(data) {
// Proses...
}, "html");
return false;
});

Kita akan menggunakan elemen .blog-posts untuk memuat posting-posting baru dari halaman selanjutnya.

Menerapkan AJAX pada Navigasi Halaman

Pastikan JQuery sudah terpasang pada template. Masuk ke editor HTML template, kemudian salin kode ini dan letakkan di atas </body>:

<b:if cond='data:blog.pageType != &quot;item&quot;'>
<b:if cond='data:blog.pageType != &quot;static_page&quot;'>
<script type='text/javascript'>
//<![CDATA[
(function($) {
var $pager = $('#blog-pager'),
$posts = $('.blog-posts');
$pager.find('#blog-pager-newer-link').remove(); // Menyingkirkan navigasi posting lebih baru
$pager.on("click", "#blog-pager-older-link a", function() {
$.get(this.href, {}, function(data) {
var source = $(data).find('.post').length ? $(data) : $('<div></div>');
$posts.append(source.find('.blog-posts').html()); // Menyisipkan posting
$pager.html(source.find('#blog-pager-older-link').clone()); // Memperbaharui navigasi
}, "html");
$(this).replaceWith('<span>Memuat...</span>'); // Ubah navigasi posting menjadi indikator memuat saat sedang memuat
return false;
});
})(jQuery);
//]]>
</script>
</b:if>
</b:if>

Klik Simpan Template.

Sekarang coba buka halaman blog Anda kemudian klik navigasi Posting Lama atau Older Post. Jika navigasi tersebut berubah menjadi teks bertuliskan “memuat...” seperti ini, maka itu artinya AJAX sedang bekerja:

Ini adalah gambar navigasi halaman yang sedang memuat halaman baru dengan AJAX
Indikator sedang memuat

Tunggu sampai posting-posting baru muncul di bawah posting-posting yang sedang terlihat saat ini.

Infinite Scroll (?)

Untuk menciptakan infinite scroll pada sistem navigasi halaman, cukup nyatakan event .scroll() pada $(window) dan cek apakah jarak gulungan layar telah mencapai batas akhir atau belum. Jika ya, picu event .click() pada navigasi AJAX yang telah kita buat sebelumnya.

Dalam kasus ini, Saya menentukan batas akhir gulungan layar bukan berdasarkan tinggi halaman, melainkan berdasarkan posisi navigasi terhadap bagian teratas dari layar:

(function($) {

var $pager = $('#blog-pager'),
$posts = $('.blog-posts'),
loading = false;

// AJAX
$pager.find('#blog-pager-newer-link').remove(); // Menyingkirkan navigasi posting lebih baru
$pager.on("click", "#blog-pager-older-link a", function() {
$.get(this.href, {}, function(data) {
var source = $(data).find('.post').length ? $(data) : $('<div></div>');
$posts.append(source.find('.blog-posts').html());
$pager.html(source.find('#blog-pager-older-link').clone());
loading = false;
}, "html");
$(this).replaceWith('<span>Memuat...</span>'); // Ubah navigasi posting menjadi indikator memuat saat sedang memuat
return false;
});

// INFINITE SCROLL
$(window).on("scroll resize", function() {
// Jika AJAX sedang tidak memuat dan jika jarak gulungan layar + tinggi layar telah mencapai
// tinggi yang sama dengan/lebih besar dari offset navigasi halaman terhadap bagian teratas dari layar...
if (!loading && ($(this).scrollTop() + $(this).height()) >= $pager.offset().top) {
$pager.find('#blog-pager-older-link a').trigger("click"); // Picu event `.click()` pada navigasi AJAX posting
loading = true; // Mulai antre pemuatan
}
});

})(jQuery);

Catatan: JavaScript Auto Read-More akan tereksekusi saat halaman dimuat dengan cara biasa, sehingga jangan kaget jika posting-posting baru yang dimuat oleh AJAX tidak akan terpotong menjadi ringkasan posting. Saya sarankan Anda untuk menggunakan konsep ringkasan posting tanpa JavaScript yang pernah Saya tuliskan sebelumnya di sini.

Minggu, 24 Maret 2013

Catatan Pembaharuan JQuery

Baru: Fitur baru ditambahkan ke dalam perpustakaan

Deprecated/Usang: Fitur sudah usang, dan akan disingkirkan suatu saat nanti. Alasan sebuah fitur/API menjadi usang biasanya adalah karena beberapa fitur baru yang ditambahkan memiliki kemampuan yang lebih baik dibandingkan dengan fitur yang lama sehingga disarankan untuk beralih ke metode yang baru dan melupakan metode yang lama. Selain itu, perbaikan struktur perpustakaan juga menjadi salah satu penyebab.

Disingkirkan: Fitur benar-benar disingkirkan dari perpustakaan. Anda sudah tidak bisa lagi memakai fitur-fitur yang sudah disingkirkan jika Anda menggunakan JQuery pada versi tersebut.

Versi 1.0

Daftar API untuk JQuery versi 1.0:

  1. .add()
  2. .addClass()
  3. .after()
  4. .ajaxComplete()
  5. .ajaxError()
  6. .ajaxSend()
  7. .ajaxStart()
  8. .ajaxStop()
  9. .ajaxSuccess()
  10. .animate()
  11. .append()
  12. .appendTo()
  13. .attr()
  14. .before()
  15. .bind()
  16. .blur()
  17. .change()
  18. .children()
  19. .click()
  20. .clone()
  21. .css()
  22. .dblclick()
  23. .each()
  24. .empty()
  25. .end()
  26. .error()
  27. event.preventDefault()
  28. event.stopPropagation()
  29. event.target
  30. event.type
  31. .fadeIn()
  32. .fadeOut()
  33. .fadeTo()
  34. .filter()
  35. .find()
  36. .focus()
  37. .get()
  38. .height()
  39. .hide()
  40. .hover()
  41. .html()
  42. .index()
  43. .insertAfter()
  44. .insertBefore()
  45. .is()
  46. jQuery.ajax()
  47. jQuery.boxModel
  48. jQuery.browser
  49. jQuery.each()
  50. jQuery.extend()
  51. jQuery.get()
  52. jQuery.getJSON()
  53. jQuery.getScript()
  54. jQuery.grep()
  55. jQuery.map()
  56. jQuery.merge()
  57. jQuery.noConflict()
  58. jQuery.post()
  59. jQuery.trim()
  60. .keydown()
  61. .keypress()
  62. .keyup()
  63. .length
  64. .load() (AJAX)
  65. .load() (Event)
  66. .mousedown()
  67. .mouseenter()
  68. .mouseleave()
  69. .mousemove()
  70. .mouseout()
  71. .mouseover()
  72. .mouseup()
  73. .next()
  74. .not()
  75. .parent()
  76. .parents()
  77. .prepend()
  78. .prependTo()
  79. .prev()
  80. .ready()
  81. .pushStack()
  82. .remove()
  83. .removeAttr()
  84. .removeClass()
  85. .resize()
  86. .scroll()
  87. .select()
  88. .serialize()
  89. .show()
  90. .siblings()
  91. .size()
  92. .slideDown()
  93. .slideToggle()
  94. .slideUp()
  95. .submit()
  96. .text()
  97. .toggle() (Efek)
  98. .toggle() (Event)
  99. .toggleClass()
  100. .trigger()
  101. .unbind()
  102. .unload()
  103. .val()
  104. .width()
  105. .wrap()

Daftar API untuk selektor:

  1. * All Selector
  2. [name|="value"] Attribute Contains Prefix Selector
  3. [name*="value"] Attribute Contains Selector
  4. [name~="value"] Attribute Contains Word Selector
  5. [name$="value"] Attribute Ends With Selector
  6. [name="value"] Attribute Equals Selector
  7. [name!="value"] Attribute Not Equal Selector
  8. [name^="value"] Attribute Starts With Selector
  9. :button
  10. :checkbox
  11. :checked
  12. parent > child Child Selector
  13. .class Class Selector
  14. ancestor descendant Descendant Selector
  15. :disabled
  16. tag Element Selector
  17. :empty
  18. :enabled
  19. :eq()
  20. :even
  21. :file
  22. :first
  23. :gt()
  24. [attribute] Has Attribute Selector
  25. :hidden
  26. #id ID Selector
  27. :image
  28. :input
  29. :last
  30. :lt()
  31. [name="value"][name2="value2"] Multiple Attribute Selector
  32. selector1, selector2, selectorN Multiple Selector
  33. prev + next Next Adjacent Selector
  34. prev ~ siblings Next Siblings Selector
  35. :not()
  36. :odd
  37. :parent
  38. :password
  39. :radio
  40. :reset
  41. :selected
  42. :submit
  43. :text
  44. :visible

Versi 1.0.4

Baru:

  1. event.metaKey
  2. event.pageX
  3. event.pageY
  4. jQuery.globalEval()

Versi 1.1

Baru:

  1. event.data
  2. jQuery.ajaxSetup()
  3. .one()

Memperbaharui .attr(), dari sebelumnya yang hanya berfungsi untuk mendapatkan nilai atribut elemen menjadi berfungsi untuk mendapatkan atribut dan juga mengeset atribut dalam berbagai cara seperti ini:

// Konsep awal
var src = $('img').attr('src');

// Mengeset nilai atribut
$('img').attr('src', '/path/to/image.jpg');

// Mengeset beberapa atribut sekaligus
$('img').attr({
alt: 'My profile photo',
src: '/path/to/image.jpg'
});

// Concat/menyisipkan nilai atribut baru tanpa menghilangkan nilai atribut awal
$('img').attr('id', function(i, value) {
return value + '-main';
});

Versi 1.1.2

Baru:

  1. .eq()

Versi 1.1.3

Baru:

  1. jQuery.browserjQuery.browser.version
  2. event.which
  3. jQuery.unique()

Versi 1.1.4

Baru:

  1. event.relatedTarget
  2. jQuery.isXMLDoc()
  3. .slice()
  4. :contains()
  5. :first-child
  6. :last-child
  7. :has()
  8. :nth-child()
  9. :only-child

Versi 1.2

Baru:

  1. .andSelf()
  2. .contents()
  3. .dequeue()
  4. .hasClass()
  5. .map()
  6. .nextAll()
  7. .offset()
  8. .position()
  9. .prevAll()
  10. .queue()
  11. .replaceAll()
  12. .replaceWith()
  13. .serializeArray()
  14. .stop()
  15. .triggerHandler()
  16. .wrapAll()
  17. .wrapInner()
  18. :animated
  19. :header
  20. jQuery.inArray()
  21. jQuery.isFunction()
  22. jQuery.makeArray()
  23. jQuery.param()

Versi 1.2.3

Baru:

  1. .data()
  2. .removeData()
  3. jQuery.data()
  4. jQuery.removeData()

Versi 1.2.6

Baru:

  1. event.timeStamp
  2. .innerHeight()
  3. .innerWidth()
  4. .outerHeight()
  5. .outerWidth()
  6. .scrollLeft()
  7. .scrollTop()

Versi 1.3

Baru:

  1. .closest()
  2. .context
  3. .die()
  4. event.currentTarget
  5. event.isDefaultPrevented()
  6. event.isImmediatePropagationStopped()
  7. event.isPropagationStopped()
  8. event.result
  9. event.stopImmediatePropagation()
  10. jQuery.dequeue()
  11. jQuery.fx.off
  12. jQuery.isArray()
  13. jQuery.queue()
  14. jQuery.support
  15. .live()
  16. .pushStack()
  17. .toggleClass()

Menerapkan .toggle() tanpa parameter durasi dan/atau callback akan menghasilkan sikap tampil dan menghilang, tanpa efek:

// Dasar
$('div').click(function() {
$(this).toggle(600);
});

// Penerapan seperti ini bisa dilakukan di JQuery 1.3
$('div').click(function() {
$(this).toggle(); // Lebih baik dibandingkan dengan `$(this).toggle(0)`
});

Deprecated/Usang:

  1. jQuery.boxModel
  2. jQuery.browser

Versi 1.4

Baru:

  1. .clearQueue()
  2. .delay()
  3. .detach()
  4. .first()
  5. .focusin()
  6. .focusout()
  7. .has()
  8. jQuery() (pembaharuan kecil)
  9. jQuery.contains()
  10. jQuery.isEmptyObject()
  11. jQuery.isPlainObject()
  12. jQuery.noop()
  13. jQuery.proxy()
  14. .last()
  15. .nextUntil()
  16. .not()
  17. .parentsUntil()
  18. .prevUntil()
  19. .toArray()
  20. .unwrap()

Pembaharuan .addClass() dan .removeClass(), yang kini bisa menerima fungsi anonim untuk keperluan bypass/jalan pintas seperti ini:

// KASUS: Menambahkan kelas dengan akhiran berupa indeks elemen

// Cara panjang: Menggabungkan `.each()` dengan `.addClass()`
$('ul li').each(function(index) {
$(this).addClass('item-' + index);
});

// Jalan pintas dengan fungsi anonim
$('ul li').addClass(function(index) {
return 'item-' + index;
});

// Contoh untuk `.removeClass()`
$('ul li').removeClass(function(index) {
return $(this).prev().attr('class')
});

Pembaharuan .before(), .after(), .css(), .filter(), .html(), .text(), dan beberapa fungsi yang sudah ada yang kini bisa menerima fungsi anonim untuk keperluan jalan pintas. Selengkapnya baca di dokumentasi. Berikut ini adalah beberapa contoh:

// `.before()`
$('p').before(function(index) {
return '<div class="new-class-' + index + '"></div>';
});

// `.after()`
$('p').after(function(index) {
return '<div class="new-class-' + index + '"></div>';
});

// `.css()`
$('div').css("border", function(i) {
return (i + 1) + 'px solid black';
});

$('div').css({
"border": function(index) {
return (index + 1) + 'px solid black'
},
"background-color": function(index) {
return '#' + (index < 7 ? index : "a") + '00'
}
});

// `.filter()`
$('li').filter(function() {
return $('strong', this).length == 1;
}).css('background-color', 'red');

// dst...

Pembaharuan .offset(), yang kini bisa menerima argumen koordinat untuk mengeset posisi elemen. Sebelumnya hanya berfungsi untuk mendapatkan posisi elemen dari dokumen:

// Sebelum 1.4
var top = $('div').offset().top;
var left = $('div').offset().left;

// 1.4
$('div').offset({
top: 30,
left: 200
});

Versi 1.4.1

Baru:

  1. jQuery.error()
  2. jQuery.parseJSON()

Dan beberapa pembaharuan kecil.

Versi 1.4.2

Baru:

  1. .delegate()
  2. .undelegate()

Versi 1.4.3

Baru:

  1. event.namespace
  2. jQuery.cssHooks
  3. jQuery.fx.interval
  4. jQuery.isWindow()
  5. jQuery.now()
  6. jQuery.type()

Memungkinkan menerapkan easing pada .show(), .hide(), .toggle(), .slideDown(), .slideUp(), .slideToggle(), .fadeIn(), .fadeOut() dan .fadeTo()

// Sebelum 1.4.3
$('div').slideDown(400, function() {
alert("Complete!");
});

// 1.4.3
$('div').slideDown(400, "swing", function() {
alert("Complete!");
});

Versi 1.4.4

Baru:

  1. .fadeToggle()

Versi 1.5

  1. deferred.done()
  2. deferred.fail()
  3. deferred.isRejected()
  4. deferred.isResolved()
  5. deferred.promise()
  6. deferred.reject()
  7. deferred.rejectWith()
  8. deferred.resolve()
  9. deferred.resolveWith()
  10. deferred.then()
  11. jQuery.ajaxPrefilter()
  12. jQuery.ajaxTransport()
  13. jQuery.Deferred()
  14. jQuery.hasData()
  15. jQuery.parseXML()
  16. jQuery.sub()
  17. jQuery.when()

Versi 1.5.1

Pembaharuan jQuery.ajax() dan jQuery.support

Versi 1.6

Baru:

  1. deferred.always()
  2. deferred.pipe()
  3. jQuery.holdReady()
  4. jQuery.map()
  5. .promise()
  6. .prop()
  7. .removeProp()
  8. :focus

Pembaharuan .is() yang kini bisa menerima fungsi anonim untuk melakukan pengecekan yang lebih kompleks dibandingkan dengan pengecekan sebelumnya yang hanya berdasarkan selektor:

// Sebelum 1.6
if ($('#foo').is('input')) {
$('#foo').val("");
} else {
$('#foo').html("");
}

// 1.6
var fooHasChildren = $('#foo').is(function() {
return $(this).children().length;
});
if (fooHasChildren) {
$('#foo').children().addClass('item');
} else {
$('#foo').addClass('empty');
}

Versi 1.7

Baru:

  1. callbacks.add()
  2. callbacks.disable()
  3. callbacks.disabled()
  4. callbacks.empty()
  5. callbacks.fire()
  6. callbacks.fired()
  7. callbacks.fireWith()
  8. callbacks.has()
  9. callbacks.lock()
  10. callbacks.locked()
  11. callbacks.remove()
  12. deferred.notify()
  13. deferred.notifyWith()
  14. deferred.progress()
  15. deferred.state()
  16. event.delegateTarget
  17. jQuery.Callbacks()
  18. jQuery.isNumeric()
  19. .off()
  20. .on()

Pembaharuan .removeAttr(), yang kini bisa menghapus beberapa atribut sekaligus dalam satu kali eksekusi dengan cara menuliskan beberapa nama atribut terpisah oleh spasi:

// Sebelum 1.7
$('img').removeAttr('title').removeAttr('src').removeAttr('alt');

// 1.7
$('img').removeAttr('title src alt');

Deprecated/Usang:

  1. deferred.isRejected() digantikan oleh deferred.state()
  2. deferred.isResolved() digantikan oleh deferred.state()
  3. .die() digantikan oleh .off()
  4. jQuery.sub()
  5. .live() digantikan oleh konteks yang lebih kecil untuk performa yang lebih baik, dengan JQuery .on()
  6. .selector
// Usang
$('a').live("click", function() {
alert('OK!');
});

// Baru
$(document.body).on("click", "a", function() {
alert('OK!');
});

// Disarankan, jika ada induk statis yang lebih dekat, gunakan induk itu sebagai konteks
// Mirip dengan `$('#container').delegate("a", "click", function() {})`
$('#container').on("click", "a", function() {
alert('OK!');
});

Versi 1.8

Baru:

  1. .addBack()
  2. jQuery.parseHTML()

Pembaharuan selektor :eq() yag kini bisa menyeleksi urutan elemen melalui alur mundur dengan menuliskan nilai berupa angka negatif.

Deprecated/Usang:

  1. .andSelf() digantikan oleh .addBack()
  2. deferred.pipe()
  3. .error()
  4. jQuery.error()
  5. .load() (Event)
  6. .size() digantikan oleh kembarannya .length
  7. .toggle() (Event)
  8. .unload()

Versi 1.9

Baru:

  1. .finish()
  2. :first-of-type
  3. :lang
  4. :last-of-type
  5. :nth-last-child()
  6. :nth-last-of-type()
  7. :nth-of-type()
  8. :only-of-type
  9. :root
  10. :target

Pembaharuan untuk .css(), yang sebelumnya hanya bisa mendapatkan satu nilai properti saja setiap kali eksekusi, sekarang kita bisa menggunakan array untuk mengelompokkan properti-properti CSS yang ingin didapatkan, sedangkan hasilnya nanti akan berubah menjadi objek:

// Sebelum 1.9
var width = $('div').css('width');
var height = $('div').css('height');
var paddTop = $('div').css('padding-top');

// 1.9
var props = $('div').css(["width", "height", "padding-top"]); // Hasil => `props = {width:N,height:N,padding-top:N}`
var width = props.width;
var height = props.height;
var paddTop = props["padding-top"];

Disingkirkan:

  1. .toggle() (Event)
  2. jQuery.browser()
  3. .live()
  4. .die()
  5. jQuery.sub()

Minggu, 10 Maret 2013

Mendapatkan Tinggi dan Lebar Layar Monitor

Versi JQuery

var x = $(window).width(),
y = $(window).height();

// Tampilkan lebar dan tinggi layar dalam kotak pesan
alert('Lebar layar: ' + x + '; Tinggi layar: ' + y);

Versi JavaScript Murni

var w = window,
d = document,
e = d.documentElement,
g = d.body,
x = w.innerWidth || e.clientWidth || g.clientWidth, // x = Lebar layar
y = w.innerHeight || e.clientHeight || g.clientHeight; // y = Tinggi layar

// Tampilkan lebar dan tinggi layar dalam kotak pesan
alert('Lebar layar: ' + x + '; Tinggi layar: ' + y);

Minggu, 24 Februari 2013

AJAX JQuery: Memuat Beberapa Bagian Halaman Sekaligus Dalam Satu Kali Permintaan

Ini adalah metode dasar yang sering Anda gunakan untuk memuat sebagian halaman ke dalam kontainer yang sudah dipersiapkan menggunakan AJAX. Di sini Saya menggambarkan Anda akan memuat elemen #content dari halaman /p/sample-page.html ke dalam elemen #container:

$('button').on("click", function() {
$('#container').load('/p/sample-page.html #content');
});

Setelah tombol diklik, maka elemen #content dari halaman /p/sample-page.html akan termuat di dalam elemen #container. Ini adalah kasus yang sederhana. Namun kasus ini akan menjadi lebih rumit ketika Anda ingin memuat beberapa bagian dari halaman lain secara bersamaan dalam satu kali permintaan. Sebagai contoh, Anda ingin memuat bagian posting, navigasi halaman dan komentar secara bersamaan dalam satu kali permintaan HTTP ke dalam beberapa kontainer yang sudah dipersiapkan. Berikut ini adalah cara yang tidak efisien:

$('button').on("click", function() {
$('#container-1').load('http://blog.my_site.com/p/sample-page.html .post');
$('#container-2').load('http://blog.my_site.com/p/sample-page.html #nav');
$('#container-3').load('http://blog.my_site.com/p/sample-page.html #comments');
});

Lebih Efisien: Gunakan $.get()

Jangan memakai JQuery .load() untuk memuat beberapa bagian halaman sekaligus. Tapi gunakan JQuery $.get():

$('button').on("click", function() {
$.get('http://blog.my_site.com/p/sample-page.html', function(data) {
$('#container-1').html($(data).find('.post'));
$('#container-2').html($(data).find('#nav'));
$('#container-3').html($(data).find('#comments'));
});
});

Pada metode ini, Anda mengeklik sebuah tombol. Kemudian permintaan akan terjadi. Setelah proses permintaan berhasil dilakukan dan halaman yang diminta berhasil dipanggil, maka halaman tersebut tidak akan langsung dimuat ke dalam area/kontainer yang sudah dipersiapkan, melainkan masih berada di dalam parameter data.

Pada kasus ini, parameter data bisa disamakan sebagai keseluruhan HTML dari halaman http://blog.my_site.com/p/sample-page.html.

Dari parameter tersebut Anda bisa menelusuri bagian-bagian halaman lainnya dengan cara menyeleksi elemen yang diinginkan di dalam $(data) untuk kemudian bisa dimuat ke dalam kontainer yang diinginkan melalui JQuery manipulasi DOM seperti .html(), .text(), .append() dan .prepend() atau yang lainnya.

Demo?

Jika Anda sedang menggunakan peramban Firefox, klik pada menu drop-down di pojok kiri atas. Pilih menu Web Developer kemudian klik sub menu Scratchpad (Atau cukup tekan tombol Shift + F4). Salin kode di bawah ini kemudian tempelkan di dalam editor Scratchpad:

$('a').click(function() {
$.get(this.href, function(data) {
$('.post').html($(data).find('.post').html());
$('#blog-pager').html($(data).find('#blog-pager').html());
$('#comments').html($(data).find('#comments').html());
}, 'html');
return false;
});

Klik menu Execute dan pilih Run:

Firefox ScratchPad
Setelah kode ditempelkan, pilih menu Execute kemudian klik Run.

Sekarang klik salah satu tautan pada daftar entri/posting populer di sidebar blog ini dan tunggu beberapa saat sampai bagian dari halaman tersebut termuat. Jika berhasil, maka bagian yang akan berganti isinya adalah ada pada posting, navigasi halaman blog dan isi komentar (isi posting akan berubah, tautan navigasi halaman akan berubah dan isi komentar juga akan berubah).

Catatan dan Tambahan

JQuery .load() bisa menerima beberapa selektor sekaligus, jika Anda tidak tahu:

// Memuat `#sidebar`, `#comments` dan `#blog-pager`
// dari `http://abc_site.com/sample-page.html` ke dalam `#container`
$('#container').load('http://abc_site.com/sample-page.html #comments,#sidebar,#blog-pager');

Jika proses pemuatan menggunakan $.get() gagal (yang Saya alami adalah muncul pesan error TypeError: n.innerHTML is undefined), cobalah untuk menggunakan pola ini:

$.get('http://abc_site.com/sample-page.html', {}, function(data) {
// Lakukan sesuatu dengan `$(data)`
}, 'html');

Selasa, 19 Februari 2013

Membangun Layout Paralaks dengan JQuery

JQuery Parallax layout

Membuat layout paralaks, jika Anda masih kesulitan untuk memahami bagaimana cara kerja dan cara membuatnya, di sini Saya akan menjelaskannya dengan rinci mengenai bagaimana layout tersebut tercipta. Pada dasarnya, sebuah layout paralaks hanyalah elemen HTML dengan beberapa tumpukan layer di dalamnya, dimana setiap layer tersebut akan dianimasikan posisinya dengan kecepatan yang sama namun dengan jarak yang berbeda untuk menciptakan efek tiga dimensi saat layer-layer tersebut bergerak.

Membuat Latar Paralaks

Kita mulai dengan elemen HTML seperti ini:

<div id="parallax-wrapper" class="parallax-wrapper">
<div class="layer layer-1"></div>
<div class="layer layer-2"></div>
<div class="layer layer-3"></div>
...
...
</div>

Saya membuat sebuah elemen HTML sebagai kontainer dengan beberapa layer di dalamnya. Elemen utamanya adalah #parallax-wrapper. Elemen ini berfungsi sebagai wadah dari semua elemen paralaks di dalamnya. Sedangkan elemen-elemen .layer nantinya akan kita gunakan sebagai penampil latar. Kita akan memposisikan layer-layer tersebut menjadi bertumpukan layaknya tumpukan kaca. Jadi kita memerlukan ini untuk mengatur dimensi paralaks yang kita buat:

.parallax-wrapper {
border:1px solid black;
height:200px; /* Tentukan tinggi area paralaks, ukuran lebar tidak begitu penting */
position:relative; /* Penting! Posisi absolut pada elemen induk */
overflow:hidden;
}

/* Buat semua layer paralaks sebagai elemen absolut,
sehingga tampilannya akan bertumpuk satu sama lainnya */
.parallax-wrapper .layer {
position:absolute;
top:0;
right:0;
bottom:0;
left:0;
/* set beberapa pengaturan latar di sini,
sebelum kita mendefinisikan latar gambar secara sepihak
pada masing-masing layer */
background-position:0 0;
background-color:transparent;
background-repeat:repeat-x;
}

Setelah itu, gambar-gambar bisa diterapkan pada masing-masing layer:

.parallax-wrapper .layer-1 {background-image:url('img/parallax-bg-1.png')}
.parallax-wrapper .layer-2 {background-image:url('img/parallax-bg-2.png')}
.parallax-wrapper .layer-3 {background-image:url('img/parallax-bg-3.png')}

Navigasi Paralaks

Navigasi ini digunakan untuk menggerakkan latar paralaks —dan konten di dalamnya tentunya, agar paralaks tidak hanya berfungsi sebagai hiasan. Navigasi terdiri dari elemen <span> dengan beberapa tautan di dalamnya. Anda bisa membuatnya menggunakan elemen apa saja, tapi di sini Saya mencoba untuk membuatnya seminimalis mungkin:

<span id="parallax-navigation" class="parallax-navigation">
<a href="#1">1</a>
<a href="#2">2</a>
<a href="#3">3</a>
<a href="#4">4</a>
...
...
</span>

CSS untuk navigasinya:

.parallax-navigation {
display:block;
height:30px;
line-height:30px;
position:relative;
text-align:right;
font-size:11px;
font-weight:bold;
}

.parallax-navigation a {
text-decoration:none;
color:black;
background-color:#eee;
padding:5px 10px;
}

/* set latar dan warna yang berbeda untuk item navigasi yang sedang aktif */
.parallax-navigation a.active {
background-color:#529834;
color:white;
}

Selesai sampai di sini, sekarang kita akan mengerjakan fungsi dasar untuk menggerakkan layer:

Efek Paralaks

Beberapa mungkin akan membuat efek paralaks dengan cara menganimasikan properti left pada elemen relatif untuk menggerakkan elemen ke kiri atau ke kanan. Tapi kekurangannya adalah, mengubah jarak left terlalu jauh akan membuat posisi layer berubah dan pada akhirnya akan menghilang dari pandangan jika jaraknya sudah terlalu jauh. Di sini Saya lebih menyarankan untuk menganimasikan posisi latar dibandingkan posisi layer itu sendiri, sehingga layer tidak akan bergerak, hanya latarnya saja yang bergerak.

Namun tidak mendukung properti animasi background-position dengan baik, jadi kita membutuhkan sebuah plugin untuk itu. Anda akan menemukan begitu banyak plugin JQuery yang berfungsi untuk menganimasikan posisi latar jika Anda mencarinya, dan Saya memilih untuk menggunakan plugin animasi posisi latar dari Keith Wood. Saya tidak kenal dengan orang itu, tapi pluginnya bagus ⇒ http://keith-wood.name/backgroundPos.html

<!-- Muat JQuery di awal -->
<script type="text/javascript" src="js/jquery.js"></script>
<!-- Sertakan plugin JQuery BackgroundPos -->
<script type="text/javascript" src="js/jquery.backgroundpos.min.js"></script>
<script type="text/javascript">
// Pekerjaan kita di sini...
</script>

Definisikan beberapa variabel untuk mempermudah kita dalam menyeleksi elemen dan sekaligus juga memperbaiki performa. Seperti biasa:

var $parallax = $('#parallax-wrapper'),
$layer = $parallax.find('.layer'),
$nav = $('#parallax-navigation');

Setelah itu kita kumpulkan semua item navigasi dan layer di dalam paralaks. Kita akan cenderung menggunakan JQuery .each() di sini, karena ini adalah cara yang paling mudah untuk mendapatkan indeks/urutan masing-masing elemen. Kita akan menganimasikan elemen dengan parameter dari indeks elemen (urutan elemen):

$nav.find('a').each(function() {
// Saat pengguna mengeklik item navigasi...
$(this).on("click", function() {
var step = $(this).index(); // Dapatkan indeks dari setiap item navigasi
// Kumpulkan layer...
$layer.each(function() {
// Definisikan jarak animasi latar pada setiap layer berdasarkan indeksnya
var distance = ($(this).index()+1) * 200; // Kalikan dengan 200
});
return false;
});
}).first().addClass('active'); // Tambahkan kelas `active` pada item navigasi pertama sebagai awalan

Setelah itu, buat fungsi untuk menambah dan melepas kelas active pada setiap item navigasi. Dulu Saya sudah pernah menuliskan kodenya di sini

$nav.find('a').each(function() {
// Saat pengguna mengeklik item navigasi...
$(this).on("click", function() {
var step = $(this).index(); // Dapatkan indeks dari setiap item navigasi
$nav.find('.active').removeClass('active'); // Singkirkan kelas `active` pada item navigasi
$(this).addClass('active'); // Tambahkan kelas `active` pada item navigasi yang diklik
// Kumpulkan layer...
$layer.each(function() {
// Definisikan jarak animasi latar pada setiap layer berdasarkan indeksnya
var distance = ($(this).index()+1) * 200; // Kalikan dengan 200
});
return false;
});
}).first().addClass('active'); // Tambahkan kelas `active` pada item navigasi pertama sebagai awalan

Animasikan posisi latar pada masing-masing layer dengan parameter berupa urutan layer, sehingga jarak perubahan posisi akan berbeda-beda pada masing-masing layer (lebih tepatnya: jarak animasi akan meningkat berdasarkan urutan layer):

$nav.find('a').each(function() {
// Saat pengguna mengeklik item navigasi...
$(this).on("click", function() {
var step = $(this).index(); // Dapatkan indeks dari setiap item navigasi
$nav.find('.active').removeClass('active'); // Singkirkan kelas `active` pada item navigasi
$(this).addClass('active'); // Tambahkan kelas `active` pada item navigasi yang diklik
// Kumpulkan layer...
$layer.each(function() {
// Definisikan jarak animasi latar pada setiap layer berdasarkan indeksnya
var distance = ($(this).index()+1) * 200; // Kalikan dengan 200
// Animasikan posisi latar
$(this).stop().animate({backgroundPosition: '-' + (step*distance) + 'px 0px'}, 1500);
});
return false;
});
}).first().addClass('active'); // Tambahkan kelas `active` pada item navigasi pertama sebagai awalan

Dan beginilah hasil akhir sementara kita. Baru latarnya saja yang dianimasikan, belum ada konten:

Langkah Akhir: Menambahkan Konten

Animasi paralaks sudah berhasil dibuat, sekarang tinggal membuat konten paralaks saja. Setiap konten merupakan item yang bisa Anda isi dengan tulisan dan/atau gambar layaknya slideshow:

HTML

<div id="parallax-wrapper" class="parallax-wrapper">
<div class="layer layer-1"></div>
<div class="layer layer-2"></div>
<div class="layer layer-3"></div>
<div class="box-item-wrapper">
<div class="box-item"> ... </div>
<div class="box-item"> ... </div>
<div class="box-item"> ... </div>
<div class="box-item"> ... </div>
...
...
</div>
</div>

CSS

.box-item-wrapper {
position:relative;
overflow:hidden;
}

.box-item-wrapper .box-item {
float:left; /* posisikan `.box-item` sebagai layout mendatar */
width:100%;
margin:7em 0;
padding:1.5em 2em;
}

Fungsi selanjutnya ditujukan untuk mengeset ukuran kontainer item dan lebar item, serta menganimasikan kontainer item menuju ke kiri dengan jarak tertentu berdasarkan indeks item navigasi. Pertama-tama kita atur ukuran lebar .box-item-wrapper dan .box-item:

var $window = $(window),
$wrap = $parallax.find('.box-item-wrapper'),
width, totalWidth; // Variabel kosong

$window.on("resize", function() {

width = $parallax.width(); // Mendapatkan lebar `#parallax-wrapper`
totalWidth = width * $wrap.find('.box-item').length; // Lebar total = lebar `#parallax-wrapper` dikalikan jumlah `.box-item`

// Set lebar `.box-item-wrapper` selebar `totalWidth`
$wrap.width(totalWidth)
// Set lebar `.box-item` selebar `#parallax-wrapper`
.find('.box-item').width(width);

}).trigger("resize");

Saya menuliskan variabel width dan totalWidth kosong, kemudian menyatakan nilainya di dalam $window.on("resize", function() {}) agar lebar elemen bisa diperbaharui setiap kali ukuran layar diubah. Saya juga menyatakan lebar elemen di dalam event tersebut.

Terakhir, gabungkan animasi properti left di dalam event klik item navigasi untuk menganimasikan posisi .box-item-wrapper:

$nav.find('a').each(function() {
// Saat pengguna mengeklik item navigasi...
$(this).on("click", function() {
var step = $(this).index(); // Dapatkan indeks dari setiap item navigasi
$nav.find('.active').removeClass('active'); // Singkirkan kelas `active` pada item navigasi
$(this).addClass('active'); // Tambahkan kelas `active` pada item navigasi yang diklik
// Kumpulkan layer...
$layer.each(function() {
// Definisikan jarak animasi latar pada setiap layer berdasarkan indeksnya
var distance = ($(this).index()+1) * 200; // Kalikan dengan 200
// Animasikan posisi latar
$(this).stop().animate({backgroundPosition: '-' + (step*distance) + 'px 0px'}, 1500);
});
// Animasikan `.box-item-wrapper` ke kiri untuk menggerakkan `.box-item`
$wrap.stop().animate({'left': -(step*width)}, 1500);
return false;
});
}).first().addClass('active'); // Tambahkan kelas `active` pada item navigasi pertama sebagai awalan

Produk Final

HTML

<div id="parallax-wrapper" class="parallax-wrapper">
<div class="layer layer-1"></div>
<div class="layer layer-2"></div>
<div class="layer layer-3"></div>
<div class="box-item-wrapper">
<div class="box-item"> ... </div>
<div class="box-item"> ... </div>
<div class="box-item"> ... </div>
<div class="box-item"> ... </div>
</div>
</div>

<span id="parallax-navigation" class="parallax-navigation">
<a href="#1">1</a>
<a href="#2">2</a>
<a href="#3">3</a>
<a href="#4">4</a>
</span>

CSS

.parallax-wrapper {
border:1px solid black;
height:200px;
position:relative;
overflow:hidden;
}

.parallax-wrapper .layer {
position:absolute;
top:0;
right:0;
bottom:0;
left:0;
background-position:0 0;
background-color:transparent;
background-repeat:repeat-x;
}

.parallax-wrapper .layer-1 {background-image:url('img/parallax-bg-1.png')}
.parallax-wrapper .layer-2 {background-image:url('img/parallax-bg-2.png')}
.parallax-wrapper .layer-3 {background-image:url('img/parallax-bg-3.png')}

.box-item-wrapper {
position:relative;
overflow:hidden;
}

.box-item-wrapper .box-item {
float:left;
width:100%;
margin:5em 0 0;
padding:1.5em 2em;
}

.parallax-navigation {
display:block;
height:30px;
line-height:30px;
position:relative;
text-align:right;
font-size:11px;
font-weight:bold;
}

.parallax-navigation a {
text-decoration:none;
color:black;
background-color:#eee;
padding:5px 10px;
}

.parallax-navigation a.active {
background-color:#529834;
color:white;
}

JQuery

(function($) {

// Cache some elements
var $window = $(window),
$parallax = $('#parallax-wrapper'),
$layer = $parallax.find('.layer'),
$wrap = $parallax.find('.box-item-wrapper'),
$nav = $('#parallax-navigation'), width, totalWidth;

// Set the parallax content & item width in window resize ...
// ... so we can be sure that when the window is resized, the size of the elements will be updated too
$window.on("resize", function() {
width = $parallax.width(); // get the parallax wrapper width
totalWidth = width * $wrap.find('.box-item').length; // total width = (parallax wrapper width * box item length)
$wrap.width(totalWidth).find('.box-item').outerWidth(width);
}).trigger("resize");

// Collect all navigation item inside parallax navigation, then get their index to set the animation distance
$nav.find('a').each(function() {
// when user click on the navigation item
$(this).on("click", function() {
var step = $(this).index(); // get the index (0, 1, 2, 3, ...)
$nav.find('.active').removeClass('active'); // remove the active class from navigation item
$(this).addClass('active'); // add the active class to the clicked navigation item
$layer.each(function() {
// set the background-position per-animation distance of each layer ...
// ... based on its index
var distance = ($(this).index()+1) * 200; // multiplied by 200
$(this).stop().animate({backgroundPosition: '-' + (step*distance) + 'px 0px'}, 1500); // (jQuery background position plugin required)
});
// also, animate the `.box-item-wrapper` to the left to move the `.box-item`
$wrap.stop().animate({'left': -(step*width)}, 1500);
return false;
});
}).first().addClass('active'); // add active class to the first navigation item on initiation

})(jQuery);

Demo