Friday, July 19, 2013

Daftar Snippet untuk Implementasi DOM Range API

Mendapatkan Teks yang Terseleksi

Paling dasar. Fungsi ini digunakan untuk mengambil teks yang terseleksi. Hanya teks. Tag HTML tidak akan direpresentasikan sebagai node apa adanya. Untuk mengubah node terseleksi menjadi HTML, gunakan fungsi ini:

function getSelectionText() {
    var sel = "";
    if (window.getSelection) {
        sel = window.getSelection();
    } else if (document.getSelection) {
        sel = document.getSelection();
    } else if (document.selection) { // IE
        sel = document.selection.createRange().text;
    }
    return sel;
}

Contoh Penggunaan

document.onmouseup = function() {
    alert(getSelectionText());
};

Lihat Demo

Seleksi Teks Otomatis

function autoSelect(elem) {
    var sel, range;
    if (window.getSelection) {
        sel = window.getSelection();
        range = document.createRange();
        range.selectNodeContents(elem);
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (document.selection) { // IE
        sel = document.selection.createRange().text;
        range = document.body.createTextRange();
        range.moveToElementText(elem);
        range.select();
    }
}

Selengkapnya

Konversi Node Terseleksi ke HTML

Fungsinya adalah untuk membawa bagian-bagian yang terseleksi menjadi HTML dalam bentuk string, sehingga hasil yang didapatkan bisa ditempelkan ke area tertentu sebagai duplikat yang sama dengan bagian yang terseleksi:

// http://stackoverflow.com/a/4652824
function getSelectionHTML() {
    var html = "";
    if (typeof window.getSelection != 'undefined') {
        var sel = window.getSelection();
        if (sel.rangeCount) {
            var container = document.createElement('div'); // Just a placeholder
            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
                container.appendChild(sel.getRangeAt(i).cloneContents());
            }
            html = container.innerHTML;
        }
    } else if (typeof document.selection != 'undefined') {
        if (document.selection.type == 'Text') {
            html = document.selection.createRange().htmlText;
        }
    }
    return html;
}

Contoh Penggunaan

Sisipkan bagian yang terseleksi ke dalam area #result-container sebagai HTML:

document.getElementById('action-btn').onclick = function() {
    document.getElementById('result-container').innerHTML = getSelectionHTML();
};

Lihat Demo

Manipulasi Posisi dan Jarak Seleksi

Fungsi ini digunakan untuk membuat jarak seleksi pada posisi yang telah ditentukan. Cuma berlaku untuk elemen formulir. Menentukan nilai yang sama pada parameter selectionStart dan selectionEnd memungkinkan fungsi ini untuk digunakan sebagai pengatur letak caret teks:

// http://stackoverflow.com/a/499158
function setSelectionRange(input, selectionStart, selectionEnd) {
    if (input.setSelectionRange) {
        input.focus();
        input.setSelectionRange(selectionStart, selectionEnd);
    } else if (input.createTextRange) {
        var range = input.createTextRange();
        range.collapse(true);
        range.moveEnd('character', selectionEnd);
        range.moveStart('character', selectionStart);
        range.select();
    }
}

Contoh Penggunaan

document.getElementById('action-btn').onclick = function() {
    setSelectionRange(document.getElementById('target-textarea'), 10, 100);
};

Lihat Demo

Memposisikan Caret ke Bagian Akhir Area Teks

// http://stackoverflow.com/a/4716021
function moveCaretToEnd(el) {
    if (typeof el.selectionStart == 'number') {
        el.selectionStart = el.selectionEnd = el.value.length;
    } else if (typeof el.createTextRange != 'undefined') {
        el.focus();
        var range = el.createTextRange();
        range.collapse(false);
        range.select();
    }
}

Contoh Penggunaan

<textarea onfocus="moveCaretToEnd(this);"> ... </textarea>

Lihat Demo

Menyimpan dan Mengembalikan Teks Terseleksi

Fungsi pertama digunakan untuk mendapatkan teks terseleksi agar bisa Anda simpan ke dalam variabel. Fungsi ke dua digunakan untuk mengembalikan node terseleksi yang telah Anda simpan tadi:

// http://stackoverflow.com/a/2925633

var savedSelection = null; // Variable to save the selected node

