调用WCF Web服务时jquery-ui自动完成的简明语法

时间:2012-01-24 13:22:48

标签: ajax wcf jquery-ui autocomplete

This example of using jquery-ui autocomplete with a remote web service有一个很简洁的语法:

$( "#birds" ).autocomplete({
source: "search.php",
minLength: 2
});

这里search.php返回一个数组,如下所示:

[ 
    { "id": "Passer domesticus", "label": "House Sparrow", "value": "House Sparrow" },
    ...
]

我想使用WCF Web服务,但相同的语法不起作用because the array returned is wrapped in a 'd' container object

{"d":
    [ 
    { "id": "Passer domesticus", "label": "House Sparrow", "value": "House Sparrow" },
    ...
    ]
}

当然,我可以通过编写代码查看“d”容器来解决这个问题,例如以下内容(未经测试 - 可能有拼写错误):

$( "#birds" ).autocomplete({
minLength: 2
     source: function (request, response) {
            $.getJSON("search.svc/GetBirds", request, function (data, status, xhr) {
                if (status == "success") response(data.d);
                }
            }
});

这是我能做的最好的还是有一些更简洁的语法?

理想情况下,我希望能够将“source”指定为url并使其与使用或不使用“d”容器返回的响应一起使用。

1 个答案:

答案 0 :(得分:1)

在我看来,你有两种选择。

第一个是创建一个帮助函数,为您映射结果。这可能是最好/最简单的解决方案。简单的代码:

$( "#birds" ).autocomplete({
minLength: 2
     source: function (request, response) {
            $.getJSON("search.svc/GetBirds", request, function (data, status, xhr) {
                if (status == "success") 
                   handleResponse(data); //you write this function
                }
            }
});

第二个选项是"monkeypatch"AutoComplete plugin函数可以覆盖默认行为。

因此,在您的情况下,您想要覆盖$.ui.autocomplete.prototype._initSource函数。这里公平警告您基本上覆盖了UI库中的核心功能,如果该库已更新,您的功能将始终覆盖它。

// Create a closure so that we can define intermediary
// method pointers that don't collide with other items
// in the global name space. 

function monkeyPatchAutocomplete() {

    // don't really need this, but in case I did, I could store it and chain 
    var oldFn = $.ui.autocomplete.prototype._renderItem;
    var requestIndex = 0;
    $.ui.autocomplete.prototype._initSource = function() {
        // whatever
        console.log("Override method");
        var self = this,
            array, url;
        if ($.isArray(this.options.source)) {
            array = this.options.source;
            this.source = function(request, response) {
                response($.ui.autocomplete.filter(array, request.term));
            };
        } else if (typeof this.options.source === "string") {
            url = this.options.source;
            this.source = function(request, response) {
                if (self.xhr) {
                    self.xhr.abort();
                }
                self.xhr = $.ajax({
                    url: url,
                    data: request,
                    dataType: "json",
                    autocompleteRequest: ++requestIndex,
                    success: function(data, status) {
                        console.log("Override success function, handling request");
                        if (this.autocompleteRequest === requestIndex) {
                            response(data); //you handle both types of data here
                        }
                    },
                    error: function() {
                        console.log("Override error function, handling request");
                        if (this.autocompleteRequest === requestIndex) {
                            response([]);
                        }
                    }
                });
            };
        } else {
            this.source = this.options.source;
        }
    };
}


// When DOM is ready, initialize.
$(document).ready(function() {
    monkeyPatchAutocomplete();

    $("#birds").autocomplete({
        source: "http://jqueryui.com/demos/autocomplete/search.php",
        minLength: 2
    });

});

然后你的代码不需要执行任何不同的操作,它只是处理差异并将其传递给success方法。

这是一个jsFiddle:http://jsfiddle.net/lemkepf/DAQ6s/5/ 注意:实际的自动完成功能不适用,因为跨域安全性已经到位。您可以打开firebug并在开始在框中键入时看到console.debug线条。