Tampilkan postingan dengan label Code Snippet. Tampilkan semua postingan
Tampilkan postingan dengan label Code Snippet. Tampilkan semua postingan

Minggu, 12 Juli 2015

AJAX dengan JavaScript Mentah

Mendapatkan konten dari dokumen HTML yang lain pada domain yang sama tanpa menggunakan JQuery.

/**
* Get data from a URL
* @param {String} url The URL to get
* @param {Function} success Callback to run on success
* @param {Function} error Callback to run on error
*/

var getURL = function(url, success, error) {
// Feature detection
if (!window.XMLHttpRequest) return;
// Create new request
var request = new XMLHttpRequest();
// Setup callbacks
request.onreadystatechange = function() {
// If the request is complete
if (request.readyState === 4) {
// If the request failed
if (request.status !== 200) {
if (error && typeof error === "function") {
error(request.responseText, request);
}
return;
}
// If the request succeeded
if (success && typeof success === "function") {
success(request.responseText, request);
}
}
};
// Get the HTML
request.open('GET', url);
request.send();
};

Penggunaan

Dasar:

getURL(
'/about',
function(data) {
// On success…
},
function(data) {
// On failure…
}
);

Cari elemen spesifik pada halaman yang dipanggil dan masukkan kontennya ke dalam elemen tertentu pada halaman saat ini:

getURL(
'/about',
function(data) {
// Create a `<div>` and inject the HTML into it
var div = document.createElement(div);
div.innerHTML = data;
// Find the element you’re looking for in the `<div>`
var from = div.querySelector('#some-element');
var to = document.querySelector('#another-element');
// Quit if the element or the place where you want to inject it doesn’t exist
if (!from || !to) return;
// Inject the element into the DOM
to.innerHTML = from.innerHTML;
}
);

Referensi: Making AJAX Requests with Native JavaScript

Minggu, 26 April 2015

Password Overlay

Di sini, JavaScript btoa digunakan untuk menyembunyikan teks, sedangkan atob digunakan untuk mengembalikan teks yang tersembunyi tersebut:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Password Overlay Test</title>

<style>
.body {
padding:10% 0;
text-align:center;
}
.overlay {
position:fixed;
top:0;
right:0;
bottom:0;
left:0;
z-index:9999;
background-color:black;
color:white;
padding:10% 0;
text-align:center;
}
</style>

</head>
<body>

<div id="protect-body" class="body">Content goes here…</div>
<div id="protect-overlay" class="overlay">
<form action="#">
<input name="answer" type="password" placeholder="Password?"/> <button type="submit">Open</button>
</form>
</div>

<script>
// https://developer.mozilla.org/En/DOM/Window.btoa
// https://developer.mozilla.org/en/DOM/window.atob
// to get the obfuscated text, use `console.log(btoa('your text goes here'))`
// `aSBsb3ZlIHlvdQ==` => `i love you`
(function() {
var o = document.getElementById('protect-overlay');
o.getElementsByTagName('form')[0].onsubmit = function() {
if (this.answer.value === atob('aSBsb3ZlIHlvdQ==')) {
o.style.display = "none"; // passed!
} else {
alert('Wrong password!');
}
return false;
};
})();
</script>

</body>
</html>

Demo

Kata kunci: i love you

Jumat, 02 Januari 2015

Minggu, 31 Agustus 2014

Tag Facebook Open Graph untuk Blogspot

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

Optional. Read more → Insights for your Facebook App, Domain or Page

<meta property='fb:admins' content='{{FB ADMINS}}'/>
<meta property='fb:app_id' content='{{APP ID}}'/>

-->

Lainnya

Kamis, 28 Agustus 2014

Mendapatkan Ukuran Folder/Direktori

Fungsi ini akan menunjukkan ukuran sebuah folder/direktori dengan cara menghitung jumlah total ukuran semua berkas yang ada di dalamnya.

// http://stackoverflow.com/a/21409562/1163000
function get_directory_size($path) {
$size = 0;
$path = realpath($path);
if($path !== false) {
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object) {
$size += $object->getSize();
}
}
return $size; // in bytes
}

Penggunaan

echo (get_directory_size('path/to/folder') / 1024) . ' KB';

Rabu, 20 Agustus 2014

