Match words in any order in Isotope (using input value) - javascript

I'm using Isotope.js with vanilla javascript.
Inside my items, I have put a div with a display:none to hide keywords for each item. For example, the item Orange has the keywords 'color' and 'fruit'. So if someone types in any of those three words into the input form (orange, color, or fruit) that item will be shown via Isotope.
Here is a jsfiddle showing my project.
What I'm wanting to do, is if someone were to type all three words into the input form in any order the item will show. Right now the item will only show if the keywords are typed in order. For example, typing in "fruit color" will show the item Orange, but "color fruit" will not.
Edit: This answer here does exactly what I'm trying to achieve. I applied it to a jQuery version of my project and worked perfectly. However, I'm having troubling rewriting it in vanilla JS. Any help is immensely appreciated.

Can you try changing the following, I have removed the regex to string
filter: function(itemElem) {
return qsRegex ? itemElem.textContent.indexOf(qsRegex) !== -1 : true;
}
var quicksearch = document.querySelector('input[type="text"]');
quicksearch.addEventListener('input', function() {
// match items by first letter only
qsRegex = quicksearch.value; // Changed here
iso.arrange();
});

I ended up getting it working myself. I apologise, I'm still new to Javascript and am learning by trial and error, and I'm not sure how to give a proper explanation on how I got it working. But here is the final result:
var qsRegex;
var quicksearch = document.querySelector('input[type="text"]');
// init Isotope
var iso = new Isotope('#grid', {
itemSelector: '.item',
layoutMode: 'fitRows',
transitionDuration: 1000,
filter: function(itemElem) {
var qsRegex = [];
var resultRegex = [];
var endResult = new Boolean();
var searchID = quicksearch.value;
var searchTable = searchID.split(" ");
for (var i = 0; i < searchTable.length; i++) {
qsRegex[i] = new RegExp("(^|\\s)(" + searchTable[i] + ")", 'gi');
resultRegex[i] = qsRegex[i] ? itemElem.textContent.match(qsRegex[i]) : true;
endResult = endResult && resultRegex[i];
}
return endResult;
}
});
// use value of input to filter
var quicksearch = document.querySelector('input[type="text"]');
quicksearch.addEventListener('input', function() {
iso.arrange();
});
Updated jsfiddle link

Related

Select2 Tags replace spaces with underscores

I have a select2 JavaScript that does my tags. The client decided that they wanted to have a space. As you know spaces ruin everything so we compromised with an underscore but we wanted to replace all spaces with an underscore just in case not everyone follows instructions.
So I added a little JavaScript, but when I save new values to their assigned attributes select2 breaks, and it seems to be two lines of code that is breaking the process.
Is there any other way to write these two lines?
My JavaScript (I will mark the ones that are messing up the program))
<script>
$("#tags").select2({
placeholder: "Add Tag(s)...",
tags: true
});
$('#tags').change(function() {
var self = this;
$(self).find('option').each(function() {
var value = $(this).val();
var text = $(this).text();
var newValue = value.split(' ').join('_');
var newText = text.split(' ').join('_');
$(this).val(newValue); // This line overrides the tag manually input before it.
$(this).text(newText);
$('.select2-selection__choice').each(function() {
var title = $(this).attr('title');
var newTitle = title.split(' ').join('_');
$(this).val(newTitle)
$(this).text(newTitle); //This line deletes the x in the tags
});
});
});
});
</script>
If you need to change the text and value on select field change, you can do it like this:
$(function(){
$('#tags').change(function() {
$(this).find('option').each(function() {
var value = $(this).val();
var text = $(this).text();
$(this).val(value.split(' ').join('_'))
$(this).text(text.split(' ').join('_'))
});
});
});
Here's a plunkr demo

Tablesorter Set output widget options on the fly

