I'm trying to use jquery to to create a live filter to hide divs on realtime text input. So far I have the following:
<input type="text" class="form-control" id="filter" name="filter" class="filter">
<div class="media">
<div class="media-body>
<h4>Apples</h4>
...
</div>
</div>
<div class="media">
<div class="media-body>
<h4>Oranges</h4>
...
</div>
</div>
<script>
$('#filter').keyup(function () {
var filter = $("#filter").val();
$('.media').each(function(i, obj) {
if ($('this > .media-body > h4:contains(filter)').length === 0) {
$(this).css("display","none");
}
});
});
</script>
I want this to work so that as soon as someone types an 'o' the apples div is hidden but currently it hides all the divs as soon as anything is typed.
Also how can I make it case insensitive?
Big thanks to everyone who responded to this question - in the end I went with the solution Fabrizio Calderan provided, but have made a few modifications to it that allow for the text filter to search a string for words in any order and to redisplay previously hidden divs if the user deletes what they've typed, I thought I would share this modified solution with you:
$('#filter').keyup(function () {
var filter_array = new Array();
var filter = this.value.toLowerCase(); // no need to call jQuery here
filter_array = filter.split(' '); // split the user input at the spaces
var arrayLength = filter_array.length; // Get the length of the filter array
$('.media').each(function() {
/* cache a reference to the current .media (you're using it twice) */
var _this = $(this);
var title = _this.find('h4').text().toLowerCase();
/*
title and filter are normalized in lowerCase letters
for a case insensitive search
*/
var hidden = 0; // Set a flag to see if a div was hidden
// Loop through all the words in the array and hide the div if found
for (var i = 0; i < arrayLength; i++) {
if (title.indexOf(filter_array[i]) < 0) {
_this.hide();
hidden = 1;
}
}
// If the flag hasn't been tripped show the div
if (hidden == 0) {
_this.show();
}
});
});
You need to properly interpolate the selector string with the actual value of filter.
You also have a typo in $('this > ....
Try this code (with some improvements)
$('#filter').keyup(function () {
var filter = this.value.toLowerCase(); // no need to call jQuery here
$('.media').each(function() {
/* cache a reference to the current .media (you're using it twice) */
var _this = $(this);
var title = _this.find('h4').text().toLowerCase();
/*
title and filter are normalized in lowerCase letters
for a case insensitive search
*/
if (title.indexOf(filter) < 0) {
_this.hide();
}
});
});
Try
if (!RegExp.escape) {
RegExp.escape = function (value) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
};
}
var $medias = $('.media'),
$h4s = $medias.find('> .media-body > h4');
$('#filter').keyup(function () {
var filter = this.value,
regex;
if (filter) {
regex = new RegExp(RegExp.escape(this.value), 'i')
var $found = $h4s.filter(function () {
return regex.test($(this).text())
}).closest('.media').show();
$medias.not($found).hide()
} else {
$medias.show();
}
});
Demo: Fiddle
Modified the answer to this
var filter = this.value.toLowerCase(); // no need to call jQuery here
$('.device').each(function() {
/* cache a reference to the current .device (you're using it twice) */
var _this = $(this);
var title = _this.find('h3').text().toLowerCase();
/*
title and filter are normalized in lowerCase letters
for a case insensitive search
*/
if (title.indexOf(filter) < 0) {
_this.hide();
}
else if(filter == ""){
_this.show();
}
else{
_this.show();
}
});
});
Try this -
if ($('.media-body > h4:contains('+filter+')',this).length === 0) {
$(this).css("display","none");
}
This is wrong:
if ($('this > .media-body > h4:contains(filter)').length === 0) {
You should do like this:
if ($(this).find(' > .media-body > h4:contains('+filter+')').length === 0) {
Or like this:
if ($(' > .media-body > h4:contains('+filter+')', this).length === 0) {
You need to use .children() as well as concatenate your filter variable using +, so use:
if ($(this).children('.media-body > h4:contains(' + filter +')').length === 0) {
$(this).css("display","none");
}
instead of:
if ($('this > .media-body > h4:contains(filter)').length === 0) {
$(this).css("display","none");
}
example here
$('#filter').keyup(function () {
var filter = $("#filter").val();
$('.media').each(function() {
$(this).find("h4:not(:contains('" + filter + "'))").hide();
$(this).find("h4:contains('" + filter + "')").show();
});
});
You can simplify this code to:
$('#filter').keyup(function () {
// create a pattern to match against, in this one
// we're only matching words which start with the
// value in #filter, case-insensitive
var pattern = new RegExp('^' + this.value.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"), 'i');
// hide all h4's within div.media, then filter
$('div.media h4').hide().filter(function() {
// only return h4's which match our pattern
return !!$(this).text().match(pattern);
}).show(); // show h4's which matched the pattern
});
Here's a fiddle
Credit to this answer for the expression to escape special characters in the value.
You can use this code.
$('#filter').keyup(function () {
var filter = this.value.toLowerCase();
$('.media').each(function () {
var _this = $(this);
var title = _this.find('h1').text().toLowerCase();
if (title.indexOf(filter) < 0) {
_this.hide();
}
if (title.indexOf(filter) == 0) {
_this.show();
}
});
});
Related
So, I while I type I need to show elements with certain text that is equals data-value="certain text". I've tried several ways, but nothing seems to work.
Here is what I have so far.
$(".search").keyup(function () {
var filter = $(this).val(), count = 0;
$(".element-holder .element").each(function () {
var current = $('.element').attr('data-name');
if ($(".element[data-name='" + current + "']").text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut();
} else {
$(this).show();
count++;
}
});
});
This is what I need help with ;l
#Edit
HTml here
<div class="element-holder ">
<div class="element" data-name='Adam' id='1'>
</div>
<div class="element" data-name='Eva' id='32'>
</div>
<div class="element" data-name='Sara' id='412'>
</div>
</div>
Please try below
$(".search").keyup(function () {
var filter = $(this).val(), count = 0;
$(".element-holder .element").each(function () {
var current = $('.element').attr('data-name');
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut();
} else {
$(this).show();
count++;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="search"/>
<div class="element-holder ">
<div class="element" data-name='Adam' id='1'>How to Format
</div>
<div class="element" data-name='Eva' id='32'>How to Edit
</div>
<div class="element" data-name='Sara' id='412'>Searching throught data-value on keyup
</div>
</div>
Lot of mistakes in your html .
spelling mistakes of element class used.
You did not show the search input html.
Different data attribute name.
If you are using each and make use of $(this) to select current element
Checkout my below demo
$(".search").keyup(function () {
var entered = $(this).val();
$(".elemnet").each(function () {
var text = $(this).html();
if(entered !="")
{
if(text.indexOf(entered) > -1)
{
$(this).show();
}else
{
$(this).hide();
}
}else{
$(".elemnet").hide();
}
});
});
Working Demo
Demo using data attribute
Searching through the entire DOM on each keyup is going to cause a huge performance drop. Cache your results
Throttle your keyup event to only fire the filter when the user pauses typing
Re use your regular expression instead of re creating it multiple times inside your loop
```
// Cache your elements before hand
var namedElements = $(".element-holder .element");
// inside your throttled keyup event handler
// Check for empty strings
var filter = (this.value || "").trim(),
regex = new RegExp(filter, 'i');
var toShow = namedElements.filter(function(index, element) {
var dataName = element.data("name");
return regex.test(dataName);
});
toShow.show();
var toHide = namedElements.filter(function(index, element) {
var dataName = element.data("name");
return !regex.test(dataName);
});
toHide.hide();
```
I have a table on my page, and a filtering text box above it that works fantastic, using the following JQuery:
$("#searchInputCompanies").keyup(function () {
//split the current value of searchInput
var data = this.value.split(" ");
//create a jquery object of the rows
var jo = $("#cBody").find("tr");
if (this.value == "") {
jo.show();
return;
}
//hide all the rows
jo.hide();
//Recusively filter the jquery object to get results.
jo.filter(function(i, v) {
var $t = $(this);
for (var d = 0; d < data.length; ++d) {
if ($t.text().toLowerCase().indexOf(data[d].toLowerCase()) > -1) {
return true;
}
}
return false;
})
//show the rows that match.
.show();
$('#selectAllCompanies').prop('checked', '');
}).focus(function () {
this.value = "";
$(this).css({
"color": "black"
});
$(this).unbind('focus');
}).css({
"color": "#C0C0C0"
});
How can I set up a Reset Filter button for this?
Uhh, this is quite a bad implementation :(
First, you need to change the event for $("#searchInputCompanies") to make it all a bit easier. So, it will become $("#searchInputCompanies").on("input", function() {...
$("#resetAction").on("whatEventYouWant", function() {
$("#searchInputCompanies").val("").trigger("input");
});
This will trigger input event on $("#searchInputCompanies") and because the text box is empty all rows will become visible.
I am searching in list of 500 li's. using following code. but facing two problems. one when i press backspace very fastly after typing something, it is not captured. and also searching is case sensitive which i dont want. please suggest improvements in below code :
$('#find_question').bind("keyup", function() {
searchWord = $(this).val();
console.log("input length",searchWord);
if (searchWord.length >= 0) {
$('#leftSection li').each(function(i, data) {
text = $(this).text();
if (text.match(RegExp(searchWord, 'i')))
$(this).show();
else
$(this).hide();
});
}
});
Try this
The containsIgnoreCase comes from How do I make jQuery Contains case insensitive, including jQuery 1.8+?
Live Demo
$.expr[':'].containsIgnoreCase = function (n, i, m) {
return jQuery(n).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};
$function() {
$('#find_question').on("keyup", function() {
searchWord = $(this).val();
$('#leftSection li').hide();
if (searchWord.length >= 0) {
$('#leftSection li:containsIgnoreCase("'+searchWord+'")').show();
}
});
});
I am trying to implement tagging just like what facebook does with #friendname. I have a textarea and I wanted to detect when a user typed in #. How do I do so using a keyup listener? Is it possible to get the entered text using keyup? Here's what I have now
$("#recommendTextArea").keyup(function () {
var content = $(this).val(); //content Box Data
var go = content.match(start); //content Matching #
var name = content.match(word); //content Matching #friendname
console.log(content[content.length-1]);
//If # available
if(go.length > 0)
{
//if #abc avalable
if(name.length > 0)
{
//do something here
}
}
});
Most importantly what I need is the index of the'#' that the user just entered.
LINK
(function ($, undefined) {
$.fn.getCursorPosition = function() {
var el = $(this).get(0);
var pos = 0;
if('selectionStart' in el) {
pos = el.selectionStart;
} else if('selection' in document) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
return pos;
}
})(jQuery);
$("#recommendTextArea").on('keypress', function(e){
var key = String.fromCharCode(e.which);
if(key === '*') {
var position = $(this).getCursorPosition();
alert(position); // It is the position
alert($(this).val()); // This is the value
}
});
I made some changes HERE.
To detect a #, you'd do something like :
$("#recommendTextArea").keyup(function (e) {
if (e.which===50) {
alert('you typed #');
}
});
and this.value get's you whatever is typed into the textarea, and you'll need a regex to get what's between # and the first following space, or something similar depending on how you intend to do this ?
To get a name, you can do something like this :
var _name = false;
$("#recommendTextArea").keyup(function (e) {
if (_name) {
$('#name').text('name : ' + this.value.substring( this.value.lastIndexOf('#') ) )
}
if (e.which === 50) {
_name = true;
}
if (e.which === 32) {
_name = false;
}
});
FIDDLE
This is just a quick demo, building something that always works and accounts for every possible outcome will be a lot more work than this.
EDIT:
Most importantly what I need is the index of the'#' that the user just
entered.
that would be this.value.lastIndexOf('#')
EDIT AGAIN:
To get the names typed in the textarea regardless of cursor position, number of names etc. you'll have to use a regex, here's a quick example that gets all and any names typed in, as long as they start with a #, and ends with a blank space :
$("#recommendTextArea").keyup(function (e) {
var names = this.value.match(/#(.*?)\s/g);
$('#name').html('names typed : <br/><br/>' + names.join('<br/>'));
});
FIDDLE
I've checked the related questions on stack overflow, but can't seem to find an answer to my predicament. I'm trying to use a plugin for javascript (Tag it! - Tag Editor) and I need to find a way to call one of its functions "create_choice()" EDIT: at some point after it has been initiated. Is there a way after calling :
$tagit = $("#mytags").tagit();
that I can then call something like
$tagit.create_choice('test123');
Here is a link for the example :
http://levycarneiro.com/projects/tag-it/example.html
Below is the code from the plugin if it is any help
(function($) {
$.fn.tagit = function(options) {
var el = this;
const BACKSPACE = 8;
const ENTER = 13;
const SPACE = 32;
const COMMA = 44;
// add the tagit CSS class.
el.addClass("tagit");
// create the input field.
var html_input_field = "<li class=\"tagit-new\"><input class=\"tagit-input\" type=\"text\" /></li>\n";
el.html (html_input_field);
tag_input = el.children(".tagit-new").children(".tagit-input");
$(this).click(function(e){
if (e.target.tagName == 'A') {
// Removes a tag when the little 'x' is clicked.
// Event is binded to the UL, otherwise a new tag (LI > A) wouldn't have this event attached to it.
$(e.target).parent().remove();
}
else {
// Sets the focus() to the input field, if the user clicks anywhere inside the UL.
// This is needed because the input field needs to be of a small size.
tag_input.focus();
}
});
tag_input.keypress(function(event){
if (event.which == BACKSPACE) {
if (tag_input.val() == "") {
// When backspace is pressed, the last tag is deleted.
$(el).children(".tagit-choice:last").remove();
}
}
// Comma/Space/Enter are all valid delimiters for new tags.
else if (event.which == COMMA || event.which == SPACE || event.which == ENTER) {
event.preventDefault();
var typed = tag_input.val();
typed = typed.replace(/,+$/,"");
typed = typed.trim();
if (typed != "") {
if (is_new (typed)) {
create_choice (typed);
}
// Cleaning the input.
tag_input.val("");
}
}
});
tag_input.autocomplete({
source: options.availableTags,
select: function(event,ui){
if (is_new (ui.item.value)) {
create_choice (ui.item.value);
}
// Cleaning the input.
tag_input.val("");
// Preventing the tag input to be update with the chosen value.
return false;
}
});
function is_new (value){
var is_new = true;
this.tag_input.parents("ul").children(".tagit-choice").each(function(i){
n = $(this).children("input").val();
if (value == n) {
is_new = false;
}
})
return is_new;
}
function create_choice (value){
var el = "";
el = "<li class=\"tagit-choice\">\n";
el += value + "\n";
el += "<a class=\"close\">x</a>\n";
el += "<input type=\"hidden\" style=\"display:none;\" value=\""+value+"\" name=\"item[tags][]\">\n";
el += "</li>\n";
var li_search_tags = this.tag_input.parent();
$(el).insertBefore (li_search_tags);
this.tag_input.val("");
}
};
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g,"");
};
})(jQuery);
I've created a working example at http://jsfiddle.net/nickywaites/DnkBt/ but it does require making changes to the plugin.
Change
$.fn.tagit = function(options) { ...
to
$.fn.tagit = function(options,callback) { ...
Add
if (callback && typeof callback == 'function') {
callback();
}
after
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g,"");
};
Now you can call a function of your choice right after the tagit call:
$tagit = $("#mytags").tagit(yourOptions, function(){
alert('hi')!
});
You can try to add
return this;
right after the function create_choice block. tagit will return itself and you can call make_choice or any function contained in .fn.tagit