Jumat, 29 Maret 2019

Membuat Posting Layar Penuh

Membuat Posting Layar Penuh

Mode layar penuh.
Mode layar penuh.

Saya membuat sebuah aplikasi/widget kecil untuk membuat posting di blog menjadi memiliki alternatif tampilan “layar penuh”. Tidak benar-benar layar penuh sebenarnya, karena widget ini hanya bekerja dengan cara menyisipkan tabir baru berisi duplikat judul dan konten posting. Kalau Anda ingin membuat fitur full screen sungguhan yang bisa memenuhi seluruh layar, Anda bisa mempelajari API JavaScript ini ⇒ MDN – Using Full Screen Mode
Untuk memasang widget ini, masuklah ke halaman editor HTML Templat, lalu letakkan kode ini di atas </body>:
<b:if cond='data:blog.pageType == &quot;item&quot;'>
  <script src='https://cdn.rawgit.com/tovic/dte-project/2fd2d2971c3398029ea5e149696447243e7f4d94/full-screen.min.js'/>
  <script>
  //<![CDATA[
  postFullScreen({
    titleSource: document.querySelector('.post-title'),
    contentSource: document.querySelector('.post-body'),
    background: "#fff",
    color: "inherit",
    fontSize: "120%",
    padding: 50,
    maxWidth: 750,
    openText: "Full Screen Mode",
    closeText: "Exit full screen mode",
    appendButtonTo: null,
    beforeInit: null,
    afterInit: null
  });
  //]]>
  </script>
</b:if>
Atau Saya sarankan lebih baik letakkan kode di atas sedekat mungkin dengan posting. Lebih tepatnya di bagian paling bawah dari posting:
<b:section class='main' id='main' showaddelement='no'>
  <b:widget id='Blog1' locked='true' title='Posting Blog' type='Blog'> … </b:section>
</b:section>
<!-- Letakkan di sini -->
Klik Simpan Templat.

Konfigurasi

OpsiKeterangan
titleSourceSelektor elemen HTML dimana di dalamnya berisi teks judul. Di atas Saya menggunakan selektor document.querySelector('.post-title') untuk memperoleh teks judul dari dalam elemen <h3 class='post-title'></h3>. Sebagai alternatif, Anda bisa mencoba untuk menggunakan selektor document.title untuk memperoleh judul dari address bar.
contentSourceSelektor elemen HTML dimana di dalamnya terdapat konten artikel/posting. Pengaturannya sama persis dengan opsi titleSource.
backgroundDigunakan untuk menentukan warna latar tabir layar penuh.
colorDigunakan untuk menentukan warna teks mode layar penuh. inherit artinya warna menyesuaikan dengan warna teks posting.
fontSizeDigunakan untuk menentukan besar teks di artikel layar penuh.
paddingDigunakan untuk menentukan padding tabir layar penuh.
maxWidthDigunakan untuk menentukan lebar maksimal area artikel layar penuh.
openTextDigunakan untuk menentukan teks tombol pemicu layar penuh.
closeTextDigunakan untuk menentukan teks tombol penutup tampilan layar penuh.
createButtonDigunakan untuk membuat tombol kustom. Lihat penjelasan di bawah.
appendButtonToNilai berupa selektor elemen HTML. Jika nilainya null, tombol akan secara otomatis disisipkan di bawah posting. Jika nilainya false, tombol tidak akan disisipkan secara otomatis (bermanfaat jika Anda ingin membuat tombol pemicu tersendiri secara terpisah).
beforeInitLihat penjelasan di bawah.
afterInitLihat penjelasan di bawah.

Penjelasan Ekstra

createButton

Opsi ini digunakan sebagai alternatif jika Anda tidak suka dengan tampilan tombol pemicu layar penuh secara normal. Anda bisa memanfaatkan opsi ini untuk menentukan/membuat elemen tombol kustom. Sebagai contoh di sini Saya menggunakan elemen tautan sebagai tombol:
var buttonMarkup = document.createElement('a');
    buttonMarkup.className = "custom-button";
    buttonMarkup.style.display = "block";
    buttonMarkup.style.marginTop = "20px";

postFullScreen({
    openText: "Layar Penuh!",
    createButton: buttonMarkup
});

/*

akan menghasilkan ini:

<a class="custom-button" style="display:block;margin-top:20px;">Layar Penuh!</a>

*/
Atau Anda juga bisa menentukan nilainya sebagai objek yang sudah ada. Sebagai contoh Anda membuat tombol pemicu secara manual di tempat tertentu, misalnya di sidebar:
<aside>
  ...
  <button id="full-screen-button">Layar Penuh</button>
  ...
  ...
</aside>
Kemudian Anda bisa melakukan ini untuk membuat tombol tersebut menjadi aktif:
postFullScreen({
    createButton: document.getElementById('full-screen-button'),
    appendButtonTo: false
});
Jangan lupa untuk mengatur opsi appendButtonTo menjadi false karena jika tidak tombol tersebut mungkin akan berpindah tempat. Secara umum akan berpindah ke bagian akhir posting:

appendButtonTo

Opsi ini digunakan untuk menentukan ke mana tombol pemicu tampilan layar penuh akan disisipkan. Berikut ini adalah sebuah contoh jika Anda ingin menyisipkan tombol pemicu layar penuh di dalam elemen #button-container:
<div id="button-container"></div>
postFullScreen({
    ...
    appendButtonTo: document.getElementById('button-container')
});

beforeInit dan afterInit

Ini adalah opsi untuk membuat fungsi bebas yang akan tereksekusi sebelum (untuk beforeInit) dan sesudah (untuk afterInit) markup tabir tersisip ke blog. Yang paling berguna adalah beforeInit. Fungsi ini bisa Anda gunakan untuk memastikan bahwa manipulasi konten posting yang dilakukan oleh JavaScript telah dilakukan sebelum widget ini tereksekusi. Misalnya mengenai Syntax Highlighter atau JavaScript emotikon. Jika Syntax Highlighter atau JavaScript emotikon tidak diaktifkan sebelum widget ini aktif, maka kemungkinannya posting-posting kode yang berada di dalam artikel layar penuh tidak akan berwarna, dan emotikon-emotikon di dalam artikel tidak akan berubah menjadi gambar:
postFullScreen({
    beforeInit: function() {
        repText('post-12345');
        hljs.initHighlighting();
    },
    afterInit: function() {
        alert('OK!');
    }
});

Pengguna jQuery

Jangan lupa untuk menambahkan indeks [0] setelah selektor jika Anda menggunakan API selektor elemen jQuery:
postFullScreen({
    titleSource: $('.post-title')[0],
    contentSource: $('.post-body')[0]
});

Rabu, 18 Desember 2013

Panduan Mendesain Elemen-Elemen Formulir HTML dari Awal

HTML Form Elements
Elemen-elemen formulir.
Mendesain elemen UI itu bukan cuma soal menentukan efek gradiasi yang bagus, efek bayangan yang realistis dan juga pewarnaan yang cocok dengan lingkungan. Web tidak sama dengan sekedar mendesain grafis, yang artinya bahwa semuanya tidak akan bisa semudah itu dibuat menjadi tampak sama pada semua peramban. Setiap peramban memiliki spesifikasinya sendiri-sendiri, dan terkadang mereka juga memiliki spesifikasi yang sangat berbeda, yang menurut kita mungkin sangat mengganggu. Namun tentunya spesifikasi tersebut memiliki tujuan tersendiri yang sangat khusus untuk peramban terkait agar bisa bekerja dengan baik/lebih baik dibandingkan dengan peramban-peramban yang lain. Kita tidak bisa melakukan apa-apa.
Membuat desain tampilan menjadi tampak sama —atau setidaknya nyaris sama— itu tidak mudah untuk elemen-elemen formulir. Anda harus mengikuti beberapa tahapan pembentukan ulang… dan yang terpenting adalah mengenai prioritas dalam hal kestabilan tampilan dibandingkan dengan keindahan tampilan.

Memulai dengan Tahap Pembentukan Ulang

Langkah awal yang harus Anda lakukan adalah menentukan posisi, jarak, padding dan beberapa pengaturan warna serta tipe fon secara global sebisa mungkin ke semua elemen formulir yang ada:
button,
input,
select,
textarea {
  display:inline-block; /* alternatif yang lebih baik dibandingkan `display:inline` */
  vertical-align:middle; /* posisikan elemen ke tengah secara vertikal terhadap teks */
  width:170px; /* tentukan lebar elemen secara umum */
  margin:1px 0; /* tentukan `margin` elemen secara umum */
  padding:4px; /* tentukan `padding` elemen secara umum */
  font:normal normal 13px/normal Arial,Sans-Serif; /* tentukan tipe fon secara umum */
  color:#333; /* tentukan warna teks secara umum */
  line-height:normal; /* tentukan `line-height` secara umum (deklarasi `line-height` pada selektor `font` di atas biasanya tidak bekerja pada elemen `<button>`) */
  background-color:white; /* tentukan warna latar secara umum */
  border:1px solid #333; /* tentukan `border` secara umum */

  /* deklarasikan `box-sizing` yang seragam */
  -webkit-box-sizing:border-box;
  -moz-box-sizing:border-box;
  box-sizing:border-box;

  /* hapus outline jika mungkin */
  outline:none;
  outline-offset:-2px;
}
Pada kode di atas Saya juga menentukan ukuran lebar sebesar 170px secara global. Penentuan lebar elemen ini sebenarnya Saya tujukan hanya kepada elemen select dan elemen inputyang berfungsi untuk menyisipkan teks (misalnya elemen formulir bertipe dateemailnumberteltext dan url). Namun karena Saya menerapkannya pada selektor CSS berupa inputtanpa adanya penambahan atribut type secara spesifik, maka deklarasi lebar ini juga akan mempengaruhi semua elemen input yang tidak kita kehendaki, misalnya pada elemen inputbertipe button dan checkbox. Oleh karena itulah setelah pendeklarasian tersebut dilakukan, kita juga harus mengembalikan ukuran lebar pada elemen-elemen formulir yang tidak kita kehendaki memiliki ukuran lebar tetap.
Kebetulan di sini Saya mengatur nilai lebar kembali menjadi auto pada elemen-elemen formulir berupa tombol, sehingga pada saat yang bersamaan Saya juga bisa menambahkan beberapa warna baru pada elemen-elemen ini untuk membedakan tampilannya dengan elemen-elemen formulir berupa masukan teks:
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
  width:auto; /* mengembalikan ukuran lebar ke keadaan semula */
  background-color:#333; /* tentukan warna latar yang berbeda untuk elemen-elemen tombol */
  color:white; /* tentukan warna teks yang berbeda untuk elemen-elemen tombol */

  /* buat `padding` kiri dan kanan menjadi lebih lebar untuk membuatnya lebih gemuk */
  padding-right:8px;
  padding-left:8px;

  font-weight:bold; /* buat teks menjadi tebal */
  cursor:pointer; /* ubah kursor menjadi `pointer` untuk kenyamanan */
  border-color:transparent; /* opsional */
}

