Ahmad Masykur

Share your knowledge although one function!

About the author

Ahmad Masykur is a Software Architecture Engineer at PT. Freeport Indonesia Jakarta Indonesia.
In this blog, I share things of interest to me. Most topics are likely to be related to software development, but don't hold me to it.

Certificates



Awards


Powered by

Widget Prayer Time not found.

There is an error in XML document (4, 16278).X

Page List

Validators


Ahmad Masykur

Internet Explorer Open Modal Window

Pada Internet Explorer terdapat salah satu fitur untuk membuat pop-up window  yang bersifat modal, yaitu ketika window pop-up muncul maka window pemanggilnya tidak bisa diakses (terkunci). Fasilitas ini sangat menarik karena dalam pembuatan aplikasi web seringkali harus membuat window kecil untuk input/pemilihan data.

Kode yang digunakan untuk membuat modal window adalah window.showModalDialog, penggunaannya seperti pada baris berikut.


vReturnValue = window.showModalDialog(sURL [,vArguments] [,sFeatures])

Pada contoh kode di atas, fungsi showModalDialog memiliki tiga argument dengan dua argument optional.

  • sURL: merupakan url window yang akan ditampilkan
  • vArguments: merupakan arguments yang nilainya dapat diterima/dibaca oleh window target melalui property window.dialogArguments.
  • sFeatures: merupakan kumpulan atribut dari pop-up window, masing-masing atribut dipisahkan dengan tanda titik koma. Atribut yang bisa digunakan yaitu:
    dialogHeight: sHeight
    dialogWidth: sWidth
    dialogLeft: sXPos
    dialogTop: sYPos
    center: { yes | no | 1 | 0 | on | off } default = yes
    dialogHide: { yes | no | 1 | 0 | on | off } default = no
    edge: { sunken | raised } default = raised
    resizable: { yes | no | 1 | 0 | on | off } default = no
    scroll: { yes | no | 1 | 0 | on | off } default = yes
    status: { yes | no | 1 | 0 | on | off } default = yes
    unadorned { yes | no | 1 | 0 | on | off } default = no
  • vReturnValue: merupakan nilai kembalian dari pop-up window. Nilai kembalian ini dihasilkan dari property window.returnValue yang diset dari pop-up window.

Contoh kode:

Window induk:


function openDialog() {
    var retVal = window.showModalDialog(url,"name", "dialogWidth:255px;dialogHeight:250px");
    alert(retVal);
}

Pada window pop-up, saat menutup window untuk mendapatkan nilai kembalian property window.returnValue harus diisi.


function closeDialog() {
    window.returnValue = 'kembalian';
    window.close();
}

Masalah PostBack pada Pop-Up Modal Window

Terdapat masalah pada aplikasi ASP.NET dengan pop-up modal window. Setiap kontrol yang memerlukan postback ke server, hasil pemprosesan server tidak ditampilkan dalam pop-up window yang sama melainkan akan membuka window baru. Hal ini dapat diatasi dengan menambahkan element <base target="_self"> pada header seperti contoh berikut.


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PopUp.aspx.cs" Inherits="WebApplication1.PopUp" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server">    <title>PopUp Window</title>    <base target="_self"></head><body>    <form id="form1" runat="server">    <div>        <asp:TextBox runat="server" ID="userName"></asp:TextBox>        <asp:Button runat="server" ID="submitButton" Text="Submit" />        <input type="button" value="Close" onclick="window.returnValue = true; window.close();" />    </div>    </form></body></html>

Demikian tutorial singkat untuk membuat modal window pop-up pada Internet Explorer.

Semoga bermanfaat.


Permalink | Comments (13) | Post RSSRSS comment feed

Object Oriented JavaScript: Overloading dan Type-Checking

Pada dasarnya JavaScript merupakan dynamic language programming yang hanya tidak type-safe. Dalam JavaScript hanya mengenal lima macam tipe data string, number, boolean, function dan object. Setiap variable adalah variant yaitu dapat diisi dengan tipe data apa saja.

