DTE :]

Friday, April 10, 2020

Kompres dan Tata Ulang Kode CSS, HTML dan JavaScript Kalian dengan Alat Ini

Saya membuat proyek baru berupa situs web berisi kumpulan alat untuk mengompres kode HTML, CSS dan JavaScript secara daring. Saat ini sudah tersedia alat pengompres kode HTML, CSS, JavaScript dan JSON. Untuk ke depannya mungkin akan Saya tambahkan alat-alat kompresi yang lain. Halaman web alat dapat kamu kunjungi melalui tautan https://minify.js.org

Selain alat pengompres, alat untuk menata ulang kode-kode yang sudah dikompres juga tersedia. Saat ini sudah tersedia alat penata kode HTML, CSS, JavaScript dan JSON. Halaman web alat dapat kamu kunjungi melalui tautan https://tidy.js.org

Berikut ini adalah kode-kode pihak ke tiga yang Saya gunakan untuk membuat alat-alat tersebut:

Sebelumnya Saya pernah membuat situs web kumpulan alat serupa pada repositori https://github.com/taufik-nurrohman/mini-web-tools. Tapi dengan adanya situs web yang baru, repositori tersebut kemungkinan besar akan Saya arsipkan. Silakan beri komentar dan saran mengenai alat-alat ini, simpan tautan ke penanda buku, dan bagikan ke teman-teman yang lain kalau kamu merasa bahwa alat-alat ini bermanfaat untuk kamu dan untuk mereka. Terima kasih ♥

Labels: , , , , , ,

Sunday, May 31, 2015

Mengenal Virtual Web Server

Server lokal atau localhost atau virtual web server atau virtual web hosting merupakan server web yang bersifat offline. Ketika sebuah situs web yang asli bisa diakses dengan cara mengetik alamat seperti http://www.example.com, maka sebuah situs web lokal pada umumnya dapat diakses dengan cara mengetik alamat http://localhost. Server lokal digunakan sebagai alat bantu untuk membuat situs web secara offline tanpa koneksi internet. Di dalam sebuah aplikasi server lokal biasanya sudah terdapat beberapa fitur yang ada di dalam server web online yang ada di internet pada umumnya seperti PHPMyAdmin, PHP, MySQL dan Apache. Aplikasi yang paling sering digunakan —terutama untuk menangani berkas-berkas dengan ekstensi .php— adalah WAMPSERVER dan XAMPP.

Proses instalasi sangat mudah: Unduh salah satu aplikasi tersebut sesuai dengan tipe Sistem Operasi yang Anda pakai (32 bits atau 64 bits). Buka berkas hasil unduhan, kemudian akan muncul jendela bimbingan instalasi aplikasi, setelah itu tinggal klik next… next… next… saja, I agree with the term of service… dan seterusnya sampai muncul tombol Finish.

WampServer Logo

Sebagai contoh, di sini Saya menggunakan WAMPSERVER sebagai server lokal. Yang paling penting untuk Anda perhatikan adalah ada pada folder www, selebihnya bisa Anda abaikan terlebih dahulu sebagai tahap awal latihan. Masing-masing aplikasi server lokal memiliki nama folder publik mereka sendiri. Sebagai contoh, XAMPP memiliki folder publik bernama htdocs. Tapi secara umum Anda akan dapat menemukan folder-folder publik pada aplikasi-aplikasi semacam ini dengan nama www, public_html dan htdocs. Ini juga akan Anda temukan pada server web yang asli, jadi Anda tidak perlu bingung.

Klik ikon WampServer yang ada di desktop komputer Anda, atau kalau tidak ada Anda bisa mencari programnya melalui tombol Start. Setelah itu akan muncul kotak dialog User Account Control. Klik tombol Yes. Lihat daftar ikon pada Taskbar atau Superbar di sebelah kanan bawah, di situ seharusnya akan muncul ikon WAMPSERVER berwarna merah, yang secara normal seharusnya akan berubah warna menjadi jingga dan kemudian menjadi hijau secara perlahan.

Buka peramban favorit Anda, lalu akses alamat http://localhost. Jika muncul halaman seperti ini, maka itu artinya proses instalasi telah berhasil dilakukan dan server lokal Anda sudah siap untuk digunakan:

Menu WampServer
Halaman awal server WAMP.

www

Kembali ke folder www. Jika sebelumnya Anda tidak mengubah-ubah pengaturan lokasi folder www pada saat instalasi, maka folder tersebut seharusnya akan terletak pada lokasi C:\wamp\www. Anda bisa dengan mudah mengakses lokasinya melalui menu:

Menu WampServer
Menu server WAMP.

Anda bisa membuang semua berkas yang ada di dalamnya, tapi untuk berjaga-jaga, Anda bisa membiarkan mereka seperti apa adanya sampai Anda cukup percaya diri untuk membuangnya. Di dalam folder ini Anda bisa memasukkan berkas-berkas web Anda untuk ditampilkan di layar peramban nantinya. Sebagai contoh, Anda membuat berkas bernama tes-halaman.php pada folder ini, maka Anda akan bisa mengakses berkas tersebut melalui alamat http://localhost/tes-halaman.php

Sebenarnya Anda bisa melakukan hal ini di lokasi mana saja di folder komputer Anda, hanya bedanya, Anda tidak akan bisa menerjemahkan kode-kode Hypertext Preprocessor menjadi HTML jika berkas tersebut tidak ditempatkan di dalam folder www. Misalnya Anda membuat berkas tes-halaman.php di desktop, maka Anda bisa membuka berkas tersebut dengan cara klik-kanan pada ikon berkas dan kemudian pilih Open with » Firefox (misalnya). Sehingga pada address bar akan tampil alamat seperti file:///C:/Users/DTE/Desktop/tes-halaman.php

Seperti itu saja dulu. Selanjutnya Anda bisa mencoba belajar bahasa pemrograman PHP atau sekedar mengetes CMS yang Anda unduh di dalam folder ini. Cukup salin dan tempel berkas saja seperti biasa. Target Saya membuat tutorial ini sebenarnya adalah untuk memperkenalkan CMS Mecha pada pembaca, tapi rilis versi stabil yang terakhir masih belum ada dan masih dalam tahap pengetesan.

Labels: , ,

Monday, February 2, 2015

JavaScript Spoiler

JavaScript Spoiler
Spoiler

Ini adalah versi mentah dari plugin spoiler pada CMS Mecha. Anda bisa menerapkannya di Blogger atau di web mana saja dengan cara mengikuti langkah-langkah berikut.

Masuklah ke halaman editor HTML Template Anda. Pertama-tama salin kode di bawah ini dan letakkan di atas kode </head>:

<script>document.documentElement.className += ' spoiler-js';</script>

Setelah itu salin kode CSS ini dan letakkan di atas kode ]]></b:skin> atau </style>:

.spoiler {
  background-color:darkslategray;
  color:white;
  padding:.15384615384615385em;
  margin:1em 0;
}

.spoiler-toggle,
.spoiler-toggle:focus,
.spoiler-toggle:hover,
.spoiler-toggle:active {
  display:block;
  margin:0;
  padding:0 1.2em 0 .6em;
  height:2em;
  font:normal normal 100%/2em Helmet,FreeSans,Sans-Serif;
  color:inherit;
  text-decoration:none;
  outline:none;
  position:relative;
  overflow:hidden;
  white-space:nowrap;
  text-overflow:ellipsis;
  cursor:pointer;
}

.spoiler-toggle:before {
  content:"";
  display:block;
  float:right;
  width:0;
  height:0;
  border-width:.3076923076923077em .3076923076923077em 0;
  border-style:solid;
  border-color:white transparent transparent;
  margin:.9230769230769231em -.6em 0 0;
}

.spoiler-content {
  padding:1em;
  background-color:white;
  color:#333;
}

.spoiler-state-expanded .spoiler-toggle {padding-bottom:inherit}

.spoiler-state-expanded .spoiler-toggle:before {
  border-width:0 .3076923076923077em .3076923076923077em;
  border-color:transparent transparent white;
  margin-top:.8461538461538461em;
}

.spoiler-state-expanded .spoiler-content + .spoiler-toggle {
  padding-top:inherit;
  padding-bottom:0;
}

.spoiler-state-disabled .spoiler-toggle {
  cursor:default;
  cursor:not-allowed;
}

.spoiler-state-disabled .spoiler-toggle:before,
.spoiler-js .spoiler-state-collapsed .spoiler-content {display:none}

.spoiler-primary {background-color:steelblue}
.spoiler-success {background-color:mediumseagreen}
.spoiler-info {background-color:skyblue}
.spoiler-warning {background-color:sandybrown}
.spoiler-danger {background-color:salmon}

Terakhir, salin kode JavaScript ini dan letakkan di atas </body>:

<script>
//<![CDATA[

// http://www.dte.web.id

(function(w, d) {
  var panel = d.getElementsByClassName('spoiler');
  if (!panel) return;
  for (var i = 0, len = panel.length; i < len; ++i) {
    if (!panel[i].id) panel[i].id = 'spoiler-' + (i + 1);
  }
  function toggleSpoiler(elem, index) {
    var toggle = d.createElement('a'),
        toggleText = (elem[index].getAttribute('data-toggle-text') || '&nbsp;').split(' | '),
        togglePlacement = elem[index].getAttribute('data-toggle-placement') && elem[index].getAttribute('data-toggle-placement') !== 'bottom' ? elem[index].getAttribute('data-toggle-placement') : 'bottom';
    toggleText.push(toggleText[0]);
    toggle.className = 'spoiler-toggle';
    toggle.href = '#' + elem[index].id;
    toggle.innerHTML = toggleText[/(^| )spoiler-state-collapsed( |$)/.test(elem[index].className) ? 0 : 1];
    toggle.onclick = function() {
      var target = this.parentNode,
          isExpanded = /(^| )spoiler-state-expanded( |$)/.test(target.className),
          isConnected = target.getAttribute('data-connection');
      if (/(^| )spoiler-state-disabled( |$)/.test(target.className)) return false;
      target.className = isExpanded ? target.className.replace(/(^| )spoiler-state-expanded( |$)/, '$1spoiler-state-collapsed$2') : target.className.replace(/(^| )spoiler-state-collapsed( |$)/, '$1spoiler-state-expanded$2');
      this.innerHTML = toggleText[isExpanded ? 0 : 1];
      if (isConnected) {
        for (var i = 0, len = elem.length; i < len; ++i) {
          var isConnectedTo = elem[i].getAttribute('data-connection'),
              toggleTextSibling = (elem[i].getAttribute('data-toggle-text') || '&nbsp;').split(' | '),
              togglePlacementSibling = elem[i].getAttribute('data-toggle-placement') && elem[i].getAttribute('data-toggle-placement') !== 'bottom' ? elem[i].getAttribute('data-toggle-placement') : 'bottom';
          if (isConnectedTo && isConnected === isConnectedTo && target.id !== elem[i].id) {
            elem[i].className = elem[i].className.replace(/(^| )spoiler-state-expanded( |$)/, '$1spoiler-state-collapsed$2');
            elem[i].children[togglePlacementSibling === 'bottom' ? 1 : 0].innerHTML = toggleTextSibling[0];
          }
        }
      }
      return false;
    };
    toggle.onmousedown = false;
    elem[index].insertBefore(toggle, togglePlacement == 'bottom' ? null : elem[index].firstChild);
  }
  for (var i = 0, len = panel.length; i < len; ++i) {
    toggleSpoiler(panel, i);
  }
})(window, document);
//]]>
</script>

