Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Customizable Resultsbox Rows & Customizable Display Results in Input Box #3

Merged
merged 3 commits into from Apr 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 47 additions & 3 deletions README.md
Expand Up @@ -14,18 +14,30 @@ The simplest usage of the plugin is to simply call the plugin on your jQuery sel

## Options

`display` (type: `String`)
`display` (type: `String` or `Function`)

Defines which property of the supplied JSON data will be used as the displayed text.
Defines which property of the supplied JSON data will be used as the displayed text. If function is defined, the function is called during each row to generate the results box row. The function signature should be: `function (result, key) { .. }`.

`key` (type: `String`)
`displayValue` (type: `String` or `Function`)

Controls what data is displayed in the input box after a selection has been made from the results box. Can either be a string to define the key of the result data to display or a function with the signature `function (result, key) { .. }` where the return value will be the data inputted into the input box on selection.

`key` (type: `String` or `Function`)

Defines which property of the supplied JSON data will be used as the `value` parameter for the hidden `<select>` element.

`extraData` (type: `String` or `Function`)

Defines what data will be set to the `extraData` key in the selectBox/searchBox data. String will be the key while a function will utilize the same signature as display (`function (result, key) { .. }`). If extraData option is not set, the extraData field will be left undefined.

`resultsLimit` (type: `Integer`)

Defines the maximum number of results to display at a time.

`allowFreeInput` (type: `Boolean`)

Default false. Disregards everything mentioned in the usage section and does not replace the input element with a select element. This allows free form text that does not match a select element to be inputted. With `allowFreeInput` false, text inputted that does not match a selection would be discarded (field would be blank) on form submission.

`fuseOptions` (type: `Object`)