Contoh:


var i = 0;

Variabel i juga dapat diisi dengan nilai string.


var i = 0;
i = "nilai i";

Begitu pula dalam sebuah parameter fungsi, parameter dapat diisi dengan berbagai macam time data dan itu memang diperbolehkan dalam  javascript.


function Penambahan(x, y) {
    return x + y;
}

Pada contoh kode di atas, nilai x dan y bisa diisi dengan angka (baik bulan / integer maupun pecahan / float) dan juga bisa diisi dengan string.


function Penambahan(x, y) {
    return x + y;
}
Penambahan(1, 2); // menghasilkan nilai 3
Penambahan("1", "2"); // menghasilkan nilai string "12"

Dari contoh di atas, semua jenis data dapat masuk kedalam fungsi tanpa diperiksa tipe datanya. Bagaimana dengan overloading seperti yang umum dipake oleh bahasa pembrograman yang telah mendukung object oriented? Dalam JavaScript tidak mendukung overloading secara internal tapi dapat dilakukan sedikit trik supaya overloading dapat dilakukan pada JavaScript.

JavaScript memilika satu keyword typeof untuk mengecek tipe data apa yang terdapat dalam variable. Fungsi penambahan di sebelumnya dapat dioverload seperti kode di bawah.


function Penambahan(x, y) {
    // pengecekan apakah kedua parameter terisi atau tidak
    if ((typeof x == "undefined") || (typeof y == "undefined)) {
        alert("
Parameter x dan y harus diisi");
        return null;
    }
    // Jika x dan y adalah string
    if ((typeof x == "
string") && (typeof y == "string")) {
        return x + "
plus " + y;
    }
    // Overload x dan y adalah number
    if ((typeof x == "
number") && (typeof y == "number")) {
        return x + y;
    } else {
        return null;
    }
}
Penambahan(1, 2); // menghasilkan nilai 3
Penambahan("
1", "2"); // menghasilkan nilai string "1 plus 2"

Keyword typeof hanya dapat mengecek object, function, boolean, string, dan number. Array dan object yang terdefinisi tidak dapat dicek melalui keyword ini. Untuk mengatasi masalah ini dapat digunakan contructor dari masing-masing variabel. Fungsi penambahan di dapat diganti dengan.


function Penambahan(x, y) {
    // Jika x dan y adalah string
    if ((typeof.constructor == String) && (y.constructor == String)) {
        return x + " plus " + y;
    }
    // Overload x dan y adalah number
    if ((x.constructor == Number) && (y.constructor == Number)) {
        return x + y;
    }
    // Overload x dan y adalah array
    if (x.contructor == Array) && (y.constructor == Array) {
        var ret = [];
        var i=0;
        for (i=0; i < x.length; i++) {
            ret.push(x[i]+y[i]);
        }
        return ret;
    } else {
        return null;
    }
}
var array
Penambahan(1, 2); // menghasilkan nilai 3
Penambahan("1", "2"); // menghasilkan nilai string "1 plus 2"
Penambahan([1, 2, 3], [2, 4, 5]); // menghasilkan nilai array [3, 6, 8]

Selain type-checking, dalam fungsi JavaScript, terdapat satu array variabel yaitu arguments yang berisi semua parameter yang dimasukkan. Karena arguments berupa array, maka kita dapat memasukkan berapapun jumlah parameter tanpa batas. Sebagai contoh.


function Penambahan() {
    var ret = 0;
    var i;
    for (i=0; i arguments.length; i++) {
        if (arguments[i].constructor == Number) {
            ret += arguments[i];
        }
    }
    return ret;
}
Penambahan(1, 2); // menghasilkan nilai 3
Penambahan(1, 2, 3); // menghasilkan nilai 6
Penambahan(1, 2, 3, "4"); // menghasilkan nilai 6 karena parameter "4" bertipe string
                        // Dalam fungsi selain number tidak masuk dalam perhitungan

Dengan type-checking dan variabel arguments, kita dapat membuat overloading function sebagaimana halnya bahasa pemprograman lain.

Demikian pemaparan singkat mengenai salah satu fitur pemprograman object oriented menggunakan javascript. Semoga tulisan ini bisa bermanfaat bagi semua.


Categories: JavaScript | Tips
Permalink | Comments (0) | Post RSSRSS comment feed

JavaScript Code Compressor

JavaScript code compressor sudah banyak kita jumpai, mulai dari yang gratis sampai yang berbayar, dari yang dicompress secara online maupun software yang ditanam di komputer kita. Terdapat dua macam JavaScript code compressor yaitu: (1) bekerja dengan hanya menghilangkan komentar dan whitespace; (2) selain menghilangkan komentar dan whitespace juga menyingkat semua nama variabel dan fungsi menjadi beberapa karakter yang lebih pendak.

Dalam tulisan kali ini, saya hanya akan membahas code compressor yang pertama. Sepintas untuk menghilangkan whitespace dan komentar tampak mudah. Whitespace dapat dihilangkan dengan menghilangkan spasi di depan dan akhir kode. Komentar dapat dikenali dengan karakter pembukan dan penutup pada komentar multibaris atau pembuka komentar pada komentar baristunggal. Permasalahan timbul jika terdapat karakter pembuka komentar yang terdapat pada string, misalhnya string "http://www.masykur.web.id". String tersebut mengandung karakkter komentar, jika tidak hati hati karakter di belakang // akan ikut dihilangkan. Permasalahan tidak hanya terjadi pada string namun juga pada regular expression. Keduanya dapat berisi semua bentuk string termasuk penanda komentar.

Untuk mengatasi permasalahan ini, semua string dan regular expression harus diselamatkan dari pembersihan. Untuk itu sebelum dilakukan pembersihan, simpan dulu semua string dan regular expression ke dalam array/collection yang pada akhir pembersihan string dan regular expression tersebut dikembalikan dengan bentuk seperti semula. Pada contoh sebelumnya, string dapat diganti menjadi sebuah tanda yang unik seperti "_____STRINGREGEX_n_STRINGREGEX____", dengan n adalah nomor urut string yang ditemukan. Metode ini yang saya terapkan pada code compressor BlogEngine.NET.

Penyimpanan string dapat dilakukan dengan mencari pattern string dan regular expression menggunakan regular expression. Jika ada pattern yang cocok, hasilnya dimasukkan dalam collection. Kode dapat dilihat pada contoh berikut. (Pada contoh script disimpan dalam variable body).


// mark strings and regular expressions
Regex re = new Regex("\"(([^\"\\r\\n])|(\\\"))*\"|'[^'\\r\\n]*'|/[^/\\*](?<![/\\S]/.)([^/\\\\\\r\\n]|\\\\.)*/(?=[ig]{0,2}[^\\S])", RegexOptions.Compiled | RegexOptions.Multiline);
List<string> strs = new List<string>();
MatchCollection m = re.Matches(body);
for (int i=0; i < m.Count; i++)
{
    strs.Add(m[i].Value);
    // replace string and regular expression with marker
    StringBuilder sb = new StringBuilder();
    sb.Append("_____STRINGREGEX_");
    sb.Append(i.ToString());
    sb.Append("_STRINGREGEX_____");
    body = re.Replace(body, sb.ToString(), 1);
}

Pada contoh di atas, regular expression akan mencari semua pattern untuk string dan regular expression. String dalam JavaScript dapat berupa karakter yang berada di dalam tanda kutip tunggal maupun kutip ganda. Oleh karena itu pada regular expression harus mengecek keduanya. Setelah pattern ditemukan, hasilnya disimpan dalam collection dan ganti pattern string/regular expression dengan tanda yang unik.

Setalah kode bersih dari string dan regular expression, selanjutnya kita dengan mudah dapat membersihkan whitespace dan komentar yang ada dengan regular expression juga seperti pada kode berikut.


// remove line comments
body = Regex.Replace(body, "//.*[\r\n]", String.Empty, RegexOptions.Compiled | RegexOptions.ECMAScript);
// remove C styles comments
body = Regex.Replace(body, "/\\*.*?\\*/", String.Empty, RegexOptions.Compiled | RegexOptions.Singleline);
// trim left
body = Regex.Replace(body, "^\\s*", String.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
// trim right
body = Regex.Replace(body, "\\s*[\\r\\n]", "\r\n", RegexOptions.Compiled | RegexOptions.ECMAScript);
// remove whitespace beside of left curly braced
body = Regex.Replace(body, "\\s*{\\s*", "{", RegexOptions.Compiled | RegexOptions.ECMAScript);
// remove whitespace beside of right curly braced
body = Regex.Replace(body, "\\s*}\\s*", "}", RegexOptions.Compiled | RegexOptions.ECMAScript);
// remove whitespace beside of coma
body = Regex.Replace(body, "\\s*,\\s*", ",", RegexOptions.Compiled | RegexOptions.ECMAScript);
// remove whitespace beside of semicolon
body = Regex.Replace(body, "\\s*;\\s*", ";", RegexOptions.Compiled | RegexOptions.ECMAScript);
// remove newline after keywords
body = Regex.Replace(body, "\\r\\n(?<=\\b(abstract|boolean|break|byte|case|catch|char|class|const|continue|default|delete|do|double|else|extends|false|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|long|native|new|null|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|true|try|typeof|var|void|while|with)\\r\\n)", " ", RegexOptions.Compiled | RegexOptions.ECMAScript);
// remove all newline
body = Regex.Replace(body, "\\r\\n", "", RegexOptions.Compiled | RegexOptions.ECMAScript);

Setelah kode bersih dari whitespace dan komentar, kembalikan lagi string dan regular expression yang telah disimpan sebelumnya dengan mengganti tanda unik dengan string yang disimpan dalam collection.


// restore marked strings and regular expressions
for (int i = 0; i < strs.Count; i++)
{
    StringBuilder sb = new StringBuilder();
    sb.Append("_____STRINGREGEX_");
    sb.Append(i.ToString());
    sb.Append("_STRINGREGEX_____");
    body = Regex.Replace(body, sb.ToString(), strs[i]);
}

Dengan kompresi tersebut, kode JavaScript akan menjadi lebih kecil karena semua whitespace dan komentar telah dibersihkan. Baris kode secara lengkap dapat dilihat pada kode berikut.


/// <summary>
/// Strips the whitespace from any .js file.
/// <remarks>Modified by Ahmad Masykur - "http://www.masykur.web.id">http://www.masykur.web.id, modified date: March 03, 2008 2:50PM+7</remarks>
/// </summary>
private static string StripWhitespace(string body)
{
    // mark strings and regular expressions
    Regex re = new Regex("\"(([^\"\\r\\n])|(\\\"))*\"|'[^'\\r\\n]*'|/[^/\\*](?<![/\\S]/.)([^/\\\\\\r\\n]|\\\\.)*/(?=[ig]{0,2}[^\\S])", RegexOptions.Compiled | RegexOptions.Multiline);
    List<string> strs = new List<string>();
    MatchCollection m = re.Matches(body);
    for (int i=0; i < m.Count; i++)
    {
        strs.Add(m[i].Value);
        // replace string and regular expression with marker
        StringBuilder sb = new StringBuilder();
        sb.Append("_____STRINGREGEX_");
        sb.Append(i.ToString());
        sb.Append("_STRINGREGEX_____");
        body = re.Replace(body, sb.ToString(), 1);
    }
    // remove line comments
    body = Regex.Replace(body, "//.*[\r\n]", String.Empty, RegexOptions.Compiled | RegexOptions.ECMAScript);
    // remove C styles comments
    body = Regex.Replace(body, "/\\*.*?\\*/", String.Empty, RegexOptions.Compiled | RegexOptions.Singleline);
    // trim left
    body = Regex.Replace(body, "^\\s*", String.Empty, RegexOptions.Compiled | RegexOptions.Multiline);
    // trim right
    body = Regex.Replace(body, "\\s*[\\r\\n]", "\r\n", RegexOptions.Compiled | RegexOptions.ECMAScript);
    // remove whitespace beside of left curly braced
    body = Regex.Replace(body, "\\s*{\\s*", "{", RegexOptions.Compiled | RegexOptions.ECMAScript);
    // remove whitespace beside of right curly braced
    body = Regex.Replace(body, "\\s*}\\s*", "}", RegexOptions.Compiled | RegexOptions.ECMAScript);
    // remove whitespace beside of coma
    body = Regex.Replace(body, "\\s*,\\s*", ",", RegexOptions.Compiled | RegexOptions.ECMAScript);
    // remove whitespace beside of semicolon
    body = Regex.Replace(body, "\\s*;\\s*", ";", RegexOptions.Compiled | RegexOptions.ECMAScript);
    // remove newline after keywords
    body = Regex.Replace(body, "\\r\\n(?<=\\b(abstract|boolean|break|byte|case|catch|char|class|const|continue|default|delete|do|double|else|extends|false|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|long|native|new|null|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|true|try|typeof|var|void|while|with)\\r\\n)", " ", RegexOptions.Compiled | RegexOptions.ECMAScript);
    // remove all newline
    body = Regex.Replace(body, "\\r\\n", "", RegexOptions.Compiled | RegexOptions.ECMAScript);

    // restore marked strings and regular expressions
    for (int i = 0; i < strs.Count; i++)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("_____STRINGREGEX_");
        sb.Append(i.ToString());
        sb.Append("_STRINGREGEX_____");
        body = Regex.Replace(body, sb.ToString(), strs[i]);
    }

    return body;
}

Yang perlu diingat dari kompresi javascript ini adalah, kita harus menambahkan tanda titik koma (;) pada setiap pernyataan JavaScript. Kode berikut akan dieksekusi dengan benar oleh broser jika pada kondisi tanpa terkompress, namun akan terjadi error setelah dilakukan kompresi.


var xfnRelationships = ['friend', 'acquaintance', 'contact', 'met'
                                    , 'co-worker', 'colleague', 'co-resident'
                                    , 'neighbor', 'child', 'parent', 'sibling'
                                    , 'spouse', 'kin', 'muse', 'crush', 'date'
                                    , 'sweetheart', 'me']
// Applies the XFN tags of a link to the title tag
function HightLightXfn()
{
  var content = $('content')
  if (content == null)
    return;
  var links = document.getElementsByTagName('a')
  for (i = 0; i < links.length; i++)
  {
    var link = links[i];
    var rel = link.getAttribute('rel');
    if (rel && rel != "nofollow")
    {
      for (j = 0; j < xfnRelationships.length; j++)
      {
        if(rel.indexOf(xfnRelationships[j]) > -1)
        {
          link.title = 'XFN relationship: ' + rel;
          break;
        }
      }
    }
  }
}

Baris 5, 9, dan 12 merupakan kode yang benar dalam JavaScript tapi ketika kode tersebut dikompres, akan menimbulkan kesalahan karena akan menyatu dengan baris berikutnya, seperti terlihat pada kode berikut.


<dipotong>...,'sweetheart','me']function HightLightXfn(){var content=$('content')if(content==null)return;var links=document.getElementsByTagName('a')for(i=0;i<links.length;i++)...<dipotong>

Kode diatas sengaja dipotong karena akan terlalu panjang jika ditulis semua. Dari kode tersebut akan terjadi kesalahan karena antara array dan fungsi tidak ada pemisah, deklarasi variable content menjadi error karena nilainya kacau (pernyataan if ikut ke dalam nilai content karena tanpa pemisah). Dan kode lainnya yang tidak mengguakan akhiran titik koma menjadi error.


Categories: JavaScript | Tips
Permalink | Comments (15) | Post RSSRSS comment feed