how can i make a search bar on my webpage that:
filters the items (list items/cards) on my page without pressing enter
with the current search bar value and updates automatically as user types
then revert the changes back also when the user deletes letters - (ex: display:none -> display:block)
in plain js
also the current search lags 1 key behind
this is where i am trying to implement it
http://codepen.io/lycjee/pen/dNjBPE
and this is the corrseponding code for the search bar
searchbar.addEventListener('keypress', function(e) {
//filter with keypress - without enter
//filter function - on "chan" array
var filterItems = function(query) {
return chan.filter(function(el) {
return el.toLowerCase().indexOf(query.toLowerCase()) <= -1;
});
};
//searchquery
var searchQuery = document.getElementById('searchbar').value;
//declare a var for array of items to be filtered
var filtered = filterItems(searchQuery);
console.log(searchQuery);
console.log(filtered);
console.log(chan);
//if searchbar is blank and there is a keypress after it
//shows all elements according to the original chan array
//else disables elements according to filtered array
if (searchQuery === "") {
for (let i = 0; i < chan.length; i++) {
document.getElementById(chan[i]).style.display = "block";
}
}
else {
for (let i = 0; i < filtered.length; i++) {
document.getElementById(filtered[i]).style.display = "none";
}
}
filtered = chan;
}
Related
I have a UI application to display business information. I have used slick grid to show all business data in tabular/grid structure by using all built-in properties of slick grid. I have used filter property to filter data on each column.
But I have a condition that i am getting 1k data from the Azure storage table and i set the pageSize to 10 and i pass the pageSize to set the pagination in dataView.setPagingOptions({pageSize:pageSize}); When we click on slick-header-menuitem in dropdown it displays (Sort Ascending,Sort Descending,Search and data whatever grid containing on the (filter div) ).
Now once I click on the checkbox to filter the data whatever the data i need to filter it will filter those data fine without any issue.Uptill here every thing is working as expected as here in my filter dropdown i have 4 option like (Select All , Blank , IT ,U.S.A ,USA ) which is shown in the image below.
But the problem starts form here once i again click on the slick-header-menuitem after the filteration dropdown (filter div) display few more data like
(Select All , Blank , IT ,U.S.A ,USA ,UNITED STATES,US) because i have filtered data suppose (IT) so in grid all the data filter and get the data from the 1k records but it will also get the data appended in the filter div options which was not there in previously.
for refrence my grid is looking someting like this (below is the url) except search and pagination
http://danny-sg.github.io/slickgrid-spreadsheet-plugins/examples/example-2-everything.htm
I am also attaching two images
first image indicate when i click on the first time on slick-header-menuitem dropdown.
And second image indicate when i again click on the slick-header-menuitem dropdown after the filtered data.
I have gone through the slickgrid library in which there is a plugin folder this folder contain filter folder and filter folder contain ext.headerfilter.js
this file contain method called "function getFilterValues(dataView, column){...}", "function getFilterValuesByInput($input){...}" and "function getAllFilterValues(data, column){...}", i have debug it but won't get any success.
finally a lots of debugging i got the solution for filtering the records
here i am not bothering about the slick-grid library,it is an awsome library as per my experience
so on the basis of my requirement i have done some changes in ext.headerfilter.js file
go to the function called getFilterValues() and getFilterValuesByInput($input), inside these function i have done some changes in for loop and variable below is the code has been implemented for getFilterValues() and getFilterValuesByInput($input)
function getFilterValues(dataView, column) {
var seen = [];
// for (var i = 0; i < dataView.getLength() ; i++) {
for (var i = 0; i < dataView.getItems().length ; i++) {
// var value = dataView.getItem(i)[column.field];
var value = dataView.getItems()[i][column.field];
if (!_.contains(seen, value)) {
seen.push(value);
}
}
return _.sortBy(seen, function (v) { return v; });
}
code for getFilterValuesByInput($input)
function getFilterValuesByInput($input) {
var column = $input.data("column"),
filter = $input.val(),
dataView = grid.getData(),
seen = [];
// for (var i = 0; i < dataView.getLength() ; i++) {
for (var i = 0; i < dataView.getItems().length ; i++) {
// var value = dataView.getItem(i)[column.field];
var value = dataView.getItems()[i][column.field];
if (filter.length > 0) {
var mVal = !value ? '' : value;
var lowercaseFilter = filter.toString().toLowerCase();
var lowercaseVal = mVal.toString().toLowerCase();
if (!_.contains(seen, value) && lowercaseVal.indexOf(lowercaseFilter) > -1) {
seen.push(value);
}
}
else {
if (!_.contains(seen, value)) {
seen.push(value);
}
}
}
return _.sortBy(seen, function (v) { return v; });
}
My app dynamically creates and deleted new elements based on the + / - buttons.
Inside the dynamically created elements are text forms. I want whatever the user types into the text form to be displayed in another dynamically created element.
$('.LName').keyup(function(event) {
var crazy = {};
for (var x = 1; x < i; x++) {
crazy[x] = function() {
$('#sideChange'+ x).keyup(function(event) {
var value = $(this).val();
$('.sLoan'+ x).text(value);
})
}
}
for (var p = 1; p < i; p++) {
crazy[p]();
}
});
For example, I accomplished this for changing the text in the previous element by including the function in the html onkeyup attribute, but I don't know how to accurately target other elements.
var changeTitle = function() {
var loanTitle = $(this).val();
var code = $("input[type='text'][name='loanName']").keyCode || $("input[type='text'][name='loanName']").which;
var length = loanTitle.length;
console.log(length);
if(length < 1 || code == 8) {
$(this).prev().text('Loan');
}
else {
$(this).prev().text(loanTitle);
}
};
What youll probably want to do is data bind the two elements with some sort of ID you generate. In the fiddle below, I just use an incrementing number. When the keyup happens, I grab that elements data-id and use it to find its "mirrored" input.
$('.mirror[data-id="'+id+'"]').val(text);
Your question was a bit vague but I think this is what you were asking for.
http://jsfiddle.net/swoogie/f8cd4voz/
I'm working on a web game and need to check for which cells on the table have been selected by the user. Right now I'm just checking for the row and cell index value:
JavaScript
function checkForWin() {
var card = document.getElementById('card');
if ((card.rows[0].cells[0].marker && // 1st row
card.rows[0].cells[1].marker &&
card.rows[0].cells[2].marker &&
card.rows[0].cells[3].marker &&
card.rows[0].cells[4].marker)) {
youWin();
} else {
noWin();
}
}
Is there a more elegant of doing this with jQuery?
Just make some loop :
function checkForWin() {
var card = document.getElementById('card');
var win = true;
for (var i = 0; i < card.rows[0].cells.length; i++){
if(!card.rows[0].cells[i])
win = false;
}
if(win)
youWin();
else
noWin();
}
Using jQuery you could iterate over the list of marked cells or just get the list of marked cells like this:
var marked = $('#cards td.marked');
// If you have a special way to detect a cell is marked that
// needs more custom test than checking the class you can use .filter.
// Just as example I use the same condition.
//var marked = $('#cards td').filter(function () {
// return $(this).hasClass('marked');
//});
// If you want to just iterate the selected cells.
marked.each(function () {
var i = $(this).closest('tr').index();
var j = $(this).index();
console.log(i, j);
});
// If you want to the the array of selected cells.
var indexes = marked.map(function () {
return {
i: $(this).closest('tr').index(),
j: $(this).index()
};
}).get();
To make it easier I assumed that a cell with the marked class means a marked cell. However you can use the condition you want to get the list of marked cells.
See small demo
I am creating a program using JavaScript while a clicking of button it will select a seat and change its background color to green and at the same time the button value will be added to the text field and will toggle accordingly.
Issue: I am adding all the value to the text field using an array, which is successful but during toggling it cannot able to subtract the particular clicking button value from array.
Here I cannot able to use jQuery because this page is coming from a ajax-page load.
// JavaScript Document
var Cur_id;
var Cur_val;
function setId(id, value) {
Cur_id = id;
Cur_val = value;
var SeatVal = document.getElementById(id);
if (SeatVal.style.backgroundImage == "") {
SeatVal.style.backgroundImage = "url(\'themes/frontend/images/greenseat.png\')";
var txbtElementSeat = new Array(document.getElementById("selectedseat").value += Cur_val + ",");
} else if (SeatVal.style.backgroundImage == 'url("themes/frontend/images/greenseat.png")') {
SeatVal.style.backgroundImage = "url(\'themes/frontend/images/seat.png\')";
var txbtElementSeatnbg = document.getElementById("selectedseat").value;
removeSeat(txbtElementSeatnbg, Cur_val);
function removeSeat(txbtElementSeatnbg, value) {
for (var i = 0; i <= txbtElementSeatnbg.length; i++) {
if (txbtElementSeatnbg[i] == value) {
txbtElementSeatnbg.splice(i, 1);
break;
}
}
}
} else if (SeatVal.style.backgroundImage == 'url("themes/frontend/images/seat.png")') {
SeatVal.style.backgroundImage = "url(\'themes/frontend/images/greenseat.png\')";
var txbtElementseatnb = document.getElementById("selectedseat").value += Cur_val + ",";
}
}
Your main issue seems to be that you try to save an array into a textfield. That will actually work, but will convert the array to a string representation.
var a = document.getElementById('selectedseat').value; therefore loads the string representation of the array into a variable "a", not the array itself!
Why don't you use a variable in the outer context (not the local function scope of setId()!) to hold the array? Maybe somewhat like this:
// Create a variable for the array!
var selectedSeats = new Array();
// Build a function that will update the textfield.
// Call this, whenever the array gets changed!
function updateListOfSelectedSeats() {
document.getElementById('selectedseat').value = selectedSeats.join(',');
}
// Removes a seat from the list of selected seats
function removeSeatFromList(seat) {
for (var i = 0; i < selectedSeats.length; i++) {
if (selectedSeats[i] == seat) {
selectedSeats.splice(i, 1);
updateListOfSelectedSeats();
break;
}
}
}
// Now the function that reacts to clicks on a seat
function setId(id, value) {
var Seat = document.getElementById(id);
switch (Seat.style.backgroundImage) {
case 'url("themes/frontend/images/greenseat.png")':
// Seat is already selected and needs to be deselected
Seat.style.backgroundImage = 'url("themes/frontend/images/seat.png")';
removeSeatFromList(value);
break;
case '':
case 'url("themes/frontend/images/seat.png")':
// Seat is empty, select it!
Seat.style.backgroundImage = 'url("themes/frontend/images/greenseat.png")';
selectedSeats.push(value);
updateListOfSelectedSeats();
break;
}
}
To remove the seat from the list use this
//remove seat from list
function removeSeat(seatListElm, seatValue) {
var arr=seatListElm.value.split(',');
var p=arr.indexOf(seatValue);
if(p!=-1){
arr.splice(p, 1);
seatListElm.value=arr.join(',');
}
}
seatListElm would be the element that hold "b5,c7,d5,c2"
seatValue would be something like this "c7"
Working demo code: JSFIDDLE
I have two Select lists, between which you can move selected options. You can also move options up and down in the right list.
When I move options back over to the left list, I would like them to retain their original position in the list order, even if the list is missing some original options. This is solely for the purpose of making the list more convenient for the user.
I am currently defining an array with the original Select list onload.
What would be the best way to implement this?
You can store the original order in an array, and when inserting back, determine what's the latest element in the array that precedes the one to be inserted AND matches what's currently in the select list. Then insert after that.
A better solution is to just store the old array whole and re-populate on every insertion with desired elements as follows (warning: code not tested)
function init(selectId) {
var s = document.getElementById(selectId);
select_defaults[selectId] = [];
select_on[selectId] = [];
for (var i = 0; i < s.options.length; i++) {
select_defaults[selectId][i] = s.options[i];
select_on[selectId][i] = 1;
var value = list.options[i].value;
select_map_values[selectId][value] = i if you wish to add/remove by value.
var id = list.options[i].id; // if ID is defined for all options
select_map_ids[selectId][id] = i if you wish to add/remove by id.
}
}
function switch(selectId, num, id, value, to_add) { // You can pass number, value or id
if (num == null) {
if (id != null) {
num = select_map_ids[selectId][id]; // check if empty?
} else {
num = select_map_values[selectId][value]; // check if empty?
}
}
var old = select_on[selectId][num];
var newOption = (to_add) : 1 : 0;
if (old != newOption) {
select_on[selectId][num] = newOption;
redraw(selectId);
}
}
function add(selectId, num, id, value) {
switch(selectId, num, id, value, 1);
}
function remove(selectId, num, id, value) {
switch(selectId, num, id, value, 0);
}
function redraw(selectId) {
var s = document.getElementById(selectId);
s.options.length = 0; // empty out
for (var i = 0; i < select_on[selectId].length; i++) {
// can use global "initial_length" stored in init() instead of select_on[selectId].length
if (select_on[selectId][i] == 1) {
s.options.push(select_defaults[selectId][i]);
}
}
}
I would assign ascending values to the items so that you can insert an item back in the right place. The assigned value stays with the item no matter which list it's in.