box-sizing

Sedikit catatan mengenai deklarasi box-sizing yang Saya tambahkan. Itu berfungsi untuk mengatasi masalah ukuran lebar yang tidak seragam terutama pada elemen formulir berupa masukan teks dan selectbox:
Text Input and Select Element without CSS `box-sizing`
Membandingkan ukuran elemen input dengan elemen select yang sudah dimodifikasi tanpa adanya deklarasi box-sizing yang seragam.
Dari gambar di atas terlihat bahwa meskipun keduanya sama-sama Saya beri ukuran lebar sebesar 170 piksel, padding sebesar 2 piksel dan border setebal 1 piksel (gambar perbandingan yang ke dua), pada kenyataannya elemen masukan teks akan menghasilkan lebar sebesar 173 piksel (border-left-width + padding-left + width + padding-right + border-right-width ), sedangkan elemen selectbox akan memiliki lebar sebesar 170 piksel (width ). Ini berarti bahwa elemen selectbox telah memiliki deklarasi box-sizing sebagai border-box secara normal, sedangkan elemen yang lain tidak —telah ditentukan oleh User Agent Stylesheet.
Anda bisa memilih untuk menentukan nilai properti ini menjadi border-box atau padding-boxkarena tujuan utama pendeklarasian properti ini memang hanya untuk menyamakan logika CSS Box-Model mereka saja. Tapi Saya sarankan untuk menggunakan border-box saja karena deklarasi ini memiliki satu keuntungan lain yaitu akan mempermudah Anda di dalam mengatasi masalah penentuan lebar elemen menuju ukuran 100% dengan hasil tampilan yang benar.
Kembalikan semua ukuran lebar elemen input bertipe checkbox dan radio serta image. Hilangkan juga deklarasi borderpadding dan background yang kita deklarasikan sebelumnya:
/* hilangkan nilai `width`, `border`, `padding`, `background` yang telah dibuat sebelumnya pada elemen-elemen ini */
input[type="checkbox"],
input[type="image"],
input[type="radio"] {
  width:auto;
  padding:0;
  background:none;
  border:none;
  cursor:pointer;
}
Setelah itu atur posisi elemen label menjadi berada di tengah secara vertikal. Atur juga tipe kursor menjadi pointer untuk menambahkan kenyamanan bagi pengguna. Bisa juga digabungkan dengan selectinput[type="color"] dan input[type="file"] untuk meringkas kode CSS (meskipun properti display dan vertical-align sebenarnya sudah ditentukan sebelumnya):
input[type="color"],
input[type="file"],
label,
select {
  display:inline-block;
  vertical-align:middle;
  cursor:pointer;
}
Atau pakai ini saja untuk CSS yang lebih panjang namun lebih logis:
input[type="color"],
input[type="file"],
select {cursor:pointer}

label {
  display:inline-block;
  vertical-align:middle;
  cursor:pointer;
}

Elemen Tombol Tampak Lebih Besar di Firefox

Mungkin Anda pernah mengalami ini. Masalahnya bukan karena kode CSS Anda yang salah, tetapi karena Firefox memiliki elemen DOM bayangan yang mengitari bagian sebelah dalam elemen button dan elemen input bertipe buttonsubmit atau reset seperti ini, yang telah membuat ukuran tombol menjadi lebih gemuk di Firefox:
::-moz-focus-inner
::-moz-focus-inner pada peramban Firefox.
CSS ini bisa mengatasi masalah tersebut:
button::-moz-focus-inner,
input::-moz-focus-inner {
  margin:0;
  padding:0;
  border:none;
  outline:none;
}

Textarea di Internet Explorer

Internet Explorer secara normal memiliki tampilan elemen textarea yang akan tetap meninggalkan scrollbar vertikal meskipun isinya kosong. Gunakan deklarasi overflow:autountuk menghilangkan scrollbar pada elemen ini agar tampilannya sama dengan apa yang terlihat di peramban lain:
textarea {overflow:auto}
Beberapa deklarasi lain yang umum untuk membuat elemen ini menjadi lebih stabil:
textarea {
  overflow:auto;
  display:block; /* set sebagai elemen blok */
  width:100%; /* buat lebarnya menjadi 100% */
  resize:vertical; /* agar `textarea` hanya bisa diubah ukurannya secara vertikal (lainnya: `both`, `horizontal`, `none`) */
}

Efek :focus:hover dan :active