Klik tombol Simpan Templat.

Penggunaan

Semua konfigurasi hanya didasarkan pada atribut-atribut di dalam HTML spoiler.

Dasar

Sebuah spoiler sederhana dapat dibuat dengan menyisipkan kode HTML ini ke dalam posting. Pastikan Anda sedang berada pada mode HTML, dan bukannya berada pada mode Tulis:

<div class="spoiler spoiler-state-collapsed" data-toggle-text="Spoiler">
  <div class="spoiler-content">Konten di sini…</div>
</div>

Terbuka secara Default

Ganti kelas spoiler-state-collapsed menjadi spoiler-state-expanded untuk membuat spoiler menjadi terbuka secara default:

<div class="spoiler spoiler-state-expanded" data-toggle-text="Spoiler">
  <div class="spoiler-content">Konten di sini…</div>
</div>

Modifikasi Teks pada Tombol Toggle

Tambahkan atribut data-toggle-text untuk menambahkan teks pada tombol. Pisahkan teks tombol menjadi dua bagian dengan sebuah “ | ” untuk membuat tombol berubah status secara bergantian ketika panel spoiler terbuka dan tertutup:

<div class="spoiler spoiler-state-collapsed" data-toggle-text="Buka Spoiler | Tutup Spoiler">
  <div class="spoiler-content">Konten di sini…</div>
</div>

Mengubah Posisi Tombol

Secara normal, tombol toggle akan ditempatkan setelah panel. Anda bisa mengubah posisinya menjadi sebelum panel dengan cara menambahkan atribut data-toggle-placement dengan nilai sebagai top:

<div class="spoiler spoiler-state-collapsed" data-toggle-placement="top">
  <div class="spoiler-content">Konten di sini…</div>
</div>

Kelas Kustom

Kelas kustom terinspirasi dari Twitter Bootstrap:

<div class="spoiler spoiler-default spoiler-state-collapsed" data-toggle-text="Default">
  <div class="spoiler-content">Konten di sini…</div>
</div>

<div class="spoiler spoiler-primary spoiler-state-collapsed">
  <div class="spoiler-content">Konten di sini…</div>
</div>

<div class="spoiler spoiler-success spoiler-state-collapsed">
  <div class="spoiler-content">Konten di sini…</div>
</div>

<div class="spoiler spoiler-info spoiler-state-collapsed">
  <div class="spoiler-content">Konten di sini…</div>
</div>

<div class="spoiler spoiler-warning spoiler-state-collapsed">
  <div class="spoiler-content">Konten di sini…</div>
</div>

<div class="spoiler spoiler-danger spoiler-state-collapsed">
  <div class="spoiler-content">Konten di sini…</div>
</div>

Efek Akordion

Tambahkan atribut data-connection untuk mengaitkan antara panel yang satu dengan panel yang lainnya yang juga memiliki atribut data-connection dengan nilai yang sama. Nilai bisa berupa apa saja:

<div class="spoiler spoiler-state-expanded" data-toggle-text="Panel 1" data-connection="A">
  <div class="spoiler-content">Konten panel 1.</div>
</div>

<div class="spoiler spoiler-state-collapsed" data-toggle-text="Panel 2" data-connection="A">
  <div class="spoiler-content">Konten panel 2.</div>
</div>

<div class="spoiler spoiler-state-collapsed" data-toggle-text="Panel 3" data-connection="A">
  <div class="spoiler-content">Konten panel 3.</div>
</div>

Nonaktif

Untuk menonaktifkan spoiler, cukup tambahkan kelas spoiler-state-disabled:

<div class="spoiler spoiler-state-collapsed spoiler-state-disabled">
  <div class="spoiler-content">Konten di sini…</div>
</div>

Demo selengkapnya bisa Anda lihat di sini:

Lihat Demo

Pengguaan spoiler ini kelihatannya memang sedikit rumit jika dilihat dari segi penulisan markup HTML. Mungkin beberapa dari kalian lebih menginginkan markup yang sederhana seperti sebuah elemen <div> dengan ID spoiler-1 dan sebuah tombol dengan atribut onclick bernilai toggleSpoiler('spoiler-1'). Tapi ini adalah resiko yang akan selalu muncul pada semua alat, widget dan plugin dengan fitur yang cukup banyak. Terdapat arsitektur dan pola tersendiri di dalamnya yang tidak bisa dilepaskan maupun disederhanakan begitu saja.

Labels: , ,

Saturday, January 10, 2015

Unduh Berkas Presentasi Perkenalan HTML untuk Pemula

Aslinya ini adalah tugas bebas yang Saya dapat dari kampus, akan tetapi karena Saya merasa berkas ini cukup bermanfaat jadi Saya bagikan saja untuk kalian.

Labels: , , ,

Sunday, August 31, 2014

Tag Facebook Open Graph untuk Blogspot

<meta property='og:title' expr:content='data:blog.pageTitle'/>
<b:if cond='data:blog.pageType == &quot;item&quot;'>
  <meta property='og:type' content='article'/>
<b:else/>
  <meta property='og:type' content='website'/>
</b:if>
<meta property='og:url' expr:content='data:blog.canonicalUrl'/>
<!-- Large image, original size -->
<b:if cond='data:blog.postImageUrl'>
  <meta property='og:image' expr:content='data:blog.postImageUrl'/>
<b:else/>
  <!-- Thumbnail image, 72 × 72 pixels -->
  <b:if cond='data:blog.postImageThumbnailUrl'>
    <meta property='og:image' expr:content='data:blog.postThumbnailUrl'/>
  <b:else/>
    <!-- Default, no image. Use favicon or your own image URL -->
    <meta property='og:image' expr:content='data:blog.blogspotFaviconUrl'/>
  </b:if>
</b:if>
<b:if cond='data:blog.metaDescription'>
  <meta property='og:description' expr:content='data:blog.metaDescription'/>
<b:else/>
  <meta property='og:description' content='{{DEFAULT SITE DESCRIPTION GOES HERE}}'/>
</b:if>
<meta property='og:site_name' expr:content='data:blog.title'/>
<!--

Optional. Read more → Insights for your Facebook App, Domain or Page<meta property='fb:admins' content='{{FB ADMINS}}'/>
<meta property='fb:app_id' content='{{APP ID}}'/>

-->

Lainnya

Labels: , ,

Thursday, May 30, 2013

Aksesibilitas pada Soal Pilihan Ganda Online

Example of Accessible QA Form

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

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

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

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

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

Selalu Ingat untuk Menambahkan Elemen Label

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

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

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

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

Kursor

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

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

Efek Timbal Balik

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

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

Demonstrasi

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

HTML

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

CSS

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

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

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

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

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

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

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

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

jQuery

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

Lihat Demo

Kesimpulan

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

Labels: , , ,

Thursday, May 23, 2013

Framework CSS · Utamakan Konsistensi Tampilan Artikel Sebelum Layout

CSS Framework

Yang Saya maksudkan di sini adalah, jadikan tampilan artikel sebagai prioritas utama sebelum memulai pondasi desain/rancangan tema/template. Mengingat kebiasaan buruk yang sering terjadi adalah kita membentuk hasil jadinya terlebih dahulu kemudian baru merancang tampilan-tampilan paragraf, kuota dan blok kode. Padahal, dengan merancang elemen-elemen kecil dan umum tersebut terlebih dahulu, kita bisa memastikan bahwa tampilan akhir nantinya akan menjadi lebih konsisten.

Merancang penampilan secara keseluruhan dan melanjutkannya dengan merancang tampilan elemen artikel hanya akan menambah waktu kerja kita menjadi dua kali lipat lebih lama dan lebih rumit tanpa kita sadari. Sebagai contoh, saat kita merancang tampilan posting, saat itu kita juga akan menentukan tampilan judulnya. Setelah itu kita akan merancang tampilan sidebar dan footer, kemudian juga akan menentukan tampilan judulnya dan seterusnya:

Contoh Buruk

/* posting */
.post {
  font-family:Arial,Sans-Serif;
  font-size:12px;
  color:#333;
}

.post h2 {
  font-size:30px;
  font-weight:bold;
  margin-bottom:15px;
  color:#3399ff;
}

/* sidebar */
.sidebar {
  float:right;
  width:200px;
  overflow:hidden;
  word-wrap:break-word;
  font-family:Arial,Sans-Serif;
  color:#222;
}

.sidebar h2 {
  font-weight:normal;
  font-size:12px;
  text-transform:uppercase;
  margin-bottom:15px;
}

/* footer */
.footer {
  background-color:#2f2f2f;
  font-family:Georgia,Serif;
  font-size:13px;
  color:#666;
}

.footer h2 {
  font-weight:normal;
  font-size:20px;
  color:#f5f5f5;
}

Terlalu banyak pekerjaan hanya untuk membuat beberapa blok area saja. Seharusnya pekerjaan ini bisa menjadi lebih singkat apabila kita merancang framework elemen-elemen artikel terlebih dahulu secara global. Sudah ada beberapa framework yang tersedia untuk mengatasi kebiasaan buruk ini, misalnya Normalize dan HTML5 Boilerplate. Tapi di sini kita akan mencoba untuk membuatnya sendiri. Dimulai dengan CSS reset.

Merancang Framework CSS

CSS Reset

CSS ini akan menormalkan semua tampilan elemen HTML —kecuali elemen-elemen formulir— menjadi seragam/normal. Dimulai dari ukuran, warna, margin, padding, dimensi dan juga ketebalannya. Mengawali rancangan elemen artikel dengan CSS reset akan mempermudah kita dalam merancang tampilan elemen-elemen HTML setelah ini:

/* http://meyerweb.com/eric/tools/css/reset/
   v2.0 | 20110126
   License: none (public domain)
*/
html,body,div,span,
applet,object,iframe,
h1,h2,h3,h4,h5,h6,
p,blockquote,pre,
a,abbr,acronym,address,
big,cite,code,del,dfn,
em,img,ins,kbd,q,
s,samp,small,strike,strong,
sub,sup,tt,
var,b,u,i,center,
dl,dt,dd,
ol,ul,li,
fieldset,form,label,legend,
table,caption,tbody,tfoot,thead,tr,th,td,
article,aside,canvas,details,embed,
figure,figcaption,
footer,header,hgroup,menu,nav,
output,ruby,
section,summary,
time,mark,audio,video {
  margin:0;
  padding:0;
  border:0;
  font-size:100%;
  font:inherit;
  vertical-align:baseline;
}

/* HTML5 display-role reset for older browsers */
article,aside,details,
figcaption,figure,footer,
header,hgroup,menu,nav,section {
  display:block;
}

body {
  line-height:1;
}

ol,ul {
  list-style:none;
}

blockquote,q {
  quotes:none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
  content:'';
  content:none;
}

table {
  border-collapse:collapse;
  border-spacing:0;
}

Elemen <BODY>

Berikutnya kita atur ukuran huruf, tipe huruf, line-height dan warna huruf secara global pada elemen <body>:

body {
  /* `font-style:normal`,
     `font-weight:normal`,
     `font-size:13px`,
     `line-height:1.4em`,
     `font-family:Arial,Sans-Serif` */
  font:normal normal .8125em/1.4 Arial,Sans-Serif;
  background-color:white; /* warna latar secara global */
  color:#333; /* warna huruf secara global */
}

Huruf Tebal, Huruf Miring dan Elemen-Elemen Kecil Lainnya

