algolia/instantsearch: connectMenu refine() remove current refined value - algolia

Is there any way to REMOVE a refined value with connectMenu’s connector?
These are the things I tried that did not work:
passing an empty string refine('')
passing a null value refine(null)
passing a false value refine(false)
passing no parameter refine()
The reason why I’d like to do this is because otherwise currentRefinedValues widget shows an attribute as refined even if it’s not.
var customMenuRenderFn = function (renderParams, isFirstRendering) {
var container = renderParams.widgetParams.containerNode;
var title = renderParams.widgetParams.title || 'dropdownMenu';
var templates = renderParams.widgetParams.templates;
var hideIfIsUnselected = renderParams.widgetParams.hideIfIsUnselected || false;
var cssClasses = renderParams.widgetParams.cssClasses || "";
if (isFirstRendering)
{
$(container).append(
(templates.header || '<h1>' + renderParams.widgetParams.attributeName + '</h1>') +
'<select class="' + cssClasses.select + '">' +
'<option value="__EMPTY__">Tutto</option>' +
'</select>'
).hide();
var refine = renderParams.refine;
if (! hideIfIsUnselected)
{
$(container).show();
}
else
{
$(hideIfIsUnselected).find('select').on('items:loaded', function () {
if (isFirstRendering) {
var valueToCheck = $(hideIfIsUnselected).find('select').val();
$(container).toggle(valueToCheck !== '__EMPTY__');
$(container).find('select').off('items:loaded');
}
});
$(hideIfIsUnselected).find('select').on('change', function (event) {
var value = event.target.value === '__EMPTY__' ? '' : event.target.value;
if (value === '') {
refine();
}
$(container).toggle(value !== '');
});
}
$(container).find('select').on('change', function (event) {
var value = event.target.value === '__EMPTY__' ? '' : event.target.value;
refine(value);
});
}
function updateHits (hits)
{
var items = renderParams.items;
optionsHtml = ['<option class="' + cssClasses.item + '" value="__EMPTY__" selected>Tutto</option>']
.concat(
items.map(function (item) {
return `<option class="${cssClasses.item}" value="${item.value}" ${item.isRefined ? 'selected' : ''}>
${item.label} (${item.count})
</option>`;
})
);
$(container).find('select').html(optionsHtml);
$(container).find('select').trigger('items:loaded');
}
if (hideIfIsUnselected && $(hideIfIsUnselected).val() !== '__EMPTY__') {
updateHits(renderParams.items);
} else if (! hideIfIsUnselected) {
updateHits(renderParams.items);
}
}
var dropdownMenu = instantsearch.connectors.connectMenu(customMenuRenderFn);

The refine function actually toggles the value (setting it if not set, or unsetting if set). If you want to unselect any item in the menu, you need to find the currently selected value and use refine on it.
connectMenu(function render(params, isFirstRendering) {
var items = params.items;
var currentlySelectedItem = items.find(function isSelected(i) {
return i.isRefined;
});
params.refine(currentlySelectedItem);
});
This example won't solve your code completely, but it shows how to find the currently selected item and unselect it.

Related

Limit size of entered data in tinyMCE 5

