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

Drawing using JavaScript and jQuery

Drawing functionality is not supported in most of popular browsers except Firefox and Safari with Canvas object. Using little trick we can draw line and circle using JavaScript. This is not best practice because need lot of execution time but it can be alternative way to draw simple and little objects.

Basically this trick is drawing many DIV elements with 1x1 pixel size inside the document. Basically we can't draw 1x1 pixel suze DIV element in IE. To resolve this issue, you can add IMG element inside the DIV with 1x1 pixel image. Here's the complete code to draw line and circle into HTML document.

<html> <head> <title>Drawing</title> <script type="text/javascript" src="jquery-1.3.2.min.js"></script> <script type="text/javascript"> $(document).ready(function() { line(50,30, 100, 150); circle(110,110, 100); }); function line(x1, y1, x2, y2) { c = $(document.body); var dx = Math.abs(x2-x1); var dy = Math.abs(y2-y1); var d = Math.max(dx, dy); var i=0; for(i=0; i < d; i++) { var img = $(document.createElement('img')).attr('src', 'blank.gif'); var div = $(document.createElement('div')).width(1).height(1).css({'background-color': '#f00', position: 'absolute', left: Math.min(x1,x2)+(i*dx/d), top: Math.min(y1,y2)+(i*dy/d) }); div.append(img); c.append(div); } } function circle(x, y, r) { c = $(document.body); var l = 2 * Math.PI * r; var i=0; for(i=0; i < l * (1+((10-Math.log(r+1))/10)); i++) { var x2 = r * Math.sin(360 * i/l); var y2 = r * Math.cos(360 * i/l); var img = $(document.createElement('img')).attr('src', 'blank.gif'); var div = $(document.createElement('div')).width(1).height(1).css({'background-color': '#f00', position: 'absolute', left: x+x2, top: y+y2 }); div.append(img); c.append(div); } } </script> </head> <body> </div> </body> </html>

The result of rendered document is

image

I hope this trick is useful.


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

Gunakan jQuery untuk Mendapatkan Client ID ASP.NET Server Control

jQuery merupakan salah satu library JavaScript yang sangat handal. Berdasarkan informasi dari blog ScottGu di http://weblogs.asp.net/scottgu/archive/2008/09/28/jquery-and-microsoft.aspx, menyatakan bahwa jQuery akan diintegrasikan dengan ASP.NET Ajax. Kemampuan jQuery untuk melakukan query terhadap DOM sangat membantu dalam penulisan kode JavaScript. Dengan jQuery tidak perlu lagi hawatir terhadap perbedaan penulisan pada beberapa browser, cukup dengan satu syntax akan berjalan dengan baik di beberapa browser populer.

Dalam tulisan ini saya akan menunjukkan kemampuan jQuery dalam melakukan query DOM yang di-generate oleh ASP.NET Server Control. Permasalahan utama adalah server control akan membangkitkan client ID secara dynamic jika control tersebut berada di dalam control lain.

Contoh, jika kita membuat page di dalam Master Page, kode server control dalam page berada di dalam Content place holder di berikut:

<asp:Content ID="DefaultContainer" ContentPlaceHolderID="cpMain" runat="server"> <asp:TextBox ID="TextBox1" runat="server" Text="Test"></asp:TextBox> </asp:Content>

akan terender di browser menjadi

<input name="ctl00$cpMainTextBox1" type="text" value="Test" id="ctl00_cpMain_TextBox1" />

Untuk mendapatkan DOM dari input box di atas dari JavaScript tidak dapat dilakukan dengan menyebutkan ID control secara langsung dengan code berikut.

<script type="text/javascript"> <!-- var textBox1 = document.getElementById('TextBox1'); // --> </script>

Control ID akan secara otomatis berubah menjadi unique ID seperti terlihat pada hasil render code di atas sehingga kode getElementById tidak akan pernah menemukan DOM yang dimaksud. Untuk menangani masalah ini dapat dilakukan dengan menuliskan kode JavaScript dalam satu file dengan halaman (file .aspx). Contoh:

<script type="text/javascript"> <!-- var textBox1 = document.getElementById('<%= TextBox1.ClientID %>'); // --> </script>

Dengan cara tersebut memang bisa tapi halaman jadi tampak semrawut karena campur aduk antara tag HTML dan JavaScript. Proses debugging JavaScript dengan metode tersebut juga lebih sulit karena break point tidak bisa diset sebelum halaman dijalankan. Dengan menggunakan jQuery, untuk mendapatkan client ID dari server control dapat dilakukan dengan cara:

<script type="text/javascript"> <!-- var textBox1 = $("input[name$='TextBox1']"); // --> </script>

Kode di atas artinya melakukan query terhadap semua element INPUT yang memiliki attribute name dengan akhiran "TextBox1". Apapun prefix yang dirender oleh ASP.NET, TextBox1 akan selalu terender sebagai akhiran client ID. Dengan menggunakan jQuery, tidak perlu lagi kode JavaScript menjadi satu dalam halaman HTML. Hal ini mempermudah proses debugging dan meningkatkan performance karena kode JavaScript dapat di-cache oleh browser / server.


Tags:
Categories: ASP.NET | JavaScript
Permalink | Comments (12) | Post RSSRSS comment feed

Deserialize JSON String ke Strong-Type Object.

Tulisan ini merupakan kelanjutan dari post sebelumnya tentang Json Serializer dan Deserializer. Pada tulisan sebelumnya, string JSON dideserialize ke dalam Generic Dictionary. Kekurangan dari metode tersebut adalah kita tidak bisa menggunakan strong-type object untuk deserialize JSON. Metode tersebut juga sudah dianggap usang oleh .NET Framework 3.5 karena dalam framework tersebut sudah disediakan pengganti System.Web.Script.Serialization.JavaScriptSerializer yaitu System.Runtime.Serialization.Json.DataContractJsonSerializer.

Untuk dapat menggunakan System.Runtime.Serialization.Json.DataContractJsonSerializer perlu menambahkan dua assembly reference ke dalam project yaitu: System.Runtime.Serialization (butuh .NET Framework 3.0) dan System.ServiceModel.Web (butuh .NET Framework 3.5). Setelah kedua assembly ini direferensikan, beberapa hal yang perlu disiapkan diantaranya.

1. Tambahkan kedua namespace berikut

using System.Runtime.Serialization.Json; using System.Runtime.Serialization;

2. Buat class yang digunakan untuk men-deserialize JSON string.

Dalam contoh ini dibuat class berdasarkan JSON yang sama seperti tulisan sebelumnya (Json Serializer dan Deserializer). Struktur string JSON tersebut adalah:

var dateFormat = '<%= GlobalCallCenter.Common.CallCenterConfig.Get("SHORT_DATE_FORMAT") %>'; var filter = { instance: $get('<%= instanceList.ClientID %>').value, requestNo: $get('<%= requestNoTextBox.ClientID %>').value, category: $get('<%= categoryList.ClientID %>').value, itemCategory: $get('<%= itemAffectedList.ClientID %>').value, ticketGroup: $get('<%= ticketGroupList.ClientID %>').value, status: $get('<%= statusList.ClientID %>').value, requestType: $get('<%= typeList.ClientID %>').value, startDate: Date.parseLocale($get('<%= dateFromTextBox.ClientID %>').value, dateFormat), finishDate: Date.parseLocale($get('<%= dateToTextBox.ClientID %>').value, dateFormat), requestedFor: $get('requestedForEmployeeId').value, assigneeId: ($get('<%= assigneeForEmployeeId.ClientID %>') != null) ? $get('<%= assigneeForEmployeeId.ClientID %>').value : $get('<%= assigneeForEmployeeIdLabel.ClientID %>').innerHTML };


Dari JSON tersebut di atas, dibuat class sebagai berikut:

[DataContract(Name = "Filter", Namespace = "")] protected internal class Filter { [DataMember(Name = "instance", Order = 1)] public string Instance { get; set; } [DataMember(Name = "requestNo", Order = 2)] public string RequestNo { get; set; } [DataMember(Name = "category", Order = 3)] public string Category { get; set; } [DataMember(Name = "itemCategory", Order = 4)] public string ItemCategory { get; set; } [DataMember(Name = "ticketGroup", Order = 5)] public string TicketGroup { get; set; } [DataMember(Name = "status", Order = 6)] public string Status { get; set; } [DataMember(Name = "requestType", Order = 7)] public string RequestType { get; set; } [DataMember(Name = "startDate", Order = 9)] public DateTime StartDate { get; set; } [DataMember(Name = "finishDate", Order = 10)] public DateTime FinishDate { get; set; } [DataMember(Name = "requestedFor", Order = 10)] public string RequestedFor { get; set; } [DataMember(Name = "assigneeId", Order = 10)] public string AssigneeId { get; set; } }

3. Buat implementasi deserialization.

Seperti pada tulisan sebelumnya di Json Serializer dan Deserializer, saya gunakan contoh yang sama yaitu event callback pada Janus Grid sebagai berikut.

protected void GridEX1_CustomCallBack(object sender, Janus.Web.Common.CustomCallBackEventArgs e) { var edata = System.Web.HttpUtility.UrlDecode(e.EventData.ToString()); System.IO.MemoryStream stream = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(edata.ToString())); DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Filter)); Filter filter = (Filter)serializer.ReadObject(stream); }

Dengan menggunakan strong-type kita langsung dapat mengakses property dari class tersebut, seperti terlihat pada gambar berikut.

image

Berbeda dari tulisan sebelumnya, dengan menggunakan strong-type object, semua property dapat diakses sesuai dengan tipe yang sudah didefinisikan.

Semoga bermanfaat.


Categories: ASP.NET AJAX | JavaScript | JSON
Permalink | Comments (8) | Post RSSRSS comment feed

JSON Serializer & Deserializer

Saya ingin berbagi sedikit tips mengenai JSON serializer dan deserializer yang ada di ASP.NET AJAX. Dengan menggunakan ASP.NET Ajax pertukaran data antara client (JavaScript) dengan server menjadi gampang banget. Kita tidak perlu lagi pake XMLyang rumit. Dengan JSON data mudah banget di-parse.

Contoh code di client (JS):