Karena tampilan elemen HTML sudah diatur ulang oleh CSS reset, maka kita perlu mengatur beberapa tampilan elemen menjadi seperti semula:

/* huruf tebal */
strong,b {
  font-weight:bold;
}

/* citation & huruf miring (italic + emphasis) */
cite,em,i {
  font-style:italic;
}

/* tautan */
a {
  text-decoration:none;
}

a:hover {
  text-decoration:underline;
}

/* Internet Explorer akan menambahkan border pada gambar
   yang diliputi oleh tautan */
a img {
  border:none;
}

/* abbreviation & acronym */
abbr,
acronym {
  border-bottom:1px dotted;
  cursor:help;
}

/* superscript & subscript */
sup,
sub {
  vertical-align:baseline;
  position:relative;
  top:-.4em;
  font-size:86%;
}

sub {
  top:.4em;
}

/* huruf kecil */
small {
  font-size:86%;
}

/* tombol keyboard */
kbd {
  font-size:80%;
  border:1px solid #999;
  padding:2px 5px;
  border-bottom-width:2px;
  border-radius:3px;
}

/* penanda teks */
mark {
  background-color:#ffce00;
  color:black;
}

Margin Paragraf

Paragraf membutuhkan kerenggangan antara teks paragraf yang satu dengan yang lainnya. Begitu pula elemen-elemen lain yang biasa menyertainya seperti kuota, tabel, figur, formulir, daftar dan blok kode:

p,blockquote,pre,
table,figure,hr,form,
ol,ul,dl {
  margin:1.5em 0;
}

Elemen Heading

Atur elemen heading dengan line-height menjadi normal dan huruf menjadi tebal. Tentukan juga margin heading secara global sebelum kemudian kita melanjutkannya dengan menentukan ukuran elemen heading sesuai dengan level/tingkatannya:

h1,h2,h3,h4,h5,h6 {
  font-weight:bold;
  line-height:normal;
  margin:1.5em 0 0;
}

h1 {font-size:200%}
h2 {font-size:180%}
h3 {font-size:160%}
h4 {font-size:140%}
h5 {font-size:120%}
h6 {font-size:100%}

Elemen Daftar

Jangan biarkan elemen daftar menjadi terlalu sejajar dengan paragraf karena pada umumnya itu hanya akan membuat mata kita menjadi merasa tidak nyaman dan tertekan. Posisikan elemen daftar menjadi sedikit menjorok ke depan untuk menciptakan kesan istirahat/fokus:

/* ordered, unordered list & description list */
ol,ul,dl {margin-left:3em}

ol {list-style:decimal outside} /* atur ulang `list-style` pada elemen `<ol>` */
ul {list-style:disc outside} /* atur ulang `list-style` pada elemen `<ul>` */
li {margin:.5em 0} /* beri sedikit jarak atas dan bawah pada elemen `<li>` untuk item daftar dengan konten yang panjang */

dt {font-weight:bold}
dd {margin:0 0 .5em 2em}

Elemen Formulir

Biasanya ini tidak terlalu penting. Tetapi setidaknya samakanlah tipe dan ukuran huruf sesuai dengan huruf pada elemen induknya. Mengenai tampilan selanjutnya seperti warna latar dan efek :hover bisa ditentukan nanti setelah framework selesai dibuat:

input,
button,
select,
textarea {
  font:inherit;
  font-size:100%;
  line-height:normal;
  vertical-align:baseline;
}

/* mengeset `box-sizing` menjadi `border-box` pada `<textarea>` untuk mengatasi masalah
   pengguna yang sering kesulitan menentukan lebar akurat
   pada elemen ini menjadi `100%` ketika menggunakan logika box-model yang lama */
textarea {
  display:block;
  -webkit-box-sizing:border-box;
  -moz-box-sizing:border-box;
  box-sizing:border-box;
}

Blok Kode dan Kuota

<pre> dan <blockquote> biasanya mendapatkan perlakuan khusus mengingat elemen ini biasa kita gunakan untuk menyatakan hal-hal yang penting. Blok kode digunakan untuk menyatakan kode yang perlu dicatat/dipahami dan kuota digunakan untuk menyatakan teks yang perlu diingat atau direnungkan:

pre,
code {
  font-family:"Courier New",Courier,Monospace;
  color:inherit;
}

/* jika perlu tentukan juga warna latar dan huruf */
pre {
  white-space:pre;
  word-wrap:normal;
  overflow:auto;
}

blockquote {
  margin-left:2em;
  margin-right:2em;
  border-left:4px solid #ccc;
  padding-left:1em;
  font-style:italic;
}

Tabel

Seperti yang pernah Saya nyatakan pada tutorial pembuatan tabel dengan HTML, disarankan untuk menentukan border dan padding pada tabel yang memiliki atribut border=1 saja demi keamanan:

table[border="1"] th,
table[border="1"] td,
table[border="1"] caption {
  border:1px solid;
  padding:.5em 1em;
  text-align:left;
  vertical-align:top;
}

th {
  font-weight:bold;
}

table[border="1"] caption {
  border:none;
  font-style:italic;
}

Hasil Akhir

/* http://meyerweb.com/eric/tools/css/reset/
   v2.0 | 20110126
   License: none (public domain)
*/
html,body,div,span,
applet,object,iframe,
h1,h2,h3,h4,h5,h6,
p,blockquote,pre,
a,abbr,acronym,address,
big,cite,code,del,dfn,
em,img,ins,kbd,q,
s,samp,small,strike,strong,
sub,sup,tt,
var,b,u,i,center,
dl,dt,dd,
ol,ul,li,
fieldset,form,label,legend,
table,caption,tbody,tfoot,thead,tr,th,td,
article,aside,canvas,details,embed,
figure,figcaption,
footer,header,hgroup,menu,nav,
output,ruby,
section,summary,
time,mark,audio,video {
  margin:0;
  padding:0;
  border:0;
  font-size:100%;
  font:inherit;
  vertical-align:baseline;
}

/* HTML5 display-role reset for older browsers */
article,aside,details,
figcaption,figure,footer,
header,hgroup,menu,nav,section {
  display:block;
}

body {
  line-height:1;
}

ol,ul {
  list-style:none;
}

blockquote,q {
  quotes:none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
  content:'';
  content:none;
}

table {
  border-collapse:collapse;
  border-spacing:0;
}

/* ===============
   FRAMEWORK START
   =============== */
body {
  font:normal normal .8125em/1.4 Arial,Sans-Serif;
  background-color:white;
  color:#333;
}

strong,b {
  font-weight:bold;
}

cite,em,i {
  font-style:italic;
}

a {
  text-decoration:none;
}

a:hover {
  text-decoration:underline;
}

a img {
  border:none;
}

abbr,
acronym {
  border-bottom:1px dotted;
  cursor:help;
}

sup,
sub {
  vertical-align:baseline;
  position:relative;
  top:-.4em;
  font-size:86%;
}

sub {
  top:.4em;
}

small {
  font-size:86%;
}

kbd {
  font-size:80%;
  border:1px solid #999;
  padding:2px 5px;
  border-bottom-width:2px;
  border-radius:3px;
}

mark {
  background-color:#ffce00;
  color:black;
}

p,blockquote,pre,
table,figure,hr,form,
ol,ul,dl {
  margin:1.5em 0;
}

hr {
  height:1px;
  border:none;
  background-color:#666;
}

h1,h2,h3,h4,h5,h6 {
  font-weight:bold;
  line-height:normal;
  margin:1.5em 0 0;
}

h1 {font-size:200%}
h2 {font-size:180%}
h3 {font-size:160%}
h4 {font-size:140%}
h5 {font-size:120%}
h6 {font-size:100%}

ol,ul,dl {margin-left:3em}
ol {list-style:decimal outside}
ul {list-style:disc outside}
li {margin:.5em 0}

dt {font-weight:bold}
dd {margin:0 0 .5em 2em}

input,
button,
select,
textarea {
  font:inherit;
  font-size:100%;
  line-height:normal;
  vertical-align:baseline;
}

textarea {
  display:block;
  -webkit-box-sizing:border-box;
  -moz-box-sizing:border-box;
  box-sizing:border-box;
}

pre,
code {
  font-family:"Courier New",Courier,Monospace;
  color:inherit;
}

pre {
  white-space:pre;
  word-wrap:normal;
  overflow:auto;
}

blockquote {
  margin-left:2em;
  margin-right:2em;
  border-left:4px solid #ccc;
  padding-left:1em;
  font-style:italic;
}

table[border="1"] th,
table[border="1"] td,
table[border="1"] caption {
  border:1px solid;
  padding:.5em 1em;
  text-align:left;
  vertical-align:top;
}

th {
  font-weight:bold;
}

table[border="1"] caption {
  border:none;
  font-style:italic;
}

Sampai di sini Saya rasa sudah cukup untuk dijadikan sebagai dasar. Setelah ini Anda bisa melanjutkan untuk membuat kelas-kelas produktif seperti .hidden, .visually-hidden, .btn dan yang lainnya untuk keperluan rancangan tingkat lanjut:

.hidden,[hidden] {
  display:none;
}

.invisible {
  visibility:hidden;
}

.visually-hidden {
  position:absolute !important;
  overflow:hidden;
  clip:rect(0px 0px 0px 0px);
  clip:rect(0px,0px,0px,0px);
  height:1px;
  width:1px;
  margin:-1px 0 0;
  padding:0;
  border:0;
}

.clear {
  display:block;
  clear:both;
}

.clearfix:before,
.clearfix:after {
  content:"";
  display:table;
}

.clearfix:after {
  clear:both;
}

.clearfix {
  *zoom:1;
}

.pull-left {
  float:left;
}

.pull-right {
  float:right;
}

.centered {
  clear:both;
  display:block;
  text-align:center;
  margin-left:auto;
  margin-right:auto;
}

.text-center {
  text-align:center;
}

.text-left {
  text-align:left;
}

.text-right {
  text-align:right;
}

.text-justify {
  text-align:justify;
}

.btn {
  color:white;
  background-color:black;
  /* ... */
}

.btn:hover {
  /* ... */
}

.btn:active {
  /* ... */
}

Beberapa nama kelas di atas akan sangat mudah Anda temui pada framework HTML5 Boilerplate dan Twitter Bootstrap (Twitter Bootstrap juga memakai HTML5 Boilerplate). Anda akan mengetahui fungsi-fungsi kelas tersebut, mengapa kelas tersebut dibuat dan mengapa kelas-kelas tersebut menjadi semacam “standar” saat Anda mempelajarinya.

Beralih ke Framework Buatan Sendiri

Untuk mempercepat pekerjaan, yang terpenting sebenarnya adalah framework. Namun jika Anda tidak mengerti apa dan bagaimana framework itu dibuat dan digunakan, maka hasil akhirnya nanti akan sama saja. Memulai membuat framework sendiri Saya pikir jauh lebih baik dibandingkan hanya sekedar menyalin dan menempel kode dari framework lain yang sudah ada. Mengikuti dan mempelajari bagaimana mereka menciptakan framework seharusnya lebih diutamakan dibandingkan hanya sekedar memakainya. Karena dengan mempelajari bagaimana sebuah framework terbentuk, maka dari situ Anda bisa lebih cerdas di dalam mencontoh dan menyaring apa-apa saja yang sebenarnya diperlukan dan apa saja yang sebenarnya tidak diperlukan menurut kebutuhan Anda saat itu untuk keperluan yang lebih spesifik dan efisien tentunya:

