(function ($, undefined) {

    $.widget('ui.weblookup', {

        options: {
            minLength: 1,
            multiSelect: false,
            multiSelectKeyName: null,
            type: 'POST',
            url: '',
            urlOne: '',
            limit: 20,
            otherInputParameters: '',
            delay: 300,
            async: true,
            selectedItem: null,
            selectedItems: [],
            scrollable: true,
            height: 200,
            width: 'auto',
            search: null,
            focus: null,
            select: null,
            change: null,
            changeSelectedItem: null,
            changeSelectedItems: null,
            successrequest: null,
            errorrequest: null,
            renderitem: null,
            rendertext: null,
            inputHiddenId: null,


            ul: null,
            currentItem: -1,
            sourceLength: 0,
            hasAnimate: true
        },

        _init: function () {
            var _element = this.element;
            var _altItem = false;

            var keys = ['minLength', 'multiSelect', 'multiSelectKeyName', 'url', 'urlOne', 'limit',
                            'otherInputParameters', 'delay', 'async', 'selectedItem', 'selectedItems', 'scrollable',
                            'height', 'width', 'search', 'focus', 'select', 'change', 'changeSelectedItem', 'changeSelectedItems',
                            'successrequest', 'errorrequest', 'renderitem', 'rendertext'];
            for (var i = 0; i < keys.length; i++) {
                _element.weblookup('validateOption', keys[i], _element.weblookup('option', keys[i]));
            }

            function ulSize(ul) {
                var _ul_height = 0;
                ul.contents('li[x_class]').each(
                        function () {
                            _ul_height = _ul_height + $(this).height();
                        }
                    );
                return _ul_height;
            }

            function move(count) {
                if (_element.weblookup('option', 'ul') != null) {
                    var _index = _element.weblookup('option', 'currentItem');
                    var ul = _element.weblookup('option', 'ul');
                    _index = _index + count;
                    if (_index >= _element.weblookup('option', 'sourceLength')) {
                        _index = 0;
                    }
                    else {
                        if (_index == -1) {
                            _index = _element.weblookup('option', 'sourceLength') - 1;
                        }
                    }
                    var _scroll = 0;
                    var _ul_height = ulSize(ul);
                    ul.contents('li[x_class]').each(
                            function () {
                                var _li = $(this);
                                var _curr = parseInt(_li.attr('x_index'));
                                if (_curr <= _index) {
                                    _scroll = _scroll + _li.height();
                                }
                            }
                        );
                    var _currHeight = ul.contents('li[x_index=' + _index + ']').height();
                    var _li = ul.contents('li[x_index=' + _index + ']');
                    if (_index == 0) {
                        _element.weblookup('animate', { scrollTop: 0 });
                    }
                    else {
                        if (_index == _element.weblookup('option', 'sourceLength') - 1) {
                            _element.weblookup('animate', { scrollTop: _ul_height - ul.height() });
                        }
                        else {
                            if (count > 0) {
                                if (ul.offset().top + ul.height() < _li.offset().top + _li.height()) {
                                    _element.weblookup('animate', { scrollTop: ul[0].scrollTop + _li.height() });
                                }
                                else {
                                    _element.weblookup('animate', { scrollTop: 0 });
                                }
                            }
                            else {
                                if (ul.offset().top > _li.offset().top) {
                                    _element.weblookup('animate', { scrollTop: ul[0].scrollTop - _li.height() });
                                }
                                else {
                                    _element.weblookup('animate', { scrollTop: ul[0].scrollTop });
                                }
                            }
                        }
                    }
                    setCurrentItem(_index);
                }
            }

            function setCurrentItem(_index) {
                _element.weblookup('option', 'currentItem', _index);
                var ul = _element.weblookup('option', 'ul');
                if (ul != null) {
                ul.contents('li[x_class]').each(
                        function () {
                            var _li = $(this);
                            var _curr = parseInt(_li.attr('x_index'));
                            if (_curr == _index) {
                                _li.removeClass(_li.attr('x_class'));
                                _li.addClass(_li.attr('x_class_hover'));
                            }
                            else {
                                _li.removeClass(_li.attr('x_class_hover'));
                                _li.addClass(_li.attr('x_class'));
                            }
                        }
                    );
            }
            }

            _element.keydown(function (event) {
                if (_element.weblookup('option', 'multiSelect')) {
                    if (_element.weblookup('option', 'ul') != null) {
                        if (_element.weblookup('option', 'hasAnimate')) {
                            switch (event.keyCode) {
                                case $.ui.keyCode.DOWN:
                                    move(1);
                                    event.preventDefault();
                                    break;
                                case $.ui.keyCode.UP:
                                    move(-1);
                                    event.preventDefault();
                                    break;
                                case $.ui.keyCode.PAGE_DOWN:
                                    if (_element.weblookup('option', 'scrollable')) {
                                        var _index = _element.weblookup('option', 'currentItem');
                                        var ul = _element.weblookup('option', 'ul');
                                        var _height = ul.height();
                                        if (_index < _element.weblookup('option', 'sourceLength') - 1) {
                                            var _scrollSize = 0;
                                            while (_height > 0 && _index < _element.weblookup('option', 'sourceLength') - 1) {
                                                _height = _height - ul.contents('li[x_index=' + _index + ']').height();
                                                _index++;
                                                _scrollSize = _scrollSize + ul.contents('li[x_index=' + _index + ']').height();
                                            }
                                            setCurrentItem(_index);
                                            _element.weblookup('animate', { scrollTop: ul[0].scrollTop + _scrollSize });
                                        }
                                        else {
                                            setCurrentItem(_element.weblookup('option', 'sourceLength') - 1);
                                            _element.weblookup('animate', { scrollTop: ulSize(ul) });
                                        }
                                    }
                                    else {
                                        setCurrentItem(_element.weblookup('option', 'sourceLength') - 1);
                                    }
                                    break;
                                case $.ui.keyCode.PAGE_UP:
                                    if (_element.weblookup('option', 'scrollable')) {
                                        var _index = _element.weblookup('option', 'currentItem');
                                        if (_index > 0) {
                                            var ul = _element.weblookup('option', 'ul');
                                            var _scrollSize = 0;
                                            var _height = ul.height();
                                            while (_height > 0 && _index > 0) {
                                                _height = _height - ul.contents('li[x_index=' + _index + ']').height();
                                                _index--;
                                                _scrollSize = _scrollSize + ul.contents('li[x_index=' + _index + ']').height();
                                            }

                                            if (ul[0].scrollTop - _scrollSize < 0) {
                                                setCurrentItem(0);
                                                _element.weblookup('animate', { scrollTop: 0 });
                                            }
                                            else {
                                                setCurrentItem(_index);
                                                _element.weblookup('animate', { scrollTop: ul[0].scrollTop - _scrollSize });
                                            }
                                        }
                                        else {
                                            setCurrentItem(0);
                                            _element.weblookup('animate', { scrollTop: 0 });
                                        }
                                    }
                                    else {
                                        setCurrentItem(0);
                                    }
                                    break;
                                case $.ui.keyCode.NUMPAD_ADD:
                                    var _index = _element.weblookup('option', 'currentItem');
                                    var ul = _element.weblookup('option', 'ul');
                                    ul.contents('li[x_class]').each(
                                            function () {
                                                var _li = $(this);
                                                var _curr = parseInt(_li.attr('x_index'));
                                                if (_curr == _index) {
                                                    _li.trigger('click');
                                                }
                                            }
                                        );
                                    event.preventDefault();
                                    break;
                            }
                        }
                    }
                }
            });

            _element.keyup(function (event) {
                if (_element.val().length == 0) {
                    _element.weblookup('clear');
                    event.preventDefault();
                    return;
                }
            });



            _element.autocomplete({
                minLength: _element.weblookup('option', 'minLength'),
                delay: _element.weblookup('option', 'delay'),
                source: function (request, response) {
                    _altItem = false;
                    _element.weblookup('option', 'currentItem', -1)
                    var _otherInputParameters = _element.weblookup('option', 'otherInputParameters');
                    if (typeof (_otherInputParameters) == 'object') {
                        _otherInputParameters = _element.weblookup('toJSON', _otherInputParameters);
                    }

                    if (jQuery.trim(_otherInputParameters) != '') {
                        _otherInputParameters = _otherInputParameters.replace('{', '');
                        _otherInputParameters = _otherInputParameters.replace('}', '');
                        _otherInputParameters = ', ' + _otherInputParameters;
                    }

                    var _data = '{"q": "' + request.term + '"';
                    var _limit = _element.weblookup('option', 'limit');
                    if (_limit != null) {
                        _data = _data + ', "limit": "' + _limit + '"';
                    }
                    _data = _data + _otherInputParameters + '}';

                    _element.weblookup('option', 'ul', null);

                    if (jQuery.trim(request.term) != '') {
                        _element.removeClass('ui-autocomplete-input');
                        _element.addClass('ui-autocomplete-loading');
                        $.ajax(
                                    {
                                        type: _element.weblookup('option', 'type'),
                                        contentType: 'application/json; charset=utf-8',
                                        url: _element.weblookup('option', 'url'),
                                        data: _data,
                                        dataType: 'json',
                                        async: _element.weblookup('option', 'async'),
                                        success: function (data, textStatus, XMLHttpRequest) {
                                            //alert($.toJSON(data));
                                            //alert(data.d);
                                            var jsondata;
                                            if (typeof (data) == 'object') {
                                                if (typeof (data.d) == 'string') {
                                                    jsondata = jQuery.parseJSON(data.d);
                                                }
                                                else {
                                                    //throw 'Invalid Response Data';
                                                    jsondata = data;
                                                }
                                            }
                                            else {
                                                if (typeof (data) == 'string') {
                                                    jsondata = jQuery.parseJSON(data);
                                                }
                                                else {
                                                    throw 'Invalid Response Data';
                                                }
                                            }
                                            _element.weblookup('option', 'sourceLength', jsondata.length);
                                            response(jsondata);
                                            if (_element.weblookup('option', 'successrequest') != null) {
                                                _element.weblookup('option', 'successrequest')(data, textStatus, XMLHttpRequest);
                                            }
                                            _element.removeClass('ui-autocomplete-loading');
                                            _element.addClass('ui-autocomplete-input');
                                            if (jsondata.length > 0) {
                                                _element.weblookup('option', 'ul').animate({ scrollTop: 0 }, 10);
                                                setCurrentItem(0);
                                            }
                                        },
                                        error: function (XMLHttpRequest, textStatus, errorThrown) {
                                            if (_element.weblookup('option', 'errorrequest') != null) {
                                                _element.weblookup('option', 'errorrequest')(XMLHttpRequest, textStatus, errorThrown);
                                            }
                                            else {
                                                var errorMessage = "Status: " + textStatus + ". ";
                                                errorMessage = errorMessage + "XMLHttpRequest.status: " + XMLHttpRequest.status + ". ";
                                                errorMessage = errorMessage + "XMLHttpRequest.responseText: " + XMLHttpRequest.responseText + ". ";
                                                throw errorMessage;
                                                /*
                                                alert(textStatus);
                                                alert(XMLHttpRequest.status);
                                                alert(XMLHttpRequest.getAllResponseHeaders());
                                                alert(XMLHttpRequest.responseText);
                                                */
                                            }
                                            _element.removeClass('ui-autocomplete-loading');
                                            _element.addClass('ui-autocomplete-input');
                                            _element.weblookup('option', 'sourceLength', 0);
                                            _element.weblookup('option', 'currentItem', -1);
                                        }
                                    });
                    }
                    else {
                        response([]);
                    }
                },
                change: function (event, ui) {
                    if (_element.weblookup('option', 'change') != null) {
                        return _element.weblookup('option', 'change')(event, ui);
                    }
                    else {
                        return true;
                    }
                },
                search: function (event, ui) {
                    if (_element.weblookup('option', 'search') != null) {
                        return _element.weblookup('option', 'search')(event, ui);
                    }
                    else {
                        return true;
                    }
                },
                focus: function (event, ui) {
                    if (_element.weblookup('option', 'focus') != null) {
                        return _element.weblookup('option', 'focus')(event, ui);
                    }
                    else {
                        return false;
                    }
                },
                select: function (event, ui) {
                    if (!_element.weblookup('option', 'multiSelect')) {
                        _element.weblookup('option', 'selectedItem', ui.item);

                        if (_element.weblookup('option', 'select') != null) {
                            _element.weblookup('option', 'select')(event, ui);
                        }
                    }
                    return false;
                }
            }).data('autocomplete')._renderItem = function (ul, item) {
                if (_element.weblookup('option', 'ul') == null) {
                    _element.weblookup('option', 'ul', ul);
                }
                if (_element.weblookup('option', 'scrollable')) {
                    ul.css('max-height', _element.weblookup('option', 'height'));
                    ul.css('overflow-y', 'auto');
                    ul.css('overflow-x', 'hidden');
                    ul.css('padding-right', 2);
                }

                var _item = null;
                if (_element.weblookup('option', 'renderitem') != null) {
                    _item = _element.weblookup('option', 'renderitem')(item);
                }
                if (_item == null) {
                    _item = 'Event "renderitem" is not defined';
                }

                var _li = $('<li x_item_li="1" ></li>');

                var _width = _element.weblookup('option', 'width');
                if (_width == 'input') {
                    _li.css('width', _element.width());
                }
                else {
                    if (_width != 'auto') {
                        _li.css('width', _width);
                        if (_li.width() < _element.width()) {
                            _li.css('width', _element.width());
                        }
                    }
                }

                _altItem = !_altItem;
                if (_element.weblookup('option', 'multiSelect')) {
                    _li.addClass('ui-menu-item');
                    _li.addClass('ui-corner-all');
                    if (_altItem) {
                        _li.addClass('ui-autocomplete-item-multiselect-alt');
                        _li.attr('x_class', 'ui-autocomplete-item-multiselect-alt');
                    }
                    else {
                        _li.addClass('ui-autocomplete-item-multiselect');
                        _li.attr('x_class', 'ui-autocomplete-item-multiselect');
                    }
                    _li.attr('x_class_hover', 'ui-autocomplete-item-multiselect-hover');

                    var _currentItem = _element.weblookup('option', 'currentItem');
                    _currentItem++;
                    _li.attr('x_index', _currentItem);
                    _element.weblookup('option', 'currentItem', _currentItem);

                    _li.mouseover(
                                                                    function (event) {
                                                                        setCurrentItem(parseInt(_li.attr('x_index')));
                                                                    }
                                                                );

                    _li.mouseout(
                                                                    function (event) {
                                                                        setCurrentItem(-1);
                                                                    }
                                                                );

                    var _checkbox = $('<input type="checkbox" x_item_checkbox="1" style="padding-right:3px;" /><span class="ui-autocomplete-item-multiselect-span">' + _item + '</span>');
                    var multiSelectKeyName = _element.weblookup('option', 'multiSelectKeyName');
                    if (multiSelectKeyName != null) {
                        var items = _element.weblookup('option', 'selectedItems');
                        for (var i = 0; i < items.length; i++) {
                            if (items[i][multiSelectKeyName] == item[multiSelectKeyName]) {
                                _checkbox[0].checked = true;
                                break;
                            }
                        }
                    }
                    _li.bind('click', item,
                                                                    function (event) {
                                                                        _element.focus();
                                                                        setCurrentItem(parseInt(_li.attr('x_index')));
                                                                        var target = $(event.target);
                                                                        var isCheck = target.attr('x_item_checkbox') == '1';
                                                                        var isLi = target.attr('x_item_li') == '1';
                                                                        if (!isLi) {
                                                                            target.parents().each(
                                                                                function () {
                                                                                    var element = $(this);
                                                                                    if (element.attr('x_item_li') == '1') {
                                                                                        target = element;
                                                                                    }
                                                                                }
                                                                            );
                                                                        }

                                                                        target.contents().each(
                                                                            function () {
                                                                                var box = $(this);
                                                                                if (box.attr('x_item_checkbox') == '1') {
                                                                                    if (!isCheck) {
                                                                                        box[0].checked = !box[0].checked;
                                                                                    }
                                                                                    var multiSelectKeyName = _element.weblookup('option', 'multiSelectKeyName');
                                                                                    if (multiSelectKeyName != null) {
                                                                                        var items = _element.weblookup('option', 'selectedItems');
                                                                                        if (box[0].checked) {
                                                                                            var isAdd = true;
                                                                                            for (var i = 0; i < items.length; i++) {
                                                                                                if (items[i][multiSelectKeyName] == event.data[multiSelectKeyName]) {
                                                                                                    isAdd = false;
                                                                                                    break;
                                                                                                }
                                                                                            }
                                                                                            if (isAdd) {
                                                                                                items[items.length] = event.data;
                                                                                                _element.weblookup('option', 'selectedItems', items);
                                                                                            }
                                                                                        }
                                                                                        else {
                                                                                            var _index = -1;
                                                                                            for (var i = 0; i < items.length; i++) {
                                                                                                if (items[i][multiSelectKeyName] == event.data[multiSelectKeyName]) {
                                                                                                    _index = i;
                                                                                                    break;
                                                                                                }
                                                                                            }
                                                                                            if (_index > -1) {
                                                                                                var newItems = [];
                                                                                                for (var i = 0; i < items.length; i++) {
                                                                                                    if (i != _index) {
                                                                                                        newItems[newItems.length] = items[i];
                                                                                                    }
                                                                                                }
                                                                                                _element.weblookup('option', 'selectedItems', newItems);
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                    if (_element.weblookup('option', 'changeSelectedItems') != null) {
                                                                                        _element.weblookup('option', 'changeSelectedItems')(event.data, box[0].checked);
                                                                                    }
                                                                                }
                                                                            }
                                                                        );
                                                                    }
                                                                )
                    return _li.data('item.autocomplete', item).append(_checkbox).appendTo(ul);
                }
                else {
                    if (_altItem) {
                        _li.addClass('ui-autocomplete-item-alt');
                    }
                    else {
                        _li.addClass('ui-autocomplete-item');
                    }
                    var _a = $('<a>' + _item + '</a>');
                    return _li.data('item.autocomplete', item).append(_a).appendTo(ul);
                }
            };


            var inputHiddenValue = _element.weblookup('getInputHiddenValue');
            if (inputHiddenValue != null && inputHiddenValue != "") {
                _element.weblookup('setItem', inputHiddenValue);
            }
        },
        clear: function () {
            this.element.val('');
            this.element.weblookup('option', 'selectedItem', null);
            if (this.element.weblookup('option', 'changeSelectedItem') != null) {
                this.element.weblookup('option', 'changeSelectedItem')(null);
                this.element.weblookup('setInputHidden', "");
            }
        },
        setInputHidden: function (value) {
            var inputHiddenId = this.element.weblookup('option', 'inputHiddenId');
            if (inputHiddenId != null) {
                var inputHidden = $("#" + inputHiddenId);
                inputHidden.val(value)
            }
        },
        getInputHiddenValue: function () {
            var inputHiddenId = this.element.weblookup('option', 'inputHiddenId');
            if (inputHiddenId != null) {
                var inputHidden = $("#" + inputHiddenId);
                return inputHidden.val();
            }
            else {
                return null;
            }
        },
        clearItems: function () {
            this.element.weblookup('option', 'selectedItems', []);
        },
        setItem: function (key) {
            var _element = this.element;
            if (_element.weblookup('option', 'urlOne') == null || _element.weblookup('option', 'urlOne') == "") {
                throw "Option urlOne is empty";
            }
            else {
                $.ajax(
                {
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    url: _element.weblookup('option', 'urlOne'),
                    data: '{ "id": "' + key + '"}',
                    dataType: 'json',
                    async: _element.weblookup('option', 'async'),
                    success: function (data, textStatus, XMLHttpRequest) {
                        var jsondata;
                        if (typeof (data) == 'object') {
                            if (typeof (data.d) == 'string') {
                                jsondata = jQuery.parseJSON(data.d);
                            }
                            else {
                                throw 'Invalid Response Data';
                            }
                        }
                        else {
                            if (typeof (data) == 'string') {
                                jsondata = jQuery.parseJSON(data);
                            }
                            else {
                                throw 'Invalid Response Data';
                            }
                        }
                        if (jsondata.length != 1) {
                            throw "Response object must be one size";
                        }
                        else {
                            _element.weblookup('option', 'selectedItem', jsondata[0]);
                        }
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        if (_element.weblookup('option', 'errorrequest') != null) {
                            _element.weblookup('option', 'errorrequest')(XMLHttpRequest, textStatus, errorThrown);
                        }
                        else {
                            var errorMessage = "Status: " + textStatus + ". ";
                            errorMessage = errorMessage + "XMLHttpRequest.status: " + XMLHttpRequest.status + ". ";
                            errorMessage = errorMessage + "XMLHttpRequest.responseText: " + XMLHttpRequest.responseText + ". ";
                            throw errorMessage;
                        }
                    }
                });
            }
        },
        _setOption: function (key, value) {
            this.element.weblookup('validateOption', key, value);
            this.options[key] = value;
            if (key == 'selectedItem') {
                if (value == null) {
                    this.element.val('');
                }
                else {
                    var _text = null;
                    if (this.element.weblookup('option', 'rendertext') != null) {
                        _text = this.element.weblookup('option', 'rendertext')(value);
                    }
                    this.element.val(_text);
                }
                var multiSelectKeyName = this.element.weblookup('option', 'multiSelectKeyName');
                if (multiSelectKeyName != null) {
                    if (value == null) {
                        this.element.weblookup('setInputHidden', "");
                    }
                    else {
                        this.element.weblookup('setInputHidden', value[multiSelectKeyName]);
                    }

                }
                if (this.element.weblookup('option', 'changeSelectedItem') != null) {
                    this.element.weblookup('option', 'changeSelectedItem')(value);
                }
            }
        },
        toJSON: function (o) {
            var type = typeof (o);

            if (o == null)
                return "null";

            if (type == "undefined")
                return undefined;

            if (type == "number" || type == "boolean")
                return o + "";

            if (type == "string")
                return $.quoteString(o);

            if (type == 'object') {
                if (typeof o.toJSON == "function")
                    return this.element.weblookup('toJSON', o.toJSON());

                if (o.constructor === Date) {
                    var month = o.getUTCMonth() + 1;
                    if (month < 10) month = '0' + month;

                    var day = o.getUTCDate();
                    if (day < 10) day = '0' + day;

                    var year = o.getUTCFullYear();

                    var hours = o.getUTCHours();
                    if (hours < 10) hours = '0' + hours;

                    var minutes = o.getUTCMinutes();
                    if (minutes < 10) minutes = '0' + minutes;

                    var seconds = o.getUTCSeconds();
                    if (seconds < 10) seconds = '0' + seconds;

                    var milli = o.getUTCMilliseconds();
                    if (milli < 100) milli = '0' + milli;
                    if (milli < 10) milli = '0' + milli;

                    return '"' + year + '-' + month + '-' + day + 'T' +
                                 hours + ':' + minutes + ':' + seconds +
                                 '.' + milli + 'Z"';
                }

                if (o.constructor === Array) {
                    var ret = [];
                    for (var i = 0; i < o.length; i++)
                        ret.push(this.element.weblookup('toJSON', o[i]) || "null");

                    return "[" + ret.join(",") + "]";
                }

                var pairs = [];
                for (var k in o) {
                    var name;
                    var type = typeof k;

                    if (type == "number")
                        name = '"' + k + '"';
                    else if (type == "string")
                        name = $.quoteString(k);
                    else
                        continue;  //skip non-string or number keys

                    if (typeof o[k] == "function")
                        continue;  //skip pairs where the value is a function.

                    var val = this.element.weblookup('toJSON', o[k]);

                    pairs.push(name + ":" + val);
                }

                return "{" + pairs.join(", ") + "}";
            }
        },
        animate: function (properties) {
            if (this.element.weblookup('option', 'hasAnimate')) {
                var _element = this.element;
                var ul = this.element.weblookup('option', 'ul');
                this.element.weblookup('option', 'hasAnimate', false);
                ul.animate(properties, 50, 'linear', function () {
                    _element.weblookup('option', 'hasAnimate', true);
                }
                );
            }
        },
        validateOption: function (key, value) {
            var _element = this.element;
            var id = this.element.attr("id");
            var prefix = 'Option: ' + key + '. ';
            if (id != null) {
                prefix = 'Control Id: ' + id + '. ' + prefix;
            }
            var type = typeof (value);

            function throwNull() {
                if (value == null) throw prefix + 'Value can not be null.';
            }
            function throwUndefined() {
                if (type == 'undefined') throw prefix + 'Value can not be undefined.';
            }
            function throwNotNumber() {
                if (type != 'number') throw prefix + 'Value must have number type.';
            }
            function throwNotBoolean() {
                if (type != 'boolean') throw prefix + 'Value must have boolean type.';
            }
            function throwNotString() {
                if (type != 'string') throw prefix + 'Value must have string type.';
            }
            function throwNotObject() {
                if (value != null && type != 'undefined' && type != 'object') throw prefix + 'Value must have object type.';
            }
            function throwNotFunction() {
                if (value != null && type != 'undefined' && type != 'function') throw prefix + 'Value must have function type.';
            }

            function throwNotJSON() {

                var filtered;
                if (type == 'string') {
                    filtered = value;
                }
                else {
                    filtered = _element.weblookup('toJSON', value);
                }

                filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
                filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
                filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');

                if (!(/^[\],:{}\s]*$/.test(filtered))) {
                    throw new SyntaxError(prefix + "Error parsing JSON, value is not valid.");
                }
            };

            switch (key) {
                case 'minLength':
                    throwNull();
                    throwUndefined();
                    throwNotNumber();
                    break;
                case 'delay':
                    throwNull();
                    throwUndefined();
                    throwNotNumber();
                    break;
                case 'height':
                    throwNull();
                    throwUndefined();
                    throwNotNumber();
                    break;
                case 'async':
                    throwNull();
                    throwUndefined();
                    throwNotBoolean();
                    break;
                case 'scrollable':
                    throwNull();
                    throwUndefined();
                    throwNotBoolean();
                    break;
                case 'multiSelect':
                    throwNull();
                    throwUndefined();
                    throwNotBoolean();
                    break;
                case 'multiSelectKeyName':
                    if (value != null) throwNotString();
                    break;
                case 'url':
                    throwNull();
                    throwUndefined();
                    throwNotString();
                    break;
                case 'urlOne':
                    throwNull();
                    throwUndefined();
                    throwNotString();
                    break;
                case 'limit':
                    if (value != null) throwNotNumber();
                    break;
                case 'otherInputParameters':
                    throwNull();
                    throwUndefined();
                    if (type != 'string' && type != 'object') throw prefix + 'Value must have object type or string type.'
                    throwNotJSON();
                    break;
                case 'selectedItem':
                    throwNotObject();
                    break;
                case 'selectedItems':
                    throwNotObject();
                    break;
                case 'width':
                    throwNull();
                    throwUndefined();
                    if (type != 'string' && type != 'number') throw prefix + 'Value must have number type or string type.'
                    break;
                case 'search':
                    throwNotFunction();
                    break;
                case 'focus':
                    throwNotFunction();
                    break;
                case 'select':
                    throwNotFunction();
                    break;
                case 'change':
                    throwNotFunction();
                    break;
                case 'changeSelectedItem':
                    throwNotFunction();
                    break;
                case 'successrequest':
                    throwNotFunction();
                    break;
                case 'errorrequest':
                    throwNotFunction();
                    break;
                case 'renderitem':
                    throwNotFunction();
                    break;
                case 'rendertext':
                    throwNotFunction();
                    break;
            }
        }
    });
})(jQuery);