I'm using the tablesorter fork from Mottie. I am not very experienced with javascript, but so far I got everything to work. Here is the problem:
NOW I want to have two buttons above my table to allow the download of either all rows or download just the selected rows.
For this I have the following javascript code which works partly. I just need to get it to work to download all(!) rows.
What I am doing wrong ?
Here is the portion which outputs all:
$('.downloadall').click(function(){
var $table = $('.tablesorter');
wo = $table[0].config.widgetOptions,
saved = $table.find('.output-filter-all :checked').attr('class');
wo.output_includeHTML = false;
wo.output_delivery = 'p';
// d = download p = page
wo.output_saveRows ='a';
// a = all f=filtered
$table.trigger('outputTable');
return false;
});
This works very well including the setting of all the other output options.
The following code does exactly the same thing, but I want, of course, just the selected rows.
$('.downloadselected').click(function(){
var $table = $('.tablesorter');
wo = $table[0].config.widgetOptions,
saved = $table.find('.output-filter-all :checked').attr('class');
wo.output_includeHTML = false;
wo.output_delivery = 'p';
// d = download p = page
wo.output_saveRows = saved;
// a = all f=filtered
$table.trigger('outputTable');
return false;
});
I've tried various things but with no luck.
Since I can't tell what to expect from the table HTML. I don't know what the saved variable ends up as, but it appears to be missing the leading period to make a jQuery selector for a class name.
wo.output_saveRows = '.' + saved;
Anyway, it got me thinking that currently you can't select a row based on its content, so I updated the saveRows option to now accept a filter callback function which as of this writing is currently only available in the master branch, and can be used as follows:
$('.downloadselected').click(function(){
var $table = $('.tablesorter'),
wo = $table[0].config.widgetOptions
wo.output_includeHTML = false;
wo.output_delivery = 'p';
wo.output_saveRows = function(){
// include row only if it has a checked checkbox
return $(this).find('input[type="checkbox"]:checked').length > 0;
};
$table.trigger('outputTable');
return false;
});
Well I just overlooked that the class name '.saved' is of course not correct. At the end Mottie pointed me to the right direction. Here is the solution to my original question just use the correct class name .checked and everthing works as expected.:
$('.downloadselected').click(function(){
var $this =$('#table');
var $table = $('.tablesorter');
wo = $table[0].config.widgetOptions,
wo.output_includeHTML = false;
wo.output_delivery = 'p';
// d = download p = page
//saved = '.checked';
// a = all f=filtered
wo.output_saveRows = '.checked';
$table.trigger('outputTable');
return false;
});
It

Auto highlighting part of word