Lihat Demo

Labels: , , ,

Saturday, March 23, 2013

Print/Mencetak Sebagian Halaman Saja dengan JavaScript

Gambar untuk dialog pencetakan pada Google Chrome
Mencetak sebagian halaman dengan JavaScript

Berbeda dengan dasar window.print() yang akan mencetak keseluruhan halaman, fungsi ini akan mencetak halaman pada bagian-bagian tertentu saja. Cara kerjanya adalah fungsi ini akan mencetak duplikat konten area di dalam iframe pencetakan.

Dua buah elemen, yaitu <textarea> dan <iframe> dibuat untuk keperluan ini. Area teks digunakan untuk menyimpan kode CSS pencetakan, sedangkan iframe digunakan untuk menampung salinan bagian halaman yang ingin dicetak. Saat salinan bagian halaman tersebut sudah masuk ke dalam iframe yang kita sembunyikan wujudnya, hal yang perlu kita lakukan selanjutnya adalah mencetak konten iframe tersebut, bukan halaman yang sedang aktif:

<textarea id="printing-css" style="display:none;">.no-print{display:none}</textarea>
<iframe id="printing-frame" name="print_frame" src="about:blank" style="display:none;"></iframe>
<script>
//<![CDATA[
function printDiv(elementId) {
    var a = document.getElementById('printing-css').value;
    var b = document.getElementById(elementId).innerHTML;
    window.frames["print_frame"].document.title = document.title;
    window.frames["print_frame"].document.body.innerHTML = '<style>' + a + '</style>' + b;
    window.frames["print_frame"].window.focus();
    window.frames["print_frame"].window.print();
}
//]]>
</script>

Aktivasi bisa dilakukan dengan cara memicu fungsi printDiv(elementId) pada tautan atau tombol, dimana elementId adalah ID dari area khusus yang ingin dicetak:

<a class="no-print" href="javascript:printDiv('area-1');">Print</a>

...

<div id="area-1">Teks ini akan tercetak di kertas...</div>
<div id="area-2">Tapi tidak untuk teks ini.</div>

Lihat Demo

Kode CSS pencetakan yang digunakan Saya sarankan adalah kode CSS yang pernah Saya tuliskan di sini, untuk memastikan agar tampilan halaman yang dicetak tertata dengan rapi. Atau kosongkan saja textarea tersebut dan biarkan User Agent Stylesheet pada masing-masing peramban menangani tampilan elemen yang ada.

Alternatif lain, Anda juga bisa menggunakan CSS eksternal jika Anda merasa bahwa textarea tanpa makna di atas hanya akan mengganggu kebersihan kode sumber web Anda:

<iframe id="printing-frame" name="print_frame" src="about:blank" style="display:none;"></iframe>
<script>
//<![CDATA[
function printDiv(elementId) {
    var a = "/path/to/printing-css.css";
    var b = document.getElementById(elementId).innerHTML;
    window.frames["print_frame"].document.title = document.title;
    window.frames["print_frame"].document.body.innerHTML = '<link rel="stylesheet" href="' + a + '">' + b;
    window.frames["print_frame"].window.focus();
    window.frames["print_frame"].window.print();
}
//]]>
</script>

Hasilnya akan terlihat jelas pada peramban Google Chrome yang notabene memiliki komunikasi pencetakan halaman yang berbeda dengan peramban lainnya.

Labels: , , ,

Monday, February 11, 2013

Input Teks dengan Ikon Pembersih

Text Input with Clear Button

Pada peramban WebKit seperti Google Chrome dan Safari, sebuah elemen input bertipe search memiliki kemampuan untuk menampilkan ikon/tombol pembersih kecil di samping input teks jika kita telah mengetikkan sesuatu di dalamnya. Tapi tidak pada peramban yang lain. Terkadang kita merasa butuh dan menyukai fitur itu, dan berharap bisa bekerja pada semua peramban.

Kita bisa menggunakan markup ekstra dan sedikit JavaScript untuk menciptakan rekayasa seperti itu. Tapi untuk memastikan tampilannya polos, gunakan elemen input bertipe text, bukan search:

HTML

<form id="search-form" action="/search" method="get">
    <span class="text-input-wrapper">
        <input type="text" name="q" size="18"><span title="Clear">&times;</span>
    </span>
    <input type="submit" value="Submit">
</form>

CSS

.text-input-wrapper {
  border:1px solid;
  background-color:white;
  padding:1px 6px 1px 1px;
  display:inline-block;
}

.text-input-wrapper input {
  border:none;
  background:none;
  outline:none;
  padding:0 0;
  margin:0 0;
  font:inherit;
}

.text-input-wrapper span {
  cursor:pointer;
  color:blue;
  font-weight:bold;
  visibility:hidden;
}

JavaScript

(function() {
    var searchForm = document.getElementById('search-form'),
        textInput = searchForm.q,
        clearBtn = textInput.nextSibling;
    textInput.onkeyup = function() {
        // Show the clear button if text input value is not empty
        clearBtn.style.visibility = (this.value.length) ? "visible" : "hidden";
    };
    // Hide the clear button on click, and reset the input value
    clearBtn.onclick = function() {
        this.style.visibility = "hidden";
        textInput.value = "";
    };
})();

Demo

Labels: , , ,

Wednesday, January 30, 2013

Membuat Tabel dengan HTML

Tutorial ini akan menjelaskan langkah-langkah singkat mengenai cara membuat tabel dengan HTML. Anda akan diberi beberapa penjelasan mengenai kerangka HTML tabel dari yang paling sederhana hingga menuju langkah-langkah modifikasi tampilan.

Lihat Semua Demo

Lihat demo-demo tabelnya terlebih dahulu:

Lihat Demo

Kerangka Tabel Paling Sederhana

Sebuah tabel sederhana terdiri dari elemen <table> yang diisi dengan beberapa <tr>, dimana setiap <tr> akan berisi beberapa <td>. <table> adalah table, <tr> adalah table row dan <td> adalah table data:

<table>
    <tr><td>1.1</td><td>1.2</td><td>1.3</td></tr>
    <tr><td>2.1</td><td>2.2</td><td>2.3</td></tr>
</table>

Header Tabel

Header tabel terbentuk dari elemen <th> (table header). Secara normal, tampilan teks di dalam header tabel akan secara otomatis bercetak tebal dan tersusun rata tengah:

<table>
    <tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
    <tr><td>1.1</td><td>1.2</td><td>1.3</td></tr>
    <tr><td>2.1</td><td>2.2</td><td>2.3</td></tr>
</table>

Menambahkan Border

tambahkan atribut border dengan nilai bukan 0 untuk menampilkan border pada tabel:

<table>
    <tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
    <tr><td>1.1</td><td>1.2</td><td>1.3</td></tr>
    <tr><td>2.1</td><td>2.2</td><td>2.3</td></tr>
</table>

Atribut ini sebenarnya tidak begitu penting, karena akan lebih efektif jika kita menggunakan untuk mengeset border pada tabel.

Caption/Judul Tabel

Tambahkan elemen <caption> tepat setelah kode <table> sebagai judul tabel:

<table>
    <caption>Judul Tabel</caption>
    <tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
    <tr><td>1.1</td><td>1.2</td><td>1.3</td></tr>
    <tr><td>2.1</td><td>2.2</td><td>2.3</td></tr>
</table>

Menggabungkan Sel-Sel Tabel (Merge Cell)

Ada dua atribut yang bisa Anda gunakan, yaitu colspan untuk menggabungkan kolom tabel dan rowspan untuk menggabungkan baris tabel. Nilai rowspan dan colspan menunjukkan jumlah sel yang ingin disatukan:

<table>
    <caption>Judul Tabel</caption>
    <tr><th colspan="2">Header 1</th><th>Header 2</th><th>Header 3</th></tr>
    <tr><td>1.1</td><td>1.2</td><td>1.3</td></tr>
    <tr><td>2.1</td><td>2.2</td><td>2.3</td></tr>
</table>

Catatan: Karena sel tabel mendapatkan atribut colspan="2", maka dua buah posisi sel akan digabungkan. Jadi, sel di sebelahnya harus dibuang. Ini berlaku juga untuk rowspan, hanya saja penggabungannya secara vertikal:

<table>
    <caption>Judul Tabel</caption>
    <tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
    <tr><td rowspan="2">1.1</td><td>1.2</td><td>1.3</td></tr>
    <tr><td>2.1</td><td>2.2</td><td>2.3</td></tr>
</table>

Mengubah Tampilan Tabel dengan CSS

Diutamakan untuk border, CSS akan membuat tampilan border pada tabel menjadi lebih baik dan lebih bisa dikendalikan:

table, th, td {
  border:1px solid purple;
}

Namun, karena border tabel secara normal tampak terpisah, kita harus mendeklarasikan border-collapse:collapse untuk merapatkan mereka:

table, th, td {
  border:1px solid purple;
  border-collapse:collapse; /* untuk menghilangkan jarak antar sel */
}

Setelah itu Anda bisa menentukan width, padding, background, font, color dan lain-lain. Beberapa properti CSS seperti vertical-align dan text-align juga nantinya akan dibutuhkan:

table {
  width:100%; /* lebar tabel menjadi sama dengan lebar kontainer */
  font:normal normal 13px/1.4 Arial,Sans-Serif;
  color:#333;
  border-collapse:collapse; /* untuk menghilangkan jarak antar sel */
}

table caption {
  padding:.4em 0;
  font-style:italic;
  font-weight:bold;
  text-align:left;
  border-top:2px solid black;
}

table, th, td {
  border:1px solid black;
}

th, td {
  padding:1em 1.4em;
  vertical-align:top; /* membuat semua konten tabel menjadi rata atas */
  text-align:left; /* membuat semua teks di dalam tabel menjadi rata kiri */
}

th {
  background-color:#080;
  color:white;
}

Markup HTML Standar

Markup HTML tabel standar secara garis besar dapat disusun seperti ini:

<table summary="Tabel ini menjelaskan tentang perkembangan kelangsungan hidup umat manusia di tahun 2013">
    <caption>Tabel Kelangsungan Hidup Manusia</caption>
    <thead>
        <tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
    </thead>
    <tbody>
        <tr><td>1.1</td><td>1.2</td><td>1.3</td></tr>
        <tr><td>2.1</td><td>2.2</td><td>2.3</td></tr>
        <tr><td>3.1</td><td>3.2</td><td>3.3</td></tr>
        <tr><td>4.1</td><td>4.2</td><td>4.3</td></tr>
        <tr><td>5.1</td><td>5.2</td><td>5.3</td></tr>
    </tbody>
</table>

Setiap kelompok baris yang mengandung elemen <th> akan dibungkus kembali dengan elemen <thead> sementara kelompok baris yang mengandung elemen <td> akan dibungkus dengan elemen <tbody>

Footer Tabel

Anehnya, footer tabel harus diletakkan di sebelah atas, lebih tepatnya sebelum <tbody>. Tapi jangan khawatir, karena hasil akhirnya nanti akan tetap tampil di bagian paling bawah:

<table>
    <caption>Judul Tabel</caption>
    <thead>
        <tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
    </thead>
    <tfoot>
        <tr><td>Total</td><td>XXX</td><td>YYY</td></tr>
    </tfoot>
    <tbody>
        <tr><td>1.1</td><td>1.2</td><td>1.3</td></tr>
        <tr><td>2.1</td><td>2.2</td><td>2.3</td></tr>
        <tr><td>3.1</td><td>3.2</td><td>3.3</td></tr>
        <tr><td>4.1</td><td>4.2</td><td>4.3</td></tr>
        <tr><td>5.1</td><td>5.2</td><td>5.3</td></tr>
    </tbody>