function saveSelection() {
    if (window.getSelection) {
        var sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection && document.selection.createRange) {
        return document.selection.createRange();
    }
    return null;
}

function restoreSelection(range) {
    if (range) {
        if (window.getSelection) {
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (document.selection && range.select) {
            range.select();
        }
    }
}

Penggunaan

document.getElementById('save-selection-btn').onclick = function() {
    savedSelection = saveSelection();
};

document.getElementById('restore-selection-btn').onclick = function() {
    restoreSelection(savedSelection);
};

Lihat Demo

Mendapatkan Jarak Awal dan Akhir Teks Terseleksi pada Area Teks

function getInputSelection(el) { // http://stackoverflow.com/a/3053640

    var start = 0,
        end = 0,
        normalizedValue,
        range,
        textInputRange,
        len,
        endRange;

    if (typeof el.selectionStart == 'number' && typeof el.selectionEnd == 'number') {

        start = el.selectionStart;
        end = el.selectionEnd;

    } else {

        range = document.selection.createRange();

        if (range && range.parentElement() == el) {

            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working text range that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since `moveStart`/`moveEnd` doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;
                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }

        }

    }

    return {
        start: start,
        end: end
    };

}

Penggunaan

document.getElementById('test-btn').onmousedown = function() {
    var position = getInputSelection(document.getElementById('test-textarea'));
    alert('Start: ' + position.start + ', End: ' + position.end);
};

Lihat Demo

Menyisipkan Sesuatu Setelah Caret

1. <div contenteditable>

Fungsi yang bisa bekerja pada elemen HTML dengan atribut contenteditable:

// http://stackoverflow.com/a/6691294
function pasteHtmlAtCaret(html) {
    var sel, range, el, frag, node, lastNode;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
            // `Range.createContextualFragment()` would be useful here but is
            // non-standard and not supported in all browsers (IE9, for one)
            el = document.createElement('div');
            el.innerHTML = html;
            frag = document.createDocumentFragment();
            while ((node = el.firstChild)) {
                lastNode = frag.appendChild(node);
            }
            range.insertNode(frag);
            // Preserve the selection
            if (lastNode) {
                range = range.cloneRange();
                range.setStartAfter(lastNode);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }
    } else if (document.selection && document.selection.type != 'Control') {
        // IE < 9
        document.selection.createRange().pasteHTML(html);
    }
}

Contoh Penggunaan

Sisipkan emoticon setelah kursor caret:

document.getElementById('insert-btn').onclick = function() {
    pasteHtmlAtCaret('<img src="emoticon.gif" width="16" height="16">');
};

Lihat Demo

2. <textarea>

Fungsi yang bisa bekerja pada elemen formulir teks seperti <textarea>:

// http://stackoverflow.com/a/11070952
function insertStringAtCaret(str, elem) {
    var value = elem.value,
        before = value.substring(0, elem.selectionStart),
        after = value.substring(elem.selectionEnd, value.length),
        pos = before.length + str.length;
    elem.value = before + str + after;
    setSelectionRange(elem, pos, pos);
}