I use tinyMCE 5 in my web site to enter data stored in a database. Therefore I need to limit the entered size, including format information, to the size of the data field. How can I prohibit the user to enter more then the allowed number of bytes, say 2000?
Best of all if I could add some information like "42/2000" on the status bar.
We had a similar requirement in our project (difference: the output should be <entered_chars>/<chars_left> instead of <entered_chars>/<max_chars>), and it ended up being a custom plugin, based on the wordcount plugin. There is some hacks in there, which could make it fail whenever tinyMCE changes, since there is no API for the statusbar in version 5 at this point of time.
But maybe you will still find it useful:
(function () {
'use strict';
var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
var maxChars = function (editor) {
return editor.getParam('number_max_chars', 3600);
};
var applyMaxChars = function (editor) {
return editor.getParam('restrict_to_max_chars', true);
};
var Settings = {
maxChars: maxChars,
applyMaxChars: applyMaxChars
};
var global$1 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker');
var getText = function (node, schema) {
var blockElements = schema.getBlockElements();
var shortEndedElements = schema.getShortEndedElements();
var isNewline = function (node) {
return blockElements[node.nodeName] || shortEndedElements[node.nodeName];
};
var textBlocks = [];
var txt = '';
var treeWalker = new global$1(node, node);
while (node = treeWalker.next()) {
if (node.nodeType === 3) {
txt += node.data;
} else if (isNewline(node) && txt.length) {
textBlocks.push(txt);
txt = '';
}
}
if (txt.length) {
textBlocks.push(txt);
}
return textBlocks;
};
var strLen = function (str) {
return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length;
};
var countCharacters = function (node, schema) {
var text = getText(node, schema).join('');
return strLen(text);
};
var createBodyCounter = function (editor, count) {
return function () {
return count(editor.getBody(), editor.schema);
};
};
var createMaxCount = function (editor) {
return function () {
return Settings.maxChars(editor);
}
}
var createRestrictToMaxCount = function (editor) {
return function () {
return Settings.applyMaxChars(editor);
}
}
var get = function (editor) {
return {
getCount: createBodyCounter(editor, countCharacters),
getMaxCount: createMaxCount(editor),
getRestrictToMaxCount: createRestrictToMaxCount(editor)
};
};
var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay');
function isAllowedKeycode(event) {
// allow arrow keys, backspace and delete
const key = event.keyCode;
return key === 37 || key === 38 || key === 39 || key === 40 || key === 8
|| key === 46;
}
var updateCount = function (editor, api) {
editor.getContainer().getElementsByClassName(
'tox-statusbar__text-container')[0].textContent = String(
api.getCount()) + " / " + String(
Settings.maxChars(editor) - api.getCount());
};
var setup = function (editor, api, delay) {
var debouncedUpdate = global$2.debounce(function () {
return updateCount(editor, api);
}, delay);
editor.on('init', function () {
updateCount(editor, api);
global$2.setEditorTimeout(editor, function () {
editor.on('SetContent BeforeAddUndo Undo Redo keyup', debouncedUpdate);
editor.on('SetContent BeforeAddUndo Undo Redo keydown', function (e) {
if (!isAllowedKeycode(e) && Settings.applyMaxChars(editor) &&
api.getCount() >= Settings.maxChars(editor)) {
e.preventDefault();
e.stopPropagation();
}
});
}, 0);
});
};
function Plugin(delay) {
if (delay === void 0) {
delay = 300;
}
global.add('charactercount', function (editor) {
var api = get(editor);
setup(editor, api, delay);
return api;
});
}
Plugin();
}());
Currently I'm working on a preprocessor for the paste plugin, so that the max_length effects also pasted text. That's why you see the charactercount API in the code.

Problem inserting checkbox in select using DataTables