</table>

Berikut ini adalah salah satu uraian mengenai elemen <tfoot> dari W3:

TFOOT must appear before TBODY within a TABLE definition so that user agents can render the foot before receiving all of the (potentially numerous) rows of data.

Catatan Tambahan

Lawan border-collapse:collapse adalah border-collapse:separate

Tidak semua tabel harus dilengkapi dengan border. Lebih baik set deklarasi border hanya untuk elemen tabel yang memiliki atribut border="1":

table[border=1] {
  border-collapse:collapse;
  background-color:white;
}

table[border=1] th,
table[border=1] td {
  border:1px solid black;
  padding:1em 1.4em;
}

Dulu Saya pernah sekali mencatat beberapa kode CSS untuk HTML tabel. Anda bisa membacanya di sini. Mungkin itu akan berguna sebagai referensi tambahan.

Labels: ,

Input Teks dengan Pelengkap Sugesti

Text Input with Suggestion

Elemen UI ini terinspirasi dari Google, lebih tepatnya pada bagian atas dasbor Forum Blogger (2013). Ini hanyalah penerapan konsep drop-down menu sebagai pelengkap elemen input teks dan sama sekali tidak ada hubungannya dengan cara kerja filter penelusuran/sortir topik pembicaraan seperti pada grup Google.

Elemen ini bisa Anda gunakan untuk memberikan sugesti atau pilihan kata kunci secara tidak langsung tanpa harus repot-repot menuliskan perintah-perintah khusus di sekitar formulir untuk pengguna agar mereka menuliskan kata kunci seperti ini dan itu. Cukup letakkan beberapa sugesti kata kunci pada menu drop-down, maka para pengguna akan segera mengerti gambaran formulir tersebut saat mereka menampilkan menu:

HTML

<div class="input-text-wrap">
    <form action="//your_site_name.com/search" method="get">
        <input class="text-input" type="text" name="q" autocomplete="off">
        <span class="down-arrow"></span>
        <input class="submit-button" type="submit" value="Search">
        <ul>
            <li>Wallpaper 3D</li>
            <li>Anime</li>
            <li>Manga</li>
            <li>Comics List</li>
            <li>Characters</li>
            <li>Animepedia</li>
        </ul>
    </form>
</div>

CSS

/*
  @credit: http://www.dte.web.id, https://plus.google.com/108949996304093815163/about
  font-family: Segoe,"Segoe UI",Arial,Sans-Serif
  font-size: 12px
  line-height: 30px
  border-color: #8E8E74, black
  color: #333, #666, black
  background-color: white, #FFEAD3, #EDD8BF, #E0CBB2
*/

/* outer */
.input-text-wrap {
  text-align:left;
  display:inline-block;
  background-color:white;
  border:1px solid #8E8E74;
  height:30px;
  position:relative;
  font:normal normal 12px/30px Segoe,"Segoe UI",Arial,Sans-Serif;
  color:#333;
  -webkit-box-shadow:inset 0 1px 2px -1px rgba(0,0,0,.4);
  -moz-box-shadow:inset 0 1px 2px -1px rgba(0,0,0,.4);
  box-shadow:inset 0 1px 2px -1px rgba(0,0,0,.4);
}

/* focused `.input-text-wrap` */
.input-text-wrap.focused {
  -webkit-box-shadow:inset 0 1px 2px -1px rgba(0,0,0,.7);
  -moz-box-shadow:inset 0 1px 2px -1px rgba(0,0,0,.7);
  box-shadow:inset 0 1px 2px -1px rgba(0,0,0,.7);
  border-color:black;
}

/* resets or netralize all element inside */
.input-text-wrap input,
.input-text-wrap form,
.input-text-wrap ul,
.input-text-wrap li {
  margin:0 0;
  padding:0 0;
  list-style:none;
  border:none;
  background:none;
  font:inherit;
  color:inherit;
  vertical-align:top;
}

.input-text-wrap input {display:inline-block}

.input-text-wrap .text-input,
.input-text-wrap .submit-button {
  height:30px;
  line-height:30px;
  font-weight:bold;
  margin:0 20px 0 5px;
  outline:none;
}

/* the text input */
.input-text-wrap .text-input {
  width:160px; /* set the text input width here */
}

/* the submit button */
.input-text-wrap .submit-button {
  width:70px;
  padding:0 0 2px;
  margin:0 0;
  background-color:#FFEAD3;
  border-left:1px solid #8E8E74;
  color:#666;
  cursor:pointer;
  -webkit-box-shadow:0 0 2px rgba(0,0,0,.4);
  -moz-box-shadow:0 0 2px rgba(0,0,0,.4);
  box-shadow:0 0 2px rgba(0,0,0,.4);
  position:relative;
}

.input-text-wrap .submit-button:hover {
  background-color:#EDD8BF;
  color:black;
}

/* the drop-down menu */
.input-text-wrap ul {
  position:absolute;
  top:100%;
  right:-1px;
  left:-1px;
  z-index:99;
  background-color:white;
  border:1px solid black;
  -webkit-box-shadow:0 1px 2px rgba(0,0,0,.4);
  -moz-box-shadow:0 1px 2px rgba(0,0,0,.4);
  box-shadow:0 1px 2px rgba(0,0,0,.4);
  display:none;
}

/* drop-down menu item */
.input-text-wrap li {
  line-height:26px;
  padding:0 10px;
  cursor:pointer;
}

.input-text-wrap li:hover {
  background-color:#E0CBB2;
  color:black;
}

/* the down arrow before the submit button */
.input-text-wrap .down-arrow {
  display:block;
  width:20px;
  height:30px;
  position:absolute;
  top:0;
  right:70px;
  cursor:pointer;
}

.input-text-wrap .down-arrow:hover,
.input-text-wrap .down-arrow.active {
  background-color:white;
  -webkit-box-shadow:-1px 1px 2px rgba(0,0,0,.4);
  -moz-box-shadow:-1px 1px 2px rgba(0,0,0,.4);
  box-shadow:-1px 1px 2px rgba(0,0,0,.4);
  z-index:2;
}

.input-text-wrap .down-arrow:active,
.input-text-wrap .down-arrow.active {
  -webkit-box-shadow:-1px 1px 1px rgba(0,0,0,.2);
  -moz-box-shadow:-1px 1px 1px rgba(0,0,0,.2);
  box-shadow:-1px 1px 1px rgba(0,0,0,.2);
}

/* create the down-arrow triangle with pseudo-element and border hack */
.input-text-wrap .down-arrow:before {
  content:"";
  display:block;
  width:0;
  height:0;
  border:4px solid transparent;
  border-top-color:#666;
  position:absolute;
  top:14px;
  left:50%;
  margin-left:-4px;
}

jQuery

(function($) {

    var $inputWrap = $('.input-text-wrap'),
        $arrow = $inputWrap.find('.down-arrow');

    // Hide the dropdown menu when user click outside the `.input-text-wrap`, anywhere...
    $(document).on("click", function() {
        $inputWrap.find('ul').hide();
        $arrow.removeClass('active');
    });

    $arrow.on("click", function(e) {

        // Remove all the `focused` class and hide all visible drop-down menu
        $inputWrap.removeClass('focused').find('ul:visible').hide();
        // Remove al the `active` down arrow
        $arrow.removeClass('active');

        // Toggle the `.down-arrow` active class
        $(this).toggleClass('active')
            // Add a `focused` class to the `.input-text-wrap`
            .closest('.input-text-wrap').addClass('focused')
                // Show or hide the dropdown `ul`
                .find('ul').toggle()
                    // When we click the `li`...
                    .find('li').on("click", function() {
                        // Set the input text value to the clicked `li`'s text
                        $(this).closest('.input-text-wrap').find('.text-input').val($(this).text())
                            // and trigger the focus event to it
                            .trigger("focus");
                        // After that, hide the visible dropdown menu
                        $(this).parent().hide();
        });

        // Prevent event bubbling!
        e.stopPropagation();

    });

    // When the text input focused...
    $inputWrap.find('.text-input').on("focus", function() {
        // Add a `focused` class to the `.input-text-wrap`
        $(this).closest('.input-text-wrap').addClass('focused');
    // When the text input loses the focus...
    }).on("blur", function(e) {
        // Remove the `focused` class from `.input-text-wrap`
        $(this).closest('.input-text-wrap').removeClass('focused');
    });

})(jQuery);

Demo

Labels: , , ,

Friday, January 11, 2013

Menyamakan Tampilan Elemen input[type=file] pada Semua Peramban

Styled File Input

Elemen input bertipe file sebenarnya tidak jauh berbeda dengan elemen radio atau checkbox. Mereka sangat sulit untuk dimodifikasi tampilannya. Selain itu, elemen <input type="file"> juga memiliki tampilan default yang berbeda-beda pada setiap peramban:

Different File Input Appearance in Different Browsers
Tampilan elemen input file yang berbeda-beda, tergantung jenis peramban.

Namun, dengan sedikit elemen tambahan, kita bisa membuat elemen ini tampak sama pada semua peramban. Pada intinya kita hanya akan mengubah tampilan input tersebut menjadi transparan, kemudian kita letakkan sesuatu di bawahnya sebagai elemen input palsu, sehingga saat elemen palsu tersebut diklik, yang terjadi sebenarnya adalah kita memicu elemen input yang menutupi di atasnya yang tidak tampak karena transparan:

HTML

<div class="custom-file-input">
  <span></span>
  <span>Browse<input type="file"></span>
</div>

CSS

.custom-file-input {
  display:inline-block;
  position:relative;
  width:250px;
  height:30px;
  background-color:black;
  color:white;
  font:normal normal 13px/30px Helmet,FreeSans,Sans-Serif;
  border-radius:3px;
  overflow:hidden;
  cursor:text;
}
.custom-file-input input {
  opacity:0;
  filter:alpha(opacity=0);
  display:block;
  position:absolute;
  top:0;
  right:0;
  margin:0;
  padding:0;
  font-size:2000%;
  z-index:4;
  cursor:pointer;
}
.custom-file-input span {
  display:block;
  position:absolute;
  top:0;
  right:0;
  bottom:0;
  left:0;
  padding:0 10px;
  overflow:hidden;
}
.custom-file-input span + span {
  left:auto;
  background-color:#234;
  border-radius:0 3px 3px 0;
  padding:0 15px;
  box-shadow:0 0 3px black,0 0 10px black;
}
.custom-file-input input::-ms-value {display:none}
.custom-file-input input::-ms-browse {
  display:block;
  margin:0;
  padding:0;
  cursor:inherit;
}

JavaScript

JavaScript ini sebenarnya tidak terlibat secara langsung pada kerja <input type="file">, dan hanya digunakan sebagai pelengkap. Fungsinya untuk mengambil nilai elemen input tersebut, kemudian meletakkannya ke dalam elemen <span> yang berperan sebagai pengganti kontainer teks (penampil path menuju file):

(function() {
    var input = document.getElementsByClassName('custom-file-input');
    for (var i = 0, len = input.length; i < len; ++i) {
        var theInput = input[i].getElementsByTagName('input')[0];
        theInput.onchange = function() {
            this.parentNode.parentNode.children[0].innerHTML = this.value;
            this.title = this.value;
        };
    }
})();

