Closed nolybom closed 6 years ago
Hi,
Regarding showing the number of total shown targets on load, I would decouple your functionality from the onMixEnd
callback, and then call it firstly after instantiation, and then also on each onMixEnd
callback.
For example:
function renderTotalShow(state) {
$('.itemCount').html(state.totalShow)
}
var mixer = mixitup(container, {
callbacks: {
onMixEnd: renderTotalShow
}
});
var initialState = mixer.getState();
renderTotalShow(initialState);
Secondly, in terms of rendering a "human readable" list of active filters, the first question should be where do we get human readable "labels" for each filter from (because selectors alone are not human readable)? One option is your from own controls markup, assuming each control contains a human readable label inside it.
<button type="button" data-filter=".filter-1" data-label="Filter 1">Filter 1</button>
In the above example, you could each pull the label ("Filter 1") out of the button's textContent
property, or a better way would be to include it as a second data attribute as bove (data-label
).
When a mixitup control is active, it will have an active class added to it (e.g. '.mixitup-control-active'
), that you can use to query it by. If it's a checkbox or a select option, it will have a checked
or selected
attribute set which you could query it by in lieu of an active class.
Therefore, using the onMixEnd
callback again, we could query the DOM for active controls, iterate through them, reading in their data-label
values, and output that in your HTML.
Here's a basic example, the final format of your list is up to you.
var mixer = mixitup(container, {
callbacks: {
onMixEnd: function(state) {
renderTotalShow(state);
renderActiveFilters();
}
}
});
function renderActiveFilters() {
var activeControls = Array.from(document.querySelectorAll('.mixitup-control-active'));
var activeFiltersDiv = document.querySelector('.active-filters-div');
activeFilterDiv.innerHTML = '';
activeLabels = activeControls.map(function(activeControl) {
return activeControl.getAttribute('data-label');
});
activeFilterDiv.innerHTML = activeLabels.join(', '); // eg: 'Filter 1, Filter 2, Filter 3'
}
Very logic! And it works perfectly with all filter buttons and checkboxes with the slightly fixed code:
function renderTotalShow(state) {
$('.itemCount').html(state.totalShow)
}
function renderActiveFilters() {
var activeControls = Array.from(document.querySelectorAll('.mixitup-control-active, .checkbox-style:checked, .userInput'));
var activeFiltersDiv = document.querySelector('.active-filters-div');
activeFiltersDiv.innerHTML = '';
activeLabels = activeControls.map(function(activeControl) {
return activeControl.getAttribute('data-label');
});
activeFiltersDiv.innerHTML = activeLabels.join(', '); // eg: 'Filter 1, Filter 2, Filter 3'
}
var mixer = mixitup(containerEl, {
callbacks: {
onMixEnd: function(state) {
renderTotalShow(state);
renderActiveFilters();
}
}
});
var initialState = mixer.getState();
renderTotalShow(initialState);
To finish this up all there is still needed is the user input text and the select options.
Since the value of data-label on the input text field is depending on users input i thought mirroring users input might make sense:
$('.userInput').on('keyup', function() { if( !$(this).val() ) { var value = $(this).val(); $(this).attr('data-label', value); } });
It works but the output then looks like this when starting to filter with a button:
, , Filter 1
..and when typing in something then:
, textinput
Regarding getting info from a select option i have taken many paths but none threw the data-label out. I guess when using bootstrap-select one must maybe mirror the value as well because the markup is set by the script!?
I see light! So close to wrap this up. :-)
Couple of ideas for you:
<input class="user-input" type="text"/>
function renderActiveFilters() {
var activeControls = Array.from(document.querySelectorAll('.mixitup-control-active, .checkbox-style:checked'));
var userInput = document.querySelector('.user-input');
var activeFiltersDiv = document.querySelector('.active-filters-div');
activeFiltersDiv.innerHTML = '';
activeLabels = activeControls.map(function(activeControl) {
return activeControl.getAttribute('data-label');
});
// Add the value from the text input
if (userInput.value !== '') {
activeLabels.push(userInput.value);
}
activeFiltersDiv.innerHTML = activeLabels.join(', '); // eg: 'Filter 1, Filter 2, Filter 3'
}
<option>
:<select class="user-select">
<option value=".filter-1" data-label="Filter 1">Filter 1</option>
...
</select>
function renderActiveFilters() {
var activeControls = Array.from(document.querySelectorAll('.mixitup-control-active, .checkbox-style:checked'));
var userInput = document.querySelector('.user-input');
var userSelect = document.querySelector('.user-select');
var activeFiltersDiv = document.querySelector('.active-filters-div');
var selectedOption = userSelect.selectedOptions[0] || null;
// Add selected option to list of active controls
if (selectedOption) {
activeControls.push(selectedOption);
}
activeFiltersDiv.innerHTML = '';
activeLabels = activeControls.map(function(activeControl) {
return activeControl.getAttribute('data-label');
});
// Add the value from the text input to active labels
if (userInput.value !== '') {
activeLabels.push(userInput.value);
}
activeFiltersDiv.innerHTML = activeLabels.join(', '); // eg: 'Filter 1, Filter 2, Filter 3'
}
I would like to show the number of items when mixitup is finished loading.
I couldn't find a way to achieve that so i am doing this workaround:
<h5>Showing <span class="itemCount">all</span> properties</h5>
onMixEnd: function(state){ $('.itemCount').html(state.totalShow) },
That way it indicates that properties are shown at the first place and the number gets refreshed after a filter has been triggered. Is there another path to take to display the number of items onload?
And in addition to that i would very much aim to print the active filters as html text into a defined div element. This is because some of my filters are hidden behind a push panel and not visible to the user. Therefor i think it is user friendlier to have the active filters be always visible.
console.log(state.activeFilter)
shows the active filters in the console as
selector: ".option1.filter1, .option2.filter1, ..."
But how would one print them in a human readable way into the html?