I'm trying to build a "search in the shown elements" function with jquery and css.
Here's what I got so far:
http://jsfiddle.net/jonigiuro/wTjzc/
Now I need to add a little feature and I don't know where to start. Basically, when you write something in the search field, the corresponding letters should be highlighted in the list (see screenshot, the blue highlighted part)
Here's the script so far:
var FilterParticipants = function(options) {
this.options = options;
this.participantList = [];
this.init = function() {
var self = this;
//GENERATE PARTICIPANTS OPBJECT
for(var i = 0; i < this.options.participantBox.length ; i++) {
this.participantList.push({
element: this.options.participantBox.eq(i),
name: this.options.participantBox.eq(i).find('.name').text().toLowerCase()
})
}
//ADD EVENT LISTENER
this.options.searchField.on('keyup', function() {
self.filter($(this).val());
})
}
this.filter = function( string ) {
var list = this.participantList;
for(var i = 0 ; i < this.participantList.length; i++) {
var currentItem = list[i];
//COMPARE THE INPUT WITH THE PARTICIPANTS OBJECT (NAME)
if( currentItem.name.indexOf(string.toLowerCase()) == -1) {
currentItem.element.addClass('hidden');
} else {
currentItem.element.removeClass('hidden');
}
}
}
this.init();
}
var filterParticipants = new FilterParticipants({
searchField: $('#participants-field'),
participantBox: $('.single_participant'),
nameClass: 'name'
});
I think you're just complicating things too much... You can do this easily in a few lines. Hope this helps:
var $search = $('#participants-field');
var $names = $('.single_participant p');
$search.keyup(function(){
var match = RegExp(this.value, 'gi'); // case-insensitive
$names
.hide()
.filter(function(){ return match.test($(this).text()) })
.show()
.html(function(){
if (!$search.val()) return $(this).text();
return $(this).text().replace(match, '<span class="highlight">$&</span>');
});
});
I used hide and show because it feels snappier but you can use CSS3 animations and classes like you were doing.
Demo: http://jsfiddle.net/elclanrs/wTjzc/8/
Here`s the way to do it with jQuery autocomplete so question
If you want to build it on your own you can do the following:
1. Get the data of every item.
2. Make render function in which you will substitute say "Fir" in Fire word to Fire
3. Every time you change the text in the input you can go through the items and perform substitution.

Update div with jQuery upon entry of data

I have a form with four text input elements. Every time one of them is updated, I want the sum of the four text input boxes to be displayed in a div below without the user pushing a button. Here's what I have so far (I got the idea from here [does this only work with select?]):
var getSum = function() {
var email = $('#emailDown').val();
var internet = $('#internetDown').val();
var server = $('#serverDown').val();
var desktop = $('#pcDown').val();
//TODO:Check for integers (not needed with sliders)
var sum = email + internet + server + desktop;
$('totalHoursDown').html(sum);
}
$('#emailDown').change(getSum(event));
$('#internetDown').change(getSum(event));
$('#serverDown').change(getSum(event));
$('#pcDown').change(getSum(event));
Currently, it's not updating. (Don't worry about validating). I'm new to PHP, so I'm not sure if I should be using it in this instance.
You are missing a # or . in your selector, depending on if totalHoursDown is a class or an ID:
$('totalHoursDown').html(sum);
// Should be this if ID
$('#totalHoursDown').html(sum);
// or this if class
$('.totalHoursDown').html(sum);
Update:
I modified the code by jmar777 a bit to make it work. Try this instead:
$(function(){
var $fields = $('#emailDown, #internetDown, #serverDown, #pcDown'),
$totalHoursDown = $('#totalHoursDown');
$fields.change(function() {
var sum = 0;
$fields.each(function()
{
var val = parseInt($(this).val(), 10);
sum += (isNaN(val)) ? 0 : val;
});
$totalHoursDown.html(sum);
});
});
​Here is a working fiddle as well: http://jsfiddle.net/mSqtD/
Try this:
var $fields = $('#emailDown, #internetDown, #serverDown, #pcDown'),
$totalHoursDown = $('#totalHoursDown');
$fields.change(function() {
var sum = 0;
$fields.each(function() { sum += $(this).val(); });
$totalHoursDown.html(sum);
});
Also, in your example, you had $('totalHoursDown').html(sum);, which I'm assuming was intended to be an ID selector (i.e., $('#totalHoursDown').html(sum);.

Jquery script freezing browser but working

i'm trying to make a live search for my mobile website, I don't want to query the database every time a user type a letter so I created a ordered list with all the names that can be searched for and i'm looping through it with jquery, problem is that I have 3300 names and it's freezing the browser when it searches through them, can anyone give me a tip about better ways to do it? here is my code:
$(document).ready(function(){
$("input#search").keyup(function(){
var filter = $(this).val(), count = 0;
var html = "";
$("ol.pacientes li").each(function(){
var nome_paciente = $(this).text();
if(nome_paciente.indexOf(filter.toUpperCase()) != -1){
html = html + " " + nome_paciente;
}
$('#pacientes_hint').html(html);
});
Use the jQuery autocomplete version. You can load an array with all your names and pass it in to autocomplete, which will work on the fly.
http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/
You could change your each to:
var text = $("ol.pacientes li:contains(\""+filter.toUpperCase()+"\")").map(function() {
return $(this).text();
}).join(' ');
$('#pacientes_hint').text(text);
Besides being shorter, the only improvement will be setting the contents of $('#pacientes_hint') only at the end, which could help.
Let me know if you need a more creative solution.
First of all, you could move #pacientes_hint outside the each function.
$(document).ready(function(){
$("input#search").keyup(function(){
var filter = $(this).val(), count = 0;
var html = "";
$("ol.pacientes li").each(function(){
var nome_paciente = $(this).text();
if(nome_paciente.indexOf(filter.toUpperCase()) != -1){
html = html + " " + nome_paciente;
} // end if
}); // end each
$('#pacientes_hint').html(html);
Then, you can define ol.pacientes as a variable before the keyup handler, so it doesn't look for it everytime and in the each function, search inside the variable:
$(document).ready(function(){
var pacientes_list = $("ol.pacientes");
var pacientes_hint = $("#pacientes_hint");
$("input#search").keyup(function(){
...
$("li", $(pacientes_list)).each(function(){ // search in the container
...
}); // end each
$(pacientes_hint).html(html);

Categories