function setSelectionRange(input, selectionStart, selectionEnd) {#code-snippet:manipulasi-posisi-dan-jarak-seleksi}

Contoh Penggunaan

<button onmousedown="insertStringAtCaret(' :D ', document.getElementById('target-textarea'));">:D</button>

Lihat Demo

Menyisipkan Sesuatu Sebelum dan Setelah Teks Terseleksi

Pada umumnya digunakan untuk menyisipkan tag HTML sebelum teks terseleksi dan setelah teks terseleksi. Fungsi ini Saya buat berdasarkan fungsi di atas:

// Mendukung untuk semua peramban mayor dan IE8+
function wrapText(str1, str2, elem) {
    var value = elem.value,
        before = value.substring(0, elem.selectionStart),
        selected = value.substring(elem.selectionStart, elem.selectionEnd),
        after = value.substring(elem.selectionEnd, value.length),
        endpos = before.length + str1.length + selected.length + str2.length;
    elem.value = before + str1 + selected + str2 + after;
    setSelectionRange(elem, before.length, endpos);
}

function setSelectionRange(input, selectionStart, selectionEnd) {#code-snippet:manipulasi-posisi-dan-jarak-seleksi}

Contoh Penggunaan

<button onclick="wrapText('<b>', '</b>', document.getElementById('target-textarea'));">Bold</button>

Lihat Demo

Mendapatkan Elemen Induk dari Teks yang Terseleksi

// http://stackoverflow.com/a/1336922
// The following will return the container element of the start or end boundary of the current selection
// `getSelectionBoundaryElement()` will select the last container element of the current multiple container selection.
// `getSelectionBoundaryElement(true)` will select the first container element of the current multiple container selection.
function getSelectionBoundaryElement(isStart) {
    var range, sel, container;
    if (document.selection) {
        range = document.selection.createRange();
        range.collapse(isStart);
        return range.parentElement();
    } else {
        sel = window.getSelection();
        if (sel.getRangeAt) {
            if (sel.rangeCount > 0) {
                range = sel.getRangeAt(0);
            }
        } else {
            // Old WebKit
            range = document.createRange();
            range.setStart(sel.anchorNode, sel.anchorOffset);
            range.setEnd(sel.focusNode, sel.focusOffset);
            // Handle the case when the selection was selected backwards (from the end to the start in the document)
            if (range.collapsed !== sel.isCollapsed) {
                range.setStart(sel.focusNode, sel.focusOffset);
                range.setEnd(sel.anchorNode, sel.anchorOffset);
            }
        }
        if (range) {
           container = range[isStart ? "startContainer" : "endContainer"];
           // Check if the container is a text node and return its parent if so
           return container.nodeType === 3 ? container.parentNode : container;
        }   
    }
}

Contoh Penggunaan

function getSelectionText() {#code-snippet:mendapatkan-teks-yang-terseleksi}

document.onmouseup = function() {
    if (getSelectionText().toString() !== "") {
        var parentElem = getSelectionBoundaryElement();
        parentElem.style.backgroundColor = "#ff0";
    }
};

Lihat Demo


Labels: , ,

Wednesday, July 17, 2013

Lisensi, Atribusi dan Hak Cipta

Sebuah hasil karya yang dipublikasikan tanpa lisensi tidak memiliki artian bahwa hasil karya tersebut merupakan karya yang bebas atau telah dibuang. Selalu ada beberapa hal yang akan mengikat Anda sebagai pihak pengguna, tidak peduli apakah pihak pencipta telah memberitahukannya kepada Anda atau tidak.

Dalam sebuah produk karya ciptaan, setidaknya terdapat minimal 5 persyaratan yang akan mengikat Anda sebagai seorang calon pemakai hasil karya secara tidak langsung, meski sang pembuat produk tersebut tidak memberitahukannya sejak awal. Beberapa persyaratan yang Saya maksud diantaranya adalah:

  1. Apakah boleh dipakai?
  2. Apakah boleh dimodifikasi?
  3. Apakah boleh disebarluaskan?
  4. Apakah boleh menghapus atribusi pembuat hasil karya?
  5. Apakah boleh dijual?

1. Apakah boleh dipakai?

Kalau tidak boleh dipakai ya jangan dipakai!!! Kamu itu bagaimana sih?! Itu kan bukan barang-barang kepunyaanmu.

2. Apakah boleh dimodifikasi?

Kemungkinanya boleh. Jika boleh, maka umumnya syarat legal yang harus Anda penuhi sebagai seseorang yang akan memodifikasi hasil karya adalah dengan cara tetap mencantumkan nama si pembuat asli hasil karya tersebut, untuk kemudian bisa diikuti dengan nama Anda di bawahnya. Itu adalah cara terbaik dan paling miskin yang bisa Anda lakukan untuk menghargai karya ciptaan orang lain, terutama jika Anda tidak memiliki biaya untuk membeli hak cipta dari hasil karya yang sedang coba Anda pakai. Misalnya seperti ini:

/*
Created by Taufik Nurrohman (http://www.my_site.com)
Modified by Lorem Ipsum (http://www.your_site.com)
*/

Pastikan nama dan alamat sumber tertulis secara jelas dan jangan sekali-kali berusaha untuk mengaburkan sumber aslinya, karena itu bisa mengakibatkan kebingungan bagi para pengguna lain yang mungkin tidak sengaja memakai hasil karya salinan dengan lisensi atribusi yang sudah tidak benar. Jika itu terjadi, setiap orang bisa saja mencoba untuk mengambil kepemilikan dari hasil karya tersebut. Jika kebetulan orang tersebut adalah orang penting dan merasa bahwa hasil karya tersebut adalah sesuatu yang sangat berharga baginya, kemungkinan orang tersebut akan berubah gila dan akan menuntut secara hukum siapa saja yang mengaku sebagai pembuat asli hasil karya tersebut, padahal dia sendiri sebenarnya juga bukan pembuat asli hasil karya tersebut. Hanya karena dia punya banyak uang dan memiliki pengacara, maka dia bisa memenangkan hak cipta dari sebuah hasil karya dengan cara yang tidak benar. Jika itu sampai terjadi, sang pembuat hasil karya yang asli bisa terjerat masalah hukum yang seharusnya tidak ditimpakan kepadanya hanya karena perbuatanmu.

3. Apakah boleh disebarluaskan?

Jika ternyata boleh, pastikan semua data masih dalam keadaan utuh sebagaimana mestinya. Jangan ada bagian manapun yang Anda modifikasi.

Terkadang Saya merasa heran dengan para distributor template atau tema blog yang suka mencantumkan tautan mereka di footer hasil karya orang lain seperti ini:

Attribution of a creation.
Menyisipkan atribusi di sekitar atribusi orang lain tanpa izin.

Sebagai seorang distributor, sebenarnya wajar jika Anda sempat terpikir (sampai kemudian melakukannya) untuk “numpang” menambahkan tautan Anda di sekitar atribusi mereka agar bisa memperoleh trafik secara gratis dari para pemakai. Namanya juga kesempatan. Tapi apakah tidak bisa jika Anda mencantumkan tautan Anda secara terpisah saja, misalnya di dalam sebuah file teks dengan isi seperti ini. Menurut Saya cara ini lebih sopan:

Readme file.
File readme untuk mencantumkan alamat sumber distributor.

Berikut ini adalah salah satu contoh file lisensi yang Saya dapatkan dari dalam sebuah paket font berlisensi gratis:

  *        *
hello there font lover you've downloaded a
*        *
SOLAR*SISTER font 

from www.hellostranger.com/solarsister/

  *            * *
   *      *           *      *
    *    *
there are only a few rules:
        *            *
The fonts are all free ware, which means you can do pretty much
whatever the hell you want with them, except claim them as your own,
of course. If you use them though, I'd like to see where. Drop me a line:

solarsister@hellostranger.com. 
                   *                    *
However, if you want to redistribute any of the typefaces contained
herein, please ask first. Of course, this read-me file must be attatched. 

     *            * *
   *      *           *      *
    *

send me a postcard with your e-mail address and I'll send you a special font
 *      *           *      *
PO Box 616
Mt Lawley WA 6929
Australia
 *      *           *      *
  *            * *
   *      *           *      *
    *

4. Apakah boleh menghapus atribusi pembuat hasil karya?

Ini adalah pertanyaan yang biasa dilontarkan orang-orang gengsi yang ingin tampil mengesankan tapi dengan cara memakai barang-barang hasil ciptaan orang lain. Kebanyakan pembuat hasil karya terbuka/gratis umumnya memperbolehkan Anda untuk menghapus/tidak mencantumkan atribusi mereka selama Anda tidak mengganti atribusi mereka dengan atribusi-atribusi palsu (biasanya dengan cara mengganti nama mereka dengan nama Anda untuk mengklaim bahwa karya tersebut adalah buatan Anda). Jika tidak boleh dihapus, seharusnya mereka akan memberikan peringatan bahwa hasil karya mereka boleh dipakai dengan syarat tetap mencantumkan atribusi mereka. Entah dengan cara mencantumkan tautan sumber pada footer atau bagian-bagian akhir artikel Anda dimana hasil karya orang tersebut terdapat di dalamnya, atau sekedar menuliskannya di dalam komentar-komentar file HTML, CSS dan JavaScript jika karya tersebut merupakan kode/teks. Tapi Saya sarankan tetap pertahankan saja atribusi mereka untuk menghargai apa yang berhasil mereka ciptakan.

5. Apakah boleh dijual?

Untuk hasil karya bebas yang biasa tersebar di internet, umumnya selalu terdapat semacam file teks berjudul readme di dalam paket unduhan yang bisa Anda baca untuk mengetahui syarat-syarat apa saja yang harus dipenuhi oleh Anda sebagai calon pemakai hasil karya tersebut. Untuk karya-karya dengan lisensi gratis biasanya cukup dengan mencantumkan atribusi sang pembuat hasil karya pada tempat-tempat yang mereka inginkan. Setelah itu Anda sudah bisa memakainya secara legal. Namun beberapa kegiatan lain seperti penghapusan atribusi atau penjualan hasil karya biasanya harus mengikuti langkah-langkah yang lebih rumit. Akan terdapat beberapa syarat yang akan mengarahkan Anda kepada aktivitas pemberian sejumlah uang, karena Anda sedang mencoba untuk mengomersialisasikan dan/atau menghilangkan jejak dari sesuatu yang bukan merupakan milik Anda. Syarat yang paling sederhana misalnya, berupa pemberian sejumlah uang sebagai donasi atau melakukan perjanjian royalti. Seperti itulah. Ini contohnya:

anke-art fonts = Donation Ware!

Hi! This is another annoying readme-file.
But if you like my font, I'm asking you to
put a link to my page www.anke-art.de on YOUR page.
On my homepage you can find a little logo in the
upper left corner which you can copy as a link.

If you don't want to link to my page,
but still want to use my font(s) nevertheless,please send any amount in US-Dollars (which you think the font is worth) to:

Anke Arnold
Fabrikstrasse 62
73240 Wendlingen
Germany

Thank you sooo much!

Mengenai Penggantian Atribusi Hasil Karya

Pembolehan penggantian atribusi Saya rasa tidak akan pernah ada di dalam persyaratan seorang pembuat hasil karya sampai kapanpun, karena itu sudah masuk ke dalam wilayah kejahatan plagiarisme. Yaitu ketika Anda mencoba untuk menipu banyak orang dengan cara mengambil hasil karya orang lain yang menurut Anda bisa membuat orang-orang di sekitar Anda terkesan, kemudian mengklaim bahwa hasil karya tersebut merupakan hasil karya ciptaan Anda. Itu dilakukan tidak lain untuk memperoleh pencitraan yang baik dalam diri Anda atau untuk mencapai tujuan-tujuan lain yang berbau komersial sampai ke arah usaha-usaha untuk menjatuhkan pihak lain yang sedang Anda benci saat itu.

Memang, mungkin sang pembuat hasil karya memperbolehkan Anda untuk memodifikasi hasil karya mereka, namun bukan berarti Anda diperbolehkan untuk mengganti keterangan pembuat hasil karya tersebut secara keseluruhan dengan nama Anda. Itu ilegal. Bahkan Saya bisa mengatakan bahwa menghapus atribusi masih termasuk dalam kejahatan (kejahatan, dalam artian bahwa si pembuat hasil karya asli tidak memperbolehkan Anda untuk menghapus atribusi mereka) yang bisa dimaafkan, karena Saya sadar bahwa tidak semua orang bisa merasa nyaman jika harus selalu hidup dibawah bayang-bayang nama orang lain melalui barang-barang yang sedang mereka pakai.

Tidak ada yang salah dengan sesuatu yang gratis. Hanya saja, untuk mendapatkan sesuatu secara gratis pasti akan ada beberapa syarat yang harus Anda penuhi. Jika Anda tidak mau mematuhi persyaratan yang mereka berikan, ya Anda jangan sekali-kali memakai hasil karya mereka. Belajarlah untuk membuatnya sendiri.

Sebagai informasi, mempertahankan atribusi adalah satu-satunya cara yang bisa Anda lakukan untuk menghargai para kreator yang telah rela membagikan hasil-hasil karya mereka secara gratis. Karena mereka tidak mendapatkan keuntungan apa-apa dari hasil karya yang mereka buat.

Hubungi Mereka

Meski kemudian pada akhirnya Anda diperbolehkan untuk melanggar beberapa persyaratan yang mereka berikan, tentunya akan terdapat beberapa “ritual” ganti rugi yang harus Anda korbankan sebagai pihak pengguna yang reseh dan banyak maunya. Akan lebih baik jika Anda menghubungi si pembuat hasil karya tersebut secara langsung dan menanyakan mengenai pembolehan Anda sebagai seorang pengguna untuk melakukan sesuatu terhadap hasil karya mereka jika Anda merasa tidak cukup jelas dengan lisensinya. Misalnya dengan cara bertanya seperti ini:

Saya ingin menggunakan foto hasil karya Anda pada halaman ini (merujuk ke sebuah URL atau tempat yang terkait dengan hasil karya yang dimaksud). Jika boleh, Saya akan mancantumkan nama dan alamat web Anda pada halaman kredit web Saya. Jika itu belum cukup, apa saja yang harus Saya lakukan agar Saya diperbolehkan untuk menggunakan hasil karya Anda?

Walau bagaimanapun juga, sebagai seorang pengguna/pemakai Anda harus siap sejak awal untuk memenuhi apa yang diinginkan oleh si pembuat hasil karya jika hendak menggunakan hasil karya tersebut. Bagaimanapun, itu semua bukan barang-barang kepunyaan Anda, jadi Anda harus meminta izin terlebih dahulu untuk memperoleh kesepakatan.

Lisensi untuk Kalangan Amatir

Jika Anda merupakan pihak pencipta, dan Anda ingin melindungi hasil karya Anda yang terbilang lemah di mata hukum karena Anda merupakan seorang amatir yang membuat sesuatu hanya untuk memenuhi hobi/kepuasan diri sendiri, dan tidak melakukannya secara profesional untuk mendapatkan penghasilan, lisensi CC BY-NC-SA sangat cocok dalam kasus ini. Lisensi ini mencakup:

  • Atribusi: Artinya pengguna wajib meninggalkan atribusi dari kreator asli tersebut pada karya yang sedang mereka gunakan.
  • Nonkomersial: Artinya pengguna tidak boleh menjual hasil karya Anda/tidak boleh menggunakan hasil karya Anda untuk hal-hal yang komersial.
  • Berbagi Serupa: Artinya pengguna boleh menyebarluaskan hasil karya Anda, namun dengan syarat bahwa lisensi baru yang diterapkan harus mengikuti lisensi asli dari karya sebelumnya. Biasanya ini terkait pada masalah modifikasi hasil karya.

Memodifikasi hasil-hasil karya yang berada di bawah lisensi ini diperbolehkan, karena tidak terdapat kode ND yang berarti No Derivative Works, atau tidak diperbolehkan untuk menciptakan karya turunan dari karya Anda, atau tidak boleh dimodifikasi. Untuk kalangan amatir, kode SA sangat penting diterapkan pada hasil karya mereka agar mereka bisa memastikan apakah karya-karya yang telah dimodifikasi akan para modifikator publikasikan di bawah lisensi yang sama atau tidak. Karena Saya yakin, Anda tidak akan merasa senang jika suatu saat Anda mendapati barang-barang hasil karya orang lain dijual secara bebas, yang ternyata barang tersebut merupakan hasil karya turunan dari karya Anda. Anda akan rugi karena itu.

Labels:

Wednesday, July 10, 2013

JavaScript/jQuery · Cek Jika Latar Gambar Telah Termuat

Lakukan sesuatu jika latar gambar pada elemen #test-bg telah termuat.

Tidak ada fungsi bawaan khusus yang bisa digunakan untuk mengecek bahwa sebuah latar gambar telah termuat. Tetapi Anda bisa melakukan itu dengan cara mengambil URL latar gambar pada elemen yang Anda inginkan untuk Anda sisipkan ke dalam atribut src gambar palsu yang Anda buat melalui JavaScript. Mengapa gambar? Karena kita bisa mendeteksi event onload pada gambar:

JavaScript Mentah

function getBgUrl(el) {
    var bg = "";
    if (el.currentStyle) { // IE
        bg = el.currentStyle.backgroundImage;
    } else if (document.defaultView && document.defaultView.getComputedStyle) { // Firefox
        bg = document.defaultView.getComputedStyle(el, "").backgroundImage;
    } else { // try and get inline style
        bg = el.style.backgroundImage;
    }
    return bg.replace(/url\(['"]?(.*?)['"]?\)/i, "$1");
}

var image = document.createElement('img');
image.src = getBgUrl(document.getElementById('test-bg'));
image.onload = function() {
    alert('Loaded!'); // Test!
};

jQuery

var bg = $('#test-bg').css('background-image').replace(/url\(['"]?(.*?)['"]?\)/i, "$1");
$('<img />').attr('src', bg).on("load", function() {
    alert('Loaded!'); // Test!
});

Lihat Demo


Referensi: SO - How Can I Check if a Background Image is Loaded?

Labels: , , ,

Saturday, July 6, 2013

Widget Artikel Terkait Blogger · 6 dalam 1

Contoh tampilan widget artikel terkait Blogger yang paling populer
Contoh-contoh tampilan widget. Klik untuk memperbesar gambar.

Saat ini terdiri dari 6 jenis tampilan yang bisa Anda sesuaikan sendiri. Widget ini merupakan pengembangan dari konsep random post ringan yang pernah Saya tuliskan di sini. Hanya saja, karena pemanggilan feed posting difilter melalui label posting yang spesifik, maka widget random post ini sekarang bisa dijadikan sebagai widget artikel terkait (random post dengan sortir label otomatis berdasarkan posting).

Widget-widget artikel terkait yang lama kurang bersahabat menurut Saya, sehingga Saya membuatnya lagi secara pribadi. Dan untuk menyingkat jumlah posting, maka model-model widget artikel terkait yang sudah populer kini telah Saya gabungkan menjadi satu kesatuan. Tujuan utamanya tetap. Mencoba untuk menampilkan posting-posting lama dengan jarak waktu penerbitan yang tidak terbatas namun dengan tenaga sesedikit mungkin:

Buka Generator Widget Kode Sumber

Klik tombol Preview & Get Code! Di situ nanti Anda akan mendapatkan kode CSS dan XML template. Masuk ke halaman editor HTML template kemudian letakkan kode CSS yang dihasilkan di atas kode ]]></b:skin>. Kode XML bisa Anda letakkan di mana saja di dalam elemen <b:includable id='post' var='post'/>, tapi Saya sarankan untuk meletakkan kode tersebut di atas kode ini karena posisinya yang mudah ditemukan dan lebih minim resiko:

<div class='post-footer'>

Tabel Pengaturan

Pengaturannya tidak banyak, dan karena Saya sudah membuat generatornya, jadi Anda sebenarnya tidak perlu lagi menyentuh variabel-variabel di dalam widget ini secara langsung. Tabel ini Saya buat untuk kepentingan dokumentasi saja:

Opsi Keterangan
widgetStyle Kode model widget artikel terkait berupa angka. Mengubah nilai variabel ini akan mengubah markup HTML widget, sehingga kode CSS harus disesuaikan ulang. Lebih baik gunakan generator.
homePage Digunakan untuk menentukan URL blog Anda. Nilai sudah diotomatisasikan melalui elemen <data:blog.homepageUrl/>
widgetTitle Markup HTML untuk judul/kepala widget. Bisa digunakan untuk menyisipkan kode HTML lain juga jika mau. Kode tersebut nantinya akan tampil di atas daftar item posting di dalam widget.
numPosts Digunakan untuk menentukan jumlah posting yang ingin ditampilkan.
summaryLength Digunakan untuk menentukan panjang karakter ringkasan posting.
titleLength Digunakan untuk memotong jumlah karakter judul posting sesuai dengan besar angka yang dituliskan. Ubah menjadi "auto" untuk menonaktifkan pemotongan karakter pada judul posting.
thumbnailSize Digunakan untuk menentukan lebar/tinggi thumbnail posting yang berbentuk kotak.
noImage Isi dengan URL gambar cadangan untuk posting yang tidak memiliki gambar.
containerId ID elemen HTML untuk menampung daftar posting yang berhasil terpanggil.
newTabLink Ubah nilainya menjadi true untuk membuat tautan-tautan di dalam widget ini membuka di tab/jendela baru secara otomatis ketika diklik.
moreText Teks “Baca Selengkapnya”.
callBack Fungsi tambahan yang akan bekerja setelah daftar posting termuat ke dalam kontainer widget. Lihat penjelasannya di bawah.

Menerapkan Fungsi callBack Widget

Opsi ini berfungsi untuk menciptakan perilaku tambahan pada widget. Fungsi ini akan bekerja setelah widget berhasil dimuat. Cocok digunakan untuk menambahkan efek-efek khusus. Dasar penerapannya adalah seperti ini. Kode di bawah ini akan menampilkan pesan peringatan bahwa widget telah berhasil termuat jika widget berhasil termuat:

var relatedPostConfig = {
    callBack: function() {
        alert('Widget successfully loaded.');
    }
};

Contoh 1: Membuat Efek Transisi Hover pada Tooltip

Set tampilan widget menjadi artikel terkait dengan tooltip, kemudian buat fungsi jQuery seperti ini:

var relatedPostConfig = {
    ...
    widgetStyle: 4,
    containerId: "random-post",
    callBack: function() {
        $('#' + this.containerId + ' li').hover(function() {
            $('.related-post-item-tooltip', this).filter(':not(:animated)').animate({
                marginBottom: -5,
                opacity: "show"
            }, 400);
        }, function() {
            $('.related-post-item-tooltip', this).animate({
                marginBottom: 10,
                opacity: "hide"
            }, 200);
        }).find('.related-post-item-tooltip').css('margin-bottom', 10);
    }
};

Hapus efek :focus dan :hover pada CSS:

.related-post-style-4 .related-post-item:focus .related-post-item-tooltip,
.related-post-style-4 .related-post-item:hover .related-post-item-tooltip {display:block}

Lihat Demo

Contoh 2: Membuat Efek Sliding pada Tabir Judul

Set tampilan widget menjadi artikel terkait dengan tabir tooltip:

var relatedPostConfig = {
    ...
    widgetStyle: 5,
    titleLength: 50,
    thumbnailSize: 130,
    containerId: "random-post",
    callBack: function() {
        $('#' + this.containerId + ' li').hover(function() {
            $('.related-post-item-tooltip', this).filter(':not(:animated)').animate({
                marginTop: "50%"
            }, 400);
        }, function() {
            $('.related-post-item-tooltip', this).animate({
                marginTop: "100%"
            }, 200);
        }).find('.related-post-item-tooltip').css('margin-top', '100%');
    }
};

Hapus deklarasi display:none pada selektor tooltip widget, hapus juga efek :focus dan :hover pada CSS:

.related-post-style-5 .related-post-item-tooltip {
  display:block;
  background-color:black;
  background-color:rgba(0,0,0,.9);
  position:absolute;
  top:0;
  right:0;
  bottom:0;
  left:0;
  padding:10px;
  line-height:normal;
  font-style:italic;
  color:white;
  overflow:hidden;display:none;}
.related-post-style-5 .related-post-item:focus .related-post-item-tooltip,
.related-post-style-5 .related-post-item:hover .related-post-item-tooltip {display:block}

Lihat Demo

Contoh 3: Membuat Efek News Ticker

Set tampilan widget menjadi artikel terkait tipe thumbnail dan summary:

var relatedPostConfig = {
    ...
    numPosts: 10,
    widgetStyle: 2,
    containerId: "random-post",
    callBack: function() {
        var $container = $('#' + this.containerId + ' > ul'),
            $list = $container.find('li'),
            innerHeight = $list.first().height(),
            outerHeight = $list.first().outerHeight(true);
        // Container & list height setup
        $container.css({
            "height": outerHeight * $list.length / 2,
            "overflow": "hidden"
        });
        $list.css({
            "height": innerHeight,
            "overflow": "hidden"
        });
        // Animation
        function newsTicker() {
            window.setTimeout(function() {
                $container.find('li:last').stop().animate({
                    opacity: 0
                }, 1000, function() {
                    $(this).hide().prependTo($container).slideDown(1000, function() {
                        $(this).stop().animate({
                            opacity: 1
                        }, 1000, newsTicker);
                    });
                });
            }, 3000);
        } newsTicker();
    }
};

Lihat Demo

Dan seterusnya. Buat efek-efek baru yang lain sesuka hati melalui opsi callBack.

Catatan: Saat menerapkan beberapa fungsi di atas, mungkin templat Anda nanti menjadi tidak bisa disimpan. Cobalah untuk mengelilingi fungsi callBack dengan komentar CDATA seperti ini:

var relatedPostConfig = {
    callBack: function() {
        //<![CDATA[

        Tuliskan fungsi di sini...

        //]]>
    }
};

Atau baca posting ini sebagai referensi tambahan.

Labels: , ,