Demo

Lihat Demo

Labels: , , , ,

Tuesday, January 1, 2013

Bekerja dengan Blog Seluler

Berikut ini adalah beberapa cara yang bisa Anda lakukan untuk menangani tampilan blog versi mobile/perangkat seluler. Namun sebelum memulainya, ada beberapa hal penting yang harus Saya jelaskan terlebih dahulu sebagai pondasi:

1. URL Blog Desktop dan Seluler

Menampilkan tampilan blog blogspot versi seluler bisa dilakukan dengan cara menambahkan kueri berupa ?m=1 pada URL. Sebagai contoh, jika alamat blog Anda adalah http://nama_blog.blogspot.com, maka untuk menampilkan tampilan blog perangkat seluler, Anda harus mengubah URLnya menjadi http://nama_blog.blogspot.com/?m=1. Tampilan blog versi biasa bisa Anda akses dengan mengubah nilai m menjadi 0, atau cukup buang kueri tersebut dari URL:

URL Blog Seluler: http://nama_blog.blogspot.com/?m=1URL Blog Normal: http://nama_blog.blogspot.com/?m=0URL Blog Normal: http://nama_blog.blogspot.com/

2. Perbedaan Elemen HTML Blog Desktop dengan Blog Seluler

Setiap widget posting yang masih asli akan selalu dilengkapi dengan duplikat markup HTML khusus untuk tampilan blog seluler. Ini ditandai dengan munculnya beberapa elemen <b:includable> dengan atribut-atribut bernilai (atau setidaknya memiliki imbuhan kata) “mobile”.

Berikut ini adalah contoh susunan XHTML navigasi halaman blog pada versi tampilan biasa:

<b:includable id='nextprev'>
  <div class='blog-pager' id='blog-pager'>
    <b:if cond='data:newerPageUrl'>
      <span id='blog-pager-newer-link'>
      <a class='blog-pager-newer-link' expr:href='data:newerPageUrl' expr:id='data:widget.instanceId + &quot;_blog-pager-newer-link&quot;' expr:title='data:newerPageTitle'><data:newerPageTitle/></a>
      </span>
    </b:if>

    <b:if cond='data:olderPageUrl'>
      <span id='blog-pager-older-link'>
      <a class='blog-pager-older-link' expr:href='data:olderPageUrl' expr:id='data:widget.instanceId + &quot;_blog-pager-older-link&quot;' expr:title='data:olderPageTitle'><data:olderPageTitle/></a>
      </span>
    </b:if>

    <a class='home-link' expr:href='data:blog.homepageUrl'><data:homeMsg/></a>

    <b:if cond='data:mobileLinkUrl'>
      <div class='blog-mobile-link'>
        <a expr:href='data:mobileLinkUrl'><data:mobileLinkMsg/></a>
      </div>
    </b:if>

  </div>
  <div class='clear'/>
</b:includable>

Beberapa gulungan layar ke bawah, Anda akan menemukan kode yang nyaris sama dengan kode di atas. Perbedaan hanya terlihat pada karakteristik berupa ditambahkannya kelas-kelas dengan imbuhan “mobile” dan/atau hilangnya beberapa elemen HTML dari kode mirip yang pertama kali Anda temukan:

<b:includable id='mobile-nextprev'>
  <div class='blog-pager' id='blog-pager'>
    <b:if cond='data:newerPageUrl'>
      <div class='mobile-link-button' id='blog-pager-newer-link'>
      <a class='blog-pager-newer-link' expr:href='data:newerPageUrl' expr:id='data:widget.instanceId + &quot;_blog-pager-newer-link&quot;' expr:title='data:newerPageTitle'>&amp;lsaquo;</a>
      </div>
    </b:if>

    <b:if cond='data:olderPageUrl'>
      <div class='mobile-link-button' id='blog-pager-older-link'>
      <a class='blog-pager-older-link' expr:href='data:olderPageUrl' expr:id='data:widget.instanceId + &quot;_blog-pager-older-link&quot;' expr:title='data:olderPageTitle'>&amp;rsaquo;</a>
      </div>
    </b:if>

    <div class='mobile-link-button' id='blog-pager-home-link'>
    <a class='home-link' expr:href='data:blog.homepageUrl'><data:homeMsg/></a>
    </div>

    <div class='mobile-desktop-link'>
      <a class='home-link' expr:href='data:desktopLinkUrl'><data:desktopLinkMsg/></a>
    </div>

  </div>
  <div class='clear'/>
</b:includable>

Fungsinya adalah untuk membedakan markup HTML antara blog tampilan layar desktop dengan blog tampilan seluler. Sehingga, sebagai contoh, jika kita mengakses halaman blog kita pada perangkat desktop, maka kita akan melihat kode HTML seperti ini pada sumbernya:

<div class='blog-pager' id='blog-pager'>
  <span id='blog-pager-newer-link'>
    <a class='blog-pager-newer-link' href='…' id='Blog1_blog-pager-newer-link' title='Posting Lebih Baru'>Posting Lebih Baru</a>
  </span>
  <span id='blog-pager-older-link'>
    <a class='blog-pager-older-link' href='…' id='Blog1_blog-pager-older-link' title='Posting Lama'>Posting Lama</a>
  </span>
  <a class='home-link' href='/'>Beranda</a>
  <div class='blog-mobile-link'>
    <a href='/?m=1'>Lihat versi seluler</a>
  </div>
</div>
<div class='clear'></div>

Namun, saat kita membuka halaman blog pada perangkat seluler, kita akan melihat bahwa elemen-elemen navigasi blog telah berubah:

<div class='blog-pager' id='blog-pager'>
  <div class='mobile-link-button' id='blog-pager-newer-link'>
    <a class='blog-pager-newer-link' href='…' id='Blog1_blog-pager-newer-link' title='Posting Lebih Baru'>&amp;lsaquo;</a>
  </div>
  <div class='mobile-link-button' id='blog-pager-older-link'>
    <a class='blog-pager-older-link' href='…' id='Blog1_blog-pager-older-link' title='Posting Lama'>&amp;rsaquo;</a>
  </div>
  <div class='mobile-link-button' id='blog-pager-home-link'>
    <a class='home-link' href='/'>Beranda</a>
  </div>
  <div class='mobile-desktop-link'>
    <a class='home-link' href='/?m=0'>Lihat versi web</a>
  </div>
</div>
<div class='clear'></div>

Logikanya seperti itu.

Masing-masing elemen <b:includable> akan ditampilkan sesuai keadaannya (dalam hal ini adalah mengenai apakah kita sedang berada pada perangkat desktop ataukah perangkat seluler), yang dalam sebuah widget dapat dikondisikan dengan kondisional <b:if cond='data:mobile'>:

<b:if cond='data:mobile'>
  <!-- menampilkan navigasi halaman versi mobile pada perangkat seluler -->
  <b:include name='mobile-nextprev'/>
<b:else/>
  <!-- menampilkan navigasi halaman versi desktop pada perangkat desktop -->
  <b:include name='nextprev'/>
</b:if>

<b:if cond='data:mobile'> hanya berlaku jika diletakkan/dideklarasikan di dalam <b:includable> dan tidak bisa bekerja di luar elemen itu. Kondisional universal untuk menyatakan tampilan seluler bisa dinyatakan sebagai ini:

<b:if cond='data:blog.isMobile'> … </b:if>
<b:if cond='data:blog.isMobileRequest'> … </b:if>

Anda bisa menerapkan kondisional di atas di mana saja.

Pastikan Fitur Blog Seluler Aktif

Pembaharuan: Kondisional data:blog.isMobileRequest dapat bekerja meski fitur blog seluler tidak aktif, karena kondisional ini tampaknya hanya mengecek keberadaan ?m=1 pada URL.

Jika tidak, aktifkan kembali dengan cara masuk ke tab Templat kemudian klik ikon roda gigi yang berada di bawah penayang blog seluler Anda:

Mengaktifkan Fitur Blog pada Perangkat Seluler
Mengaktifkan fitur blog seluler.

Setelah itu Anda akan mendapati pilihan untuk mengaktifkan atau tidak mengaktifkan fitur blog seluler. Pilih untuk mengaktifkan fitur blog seluler.

Dua Metode Modifikasi

Setelah mengerti tentang bagaimana Blogger bisa menangani tampilan blog seluler terhadap tampilan blog biasa, kita bisa memulai untuk mengetahui dua ide yang biasa digunakan untuk membedakan tampilan antara blog versi biasa dengan blog versi seluler.

Metode 1: Menambahkan Kelas Khusus Tampilan Seluler pada Tag <body>

Blogger sudah memiliki tag data tersendiri yang akan menggenerasikan kelas bernama mobile berdasarkan tipe tampilan blog, yaitu data:blog.mobileClass yang bisa kita letakkan pada tag HTML di dalam templat sebagai nilai kelas. Misalnya pada tag <body> seperti ini:

<body expr:class='data:blog.mobileClass'>

Dengan cara di atas, maka kita akan mendapati bahwa tag <body> telah dilengkapi dengan kelas mobile pada blog tampilan seluler seperti ini:

<body class=' mobile'>

Saat kita membuka blog pada tampilan desktop, nilai mobile pada atribut akan menghilang. Sehingga kita bisa membedakan tampilan blog seluler dengan blog biasa melalui kelas blog seluler tersebut melalui CSS:

#header-wrapper {
  background-color:#000;
  color:#fff;
}

#main-wrapper {
  width:900px;
  margin:0 auto;
}

/* mobile */
body.mobile #header-wrapper {
  background-color:#fff;
  color:#000;
}

body.mobile #main-wrapper {
  width:auto;
  margin:0 10px;
}

Metode 2: Memanfaatkan Kondisional Seluler

Kita juga bisa menggunakan kondisional universal yang digunakan untuk menyatakan tampilan blog seluler sebagai pembatas tampilnya elemen-elemen HTML —termasuk tag <style>— dengan cara seperti ini:

Membedakan CSS Blog Desktop dengan Blog Seluler

<b:if cond='data:blog.isMobile'>
  <style>
  body {background-color:black} /* blog akan berwarna hitam pada tampilan seluler */
  </style>
<b:else/>
  <style>
  body {background-color:white} /* blog akan berwarna putih pada tampilan desktop */
  </style>
</b:if>

Menghilangkan/Menampilkan Elemen HTML

Beberapa pola yang biasa digunakan:

<b:if cond='data:blog.isMobile == &quot;false&quot;'>
  <div id='header-wrapper' class='desktop-header'>
    Header Blog Tampilan Layar Desktop
  </div>
</b:if>
<b:if cond='data:blog.isMobile'>
  <div id='header-wrapper' class='mobile-header'>
    Header Blog Tampilan Seluler
  </div>
</b:if>
<b:if cond='data:blog.isMobile == &quot;true&quot;'>
  <div id='header-wrapper' class='mobile-header'>
    Header Blog Tampilan Seluler
  </div>
</b:if>
<b:if cond='data:blog.isMobile != &quot;true&quot;'>
  <div id='header-wrapper' class='desktop-header'>
    Header Blog Tampilan Layar Desktop
  </div>
</b:if>

Menggunakan Kondisional Seluler Sebagai Bagian dari Kelas