Lettering PHP

Versi PHP untuk lettering.js

function lettering_PHP($text) {
$results = '<span class="word-1 char-group">';
$skip = false;
$entity_open = false;
$entity_close = false;
$index_word = 2;
$index_letter = 1;
$letters = preg_split('#(?<!^)(?!$)#u', $text);
foreach($letters as $letter) {
$entity_open = $letter == '&';
$entity_close = $letter == ';';
if($letter == '<' || $entity_open) $skip = true;
if($letter == '>' || $entity_close) $skip = false;
if( ! $skip && $letter == ' ') {
$results .= '</span> <span class="word-' . $index_word . ' char-group">';
$index_word++;
} else {
if( ! $skip && $letter != '<' && $letter != '>' && $letter != '&' && $letter != ';' && $letter != ' ') {
$results .= '<span class="char-' . $index_letter . '">' . $letter . '</span>';
$index_letter++;
} else {
if($entity_open) {
$results .= '<span class="char-' . $index_letter . '">';
}
$results .= $letter;
if($entity_close) {
$results .= '</span>';
$index_letter++;
}
}
}
}
return '<span aria-label="' . str_replace(array('"', '\''), array('&quot;', '&#039;'), strip_tags($text)) . '"><span aria-hidden="true" class="word-group">' . $results . '</span></span></span>';
}

Penggunaan

<h2><?php echo lettering_PHP('Lorem Ipsum Dolor Sit Amet'); ?></h2>

Sebelum

<h2>Lorem Ipsum Dolor Sit Amet</h2>

Sesudah

<h2>
<span aria-label="Lorem Ipsum Dolor Sit Amet">
<span aria-hidden="true" class="word-group">
<span class="word-1 char-group">
<span class="char-1">L</span>
<span class="char-2">o</span>
<span class="char-3">r</span>
<span class="char-4">e</span>
<span class="char-5">m</span>
</span>
<span class="word-2 char-group">
<span class="char-6">I</span>
<span class="char-7">p</span>
<span class="char-8">s</span>
<span class="char-9">u</span>
<span class="char-10">m</span>
</span>
<span class="word-3 char-group">
<span class="char-11">D</span>
<span class="char-12">o</span>
<span class="char-13">l</span>
<span class="char-14">o</span>
<span class="char-15">r</span>
</span>
<span class="word-4 char-group">
<span class="char-16">S</span>
<span class="char-17">i</span>
<span class="char-18">t</span>
</span>
<span class="word-5 char-group">
<span class="char-19">A</span>
<span class="char-20">m</span>
<span class="char-21">e</span>
<span class="char-22">t</span>
</span>
</span>
</span>
</h2>

Minggu, 06 Juli 2014

Fake Link

HTML

<form class="fake-link" action="http://example.org" method="get" target="_blank">
<input name="aff" type="hidden" value="1234567">
<button type="submit">affiliate link</button>
</form>

CSS

.fake-link,
.fake-link button {
margin:0;
padding:0;
width:auto;
height:auto;
background:none;
border:none;
font:inherit;
text-transform:none;
display:inline;
}
.fake-link button {
color:blue;
cursor:pointer;
}
.fake-link button::-moz-focus-inner {
margin:0;
padding:0;
border:none;
outline:none;
}
.fake-link button:focus,
.fake-link button:hover {text-decoration:underline}
.fake-link button:active {color:red}

Demo

Senin, 21 April 2014

JavaScript Brightness

/**
* http://www.sitepoint.com/javascript-generate-lighter-darker-color/
*/

function colorLuminance(hex, lum) {
// Validate hex string
hex = String(hex).replace(/[^0-9a-f]/gi, "");
if (hex.length < 6) {
hex = hex.replace(/(.)/g, '$1$1');
}
lum = lum || 0;
// Convert to decimal and change luminosity
var rgb = '#', c;
for (var i = 0; i < 3; ++i) {
c = parseInt(hex.substr(i * 2, 2), 16);
c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
rgb += ('00' + c).substr(c.length);
}
return rgb;
}

Penggunaan

colorLuminance('#aabbaa', 0.5); // lighter
colorLuminance('#aabbaa', -0.5); // darker

Kamis, 03 April 2014

