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: , , , , , ,

Saturday, April 4, 2020

Pilih Mana: Memuat JSON Blogger dengan Metode Tradisional atau dengan Metode AJAX?

Menambahkan parameter alt dengan nilai json atau json-in-script pada URL umpan blog akan memberikan hasil keluaran data berupa JSON. Pengembang bisa memanfaatkan data tersebut untuk membuat gawai blog. Namun untuk bisa memproses data, kita perlu menemukan cara untuk menampung data tersebut ke dalam parameter fungsi:

function recentPosts(json) {
    // Ubah data `json` menjadi gawai di sini…
}

recentPosts( /* Masukan data JSON di sini… */ );

Metode Tradisional

Blogger memberikan akses kepada para pengembang untuk memproses data yang diberikan melalui parameter callback. Dengan menyatakan nama fungsi pada parameter tersebut, maka hasil keluaran JSON mentah yang diberikan akan dilengkapi dengan kode eksekusi fungsi yang membungkus data JSON tersebut. Sebenarnya tidak ada hal yang ajaib dalam sistem pemuatan data seperti itu. Tanpa parameter callback, hasil keluaran yang akan diberikan adalah seperti ini:

{
  "version": "1.0",
  "encoding": "UTF-8",
  "feed": { … }
}

Sedangkan ketika menggunakan parameter callback dengan nilai recentPosts, maka hasil keluaran yang akan diberikan adalah seperti ini:

recentPosts({
  "version": "1.0",
  "encoding": "UTF-8",
  "feed": { … }
});

Sehingga ketika umpan blog berhasil dimuat, maka data yang akan termuat bukan hanya terdiri dari JSON saja tetapi juga fungsi global yang memproses data JSON tersebut pada saat yang bersamaan ketika JSON termuat:

<!-- Tanpa eksekusi fungsi -->
<script src="/feeds/posts/summary?alt=json"></script>

<!-- Dengan eksekusi fungsi -->
<script src="/feeds/posts/summary?alt=json&amp;callback=recentPosts"></script>

Menerapkan metode seperti ini bukan berarti tidak memiliki kekurangan. Karena umpan blog perlu menerima nama fungsi yang bersifat global, maka kita harus mengaitkan fungsi gawai yang kita buat pada objek window. Satu-satunya cara yang bisa kita lakukan adalah dengan mendeklarasikan fungsi tersebut pada bagian terluar dari berkas JavaScript, atau dengan mendeklarasikan fungsi tersebut sebagai salah satu properti dari window jika fungsi tersebut berada di dalam fungsi-fungsi yang lain:

// Metode 1
function recentPosts(json) { … }

// Metode 2
window.recentPosts = function(json) { … };

// Metode 3
(function(w) {
    w.recentPosts = function(json) { … };
})(window);

// Metode 4
function start() {
    function createRecentPostsFunction() {
        function a() { … }
        function b() { … }
        function c() {
            window.recentPosts = function(json) { … };
        }
        a();
        b();
        c();
    }
    function hasRecentPostsFunction() {
        return 'recentPosts' in window && 'function' === typeof window.recentPosts;
    }
    if (!hasRecentPostsFunction()) {
        createRecentPostsFunction();
    }
}

start();

Karena JavaScript memungkinkan kita untuk menimpa fungsi yang telah dibuat sebelumnya dengan cara membuat fungsi yang baru (atau membuat variabel) menggunakan nama yang sama, maka akan sangat mudah bagi fungsi tersebut untuk mengalami konflik-konflik penamaan seperti ini:

<!-- Kode pihak ke 1 (kamu) -->
<script>
function recentPosts(json) { … }
</script>

<!-- Kode pihak ke 3 (orang lain) yang akan merusak fungsi `recentPosts()` -->
<script>
var recentPosts = null;
</script>

<!-- Di sini akan muncul pesan kesalahan “TypeError: recentPosts is not a function” -->
<script src="/feeds/posts/summary?alt=json&amp;callback=recentPosts"></script>

Ada dua cara yang dapat kamu lakukan untuk menghindari masalah tersebut. Cara yang pertama adalah dengan mendeklarasikan fungsi recentPosts sebagai konstanta agar nama fungsi tersebut tidak bisa digunakan lagi di tempat lain setelah konstanta tersebut dinyatakan:

