altinn-designsystem
Version:
Altinn Design system based on Pattern Lab.
564 lines (500 loc) • 17.9 kB
JavaScript
/* globals $ */
var genericSearch = function() {
var dimensions;
var base;
var page = 0;
var articlesPerPage = 20;
var inputBy;
var selection = [];
var dataList;
var elements = {};
var keys = {
forceHiddenClass: 'a-js-forceHidden',
genericSearchSelector: '.a-js-genericSearch',
showResultsButtonSelector: '.a-js-expandResults',
tagFilterSectionSelector: '.a-card-filter',
generalArticleSelector: 'a-js-underneath'
};
function arrayIncludes(array, element) {
var newArray;
var includes;
if (array.includes) {
includes = array.includes(element);
} else { // IE
newArray = array.filter(function(el) {
return el === element;
});
includes = newArray.length > 0;
}
return includes;
}
function grinder(item) {
var i;
var j;
var itemDimension;
var isMatch = false;
var itemDimensionsCount = 0;
for (i = 0; i < dimensions.length; i += 1) {
itemDimensionsCount += item[dimensions[i].name].length;
for (j = 0; j < item[dimensions[i].name].length; j += 1) {
itemDimension = item[dimensions[i].name][j];
if (arrayIncludes(selection, 'd' + (i + 1) + '-' + itemDimension)) {
isMatch = true;
break;
}
}
}
// General item
if (itemDimensionsCount === 0) {
isMatch = true;
}
return isMatch;
}
function tags() {
return $(keys.tagFilterSectionSelector).find('input[type="checkbox"].sr-only');
}
function selectedTags() {
return $(keys.tagFilterSectionSelector).find('input[type="checkbox"]:checked.sr-only');
}
function urlFilterPrefix(id) {
return id.replace('filterDim1ID', 'd1-').replace('filterDim2ID', 'd2-');
}
function resetPage() {
page = 1;
}
// TODO: This method is copied from colnavCustom.js, should be put in a common
// module
function urlQuery(query) { // Parse current URL for query value
var _query = query.replace(/[[]/, '[').replace(/[\]]/, '\\]');
var expr = '[\\?&]' + _query + '=([^&#]*)';
var regex = new RegExp(expr);
var results = regex.exec(window.location.href);
if (results !== null) {
return results[1];
}
return false;
}
function getDataSource(index) {
var dataSources = $(keys.genericSearchSelector).attr('data-source').split(',');
var dataUrl = dataSources[index];
if (window.location.pathname.indexOf('/DesignSystem/') === -1 && window.location.origin.indexOf('/localhost') === -1) {
// Do not add the language attribute when running locally or in Github
dataUrl += '/' + $('html').attr('lang');
}
return dataUrl;
}
function getSelection() {
var id;
var idPattern = /d(\d+)-.*/;
var match;
var dimension;
var dimensionIndex;
var index;
selection = [];
for (index = 0; index < dimensions.length; index += 1) {
dimension = dimensions[index];
dimension.isSelected = false;
dimension.selectedCount = 0;
}
selectedTags().each(function() {
id = urlFilterPrefix($(this).attr('name'));
match = idPattern.exec(id);
if (match != null && match.length > 1) {
dimensionIndex = match[1] - 1;
dimensions[dimensionIndex].isSelected = true;
dimensions[dimensionIndex].selectedCount += 1;
}
selection.push(id);
});
}
function userHasSelectedTags() {
return selection.length > 0;
}
function setHistoryState() {
var newurl = window.location.pathname;
var urlQueryString = '?filter=';
if (selection.length > 0) {
urlQueryString += selection.join(',');
newurl += urlQueryString;
}
if (history.replaceState) {
window.history.replaceState({
path: newurl
}, '', newurl);
}
}
function getUrlFilter() {
if (urlQuery('filter')) {
selection = urlQuery('filter').split(',');
}
}
function hideContainers() {
elements.$container.hide();
if (elements.$altContainer !== null) {
elements.$altContainer.hide();
}
}
function showContainers() {
if (dimensions[1].isSelected) {
elements.$container.hide();
if (elements.$altContainer !== null) {
elements.$altContainer.show();
elements.$altContainer.removeClass(keys.forceHiddenClass);
}
} else {
elements.$container.show();
elements.$container.removeClass(keys.forceHiddenClass);
if (elements.$altContainer !== null) {
elements.$altContainer.hide();
}
}
}
function setElementsVisibility(filteredList) {
if (userHasSelectedTags()) {
elements.$loadMoreButton[filteredList.length <= articlesPerPage * page ? 'hide' : 'show']();
elements.$noResultsMessage[filteredList.length === 0 ? 'show' : 'hide']();
elements.$showResultsButton.removeAttr('disabled');
elements.$showResultsButton.removeClass(keys.forceHiddenClass);
elements.$showResultsButton.show();
} else {
elements.$showResultsButton.hide();
}
}
function showResults() {
$('.a-collapse-title').not('.collapsed').click();
elements.$container.removeClass(keys.forceHiddenClass);
if (elements.$altContainer !== null) {
elements.$altContainer.removeClass(keys.forceHiddenClass);
}
elements.$loadMoreButton.removeClass(keys.forceHiddenClass);
elements.$showResultsButton.hide();
showContainers();
$('body').scrollTop($('.a-js-filterDim1').offset().top - 12);
}
function setDimenstionLabels() {
var $dimensionSectionContainer = null;
var $noSelectionLabel = null;
var $selectionLabel = null;
var $selectionLabelType = null;
dimensions.forEach(function(dimension, index) {
$dimensionSectionContainer = $('.a-js-filterDim' + (index + 1));
$noSelectionLabel = $dimensionSectionContainer.find('.a-js-none');
$selectionLabel = $noSelectionLabel.prev();
$selectionLabel.find('.badge').html(dimension.selectedCount);
$selectionLabelType = $selectionLabel.find('.a-js-card-filter-type');
switch (dimension.selectedCount) {
case 0:
$noSelectionLabel.show();
$selectionLabel.hide();
break;
case 1:
$noSelectionLabel.hide();
$selectionLabel.show();
$selectionLabelType.text($selectionLabelType.attr('data-singular-text'));
break;
default:
$noSelectionLabel.hide();
$selectionLabel.show();
$selectionLabelType.text($selectionLabelType.attr('data-plural-text'));
break;
}
});
}
function hideResultItems() {
elements.$container.find('.a-js-result').hide();
if (elements.$altContainer !== null) {
elements.$altContainer.find('.a-js-result').hide();
}
}
function setAboveItemsVisibility(filteredList, maxNumberOfItemsToDisplay) {
var aboveCount = 0;
var i = 0;
var item;
while (i < filteredList.length && aboveCount < maxNumberOfItemsToDisplay) {
item = filteredList[i];
$('#' + item.id).show();
if (item.isAbove) {
$('#' + item.altId).show();
aboveCount += 1;
}
i += 1;
}
return aboveCount;
}
function setBelowItemsVisibility(filteredList, maxNumberOfItemsToDisplay) {
var showExtraHeading = false;
var belowCount = 0;
var i = 0;
var item;
var $altItem = null;
while (i < filteredList.length
&& belowCount < maxNumberOfItemsToDisplay) {
item = filteredList[i];
if (!item.isAbove) {
$altItem = $('#' + item.altId);
if ($altItem.hasClass(keys.generalArticleSelector)) {
showExtraHeading = true;
}
$altItem.show();
belowCount += 1;
}
i += 1;
}
return showExtraHeading;
}
function filterArticles() {
var aboveCount = 0;
var filteredList = [];
var showExtraHeading;
var maxNumberOfItemsToDisplay;
getSelection();
setHistoryState();
setDimenstionLabels();
hideResultItems();
filteredList = dataList.filter(grinder);
maxNumberOfItemsToDisplay = articlesPerPage * page;
aboveCount = setAboveItemsVisibility(filteredList, maxNumberOfItemsToDisplay);
if (aboveCount < maxNumberOfItemsToDisplay) {
maxNumberOfItemsToDisplay -= aboveCount;
showExtraHeading = setBelowItemsVisibility(filteredList, maxNumberOfItemsToDisplay);
}
if (showExtraHeading) {
elements.$extraResultsHeading.show();
} else {
elements.$extraResultsHeading.hide();
}
setElementsVisibility(filteredList);
hideContainers();
}
function appendExtraResultsHeading() {
if (elements.$altContainer !== null) {
elements.$altContainer.append('<span class="a-js-top"></span>');
elements.$altContainer.append(elements.$altContainer.attr('data-extraresultsheading'));
elements.$altContainer.append('<span class="a-js-bottom"></span>');
elements.$extraResultsHeading = $('.a-js-extraHeading');
}
}
function createResultElement(template, name, url, description, id, cssClasses) {
return template.replace('%NAME%', name)
.replace(/%URL%/g, url)
.replace('%DESC%', description || 'Ingen beskrivelse.')
.replace('%IDENTIFIER%', id)
.replace('a-linkArticle', cssClasses);
}
function buildResultsList(mappedKeys) {
var element;
var name;
var url;
var description;
var id;
var cssClasses;
dataList.forEach(function(item, index) {
dataList[index].id = 'result-' + index;
dataList[index].altId = 'altResult-' + index;
if (item.Purposes.length !== 0 || item.Industries.length !== 0) {
dataList[index].isAbove = true;
} else {
dataList[index].isAbove = false;
}
name = item[mappedKeys.NAME];
url = item[mappedKeys.URL];
description = item[mappedKeys.DESC] || 'Ingen beskrivelse.';
id = 'result-' + index;
cssClasses = 'a-linkArticle a-js-result';
element = createResultElement(base, name, url, description, id, cssClasses);
elements.$container.append(element);
id = 'altResult-' + index;
if (dataList[index].isAbove) {
element = createResultElement(base, name, url, description, id, cssClasses);
elements.$extraResultsHeading.before(element);
} else {
cssClasses = 'a-linkArticle a-js-result ' + keys.generalArticleSelector;
element = createResultElement(base, name, url, description, id, cssClasses);
if (elements.$altContainer !== null) {
elements.$altContainer.append(element);
}
}
});
elements.$container.find('.a-js-result').each(function(index, item) {
$(this)[index < articlesPerPage * page ? 'show' : 'hide']();
});
resetPage();
elements.$loader.hide();
filterArticles();
}
function toggleTag() {
resetPage();
filterArticles();
}
function getDimensionNames() {
var dimensionNames;
var dimensionAliases;
var dimensionIndex;
var parts;
var i;
dimensions = [];
dimensionNames = $(keys.genericSearchSelector).attr('data-dimensions').split(',');
dimensionAliases = $(keys.genericSearchSelector).attr('data-dimensionsaliases').split(',');
for (i = 0; i < dimensionNames.length; i += 1) {
dimensions.push({
name: dimensionNames[i],
alias: dimensionAliases[i],
isSelected: false,
selectedCount: 0
});
}
}
function getMappedKeys() {
var mappedKeys = {};
var parts;
$(keys.genericSearchSelector).attr('data-mappedkeys').split(',').forEach(function(pair) {
parts = pair.split('=');
mappedKeys[parts[0]] = parts[1];
});
return mappedKeys;
}
function buildTagsAndDimensions(data) {
var lastKeypress;
var iterate;
var mappedKeys;
getDimensionNames();
mappedKeys = getMappedKeys();
dimensions.forEach(function(dimension, index) {
var hasNote = $('.a-js-filterDim' + (index + 1)).find('.d-block').length > 0;
var where = data[dimension.name + 'List'] ?
data[dimension.name + 'List'] : data[dimensions[index].alias + 'List'];
where.forEach(function(item) {
var $tag = $('<div class="a-switch">' +
$('.a-js-filterDim' + (index + 1)).find('.a-switch').eq(0).html()
.replace(/%ID%/g, item[mappedKeys.ID])
.replace('%TITLE%', item[mappedKeys.TITLE]) + '</div>');
var $input = $tag.find('input[type="checkbox"]');
var tagId = urlFilterPrefix($input.attr('id'));
if (arrayIncludes(selection, tagId)) {
$input.attr('checked', true);
}
$('.a-js-filterDim' + (index + 1))
.find(hasNote ? '.d-block' : '.text-sm-center')[hasNote ? 'before' : 'append']($tag);
});
$('.a-js-filterDim' + (index + 1)).find('.a-switch').eq(0).hide();
});
tags().on('change', toggleTag);
// Give the browser time to update the UI
setTimeout(function() {
buildResultsList(mappedKeys);
}, 0);
}
function processData(data) {
var lastKeypress;
var iterate;
if (inputBy === 'filter') {
// We keep the order the in the data sent by the server
dataList = data.SubsidiesList;
}
$(keys.genericSearchSelector).next().find(keys.tagFilterSectionSelector).show();
if (inputBy === 'search') {
$(keys.genericSearchSelector).find('form').on('keyup keypress', function(e) {
var keyCode = e.keyCode || e.which;
if (keyCode === 13) {
e.preventDefault();
return false;
}
return true;
});
$(keys.genericSearchSelector).find('form').find('input[type=search]')
.on('keypress', function() {
lastKeypress = new Date().getTime();
iterate = true;
elements.$loader.show();
elements.$legend.hide();
elements.$noResultsMessage.hide();
elements.$container.html('');
}
);
setInterval(function() {
var value = $(keys.genericSearchSelector).find('form').find('input[type=search]')
.val();
var query = value !== undefined ? value.toLowerCase() : '';
if (query.length > 0 && (new Date().getTime() - lastKeypress > 1500) && iterate) {
iterate = false;
data.items.forEach(function(item) {
if (item.name.toLowerCase().indexOf(query) !== -1 ||
item.parent.toLowerCase().indexOf(query) !== -1) {
elements.$container[item.name.toLowerCase().indexOf(query) !== -1 ? 'prepend' : 'append'](
base.replace('%NAME%', item.name).replace('%PARENT%', item.parent)
.replace(/%URL%/g, item.url).replace('../..', '')
);
}
});
elements.$loader.hide();
elements.$noResultsMessage[elements.$container.html() === '' ? 'show' : 'hide']();
elements.$legend[elements.$container.html() === '' ? 'hide' : 'show']();
}
}, 2000);
} else {
buildTagsAndDimensions(data);
}
}
function onSecondError() {
$.getJSON(getDataSource(2), processData);
}
function onError() {
$.ajax({
type: 'GET', url: getDataSource(1), success: processData, error: onSecondError
});
}
function addEventHandlers() {
elements.$showResultsButton.on('click', showResults);
elements.$loadMoreButton.on('click', function() {
page += 1;
filterArticles();
showContainers();
});
}
function findElements() {
if (inputBy === 'search') {
elements.$container = $(keys.genericSearchSelector).find('.a-list');
elements.$altContainer = null;
} else {
elements.$container = $(keys.genericSearchSelector).next().find('.a-js-results');
elements.$altContainer = $(keys.genericSearchSelector).next().find('.a-js-alternativeResults');
}
base = elements.$container.html();
elements.$genericSearch = $(keys.genericSearchSelector);
if (inputBy !== 'search') {
elements.$genericSearch = elements.$genericSearch.next();
}
elements.$legend = elements.$genericSearch.find('.a-legend');
elements.$loader = elements.$genericSearch.find('.a-loader');
elements.$noResultsMessage = elements.$genericSearch.find('.a-js-noResults');
elements.$showResultsButton = $(keys.showResultsButtonSelector);
elements.$loadMoreButton = $('.a-js-moreResults');
}
function initialLayout() {
elements.$container.find('li:gt(0)').remove();
elements.$container.find('.a-js-result:gt(0)').remove();
elements.$container.html('');
if (elements.$altContainer !== null) {
elements.$altContainer.html('');
}
}
function getInputType() {
inputBy = $(keys.genericSearchSelector).find('input[type=search]').length > 0 ? 'search' : 'filter';
}
function getData() {
var dataUrl = getDataSource(0);
// This line only for development, do not commit uncommented
// dataUrl = '/data/getsubsidy.json';
$.ajax({ type: 'GET', url: dataUrl, success: processData, error: onError });
}
if ($(keys.genericSearchSelector).length > 0) {
getUrlFilter();
getInputType();
findElements();
initialLayout();
appendExtraResultsHeading();
addEventHandlers();
// Give the browser time to update the UI
setTimeout(getData, 0);
}
};