I'm looking for a way to insert a checkbox into a select and fetch each column individually, all using DataTables. I found an excellent example in https://jsfiddle.net/Lxytynm3/2/ but for some reason, when selecting all records, filtering does not display the data as expected. Would anyone have a solution to work properly?
Thanks in advance.
The link application code is as follows:
$(document).ready(function() {
function cbDropdown(column) {
return $('<ul>', {
'class': 'cb-dropdown'
}).appendTo($('<div>', {
'class': 'cb-dropdown-wrap'
}).appendTo(column));
}
$('#example').DataTable({
initComplete: function() {
this.api().columns().every(function() {
var column = this;
var ddmenu = cbDropdown($(column.header()))
// -------------------------------------------------------
.on('change', ':checkbox', function() {
var active;
var vals = $(':checked', ddmenu).map(function(index, element) {
active = true;
return $.fn.dataTable.util.escapeRegex($(element).val());
}).toArray().join('|');
column
.search(vals.length > 0 ? '^(' + vals + ')$' : '', true, false)
.draw();
// -------------------------------------------------------
// Highlight the current item if selected.
if (this.checked) {
$(this).closest('li').addClass('active');
// If 'Select all / none' clicked ON
if ($(this).val() === "1") {
$(ddmenu).find('input[type="checkbox"]').prop('checked', this.checked)
//$(".cb-dropdown li").prop('checked', true);
//$('.cb-dropdown').closest('li').find('input[type="checkbox"]').prop('checked', true);
// $('this input[type="checkbox"]').prop('checked', true); works!
// $( 'input[type="checkbox"]' ).prop('checked', this.checked);
// $(this).find('input[type="checkbox"]').prop('checked', this.checked)
//$('div.cb-dropdown-wrap.active').children().find('input[type="checkbox"]').prop('checked', this.checked)
}
} else // 'Select all / none' clicked OFF
{
$(this).closest('li').removeClass('active');
// test if select none
if ($(this).val() === "1") {
// code to untick all
$(ddmenu).find('input[type="checkbox"]').prop('checked', false)
}
}
// Highlight the current filter if selected.
var active2 = ddmenu.parent().is('.active');
if (active && !active2) {
ddmenu.parent().addClass('active');
// Change Container title to "Filter on" and green
//$(this).parent().find('.cb-dropdown li:nth-child(n+1)').css('color','red');
$('active2 li label:contains("Filter OFF")').text('Yeees');
} else if (!active && active2) {
ddmenu.parent().removeClass('active');
}
});
// -------------------------------------------------------
var mytopcount = '0'; // Counter that ensures only 1 entry per container
// loop to assign all options in container filter
column.data().unique().sort().each(function(d, j) {
// Label
var $label = $('<label>'),
$text = $('<span>', {
text: d
}),
// Checkbox
$cb = $('<input>', {
type: 'checkbox',
value: d
});
$text.appendTo($label);
$cb.appendTo($label);
ddmenu.append($('<li>').append($label));
// -----------------
// Add 'Select all / none' to each dropdown container
if (mytopcount == '0') // Counter that ensures only 1 entry per container
{
$label = $('<label>'), $text = $('<span>', {
text: "Select all / none"
}),
$cb = $('<input>', {
type: 'checkbox',
value: 1
});
$text.prependTo($label).css('margin-bottom', '6px');
$cb.prependTo($label);
ddmenu.prepend($('<li>').prepend($label).css({
'border-bottom': '1px solid grey',
'margin-bottom': '6px'
}));
mytopcount = '1' // This stops this section running again in cotainer
}
});
});
}
});
});
It seems as though the issue was with the select all checkbox. One solution would be to check for "1" within the vals initialisation, this seems to work:
var vals = $(':checked', ddmenu).map(function(index, element) {
if($(element).val() !== "1"){
return $.fn.dataTable.util.escapeRegex($(element).val());
}
}).toArray().join('|');
That should see you with some results upon the top checkbox being checked. Hope that helps.

How to customise the ghost-text (drag item name) with AgGrid

As per title, is there a way to customise the "ghost text" with the (unmanaged) row-dragging implementation in AgGrid via the API?
I found workaround using valueGetter property to change this text.
Example configuration of column:
private dragDropColumn= {
rowDrag: true,
...
valueGetter: (params) => {
return params.data.myVariableFromRow;
}
}
Hope this helps
You can now use colDef.rowDragText to set a callback function to set the dragged text.
https://www.ag-grid.com/javascript-grid-row-dragging/#custom-row-drag-text
onRowDragEnter event,
you could search for the ghost element
and then append your custom class to it.
document.querySelectorAll('.ag-dnd-ghost')[0]
.classlist.add('my-custom-ghost-element');
Dont forget to follow the hierarchy of classes, otherwise you would end up using !important in the custom class :-)
// For updating text
search for the element with className ag-dnd-ghost-label
document.querySelectorAll('.ag-dnd-ghost-label')[0]
.innerHTML = 'your_custom_text';
Ghost element is added only during drag, once drag is ended, its removed from dom by Ag-Grid.
Hope this helps
I've researched this and there is nothing built in to ag-grid. I accomplished this by attaching to the onRowDragMove and onRowDragMove events.
I set a class variable 'isRowDragging' to only do this once while dragging.
I use the Angular Renderer2 class (this.ui) to find and update the Element of the ghost label.
All of this is available with vanilla javascript or other supported ag-grid frameworks.
this.gridOptions.onRowDragMove = (params: RowDragMoveEvent) => {
const overNode = params.overNode;
const movingNode = params.node;
if (!this.isRowDragging) {
this.isRowDragging = true;
if (!movingNode.isSelected()) {
if (params.event && params.event.ctrlKey) {
movingNode.setSelected(true);
}
if (params.event && !params.event.ctrlKey) {
movingNode.setSelected(true, true);
}
}
let labelText: string = '';
const selectedNodes = this.gridOptions.api.getSelectedNodes();
if (selectedNodes.length === 1) {
labelText = selectedNodes[0].data.Name;
}
else {
const guids: string[] = [];
let folderCount: number = 0;
let docCount: number = 0;
selectedNodes.forEach((node: RowNode) => {
guids.push((node.data.FolderGuid || node.data.DocumentGuid).toLowerCase());
if (node.data.FolderGuid !== undefined) {
folderCount++;
}
else {
docCount++;
}
});
if (folderCount === 1) {
labelText = '1 folder';
}
else if (folderCount > 1) {
labelText = folderCount + ' folders';
}
if (docCount === 1) {
labelText += (labelText !== '' ? ', ' : '') + '1 document';
}
else if (docCount > 1) {
labelText += (labelText !== '' ? ', ' : '') + docCount + ' documents';
}
}
console.log(this.ui.find(document.body, '.ag-dnd-ghost').outerHTML);
this.ui.find(document.body, '.ag-dnd-ghost-label').innerHTML = labelText;
}
}
this.gridOptions.onRowDragEnd = (event: RowDragEndEvent) => {
this.isRowDragging = false;
}
I am using ag-grid with react and using cellRendererFramework property of ColDef to use custom react component, my value getter returns object, so when I start dragging I am getting [object object], I added toString method to returning object and did the trick, below is my sample code
const col1 = {
rowDrag: true,
...
valueGetter: (params) => {
const {id, name} = params.data;
return {id, name, toString: () => name}; // so when dragging it will display name property
}
}