<script>
const recentPosts = json => { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
function recentPosts(json) { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
let recentPosts = json => { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
const recentPosts = json => { … };
</script>

Cara yang ke dua adalah dengan membuat nama fungsi yang tidak permanen dan bersifat acak. Cara di bawah ini memungkinkan kita untuk membuat fungsi global yang bisa berubah-ubah namanya setiap kali halaman dimuat, sehingga akan memperkecil kemungkinan pihak lain untuk mendeklarasikan fungsi gawai dengan nama yang sama:

let id = Math.floor(Math.random() * 1000),
    node = document.createElement('script');

window['recentPosts_' + id] = json => { … };

node.src = '/feeds/posts/summary?alt=json&callback=recentPosts_' + id;

document.head.appendChild(node);

Metode AJAX

Memuat data menggunakan AJAX relatif lebih praktis, walaupun dari segi sintaks mungkin akan terlihat rumit bagi orang-orang yang belum terbiasa. Kamu bisa menggunakan fungsi ini sebagai contekan selama kamu masih belum menguasai konsep AJAX. Dengan menggunakan AJAX, kamu tidak perlu menambahkan parameter callback karena data yang dimuat nantinya akan secara otomatis tertampung ke dalam parameter fungsi untuk menyatakan kesuksesan proses pemuatan data. Kamu bisa menggunakan XMLHttpRequest atau fetch. Pilih salah satu:

let xhr = new XMLHttpRequest;

// Buka tautan umpan dengan metode `GET`
xhr.open('GET', '/feeds/posts/summary?alt=json', true);

// Atur tipe respons sebagai JSON, bukan teks
xhr.responseType = 'json';

// Proses manipulasi data dilakukan di dalam acara `readystate`
xhr.addEventListener('readystate', function() {
    if (4 === this.readyState && 200 === this.status) {
        let json = this.response;
        // Ubah data `json` menjadi gawai mulai dari sini…
    }
}, false);

// Memulai permintaan data!
xhr.send();
// Memulai permintaan data!
fetch('/feeds/posts/summary?alt=json').then(response => {
    return response.json(); // Atur tipe respons sebagai JSON, bukan teks
}).then(json => {
    // Ubah data `json` menjadi gawai mulai dari sini…
});

Pakai jQuery juga bisa! Tapi akhir-akhir ini jQuery sudah ketinggalan zaman:

$.ajax({
    type: 'GET',
    url: '/feeds/posts/summary?alt=json',
    dataType: 'json'
}).done(function(json) {
    // Ubah data `json` menjadi gawai di sini…
});
$.get('/feeds/posts/summary?alt=json', function(json) {
    // Ubah data `json` menjadi gawai di sini…
}, 'json');

Mengeksekusi fungsi recentPosts() melalui respons AJAX dapat dilakukan dengan cara seperti ini:

xhr.addEventListener('readystate', function() {
    if (4 === this.readyState && 200 === this.status) {
        recentPosts(this.response);
    }
}, false);
fetch('/feeds/posts/summary?alt=json').then(response => response.json()).then(recentPosts);
$.ajax({
    type: 'GET',
    url: '/feeds/posts/summary?alt=json',
    dataType: 'json'
}).done(recentPosts);
$.get('/feeds/posts/summary?alt=json', recentPosts, 'json');

Kelebihan dari menggunakan metode AJAX adalah kamu tidak diharuskan untuk membuat fungsi gawai sebagai fungsi yang bersifat global, sehingga akan lebih ramah bagi lingkungan di luar gawai, serta dapat membebaskan fungsi tersebut dari kemungkinan-kemungkinan terjadinya konflik penamaan fungsi seperti yang telah Saya jelaskan sebelumnya pada metode pemuatan data umpan secara tradisional. Nama fungsi juga dapat dikompres dengan alat pengompres JavaScript tanpa memberikan pengaruh apa-apa pada hasil keluarannya:

(function() {
    function recentPosts(json) { … }
    fetch('/feeds/posts/summary?alt=json').then(response => response.json()).then(recentPosts);
})();

// Akan muncul pesan kesalahan “ReferenceError: recentPosts is not defined”
console.log(recentPosts);

Setiap metode tentu memiliki kekurangan dan kelebihannya masing-masing. Beberapa hal yang sudah Saya jabarkan di sini hanyalah sebagian kecilnya saja. Selebihnya mungkin dapat dijelaskan dengan contoh kasus. Jadi, mau pilih yang mana?

Labels: , , ,

Saturday, March 28, 2020

Cara Merilis Paket Node.js Secara Otomatis Bersamaan dengan Rilis pada GitHub

GitHub + NPM
Gambar oleh GitHub.

Dengan membaca artikel ini, Saya menganggap kamu sudah paham mengenai apa dan bagaimana itu NPM dan GitHub.

Pada tanggal 16 Maret 2020 yang lalu, GitHub —yang sebelumnya juga telah berhasil diakuisisi oleh Microsoft— mengumumkan sebuah kabar gembira bahwa NPM memutuskan untuk bergabung dengan GitHub. Dengan mengesampingkan ketidaksukaan Saya terhadap pola-pola modul JavaScript, sejak saat itu Saya mulai menelusuri tentang bagaimana cara melakukan integrasi NPM dengan GitHub. Untuk apa? Untuk membuat aktivitas NPM menjadi serba otomatis menyesuaikan dengan berbagai aktivitas yang Saya lakukan di GitHub.

Karena Saya yang tidak suka dengan NPM namun tidak bisa menghindari kenyataan bahwa beberapa pengguna aplikasi Saya ternyata menginginkan Saya untuk memberikan opsi pemasangan aplikasi melalui NPM, dan karena aktivitas utama koding jarak jauh Saya sekarang hampir seluruhnya berada di GitHub, dan karena dalam lubuk hati Saya yang paling dalam (cie…) sebenarnya Saya tetap saja tidak menyukai konsep pemuatan modul di NPM, pada akhirnya Saya memutuskan untuk keluar dari zona nyaman Saya.

Sebelumnya Saya sudah beberapa kali melakukan rilis paket Node.js secara manual, secara biasa, sesuai dengan prosedur pada situs web dokumentasi NPM, yaitu dengan cara menuliskan perintah npm publish --access public setiap kali Saya sudah siap merilis versi paket yang lebih baru, yang hal tersebut tentu saja memaksa Saya untuk memasang lingkungan Node.js terlebih dahulu di komputer yang sedang Saya pakai, yang kadang hal tersebut menurut Saya agak ribet, karena saat ini Saya masih berada di luar kebutuhan untuk menggunakan Node.js sebagai peladen lokal.

Kemudian Saya mengetahui bahwa NPM sekarang bergabung dengan GitHub. Saya pikir, pasti ada cara tertentu untuk membuat semuanya menjadi serba otomatis. Cara seperti itu pasti ada, dan ternyata memang benar.

Mengenal GitHub Actions

Actions atau Aksi pada GitHub merupakan fitur yang memungkinkan kita untuk mengeksekusi perintah-perintah tertentu secara otomatis setiap kali kita melakukan aktivitas pada GitHub. Cara kerjanya sama dengan kait atau hook pada sistem manajemen konten Mecha dan pendengar acara atau event listener pada JavaScript. Setiap kali kita melakukan aktivitas dorong dan tarik, menulis isu dan komentar misalnya, pada saat itu sebenarnya terdapat kait dengan nama tertentu yang akan dieksekusi oleh GitHub. Dengan memanfaatkan nama kait tersebut, maka kita bisa mengeksekusi perintah yang kita inginkan pada saat kait tersebut dipanggil.

Pada kasus yang sedang kita bahas sekarang, nama kait yang Saya maksud di sini adalah release, dan bentuk aksi yang akan kita lakukan adalah mengeksekusi perintah npm publish pada repositori jarak jauh yang baru saja kita rilis. Namun karena kita tidak memiliki akses kepada peladen Node.js di GitHub, dan karena membuat kait web memerlukan peladen Node.js pribadi untuk menentukan tautan sebagai penerima muatan dari GitHub, maka memanfaatkan fitur Webhooks menjadi tidak mungkin.

Fitur aksi pada GitHub memberikan akses kepada kita untuk memanfaatkan lingkungan peladen yang ada di GitHub dengan cara menuliskan berkas konfigurasi tertentu untuk dijalankan oleh GitHub.

Menu Actions seharusnya sudah ada pada halaman awal repositori masing-masing selama fitur tersebut tidak dinonaktifkan melalui menu Settings. Untuk membuat aksi, klik menu Actions pada repositori yang diinginkan kemudian pilih jenis alur kerja yang akan dipakai, dalam hal ini adalah Node.js:

Memilih alur kerja.
Memilih alur kerja.

Kamu mungkin juga akan melihat opsi Publish Node.js Package di situ yang secara logika seharusnya lebih tepat untuk dipilih. Tapi di sini Saya lebih cenderung ke opsi Node.js karena kedua opsi tersebut pada dasarnya sama. Hanya saja opsi Node.js sifatnya lebih menyeluruh, sedangkan opsi Publish Node.js Package tersedia hanya untuk menangani aktivitas publikasi paket saja. Harapan Saya adalah ketika suatu saat nanti Saya ingin membuat artikel yang sejenis atau terkait dengan implementasi GitHub Actions pada artikel ini, maka Saya hanya tinggal meminta kalian untuk melakukan sedikit perubahan pada pengaturan yang sudah kalian buat di sini.

Setelah mengambil pilihan, kamu akan diminta untuk mengisi formulir yang bertujuan untuk membuat berkas bernama .\.github\workflows\nodejs.yml seperti ini:

Membuat `nodejs.yml`
Membuat berkas konfigurasi.

Hapus semua isinya kemudian ganti dengan ini:

name: Publish

on:
  release:
    types: [published]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: actions/setup-node@v1
        with:
          node-version: 12
          registry-url: https://registry.npmjs.org/
      - run: yarn install
      - run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

Klik tombol Start commit untuk memulai pembuatan berkas.

Kalau kamu sudah mahir menggunakan aplikasi Git, kamu sebenarnya bisa kok membuat berkas tersebut secara manual pada repositori lokal melalui terminal. Setelah itu, kamu tinggal menjalankan perintah git push untuk menambahkan berkas tersebut ke repositori jarak jauh. Namun karena pada contoh di atas, yang kamu lakukan adalah membuat berkas baru secara langsung melalui repositori jarak jauh, maka kamu perlu melakukan sinkronisasi kembali dengan repositori lokal, dengan cara menjalankan perintah git pull pada terminal untuk memastikan agar kedua repositori tetap berada dalam kondisi dan status yang sama persis.

Pada data konfigurasi di atas, kita bisa sedikit memahami, dimulai dari data yang ini, yang berfungsi untuk menjalankan jobs pada saat kait release dengan tipe published berhasil dipanggil:

on:
  release:
    types: [published]

Perintah publikasi paket berada pada baris ini:

jobs:
  build:
    steps:
      - …
      - …
      - run: npm publish --access public

Variabel ${{secrets.NPM_TOKEN}} berisi token rahasia yang perlu kita buat secara manual melalui dasbor NPM.

Membuat Token Akses untuk Autentikasi

Agar bisa berkomunikasi dengan NPM, kita perlu membuat token rahasia yang berfungsi untuk memberikan akses kepada paket-paket kita di NPM.

Buka tautan https://www.npmjs.com/settings/nama-pengguna/tokens atau klik pada ikon avatar di pojok kanan atas kemudian pilih menu Auth Tokens. Klik pada tombol Create New Token.

Membuat token akses di NPM.
Membuat token akses baru.

Pilih tingkatan akses ke Read and Publish kemudian klik tombol Create Token.

Segera salin token yang sudah berhasil dibuat!

Sampai di sini, sebenarnya kamu bisa mengganti variabel ${{secrets.NPM_TOKEN}} dengan kode token yang baru saja kamu salin. Tapi karena token ini bersifat rahasia dan berfungsi sebagaimana kata kunci yang kita gunakan untuk log masuk, maka ada baiknya jika kita simpan token tersebut ke dalam variabel secrets.NPM_TOKEN di GitHub, sehingga nilainya dapat diakses melalui properti NPM_TOKEN di variabel secrets, namun tidak akan bisa dilihat secara langsung karena sudah tersimpan di tempat yang lain.

Menyimpan Token NPM di GitHub

Untuk menyimpan token rahasia di GitHub, gunakan fitur GitHub Secrets. Pada setiap repositori, fitur ini dapat diakses melalui menu Settings. Buat variabel baru dengan nama NPM_TOKEN kemudian tempelkan kode token yang sudah kamu salin tadi:

Membuat token akses di NPM.
Menyimpan token akses rahasia ke GitHub.

Klik tombol Add secret. Kode token rahasia sudah berhasil disimpan dan tidak akan pernah bisa dibuka lagi. Kamu tidak perlu melakukan perubahan apa-apa pada berkas nodejs.yml yang telah kamu buat sebelumnya.

Sistem rilis paket Node.js otomatis sudah selesai dibuat!


Cara Merilis Paket Node.js Melalui GitHub

Untuk merilis paket dari GitHub ke NPM secara otomatis, kamu hanya perlu membuat item rilis baru di GitHub untuk memicu kait release pada repositori tersebut. Tapi sebelum itu, pastikan properti version di dalam berkas package.json sudah diperbarui:

{
  "name": "@taufik-nurrohman/query-string-parser",
  "description": "Convert URL’s query string into JavaScript object.",
  "version": "1.0.1",
  "main": "q2o.js",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/taufik-nurrohman/query-string-parser.git"
  },
  "author": "Taufik Nurrohman",
  "license": "MIT",
  …
}

Pada halaman formulir rilis baru, tentukan nama label sesuai dengan nilai properti version pada berkas package.json:

Merilis versi baru.
Merilis versi baru.

Nama label ini, setahu Saya tidak ada kaitannya dengan NPM karena NPM hanya akan membaca berkas package.json pada repositori terkait untuk mengecek apakah nilai properti version sudah berubah atau belum. Tapi ada baiknya untuk tetap menyesuaikan nilainya dengan versi paket untuk menjaga konsistensi antara GitHub dengan NPM. Silakan isi judul dan konten rilis sesuka hati untuk memperjelas maksud dan tujuan rilis pada versi tersebut.

Setelah berhasil melakukan rilis pada GitHub, harusnya salinan repositori GitHub tersebut akan secara otomatis dibuat (atau diperbarui jika sudah ada) sebagai paket Node.js di situs web NPM, seperti ini:

Beberapa detik yang lalu.
Lihat keterangan bahwa paket @taufik-nurrohman/query-string-parser baru saja diperbarui beberapa detik yang lalu.

Labels: ,

Tuesday, June 25, 2019

Membuat Formulir Kontak dengan Google Drive

Tutorial kali ini merupakan tindak lanjut dari tutorial sejenis yang pernah Saya publikasikan sebelumnya di sini. Sebelum artikel tersebut ditandai sebagai artikel kadaluarsa, layanan Google Drive saat itu masih bernama Google Docs. Saya sempat berpikir untuk memperbarui artikel tersebut saja, tapi karena terdapat unsur historis pada artikel tersebut maka Saya memutuskan untuk membuat artikel yang baru saja.

Tutorial kali ini Saya harap akan jauh lebih mudah untuk diikuti karena di sini Anda tidak lagi membutuhkan ID spreadsheet untuk membuat formulir kontak bekerja. Tidak perlu panjang-panjang, kita langsung ke langkah-langkahnya saja ya!

Membuat Spreadsheet

Berbeda dari tutorial sebelumnya yang dimulai dengan membuat formulir baru, di sini Anda buat spreadsheet-nya terlebih dahulu. Spreadsheet ini nantinya akan kita gunakan sebagai basis-data untuk semua pesan yang berhasil dikirim. Buka https://drive.google.com/drive kemudian klik pada tombol Baru di pojok kiri atas. Pilih Google Spreadsheet kemudian pilih Spreadsheet kosong.

Membuat Spreadsheet Baru
Membuat spreadsheet baru.

Jendela baru akan terbuka untuk memuat editor spreadsheet dari Google. Setelah termuat, klik pada judulnya kemudian ubah namanya menjadi ‘Pesan Masuk’.

Mengganti nama spreadsheet.

Sekarang pilih menu Alat kemudian pilih Buat formulir.

Buat formulir baru.

Tunggu beberapa saat maka akan muncul tab baru di bagian bawah editor dengan label ‘Form Responses 1’.

Sheet baru dibuat secara otomatis.

Klik untuk mengaktifkan sheet tersebut! Anda boleh menghapus sheet sebelumnya karena itu tidak ada gunanya.

Formulir Anda sebenarnya sudah jadi, tapi masih belum berisi apa-apa kecuali satu bidang dengan label Timestamp dan satu bidang lagi yang hanya berfungsi sebagai contoh saja.

Menyunting Formulir

Pilih menu Formulir kemudian pilih Edit formulir. Maka jendela baru akan terbuka untuk memuat editor formulir.

Menyunting formulir.

Pada editor tersebut, hapus atau sunting bidang contoh, kemudian buat bidang-bidang baru dengan rincian seperti berikut:

  • Perihal
    • Tipe: Jawaban singkat
    • Wajib diisi: Ya
  • Nama
    • Tipe: Jawaban singkat
    • Wajib diisi: Ya
  • Surel
    • Tipe: Jawaban singkat
    • Wajib diisi: Ya
  • Situs Web
    • Tipe: Jawaban singkat
    • Wajib diisi: Tidak
  • Pesan
    • Tipe: Paragraf
    • Wajib diisi: Ya

Semua perubahan akan tersimpan secara otomatis.

Membuat Skrip Pemicu

Skrip ini nantinya akan bekerja setiap kali pesan dikirimkan melalui formulir terkait. Untuk membuatnya, pilih menu Alat kemudian pilih Editor skrip. Jendela baru akan terbuka untuk memuat editor skrip.

Membuka editor skrip.

Pada bidang Kode.gs, tempelkan kode ini:

function onFormSubmit(e) {
    GmailApp.sendEmail('you@example.com', 'Tes', JSON.stringify(e));
}

Simpan kode tersebut dengan nama ‘Kirim Pesan’.

Ganti kode yang Saya beri tanda dengan alamat surel Anda. Sekarang pilih menu yang tampak seperti simbol jam untuk mengaktifkan pemicu (biasanya bernama ‘Pemicu proyek saat ini’). Jendela baru akan terbuka untuk memuat halaman pemicu proyek.

Klik tombol Tambahkan Pemicu di pojok kanan bawah. Pada bidang Pilih fungsi yang ingin dijalankan pilih onFormSubmit (sesuai dengan nama fungsi yang kita buat sebelumnya). Pada bidang Pilih penerapan mana yang harus dijalankan pilih Head. Pada bidang Pilih sumber acara pilih Dari Spreadsheet. Pada bidang Pilih jenis acara pilih Saat mengirim formulir. Pada bidang Setelan notifikasi kegagalan ambil pilihan sesuai kebutuhan saja.

Setelah itu tekan tombol Simpan. Anda akan diminta untuk mengautentikasi pemicu tersebut melalui jendela munculan. Ikuti petunjuk yang ada, kemudian tekan tombol Izinkan di akhir tahapan.

Mengirim Pesan

Sekarang kita coba kirimkan pesan. Pilih menu Formulir kemudian pilih Buka formulir langsung. Jendela baru akan terbuka untuk memuat formulir publik Anda. Salin URL pada jendela tersebut untuk dibagikan nanti. Isi semua bidang yang ada kemudian tekan tombol Kirim untuk mengetes. Jika berhasil, maka Anda akan mendapatkan pesan masuk yang kurang lebihnya tampak seperti ini:

Pesan masuk.

Di situ akan tampak semua data yang telah kita kirimkan tadi. Untuk saat ini kita fokus ke bidang values dan namedValues saja. Kita pilih bidang namedValues karena bidang ini memiliki format {"key": "value"} yang lebih mudah untuk diproses.

Buka kembali editor skrip kemudian ubah fungsi onFormSubmit menjadi seperti ini:

function onFormSubmit(e) {
    var to = 'you@example.com',
        values = e.namedValues,
        key, value,
        body = "";
    for (key in values) {
        value = values[key];
        if (typeof value === "object" && value[0]) {
            value = value[0];
        }
        body += key + ': ' + value + '\n';
    }
    GmailApp.sendEmail(to, 'Pesan baru!', body.trim());
}

Simpan perubahan. Kemudian Anda coba kirim pesan lagi, maka format pesan yang masuk akan tampak lebih mudah dibaca sekarang!


Tingkat Lanjut

Mengirim HTML

Pada fungsi sebelumnya, setiap pesan yang dikirim akan diperlakukan sebagai data yang mentah, dimana karakter ganti baris akan diubah menjadi <br> dan tag-tag HTML yang lain akan dianggap sebagai teks biasa. Untuk mengirimkan kode HTML seperti apa adanya, Anda perlu mengosongkan bidang body kemudian ambil parameter berikutnya untuk menempatkan data pada bidang htmlBody agar data yang dikirimkan nantinya dapat dianggap sebagai kode HTML:

GmailApp.sendEmail(to, 'Pesan baru!', "", {
    htmlBody: body
});

Berikut ini adalah fungsi yang telah Saya modifikasi sedemikian rupa agar pesan yang masuk nantinya lebih nyaman untuk dibaca:

function onFormSubmit(e) {
    var to = 'you@example.com',
        values = e.namedValues,
        key, value,
        body = "";
    body += '<table style="width:100%;font-size:13px;font-family:sans-serif;line-height:1.5em;;background:#fff;color:#000;table-layout:fixed;border-collapse:separate;border-spacing:2px;">';
    body += '<tbody>';
    for (key in values) {
        value = values[key];
        if (typeof value === "object" && value[0]) {
            value = value[0];
        }
        // Ubah karakter `\n` menjadi `<br>`
        value = value.replace(/\n/g, '<br>');
        body += '<tr>';
        body += '<th style="font:inherit;font-size:100%;font-weight:bold;width:12em;background:#c3d9ff;padding:.5em 1em;vertical-align:top;text-align:right;">' + key + '</th>';
        body += '<td style="font:inherit;font-size:100%;background:#e0ecff;padding:.5em 1em;vertical-align:top;text-align:left;">' + value + '</td>';
        body += '</tr>';
    }
    body += '</tbody>';
    body += '</table>';
    GmailApp.sendEmail(to, values['Perihal'][0] || 'Pesan Baru!', "", {
        htmlBody: body
    });
}

Mengurutkan Data

Jika pesan yang terkirim tampak tidak sesuai dengan urutan yang seharusnya, Anda bisa mengatur data yang ditampilkan secara manual tanpa melalui pengulangan for:

values['Perihal'] && (body += 'Perihal: ' + values['Perihal'][0] + '\n');
values['Nama'] && (body += 'Nama: ' + values['Nama'][0] + '\n');
values['Surel'] && (body += 'Surel: ' + values['Surel'][0] + '\n');
values['Situs Web'] && (body += 'Situs Web: ' + values['Situs Web'][0] + '\n');
values['Pesan'] && (body += 'Pesan: ' + values['Pesan'][0]);

Atau seperti ini juga bisa:

var orders = ['Perihal', 'Nama', 'Surel', 'Situs Web', 'Pesan'],
    values = e.namedValues,
    key, value,
    body = "";
for (key in orders) {
    if (value = values[key = orders[key]]) {
        if (typeof value === "object" && value[0]) {
            value = value[0];
        }
        body += key + ': ' + value + '\n';
    }
}

Bidang Perihal sebagai Kategori

Anda bisa memanfaatkan fitur editor formulir untuk membatasi bidang yang ada agar hanya bisa diisi oleh nilai-nilai tertentu saja, misalnya dengan memilih tipe bidang Pilihan ganda.

Validasi Alamat Surel

Klik menu tambahan di samping sakelar Wajib diisi kemudian pilih Validasi respons. Pada pilihan Panjang ganti nilainya menjadi Ekspresi reguler (Anda menggunakan Panjang untuk menentukan batasan panjang pesan yang dikirimkan). Dan pada pilihan tambahan di sampingnya ganti nilainya dari Berisi menjadi Kecocokan. Pada bidang Pola, isi dengan ekspresi reguler yang cocok dengan alamat surel (tanpa awalan / dan akhiran /), misalnya seperti ini. Pada bidang Teks kesalahan khusus, isi dengan ‘Pola alamat surel tidak valid.’

Anda juga bisa menerapkan ini pada bidang Situs Web.

Labels: , , ,

Sunday, October 14, 2018

CKEditor 5 Image Upload Adapter

CKEditor 5 Image Upload
Sumber gambar: CKEditor

Menggunakan kode JavaScript <ES6 untuk mengaktifkan fitur pengunggah gambar di CKEditor 5 tanpa layanan Easy Image.

Pembaharuan 2018/12/24: Paket CKEditor 5 Custom Builder untuk pemula sudah tersedia di https://github.com/mecha-cms/c-k-editor.5.

Labels: , , ,

Tuesday, September 25, 2018

Menambahkan Fitur Paginasi di dalam Artikel dengan JavaScript

Fitur Paginasi di dalam Artikel Blogger
Fitur paginasi di dalam artikel.

Fitur ini merupakan implementasi JavaScript dari plugin Mecha bernama Next yang berfungsi untuk memotong konten artikel menjadi beberapa bagian sehingga pengunjung dapat diajak untuk membaca konten artikel langkah demi langkah.

Lihat Demo


Integrasi Widget ke Blogger

Untuk menambahkan fitur ini di blog, pertama-tama buka editor HTML tema Anda kemudian temukan kode yang tampak kurang lebih seperti ini:

<b:widget id='Blog1' type='Blog'>

Pada bagian bawah kode tersebut, sisipkan kode ini:

<b:includable id='postTypeNext' var='post'>
  <b:if cond='data:view.isSingleItem and data:post.labels any (i => i.name in ["Next", "Steps", "How-To", "Berikutnya", "Langkah-Langkah", "Bagaimana-Cara", "type:next"])'>
    <b:class name='type:next'/>
    <script src='//dte-project.github.io/blogger/next.min.js'></script>
  </b:if>
</b:includable>

Kemudian cari kode ini:

<data:post.body/>

Pada setiap kode yang Anda temukan, sisipkan kode ini di bawahnya:

<b:include data='post' name='postTypeNext'/>

Klik Simpan Tema. Fitur paginasi artikel sekarang sudah siap untuk digunakan! Yang perlu Anda lakukan berikutnya adalah menambahkan label Langkah-Langkah atau Bagaimana-Cara atau Steps atau How-To pada artikel yang Anda inginkan.

Untuk menandai bagian-bagian yang perlu dipotong, tambahkan komentar <!-- next --> pada baris yang ingin Anda potong di dalam artikel. Pastikan Anda sedang berada pada mode HTML saat menyunting:

<p>Halaman 1</p>
<!-- next -->
<p>Halaman 2</p>
<!-- next -->
<p>Halaman 3</p>
<!-- next -->
<p>Halaman 4</p>
<!-- next -->
<p>Dan seterusnya.</p>

Jika para pembaca artikel Anda dapat dipastikan menggunakan peramban dengan JavaScript yang aktif, maka akan lebih efektif jika Anda mengaktifkan fitur pramuat gambar pada plugin ini. Cara mengaktifkan fitur pramuat gambar adalah dengan mengubah atribut src pada elemen <img> menjadi data-src sehingga gambar-gambar yang ada tidak akan dimuat sebelum potongan halaman yang berisi gambar tersebut dibuka oleh pembaca:

Sebelum

<img alt="" src="path/to/image.jpg">

Sesudah

<img alt="" src="loading.png" data-src="path/to/image.jpg">

Ganti bagian yang Saya beri tanda dengan URL gambar berukuran kecil, atau jika dirasa kurang praktis, Anda bisa menghapus atribut src pada gambar tersebut.

Pengaturan

Opsi Keterangan
hash Merupakan format fragmen URL untuk menandai pergantian halaman. Pola %i% pada !page=%i% akan diubah menjadi nomor halaman.
kin Digunakan untuk menentukan banyaknya kerabat tombol angka halaman yang akan ditampilkan sebelum dan setelah tombol angka halaman yang aktif.
top Jarak perhentian tambahan antara bagian atas layar halaman dengan bagian atas konten artikel setiap kali halaman berganti.
text Label-label yang diperlukan pada artikel. text[first] untuk menampilkan teks First, text[previous] untuk menampilkan teks Previous, text[next] untuk menampilkan teks Next, text[last] untuk menampilkan teks Last, dan text[current] untuk menampilkan teks Page 1 of 20.

Parameter-parameter di atas dapat Anda tambahkan sebagai parameter URL setelah nama berkas next.min.js:

<script src="next.min.js?top=20"></script>

Labels: , ,

Monday, September 24, 2018

Google Custom Search API

Google Custom Search
Google Penelusuran kustom.

Implementasi dasar API Google Custom Search untuk menampilkan hasil pencarian pada halaman yang sama tanpa harus memuat ulang halaman, dengan HTML formulir yang dibuat secara terpisah dari hasil penelusuran. Selengkapnya bisa dilihat pada kode sumber.


Referensi: Custom Search Element Control API · Google Custom Search

Labels: , , ,

Saturday, September 22, 2018

Mendeteksi Arah Gulungan Layar dengan JavaScript

Google+
Google+

Saat menggunakan aplikasi Google+, tajuk dan navigasi di bagian atas dan bawah akan menghilang ketika Anda menggulung layar ke bawah, sebaliknya, ketika Anda menggulung layar ke atas, tajuk dan navigasi akan muncul kembali.

JavaScript

var currentPageXOffset = 0,
    currentPageYOffset = 0;
window.addEventListener("scroll", function() {
    var X = this.pageXOffset,
        Y = this.pageYOffset;
    if (currentPageXOffset < X) {
        console.log('scroll right');
    } else if (currentPageXOffset > X) {
        console.log('scroll left');
    }
    if (currentPageYOffset < Y) {
        console.log('scroll down');
    } else if (currentPageYOffset > Y) {
        console.log('scroll up');
    }
    currentPageXOffset = X;
    currentPageYOffset = Y;
}, false);

Contoh

Demonstrasi penggunaan deteksi arah gulungan layar untuk menentukan kapan elemen <header> dan <footer> harus ditampilkan atau disembunyikan:

Lihat Demo

Demonstrasi penggunaan deteksi arah gulungan layar untuk menciptakan efek seperti aplikasi Google+:

Lihat Demo

Labels: ,

Wednesday, September 19, 2018

Menambahkan Fitur AJAX Penelusuran di Blog

Fitur AJAX Penelusuran di Blogger
Fitur kotak penelusuran AJAX di blog.

Artikel ini merupakan hasil akumulasi dari temuan-temuan Saya tentang bagaimana kita bisa menggunakan JSON Blogger untuk menciptakan fitur penelusuran dinamis hanya dengan memanfaatkan parameter q pada tautan umpan. Fitur ini dapat diterapkan pada semua tema dan tidak bergantung pada apapun.

Lihat Demo


Integrasi Widget ke Blogger

Untuk mengaktifkan fitur penelusuran AJAX pada blog, Anda tidak perlu menambahkan markup HTML apapun ke dalam tema, karena widget ini akan menggunakan kotak penelusuran yang ada sebagai kotak penelusuran AJAX. Yang perlu Anda lakukan hanya menambahkan sebuah elemen halaman HTML/JavaScript dengan konten berupa kode ini:

<script src="//dte-project.github.io/blogger/search.min.js?live=true"></script>

Klik Simpan Setelan. Fitur penelusuran AJAX sekarang sudah siap untuk digunakan!

Jika kotak penelusuran AJAX tidak bekerja, mungkin itu karena Anda menambahkan widget ini sebelum widget kotak penelusuran. Untuk membuatnya bisa bekerja, Anda perlu meletakkan widget ini setelah widget kotak penelusuran. Selengkapnya bisa dibaca di sini.

Pengaturan

Opsi Keterangan
live Jika bernilai false, maka pengguna perlu mengeklik tombol Telusuri pada formulir atau menekan tombol Enter pada papan ketik untuk memulai penelusuran.
url Ganti nilainya dengan alamat blog Anda atau alamat blog orang lain yang ingin Anda tampilkan kontennya.
id Alternatif untuk menentukan sumber data selain dengan url. Ganti nilainya dengan ID blog Anda atau ID blog orang lain yang ingin Anda tampilkan kontennya. ID harus dituliskan sebagai string. Menambahkan parameter id akan mengabaikan nilai parameter url. Contoh: id="4890949828965961610"
direction Direksi teks pada blog Anda. Nilainya bisa berupa "ltr" atau "rtl".
source Selektor CSS untuk menentukan formulir kotak penelusuran yang ingin dijadikan sebagai kotak penelusuran AJAX. Menghilangkan parameter ini akan membuat widget secara otomatis menyeleksi elemen formulir pertama yang ditemukan yang memiliki nilai atribut action berupa /search pada bagian akhir. Anda bisa menentukan target yang lebih spesifik, misalnya source=%23BlogSearch1%20form untuk menyeleksi elemen formulir pada widget kotak penelusuran yang memiliki ID #BlogSearch1.
container Selektor CSS untuk menentukan di mana hasil penelusuran akan ditampilkan. Menghilangkan parameter ini akan membuat widget secara otomatis menampilkan hasil penelusuran tepat di bawah formulir penelusuran. [demo]
excerpt Ganti nilainya menjadi true untuk menampilkan ringkasan artikel. Atau gunakan angka untuk menentukan maksimal karakter yang akan ditampilkan dalam ringkasan artikel sebelum diakhiri oleh karakter .
image Ganti nilainya menjadi true untuk menampilkan gambar artikel. Atau gunakan angka untuk menentukan ukuran lebar dan tinggi gambar. Anda juga bisa menggunakan parameter standar gambar Google untuk memanipulasi ukuran, seperti "s100", "s100-c", dan "w100-h50".
target Jika bernilai "_blank", semua tautan akan terbuka di tab/jendela baru saat diklik.
chunk Digunakan untuk menentukan banyaknya hasil temuan yang ditampilkan dalam satu kali penelusuran.
text Label-label yang diperlukan pada tampilan penelusuran.

Parameter-parameter di atas dapat Anda tambahkan sebagai parameter URL setelah nama berkas search.min.js:

<script src="search.min.js?live=true&amp;chunk=100&amp;text[loading]=Memuat%E2%80%A6"></script>

Labels: , ,

Saturday, September 8, 2018

Fungsi PHP dan JavaScript untuk Navigasi Halaman Angka

Pagination

Berikut ini adalah fungsi navigasi halaman angka yang paling standar dan paling sesuai untuk diterapkan pada semua kasus. Saya sediakan dalam bahasa JavaScript dan PHP, karena menurut Saya tampilan navigasi ini sangat sederhana namun sudah mencakup semua fitur yang ada. Yaitu fitur navigasi halaman Awal, Akhir, Berikutnya, Sebelumnya, dan navigasi halaman angka yang memungkinkan kita untuk melompati beberapa halaman sekaligus.

JavaScript

function pager(current, count, chunk, peek, fn, first, previous, next, last) {
    var begin = 1,
        end = Math.ceil(count / chunk),
        s = "",
        i, min, max;
    if (end <= 1) {
        return s;
    }
    if (current <= peek + peek) {
        min = begin;
        max = Math.min(begin + peek + peek, end);
    } else if (current > end - peek - peek) {
        min = end - peek - peek;
        max = end;
    } else {
        min = current - peek;
        max = current + peek;
    }
    if (previous) {
        s = '<span>';
        if (current === begin) {
            s += '<b title="' + previous + '">' + previous + '</b>';
        } else {
            s += '<a href="' + fn(current - 1) + '" title="' + previous + '" rel="prev">' + previous + '</a>';
        }
        s += '</span> ';
    }
    if (first && last) {
        s += '<span>';
        if (min > begin) {
            s += '<a href="' + fn(begin) + '" title="' + first + '" rel="prev">' + begin + '</a>';
            if (min > begin + 1) {
                s += ' <span>&hellip;</span>';
            }
        }
        for (i = min; i <= max; ++i) {
            if (current === i) {
                s += ' <b title="' + i + '">' + i + '</b>';
            } else {
                s += ' <a href="' + fn(i) + '" title="' + i + '" rel="' + (current >= i ? 'prev' : 'next') + '">' + i + '</a>';
            }
        }
        if (max < end) {
            if (max < end - 1) {
                s += ' <span>&hellip;</span>';
            }
            s += ' <a href="' + fn(end) + '" title="' + last + '" rel="next">' + end + '</a>';
        }
        s += '</span>';
    }
    if (next) {
        s += ' <span>';
        if (current === end) {
            s += '<b title="' + next + '">' + next + '</b>';
        } else {
            s += '<a href="' + fn(current + 1) + '" title="' + next + '" rel="next">' + next + '</a>';
        }
        s += '</span>';
    }
    return s;
}

PHP

function pager($current, $count, $chunk, $peek, $fn, $first, $previous, $next, $last) {
    $begin = 1;
    $end = (int) ceil($count / $chunk);
    $s = "";
    if ($end <= 1) {
        return $s;
    }
    if ($current <= $peek + $peek) {
        $min = $begin;
        $max = min($begin + $peek + $peek, $end);
    } else if ($current > $end - $peek - $peek) {
        $min = $end - $peek - $peek;
        $max = $end;
    } else {
        $min = $current - $peek;
        $max = $current + $peek;
    }
    if ($previous) {
        $s = '<span>';
        if ($current === $begin) {
            $s .= '<b title="' . $previous . '">' . $previous . '</b>';
        } else {
            $s .= '<a href="' . call_user_func($fn, $current - 1) . '" title="' . $previous . '" rel="prev">' . $previous . '</a>';
        }
        $s .= '</span> ';
    }
    if ($first && $last) {
        $s .= '<span>';
        if ($min > $begin) {
            $s .= '<a href="' . call_user_func($fn, $begin) . '" title="' . $first . '" rel="prev">' . $begin . '</a>';
            if ($min > $begin + 1) {
                $s .= ' <span>&hellip;</span>';
            }
        }
        for ($i = $min; $i <= $max; ++$i) {
            if ($current === $i) {
                $s .= ' <b title="' . $i . '">' . $i . '</b>';
            } else {
                $s .= ' <a href="' . call_user_func($fn, $i) . '" title="' . $i . '" rel="' . ($current >= $i ? 'prev' : 'next') . '">' . $i . '</a>';
            }
        }
        if ($max < $end) {
            if ($max < $end - 1) {
                $s .= ' <span>&hellip;</span>';
            }
            $s .= ' <a href="' . call_user_func($fn, $end) . '" title="' . $last . '" rel="next">' . $end . '</a>';
        }
        $s .= '</span>';
    }
    if ($next) {
        $s .= ' <span>';
        if ($current === $end) {
            $s .= '<b title="' . $next . '">' . $next . '</b>';
        } else {
            $s .= '<a href="' . call_user_func($fn, $current + 1) . '" title="' . $next . '" rel="next">' . $next . '</a>';
        }
        $s .= '</span>';
    }
    return $s;
}

Tentukan nomor halaman saat ini (dimulai dari angka 1), pada current, jumlah total data pada count, jumlah data yang ingin ditampilkan per halaman pada chunk, jumlah navigasi angka yang perlu ditampilkan sebelum dan sesudah angka halaman yang aktif pada peek, fungsi untuk membuat tautan pada fn dan teks untuk masing-masing tautan navigasi pada first, previous, next dan last.

Contoh

JavaScript

container.innerHTML = '<nav>' + pager(1, 500, 10, 2, i => {
    return i === 1 ? '/article' : '/article/' + i;
}, 'Awal', 'Sebelumya', 'Berikutnya', 'Akhir') + '</nav>';

PHP

echo '<nav>' . pager(1, 500, 10, 2, function($i) {
    return $i === 1 ? '/article' : '/article/' . $i;
}, 'Awal', 'Sebelumya', 'Berikutnya', 'Akhir') . '</nav>';

Referensi: StackOverflow Like Pagination

Labels: , ,

Thursday, September 6, 2018

Menghilangkan CSS dan JavaScript Bawaan Blogger

Pembaharuan sintaks Blogger yang sekarang memungkinkan kita mencegah mesin Blogger untuk menyisipkan kode CSS dan JavaScript bawaan ke dalam hasil keluaran HTML tema. Caranya adalah dengan menambahkan atribut b:css dan b:js dengan nilai false.

<html b:css='false' b:js='false'> … </html>

Namun satu hal yang perlu diingat bahwa beberapa fitur bawaan yang bekerja dengan JavaScript mungkin tidak akan bisa bekerja karena perubahan ini. Fitur-fitur tersebut di antaranya adalah fitur balas komentar, fitur buka-tutup pada widget arsip hierarki, fitur formulir kontak, dan juga fitur ini.

Labels: , , ,

Mengakses Tag Kondisional Halaman Blogger di dalam JavaScript

Widget Manager
_WidgetManager._GetAllData()
document.addEventListener("DOMContentLoaded", function() {
    if (typeof _WidgetManager === "undefined") return;
    var data = _WidgetManager._GetAllData();
    // Lakukan sesuatu dengan `data` di sini …
}, false);

Contoh

if (data.view.isSingleItem) { … }
if (data.view.type === "item") { … }
var url = data.view.url;

Labels: , , ,

Wednesday, September 5, 2018

Menambahkan Fitur Komik di Blog dengan JavaScript

Fitur Komik di Blogger
Fitur komik di blog.

Artikel ini merupakan tindak lanjut dari berbagai permintaan pengguna yang mereka tambahkan pada artikel ini yang membahas tentang bagaimana caranya agar gambar-gambar di dalam komik web dapat dimuat secara bergantian untuk mengurangi beban muat halaman. Setelah sekian lama akhirnya Saya punya waktu juga untuk membuat widget yang lebih baik dengan beberapa fitur tambahan, dan yang paling penting adalah widget ini tidak lagi tergantung pada .

Lihat Demo


Integrasi Widget ke Blogger

Untuk menambahkan fitur komik di blog, pertama-tama buka editor HTML tema Anda kemudian temukan kode yang tampak kurang lebih seperti ini:

<b:widget id='Blog1' type='Blog'>

Pada bagian bawah kode tersebut, sisipkan kode ini:

<b:includable id='postTypeComic' var='post'>
  <b:if cond='data:view.isSingleItem and data:post.labels any (i => i.name in ["Comic", "Komik", "type:comic"])'>
    <b:class name='type:comic'/>
    <script src='//dte-project.github.io/blogger/comic.min.js?save=false'></script>
  </b:if>
</b:includable>

Kemudian cari kode ini:

<data:post.body/>

Pada setiap kode yang Anda temukan, sisipkan kode ini di bawahnya:

<b:include data='post' name='postTypeComic'/>

Klik Simpan Tema. Fitur komik sekarang sudah siap untuk digunakan! Yang perlu Anda lakukan berikutnya adalah membuat artikel-artikel baru berisi gambar-gambar, setelah itu cukup tambahkan label Komik atau Comic untuk mengaktifkan tampilan komik.

Widget ini akan mencari semua elemen <a> dan <img> di dalam artikel yang memiliki label Komik atau Comic dan akan mengambil nilai atribut href dan src pada elemen tersebut untuk dijadikan sebagai daftar antrean gambar. Khusus pada nilai atribut href pada elemen <a>, widget ini hanya akan mengambil tautan yang tampak sebagai tautan gambar, yaitu yang memiliki akhiran berupa ekstensi GIF, JPEG, JPG dan PNG.

Selain dari itu akan dianggap sebagai sinopsis atau ringkasan mengenai isi komik.

Saya perlu menambahkan alternatif berupa elemen <a> sebagai penyimpan tautan gambar karena dengan hanya mengandalkan elemen <img>, sama saja dengan meminta peramban untuk memuat semua gambar yang ada saat artikel sedang memuat. Meskipun nantinya ketika komik ditampilkan, gambar-gambar yang ada akan muncul secara bergantian, namun di balik layar sebenarnya peramban akan memuat semua gambar yang ada.

Oleh karena itu Saya sarankan untuk membuat artikel bertipe komik yang terdiri dari satu gambar saja yaitu gambar sampul komik. Sedangkan gambar-gambar yang lainnya dapat Anda tampilkan sebagai tautan biasa seperti ini:

<p>In every class, it’s not usual for there to be one or two people who seem a little strange. In Oda’s class, there is Hototogi.</p>
<p><img alt="Cover" title="Page 1" src="/path/to/image/1.png"></p>
<p><a href="/path/to/image/2.png">Page 2</a></p>
<p><a href="/path/to/image/3.png">Page 3</a></p>
<p><a href="/path/to/image/4.png">Page 4</a></p>
<p><a href="/path/to/image/5.png">Page 5</a></p>
<p><a href="/path/to/image/6.png">Page 6</a></p>
<p><a href="/path/to/image/7.png">Page 7</a></p>

Untuk memperoleh waktu muat komik yang paling cepat, Anda bisa menghapus semua gambar yang ada dan menggantinya dengan elemen <a>, namun kekurangannya adalah nanti Anda tidak akan memiliki elemen <data:post.thumbnailUrl/> untuk ditampilkan sebagai keluku artikel.

Pengaturan

Opsi Keterangan
hash Merupakan format fragmen URL untuk menandai pergantian halaman. Pola %i% pada !page=%i% akan diubah menjadi nomor halaman. [demo]
save Pilihan untuk memungkinkan para pembaca menyimpan gambar komik Anda dengan cara klik kanan pada gambar. Ganti nilainya menjadi false untuk melarang pembaca menyimpan gambar-gambar komik Anda.
image Resolusi maksimal gambar komik yang Anda simpan di Google berupa angka. [demo]
chunk Pilihan untuk menampilkan beberapa gambar sekaligus dalam satu lompatan halaman. Nilai bawaan adalah 1. Jika Anda mengubah nilainya menjadi 2, maka setiap halaman komik akan menampilkan dua gambar. [demo]
kin Digunakan untuk menentukan banyaknya kerabat tombol angka halaman yang akan ditampilkan sebelum dan setelah tombol angka halaman yang aktif.
top Jarak perhentian tambahan antara bagian atas layar halaman dengan bagian atas area komik setiap kali halaman berganti. [demo]
text Label-label yang diperlukan pada komik. text[first] untuk menampilkan teks First, text[previous] untuk menampilkan teks Previous, text[next] untuk menampilkan teks Next, text[last] untuk menampilkan teks Last, text[current] untuk menampilkan teks Page 1 of 20, dan text[enter] untuk menampilkan teks Read on….

Parameter-parameter di atas dapat Anda tambahkan sebagai parameter URL setelah nama berkas comic.min.js:

<script src="comic.min.js?save=false&amp;chunk=2&amp;text[enter]=Read%20More"></script>

Beberapa tema seperti 000000.min.css dan ffffff.min.css dapat Anda tambahkan seperti ini:

  …
  …
  <link href='//dte-project.github.io/blogger/comic/000000.min.css' rel='stylesheet'/>
</head>

Labels: , , ,

Saturday, September 1, 2018

Gawai Daftar Isi Akordion untuk Blogger

Pembaruan 2018/09/01: Berbagai perubahan dan fitur baru telah ditambahkan untuk memenuhi saran dan permintaan para pengguna. Beberapa diskusi yang terdapat di dalam ruang komentar mungkin sudah tidak relevan lagi dengan isi artikel.

Gawai Daftar Isi Akordion untuk Blogger

Kali ini Saya akan memperkenalkan gawai daftar isi akordion berdasarkan label setelah sebelumnya Saya pernah menuliskan tentang gawai daftar isi akordion berdasarkan bulan terbit:

Lihat Demo


Integrasi Gawai ke Blogger

Memasang widget ini memerlukan kemampuan dasar dalam membaca dan menulis kode HTML. Jika Anda termasuk kategori penulis blog yang masih bergantung pada perangkat tulis WYSIWYG atau pada mode Compose di editor Blogger, mungkin Anda perlu mempelajari dasar-dasar penulisan kode HTML terlebih dahulu sebelum menerapkan gawai ini. Sebuah blog dari Niagahoster menyediakan tutorial dasar tentang pemahaman kode HTML untuk pemula dimulai dari persiapan alat hingga pengenalan berbagai tag dan atribut HTML dasar, terutama yang sangat umum dijumpai di dalam konten sebuah artikel seperti format judul, efek huruf tebal dan miring, serta penjelasan tentang cara menyisipkan tautan dan gambar. Anda bisa membacanya di halaman Belajar HTML.

Pertama-tama klik menu Laman pada bilah sisi. Kemudian, pada menu Laman Baru pilihlah Laman Kosong:

Blogger Post Editor
Menambahkan halaman statis baru.

Setelah itu kamu akan melihat formulir halaman statis seperti ini. Klik mode HTML:

Blogger Post Editor
Memilih mode HTML.

Salin kode di bawah ini kemudian letakkan di dalam formulirnya:

<link href="//dte-project.github.io/blogger/stacked-toc/248ab0.min.css" rel="stylesheet">
<script src="//dte-project.github.io/blogger/stacked-toc.min.js?url=http://dte-feed.blogspot.com&amp;active=0"></script>

Ganti URL yang Saya beri tanda dengan alamat blog kamu kemudian klik tombol Publikasikan.

Menghilangkan parameter url akan membuat gawai ini secara otomatis menentukan URL halaman muka berdasarkan URL pada bilah alamat. Berkas 248ab0.min.css adalah berkas tema. Kamu bisa menghapus berkas tersebut jika kamu ingin membuat tema sendiri:

<style>
/* Kode tema kustom di sini… */
</style>
<script src="//dte-project.github.io/blogger/stacked-toc.min.js?active=0"></script>

Pengaturan

Opsi Keterangan
url Ganti nilainya dengan alamat blog kamu atau alamat blog orang lain yang ingin kamu tampilkan kontennya.
id Alternatif untuk menentukan sumber data selain dengan url. Ganti nilainya dengan ID blog kamu atau ID blog orang lain yang ingin kamu tampilkan kontennya. ID harus dituliskan sebagai string. Menambahkan parameter id akan mengabaikan nilai parameter url. Contoh: id="4890949828965961610"
direction Direksi teks pada blog kamu. Nilainya bisa berupa "ltr" atau "rtl".
container Selektor CSS untuk menentukan di mana gawai akan ditampilkan. Menghilangkan parameter ini akan membuat gawai secara otomatis menempatkan diri tepat sebelum tag <script> yang kamu sisipkan.
active Digunakan untuk menentukan urutan panel yang akan aktif saat pertama kali halaman dimuat. Nilai 0 akan membuat panel di urutan pertama menjadi aktif. Nilai "Musim Gugur" akan membuat panel dengan label Musim Gugur menjadi aktif.
toggle Digunakan untuk menentukan sifat panel ketika diklik. Menentukan nilai true akan membuat panel yang aktif menutup dirinya sendiri ketika kamu mengeklik panel tersebut, atau ketika kamu mengeklik panel yang lainnya. Menentukan nilai false akan membuat panel yang aktif menutup hanya ketika kamu mengeklik panel yang lainnya. Menentukan nilai -1 akan membuat panel yang aktif menutup dirinya sendiri hanya ketika kamu mengeklik panel tersebut; panel-panel yang lain tidak akan terpengaruh.
hide Tentukan nama-nama label yang tidak ingin kamu tampilkan.
date Ganti nilainya menjadi false untuk menyembunyikan waktu penerbitan artikel. Selain itu akan dianggap sebagai format waktu penerbitan: %Y% untuk menampilkan angka tahun, %M% untuk menampilkan angka bulan, %D% untuk menampilkan angka hari, %h% untuk menampilkan angka jam format 12, %m% untuk menampilkan angka menit, %s% untuk menampilkan angka detik, %M~% untuk menampilkan nama bulan, %D~% untuk menampilkan nama hari, %h~% untuk menampilkan angka jam format 24, dan %N% untuk menampilkan keterangan waktu format 12; nilainya bisa berupa "AM" atau "PM" tergantung dari data text[midday].
excerpt Ganti nilainya menjadi true untuk menampilkan ringkasan artikel. Atau gunakan angka untuk menentukan maksimal karakter yang akan ditampilkan dalam ringkasan artikel sebelum diakhiri oleh karakter .
image Ganti nilainya menjadi true untuk menampilkan gambar artikel. Atau gunakan angka untuk menentukan ukuran lebar dan tinggi gambar. Kamu juga bisa menggunakan parameter standar gambar Google untuk memanipulasi ukuran, seperti "s100", "s100-c", dan "w100-h50".
target Jika bernilai "_blank", semua tautan akan terbuka di tab/jendela baru saat diklik.
load Digunakan untuk menentukan waktu penundaan pemuatan JSON. Tentukan sebagai angka untuk waktu penundaan memuat dalam satuan milidetik atau true agar gawai ini memuat setelah keseluruhan halaman telah selesai termuat.
sort false untuk menyortir artikel secara normal berdasarkan bulan terbit, 1 untuk menyortir artikel dari A ke Z, -1 untuk menyortir artikel dari Z ke A.
recent false untuk menyembunyikan tanda New!. Ganti dengan angka untuk menentukan berapa banyak artikel terbaru yang ingin ditandai dengan label New!.
text[recent] Markup HTML bebas untuk membuat label New! pada artikel-artikel terbaru.
text[months] Digunakan untuk menentukan nama-nama bulan sesuai dengan sistem kalender di negara tempat kamu tinggal.
text[days] Digunakan untuk menentukan nama-nama hari sesuai dengan sistem kalender di negara tempat kamu tinggal.

Contoh

Menampilkan gambar dan ringkasan:

<script src="stacked-toc.min.js?excerpt=200&amp;image=80"></script>

Membuat panel ke tiga aktif saat pertama kali halaman dimuat:

<script src="stacked-toc.min.js?active=2"></script>

Membuat panel dengan label Iklan aktif saat pertama kali halaman dimuat:

<script src="stacked-toc.min.js?active=Iklan"></script>

Menyembunyikan panel dengan label Iklan dan Tautan:

<script src="stacked-toc.min.js?hide=["Iklan","Tautan"]"></script>
<script src="stacked-toc.min.js?hide[0]=Iklan&amp;hide[1]=Tautan"></script>

Memodifikasi format waktu penerbitan (karakter % harus diubah menjadi %25):

<script src="stacked-toc.min.js?date=%25Y%25-%25M%25-%25D%25%20%25h%25%3A%25m%25%3A%25s%25"></script>

Menentukan kontainer spesifik (karakter # harus diubah menjadi %23):

<script src="stacked-toc.min.js?container=%23content"></script>

Kemudian, pada suatu tempat, Anda buat elemen HTML seperti ini:

<div id="content"></div>

Gunakan alat ini untuk mempermudah dalam mengubah karakter mentah menjadi karakter yang aman untuk URL.


Animasi

Fitur animasi pada gawai ini sudah tidak lagi dibuat menggunakan API jQuery, melainkan hanya memanfaatkan fitur CSS3 transisi. Kamu bisa memodifikasi kecepatan dan percepatan animasi dengan cara seperti ini:

<style>
.stacked-toc-panel {
  /* `ease-in-out-quart` */
  -webkit-transition-timing-function: cubic-bezier(.77, 0, .18, 1);
  -moz-transition-timing-function: cubic-bezier(.77, 0, .18, 1);
  transition-timing-function: cubic-bezier(.77, 0, .18, 1);
  /* ½ detik */
  -webkit-transition-duration: .5s;
  -moz-transition-duration: .5s;
  transition-duration: .5s;
}
</style>
<script src="stacked-toc.min.js?active=0"></script>

Contoh

Labels: , ,

Tuesday, August 14, 2018

Gawai Daftar Isi Tabulasi untuk Blogger

Pembaruan 2018/08/13: Berbagai perubahan dan fitur baru telah ditambahkan untuk memenuhi saran dan permintaan para pengguna. Beberapa diskusi yang terdapat di dalam ruang komentar mungkin sudah tidak relevan lagi dengan isi artikel.

Widget Daftar Isi Tabulasi untuk Bogger

Berikut ini adalah sebuah gawai daftar isi blog berbentuk tabulasi. Gawai ini terdiri dari dua bilah sisi berupa daftar label dan daftar artikel. Setiap nama label akan menjadi tab, sedangkan daftar artikel akan menjadi panel tab yang akan tampil setiap kali tab diklik:

Lihat Demo


Integrasi Gawai ke Blogger

Pertama-tama klik menu Laman pada bilah sisi. Kemudian, pada menu Laman Baru pilihlah Laman Kosong:

Blogger Post Editor
Menambahkan halaman statis baru.

Setelah itu kamu akan melihat formulir halaman statis seperti ini. Klik mode HTML:

Blogger Post Editor
Memilih mode HTML.

Salin kode di bawah ini kemudian letakkan di dalam formulirnya:

<link href="//dte-project.github.io/blogger/tabbed-toc/224c19.min.css" rel="stylesheet">
<script src="//dte-project.github.io/blogger/tabbed-toc.min.js?url=http://dte-feed.blogspot.com&amp;active=0"></script>

Ganti URL yang Saya beri tanda dengan alamat blog Anda kemudian klik tombol Publikasikan.

Menghilangkan parameter url akan membuat gawai ini secara otomatis menentukan URL halaman muka berdasarkan URL pada bilah alamat. Berkas 224c19.min.css adalah berkas tema. Kamu bisa menghapus berkas tersebut jika kamu ingin membuat tema sendiri:

<style>
/* Kode tema kustom di sini… */
</style>
<script src="//dte-project.github.io/blogger/tabbed-toc.min.js?active=0"></script>

Pengaturan

Opsi Keterangan
url Ganti nilainya dengan alamat blog kamu atau alamat blog orang lain yang ingin kamu tampilkan kontennya.
id Alternatif untuk menentukan sumber data selain dengan url. Ganti nilainya dengan ID blog kamu atau ID blog orang lain yang ingin kamu tampilkan kontennya. ID harus dituliskan sebagai string. Menambahkan parameter id akan mengabaikan nilai parameter url. Contoh: id="4890949828965961610"
direction Direksi teks pada blog kamu. Nilainya bisa berupa "ltr" atau "rtl".
container Selektor CSS untuk menentukan di mana gawai akan ditampilkan. Menghilangkan parameter ini akan membuat gawai secara otomatis menempatkan diri tepat sebelum tag <script> yang kamu sisipkan.
active Digunakan untuk menentukan urutan tab yang akan aktif saat pertama kali halaman dimuat. Nilai 0 akan membuat tab di urutan pertama menjadi aktif. Nilai "Musim Gugur" akan membuat tab dengan label Musim Gugur menjadi aktif.
hide Tentukan nama-nama label yang tidak ingin kamu tampilkan.
date Ganti nilainya menjadi false untuk menyembunyikan waktu penerbitan artikel. Selain itu akan dianggap sebagai format waktu penerbitan: %Y% untuk menampilkan angka tahun, %M% untuk menampilkan angka bulan, %D% untuk menampilkan angka hari, %h% untuk menampilkan angka jam format 12, %m% untuk menampilkan angka menit, %s% untuk menampilkan angka detik, %M~% untuk menampilkan nama bulan, %D~% untuk menampilkan nama hari, %h~% untuk menampilkan angka jam format 24, dan %N% untuk menampilkan keterangan waktu format 12; nilainya bisa berupa "AM" atau "PM" tergantung dari data text[midday].
excerpt Ganti nilainya menjadi true untuk menampilkan ringkasan artikel. Atau gunakan angka untuk menentukan maksimal karakter yang akan ditampilkan dalam ringkasan artikel sebelum diakhiri oleh karakter .
image Ganti nilainya menjadi true untuk menampilkan gambar artikel. Atau gunakan angka untuk menentukan ukuran lebar dan tinggi gambar. Kamu juga bisa menggunakan parameter standar gambar Google untuk memanipulasi ukuran, seperti "s100", "s100-c", dan "w100-h50".
target Jika bernilai "_blank", semua tautan akan terbuka di tab/jendela baru saat diklik.
load Digunakan untuk menentukan waktu penundaan pemuatan JSON. Tentukan sebagai angka untuk waktu penundaan memuat dalam satuan milidetik atau true agar gawai ini memuat setelah keseluruhan halaman telah selesai termuat.
sort false untuk menyortir artikel secara normal berdasarkan bulan terbit, 1 untuk menyortir artikel dari A ke Z, -1 untuk menyortir artikel dari Z ke A.
recent false untuk menyembunyikan tanda New!. Ganti dengan angka untuk menentukan berapa banyak artikel terbaru yang ingin ditandai dengan label New!.
text[recent] Markup HTML bebas untuk membuat label New! pada artikel-artikel terbaru.
text[months] Digunakan untuk menentukan nama-nama bulan sesuai dengan sistem kalender di negara tempat kamu tinggal.
text[days] Digunakan untuk menentukan nama-nama hari sesuai dengan sistem kalender di negara tempat kamu tinggal.

Contoh

Menampilkan gambar dan ringkasan:

<script src="tabbed-toc.min.js?excerpt=200&amp;image=80"></script>

Membuat tab ke tiga aktif saat pertama kali halaman dimuat:

<script src="tabbed-toc.min.js?active=2"></script>

Membuat tab dengan label Iklan aktif saat pertama kali halaman dimuat:

<script src="tabbed-toc.min.js?active=Iklan"></script>

Menyembunyikan tab dengan label Iklan dan Tautan:

<script src="tabbed-toc.min.js?hide=["Iklan","Tautan"]"></script>
<script src="tabbed-toc.min.js?hide[0]=Iklan&amp;hide[1]=Tautan"></script>

Memodifikasi format waktu penerbitan (karakter % harus diubah menjadi %25):

<script src="tabbed-toc.min.js?date=%25Y%25-%25M%25-%25D%25%20%25h%25%3A%25m%25%3A%25s%25"></script>

Menentukan kontainer spesifik (karakter # harus diubah menjadi %23):

<script src="tabbed-toc.min.js?container=%23content"></script>

Kemudian, pada suatu tempat, Anda buat elemen HTML seperti ini:

<div id="content"></div>

Gunakan alat ini untuk mempermudah dalam mengubah karakter mentah menjadi karakter yang aman untuk URL.

Menyembunyikan iklan:

<script src="tabbed-toc.min.js?ad=false"></script>

Gawai ini Saya buat sebagai kode sumber yang terbuka sehingga Saya pada dasarnya tidak menghasilkan keuntungan apa-apa secara finansial. Ada baiknya kamu bersedia membantu Saya untuk menyebarkan alamat web ini dengan cara tidak menentukan nilai parameter ad sebagai false atau dengan cara berinisiatif memasang iklan pada web ini. Dengan begitu Saya dapat terus termotivasi untuk mengembangkan gawai-gawai yang ada. Menentukan nilai berupa angka akan membuat tautan web ini muncul setiap N sekali dimana N memiliki arti seberapa banyak pengunjung yang sama memuat ulang halaman kamu:

<script src="tabbed-toc.min.js?ad=10"></script>

Contoh

Labels: , ,

Parser JSON untuk Blogger · Tahun Awal dan Tahun Akhir

var url = 'http://dte-feed.blogspot.com/feeds/posts/summary?alt=json-in-script&callback=';

// Function to load a `<script>` tag without `document.write`
function load(url) {
    var script = document.createElement('script');
    script.src = url;
    document.head.appendChild(script);
}

// Get the first and last post year…
function getFirstAndLastYear($) {
    $ = $.feed || {};
    var entry = $.entry || [],
        range = {};
    // Get the first post year from `json.feed.entry[i].published.$t` value
    range[0] = entry[0] && +entry[0].published.$t.split('-')[0] || false;
    // Get the last post year from `json.feed.updated.$t` value
    range[1] = +$.updated.$t.split('-')[0];
    // [3]. Result will be available in the `range` variable as `[from, to]` format
    console.log(range);
    // You can now do stuff using the `range` variable start from here
    document.getElementById('blog-history').innerHTML = '\u00A9 Copyright ' + range[0] + ' \u2013 ' + range[1];
}

// Get the total posts…
function getTotalPosts($) {
    $ = $.feed || {};
    var i = $.openSearch$totalResults.$t,
        entry = $.entry || [];
    // [2]. Get the first and last post year…
    // Use the `max-results` and `start-index` parameter to limit the posts
    load(url + 'getFirstAndLastYear&max-results=1&start-index=' + i);
}

// [1]. Get the total posts…
load(url + 'getTotalPosts&max-results=0');

Labels: , , ,

Friday, May 4, 2018

Menyimpan Data Konfigurasi pada Skrip Pemanggil

Belakangan ini Saya mulai mengimplementasikan teknik penyimpanan data konfigurasi JavaScript yang menarik pada ekstensi-ekstensi Mecha yang berhubungan dengan JavaScript. Saya pikir, mungkin akan bermanfaat jika Saya menjabarkannya juga di sini karena beberapa pengembang skrip Blogger tentu akan sangat terbantu dengan teknik semacam ini. Saya sendiri tidak tahu siapa yang pertama kali memberikan gagasan ini, jadi untuk saat ini Saya masih tidak dapat menyebutkan orang-orang yang terkait dengan praktik semacam ini satu per satu. Metode klasik yang sering kita jumpai tentang bagaimana cara menyimpan variabel konfigurasi JavaScript adalah sebagai berikut:

Metode 1: Pada Tag Skrip Terpisah

Di sini pengguna diminta untuk mendefinisikan data konfigurasi pada variabel JavaScript yang diletakkan terpisah dari skrip utama.

<script>
var config = {
    var_1: 'foo',
    var_2: 'bar',
    var_3: 4
};
</script>
<script src="main.js"></script>

Kemudian di dalam berkas main.js kita bisa memanggil data konfigurasi yang ada satu per satu. Beberapa nilai default mungkin perlu ditentukan juga untuk memastikan skrip tetap bisa bekerja meski pengguna tidak mendefinisikan data konfigurasi yang diperlukan pada variabel konfigurasi pengguna:

var config = config || {};

var var_1 = config.var_1 || 'foo',
    var_2 = config.var_2 || 'bar',
    var_3 = config.var_3 || 4;

// Lakukan sesuatu dengan `var_1`, `var_2` dan `var_3` di sini…

Metode 2: Pada Argumen Fungsi

Di sini pengguna diminta untuk mendefinisikan data konfigurasi pada variabel JavaScript sebagai parameter fungsi. Tampilannya lebih ringkas jika dibandingkan dengan metode pertama meski kita masih tetap memerlukan tag skrip terpisah. Parameter bisa berupa satu variabel sebagai objek yang menyimpan beberapa data atau beberapa variabel yang masing-masing variabel menyimpan data tunggal:

Sebagai Objek

<script src="main.js"></script>
<script>
var main = new Main({
    var_1: 'foo',
    var_2: 'bar',
    var_3: 4
});
</script>

Kemudian di dalam berkas main.js:

function Main(config) {
    config = config || {};
    this.var_1 = config.var_1 || 'foo';
    this.var_2 = config.var_2 || 'bar';
    this.var_3 = config.var_3 || 4;

    // Lakukan sesuatu dengan `this.var_1`, `this.var_2` dan `this.var_3` di sini…

}

Sebagai Deret Variabel

<script src="main.js"></script>
<script>
var main = new Main('foo', 'bar', 4);
</script>

Kemudian di dalam berkas main.js:

function Main(var_1, var_2, var_3) {
    this.var_1 = var_1 || 'foo';
    this.var_2 = var_2 || 'bar';
    this.var_3 = var_3 || 4;

    // Lakukan sesuatu dengan `this.var_1`, `this.var_2` dan `this.var_3` di sini…

}

Metode 3: Pada Elemen HTML

Beberapa ada juga yang menggunakan teknik penyimpanan data konfigurasi JavaScript pada elemen HTML yang terkait dengan eksekusi skrip tertentu. Hal ini biasanya dipraktikkan untuk meringkas beberapa eksekusi JavaScript sekaligus yang memerlukan data konfigurasi yang berbeda-beda pada masing-masing elemen HTML yang dikenai.

Ketika kita menggunakan metode ke dua, maka ini yang akan terjadi:

<div class="item" id="item-1"></div>
<div class="item" id="item-2"></div>
<div class="item" id="item-3"></div>

<script src="main.js"></script>
<script>

var itam_1 = new Item(document.querySelector('#item-1'), {
    var_1: 'foo untuk item 1',
    var_2: 'bar untuk item 1',
    var_3: 4
});

var itam_2 = new Item(document.querySelector('#item-2'), {
    var_1: 'foo untuk item 2',
    var_2: 'bar untuk item 2',
    var_3: 7
});

var itam_3 = new Item(document.querySelector('#item-3'), {
    var_1: 'foo untuk item 3',
    var_2: 'bar untuk item 3',
    var_3: 2
});

</script>

Kemudian di dalam berkas main.js:

function Item(target, config) {
    config = config || {};
    target.innerHTML = config.var_1 || "";
    target.title = config.var_2 || null;

    // dan seterusnya…

}

Solusi paling mudah untuk mengatasi masalah ini adalah dengan menyimpan data konfigurasi pada elemen target itu sendiri. Mengenai format data yang tersimpan bisa bermacam-macam, tapi yang paling umum adalah tersimpan sebagai JSON:

<div class="item" id="item-1" data-config='{
  "var_1": "foo untuk item 1",
  "var_2": "bar untuk item 1",
  "var_3": 4
}'></div>

<div class="item" id="item-2" data-config='{
  "var_1": "foo untuk item 2",
  "var_2": "bar untuk item 2",
  "var_3": 7
}'></div>

<div class="item" id="item-3" data-config='{
  "var_1": "foo untuk item 3",
  "var_2": "bar untuk item 3",
  "var_3": 2
}'></div>

<script src="main.js"></script>
<script>

document.querySelectorAll('.item').forEach(function(target) {
    new Item(target, JSON.parse(target.getAttribute('data-config')));
});

</script>

Metode 4: Pada Tag Skrip Itu Sendiri

Ini adalah metode penyimpanan data konfigurasi yang belakangan ini Saya sukai karena dapat meringkas penulisan data konfigurasi global yang biasanya harus dituliskan pada variabel terpisah (untuk menyederhanakan penerapan data konfigurasi yang spesifik pada target yang berbeda, Saya lebih memilih metode ke tiga).

<script src="main.js" data-config='{
  "var_1": "foo",
  "var_2": "bar",
  "var_3": 4
}'></script>

Kemudian di dalam berkas main.js, kita menggunakan document.currentScript untuk mendapatkan elemen <script> yang digunakan untuk memanggil berkas main.js:

var script = document.currentScript;

var config = JSON.parse(script.getAttribute('data-config'));

Kita juga bisa menggunakan teks kueri di URL berkas main.js untuk menyimpan data konfigurasi, tapi kita perlu fungsi khusus seperti ini atau ini atau ini untuk mengubah teks kueri menjadi objek.

<script src="main.js?var_1=foo&amp;var_2=var&amp;var_3=4"></script>
var script = document.currentScript;

var config = get_vars(script.src);

function get_vars(url) {  }

Labels: ,