PHP Konversi Array Menjadi Objek/Objek Menjadi Array

1. Array ke Objek

Fungsi

function array_to_object($array) {
if(is_array($array)) {
return (object) array_map(__FUNCTION__, $array);
} else {
return $array;
}
}

Contoh Kasus

Sebelum dikonversi…

$test = array(
'A' => 'Test A',
'B' => 'Test B',
'C' => array(
'CA' => 'Test CA',
'CB' => array(
'CBA' => 'Test CBA'
)
),
'D' => 'Test D'
);

// Pemanggilan...
echo $test['A']; // Hasil => `Test A`
echo $test['C']['CB']; // Hasil => `Test CB`
echo $test['C']['CB']['CBA']; // Hasil => `Test CBA`

Sesudah dikonversi…

...

$object_test = array_to_object($test);

// Pemanggilan...
echo $object_test->A; // Hasil => `Test A`
echo $object_test->C->CB; // Hasil => `Test CB`
echo $object_test->C->CB->CBA; // Hasil => `Test CBA`

2. Objek ke Array

Fungsi

function object_to_array($object) {
if(is_object($object)) {
$object = get_object_vars($object);
}
if(is_array($object)) {
return array_map(__FUNCTION__, $object);
} else {
return $object;
}
}

Contoh Kasus

Sebelum dikonversi…

$test = new stdClass;
$test->A = 'Test A';
$test->B = 'Test B';
$test->C = new stdClass;
$test->C->CA = 'Test CA';
$test->C->CB = new stdClass;
$test->C->CB->CBA = 'Test CBA';
$test->D = 'Test D';

// Pemanggilan
echo $test->A; // Hasil => `Test A`

Sesudah dikonversi…

...

$array_test = object_to_array($test);

// Pemanggilan
echo $array_test['A']; // Hasil => `Test A`

PHP Konversi Array Menjadi HTML List

PHP

function array_to_list($array, $list_type = 'ul') {
$output = '<' . $list_type . '>';
foreach($array as $key => $values) {
if(is_array($values)) {
$output .= '<li><a href="#">' . $key . '</a>' . array_to_list($values, $list_type) . '</li>';
} else {
$output .= '<li><a href="#' . $values . '">' . $key . '</a></li>';
}
}
return $output . '</' . $list_type . '>';
}

Penggunaan

Ubah array $test menjadi elemen HTML daftar:

// Testing...
$test = array(
'A' => 'list-A',
'B' => 'list-B',
'C' => 'list-C',
'D' => array(
'AA' => 'list-AA',
'AB' => 'list-AB',
'AC' => 'list-AC',
'AD' => array(
'ADA' => 'list-ADA',
'ADB' => 'list-ADB',
'ADC' => 'list-ADC'
),
'AE' => 'list-AE'
),
'E' => 'list-E'
);

echo array_to_list($test, 'ol');

Akan menghasilkan ini:

Minggu, 23 Maret 2014

JavaScript “Extend”

Fungsi ini setara dengan JQuery.extend() yang memungkinkan kita untuk menciptakan variabel opsional, dimana variabel tersebut bisa dinyatakan ataupun ditiadakan. Jika tidak dinyatakan, maka nilai variabel yang tidak hadir tersebut akan jatuh pada nilai default yang telah ditentukan di dalam fungsi:

// http://stackoverflow.com/a/12317051/1163000
function extend(target, source) {
target = target || {};
for (var prop in source) {
if (typeof source[prop] === "object") {
target[prop] = extend(target[prop], source[prop]);
} else {
target[prop] = source[prop];
}
}
return target;
}

Contoh Penggunaan

function myFunction(config) {

var defaults = {
firstName: 'Taufik',
lastName: 'Nurrohman',
age: 22
};

// Extend...
config = extend(defaults, config);

return config;

}

Ketika Anda mengubah beberapa nilai variabel konfigurasi, maka variabel-variabel konfigurasi default yang lain yang tidak diubah akan menyesuaikan:

myFunction({
firstName: 'Foo'
});

Hasil

JavaScript Extend Test via Window Console
Taufik telah berubah menjadi Foo.

Sebenarnya dulu Saya sudah pernah menulis posting yang sejenis dengan ini. Tapi metode yang Saya tuliskan dalam posting tersebut tidak mampu untuk menangani objek multi-dimensi seperti ini:

