Selasa, 12 Februari 2013

Modifikasi Typeahead Bootstrap dan Ajax

Jika kamu belum tahu apa itu Bootstrap bisa dilihat disini. Jika kamu sudah tahu Bootstrap tapi belum tahu tentang Typeahead bisa dilihat disini. Secara singkat Typeahead adalah input yang memunculkan pilihan saat kita mengetikkan sesuatu yang mirip dengan input yang kita masukkan. Contoh: waktu kamu mengetikkan nama di Facebook pasti muncul pilihan pada input tersebut daftar teman-temanmu yang memiliki nama yang mirip dengan input yang kamu masukkan.
Bootstrap memiliki Typeahead yang sebenarnya sudah cukup keren, tapi kita akan memodifikasi Typeahead ini agar bisa menampilkan foto dan menerima sumber data dari Ajax sehingga mirip dengan input di Facebook. Jika kamu penasaran bentuk asli dari Typeahead kita akan buat kerangka dasarnya dulu.

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Typeahead</title>
  <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" media="all">
  <link rel="stylesheet" href="bootstrap/css/bootstrap-responsive.min.css" media="all">
  <script src="jquery/jquery-1.9.0.min.js"></script>
  <script src="bootstrap/bootstrap.min.js"></script>
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="span8 offset2">
        <h3>Bootstrap Typeahead</h3>
        <hr>
        <form class="form-horizontal">
          <div class="control-group">
            <label for="artis" class="control-label">Pilih Artis</label>
            <div class="controls">
              <input type="text" name="artis" id="artis" class="input-xlarge" data-provide="typeahead" data-source='["Maria Selena", "Gita Gutawa", "Sandra Dewi", "Citra Kirana"]'>
            </div>
          </div>
          <div class="form-actions">
            <button class="btn btn-primary">SIMPAN</button> &nbsp;
            <button class="btn">BATAL</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</body>
</html>

Untuk path css dan javascriptnya ubah sesuai dengan letak file Bootstrap dan jQuery yang kamu punyai. Untuk mengaplikasi typeahead pada sebuah input sangatlah mudah, bahkan cuma menambahkan atribut data-provide="typeahead" dan data-source yang beruba array string maka typeahead sudah bisa berjalan seperti pada gambar ini:



Lumayan keren kan?, tapi sekarang kita akan memodifikasinya sehingga bisa menampilkan foto bersama dengan namanya. Bootstrap Typeahead memiliki API yang bisa kita ubah agar kita dapat mengubah tampilan defaultnya yaitu menggunakan highlighter dan updater. Berikut ini kode Javascriptnya yang bisa kamu masukkan dimanapun (sebaiknya sebelum tutup tag BODY).
/* 
 * load data dengan ajax dimana data yang diperoleh memiliki format:
 * [{ nama: 'nama artist', foto: 'url foto' }]
 *
 * jika tidak menggunakan ajax langsung masukkan di source
 */
$.ajax({
  url: 'respond.php?artis',
  dataType: 'json',
  success: function(d) {
    var data = d;
    
    /*
     * ini deklarasi typeaheadnya yang sudah dimodifikasi
     */
    $('#artis').typeahead({
      source: function(query, process) {
        objects = [];
        // iterasi data
        $.each(data, function(i, object) {
          objects.push(object.foto + '#' + object.nama);
        });
        process(objects);
      },
      items: 4, // jumlah list maksimal yang muncul
      highlighter: function(item) {
        var s = item.split('#'),
          regex = new RegExp('(' + this.query + ')', 'i'),
          nama = s[1].replace(regex, "<strong>$1</strong>");
        html = '<div class="typeahead">';
        html += '<div class="typeahead-media"><img src="img/' + s[0] + '" class="pull-left">';
        html += '<div class="media-body">';
        html += '<p class="media-heading">' + nama + '</p>';
        html += '</div>';
        html += '</div>';
        return html;
      },
      updater: function(item) {
        var s = item.split('#');
        return s[1];
      },
      matcher: function(item) {
        var s = item.split('#');
        return s[1].toLowerCase().indexOf(this.query.toLowerCase()) != -1
      }
    });
  }
});

Dan hasil yang kita peroleh seperti gambar ini:



