diff --git a/awesomplete.js b/awesomplete.js index 396fb711..b98da1e6 100644 --- a/awesomplete.js +++ b/awesomplete.js @@ -38,6 +38,7 @@ var _ = function (input, o) { container: _.CONTAINER, item: _.ITEM, replace: _.REPLACE, + suggestion: Suggestion, tabSelect: false }, o); @@ -307,7 +308,7 @@ _.prototype = { this.suggestions = this._list .map(function(item) { - return new Suggestion(me.data(item, value)); + return new me.suggestion(me.data(item, value)); }) .filter(function(item) { return me.filter(item, value); diff --git a/index.html b/index.html index 9676d747..86637d53 100644 --- a/index.html +++ b/index.html @@ -304,6 +304,12 @@

Extend

Awesomplete.DATA: Identity function which just returns the original list item. + + suggestion + Controls the class used to create new Suggestions. + A class that responds to the label, value, and length properties and the toString and valueOf methods. + Suggestion: A basic class, protoyped from String, which provides the requisite functionality. + diff --git a/test/init/optionsSpec.js b/test/init/optionsSpec.js index fc60997c..705f1015 100644 --- a/test/init/optionsSpec.js +++ b/test/init/optionsSpec.js @@ -38,6 +38,10 @@ describe("Constructor options", function () { it("replaces input value with REPLACE", function () { expect(this.subject.replace).toEqual(Awesomplete.REPLACE); }); + + it("creates a default Suggestion", function () { + expect(this.subject.suggestion.toString()).toMatch(/function Suggestion\(/); + }); }); describe("with custom options in constructor", function () { @@ -77,4 +81,107 @@ describe("Constructor options", function () { expect(this.subject.autoFirst).toBe(true); }); }); + + describe("with a custom suggestion option", function () { + def("element", "#with-data-list"); + + function CustomSuggestion1(data) { + var o = Array.isArray(data) + ? { label: data[0], value: data[1] } + : typeof data === "object" && "label" in data && "value" in data ? data : { label: data, value: data }; + + this.label = o.label || o.value; + this.value = o.value; + this.custom = o.label.toUpperCase(); + } + + Object.defineProperty(CustomSuggestion1.prototype = Object.create(String.prototype), "length", { + get: function() { return this.label.length; } + }); + + CustomSuggestion1.prototype.toString = CustomSuggestion1.prototype.valueOf = function () { + return "" + this.label; + }; + + function CustomSuggestion2(data) { + var o = Array.isArray(data) + ? { label: data[0], value: data[1] } + : typeof data === "object" && "label" in data && "value" in data ? data : { label: data, value: data }; + + this.label = o.label || o.value; + this.value = o.value; + this.custom = o.label.toLowerCase(); + } + + Object.defineProperty(CustomSuggestion2.prototype = Object.create(String.prototype), "length", { + get: function() { return this.label.length; } + }); + + CustomSuggestion2.prototype.toString = CustomSuggestion2.prototype.valueOf = function () { + return "" + this.label; + }; + + describe("using a class", function () { + def("options", function () { + return { + minChars: 0, + filter: function (item) { return item; }, + sort: $.noop, + item: function (suggestion) { + var element = document.createElement("li"); + element.textContent = suggestion.custom; + + return element; + }, + replace: $.noop, + suggestion: CustomSuggestion1 + }; + }); + + it("overrides simple default options", function () { + this.subject.evaluate(); + + this.subject._list.forEach(function (item, index) { + expect(this.subject.ul.children[index].textContent).toEqual(item.label.toUpperCase()); + }, this); + }); + }); + + describe("using a function to return different classes", function () { + def("options", function () { + return { + minChars: 0, + filter: function (item) { return item; }, + sort: $.noop, + item: function (suggestion) { + var element = document.createElement("li"); + element.textContent = suggestion.custom; + + return element; + }, + replace: $.noop, + suggestion: function (datum) { + if (datum.label === "Data") { + return new CustomSuggestion1(datum); + } else { + return new CustomSuggestion2(datum); + } + } + }; + }); + + it("overrides simple default options", function () { + this.subject.suggestion = this.subject.suggestion.bind(this.subject); + this.subject.evaluate(); + + this.subject._list.forEach(function (item, index) { + if (item.label === "Data") { + expect(this.subject.ul.children[index].textContent).toEqual(item.label.toUpperCase()); + } else { + expect(this.subject.ul.children[index].textContent).toEqual(item.label.toLowerCase()); + } + }, this); + }); + }); + }); });