Library
/**
 ** jquery.wikidot-api.js lib
 ** 
 ** (C) Piotr Gabryjeluk 2010-2011
 **/
 
;(function($) {
    $.wikidot = function(app_name, api_key, sync) {
        var sync = sync || false;
 
        var endpoint = location.protocol + '//' + app_name + ':' + api_key + '@' + location.host + '/xml-rpc-api.php';
 
        var encode = function(obj, doc) {
            var val;
            var type = typeof(obj);
 
            if (type == 'string') {
                val = $("<string/>", doc).text(obj);
            } else if (type == 'number') {
                val = $("<int/>", doc).text(obj);
            } else if ($.isArray(obj)) {
                val = $("<array/>", doc);
                var data = $("<data/>", doc);
                for (var i = 0; i < obj.length; i++) {
                    data.append(encode(obj[i]));
                }
                val.append(data);
            } else if (type == 'object') {
                for (key in obj) {
                    val = $("<struct/>", doc);
                    for (var key in obj) {
                        var member = $("<member/>", doc);
                        member.append($("<name/>", doc).text(key));
                        member.append(encode(obj[key]));
                        val.append(member);
                    }
                }
            } else {
                val = $("<nil/>", doc);
            }
 
            return $("<value/>", doc).append(val);
        };
 
        var decode = function(obj) {
            obj = $(obj);
            var ret = null;
            obj.children('array').each(function() {
                ret = [];
                $(this).children('data').children('value').each(function() {
                    ret.push(decode(this));
                });
            });
            obj.children('string').each(function() {
                ret = obj.text();
            });
            obj.children('int').each(function() {
                ret = parseInt(obj.text());
            });
            obj.children('struct').each(function() {
                ret = {};
                $(this).children('member').each(function() {
                    ret[$(this).children('name').text()] = decode($(this).children('value'));
                });
            });
            return ret;
        };
 
        var createDocument = function(rootTagName) {
            // for IE, you need other trick, check later
            return document.implementation.createDocument(null, rootTagName, null);
        };
 
        var prepareRequest = function(method, params) {
            if (! $.isArray(params)) {
                params = [ params ];
            }
 
            var doc = createDocument("methodCall");
 
            var methodName = $('<methodName/>', doc).text(method);
            var m_params = $("<params/>", doc);
            for (var i = 0; i < params.length; i++) {
                m_params.append($("<param/>", doc).append(encode(params[i], doc)));
            }
 
            $("methodCall", doc).append(methodName);
            $("methodCall", doc).append(m_params);
 
            return doc;
        };
 
        var call = function(method, params, callback) {
            $.ajax({
                async: ! sync,
                url: endpoint,
                type: 'POST',
                contentType: 'text/xml',
                data: prepareRequest(method, params),
                dataType: 'xml',
                processData: false,
                success: function(data) {
                    var ret = decode($(data).children('methodresponse').children('params').children('param').children('value'));
                    if (typeof(callback) == 'function') {
                        callback(ret);
                    }
                }
            });
        };
 
        var api = {};
 
        var namespaces = ['categories', 'files', 'tags', 'pages', 'posts', 'users'];
        var methods = ['select', 'get_meta', 'get_one', 'save_one', 'get', 'get_me'];
 
        var register_method = function(namespace, method) {
            if (typeof(api[namespace]) == 'undefined') {
                api[namespace] = {};
            }
            api[namespace][method] = function(params, callback) {
                call(namespace + '.' + method, params, callback);
            };
        };
 
        for (var i = 0; i < namespaces.length; i++) {
            for (var j = 0; j < methods.length; j++) {
                register_method(namespaces[i], methods[j]);
            }
        }
 
        return api;
    };
})(jQuery);