From 368cfb3c56274b0928aceae268ee8b4da5855ef9 Mon Sep 17 00:00:00 2001 From: Tomas Kirda Date: Wed, 19 Dec 2012 15:53:34 -0600 Subject: [PATCH] Add onSearchStart and onSearchComplete tests. Update documentation. --- readme.md | 18 +++++++-- spec/autocompleteBehavior.js | 72 +++++++++++++++++++++++++++++++++++- spec/runner.html | 1 + src/jquery.autocomplete.js | 13 +++++-- 4 files changed, 96 insertions(+), 8 deletions(-) diff --git a/readme.md b/readme.md index 8f2c8fb..f37d303 100644 --- a/readme.md +++ b/readme.md @@ -25,6 +25,8 @@ autocomplete/autosuggest boxes for text input fields. * `zIndex`: 'z-index' for suggestions container. Default: `9999`. * `type`: Ajax request type to get suggestions. Default: `GET`. * `noCache`: Boolean value indicating whether to cache suggestion results. Default `true`. + * `onSearchStart`: `function (query) {}` called before ajax request. `this` is bound to input element. + * `onSearchComplete`: `function (query) {}` called after ajax response is processed. `this` is bound to input element. ##Usage @@ -60,12 +62,19 @@ Local lookup (no ajax): Generated HTML markup for suggestions is displayed bellow. You may style it any way you'd like. -
+
...
...
...
+Style sample: + + .autocomplete-suggestions { border: 1px solid #999; background: #FFF; overflow: auto; } + .autocomplete-suggestion { padding: 2px 5px; white-space: nowrap; overflow: hidden; } + .autocomplete-selected { background: #F0F0F0; } + .autocomplete-suggestions strong { font-weight: normal; color: #3399FF; } + ##Response Format Response from the server must be JSON formatted following JavaScript object: @@ -79,14 +88,17 @@ Response from the server must be JSON formatted following JavaScript object: ] } -Data can be any value or object. Data object is passed to formatResults function and onSelect callback. Alternatively, if there is no data you can supply just a string array for suggestions: +Data can be any value or object. Data object is passed to formatResults function +and onSelect callback. Alternatively, if there is no data you can +supply just a string array for suggestions: { query: "Unit", suggestions: ["United Arab Emirates", "United Kingdom", "United States"] } -Important: query value must match original value in the input field, otherwise suggestions will not be displayed. +Important: query value must match original value in the input +field, otherwise suggestions will not be displayed. ##License diff --git a/spec/autocompleteBehavior.js b/spec/autocompleteBehavior.js index 60e9fc4..b556195 100644 --- a/spec/autocompleteBehavior.js +++ b/spec/autocompleteBehavior.js @@ -1,9 +1,13 @@ /*jslint vars: true*/ -/*global describe, it, expect, $*/ +/*global describe, it, expect, waitsFor, runs, afterEach, $*/ describe('Autocomplete', function () { 'use strict'; + afterEach(function () { + $('.autocomplete-suggestions').hide(); + }); + it('Should initialize autocomplete options', function () { var input = document.createElement('input'), options = { serviceUrl: '/autocomplete/service/url' }, @@ -34,6 +38,29 @@ describe('Autocomplete', function () { expect(autocomplete.currentValue).toEqual('Jam'); }); + it('Should call formatResult three times', function () { + var input = document.createElement('input'), + counter = 0, + suggestion, + currentValue, + autocomplete = new $.Autocomplete(input, { + lookup: ['Jamaica', 'Jamaica', 'Jamaica'], + formatResult: function (s, v) { + suggestion = s; + currentValue = v; + counter += 1; + } + }); + + input.value = 'Jam'; + autocomplete.onValueChange(); + + expect(suggestion.value).toBe('Jamaica'); + expect(suggestion.data).toBe(null); + expect(currentValue).toEqual('Jam'); + expect(counter).toEqual(3); + }); + it('Verify onSelect callback', function () { var input = document.createElement('input'), context, @@ -67,4 +94,47 @@ describe('Autocomplete', function () { expect(autocomplete.options.lookup[1].value).toBe('B'); }); + it('Should execute onSearchStart and onSearchCompleted', function () { + var input = document.createElement('input'), + startQuery, + completeQuery, + ajaxExecuted = false, + autocomplete = new $.Autocomplete(input, { + serviceUrl: '/test', + onSearchStart: function (query) { + startQuery = query; + }, + onSearchComplete: function (query) { + completeQuery = query; + } + }); + + $.mockjax({ + url: '/test', + responseTime: 50, + response: function (settings) { + ajaxExecuted = true; + var query = settings.data.query, + response = { + query: query, + suggestions: [] + }; + ajaxExecuted = true; + this.responseText = JSON.stringify(response); + } + }); + + input.value = 'A'; + autocomplete.onValueChange(); + + waitsFor(function () { + return ajaxExecuted; + }, 'Ajax call never completed.', 100); + + runs(function () { + expect(ajaxExecuted).toBe(true); + expect(startQuery).toBe('A'); + expect(completeQuery).toBe('A'); + }); + }); }); \ No newline at end of file diff --git a/spec/runner.html b/spec/runner.html index 108ba3d..dd6f91b 100644 --- a/spec/runner.html +++ b/spec/runner.html @@ -9,6 +9,7 @@ + diff --git a/src/jquery.autocomplete.js b/src/jquery.autocomplete.js index 3bd2a3d..4a9e1e8 100644 --- a/src/jquery.autocomplete.js +++ b/src/jquery.autocomplete.js @@ -49,7 +49,8 @@ }()); function Autocomplete(el, options) { - var that = this, + var noop = function () { }, + that = this, defaults = { serviceUrl: null, lookup: null, @@ -63,7 +64,9 @@ delimiter: null, zIndex: 9999, type: 'GET', - noCache: false + noCache: false, + onSearchStart: noop, + onSearchComplete: noop }; // Shared variables: @@ -294,7 +297,7 @@ onValueChange: function () { clearInterval(this.onChangeInterval); this.currentValue = this.element.value; - + var q = this.getQuery(this.currentValue); this.selectedIndex = -1; @@ -342,7 +345,8 @@ that.suggestions = response.suggestions; that.suggest(); } else if (!that.isBadQuery(q)) { - that.options.params.query = q; + options.onSearchStart.call(that.element, q); + options.params.query = q; $.ajax({ url: options.serviceUrl, data: options.params, @@ -350,6 +354,7 @@ dataType: 'text' }).done(function (txt) { that.processResponse(txt); + options.onSearchComplete.call(that.element, q); }); } },