var defaults = {
option_1: value_1,
option_2: value_2,
option_3: {
option_3_1: {
option_3_1_1: value_3_1_1,
option_3_1_2: value_3_1_2
},
option_3_2: value_3_2,
option_3_3: value_3_3
},
option_4: value_4
};

Minggu, 09 Maret 2014

Sortir Array Berdasarkan Nilai dari Key

// http://stackoverflow.com/a/2699110/1163000
function sort_array_by_value($key, &$array) {

$sorter = array();
$ret = array();

reset($array);

foreach($array as $ii => $value) {
$sorter[$ii] = $value[$key];
}

asort($sorter);

foreach($sorter as $ii => $value) {
$ret[$ii] = $array[$ii];
}

$array = $ret;

}

Contoh Kasus

Sampel array:

$my_array = array(
array(
'id' => 1,
'title' => 'Orange',
'time' => '2014-03-05 03:00:42'
),
array(
'id' => 2,
'title' => 'Banana',
'time' => '2013-01-06 13:05:15'
),
array(
'id' => 3,
'title' => 'Grape',
'time' => '2011-05-15 01:30:45'
)
);

Menyortir data berdasarkan nilai dari title

sort_array_by_value('title', $my_array);

print_r($my_array);

Akan menghasilkan urutan seperti ini:

Array
(
[1] => Array
(
[id] => 2
[title] => Banana
[time] => 2013-01-06 13:05:15
)

[2] => Array
(
[id] => 3
[title] => Grape
[time] => 2011-05-15 01:30:45
)

[0] => Array
(
[id] => 1
[title] => Orange
[time] => 2014-03-05 03:00:42
)

)

Minggu, 02 Maret 2014

Syntax Highlighter Generik dengan PHP

PHP

<?php

/**
* Original => http://phoboslab.org/log/2007/08/generic-syntax-highlighting-with-regular-expressions
* Usage => `echo SyntaxHighlight::process('source code here');`
*/

class SyntaxHighlight {
public static function process($s) {
$s = htmlspecialchars($s);

// Workaround for escaped backslashes
$s = str_replace('\\\\','\\\\<e>', $s);

$regexp = array(

// Comments/Strings
'/(
\/\*.*?\*\/|
\/\/.*?\n|
\#.[^a-fA-F0-9]+?\n|
\&lt;\!\-\-[\s\S]+\-\-\&gt;|
(?<!\\\)&quot;.*?(?<!\\\)&quot;|
(?<!\\\)\'(.*?)(?<!\\\)\'
)/isex'
=> 'self::replaceId($tokens,\'$1\')',

// Punctuations
'/([\-\!\%\^\*\(\)\+\|\~\=\`\{\}\[\]\:\"\'<>\?\,\.\/]+)/'
=> '<span class="P">$1</span>',

// Numbers (also look for Hex)
'/(?<!\w)(
(0x|\#)[\da-f]+|
\d+|
\d+(px|em|cm|mm|rem|s|\%)
)(?!\w)/ix'
=> '<span class="N">$1</span>',

// Make the bold assumption that an
// all uppercase word has a special meaning
'/(?<!\w|>|\#)(
[A-Z_0-9]{2,}
)(?!\w)/x'
=> '<span class="D">$1</span>',

// Keywords
'/(?<!\w|\$|\%|\@|>)(
and|or|xor|for|do|while|foreach|as|return|die|exit|if|then|else|
elseif|new|delete|try|throw|catch|finally|class|function|string|
array|object|resource|var|bool|boolean|int|integer|float|double|
real|string|array|global|const|static|public|private|protected|
published|extends|switch|true|false|null|void|this|self|struct|
char|signed|unsigned|short|long
)(?!\w|=")/ix'
=> '<span class="K">$1</span>',

// PHP/Perl-Style Vars: $var, %var, @var
'/(?<!\w)(
(\$|\%|\@)(\-&gt;|\w)+
)(?!\w)/ix'
=> '<span class="V">$1</span>'

);

$tokens = array(); // This array will be filled from the regexp-callback

$s = preg_replace(array_keys($regexp), array_values($regexp), $s);