function getFilterData() { var dateFormat = '<%= HelpdeskSystem.DateFormat %>'; var filter = { instance: $get('<%= instanceList.ClientID %>').value, requestNo: $get('<%= requestNoTextBox.ClientID %>').value, category: $get('<%= categoryList.ClientID %>').value, itemCategory: $get('<%= itemAffectedList.ClientID %>').value, ticketGroup: $get('<%= ticketGroupList.ClientID %>').value, status: $get('<%= statusList.ClientID %>').value, requestType: $get('<%= typeList.ClientID %>').value, startDate: Date.parseLocale($get('<%= dateFromTextBox.ClientID %>').value, dateFormat), finishDate: Date.parseLocale($get('<%= dateToTextBox.ClientID %>').value, dateFormat), requestedFor: $get('requestedForEmployeeId').value, assigneeId: ($get('<%= assigneeForEmployeeId.ClientID %>') != null) ? $get('<%= assigneeForEmployeeId.ClientID %>').value : $get('<%= assigneeForEmployeeIdLabel.ClientID %>').innerHTML }; return Sys.Serialization.JavaScriptSerializer.serialize(filter); // Serialize object to JSON string }

Di server side (C#), tinggal di-deserialize. Dalam hal ini saya pake data JSON tersebut pada event CallBack Janus Grid:

protected void GridEX1_CustomCallBack(object sender, Janus.Web.Common.CustomCallBackEventArgs e) { System.Web.Script.Serialization.JavaScriptSerializer jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); var edata = System.Web.HttpUtility.UrlDecode(e.EventData.ToString()); var data = jsSerializer.DeserializeObject(edata); // data selanjutnya di prosess di sini }

Simple banget.

Hasil deserialize object ketika debugging tersebut dapat dilihat seperti gambar di bawah.

image

Dari gambar tersebut, string JSON telah di-deserialize menjadi object (string, Date, dll). Mudah bukan?

Semoga bermanfaat.


Categories: ASP.NET AJAX | JavaScript | JSON | Tips
Permalink | Comments (4) | Post RSSRSS comment feed

Mencegah Print Screen Halaman Web

Hak Atas Kekayaan Intelektual (HAKI) dan Hak Cipta merupakan suatu hak yang harus ditegakkan. Susah-susah membuat tulisan berdasarkan hasil pemikiran sendiri, dengan mudah dalam sekejap dijiplak orang lain dan diaku sebagai hasil karya sendiri.
Sering kali dijumpai beberapa situs tidak bisa disalin halaman web-nya. Orang yang memang punya niat mencuri dengan berbagai cara tetep bisa menyalin isinya dengan cara print-screen, baik dengan tombol yang ada di keyboard maupun dengan software. Dalam tulisan ini akan saya akan membagi trik untuk mencegah tindakan print-screen terhadap halaman web yang kita buat.
Untuk mencegah tindakan print-scrint salah satunya adalah dengan cara menghilangkan isi clipboard secara berkala. Cara tersebut dapat dilakukan dengan script berikut.


function clearImage()
{
    r = window.clipboardData.clearData("Image");
}
ci = setInterval("clearImage()", 10);

Code tersebut akan menghapus data clipboard dengan type Image karena hasil print-screen akan disimpan di clipboard dalam bentuk image.
Catatan: Script ini hanya berjalan di Internet Explorer.
Untuk memastikan bahwa ini berjalan di IE dan tidak menimbulkan error di browser lain perlu adanya pengecekan terlebih dahulu. Script di atas dapat diubah menjadi.

function clearImage() {
    if (window.clipboardData) {
        r = window.clipboardData.clearData("Image");
    }
}
ci = setInterval("clearImage()", 10);

Script di atas saya dapatkan dari dendy=at=ins.co.id di milis PHPUG.
Semoga bermanfaat.


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

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

JSON vs XML

JSON (JavaScript Object Notation) merupakan format pertukaran data berdasarkan notasi JavaScript. Dari beberapa sumber mengatakan bahwa JSON lebih baik dari XML sebagai format pertukaran data. Benarkah demikian? Saya coba untuk membuat test sedarhana membandingkan kedua format data tersebut pada ASP.NET WebService.

Saya menggunakan dua parameter pembanding yaitu besar stream yang ditransmisikan dan response time. Untuk menganalisis kinerja keduanya saya gunakan tool buatan Nikhil Kotari yaitu Web Development Helper yang dapat di download dari situs pribadinya di Nikhil Kothari's Projects - Web Development Helper

Pertama saya buat sebuat object Employee dengan data EmpId, Name, Sex dan Title. object ini yang akan diserialisasi ke JSON dan XML sebagai return value WebService.

namespace JSONSample
{
    public class Employee
    {
        public string EmpId { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public char Sex { get; set; }
    }
}

Selanjutnya buat web service dengan dua method yang mengembalikan Employee dalam format JSON dan XML. Jangan lupa untuk menambahkan namespace System.Web.Script.Services dan class attribute [ScriptService]

using System;
using System.Collections;
using System.ComponentModel;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Web.Script.Services;

namespace JSONSample
{
    /// <summary>
    /// Summary description for WebService1
    /// </summary>
    [WebService(Namespace = "">http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    [ScriptService]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    // [System.Web.Script.Services.ScriptService]
    public class WebService1 : System.Web.Services.WebService
    {

        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
        public Employee GetEmployee(string EmpId)
        {
            var emp = new Employee();
            emp.EmpId = EmpId;
            emp.Name = "Ahmad Masykur";
            emp.Sex = 'M';
            emp.Title = "Analyst, Application Architecture";
            return emp;
        }
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Employee GetEmployeeJSON(string EmpId)
        {
            var emp = new Employee();
            emp.EmpId = EmpId;
            emp.Name = "Ahmad Masykur";
            emp.Sex = 'M';
            emp.Title = "Analyst, Application Architecture";
            return emp;
        }
    }
}

Berikutnya adalah buat kode javascript untuk memanggil memanggil kedua method pada WebService yang telah dibuat sebelumnya.

var displayElement1;
var displayElement2;

// Initializes global variables and session state.
function pageLoad()
{
    displayElement1 = $get("ResultId1");
    displayElement2 = $get("ResultId2");
}
function getEmployee() {
    JSONSample.WebService1.GetEmployee("894683", OnSucceeded, OnFailed);
    JSONSample.WebService1.GetEmployeeJSON("894683", OnSucceeded, OnFailed);
}

// Callback function invoked on successful
// completion of the page method.
function OnSucceeded(result, userContext, methodName)
{
    if (methodName=="GetEmployee") { // xml
        displayElement1.innerHTML = result.documentElement.selectSingleNode('//Name').text;
    }
    else { // json
        displayElement2.innerHTML = result.Name;
    }
}

// Callback function invoked on failure
// of the page method.
function OnFailed(error, userContext, methodName)
{
    if(error !== null)
    {
        displayElement.innerHTML = "An error occurred: " +
            error.get_message();
    }
}

if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();

Terakhir buat halaman ASP.NET AJAX yang akan meregister JavaScript dan WebService sehingga WebService dapat dipanggil melalui JavaScript oleh ASP.NET AJAX proxy service.


<%@ Page Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.Page" %> <!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>Untitled Page</title></head><body>    <form id="form1" runat="server">    <div>        <asp:ScriptManager ID="ScriptManager1" runat="server">        <Scripts>            <asp:ScriptReference Path="~/clientscript.js" />        </Scripts>        <Services>            <asp:ServiceReference Path="~/WebService1.asmx" />        </Services>        </asp:ScriptManager>           <input type="button" value="Invoke" onclick="getEmployee()" />        <div id="ResultId1"></div>        <div id="ResultId2"></div>    </div>    </form></body></html>

Setelah dijalankan, aktifkan Web Development Helper dan check Enable Logging. Selanjutnya klik tombol Invoke tiga kali pada halaman dan periksa hasilnya.

image

Dari hasil keluaran log dapat dilihat bahwa dengan data yang sama, format XML memerlukan 226 byte sedangkan JSON hanya 132 byte. Ini jauh lebih kecil (kurang dari setengah) dibandingkan XML. Dari sisi response time, pada invoke yang pertama XML membutuhkan waktu 0:0:3430 sedangkan JSON 0:0:3280 dan invoke berikutnya untuk XML 0:0:0150 sedangkan JSON 0:0:0000. Dari data ini membuktikan bahwa JSON memang lebih ringan dibandingkan XML baik dari sisi ukuran stream yang ditransmisikan lebih kecil maupun waktu proses di server juga lebih singkat.


Tags: ,
Categories: ASP.NET AJAX | JavaScript | JSON
Permalink | Comments (15) | Post RSSRSS comment feed

Invoke Web Service Menggunakan XMLHttpRequest

Banyak library Ajax yang sudah gede dan banyak fiturnya seperti ASP.NET AJAX, Anthem.NET, AjaxAnywhere, ajaxCFC, AJS, Dojo, Rico dan beberapa library lainnya. Dalam tulisan ini akan saya jelaskan konsep invoke Web Service langsung menggunakan objek XMLHttpRequest (XHR). Saya asumsikan bahwa pembaca sudah memahami konsep dasar XMLHttpRequest, jika belum silakan baca tulisan saya sebelumnya di Pengenalan AJAX.

Pertama buat root object dengan nama Masykur, root object ini bisa disamakan sebagai namespace pada OOP.

if (!window.Masykur) {
    window.Masykur = {};
}

Setelah root object dibuat kemudian buat member yang berisi DOM dan Ajax. DOM digunakan untuk mendapatkan informasi DOM dan browser sedangkan Ajax adalah object yang menangani komunikasi singkron dengan Web Service.

if (!Masykur.DOM) {
    Masykur.DOM = function() {}
}
if (!Masykur.Ajax) {
    Masykur.Ajax = function() {}
}

Pada objek Masykur.DOM, tambahkan property untuk pengecekan browser. Pengecekan browser ini digunakan untuk mengecek kemampuan dari masing-masing browser karena masing-masing browser menggunakan objek yang berbeda untuk menangani XHR maupun dokumen XML.

Masykur.DOM.isInternetExplorer = (navigator.userAgent.indexOf("MSIE") >= 0);
Masykur.DOM.isMozilla = (navigator.userAgent.indexOf("Gecko") >= 0);
Masykur.DOM.isOpera = (navigator.userAgent.indexOf("Opera") >= 0);

Pada objek Masykur.Ajax, buat variabel nameSpace yang digunakan sebagai namespace pada Envelope SOAP. Selain variabel juga tambahkan fungsi set dan get namespace.

Masykur.Ajax = function() {
    var nameSpace = "http://tempuri.org/";
    this.setNameSpace = function(ns){
        nameSpace = ns;
    }//end setNameSpace()
    
    this.getNameSpace = function(){
        return nameSpace;
    }//end getNameSpace()
}

Buat objek XHR lintas browser dengan mencoba semua metode dari create XMLHttpRequest dari JavaScript object, ActiveX dan SOAPCall object. Ini dimaksudkan supaya semua library tidak tergantung dengan browser yang digunakan, dapat berjalan baik IE, Firefox maupun Opera.

Masykur.Ajax = function(){
    // ...
    var ajaxObject = function(){
        try{return new XMLHttpRequest();}catch(ex){};
        try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(ex){};
        try{return new SOAPCall();}catch(ex){};
    }//end ajaxObject()
}

Buat fungsi penanganan error yang kemudian dapat di-override dengan fungsi sendiri saat digunakan.

Masykur.Ajax = function(){
    // ...
    this.onError = function(error){
        alert(error);
    }//end onError()
}

Setelah semua persiapan objek XHR selesai, sekarang tinggal buat fungsi callService untuk invoke ke Web Service.

Masykur.Ajax = function(){
    // ...
    this.callService = function(serviceUrl, soapMethod, callbackFunction /*, unlimited params */){
        // code
    }
}

Pertama yang perlu disiapkan adalah URL web service. Tambahkan "?WSDL" dibelakang URL.

if(serviceUrl.indexOf("http://") < 0)
    serviceUrl = "http://" + serviceUrl;
serviceUrl += "?WSDL";

Hal penting yang harus disiapkan adalah envelope untuk membungkus data yang akan dikirimkan ke server. Envelope berisi semua parameter yang dibutuhkan oleh web service method. Parameter dibungkus dalam tag <soap:Body>, nama parameter merupakan sebuah elemen child <soap:Body> dan valuenya dimasukkan sebagai text element parameter.

var soapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
soapEnvelope += "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
soapEnvelope += "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ";
soapEnvelope += "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">";
soapEnvelope += "<soap:Body>";
soapEnvelope += "<" + soapMethod + " xmlns=\"" + nameSpace + "\">";

if(arguments.length > 3){
    for (var i = 3; i < arguments.length; i++)
    {
        var params = [];
        var arg = arguments[i];
        var ieq = arg.indexOf('=');
        params[0] = arg.substr(0, ieq);
        params[1] = arg.substr(ieq + 1);
        soapEnvelope += "<" + params[0] + ">";
        soapEnvelope += params[1];
        soapEnvelope += "</" + params[0] + ">";
    }//end for
}//end if

soapEnvelope += "</" + soapMethod + ">";
soapEnvelope += "</soap:Body>";
soapEnvelope += "</soap:Envelope>";

Set event onreadystate pada objek XHR dan kembalikan hasil respon web service dalam format string setelah semua data lengkap diterima.

Terakhir buka sambungan dengan server menggunakan mode POST dan set header content-type menjadi "text/xml" dan tambahkan juga header "soapaction" dengan data namespace diikuti dengan soap method. Kirimkan soap envelope pada request body seperti pada kode berikut.

ao.open("POST", serviceUrl, true);
ao.setRequestHeader("Content-Type", "text/xml");
ao.setRequestHeader("soapaction", nameSpace + soapMethod);
ao.send(soapEnvelope);

Script lengkap dapat dilihat pada kode berikut.

if (!window.Masykur) {
    window.Masykur = {};
}
if (!Masykur.DOM) {
    Masykur.DOM = function() {}
}
if (!Masykur.Ajax) {
    Masykur.Ajax = function() {}
}
Masykur.DOM.isInternetExplorer = (navigator.userAgent.indexOf("MSIE") >= 0);
Masykur.DOM.isMozilla = (navigator.userAgent.indexOf("Gecko") >= 0);
Masykur.DOM.isOpera = (navigator.userAgent.indexOf("Opera") >= 0);

Masykur.Ajax = function(){

    var nameSpace = "http://tempuri.org/";
    
    //private method for returning an ajax enabled
    //object specific to a browser
    var ajaxObject = function(){
        try{return new XMLHttpRequest();}catch(ex){};
        try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(ex){};
        try{return new SOAPCall();}catch(ex){};
    }//end ajaxObject()
    
    this.onError = function(error){
        alert(error);
    }//end onError()

    this.callService = function(serviceUrl, soapMethod, callbackFunction /*, unlimited params */){
        
        var callServiceError = this.onError;
        
        var ao = ajaxObject();
        
        if(!ao.encode){
            if(serviceUrl.indexOf("http://") < 0)
                serviceUrl = "http://" + serviceUrl;
            serviceUrl += "?WSDL";
            
            var soapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
            soapEnvelope += "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
            soapEnvelope += "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ";
            soapEnvelope += "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">";
            soapEnvelope += "<soap:Body>";
            soapEnvelope += "<" + soapMethod + " xmlns=\"" + nameSpace + "\">";
            
            if(arguments.length > 3){
                for (var i = 3; i < arguments.length; i++)
                {
                    var params = [];
                    var arg = arguments[i];
                    var ieq = arg.indexOf('=');
                    params[0] = arg.substr(0, ieq);
                    params[1] = arg.substr(ieq + 1);
                    soapEnvelope += "<" + params[0] + ">";
                    soapEnvelope += params[1];
                    soapEnvelope += "</" + params[0] + ">";
                }//end for
            }//end if
            
            soapEnvelope += "</" + soapMethod + ">";
            soapEnvelope += "</soap:Body>";
            soapEnvelope += "</soap:Envelope>";
            
            ao.onreadystatechange = function(){
                
                if(ao.readyState == 4){
                    
                    if(Masykur.DOM.isOpera){
                        //opera
                        var response = ao.responseXML.getElementsByTagName(soapMethod + "Result")[0];
                        if(!response)
                            response = ao.responseXML.getElementsByTagName(soapMethod + "Response")[0];
                        if(!response){
                            callServiceError("WebService does not contain a Result/Response node");
                            return;
                        }//end if
                        
                        ao.callbackFunction(ao.responseXML.getElementsByTagName(soapMethod + "Result")[0].innerHTML);
                    }
                    else if(Masykur.DOM.isInternetExplorer){
                        //IE
                        var responseXml = new ActiveXObject('Microsoft.XMLDOM');
                        responseXml.loadXML(ao.responseText);
                            
                        var responseNode = responseXml.selectSingleNode("//" + soapMethod + "Result");
                        if(!responseNode)
                            responseNode = responseXml.selectSingleNode("//" + soapMethod + "Response");
                        if(!responseNode) {
                            callServiceError("Response/Result node not found.\n\nResponse:\n" + ao.responseText);
                            return;
                        }//end if
                        var resultNode = responseNode.firstChild;
                        if (resultNode != null){
                            try{
                                callbackFunction(resultNode.xml);
                            }
                            catch(ex){
                                callServiceError(ex);
                            }//end tc
                        }
                        else{
                            try{
                                callbackFunction();
                            }
                            catch(ex){
                                callServiceError(ex);
                            }//end tc
                        }//end if
                    }
                    else if(Masykur.DOM.isMozilla){
                        //Mozilla
                        var xmlDocument = new DOMParser().parseFromString(ao.responseText, "text/xml");
                        
                        var xr = xmlDocument.evaluate("//" + soapMethod + "Result", 
                                 xmlDocument.childNodes[xmlDocument.childNodes.length-1], 
                                 null, 
                                 XPathResult.ANY_TYPE, null);
                        var responseNode = xr.iterateNext();
                        
                        if(!responseNode)
                            callServiceError("Response/Result node not found.\n\nResponse:\n" + ao.responseText);
                        
                        var resultNode = responseNode.firstChild;
                        
                        if (resultNode != null){
                            try{
                                callbackFunction(resultNode.textContent);
                            }
                            catch(ex){
                                callServiceError(ex);
                            }//end tc
                        }
                        else{
                            try{
                                callbackFunction();
                            }
                            catch(ex){
                                callServiceError(ex);
                            }//end tc
                        }//end if
                    }//end if
                }//end if
            };
            
            ao.open("POST", serviceUrl, true);            
            ao.setRequestHeader("Content-Type", "text/xml");
            ao.setRequestHeader("soapaction", nameSpace + soapMethod);
            try{
                ao.send(soapEnvelope);
            }
            catch(ex){
                serviceCallError(ex);
            }//end tc
        }
        else{
            var soapParams = new Array();
            var headers = new Array();
            var soapVersion = 0;
            var object = nameSpace;
            
            if(serviceUrl.indexOf("http://") < 0)
                serviceUrl = document.location + serviceUrl;
            
            ao.transportURI = serviceUrl;
            ao.actionURI = nameSpace + soapMethod;
            
            for(var i=3; i<arguments.length; i++){
                var params = arguments[i].split("=");
                soapParams.push( new SOAPParameter(params[1],params[0]) );
            }//end for
            
            try{
                ao.encode(soapVersion, soapMethod, object, headers.length, headers, soapParams.length, soapParams);
            }
            catch(ex){
                serviceCallError(ex);
            }//end tc
        
            try{
                netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
            } 
            catch(ex){
                return false;
            }//end tc
            
            try{
                ao.asyncInvoke(
                    function(resp,call,status){

                    if(resp.fault)
                        return callServiceError(resp.fault);
                    if(!resp.body){
                        callServiceError("Service " + call.transportURI + " not found.");
                    }
                    else{
                        try{
                            callbackFunction(resp.body.firstChild.firstChild.firstChild.data);
                        }
                        catch(ex){
                            callServiceError(ex);
                        }//end tc
                    }//end if
                }
                );
            }
            catch(ex){
                serviceCallError(ex);
            }//end tc
                        
        }//end if
        
    }//end callService()
    
    this.setNameSpace = function(ns){
        nameSpace = ns;
    }//end setNameSpace()
    
    this.getNameSpace = function(){
        return ns;
    }//end getNameSpace()
    
}//end Masykur.Ajax()

Categories: AJAX | JavaScript
Permalink | Comments (17) | Post RSSRSS comment feed