Ajax AutoComplete for jQuery "onEmpty"-type of event - autocomplete

I'm using Ajax Autocomplete for Jquery (https://www.devbridge.com/sourcery/components/jquery-autocomplete/) with DataTables to search on a specific column.
Using onSearchComplete and onSelect from Autocomplete I can filter both the input and the table together as the user is typing (onSearchComplete) and when they select an entry (onSelect):
$("#scoreboard_site_name_filter").autocomplete({
serviceUrl: "/wiki/extensions/CFBHA/models/_mSiteNames.php",
onSearchComplete: function(suggestion) {
update_scoreboard_by_site_name_filter(suggestion);
},
onSelect: function(suggestion) {
update_scoreboard_by_site_name_filter(suggestion);
}
});
function update_scoreboard_by_site_name_filter(suggestion) {
var colname = "site_name:name";
if (scoreboard.column(colname).search() !== suggestion) {
scoreboard.column(colname).search(suggestion).draw();
}
};
However, when the input is deleted, then the DataTable is left filtered on the last input because neither event is fired in that case.
I've tried the keyup and change events on the input itself to pass an empty string to the DataTable search:
$("#scoreboard_site_name_filter").on("keyup change", function() {
var suggestion = "";
update_scoreboard_by_site_name_filter(suggestion);
});
If I place it before the autocomplete then it has no affect and if I place it after then of course I lose the ability to filter the table as I type because it fires after the autocomplete.
How can I detect when the input has been deleted and then re-filter the table on an empty string (i.e., clear that filter)?

OK, I was overthinking it . . .
I removed the onSearchComplete event and just went with the input event on the input itself and everything is working great.
I left the onSelect for the Autocomplete and am now properly passing suggestion.value instead of suggestion.
Here's the proper code for anyone interested:
$("#scoreboard_site_name_filter").on("keyup change", function() {
update_scoreboard_by_site_name_filter(this.value);
});
$("#scoreboard_site_name_filter").autocomplete({
serviceUrl: "/wiki/extensions/CFBHA/models/_mSiteNames.php",
onSelect: function(suggestion) {
update_scoreboard_by_site_name_filter(suggestion.value);
}
});
function update_scoreboard_by_site_name_filter(suggestion) {
var colname = "site_name:name";
if (scoreboard.column(colname).search() !== suggestion) {
scoreboard.column(colname).search(suggestion).draw();
}
};
Additionally I updated the code to make the search regex if the suggestion is actually selected (clicked on or entered on) and to add a class to the input as an indicator that the table is now filtered on that exact search term:
$("#scoreboard_site_name_filter").on("input", function() {
update_scoreboard_by_site_name_filter(this.value, false);
});
$("#scoreboard_site_name_filter").autocomplete({
serviceUrl: "/wiki/extensions/CFBHA/models/_mSiteNames.php",
onSelect: function(suggestion) {
update_scoreboard_by_site_name_filter(suggestion.value, true);
}
});
function update_scoreboard_by_site_name_filter(suggestion, selected) {
var colname = "site_name:name";
if (!selected) {
scoreboard.column(colname).search(suggestion).draw();
$("#scoreboard_site_name_filter").removeClass("autocomplete-input-selected");
} else {
scoreboard.column(colname).search("^" + suggestion + "$", true, false).draw();
$("#scoreboard_site_name_filter").addClass("autocomplete-input-selected");
};
};

Related

In SAPUI5 SmartTable on event beforeRebindTable adding some filters

My requiremnt is to put some filters on smartTable form my controller.
In Event beforeRebindTable i am using the following code to put filter using this code which is working fine.
onBeforeRebindTable: function (oEvent) {
var oBindingParams = oEvent.getParameter("bindingParams");
statFilter = new sap.ui.model.Filter("Claim_TYPE", "EQ", "1234");
oBindingParams.filters.push(statFilter);
}
But the problem is when the user is clicling on table column on filter again, the filter i am adding in above code is not visible in the selection dialog. User may need to delete this filter, If its not visible in dialog they wont be able to delete it.
I am not able to establish the link why the dialog is not getting updated, or should i add this somewhere else.
Thanks
Sonal.
onBeforeRebindTable: function (oEvent) {
var oSmartTable = oEvent.getSource();
if (this._isOnInit == null) this._isOnInit = true;
if (this._isOnInit) {
oSmartTable.applyVariant(
{
filter: {
filterItems: [{
columnKey: "YourSelectedColumn",
exclude: false,
operation: "EQ",
value1: "SomeEnteredValue",
value2: ""
}]
}
}
);
this._isOnInit = false;
}
}

ComboBox with entered text filtering - SAP UI5