jquery.jeditable.ajaxupload.js how to send file?

maybe somebody can to explain me why I can't send file, maybe needed additional script or something els?
/*
* Ajaxupload for Jeditable
*
* Copyright (c) 2008-2009 Mika Tuupola
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Depends on Ajax fileupload jQuery plugin by PHPLetter guys:
* http://www.phpletter.com/Our-Projects/AjaxFileUpload/
*
* Project home:
* http://www.appelsiini.net/projects/jeditable
*
* Revision: $Id$
*
*/
$.editable.addInputType('ajaxupload', {
/* create input element */
element : function(settings) {
settings.onblur = 'ignore';
var input = $('<input type="file" id="upload" name="upload" />');
$(this).append(input);
return(input);
},
content : function(string, settings, original) {
/* do nothing */
},
plugin : function(settings, original) {
var form = this;
form.attr("enctype", "multipart/form-data");
$("button:submit", form).bind('click', function() {
//$(".message").show();
// Modification to include original id and submitdata in target's querystring
var queryString;
if ($.isFunction(settings.submitdata)) {
queryString = jQuery.param(settings.submitdata.apply(self, [self.revert, settings]));
} else {
queryString = jQuery.param(settings.submitdata);
}
if (settings.target.indexOf('?') < 0) {
queryString = '?' + settings.id + '=' + $(original).attr('id') + '&' + queryString;
} else {
queryString = '&' + settings.id + '=' + $(original).attr('id') + '&' + queryString;
}
settings.target += queryString;
// End modification
$.ajaxFileUpload({
url: settings.target,
secureuri:false,
// Add the following line
data : settings.submitdata,
fileElementId: 'upload',
dataType: 'html',
success: function (data, status) {
$(original).html(data);
original.editing = false;
},
error: function (data, status, e) {
alert(e);
}
});
return(false);
});
}
});
$(\".ajaxupload\").editable('/?action=upload_profile_photo', {
indicator : '<i class=\"fa fa-spinner fa-pulse\"></i>',
type : 'ajaxupload',
submit : 'Upload',
cancel : 'Cancel',
tooltip : \"Click to upload...\"
});
<p class=\"ajaxupload\" id=\"profile_photo\"><img class=\"img-thumbnail img-responsive\" src=\"http://www.in-elite.com/?action=no_image_text\" alt=\"\"></p>
how result its passed only
print_r($._GET)Array ( [action] => upload_profile_photo [id] =>
profile_photo ) print_r($._POST)Array ( [value] => 20150501_153530.jpg
[id] => profile_photo )
And question so, How to send file?
Ux I found the problem ;-)
I'm forgot to add one js file called jquery.ajaxfileupload.js
<script type=\"text/javascript\" src=\"/includes/JS/jquery.ajaxfileupload.js\" charset=\"utf-8\"></script>
And content of this jquery.ajaxfileupload.js file is
jQuery.extend({
createUploadIframe: function(id, uri)
{
//create frame
var frameId = 'jUploadFrame' + id;
if(window.ActiveXObject) {
var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
if(typeof uri== 'boolean'){
io.src = 'javascript:false';
}
else if(typeof uri== 'string'){
io.src = uri;
}
}
else {
var io = document.createElement('iframe');
io.id = frameId;
io.name = frameId;
}
io.style.position = 'absolute';
io.style.top = '-1000px';
io.style.left = '-1000px';
document.body.appendChild(io);
return io
},
createUploadForm: function(id, fileElementId)
{
//create form
var formId = 'jUploadForm' + id;
var fileId = 'jUploadFile' + id;
var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
var oldElement = $('#' + fileElementId);
var newElement = $(oldElement).clone();
$(oldElement).attr('id', fileId);
$(oldElement).before(newElement);
$(oldElement).appendTo(form);
//set attributes
$(form).css('position', 'absolute');
$(form).css('top', '-1200px');
$(form).css('left', '-1200px');
$(form).appendTo('body');
return form;
},
ajaxFileUpload: function(s) {
// TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
s = jQuery.extend({}, jQuery.ajaxSettings, s);
var id = new Date().getTime()
var form = jQuery.createUploadForm(id, s.fileElementId);
var io = jQuery.createUploadIframe(id, s.secureuri);
var frameId = 'jUploadFrame' + id;
var formId = 'jUploadForm' + id;
// Watch for a new set of requests
if ( s.global && ! jQuery.active++ )
{
jQuery.event.trigger( "ajaxStart" );
}
var requestDone = false;
// Create the request object
var xml = {}
if ( s.global )
jQuery.event.trigger("ajaxSend", [xml, s]);
// Wait for a response to come back
var uploadCallback = function(isTimeout)
{
var io = document.getElementById(frameId);
try
{
if(io.contentWindow)
{
xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
}else if(io.contentDocument)
{
xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
}
}catch(e)
{
jQuery.handleError(s, xml, null, e);
}
if ( xml || isTimeout == "timeout")
{
requestDone = true;
var status;
try {
status = isTimeout != "timeout" ? "success" : "error";
// Make sure that the request was successful or notmodified
if ( status != "error" )
{
// process the data (runs the xml through httpData regardless of callback)
var data = jQuery.uploadHttpData( xml, s.dataType );
// If a local callback was specified, fire it and pass it the data
if ( s.success )
s.success( data, status );
// Fire the global callback
if( s.global )
jQuery.event.trigger( "ajaxSuccess", [xml, s] );
} else
jQuery.handleError(s, xml, status);
} catch(e)
{
status = "error";
jQuery.handleError(s, xml, status, e);
}
// The request was completed
if( s.global )
jQuery.event.trigger( "ajaxComplete", [xml, s] );
// Handle the global AJAX counter
if ( s.global && ! --jQuery.active )
jQuery.event.trigger( "ajaxStop" );
// Process result
if ( s.complete )
s.complete(xml, status);
jQuery(io).unbind()
setTimeout(function()
{ try
{
$(io).remove();
$(form).remove();
} catch(e)
{
jQuery.handleError(s, xml, null, e);
}
}, 100)
xml = null
}
}
// Timeout checker
if ( s.timeout > 0 )
{
setTimeout(function(){
// Check to see if the request is still happening
if( !requestDone ) uploadCallback( "timeout" );
}, s.timeout);
}
try
{
// var io = $('#' + frameId);
var form = $('#' + formId);
$(form).attr('action', s.url);
$(form).attr('method', 'POST');
$(form).attr('target', frameId);
if(form.encoding)
{
form.encoding = 'multipart/form-data';
}
else
{
form.enctype = 'multipart/form-data';
}
$(form).submit();
} catch(e)
{
jQuery.handleError(s, xml, null, e);
}
if(window.attachEvent){
document.getElementById(frameId).attachEvent('onload', uploadCallback);
}
else{
document.getElementById(frameId).addEventListener('load', uploadCallback, false);
}
return {abort: function () {}};
},
uploadHttpData: function( r, type ) {
var data = !type;
data = type == "xml" || data ? r.responseXML : r.responseText;
// If the type is "script", eval it in global context
if ( type == "script" )
jQuery.globalEval( data );
// Get the JavaScript object, if JSON is used.
if ( type == "json" )
eval( "data = " + data );
// evaluate scripts within html
if ( type == "html" )
jQuery("<div>").html(data);
//jQuery("<div>").html(data).evalScripts();
//alert($('param', data).each(function(){alert($(this).attr('value'));}));
return data;
}
})
Now everything ok and file are uploaded successfully.... Just needed to modified php script for which type of the data you need to upload