Sebaiknya ukuran file gambarnya sama dan berbentuk bujursangkar. Karena tampilannya masih acak-acakan kita butuh sedikit CSS untuk merapikannya. Tambahkan kode CSS ini di dalam tag HEAD:
ul.typeahead.dropdown-menu {
  min-width: 370px; }
ul.typeahead li a {
  padding: 4px; }
.typeahead-media img {
    width: 28px;
  margin-right: 5px; }

Dan inilah hasil akhirnya:



Gak jelek2 amat kan :D. Semoga bermanfaat.

Jika kamu penasaran dan ingin tahu seperti apa file php yang memproses request sehingga menghasilkan bentuk yang diinginkan maka ini contoh kerangka kodenya:

<?php
if (isset($_GET['artis'])) {
  $query = mysql_query("SELECT `nama`, `foto` FROM `artis`");
  $hasil = array();
  while ($d = mysql_fetch_array($query, MYSQL_ASSOC)) {
    $hasil[] = array(
      'nama' => $d['nama'],
      'foto' => $d['foto']
    );
  }
  echo json_encode($hasil, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
}

Senin, 11 Februari 2013

Pagination dengan CodeIgniter, jQuery dan Bootstrap

Karena ada beberapa teman yang kesulitan mengaplikasikan pagination di CodeIgniter dengan jQuery, maka aku coba membuat sesuatu yang menurutku simple dan mudah dipahami (*semoga :). Kali ini aku akan menggunakan Twitter Bootstrap untuk CSS-nya dan jQuery untuk meload data. Kerangka dasar dokumennya adalah seperti ini:
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Pagination</title>
  <link rel="stylesheet" href="/third_party/bootstrap/css/bootstrap.min.css" />
  <link rel="stylesheet" href="/third_party/bootstrap/css/bootstrap-responsive.min.css" />
  <script src="/third_party/jquery/jquery-1.8.2.js"></script>
  <script>
    // masukkan kode javascript berikutnya disini
  </script>
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="span12">
        <h1>Pagination Dokumen</h1>
        <hr>
        <form class="form-inline">
          <input type="text" name="query" id="query" class="input-large"> &nbsp; 
          <button class="btn" onclick="return Document.search()"><i class="icon-search"></i> Cari</button>
        </form>
        <hr>
        <table class="table table-bordered table-condensed table-striped">
          <thead>
            <tr>
              <th>Judul</th>
              <th>Pengarang</th>
              <th>Tahun</th>
            </tr>
          </thead>
          <tbody id="document-data">
            <tr>
              <td></td>
              <td></td>
              <td></td>
            </tr>
          </tbody>
        </table>
        <hr>
        <div class="pagination pagination-centered pagination-medium" id="pagination">
          <ul>
            <li><a href="">&laquo;</a></li>
            <li><a href="">1</a></li>
            <li><a href="">&raquo;</a></li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</body>
</html>



Pada dokumen diatas kita memiliki sebuah tabel yang akan menampilkan data dokumen dengan kolom Judul, Pengarang, dan Tahun. Diatas tabel terdapat form untuk memasukkan kata kunci pencarian. Dibawah tabel terdapat template pagination yang nanti akan diubah setelah data diload oleh Ajax. Perhatikan ada beberapa id dari elemen yang berperan yaitu:
  • query. id untuk input kata kunci pencarian
  • document-data. id di tbody tabel data
  • pagination. id untuk bagian pagination dibawah tabel
Jika diperhatikan, di tombol Cari ada atribut onclick="return Document.search()". Nah sekarang kita tambahkan fungsi Javascriptnya untuk menangani tampilan data dan pagination di dokumen ini. Kode Javascript ini bisa kamu letakkan di dalam tag HEAD setelah jquery (di bagian yang aku tandai sebelumnya).
var Document = {
  param: {
    dataperpage: 3, // jumlah data per halaman
    query: '',
    curpage: 0,
    numpage: 0
  },
  url: '/test/document',
  search: function() {
    this.param.query = $('#query').val();
    this.param.curpage = 0;
    this.loadData();
    return false;
  },
  setPage: function(n) {
    this.param.curpage = n;
    this.loadData();
    return false;
  },
  prevPage: function() {
    if (this.param.curpage > 0) {
      this.param.curpage--;
      this.loadData();
    }
    return false;
  },
  nextPage: function() {
    if (this.param.curpage < this.param.numpage) {
      this.param.curpage++;
      this.loadData();
    }
    return false;
  },
  loadData: function() {
    $.ajax({
      url: Document.url,
      type: 'POST',
      dataType: 'json',
      data: jQuery.param(Document.param),
      success: function(d) {
        $('#pagination').html(d.pagination);
        Document.param.numpage = d.numpage;
        var t = '', dt = {};
        for (var i = 0; i < d.data.length; i++) {
          dt = d.data[i];
          t += '<tr><td>' + dt.judul +'</td>' + 
             '<td>' + dt.pengarang + '</td>' + 
             '<td>' + dt.tahun + '</td></tr>';
        }
        $('#document-data').html(t); // id dari tbody tabel data
      }
    });
  }
}

$(document).ready(function() {
  Document.search();
});
Ada bagian penting di property param dalam object Document diatas yaitu dataperpage yang berisi jumlah data perhalaman yang akan ditampilkan di tabel. Kamu bisa mengubah-ubah sesuai keinginanmu. Lalu bagian url juga harus disesuaikan dengan route yang akan kita buat di CodeIgniternya. Agar javascript meload data untuk pertamakalinya maka kita panggil Document.search() ketika dokumen siap melakui event $(document).ready(). Jangan simpan dulu file dokumen tadi karena setelah kita buat Controller baru kita bisa tahu mau disimpan dimana dokumen ini.
Sekarang kita buka file application/config/routes.php di CodeIgniter dan masukkan baris berikut:
$route['test'] = "test";
$route['test/document'] = "test/pagination";
Kita mesti punya Test controller sekarang. buat Controller baru dan beri nama Test yang isinya seperti ini:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Test extends CI_Controller {
  public function index() {
    $this->load->view('test/pagination.php');
  }
  
  public function pagination() {
    $this->load->database();
    $this->load->model('test_model');
    $this->test_model->search_document();
  }
}
Perhatikan di method index kita meload View test/pagination.php. Nah, file view ini adalah file dokumen yang berisi HTML dan Javascript yang telah kita buat sebelumnya. Berarti file dokumen tadi simpan di dalam folder application/views/test dan diberi nama pagination.php. Kalau kamu punya struktur view dan controller sendiri maka bagian controller bisa diubah sesuai dengan struktur yang kamu punya yang penting dokumennya ketemu.
Selanjutnya di controller tadi kita lihat bahwa controller meload model test_model, berarti sekarang kita buat modelnya:
<?php
class Test_model extends CI_Model {
  public function search_document() {
    $input = array('dataperpage', 'query', 'curpage');
    foreach ($input as $val)
      $$val = $this->input->post($val);
    
    $query = $this->db->escape_like_str($query);
    $where = "`JUDUL_DOKUMEN` LIKE '%{$query}%' OR `PENGARANG_DOKUMEN` LIKE '%{$query}%'";
    
    $query = $this->db->query("SELECT COUNT(`ID_DOKUMEN`) AS `HASIL` FROM `tb_dokumen` WHERE $where");
    $total = $query->row()->HASIL;
    $npage = ceil($total / $dataperpage);
    
    $start = $curpage * $dataperpage;
    $end = $start + $dataperpage;
    $query = $this->db->query("SELECT `JUDUL_DOKUMEN`, `PENGARANG_DOKUMEN`, `TAHUN_PENERBITAN_DOKUMEN` FROM `tb_dokumen` WHERE $where LIMIT $start, $dataperpage");
    $hasil = array(
      'data' => array(),
      'pagination' => '',
      'numpage' => $npage - 1,
    );
    if ($query->num_rows() > 0) {
      foreach ($query->result() as $row) {
        $hasil['data'][] = array(
          'judul' => $row->JUDUL_DOKUMEN,
          'pengarang' => $row->PENGARANG_DOKUMEN,
          'tahun' => $row->TAHUN_PENERBITAN_DOKUMEN
        );
      }
    }
    
    $hasil['pagination'] .= '<ul>
      <li class="'. ($curpage == 0 ? 'disabled' : '') .'" onclick="return Document.prevPage()"><a href>&laquo;</li>';
    for ($i = 1; $i <= $npage; $i++) {
      $hasil['pagination'] .= '<li class="' . ($curpage == ($i - 1) ? 'active' : '') . '" onclick="return Document.setPage(' . ($i - 1) .')"><a href>' . $i . '</a></li>';
    }
    $hasil['pagination'] .= '<li class="' . ($curpage == $npage - 1 ? 'disabled' : '') . '" onclick="return Document.nextPage()"><a href>&raquo;</a></li>
      </ul>';
    
    echo json_encode($hasil, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
  }
}
Kita akan mereturn hasil berupa JSON yang akan diterima oleh Javascript. Jika kamu memiliki database yang berbeda maka ubah saja bagian model diatas dan edit sesuai keinginanmu. Dan berikut ini hasil akhirnya:



Semoga bermanfaat dan mudah dipahami :D

Minggu, 21 Oktober 2012

Google Authorship Markup


Mungkin kamu baru mendengar istilah ini tapi jangan khawatir karena aku yakin kamu bukan satu-satunya orang yang baru mendengar salah satu fitur dari Google ini. Untuk lebih jelasnya apakah Google Authorship Markup itu maka akan saya tunjukkan gambar hasil dari penggunaan fitur ini:


Gambar diatas adalah SERP (Search Engine Result Page) untuk kata kunci "belajar yql", dimana hasil pertama adalah tulisan di blog ini menampilkan foto penulisnya (foto profil yang ada di akun Google+ ku) lengkap dengan kata-kata "oleh Nazir Arifin". Coba bandingkan dengan hasil kedua yang tidak memiliki foto penulisnya, keliatan membosankan kan. Setidaknya dengan fitur ini kamu bisa langsung narsis di halaman pencarian Google :).

Bisa saja kamu merasa ini cuma akal-akalan Google untuk meningkatkan penggunaan Google+ mungkin ada benarnya, tapi untuk tujuan optimasi penggunaan dan pemanfaatan Search Engine Google bagi blog atau websitemu maka penggunaan fitur ini sangat direkomendasikan (kita tahu hampir semua orang menggunakan Google untuk pencarian di internet). Dengan ini orang bisa langsung tahu siapa penulis dan foto profil dari penulis artikel cukup dari melihat hasil pencarian di Google.

Disini ada dua proses, yang pertama menentukan authorship markup-mu dan kedua memasang tag tertentu pada blog atau websitemu.

Buat Google Author Markup


1. Pastikan bahwa kamu sudah membuat akun di Google+ dan profilmu dapat dilihat oleh public. Buka akun Google+ > Profil -> Edit Profil (punyaku pakai bahasa Indonesia :D), geser kebawah sampai menemukan bagian "Penemuan profil", klik dan pastikan bahwa tanda cek disitu dicentang lalu tekan Simpan.
2. Trus lanjut kebawah disitu ada "Kontributor untuk", klik dan tambahkan blog atau websitemu seperti gambar berikut:



3. Sekarang sambungkan profil Google+ dengan situsmu. Salah satu caranya dengan menambahkan tombol G+ dan letakkan disitus atau blogmu (atau kamu juga bisa menggunakan teks di bagian footer jika tidak mau menggunakan tombol G+). Untuk membuat tombol G+ bisa dibuat disini: https://developers.google.com/+/plugins/badge/#profile-tag.
4. Jika kamu menggunakan blogger/blogspot maka kamu bisa menggunakan widget. Masukkan perintah HTML yang tersedia ke blog atau websitemu. Contoh kodenya:

<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<div class="g-plus" data-href="https://plus.google.com/{profileId}" data-width="100" data-height="69" rel="author"></div>

Pastikan kamu mengubah bagian {profileId} dengan angka yang ada di halaman profil Google+ mu (contohnya: https://plus.google.com/107344129806379926487). Bagian data-width dan data-height untuk menentukan lebar dan tinggi dari tombol G+ yang akan ditampilkan. Untuk nilainya sudah ditentukan disitu, untuk lebar: 100, 169, 170 dan 300 pixel. Sedangkan untuk tingginya adalah: 69, dan 131 pixel.

Selesai :D, untuk melihat apakah kamu berhasil menyambungkan blogmu dengan profil Google+ mu maka kamu bisa cek disini: http://www.google.com/webmasters/tools/richsnippets.



Jika semua berjalan baik maka kamu akan melihat tanda hijau "Terverifikasi" authorship markup. Demikian pembahasan ini semoga bermanfaat.

Sumber:

http://www.iblogzone.com/2011/08/how-to-google-authorship-markup-rel-author.html