// Paste the comments and strings back in again
$s = str_replace(array_keys($tokens), array_values($tokens), $s);

// Delete the "Escaped Backslash Workaround Token" (TM)
// and replace tabs with four spaces.
$s = str_replace(array('<e>', "\t"), array('', ' '), $s);

return '<pre><code>' . $s . '</code></pre>';
}

// Regexp-Callback to replace every comment or string with a uniqid and save
// the matched text in an array
// This way, strings and comments will be stripped out and wont be processed
// by the other expressions searching for keywords etc.
private static function replaceId(&$a, $match) {
$id = "##r" . uniqid() . "##";

// String or Comment?
if(substr($match, 0, 2) == '//' || substr($match, 0, 2) == '/*' || substr($match, 0, 2) == '##' || substr($match, 0, 7) == '&lt;!--') {
$a[$id] = '<span class="C">' . $match . '</span>';
} else {
$a[$id] = '<span class="S">' . $match . '</span>';
}
return $id;
}
}

?>

CSS

pre {
display:block;
background-color:#3F3F3F;
margin:1em 0;
padding:1em;
font:normal normal 13px/1.4 Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,Monospace;
color:#E3CEAB;
overflow:auto;
white-space:pre;
word-wrap:normal;
}
pre code {
font:inherit;
color:inherit;
}
pre span.N {color:#8CD0D3} /* Numbers */
pre span.S {color:#CC9385} /* Strings */
pre span.C {color:#7F9F7F} /* Comments */
pre span.K {color:#DFC47D} /* Keywords */
pre span.V {color:#CEDF99} /* Vars */
pre span.D {color:#FFFFFF} /* Defines */
pre span.P {color:#9F9D65} /* Punctuations */

Jumat, 28 Februari 2014

Mengambil URL Gambar Pertama dari Posting

Versi PHP

function get_first_image_url($data, $default_url = null) {

/**
* Matched with ...
* ----------------
*
* [1]. `![alt text](IMAGE URL)`
* [2]. `![alt text](IMAGE URL "optional title")`
*
* ... and the single-quoted version of them
*
*/
if(preg_match_all('#\!\[.*?\]\(([^\s]+?)( +([\'"]).*?\3)?\)#', $data, $matches)) {
return $matches[1][0];
}

/**
* Matched with ...
* ----------------
*
* [1]. `<img src="IMAGE URL">`
* [2]. `<img foo="bar" src="IMAGE URL">`
* [3]. `<img src="IMAGE URL" foo="bar">`
* [4]. `<img src="IMAGE URL"/>`
* [5]. `<img foo="bar" src="IMAGE URL"/>`
* [6]. `<img src="IMAGE URL" foo="bar"/>`
* [7]. `<img src="IMAGE URL" />`
* [8]. `<img foo="bar" src="IMAGE URL" />`
* [9]. `<img src="IMAGE URL" foo="bar" />`
*
* ... and the uppercased version of them, and the single-quoted version of them
*
*/
if(preg_match_all('#<img .*?src=([\'"])([^\'"]+?)\1.*? *\/?>#i', $data, $matches)) {
return $matches[2][0];
}

return $default_url; // Default image URL if nothing matched
}

Penggunaan

<img src="<?php echo get_first_image_url($page['content'], 'img/no-image.png'); ?>">

$page['content'] cuma contoh. Anda harus mengambilnya dari konten posting Anda sesuai dengan API pada CMS yang Anda pakai.

Versi JavaScript

function getFirstImageURL(data, noImage) {

/**
* Matched with ...
* ----------------
*
* [1]. `![alt text](IMAGE URL)`
* [2]. `![alt text](IMAGE URL "optional title")`
*
* ... and the single-quoted version of them
*
*/
var matches = /\!\[.*?\]\(([^\s]+?)( +[\'"].*?[\'"])?\)/.exec(data);
return matches ? matches[1] : noImage;

/**
* Matched with ...
* ----------------
*
* [1]. `<img src="IMAGE URL">`
* [2]. `<img foo="bar" src="IMAGE URL">`
* [3]. `<img src="IMAGE URL" foo="bar">`
* [4]. `<img src="IMAGE URL"/>`
* [5]. `<img foo="bar" src="IMAGE URL"/>`
* [6]. `<img src="IMAGE URL" foo="bar"/>`
* [7]. `<img src="IMAGE URL" />`
* [8]. `<img foo="bar" src="IMAGE URL" />`
* [9]. `<img src="IMAGE URL" foo="bar" />`
*
* ... and the uppercased version of them, and the single-quoted version of them
*
*/
matches = /<img .*?src=[\'"]([^\'"]+?)[\'"].*? *\/?>/i.exec(data);
return matches ? matches[1] : noImage;

}

Penggunaan

var img = '<img src="' + getFirstImageURL(sourceText, 'img/no-image.png') + '">';
document.write(img);

sourceText cuma contoh. Anda harus mengambilnya dari konten posting Anda, misalnya dengan cara ini:

var sourceText = document.querySelector('.post-body').innerHTML;

Kamis, 13 Februari 2014

Regex untuk Validasi Tag HTML

<("[^"]*"|'[^']*'|[^'">])*>

Cocok untuk pola ini:

  1. <input value='>'>
  2. <input value='<'>
  3. <a href="http://www.nama_web.com">
  4. <br>, <br/>
  5. <input value="'" id="test">, <input value='"' id='test'>

Rabu, 05 Februari 2014

Tab & Untab

Fungsi ini memungkinkan Anda untuk melakukan perintah indentasi atau outdentasi pada lebih dari satu baris teks sekaligus di dalam elemen <textarea>:

(function() {

var tabCharacter = ' '; // Use `\t` or multiple space character

var select = function(start, end, target) {
target.focus();
target.setSelectionRange(start, end);
};

window._tab = function(target) {

var start = target.selectionStart,
end = target.selectionEnd,
value = target.value,
selections = value.substring(start, end).split('\n');

for (var i = 0, len = selections.length; i < len; ++i) {
selections[i] = tabCharacter + selections[i];
}

target.value = value.substring(0, start) + selections.join('\n') + value.substring(end);

// re-select text after tabbing
var selectEnd = (end + (tabCharacter.length * selections.length));
if (start == end) {
select(selectEnd, selectEnd, target);
} else {
select(start, selectEnd, target);
}

};

window._untab = function(target) {

var start = target.selectionStart,
end = target.selectionEnd,
value = target.value,
pattern = new RegExp("^" + tabCharacter),
edits = 0;

if (start == end) { // single line

while (start > 0) {
if(value.charAt(start) == '\n') {
start++;
break;
}
start--;
}

var portion = value.substring(start, end),
matches = portion.match(pattern);

if (matches) {
target.value = value.substring(0, start) + portion.replace(pattern, "") + value.substring(end);
end--;
}

// set caret position after tabbing
var selectEnd = end <= start ? end : end - tabCharacter.length + 1;
select(selectEnd, selectEnd, target);

} else { // multiline

var selections = value.substring(start, end).split('\n');

for (var i = 0, len = selections.length; i < len; ++i) {
if (selections[i].match(pattern)) {
edits++;
selections[i] = selections[i].replace(pattern, "");
}
}

target.value = value.substring(0, start) + selections.join('\n') + value.substring(end);

// re-select text after tabbing
select(start, (edits > 0 ? end - (tabCharacter.length * edits) : end), target);

}

};

})();

Penggunaan

Dengan tombol:

<button onclick="_tab(document.getElementById('ID-TEXTAREA'));">Tab</button>
<button onclick="_untab(document.getElementById('ID-TEXTAREA'));">Untab</button>

Dengan tombol Tab dan Shift + Tab pada papan kunci:

document.getElementById('ID-TEXTAREA').onkeydown = function(e) {
// Shift + Tab ditekan
if (e.shiftKey && e.keyCode == 9) {
_untab(this);
return false;
}
// Tab ditekan
if (e.keyCode == 9) {
_tab(this);
return false;
}
};

Terkait: Daftar Snippet untuk Implementasi DOM Range API

Sabtu, 05 Oktober 2013

JavaScript Table Sorter

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

JavaScript

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

CSS

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

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

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

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

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

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

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

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

HTML

<table class="table-sortable" id="table-1">
<thead>
<tr><th>Header 1</th><th>Header 2</th><th>Header 3</th></tr>
</thead>
<tbody>
<!-- Sortable rows -->
<tr><td> ... </td><td> ... </td><td> ... </td></tr>
<tr><td> ... </td><td> ... </td><td> ... </td></tr>
<tr><td> ... </td><td> ... </td><td> ... </td></tr>
...
</tbody>
</table>
<script>makeSortable(document.getElementById('table-1'));</script>

Meski masih ada sedikit kekurangan karena fungsi sortir ini hanya memakai logika berdasarkan abjad. Coba Anda klik pada header Harga. Hasilnya tidak akan sesuai dengan apa yang kita harapkan. Masih sedang mencari solusi yang paling mudah untuk menangani satuan harga pada fungsi ini…

Demo

Jumat, 27 September 2013

Data Asinkron dengan Callback

Fungsi ini bisa digunakan untuk memuat file JavaScript secara asinkron, sekaligus juga memungkinkan pengguna untuk mengeksekusi fungsi sesaat setelah data tersebut berhasil termuat:

function asyncData(url, callback) {
var script = document.createElement('script');
script.src = url;
script.onload = function() {
if (typeof callback == "function") callback();
callback = null;
};
script.onreadystatechange = function() {
if (script.readyState == 4 || script.readyState == "complete") {
if (typeof callback == "function") callback();
callback = null;
}
};
document.getElementsByTagName('head')[0].appendChild(script);
}

Penggunaan

Sebagai contoh, Anda ingin memuat skrip Syntax Highighter secara tidak langsung. Namun pada saat yang bersamaan Anda juga ingin memastikan agar eksekusi plugin terjadi hanya jika skrip tersebut telah termuat:

asyncData("../js/highlight.min.js", function() {
hljs.initHighlighting();
});

Demo

Skrip Asinkron Dasar (Tanpa Fitur Callback)

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

Sabtu, 03 Agustus 2013

JQuery Find and Highlight Text

HTML, CSS & JQuery

<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="utf-8">
<title>JQuery Find and Highlight Text</title>
<style>
body {
background-color:white;
padding:40px 10px 10px;
font:normal normal 13px/1.4 Arial,Sans-Serif;
color:black;
}
.text-finder {
position:fixed;
top:0;
right:0;
left:0;
z-index:999;
background-color:white;
border-bottom:1px solid gray;
padding:5px 6px;
box-shadow:0 1px 2px rgba(0,0,0,.4);
}
.highlight {
background-color:yellow; /* highlight color */
font-weight:bold;
}
</style>
<script src="http://code.jquery.com/jquery-2.0.2.js"></script>
<script>
/*!
highlight v4
Highlights arbitrary terms.
<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
MIT license.
Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>
*/
(function($) {
$.fn.highlight = function(pat) {
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
} else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
return this.length && pat && pat.length ? this.each(function() {
innerHighlight(this, pat.toUpperCase());
}) : this;
};
$.fn.removeHighlight = function() {
return this.find("span.highlight").each(function() {
this.parentNode.firstChild.nodeName;
with (this.parentNode) {
replaceChild(this.firstChild, this);
normalize();
}
}).end();
};
})(jQuery);

// Text finder form function
(function($) {
$(document).ready(function() {
var $finder = $('#text-finder'),
$field = $finder.children().first(),
$clear = $field.next(),
$area = $(document.body),
$viewport = $('html, body');
$field.on("keyup", function() {
$area.removeHighlight().highlight(this.value); // Highlight text inside `$area` on keyup
$viewport.scrollTop($area.find('span.highlight').first().offset().top - 50); // Jump the viewport to the first highlighted term
});
$clear.on("click", function() {
$area.removeHighlight(); // Remove all highlight inside `$area`
$field.val('').trigger("focus"); // Clear the search field
$viewport.scrollTop(0); // Jump the viewport to the top
return false;
});
});
})(jQuery);
</script>
</head>
<body>

<form id="text-finder" class="text-finder" action="javascript:;">
<input type="text" placeholder="Find...">
<input type="reset" value="&times;">
</form>

Content goes here...

</body>
</html>

Jumat, 19 Juli 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());
};

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();
}
}

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();
};

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);
};

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>

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);
};

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);
};

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">');
};

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>

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>

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";
}
};