I am trying to create searchable content with the help of some JS yet am having trouble hiding the content when there is no input in the search field.
Here is my script:
var $searchContainer = $("#search");
var $contentBoxes = $searchContainer.find(".content");
var $searchInput = $searchContainer.find("#search-input");
var $searchBtn = $searchContainer.find("#search-btn");
$searchBtn.on("click", searchContent);
$searchInput.on("input", searchContent);
while($searchInput == null) {
for($contentBoxes) {
hide();
}
}
function searchContent(){
var userInput;
//Check if call comes from button or input change
if($(this).is(":button")){
userInput = $(this).siblings("input").val();
} else {
userInput = $(this).val();
}
//make the input all lower case to make it compatible for searching
userInput = userInput.toLowerCase();
//Loop through all the content to find matches to the user input
$contentBoxes.each(function(){
var headerText = $(this).find(".title").text();
var contentText = $(this).find(".description").text();
//add the title and content of the contentbox to the searchable content, and make it lower case
var searchableContent = headerText + " " + contentText;
searchableContent = searchableContent.toLowerCase();
//hide content that doesn't match the user input
if(!searchableContent.includes(userInput)){
$(this).hide();
} else {
$(this).show();
}
});
};
I understand a while loop could have a condition where if userInput is equal to null it would loop through each content box and hide the element.
Something like this maybe?
while($searchInput == null) {
$contentBoxes.each(function(){
hide();
}
}
Any help would be greatly appreciated.
You would need to update your userInput variable every cycle of the loop because the userInput value never gets updated. Nonetheless this not a good way to do this because you will block your entire application.
There is no need for a loop, just use an if statement. Also, because this function gets executed when the value of the input is changed, there is no need to use this.
You could put this block of code beneath your $contentBoxes.each function:
$contentBoxes.each(function(){
var headerText = $(this).find(".title").text();
var contentText = $(this).find(".description").text();
//add the title and content of the contentbox to the searchable content, and make it lower case
var searchableContent = headerText + " " + contentText;
searchableContent = searchableContent.toLowerCase();
//hide content that doesn't match the user input
if(!searchableContent.includes(userInput)){
$(this).hide();
} else {
$(this).show();
}
});
if (userInput === null) {
$contentBoxes.each(function(){
$(this).hide();
});
}
I think it will be work like this. You just check if search input !== null and dont hide any content in this case
if($searchInput != null && !searchableContent.includes(userInput)){
$(this).hide();
} else {
$(this).show();
}
Related
I am trying to append an error message to html once there was no match in the search bar. I have a list and once there is no match the list items get display:none; That's when i want to have the message. The problem is that being inside a loop to iterate through the list this message is appended the same number of times as the number of list items.
Updated code: it seems the error message doesn't appear each time i search for a student that is not a match...unless i refresh the page. Also sometimes even when i have the matching student the error shows although it shouldn't.
//add search bar
$( ".page-header" ).append('<div class="student-search"></div>');
$( ".student-search" ).append('<input id="input-search" placeholder="Search for students..."/><button id="search">Search</button>');
$('.page').append('<div class="error"></div>');
$('.error').append('<p>"Student not found!"</p>');
$('.error').hide();
var found = true;
//myFunction
function myFunction() {
var input = document.getElementById("input-search");
var filter = input.value.toUpperCase();
var ul = document.getElementsByClassName("student-list");
var li = document.getElementsByTagName("li");
for (var i = 0; i < li.length; i++) {
var h = li[i].getElementsByTagName("h3")[0];
if (h.innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
found = true;
} else {
li[i].style.display = "none";
console.log('Hello! Student is not found!');
found = false;
}
}
$('.pagination').hide();
if (found === false) {
$('.error').show();
}
}
//myFunction end
// when the input is empty return to page 1, empty the error div, show pagination,
$('#input-search').on('keyup', function() {
if($(this).val() === '') {
$('.error').empty();
go_to_page(0);
$('.pagination').show();
}
});
$('#search').click(function(){
myFunction();
});
Thanks,
Alina
I made a demo for you, I hope it's what you want:
https://jsfiddle.net/jondion/xpdof2jh/14/
First, every time the user makes a search, we need to remove all the previous errors. I added a variable found to track if the username matches the filter. I added conditions to show the search results.
Reset the .error when the input is empty.
$('input').on('keyup', function() {
if($(this).val() === '') {
$('.error').empty()
}
});
I can't figure out why $('label.error') is showing up on every bootstrap tab when that particular element should only show on 1 tab. I have a field that's not passing validation on a bootstrap tab and thus a label with class error is being appended the DOM on the violating field. But, I can't seem to get my code to land on the specific tab that has the violating field. What am I doing wrong in the code below? isErrorPresent should only be true on 1 particular tab but EVERY tab is showing it to be true...
$("#" + formId).validate({ignore:""}).form(); // ignore:"" allows for hidden fields to be validated as well
$(".tab-content").find("div.tab-pane").each(function (index, tab) {
var id = $(tab).attr("id");
$('a[href="#' + id + '"]').click();
alert('processing tab ' + id);
var isErrorPresent = $('div.tab-pane, div.active').find('label.error').length > 0;
alert(isErrorPresent);
// if (isErrorPresent) {
// alert("label.error detected...");
// hasError = true;
// return false; // Break .each loop and return to page
// }
});
Without seeing more markup, this is what I am thinking:
You are doing this:
var isErrorPresent = $('div.tab-pane, div.active').find('label.error').length > 0;
The selector has a comma in it, meaning you want to checking on div.tab-pane && div.active
Is that what you wanted? Maybe you meant to do this (no comma and no space):
var isErrorPresent = $('div.tab-pane.active').find('label.error').length > 0;
Figured it out with #Red2678's help (thanks)...here's what's working for me now...
// Check all tabs for errors & show first tab that has errors
$(".tab-content").find("div.tab-pane").each(function (index, tab) {
var id = $(tab).attr("id");
$('a[href="#' + id + '"]').click();
$("#" + formId).validate().form();
var activeTab = $('div.tab-pane.active');
var isErrorPresent = false;
if ($(activeTab).find('label.error').length > 0) {
isErrorPresent = $(activeTab).find('label.error').css('display') !== 'none';
}
if (isErrorPresent) {
hasError = true;
return false; // Break .each loop and return to page
}
});
I am able to validate all fields within a div but I only want to validate specific fields. Here is a jsfiddle to show what I mean Once validation is passed the div is hidden. I have to enter data in all of the fields so if you check 'Yes' from the checkbox you will see a input field appear I don't want to include that and also if you select 'NoGame' from the dropdownlist once you enter data in all the fields apart from the two fields in the lower div (green border) and click the Test1 button you will see what I mean. Any suggestions?
This is the code which validates all fields and then Hides the div, which can also be seen in the fiddle
function IsValid(divid) {
var $div = $('#' + divid);
var result = true;
$.each($div.find("input[type='text']"), function (i, input) {
if ($(input).val().length == 0 || $.trim($(input).val()) == '') {
result = false;
return;
}
});
return result;
}
$(document).ready(function(){
$("#hide").click(function(){
if (IsValid('contentone')) {
$('#contentone').hide();
};
});
});
Input fields of type text that you don't want to validate exclude them from the validation process
function IsValid(divid) {
var $div = $('#' + divid);
var result = true;
var excludeElement = ["reason"]; //<-- EXCLUDED ELEMENTS IDS
$.each($div.find("input[type='text']"), function (i, input) {
if ($.inArray($(input).attr('id'), excludeElement) < 0 && ($(input).val().length == 0 || $.trim($(input).val()) == '')) {
result = false;
return;
}
});
return result;
}
Sorry for the horrible title, Am terrible at wording these things.
What I am trying to do is quite simple I think.
I have a set of hidden letters that make up a word.
Below them is a selection of random jumbled up letters.
When people click one of the random jumbled letters I am filtering through the hidden letters and showing the corresponding letter.
What I need to do is, if someone clicks a letter, filter through the hidden letters and either return a "true" and show the letter or return a "false/null" and make an alert();
This is how I am filtering at the moment. I am confused as to where to place an if statement or if that is even the approach I should be taking.
And here is a fiddle (the hidden word is "Seal") - http://jsfiddle.net/GA7WB/
var $buttons = $('#letters span'),
$hidden = $('.letter');
$buttons.click(function(){
_selected = $(this).html();
$hidden.filter(function() {
return $(this).text() == _selected;
}).show();
});
You just need to check the length of the results returned by the filter:
// get matched elements
var matches = $hidden.filter(function() {
return $(this).text() == _selected;
});
// show them, or alert if none
if (matches.length > 0) matches.show();
else alert("There are no " + _selected + "'s");
See Fiddle
Try setting a flag if you find one:
var $buttons = $('#letters span'),
var $hidden = $('.letter');
$buttons.click(function(){
_selected = $(this).html();
var foundOne = false;
$hidden.filter(function() {
var retval = $(this).text() == _selected;
if (retval) foundOne = true;
return retval;
}).show();
if (!foundOne) {
alert("Nope");
}
});
FIDDLE http://jsfiddle.net/GA7WB/4/
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