tag:blogger.com,1999:blog-258657902024-03-13T11:34:10.767-07:00dicarveBlogspot Arie Nugraha ( Ari Nugraha ). Mahasiswa doktoral di University of Tsukuba, staf pengajar Departemen Ilmu Perpustakaan dan Informasi FIB UI dan sekaligus programmer yang suka programming, database, desain dan berharap bisa memberikan manfaat pada banyak orang. Amin. Menurut Arie Nugraha, Open Source bukan soal gratis, tapi soal menghormati hasil karya orang lain dan belajar ga make aplikasi bajakan.arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.comBlogger37125tag:blogger.com,1999:blog-25865790.post-8743125547358211362020-03-28T00:06:00.002-07:002020-03-28T21:42:13.974-07:00Goodbye jQuery...<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjsQGXsmedlY7bp4MEkirdUaWOx4lHn-bChFPKcmT7Qdr4qJz9pIz9NoXIxekY413DDOfkE8tRsF_T87rtmfNDwJuJpajI-EAhs8ZzgKyRYMJj1aZw8yQYOPdf2M9i3HTAxzI/s1600/goodbye-jquery.jpg" style="width: 100%" />
As the web standards becoming more mature each day, my prediction is that the need for third-party JavaScript library such as <a href="https://jquery.com/">jQuery</a> will slowly decline. jQuery is indeed still one of the best client-side JavaScript library in my opinion and even I still use it on some of my projects, but as the web application becoming more complex, programmers will starting to look at browser's native solution which will (maybe) offers better performance than the third-party library. In this post i will show you some of the browser's native API for replacing jQuery's DOM selector method, the obvious "<b>$</b>" or "<b>jQuery</b>" function. Under the hood, jQuery is actually using <a href="https://github.com/jquery/sizzle/wiki">Sizzle</a> library for its DOM selector, which i believe (even though I haven't dig inside the source code) Sizzle also using some of the browser's native API.
<h3>DOM selector with <code>document.querySelector(selectors)</code></h3>
<p>As the name already suggests, this method under the <b>Document</b> object fetch the first element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned. One important thing that we need to know here is that, using this method will return "<b>null</b>" value when no matches were found. For those who familiar with jQuery need to pay attention as the jQuery selector always returns empty Array when no matches were found. Below I show you some example.</p>
<pre><code class="html"><!doctype html>
<html><head><title>Query Selector in JavaScript</title><meta charset="UTF-8"></head>
<body>
<div>This is the first DIV</div>
<div>This is the second DIV</div>
<div>This is the third DIV</div>
<div>This is the fourth DIV</div>
<div>This is the fifth DIV</div>
<script>
// get the first DIV
let firstDiv = document.querySelector('div');
console.log('This is ', firstDiv);
// get the second DIV
let secondDiv = document.querySelector('div:nth-of-type(2)');
console.log('This is the ', secondDiv);
// change the text color to blue
secondDiv.style.color = 'blue';
// get the third DIV
let thirdDiv = document.querySelector('div:nth-of-type(3)');
console.log('This is the ', thirdDiv);
// change the text format to bold
thirdDiv.style.fontWeight = 'bold';
// check if element exists
let sixthDiv = document.querySelector('div:nth-of-type(6)');
if (sixthDiv == null) {
// add the sixth div if it is not exists yet
let newDiv = document.createElement("div")
newDiv.innerText = 'This is the sixth DIV';
document.body.append(newDiv);
}
</script>
</body>
</html>
</code></pre>
<h3>Tree traversal</h3>
<p><code>querySelector</code> method accepts all type of CSS selector and can be used to do DOM element tree traversal. In fact I already showed one of it the first example using <code>nth-of-type(n)</code> modifier. You can of course use parent children relationship selector also in this case.</p>
<pre><code class="html"><!doctype html>
<html><head><title>Query Selector in JavaScript</title><meta charset="UTF-8"></head>
<body>
<div id="parent">
<div class="child">
<div class="grandchild">
<div class="great_grandchild"></div>
</div>
</div>
<div class="child">
<div class="grandchild"></div>
</div>
</div>
<script>
/* TREE TRAVERSAL */
// get the first direct child under parent
let firstChild = document.querySelector('#parent > .child');
console.log('This is the ', firstChild);
// get the great grandchild under parent
let greatGrandChild = document.querySelector('#parent .great_grandchild');
console.log('This is the ', greatGrandChild);
// alternative syntax to get the great grandchild
greatGrandChild = firstChild.querySelector('.great_grandchild');
console.log('This is the ', greatGrandChild);
// add new first child under parent
let newFirstChild = document.createElement("div");
newFirstChild.innerText = 'The real 1st child';
document.querySelector('#parent').prepend(newFirstChild);
// get the parent of great grandchild
let parentOfGrandChild = greatGrandChild.parentNode;
console.log(parentOfGrandChild);
</script>
</body>
</html>
</code></pre>
<h3>Multiple DOM element matches and manipulation with <code>querySelectorAll</code></h3>
<p>The <code>querySelectorAll</code> method behaves almost similar with the <code>querySelector</code>, except that it returns not only single match but an array in form of NodeList object instead. You can use this if you want to manipulate more than one element that match with your specified selector. Just remember to add <code>:scope</code> pseudo class at the very first of selector string to make sure the browser only get the child element under the specified element.</p>
<pre><code class="html"><!doctype html>
<html><head><title>Query Selector in JavaScript</title><meta charset="UTF-8"></head>
<body>
<ul id="bio">
<li class="name">The first one</li>
<li class="location">Tsukuba, Japan</li>
<li class="name">The second one</li>
<li class="location">Tokyo, Japan</li>
<li class="name">The third one</li>
<li class="location">Jakarta, Indonesia</li>
<li class="name">The fourth one</li>
<li class="location">Seoul, South Korea</li>
<li class="name">The fifth one</li>
<li class="location">Wuhan, China</li>
</ul>
<script>
/* querySelectorAll */
// get all names
let names = document.querySelectorAll(':scope #bio .name');
console.log('Number of names ', names.length);
console.log('The elements are ', names);
// get all locations
let locations = document.querySelectorAll(':scope #bio .location');
console.log('The elements are ', locations);
// make all location texts italic
locations.forEach(e => e.style.fontStyle = 'italic');
// prepend "name" text inside name element
names.forEach(e => e.prepend('Name: '));
// add empty list element with bottom border after location
// as a data separator
locations.forEach(function(e){
let borderedList = document.createElement('li');
borderedList.style.borderBottom = '1px solid #999';
e.after(borderedList);
});
</script>
</body>
</html>
</code></pre>
<p>Pretty neat huh? :D</p>
<h3>Sibling manipulation with <code>previousElementSibling</code> and <code>nextElementSibling</code></h3>
<p>It is very often we want to manipulate DOM elements which are positioned on the same level as current selected element, or the siblings of current element. In this case we can use the <code>previousElementSibling</code> and <code>nextElementSibling</code> property.</p>
<pre><code class="html"><!doctype html>
<html><head><title>Query Selector in JavaScript</title><meta charset="UTF-8"></head>
<body>
<div id="friends">
<div class="friend">Harada</div>
<div class="friend">Sasaki</div>
<div class="friend">Iqbal</div>
<div class="friend">Michael</div>
<div class="friend">Megumi</div>
</div>
<script>
/* SIBLINGS */
// get iqbal
let iqbal = document.querySelector('#friends .friend:nth-of-type(3)');
console.log(iqbal);
// who is our friend before iqbal
let beforeIqbal = iqbal.previousElementSibling;
// change the color to orange
beforeIqbal.style.color = 'orange';
// who is our friend after iqbal
let afterIqbal = iqbal.nextElementSibling;
// change the color to purple
afterIqbal.style.color = 'purple';</script>
</body>
</html>
</code></pre>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com0tag:blogger.com,1999:blog-25865790.post-39693730580690275582019-01-17T01:59:00.003-08:002019-01-18T00:24:38.101-08:00Operasi Array dan Object dengan Plain Vanilla Javascript<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzJOYG_Ippyh1SO-So6QNbFCgaCHXXqN8v41bw21wMSB8l7BYWmvsgo_k-1X8XIXcxqQd4mG4Gb_oO2YDTAChabQqiIN-Vp9G_fjbcSF0KedlzmK0yxjrlXmT5seAtDqWFTs0/s1600/vanillaJS.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzJOYG_Ippyh1SO-So6QNbFCgaCHXXqN8v41bw21wMSB8l7BYWmvsgo_k-1X8XIXcxqQd4mG4Gb_oO2YDTAChabQqiIN-Vp9G_fjbcSF0KedlzmK0yxjrlXmT5seAtDqWFTs0/s1600/vanillaJS.jpg" style="width: 100%;" /></a></div>
<p>Dengan semakin matangnya standar JavaScript saat ini berkat hadirnya edisi ke-enam dari standar <a href="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 2015</a> dan dukungan berbagai <em>browser</em> modern, pemrograman web dengan Javascript menjadi semakin mudah. Salah satu operasi pemrograman yang sering saya lakukan adalah operasi yang melibatkan <code>Array</code> dan <code>Object</code> (utamanya JSON). Berikut ini adalah beberapa <em>code snippet</em> yang saya coba dokumentasikan yang mungkin bermanfaat bagi teman-teman yang membaca artikel ini. Karena fungsi-fungsi/metode-metode <code>object</code> yang digunakan dalam artikel ini adalah standar, walaupun <em>snippet</em> yang saya contohkan untuk digunakan pada <em>browser</em> (client-side), maka kemungkinan besar <em>snippet</em> kode-kode ini juga bisa berjalan pada NodeJS a.k.a JavaScript di <code>server-side</code>. Karena artikel ini tidak mencakup dasar-dasar pemrograman Javascript, ada baiknya teman-teman yang belum mengenal JavaScript mempelajari terlebih dahulu dasar-dasar pemrograman JavaScript sebelum membaca artikel ini.</p>
<h3>Iterasi Array dengan <em>method</em> <code>forEach</code></h3>
<p>Untuk melakukan iterasi terhadap isi dari Array biasanya kita menggunakan <em>loop construct</em> seperti <code>for</code>, alternatifnya kita bisa juga menggunakan <code>forEach</code> yang relatif lebih praktis.</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// sebuah Array berisi daftar nama teman-teman
var temanTeman = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
temanTeman.forEach(function(teman) {
// tampilkan ke console JavaScript
console.log(teman);
// tampilkan pada body dokumen HTML
document.writeln(teman + '<br/>');
});
</script>
</body>
</html>
</code></pre>
<h3>Iterasi Object dengan <em>method</em> <code>forEach</code></h3>
<p>Untuk melakukan iterasi terhadap property dan nilai yang ada dalam sebuah Object kita bisa juga menggunakan <code>forEach</code> dengan cara sedikit berbeda seperti berikut ini:</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
var sebuahObject = {nama: 'Ari', pekerjaan: 'Mahasiswa', usia: 36}
Object.keys(sebuahObject).forEach(function(prop) {
// ambil nilai untuk prop ini
const propVar = Object.getOwnPropertyDescriptor(sebuahObject, prop);
// tampilkan pada body dokumen HTML
document.writeln(prop + ': ' + propVar.value + '<br/>');
});
</script>
</body>
</html>
</code></pre>
<h3>Mencari tahu apakah sebuah nilai ada pada sebuah Array dengan <em>method</em> <code>includes</code></h3>
<p>Untuk mengetahui apakah sebuah nilai ada pada sebuah Array kita bisa menggunakan <code>includes</code>, seperti contoh berikut ini:</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// sebuah Array berisi daftar nama teman-teman
var temanTeman = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
// apakah "Budi" ada dalam daftar-daftar teman-teman kita?
const yangKitaCari = 'Budi'
if (temanTeman.includes(yangKitaCari)) {
// tampilkan ke console JavaScript
console.log(yangKitaCari+' ada dalam daftar!');
// tampilkan pada body dokumen HTML
document.writeln('<p>'+yangKitaCari+' ada dalam daftar!</p>')
} else {
// tampilkan ke console JavaScript
console.log(yangKitaCari+' TIDAK ADA dalam daftar!');
// tampilkan pada body dokumen HTML
document.writeln('<p>'+yangKitaCari+' TIDAK ADA dalam daftar!</p>')
}
</script>
</body>
</html>
</code></pre>
<h3>Menggabungkan dua atau lebih Array menjadi satu dengan <em>method</em> <code>concat</code></h3>
<p>Kita bisa dengan mudah menggabungkan dua atau lebih Array menjadi satu dengan menggunakan <code>concat</code>, seperti contoh berikut ini:</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// menggabungkan dua atau lebih Array menjadi satu
var temanKu = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
var temanDia = ['Ferry', 'Giri', 'Helmi', 'Iman'];
// gabungkan Array menjadi Array baru
var temanKudanDia = temanKu.concat(temanDia);
console.log(temanKudanDia);
temanKudanDia.forEach(function(teman) {
// tampilkan pada body dokumen HTML
document.writeln(teman + '<br/>');
});
</script>
</body>
</html>
</code></pre>
<h3>Melakukan filter isi Array berdasarkan kriteria tertentu dengan <em>method</em> <code>filter</code></h3>
<p>Untuk melakukan filter terhadap isi dari Array kita bisa menggunakan <code>filter</code>. Callback dari method <code>filter</code> harus mengembalikan nilai <code>true</code> apabila elemen tersebut ingin dipertahankan dalam Array atau sebaliknya. Bisa dilihat pada contoh berikut ini:</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// mem-filter Array sesuai dengan kriteria tertentu
var temanKu = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma', 'Kampret', 'Kecebong'];
var benarBenarTemanKu = temanKu.filter(teman => teman!='Kampret'&&teman!='Kecebong');
console.log(benarBenarTemanKu);
benarBenarTemanKu.forEach(function(teman) {
// tampilkan pada body dokumen HTML
document.writeln(teman + '<br/>');
});
</script>
</body>
</html>
</code></pre>
<h3>Mengubah isi Array menjadi Array baru dengan isi yang sudah dimodifikasi dengan <em>method</em> <code>map</code></h3>
<p>Ada kalanya kita ingin memodifikasi/mengubah isi sebuah Array. Hal tersebut bisa dilakukan dengan mudah dengan <code>map</code>:</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// membuat Array baru yang isi merupakan hasil modifikasi dari isi Array sebelumnya
var stringTemanKu = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
// stringTemanKu sebelumnya adalah Array berisi string
// sekarang kita ubah menjadi Array baru berisi object
var objectTemanKu = stringTemanKu.map(teman => {
var objectTeman = {nama: teman, status: 'teman'};
return objectTeman;
});
console.log(objectTemanKu);
// bisa juga sebaliknya, dari Array berisi object menjadi Array berisi string
var stringTemanKuJuga = objectTemanKu.map(teman => teman.nama+' adalah seorang '+teman.status);
console.log(stringTemanKuJuga);
stringTemanKuJuga.forEach(function(teman) {
// tampilkan pada body dokumen HTML
document.writeln(teman + '<br/>');
});
</script>
</body>
</html>
</code></pre>
<h3>Mengubah string menjadi Array elemennya adalah setiap huruf dari string tersebut dengan <em>function</em> <code>Array.from</code></h3>
<p>Bagaimana apabila kita ingin mengubah sebuah string dan memecahnya menjadi Array yang berisikan setiap huruf dari string tersebut? Mudah!:</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// membuat Array dari string
var deretanHuruf = 'ABCDEFGHIJKLM';
var deretanHurufArray = Array.from(deretanHuruf);
deretanHurufArray.forEach(function(huruf) {
// tampilkan pada body dokumen HTML
document.writeln('Ini huruf '+ huruf + '!<br/>');
});
</script>
</body>
</html>
</code></pre>
<h3>Mengubah Array menjadi string dengan <em>method</em> <code>join</code></h3>
<p>Bagaimana sebaliknya apabila kita ingin mengubah sebuah Array menjadi sebuah string? Mudah!:</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// membuat string dari Array
var temanKu = ['Asri', 'Budi', 'Choirul', 'Deni', 'Erma'];
// kita persatukan teman-teman kita dengan sebuah koma
var stringTemanKu = temanKu.join(', ');
// tampilkan pada body dokumen HTML
document.writeln('Teman-temanku adalah: '+ stringTemanKu);
</script>
</body>
</html>
</code></pre>
<h3>Melakukan tes pada setiap isi Array apakah sudah memenuhi kriteria dengan <em>method</em> <code>every</code></h3>
<p>Adakalanya kita ingin mengetahui apakah setiap anggota dari Array sudah memenuhi kriteria tertentu, untuk melakukan tes tersebut kita bisa menggunakan <code>every</code>:</p>
<pre><code class="html"><!doctype html>
<html><head><title>Plain Vanilla JavaScript</title><meta charset="UTF-8"></head>
<body>
<script>
// melakukan tes pada setiap elemen Array apakah memenuhi kriteria tertentu
var anggota = [
{nama: 'Asri', usia: 17},
{nama: 'Budi', usia: 18},
{nama: 'Choirul', usia: 19},
{nama: 'Deni', usia: 20},
{nama: 'Erma', usia: 15}
];
// apakah semua orang dalam anggota sudah lebih dari 16 tahun?
var semuaSudahDewasa = anggota.every(orang => orang.usia>16);
if (semuaSudahDewasa) {
document.writeln('Semua sudah dewasa!');
} else {
document.writeln('Masih ada di antara mereka yang belum dewasa!');
}
</script>
</body>
</html>
</code></pre>
<p>Semoga artikel ini bermanfaat, apabila ada pertanyaan terkait dengan beberapa fungsi dasar dari JavaScript bisa teman-teman tanyakan pada kolom komentar.</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com0tag:blogger.com,1999:blog-25865790.post-74371424855390488602018-02-08T05:15:00.002-08:002018-02-08T17:15:13.778-08:00Membuat Aplikasi Berbasis Web "Single Page Application" dengan Vue.js (Bagian 1)<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMLJ4Q00bSu9-tyH5yoLUmLfAaZqkr3Qm43oTrp8IS3IVXo4uSGxuRA2FPIsKplfZ5H7079CWK3HHlFeF5pc4rGaxvuS-oGImOeITRq90Xe2BcKOdukFPZBW1Ib7I9Mj2FyF4/s1600/Vue1-blog.jpg" style="width: 100%" /></div>
<p>Javascript saat ini semakin populer digunakan dalam pengembangan aplikasi berbasis web baik di sisi <i>client</i> (<i>browser</i>) maupun <i>server</i>, yang semakin diperkuat dengan munculnya standar-standar ECMAScript terbaru seperti <b>ECMAScript6 (ES6)</b> atau biasa disebut juga <b>ECMAScript 2015 (ES2015)</b>. Untuk lebih lengkapnya mengenai ES6 ini silahkan baca <a href="https://github.com/lukehoban/es6features#readme">halaman web penjelasan dari Luke Hoban yang sangat bermanfaat ini</a>. Sejarahnya dulu saya ingat Javascript ini adalah bahasa pemrograman <i>client-side</i> yang paling menyebalkan karena perbedaan standar setiap browser, aplikasi web kita berjalan lancar di Interner Explorer 5 atau 6, pas dijalankan dengan Mozilla, Netscape atau Firefox tidak jalan sama sekali dan juga berlaku sebaliknya, Mikocok ehhh maksud saya Microsoft cenderung membuat implementasi mereka sendiri. Seiring dengan semakin maraknya penggunaan aplikasi berbasis web, Javascript semakin banyak digunakan untuk membuat aplikasi web yang responsif dan <b>"reaktif"</b>. Istilah <b>"Reaktif"</b> sedang "in" dalam pengembangan web saat ini, yang merujuk kepada kemampuan untuk "mereaktifkan" elemen DOM (Document Object Model)/tag HTML sehingga ketika diubah nilainya pada kode Javascript, maka secara otomatis tag HTML tersebut juga akan berubah, begitu juga sebaliknya apabila kita melalukan perubahan di sisi HTML, maka perubahan tersebut akan terefleksi pada kode Javascript. Beberapa framework/library Javascript yang memungkinkan kita membangun aplikasi web yang reaktif ini antara lain: <a href="https://angularjs.org/">AngularJS (bukan Angular)</a>, <a href="http://backbonejs.org/">Backbone.js</a>, <a href="https://www.emberjs.com/">Ember</a>, <a href="https://reactjs.org/">React</a>, <a href="http://riotjs.com/">Riot</a>, <a href="https://www.polymer-project.org/">Polymer</a>, dan yang akan kita bahas kali ini adalah <a href="https://vuejs.org/">Vue.js</a> yang menyatakan dirinya sebagai "<i>The Progressive JavaScript Framework</i>" (kayanya semua framework menyatakan diri mereka paling hebat dibandingkan dengan framework lain 😬).</p>
<h3>Reaktifitas</h3>
<p>Untuk melihat contoh "reaktifitas" dengan Vue, silahkan buat sebuah file HTML bernama <code>index.html</code> dan masukkan kode berikut:
<h3><code>index.html</code></h3>
<pre><code class="html"><!doctype html>
<html lang="id">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<script src="assets/js/vue.min.js"></script>
<title>Contoh Reaktifitas</title>
</head>
<body>
<div id="spa">
<div class="jumbotron jumbotron-fluid p-3">
<h1 class="display-4 text-center">{{ teks_yang_reaktif?teks_yang_reaktif:'Hmmmm...' }}</h1>
<hr class="my-4"/>
<p class="lead text-center"><input type="text" class="form-control" v-model="teks_yang_reaktif"/></p>
</div>
<script>
var spa = new Vue({
el: '#spa',
data: {
teks_yang_reaktif: 'Sebuah Teks yang Reaktif!'
}
})
</script>
</body>
</html>
</code></pre>
</p>
<p>Buka file <code>index.html</code> ini pada <i>browser</i> dan kita akan melihat seperti berikut ini:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu1EscGV2L-IdsmiD5V0RTPHjLfi8nibmJ_BhEgAT-pUWMcBS2FugHio2kKA5lMSMGnANudNNFb8pJdWa8M4FWv3R30aMvW-Id6EvhaOhCEESlMyuCch6715WERFrzKStjvm4/s1600/vue-reaktif.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu1EscGV2L-IdsmiD5V0RTPHjLfi8nibmJ_BhEgAT-pUWMcBS2FugHio2kKA5lMSMGnANudNNFb8pJdWa8M4FWv3R30aMvW-Id6EvhaOhCEESlMyuCch6715WERFrzKStjvm4/s1600/vue-reaktif.gif" data-original-width="600" data-original-height="212" /></a></div>
<h3>Single Page Application</h3>
<p>Dengan munculnya library/framework reaktif seperti Vue.js ini mendorong model pengembangan aplikasi berbasis web "Single Page Application (SPA)", dimana semua "<i>view</i>" atau tampilan antar muka dibangun dengan hanya menggunakan sebuah file HTML yang kemudian akan me-<i>load</i> <i>view</i> komponen/modul lain dengan meng-injeksi (atau istilah kerennya: <i>render</i>) secara dinamis dengan Javascript. Dengan model SPA ini maka aplikasi di sisi server tidak lagi harus mengirimkan respon balik halaman HTML full, cukup data saja dalam format JSON (menggunakan AJAX) misalnya yang kemudian akan direaktifkan oleh Vue, setiap perubahan di sisi klien akan memicu perubahan pada server, begitu juga sebaliknya dan pada akhirnya komunikasi data antara client dengan server berlangsung lebih cepat karena ukuran data yang kecil. Kita lihat contoh sederhana dengan menggunakan Vue berikut ini:</p>
<h3><code>index.html</code></h3>
<pre><code class="html"><!doctype html>
<html lang="id">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<script src="assets/js/vue.min.js"></script>
<script src="assets/js/vue-router.min.js"></script>
<title>Single Page Application Vue.js</title>
</head>
<body>
<div id="spa"><!-- elemen root/utama dari SPA Vue -->
<!-- Navigasi utama aplikasi SPA
perhatikan tag "router-link" adalah tag khusus untuk membuat hyperlink ke router Vue -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<router-link class="navbar-brand" to="/">SPA Vue.js</router-link>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navigasi"
aria-controls="navigasi" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navigasi">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<router-link class="nav-link" to="/">Home</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" to="/berita">Berita</router-link>
</li>
</ul>
</div>
</nav>
<!-- link dari "router-link" di atas akan merender view masing2 di dalam tag "router-view" -->
<div id="main-content">
<router-view></router-view>
</div>
</div>
<!-- template view untuk komponen "Home" -->
<script type="text/x-template" id="home">
<div class="jumbotron jumbotron-fluid"><h1 class="display-4 text-center">{{ judul }}</h1>
<hr class="my-4"/>
<p class="lead text-center">{{ konten }}</p>
</script>
<!-- template view untuk komponen "Berita" -->
<script type="text/x-template" id="berita">
<div>
<p class="p-1"><input type="text" class="form-control" v-model="keywords"
v-on:keyup="search"
placeholder="Masukkan kata kunci pencarian"></p>
<div v-if="berita_filtered.length>0">
<div class="berita p-2" v-for="b in berita_filtered">
<p class="h4">{{ b.judul }}</p>
<p class="lead">{{ b.konten }}</p>
<hr/>
</div>
</div>
<div v-else>
<div class="berita p-2" v-for="b in berita">
<p class="h4">{{ b.judul }}</p>
<p class="lead">{{ b.konten }}</p>
<hr/>
</div>
</div>
</div>
</script>
<!-- kode javascript untuk menjalankan Vue.js -->
<script src="assets/js/app.js"></script>
</body>
</html>
</code></pre>
<h3><code>assets/js/app.js</code></h3>
<pre><code class="javascript">// 1. Definisikan komponen Vue
// Komponen "Home" akan menampilkan halaman depan aplikasi
const Home = Vue.extend({
template: '#home',
data: function() {
return {
judul: 'Selamat datang di Single Page Application',
konten: 'Vue.js memungkinkan developer web membangun aplikasi web yang dinamis, ringan dan cepat.'
}
}
});
// Komponen "Berita" akan menampilkan daftar berita
var data_berita = {
keywords: '',
berita: [
{judul: 'Lorem Ipsum', konten: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur feugiat, eros quis semper dignissim, libero erat semper ante, non porttitor sem metus a neque.'},
{judul: 'In Vehicula Vulputate', konten: 'In vehicula vulputate eros vitae porttitor. Praesent commodo accumsan semper. Proin eu tellus purus, eu malesuada sapien.'},
{judul: 'Aliquam Laoreet Gravida Erat', konten: 'Aliquam laoreet gravida erat, in hendrerit arcu lobortis id. Cras libero augue, aliquam nec sollicitudin id, molestie eu ante.'},
{judul: 'Donec Adipiscing', konten: 'Donec adipiscing, diam eget tempor volutpat, odio justo molestie dolor, vitae sodales felis risus a mi.'},
{judul: 'Praesent Mollis', konten: 'Praesent mollis placerat mi ut accumsan. Vivamus ultricies lobortis risus, quis venenatis ligula elementum id.'},
],
berita_filtered: []
};
const Berita = Vue.extend({
template: '#berita',
data: function() {
return data_berita;
},
methods: {
search: function() {
var katakunci = new RegExp(this.keywords, 'ig');
if (this.keywords.length > 2) {
this.berita_filtered = this.berita.filter(el => el.judul.search(katakunci)>-1);
} else {
this.berita_filtered = [];
}
}
}
});
// 2. Definisikan routing menuju komponen
const routes = [
{ path: '/', component: Home},
{ path: '/berita', component: Berita }
]
// 3. Buat instance Router Vue
const router = new VueRouter({ routes })
// 4. Tempelkan instance "router" ke App Vue
const spa = new Vue({ router }).$mount('#spa');
</code></pre>
<p>Saya akan coba jelaskan beberapa poin penting yang perlu kita perhatikan disini, terutama bagi teman-teman yang baru mengenal Vue:
<ol>
<li>Untuk contoh SPA ini saya menggunakan juga framework <a href="http://getbootstrap.com">Bootstrap versi 4.0</a>, jadi pastikan bahwa Anda juga sudah mengunduh dan menginstall Bootstrap. Pada tulisan ini semua file CSS saya letakkan pada direktori <code>assets/css/</code> dan semua file Javascript saya letakkan pada direktori <code>assets/js/</code>;</li>
<li>Untuk menggunakan Vue, kita harus sudah meng-<i>include</i> library Javascript Vue pada bagian head file HTML. Karena kita membangun antar muka SPA, maka kita juga memerlukan Vue Router yang bertugas melakukan routing komponen ke view-nya masing-masing. <a href="https://vuejs.org/js/vue.min.js">Unduh library Vue.js di sini</a> dan <a href="https://github.com/vuejs/vue-router/releases">Vue Router di sini</a>. Atau apabila Anda adalah tipe pemalas download library Javascript gunakan versi CDN masing-masing hehehe;</li>
<li>Perhatikan terdapat <i>custom tag</i> <code><router-link class="nav-link" to="/">Home</router-link></code> yang secara otomatis akan dikenali oleh Vue Router dan akan diubah ke tag A sebagai hyperlink menuju route yang ditunjuk oleh atribut "to". Semua hyperlink yang menuju ke route Vue harus menggunakan <i>custom tag</i> ini;</li>
<li>Custom tag <code><router-view></router-view></code> berfungsi sebagai tempat penampung (<i>placeholder</i>) dari view untuk masing-masing komponen route;</li>
<li>View atau tampilan untuk masing-masing komponen kita definisikan dengan menggunakan tag <code><script type="text/x-template" id="berita"></code>. X-Templates adalah salah satu jenis template yang didukung oleh Vue, dan menurut saya yang paling aman dan mudah untuk digunakan untuk kebutuhan aplikasi skala kecil hingga menengah;</li>
<li>Kode dalam bentuk seperti <code>{{ judul }}, {{ konten }}</code> disebut juga sebagai <i>Mustache</i> yang merupakan placeholder untuk data.
moustache akan otomatis digantikan oleh Vue dengan data yang kita tetapkan pada komponen dan data tersebut sudah bersifat reaktif.</li>
<li>Vue juga memiliki atribut <i>directive</i>, yang kita gunakan pada contoh ini antara lain adalah <code>v-bind, v-if, v-else, v-for, v-model dan v-on</code>. <code>v-model</code> kita gunakan untuk mereaktifkan sebuah tag HTML dengan model data yang kita definisikan pada Vue/komponen, <code>v-if dan v-else</code> memungkinkan kita me-load bagian dari view dengan kondisi tertentu, <code>v-for</code> memungkinkan kita untuk melakukan pengulangan/loop pada view dan sangat berguna untuk menampilkan data dalam bentuk <i>Array</i> atau <i>Object</i> Javascript dan <code>v-on</code> kita gunakan untuk mengaitkan suatu tag HTML dengan "<i>method</i>" yang kita definisikan di dalam kode Javascript Vue;</li>
<li>Semua kode Javascript untuk menjalankan Vue diletakkan pada file <code>assets/js/app.js</code> dan diletakkan pada bagian paling bawah kode HTML;</li>
<li>Variabel objek <code>data_berita</code> pada kode Javascript Vue bersifat <i>static</i> (tidak dinamis), pada aplikasi SPA yang sesungguhnya data berita ini akan diambil melalui AJAX ke database pada aplikasi di sisi server;</li>
<li>Untuk membuat komponen (dalam terminologi aplikasi web MVC tradisional kita bisa anggap komponen merupakan sebuah <i>controller</i> sekaligus <i>model</i>), kita menggunakan sintak <code>Vue.extend({})</code>;</li>
<li>Setiap komponen merupakan objek Javascript yang biasanya memiliki property <code>template, data, methods</code> dan/atau <code>computed</code>;</li>
<li>Aplikasi Vue dijalankan dengan membuat instance melalui konstruktor Vue yaitu <code>const spa = new Vue({})</code>. Setelah itu objek <code>spa</code> bisa diakses oleh komponen melalui <code>methods</code>.</li>
</ol>
</p>
<p>Apabila file <code>index.html</code> kita jalankan melalui browser maka kita akan melihat aplikasi kita seperti berikut ini:
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhO_jQZiUytGvf3Kvn479x4AtZGY0hiPdb_Fq2jNRfueGoDIDEoFMMQwmnBLasqCkTk_u9-YMEzKYryWB_49f9ZoIoGvZGlTuAJg9bVlOZPRo0MM8TIrq8zcx6BR5FTG04lqOU/s1600/vue-app-simple.gif" style="width: 50%" /></div>
</p>
<p>Kita bisa lihat bahwa perpindahan antara satu halaman ke halaman lain dilakukan dengan sangat cepat karena tidak membutuhkan request HTTP kembali ke server. Semua proses pengolahan/<i>rendering</i> tampilan antar muka dilakukan di sisi <i>client</i> oleh Vue, request HTTP hanya dibutuhkan untuk komunikasi data dalam format JSON atau <i>plain-text</i> lainnya, bukan untuk kode HTML yang membuat aplikasi menjadi lebih cepat layaknya aplikasi <i>desktop</i>. Pada tulisan bagian 2 kita akan melihat contoh yang sedikit lebih kompleks dengan melibatkan form isian data. Selamat mencoba!</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com5Tsukuba, Ibaraki Prefecture, Japan36.0834857 140.076642335.672891699999994 139.4311953 36.4940797 140.7220893tag:blogger.com,1999:blog-25865790.post-90152450837105679092018-01-01T07:31:00.001-08:002018-01-01T07:31:49.384-08:00Promise : Sebuah Janji Eksekusi dari Javascript <div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhenYJIX-En7UN_wpERrjGfLLSqns0OkBNS9P7UNTHO3LuA0QXtRxpWicZ_uMES-re-HXkAUoJJJdtb3rhoKShLLCAeijXfiz73P-_Wyut1CPE33lwUZ1mL8hTezTJlcPXFJAs/s1600/Promise+blog.jpg" style="width: 100%" /></div>
<p>Judul artikel ini mungkin agak sedikit bombastis: "<i>Promise : Sebuah Janji Eksekusi dari Javascript</i>". <b>Promise</b> adalah sebuah mekanisme dari standar ECMAScript 2015 yang memungkinkan kita melakukan eksekusi kode fungsi Javascript asynchronous (salah satunya adalah request AJAX) dan mendapatkan nilai balik (<i>return value</i>) dari eksekusi kode tersebut tidak secara langsung, melainkan berupa objek "<strong>Promise</strong>" yang menjanjikan eksekusi di masa yang akan datang! Paham? Tidak? kalau teman-teman pembaca tidak paham itu wajar, saya juga awalnya bingung kenapa pula ini ada fitur di bahasa pemrograman pake "janji-janji" segala!? Mari kita tengok definisi dari <b>Promise</b> yang saya kutip dari dokumentasi <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises">Mozilla Developer Network</a> : </p>
<blockquote>A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.</blockquote>
<p>Masih belum <i>mudeng</i>? sama saya juga hahaha🤣🤣🤣! Kalau begitu mari kita lihat contoh kode HTML dan Javascript sebagai berikut sebagai berikut:</p>
<h3><code>promise.html</code></h3>
<pre><code class="html"><!doctype html>
<html>
<head><title>Promise</title><meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
var datauser = [];
// fungsi untuk melakukan request AJAX
function getUsers(url) {
$.ajax({
url: url,
method: 'get'
}).done(function(hasil) {
// isi variabel global datauser dengan hasil dari AJAX
datauser = hasil;
});
}
// fungsi untuk mengubah data JSON ke list HTML
function ubahDataKeHTML(datauser) {
var html = '<ul>';
$.each( datauser, function( key, value ) {
html += '<li>'+value.name+' - '+value.email+'</li>'
});
html += '</ul>';
return html;
}
// panggil fungsi 'getUsers'
getUsers('https://jsonplaceholder.typicode.com/users');
// ubah data dari hasil AJAX ke list HTML
var datauserHTML = ubahDataKeHTML(datauser);
// tampilkan isi variabel ke log
console.log(datauser);
console.log(datauserHTML);
// tampilkan data user
$(document).ready(function() {
$('.container').html(datauserHTML);
});
</script>
</head>
<body>
<div class="container"></div>
</body>
</html>
</code></pre>
<p>Hasil yang muncul adalah sebagai berikut:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVx11DmwJAxEGtUD6tH8UW3Reb1zzHNgTzRh7zyZg45_q-xvIIbd3GBCNaMG1KkSiPRIU8eOjEnSnQAmXwYOGB_NIzIkwwfa22as8WH34ld_8Tp69Wqjw7jC7FpvG89_ntNaM/s1600/Promise+not+working.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVx11DmwJAxEGtUD6tH8UW3Reb1zzHNgTzRh7zyZg45_q-xvIIbd3GBCNaMG1KkSiPRIU8eOjEnSnQAmXwYOGB_NIzIkwwfa22as8WH34ld_8Tp69Wqjw7jC7FpvG89_ntNaM/s400/Promise+not+working.png" width="400" height="269" data-original-width="1600" data-original-height="1076" /></a></div>
<p>Apa yang terjadi? ternyata tidak sesuai apa yang kita harapkan! tag <code>div</code> kita tidak terisi dengan list data user seperti yang kita mau, dan juga ternyata variabel array <code>datauser</code> tidak terisi dengan data padahal tidak ada yang salah dengan kode ini, semua berjalan dengan baik. saya yakin banyak dari teman-teman web programmer yang pernah mengalami hal ini dan <i>garuk-garuk</i> kepala, lalu <i>browsing</i> cari jawaban di Stackoverflow kan? hehehe :D.
<blockquote>Loh mas ngapain ribet, heeellllooowwww?? ubah aja kode-nya, misalnya lakukan eksekusi fungsi <code>ubahDataKeHTML</code> ke dalam fungsi <code>.done</code> dari objek <code>$.ajax()</code>? atau ngapain juga bikin fungsi-fungsi segala?</blockquote>
<p>Hehehe, silahkan saja dicoba, paling nanti ada saatnya kepentok lagi hehehe 😬😬😬. Kegagalan kode di atas terjadi karena eksekusi kode <code>$.ajax</code> dan <code>.done</code> berjalan secara <i>asynchronous</i>/paralel dan tidak terjadi secara berurutan sehingga variabel global <code>datauser</code> mungkin belum terisi dengan hasil dari request AJAX karena request AJAX belum selesai. Penyebab lain adalah karena Javascript hanya bisa mengakses variabel global satu tingkat di atas cakupan fungsi, dalam hal kode di atas variabel <code>datauser</code> berarti dua tingkat di atas cakupan fungsi <code>.done</code>. Cara yang elegan untuk masalah ini adalah dengan menggunakan <b>Promise</b> yang sudah menjadi standar default sejak spesifikasi ECMAScript 2015 atau serin disingkat ES2015. Berikut adalah kode Javascript yang sudah kita ubah dengan memanfaatkan Promise:</p>
<h3><code>promise1.html</code></h3>
<pre><code class="html"><!doctype html>
<html>
<head><title>Promise</title><meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
// fungsi untuk melakukan request AJAX dan mengembalikan objek Promise
function getUsers(url) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
method: 'get'
}).done(function(hasil) {
// simpan hasil dari AJAX ke callback 'resolve' dari Promise
// untuk kemudian nanti dipakai oleh fungsi '.then'
<span style="background-color: yellow">resolve</span>(hasil);
});
})
}
// fungsi untuk mengubah data JSON ke list HTML
function ubahDataKeHTML(datauser) {
var html = '<ul>';
$.each( datauser, function( key, value ) {
html += '<li>'+value.name+' - '+value.email+'</li>'
});
html += '</ul>';
return html;
}
// panggil fungsi 'getUsers' dan jalankan fungsi '.then'
// argumen dari fungsi '.then' adalah sebuah callback dengan argumen 'hasil'
// yang berisikan objek JSON hasil AJAX
getUsers('https://jsonplaceholder.typicode.com/users').<span style="background-color: yellow">then</span>(function(hasil) {
console.log(hasil);
console.log('Janji telah dipenuhi!');
var datauserHTML = ubahDataKeHTML(hasil);
// tampilkan data user
$(document).ready(function() {
$('.container').html(datauserHTML);
});
});
</script>
</head>
<body>
<div class="container"></div>
</body>
</html></code></pre>
<p>Dengan kode ini kita akan melihat hasil seperti berikut ini: </p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU0w3QXRD8OYJKa0hmrEqnUmyMbnGG_I0dATR0KyY_kw51o0AgzqLh8OGdzoy1lbRhKqpATAjeGbJYUC0Th8_EqQrBZi8i-xi0zCvaaxQaykbxGqCmByxLcmM-Gi2TBgF8Owk/s1600/Promise+working.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhU0w3QXRD8OYJKa0hmrEqnUmyMbnGG_I0dATR0KyY_kw51o0AgzqLh8OGdzoy1lbRhKqpATAjeGbJYUC0Th8_EqQrBZi8i-xi0zCvaaxQaykbxGqCmByxLcmM-Gi2TBgF8Owk/s400/Promise+working.png" width="400" height="269" data-original-width="1600" data-original-height="1076" /></a></div>
<p>Penjelasan sederhana dari kode ini adalah, ketika kita menggunakan <b>Promise</b>, maka kita menggunakan <i>callback</i> <code>resolve</code> untuk menyimpan hasil dari request AJAX kita, yang kemudian hasil ini akan tersedia pada argumen callback fungsi <code>.then</code> untuk selanjutnya diolah dan dijadikan HTML oleh fungsi <code>ubahDataKeHTML</code>.</p>
<h2>Chaining</h2>
<p>Salah satu kelebihan dari <b>Promise</b> adalah memungkinkan terjadinya <i>chaining</i> atau eksekusi <b>Promise</b> berantai, fitur ini berguna ketika kita ingin melakukan eksekusi kode secara berantai dimana eksekusi kode dilakukan benar-benar setelah eksekusi kode sebelumnya sudah selesai atau terpenuhi, seperti bisa kita lihat pada kode berikut: </p>
<h3><code>promise2.html</code></h3>
<pre><code class="html"><!doctype html>
<html>
<head><title>Promise</title><meta charset="UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
// fungsi untuk melakukan request AJAX dan mengembalikan objek Promise
function getUsers(url) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
method: 'get'
}).done(function(hasil) {
// simpan hasil dari AJAX ke callback 'resolve' dari Promise
// untuk kemudian nanti dipakai oleh fungsi '.then'
resolve(hasil);
}).fail(function() {
<span style="background-color: yellow">reject</span>('Error pada request AJAX!');
});
})
}
// fungsi untuk mengubah data JSON ke list dan tabel HTML
function ubahDataKeHTML(datauser) {
console.log('Janji pertama (request AJAX) telah dipenuhi');
var list = '<h3>Data users dalam format list</h3>';
list += '<ul>';
var tabel = '<h3>Data users dalam format tabel</h3>';
tabel += '<table class="table table-bordered">';
$.each( datauser, function( key, value ) {
list += '<li>'+value.name+' - '+value.email+'</li>'
tabel += '<tr><td>'+value.name+'</td><td>'+value.email+'</td></tr>'
});
list += '</ul>';
tabel += '</table>';
return {htmlList: list, htmlTable: tabel};
}
// fungsi untuk menginject HTML ke dalam div .container
function injectHTML(html) {
console.log('Janji kedua (ubah JSON ke HTML) telah dipenuhi');
return $('.container').append(html.htmlList).append(html.htmlTable);
}
// fungsi untuk menampilkan log pada console
function terakhir(objJquery) {
console.log('Janji terakhir (inject HTML ke .container) telah dipenuhi');
console.log('Berikut objek jQuery dari nilai balik callback Janji (Promise) sebelumnya:');
console.log(objJquery);
}
// setiap kali '.then' dipanggil maka akan mengembalikan objek Promise
// dan nilai balik dari callback bisa diakses pada callback berikutnya
// yang bisa kita 'chain' tanpa batas
// fungsi '.catch' menangkap hasil dari callback 'reject' yang apabila terjadi
// maka Promise tidak bisa terpenuhi
getUsers('https://jsonplaceholder.typicode.com/users')
.then(hasil => ubahDataKeHTML(hasil))
.then(html => injectHTML(html))
.then(objJquery => terakhir(objJquery))
.<span style="background-color: yellow">catch</span>(error => {
console.log(error);
$('.container').html('<div class="alert alert-danger">Data users gagal diambil disebabkan oleh : '+error+'</div>');
});
</script>
</head>
<body>
<div class="container"></div>
</body>
</html></code></pre>
<p>Kita akan melihat hasil sebagai berikut untuk kode di atas:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzrd-J9HlWoZc5dPc6ryUIdlEeW0RNQRp78boY1ZNva0ebs0usNzaMzlKkKx-WA0TcZF2Brp2YV_IBqNdv0ZhYEhil6-u-vnZ3wm_c5w81axPW0Ymt_xFILXQ9G0aszbRYSFY/s1600/Promise+chaining.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzrd-J9HlWoZc5dPc6ryUIdlEeW0RNQRp78boY1ZNva0ebs0usNzaMzlKkKx-WA0TcZF2Brp2YV_IBqNdv0ZhYEhil6-u-vnZ3wm_c5w81axPW0Ymt_xFILXQ9G0aszbRYSFY/s400/Promise+chaining.png" width="400" height="360" data-original-width="1600" data-original-height="1440" /></a></div>
<p>Syntax alternatif untuk <i>chaining</i> Promise menggunakan standar ES2017 adalah dengan menggunakan <code>async/await</code> seperti berikut ini:</p>
<h3><code>promise3.html</code></h3>
<pre><code class="html"><script>
...
// alternatif chaining dengan menggunakan 'async/await'
async function ambilUserDanTampilkan(url) {
try {
let hasil = await getUsers(url);
let html = await ubahDataKeHTML(hasil);
let objJquery = await injectHTML(html);
terakhir(objJquery);
} catch(error) {
console.log(error);
$('.container').html('<div class="alert alert-danger">Data users gagal diambil disebabkan oleh : '+error+'</div>');
}
}
// jalankan fungsi async
ambilUserDanTampilkan('https://jsonplaceholder.typicode.com/users');
</script></code></pre>
<h2>Promise.all</h2>
<p>Ada kalanya dalam membangun aplikasi web interaktif dengan Javascript kita ingin suatu kode dieksekusi ketika semua persyaratan (eksekusi kode lain) sudah terpenuhi, tanpa memperdulikan urutan selesai-nya persyaratannya tersebut. Misalnya kita melakukan request AJAX ke banyak sumber yang berbeda dan setelah semua request AJAX selesai kita akan mengeksekusi kode terakhir yang menampilkan kotak alert menandakan bahwa semua request tersebut telah selesai, maka kita bisa menggunakan metode <code>Promise.all</code> dalam hal ini. Mari kita ilustrasikan dengan kode berikut ini: </p>
<h3><code>promise-all.html</code></h3>
<pre><code class="html"><!doctype html>
<html>
<head><title>Promise</title><meta charset="UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script>
function autentikasiUser(url, username, password) {
return new Promise(function(resolve, reject) {
// lakukan request AJAX
// kita umpamakan berhasil dan selesai dalam waktu 1,5 detik
setTimeout(function(){
resolve("Autentikasi user berhasil!"); console.log('Autentikasi berhasil'); }, 1500);
});
}
function ambilDataBerita(url) {
return new Promise(function(resolve, reject) {
// lakukan request AJAX
// kita umpamakan berhasil dan selesai dalam waktu 2,5 detik
setTimeout(function(){
resolve('berita terbaru berhasil diambil'); console.log('Berita berhasil diambil'); }, 2500);
});
}
function ambilDataCuaca(url) {
return new Promise(function(resolve, reject) {
// lakukan request AJAX
// kita umpamakan berhasil dan selesai dalam waktu 3,5 detik
setTimeout(function(){
resolve('Data cuaca berhasil diambil'); console.log('Cuaca berhasil diambil'); }, 3500);
});
}
let c = ambilDataCuaca('http://servercuaca.com');
let a = autentikasiUser('http://serverautentikasi.com', 'dicarve', 'rahasia');
let b = ambilDataBerita('http://serverberita.com');
let pAll = Promise.all([c, b, a]).then(hasil => {
console.log('Semua Promise (Janji) telah terpenuhi');
$('.container .alert').removeClass('alert-info').addClass('alert-success').html('Semua data berhasil diambil dari server!');
}, error => {
console.log('Terjadi error karena salah satu Promise tidak bisa terpenuhi!')
$('.container .alert').removeClass('alert-info').addClass('alert-danger').html('Error disebabkan oleh: '+error);
});
</script>
</head>
<body>
<div class="container"><div class="alert alert-info">Loading data...</div></div>
</body>
</html></code></pre>
<p>Ketika kita menggunakan <code>Promise.all</code>, argumen yang digunakan harus berupa <i>Array</i> yang mengandung semua fungsi <b>Promise</b> yang kita eksekusi. Apabila semua fungsi <b>Promise</b> ini berhasil dan terpenuhi (<b>resolve</b>), maka kode di dalam callback pertama fungsi <code>.then</code> akan dieksekusi. Sedangkan apabila salah satu saja gagal alias <b>reject</b>, maka callback kedua akan dijalankan dan pesan error akan muncul. Bagaimana? menarik bukan? sekali kita paham akan pemanfaatan <b>Promise</b> maka kemungkinan besar kita akan banyak memanfaatkannya untuk menuliskan kode yang lebih elegan untuk operasi-operasi <i>asynchronous</i> di kode Javascript kita. Selamat mencoba!</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com1Tsukuba, Ibaraki Prefecture, Japan36.0834857 140.076642335.672891699999994 139.4311953 36.4940797 140.7220893tag:blogger.com,1999:blog-25865790.post-49099396425965926602017-12-27T06:31:00.001-08:002018-01-07T04:41:40.112-08:00Template Aplikasi Web CRUD Sederhana dengan CodeIgniter<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghYFwVaQGkvVdYIM4xI-YvbCj3OmD_jURbebA8nHmqbbwFjbT8Am9w7wAhoeaUCqhYG0dz6wh4-h2juHhJ5uhT1N7Exc7v1caXLPOXyMvM2MofVQDVcv7XhQgIU9bktTLHHEQ/s1600/CodeIgniter+Blog.png" style="width: 100%" /></div>
<p><a href="https://codeigniter.com/">CodeIgniter (CI)</a> adalah <i>framework</i> MVC berbasis PHP favorit saya, terserah deh orang-orang mau bilang sudah ketinggalan zaman, kurang elegan, <a href="https://laravel.com/">kurang "artistis" lah</a> 🤣🤣🤣. Cepat, konfigurasi minimal, tanpa harus menggunakan perintah command-line (eeeehhhmmmm 😬), <i>learning-curve</i> relatif landai dibandingkan framework MVC lain, dan <a href="https://www.codeigniter.com/user_guide/">dokumentasi yang mantap dan mudah dimengerti</a> adalah sebagian dari kelebihan CI yang saya suka (subjektif pastinya). Beberapa aplikasi Open Source yang saya kembangkan seperti <a href="https://github.com/dicarve/pustakawan">Pustakawan</a> dan <a href="http://arteri.sainsinformasi.org/">Arteri</a> menggunakan CI sebagai framework-nya. Karena operasi CRUD (Create-Read-Update-Delete) adalah operasi paling umum dalam sebuah sistem informasi maka kali ini saya akan menuliskan aplikasi web untuk operasi CRUD minimalistik dengan CI yang mungkin bisa bermanfaat sebagai <i>template</i> bagi teman-teman dalam mengembangkan aplikasi lain. Untuk contoh aplikasi CRUD yang kita bangun adalah aplikasi data <b>users</b> dengan tiga buah <i>field</i>/ruas: <b><code>id</code></b>, <b><code>nama</code></b> dan <b><code>email</code></b>.</p>
<h2>Konfigurasi</h2>
<p>Karena ini contoh yang minimalistik maka untuk database lagi-lagi kita gunakan SQLite3. Untuk menggunakan SQLite3 sebagai <i>storage</i> penyimpanan data, maka kita perlu mengkonfigurasi CI dengan membuka file <code>application/config/database.php</code> dan menuliskan konfigurasi database seperti ini:
<h3><code>application/config/database.php</code></h3>
<pre><code class="php">$db['default'] = array(
'dsn' => 'sqlite:./db/db.sq3',
'hostname' => 'localhost',
'username' => '',
'password' => '',
'database' => '',
'dbdriver' => 'pdo',
'dbprefix' => '',
'pconnect' => FALSE,
'db_debug' => (ENVIRONMENT !== 'production'),
'cache_on' => FALSE,
'cachedir' => '',
'char_set' => 'utf8',
'dbcollat' => 'utf8_general_ci',
'swap_pre' => '',
'encrypt' => FALSE,
'compress' => FALSE,
'stricton' => FALSE,
'failover' => array(),
'save_queries' => TRUE
);
</code></pre>
<p>Buatlah sebuah folder dengan nama <code>db</code> pada direktori <i>root</i> CI, karena folder ini akan digunakan sebagai tempat untuk menyimpan file database SQLite3 aplikasi ini. Selanjutnya bukalah file konfigurasi <code>application/config/autoload.php</code> dan ubahlah baris dengan tulisan <code class="php">$autoload['helper'] = array();</code> menjadi <code class="php">$autoload['helper'] = array('url');</code>.</p>
<h2>Controller</h2>
<p>Kita tidak perlu buat file <i>controller</i> khusus, langsung saja kita ubah file <i>controller</i> bawaan CI yaitu <code>application/controllers/Welcome.php</code> dan ubah isi kode di dalamnya dengan editor teks dengan kode berikut ini:</p>
<h3><code>application/controllers/Welcome.php</code></h3>
<pre><code class="php"><?php defined('BASEPATH') OR exit('No direct script access allowed');
class Welcome extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->database();
}
public function index()
{
// buat tabel 'users' apabila belum ada
$this->db->query('CREATE TABLE IF NOT EXISTS users (id VARCHAR PRIMARY KEY, nama VARCHAR, email VARCHAR UNIQUE)');
// apakah ada pencarian data spesifik dengan kata kunci tertentu?
$search = $this->input->get('search');
if (!empty($search)) {
$this->db->like('id', $search, 'both');
$this->db->or_like('nama', $search, 'both');
$this->db->or_like('email', $search, 'both');
}
$users = $this->db->get('users');
$data['result'] = $users->result_array();
$data['num_rows'] = $users->num_rows();
$this->load->view('head');
$this->load->view('read', $data);
$this->load->view('foot');
}
public function save()
{
$input['id'] = $this->input->post('id');
$input['nama'] = $this->input->post('nama');
$input['email'] = $this->input->post('email');
$updateID = $this->input->post('updateID');
if (!empty($updateID)) {
$this->db->where('id', $updateID);
$this->db->update('users', $input);
} else {
$this->db->insert('users', $input);
}
redirect('/welcome/index');
}
public function create()
{
$this->load->view('head');
$this->load->view('create');
$this->load->view('foot');
}
public function update($id)
{
$this->db->where('id', $id);
$data['update'] = $this->db->get('users')->row_array();
$this->load->view('head');
$this->load->view('create', $data);
$this->load->view('foot');
}
public function delete($id)
{
$this->db->where('id', $id);
$data['delete'] = $this->db->get('users')->row_array();
$this->load->view('head');
$this->load->view('delete', $data);
$this->load->view('foot');
}
public function real_delete()
{
$id = $this->input->post('id');
$this->db->where('id', $id);
$this->db->delete('users');
redirect('/welcome/');
}
}
</code></pre>
<h2>Views</h2>
<p>Untuk view buatlah file-file PHP dengan nama-nama berikut: <code>create.php, delete.php, foot.php, head.php, read.php</code> dan isikan masing-masing file tersebut dengan kode-kode sebagai berikut:</p>
<h3><code>application/views/head.php</code></h3>
<pre><code class="html"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CRUD</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="<?php echo site_url('/welcome/') ?>">CRUD</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#menu" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="menu">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a href="<?php echo site_url('/welcome/') ?>" class="nav-link">List</a>
</li>
<li class="nav-item">
<a href="<?php echo site_url('/welcome/create') ?>" class="nav-link">Create New User</a>
</li>
</ul>
</div>
</nav>
</code></pre>
<h3><code>application/views/foot.php</code></h3>
<pre><code class="html"><!-- tambahkan file library javascript apabila dibutuhkan pada bagian ini -->
</body>
</html>
</code></pre>
<h3><code>application/views/read.php</code></h3>
<pre><code class="html"><?php
/**
* View untuk menampilkan daftar/list data (Read)
* beserta dengan form yang memungkinkan pencarian data spesifik dengan kata kunci
*
*/
?>
<br/>
<div class="container">
<div class="card">
<div class="card-body">
<form method="get" action="<?php echo site_url('/welcome/') ?>" class="form-inline">
<div class="form-group">
<input type="text" class="form-control" name="search" id="search" placeholder="Kata Kunci Pencarian">
</div>
<button type="submit" class="btn btn-primary">Cari</button>
</form>
</div>
</div>
<br/>
<div class="alert alert-info">Ditemukan data dalam jumlah <strong><?php echo $num_rows ?></strong></div>
<table class="table table-bordered">
<tr>
<th>ID</th><th>Nama</th><th>E-mail</th>
<th style="width: 1%;"> </th><th style="width: 1%;"> </th>
</tr>
<?php foreach ($result as $r) {
echo '<tr>';
echo '<td>'.$r['id'].'</td><td>'.$r['nama'].'</td><td>'.$r['email'].'</td>';
echo '<td><a href="'.site_url('/welcome/update/'.$r['id']).'" class="btn btn-primary">Edit</a></td>';
echo '<td><a href="'.site_url('/welcome/delete/'.$r['id']).'" class="btn btn-danger">Delete</a></td>';
echo '</tr>';
}
?>
</table>
</div>
</code></pre>
<h3><code>application/views/create.php</code></h3>
<pre><code class="html"><?php
/**
* View untuk form penambahan (Create) data dan sekaligus pengubahan (Update) data
*
*/
// periksa apakah kita sedang dalam mode 'Update'
if (!isset($update)) {
$update = array('id' => '', 'nama' => '', 'email' => '');
} else {
$update_flag = '<input type="hidden" name="updateID" value="'.$update['id'].'">';
}
?>
<br/>
<div class="container">
<?php if (isset($update_flag)) {
echo '<div class="alert alert-info">Anda akan mengubah data user <strong>'.$update['nama'].'</strong></div>';
} ?>
<div class="card">
<div class="card-body">
<form method="post" action="<?php echo site_url('/welcome/save') ?>">
<div class="form-group">
<label for="id">ID</label>
<input type="text" class="form-control" name="id" id="id" value="<?php echo $update['id'] ?>" placeholder="ID User">
</div>
<div class="form-group">
<label for="nama">Nama</label>
<input type="text" class="form-control" name="nama" id="nama" value="<?php echo $update['nama'] ?>" placeholder="Nama">
</div>
<div class="form-group">
<label for="email">E-mail</label>
<input type="email" class="form-control" name="email" id="email" value="<?php echo $update['email'] ?>" placeholder="E-mail">
</div>
<?php if (isset($update_flag)) {
echo $update_flag;
} ?>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</div>
</code></pre>
<h3><code>application/views/delete.php</code></h3>
<pre><code class="html"><?php
/**
* View untuk proses konfirmasi penghapusan data (Delete)
*
*/
?>
<br />
<div class="container">
<div class="card">
<div class="card-body">
<form method="post" action="<?php echo site_url('/welcome/real_delete') ?>">
<p>Apakah anda yakin ingin menghapus user <strong><?php echo $delete['nama'] ?></strong></p>
<input type="hidden" name="id" value="<?php echo $delete['id'] ?>">
<a class="btn btn-primary" href="<?php echo site_url('/welcome/') ?>">BATAL</a>
<button type="submit" class="btn btn-danger">DELETE</button>
</form>
</div>
</div>
</div>
</code></pre>
<p>Selesai! Apabila semua kode sudah ditulis dengan benar maka kita akan melihat antar muka aplikasi kita seperti berikut ini:</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKBVYDpWAGMBdR71CrzbuQfiD3aQfulowTqnDw0sLSFqN4n5LaHPZJed1C8ZxnVO6emhA4MazTjUUWLd9kfRzkmIAMToE3igzodefdqkt6GY1-w4CcLjm1xMdPgRWzpwVYnSo/s1600/crud-views.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKBVYDpWAGMBdR71CrzbuQfiD3aQfulowTqnDw0sLSFqN4n5LaHPZJed1C8ZxnVO6emhA4MazTjUUWLd9kfRzkmIAMToE3igzodefdqkt6GY1-w4CcLjm1xMdPgRWzpwVYnSo/s1600/crud-views.png" style="width: 100%" /></a></div>
<p>Selamat mencoba dan semoga bermanfaat!</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com11tag:blogger.com,1999:blog-25865790.post-46414834967034725132017-12-20T23:18:00.002-08:002017-12-26T03:05:38.372-08:00Frontend aplikasi web dengan AngularJS dan backend PHP<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLC50k1n4ezgwGfk2KMDSeBEcQ-f0KlzOeOooJIJPRjjOCk7bLEWoet5kJ8aAtLC2nVhQHoNfRoxn7P1ZUzfFnTJSP76dO3RMplS4Bp3exmXiLpvUv8SIqnqABwf7vowAV_p0/s1600/Angular-blog.jpg" style="width: 100%" /></div>
<p>Sebenarnya topik ini sudah agak basi, tetapi berhubung saya ingin mendokumentasikan <em>"eksperimen"</em> saya pada framework frontend dan backend untuk pengembangan aplikasi berbasis web, maka saya tetap ingin menulis artikel ini. Bagi teman-teman yang belum mengenal framework AngularJS, bisa membaca FAQ-nya di <a href="https://docs.angularjs.org/misc/faq">halaman FAQ AngularJS</a>. Intinya AngularJS adalah framework untuk membangun antarmuka aplikasi web berbasis Javascript. Ada dua versi Angular, AngularJS (versi 1) dan Angular (versi 2) yang full terintegrasi dengan Node.js, yang saya bahas adalah versi pertama dimana kita tidak perlu menggunakan Node.js. Kenapa saya memilih versi ini karena versi pertama bisa kita integrasikan dengan <em>project</em> aplikasi web yang sudah dengan backend apapun, dalam artikel ini saya menggunakan PHP.</p>
<h2>Instalasi</h2>
<p>Untuk menggunakan AngularJS kita perlu mengunduh (<i>download</i>) <a href="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js">file Javascript-nya AngularJS terlebih dahulu</a>. Setelah file Javascript AngularJS telah terunduh berikutnya kita tinggal me-link file Javascript tersebut dari dalam kode HTML kita. Pada artikel ini saya menempatkan file <code>angular.min.js</code> pada direktori <code>libs/js/angular.min.js</code>. Apabila kita masukkan pada kode HTML akan seperti ini:
<pre><code class="html5"><!doctype html>
<html ng-app="arsipApp"><head>
<title>Aplikasi Web Arsip</title>
<script src="libs/js/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
</head></code></pre>
Atau apabila aplikasi web kita sudah kita letakkan pada server dan sudah terkoneksi dengan jaringan Internet maka kita bisa memanfaatkan layanan CDN:
<pre><code class="html"><!doctype html>
<html ng-app="arsipApp"><head>
<title>Aplikasi Web Arsip</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">
</head></code></pre>
Pada kode di atas saya juga me-link file HTML dengan framework CSS <a href="http://getbootstrap.com/">Bootstrap</a> agar tampilan aplikasi web sedikit lebih nyaman dilihat.
<h2>Frontend static</h2>
<p>Bagi teman-teman yang sudah menggunakan aplikasi web Gmail atau Google Mail maka akan melihat bahwa Google membangun antarmukanya dengan menggunakan Javascript yang kemungkinan juga merupakan cikal bakal dari lahirnya framework AngularJS ini. AngularJS menganut prinsip MVW (Model-View-Whatever), dimana file HTML merupakan View (tampilan) dan kode Javascript yang mengandung logika aplikasi dan model (<i>controller</i>). Untuk contoh aplikasi web yang saya buat untuk artikel ini saya akan membuat aplikasi web untuk pendataan Arsip sederhana. Untuk melihat cara kerja dari AngularJS ada baiknya kita coba dengan menggunakan halaman web sederhana yang menggunakan data tidak permanen (data tidak disimpan secara permanen ke backend). Buatlah sebuah file HTML dengan nama <code>index.html</code> dan isikan dengan kode HTML berikut:</p>
<h3><code>index.html</code></h3>
<pre><code class="html"><!doctype html>
<html <span style="background-color: yellow">ng-app</span>="arsipApp">
<head>
<title>Aplikasi Web Arsip</title>
<script src="libs/js/angular.min.js"></script>
<script src="controllers/arsip.js"></script>
<link rel="stylesheet" type="text/css" href="libs/bootstrap/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<h2>Aplikasi Arsip</h2>
<hr/>
<div <span style="background-color: yellow">ng-controller</span>="arsipController as arsip">
<input type="text" <span style="background-color: yellow">ng-model</span>="arsip.cari" class="form-control" style="border-radius: 50px;" placeholder="Masukkan kata kunci untuk mencari" />
<hr/>
<h5>Tambah Data Arsip</h5>
<form name="formArsip" <span style="background-color: yellow">ng-submit</span>="arsip.tambah()">
<div class="row">
<div class="col">
<input type="text" <span style="background-color: yellow">ng-model</span>="arsip.inputKode" class="form-control" placeholder="Kode arsip" required />
</div>
<div class="col">
<input type="text" <span style="background-color: yellow">ng-model</span>="arsip.inputJudul" class="form-control" placeholder="Judul arsip" required />
</div>
<div class="col">
<input class="btn btn-primary" type="submit" value="Tambah" <span style="background-color: yellow">ng-disabled</span>="formArsip.$invalid">
</div>
</div>
</form>
<hr/>
<div class="alert alert-info">Jumlah total arsip <span style="background-color: cyan">{{arsip.total()}}</span></div>
<table class="table table-bordered table-striped">
<thead>
<tr><th>Kode</th><th>Judul</th><th> </th></tr>
</thead>
<tbody>
<tr <span style="background-color: yellow">ng-repeat</span>="data in arsip.data | filter:arsip.cari track by data.kode">
<td><span style="background-color: cyan">{{data.kode}}</span></td>
<td><span style="background-color: cyan">{{data.judul}}</span></td>
<td><button type="button" class="btn btn-danger" <span style="background-color: yellow">ng-click</span>="arsip.hapus(data.kode)">Hapus</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
</code></pre>
<p>Buatlah sebuah direktori baru dengan nama <code>controllers</code>, dan didalam direktori baru ini buatlah sebuah file Javascript bernama <code>arsip.js</code>. Isikan file tersebut dengan kode berikut:</p>
<h3><code>controllers/arsip.js</code></h3>
<pre><code class="javascript">/**
* Modul "arsipApp"
* Controller "arsipController"
*/
angular.module('arsipApp', []).controller('arsipController', function() {
// variabel "arsip" merujuk kepada objek/instance dari "arsipController"
var arsip = this;
// controller "arsipController" memiliki property/anggota "data" untuk menampung data arsip
arsip.data = [];
// metode "tambah" untuk menambahkan data arsip
arsip.tambah = function() {
arsip.data.push({kode: arsip.inputKode, judul:arsip.inputJudul});
arsip.inputJudul = '';
arsip.inputKode = '';
};
// metode "hapus" untuk menghapus data arsip terpilih
arsip.hapus = function() {
var konf = confirm('Yakin akan menghapus data ini?');
if (konf) {
arsip.data.splice(this.$index, 1);
}
};
// metode "total" untuk mendapatkan jumlah total data arsip
arsip.total = function() {
var count = arsip.data.length;
return count;
};
});
</code></pre>
<p>Pada kode HTML <code>index.html</code> coba perhatikan pada atribut tag yang saya berikan warna kuning, atribut-atribut tersebut adalah atribut spesifik AngularJS atau biasa juga disebut <i>directive</i>. Atribut <code style="background-color: yellow">ng-app</code> contohnya menandakan bahwa halaman web ini menggunakan modul <code>arsipApp</code> yang kita definisikan pada file <code>controllers/arsip.js</code>, sedangkan atribut <code style="background-color: yellow">ng-controller</code> menetapkan bahwa semua yang berada di dalam <em>scope</em> atau cakupan dari tag tersebut bisa menggunakan controller <code>arsipController</code> yang instance/objek-nya bernama <code>arsip</code> sebagaimana tertulis <code>arsipController as arsip</code>. Atribut <code style="background-color: yellow">ng-repeat</code> kita gunakan untuk melakukan iterasi/loop data. Atribut <code style="background-color: yellow">ng-model</code> mengikat (<i>binding</i>) tag tersebut ke properti yang namanya didefinisikan di dalamnya. Atribut <code style="background-color: yellow">ng-click, ng-submit</code> merupakan atribut terkait <i>event</i> yang terjadi pada browser, dimana nilai atribut-atribut ini biasanya memanggil metode-metode yang sudah kita definisikan pada controller <code>arsipController</code>. Adapun untuk menampilkan nilai (<i>value</i>) dari suatu variabel Javascript pada AngularJS kita menggunakan ekspresi <span style="background-color: cyan">{{namaVariabel}}</span>. Apabila kita buka file <code>index.html</code> pada browser maka kita akan melihat tampilan seperti berikut ini:</p>
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglEGi1XBlAyjIM8W1Z_Ssr8C37I4EZwTSY_TTm9KuTSJqT4Vetba5Ot5yijoBdlnzMsTY0K93IDyKa1-BXa8tg0FCBt_A9eSXHoG8HR8GBJi-_unN3Liw0I3FrVyrKSCtiUrM/s1600/Aplikasi+Web+AngularJS.png" style="width: 80%" /></div>
<p>Coba isikan beberapa data arsip untuk melihat hasilnya.</p>
<h2>Frontend Dinamis dengan Backend server</h2>
<p>Sayangnya pada contoh aplikasi yang kita buat sebelumnya, data arsip yang kita buat tidaklah permanen karena aplikasi sebenarnya hanya berjalan di sisi <i>client</i> saja (<i>browser</i>), sehingga ketika browser kita tutup maka data arsip yang sudah kita masukkan hilang. Agar kita bisa menyimpan data arsip secara permanen maka kita harus menggunakan backend server, salah satunya dengan menggunakan PHP. Kita bisa juga menggunakan solusi penyimpanan data cloud seperti Firebase atau Google Cloud. Untuk contoh kali ini kita akan membuat <i>backend</i> sendiri dengan menggunakan PHP dan database SQLite. Buatlah sebuah folder pada direktori web server dengan nama <code>testws</code> dan di dalamnya buatlah file PHP dengan nama <code>index.php</code>, <code>db.php</code>, <code>post.php</code> dan sebuah direktori kosong dengan nama <code>db</code> (sebagai tempat file database SQLite_. Isikan file <code>index.php</code> dengan kode sebagai berikut:</p>
<h3><code>htdocs/testws/db.php</code></h3>
<pre><code class="php"><?php
// koneksi ke database SQLite3
try {
$pdo = new PDO('sqlite:./db/arsip.sq3', null, null, array(PDO::ATTR_PERSISTENT => true));
} catch(Exception $e) {
$error = array('error' => 'Gagal terkoneksi ke database karena '.$e);
// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
echo json_encode($error); die();
}
// buat tabel apabila belum ada
$table_def = 'CREATE TABLE IF NOT EXISTS arsip (kode VARCHAR PRIMARY KEY, judul VARCHAR NOT NULL)';
$create = $pdo->exec($table_def);
if ($create === false) {
$error = array('error' => 'Error ketika membuat tabel!');
// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
echo json_encode($error); die();
}</code></pre>
<p>Script PHP <code>index.php</code> melakukan koneksi ke database SQLite dengan nama <code>arsip.sq3</code> dan membuat tabel arsip apabila belum ada sebelumnya.</p>
<h3><code>htdocs/testws/index.php</code></h3>
<pre><code class="php"><?php
// koneksi ke database SQLite3
require 'db.php';
// ambil data
$json = array();
$select_str = 'SELECT * FROM arsip';
// filter data berdasarkan kata kunci pencarian
$filter = filter_input(INPUT_GET, 'katakunci');
if ($filter) {
$select_str .= " WHERE kode LIKE '$filter%' OR judul LIKE '%$filter%'";
}
$query_data = $pdo->query($select_str);
while ($row = $query_data->fetch(PDO::FETCH_ASSOC)) {
$json[] = $row;
}
// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json');
echo json_encode($json); die();</code></pre>
<p>Script PHP <code>index.php</code> menampilkan data dalam format JSON.</p>
<h3><code>htdocs/testws/post.php</code></h3>
<pre><code class="php"><?php
// koneksi ke database SQLite3
require 'db.php';
// masukkan data
$post_data = file_get_contents('php://input');
$input = json_decode($post_data);
if (is_object($input)) {
$sth = $pdo->prepare('REPLACE INTO arsip VALUES (:kode, :judul)');
$data = array(':kode' => $input->kode, ':judul' => $input->judul);
$sth->execute($data);
$json = array('status' => 'sukses');
} else {
$json = array('status' => 'gagal');
}
// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: *');
header('Access-Control-Allow-Methods: POST');
header('Content-type: application/json');
echo json_encode($json); die();</code></pre>
<p>Script PHP <code>post.php</code> menerima data dalam format JSON melalui front end AngularJS untuk dimasukkan ke database SQLite.</p>
<h3><code>htdocs/testws/delete.php</code></h3>
<pre><code class="php"><?php
// koneksi ke database SQLite3
require 'db.php';
// masukkan data
$kode_delete = file_get_contents('php://input');;
if (!empty($kode_delete)) {
$sth = $pdo->prepare('DELETE FROM arsip WHERE kode=:kode');
$data = array(':kode' => $kode_delete);
$sth->execute($data);
$json = array('status' => 'sukses');
} else {
$json = array('status' => 'gagal');
}
// tampilkan data dalam format json
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: *');
header('Access-Control-Allow-Methods: DELETE');
header('Content-type: application/json');
echo json_encode($json); die();</code></pre>
<p>Script PHP <code>delete.php</code> menghapus record arsip pada database SQLite sesuai dengan kode yang dikirim melalui front end AngularJS. Kita juga harus mengubah kode controller Javascript kita pada file <code>arsip.js</code> agar menggunakan service <code>$http</code> yang disediakan oleh AngularJS untuk melakukan request AJAX ke backed server PHP yang sudah kita buat.</p>
<h3><code>controllers/arsip.js</code></h3>
<pre><code class="javascript">/**
* Modul "arsipApp"
* Controller "arsipController"
*/
angular.module('arsipApp', []).controller('arsipController', function($scope, <span style="background-color: yellow">$http</span>) {
// variabel "arsip" merujuk kepada objek/instance dari "arsipController"
var arsip = this;
// controller "arsipController" memiliki property/anggota "data" untuk menampung data arsip
arsip.data = [];
// ambil data arsip dari server
<span style="background-color: yellow">$http</span>.get('http://localhost/testws/index.php').then(function(response) {
arsip.data = response.data;
});
// metode "tambah" untuk menambahkan data arsip
arsip.tambah = function() {
var baru = {kode:arsip.inputKode, judul:arsip.inputJudul};
var updateIndex = arsip.data.findIndex(function(obj) {
return obj.kode == arsip.inputKode;
});
<span style="background-color: yellow">$http</span>.post('http://localhost/testws/post.php', angular.toJson(baru))
.then(function() {
if (updateIndex > -1) {
arsip.data[updateIndex].kode = arsip.inputKode;
arsip.data[updateIndex].judul = arsip.inputJudul;
} else {
arsip.data.push(baru);
}
arsip.inputJudul = '';
arsip.inputKode = '';
}, function() {
alert('Data gagal dimasukkan ke database');
});
};
// metode "hapus" untuk menghapus data arsip terpilih
arsip.hapus = function(kode) {
var deleteIndex = arsip.data.findIndex(function(obj) {
return obj.kode == kode;
});
var konf = confirm('Yakin akan menghapus data ini?');
if (konf) {
<span style="background-color: yellow">$http</span>.delete('http://localhost/testws/delete.php', {data: kode})
.then(function() {
arsip.data.splice(deleteIndex, 1);
}, function() {
alert('Data gagal dihapus ke database');
});
}
};
// metode "ubah" untuk mengubah data arsip
arsip.ubah = function(kode) {
var ubahIndex = arsip.data.findIndex(function(obj) {
return obj.kode == kode;
});
console.log(arsip.inputKode);
arsip.inputJudul = arsip.data[ubahIndex].judul;
arsip.inputKode = arsip.data[ubahIndex].kode;
};
// metode "total" untuk mendapatkan jumlah total data arsip
arsip.total = function() {
var count = arsip.data.length;
return count;
};
});
</code></pre>
<p>Pada kode view <code>index.html</code> kita ubah sedikit kode HTML pada bagian tag table menjadi seperti berikut ini:</p>
<h3><code>index.html</code></h3>
<pre><code class="html">...
<table class="table table-bordered table-striped">
<thead>
<tr><th>Kode</th><th>Judul</th><th> </th><th> </th></tr>
</thead>
<tbody>
<tr ng-repeat="data in arsip.data | filter:arsip.cari track by data.kode">
<td>{{data.kode}}</td>
<td>{{data.judul}}</td>
<td><button type="button" class="btn btn-info" ng-click="arsip.ubah(data.kode)">Ubah</button></td>
<td><button type="button" class="btn btn-danger" ng-click="arsip.hapus(data.kode)">Hapus</button></td>
</tr>
</tbody>
</table>
...
</code></pre>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxeKmvnAoQAgCmPtXz247aG7zhhenSXhOqh1mcQXP2drO2Z1vzkHf-LOjPU0q_8Nn6iaXMXbZ-FJOXFbevagsJ-Hu9-JlqNWIw3PEiW2oe9D9gUEtuDUU6z7kqCqMpjw2EmuM/s1600/Screenshot-2017-12-26+Aplikasi+Web+Arsip.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxeKmvnAoQAgCmPtXz247aG7zhhenSXhOqh1mcQXP2drO2Z1vzkHf-LOjPU0q_8Nn6iaXMXbZ-FJOXFbevagsJ-Hu9-JlqNWIw3PEiW2oe9D9gUEtuDUU6z7kqCqMpjw2EmuM/s400/Screenshot-2017-12-26+Aplikasi+Web+Arsip.png" width="400" height="245" data-original-width="1600" data-original-height="979" /></a></div>
<p>Dengan menggunakan kode baru ini maka aplikasi web AngularJS kita telah menggunakan data real-time ke server backend menggunakan PHP dan database SQLite, silahkan dicoba untuk memasukkan data, menghapus dan mengubah data. Selamat coding dan mencoba 😁.</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com4tag:blogger.com,1999:blog-25865790.post-8565305789912289752017-12-12T22:44:00.001-08:002017-12-14T00:32:40.732-08:00Membangun Aplikasi Web dengan Platform MVC Rails (Ruby)<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR8mHCBqz9cJkaVHb5_nx2VMv7Ld9EXJZ2-gIf_OjXErkk4exjBjVWwp-MEY2Q0vw_teIMxe-CmL9q5vfuWgb1lf-S8V9Yih0DtlbWudmKVJBp-hd7M-iXokvJWdDaoRorvpQ/s1600/Screenshot-2017-12-13+Ruby+on+Rails.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR8mHCBqz9cJkaVHb5_nx2VMv7Ld9EXJZ2-gIf_OjXErkk4exjBjVWwp-MEY2Q0vw_teIMxe-CmL9q5vfuWgb1lf-S8V9Yih0DtlbWudmKVJBp-hd7M-iXokvJWdDaoRorvpQ/s400/Screenshot-2017-12-13+Ruby+on+Rails.png" width="400" height="228" data-original-width="1600" data-original-height="912" /></a></div>
<p>Ruby dikenal sebagai salah satu bahasa pemrograman yang relatif mudah dipelajari. Salah satu framework Model-View-Controller yang cukup populer berbasis Ruby adalah <a href="http://rubyonrails.org/">Rails</a>. Kali ini saya tertarik untuk mendokumentasikan pengembangan aplikasi web dengan menggunakan framework Rails. Untuk menggunakan Rails tentunya kita harus memastikan bahwa Ruby sudah terinstall pada Komputer/PC kita. Ruby pada sistem operasi GNU/Linux, macOS dan beberapa varian UNIX lain biasanya sudah terinstall secara default, sedangkan bagi pengguna sistem operasi Windows harus menginstall Ruby terlebih dahulu melalui <a href="https://rubyinstaller.org/">RubyInstaller</a>. Bagi pengguna macOS seperti saya ada baiknya menginstall <a href="https://brew.sh/">Homebrew</a> terlebih dahulu, untuk memudahkan instalasi perangkat lunak tambahan pihak ketiga seperti Rails. Ada beberapa persyaratan perangkat lunak yang harus tersedia sebelum kita mulai menggunakan Rails yang instalasinya akan saya jelaskan pada paragraf-paragraf berikutnya. Pastikan komputer/PC kita terkoneksi dengan jaringan Internet untuk melalui tahapan proses instalasi Rails.</p>
<h1>Instalasi</h1>
<h2>GNU/Linux</h2>
<p>Pengguna GNU/Linux dengan distro-distro populer seperti Ubuntu, Debian, CentOS, SuSe, RedHat, dsb. dapat menginstall Rails dengan mudah menggunakan aplikasi package-manager bawaan. Seperti pada Ubuntu 16.04 kita jalankan perintah-perintah berikut ini secara berurutan pada aplikasi console/terminal:
<pre><code class="bash">curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update
sudo apt-get install git-core zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev nodejs yarn
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
exec $SHELL
rbenv install 2.4.2
rbenv global 2.4.2
gem install bundler
gem install rails
rbenv rehash
</code></pre>
Wwweeeeww panjang yak! 😂😂😂. Kalau tidak ada masalah dalam proses perjalanan instalasinya maka Rails siap digunakan.
</p>
<h2>Apple macOS</h2>
<p>Tahapan paling pertama adalah pastikan bahwa kita sudah menginstall Xcode dan command-line toolsnya (bisa didownload gratis melalui laman resmi Apple di <a href="https://developer.apple.com/xcode/">https://developer.apple.com/xcode/</a> (ukuran file instalasi Xcode besar, pastikan mengunduh dengan menggunakan jaringan WiFi atau LAN, kecuali paket data 4G Anda unlimited FUP-nya :D ). Apabila Xcode sudah terinstall berikutnya buka Terminal dan jalankan:
<pre><code class="bash">xcode-select --install</code></pre>
Akan muncul dialog terkait dengan lisensi yang harus kita setujui. Pengguna GNU/Linux, UNIX, ataupun Windows tidak perlu melakukan tahap ini.</p>
<p>Khusus pengguna Apple macOS jangan lupa meng-install Homebrew pada macOS dengan membuka aplikasi Terminal dan jalankan perintah berikut:
<pre><code class="bash">/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"</code></pre></p>
<p>Berikutnya jangan lupa mengupdate "gem" (package manager khusus library Ruby) ke versi terbaru:
<pre><code class="bash">sudo gem update --system</code></pre></p>
<p>Lagi-lagi Khusus pengguna Apple macOS, tahap berikutnya kita perlu menginstall library libxml2 dari Homebrew, karena entah kenapa di macOS High Sierra (11.13.1) dengan Xcode versi teranyar selalu gagal di proses kompilasi library Nokogiri (parser HTML dan XML) karena libxml2 yang tidak cocok.
<pre><code class="bash">brew install libxml2
sudo gem install -n /usr/local/bin nokogiri -- --use-system-libraries --with-xml2-include=$(brew --prefix libxml2)/include/libxml2</code></pre></p>
<p>Setelah semua sukses diinstall baru kemudian kita install Rails dan Bundler dengan perintah:
<pre><code class="bash">sudo gem install -n /usr/local/bin rails
sudo gem install -n /usr/local/bin bundler</code></pre>
Tunggu proses hingga selesai. Apabila tidak muncul galat/error selama prosesnya makan Rails berhasil terinstall di Komputer/PC kita. Kemungkinan besar Anda akan bertanya apa itu "Bundler"? Bundler adalah dependancy manager semua gems (library Ruby) untuk project aplikasi yang dibangun dengan Rails. Dengan menggunakan bundle kita memastikan bahwa requirement gems aplikasi web kita terpenuhi.</p>
<h2>Microsoft Windows ( versi >= 7)</h2>
<p>Instalasi Rails di sistem operasi Windows, bisa dibilang gampang-gampang susah (sebenarnya instalasi di GNU/Linux dan Apple macOS juga tidak bisa dibilang gampang 😂😂😂), karena ada beberapa perangkat lunak pendukung yang harus ada. Berikut langkah-langkahnya:
<ol>
<li>Install Ruby dengan mengunduh/men-download dan menjalankan installer RubyInstaller. Pastikan opsi "Add Ruby executables to your PATH" dicentang pada saat proses instalasi</li>
<li>Install MSYS2 dari <a href="http://www.msys2.org/">http://www.msys2.org/</a>, karena Rails akan membutuhkan library native Ruby yang dikompilasi dengan compiler C</li>
<li>Unduh/download NodeJS dan jalankan installer-nya dari <a href="https://nodejs.org">https://nodejs.org</a></li>
<li>Buka/cari aplikasi "Start Command Prompt with Ruby" dari RubyInstaller yang terdapat pada menu utama Windows</li>
<li>Pada Command Prompt Ruby ketikkan perintah: <pre><code class="bash">gem install rails
gem install bundler</code></pre></li>
</ol>
Apabila tidak ada masalah dalam proses perjalanan instalasinya maka Rails siap digunakan.
</p>
<h1>Membangun Aplikasi Web</h1>
<p>Hampir serupa dengan model framework fullstack seperti Meteor yang saya tulis pada <a href="https://dicarve.blogspot.jp/2017/11/membangun-aplikasi-web-dengan-platform.html">artikel sebelumnya</a>, apabila kita akan membuat aplikasi web dengan Rails maka Rails akan membuatkan skeleton/kerangka dari aplikasi kita. Untuk membuat aplikasi web baru dengan Rails, maka pada Terminal jalankan perintah berikut:
<pre><code class="bash">rails new aplikasiweb -d sqlite3 -B
cd aplikasiweb/
bundle install
</code></pre>
Tunggu sampai proses selesai. Perintah diatas membuat sebuah direktori aplikasi web baru bernama "aplikasiweb" beserta dengan skeleton/kerangka dan semua requirement yang dibutuhkan dan secara default menggunakan database <code>sqlite3</code> sebagai backend penyimpanan datanya, bagi penggemar MySQL bisa diganti dengan <code>mysql</code>, bagi penggemar PostgreSQL bisa diganti dengan <code>postgresql</code>. SQLite3 dipilih karena dia sangat sederhana, hanya berbasis file dan tidak membutuhkan instalasi perangkat lunak tambahan, cocok untuk aplikasi web sederhana untuk belajar.
</p>
<h2>Controller dan Views</h2>
<p>Ketika membangun aplikasi web berbasis MVC, biasanya saya membuat "Controller" terlebih dahulu, ada juga dengan yang mulai dengan membangun "Model" terlebih dahulu, ini masalah selera dan kebiasaan kalau menurut saya. Controller bisa kita anggap sebagai logika bisnis dari sebuah aplikasi, yang mengatur proses/flow aplikasi berjalan. Untuk membuat controller bernama <code>"Home"</code> dengan sebuah metode bernama <code>"index"</code> kita akan menjalankan perintah berikut:
<pre><code class="bash">rails generate controller home index</code></pre>
Setelah menjalankan perintah ini kita akan melihat bahwa rails membuat beberapa file, tetapi yang paling penting adalah file <code>app/controllers/home_controller.rb</code> dan <code>app/views/home/index.html.erb</code>, kedua file ini yang akan kita modifikasi isinya alias <em>coding</em>. Buka file explorer dan kemudian arahkan ke dalam direktori/folder <code>aplikasiweb</code> dan bukalah kedua file tersebut dengan editor teks favorit masing-masing.
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf_te2KlDcNnePy1kHF-KzCIJvCvufarPUTd2Xg9K94AMpVLTfXi3bWBAgT2lcMkX3S05YwszVCl9tgO8rxj5klhxqE53w8N8rve9nGtlFRBJxiMKlENE-YV2POFCqzLCYpV4/s1600/rails+directories.png" style="width: 80%; display: block; margin: 0 auto;" /></p>
Isikan kedua file tersebut dengan kode-kode seperti berikut ini:
</p>
<h3><code>app/controllers/home_controller.rb</code></h3>
<p><pre><code class="ruby">class HomeController < ApplicationController
def index
@judul = 'Aplikasi Web Rails'
@isi = 'Halo Rails!'
end
end</code></pre></p>
<h3><code>app/views/home/index.html.erb</code></h3>
<p><pre><code class="html"><h1><%= @judul %></h1>
<hr/>
<p><%= @isi %></p><</code></pre>
Fungsi dari file <code>app/views/home/index.html.erb</code> adalah sebagai "views" atau "tampilan" bagi controller <code>"Home"</code> dan metode <code>"index"</code>.
</p>
<p>Untuk melihat bagaimana aplikasi web sederhana ini berjalan, maka pada Terminal/console, pastikan kita berada di dalam direktori <code>aplikasiweb</code>, jalankan perintah berikut:
<pre><code class="bash">rails server -p 9000</code></pre>
Kemudian bukalah browser favorit masing-masing dan arahkan ke URL: <a href="http://localhost:9000/home/index">http://localhost:9000/home/index</a> dan kita akan melihat hasil seperti gambar berikut:
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd_x6WFi9NqRslPJPtMux_LU9Wf9siJx3yLc6pGYU93KuehNL6VWouBKwqDtHkS-LvTrtzay9seRIEXcB6BRsHaoDFXMy7B0FzIWPMzR8-RbxI4PnAH3O_S3m6cdmvO4y9iY0/s1600/Rails+preview+1.png" style="width: 70%; display: block; margin: 0 auto;" /></p>
Apabila pada browser terlihat seperti tampilan di atas maka, selamat! kita sudah berhasil membuat aplikasi web dengan Rails pertama kita!
</p>
<p>Sekarang kita ubah <em>coding</em> controller <code>"Home"</code> kita:
<h3><code>app/controllers/home_controller.rb</code></h3>
<p><pre><code class="ruby">class HomeController < ApplicationController
# metode index
def index
@judul = 'Aplikasi Web Rails'
@isi = 'Halo Rails!'
end
# metode informasi
def informasi
@judul = 'Halaman Informasi'
@isi = 'Ini adalah halaman informasi terkait dengan aplikasi web yang dibangun dengan Rails. '
@isi << 'Rails adalah framework MVC berbasis Ruby yang banyak digunakan oleh pengembang aplikasi web '
@isi << 'di Internet'
# array daftar framework
@framework = [{:url => 'http://rubyonrails.org/', :text => 'Ruby on Rails'},
{:url => 'https://codeigniter.com/', :text => 'Codeigniter'},
{:url => 'http://www.web2py.com/init/default/index', :text => 'Web2py'}
]
end
end</code></pre></p>
Kita mendefinisikan metode baru bernama <code>"informasi"</code> yang nantinya akan diakses melalui URL <a href="http://localhost:9000/home/informasi">http://localhost:9000/home/informasi</a>. Tetapi sebelum bisa diakses kita perlu membuat sebuah file "views" yang akan menampilkan isi dari metode "informasi". Buatlah file <code>app/views/home/informasi.html.erb</code> dan isikan dengan kode berikut:
<h3><code>app/views/home/informasi.html.erb</code></h3>
<p><pre><code class="html"><h1><%= @judul %></h1>
<hr/>
<p><%= @isi %></p>
<p>Framework MVC populer antara lain:
<ul>
<% @framework.each do |mv| %>
<li><a href="<%= mv[:url] %>"><%= mv[:text] %></a></li>
<% end %>
</ul>
</p></code></pre></p>
Kemudian bukalah file <code>config/routes.rb</code> dan ubahlah isi file tersebut menjadi seperti berikut:
<h3><code>config/routes.rb</code></h3>
<p><pre><code class="ruby">Rails.application.routes.draw do
root 'home#index'
get 'home/index'
get 'home/informasi'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end</code></pre></p>
Buka browser kemudian arahkan ke URL: <a href="http://localhost:9000/home/informasi">http://localhost:9000/home/informasi</a> dan kita akan melihat hasil seperti gambar berikut:
<p><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvIYVCbtxqftFVyVDQ5pcjRjJOL2hieXXwMGYxcN9vW01dbYLv8iXd-aN2ntpgI-z-lBOy3XiXEWeXlBcBGuaI4-ROwoPjXgqvXWAe9lKHfNM3Ge7WKNzbZRx0Vm8UIvYPGvo/s1600/Rails+sample+2.png" style="width: 70%; display: block; margin: 0 auto;" /></p>
Jangan lupa menambahkan daftar "route" pad file <code>config/routes.rb</code>, setiap kali kita menambahkan metode pada controller agar bisa diakses melalui browser.
</p>
<h3>Integrasi dengan framework UI (Bootstrap)</h3>
<p>Sejauh ini contoh aplikasi yang kita buat tampilannya sangat sederhana, karena kita belum menambahkan CSS di aplikasi kita. Framework seperti Rails menyediakan cara mengintegrasikan framework UI seperti <a href="http://getbootstrap.com/">Bootstrap</a> tanpa harus men-setup secara manual. Caranya adalah seperti ini:
<ol>
<li>Matikan server Rails yang sedang berjalan pada Terminal/console/command prompt dengan menekan <strong>"Ctrl+C"</strong></li>
<li>Buka file <code>Gemfile</code> (bukan <code>Gemfile.lock</code>) yang terdapat pada root direktori aplikasi web Rails kita dengan editor teks dan kemudian pada baris akhir tambahkan:
<h4><code>Gemfile</code></h4>
<p><pre><code class="bash"># Bootstrap
gem 'bootstrap', '~> 4.0.0.beta'
gem 'jquery-rails'</code></pre></p></li>
<li>Kembali ke Terminal/console/command prompt, masuk ke direktori aplikasi web kita dan jalankan perintah:
<p><pre><code class="bash">bundle install
mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss</code></pre></p></li>
<li>Buka file <code>app/assets/stylesheets/application.scss</code> dengan editor teks dan kemudian pada baris akhir tambahkan:
<h4><code>app/assets/stylesheets/application.scss</code></h4>
<p><pre><code class="bash">@import "bootstrap";</code></pre></p></li>
<li>Buka file <code>app/assets/javascripts/application.js</code> dengan editor teks dan kemudian pada baris akhir tambahkan:
<h4><code>app/assets/javascripts/application.js</code></h4>
<p><pre><code class="bash">//= require jquery3
//= require popper
//= require bootstrap</code></pre></p></li>
<li>Hidupkan kembali server Rails dengan perintah:
<p><pre><code class="bash">rails server -p 9000</code></pre></p></li>
</ol>
</p>
<p>Sebelum kita lihat efek perubahan halaman web kita dengan terinstallnya Bootstrap, mari kita ubah dulu kode di beberapa file <code>views</code> kita menjadi seperti berikut ini:
<h3><code>app/views/home/index.html.erb</code></h3>
<p><pre><code class="html"><div class="jumbotron jumbotron-fluid" style="background-image: url('/bg.jpg'); background-size: cover;">
<div class="container">
<h1 class="display-3">Selamat Datang</h1>
<p class="lead">Ruby on Rails!</p>
</div>
</div>
<div class="container">
<h1><%= @judul %></h1>
<hr/>
<p><%= @isi %></p>
</div></code></pre></p>
<h3><code>app/views/home/informasi.html.erb</code></h3>
<p><pre><code class="html"><div class="container">
<h1 class="text-center"><%= @judul %></h1>
<hr/>
<p><%= @isi %></p>
<p>Framework MVC populer antara lain:
<ul>
<% @framework.each do |mv| %>
<li><a href="<%= mv[:url] %>"><%= mv[:text] %></a></li>
<% end %>
</ul>
</p>
</div>
</code></pre></p>
Buatlah dua file views baru, masing-masing bernama <code>_main_menu.html.erb</code> dan <code>_footer.html.erb</code>, dan letakkan kedua file ini pada direktori <code>app/views/layouts/</code> dan isikan masing-masing dengan kode berikut:
<h3><code>app/views/layouts/_main_menu.html.erb</code></h3>
<p><pre><code class="html"><nav class="navbar navbar-dark bg-dark">
<a class="navbar-brand" href="/">Aplikasi Web Rails</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="mainMenu">
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="/">Beranda</a></li>
<li class="nav-item"><a class="nav-link" href="/home/informasi">Informasi</a></li>
</ul>
</div>
</nav></code></pre></p>
<h3><code>app/views/layouts/_footer.html.erb</code></h3>
<p><pre><code class="html"><div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-3">Selamat Datang</h1>
<p class="lead">Ruby on Rails!</p>
</div>
</div>
<div class="container">
<h1><%= @judul %></h1>
<hr/>
<p><%= @isi %></p>
</div></code></pre></p>
Kemudian bukalah file <code>app/views/layouts/application.html.erb</code> yang merupakan file views layout utama aplikasi Rails dan isikan dengan kode berikut:
<h3><code>app/views/layouts/application.html.erb</code></h3>
<p><pre><code class="html"><!DOCTYPE html>
<html>
<head>
<title>Aplikasi Web Rails</title>
<meta name="dc.creator" content="Ari Nugraha" />
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= render "layouts/main_menu" %>
<%= yield %>
<%= render "layouts/footer" %>
</body>
</html></code></pre></p>
File views <code>app/views/layouts/_main_menu.html.erb</code> dan <code>app/views/layouts/_footer.html.erb</code> dalam terminologi Rails disebut sebagai "partial views", yaitu file views yang merupakan potongan-potongan untuk dimasukkan ke dalam file views lain, dalam hal ini kedua file tersebut kita masukkan ke dalam file views <code>app/views/layouts/application.html.erb</code> dengan menggunakan perintah <code>render</code>. Tanda <u>underscore</u> ditiadakan ketika kita meng-include "partial views" dengan perintah <code>render</code>. Apabila semua kode telah kita tuliskan dengan benar maka kita akan melihat hasil aplikasi web kita menjadi seperti berikut ini:
</p>
<div style="width: 45%; float: left">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCt89k-cIwsO5c4tqgCFx2Wv-yofe-tXPO2WJduBhyphenhyphenxRfJqRPdCYLEPogMMO3n4_3EAQCiH-Sr8Y5T0IfUs9jnv9-iSXhcgkgVp7DTmQZHO8Vy4cIYESI3P1nLaHxscFzGjfA/s1600/Rails+bootstrap+1.png" style="width: 90%; display: block; margin: 0 auto;" />
</div>
<div style="width: 45%; float: right">
<img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtH8NB358OlDK3HACD0mcSep8URER2vbH0pn8FVRUAwfSAd4xUD8JKkTU42xFb-ZAJEW6ooVuU9fyfFxDN-5E4QeWpr5yzy5g9eDil77RQ6wdV6sr7uGHANK0Avpg304Cok2s/s1600/Rails+bootstrap+2.png" style="width: 90%; display: block; margin: 0 auto;" />
</div>
<div style="clear: both"> </div>
<p>Bisa kita lihat setelah diintegrasikan dengan Bootstrap, tampilan aplikasi web kita menjadi lebih bagus dan tentunya menjadi responsive secara otomatis.</p>
<h2>Model</h2>
<p>Kita sudah melihat bagaimana cara kerja <em>controller</em> dan <em>views</em> pada Rails, dan tentunya aplikasi web yang dinamis akan memiliki konten yang dibuat secara dinamis juga, dimana konten-konten dinamis ini biasanya disimpan dan diambil dari <em>database</em>. Model dalam hal ini mendefinisikan bagaimana data dari sebuah aplikasi dibuat, diambil/dibaca, diubah dan dihapus atau bahasa kerennya operasi <em>CRUD (Create, Read, Update, Delete)</em>. Untuk lebih jelasnya mengenai bagaimana pemanfaatan Model di Rails akan saya tuliskan pada artikel berikutnya :).</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com0tag:blogger.com,1999:blog-25865790.post-68843646542118195392017-11-17T18:33:00.002-08:002017-12-13T16:59:38.595-08:00Membangun Aplikasi Web dengan Platform Javascript Fullstack Meteor <div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif6p8BsKH_hr5GASSGjddE3GCOiE0IEiPFTQuTzaldXdmIqh8xcLnsK7HbAjGyWa1kIsFGauNCna9jykgxR2iwbDWqvUT2gD1xcLTlWyqb9XVpjFkjOqkQjbi4HJTSP9mxrG8/s1600/JavaScript+Meteor.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1004" data-original-width="1600" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif6p8BsKH_hr5GASSGjddE3GCOiE0IEiPFTQuTzaldXdmIqh8xcLnsK7HbAjGyWa1kIsFGauNCna9jykgxR2iwbDWqvUT2gD1xcLTlWyqb9XVpjFkjOqkQjbi4HJTSP9mxrG8/s320/JavaScript+Meteor.jpg" width="320" /></a></div>
<p>Sudah lama tidak menulis blog, rasanya kangen juga ingin menulis sesuatu. Kebetulan disuruh oleh sensei (supervisor PhD) untuk belajar bahasa pemrograman baru untuk web programming, setelah baca-baca prosiding konferensi ACM CHI Conference on Human Factors in Computing Systems 2017, salah satu paper menuliskan tentang pengembangan prototipe aplikasi berbasis web untuk kolaborasi pemrograman web dan platform yang mereka gunakan untuk membangun aplikasi tersebut adalah platform berbasis server side <a href="https://nodejs.org/">Javascript NodeJS</a>, <a href="https://www.meteor.com/">Meteor</a>. Akhirnya saya tertarik untuk mencoba membangun aplikasi dengan menggunakan Meteor dan sekalian mencoba mendokumentasikan pengembangan aplikasi dengan menulis artikel blog ini, dan siapa tahu bermanfaat untuk teman-teman yang membacanya, terutama yang sedang mencari, ehhhmmmm... bahasa pemrograman baru :D .<br />
Sebelumnya kita mulai ada baiknya kita kenal dulu apa itu Meteor sebenarnya. Seperti saya kutip dari <a href="http://docs.meteor.com/#/full/">dokumentasi terakhir Meteor</a>, Meteor adalah:</p>
<blockquote>Meteor is a full-stack JavaScript platform for developing modern web and mobile applications... Meteor uses <i>data on the wire</i>, meaning the server sends data, not HTML, and the client renders it.</blockquote>
<p>Konsep hampir serupa dengan <i>data on the wire</i> sebenarnya juga diterapkan pada beberapa framework Javascript seperti <a href="https://angularjs.org/">AngularJS</a> dan <a href="https://reactjs.org/">ReactJS</a>, dimana data dari server tidak dikirim dalam bentuk kode HTML, tetapi dalam bentuk data seperti <a href="https://www.json.org/">JSON (JavaScript Object Notation)</a> dan kemudian data dari server diformat ke dalam kode HTML yang diproses oleh library Javascript di sisi klien, membuat beban komunikasi server dan klien menjadi lebih ringan karena hanya berkomunikasi dalam format data ringan seperti JSON. Meteor pada intinya adalah sebuah <i>platform fullstack</i> yang intinya adalah NodeJS, beserta dengan beberapa komponennya, termasuk juga Meteor sudah menyediakan server MongoDB sehingga kita tidak perlu lagi install MongoDB sebagai server terpisah. (sisi negatifnya adalah ukuran download Meteor yang besar dan harus di-download melalui terminal/command line).
</p>
<p>Untuk mengembangkan aplikasi web dengan menggunakan Meteor, ada beberapa hal yang sebaiknya kita kuasai terlebih dahulu yaitu: HTML5, CSS, Javascript, jQuery dan MongoDB. Jangan lupa juga menginstall text editor pemrograman favorit masing-masing untuk menuliskan kode-kode Javascript Meteor nanti.
</p>
<h2>Instalasi</h2>
<p>Untuk menggunakan platform Meteor maka kita harus menginstallnya terlebih dahulu dengan menggunakan terminal/console/command prompt/powershell. Pada tulisan ini saya menggunakan aplikasi Terminal pada Operating System (OS) Apple macOS High Sierra dan kemudian menjalankan perintah:
<pre><code class="bash">curl https://install.meteor.com/ | sh</code></pre>
Pengguna OS GNU/Linux dengan berbagai distro-nya bisa menjalankan perintah yang sama, pastikan bahwa <strong>curl</strong> sudah terinstall, apabila belum, install terlebih dahulu dengan menggunakan package manager distro masing-masing.
</p>
<p>Bagi pengguna OS Microsoft Windows, ada perangkat lunak tambahan untuk menginstall Meteor yaitu <a href="https://chocolatey.org/">Chocolatey</a>. Chocolatey merupakan package manager/software installer untuk platform Windows. Cara instalasi Chocolatey silahkan ikuti buka tautan/link ke <a href="https://chocolatey.org/install">cara instalasi Chocolatey</a>. Setelah Chocolatey terinstall maka langkah berikutnya adalah menjalankan perintah berikut pada command prompt/powershell Windows:
<pre><code class="bash">choco install meteor</code></pre>
</p>
<h2>Persiapan Kerangka Struktur Aplikasi</h2>
<p>Setelah Meteor sudah terinstall, maka kita bisa mulai untuk membuat aplikasi web Javascript pertama kita. Untuk contoh aplikasi web yang akan kita kembangkan adalah aplikasi sederhana untuk membuat agenda kegiatan. Pada Terminal jalankan perintah berikut ini secara berurutan:
<pre><code class="bash">mkdir meteorapp
cd meteorapp
meteor create agendakegiatan
cd agendakegiatan
</code></pre>
</p>
<p>Saat ini kita sedang berada di dalam folder/direktori agendakegiatan dan kita akan melihat bahwa pada folder ini Meteor sudah membuat kerangka dasar aplikasi web kita (<i>skeleton</i>), yang terdiri atas folder <code>client</code>, <code>server</code>, <code>node_modules</code>, dan file <code>package-lock.json</code> dan <code>package.json</code>. Kita akan banyak bermain di dalam folder <code>client</code>, <code>server</code> dan satu buah folder ini tempat kita akan banyak menyimpan berbagai kode Javascript yaitu <code>imports</code>. Folder <code>client</code> adalah folder yang mengandung semua file terkait dengan apa yang akan ditampilkan kepada browser, sedangkan folder <code>server</code> mengandung semua file terkait dengan pemrosesan di sisi server.
<br />
Karena folder <code>imports</code> belum ada, maka kita perlu membuatnya terlebih dahulu, sekaligus kita membuat folder-folder lain di bawahnya dengan menjalankan perintah-perintah berikut:
<br />
<pre><code class="bash">mkdir imports
cd imports
mkdir ui
mkdir api
</code></pre>
</p>
<p>Setelah kita selesai membuat folder-folder baru tersebut, maka selanjutnya kita juga perlu membuat beberapa file tambahan yang akan kita isikan dengan kode Javascript dan kode HTML. Jalankan perintah-perintah berikut ini untuk membuat file-file tersebut:
<pre><code class="bash">touch ui/body.html
touch ui/body.js
touch api/agenda.js
</code></pre>
</p>
<h2>Coding</h2>
<p>Saatnya kita mulai menuliskan kode-kode! Buka text editor favorit masing-masing dan bukalah file-file berikut ini (relatif terhadap direktori <code>agendakegiatan</code> :
<br />
<ol>
<li><code>client/main.html</code></li>
<li><code>client/main.js</code></li>
<li><code>client/main.css</code></li>
<li><code>imports/ui/body.html</code></li>
<li><code>imports/ui/body.js</code></li>
<li><code>imports/api/agenda.js</code></li>
<li><code>server/main.js</code></li>
</ol>
Berikutnya silahkan ubah dan isikan masing masing file dengan kode-kode berikut.
</p>
<h3><code>client/main.html</code></h3>
<pre><code class="html"><head>
<title>Aplikasi Agenda Kegiatan</title>
<meta name="author" content="Ari Nugraha"/>
<meta name="keywords" content="Meteor, Javascript, Agenda, Aplikasi Web"/>
</head>
</code></pre>
<h3><code>client/main.js</code></h3>
<pre><code class="javascript">import '../imports/ui/body.js';</code></pre>
<h3><code>imports/ui/body.html</code></h3>
<pre><code class="html"><body>
<div class="ui container">
<h2 class="ui block header">Agenda Kegiatan</h2>
<div class="ui container segment">
<form class="ui form form-kegiatan">
<div class="three fields">
<div class="field">
<label>Nama Kegiatan</label>
<input type="text" name="nama_kegiatan" class="form-text form-control" placeholder="Nama kegiatan" />
</div>
<div class="field">
<label>Tanggal Kegiatan</label>
<input type="text" name="tgl_kegiatan" class="form-text form-control" placeholder="Tanggal kegiatan" />
</div>
<div class="field">
<label>Lokasi Kegiatan</label>
<input type="text" name="lokasi_kegiatan" class="form-text form-control" placeholder="Lokasi kegiatan" />
</div>
</div>
<input type="hidden" name="_id" value="" />
</form>
<table class="ui celled table">
<thead>
<tr>
<th class="ten wide">Nama Kegiatan</th>
<th>Tanggal</th>
<th>Lokasi</th>
<th class="one wide"> </th>
</tr>
</thead>
<tbody>
{{#each agenda}}
{{> data}}
{{/each}}
</tbody>
</table>
</div>
</div>
</body>
<template name="data">
<tr>
<td><a class="edit-button" data-id="{{_id}}" href="#">{{kegiatan}}</a></td>
<td>{{tgl}}</td>
<td>{{lokasi}}</td>
<td><button class="ui icon button delete"><i class="trash icon"></i></button></td>
</tr>
</template>
</code></pre>
<h3><code>imports/ui/body.js</code></h3>
<pre><code class="javascript">import { Template } from 'meteor/templating';
import { Agenda } from '../api/agenda.js';
import './body.html';
Template.body.helpers({
agenda() {
return Agenda.find({}, { sort: { tgl: -1 } });
}
});
Template.body.events({
'keypress .form-text'(event) {
// event.preventDefault();
// console.log(event);
const enterKey = event.key == "Enter";
// console.log(enterKey);
if (enterKey) {
// ambil objek form
const form = $('.form-kegiatan');
// ambil nilai form
const kegiatan = form.find('[name="nama_kegiatan"]');
const tgl = form.find('[name="tgl_kegiatan"]');
const lokasi = form.find('[name="lokasi_kegiatan"]');
const _id = form.find('[name="_id"]');
if (!kegiatan.val() || !tgl.val() || !lokasi.val()) {
return false;
}
// console.log(form);
if (_id.val().trim() != '') {
// masukkan ke database
Agenda.update(
{_id: _id.val()},
{ kegiatan: kegiatan.val(),
tgl: tgl.val(),
lokasi: lokasi.val(),
});
} else {
// masukkan ke database
Agenda.insert({
kegiatan: kegiatan.val(),
tgl: tgl.val(),
lokasi: lokasi.val(),
tgl_input: new Date(),
});
}
// reset nilai form
kegiatan.val('');
tgl.val('');
lokasi.val('');
_id.val('');
}
}
});
Template.data.events({
'click .delete'(event) {
const confirmDelete = confirm('Yakin akan menghapus data ini?');
if (confirmDelete) {
Agenda.remove(this._id);
}
},
'click .edit-button'(event) {
const updateData = Agenda.findOne({_id: this._id});
// console.log(updateData);
const form = $('.form-kegiatan');
const kegiatan = form.find('[name="nama_kegiatan"]');
const tgl = form.find('[name="tgl_kegiatan"]');
const lokasi = form.find('[name="lokasi_kegiatan"]');
const _id = form.find('[name="_id"]');
kegiatan.val(updateData.kegiatan);
tgl.val(updateData.tgl);
lokasi.val(updateData.lokasi);
_id.val(this._id);
}
});
</code></pre>
<h3><code>imports/api/agenda.js</code></h3>
<pre><code class="javascript">import { Mongo } from 'meteor/mongo';
export const Agenda = new Mongo.Collection('agenda');
</code></pre>
<h3><code>server/main.js</code></h3>
<pre><code class="javascript">import '../imports/api/agenda.js';</code></pre>
<h3><code>client/main.css</code></h3>
<pre><code class="css">body {
margin: 0; padding: 0;
top: 0; bottom: 0;
left: 0; right: 0;
position: absolute;
min-height: 100%;
font-family: Helvetica, sans-serif, Arial;
background: #777;
}
.container {
position: relative;
margin: 0 auto;
width: 600px;
background: #ccc;
height: 100%;
}
.header {
text-align: center;
background: linear-gradient(180deg, #555, #999);
margin: 0;
color: #fff;
padding: 20px;
}
.field {
clear: both;
}
.field label {
padding: 5px;
display: block;
float: left;
width: 24%;
}
.field input {
padding: 5px;
display: block;
float: right;
width: 72%;
font-size: 1.1em;
border: 0;
border-bottom: 1px solid #ccc;
}
.table {
width: 100%;
border-spacing: 0;
}
.celled thead tr th {
padding: 10px;
border-bottom: 1px solid #333;
background: linear-gradient(180deg, #555, #999);
margin: 0;
color: #fff;
}
.celled tbody tr td {
margin: 0;
padding: 9px;
border-bottom: 1px solid #777;
}
.button {
display: inline-block;
width: 100%;
font-size: 1.2em;
}
</code></pre>
<h2>Ujicoba Aplikasi</h2>
<p>Setelah semua kode sudah kita tuliskan maka berikutnya adalah mengujicoba apakah aplikasi sudah berjalan dengan baik. Untuk menjalankan aplikasi dengan Meteor, buka kembali Terminal/console, masuk ke dalam folder aplikasi <code>agendakegiatan</code> dan kemudian jalankan perintah:
<pre><code class="bash">meteor</code></pre>
maka kemudian kita akan melihat status seperti ini pada Terminal/console kita:
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiAJBPa7yX34kxSiK1ZLn_oPsrFnrmcvsfDjqFMTbYfY8epQSsftrJCv8w2pr2t2-ZSUxfYOJX4xGX0tFXjan3b7VY6mPMLKTk98y07xSDl1m9lG9J3TeG2XuFgArIGb2fb-o/s1600/meteor-is-run.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="929" data-original-width="1600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiAJBPa7yX34kxSiK1ZLn_oPsrFnrmcvsfDjqFMTbYfY8epQSsftrJCv8w2pr2t2-ZSUxfYOJX4xGX0tFXjan3b7VY6mPMLKTk98y07xSDl1m9lG9J3TeG2XuFgArIGb2fb-o/s320/meteor-is-run.png" style="width: 80%;" /></a></div></p>
<p>Selanjutnya buka browser favorit masing-masing dan arahkan ke alamat URL: <a href="http://localhost:3000/">http://localhost:3000</a>, dan kita akan melihat aplikasi web kita sudah berjalan dengan tampilan seperti ini:
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR4MDQXPlPJHNwLucsesKBix1fvmFWSgjIfipFMtgsn0DmGw5K51kXMESNTCFPoO7ihDpwhP3n06IQeSQJUVRYD8re768u_E3fCIlnjusmDWB9Lz5DGETM2Vf7XOeXY06QdCw/s1600/Screenshot-2017-11-18+Aplikasi+Agenda+Kegiatan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="968" data-original-width="1200" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR4MDQXPlPJHNwLucsesKBix1fvmFWSgjIfipFMtgsn0DmGw5K51kXMESNTCFPoO7ihDpwhP3n06IQeSQJUVRYD8re768u_E3fCIlnjusmDWB9Lz5DGETM2Vf7XOeXY06QdCw/s320/Screenshot-2017-11-18+Aplikasi+Agenda+Kegiatan.png" width="320" /></a></div></p>
<p>Coba isikan data pada kotak input isian nama kegiatan, tanggal kegiatan dan lokasi kegiatan dan kemudian tekan <strong>Enter</strong> untuk melihat menyimpan data isian kita. Kita lihat bahwa setelah kita menekan tombol <strong>Enter</strong>, maka data yang kita masukkan langsung muncul pada tabel di bawah form isian tanpa terjadi reload halaman! Dan yang lebih menarik bahwa apabila kita menjalankan dua browser yang berbeda bersamaan, ketika kita mengupdate data pada satu browser, maka otomatis tampilan pada browser lain akan otomatis terupdate tanpa harus me-refresh/reload browser tersebut! Hal ini terjadi karena aplikasi yang dibangun dengan Meteor telah menerapkan konsep <strong>push</strong> dari server ke client. Silahkan lihat pada video di bawah ini untuk melihat demo push data pada Meteor:</p>
<iframe width="560" height="315" style="display: block; margin: 0 auto;" src="https://www.youtube.com/embed/AVuclU6Xs9c" frameborder="0" gesture="media" allowfullscreen></iframe>
<p>Bagaimana? menarik bukan membangun aplikasi dengan menggunakan Meteor? Mengenai penjelasan lebih detail mengenai masing-masing kode, akan saya coba tulis pada artikel berikutnya, selamat mencoba dan semoga bermanfaat!</p>
arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com1tag:blogger.com,1999:blog-25865790.post-11721632281916247532014-12-01T16:02:00.002-08:002017-12-13T18:05:00.275-08:00Presentasi "Interoperabilitas SLiMS" dan "RDA dengan SLiMS" di SLiMS Commeet 2014 Semarang<p>Bagi rekan-rekan yang tertarik dan ingin membaca presentasi saya mengenai <b>Interoperabilitas dengan SLiMS</b> dan <b>RDA dengan SLiMS</b> di SLiMS Commeet 2014 Semarang beberapa waktu yang lalu, bisa mengunduhnya pada tautan berikut ini:</p>
<ul>
<li><a href="https://drive.google.com/file/d/0BzZt7DLxfV4XNXkxWGNKdkNaT3M/view?usp=sharing">Interoperabilitas dengan SLiMS</a></li>
<li><a href="https://drive.google.com/file/d/0BzZt7DLxfV4XbXlrUnlXUkdEa3c/view?usp=sharing">RDA dengan SLiMS</a></li>
</ul>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com1tag:blogger.com,1999:blog-25865790.post-64380695440614012682014-08-04T05:14:00.003-07:002018-01-07T04:56:52.521-08:00Memindahkan Direktori Database MySQL di Ubuntu GNU/Linux<p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihmIsG3og5rzWqT0cGPW3RX3E2xzGPbZ956ljgM_SMfmhEqj6ZZazYXc2Hb9xuznAWS5jMoZ2oyg_hK0UJjjgxrkbJ26CkqwxJE-h7ixGPMw9n3aa8LlEsr0jXihsk8YjpmRQ/s1600/Screenshot+from+2014-08-04+20:08:04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihmIsG3og5rzWqT0cGPW3RX3E2xzGPbZ956ljgM_SMfmhEqj6ZZazYXc2Hb9xuznAWS5jMoZ2oyg_hK0UJjjgxrkbJ26CkqwxJE-h7ixGPMw9n3aa8LlEsr0jXihsk8YjpmRQ/s400/Screenshot+from+2014-08-04+20:08:04.png"></a></div></p>
<p>Baru baru ini saya meng-<i>install</i> sistem operasi <i>desktop</i> Ubuntu versi 14.04.1 LTS ke laptop dan salah satu aplikasi "wajib" adalah <i>database server</i> MySQL, karena hampir semua aplikasi web yang saya bangun menggunakan MySQL sebagai <i>backend</i>-nya. Salah satu kebiasaan saya ketika meng-<i>install</i> MySQL adalah memindahkan direktori tempat MySQL menyimpan semua databasenya ke lokasi non-standar, yang <i>by default</i> berlokasi di <code>/var/lib/mysql</code>, saya pindahkan ke lokasi <code>/home/direktori/mysql</code> misalnya. Hal ini saya lakukan agar memudahkan pemindahan dan backup data apabila Ubuntu-nya akan saya upgrade ke versi <i>major</i>.</p>
<p>Ternyata memindahkan direktori database MySQL di distro GNU/Linux populer seperti Ubuntu dan CentOS tidak semudah zaman dahulu, seperti zaman Ubuntu versi 8.04 dulu (lama banged yak :p) misalnya. Kalau dulu cukup ubah konfigurasi di file konfigurasi <code>/etc/my.cnf</code>, ubah <i>permission</i> direktori, restart <i>daemon</i> semua langsung jalan. Dengan semakin tinggi-nya keamanan di lapisan aplikasi ada beberapa hal yang harus kita lakukan untuk memindahkan direktori database MySQL di distro Ubuntu 14.04. Berikut akan saya paparkan caranya.</p>
<h3>Ubah konfigurasi di my.cnf</h3>
<p>Tahap pertama adalah dengan mengubah/memodifikasi file konfigurasi utama MySQL, <code>my.cnf</code>, yang pada Ubuntu terletak pada direktori <code>/etc/mysql</code>. Pada konfigurasi default kita akan melihat konfigurasi seperti ini:
<pre><code class="bash">...
[mysqld]
#
# * Basic Settings
#
...
datadir = /var/lib/mysql/
...</code></pre>
Ubah file <code>my.cnf</code> dengan <i>text editor</i> favorit anda, dan ubah pada bagian parameter <code>datadir</code> dan pada bagian InnoDB menjadi sebagai berikut:
<pre><code class="bash">...
[mysqld]
#
# * Basic Settings
#
...
datadir = /home/dicarve/mysql # sesuaikan dengan direktori baru database MySQL yang kita inginkan
...
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
innodb_data_home_dir = /home/dicarve/mysql/
innodb_log_group_home_dir = /home/dicarve/mysql/
innodb_data_file_path = ibdata1:10M:autoextend
...</code></pre>
Simpan perubahan file tersebut.
</p>
<p>Selanjutnya buka program <code>Terminal</code> dan ubah <i>ownership</i> direktori baru database MySQL kita (dalam hal ini <code>/home/dicarve/mysql</code>), agar bisa diakses oleh daemon server MySQL, sekaligus kita copy-kan isi direktori <code>/var/lib/mysql</code> ke direktori baru kita dengan perintah:
<pre><code class="bash">dicarve@localhost:~$ sudo cp -R /var/lib/mysql/* /home/dicarve/mysql/
dicarve@localhost:~$ sudo chown -R mysql /home/dicarve/mysql</code></pre>
</p>
<h3>Ubah setting AppArmor</h3>
<p>
Distro GNU/Linux populer biasanya menggunakan AppArmor, sebuah modul sistem keamanan kernel Linux yang salah satu fungsinya adalah membatasi aplikasi-aplikasi tertentu di lingkungan GNU/Linux, agar hanya bisa mengakses berkas atau direktori tertentu. Untuk lebih jelasnya mengenai AppArmor bisa kita baca di <a href="http://wiki.apparmor.net/index.php/Main_Page">Wiki AppArmor</a>. Agar daemon server MySQL bisa mengakses direktori database baru yang sudah kita ubah di file <code>my.cnf</code>, kita harus mengubah konfigurasi AppArmor MySQL dengan memodifikasi file <code>/etc/apparmor.d/local/usr.sbin.mysqld</code>. Tambahkan baris berikut pada berkas tersebut:
<pre><code class="bash"># Site-specific additions and overrides for usr.sbin.mysqld.
# For more details, please see /etc/apparmor.d/local/README.
/home/dicarve/mysql/* rw</code></pre>
Simpan perubahan berkas tersebut kemudian jalan perintah berikut pada Terminal:
<pre><code class="bash">dicarve@localhost:~$ sudo /etc/init.d/apparmor reload</code></pre>
</p>
<h3>Restart server MySQL</h3>
<p>
Selanjutnya adalah me-restart server MySQL kita dengan perintah:
<pre><code class="bash">dicarve@localhost:~$ sudo /etc/init.d/mysql restart</code></pre>
Apabila semua berjalan lancar, maka kita telah berhasil memindahkan direktori database MySQL kita ke lokasi yang baru yang kita inginkan. Ada kemungkinan cara ini juga berhasil untuk database server <a href="https://mariadb.org/">MariaDB</a>, tetapi saya belum mencobanya. Semoga bermanfaat dan selamat mencoba :).
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com1tag:blogger.com,1999:blog-25865790.post-3202927809294093982014-05-13T04:25:00.000-07:002017-12-13T18:05:30.279-08:00Memanfaatkan Facades pada Framework Laravel<blockquote>"Facades provide a "static" interface to classes that are available in the application's IoC container."</blockquote>
<p>Terjemahan bebas dari saya adalah <em>Facades</em> menyediakan antar muka <em>static</em> pada semua kelas yang ada dalam Laravel, biasanya <em>Model</em>. Untuk lebih mengerti mengenai apa itu Inversion of Control (IoC) <em>container</em> dan Facade silahkan anda membaca artikel karya Edd Mann yang berjudul
<a href="http://eddmann.com/posts/how-static-facades-and-ioc-are-used-in-laravel/" target="blank"><em>How Static Facades and IoC are used in Laravel</em></a>. Salah satu fitur menarik dari <em>framework</em> <a href="http://laravel.com">Laravel</a> adalah <em>Facades</em>, Facade ada dimana-mana pada Laravel, bahkan tanpa sadar kita juga sudah sering menggunakannya, misalnya statement <strong>View::make('form'), Redirect::to('front'), Input::get('nama')</strong>, dsb. Misalnya kita memiliki sebuah kelas model dalam aplikasi Laravel kita seperti ini:</p>
<pre><code class="php">
namespace AhliInformasi;
class Pustakawan {
/**
* Ambil semua data Pustakawan
*/
public function semuaPustakawan($offset=0, $limit=100) {
return DB::table('pustakawan')->select(DB::Raw('id,
nama_pustakawan,
tingkatan.nama as tingkatan_pustakawan,
status.nama as status_pustakawan,
email_pustakawan,
foto_pustakawan'))
->join('tingkatan', 'pustakawan.tingkatan', '=', 'tingkatan.id')
->join('status', 'pustakawan.status', '=', 'status.id')
->orderBy('login_terakhir', 'desc')->skip($offset)->take($limit);
}
/**
* Ambil detail data Pustakawan
*/
public function seorangPustakawan($id_nya) {
return DB::table('pustakawan')->where('id', '=', $id_nya)->first();
}
}
</code></pre>
<p>
Model tersebut kita simpan dengan nama AhliInformasi/Pustakawan.php (karena kita menggunakan namespace disini)
dalam direktori model. Nah biasanya ketika kita memanggil model ini di controller kita melakukannya dengan seperti ini:
</p>
<pre><code class="php">
class PustakawanController extends BaseController {
/**
* Ambil semua data Pustakawan
*/
public function lihatSemuaPustakawan($offset=0, $limit=100) {
$pustakawan = new \AhliInformasi\Pustakawan;
$view_data['data_pustakawan'] = $pustakawan->semuaPustakawan($offset, $limit);
return View::make('ahliinformasi.index', $view_data);
}
}
</code></pre>
<p>Dengan memanfaatkan Facades kita bisa lebih mempersingkat pemanggilan model kita sekaligus
lebih ekspresif dan juga lebih mudah di-tes. Untuk menjadikan model kita menjadi Facade maka
kita akan menambahkan sedikit kode, yang pertama adalah "<em>mengikat</em>" atau bahasa kerennya
<em>binding</em> model kita sebagai <em>IoC Container</em>. Cara paling elegan adalah dengan menambahkan
Service Provider:</p>
<pre><code class="php">
namespace AhliInformasi;
use Illuminate\Support\ServiceProvider;
class PustakawanServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('pustakawan', function()
{
return new \AhliInformasi\Pustakawan;
});
}
}
</code></pre>
<p>Simpan file dengan nama PustakawanServiceProvider.php pada direktori model/AhliInformasi. Kemudian tambahkan juga implementasi kelas Facade kita dengan kode berikut ini:</p>
<pre><code class="php">
namespace AhliInformasi;
use Illuminate\Support\Facades\Facade;
class PustakawanFacade extends Facade {
protected static function getFacadeAccessor() { return 'pustakawan'; }
}
</code></pre>
<p>Kemudian simpan dengan nama PustakawanFacade.php pada direktori model/AhliInformasi. Langkah selanjutnya adalah me-register Service Provider dan Facade kita pada file konfigurasi config/app.php, dengan menambahkan:</p>
<pre><code class="php">
'providers' => array(
'Illuminate\Foundation\Providers\ArtisanServiceProvider',
'Illuminate\Auth\AuthServiceProvider',
'Illuminate\Cache\CacheServiceProvider',
'Illuminate\Session\CommandsServiceProvider',
...
'AhliInformasi\PustakawanServiceProvider' // tambahkan ini
),
...
'aliases' => array(
'App' => 'Illuminate\Support\Facades\App',
'Artisan' => 'Illuminate\Support\Facades\Artisan',
'Auth' => 'Illuminate\Support\Facades\Auth',
'Blade' => 'Illuminate\Support\Facades\Blade',
'Cache' => 'Illuminate\Support\Facades\Cache',
'ClassLoader' => 'Illuminate\Support\ClassLoader',
...
'Pustakawan' => 'AhliInformasi\PustakawanFacade' // tambahkan ini
),
</code></pre>
<p>Terakhir jangan lupa untuk men-generate ulang file autoload.php agar kelas-kelas kita yang baru kita buat
dikenali langsung oleh aplikasi (tanpa harus include/require manual), dengan menjalankan perintah berikut
dengan menggunakan terminal pada direktori root aplikasi Laravel:</p>
<pre><code class="bash">
composer dump-autoload
</code></pre>
<p>Jujur sebenarnya saya juga bingung kenapa harus melakukan proses dump-autoload, karena seharusnya semua kelas yang ada
di dalam direktori model secara otomatis di-load oleh Laravel pada saat proses <em>bootstrap</em>,
tetapi ketika saya tidak melakukan proses ini muncul <em>error</em> kelas Service Provider tidak ditemukan.
Selanjutnya dan seterusnya untuk memanggil model Pustakawan kita bisa langsung memanggilnya melalui
Facade kita dengan seperti ini:</p>
<pre><code class="php">
class PustakawanController extends BaseController {
/**
* Ambil semua data Pustakawan
*/
public function lihatSemuaPustakawan($offset=0, $limit=100) {
$view_data['data_pustakawan'] = Pustakawan::semuaPustakawan($offset, $limit);
return View::make('ahliinformasi.index', $view_data);
}
}
</code></pre>
<p>Nah itu penjelasan mengenai Facades pada Laravel, semoga bermanfaat!</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com2tag:blogger.com,1999:blog-25865790.post-47169891442291158032014-04-13T01:45:00.000-07:002017-12-13T18:06:26.727-08:00An (Relatively) Easy Way for Installing Social Feed Manager on Mac OSX<p>On Monday, March 24, 2014 at <a href="http://code4lib.org/conference/2014/">Code4Lib 2014 Conference</a> in Raleigh, North Carolina, i was fortunate to get the opportunity to learn <a href="https://github.com/gwu-libraries/social-feed-manager">Social Feed Manager (SFM)</a>, directly from the developers, Daniel Chudnov, Daniel Kerchner and also Laura Wruber from George Washington University (thank you for all of you for patienly guide me to get SFM working). SFM is a django application for managing multiple feeds of social media data. It's been a long time i'm searching for this kind of software to grab social media feed from Twitter. I know that Twitter already provide an API to fetch tweets, but i'm too lazy to learn the API :D, so SFM is great solution for me.</p>
<p>This article will try to explain step by step on how to install SFM on Mac OSX. Why Mac OSX? because i use Mac OSX on Macbook Air everyday for my work. Currently at the time this article was written, i'm using Mac OSX version 10.7.5 (Lion) with latest update from Apple. Below are the specs of my Macbook Air: <div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihM_LodeATlc-paxEZVAxT9KffMOBSDrtiuwYizOMh5Ae1czulDKkoeHy-NKmoycGlQKqRUC3GYSMl-Uvk8jGMBZ5_7p2CHinXKd4rvEcZFhuHW8wgYnZzTusuovaBGGR2Tx4/s1600/DicarveMacbookAbout.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihM_LodeATlc-paxEZVAxT9KffMOBSDrtiuwYizOMh5Ae1czulDKkoeHy-NKmoycGlQKqRUC3GYSMl-Uvk8jGMBZ5_7p2CHinXKd4rvEcZFhuHW8wgYnZzTusuovaBGGR2Tx4/s400/DicarveMacbookAbout.jpg"></a></div></p>
<p>Ok, lets get it started, before installing SFM on Mac OSX you NEED to have/install these requirements:
<ol>
<li>A working (and fast if you have) Internet connection</li>
<li>A Twitter account!</li>
<li>Latest <a href="https://developer.apple.com/xcode/">Xcode</a>. After finished installing Xcode, open the Xcode.app and accept the Xcode license agreement.</li>
<li>Latest PostgreSQL database server for Mac OSX. I prefer <a href="http://postgresapp.com/">Postgres.app</a>, "The easiest way to get started with PostgreSQL on the Mac" <- that's what they said about it, and i think it is true :)</li>
<li>and after installing Xcode and PostgreSQL, you need to install <a href="http://brew.sh/">Homebrew</a>, a package manager similiar to apt on Ubuntu for Mac OSX.</li>
</ol>
</p>
<p>After successfully installing above three softwares, now you must open Terminal application (press Command+Space button and type "Terminal" if you're too lazy to find it :D) and do the "geek typing" works :D. If you</p>
<p>First installing python package manager, "<strong>pip</strong>" by typing:
<pre><code class="bash">$ sudo easy_install pip</code></pre>
</p>
<p>Second, you need to install python "<strong>virtualenv</strong>" package by typing:
<pre><code class="bash">$ sudo pip install virtualenv</code></pre>
with virtualenv you can localize all required python library dependacies only on project directory (in this case is SFM).
</p>
<p>Now, we start to install the SFM itself by cloning the source code directly from the SFM GitHub repository by typing:
<pre><code class="bash">$ cd
$ git clone git://github.com/gwu-libraries/social-feed-manager.git
$ cd social-feed-manager</code></pre>
In this example, we install the SFM on our home directory. You will see that there is <strong>social-feed-manager</strong> directory on our home directory now.
</p>
<p>Currently, we are inside the <strong>social-feed-manager</strong> directory. We will create a virtual environment directory inside this folder, and we name it ENV by invoking below commands:
<pre><code class="bash">$ virtualenv --no-site-packages ENV
$ source ENV/bin/activate
</code></pre>
You will see there is something a bit different with our command shell, it is appended with "<strong>(ENV)</strong>" which means that we are already inside our python sandbox/virtual environment.
</p>
<p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuLfEXslZd5ccHsp23tHj8D3kKnMxwryOXxSyaQ7IVR22P_CI8_cC1Hs3CEItsfVVXifTPxcKdMmjS86pWSEVuY9sJl1pIocEpeyxW2fdwhhBth7O0EJzUpbOXyYB2hJMUguE/s1600/sfm-virtualenv.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuLfEXslZd5ccHsp23tHj8D3kKnMxwryOXxSyaQ7IVR22P_CI8_cC1Hs3CEItsfVVXifTPxcKdMmjS86pWSEVuY9sJl1pIocEpeyxW2fdwhhBth7O0EJzUpbOXyYB2hJMUguE/s400/sfm-virtualenv.jpg"></a></div></p>
<p>So far so good? Hopefully! :D. Don't worry we will see our SFM working in a few hour to go hahaha, just kidding, in a "few steps" to go. Next step is preparing our PostgreSQL database for SFM to store its data, so we will launch our Postgres.app application and click "Open psql" button to open "psql" terminal. On psql console type below commands:
<pre><code class="sql">CREATE USER sfmuser with createdb PASSWORD 'sfmuser_secret';
CREATE DATABASE sfmdb WITH OWNER sfmuser;
</code></pre>
Remember we create a new database user/role named "sfmuser" with password "sfmuser_secret" and database named "sfmdb". We will use these values on SFM configuration file later.
</p>
<p>
Now go back to the first Terminal application where we installing SFM. We will install all python library dependancies needed by SFM such as Django, Django Social Auth, Oauth, and etc. using below command:
<pre><code class="bash">$ pip install -r requirements.txt
</code></pre>
Just wait until all process finished, and if everything is running smooth you'll see like this:
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix8pJR6_mzXrrJzrvzdvdtuU6kFjek-82BfCOsnqk0ghK5inCfAwSJzRas54tWSrYiWL9ReXM3IrUb6yQNAWOrQ9ah-4gsgcxezMNXkc1hq8WsOrc5aOqiW3oosd7Dh5uCUf4/s1600/sfm-requirements.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix8pJR6_mzXrrJzrvzdvdtuU6kFjek-82BfCOsnqk0ghK5inCfAwSJzRas54tWSrYiWL9ReXM3IrUb6yQNAWOrQ9ah-4gsgcxezMNXkc1hq8WsOrc5aOqiW3oosd7Dh5uCUf4/s400/sfm-requirements.jpg"></a></div>
</p>
<p>Continue! now type the following commands:
<pre><code class="bash">$ cd sfm
$ cp sfm/local_settings.py.template sfm/local_settings.py
$ nano sfm/local_settings.py
</code></pre>
Now you'll see that you're opening the local_settings.py file using nano text editor (yes, you can use another text editors to edit the file if you're allergic to nano), and you must edit some value inside it according to your twitter app configuration. To create your Twitter app, login to <a href="https://apps.twitter.com">https://apps.twitter.com</a> using your Twitter account and create new application in <a href="https://apps.twitter.com/app/new">https://apps.twitter.com/app/new</a>. Fill the new application form like mine below:
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJOiLWYo-tactB5ocZ6rz0fZOvixjCqapIb_WR4ZnRCs5k_BbdncldowLfvpZ_ZeqzgHLIHnfelxIl4tR5Rf5oCy0tGLOEgLwjtq1sojFGeJjPLuIFdQf8cZK_YUjqIRMoVQ0/s1600/Twitter+Apps+Application+Management.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJOiLWYo-tactB5ocZ6rz0fZOvixjCqapIb_WR4ZnRCs5k_BbdncldowLfvpZ_ZeqzgHLIHnfelxIl4tR5Rf5oCy0tGLOEgLwjtq1sojFGeJjPLuIFdQf8cZK_YUjqIRMoVQ0/s400/Twitter+Apps+Application+Management.jpeg"></a></div>
<p>After creating your new Twitter application will get an API Key like this.
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizhPF3X3PnMhGft2GRiZgDGk6H_-BRIImLEpMg7D2EJmc7ctanHgbBmMKBzbaxDDBt6r_Ji9B8bVQvnkAAw_x_T1enb3Lek0bOSf6eaMB96lMIRVVeHfarrqeYgjJz4E_ae7Q/s1600/DicarveSFM+API+Key+2.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizhPF3X3PnMhGft2GRiZgDGk6H_-BRIImLEpMg7D2EJmc7ctanHgbBmMKBzbaxDDBt6r_Ji9B8bVQvnkAAw_x_T1enb3Lek0bOSf6eaMB96lMIRVVeHfarrqeYgjJz4E_ae7Q/s400/DicarveSFM+API+Key+2.jpeg"></a></div>
</p>
</p>
<p>
On local_settings.py you need to change these lines according to your database settings
<pre><code class="bash">
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'sfmdb',
'USER': 'sfmuser',
'PASSWORD': 'sfmuser_secret',
'HOST': 'localhost',
'PORT': '5432',
}
}
</code></pre>
You MUST also change below lines according to your Twitter app API settings
<pre><code class="bash">TWITTER_DEFAULT_USERNAME = 'YOUR TWITTER USERNAME'
TWITTER_CONSUMER_KEY = 'YOUR TWITTER API KEY'
TWITTER_CONSUMER_SECRET = 'YOUR TWITTER API SECRET'
</code></pre>
Save the changes by pressing Control+X and then press Y (if you're using nano).
</p>
<p>
Now you must edit the wsgi.py file by typing these commands:
<pre><code class="bash">$ cp sfm/wsgi.py.template sfm/wsgi.py
$ nano sfm/wsgi.py
</code></pre>
Remove "#" in front of lines like below and change the ENV line so it will be look like this :
<pre><code class="bash">import site
ENV = '/Users/arienugraha/social-feed-manager/ENV'
site.addsitedir(ENV + '/lib/python2.7/site-packages')
</code></pre>
Don't forget to save the changes by pressing Control+X and then press Y (if you're using nano).
</p>
<p>Next step we will create setup a database to be used by djago by typing this command
<pre><code class="bash">$ ./manage.py syncdb</code></pre>
You'll be asked to create superuser for SFM administration page (DON'T USE YOUR TWITTER USERNAME!). In this article i create superuser with username "admin" and password "admin". If everything went smooth you'll something like this:
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1ccCRzPPwkpzqk0f0YnOQz-pxnXXgB6Et5EhAIdLYtOuyzrbVBUL2cUUVQE1dWA3ggQG-IUmUDopf_TIid28pNCsd1gaCR0eNjzgjhEV8jUhi6QKYWgHqri5ZXrQKgpQ1lYU/s1600/django-syncdb.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1ccCRzPPwkpzqk0f0YnOQz-pxnXXgB6Et5EhAIdLYtOuyzrbVBUL2cUUVQE1dWA3ggQG-IUmUDopf_TIid28pNCsd1gaCR0eNjzgjhEV8jUhi6QKYWgHqri5ZXrQKgpQ1lYU/s400/django-syncdb.jpg"></a></div>
</p>
<p>
Next run this:
<pre><code class="bash">$ ./manage.py migrate</code></pre>
</p>
<p>Hoorrayyyy!!! we almost finished! Next we need to run the Django built in web server (yes, you don't have to use Apache or another web server for development and testing) so we can access SFM administration UI. Run below command
<pre><code class="bash">$ ./manage.py runserver</code></pre>
Open your web browser and go to http://localhost:8000/admin to access SFM administration UI. By default Django web server will run on port 8000. If you want Django to run on another port, say it port 9090, just run the command like this :
<pre><code class="bash">$ ./manage.py runserver 9090</code></pre>
and go to http://localhost:9090/admin on your web browser! You'll see something like this on your web browser if everything is OK :
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5EMPj_Yx6jYYajjIhxMZ6HyffqJRRMEG1vlA8ilgp9F9aEsQb9QbdOVkdHjNwDbfM1woRbNbmBT9tRgUNYHU953K40qUliX71eor4uh0CB7JQA-WTgjQWAYRhg74zfRq55Xs/s1600/SFM+admin+UI+Log+in.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5EMPj_Yx6jYYajjIhxMZ6HyffqJRRMEG1vlA8ilgp9F9aEsQb9QbdOVkdHjNwDbfM1woRbNbmBT9tRgUNYHU953K40qUliX71eor4uh0CB7JQA-WTgjQWAYRhg74zfRq55Xs/s400/SFM+admin+UI+Log+in.jpeg"></a></div>
</p>
<p>
Login with username we already create on previous "syncdb" step, in this example the username is "admin" and the password is "admin", and you'll see webpage like this:
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlKhXZ9c453OcdXwakylysSrtf2vlH7A68yjvqtw0Avo_Ev8-6pA7Ww3O93Jq9HxYK1rg8qZUZ7fCWAfWn1BZ4psSg0MGXbCsvyv8gjGneVviT-_kzSJtgFmjwBzHd0GegFq4/s1600/SFM+admin+UI.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlKhXZ9c453OcdXwakylysSrtf2vlH7A68yjvqtw0Avo_Ev8-6pA7Ww3O93Jq9HxYK1rg8qZUZ7fCWAfWn1BZ4psSg0MGXbCsvyv8gjGneVviT-_kzSJtgFmjwBzHd0GegFq4/s400/SFM+admin+UI.jpeg"></a></div>
</p>
<p>
Fiuuhhhh!!! now we have our SFM installed and we are ready to grab Twitter feeds we want. The question is HOW DO I GRAB THE FEEDS THAT I WANT? Relax bro, relax :D. Suppose we want to grab tweets from Twitter user named @slims_official, what we must do is adding her/his Twitter screen name on http://localhost:8000/admin/ui/twitteruser/add/ and fill it on Name form field like this:
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYgsD5PnniNHcAPl9zpxUeh7AplBkFBqMGNUQs9G__6uoTuPSEgiPTDyFjT2GLR7AgZQbWZc_JgPoSx27p8dTNKUQY8a2EPSs4T3PJKCs7_OHacU6KtZS2FXcr3aOlWLEn2-g/s1600/SFM+add+Twitter+user.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYgsD5PnniNHcAPl9zpxUeh7AplBkFBqMGNUQs9G__6uoTuPSEgiPTDyFjT2GLR7AgZQbWZc_JgPoSx27p8dTNKUQY8a2EPSs4T3PJKCs7_OHacU6KtZS2FXcr3aOlWLEn2-g/s400/SFM+add+Twitter+user.jpeg"></a></div>
then click "Save" button at the bottom of the screen. Now on Terminal, run this command to grab about 3200 latest tweets from this user:
<pre><code class="bash">$ ./manage.py user_timeline</code></pre>
and you'll see something like this on your Terminal screen:
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxk5mJjnJ_wAnmD7FiprDptF_K6geREBbwDwyhd0cktw_0Y7PA_16gGUaMb1gZZDdJ1nBMC1OkFxql5OUgRzetuuSvcFrMwqeMyrtPzR2DLfT1JzjIsNj7STCoxyVU84PYlIM/s1600/SFM+user+timeline.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxk5mJjnJ_wAnmD7FiprDptF_K6geREBbwDwyhd0cktw_0Y7PA_16gGUaMb1gZZDdJ1nBMC1OkFxql5OUgRzetuuSvcFrMwqeMyrtPzR2DLfT1JzjIsNj7STCoxyVU84PYlIM/s400/SFM+user+timeline.jpg"></a></div>
You see that SFM grab 200 tweets each time from the latest to the older tweets.
</p>
<p>That's it hopefully you will find this article useful. Next i will try to write an article on how to use/utilize feeds from SFM with PHP. (Please don't ask me about Python and Django, i can only write standard "Hello World" using Python :D)</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com12tag:blogger.com,1999:blog-25865790.post-35418730759068728572013-11-21T15:50:00.001-08:002017-12-13T18:07:16.383-08:00Rilis SLIMS 7 Cendana!<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQMtUo67645dWw3P-xsKUY0jujok5PDdYWnLDCvybWAEq0ZpV-sMnSymOv2QbGEDEr4yPxQroDnNVZkbe2kcqPcAmUqf6LsAXf7TnLMeZpJVWhikdt37WTN9SOYOIGW-BjfGI/s1600/SLIMS+7+Cendana+Launch+Web+Banner.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQMtUo67645dWw3P-xsKUY0jujok5PDdYWnLDCvybWAEq0ZpV-sMnSymOv2QbGEDEr4yPxQroDnNVZkbe2kcqPcAmUqf6LsAXf7TnLMeZpJVWhikdt37WTN9SOYOIGW-BjfGI/s400/SLIMS+7+Cendana+Launch+Web+Banner.jpg" width="400"></a></div>
<p>Kamis, Tanggal 21 November 2013, bertempat di Auditorium gedung 1 Fakultas Ilmu Pengetahuan Budaya Universitas Indonesia, SLIMS versi terbaru, yaitu SLIMS 7 Cendana secara resmi dirilis. SLIMS 7 Cendana membawa beberapa fitur baru seperti antara lain:</p>
<p>
<ol>
<li>Responsive User Interface</li>
<li>User Interface baru untuk halaman Admin/Librarian</li>
<li>RSS</li>
<li>Komentar untuk koleksi</li>
<li>Keyword suggestions atau auto correct</li>
<li>Keyword highlighting</li>
<li>Sharing koleksi di OPAC ke berbagai Social app seperti Facebook dan Twitter</li>
<li>Implementasi PDF viewer baru tanpa Flash</li>
<li>Librarian page!</li>
<li>User interface baru untuk kemudahan pengubahan konfigurasi label, barcode dan kartu anggota</li>
<li>Model pengindeksan bibliografi baru dengan MongoDB</li>
<li>Tooltip untuk panduan pengisian data bibliografi</li>
<li>dan beberapa fitur dan perbaikan bugs lain...</li>
</ol>
</p>
<p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSpFco77THhA01EJXkhtE8RMVIXH_X3X_HlUM5XCOCKJCt7PlqTf4P4uBGRhHhwHrtB4UHZAPc1L9nlTMEAN-V69N7qbQUz9eN1-iOVqHnVyCsv5lntBIJr29I6hSZCK8w_GQ/s1600/slims-responsive.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSpFco77THhA01EJXkhtE8RMVIXH_X3X_HlUM5XCOCKJCt7PlqTf4P4uBGRhHhwHrtB4UHZAPc1L9nlTMEAN-V69N7qbQUz9eN1-iOVqHnVyCsv5lntBIJr29I6hSZCK8w_GQ/s400/slims-responsive.jpg"></a></div>
<div class="caption">Responsive UI</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNnPDFs75nQXBzF7yXcwYjjjVBB-wPm6IgD1VV-LS4PYA8kXUBIUp-I4TpgOl3AKknX5YaA1nSWC8WhieWL6dx5AoDSQkHyJ8Mx-fUZ3Te6Pt2TE1pKJn6vxgH12Zo-7wdFLM/s1600/SLiMS+7+Cendana+Librarian+Page.png.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNnPDFs75nQXBzF7yXcwYjjjVBB-wPm6IgD1VV-LS4PYA8kXUBIUp-I4TpgOl3AKknX5YaA1nSWC8WhieWL6dx5AoDSQkHyJ8Mx-fUZ3Te6Pt2TE1pKJn6vxgH12Zo-7wdFLM/s400/SLiMS+7+Cendana+Librarian+Page.png.jpeg"></a></div>
<div class="caption">Librarian page</div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXrSksOxU2jKFkWk1QDfUL50Zlw3GVP8jzEXTfF0sf7WGdXUxoFEGAiA3uVghSlgVmfgdkpBCqAVqnSjtPtXESxyOUcNUtg4zCir0QxhDvwPAkCeiPe_VXU5Mu2CpsX67LI0A/s1600/SLiMS+7+Cendana+Social+Sharing+Fix.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXrSksOxU2jKFkWk1QDfUL50Zlw3GVP8jzEXTfF0sf7WGdXUxoFEGAiA3uVghSlgVmfgdkpBCqAVqnSjtPtXESxyOUcNUtg4zCir0QxhDvwPAkCeiPe_VXU5Mu2CpsX67LI0A/s400/SLiMS+7+Cendana+Social+Sharing+Fix.png"></a></div>
<div class="caption">Social sharing</div>
</p>
<p>
SLIMS 7 Cendana sudah bisa di-unduh melalui <a href="http://slims.web.id">laman resmi SLIMS SLIMS</a>. Enjoy!
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com12tag:blogger.com,1999:blog-25865790.post-45954393679045071892013-04-18T07:30:00.001-07:002017-12-13T18:08:01.599-08:00PUSTAKAWAN: membuat pathfinder online menjadi lebih mudah<p><b>Pustakawan</b> adalah projek <i>open source</i> baru saya untuk memudahkan pustakawan dan profesional informasi lain dalam membangun <i>pathfinder</i> online. Bagi anda yang belum mengetahui apa itu <i>pathfinder</i>, izinkan saya menjelaskan sedikit mengenai apa yang disebut pathfinder. Sederhananya <i>pathfinder</i> adalah panduan yang disusun oleh pustakawan, yang berisikan daftar-daftar sumber informasi dalam berbagai bentuk, seperti buku, website, jurnal, jurnal online, dll. mengenai topik tertentu, untuk membantu pemustaka mendapat sumber YANG TEPAT mengenai topik tertentu</p>
<p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY1OA41jmb4fSu5ULgnOmqfNwnLyyR2LbHOq2PH59tSj_Bxwi-I1ovpTyT1dhifNgb8ySiGoTvkQl1BZDkBYFYQY-YXR5LADpDHpbgkHlxExRrlELFQ8sOYKpqIwDz2T3h-H0/s1600/Pustakawan+Home.jpeg" imageanchor="1"><img border="0" height="247" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY1OA41jmb4fSu5ULgnOmqfNwnLyyR2LbHOq2PH59tSj_Bxwi-I1ovpTyT1dhifNgb8ySiGoTvkQl1BZDkBYFYQY-YXR5LADpDHpbgkHlxExRrlELFQ8sOYKpqIwDz2T3h-H0/s400/Pustakawan+Home.jpeg" width="400"></a></div>
<div class="caption">
Halaman depan "Pustakawan" menampilkan daftar subjek terkait sumber informasi yang digunakan</div>
</p>
<p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_arT84E1a761hJL6AAqAyUOhA51sibUOclssMdN45VQ4c7s1tP0axtIJ79oftegjifbaXcAdvjFHR3EktmorYpL4ca5srbGu_W9Vys13k0dUUMZ6uec7PWIPsUPAJ729EXdg/s1600/Pustakawan+resources.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_arT84E1a761hJL6AAqAyUOhA51sibUOclssMdN45VQ4c7s1tP0axtIJ79oftegjifbaXcAdvjFHR3EktmorYpL4ca5srbGu_W9Vys13k0dUUMZ6uec7PWIPsUPAJ729EXdg/s400/Pustakawan+resources.jpeg" width="400"></a></div>
<div class="caption">Halaman daftar sumber informasi pada subjek tertentu</div>
</p>
<p>
Fitur-fitur yang akan direncanakan ke depan adalah:
<ul>
<li>Metadata sumber informasi menggunakan standar metadata Dublin Core</li>
<li>Manajemen taksonomi subjek hirarkis dengan konsep semantik seperti Tesaurus</li>
<li>Fitur langganan bagi pemustaka/peneliti yang ingin mendapatkan update mengenai subjek yang mereka inginkan</li>
<li>Integrasi dengan sumber sumber perpustakaan elektronik seperti metadata MODS yang disediakan oleh Senayan Library Management System</li>
<li>Layanan <i>feed</i>/sindikasi sumber informasi menggunakan RSS</li>
<li>Pencarian data sumber informasi</li>
<li>Fitur <i>"Ask Librarian"</i> yang memungkinkan pemustaka berkomunikasi <i>real-time</i> dengan pustakawan</li>
</ul>
</p>
<p>
Untuk saat ini software "Pustakawan" masih dalam tahap pengembangan dini, yang artinya masih sangat awal dan belum dapat digunakan untuk skala testing apalagi percobaan. Mohon doa dan restu agar bisa segera dirampungkan versi awal dari software ini. Sekali lagi dengan software ini saya ingin menekankan bahwa software hanyalah "alat", "ISI"-nya adalah tugas intelektual seorang pustakawan :)</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com21tag:blogger.com,1999:blog-25865790.post-21806001161044463752012-10-27T15:14:00.001-07:002017-12-13T18:08:42.405-08:00Genius's Guides to: membuat module Drupal 6 bagian 2<p>Nah setelah pada <a href="http://dicarve.blogspot.com/2012/10/geniuss-guides-to-membuat-module-drupal.html">posting sebelumnya</a> kita mengenal dasar-dasar coding pada file .module-nya Drupal, kali ini kita akan membahas mengenai file bernama .install yang berisikan definisi dari struktur tabel database untuk kita gunakan pada module. Drupal memungkinkan kita menambahkan atau menghapus tabel-tabel module kita pada struktur database Drupal melalui hook_schema, hook_install dan hook_uninstall.</p>
<p>Pada contoh ini misalnya kita akan membuat sebuah tabel yang nantinya akan kita gunakan sebagai tempat untuk menampung record atau data dari module kita. Jumlah tabel yang kita bisa tambahkan bisa lebih dari satu. Berikut isi dari file .install untuk module Latihan kita:</p>
<pre><code class="php">
/**
* Module Latihan
* Copyright Arie Nugraha (dicarve@gmail.com) 2012
* Licensed under GPL v3
*
*/
/**
* Fungsi ini dijalankan oleh Drupal ketika kita pertama menginstall module Latihan
*/
function latihan_install() {
// Create tables.
drupal_install_schema('latihan');
}
/**
* Fungsi ini dijalankan oleh Drupal melakukan un-install pada Latihan
*/
function latihan_uninstall() {
// Remove tables.
drupal_uninstall_schema('latihan');
}
/**
* Pada fungsi ini kita mendefinisikan struktur tabel2 database yang akan
* kita gunakan untuk menyimpan data2 module Latihan
*/
function latihan_schema() {
$schema['latihan'] = array(
'description' => 'Tabel untuk menyimpan data module Latihan.',
'fields' => array(
'lat_id' => array(
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => "ID/Key utama tabel latihan"
),
'lat_judul' => array(
'type' => 'varchar',
'length' => '250',
'not null' => TRUE,
'default' => '',
'description' => "Judul konten latihan"
),
'lat_content' => array(
'type' => 'text',
'not null' => TRUE,
'default' => '',
'description' => 'Konten dari tabel latihan.'
)
),
'primary key' => array('lat_id'),
'indexes' => array(
'judul' => array('lat_judul')
)
);
return $schema;
}
</code></pre>
<p>Kita bisa lihat pada implementasi hook_schema yaitu pada fungsi latihan_schema, kita mendefinisikan tabel dengan nama "latihan" dengan dua tiga field yaitu "lat_id", "lat_judul" dan "lat_content", dengan primary key-nya adalah "lat_id" dan juga sebuah indeks dengan nama "judul" pada field "lat_judul". Drupal akan menerjamahkan definisi ini menjadi syntax SQL yang akan di-eksekusi pada saat module "Latihan" pertama kali di-aktifkan.</p>
<p>Pertanyaan berikutnya adalah bagaimana kita memasukkan data ke dalam tabel module "Latihan"? Jawaban sederhananya adalah kita harus membuat form untuk memasukkan data tersebut. Terus bagaimana kita buat form di Drupal? Seperti saya pernah sebutkan sebelumnya Drupal sudah menyediakan API yang sangat lengkap, termasuk di dalamnya adalah <a href="http://api.drupal.org/api/drupal/includes!form.inc/group/form_api/6">Form API</a> yang memudahkan kita dalam membuat form serta memproses form, termasuk dalam hal validasi.</p>
<p>Tanpa banyak basa-basi, mari kita tambahkan kode berikut ini pada file latihan.module kita:</p>
<pre><code class="php">
/**
* Fungsi ini mendefinisikan struktur form yang akan kita gunakan untuk
* input data
* @return Array array struktur form
*/
function latihan_inputdata_formdata() {
// definisikan elemen form
$form['judul'] = array(
'#type' => 'textfield',
'#title' => t('Judul konten Latihan'),
'#default_value' => '',
'#size' => 60,
'#maxlength' => 250,
'#description' => t('Judul konten latihan yang akan kita masukkan ke dalam database')
);
$form['konten'] = array(
'#type' => 'textarea',
'#title' => t('Isi konten Latihan'),
'#default_value' => '',
'#cols' => 60,
'#rows' => 5,
'#disabled' => false,
'#description' => t('Data konten latihan yang akan kita masukkan ke dalam database')
);
$form['data_tersembunyi'] = array('#type' => 'hidden', '#value' => 'Contoh data form tersembunyi');
$form['submit'] = array('#type' => 'submit', '#value' => t('Save'), '#submit' => array('latihan_inputdata_formdata_submit'));
return $form;
}
/**
* Fungsi ini dipanggil ketika form input data latihan di-submit
* Pada fungsi ini kita memanfaatkan Database API Drupal, yaitu fungsi
* db_query() untuk melakukan query SQL ke database
* Data form yang dikirimkan browser bisa kita akses lewat variabel $form_state['values'],
* misalnya untuk mengakses data form "judul" kita mengaksesnya lewat
* $form_state['values']['judul']
*/
function latihan_inputdata_formdata_submit($form, &$form_state) {
db_query("INSERT INTO {latihan} (lat_judul, lat_content) VALUES ('%s', '%s')",
$form_state['values']['judul'],
$form_state['values']['konten']);
// redirect ke web ke halaman/path "latihan"
$form_state['redirect'] = 'latihan';
drupal_set_message(t('"Latihan" form data has been saved'));
}
/**
* Fungsi dibawah ini berfungsi me-render/menampilkan form yang sudah kita definisikan
* pada fungsi latihan_inputdata_form
*/
function latihan_inputdata() {
return drupal_get_form('latihan_inputdata_formdata');
}
</code></pre>
<p>Agar form input data-nya gampang diakses tentunya kita harus menempatkan link yang bisa diklik oler user, maka dari itu jangan lupa tambahkan kode berikut pada fungsi <b>latihan_menu</b>:</p>
<pre><code class="php">
$items['latihan/inputdata'] = array(
'title' => 'Input data module Latihan',
'page callback' => 'latihan_inputdata',
'access arguments' => array('membuat konten latihan'),
'type' => MENU_NORMAL_ITEM
);
</code></pre>
<p>
Apabila semua berjalan lancar, maka kita akan bisa melihat tampilan sebagai berikut pada Drupal kita:
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY-itljg94-lGYOt3IY_xgcAJ4JnLYuiHY3s1w8Ze_4yODRTaARlaPUlEi-6YcjE7Ei4XwLRIwTexUFlvynixQJ5Y4JkcDXJuU4G1o0lktDNfXLygOtP4c0_P80Rs_3VGYAy0/s1600/Input+data+Module+Drupal.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="205" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY-itljg94-lGYOt3IY_xgcAJ4JnLYuiHY3s1w8Ze_4yODRTaARlaPUlEi-6YcjE7Ei4XwLRIwTexUFlvynixQJ5Y4JkcDXJuU4G1o0lktDNfXLygOtP4c0_P80Rs_3VGYAy0/s320/Input+data+Module+Drupal.jpg"></a></div>
</p>
<p>Begitulah kira-kira cara dasar pemrosesan form pada Drupal. Pertanyaan berikutnya adalah bagaimana kemudian kita menampilkan data yang sudah kita masukkan ke database? Bagaiman cara kita membuat data yang sudah kita entry bisa di-edit/diubah? Entar dulu yak ane istirahat dulu, nanti ane tulis di bagian 3 :). Semoga bermanfaat</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com4tag:blogger.com,1999:blog-25865790.post-14603798069428485302012-10-26T18:47:00.002-07:002017-12-13T18:09:08.338-08:00Genius's Guides to: membuat module Drupal 6 bagian 1<p>Okay, mungkin sebagian besar dari kita sudah tahu apa itu <a href="http://drupal.org/" target="_blank">Drupal</a>. Drupal adalah Content Management Framework yang memungkinkan kita membangun website atau aplikasi web dinamis. Lah kalau begitu kenapa engga disebut Content Management System alias CMS aja macem Joomla dsb.? Drupal menggunakan kata "<i>Framework</i>" disitu karena Drupal menyediakan sebuah <i>platform</i> yang sangat memungkinkan kita membangun aplikasi web lain dengan memanfaatkan API-nya yang sangat komprehensif. Saya bilang komprehensif karena API yang disediakan Drupal sangat lengkap kap kap.</p>
<p>Di artikel blog kali ini saya mau berbagi kepada rekan-rekan pembaca blog (kalau ada yang baca hehehee) bagaimana cara kita membuat <i>module</i> Drupal kita sendiri. Dengan module kita bisa meng-extend/memperluas fungsi Drupal sesuai dengan kebutuhan kita sendiri. Sebenarnya ada beberapa module "<i>sakti</i>" yang bisa kita gunakan untuk membangun aplikasi web dengan Drupal, contohnya <a href="http://drupal.org/project/views">Views</a>, <a href="http://drupal.org/project/cck">CCK (Drupal 6)</a> dan <a href="http://drupal.org/project/token">Token</a>, tetapi bagi beberapa orang, utamanya <i>developer</i> aplikasi web yang lebih suka coding (dan yang lebih kepingin dibilang geek kaya saya hahahahaa), membuat module lebih disukai.</p>
<p>Untuk tutorial ini saya menggunakan Drupal 6. Loh kenapa bukan Drupal 7 yang lebih baru, jawaban jujur dari lubuk hati yang paling dalam adalah, saya belum sempat mempelajari API Drupal 7, dan saya sudah terbiasa dengan Drupal 6 hehehee.</p>
<p>Ok sebelum tutorial ini saya lanjutkan ada beberapa hal yang perlu saya sampaikan, terutama terkait dengan pengetahuan dan skill yang wajib dan perlu kita kuasai apabila ingin membuat module Drupal. Apa saja?</p>
<ol>
<li>Pemrograman dengan PHP</li>
<li>Pemrograman SQL dengan database server MySQL atau PostgreSQL</li>
<li>Pemrograman dengan HTML, Javascript dan CSS</li>
</ol>
Nah sebelum kita mulai coding module Drupal kita, maka beberapa hal harus kita persiapkan terlebih dahulu:
<ol>
<li>Drupal 6 yang sudah terinstall (maaf untuk instalasi Drupal saya tidak cover di tutorial ini, cara sendiri aja yak, banyak kok tersedia di web)</li>
<li>Editor teks favorit anda, untuk Windows saya selalu pakai <a href="http://notepad-plus-plus.org/">Notepad++</a>, kalau lagi pake GNU/Linux saya pakai Geany, dan kalau lagi pakai Mac OSX saya pakai Komodo Edit</li>
<li>Cemilan sama Teh :D</li>
</ol>
Pada dasarnya semua 3rd party module di Drupal, termasuk yang akan kita buat, diletakan pada direktori <b>sites/all/modules</b>. Apabila direktori <b>modules</b> belum ada pada <b>sites/all</b> maka silahkan anda buat terlebih dahulu. Pada contoh ini kita akan membuat sebuah module Drupal dengan nama "Latihan". Langkah-langkahnya adalah sebagai berikut:
<ol>
<li>Buatlah sebuah direktori bernama <b>latihan</b> di dalam direktori <b>sites/all/modules</b>
</li>
<li>Di dalam direktori latihan buatlah tiga buah file teks baru dengan nama sebagai berikut:
<ul>
<li>latihan.info</li>
<li>latihan.module</li>
<li>latihan.installl</li>
</ul>
</li>
<li>Buka file <b>latihan.info</b> dengan teks editor anda. File <b>latihan.info</b> adalah file metadata yang mendeskripsikan module Drupal. Di dalam file ada beberapa informasi dasar yang harus kita cantumkan. Untuk module "Latihan" kita akan isi sebagai berikut:
<pre><code>
name = Module Latihan
description = Module sederhana Drupal untuk latihan
core = 6.x
package = "Latihan"
</code>
</pre>
Simpan file.
</li>
<li>Selanjutnya kita akan membuka file <b>latihan.module</b> yang merupakan file utama berisi kode PHP untuk module "Latihan". Sebelum mulai coding saya mau sedikit menjelaskan cara kerja Drupal dalam menjalankan module-modulenya. Drupal menyediakan apa yang disebut sebagai "<i><b>hook</b></i>" atau "<i>kaitan</i>". "<i>Hook</i>" adalah fungsi-fungsi dari dipanggil pada saat-saat tertentu oleh Drupal. Misalnya kita akan menemui hook bernama hook_block, yang dipanggil ketika Drupal akan menampilkan "Block" pada halaman web. Untuk module maka nama hook diganti dengan format namamodule_namahook, jadi untuk mengimplementasikan hook_block di module kita, maka kita harus membuat fungsi dengan nama <b>latihan_block</b>.</li>
<li>Untuk snippet kode pertama adalah kita akan melakukan implementasi pada hook_perm. hook_perm adalah hook yang menentukan permission apa saja yang disediakan oleh module kita.
<pre><code class="php">
/**
* Permission apa saja yang disediakan oleh module Latihan?
* tentukan pada fungsi ini
* @return array Array yang mendefinisikan permission
*/
function latihan_perm() {
$_perms = array(
'membuat konten latihan',
'mengubah konten latihan',
'melihat konten latihan',
'menghapus konten latihan',
'ubah konfigurasi module latihan');
return $_perms;
}
</code></pre>
Pada fungsi latihan_perm ini kita mendefinisikan ada lima permission yang disediakan oleh module "Latihan", yaitu "membuat konten latihan" sampai "ubah konfigurasi module latihan", yang didefinisikan dalam bentuk array.
</li>
<li>
Setelah implementasi hook_perm, selanjutnya adalah kita melakukan implementasi hook_block. Untuk itu kita akan membuat sebuah fungsi lagi dengan nama latihan_block. Kodenya adalah sebagai berikut:
<pre><code class="php">
/**
* Block adalah konten yang posisi-nya bisa dipindah-pindahkan pada Drupal
* fungsi ini mendefinisikan konten blok untuk module Latihan
* @param string $op isi dari variabel argumen ini bisa "list", "view", "save" atau "configure"
* @param integer $delta kode untuk meng-identifikasi block
* @param array $edit hanya muncukl apabila argumen $op berisi "save"
* @return array data semua blok yang disediakan oleh module Latihan
*/
function latihan_block($op = 'list', $delta = 0, $edit = array()) {
// array kosong yang akan menyimpan semua data block
$block = array();
switch ($op) {
case "list":
// operasi list adalah ketika daftar block ditampilkan pada halaman admin/block
$block[0]["info"] = t('Block module Latihan');
break;
case "view":
// operasi view adalah ketika block ditampilkan sebenarnya
// subject/judul heading dari block
$block["subject"] = t("Judul Block Latihan");
// content/isi dari block
$block["content"] = '<p>Ini adalah konten/isi dari block module Latihan</p>';
break;
case "save":
break;
case "configure":
break;
}
return $block;
}
</code></pre>
</li>
<li>
Berikutnya kita akan membuat fungsi yang tugasnya menampilkan konten utama dari module Latihan. Berikut adalah snippet kode-nya:
<pre><code class="php">
/**
* Fungsi ini menampilkan konten/isi utama dari Module Latihan
*/
function latihan_main() {
// definisikan variabel konten kosong untuk inisialisasi
$content = '';
// lakukan berbagai macam manipulasi konten pada bagian ini
// seperti melakukan query dsb.
$content .= '<p>Ini adalah konten sederhana dari module Latihan</p>';
return $content;
}
</code></pre>
</li>
<li>
Bagaimana kalau kita mau module kita ada beberapa parameternya yang bisa dikonfigurasikan melalui antar muka web Drupal? Tenang, kita akan membuat sebuah fungsi yang akan menampilkan halaman konfigurasi khusus module Latihan yang kita buat. Berikut kode-nya:
<pre><code class="php">
/**
* Fungsi ini memungkinkan kita membuat halaman konfigurasi dalam Drupal
* khusus untuk module Latihan
* Pada contoh ini kita mendefinisikan 2 item konfigurasi untuk module Latihan
* @return array Array yang elemen form konfigurasi modul latihan
*/
function latihan_admin() {
$form = array();
// setting 1
$form['latihan_setting1'] = array(
'#type' => 'textfield',
'#title' => t('Setting 1 module Latihan'),
'#default_value' => variable_get('latihan_setting1', null),
'#size' => 60,
'#maxlength' => 250,
'#description' => t("Contoh setting pertama untuk module Latihan"),
'#required' => TRUE,
);
// setting 2
$form['latihan_setting2'] = array(
'#type' => 'textfield',
'#title' => t('Setting 2 module Latihan'),
'#default_value' => variable_get('latihan_setting2', null),
'#size' => 60,
'#maxlength' => 250,
'#description' => t("Contoh setting kedua untuk module Latihan"),
'#required' => TRUE,
);
return system_settings_form($form);
}
</code></pre>
</li>
<li>
Langkah penting berikutnya adalah meng-implementasika hook_menu. hook_menu mendefinisikan URL dan path apa saja yang ada pada module Latihan, sekaligus menetapkan callback (fungsi) apa yang dijalankan ketika URL tersebut dipanggil oleh browser. Kode-nya adalah sebagai berikut:
<pre><code class="php">
/**
* Fungsi menu mendefinisikan menu atau path page untuk module Latihan
*
*/
function latihan_menu() {
$items = array();
$items['admin/settings/latihan'] = array(
'title' => 'Konfigurasi Latihan',
'description' => 'Halaman untuk menampilkan konfigurasi module Latihan',
'page callback' => 'drupal_get_form',
'page arguments' => array('latihan_admin'),
'access arguments' => array('ubah konfigurasi module latihan'),
'type' => MENU_NORMAL_ITEM
);
$items['latihan'] = array(
'title' => 'Halaman utama module Latihan',
'page callback' => 'latihan_main',
'access arguments' => array('melihat konten latihan'),
'type' => MENU_NORMAL_ITEM
);
return $items;
}
</code></pre>
</li>
<li>
Nah sampai disitu dulu kode module Drupal kita, untuk kode lengkapnya silahkan anda lihat ke <a href="http://pastebin.com/JiVZC0Rg">Kode Lengkap module Latihan</a>. Selanjutnya kita akan coba mengaktifkan module Drupal yang baru kita buat dengan masuk ke halaman admin/build/modules pada website Drupal kita. Apabila berhasil maka kita akan melihat module Latihan pada daftar module yang disediakan Drupal seperti pada screenshot berikut:
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr54Ys3rLKSBR4q-ugocxR4-hnK4_FT5UxxBtVgQBs4B_speJRa17uPU3e3uSLq8DJzQV-gpm0SrJCPTykXmVkLocVE6_tOaMc3An9iSn1MnNOVo6AdWIAn6ZEenvOUyDC6tw/s1600/Modules+Latihan+Membuat+Module+Drupal.jpeg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="208" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr54Ys3rLKSBR4q-ugocxR4-hnK4_FT5UxxBtVgQBs4B_speJRa17uPU3e3uSLq8DJzQV-gpm0SrJCPTykXmVkLocVE6_tOaMc3An9iSn1MnNOVo6AdWIAn6ZEenvOUyDC6tw/s320/Modules+Latihan+Membuat+Module+Drupal.jpeg"></a></div>
Centang pada module "Module Latihan" dan kemudian tekan tombol "Save Configuration".
</li>
<li>
Apabila proses aktivasi module kita berhasil maka kita akan melihat tampilan-tampilan sebagai berikut pada website Drupal kita:
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIMYd4k2bMh9-75p9yig8YgC7VjEHlL2BeA9D3vyTX1pvsQd9FGX70T7WSlntQYWxsQcXFyPXWWYZ1axQaYBGvmbFnRvJPqxZRZy9ArgaqLPTgQ7KyOaZ12S-dbEjYwWtRpS4/s1600/Halaman+utama+module+Latihan+Membuat+Module+Drupal.jpeg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="205" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIMYd4k2bMh9-75p9yig8YgC7VjEHlL2BeA9D3vyTX1pvsQd9FGX70T7WSlntQYWxsQcXFyPXWWYZ1axQaYBGvmbFnRvJPqxZRZy9ArgaqLPTgQ7KyOaZ12S-dbEjYwWtRpS4/s320/Halaman+utama+module+Latihan+Membuat+Module+Drupal.jpeg"></a></div>
Kita bisa melihat menu dengan nama "Halaman utama module Latihan" di bagian sebelah kiri halaman web kita, yang apabila di-klik akan ditujukan ke halaman URL <b>latihan</b>.
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX00hQlKdOqb8_JldOtSTUvYopcsCkilUe282l3zLcCeQqa6UmjUBC1j0V78k4V-PehrE_y5iJdh0FjXMgev4vySXnSgL3nQEth8SHUwyfFJ5GSuWGcb18IT2TYSBLkX43Ip4/s1600/Blocks+Latihan+Membuat+Module+Drupal.jpeg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="208" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX00hQlKdOqb8_JldOtSTUvYopcsCkilUe282l3zLcCeQqa6UmjUBC1j0V78k4V-PehrE_y5iJdh0FjXMgev4vySXnSgL3nQEth8SHUwyfFJ5GSuWGcb18IT2TYSBLkX43Ip4/s320/Blocks+Latihan+Membuat+Module+Drupal.jpeg"></a></div>
Pada halaman manajemen Block Drupal di admin/build/block kita akan melihat Block dengan nama "Block module Latihan" sudah terdaftar, tinggal kita letakkan di posisi yang kita inginkan.
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5dYwOyNp4FvLn_qyfuRbEswhQpRiHF-83dFVlybQDJdz00ZsZCC8aWPlA7cfxhz_7LIC_5C0efz0TAeKKAacGiOoKOBpnQq4LMwSy4VI3IbubN-_lKIWQqSTow-Ft8AVn8HU/s1600/Konfigurasi+Latihan+Latihan+Membuat+Module+Drupal.jpeg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="208" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5dYwOyNp4FvLn_qyfuRbEswhQpRiHF-83dFVlybQDJdz00ZsZCC8aWPlA7cfxhz_7LIC_5C0efz0TAeKKAacGiOoKOBpnQq4LMwSy4VI3IbubN-_lKIWQqSTow-Ft8AVn8HU/s320/Konfigurasi+Latihan+Latihan+Membuat+Module+Drupal.jpeg"></a></div>
Halaman konfigurasi khusus module Latihan juga bisa kita ke akses melalui path URL admin/settings/latihan dan akan menampilkan tampilan seperti di atas.
</li>
</ol>
Sampai disini dulu untuk bagian satu, semoga bisa memberikan gambaran dasar bagaimana membuat module dengan Drupal. Seperti yang sudah saya sebutkan sebelumnya, Drupal menyediakan banyak API yang memudahkan kita dalam mengembangkan module. Untuk daftar lengkap beserta dokumentasi penggunaanya silahkan browsing ke <a href="http://api.drupal.org/api/drupal/6">Drupal 6 API</a>.
arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com8tag:blogger.com,1999:blog-25865790.post-69479127522224590832011-08-24T02:52:00.000-07:002011-08-24T06:13:56.634-07:00Instalasi Senayan Library Management System (SLiMS) di Mac OSX berikut dengan dukungan Z39.50 (Bagian 1)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy2V1AFT4NX3BJMudiDNhXnGtcdPLZ1MRqvl-3TO3mmzdmldA_V5xOj24rLEPYETuU_FiJ6GkjmBWh1eMPA7h01U-9FWORKa6ryrTUJp6n5gmiCFNUzMbTiPrb2QW0kLkie7k/s1600/slims-mac.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="300" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy2V1AFT4NX3BJMudiDNhXnGtcdPLZ1MRqvl-3TO3mmzdmldA_V5xOj24rLEPYETuU_FiJ6GkjmBWh1eMPA7h01U-9FWORKa6ryrTUJp6n5gmiCFNUzMbTiPrb2QW0kLkie7k/s400/slims-mac.jpg" /></a></div>
<p>Sebenernya udah lama mau nulis tutorial ini, tapi karena "kesibukan" (#eaaa) yang mendera, baru kali ini kesampean, sekalian menyambut bulan Ramadhan yang penuh barokah dan kehadiran versi SLiMS terbaru Stable15 Matoa. Berhubung saya ini juga orang sangat pelupa, maka ada baiknya sekalian saya dokumentasikan cara instalasi SLiMS di Mac OSX, kali-kali aja di kemudian hari saya lupa :D. Untuk instalasi di Mac OSX sebenernya relatif mudah, beberapa prasyarat yang harus anda penuhi adalah:
<ol>
<li>Desktop <b>MacPro, Imac, Macbook, MacbookPro atau Macbook Air</b>! (YA IYAAALLLAH!!!).</li>
<li>Terinstall sistem operasi <b>OSX minimal versi 10.4</b> (boleh Intel atau PPC) dan ke atasnya</li>
<li>Paket <a href="http://www.apachefriends.org/en/xampp-macosx.html">XAMPP for Mac terbaru</a></li>
<li>Paket <b>Xcode</b>. Xcode merupakan paket development Mac OSX yang didalamnya terdapat compiler gcc, g++, make, dll. yang kita butuhkan untuk meng-compile YAZ dan PHP-YAZ. Xcode biasanya disertakan pada setiap DVD instalasi Mac OSX, atau kalo DVD instalasinya udah raib alias hilang, download aja di website resmi Apple, gratis kok.</li>
<li>Paket <b>SLiMS versi source</b> (bukan psenayan/portable senayan) terbaru, misalnya pada saat tulisan ini dibuat SLiMS Stable15 (Matoa)</li>
</ol>
</p>
<p>
Untuk tutorial ini, saya menggunakan MacbookPro dengan <b>Mac OSX versi 10.6.8 dan paket XAMPP for Mac yang saya gunakan adalah versi 1.7.3</b>, berikut dengan paket XAMPP Dev (xampp-macosx-1.7.3-dev) dengan versi yang sama. XAMPP Dev merupakan paket tambahan opsional yang berisi file-file development header dari aplikasi-aplikasi yang terdapat di dalam XAMPP seperti PHP, MySQL, library-library, dsb.
</p>
<p>
Oke mari kita mulai proses instalasinya!
<ol>
<li>
<strong>Unduh (download) paket XAMPP untuk Mac di laman (website) <a href="http://www.apachefriends.org/en/xampp-macosx.html">Apachefriends</a></strong>. Inget ya, yang versi Mac, jangan yang versi Linux, Solaris, apalagi Winslow ehhh, Windows. <i>Silly maybe, but guess what?</i> ada aja orang yang salah download!
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSMsACbk0JySY2E3sshkq0CdEU6R4ZB0t7LQV8OJJtNqke-V9KA4eC6ztXEITsgKxUfZscW9d5JMtDTZ9Vt3bTy28wHpfCwp8QMGS5TFFDKAJMk1twco6sCC9wcPWPX01ZOTo/s1600/www.apachefriends.org+screen+capture+2011-8-24-15-46-16.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="228" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSMsACbk0JySY2E3sshkq0CdEU6R4ZB0t7LQV8OJJtNqke-V9KA4eC6ztXEITsgKxUfZscW9d5JMtDTZ9Vt3bTy28wHpfCwp8QMGS5TFFDKAJMk1twco6sCC9wcPWPX01ZOTo/s320/www.apachefriends.org+screen+capture+2011-8-24-15-46-16.png" /></a></div>
</li>
<li>
Download file Universal binary dalam format .dmg yang disediakan. Jangan lupa download juga paket development-nya agar kita bisa meng-compile library YAZ dan PHP-YAZ nanti.
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFFVetLDhVSedxgWd9IYq8O50N_PORgso6gZvs5VlwphUAqUQt1Z9DSX6eBFT5ve_9Fz7o_eWw4xjXIQmN8JDbl59ArCyRocTyBxMNmsuYnslFjiUy9RhHHiG7GSIRDaOFgBA/s1600/www.apachefriends.org+screen+capture+2011-8-24-15-46-41.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="249" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFFVetLDhVSedxgWd9IYq8O50N_PORgso6gZvs5VlwphUAqUQt1Z9DSX6eBFT5ve_9Fz7o_eWw4xjXIQmN8JDbl59ArCyRocTyBxMNmsuYnslFjiUy9RhHHiG7GSIRDaOFgBA/s320/www.apachefriends.org+screen+capture+2011-8-24-15-46-41.png" /></a></div>
</li>
<li>
Setelah selesai di-download, klik dua kali pada file image .dmg XAMPP untuk membuka installer-nya. Drag folder XAMPP ke folder Applications untuk menginstall.
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPUe-f95Ckq4qeVfZnonzYml-2-H7FR9krwctO_C4jimCzgRMpOThqhq0eHcxZ79Fr-mwgP2nqWc5gF1goLMjmgWhqzE3IFLTMPTVHk6BaSTxpY_60Tl82ysHMqplrt-kDrao/s1600/xampp-mac-install.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="216" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPUe-f95Ckq4qeVfZnonzYml-2-H7FR9krwctO_C4jimCzgRMpOThqhq0eHcxZ79Fr-mwgP2nqWc5gF1goLMjmgWhqzE3IFLTMPTVHk6BaSTxpY_60Tl82ysHMqplrt-kDrao/s320/xampp-mac-install.png" /></a></div>
</li>
<li>
Selesai proses instalasi, sekarang giliran install paket .dmg XAMPP Dev-nya. Caranya hampir sama dengan instalasi XAMPP, buka paket .dmg-nya dan jalankan installer yang terdapat di dalamnya. Ikuti proses wizard instalasinya.
</li>
<li>
Masuk ke folder Applications dan cari folder XAMPP disitu. Jalankan program "XAMPP Control". Nanti akan ada jendela aplikasi kecil yang berisi tombol untuk menjalan Apache, MySQL dan FTP. Cukup jalankan Apache dan MySQL saja, FTP server-nya engga perlu.
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJe1CewRhmNj67RAR9wizzLueVyyIy9WMQiuihmxOhaT9nOJMMZQ1vAUvqJB_auXUkCDXk_PrcmuRboeI7Oo2af9aAM_5gh3cf6rpnVSS0zZ-BKxb5fbPdJ8cPSsysCSolT6Q/s1600/xampp-control.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="200" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJe1CewRhmNj67RAR9wizzLueVyyIy9WMQiuihmxOhaT9nOJMMZQ1vAUvqJB_auXUkCDXk_PrcmuRboeI7Oo2af9aAM_5gh3cf6rpnVSS0zZ-BKxb5fbPdJ8cPSsysCSolT6Q/s320/xampp-control.png" /></a></div>
</li>
<li>
<strong>Sekarang giliran instalasi SLiMS</strong>. Ekstrak paket SLiMS versi source yang sudah anda download dari situs resmi <a href="http://slims.web.id">SLiMS</a>, dan kemudian kopikan folder hasil ekstraksinya (misal nama foldernya <b>s3st15_matoa</b>) ke folder <b>/Applications/XAMPP/htdocs/</b>.
</li>
<li>
Buka browser web favorit anda, misalnya Safari, Firefox, Chrome atau Camino dan arahkan ke URL phpMyAdmin di http://127.0.0.1/phpMyAdmin untuk membuka program manajemen database MySQL berbasis web, phpMyAdmin yang kesohor itu. By default instalasi XAMPP, phpMyAdmin bisa diakses bebas tanpa harus memasukkan username dan password.
</li>
<li>
Buatlah sebuah database baru dengan nama "<b>senayandb</b>". Setelah database berhasil dibuat masuk ke menu tab "<b>Import</b>" dan pilih file "<b>senayan.sql</b>" yang terdapat di dalam folder "install" di source SLiMS hasil ekstraksi kita tadi. Setelah proses import berhasil maka kemudian pilih menu tab "SQL" dan jalankan perintah berikut:
<code>
<pre>
GRANT ALL ON senayandb.* TO 'senayanuser'@'localhost'
IDENTIFIED BY 'password_senayanuser';
FLUSH PRIVILEGES;
</pre>
</code>
</li>
<li>
Buka Tab baru pada browser web anda dan masukkan alamat: <b>http://127.0.0.1/s3st15_matoa</b> . VOILLAA SLiMS sudah terinstall di Mac OSX ente gan!
</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv3WCJNn1lKmrCoD3wMiHRc7H-UJdHEptEyPBbOEQ0ZLgAnmw6kfbUplXRKx0sVV9kR0VZYo85i93SqTKIYAm0cHrIRwSi0eYq5C0ZXtlk42NMG0QubFyBO76uFwU48iWPlck/s1600/slims-on-mac.tiff" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="250" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv3WCJNn1lKmrCoD3wMiHRc7H-UJdHEptEyPBbOEQ0ZLgAnmw6kfbUplXRKx0sVV9kR0VZYo85i93SqTKIYAm0cHrIRwSi0eYq5C0ZXtlk42NMG0QubFyBO76uFwU48iWPlck/s400/slims-on-mac.tiff" /></a></div>
Okeh. Bagian 1 sampai disini dulu, besok bagian 2 dimana kita akan meng-compile YAZ dan PHP-YAZ agar fitur Z39.50 yang dahsyat itu bisa berjalan di Mac OSX, akan saya lanjutkan, selamat menggunakan SLiMS di Mac OSX anda! (Ane tunggu cendol-nya ya gan xixixiiiii)
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com7tag:blogger.com,1999:blog-25865790.post-3652747882033725942011-08-05T16:00:00.000-07:002011-08-05T16:49:24.052-07:00Tips dan Trik Pemeliharaan a.k.a Maintenance Senayan Library Management System (SLiMS)<p>Beberapa teman pengguna SLiMS sering bertanya kepada saya, apa saja tips dan trik dalam pemeliharaan SLiMS, terutama bagi yang menggunakan versi Portable Senayan (psenayan). OK, kalau begitu sekalian aja biar ga lupa kita dokumentasikan di posting blog saya yang jarang sekali dimutakhirkan/<i>update</i> ini (heheheeee):
</p>
<p>
<div class="tips-count">Tips 1:</div>
<div class="tips-title">Hapus semua file image barcode secara rutin</div>
<blockquote>
Setelah sekian lama menggunakan SLiMS kemudian sering membuat barcode untuk data Item/Copies koleksi, maka file-file image barcode hasil generate cetak barcode akan menumpuk di folder <strong>"lokasi_source_slims/images/barcodes"</strong>. Walaupun besar file-nya kecil-kecil tetapi cukup mengganggu juga kalau jumlah sudah ribuan, terutama bagi mereka yang pakai <i>webhosting</i> dengan <i>space</i> harddisk pas-pasan. <strong class="tips-important">Oleh karena itu bagi mereka yang sering mencetak barcode koleksi atau kartu anggota dengan SLiMS paling tidak sebulan sekali silahkan itu semua file image .png barcode di folder <strong>"lokasi_source_slims/images/barcodes"</strong> dibabat abissss!</strong>
</blockquote>
</p>
<p>
<div class="tips-count">Tips 2:</div>
<div class="tips-title">Cek file access.log dan error.log web server Apache di psenayan</div>
<blockquote>
Ada kaskus, ehhh... :p kasus dimana pengguna psenayan bingung <i>setengah hidup</i> ketika melihat ukuran folder psenayan mereka menggelembung atau bahasa kerennya, <i>BLOATED</i>, menjadi 3-5 Gigabyte padahal mereka tidak mengupload file-file digital ke SLiMS. Penyebab hal ini ternyata adalah file log milik web server Apache, yaitu <b>error.log</b> dan <b>access.log</b> yang menjadi semakin besar seiring pemakaian psenayan. Bagi anda yang belum tahu fungsinya, file access.log menyimpan semua informasi <i>request</i> HTTP yang dilakukan ke web server Apache, sedangkan error.log menyimpan semua error/galat yang terjadi pada <i>request</i> HTTP, error yang terjadi pada program Apache itu sendiri, error pada SSL, dan error-error lainnya. Letaknya ada di direktori <b>"/psenayan/apache/logs"</b>. Nah solusi masalah ini ada 3 alternatifnya:
<ol>
<li>Solusi 1: Kosongkan kedua file tersebut, atau hapus apabila terlalu besar untuk dibuka dengan Notepad dan kemudian buat kembali file teks kosong dengan nama yang sama. Solusi ini berlaku bagi mereka yang mengganggap tidak perlu mengetahui apa isi dari log web server Apache</li>
<li>Solusi 2: Compress dalam format zip atau rar kedua file tersebut dan backup ke tempat lain kemudian buat kembali file teks kosong dengan nama yang sama. Solusi ini berlaku bagi mereka yang mengganggap penting untuk mengetahui apa isi dari log web server Apache, biasanya admin jaringan perlu menganalisa isi dari log ini, terutama apabila terjadi <i>hacking, cracking, deface</i>, dll pada website</li>
<li>Solusi 3: Gunakan fasilitas Log Rotation yang disediakan oleh Apache untuk merotasi isi log secara otomatis dan periodik. Untuk lebih lengkapnya silahkan ikuti petunjuknya disini <a href="http://httpd.apache.org/docs/2.2/logs.html#rotation">Log Rotation</a>. Atau bisa juga gunakan fitur <a href="http://httpd.apache.org/docs/2.2/logs.html#piped">Piped Logs</a></li>
</ol>
</blockquote>
</p>
<p>
<div class="tips-count">Tips 3:</div>
<div class="tips-title">Backup psenayan dan database secara rutin</div>
<blockquote>
Bagi pengguna psenayan lakukan backup satu folder psenayan secara rutin dengan melakukan dua tips sebelumnya terlebih dahulu agar ukuran backup tidak terlalu besar dan kemudian kompresi folder psenayan dalam format zip atau rar (mau lebih kecil lagi? pake format 7z atau lzma sekalian :D). Beri nama file kompresi tersebut misalnya <b>psenayan-20110817.zip</b> biar kita lebih mudah mengidentifikasi kapan tanggal pembuatan backup tersebut.
<br>
Untuk membackup database, gunakan fasilitas <i>"Database Backup"</i> yang terdapat pada modul <b>"System"</b> di SLiMS. <strong class="tips-important">Sebelumnya pastikan bahwa sudah tidak ada warning mysqldump di halaman awal admin SLiMS. Jangan lupa juga untuk memindahkan semua file hasil backup SLiMS (.sql atau .sql.gz) yang terletak di direktori <b>"lokasi_source_slims/files/backup"</b> ke tempat lain</strong>.
</blockquote>
</p>
<p>
<div class="tips-count">Tips 4:</div>
<div class="tips-title">Optimasikan database SLiMS</div>
<blockquote>
Bagi anda pengguna SLiMS yang sering kali melakukan proses update data dan penghapusan data, ada baiknya lakukan proses optimisasi database SLiMS. Untuk optimasi database SLiMS gunakan saja phpMyAdmin atau kalo mau lebih hardcore login ke database server MySQL pake terminal/commandline. Dengan phpMyAdmin masuk ke database yang digunakan SLiMS (biasanya di psenayan namanya "senayandb"), dan kemudian masuk ke tab menu SQL dan masukkan perintah berikut:
<p>
<code>
OPTIMIZE TABLE `biblio` ,
`biblio_attachment` ,
`biblio_author` ,
`biblio_topic` ,
`files` ,
`item` ,
`member` ,
`mst_author` ,
`mst_label` ,
`mst_topic`;
</code>
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW89pMhW7Db0NJAFTfRsLA2vxa8n1NqIV1aGsW4KubVHlHpaWJXq74kxxwmkTk5qPte_RJsmw3Q6WQqIKD6FAB-ZYlQh9irImY492AYSzc8wG_1nzlSx7qFbyxe664UZWh2p0/s1600/optimize-slims.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="218" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW89pMhW7Db0NJAFTfRsLA2vxa8n1NqIV1aGsW4KubVHlHpaWJXq74kxxwmkTk5qPte_RJsmw3Q6WQqIKD6FAB-ZYlQh9irImY492AYSzc8wG_1nzlSx7qFbyxe664UZWh2p0/s320/optimize-slims.png" /></a></div>
</blockquote>
</p>
<p>
<div class="tips-count">Tips 5:</div>
<div class="tips-title">Backup dan kosongkan System Logs SLiMS secara rutin</div>
<blockquote>
Lakukan proses backup dengan mendownload log System SLiMS dengan menggunakan fasilitas yang sudah disediakan dan kemudian kosongkan System Log SLiMS. Lakukan ini secara berkala setiap bulan.
</blockquote>
</p>
<p>
Kira-kira begitulah tips dan trik dalam proses maintenance SLiMS yang bisa saya share kepada rekan-rekan pengguna SLiMS, ditunggu masukkan tips dan trik yang lainnya dari rekan-rekan semua. Semoga bermanfaat :)
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com9tag:blogger.com,1999:blog-25865790.post-87313349933072536492010-08-22T23:13:00.000-07:002011-08-24T06:15:04.117-07:00Kompilasi HandBrake di Ubuntu 10.04 Lucid LynxMungkin sebagian dari Anda pengguna Ubuntu, sudah tahu bahwa HandBrake tidak keluar versi binary untuk distro Ubuntu dan Fedora. Padahal HandBrake menurut saya adalah salah satu aplikasi terbaik buat nge-rip DVD/encode video ke format <a href="http://en.wikipedia.org/wiki/Matroska">MKV</a> atau <a href="http://en.wikipedia.org/wiki/MPEG-4_Part_14">MP4</a>. Alasan resmi dari developernya adalah:<br />
<blockquote>
"0.9.4 is no longer available due to compatibility issues with the newer version of gnome. "</blockquote>
Ada juga cara dengan mendownload <i>Nightly build</i>-nya di <a href="https://edge.launchpad.net/%7Estebbins/+archive/handbrake-snapshots">Launchpad-nya John Stebbins</a>.
Buat yang demen cara susah, biar keliatan lebih geek, bisa juga install dengan kompilasi dari <i>Source Code</i>. Sebelumnya coba cara susah ini, pastiin komputer anda terkoneksi ke Internet dan pastikan paket-paket development berikut ini sudah terinstall:
<br />
<ul>
<li>yasm</li>
<li>build-essential</li>
<li>autoconf</li>
<li>libtool</li>
<li>zlib1g-dev</li>
<li>libbz2-dev</li>
<li>intltool</li>
<li>libglib2.0-dev</li>
<li>libdbus-glib-1-dev</li>
<li>libgtk2.0-dev</li>
<li>libgudev-1.0-dev</li>
<li>libwebkit-dev</li>
<li>libnotify-dev</li>
<li>libgstreamer0.10-dev</li>
<li>libgstreamer-plugins-base0.10-dev</li>
</ul>
Bagaimana cara installnya? buka console, lalu seperti biasa ketikkan perintah:
<code>
sudo apt-get install yasm build-essential
autoconf libtool zlib1g-dev libbz2-dev intltool libglib2.0-dev
libdbus-glib-1-dev libgtk2.0-dev libgudev-1.0-dev
libwebkit-dev libnotify-dev libgstreamer0.10-dev
libgstreamer-plugins-base0.10-dev
</code>
<br />
Setelah paket-paket tersebut sudah terinstall dengan baik, maka lakukan langkah-langkah sebagai berikut:
<br />
<ol>
<li><a href="http://handbrake.fr/downloads.php">Download source code HandBrake (Ya iya lahh!!!)</a> (Pada saat tulisan ini dibuat HandBrake berada pada versi 0.9.4)</li>
<li>Buka console kesayangan anda dan arahkan ke direktori tempat anda mendowload <i>source code</i> HandBrake tadi.</li>
<li>Extract file tarball source code HandBrake dengan perintah:
<code>tar xvf HandBrake-0.9.4.tar.bz2</code></li>
<li>masuk ke direktori hasil ekstraksi tadi dengan perintah:
<code>cd HandBrake-0.9.4/</code></li>
<li>Jalankan perintah: <code>./configure --prefix=/usr/local</code></li>
<li>Setelah proses selesai, lalu masuk ke direktori <b>build</b> dengan perintah:
<code>cd ./build</code></li>
<li>Jalankan make dengan perintah: <code>make</code></li>
<li>Tunggu proses-nya yang cukup lama selesai (tergantung spesifikasi komputer Anda), dan beberapa dependancies akan didownload otomatis ketika proses berjalan, seperti faac, faad, ffmpeg, dsb.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCjGNt0_-SaznipAMXu294Ihaine2ciZpY-q97fh53oMmeBjEtKuYLtLn1GTdjTjrRgCGyAwMu-gefEqbobq_RozVy5j6fp9JeY14TjNZ0nJ_h1hSSowKX8liAjvWOFqo4ODc/s1600/Screenshot-dicarve@dicarve:+%7E-Downloads-HandBrake-0.9.4-build.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCjGNt0_-SaznipAMXu294Ihaine2ciZpY-q97fh53oMmeBjEtKuYLtLn1GTdjTjrRgCGyAwMu-gefEqbobq_RozVy5j6fp9JeY14TjNZ0nJ_h1hSSowKX8liAjvWOFqo4ODc/s320/Screenshot-dicarve@dicarve:+%7E-Downloads-HandBrake-0.9.4-build.png" /></a></div>
</li>
<li>Setelah proses kompilasi selesai tanpa error, jalankan perintah install:
<code>sudo make install</code></li>
<li>Untuk mencoba apakah HandBrake sudah berjalan coba jalankan perintah: <code>HandBrakeCLI</code> untuk versi <em>command line</em>-nya dan juga <code>ghb</code> untuk versi dengan GUI GTK2.0-nya</li>
<li>Bagi yang masih penasaran mengenai cara kompilasinya, silahkan baca manual kompilasi aslinya di<a href="https://trac.handbrake.fr/wiki/CompileOnLinux"> Compiling HandBrake on GNU/Linux</a>.
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOFCCDC9cMFWZhLYFRfqd2cs2cCtSE7pmlsbpCaCHbbpIx4FSnUihWfnt5z6xUVKqh6ea_Jr7D_anrAUqSW_KlJhT7M99II8S-MJYmqJ0Dvyv6o6kNjvnBNL9kR9vw1jfofHg/s1600/Screenshot-Handbrake.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOFCCDC9cMFWZhLYFRfqd2cs2cCtSE7pmlsbpCaCHbbpIx4FSnUihWfnt5z6xUVKqh6ea_Jr7D_anrAUqSW_KlJhT7M99II8S-MJYmqJ0Dvyv6o6kNjvnBNL9kR9vw1jfofHg/s320/Screenshot-Handbrake.png" /></a></div>
Selamat! sekarang HandBrake sudah bisa digunakan untuk me-rip DVD kesayangan anda dalam format MKV atau MP4, bisa lewat GUI ataupun kalo mau merasa lebih geeky lagi buang jauh-jauh GUI, pake versi <em>command line</em>-nya :P :D!!arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com2tag:blogger.com,1999:blog-25865790.post-4253802393584677352010-05-25T20:32:00.000-07:002011-08-24T06:20:09.746-07:00Mengatasi problem "wget" ketika mendownload di balik proxy (Ubuntu Lucid Lynx)<p>
Beberapa waktu yang lalu saya meng-upgrade OS GNU/Linux <a href="http://www.ubuntu.com/">Ubuntu</a> Karmic Koala (9.10) di MacbookPro saya ke versi LTS terbaru, Lucid Lynx (10.04). Saya upgrade menggunakan versi alternate yang saya download dari <a href="http://kambing.ui.ac.id/">Kambing</a>. Semua proses berjalan lancar, Lucid terinstall dengan ciamik-nya di MacbookPro dan hampir semua tombol fungsi spesial di Mac berjalan dengan baik.
</p>
<p>
Masalah muncul ketika saya akan mendownload website untuk mirroring dengan program command-line favorit saya, <b>wget</b>. Kantor saya menggunakan proxy untuk koneksi Internet, sehingga untuk menjalankan perintah-perintah dari console yang menjalankan download seperti <b>apt-get install</b> atau <b>apt-get update</b> misalnya kita harus men-set environment variable http_proxy dan ftp_proxy terlebih dahulu. Pada desktop GNOME sudah disediakan aplikasi "<b>Network Proxy</b>" yang terletak di <b>System->Preferences</b>, yang memudahkan kita mengubah setting proxy jaringan. Enaknya lagi program ini mendukung <i>multiple profile proxy</i> yang memudahkan kita untuk menyimpan lebih dari satu setting proxy, kemudian tinggal mengubahnya sesuai dengan kebutuhan kita.
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO53V9sCKkhsb8JgW21WsSGpKrm0F4g96N3HnMrY8Tj5JozKj-jZGmkri01Q49RbpO990s7XMm4DiwYOdGISWbRBZ0ABfumapGpt2CmRxdE02lKgAU4WInlWHUo7dbo5Evfcs/s1600/Gambar-Layar-Pengaturan+Proksi+Jaringan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO53V9sCKkhsb8JgW21WsSGpKrm0F4g96N3HnMrY8Tj5JozKj-jZGmkri01Q49RbpO990s7XMm4DiwYOdGISWbRBZ0ABfumapGpt2CmRxdE02lKgAU4WInlWHUo7dbo5Evfcs/s320/Gambar-Layar-Pengaturan+Proksi+Jaringan.png" /></a></div>
</p>
<p>
Sayangnya, pada Ubuntu Lucid Lynx, entah kenapa wget tidak terpengaruh dengan setting proxy ini, tetapi tools apt dan yang lainnya terpengaruh.
Setelah berkeliling internet mencari-cari solusinya, dan akhirnya menemukan solusinya di <a href="https://bugs.launchpad.net/ubuntu/+source/wget/+bug/232469">Lauchpad</a>, ternyata masalahnya sangat simple!!! Ternyata masalahnya ada di environment variable <strong>no_proxy</strong> yang secara "tidak sengaja" menaruh karakter "," (koma) di bagian akhir!!! PLLOOOKKKK!!! (tepok jidat)
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpotGCc5jAeEREErumVGOPCXJrJNJblqFMxrDaRoAfrCOHcpAITpf8EWBGEuQjTHRMEnC9uR0xf1E2XJuXwWeRgrpcD7oLoSJCwa-HtBu_9SJL9vojXN7NZO61M7C4YAsq_YE/s1600/Gambar-Layar-dicarve@dicarve:+%7E-Pictures-Wallpapers.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpotGCc5jAeEREErumVGOPCXJrJNJblqFMxrDaRoAfrCOHcpAITpf8EWBGEuQjTHRMEnC9uR0xf1E2XJuXwWeRgrpcD7oLoSJCwa-HtBu_9SJL9vojXN7NZO61M7C4YAsq_YE/s320/Gambar-Layar-dicarve@dicarve:+%7E-Pictures-Wallpapers.png" /></a></div>
</p>
<p>
Solusinya adalah dengan menghilangkan tanda koma di bagian akhir tersebut, dengan cara men-set ulang variable no_proxy di console:
<code>$export no_proxy=daftar-alamat-tidak-kena-proxy1,daftar-alamat-tidak-kena-proxy2,daftar-alamat-tidak-kena-proxy3</code>
dan kemudian wget bisa berjalan dengan normal kembali seperti biasa walau ada proxy. Jangan lupa juga cek file konfigurasi wget yang terletak di "/etc/wgetrc" dan pastikan setting <b>use_proxy=on</b> aktif dan setting <b>no_proxy</b> ditulis dengan benar (bila ada).
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com2tag:blogger.com,1999:blog-25865790.post-27810012752279700842010-04-29T03:16:00.000-07:002010-04-29T04:07:37.636-07:00Compile Sphinx indexing engine di Mac OSX 10.6.3Cari solusi <i>indexing database standalone</i> yang handal? Salah satu solusinya adalah <a href="http://www.sphinxsearch.com/about.html">Sphinx</a>. Sphinx adalah engine pengindeksan full-text yang didesain untuk terintegrasi dengan baik ke RDBMS-RDBMS macem MySQL dan PostgreSQL, dan yang asiknya laginya Sphinx sudah menyediakan API ke bahasa-bahasa scripting populer macem PHP, Python, Perl dan Ruby.
<br />
Karena saya develop aplikasi pake bahasa skripting PHP, maka Sphinx merupakan solusi yang pas untuk saya. Salah satu fitur yang bikin saya <i>ngiler</i> adalah statement berikut ini:
<br />
<blockquote>
"high search speed (avg query is under 0.1 sec on 2-4 GB text collections)"</blockquote>
Wuiidddiihhh kalo dibandingin sama indexing native mysql, 100 ribu records yang besarnya sekitar 30MB aje ude empot-empotan!!! Statement berikutnya juga bikin <i>ileran</i>
<br />
<blockquote>
"high scalability (upto 100 GB of text, upto 100 M documents on a single CPU)"</blockquote>
Saat tulisan ini dibuat, saya develop aplikasi web pake Macbook Pro, OS Snow Leopard 10.6.3, dan karena saya males compile-compile Apache, MySQL dan PHP (kecuali di OS GNU/Linux entah kenapa kurang apdol rasanya kalo ga di-compile sendiri heheheheee *kabboorr*), jadilah saya pake XAMPP for Mac OSX versi 1.7.2.
<br />
Karena binary Sphinx kage ade buat Mac OSX, cuman ade buat <i>"Mikocok Winslow"</i>, maka itu berarti kite harus compile sendiri Sphinx. ALHAMDULILLAH WA SYUKURILLAH! OSX udah nyedian Xcode yang didalemnya udah ada semua tool development UNIX macem gcc, g++, make, automake, autoconf, you name it lah! GRATIS lagi! *Getokin Apple kalo sampe paket XCode dibikin berbayar*. ALHAMDULILLAH lagi, karena Mac OSX basisnya UNIX juga (Darwin+FreeBSD), maka console dengan shell prompt Bash yang kesohor itupun ude ade by default di OSX *ffiuuuuhhhhh, can't live without those consoles*. ALHAMDULILLAH lagi! struktur direktori Mac OSX yang kaga jauh beda sama UNIX atau GNU/Linux!
<br />
Jadilah saya <i>"iseng-iseng berhadiah"</i> compile Sphinx di Macbook Pro saya. Yang pasti sebelum mulai compile Sphinx, download dan install dahulu library-library berikut ini (beserta dengan header-header developmentnya!! kudu, wajib!!):
<br />
<ol>
<li>Source code terbaru <a href="http://www.sphinxsearch.com/">Sphinx</a></li>
<li>Source code <a href="http://snowball.tartarus.org/">libstemmer</a></li>
<li>Source code dan file-file header MySQL kalo kita mau integrasikan Sphinx dengan MySQL</li>
<li>Source code dan file-file header PostgreSQL kalo kita mau integrasikan Sphinx dengan PostgreSQL</li>
<li>Bagi yang menggunakan XAMPP bisa lebih mudah, download paket XAMPP-Dev yang sesuai dengan versi yang kita pake</li>
</ol>
Proses instalasinya kira-kira begini:
<br />
<ol>
<li>Buka aplikasi "Terminal", kalo belom tau coba cari di /Applications/Utilities/</li>
<li>Ekstrak file distribusi Sphinx pake perintah:
<code>tar xvf sphinx-0.9.9.tar.gz</code>
</li>
<li>Ekstrak file distribusi libstemmer dan kopikan folder ekstraksi libstemmer ke dalam folder source Sphinx yang baru saja kita ekstrak pake perintah:
<code>cp -r ./libstemmer_c sphinx-0.9.9</code>
</li>
<li>Masuk ke direktori hasil ekstraksi pake perintah:
<code>cd sphinx-0.9.9</code>
</li>
<li>
Karena saya pake XAMPP Mac OSX perintah configure saya seperti ini:
<code>
Dicarve@Macbook sphinx-0.9.9$ CFLAGS="-O -arch i386" CXXFLAGS="-O -arch i386 -I/Applications/XAMPP/xamppfiles/include/ -I/Applications/XAMPP/xamppfiles/include/mysql" LDFLAGS="-arch i386 -L/Applications/XAMPP/xamppfiles/lib" ./configure --prefix=/usr/local/ --with-mysql -with-libstemmer --with-mysql-includes=/Applications/XAMPP/xamppfiles/include/mysql --with-mysql-libs=/Applications/XAMPP/xamppfiles/lib/mysql
</code>
Saya sempet agak-agak stress karena diawal-awal proses kompilasi gagal melulu! setelah baca-baca keliling Internet dan baca <a href="http://blog.d27n.com/2009/08/26/mac-os-x-snow-leopard-rails-mysql-and-sphinx/">disini</a>, ternyata sphinx-nye harus di-compile di mode 32 bit! *karena by default gcc di Mac OSX compile di mode 64 bit*
</li>
<li>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-MqyHYrvxBndW-wyMD1vnT6k9jBGBEmr7uqein-PZBrmsSQyla46jYavTRh_fN5iCdblfyu1mQCJ_3ZlfyS724XrjFMucOWVV0UMcV_25wzqC8Q77kfISVPRMUMyD7b1gGFE/s1600/Screen+shot+2010-04-29+at+5.56.14+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-MqyHYrvxBndW-wyMD1vnT6k9jBGBEmr7uqein-PZBrmsSQyla46jYavTRh_fN5iCdblfyu1mQCJ_3ZlfyS724XrjFMucOWVV0UMcV_25wzqC8Q77kfISVPRMUMyD7b1gGFE/s320/Screen+shot+2010-04-29+at+5.56.14+PM.png" /></a></div>
Apabila proses konfigurasi berjalan lancar tanpa masalah, maka lanjutkan dengan perintah berikut secara berurutan:
<code>
$ make<br />
$ sudo make install
</code>
</li>
</ol>
Horreee Sphinx berhasil diinstall!!!! Yiiihhuuu!!! Selanjutnya tinggal konfigurasi Sphinx biar bisa <i>"bicara"</i> sama MySQL atau PostgreSQL, selamat mencoba, dan jangan lupa baca dokumentasi sphinx di website resminya, RTFM!arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com0tag:blogger.com,1999:blog-25865790.post-28003051019080706282010-01-06T23:48:00.001-08:002010-01-07T01:03:17.667-08:00Emang Enak Kepentok Proxy!!!<p>
Mengembangkan software dengan menggunakan aplikasi source code management (SCM) emang enak. Kami, developer SENAYAN Library Management System (SLiMS) pake <a href="http://git-scm.com/">git</a> buat source code versioningnya. Asiknya pake git dibandingkan dengan aplikasi SCM lain adalah git menerapkan model ter-distribusi, tidak <span style="font-style: italic;">centralize</span> seperti cvs. Asyiknya lagi pake git, kita ga harus terkoneksi ke server, kita bisa pake lingkungan hard disk lokal untuk buat branch-branch dari project kita.
<p/>
<p>
Saya ga akan ngebahas cara make git disini, tapi saya ngebahas bagaimana kalau kita mau push dan pull request dari server repository git di internet, tapi kepentok sama proxy jaringan dan firewall yang biasanya cuman ngebolehin port 80 atau 3182.
<p/>
<p>
Tapi itulah keindahan dunia open source, "That's The Beauty of Open Source", udah ada aplikasi yang bisa bantu kita tunneling data dari git, yang by default pake protokol SSL. aplikasi command line ini namanya <a href="http://www.agroman.net/corkscrew/">Corkscrew</a>, dan tersedia untuk semua varian GNU/Linux, UNIX, BSD, Mac OSX dan MS Windows (tapi mesti install Cygwin dulu, HAHAHHAHAHA!!! EMANG ENAKK!!!!). Apa pulak "Corkscrew" ini? ngutip langsung dari websitenya :
<blockquote>
"<b><span style="font-family: Georgia,"Times New Roman",serif;">Corkscrew is a tool for tunneling SSH through HTTP proxies</span></b>."<br />
</blockquote>
Versi terakhir ketika tulisan ini diketik dan dipikirkan adalah versi 2.0.
<p/>
<p>
Buat make Corkscrew, caranya gampang banget, kalo ga bisa dibilang susah :D, cukup download source code-nya dan kemudian compile deh pake compiler C favorit anda hehehheeheee..... Kalau anda pake GNU/Linux, biasanya gcc by default ude keinstall, kalo enggak yang nasib, hehheheee.... becanda! kalo ga ada gcc ya install lah dari repo distro anda :)). Step instalasinya setelah download kira-kira seperti ini :
<br />
<ol>
<li>Buka console/terminal kesayangan anda (pliss, jangan buka DOS atau Command Prompt!!)</li>
<li>Extract file hasil download Corkscrew pake perintah: tar xvzf corkscrew-2.0.tar.gz</li>
<li>Masuk ke dalam direktori hasil ekstract: cd corkscrew-2.0</li>
<li>Jalankan perintah berikut secara berurutan:
<br />
<div style="font-family: "Courier New",Courier,monospace;">
./configure --prefix=/usr/local<br />
</div>
<div style="font-family: "Courier New",Courier,monospace;">
make<br />
</div>
<div style="font-family: "Courier New",Courier,monospace;">
sudo make install<br />
</div>
</li>
</ol>
</p>
<p>
Setelah instalasi Corkscrew berhasil, maka langkah selanjutnya adalah mengkonfigurasi ssh agar bisa tunneling SSL lewat proxy. Buka file yang namanya "config", yang ada di folder ".ssh" di home directory user. Misalnya home directory saya di "/home/dicarve" maka berarti letaknya ada di "/home/dicarve/.ssh/". Kalo file "config" belom ada.......... ya dibuatlah pake text editor, pake vi, pake vim, pake emacs, pake nano (halahhhh). Edit file config tersebut dan isikan kira-kira seperti ini :
<pre>
Host <b>gitproxy</b>
User git
HostName ssh.github.com
Port 443
ProxyCommand /usr/local/bin/corkscrew <b>alamat-atau-no-IP-proxy</b> <b>port-proxy</b> %h %p
IdentityFile /home/dicarve/.ssh/id_dsa
</pre>
Jangan lupa di-save!! :D
</p>
<p>
Setelah semua itu selesai, maka nanti ketika kita mau pull atau push data ke repository server git, misalnya SLiMS di repo-kan di <a href="http://github.com/slims">github/slims</a>, perintah git yang kita lakukan bukannya begini:
<pre>
git pull git@github.com:slims/s3st13.git master
</pre>
Tapi jadi begini:
<pre>
git pull git@<b>gitproxy</b>:slims/s3st13.git master
</pre>
atau kalo mau push
<pre>
git push git@<b>gitproxy</b>:slims/s3st13.git master
</pre>
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com0tag:blogger.com,1999:blog-25865790.post-47962860266058341552009-12-03T17:23:00.000-08:002011-08-24T06:19:11.407-07:00Workshop Nasional SENAYAN Library Management System!!!<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhXdr8aErWjSKJeVL3Zdja0YB2K76_I52VIh3nHTcWCzX_deymmqAKBl7orMZHJibqiZDc8K91GlSG-nfvkqoV0nOdu9BPRIzZl_Y4ebNPdgEMCpG1-LBvyrlVO3MkE5v9gYc/s1600-h/senayan-wp-big-preview.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhXdr8aErWjSKJeVL3Zdja0YB2K76_I52VIh3nHTcWCzX_deymmqAKBl7orMZHJibqiZDc8K91GlSG-nfvkqoV0nOdu9BPRIzZl_Y4ebNPdgEMCpG1-LBvyrlVO3MkE5v9gYc/s400/senayan-wp-big-preview.jpg" /></a><br /></div>
<p>
SENAYAN DEVELOPER COMMUNITY (SDC) kembali akan ngadain Workshop Nasional SENAYAN Library Management System (SLiMS), yang tepatnya akan dilaksanakan di Hotel Paragon Jakarta (daerah Menteng, Jakarta Pusat), pada tanggal 14 – 17 Desember 2009. Pastinya karena Workshop ini diadakan selama 4 hari 3 malam full, jadi materi yang diberikan juga akan sangat banyak dan men-detail.
</p>
<p>
Workshop ini ditujukan kepada para pustakawan atau perorangan yang ingin memanfaatkan SLiMS untuk mengelola koleksi ditempat kerja. Materi workshop dirancang untuk membantu para peserta agar dapat segera mengaplikasikan SLiMS di tempat masing-masing. Dibagi dalam 10 (Sepuluh) modul dasar ditambah materi kustomisasi dan konversi data, pengetahuan dasar perpustakaan akan sangat membantu peserta memahami materi dan panduan yang di sampaikan. Dalam pelatihan, peserta akan menggunakan versi terbaru SLiMS – atau juga dikenal dengan SENAYAN 3 stable 12.
</p>
<p>
Untuk brosur pendaftaran serta surat undangan bisa di-unduh (download) di <a href="http://www.gaia-db.com/workshop/">Workshop SLIMS</a>.
</p>
<p>
Untuk anda yang ingin belajar menggunakan SENAYAN, ngoprek, nginstall SENAYAN di GNU/Linux macem Ubuntu, Fedora atau OpenSUSE, pengen belajar cara konversi data dari database ISIS, Athenaeum atau database lainnya, jangan lewatin Workshop SLiMS ini. Trainer-nya juga langsung para Developer ASELI SLiMS!!!.
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com11tag:blogger.com,1999:blog-25865790.post-21726253058307374212009-08-26T21:28:00.000-07:002011-08-24T06:17:32.493-07:00jQuery, I Love You Full!<p>
Di postingan sebelumnya saya membahas <a href="http://www.prototypejs.org">Prototype</a>, sebuah framework Javascript ciamik untuk manipulasi DOM dan AJAX. Kali ini saya iseng-iseng coba sebuah framework Javascript yang sudah kesohor juga yaitu <a href="http://jquery.com">jQuery</a>. kalau menurut hemat saya, jQuery punya model syntax yang lebih elegan dibandingkan dengan Prototype, hal ini bisa kita lihat dalam model object jQuery yang lebih simple, terutama dalam penanganan event. Penanganan event di jQuery nemungkinkan kita benar-benar memisahkan antara layer tampilan dengan layer logic pemrograman javascript.
</p>
<p>
Perbedaan mendasar antara jQuery dengan Prototype adalah, fungsi <span style="font-weight:bold;">$</span> pada jQuery menerima argumen string Selector CSS atau XPath dan selalu mengembalikan objek jQuery dalam bentuk Array atau List, sedang pada Prototype fungsi <span style="font-weight:bold;">$</span> hanya menerima string ID dari element yang akan kita manipulasi dan mengembalikan object DOM yang sudah di-extend oleh metode-metode Prototype (walaupun sebenarnya Prototype punya fungsi yang serupa dengan <span style="font-weight:bold;">$</span>-nya jQuery, yaitu fungsi <span style="font-weight:bold;">$$</span> dan juga metode class Element, <span style="font-weight:bold;">select</span>, yang juga menerima argument string Selector CSS atau XPath). IMHO hal ini membuat jQuery menjadi lebih efisien, karena semua metode jQuery (dan juga semua metode plugins-nya) sudah pasti mengolah Array atau List objek DOM jQuery.
</p>
<p>
Contohnya, untuk me-<span style="font-style:italic;">register</span> event memunculkan box alert apabila ada link dengan id 'klikSaya' di-klik, kita cukup menulis kode seperti ini pada bagian HEAD dokumen HTML kita atau bisa juga pada bagian awal BODY dokumen HTML :
<div style="padding: 3px; font-family: Courier; border-color: #999999;
border-width: 1px; overflow: scroll;
border-style: solid;
background-color: white;"><pre class="javascript">
<span style="color: #00bbdd;"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"></span>
<span style="color: #009900;"><a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;"><html</span></a> xmlns=<span style="color: #ff0000;">"http://www.w3.org/1999/xhtml"</span> xml:<span style="color: #000066;">lang</span>=<span style="color: #ff0000;">"en"</span> <span style="color: #000066;">lang</span>=<span style="color: #ff0000;">"en"</span><span style="color: #000000; font-weight: bold;">></span></span>
<span style="color: #009900;"><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;"><head></span></a></span>
<span style="color: #009900;"><a href="http://december.com/html/4/element/meta.html"><span style="color: #000000; font-weight: bold;"><meta</span></a> <span style="color: #000066;">http-equiv</span>=<span style="color: #ff0000;">"content-type"</span> <span style="color: #000066;">content</span>=<span style="color: #ff0000;">"text/html; charset=utf-8"</span> /<span style="color: #000000; font-weight: bold;">></span></span>
<span style="color: #009900;"><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;"><script</span></a> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">"text/javascript"</span><span style="color: #000000; font-weight: bold;">></span></span>
$<span style="color: #66cc66;">(</span>document<span style="color: #66cc66;">)</span>.<span style="color: #006600;">ready</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
$<span style="color: #66cc66;">(</span><span style="color: #3366CC;">'#klikSaya'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">click</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span>evt<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #000066;">alert</span><span style="color: #66cc66;">(</span><span style="color: #3366CC;">'Hallooowww anda telah meng-klik saya!'</span><span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></script></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></head></span></span>
</pre></div>
</p>
<p>
Dan pada BODY dokumen HTML, kita cukup menuliskan kode seperti ini :
<div style="padding: 3px; font-family: Courier; border-color: #999999;
border-width: 1px; overflow: scroll;
border-style: solid;
background-color: white;"><pre class="html4strict"><span style="color: #009900;"><a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;"><body></span></a></span>
<span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;"><a</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"klikSaya"</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"#"</span><span style="color: #000000; font-weight: bold;">></span></span>Klik Saya Donk Ahhh!<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></a></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></body></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></html></span></span>
</pre></div>
</p>
<p> </p>
<p>
Apalah artinya aplikasi Web 2.0 tanpa AJAX, rasanya kurang lengkap tanpa metode nyang satu ini. jQuery menyediakan API AJAX yang cukup lengkap untuk AJAX. Contoh di BODY dokumen HTML kita punya seperti ini:
<div style="padding: 3px; font-family: Courier; border-color: #999999;
border-width: 1px; overflow: scroll;
border-style: solid;
background-color: white;"><pre class="html4strict"><span style="color: #009900;"><a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;"><body></span></a></span>
<span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;"><a</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"klikAJAX"</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"#"</span><span style="color: #000000; font-weight: bold;">></span></span>Klik Saya Buat Munculin Konten dari AJAX di bawah ini :<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></a></span></span>
<span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;"><div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"ajaxContainer"</span><span style="color: #000000; font-weight: bold;">></span></span><span style="color: #ddbb00;">&nbsp;</span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></div></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></body></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;"></html></span></span></pre></div>
</p>
<p>
Maka di bagian HEAD kita bisa menuliskan kode Javascript seperti ini :
<div style="padding: 3px; font-family: Courier; border-color: #999999;
border-width: 1px; overflow: scroll;
border-style: solid;
background-color: white;"><pre class="javascript">$<span style="color: #66cc66;">(</span>document<span style="color: #66cc66;">)</span>.<span style="color: #006600;">ready</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
$<span style="color: #66cc66;">(</span><span style="color: #3366CC;">'#klikAJAX'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">click</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span>evt<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #003366; font-weight: bold;">var</span> content = $.<span style="color: #006600;">ajax</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">{</span> url: <span style="color: #3366CC;">"kontenAJAX.php"</span>, async: <span style="color: #003366; font-weight: bold;">false</span> <span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">responseText</span>;
<span style="color: #009900; font-style: italic;">// perhatikan opsi 'async', apabila diset false, maka semua event lain di browser di-block</span>
<span style="color: #009900; font-style: italic;">// sehingga tidak ada proses AJAX dilakukan bersamaan</span>
$<span style="color: #66cc66;">(</span><span style="color: #3366CC;">'#ajaxContainer'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">html</span><span style="color: #66cc66;">(</span>content<span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>;</pre></div>
Sangat mudah bukan?
</p>
<p>
jQuery juga sudah menyediakan metode-metode untuk animasi dasar, seperti fadeIn, FadeOut, pullDown, pullUp, hide, show dan animate. Contohnya bisa dilihat sebagai berikut :
<div><a class="show-hidden" href="#">Klik Saya Donk!</a></div>
<div class="hidden-object" style="display: none; padding: 5px; border: 1px solid #CCC; background: #ccffe5; font-style: italic">
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things...
<a class="hide-hidden" href="#">Sembunyiin Lagi Ahh!</a>
</div>
Makkkk!!! gampang kali!! kode untuk efek animasi di atas hanya begini saja :
<div style="padding: 3px; font-family: Courier; border-color: #999999;
border-width: 1px; overflow: scroll;
border-style: solid;
background-color: white;"><pre class="javascript">$<span style="color: #66cc66;">(</span>document<span style="color: #66cc66;">)</span>.<span style="color: #006600;">ready</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
$<span style="color: #66cc66;">(</span><span style="color: #3366CC;">'a.show-hidden'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">click</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span>evt<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
evt.<span style="color: #006600;">preventDefault</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>;
$<span style="color: #66cc66;">(</span><span style="color: #3366CC;">'.hidden-object'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">slideDown</span><span style="color: #66cc66;">(</span><span style="color: #3366CC;">"normal"</span><span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>;
$<span style="color: #66cc66;">(</span><span style="color: #3366CC;">'a.hide-hidden'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">click</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span>evt<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
evt.<span style="color: #006600;">preventDefault</span><span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>;
$<span style="color: #66cc66;">(</span><span style="color: #3366CC;">'.hidden-object'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">slideUp</span><span style="color: #66cc66;">(</span><span style="color: #3366CC;">"normal"</span><span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>;</pre></div>
</p>
<p>
Seperti halnya Prototype, jQuery didesain agar penulisan kode semakin ringkas dan elegan, yang pada akhirnya bisa memperkecil ukuran file kode Javascript kita. Hal ini didapat dengan penerapan <em>Command Chaining</em>. Setiap hasil fungsi <span style="font-weight:bold;">$</span> bisa di-chaing atau digabung dengan fungsi-fungsi jQuery lain. Misalnya bisa kita lihat pada contoh kode berikut :
<div style="padding: 3px; font-family: Courier; border-color: #999999;
border-width: 1px; overflow: scroll;
border-style: solid;
background-color: white;"><pre class="javascript"><span style="color: #009900; font-style: italic;">// temukan semua tag 'A' dibawah element DOM dengan ID 'menu'</span>
<span style="color: #009900; font-style: italic;">// dan daftarkan event 'click' sekaligus event 'mouseover'</span>
<span style="color: #009900; font-style: italic;">// dan juga sekaligus set style CSS dari setiap tag 'A' yang ditemukan</span>
<span style="color: #009900; font-style: italic;">// dengan display = block</span>
$<span style="color: #66cc66;">(</span><span style="color: #3366CC;">'#menu'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">find</span><span style="color: #66cc66;">(</span><span style="color: #3366CC;">'a'</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">click</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span>evt<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #009900; font-style: italic;">// lakukan sesuatu untuk setiap tag 'A' disini</span>
<span style="color: #009900; font-style: italic;">// ketika di-klik</span>
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">mouseover</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">(</span>evt<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #009900; font-style: italic;">// lakukan sesuatu untuk setiap tag 'A' disini</span>
<span style="color: #009900; font-style: italic;">// ketika cursor melewati tag 'A'</span>
<span style="color: #66cc66;">}</span><span style="color: #66cc66;">)</span>.<span style="color: #006600;">css</span><span style="color: #66cc66;">(</span><span style="color: #3366CC;">'display'</span>, <span style="color: #3366CC;">'block'</span><span style="color: #66cc66;">)</span>;</pre></div>
</p>
<p>
Gampang yak? :D
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com4tag:blogger.com,1999:blog-25865790.post-61532519960349467082009-07-15T22:23:00.000-07:002017-12-13T18:32:24.732-08:00Instalasi library YAZ di PHP<p>
Pada <a href="http://senayan.diknas.go.id" target="_blank">SENAYAN 3 Stable 10</a>, saya menambahkan kemampuan untuk mengambil data melalui protokol Z39.50 pada modul <span style="font-weight:bold;">Bibliography</span> (Pengatalogan). Fitur ini memanfaatkan library <a href="http://www.indexdata.com/phpyaz" target="_blank">PHP YAZ</a>. YAZ sendiri adalah sebuah library untuk bahasa C yang dapat digunakan untuk membangun aplikasi server dan klien protokol Z39.50/SRW/SRU. Untuk lebih lengkapnya silahkan anda arahkan browser kesayangan anda ke laman resmi <a href="http://www.indexdata.com/phpyaz" target="_blank">YAZ</a>.
Fitur Z39.50 di SENAYAN 3 Stable 10 diharapkan akan semakin memudahkan pustakawan untuk mengambil data langsung ke database online Library of Congress yang kesohor itu. Cukup masukan nomor ISBN, tunggu proses pengambilan data selesai, apabila berhasil anda tinggal memilih data mana yang akan dimasukkan ke dalam database SENAYAN anda. Hidup pustakawan semakin mudah kalau pakai SENAYAN hehheeheee :).
<p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikn8H6wmbRQy2ovlMY1w1fQDHEYsAnX9bv5lkAbPJUFLV59aKkNbqGSyBweacv0vv5kLBcB7cNQPmqzj3D4Ib0GXaad64ZE-r5q8TaWqPt6n2x3ku6wWKi7KQ7gPJyMyfc1MM/s1600-h/SENAYAN-z3950-service.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 217px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikn8H6wmbRQy2ovlMY1w1fQDHEYsAnX9bv5lkAbPJUFLV59aKkNbqGSyBweacv0vv5kLBcB7cNQPmqzj3D4Ib0GXaad64ZE-r5q8TaWqPt6n2x3ku6wWKi7KQ7gPJyMyfc1MM/s320/SENAYAN-z3950-service.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5359001029952537842"></a>
</p>
</p>
<p>
Untuk yang belum mengetahui apa itu protokol Z39.50, Z39.50 adalah protokol klien server berstandar internasional (ISO 23950) untuk penelusuran dan temu kembali informasi antar komputer. Penerapan protokol ini memungkinkan beberapa institusi untuk saling bertukar data, menelusur dan menemukan kembali data (biasanya rekod bibliografis/katalog koleksi perpustakaan) dengan antar muka yang sama dan teknik penelusuran yang sama.
</p>
<p>
Untungnya pengembang YAZ juga mengembangkan extension library YAZ untuk PHP. Untuk menginstall dan mengaktifkan library YAZ di PHP caranya cukup mudah :
<h3>Windows</h3>
<ol>
<li>
Unduh/download versi terakhir <strong>php_yaz.dll</strong> di repositori <a href="http://ftp.indexdata.dk/pub/phpyaz/win32/">PHP YAZ</a> dan kopi ke folder/direktori extension PHP anda. Misal anda menginstall PHP di <i>C:\php</i>, maka kopi file php_yaz.dll ke direktori <i>C:\php\ext</i>.
</li>
<li>
Unduh/download versi terakhir <a href="http://www.indexdata.dk/yaz/" target="_blank">YAZ toolkit</a> dan lakukan instalasi.
</li>
<li>
Masuk ke direktori instalasi YAZ anda (biasanya terletak di C:\Program Files\YAZ\bin) dan kopi 4 file DLL (atau biar gampang semua file DLL juga boleh :D) yang ada di dalamnya ke direktori C:\WINDOWS\system32 dan C:\WINDOWS\system. Bisa juga apabila anda menggunakan web server Apache, kopikan semua DLL-nya YAZ ke folder bin-nya instalasi Apache.
</li>
<li>
Buka file konfigurasi PHP anda (php.ini) dan tambahkan atau hilangkan tanda ;(titik koma) baris yang bertuliskan seperti ini :<br />
<code>
extension=php_yaz.dll
</code>
</li>
<li>
Restart web server anda untuk menyelesaikan proses instalasi dan setup dan kemudian cek dengan script <code><?php phpinfo(); ?></code> apakah library YAZ sudah terinstall dengan baik.
<p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVsRWJw0osp2YrYSpeXAivkmApDLl5adUTS_GC9X3GMFWc6gekOMOY-N82oIkuTlqEXoaS3QrnodVq9CADw5XK4EDgiE2L20oGx9443NEtxXhLfvD0rhRfAuBD3ou-4DYyzoc/s1600-h/php-yaz-installed.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 74px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVsRWJw0osp2YrYSpeXAivkmApDLl5adUTS_GC9X3GMFWc6gekOMOY-N82oIkuTlqEXoaS3QrnodVq9CADw5XK4EDgiE2L20oGx9443NEtxXhLfvD0rhRfAuBD3ou-4DYyzoc/s320/php-yaz-installed.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5358999855342696114"></a>
</p>
</li>
</ol>
<p> </p>
<h3>GNU/Linux atau varian UNIX</h3>
<ol>
<li>
Download source code rilis stable <a href="http://ftp.indexdata.dk/pub/yaz/">YAZ terbaru</a>.
</li>
<li>
Download source code rilis <a href="http://ftp.indexdata.dk/pub/phpyaz/">PHP YAZ terbaru</a>.
</li>
<li>Pastikan compiler GCC, make, libtool dan tools development lainnya sudah terinstall di sistem anda.</li>
<li>
Buka console/terminal, ekstrak file tarball YAZ dengan menggunakan perintah <code>tar xvzf yaz-3.0.47.tar.gz</code> dan kemudian masuk dalam direktori hasil ekstraksi YAZ dengan perintah <code>cd yaz-3.0.47</code>.
</li>
<li>
Jalankan perintah-perintah berikut secara berurutan :
<pre>
<code>
./configure --prefix=/usr
make
sudo make install
</code>
</pre>
</li>
<li>
Ekstrak tarball PHP YAZ dengan perintah <code>tar xvzf php-yaz-1.0.14.tar.gz</code> dan kemudian masuk ke direktori hasil ekstraksi dengan perintah <code>cd php-yaz-1.0.14</code>.
</li>
<li>
Pastikan anda memiliki program <strong>phpize</strong>, bila tidak silahkan lakukan instalasi melalui perintah <code>sudo apt-get install php-dev</code> untuk distro Debian dan turunannya atau <code>yum install php-dev</code> untuk distro distro turunan Red Hat. Jalankan perintah-perintah berikut secara berurutan :
<pre>
<code>
phpize
./configure --with-php-config=/usr/bin/php-config
make
sudo make install
</code>
</pre>
</li>
<li>
Buka file konfigurasi PHP anda (php.ini) dengan editor teks favorit anda dan tambahkan atau hilangkan tanda ;(titik koma) pada baris yang bertuliskan seperti ini :<br />
<code>
extension=yaz.so
</code>
</li>
<li>
Restart service web server anda dengan menjalankan perintah <code>service apache restart</code> sebagai user ROOT atau kalau tidak bisa coba jalankan perintah <code>/etc/init.d/httpd restart</code>.
</li>
<li>
Cek dengan script <code><?php phpinfo(); ?></code> apakah library YAZ sudah terinstall dengan baik.
<p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVsRWJw0osp2YrYSpeXAivkmApDLl5adUTS_GC9X3GMFWc6gekOMOY-N82oIkuTlqEXoaS3QrnodVq9CADw5XK4EDgiE2L20oGx9443NEtxXhLfvD0rhRfAuBD3ou-4DYyzoc/s1600-h/php-yaz-installed.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 74px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVsRWJw0osp2YrYSpeXAivkmApDLl5adUTS_GC9X3GMFWc6gekOMOY-N82oIkuTlqEXoaS3QrnodVq9CADw5XK4EDgiE2L20oGx9443NEtxXhLfvD0rhRfAuBD3ou-4DYyzoc/s320/php-yaz-installed.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5358999855342696114"></a>
</p>
</li>
</ol>
</p>arinugrahahttp://www.blogger.com/profile/00094475941697093216noreply@blogger.com20