Pada dasarnya, data:blog.isMobile akan menampilkan nilai berupa true atau false tergantung dari apakah blog tersebut dibuka pada tampilan seluler ataukah pada layar desktop. Sehingga, sebenarnya kita juga bisa menggunakan data tersebut sebagai nama kelas (bagian dari nama kelas) untuk menyatakan bahwa blog tersebut sedang dibuka pada perangkat seluler atau perangkat desktop:

<body expr:class='&quot;mobile-&quot; + data:blog.isMobile'>

Kode di atas akan menampilkan dua kemungkinan nilai kelas, yaitu:

<body class='mobile-true'>

atau

<body class='mobile-false'>

tergantung dengan perangkat apa kita membuka halaman blog tersebut. Sehingga:

/* blog normal */
body.mobile-false #header-wrapper {
  background-color:white;
  color:black;
}

body.mobile-false #sidebar-wrapper {
  background-color:white;
  color:black;
}

/* blog seluler */
body.mobile-true #header-wrapper {
  background-color:black;
  color:white;
}

body.mobile-true #sidebar-wrapper {
  background-color:white;
  color:black;
}

body.mobile-true .desktop-elem {
  display:none !important;
  visibility:hidden;
}

/* dan seterusnya… */

Terakhir…

Agar pengeditan CSS pada blog tampilan seluler bisa bekerja, jangan memilih jenis templat apapun pada opsi templat seluler. Pilihlah opsi Tersesuai:

Pilih Pilihan Tersesuai
Tidak memilih template seluler apapun dengan cara memilih opsi Tersesuai

Labels: , ,

Sunday, December 16, 2012

Mendapatkan Node Komentar HTML dengan jQuery

Kode ini memungkinkan kita untuk mengambil node komentar HTML yang kemudian bisa kita gunakan sebagai elemen HTML biasa. Sehingga jika komentar HTML adalah berupa elemen HTML yang mengandung permintaan HTTP, maka kita bisa memuat elemen tersebut secara tidak langsung dengan cara menuliskannya sebagai komentar HTML terlebih dahulu:

$('#fake-elem-container').contents().filter(function() {
    return this.nodeType == 8;
}).each(function(i, e) {
    $('#container').html(e.nodeValue);
});

#fake-elem-container adalah elemen yang akan dijadikan sebagai penampung komentar HTML, sedangkan #container akan menjadi penampung node komentar yang sudah berubah menjadi elemen HTML:

<div id="fake-elem-container">
    <!-- <img alt="" src="gambar.jpg"> -->
</div>

<div id="container"></div>

Jika berhasil diterapkan, maka #container akan memuat gambar yang dibentuk dari komentar HTML di dalam elemen #fake-elem-container

Demo:

Labels: , , ,

Wednesday, December 12, 2012

Unicode untuk Membuat Diagram Pohon

Daftar Kode

Simbol Tampilan
&#9474;
&#9472;
&#9500;
&#9492;

Sampel HTML

Untuk indentasi karakter yang akurat, kode hendaknya dituliskan di dalam elemen <pre> atau elemen blok apapun yang dikenai deklarasi white-space:pre dan bertipe font Monospace:

<!-- Dengan tag `PRE` -->
<pre>
  Teks dan unikode di sini ...
</pre>

<!-- Dengan tag HTML biasa -->
<div style="white-space:pre;word-wrap:break-word;font-family:Monospace;">
  Teks dan unikode di sini ...
</div>

Demo

A
├─── AA
│    └─── AAA
├─── AB
│    ├─── ABA
│    ├─── ABB
│    └─── ABC
└─── AC
A
├─── AA
│ └─── AAA
├─── AB
│ ├─── ABA
│ ├─── ABB
│ └─── ABC
└─── AC

Labels: , ,

Friday, October 26, 2012

Kompresor HTML

Sebuah alat kecil untuk mengompres kode HTML. Paste beberapa potong kode HTML kemudian klik tombol kompresi:

Coba Alat

Labels: ,

Tuesday, September 18, 2012

Apa Itu Sticky Footer?

Non Sticky Footer
Efek yang timbul pada ujung halaman jika tinggi halaman lebih pendek dari tinggi layar.

Karena Saya lihat masih banyak yang salah paham dengan istilah Sticky Footer, jadi Saya akan membahasnya. Kebanyakan orang menganggap bahwa sticky footer itu artinya footer menempel di bawah layar dan akan tetap berada pada posisinya meskipun layar digulung.

Baiklah, memang bisa dibilang begitu, mengingat kata 'stick' juga berarti 'menempel'. Tapi bukan seperti itu pengertian sticky footer yang sebenarnya. Sticky Footer maksudnya adalah footer akan tetap berada di bawah layar meskipun tinggi halaman/dokumen lebih pendek dari tinggi layar. Sticky Footer digunakan untuk memastikan agar tampilan halaman yang rendah tidak tampak jelek saat berada pada device yang ukuran layarnya lebih tinggi dari ukuran halaman.

Berikut ini adalah sebuah demonstrasi footer biasa dimana di atasnya hanya terdapat beberapa teks, sehingga tinggi halaman tidak mampu meraih bagian bawah:

Lihat Demo

Bisa Anda lihat bahwa footer tampak menggantung di atas dan menjadikannya tidak menarik. Nah, Sticky Footer berguna untuk mengatasi masalah ini, untuk memastikan agar footer tetap berada di bawah meskipun tinggi halaman lebih rendah dari tinggi layar. Ini adalah contoh sticky footer:

Lihat Demo

Anda lihat bahwa meskipun tinggi halaman/dokumen lebih pendek dari tinggi layar, CSS Sticky Footer tetap menjaga agar halaman menekan ke sisi atas dan sisi bawah (dengan menggunakan ukuran tinggi dominan sebesar 100% pada masing-masing elemen) sehingga tidak akan ada ruang kosong yang tersisa di bagian bawah.

Masih Belum Yakin dengan Istilah Sticky Footer?

Cek situs ini ⇒ http://www.cssstickyfooter.com/

Pada bagian prolog sudah jelas tertulis, "It Sticks to the Bottom of the Page!", bukan "It Sticks to the Bottom of the Window!"

Dan ini adalah halaman demonstrasi tampilan footer biasa beserta masalahnya, yang juga terdapat pada sub-halaman dari situs tersebut: http://www.cssstickyfooter.com/non-stick-footer.html

Sticky Footer bukan berarti bahwa footer melayang di bawah layar. Sticky Footer lebih tepat dikatakan sebagai metode untuk memastikan footer tetap berada di bawah halaman meskipun tinggi halaman lebih pendek dari tinggi layar. Sticky Footer hanya akan terlihat efeknya jika tinggi halaman lebih pendek dari tinggi layar. Jika tinggi halaman tidak lebih pendek dari tinggi layar (atau katakanlah: Jika Anda bisa memastikan bahwa halaman situs Anda tidak pernah lebih pendek dari tinggi layar), maka Anda tidak perlu menggunakan Sticky Footer.

Saat tinggi halaman sudah melebihi tinggi layar, maka efek Sticky Footer akan menghilang. Dan CSS Sticky Footer sudah tidak ada gunanya lagi saat itu:

Lihat Demo


CSS & HTML Sticky Footer

HTML

<div id="wrap">
    <section id="main"> ... </section>
</div>
<footer id="footer"></footer>

CSS

/**  
 * Sticky Footer Solution
 * by Steve Hatcher 
 * http://stever.ca
 * http://www.cssstickyfooter.com
 */

* {margin:0;padding:0;} 

/* Must declare 0 margins on everything, also for main layout components use padding, not vertical margins (top and bottom) to add spacing, else those margins get added to total height and your footer gets pushed down a bit more, creating vertical scroll bars in the browser */

html, body {
  height:100%;
}

#wrap {
  min-height:100%;
}

#main {
  overflow:auto;
  padding-bottom:180px; /* must be same height as the footer */
}

#footer {
  position:relative;
  margin-top:-180px; /* negative value of footer height */
  height:180px;
  clear:both;
} 

/* Opera Fix */
body:before { /* thanks to Maleika (Kohoutec)*/
  content:"";
  height:100%;
  float:left;
  width:0;
  margin-top:-32767px; /* thank you Erik J - negate effect of float */
}

Tambahan Untuk Internet Explorer

<!--
You also need to include this conditional style in the <head> of your HTML file
to feed this style to IE 6 and lower and 8 and higher...
-->

<!--[if !IE 7]>
    <style>
        #wrap {display:table;height:100%}
    </style>
<![endif]-->

Labels: , , ,

Wednesday, September 5, 2012

Syntax Highlighter dengan PRISM

Syntax Highlighter dengan PRISM

Meskipun di blog ini Saya menggunakan syntax highlighter dari Software Maniacs, tapi jika diminta untuk memilih dari segi kecepatannya, maka Saya akan menggunakan PRISM, sebuah syntax highlighter untuk HTML, CSS, Java dan JavaScript (bekerja juga untuk PHP dengan asumsi sebagai markup):

Lihat Demo

Proses instalasi hanya membutuhkan dua langkah. Pertama-tama masuklah ke halaman editor HTML Template Anda kemudian pilih Edit HTML dan klik Lanjutkan. Temukan kode ini:

]]></b:skin>

Salin kode CSS ini dan letakkan di atasnya:

/*
Tema pribadi => RDark
Saya buat berdasarkan tema-tema SyntaxHighligter dari Alex Gorbatchev
URL: http://alexgorbatchev.com/SyntaxHighlighter/manual/themes/rdark.html*/

pre {
  padding:.5em 1em;
  margin:.5em 0;
  white-space:pre;
  word-wrap:normal;
  overflow:auto;
  background-color:#1B2426;
}

code {
  font-family:Consolas,Monaco,'Andale Mono','Courier New',Courier,Monospace;
  line-height:16px;
  color:#B43D3D;
  background-color:#eee;
  border:1px solid #ddd;
  padding:1px 2px;
}

pre code {
  display:block;
  background:none;
  border:none;
  color:#B9BDB6;
  direction:ltr;
  text-align:left;
  word-spacing:normal;
  padding:0 0;
}

code .token.punctuation {
  color:#83405A;
}

pre code .token.punctuation {
  color:#B9BDB6;
}

code .token.comment,
code .token.prolog,
code .token.doctype,
code .token.cdata {
  color:#435A4D;
}

code .namespace {
  opacity:.8;
}

code .token.property,
code .token.tag,
code .token.boolean,
code .token.number {
  color:#5BA1CF;
}

code .token.selector,
code .token.attr-name,
code .token.string {
  color:#986A7C;
}

pre code .token.selector,
pre code .token.attr-name,
pre code .token.string {
  color:#E0E8FF;
}

code .token.entity,
code .token.url,
pre .language-css .token.string,
pre .style .token.string {
  color:#E0E8FF;
}

code .token.operator {
  color:#878A85;
}

code .token.atrule,
code .token.attr-value {
  color:#48D30F;
}

pre code .token.atrule,
pre code .token.attr-value {
  color:#48E638;
}

code .token.keyword {
  color:#47A1CF;
  font-style:italic;
}

code .token.comment {
  font-style:italic;
}

code .token.regex {
  color:#B43D3D;
}

code .token.important {
  font-weight:bold;
}

code .token.entity {
  cursor:help;
}

Setelah itu temukan kode ini:

</body>

Letakkan skrip ini di atasnya:

<script "//cdn.rawgit.com/tovic/dte-project/2fd2d2971c3398029ea5e149696447243e7f4d94/prism.min.js"></script>

Klik Simpan Template.

Cara Pemakaian