See the [Fuse.js github](https://github.com/krisk/Fuse) for full documentation.
Expand Down Expand Up @@ -109,3 +121,35 @@ $(document).ready(function(){
$("#itemPicker").fuzzyComplete(items, options);
});
```


#### Custom ResultsBox & Input Box Selection

You might want to format results in a special format or combine fields from the search results. You can pass a function as the display option to define custom html in the resultbox. You can use displayValue to select what value to display in the input text box.

##### Code

```javascript
var items = [
{"itemCode":"item3442","itemName":"Bag of doorknobs"},
{"itemCode":"item3446","itemName":"Blinker fluid"},
{"itemCode":"item3479","itemName":"Widgets"},
{"itemCode":"item3495","itemName":"Firefly class transport ship"},
{"itemCode":"item3400","itemName":"Perpetual motion machine"},
{"itemCode":"item3454","itemName":"Penrose triangle"}
];
var fuseOptions = { keys: ["itemName"] };
var displayFunction = function(result,id) {
return id + ". <b>" + result['itemName'] "</b> - " + result['itemCode'];
};
var options = {
display: displayFunction,
displayValue: "itemName",
key: "itemCode",
fuseOptions: fuseOptions
};

$(document).ready(function(){
$("#customResultsBoxPicker").fuzzyComplete(items, options);
});
```
4 changes: 2 additions & 2 deletions dist/js/fuzzycomplete.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 41 additions & 2 deletions example/examples.html
Expand Up @@ -130,6 +130,43 @@ <h3>Code</h3>
});
</pre>

<h2>Custom ResultsBox & Input Box Selection</h2>
<p>
You might want to format results in a special format or combine fields from the search results. You can pass a function as the display option to define custom html in the resultbox. You can use displayValue to select what value to display in the input text box.
</p>
<h3>Demo</h3>

<p>
Shop: <input type="text" id="customResultsBoxPicker" name="item">
<label for="companyValue">Output:</label> <span class="output"></span>
</p>

<h3>Code</h3>
<pre>
var items = [
{"itemCode":"item3442","itemName":"Bag of doorknobs"},
{"itemCode":"item3446","itemName":"Blinker fluid"},
{"itemCode":"item3479","itemName":"Widgets"},
{"itemCode":"item3495","itemName":"Firefly class transport ship"},
{"itemCode":"item3400","itemName":"Perpetual motion machine"},
{"itemCode":"item3454","itemName":"Penrose triangle"}
];
var fuseOptions = { keys: ["itemName"] };
var displayFunction = function(result,id) {
return id + ". &lt;b&gt;" + result['itemName'] "&lt;/b&gt; - " + result['itemCode'];
};
var options = {
display: displayFunction,
displayValue: "itemName",
key: "itemCode",
fuseOptions: fuseOptions
};

$(document).ready(function(){
$("#customResultsBoxPicker").fuzzyComplete(items, options);
});
</pre>

<script>
var companies = [
{"companyName":"Aperture Science"},
Expand Down Expand Up @@ -162,17 +199,19 @@ <h3>Code</h3>
var fuseOptions3 = { keys: ["itemName"] };
var options3 = { display: "itemName", key: "itemCode", fuseOptions: fuseOptions3 };

var options4 = { display: function(result,id) { return id + ". <b>" + result['itemName'] + "</b> - " + result['itemCode']; }, displayValue: "itemName",key: "itemCode", fuseOptions: fuseOptions3 };

$(document).ready(function(){
$("#companyPicker").fuzzyComplete(companies);
$("#airportPicker").fuzzyComplete(airports, options2);
$("#itemPicker").fuzzyComplete(items, options3);
$("#customResultsBoxPicker").fuzzyComplete(items, options4);

$('input').on('keyup blur', function() {
$(this).parent().find(".output").html($(this).parent().find("select").val());
});
});
</script>
</div>

</body>
</html>
</html>
81 changes: 60 additions & 21 deletions src/js/fuzzycomplete.js
Expand Up @@ -20,6 +20,7 @@
display: Object.keys(jsonData[0])[0],
key: Object.keys(jsonData[0])[0],
resultsLimit: 4,
allowFreeInput: false,
fuseOptions:
{
keys: Object.keys(jsonData[0])
Expand All @@ -31,9 +32,13 @@
var searchBox = $(this);
var resultsBox = $('<div>').addClass('fuzzyResults');
searchBox.after(resultsBox);
var selectBox = $('<select>').attr('name', searchBox.attr('name')).hide();
var selectBox = $('<select>').hide();

if (options.allowFreeInput !== true) {
selectBox.attr('name', searchBox.attr('name'));
searchBox.removeAttr('name');
}
searchBox.after(selectBox);
searchBox.removeAttr('name');

var pos = searchBox.position();
pos.left += parseInt(searchBox.css('marginLeft'), 10);
Expand All @@ -46,7 +51,10 @@

function selectCurrent() {
selectBox.val(resultsBox.children('.selected').first().data('id'));
searchBox.val(resultsBox.children('.selected').first().text());
searchBox.val(resultsBox.children('.selected').first().data('displayValue'));

selectBox.data('extraData', resultsBox.children('.selected').first().data('extraData'));
searchBox.data('extraData', resultsBox.children('.selected').first().data('extraData'));
}

searchBox.keydown(function(e) {
Expand Down Expand Up @@ -112,22 +120,41 @@
if(i === 0)
selectBox.val(result[options.key]);

resultsBox.append(
$('<div>')
.text(result[options.display])
.data('id', result[options.key])
.addClass('__autoitem')
.on('mousedown', function(e) {
e.preventDefault(); // This prevents the element from being hidden by .blur before it's clicked
})
.click(function() {
resultsBox.find('.selected').removeClass('selected');
$(this).addClass('selected');
selectCurrent();
resultsBox.hide();
})
);

var resultsRow = $('<div>').addClass('__autoitem')
.on('mousedown', function(e) {
e.preventDefault(); // This prevents the element from being hidden by .blur before it's clicked
})
.click(function() {
resultsBox.find('.selected').removeClass('selected');
$(this).addClass('selected');
selectCurrent();
resultsBox.hide();
});

if (typeof options.key === 'function') {
resultsRow.data('id',options.key(result,i));
} else {
resultsRow.data('id',result[options.key]);
}
if (typeof options.display === 'function') {
resultsRow.html( options.display(result, i) );
} else {
resultsRow.text(result[options.display]);
}
if (typeof options.displayValue === 'function') {
resultsRow.data('displayValue', options.displayValue(result, i));
} else if (typeof options.displayValue === 'string') {
resultsRow.data('displayValue', result[options.displayValue]);
} else {
resultsRow.data('displayValue', resultsRow.text());
}
if (typeof options.extraData === 'function') {
resultsRow.data('extraData', options.extraData(result, i));
} else if (typeof options.extraData === 'string') {
resultsRow.data('extraData', result[options.extraData]);
}

resultsBox.append(resultsRow);
});

if(resultsBox.children().length) {
Expand All @@ -154,9 +181,21 @@
}));

jsonData.forEach(function(entry, i) {
var value;
var text;
if (typeof options.key === 'function') {
value = options.key(entry,i);
} else {
value = entry[options.key];
}
if (typeof options.display === 'function') {
text = options.display(entry, i);
} else {
text = entry[options.display];
}
selectBox.append($('<option>', {
value: entry[options.key],
text: entry[options.display]
value: value,
text: text
}));

});
Expand Down