I have had a select control where I could select from user names. Now I want to convert that select into combo box so I can give the user ability to enter text as well. The values populated in the combo box are in text property as {FirstName}, {LastName}. I do not want to use additional text as it shows at end of the row wih lot of space in between. My issue with Combo box is :
Values get populated but how do I filter? There is already some logic that is written on change method. I want to do custom filtering on the values. For example: If I write "P" it should show all the values that have P in the text (First name and last name). Where to write filter function? Also I found custom filtering code in demokit, I want to use it - but when I use it in inti method under delegate, I get error - this.get....setfilterfunction().. is not a function
View.xml
<ComboBox items= "{path:'items>/name'}" id="A"
selectedKey="{item>/Header/Name}" change="nameSelected">
<core:ListItem key="{order>NameID}" text="{order>LastName} ,{order>FirstName}"/>
</ComboBox>
Controller.js
_initializeData: function () {
var name = this.getView().byId("A");
name.addEventDelegate({
onAfterRendering: function() {
this.getView().byId("A").setFilterFunction(function(sTerm, oItem) {
return oItem.getText().match(new RegExp(sTerm, "i")) ||
oItem.getKey().match(new RegExp(sTerm, "i"));
});
}
},
nameSelected: function () {
......some logic processing..
}
You have to bind this in your function. I guess.
Can you access this.getView().byId("A") , when you put a break point in the onAfterRendering part ?
Try this solution: You are not working in the right scope.
_initializeData: function () {
var name = this.getView().byId("A");
name.addEventDelegate({
onAfterRendering: this.setFilter.bind(this) });
},
setFilter: function() {
this.getView().byId("A").setFilterFunction(function(sTerm, oItem) {
return oItem.getText().match(new RegExp(sTerm, "i")) ||
oItem.getKey().match(new RegExp(sTerm, "i"));
});
},

Store the user searchword in mysql

I working on a little snippet, a live search with MySQL.
Now i think it could be nice to store/save which searchword the user, did the search on.
Example:
User search on
My new book
Then i want to store that to my databse.
The problem is with my script right now, where i trig the ajax on keyup. Then it will store.
M My My N My Ne My New .... and so on..
and so on, how can i come around this and only store the hole line ..?
$(function() {
$("#searchword").keyup(function(){
var text = $(this).val();
if (text != ' ') {
$('#result').html(" ");
$.ajax({
type: 'post',
url: 'livesearch.php',
data: { 'search': text },
success: function(dataReturn) {
$('#result').html(dataReturn);
}
});
}
});
});
I've created a storeText(txt,time) function that will take your text as first param and time to wait before sending ajax as second param. You can change the second parameter as per your need. Add your ajax call in the function below my comment and you're good to go.
$(function() {
$("#searchword").keyup(function(){
var text = $(this).val();
if (text != ' ') {
//THIS IS WHERE YOU CAN MODIFY THE TIME
storeText(text,1000);
$('#result').html(" ");
$.ajax({
type: 'post',
url: 'livesearch.php',
data: { 'search': text },
success: function(dataReturn) {
$('#result').html(dataReturn);
}
});
}
});
});
var timer;
function storeText(txt,time){
clearTimeout(timer);
timer = setTimeout(function(){
//ADD YOUR SAVE QUERY AJAX HERE
},time);
}
Here's a JSFiddle to see it in action: https://jsfiddle.net/3n2L2v6g/
Try typing anything in the text box, it waits 1000ms before executing the code where your ajax would be.

kendo-ui autocomplete extend

I'm trying to extend the kendo-ui autocomplete control: I want the search start when te user hit enter, so basically I've to check the user input on keydown event.
I've tried to catch the keydown event with this code:
(function($) {
ui = kendo.ui,
Widget = ui.Widget
var ClienteText = ui.AutoComplete.extend({
init: function(element,options) {
var that=this;
ui.AutoComplete.fn.init.call(this, element, options);
$(this).bind('keydown',function(e){ console.log(1,e); });
$(element).bind('keydown',function(e){ console.log(2,e); });
},
options: {
[...list of my options...]
},
_keydown: function(e) {
console.log(3,e);
kendo.ui.AutoComplete.fn._keydown(e);
}
});
ui.plugin(ClienteText);
})(jQuery);
None of the binded events gets called, only the _keydown, and then I'm doing something wrong and cannot call the autocomplete "normal" keydown event.
I've seen a lot of examples that extend the base widget and then create a composite widget, but I'm not interested in doing that, I only want to add a functionality to an existing widget.
Can someone show me what I'm doing wrong?
Thank you!
What about avoiding the extend and take advantage of build in options and methods on the existing control : http://jsfiddle.net/vojtiik/Vttyq/1/
//create AutoComplete UI component
var complete = $("#countries").kendoAutoComplete({
dataSource: data,
filter: "startswith",
placeholder: "Select country...",
separator: ", ",
minLength: 50 // this is to be longer than your longest char
}).data("kendoAutoComplete");
$("#countries").keypress(function (e) {
if (e.which == 13) {
complete.options.minLength = 1; // allow search
complete.search($("#countries").val());
complete.options.minLength = 50; // stop the search again
}
});
This code actually work:
(function($) {
ui = kendo.ui,
ClienteText = ui.AutoComplete.extend({
init: function(element,options) {
ui.AutoComplete.fn.init.call(this, element, options);
$(element).bind('keydown',function(e){
var kcontrol=$(this).data('kendoClienteText');
if (e.which === 13) {
kcontrol.setDataSource(datasource_clientes);
kcontrol.search($(this).val());
} else {
kcontrol.setDataSource(null);
}
});
},
options: {
name: 'ClienteText',
}
});
ui.plugin(ClienteText);
})(jQuery);
but I don't know if it's the correct way to do it.

Handle selected event in autocomplete textbox using bootstrap Typeahead?

I want to run JavaScript function just after user select a value using autocomplete textbox bootstrap Typeahead.
I'm searching for something like selected event.
$('.typeahead').on('typeahead:selected', function(evt, item) {
// do what you want with the item here
})
$('.typeahead').typeahead({
updater: function(item) {
// do what you want with the item here
return item;
}
})
For an explanation of the way typeahead works for what you want to do here, taking the following code example:
HTML input field:
<input type="text" id="my-input-field" value="" />
JavaScript code block:
$('#my-input-field').typeahead({
source: function (query, process) {
return $.get('json-page.json', { query: query }, function (data) {
return process(data.options);
});
},
updater: function(item) {
myOwnFunction(item);
var $fld = $('#my-input-field');
return item;
}
})
Explanation:
Your input field is set as a typeahead field with the first line: $('#my-input-field').typeahead(
When text is entered, it fires the source: option to fetch the JSON list and display it to the user.
If a user clicks an item (or selects it with the cursor keys and enter), it then runs the updater: option. Note that it hasn't yet updated the text field with the selected value.
You can grab the selected item using the item variable and do what you want with it, e.g. myOwnFunction(item).
I've included an example of creating a reference to the input field itself $fld, in case you want to do something with it. Note that you can't reference the field using $(this).
You must then include the line return item; within the updater: option so the input field is actually updated with the item variable.
first time i've posted an answer on here (plenty of times I've found an answer here though), so here's my contribution, hope it helps. You should be able to detect a change - try this:
function bob(result) {
alert('hi bob, you typed: '+ result);
}
$('#myTypeAhead').change(function(){
var result = $(this).val()
//call your function here
bob(result);
});
According to their documentation, the proper way of handling selected event is by using this event handler:
$('#selector').on('typeahead:select', function(evt, item) {
console.log(evt)
console.log(item)
// Your Code Here
})
What worked for me is below:
$('#someinput').typeahead({
source: ['test1', 'test2'],
afterSelect: function (item) {
// do what is needed with item
//and then, for example ,focus on some other control
$("#someelementID").focus();
}
});
I created an extension that includes that feature.
https://github.com/tcrosen/twitter-bootstrap-typeahead
source: function (query, process) {
return $.get(
url,
{ query: query },
function (data) {
limit: 10,
data = $.parseJSON(data);
return process(data);
}
);
},
afterSelect: function(item) {
$("#divId").val(item.id);
$("#divId").val(item.name);
}
Fully working example with some tricks. Assuming you are searching for trademarks and you want to get the selected trademark Id.
In your view MVC,
#Html.TextBoxFor(model => model.TrademarkName, new { id = "txtTrademarkName", #class = "form-control",
autocomplete = "off", dataprovide = "typeahead" })
#Html.HiddenFor(model => model.TrademarkId, new { id = "hdnTrademarkId" })
Html
<input type="text" id="txtTrademarkName" autocomplete="off" dataprovide="typeahead" class="form-control" value="" maxlength="100" />
<input type="hidden" id="hdnTrademarkId" />
In your JQuery,
$(document).ready(function () {
var trademarksHashMap = {};
var lastTrademarkNameChosen = "";
$("#txtTrademarkName").typeahead({
source: function (queryValue, process) {
// Although you receive queryValue,
// but the value is not accurate in case of cutting (Ctrl + X) the text from the text box.
// So, get the value from the input itself.
queryValue = $("#txtTrademarkName").val();
queryValue = queryValue.trim();// Trim to ignore spaces.
// If no text is entered, set the hidden value of TrademarkId to null and return.
if (queryValue.length === 0) {
$("#hdnTrademarkId").val(null);
return 0;
}
// If the entered text is the last chosen text, no need to search again.
if (lastTrademarkNameChosen === queryValue) {
return 0;
}
// Set the trademarkId to null as the entered text, doesn't match anything.
$("#hdnTrademarkId").val(null);
var url = "/areaname/controllername/SearchTrademarks";
var params = { trademarkName: queryValue };
// Your get method should return a limited set (for example: 10 records) that starts with {{queryValue}}.
// Return a list (of length 10) of object {id, text}.
return $.get(url, params, function (data) {
// Keeps the current displayed items in popup.
var trademarks = [];
// Loop through and push to the array.
$.each(data, function (i, item) {
var itemToDisplay = item.text;
trademarksHashMap[itemToDisplay] = item;
trademarks.push(itemToDisplay);
});
// Process the details and the popup will be shown with the limited set of data returned.
process(trademarks);
});
},
updater: function (itemToDisplay) {
// The user selectes a value using the mouse, now get the trademark id by the selected text.
var selectedTrademarkId = parseInt(trademarksHashMap[itemToDisplay].value);
$("#hdnTrademarkId").val(selectedTrademarkId);
// Save the last chosen text to prevent searching if the text not changed.
lastTrademarkNameChosen = itemToDisplay;
// return the text to be displayed inside the textbox.
return itemToDisplay;
}
});
});