Setiap tipe bahasa memiliki kelasnya masing-masing:

  • HTML, XML, PHPlanguage-markup
  • CSSlanguage-css
  • JavaScriptlanguage-javascript
  • Javalanguage-java

Kode yang ingin diberi efek harus berada di dalam tag pre > code seperti ini:

<pre><code class="language-markup"> ... kode HTML (yang sudah di`escape`) di sini ... </code></pre>
<pre><code class="language-css"> ... kode CSS di sini ... </code></pre>
<pre><code class="language-javascript"> ... kode JavaScript di sini ... </code></pre>
<pre><code class="language-java"> ... kode Java di sini ... </code></pre>

Tema-tema yang asli bisa Anda temukan di situs sumbernya, PRISM. Atau mungkin Anda mau membuatnya sendiri?

Labels: , , , ,

Thursday, August 30, 2012

Redirect ke Halaman Lain Jika JavaScript Nonaktif

Dengan memasukkan tag <meta> penyegar halaman ke dalam tag <noscript>, kode di bawah ini akan mengirim pengunjung ke sebuah halaman yang Saya sebut sebagai no-js-page.html jika JavaScript dinonaktifkan:

<noscript>
  <meta http-equiv="refresh" content="0; url=http://www.nama-situs.com/no-js-page.html">
</noscript>

Labels: ,

Thursday, June 7, 2012

Berbicara Tentang Optimasi Kecepatan Muat Halaman

Beberapa orang berpendapat bahwa kompresi JavaScript, CSS, gambar atau bahkan HTML bisa mempercepat proses muat halaman sebuah situs. Tapi Saya tidak pernah setuju dengan itu 100%. Ada begitu banyak hal yang harus menjadi pertimbangan lebih lanjut dibandingkan sekedar memfokuskan perhatian Anda terhadap perhitungan besar kecilnya ukuran file. Kebanyakan alat kompresi hanya akan memperkecil ukuran berkas tidak lebih dari 20%:

Hasil Kompresi CSS
Hasil Kompresi CSS – CSSDrive

Dan lagipula, kompresi yang dilakukan hanya berada pada seputar peringkasan variabel dan pembuangan karakter spasi yang tidak diperlukan. Itu sama sekali tidak mempercepat proses muat halaman sepenuhnya, itu hanya akan mempercepat proses pengunduhan file secara sepihak. Dalam hal ini adalah CSS/JavaScript yang notabene hanyalah file berupa teks, sehingga mengunduh teks yang dikompresi dengan teks yang tidak dikompresi tidak akan memberikan begitu banyak perbedaan. Kecepatan muat halaman situs tidak semata-mata dipengaruhi oleh faktor ukuran file, tapi juga oleh validasi, permintaan HTTP dan juga ketepatan pendeklarasian kode tugas yang akan memberikan timbal balik berupa kemudahan peramban dalam membaca dokumen Anda.

JavaScript Packer vs. Minifier

Mana yang lebih cepat dimuat, antara JavaScript yang dikompres dengan teknik Packer dan teknik Minifier? Seharusnya Packer lebih cepat karena mereka akan mengompres kode jauh lebih banyak dibandingkan Minifier.

Mohon pertimbangkan sekali lagi. Packer memang akan memperkecil ukuran JavaScript jauh lebih banyak dibandingkan Minifier, tapi imbasnya adalah peramban harus memberikan waktu tambahan untuk menyusun kembali kode-kode yang sudah dipecah meskipun kenyataannya ukuran mereka sudah diperkecil. Packer (dan Obfuscator) akan membuat JavaScript lebih lama dimuat bukan karena ukuran file yang besar, namun karena membuat waktu membaca peramban menjadi lebih lama. Saat kita mengompres JavaScript dengan Packer atau Obfuscator, kita seperti sedang memberikan teka-teki sandi perintah terlebih dahulu untuk dijawab oleh peramban sebelum pada akhirnya mereka berhasil menjawabnya dan menjalankan tugasnya. Lebih baik gunakan Minifier dibandingkan Packer jika memang ingin mengurangi ukuran file JavaScript:

Menggunakan Base62 menambahkan langkah tambahan sebelum JavaScript dapat dimanfaatkan oleh klien. Untuk jenis perpustakaan jQuery langkah ini dapat mengambil ekstra waktu 100 - 500ms pada klien, tergantung pada banyak faktor. Sekarang kita dapat membandingkan pengurangan "waktu untuk mengunduh script" dan "waktu tambahan yang dibutuhkan untuk mengeksekusi script". Ini (packer/teknik base62) dapat mengurangi waktu pengunduhan sebanyak 50ms tetapi mengambil ekstra 100ms hanya untuk memprosesnya (menyusun kembali kode yang sudah terpecah-pecah) - Sumber

Lalu bagaimana dengan alasan perlindungan kode? Bukankah Packer dan Obfuscator jauh lebih melindungi kode dibandingkan Minifier? Ini semua adalah pilihan. Pada dasarnya setiap teknik kompresi masih tetap bisa menjaga agar file bisa dibaca oleh peramban. Ambil keputusan yang sekiranya memiliki kerugian terkecil berdasarkan tujuan.

Memperkecil Permintaan HTTP

Semakin banyak permintaan HTTP (HTTP Requests) yang terjadi, maka akan semakin lambat halaman termuat. Permintaan HTTP pada dasarnya hanyalah tentang seberapa banyak peramban menghubungi server untuk memanggil data. Cara mengecek permintaan yang terjadi sebenarnya sangat mudah. Perhatikan saja status bar pada peramban Anda saat halaman sedang dimuat:

Melihat Proses Transfer Data Melalui Status Bar
Melihat proses transfer data melalui bar status

Dari situ Anda bisa melihat mana data yang cepat diakses dan mana yang lebih lama diakses berdasarkan kecepatan perubahan status. Jika Anda sudah menemukan apa yang membuat situs Anda menjadi lambat, Anda bisa segera mengambil keputusan terhadap file yang berhubungan dengan itu. Apakah akan membuangnya atau mengubah pengurutan permintaan yang lebih lambat menuju ke level yang lebih rendah (tidak dinomorsatukan). Misalnya, dengan cara meletakkan file yang lebih lama termuat di sebelah bawah.

Usahakan untuk mengurangi permintaan HTTP dari situs pihak ke tiga sebanyak mungkin. Katakanlah kita memiliki sebuah blog yang dilengkapi dengan widget Facebook Like, Twitter Feed, Chatbox dan Disqus dalam satu halaman yang sama. Ditambah lagi foto-foto artikel dan gambar latar belakang yang diunggah di Photobucket, kode CSS yang disimpan di GitHub dan JavaScript yang disimpan di Google Code. Kita bisa mengatakan itu semua sebagai komponen permintaan situs pihak ke tiga, karena kita telah menyisipkan berbagai URL file yang disimpan di ruang penyimpanan lain ke dalam blog kita. Meskipun mereka semua hanya berupa file-file kecil yang umumnya berupa teks, namun saat Anda membuka halaman blog dimana file-file yang disertakan di dalamnya masih merupakan milik situs lain, itu tetap saja akan memiliki arti yang sama seperti halnya Anda sedang membuka semua situs tersebut secara bersamaan!

Menggabungkan Semua File Eksternal Sejenis

Menggabungkan semua file sejenis ke dalam sebuah file besar bisa menjadi solusi termudah untuk mengurangi permintaan HTTP. Artinya bahwa kita akan mengubah sesuatu yang tadinya seperti ini:

<link rel="stylesheet" href="style1.css">
<link rel="stylesheet" href="style2.css">
<link rel="stylesheet" href="style3.css">
<script src="script1.js"></script>
<script src="script2.js"></script>
<script src="script3.js"></script>

menjadi seperti ini:

<link rel="stylesheet" href="style-123.css">
<script src="script-123.js"></script>

Ini berlaku juga untuk JavaScript dan CSS internal. Meskipun mereka tidak memiliki hubungan dengan permintaan HTTP, namun mengurangi jumlah tag <style> dan <script> di dalam dokumen juga bisa mempermudah peramban dalam membaca dokumen (memperpendak jarak baca dan mengurangi pengulangan baca file dengan tipe yang sama):

<script>
function abc() {
   document.write('abc');
}
</script>
<script>
function def() {
   alert('def');
}
</script>
<script>
function ghi() {
   var c = confirm('ghi?');
   if(c) window.open('http://nama_blog.com');
}
</script>
<script>
$(function() {
    // DOM ready 1 ...
});
$(function() {
    // DOM ready 2 ...
});
$(function() {
    // DOM ready 3 ...
});
</script>
<script>
abc();
def();
ghi();
</script>
<style>#lorem {width:200px}</style>
<style>#ipsum {color:red}</style>
<style>#dolor {border:1px solid blue}</style>

Ubah semua susunan kode di atas menjadi seperti ini:

<style>
#lorem {width:200px}
#ipsum {color:red}
#dolor {border:1px solid blue}
</style>
<script>
function abc() {
   document.write('abc');
}
function def() {
   alert('def');
}
function ghi() {
   var c = confirm('ghi?');
   if(c) window.open('http://nama_blog.com');
}
$(function() {
    // DOM ready 1 ...
    // DOM ready 2 ...
    // DOM ready 3 ...
});
</script>
<script>
abc();
def();
ghi();
</script>

Meletakkan JavaScript di atas </body>

Ini memiliki arti bahwa kita meletakkan JavaScript sejauh mungkin dari sebelah atas dokumen. Hal ini disarankan untuk mencegah keterlambatan pemuatan kerangka HTML di bawahnya karena lambatnya proses muat JavaScript di atasnya. Dengan meletakkan JavaScript di bawah, maka setidaknya kita telah mengizinkan peramban untuk merayapi kerangka halaman terlebih dahulu sebelum kemudian sampai pada masa untuk memuat dan membaca JavaScript. Posisikan juga CSS lebih awal dibandingkan JavaScript sehingga pembentukan tubuh halaman akan dieksekusi terlebih dahulu dibandingkan pengerjaan JavaScript.

Tapi tunggu dulu! Meletakkan JavaScript di bagian bawah juga tidak sepenuhnya benar. Beberapa faktor bisa membuat mereka tidak bekerja. Selengkapnya bisa di baca di sini

Merasa Blog/Situs Anda Sudah Cukup Cepat?

Jangan senang dulu. Mungkin itu karena Anda telah mengunjungi situs web Anda berkali-kali, yang juga berarti bahwa cache dari situs Anda masih tersimpan di dalam komputer. Sekarang coba Anda hapus semua cache yang ada kemudian muat ulang halaman situs Anda kembali:

Menghapus Cache
Menghapus Cache

Saat cache sudah terhapus, maka Anda akan merasakan kecepatan situs Anda yang sesungguhnya seperti halnya saat pengunjung Anda membuka situs Anda.

Tentunya akan terasa sedikit lebih lambat. Itu juga merupakan kesimpulan sederhana mengenai pertanyaan bodoh tentang mengapa saat kita pertama kali mengunjungi sebuah situs terasa begitu berat, namun saat kita telah menjadi langganan mereka, semuanya berubah menjadi lebih cepat.

Pembicaraan optimasi ini sepertinya lebih banyak berputar di sekitar JavaScript dan CSS saja. Ya, karena Saya pikir pembicaraan selain itu masih bisa dipahami seperti apa adanya. Saya hanya ingin menuliskan sesuatu yang seringkali menjadi sumber kesalahpahaman. Punya tambahan?

Labels: , , ,