Tentukan efek fokus secara global. Target utamanya adalah elemen input bertipe dateemailnumberteltext dan url serta select dan textarea:
input:focus,
select:focus,
textarea:focus {background-color:#ffa}
Setelah itu buat efek :focus:hover dan :active untuk elemen-elemen tombol:
/* focus */
button:focus,
input[type="button"]:focus,
input[type="reset"]:focus,
input[type="submit"]:focus {background-color:#00f}

/* hover */
button:hover,
input[type="button"]:hover,
input[type="reset"]:hover,
input[type="submit"]:hover {background-color:#444}

/* active */
button:active,
input[type="button"]:active,
input[type="reset"]:active,
input[type="submit"]:active {background-color:#111}

fieldset dan legend

CSS untuk mengatur tampilan fieldset dan legend:
fieldset {
  margin:0 0 1em;
  padding:1em;
  border:1px solid #333;
}

legend {
  margin:0;
  padding:0 10px;
  font-weight:bold;
}

Efek :disabled

Bisa menggunakan selektor pseudo kelas :disabled, tapi Saya sarankan untuk menggunakan selektor atribut saja yang memiliki dukungan peramban lebih bagus:
button[disabled],
input[disabled],
select[disabled],
textarea[disabled] {
  opacity:.7; /* buat warnanya menjadi kabur */
  cursor:default; /* fallback */
  cursor:not-allowed; /* CSS3 */
}

Efek :readonly

Hanya untuk elemen formulir masukan teks dan area teks:
input[type="date"][readonly],
input[type="email"][readonly],
input[type="number"][readonly],
input[type="tel"][readonly],
input[type="text"][readonly],
input[type="url"][readonly],
textarea[readonly],
input[type="date"][readonly]:focus,
input[type="email"][readonly]:focus,
input[type="number"][readonly]:focus,
input[type="tel"][readonly]:focus,
input[type="text"][readonly]:focus,
input[type="url"][readonly]:focus,
textarea[readonly]:focus {
  background-color:#eee;
  cursor:default;
}

Mengubah Warna Placeholder

Berikut ini beberapa selektor CSS elemen pseudo dengan prefiks khusus yang berbeda-beda pada setiap peramban. Untuk alasan yang tidak Saya tahu, semua selektor ini tidak bisa digabungkan dengan tanda koma:
::-webkit-input-placeholder {color:#999} /* WebKit */
:-ms-input-placeholder {color:#999} /* IE 9+ */
::-moz-placeholder {color:#999} /* Firefox 19+ */
:-moz-placeholder {color:#999} /* Firefox 18- */
:placeholder {color:#999} /* W3C */

:focus::-webkit-input-placeholder {color:#b9b989}
:focus:-ms-input-placeholder {color:#b9b989}
:focus::-moz-placeholder {color:#b9b989}
:focus:-moz-placeholder {color:#b9b989}
:focus:placeholder {color:#b9b989}

Yap!

Itu adalah garis besarnya. Beberapa yang lain di bawah ini mungkin bisa Anda tambahkan tapi ini spesifik untuk peramban WebKit:
/* mengubah tampilan simbol panah pada elemen `<select>` */
select {
  -webkit-appearance:none;
  background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAASCAYAAAC0EpUuAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB90MEg4aKjycyUMAAABJSURBVDjLYzQ0NPzPQCE4d+4cIzKfiYEGYNTQkWwoC450h1ODkZEReS7FpZEYA/F6H90AYg0kGKYwg0gxkKiIItXA0XQ6hAwFADv7Cz1+RA3TAAAAAElFTkSuQmCC');
  background-repeat:no-repeat;
  background-position:100% 50%;
}

select[multiple],
select[size] {background-image:none}

/* mengubah tampilan tombol pada elemen `<input type="file">` */
input[type="file"] {-webkit-appearance:none}
input[type="file"]::-webkit-file-upload-button {
  -webkit-appearance:none;
  display:inline-block;
  vertical-align:top;
  background-color:#333;
  color:white;
  font-size:11px;
  font-weight:bold;
  margin:0;
  padding:2px 5px;
  border:none;
  cursor:pointer;
}

/* `<input type="range">` */
input[type="range"] {
  -webkit-appearance:none;
  height:0;
  padding:1px 0;
  border:1px solid #333;
  background-color:white;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance:none;
  margin:0;
  padding:0;
  border:none;
  background-color:#333;
  width:10px;
  height:18px;
  cursor:w-resize;
}

input[type="range"]::-webkit-slider-thumb:hover {background-color:#444}
input[type="range"]::-webkit-slider-thumb:active {background-color:#111}
Beberapa tautan yang Saya sarankan untuk mempelajari hal-hal terkait Shadow DOM:

Berikut ini adalah hasil akhir untuk semua hal yang telah Saya jelaskan di atas. Ini bisa dikatakan sebagai kerangka dasar, sehingga Anda bisa cukup salin-tempel kode ini saja dengan aman ke dalam berkas CSS pada setiap awal mendesain:
/* TAHAP PEMBENTUKAN ULANG */

button,
input,
select,
textarea {
  display:inline-block; /* alternatif yang lebih baik dibandingkan `display:inline` */
  vertical-align:middle; /* posisikan elemen ke tengah secara vertikal terhadap teks */
  width:170px; /* tentukan lebar elemen secara umum */
  margin:1px 0; /* tentukan `margin` elemen secara umum */
  padding:4px; /* tentukan `padding` elemen secara umum */
  font:normal normal 13px/normal Arial,Sans-Serif; /* tentukan tipe fon secara umum */
  color:#333; /* tentukan warna teks secara umum */
  line-height:normal; /* tentukan `line-height` secara umum (deklarasi `line-height` pada selektor `font` di atas biasanya tidak bekerja pada elemen `<button>`) */
  background-color:white; /* tentukan warna latar secara umum */
  border:1px solid #333; /* tentukan `border` secara umum */

  /* deklarasikan `box-sizing` yang seragam */
  -webkit-box-sizing:border-box;
  -moz-box-sizing:border-box;
  box-sizing:border-box;

  /* hapus outline jika mungkin */
  outline:none;
  outline-offset:-2px;
}


/* TOMBOL */

button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
  width:auto; /* mengembalikan ukuran lebar ke keadaan semula */
  background-color:#333; /* tentukan warna latar yang berbeda untuk elemen-elemen tombol */
  color:white; /* tentukan warna teks yang berbeda untuk elemen-elemen tombol */

  /* buat `padding` kiri dan kanan menjadi lebih lebar untuk membuatnya lebih gemuk */
  padding-right:8px;
  padding-left:8px;

  font-weight:bold; /* buat teks menjadi tebal */
  cursor:pointer; /* ubah kursor menjadi `pointer` untuk kenyamanan */
  border-color:transparent; /* opsional */
}


/* PERBAIKI DIMENSI BEBERAPA ELEMEN INI */

/* hilangkan nilai `width`, `border`, `padding`, `background` yang telah dibuat sebelumnya pada elemen-elemen ini */
input[type="checkbox"],
input[type="image"],
input[type="radio"] {
  width:auto;
  padding:0;
  background:none;
  border:none;
  cursor:pointer;
}

/*
Anda mungkin akan membutuhkan ini untuk memastikan agar
posisi checkbox dan radio bisa berada tepat di tengah secara vertikal.
Saya mengomentari deklarasi CSS ini dan tidak menjelaskannya
secara khusus di atas karena Saya pikir ini adalah
praktek Magic Number yang tidak disarankan. 

input[type="checkbox"],
input[type="radio"] {
  position:relative;
  top:-2px;
}

*/

/* set tipe kursor ke `pointer` untuk kenyamanan */
input[type="color"],
input[type="file"],
label,
select {
  display:inline-block;
  vertical-align:middle;
  cursor:pointer;
}

/* textarea */
textarea {
  overflow:auto;
  display:block; /* set sebagai elemen blok */
  width:100%; /* buat lebarnya menjadi 100% */
  resize:vertical; /* agar `textarea` hanya bisa diubah ukurannya secara vertikal (lainnya: `both`, `horizontal`, `none`) */
}


/* MENORMALKAN ::-moz-focus-inner PADA TOMBOL-TOMBOL DI FIREFOX */

button::-moz-focus-inner,
input::-moz-focus-inner {
  margin:0;
  padding:0;
  border:none;
  outline:none;
}


/* PSEUDO KELAS - :hover, :focus, :active */

/* focus */
input:focus,
select:focus,
textarea:focus {background-color:#ffa}

/* focus */
button:focus,
input[type="button"]:focus,
input[type="reset"]:focus,
input[type="submit"]:focus {background-color:#00f}

/* hover */
button:hover,
input[type="button"]:hover,
input[type="reset"]:hover,
input[type="submit"]:hover {background-color:#444}

/* active */
button:active,
input[type="button"]:active,
input[type="reset"]:active,
input[type="submit"]:active {background-color:#111}


/* FIELDSET & LEGEND */

fieldset {
  margin:0 0 1em;
  padding:1em;
  border:1px solid #333;
}

legend {
  margin:0;
  padding:0 10px;
  font-weight:bold;
}


/* DISABLED */

button[disabled],
input[disabled],
select[disabled],
textarea[disabled] {
  opacity:.7; /* buat warnanya menjadi kabur */
  cursor:default; /* fallback */
  cursor:not-allowed; /* CSS3 */
}


/* READONLY */

input[type="date"][readonly],
input[type="email"][readonly],
input[type="number"][readonly],
input[type="tel"][readonly],
input[type="text"][readonly],
input[type="url"][readonly],
textarea[readonly],
input[type="date"][readonly]:focus,
input[type="email"][readonly]:focus,
input[type="number"][readonly]:focus,
input[type="tel"][readonly]:focus,
input[type="text"][readonly]:focus,
input[type="url"][readonly]:focus,
textarea[readonly]:focus {
  background-color:#eee;
  cursor:default;
}


/* PLACEHOLDER */

::-webkit-input-placeholder {color:#999} /* WebKit */
:-ms-input-placeholder {color:#999} /* IE 9+ */
::-moz-placeholder {color:#999} /* Firefox 19+ */
:-moz-placeholder {color:#999} /* Firefox 18- */
:placeholder {color:#999} /* W3C */

:focus::-webkit-input-placeholder {color:#b9b989}
:focus:-ms-input-placeholder {color:#b9b989}
:focus::-moz-placeholder {color:#b9b989}
:focus:-moz-placeholder {color:#b9b989}
:focus:placeholder {color:#b9b989}
Setiap kali Anda mendesain elemen atom, selalu pastikan untuk menyelesaikan masalah-masalah di atas terlebih dahulu. Jika tidak, mungkin Anda akan mengalami berbagai kesulitan saat menangani masalah penampilan pada peramban-peramban tertentu.
Selain itu setidaknya Anda baru bisa/boleh mendesain tampilan elemen-elemen formulir setelah Anda menyelesaikan masalah tampilan elemen-elemen artikel. Setelah itu, Anda bisa memulai untuk menambahkan efek gradiasi, bayangan dan menyesuaikan warna-warna elemen-elemen formulir yang ada sesuai kehendak:

Jumat, 13 Desember 2013

Daftar Salinan Berkas Widget, Halaman Demo dan Templat dari Artikel-Artikel di Blog Ini

Pembaharuan: Kode sumber yang telah Saya perbaharui sekarang sudah berpindah ke akun GitHub Saya.
Setelah memperbaharui beberapa widget dan kemudian mengunggahnya kembali ke proyek Google Code yang baru, pada saat yang bersamaan sebenarnya Saya juga telah membuat salinannya di DropBox dengan harapan apabila suatu hari nanti terdapat masalah lagi pada proyek Google Code Saya, maka Saya bisa memberikan alternatif kepada kalian semua untuk mengunduh berkas salinan yang sudah Saya unggah di DropBox.
Semua tautan di bawah ini bukanlah tautan yang akan mengarahkan Anda menuju berkas secara langsung. Ini adalah tautan yang akan mengarahkan Anda menuju ke halaman unduhan, sehingga Anda harus mengunduh berkasnya terlebih dahulu, kemudian setelah mengunduh Anda harus mengunggahnya ke akun Google masing-masing. Bisa ke Google Drive atau ke Google Code:

ZIP

https://www.dropbox.com/s/cm2xhoh2if1nb4p/210492.zip
https://www.dropbox.com/s/9lfr56dy6w6wqqf/B1-A.zip
https://www.dropbox.com/s/vuqtu0iblq1ax65/CSS3DropDownMenuTemplate.zip
https://www.dropbox.com/s/dk7zicztidzxyui/Dropdowns.zip
https://www.dropbox.com/s/aur3vy8pmylmm3s/emo.zip
https://www.dropbox.com/s/4ttyepa6qkfos1z/flat-file-guestbook.zip
https://www.dropbox.com/s/sncmklr88jbuhic/jimp.zip
https://www.dropbox.com/s/64xchxolcj92cqz/JQueryPageScrolling.zip
https://www.dropbox.com/s/umxyxx49h55w6e0/NivoSlider-Examples.zip
https://www.dropbox.com/s/6vwcn6zpgo7yu7f/parallax-demo.zip
https://www.dropbox.com/s/614p81rh21n279i/Recreate-TutsPlus-Nav.zip
https://www.dropbox.com/s/gzsm4mb0i8yn4s9/Red-Rose-Blogger-Template.zip
https://www.dropbox.com/s/hx452l367unmgbw/Simple-JQuery-Modal-Dialog.zip
https://www.dropbox.com/s/lsp84idmtrnwozi/Toolpik.zip
https://www.dropbox.com/s/e16ujn4718diz8c/Tooltip-Click.zip
https://www.dropbox.com/s/op8rcodv24kyrut/Understanding-Nivo.zip

CSS

https://www.dropbox.com/s/3hudk3oap7cgft2/accordion-toc-skin.css
https://www.dropbox.com/s/cto35dbafrhxc04/blogger-toc-with-pagination_construction-theme.css
https://www.dropbox.com/s/8o3ane98yl16o18/blogger-toc-with-pagination_css3-diary-book-theme.css
https://www.dropbox.com/s/kudh1kxaz1ev1or/blogger-toc-with-pagination_dark-blue-theme.css
https://www.dropbox.com/s/ogsovt5mdeglwhx/blogger-toc-with-pagination_dark-red-theme.css
https://www.dropbox.com/s/zd2cpscjatv8llb/blogger-toc-with-pagination_default-theme.css
https://www.dropbox.com/s/lyj0jrhuvez1862/blogger-toc-with-pagination_elegant-black-theme.css
https://www.dropbox.com/s/4qn4k2wu75iosaz/blogger-toc-with-pagination_facebook-theme.css
https://www.dropbox.com/s/c4jc46z0ejmhxjo/blogger-toc-with-pagination_minima-brown-theme.css
https://www.dropbox.com/s/0gzp5022l6evqep/blogger-toc-with-pagination_minima-white-theme.css
https://www.dropbox.com/s/340gpie3m5vstwv/blogger-toc-with-pagination_yellow-green-theme.css
https://www.dropbox.com/s/s5relsppcix58hj/tabbed-toc-skin.css

Folder

https://www.dropbox.com/sh/ykqcdna6vhpqvj9/nuoB_N8S9b (blogger-feed-rotator-plugin)
https://www.dropbox.com/sh/6f1kux9lvt6m3x6/C3y5KaC9md (blogger-json-experiment)
https://www.dropbox.com/sh/ealca01myte9k5x/gDwK--6UGL (Blogger-Masonry-Widget)
https://www.dropbox.com/sh/lgbt6odiz4c22te/ebB1Yol7Cy (dialog-box)
https://www.dropbox.com/sh/ewiyu3y405a5fsu/kzwFUn1FM6 (jquery-custom-selectbox)
https://www.dropbox.com/sh/60frfrs5ye1701z/jbnDqekhYv (jquery-draggable)
https://www.dropbox.com/sh/rw3deaz7bdg8gyw/d9AWPN7fsH (json-demo)
https://www.dropbox.com/sh/wsu6a650vu9dtal/B2M5rESiuZ (long-dropdown)
https://www.dropbox.com/sh/3eoie8pesy30o8o/g0iMCbwPik (multi-feed)
https://www.dropbox.com/sh/0vclbeclkt31ztg/BEalwSfawx (myTooltip)
https://www.dropbox.com/sh/b6m65cws5mjmthl/W1iP-_rRt2 (random-post)
https://www.dropbox.com/sh/5tnoqtb5jn8ccq3/NjpcXYPfnd (related-post)
https://www.dropbox.com/sh/b45q1h717ww3m0b/CgIAIGVgEj (SimpleTab)
https://www.dropbox.com/sh/eoyonihrhtsvpsy/GvWxta1qy_ (StickyBar)

HTML

https://www.dropbox.com/s/j1d80txis4ymf2s/basic-slideshow.html
https://www.dropbox.com/s/dyrrzemyfvd0vnh/cookie-jquery.html
https://www.dropbox.com/s/sta5cnq7mphk9s9/css-mobile-navigation-concept.html
https://www.dropbox.com/s/vku05wy3elt9516/css-siblings-selector-demonstration.html
https://www.dropbox.com/s/bp82ygne2bi40v5/css-switcher.html
https://www.dropbox.com/s/4aqr1rvmbd6h3hy/demo-javascript-set-value-from-url.html
https://www.dropbox.com/s/0a293sono7f5h2r/easing-demo.html
https://www.dropbox.com/s/0v4lumf0wek5kfv/full-page-horizontal-scrolling.html
https://www.dropbox.com/s/yibhx5h8e17f4v3/javascript-custom-scrollbar.html
https://www.dropbox.com/s/qzqj7khqyvfida8/javascript-for-blogger-comments.html
https://www.dropbox.com/s/nj3wwsxv0o6a39s/personal-css-framework-example.html
https://www.dropbox.com/s/wsua2vm1bixyy4k/piksel-dan-persen-dalam-sistem-grid.html
https://www.dropbox.com/s/3yohtwiuiifq6oy/raw-masonry.html
https://www.dropbox.com/s/c63hw4rlyy22ggj/simple-hoverintent-plugin.html
https://www.dropbox.com/s/akd1j7jys0387pq/simple-useful-jquery-slideshow.html
https://www.dropbox.com/s/ecnedfsotov6kkg/simple-useful-jquery-slideshow_nivo-slider-like-effect.html
https://www.dropbox.com/s/v0nqgg9mmu0phzf/simple-useful-jquery-slideshow_with-caption.html
https://www.dropbox.com/s/8djzti6km22zqrs/simple-useful-jquery-slideshow_with-caption_with-fade-effect.html

JavaScript

https://www.dropbox.com/s/7fz4hdhwbtp6cuv/accordion-toc-1.js
https://www.dropbox.com/s/a3yjxu7mr7chsmf/accordion-toc-2.js
https://www.dropbox.com/s/s92ve64ke089kzl/artikel-terkait-deskripsi.js
https://www.dropbox.com/s/3mbdccyzfhkveqb/blogger-3d-gallery.js
https://www.dropbox.com/s/xjf7a7p6n08qjql/blogger-imageflow.js
https://www.dropbox.com/s/y6f64b8iv5vdg2h/blogger-popform.js
https://www.dropbox.com/s/1kp8hpfso2ixf4b/blogger-quick-search.js
https://www.dropbox.com/s/nytyhws4x9051pp/blogger-recent-post-with-preloader.js
https://www.dropbox.com/s/kv7aj6jhut5qey9/blogger-s3slider.js
https://www.dropbox.com/s/qkfp5p7orgl27mx/blogger-slide-panel-comments.js
https://www.dropbox.com/s/0wbce2rpk1skazn/blogger-slidesjs.js
https://www.dropbox.com/s/x1gjnrrvguvcsm4/blogger-tinycarousel.js
https://www.dropbox.com/s/aglsf3j0vjreotv/blogger-toc-with-pagination.js
https://www.dropbox.com/s/a5lgc8plcob3al8/cookie.js
https://www.dropbox.com/s/hgmosvf82hst428/full-screen.js
https://www.dropbox.com/s/kgvymfyormdge1g/full-screen.min.js
https://www.dropbox.com/s/m2n546tn68rm4q2/javascript-hujan-bintang.js
https://www.dropbox.com/s/nxylkar11592dmo/jquery-emoticons.js
https://www.dropbox.com/s/aiwv0zqckji8epj/jquery-toggle-sidebar.js
https://www.dropbox.com/s/rkkdnbs3diy7n8g/jquery-toggle-sidebar.min.js
https://www.dropbox.com/s/5eyobs5d8ydh0gp/json-dropdown.js
https://www.dropbox.com/s/rbbope90ijai0c3/prism.js
https://www.dropbox.com/s/mzug36uo0o8m8fi/recent-comments-script-with-notification.js
https://www.dropbox.com/s/6xhmvvmri0cq2hd/rp-mini-gallery.js
https://www.dropbox.com/s/qrxzj1yi1q0j3os/rp-newsticker.js
https://www.dropbox.com/s/ch42iu7zq7c8u82/tabbed-toc.js
https://www.dropbox.com/s/x26i5puflbgrgdx/toc-table-sort.js
Cara terbaik yang Saya sarankan untuk menghindari hal-hal yang tidak diinginkan pada widget Anda adalah dengan mengunduh berkas eksternal yang ada pada setiap artikel agar bisa kalian unggah ke dalam akun Google masing-masing. Atau cukup dengan cara menempelkan berkas JavaScript dan CSS secara inline di dalam templat. Hanya saja kekurangannya mungkin Anda akan ketinggalan pembaharuan yang terjadi jika sewaktu-waktu Saya melakukan pembaharuan pada widget tersebut. Tapi jangan khawatir! Sampai saat ini sepertinya semua widget buatan Saya sudah bisa berjalan dengan stabil tanpa keluhan, sehingga Saya rasa Saya tidak akan melakukan pembaharuan lagi pada widget-widget tersebut.
Mengenai permintaan penambahan fitur, diskusi pembaharuan atau saran modifikasi biasanya sudah Saya jelaskan pada komentar-komentar yang ada di bawah masing-masing artikel yang terkait dengan berkas tersebut. Anda tinggal membacanya saja dan mempelajarinya untuk kemudian menerapkannya sendiri.
Semua berkas di atas secara umum berada di bawah lisensi Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License dengan beberapa keringanan yang Saya buat setelah mempertimbangkan banyak hal, yang rencananya akan Saya buat tersendiri di dalam sebuah halaman khusus. Tapi saat ini belum ada. Untuk sementara Anda boleh berpedoman pada lisensi tersebut saja.
Saya tidak tahu apakah masih ada halaman lain di dalam blog ini yang memiliki tautan rusak. Kalau Anda kebetulan menemukan halaman seperti itu, mohon jangan sungkan-sungkan untuk mengeklik tombol Sunting yang tersedia pada setiap artikel agar Saya bisa segera memperbaiki kerusakan yang ada. Terima kasih.

Kamis, 05 Desember 2013

Mengubah Tipe Kursor pada Scrollbar

Mengubah Tipe Pointer Scrollbar
Kursor pada scrollbar berubah menjadi pointer.
Mungkin ini tidak penting tapi terkadang kita merasa bahwa menggeser-geser scrollbar dengan kursor bertipe pointer akan terasa lebih “enak” dibandingkan dengan menggeser-geser scrollbar dengan kursor bertipe default. Akan tetapi mengubah tipe kursor pada scrollbar tidak mungkin bisa dilakukan karena scrollbar tidak termasuk ke dalam elemen HTML (pengecualian jika kita menggunakan manipulasi seperti JavaScript Custom Scrollbar, karena setiap item penggulung dibuat menggunakan elemen HTML). Bahkan selektor CSS scrollbar milik WebKitpun tidak bisa dimanipulasi:
::-webkit-scrollbar-thumb {
  cursor:pointer; /* tidak bekerja! :( */
}
Satu cara sederhana yang bisa kita lakukan untuk mengubah tipe kursor pada scrollbar adalah dengan menerapkan tipe kursor menjadi pointer secara keseluruhan kepada area yang diinginkan, kemudian mengembalikan tipe kursor ke keadaan semula pada bagian dalam. Di sini kita membutuhkan elemen pembungkus ekstra:

HTML

<div class="scrollable-area">
  <div class="scrollable-area-content">
    <p>Lorem ipsum dolor sit amet...</p>
  </div>
</div>

CSS

.scrollable-area {cursor:pointer}
.scrollable-area-content {cursor:auto}

Demo

Contoh lain, mengubah tipe kursor menjadi n-resize pada scrollbar vertikal dengan tampilan kustom (buka halaman demo menggunakan peramban Google Chrome atau Safari):

Senin, 04 November 2013

Throttle dan Debounce

Throttle and Debounce Diagram
Dalam JavaScript, istilah throttle dan debounce biasa digunakan untuk menyatakan mengurangi atau menunda eksekusi fungsi yang bekerja berkali-kali, misalnya ketika pengguna sedang mengubah ukuran layar atau menggerak-gerakkan pointer mouse. Tujuan utama dari metode ini adalah untuk memastikan agar eksekusi fungsi bisa bekerja seefektif dan seefisien mungkin sekaligus juga sejarang mungkin, sehingga peramban tidak akan terlalu terbebani di dalam mengeksekusi fungsi yang terjadi berkali-kali, yang belum tentu juga fungsi tersebut memang perlu untuk dijalankan sesering itu.

Throttle

Metode ini berdasar pada sebuah usaha untuk membuat jumlah eksekusi fungsi menjadi lebih jarang dari event yang terjadi. Di sini, fungsi bernama foo() akan dieksekusi setiap 1 detik sekali selama kita menggerak-gerakkan pointer mouse di atas dokumen dan bukannya setiap kali pointer mouse berkerak:
var delay = 1000, // Interval pembatas/penundaan eksekusi berikutnya (milidetik)
    previousCall = new Date().getTime(); // Set waktu kadaluarsa awal
document.onmousemove = function() {
    var time = new Date().getTime();
    // Bandingkan antara waktu terakhir kali eksekusi dengan waktu setiap kali event bekerja.
    // Jika selisihnya sudah mencapai/melebihi `delay`, jalankan fungsi `foo()`
    if ((time - previousCall) >= delay) {
        foo();
        previousCall = time; // Set ulang waktu kadaluarsa
    }
};

function foo() {
    console.log('test!');
}

Debounce

Metode ini berdasar pada sebuah usaha untuk membuat fungsi tereksekusi hanya jika pengguna telah berhenti melakukan suatu event yang berulang, atau hanya dieksekusi sekali saja saat pertama kali event terjadi. Misalnya ketika pengguna berhenti menggerakkan pointer mouse saja atau ketika pengguna mulai menggerakkan pointer mouse saja. Yang paling umum diterapkan adalah kasus yang pertama.
Fungsi di bawah ini terdiri dari penunda berupa setTimeout di dalam jenis event sensitif yang bisa mengeksekusi fungsi berkali-keli setiap kali pengguna menggerakkan pointer mouse di atas dokumen. Namun karena pada saat yang bersamaan fungsi clearTimeout menggagalkan setTimeout untuk mencapai akhir waktu tunda, maka fungsi foo() tidak akan pernah bisa tereksekusi sebelum pengguna benar-benar menghentikan gerakkan pointer mouse mereka:
var timer = null;
document.onmousemove = function() {
    if (timer) clearTimeout(timer); // Hentikan `setTimeout` sesegera mungkin agar `foo()` tidak tereksekusi
    timer = setTimeout(function() {
        foo(); // Jalankan fungsi `foo()` jika timer tidak lagi dihentikan oleh `clearTimeout`
        timer = null;
    }, 300);
};

function foo() {
    console.log('test!');
}
Waktu penunda selama 300 milidetik dibuat hanya sebagai toleransi saja untuk memastikan agar waktu eksekusi berjalan lebih lambat dari pergerakkan pointer mouse pengguna:

Beberapa Event JavaScript yang Masuk dalam Kategori Sensitif

Saya menyebutnya sebagai event yang sensitif karena event ini bisa mengeksekusi fungsi berkali-kali dengan cepat jika sedang dikerjakan oleh pengguna. Beberapa di antaranya adalah:
  • onmousemove (menggerakkan)
  • onscroll (menggulung)
  • onresize (mengubah ukuran)
  • onkeyup (mengetik)
  • onkeydown (mengetik)
  • onkeypress (mengetik)

Contoh Penerapan dalam Kasus Nyata

Berikut ini adalah sebuah gambaran penerapan debounce untuk mencegah AJAX memanggil data berkali-kali pada saat pengguna mengetik kata kunci pencarian. Di sini, data hanya akan terpanggil hanya jika pengguna telah berhenti mengetik:
<input type="text" id="search-field">
<div id="search-result"></div>

<script src="js/jquery.js"></script>
<script>
var timer = null;
$('#search-field').on("keydown", function() {
    var keyword = this.value;
    if (timer) clearTimeout(timer);
    timer = setTimeout(function() {
        // Panggil data!
        $.get('http://sumber_data.com/search?q=' + keyword, function(data) {
            $('#search-result').html($(data));
        });
        timer = null;
    }, 300);
});
</script>
Saya tidak begitu sering melihat penerapan metode throttle dalam kasus yang nyata. Tapi pada intinya, metode ini berfungsi untuk menunda fungsi agar fungsi tersebut tereksekusi dalam interval waktu tertentu saja pada saat pengguna menjalankan event.
Beberapa manfaat lain dari metode ini:
  1. Membuat aplikasi yang dapat menyimpan data secara otomatis setiap kali pengguna berhenti mengetik.
  2. Fitur penelusuran dengan AJAX yang memungkinkan pengguna untuk memanggil data tanpa harus memaksa pengguna untuk menekan tombol Submit. Cukup dengan mengetik kata kunci dan berhenti, maka hasil penelusuran akan segera dimuat.
  3. Mengubah dan mengatur ulang posisi elemen dalam jumlah yang banyak dengan perhitungan yang rumit setiap kali pengguna mengubah ukuran layar pada interval tertentu.

Sabtu, 02 November 2013

Border Semitransparan untuk Menciptakan Efek Tajam dan Tipis pada Elemen

Saya secara alami sering dan suka memperhatikan hal-hal yang detail, terutama pada elemen-elemen UI di dalam web-web terkenal seperti GoogleFacebook dan juga berbagai frameworkweb. Kali ini Saya akan membahas mengenai tampilan menu dropdown pada frameworkBootstrap ini:
Bootstrap Dropdown
Menu dropdown pada Bootstrap.
Tampilannya terlihat sangat tajam dan dimensinya juga terlihat sangat tipis! Bagi Anda yang sudah terbiasa bekerja dengan aplikasi Photoshop dan sejenisnya mungkin tidak begitu asing dengan teknik untuk membuat efek seperti ini.
Pada kenyataannya, menciptakan elemen kotak dengan efek bayangan saja tidak cukup untuk memberikan kesan sisi yang tajam dan dimensi yang tipis seperti gambar di atas:
/* Belum cukup! */
.box {
  background-color:white;
  border:1px solid #bbb;
  box-shadow:0 4px 15px -4px rgba(0,0,0,.6);
}
Deklarasi di atas sudah cukup untuk menciptakan efek kotak bergaris batas dan berbayang, namun tidak cukup utuk memberikan efek tajam pada elemen tersebut. Jika Anda memperhatikan dengan seksama pada menu dropdown di gambar pertama, maka seharusnya Anda akan menyadari bahwa garis batas pada menu tersebut ternyata tembus pandang:
Bootstrap Dropdown
Pembesaran tampilan.
Efek semacam ini tidak cukup dibuat hanya dengan warna solid dan bayangan, melainkan kita membutuhkan warna semi transparan pada border. Kita bisa menggunakan kode warna RGBAatau HSLA pada border:
.box {
  background-color:white;
  border:1px solid rgba(0,0,0,.3);
  box-shadow:0 4px 15px -4px rgba(0,0,0,.6);
}
Tapi sekarang efek transparan pada border justru menampilkan warna latar dari elemen .box di bagian bawahnya karena warna latar secara normal memang akan menembus sampai ke sisi terluar dari border (Anda bisa mengeceknya dengan mencoba mengubah tipe border menjadi dashed atau dotted). Untuk mencegah warna latar agar tidak melebihi batas dalam lingkar border, kita bisa menggunakan CSS background-clip dengan nilai padding-box:
.box {
  background-color:white;
  border:1px solid rgba(0,0,0,.3);
  background-clip:padding-box;
  box-shadow:0 4px 15px -4px rgba(0,0,0,.6);
}

Membandingkan Hasil Tampilan

Berikut ini adalah gambar cuplikan hasil tampilan pada efek sebelum dan efek sesudah:
Efek Tajam dengan CSS
Efek sebelum dan sesudah.

Penggunaan Properti background-clip Lainnya

Fungsi CSS background-clip adalah untuk menentukan apakah latar belakang elemen, baik warna atau gambar, akan meluas ke bagian bawah perbatasan atau tidak. Nilai padding-boxpada properti ini memungkinkan warna latar yang secara normal akan melebar dan melebihi batas sebelah dalam dari lingkar border menjadi tidak melebihi batas tersebut. Selengkapnya mengenai CSS background-clip bisa Anda pelajari di sini
Secara pribadi Saya jarang menggunakannya untuk kepentingan dekorasi. Melainkan, Saya lebih sering menggunakan properti ini untuk memperbaiki tampilan yang sedikit rusak karena renderpiksel yang tidak terlalu baik pada beberapa peramban. Sebagai contoh adalah pada elemen tombol dengan efek rouded corner di sekelilingnya seperti ini:
CSS3 Button
Gambar sebelah kiri adalah tampilan standar tombol yang dibuat tanpa mendeklarasikan background-clip:padding-box. Jika Anda meperhatikannya dengan seksama, maka pada bagian sisi-sisi lengkungnya akan tampak sedikit warna latar yang melebihi batas. Saya tidak tahu mengapa, tetapi ini hanya terjadi pada elemen tombol yang dikenai deklarasi display:inline, sedangkan tombol dengan deklarasi display:inline-block atau display:block tidak mengalami masalah ini. Ini terjadi di Google Chrome.
Gambar sebelah kanan adalah hasil tampilan sesudah Saya menerapkan deklarasi background-clip:padding-box pada tombol. Terlihat lebih rapi, karena warna latar tidak menembus bagian sisi tombol.
Kembali kepada efek tajam dan super tipis pada menu dropdownGoogle Chrome juga mengimplementasikan hal yang sama, hanya saja sepertinya dia menggunakan latar gambar, bukan CSS:
Google Chrome Dropdown
Menu dropdown pada Google Chrome.
Pada Google Chrome versi lama, Anda pasti pernah melihat sebuah menu di bagian kanan bawah bernama “Barusan Ditutup” yang jika diklik akan menampilkan daftar histori munculan yang juga memiliki kesan yang sama seperti yang sedang kita bahas sekarang, akan tetapi efek itu diciptakan menggunakan metode yang sedikit berbeda dan Saya pikir ini sudah tidak standar lagi karena hasilnya yang kurang rapi dan tidak konsisten. Bukan menggunakan border semitransparan dan CSS background-clip, melainkan menggunakan outline semitransparan. Hasilnya kurang bagus karena outline tidak bisa mengikuti efek lengkung di ujung-ujung kotak. Saya menambahkan ini sebagai pengetahuan tambahan saja. Seharusnya Saya membahas ini sebelum peramban tersebut diperbaharui sampai yang seperti sekarang:
Outline Semitransparan
Outline tidak bisa mengikuti garis lengkung.
.box {
  background-color:white;
  box-shadow:0 0 3px rgba(0,0,0,.8);
  outline:1px solid rgba(0,0,0,.4);
  outline-offset:-3px;
}
Teknik lainnya adalah dengan menggunakan CSS bayangan murni, tanpa border:
.box {
  background-color:white;
  box-shadow:0 0 0 1px rgba(0,0,0,.3),0 4px 15px -4px rgba(0,0,0,.6);
}
Ini adalah teknik tersingkat, karena kita bahkan tidak memerlukan properti background-clipuntuk menciptakan efeknya di sini. Hanya saja, jika peramban tidak mendukung CSS bayangan atau tidak mendukung CSS bayangan berganda atau tidak mendukung nilai spread pada CSS bayangan, maka efek garis batasnya tidak akan terlihat. Border memungkinkan kita untuk menciptakan fallback agar tampilan elemen tidak menjadi terlalu buruk pada peramban yang tidak mendukung CSS bayangan dan warna RGBA. Begini maksudnya:
.box {
  background-color:white;
  border:1px solid #bbb; /* warna fallback untuk peramban yang tidak mendukung warna RGBA */
  border:1px solid rgba(0,0,0,.3); /* warna border yang seharusnya */
  background-clip:padding-box;
  box-shadow:0 4px 15px -4px rgba(0,0,0,.6);
}

Minggu, 06 Oktober 2013

Efek Masonry Hanya dengan CSS

CSS3 Masonry Layout
Teknik ini sudah pernah dibahas dengan cukup detail di CSS-Tricks. Hanya saja Saya tidak habis pikir mengapa beliau tetap mempertahankan deklarasi column-count untuk memecah area menjadi beberapa kolom dan menggunakan media queries untuk mengurangi jumlah kolom pada saat ukuran layar peramban menyempit. Padahal jika kita sudah menentukan lebar masing-masing item dengan ukuran yang sama, kita bisa menggunakan column-width untuk menentukan lebar kolom tetap tanpa harus melibatkan media queries untuk mengurangi jumlah kolom pada saat ukuran layar semakin sempit. column-width akan menciptakan kolom-kolom dengan jumlah yang bisa menyesuaikan diri berdasarkan ruang yang tersisa. Sudah tertulis dengan jelas dalam spesifikasi:
.container {
  column-width:150px;
  column-gap:5px; /* Margin kanan/kiri antarkolom */
}

img {
  display:block;
  width:100%;
  height:auto;
  margin:0 0 5px 0; /* Margin bawah antargambar */
}

Item Bukan Gambar

Ada satu hal yang harus diperhatikan jika Anda ingin menciptakan efek/tata letak seperti ini pada elemen yang bukan merupakan gambar, yaitu deklarasi display berupa inline-block. Mendeklarasikan perintah ini akan mencegah perpotongan yang tak terduga pada masing-masing item karena CSS3 Kolom secara normal akan berusaha untuk membuat masing-masing kolom menjadi sama tinggi. Beberapa harus terpaksa dipotong di bagian bawah mengingat properti CSS ini memang sebenarnya berbasis teks:
.container {
  column-width:150px;
  column-gap:5px; /* Margin kanan/kiri antarkolom */
}

.item {
  display:inline-block; /* Mencegah pemotongan item yang tak terduga */
  margin:0 0 5px 0; /* Margin bawah antaritem */
  padding:10px;
  background-color:black;
  color:white;
}

Ini yang Saya maksud sebagai perpotongan yang tidak diduga dan tidak dikehendaki:
Item terpotong pada akhir kolom pada tempat yang salah.
Teks terpotong pada bagian bawah untuk memastikan agar masing-masing kolom memiliki tinggi yang sama.
Tidak tahu apa itu Masonry?

Sabtu, 05 Oktober 2013

JavaScript Table Sorter

Skrip ini bisa digunakan untuk menyortir tabel dengan tampilan yang sederhana:

JavaScript

// Original code: http://stackoverflow.com/a/14268260/1163000
// Usage: `makeSortable(elem);`
(function() {
    function sortTable(table, col, reverse) {
        var tb = table.tBodies[0], // Use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
            tr = Array.prototype.slice.call(tb.rows, 0); // Put rows into array
        reverse = -((+reverse) || -1);
        tr = tr.sort(function (a, b) { // Sort rows
            return reverse * (a.cells[col].textContent.trim().localeCompare(b.cells[col].textContent.trim()));
        });
        for (var i = 0, len = tr.length; i < len; ++i) {
            tb.appendChild(tr[i]); // Append each row in order
        }
    }
    function makeSortable(table) {
        var th = table.tHead, i;
        th && (th = th.rows[0]) && (th = th.cells);
        if (th) {
            i = th.length;
        } else {
            return; // If no `<thead>` then do nothing
        }
        while (--i >= 0) (function(i) {
            var dir = 1;
            th[i].onmousedown = function() {
                for (var j = 0, jen = th.length; j < jen; ++j) {
                    th[j].className = th[j].className.replace(/(^| )desc|asc( |$)/g, "$1$2");
                }
                sortTable(table, i, (dir = 1 - dir));
                this.className += dir === 1 ? " desc" : " asc";
                return false;
            };
        }(i));
    }
    window.makeSortable = makeSortable;
})();

CSS

.table-sortable {
  border-collapse:collapse;
  table-layout:fixed;
  width:100%;
  font:normal normal 13px/1.4 Arial,Sans-Serif;
  color:black;
  background-color:white;
}

.table-sortable th,
.table-sortable td {
  margin:0;
  padding:5px 8px;
  border:none;
  vertical-align:top;
  text-align:left;
}

.table-sortable th {
  font-weight:bold;
  background-color:slategray;
  color:white;
  border-color:white;
}

.table-sortable tbody tr:nth-child(even) {background-color:whitesmoke}
.table-sortable th {cursor:pointer}

th.asc,
th.desc {background-color:lightslategray}

th.asc:before,
th.desc:before {
  content:"";
  display:block;
  float:right;
  width:0;
  height:0;
  border:.4em solid transparent;
}

th.asc:before {
  border-bottom-color:inherit;
  border-top-width:0;
  margin-top:.4em;
}

th.desc:before {
  border-top-color:inherit;
  border-bottom-width:0;
  margin-top:.5em;
}

HTML

<table class="table-sortable" id="table-1">
  <thead>
    <tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
  </thead>
  <tbody>
    <!-- Sortable rows -->
    <tr><td> ... </td><td> ... </td><td> ... </td></tr>
    <tr><td> ... </td><td> ... </td><td> ... </td></tr>
    <tr><td> ... </td><td> ... </td><td> ... </td></tr>
    ...
  </tbody>
</table>
<script>makeSortable(document.getElementById('table-1'));</script>
Meski masih ada sedikit kekurangan karena fungsi sortir ini hanya memakai logika berdasarkan abjad. Coba Anda klik pada header Harga. Hasilnya tidak akan sesuai dengan apa yang kita harapkan. Masih sedang mencari solusi yang paling mudah untuk menangani satuan harga pada fungsi ini…

Demo

Senin, 30 September 2013

JavaScript Image Trail Tooltip

SXC Browse Page
Halaman browse foto di SXC.
Pertama kali Saya melihat tooltip semacam ini di situs SXC. Saya mencoba untuk membuat replikanya dengan tanpa menyertakan dukungan untuk peramban-peramban lawas. document.all itu sudah sangat ketinggalan zaman!
Keistimewaan dari tooltip ini adalah dia bisa bergerak mengikuti gerakan pointer serta bisa mempertahankan posisinya agar tetap berada pada area yang terlihat di halaman agar Anda tidak mengalami masalah-masalah seperti: tooltip keluar terlalu jauh ke sebelah kanan atau ke sebelah bawah dari area terlihat pada halaman. JavaScript ini juga bisa digunakan untuk menggantikan salah satu plugin JQuery Saya yang tidak begitu terkenal dan tidak sering diperbaharui lagi:

JavaScript

/*! JavaScript Image Trail Tooltip by Taufik Nurrohman <http://gplus.to/tovic> */
(function(w, d) {

    var tooltip = d.createElement('div'),
        noImage = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7", // 1 x 1 pixel transparent GIF
        top = 0,
        left = 0,
        docWidth = 0,
        docHeight = 0,
        offsetTop = 20, // Default top distance of the tooltip to the mouse pointer
        offsetLeft = 20, // Default left distance of the tooltip to the mouse pointer
        wait = null;

    // Get the correct width of the document without scrollbars
    function getDocWidth() {
        return d.documentElement.clientWidth;
    }

    // Get the correct height of the document
    function getDocHeight() {
        return Math.max(
            d.body.scrollHeight, d.documentElement.scrollHeight,
            d.body.offsetHeight, d.documentElement.offsetHeight,
            d.body.clientHeight, d.documentElement.clientHeight
        );
    }

    tooltip.id = "trail-image";
    tooltip.className = "trail-image";
    tooltip.innerHTML = '<img src="' + noImage + '" alt="Loading..." style="float:none;display:block;width:100%;height:100%;max-width:none;max-height:none;min-width:0;min-height:0;border:none;outline:none;background:none;margin:0;padding:0;">';

    // Just like `DOMContentLoaded` event, but only to
    // wait for the existence of the `<body>` element
    // to insert the tooltip markup in the proper area
    function waitForBodyExist() {
        if (!d.body) {
            wait = setTimeout(waitForBodyExist, 100);
        } else {
            clearTimeout(wait);
            d.body.appendChild(tooltip);
            docWidth = getDocWidth();
            docHeight = getDocHeight();
            w.onresize = function() {
                docWidth = getDocWidth();
                docHeight = getDocHeight();
            };
            w.onscroll = hideTrail;
        }
        // console.log('Still waiting...');
    } waitForBodyExist();

    // Function to show the tooltip
    // `width`  => the tooltip width
    // `height` => the tooltip height
    // `file`   => the URL of the image to show
    function showTrail(width, height, file) {
        tooltip.style.visibility = "visible";
        tooltip.children[0].src = file;
        tooltip.style.width = parseInt(width, 10) + "px";
        tooltip.style.height = parseInt(height, 10) + "px";
        d.onmousemove = function(e) {
            if (!e) e = w.event;
            if (e.pageX || e.pageY) {
                left = e.pageX;
                top = e.pageY;
            } else if (e.clientX || e.clientY) {
                left = e.clientX + d.body.scrollLeft + d.documentElement.scrollLeft;
                top = e.clientY + d.body.scrollTop + d.documentElement.scrollTop;
            }
            tooltip.style.top = parseInt(((top >= docHeight - (height + offsetTop + 10)) ? top - (height + offsetTop) : top + offsetTop), 10) + "px";
            tooltip.style.left = parseInt(((left >= docWidth - (width + offsetLeft + 10)) ? left - (width + offsetLeft) : left + offsetLeft), 10) + "px";
        };
    }

    // Function to hide the tooltip
    function hideTrail() {
        d.onmousemove = "";
        tooltip.style.top = "-9999px";
        tooltip.style.left = "-9999px";
        tooltip.style.visibility = "hidden";
        tooltip.children[0].src = noImage;
        docWidth = getDocWidth();
        docHeight = getDocHeight();
    }

    // Add to the window object as an external/global function
    w.showTrail = showTrail;
    w.hideTrail = hideTrail;

})(window, document);

CSS

/* Image Trail Tooltip CSS */
.trail-image {
  width:0;
  height:0;
  background-color:#ddd;
  border:1px solid #888;
  position:absolute;
  top:-9999px;
  left:-9999px;
  z-index:9999;
  visibility:hidden;
  -webkit-box-shadow:0 1px 1px rgba(0,0,0,.2);
  -moz-box-shadow:0 1px 1px rgba(0,0,0,.2);
  box-shadow:0 1px 1px rgba(0,0,0,.2);
}

Penggunaan

Dasar Penggunaan

Ada dua fungsi utama dalam skrip di atas, yaitu showTrail dan hideTrailshowTraildigunakan untuk menampilkan tooltip sedangkan hideTrail digunakan untuk menyembunyikannya. Anda bisa menerapkannya pada atribut onmouseover dan onmouseoutseperti ini:
<a href="img/large.jpg">
  <img onmouseover="showTrail(250, 100, &#39;img/medium.jpg&#39;);" onmouseout="hideTrail();" src="img/small.jpg" alt="">
</a>
Tentukan lebar dan tinggi gambar baru pada parameter width dan height serta URL gambar baru yang ingin ditampilkan pada parameter file:

Menyimpan Data di dalam Atribut HTML

Menuliskan fungsi berkali-kali secara inline mungkin akan melelahkan. Untuk itu Anda bisa memodifikasinya dengan cara memasukkan setiap URL gambar yang lebih besar di dalam atribut HTML5 data-*:
<img alt="" src="img/small.jpg" data-image-preview="img/medium.jpg">
Kemudian untuk penerapan fungsinya:
(function() {
    var img = document.getElementsByTagName('img');
    for (var i = 0, len = img.length; i < len; ++i) {
        if (img[i].getAttribute('data-image-preview')) {
            img[i].onmouseover = function() {
                showTrail(this.offsetWidth * 3, this.offsetHeight * 3, this.getAttribute('data-image-preview'));
            };
            img[i].onmouseout = hideTrail;
        }
    }
})();
Pada kode di atas Saya menerapkan this.offsetWidth * 3 dan this.offsetHeight * 3untuk menciptakan skala tooltip menjadi tiga kali lipat dari gambar thumbnail yang didekati pointer. Jadi anggap saja URL yang berada di dalam atribut data-image-preview memiliki ukuran sebesar tiga kali lipat dari thumbnail.
Pastikan DOM sudah berada dalam keadaan siap:

Tip untuk Gambar-Gambar dari Picasa

Kita tahu bahwa kita bisa mengubah resolusi gambar yang disimpan di Picasa dengan cara mengubah path /sN pada setiap gambar. Berikut ini adalah contoh penerapan fungsi showTraildan hideTrail tanpa memerlukan adanya atribut data-image-preview. Sekali Anda menerapkan fungsi ini, maka semua gambar yang berasal dari Picasa dengan ukuran lebar tidak lebih dari 100 piksel akan bisa menampilkan tooltip dengan lebar gambar 400 piksel:
(function() {
    var img = document.getElementsByTagName('img');
    for (var i = 0, len = img.length; i < len; ++i) {
        var valid = (img[i].src && /\/s[0-9]+(\-c)?\/.*?\.(bmp|gif|jpg|jpeg|png)/i.test(img[i].src) && img[i].offsetWidth <= 100);
        if (valid) {
            img[i].onmouseover = function() {
                showTrail(this.offsetWidth * 4, this.offsetHeight * 4, this.src.replace(/\/s[0-9]+(\-c)?/, "/s400$1"));
            };
            img[i].onmouseout = hideTrail;
        }
    }
})();
Pembaharuan: Pengecekan lebar gambar yang Saya terapkan di atas terkadang tidak bekerja karena mungkin fungsi telah tereksekusi sebelum dimensi gambar terbentuk, sehingga lebar gambar akan sama dengan 0 dan itu membuatnya bisa lolos dari pengecekan. Anda bisa mengeluarkan logika img[i].offsetWidth <= 100 dan memasukkannya ke dalam eventonmouseover seperti ini untuk memastikan agar pengecekan lebar gambar bisa dilakukan setelah dimensi gambar terbentuk setiap kali Anda mendekatkan pointer ke atas gambar:
var valid = (img[i].src && /\/s[0-9]+(\-c)?\/.*?\.(bmp|gif|jpg|jpeg|png)/i.test(img[i].src));
if (valid) {
    img[i].onmouseover = function() {
        if (this.offsetWidth <= 100) {
            showTrail(this.offsetWidth * 4, this.offsetHeight * 4, this.src.replace(/\/s[0-9]+(\-c)?/, "/s400$1"));
        }
    };
    img[i].onmouseout = hideTrail;
}

Catatan Tambahan untuk Internet Explorer

Pastikan deklarasi <!DOCTYPE html> dinyatakan pada dokumen HTML Anda agar skrip ini bisa bekerja dengan baik. Selain itu, menambahkan tag meta ini sedekat mungkin dengan <head>juga bisa mencegah Internet Explorer untuk berubah ke mode compatibility view tanpa kita kehendaki:
<meta http-equiv='X-UA-Compatible' content='IE=Edge'>

Sabtu, 28 September 2013

Memposisikan Judul dan Ringkasan Posting di Samping Thumbnail atau Thumbnail di atas Judul dan Ringkasan Posting

Bagaimana caranya memposisikan judul dan ringkasan posting di samping thumbnail, atau bagaimana cara memposisikan thumbnail di atas judul dan ringkasan posting (biasanya untuk membuat templat List & Masonry Grid)? Di sini Saya mencoba untuk membuat kode XML posting khusus yang Saya buat sefleksibel mungkin untuk keperluan modifikasi di masa datang. Kode ini sudah mencakup modifikasi ringkasan posting, sehingga jika Anda sudah mengimplementasikan modifikasi ini, maka Anda tidak perlu lagi repot-repot untuk mengimplementasikan tutorial pembuatan posting auto read-more.
Namun sebelum melakukan modifikasi ini, perlu dipertimbangkan bahwa nanti Anda akan mengubah struktur posting secara keseluruhan, sehingga beberapa kustomisasi lama Anda seperti penambahan widget artikel terkaitwidget berbagi dan  semuanya akan menghilang. Disarankan untuk menyimpan salinan templat Anda terlebih dahulu sebelum melakukan modifikasi ini.

Kode XML

Langkah pertama adalah mengedit XML templat. Kode XML ini cukup diterapkan sekali saja. Mengenai pengaturan posisi setiap elemen bisa kita lakukan dengan CSS yang sudah Saya tuliskan di bawah:
<b:includable id='post' var='post'>

  <article expr:class='&quot;_post _post-&quot; + data:blog.pageType' expr:id='&quot;post-&quot; + data:post.id'>

    <b:if cond='data:blog.pageType != &quot;item&quot;'>
      <b:if cond='data:blog.pageType != &quot;static_page&quot;'>
        <div class='_post-part _post-thumbnail-area'>
          <b:if cond='data:post.thumbnailUrl'>
            <img class='_post-thumbnail' expr:alt='data:post.title' expr:src='resizeImage(data:post.thumbnailUrl, 200, &quot;1:1&quot;)' height='200' width='200'/>
          </b:if>
        </div> <!-- ._post-thumbnail-area -->
      </b:if>
    </b:if>

    <div class='_post-part _post-body-area'>

      <h3 class='_post-title'>
        <b:if cond='data:post.title'>
          <b:if cond='data:post.link'>
            <a expr:href='data:post.link'><data:post.title/></a>
          <b:else/>
            <b:if cond='data:post.url'>
              <b:if cond='data:blog.url != data:post.url'>
                <a expr:href='data:post.url'><data:post.title/></a>
              <b:else/>
                <data:post.title/>
              </b:if>
            <b:else/>
              <data:post.title/>
            </b:if>
          </b:if>
        <b:else/>
          [Untitled]
        </b:if>
      </h3> <!-- ._post-title -->

      <div class='_post-body'>
        <b:if cond='data:blog.pageType == &quot;item&quot;'>
          <data:post.body/>
        <b:else/>
          <b:if cond='data:blog.pageType == &quot;static_page&quot;'>
            <data:post.body/>
          <b:else/>
            <b:if cond='data:post.snippet'>
              <data:post.snippet/>
            <b:else/>
              No content.
            </b:if>
          </b:if>
        </b:if>
      </div> <!-- ._post-body -->

      <footer class='_post-footer'>
        <div class='_post-footer-line _post-footer-line-1'>
          <span class='_post-author vcard'>
            <b:if cond='data:top.showAuthor'>
              <data:top.authorLabel/> <span class='fn'>
              <b:if cond='data:post.authorProfileUrl'>
                <a class='g-profile' expr:href='data:post.authorProfileUrl' rel='author' title='Author Profile'><data:post.author/></a>
              <b:else/>
                <span class='g-profile'><data:post.author/></span>
              </b:if>
              </span>
            </b:if>
          </span> <span class='_post-time'>
          <b:if cond='data:top.showTimestamp'>
            <data:top.timestampLabel/> <a class='_post-time-link' expr:href='data:post.url' rel='bookmark' title='Permanent Link'><time class='_post-published published' expr:datetime='data:post.timestampISO8601'><data:post.timestamp/></time></a>
          </b:if>
          </span> <span class='_post-comment-link'>
          <b:if cond='data:blog.pageType != &quot;item&quot;'>
            <b:if cond='data:blog.pageType != &quot;static_page&quot;'>
              <b:if cond='data:post.allowComments'>
                <a expr:href='data:post.url + &quot;#comments&quot;'><data:post.commentLabelFull/></a>
              </b:if>
            </b:if>
          </b:if>
          </span>
        </div> <!-- ._post-footer-line-1 -->
        <div class='_post-footer-line _post-footer-line-2'>
          <span class='_post-labels'>
            <b:if cond='data:post.labels'>
              <data:postLabelsLabel/> <b:loop values='data:post.labels' var='label'>
                <a expr:href='data:label.url' rel='tag'><data:label.name/></a><b:if cond='data:label.isLast != &quot;true&quot;'>, </b:if>
              </b:loop>
            </b:if>
            <!-- b:include data='post' name='postQuickEdit'/ -->
          </span>
        </div> <!-- ._post-footer-line-2 -->
      </footer> <!-- ._post-footer -->

    </div> <!-- ._post-body-area -->

  </article> <!-- ._post -->

</b:includable>
Salin semua kode di atas untuk menggantikan kode yang tampak seperti ini di dalam templat:
<b:includable id='post' var='post'> ... </b:includable>
Langkah berikutnya adalah menambahkan CSS khusus. Pilih salah satu saja.

Tata Letak 1: Thumbnail di Sebelah Kiri Judul dan Ringkasan Posting

Post Thumbnail on the Left
Thumbnail di sebelah kiri judul dan ringkasan posting.
Salin kode CSS ini lalu letakkan di atas ]]></b:skin> atau </style>:
/*!
Thumbnail width: 200
Thumbnail height: 200
*/

._post {
  background-color:white;
  height:200px; /* Thumbnail height */
  margin:0 0 10px;
  overflow:hidden;
  *zoom:1;
}

._post:after {
  content:" ";
  display:block;
  clear:both;
}

._post-title {
  font:normal bold 20px/1.2 Arial,Sans-Serif;
  margin:0 0 10px;
  padding:0;
}

._post-thumbnail-area {
  width:200px; /* Thumbnail width */
  height:200px; /* Thumbnail height */
  background-color:#2D3957;
  float:left;
  overflow:hidden;
}

._post-thumbnail {
  display:block;
  width:100%;
  height:100%;
  max-width:none;
  max-height:none;
  min-width:0;
  min-height:0;
  margin:0;
  padding:0;
  border:none;
  outline:none;
  position:static;
}

._post-body-area {
  padding:20px;
  margin-left:200px; /* Thumbnail width */
  font-size:11px;
}

._post-footer {
  margin:10px 0 0;
  padding:10px 0 0;
  border-top:1px dotted #ddd;
  font:normal bold 8px/1.5 Verdana,Tahoma,Arial,Sans-Serif;
  text-transform:uppercase;
  color:#999;
}

/* Item + Static Page */
._post-item,
._post-static_page {height:auto}

._post-item ._post-body-area,
._post-static_page ._post-body-area {
  margin:0;
  padding:20px;
  font-size:13px;
}

._post-item ._post-title,
._post-static_page ._post-title {font-size:40px}

Tata Letak 2: Thumbnail di Sebelah Atas Judul dan Ringkasan Posting

Thumbnail Before Post Title and Summary
Thumbnail di sebelah atas judul dan ringkasan posting.
Salin kode CSS ini lalu letakkan di atas ]]></b:skin> atau </style>:
/*!
Thumbnail width: 300
Thumbnail height: 300
*/

._post {
  background-color:white;
  width:300px; /* Thumbnail width */
  margin:0 10px 10px 0;
  overflow:hidden;
  *zoom:1;
  /* float:left; */
}

._post:after {
  content:" ";
  display:block;
  clear:both;
}

._post-title {
  font:normal bold 16px/1.2 Arial,Sans-Serif;
  margin:0 0 10px;
  padding:0;
}

._post-thumbnail-area {
  width:300px; /* Thumbnail width */
  height:300px; /* Thumbnail height */
  background-color:#2D3957;
  overflow:hidden;
}

._post-thumbnail {
  display:block;
  width:100%;
  height:100%;
  max-width:none;
  max-height:none;
  min-width:0;
  min-height:0;
  margin:0;
  padding:0;
  border:none;
  outline:none;
  position:static;
}

._post-body-area {
  padding:20px;
  margin:10px 0 0;
  font-size:11px;
}

._post-footer {
  margin:10px 0 0;
  padding:10px 0 0;
  border-top:1px dotted #ddd;
  font:normal bold 8px/1.5 Verdana,Tahoma,Arial,Sans-Serif;
  text-transform:uppercase;
  color:#999;
}

/* Item + Static Page */
._post-item,
._post-static_page {width:auto}

._post-item ._post-body-area,
._post-static_page ._post-body-area {
  margin:0;
  padding:20px;
  font-size:13px;
}

._post-item ._post-title,
._post-static_page ._post-title {font-size:40px}
Kode yang Saya beri tanda adalah resolusi gambar yang akan Anda terapkan. Ini tergantung dari ukuran standar masing-masing gambar posting di atas, yang sudah Saya sertakan dalam komentar CSS.
Simpan perubahan.

Struktur Posting yang Tercipta

Berikut ini adalah diagram markup HTML yang akan tercipta secara garis besar. Semoga bisa sedikit membantu untuk memberikan gambaran modifikasi lanjutan:
  • ._post
    • ._post-part._post-thumbnail-area
      • ._post-thumbnail
    • ._post-part._post-body-area
      • ._post-title
      • ._post-body
      • ._post-footer
        • ._post-footer-line._post-footer-line-1
          • ._post-author
          • ._post-time
          • ._post-comment-link
        • ._post-footer-line._post-footer-line-2
          • ._post-labels
._post {}
._post-part {}
._post-thumbnail-area {}
._post-body-area {}
._post-title {}
._post-body {}
._post-footer {}
._post-footer-line {}
._post-footer-line-1 {}
._post-footer-line-2 {}
._post-author {}
._post-time {}
._post-comment-link {}
._post-labels {}
Catatan Tambahan: Setelah ini lebih baik Anda hapus beberapa kode CSS yang memiliki selektor seperti ini. Markup posting sudah berubah secara total, sehingga CSS ini sudah tidak diperlukan lagi:
.post {}
.post-title {}
.post-body {}
.post-footer {}
.post-footer-line {}
.post-footer-line-1 {}
.post-footer-line-2 {}
.post-footer-line-3 {}
.post-header-line {}
.post-header-line-1 {}
.post-header-line-2 {}
.post-header-line-3 {}
.post-author {}
.post-timestamp {}
.post-comment-link {}
.post-labels {}

Jumat, 27 September 2013

Data Asinkron dengan Callback

Fungsi ini bisa digunakan untuk memuat file JavaScript secara asinkron, sekaligus juga memungkinkan pengguna untuk mengeksekusi fungsi sesaat setelah data tersebut berhasil termuat:
function asyncData(url, callback) {
    var script = document.createElement('script');
    script.src = url;
    script.onload = function() {
        if (typeof callback == "function") callback();
        callback = null;
    };
    script.onreadystatechange = function() {
        if (script.readyState == 4 || script.readyState == "complete") {
            if (typeof callback == "function") callback();
            callback = null;
        }
    };
    document.getElementsByTagName('head')[0].appendChild(script);
}

Penggunaan

Sebagai contoh, Anda ingin memuat skrip Syntax Highighter secara tidak langsung. Namun pada saat yang bersamaan Anda juga ingin memastikan agar eksekusi plugin terjadi hanya jika skrip tersebut telah termuat:
asyncData("../js/highlight.min.js", function() {
    hljs.initHighlighting();
});

Demo

Skrip Asinkron Dasar (Tanpa Fitur Callback)

var script = document.createElement('script');
script.src = "../js/highlight.min.js";
document.getElementsByTagName('head')[0].appendChild(script);

Tidak ada komentar

Posting Komentar