问题
I have a page using Isotope. It combines a search box, multiple combination filters and finally some sorting options.
I have used many examples on the web to combine all this and stripped the code down as best I can (very limited isotope knowledge).
Two things -
Firstly, how can this be combined further? I currently have 3 separate 'sections' to the code.
Secondly, the search box works independent of the combination filters, and when the filters are clicked the search box stops working at all. is it possible to include the search in the filters so for example I can click two filters and type a word into the search and it will find anything that matches all three?
Here is all the code used that is relevant - Any help appreciated.
//Init Isotope and set sort options
$( function() {
var $filterDisplay = $('#filter-display');
var $container = $('.results');
$container.isotope({
filter: function() {
return qsRegex ? $(this).text().match( qsRegex ) : true;
},
itemSelector: '.excerpt-home',
masonry: {
isFitWidth: true
},
getSortData: {
name: '.name',
price: function( itemElem ) {
var price= $( itemElem ).find('.price-prop').text();
return parseFloat( price.replace( /[\(\)]/g, '') );
},
distance: function( itemElem ) {
var distance= $( itemElem ).find('.wppl-address').text();
return parseFloat( distance.replace( /[\(\)]/g, '') );
}
}
});
// sort items on button click
$('#sorts').on( 'click', 'button', function() {
var sortByValue = $(this).attr('data-sort-by');
$container.isotope({ sortBy: sortByValue });
});
// change is-checked class on buttons
$('.button-group').each( function( i, buttonGroup ) {
var $buttonGroup = $( buttonGroup );
$buttonGroup.on( 'click', 'button', function() {
$buttonGroup.find('.is-checked').removeClass('is-checked');
$( this ).addClass('is-checked');
});
});
});
var filters = {};
var qsRegex;
$(function(){
$container = $('.results');
// do stuff when checkbox change
$('#options').on( 'change', function( jQEvent ) {
var $checkbox = $( jQEvent.target );
manageCheckbox( $checkbox );
var comboFilter = getComboFilter( filters );
$container.isotope({ filter: comboFilter });
$filterDisplay.text( comboFilter );
});
});
$( function() {
// quick search regex
// init Isotope
var $container = $('.results').isotope({
itemSelector: '.excerpt-home'
});
// use value of search field to filter
var $quicksearch = $('#quicksearch').keyup( debounce( function() {
qsRegex = new RegExp( $quicksearch.val(), 'gi' );
$container.isotope();
}, 200 ) );
});
// debounce so filtering doesn't happen every millisecond
function debounce( fn, threshold ) {
var timeout;
return function debounced() {
if ( timeout ) {
clearTimeout( timeout );
}
function delayed() {
fn();
timeout = null;
}
timeout = setTimeout( delayed, threshold || 100 );
}
}
function getComboFilter( filters ) {
var i = 0;
var comboFilters = [];
var message = [];
for ( var prop in filters ) {
message.push( filters[ prop ].join(' ') );
var filterGroup = filters[ prop ];
// skip to next filter group if it doesn't have any values
if ( !filterGroup.length ) {
continue;
}
if ( i === 0 ) {
// copy to new array
comboFilters = filterGroup.slice(0);
} else {
var filterSelectors = [];
// copy to fresh array
var groupCombo = comboFilters.slice(0); // [ A, B ]
// merge filter Groups
for (var k=0, len3 = filterGroup.length; k < len3; k++) {
for (var j=0, len2 = groupCombo.length; j < len2; j++) {
filterSelectors.push( groupCombo[j] + filterGroup[k] ); // [ 1, 2 ]
}
}
// apply filter selectors to combo filters for next group
comboFilters = filterSelectors;
}
i++;
}
var comboFilter = comboFilters.join(', ');
return comboFilter;
}
function manageCheckbox( $checkbox ) {
var checkbox = $checkbox[0];
var group = $checkbox.parents('.option-set').attr('data-group');
// create array for filter group, if not there yet
var filterGroup = filters[ group ];
if ( !filterGroup ) {
filterGroup = filters[ group ] = [];
}
// index of
var index = $.inArray( checkbox.value, filterGroup );
if ( checkbox.checked ) {
if ( index === -1 ) {
// add filter to group
filters[ group ].push( checkbox.value );
}
} else {
// remove filter from group
filters[ group ].splice( index, 1 );
}
}
回答1:
I had the same problem and found the solution. The main thing to keep in mind is passing the data-attribute and the class as well, because the filter and search works as a filter function and the sorting has its own function.
Our project is to filter and sort all of the resorts by type, country, city, state. So I added classes for country, city, state, and state. For the category I added a resort type category to determine between luxury and regular resorts.
var qsRegex;
var buttonFilter;
// init Isotope
var $container = $('.grid').isotope({
itemSelector: '.element-item',
layoutMode: 'vertical',
getSortData: {
country: '.destination-country',
state: '.destination-state',
city: '.destination-city',
resortType: '[data-resort-type]',
typeR: '.destination-type-1',
typeL: '.destination-type-2',
typeAll: '.destination-type-all'
},
filter: function() {
var $this = $(this);
var searchResult = qsRegex ? $this.text().match( qsRegex ) : true;
var buttonResult = buttonFilter ? $this.is( buttonFilter ) : true;
return searchResult && buttonResult;
},
// sort top priority to lowest priority
sortBy: ['resortType', 'country', 'state', 'city']
});
and here you can see how I can the isotope plugin.
// -------- Filter FUNCTION ----------//
$('.filter-by-button-group').on( 'click', 'button', function() {
buttonFilter = $( this ).attr('data-filter-value');
console.log("Filter button click",buttonFilter);
$container.isotope();
});
// ----------- Search FUNCTION --------//
// use value of search field to filter
var $quicksearch = $('.quicksearch').keyup( debounce( function() {
qsRegex = new RegExp( $quicksearch.val(), 'gi' );
console.log("Search input",qsRegex);
$container.isotope();
}) );
// ------------- Sort FUNCTION -------------//
// bind sort button click
$('.sort-by-button-group').on( 'click', 'button', function() {
var sortValue = $(this).attr('data-sort-value');
// make an array of values
sortValue = sortValue.split(',');
console.log("Sorting button click",sortValue);
$container.isotope({
sortBy: ['resortType', sortValue]
});
});
and also have the debounce so the filtering doesn't happen every millisecond
// debounce so filtering doesn't happen every millisecond
function debounce( fn, threshold ) {
var timeout;
return function debounced() {
if ( timeout ) {
clearTimeout( timeout );
}
function delayed() {
fn();
timeout = null;
}
setTimeout( delayed, threshold || 100 );
};
}
My HTML for each Item looks like this
<!-- ----------------------------------start resort item -------------------------------------------------- -->
<li class="destination-list element-item destination-type-all destination-type-1" data-resort-type="destination-type-all destination-type-1">
<div class="resort-details col-sm-2">
<div class="resortImage">
<img class="pull-left resort-img" src="./ResortListing_files/8804623745054.jpg" alt="Marriott's Canyon Villas" title="Marriott's Canyon Villas">
</div>
<div class="resortIcons col-md-12">
<span>
<i class="sr-only">Beach</i>
<img src="ResortListing_files/beach.png"/>
</span>
<span>
<i class="sr-only">Golf</i>
<img src="ResortListing_files/golf.png"/>
</span>
<span>
<i class="sr-only">Ski</i>
<img src="ResortListing_files/Ski.png"/>
</span>
<span>
<i class="sr-only">Theme Park</i>
<img src="ResortListing_files/theme_park.png"/>
</span>
<!--
<span>
<i class="sr-only">Urban</i>
<img src="ResortListing_files/urban.png"/>
</span>
-->
</div>
</div>
<div class="resort-details col-md-7">
<a id="resortNameLink" href="https://st01.owners.marriottvacationclub.com/timeshare/mvco/exploredestination/resorts/resortoverview?resortId=CV" class="resort-name">
Marriott's Newport Coast<sup>®</sup> Villas
</a>
<span class=" fa fa-star-o" style="color: #8B5F10 !important" data-target="#assocTModal" title="Marriott Vacation Regular Resort"></span>
<span class="association assoc-t" data-toggle="modal" data-target="#assocTModal" title="Marriott Vacation Club Trust Resort">
T
</span>
<span class="association assoc-e" data-toggle="modal" data-target="#assocEModal" title="Marriott Vacation Club Exchange Resort">
E
</span>
<div class="resortLocation">
<h2 class="destination-country">USA</h2>
<h4 class="destination-state">California</h4>
<h4 class="destination-city">Newport Coast</h4>
</div>
<p class="productdesc">Elegantly appointed and spacious villas accommodate up to 8 guests. Fitness center, two outdoor heated pools, whirlpool, plus separate children's pool. Sauna, sports court, putting green, and children's activity areas.</p>
</div>
<div class="resort-details actionButton col-md-2">
<!--<img src="http://cache.marriott.com/Images/MiniStores/Brand_Logos.png" />-->
<a href="#" class="resortBrandLogo cym">Court Yard Marriott</a>
<div class="resortListWeather transparent_class">
Weather: <strong>73.1°F</strong>
<img src="http://icons.wxug.com/i/c/k/cloudy.gif" alt="Sunny"/>
</div>
<a href="https://st01.owners.marriottvacationclub.com/timeshare/mvco/exploredestination/resorts/resortoverview?resortId=CV" title="View Marriott's Canyon Villas Resort" class="btn viewResortBtn btn-default" target="_">
<span class="fa fa-arrow-circle-o-right" style="color: #8B5F10 !important" data-target="#assocTModal"></span> View This Resort
</a>
</div>
<div class="clearfix"></div>
</li>
<!--close resort item -->
来源:https://stackoverflow.com/questions/29481512/isotope-combination-filters-search-and-sorts-messy-and-not-complete