Start search after 2 character typed in Chosen drop down

In Chosen drop down plugin, a search is started after 2 characters are typed in chosen drop down.
I need the search to not start until after inputing at least two characters in the search box.
Can any one suggest how to do this?
I did a small change to start to search after the third character, is not the best option but works, in the chosen JS in the AbstractChosen.prototype.winnow_results function after the line searchText = this.get_search_text(); add the following code: if (searchText != "" && searchText.length < 3) return;. Remember to change the < 3 by your own size.
Hope this help you
See part of the code below:
AbstractChosen.prototype.winnow_results = function() {
var escapedSearchText, option, regex, regexAnchor, results, results_group, searchText, startpos, text, zregex, _i, _len, _ref;
this.no_results_clear();
results = 0;
searchText = this.get_search_text();
if (searchText != "" && searchText.length < 3) return;
escapedSearchText = searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
I know this post it's old but i had to face this problem just now and wanted to share my result. I wrapped everything in a function extendedSearch and set it as a callback while chosen is emitting the chosen:showing_dropdown event.
My problem was that i need the search to show the results after the 2nd character typed in search and must filter out certain strings from the results.
Bellow you'll find a demo which shows results on the 3rd character typed in, and will keep visible only those results that end with letter "E".
$(function() {
/**
* By default the results are hidden when clicking a dropdown.
* {
* toggleResults: false, // a function(searchValue) that returns a boolean
* filterResults: false, // a function(dropDownValue, selectValue) that returns a boolean
* }
* #param options
*/
const extendedSearch = (options = {}) => {
const defaultOptions = {
toggleResults: false,
filterResults: false,
};
options = { ...{},
...defaultOptions,
...options
};
/**
* Main element
*/
return (evt, params) => {
let originalElement = $(evt.currentTarget);
let searchInput = params.chosen.search_field;
const customSearch = (options = {}) => {
let defaultOptions = {
originalElement: null,
searchInput: null
};
options = { ...{},
...defaultOptions,
...options
};
if (!(options.originalElement instanceof jQuery) || !options.originalElement) {
throw new Error('Custom Search: originalElement is invalid.');
}
if (!(options.searchInput instanceof jQuery) || !options.searchInput) {
throw new Error('Custom Search: searchInput is invalid.');
}
let res = options.searchInput
.parent()
.next('.chosen-results');
res.hide();
if (typeof options.toggleResults !== 'function') {
options.toggleResults = (value) => true;
}
if (options.filterResults && typeof options.filterResults !== 'function') {
options.filterResults = (shownText = '', selectValue = '') => true;
}
/**
* Search Input Element
*/
return (e) => {
let elem = $(e.currentTarget);
let value = elem.val() || '';
if (value.length && options.toggleResults(value) === true) {
res.show();
if (options.filterResults) {
let children = res.children();
let active = 0;
$.each(children, (idx, item) => {
let elItem = $(item);
let elemIdx = elItem.attr('data-option-array-index');
let shownText = elItem.text();
let selectValue = options.originalElement.find('option:eq(' + elemIdx + ')').attr('value') || '';
if (options.filterResults(shownText, selectValue) === true) {
active++;
elItem.show();
} else {
active--;
elItem.hide();
}
});
if (active >= 0) {
res.show();
} else {
res.hide();
}
}
} else {
res.hide();
}
};
};
options = {
...{},
...options,
...{
originalElement,
searchInput
}
};
let searchInstance = customSearch(options);
searchInput
.off('keyup', searchInstance)
.on('keyup', searchInstance)
}
};
/** This is the final code */
const inputValidator = (value) => {
console.log('input', value);
return $.trim(value).length > 2;
};
const textResultsValidator = (dropDownValue, selectValue) => {
if ($.trim(dropDownValue).substr(-1, 1) === 'E') {
console.log('results shown', dropDownValue, '|', selectValue);
return true;
}
return false;
};
$(".chosen-select")
.chosen()
.on('chosen:showing_dropdown', extendedSearch({
toggleResults: inputValidator,
filterResults: textResultsValidator
}));
});
#import url("https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.min.css")
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.jquery.min.js"></script>
<select class="chosen-select">
<option value="">Pick something</option>
<option value="APPLE">APPLE</option>
<option value="APPLE JUICE">APPLE JUICE</option>
<option value="BANANA">BANANA</option>
<option value="ANANAS">ANANAS</option>
<option value="ORANGE">ORANGE</option>
<option value="ORANGES">ORANGES</option>
<option value="STRAWBERRY">STRAYBERRY</option>
</select>