Sorry, it’s list.js – https://raw.githubusercontent.com/javve/list.js/v2.3.1/dist/list.js
var List;List =
/******/ (function() { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./src/add-async.js":
/*!**************************!*\
!*** ./src/add-async.js ***!
\**************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module) {
module.exports = function (list) {
var addAsync = function addAsync(values, callback, items) {
var valuesToAdd = values.splice(0, 50);
items = items || [];
items = items.concat(list.add(valuesToAdd));
if (values.length > 0) {
setTimeout(function () {
addAsync(values, callback, items);
}, 1);
} else {
list.update();
callback(items);
}
};
return addAsync;
};
/***/ }),
/***/ "./src/filter.js":
/*!***********************!*\
!*** ./src/filter.js ***!
\***********************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module) {
module.exports = function (list) {
// Add handlers
list.handlers.filterStart = list.handlers.filterStart || [];
list.handlers.filterComplete = list.handlers.filterComplete || [];
return function (filterFunction) {
list.trigger('filterStart');
list.i = 1; // Reset paging
list.reset.filter();
if (filterFunction === undefined) {
list.filtered = false;
} else {
list.filtered = true;
var is = list.items;
for (var i = 0, il = is.length; i < il; i++) {
var item = is[i];
if (filterFunction(item)) {
item.filtered = true;
} else {
item.filtered = false;
}
}
}
list.update();
list.trigger('filterComplete');
return list.visibleItems;
};
};
/***/ }),
/***/ "./src/fuzzy-search.js":
/*!*****************************!*\
!*** ./src/fuzzy-search.js ***!
\*****************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module, __webpack_require__ */
/*! CommonJS bailout: module.exports is used directly at 8:0-14 */
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
var classes = __webpack_require__(/*! ./utils/classes */ "./src/utils/classes.js"),
events = __webpack_require__(/*! ./utils/events */ "./src/utils/events.js"),
extend = __webpack_require__(/*! ./utils/extend */ "./src/utils/extend.js"),
toString = __webpack_require__(/*! ./utils/to-string */ "./src/utils/to-string.js"),
getByClass = __webpack_require__(/*! ./utils/get-by-class */ "./src/utils/get-by-class.js"),
fuzzy = __webpack_require__(/*! ./utils/fuzzy */ "./src/utils/fuzzy.js");
module.exports = function (list, options) {
options = options || {};
options = extend({
location: 0,
distance: 100,
threshold: 0.4,
multiSearch: true,
searchClass: 'fuzzy-search'
}, options);
var fuzzySearch = {
search: function search(searchString, columns) {
// Substract arguments from the searchString or put searchString as only argument
var searchArguments = options.multiSearch ? searchString.replace(/ +$/, '').split(/ +/) : [searchString];
for (var k = 0, kl = list.items.length; k < kl; k++) {
fuzzySearch.item(list.items[k], columns, searchArguments);
}
},
item: function item(_item, columns, searchArguments) {
var found = true;
for (var i = 0; i < searchArguments.length; i++) {
var foundArgument = false;
for (var j = 0, jl = columns.length; j < jl; j++) {
if (fuzzySearch.values(_item.values(), columns[j], searchArguments[i])) {
foundArgument = true;
}
}
if (!foundArgument) {
found = false;
}
}
_item.found = found;
},
values: function values(_values, value, searchArgument) {
if (_values.hasOwnProperty(value)) {
var text = toString(_values[value]).toLowerCase();
if (fuzzy(text, searchArgument, options)) {
return true;
}
}
return false;
}
};
events.bind(getByClass(list.listContainer, options.searchClass), 'keyup', list.utils.events.debounce(function (e) {
var target = e.target || e.srcElement; // IE have srcElement
list.search(target.value, fuzzySearch.search);
}, list.searchDelay));
return function (str, columns) {
list.search(str, columns, fuzzySearch.search);
};
};
/***/ }),
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module, __webpack_require__ */
/*! CommonJS bailout: module.exports is used directly at 11:0-14 */
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
var naturalSort = __webpack_require__(/*! string-natural-compare */ "./node_modules/string-natural-compare/natural-compare.js"),
getByClass = __webpack_require__(/*! ./utils/get-by-class */ "./src/utils/get-by-class.js"),
extend = __webpack_require__(/*! ./utils/extend */ "./src/utils/extend.js"),
indexOf = __webpack_require__(/*! ./utils/index-of */ "./src/utils/index-of.js"),
events = __webpack_require__(/*! ./utils/events */ "./src/utils/events.js"),
toString = __webpack_require__(/*! ./utils/to-string */ "./src/utils/to-string.js"),
classes = __webpack_require__(/*! ./utils/classes */ "./src/utils/classes.js"),
getAttribute = __webpack_require__(/*! ./utils/get-attribute */ "./src/utils/get-attribute.js"),
toArray = __webpack_require__(/*! ./utils/to-array */ "./src/utils/to-array.js");
module.exports = function (id, options, values) {
var self = this,
init,
Item = __webpack_require__(/*! ./item */ "./src/item.js")(self),
addAsync = __webpack_require__(/*! ./add-async */ "./src/add-async.js")(self),
initPagination = __webpack_require__(/*! ./pagination */ "./src/pagination.js")(self);
init = {
start: function start() {
self.listClass = 'list';
self.searchClass = 'search';
self.sortClass = 'sort';
self.page = 10000;
self.i = 1;
self.items = [];
self.visibleItems = [];
self.matchingItems = [];
self.searched = false;
self.filtered = false;
self.searchColumns = undefined;
self.searchDelay = 0;
self.handlers = {
updated: []
};
self.valueNames = [];
self.utils = {
getByClass: getByClass,
extend: extend,
indexOf: indexOf,
events: events,
toString: toString,
naturalSort: naturalSort,
classes: classes,
getAttribute: getAttribute,
toArray: toArray
};
self.utils.extend(self, options);
self.listContainer = typeof id === 'string' ? document.getElementById(id) : id;
if (!self.listContainer) {
return;
}
self.list = getByClass(self.listContainer, self.listClass, true);
self.parse = __webpack_require__(/*! ./parse */ "./src/parse.js")(self);
self.templater = __webpack_require__(/*! ./templater */ "./src/templater.js")(self);
self.search = __webpack_require__(/*! ./search */ "./src/search.js")(self);
self.filter = __webpack_require__(/*! ./filter */ "./src/filter.js")(self);
self.sort = __webpack_require__(/*! ./sort */ "./src/sort.js")(self);
self.fuzzySearch = __webpack_require__(/*! ./fuzzy-search */ "./src/fuzzy-search.js")(self, options.fuzzySearch);
this.handlers();
this.items();
this.pagination();
self.update();
},
handlers: function handlers() {
for (var handler in self.handlers) {
if (self[handler] && self.handlers.hasOwnProperty(handler)) {
self.on(handler, self[handler]);
}
}
},
items: function items() {
self.parse(self.list);
if (values !== undefined) {
self.add(values);
}
},
pagination: function pagination() {
if (options.pagination !== undefined) {
if (options.pagination === true) {
options.pagination = [{}];
}
if (options.pagination[0] === undefined) {
options.pagination = [options.pagination];
}
for (var i = 0, il = options.pagination.length; i < il; i++) {
initPagination(options.pagination[i]);
}
}
}
};
/*
* Re-parse the List, use if html have changed
*/
this.reIndex = function () {
self.items = [];
self.visibleItems = [];
self.matchingItems = [];
self.searched = false;
self.filtered = false;
self.parse(self.list);
};
this.toJSON = function () {
var json = [];
for (var i = 0, il = self.items.length; i < il; i++) {
json.push(self.items[i].values());
}
return json;
};
/*
* Add object to list
*/
this.add = function (values, callback) {
if (values.length === 0) {
return;
}
if (callback) {
addAsync(values.slice(0), callback);
return;
}
var added = [],
notCreate = false;
if (values[0] === undefined) {
values = [values];
}
for (var i = 0, il = values.length; i < il; i++) {
var item = null;
notCreate = self.items.length > self.page ? true : false;
item = new Item(values[i], undefined, notCreate);
self.items.push(item);
added.push(item);
}
self.update();
return added;
};
this.show = function (i, page) {
this.i = i;
this.page = page;
self.update();
return self;
};
/* Removes object from list.
* Loops through the list and removes objects where
* property "valuename" === value
*/
this.remove = function (valueName, value, options) {
var found = 0;
for (var i = 0, il = self.items.length; i < il; i++) {
if (self.items[i].values()[valueName] == value) {
self.templater.remove(self.items[i], options);
self.items.splice(i, 1);
il--;
i--;
found++;
}
}
self.update();
return found;
};
/* Gets the objects in the list which
* property "valueName" === value
*/
this.get = function (valueName, value) {
var matchedItems = [];
for (var i = 0, il = self.items.length; i < il; i++) {
var item = self.items[i];
if (item.values()[valueName] == value) {
matchedItems.push(item);
}
}
return matchedItems;
};
/*
* Get size of the list
*/
this.size = function () {
return self.items.length;
};
/*
* Removes all items from the list
*/
this.clear = function () {
self.templater.clear();
self.items = [];
return self;
};
this.on = function (event, callback) {
self.handlers[event].push(callback);
return self;
};
this.off = function (event, callback) {
var e = self.handlers[event];
var index = indexOf(e, callback);
if (index > -1) {
e.splice(index, 1);
}
return self;
};
this.trigger = function (event) {
var i = self.handlers[event].length;
while (i--) {
self.handlers[event][i](self);
}
return self;
};
this.reset = {
filter: function filter() {
var is = self.items,
il = is.length;
while (il--) {
is[il].filtered = false;
}
return self;
},
search: function search() {
var is = self.items,
il = is.length;
while (il--) {
is[il].found = false;
}
return self;
}
};
this.update = function () {
var is = self.items,
il = is.length;
self.visibleItems = [];
self.matchingItems = [];
self.templater.clear();
for (var i = 0; i < il; i++) {
if (is[i].matching() && self.matchingItems.length + 1 >= self.i && self.visibleItems.length < self.page) {
is[i].show();
self.visibleItems.push(is[i]);
self.matchingItems.push(is[i]);
} else if (is[i].matching()) {
self.matchingItems.push(is[i]);
is[i].hide();
} else {
is[i].hide();
}
}
self.trigger('updated');
return self;
};
init.start();
};
/***/ }),
/***/ "./src/item.js":
/*!*********************!*\
!*** ./src/item.js ***!
\*********************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module) {
module.exports = function (list) {
return function (initValues, element, notCreate) {
var item = this;
this._values = {};
this.found = false; // Show if list.searched == true and this.found == true
this.filtered = false; // Show if list.filtered == true and this.filtered == true
var init = function init(initValues, element, notCreate) {
if (element === undefined) {
if (notCreate) {
item.values(initValues, notCreate);
} else {
item.values(initValues);
}
} else {
item.elm = element;
var values = list.templater.get(item, initValues);
item.values(values);
}
};
this.values = function (newValues, notCreate) {
if (newValues !== undefined) {
for (var name in newValues) {
item._values[name] = newValues[name];
}
if (notCreate !== true) {
list.templater.set(item, item.values());
}
} else {
return item._values;
}
};
this.show = function () {
list.templater.show(item);
};
this.hide = function () {
list.templater.hide(item);
};
this.matching = function () {
return list.filtered && list.searched && item.found && item.filtered || list.filtered && !list.searched && item.filtered || !list.filtered && list.searched && item.found || !list.filtered && !list.searched;
};
this.visible = function () {
return item.elm && item.elm.parentNode == list.list ? true : false;
};
init(initValues, element, notCreate);
};
};
/***/ }),
/***/ "./src/pagination.js":
/*!***************************!*\
!*** ./src/pagination.js ***!
\***************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module, __webpack_require__ */
/*! CommonJS bailout: module.exports is used directly at 5:0-14 */
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
var classes = __webpack_require__(/*! ./utils/classes */ "./src/utils/classes.js"),
events = __webpack_require__(/*! ./utils/events */ "./src/utils/events.js"),
List = __webpack_require__(/*! ./index */ "./src/index.js");
module.exports = function (list) {
var isHidden = false;
var refresh = function refresh(pagingList, options) {
if (list.page < 1) {
list.listContainer.style.display = 'none';
isHidden = true;
return;
} else if (isHidden) {
list.listContainer.style.display = 'block';
}
var item,
l = list.matchingItems.length,
index = list.i,
page = list.page,
pages = Math.ceil(l / page),
currentPage = Math.ceil(index / page),
innerWindow = options.innerWindow || 2,
left = options.left || options.outerWindow || 0,
right = options.right || options.outerWindow || 0;
right = pages - right;
pagingList.clear();
for (var i = 1; i <= pages; i++) {
var className = currentPage === i ? 'active' : ''; //console.log(i, left, right, currentPage, (currentPage - innerWindow), (currentPage + innerWindow), className);
if (is.number(i, left, right, currentPage, innerWindow)) {
item = pagingList.add({
page: i,
dotted: false
})[0];
if (className) {
classes(item.elm).add(className);
}
item.elm.firstChild.setAttribute('data-i', i);
item.elm.firstChild.setAttribute('data-page', page);
} else if (is.dotted(pagingList, i, left, right, currentPage, innerWindow, pagingList.size())) {
item = pagingList.add({
page: '...',
dotted: true
})[0];
classes(item.elm).add('disabled');
}
}
};
var is = {
number: function number(i, left, right, currentPage, innerWindow) {
return this.left(i, left) || this.right(i, right) || this.innerWindow(i, currentPage, innerWindow);
},
left: function left(i, _left) {
return i <= _left;
},
right: function right(i, _right) {
return i > _right;
},
innerWindow: function innerWindow(i, currentPage, _innerWindow) {
return i >= currentPage - _innerWindow && i <= currentPage + _innerWindow;
},
dotted: function dotted(pagingList, i, left, right, currentPage, innerWindow, currentPageItem) {
return this.dottedLeft(pagingList, i, left, right, currentPage, innerWindow) || this.dottedRight(pagingList, i, left, right, currentPage, innerWindow, currentPageItem);
},
dottedLeft: function dottedLeft(pagingList, i, left, right, currentPage, innerWindow) {
return i == left + 1 && !this.innerWindow(i, currentPage, innerWindow) && !this.right(i, right);
},
dottedRight: function dottedRight(pagingList, i, left, right, currentPage, innerWindow, currentPageItem) {
if (pagingList.items[currentPageItem - 1].values().dotted) {
return false;
} else {
return i == right && !this.innerWindow(i, currentPage, innerWindow) && !this.right(i, right);
}
}
};
return function (options) {
var pagingList = new List(list.listContainer.id, {
listClass: options.paginationClass || 'pagination',
item: options.item || "<li><a class='page' href='#'></a></li>",
valueNames: ['page', 'dotted'],
searchClass: 'pagination-search-that-is-not-supposed-to-exist',
sortClass: 'pagination-sort-that-is-not-supposed-to-exist'
});
events.bind(pagingList.listContainer, 'click', function (e) {
var target = e.target || e.srcElement,
page = list.utils.getAttribute(target, 'data-page'),
i = list.utils.getAttribute(target, 'data-i');
if (i) {
list.show((i - 1) * page + 1, page);
}
});
list.on('updated', function () {
refresh(pagingList, options);
});
refresh(pagingList, options);
};
};
/***/ }),
/***/ "./src/parse.js":
/*!**********************!*\
!*** ./src/parse.js ***!
\**********************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module, __webpack_require__ */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
module.exports = function (list) {
var Item = __webpack_require__(/*! ./item */ "./src/item.js")(list);
var getChildren = function getChildren(parent) {
var nodes = parent.childNodes,
items = [];
for (var i = 0, il = nodes.length; i < il; i++) {
// Only textnodes have a data attribute
if (nodes[i].data === undefined) {
items.push(nodes[i]);
}
}
return items;
};
var parse = function parse(itemElements, valueNames) {
for (var i = 0, il = itemElements.length; i < il; i++) {
list.items.push(new Item(valueNames, itemElements[i]));
}
};
var parseAsync = function parseAsync(itemElements, valueNames) {
var itemsToIndex = itemElements.splice(0, 50); // TODO: If < 100 items, what happens in IE etc?
parse(itemsToIndex, valueNames);
if (itemElements.length > 0) {
setTimeout(function () {
parseAsync(itemElements, valueNames);
}, 1);
} else {
list.update();
list.trigger('parseComplete');
}
};
list.handlers.parseComplete = list.handlers.parseComplete || [];
return function () {
var itemsToIndex = getChildren(list.list),
valueNames = list.valueNames;
if (list.indexAsync) {
parseAsync(itemsToIndex, valueNames);
} else {
parse(itemsToIndex, valueNames);
}
};
};
/***/ }),
/***/ "./src/search.js":
/*!***********************!*\
!*** ./src/search.js ***!
\***********************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module) {
module.exports = function (_list) {
var item, text, columns, searchString, customSearch;
var prepare = {
resetList: function resetList() {
_list.i = 1;
_list.templater.clear();
customSearch = undefined;
},
setOptions: function setOptions(args) {
if (args.length == 2 && args[1] instanceof Array) {
columns = args[1];
} else if (args.length == 2 && typeof args[1] == 'function') {
columns = undefined;
customSearch = args[1];
} else if (args.length == 3) {
columns = args[1];
customSearch = args[2];
} else {
columns = undefined;
}
},
setColumns: function setColumns() {
if (_list.items.length === 0) return;
if (columns === undefined) {
columns = _list.searchColumns === undefined ? prepare.toArray(_list.items[0].values()) : _list.searchColumns;
}
},
setSearchString: function setSearchString(s) {
s = _list.utils.toString(s).toLowerCase();
s = s.replace(/[-[\]{}()*+?.,\\^$|#]/g, '\\$&'); // Escape regular expression characters
searchString = s;
},
toArray: function toArray(values) {
var tmpColumn = [];
for (var name in values) {
tmpColumn.push(name);
}
return tmpColumn;
}
};
var search = {
list: function list() {
// Extract quoted phrases "word1 word2" from original searchString
// searchString is converted to lowercase by List.js
var words = [],
phrase,
ss = searchString;
while ((phrase = ss.match(/"([^"]+)"/)) !== null) {
words.push(phrase[1]);
ss = ss.substring(0, phrase.index) + ss.substring(phrase.index + phrase[0].length);
} // Get remaining space-separated words (if any)
ss = ss.trim();
if (ss.length) words = words.concat(ss.split(/\s+/));
for (var k = 0, kl = _list.items.length; k < kl; k++) {
var item = _list.items[k];
item.found = false;
if (!words.length) continue;
for (var i = 0, il = words.length; i < il; i++) {
var word_found = false;
for (var j = 0, jl = columns.length; j < jl; j++) {
var values = item.values(),
column = columns[j];
if (values.hasOwnProperty(column) && values[column] !== undefined && values[column] !== null) {
var text = typeof values[column] !== 'string' ? values[column].toString() : values[column];
if (text.toLowerCase().indexOf(words[i]) !== -1) {
// word found, so no need to check it against any other columns
word_found = true;
break;
}
}
} // this word not found? no need to check any other words, the item cannot match
if (!word_found) break;
}
item.found = word_found;
}
},
// Removed search.item() and search.values()
reset: function reset() {
_list.reset.search();
_list.searched = false;
}
};
var searchMethod = function searchMethod(str) {
_list.trigger('searchStart');
prepare.resetList();
prepare.setSearchString(str);
prepare.setOptions(arguments); // str, cols|searchFunction, searchFunction
prepare.setColumns();
if (searchString === '') {
search.reset();
} else {
_list.searched = true;
if (customSearch) {
customSearch(searchString, columns);
} else {
search.list();
}
}
_list.update();
_list.trigger('searchComplete');
return _list.visibleItems;
};
_list.handlers.searchStart = _list.handlers.searchStart || [];
_list.handlers.searchComplete = _list.handlers.searchComplete || [];
_list.utils.events.bind(_list.utils.getByClass(_list.listContainer, _list.searchClass), 'keyup', _list.utils.events.debounce(function (e) {
var target = e.target || e.srcElement,
// IE have srcElement
alreadyCleared = target.value === '' && !_list.searched;
if (!alreadyCleared) {
// If oninput already have resetted the list, do nothing
searchMethod(target.value);
}
}, _list.searchDelay)); // Used to detect click on HTML5 clear button
_list.utils.events.bind(_list.utils.getByClass(_list.listContainer, _list.searchClass), 'input', function (e) {
var target = e.target || e.srcElement;
if (target.value === '') {
searchMethod('');
}
});
return searchMethod;
};
/***/ }),
/***/ "./src/sort.js":
/*!*********************!*\
!*** ./src/sort.js ***!
\*********************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module) {
module.exports = function (list) {
var buttons = {
els: undefined,
clear: function clear() {
for (var i = 0, il = buttons.els.length; i < il; i++) {
list.utils.classes(buttons.els[i]).remove('asc');
list.utils.classes(buttons.els[i]).remove('desc');
}
},
getOrder: function getOrder(btn) {
var predefinedOrder = list.utils.getAttribute(btn, 'data-order');
if (predefinedOrder == 'asc' || predefinedOrder == 'desc') {
return predefinedOrder;
} else if (list.utils.classes(btn).has('desc')) {
return 'asc';
} else if (list.utils.classes(btn).has('asc')) {
return 'desc';
} else {
return 'asc';
}
},
getInSensitive: function getInSensitive(btn, options) {
var insensitive = list.utils.getAttribute(btn, 'data-insensitive');
if (insensitive === 'false') {
options.insensitive = false;
} else {
options.insensitive = true;
}
},
setOrder: function setOrder(options) {
for (var i = 0, il = buttons.els.length; i < il; i++) {
var btn = buttons.els[i];
if (list.utils.getAttribute(btn, 'data-sort') !== options.valueName) {
continue;
}
var predefinedOrder = list.utils.getAttribute(btn, 'data-order');
if (predefinedOrder == 'asc' || predefinedOrder == 'desc') {
if (predefinedOrder == options.order) {
list.utils.classes(btn).add(options.order);
}
} else {
list.utils.classes(btn).add(options.order);
}
}
}
};
var sort = function sort() {
list.trigger('sortStart');
var options = {};
var target = arguments[0].currentTarget || arguments[0].srcElement || undefined;
if (target) {
options.valueName = list.utils.getAttribute(target, 'data-sort');
buttons.getInSensitive(target, options);
options.order = buttons.getOrder(target);
} else {
options = arguments[1] || options;
options.valueName = arguments[0];
options.order = options.order || 'asc';
options.insensitive = typeof options.insensitive == 'undefined' ? true : options.insensitive;
}
buttons.clear();
buttons.setOrder(options); // caseInsensitive
// alphabet
var customSortFunction = options.sortFunction || list.sortFunction || null,
multi = options.order === 'desc' ? -1 : 1,
sortFunction;
if (customSortFunction) {
sortFunction = function sortFunction(itemA, itemB) {
return customSortFunction(itemA, itemB, options) * multi;
};
} else {
sortFunction = function sortFunction(itemA, itemB) {
var sort = list.utils.naturalSort;
sort.alphabet = list.alphabet || options.alphabet || undefined;
if (!sort.alphabet && options.insensitive) {
sort = list.utils.naturalSort.caseInsensitive;
}
return sort(itemA.values()[options.valueName], itemB.values()[options.valueName]) * multi;
};
}
list.items.sort(sortFunction);
list.update();
list.trigger('sortComplete');
}; // Add handlers
list.handlers.sortStart = list.handlers.sortStart || [];
list.handlers.sortComplete = list.handlers.sortComplete || [];
buttons.els = list.utils.getByClass(list.listContainer, list.sortClass);
list.utils.events.bind(buttons.els, 'click', sort);
list.on('searchStart', buttons.clear);
list.on('filterStart', buttons.clear);
return sort;
};
/***/ }),
/***/ "./src/templater.js":
/*!**************************!*\
!*** ./src/templater.js ***!
\**************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 216:0-14 */
/***/ (function(module) {
var Templater = function Templater(list) {
var createItem,
templater = this;
var init = function init() {
var itemSource;
if (typeof list.item === 'function') {
createItem = function createItem(values) {
var item = list.item(values);
return getItemSource(item);
};
return;
}
if (typeof list.item === 'string') {
if (list.item.indexOf('<') === -1) {
itemSource = document.getElementById(list.item);
} else {
itemSource = getItemSource(list.item);
}
} else {
/* If item source does not exists, use the first item in list as
source for new items */
itemSource = getFirstListItem();
}
if (!itemSource) {
throw new Error("The list needs to have at least one item on init otherwise you'll have to add a template.");
}
itemSource = createCleanTemplateItem(itemSource, list.valueNames);
createItem = function createItem() {
return itemSource.cloneNode(true);
};
};
var createCleanTemplateItem = function createCleanTemplateItem(templateNode, valueNames) {
var el = templateNode.cloneNode(true);
el.removeAttribute('id');
for (var i = 0, il = valueNames.length; i < il; i++) {
var elm = undefined,
valueName = valueNames[i];
if (valueName.data) {
for (var j = 0, jl = valueName.data.length; j < jl; j++) {
el.setAttribute('data-' + valueName.data[j], '');
}
} else if (valueName.attr && valueName.name) {
elm = list.utils.getByClass(el, valueName.name, true);
if (elm) {
elm.setAttribute(valueName.attr, '');
}
} else {
elm = list.utils.getByClass(el, valueName, true);
if (elm) {
elm.innerHTML = '';
}
}
}
return el;
};
var getFirstListItem = function getFirstListItem() {
var nodes = list.list.childNodes;
for (var i = 0, il = nodes.length; i < il; i++) {
// Only textnodes have a data attribute
if (nodes[i].data === undefined) {
return nodes[i].cloneNode(true);
}
}
return undefined;
};
var getItemSource = function getItemSource(itemHTML) {
if (typeof itemHTML !== 'string') return undefined;
if (/<tr[\s>]/g.exec(itemHTML)) {
var tbody = document.createElement('tbody');
tbody.innerHTML = itemHTML;
return tbody.firstElementChild;
} else if (itemHTML.indexOf('<') !== -1) {
var div = document.createElement('div');
div.innerHTML = itemHTML;
return div.firstElementChild;
}
return undefined;
};
var getValueName = function getValueName(name) {
for (var i = 0, il = list.valueNames.length; i < il; i++) {
var valueName = list.valueNames[i];
if (valueName.data) {
var data = valueName.data;
for (var j = 0, jl = data.length; j < jl; j++) {
if (data[j] === name) {
return {
data: name
};
}
}
} else if (valueName.attr && valueName.name && valueName.name == name) {
return valueName;
} else if (valueName === name) {
return name;
}
}
};
var setValue = function setValue(item, name, value) {
var elm = undefined,
valueName = getValueName(name);
if (!valueName) return;
if (valueName.data) {
item.elm.setAttribute('data-' + valueName.data, value);
} else if (valueName.attr && valueName.name) {
elm = list.utils.getByClass(item.elm, valueName.name, true);
if (elm) {
elm.setAttribute(valueName.attr, value);
}
} else {
elm = list.utils.getByClass(item.elm, valueName, true);
if (elm) {
elm.innerHTML = value;
}
}
};
this.get = function (item, valueNames) {
templater.create(item);
var values = {};
for (var i = 0, il = valueNames.length; i < il; i++) {
var elm = undefined,
valueName = valueNames[i];
if (valueName.data) {
for (var j = 0, jl = valueName.data.length; j < jl; j++) {
values[valueName.data[j]] = list.utils.getAttribute(item.elm, 'data-' + valueName.data[j]);
}
} else if (valueName.attr && valueName.name) {
elm = list.utils.getByClass(item.elm, valueName.name, true);
values[valueName.name] = elm ? list.utils.getAttribute(elm, valueName.attr) : '';
} else {
elm = list.utils.getByClass(item.elm, valueName, true);
values[valueName] = elm ? elm.innerHTML : '';
}
}
return values;
};
this.set = function (item, values) {
if (!templater.create(item)) {
for (var v in values) {
if (values.hasOwnProperty(v)) {
setValue(item, v, values[v]);
}
}
}
};
this.create = function (item) {
if (item.elm !== undefined) {
return false;
}
item.elm = createItem(item.values());
templater.set(item, item.values());
return true;
};
this.remove = function (item) {
if (item.elm.parentNode === list.list) {
list.list.removeChild(item.elm);
}
};
this.show = function (item) {
templater.create(item);
list.list.appendChild(item.elm);
};
this.hide = function (item) {
if (item.elm !== undefined && item.elm.parentNode === list.list) {
list.list.removeChild(item.elm);
}
};
this.clear = function () {
/* .innerHTML = ''; fucks up IE */
if (list.list.hasChildNodes()) {
while (list.list.childNodes.length >= 1) {
list.list.removeChild(list.list.firstChild);
}
}
};
init();
};
module.exports = function (list) {
return new Templater(list);
};
/***/ }),
/***/ "./src/utils/classes.js":
/*!******************************!*\
!*** ./src/utils/classes.js ***!
\******************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module, __webpack_require__ */
/*! CommonJS bailout: module.exports is used directly at 24:0-14 */
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
/**
* Module dependencies.
*/
var index = __webpack_require__(/*! ./index-of */ "./src/utils/index-of.js");
/**
* Whitespace regexp.
*/
var re = /\s+/;
/**
* toString reference.
*/
var toString = Object.prototype.toString;
/**
* Wrap <code>el</code> in a <code>ClassList</code>.
*
* @param {Element} el
* @return {ClassList}
* @api public
*/
module.exports = function (el) {
return new ClassList(el);
};
/**
* Initialize a new ClassList for <code>el</code>.
*
* @param {Element} el
* @api private
*/
function ClassList(el) {
if (!el || !el.nodeType) {
throw new Error('A DOM element reference is required');
}
this.el = el;
this.list = el.classList;
}
/**
* Add class <code>name</code> if not already present.
*
* @param {String} name
* @return {ClassList}
* @api public
*/
ClassList.prototype.add = function (name) {
// classList
if (this.list) {
this.list.add(name);
return this;
} // fallback
var arr = this.array();
var i = index(arr, name);
if (!~i) arr.push(name);
this.el.className = arr.join(' ');
return this;
};
/**
* Remove class <code>name</code> when present, or
* pass a regular expression to remove
* any which match.
*
* @param {String|RegExp} name
* @return {ClassList}
* @api public
*/
ClassList.prototype.remove = function (name) {
// classList
if (this.list) {
this.list.remove(name);
return this;
} // fallback
var arr = this.array();
var i = index(arr, name);
if (~i) arr.splice(i, 1);
this.el.className = arr.join(' ');
return this;
};
/**
* Toggle class <code>name</code>, can force state via <code>force</code>.
*
* For browsers that support classList, but do not support <code>force</code> yet,
* the mistake will be detected and corrected.
*
* @param {String} name
* @param {Boolean} force
* @return {ClassList}
* @api public
*/
ClassList.prototype.toggle = function (name, force) {
// classList
if (this.list) {
if ('undefined' !== typeof force) {
if (force !== this.list.toggle(name, force)) {
this.list.toggle(name); // toggle again to correct
}
} else {
this.list.toggle(name);
}
return this;
} // fallback
if ('undefined' !== typeof force) {
if (!force) {
this.remove(name);
} else {
this.add(name);
}
} else {
if (this.has(name)) {
this.remove(name);
} else {
this.add(name);
}
}
return this;
};
/**
* Return an array of classes.
*
* @return {Array}
* @api public
*/
ClassList.prototype.array = function () {
var className = this.el.getAttribute('class') || '';
var str = className.replace(/^\s+|\s+$/g, '');
var arr = str.split(re);
if ('' === arr[0]) arr.shift();
return arr;
};
/**
* Check if class <code>name</code> is present.
*
* @param {String} name
* @return {ClassList}
* @api public
*/
ClassList.prototype.has = ClassList.prototype.contains = function (name) {
return this.list ? this.list.contains(name) : !!~index(this.array(), name);
};
/***/ }),
/***/ "./src/utils/events.js":
/*!*****************************!*\
!*** ./src/utils/events.js ***!
\*****************************/
/*! default exports */
/*! export bind [provided] [no usage info] [missing usage info prevents renaming] */
/*! export debounce [provided] [no usage info] [missing usage info prevents renaming] */
/*! export unbind [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_exports__, __webpack_require__ */
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
prefix = bind !== 'addEventListener' ? 'on' : '',
toArray = __webpack_require__(/*! ./to-array */ "./src/utils/to-array.js");
/**
* Bind <code>el</code> event <code>type</code> to <code>fn</code>.
*
* @param {Element} el, NodeList, HTMLCollection or Array
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @api public
*/
exports.bind = function (el, type, fn, capture) {
el = toArray(el);
for (var i = 0, il = el.length; i < il; i++) {
el[i][bind](prefix + type, fn, capture || false);
}
};
/**
* Unbind <code>el</code> event <code>type</code>'s callback <code>fn</code>.
*
* @param {Element} el, NodeList, HTMLCollection or Array
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @api public
*/
exports.unbind = function (el, type, fn, capture) {
el = toArray(el);
for (var i = 0, il = el.length; i < il; i++) {
el[i][unbind](prefix + type, fn, capture || false);
}
};
/**
* Returns a function, that, as long as it continues to be invoked, will not
* be triggered. The function will be called after it stops being called for
* <code>wait</code> milliseconds. If <code>immediate</code> is true, trigger the function on the
* leading edge, instead of the trailing.
*
* @param {Function} fn
* @param {Integer} wait
* @param {Boolean} immediate
* @api public
*/
exports.debounce = function (fn, wait, immediate) {
var timeout;
return wait ? function () {
var context = this,
args = arguments;
var later = function later() {
timeout = null;
if (!immediate) fn.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) fn.apply(context, args);
} : fn;
};
/***/ }),
/***/ "./src/utils/extend.js":
/*!*****************************!*\
!*** ./src/utils/extend.js ***!
\*****************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 4:0-14 */
/***/ (function(module) {
/*
* Source: https://github.com/segmentio/extend
*/
module.exports = function extend(object) {
// Takes an unlimited number of extenders.
var args = Array.prototype.slice.call(arguments, 1); // For each extender, copy their properties on our object.
for (var i = 0, source; source = args[i]; i++) {
if (!source) continue;
for (var property in source) {
object[property] = source[property];
}
}
return object;
};
/***/ }),
/***/ "./src/utils/fuzzy.js":
/*!****************************!*\
!*** ./src/utils/fuzzy.js ***!
\****************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module) {
module.exports = function (text, pattern, options) {
// Aproximately where in the text is the pattern expected to be found?
var Match_Location = options.location || 0; //Determines how close the match must be to the fuzzy location (specified above). An exact letter match which is 'distance' characters away from the fuzzy location would score as a complete mismatch. A distance of '0' requires the match be at the exact location specified, a threshold of '1000' would require a perfect match to be within 800 characters of the fuzzy location to be found using a 0.8 threshold.
var Match_Distance = options.distance || 100; // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match (of both letters and location), a threshold of '1.0' would match anything.
var Match_Threshold = options.threshold || 0.4;
if (pattern === text) return true; // Exact match
if (pattern.length > 32) return false; // This algorithm cannot be used
// Set starting location at beginning text and initialise the alphabet.
var loc = Match_Location,
s = function () {
var q = {},
i;
for (i = 0; i < pattern.length; i++) {
q[pattern.charAt(i)] = 0;
}
for (i = 0; i < pattern.length; i++) {
q[pattern.charAt(i)] |= 1 << pattern.length - i - 1;
}
return q;
}(); // Compute and return the score for a match with e errors and x location.
// Accesses loc and pattern through being a closure.
function match_bitapScore_(e, x) {
var accuracy = e / pattern.length,
proximity = Math.abs(loc - x);
if (!Match_Distance) {
// Dodge divide by zero error.
return proximity ? 1.0 : accuracy;
}
return accuracy + proximity / Match_Distance;
}
var score_threshold = Match_Threshold,
// Highest score beyond which we give up.
best_loc = text.indexOf(pattern, loc); // Is there a nearby exact match? (speedup)
if (best_loc != -1) {
score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold); // What about in the other direction? (speedup)
best_loc = text.lastIndexOf(pattern, loc + pattern.length);
if (best_loc != -1) {
score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold);
}
} // Initialise the bit arrays.
var matchmask = 1 << pattern.length - 1;
best_loc = -1;
var bin_min, bin_mid;
var bin_max = pattern.length + text.length;
var last_rd;
for (var d = 0; d < pattern.length; d++) {
// Scan for the best match; each iteration allows for one more error.
// Run a binary search to determine how far from 'loc' we can stray at this
// error level.
bin_min = 0;
bin_mid = bin_max;
while (bin_min < bin_mid) {
if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) {
bin_min = bin_mid;
} else {
bin_max = bin_mid;
}
bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min);
} // Use the result from this iteration as the maximum for the next.
bin_max = bin_mid;
var start = Math.max(1, loc - bin_mid + 1);
var finish = Math.min(loc + bin_mid, text.length) + pattern.length;
var rd = Array(finish + 2);
rd[finish + 1] = (1 << d) - 1;
for (var j = finish; j >= start; j--) {
// The alphabet (s) is a sparse hash, so the following line generates
// warnings.
var charMatch = s[text.charAt(j - 1)];
if (d === 0) {
// First pass: exact match.
rd[j] = (rd[j + 1] << 1 | 1) & charMatch;
} else {
// Subsequent passes: fuzzy match.
rd[j] = (rd[j + 1] << 1 | 1) & charMatch | ((last_rd[j + 1] | last_rd[j]) << 1 | 1) | last_rd[j + 1];
}
if (rd[j] & matchmask) {
var score = match_bitapScore_(d, j - 1); // This match will almost certainly be better than any existing match.
// But check anyway.
if (score <= score_threshold) {
// Told you so.
score_threshold = score;
best_loc = j - 1;
if (best_loc > loc) {
// When passing loc, don't exceed our current distance from loc.
start = Math.max(1, 2 * loc - best_loc);
} else {
// Already passed loc, downhill from here on in.
break;
}
}
}
} // No hope for a (better) match at greater error levels.
if (match_bitapScore_(d + 1, loc) > score_threshold) {
break;
}
last_rd = rd;
}
return best_loc < 0 ? false : true;
};
/***/ }),
/***/ "./src/utils/get-attribute.js":
/*!************************************!*\
!*** ./src/utils/get-attribute.js ***!
\************************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 11:0-14 */
/***/ (function(module) {
/**
* A cross-browser implementation of getAttribute.
* Source found here: http://stackoverflow.com/a/3755343/361337 written by Vivin Paliath
*
* Return the value for <code>attr</code> at <code>element</code>.
*
* @param {Element} el
* @param {String} attr
* @api public
*/
module.exports = function (el, attr) {
var result = el.getAttribute && el.getAttribute(attr) || null;
if (!result) {
var attrs = el.attributes;
var length = attrs.length;
for (var i = 0; i < length; i++) {
if (attrs[i] !== undefined) {
if (attrs[i].nodeName === attr) {
result = attrs[i].nodeValue;
}
}
}
}
return result;
};
/***/ }),
/***/ "./src/utils/get-by-class.js":
/*!***********************************!*\
!*** ./src/utils/get-by-class.js ***!
\***********************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 53:0-14 */
/***/ (function(module) {
/**
* A cross-browser implementation of getElementsByClass.
* Heavily based on Dustin Diaz's function: http://dustindiaz.com/getelementsbyclass.
*
* Find all elements with class <code>className</code> inside <code>container</code>.
* Use <code>single = true</code> to increase performance in older browsers
* when only one element is needed.
*
* @param {String} className
* @param {Element} container
* @param {Boolean} single
* @api public
*/
var getElementsByClassName = function getElementsByClassName(container, className, single) {
if (single) {
return container.getElementsByClassName(className)[0];
} else {
return container.getElementsByClassName(className);
}
};
var querySelector = function querySelector(container, className, single) {
className = '.' + className;
if (single) {
return container.querySelector(className);
} else {
return container.querySelectorAll(className);
}
};
var polyfill = function polyfill(container, className, single) {
var classElements = [],
tag = '*';
var els = container.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp('(^|\\s)' + className + '(\\s|$)');
for (var i = 0, j = 0; i < elsLen; i++) {
if (pattern.test(els[i].className)) {
if (single) {
return els[i];
} else {
classElements[j] = els[i];
j++;
}
}
}
return classElements;
};
module.exports = function () {
return function (container, className, single, options) {
options = options || {};
if (options.test && options.getElementsByClassName || !options.test && document.getElementsByClassName) {
return getElementsByClassName(container, className, single);
} else if (options.test && options.querySelector || !options.test && document.querySelector) {
return querySelector(container, className, single);
} else {
return polyfill(container, className, single);
}
};
}();
/***/ }),
/***/ "./src/utils/index-of.js":
/*!*******************************!*\
!*** ./src/utils/index-of.js ***!
\*******************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 3:0-14 */
/***/ (function(module) {
var indexOf = [].indexOf;
module.exports = function (arr, obj) {
if (indexOf) return arr.indexOf(obj);
for (var i = 0, il = arr.length; i < il; ++i) {
if (arr[i] === obj) return i;
}
return -1;
};
/***/ }),
/***/ "./src/utils/to-array.js":
/*!*******************************!*\
!*** ./src/utils/to-array.js ***!
\*******************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 11:0-14 */
/***/ (function(module) {
/**
* Source: https://github.com/timoxley/to-array
*
* Convert an array-like object into an <code>Array</code>.
* If <code>collection</code> is already an <code>Array</code>, then will return a clone of <code>collection</code>.
*
* @param {Array | Mixed} collection An <code>Array</code> or array-like object to convert e.g. <code>arguments</code> or <code>NodeList</code>
* @return {Array} Naive conversion of <code>collection</code> to a new <code>Array</code>.
* @api public
*/
module.exports = function toArray(collection) {
if (typeof collection === 'undefined') return [];
if (collection === null) return [null];
if (collection === window) return [window];
if (typeof collection === 'string') return [collection];
if (isArray(collection)) return collection;
if (typeof collection.length != 'number') return [collection];
if (typeof collection === 'function' && collection instanceof Function) return [collection];
var arr = [];
for (var i = 0, il = collection.length; i < il; i++) {
if (Object.prototype.hasOwnProperty.call(collection, i) || i in collection) {
arr.push(collection[i]);
}
}
if (!arr.length) return [];
return arr;
};
function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
/***/ }),
/***/ "./src/utils/to-string.js":
/*!********************************!*\
!*** ./src/utils/to-string.js ***!
\********************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 1:0-14 */
/***/ (function(module) {
module.exports = function (s) {
s = s === undefined ? '' : s;
s = s === null ? '' : s;
s = s.toString();
return s;
};
/***/ }),
/***/ "./node_modules/string-natural-compare/natural-compare.js":
/*!****************************************************************!*\
!*** ./node_modules/string-natural-compare/natural-compare.js ***!
\****************************************************************/
/*! unknown exports (runtime-defined) */
/*! runtime requirements: module */
/*! CommonJS bailout: module.exports is used directly at 124:0-14 */
/***/ (function(module) {
"use strict";
var alphabet;
var alphabetIndexMap;
var alphabetIndexMapLength = 0;
function isNumberCode(code) {
return code >= 48 && code <= 57;
}
function naturalCompare(a, b) {
var lengthA = (a += '').length;
var lengthB = (b += '').length;
var aIndex = 0;
var bIndex = 0;
while (aIndex < lengthA && bIndex < lengthB) {
var charCodeA = a.charCodeAt(aIndex);
var charCodeB = b.charCodeAt(bIndex);
if (isNumberCode(charCodeA)) {
if (!isNumberCode(charCodeB)) {
return charCodeA - charCodeB;
}
var numStartA = aIndex;
var numStartB = bIndex;
while (charCodeA === 48 && ++numStartA < lengthA) {
charCodeA = a.charCodeAt(numStartA);
}
while (charCodeB === 48 && ++numStartB < lengthB) {
charCodeB = b.charCodeAt(numStartB);
}
var numEndA = numStartA;
var numEndB = numStartB;
while (numEndA < lengthA && isNumberCode(a.charCodeAt(numEndA))) {
++numEndA;
}
while (numEndB < lengthB && isNumberCode(b.charCodeAt(numEndB))) {
++numEndB;
}
var difference = numEndA - numStartA - numEndB + numStartB; // numA length - numB length
if (difference) {
return difference;
}
while (numStartA < numEndA) {
difference = a.charCodeAt(numStartA++) - b.charCodeAt(numStartB++);
if (difference) {
return difference;
}
}
aIndex = numEndA;
bIndex = numEndB;
continue;
}
if (charCodeA !== charCodeB) {
if (
charCodeA < alphabetIndexMapLength &&
charCodeB < alphabetIndexMapLength &&
alphabetIndexMap[charCodeA] !== -1 &&
alphabetIndexMap[charCodeB] !== -1
) {
return alphabetIndexMap[charCodeA] - alphabetIndexMap[charCodeB];
}
return charCodeA - charCodeB;
}
++aIndex;
++bIndex;
}
if (aIndex >= lengthA && bIndex < lengthB && lengthA >= lengthB) {
return -1;
}
if (bIndex >= lengthB && aIndex < lengthA && lengthB >= lengthA) {
return 1;
}
return lengthA - lengthB;
}
naturalCompare.caseInsensitive = naturalCompare.i = function(a, b) {
return naturalCompare(('' + a).toLowerCase(), ('' + b).toLowerCase());
};
Object.defineProperties(naturalCompare, {
alphabet: {
get: function() {
return alphabet;
},
set: function(value) {
alphabet = value;
alphabetIndexMap = [];
var i = 0;
if (alphabet) {
for (; i < alphabet.length; i++) {
alphabetIndexMap[alphabet.charCodeAt(i)] = i;
}
}
alphabetIndexMapLength = alphabetIndexMap.length;
for (i = 0; i < alphabetIndexMapLength; i++) {
if (alphabetIndexMap[i] === undefined) {
alphabetIndexMap[i] = -1;
}
}
},
},
});
module.exports = naturalCompare;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(__webpack_module_cache__[moduleId]) {
/******/ return __webpack_module_cache__[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ // module exports must be returned from runtime so entry inlining is disabled
/******/ // startup
/******/ // Load entry module and return exports
/******/ return __webpack_require__("./src/index.js");
/******/ })()
;
//# sourceMappingURL=list.js.map
@hube2 Thanks for the answer! I was able to upload videos in the ACF Gallery without needing to set anything specific. The only difference is that while the native media library accepts my function for thumbnail generation (see screenshot 1), the ACF gallery won’t take the parameters as mentioned (see screenshot 2).
As said, nothing has been set from my end to allow to upload video in the gallery
Any idea why this could happen?
Thanks
I found this thread which seems to have solved it.
https://stackoverflow.com/questions/74909221/dinamically-create-a-link-using-acf-advanced-custom-field-custom-value/76353138#76353138
But I’m not sure how to implement it
Just popping in to provide this information on hashing/unhashing because the link to andrewwho.nl is no longer.
function dec_enc($action, $string) {
$output = false;
$encrypt_method = "AES-256-CBC";
$secret_key = 'This is my secret key';
$secret_iv = 'This is my secret iv';
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
}
else if( $action == 'decrypt' ){
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
Source: https://web.archive.org/web/20161229224924/https://andrewho.nl/encrypt-decrypt-strings-php-easy-way/
Un grand salut aussi đ
Au cas oĂš dâautres personnes rencontrent le meme problème on continue en Anglais ? đ
I am definitely not a coder/dev and since the latest release of ACF what I am trying, or anyway, achieved so far, has been done without a single bit of code.
My bad, I forgot to specify that I am also using Elementor.
But here is what I have done:
I have created a new taxonomy:
https://prnt.sc/SblxWOHBmACi
https://prnt.sc/QpWKI3Qa41-S
https://prnt.sc/A8kIAtrZXW6m
Salut aussi !
Au cas oĂš dâautres personnes rencontrent le meme problème on continue en Anglais ? đ
I am definitely not a coder/dev and since the latest release of ACF what I am trying, or anyway, achieved so far, has been done without a single bit of code.
My bad, I forgot to specify that I am also using Elementor.
But here is what I have done:
I have created a new taxonomy:
https://prnt.sc/SblxWOHBmACi
https://prnt.sc/QpWKI3Qa41-S
https://prnt.sc/A8kIAtrZXW6m
Salut aussi !
Au cas oĂš dâautres personnes rencontrent le meme problème on continue en Anglais ? đ
I am definitely not a coder/dev and since the latest release of ACF what I am trying, or anyway, achieved so far, has been done without a single bit of code.
My bad, I forgot to specify that I am also using Elementor.
But here is what I have done:
I have created a new taxonomy:
https://prnt.sc/SblxWOHBmACi
https://prnt.sc/QpWKI3Qa41-S
https://prnt.sc/A8kIAtrZXW6m
And here is what I did in Elementor:
https://prnt.sc/kQmfuTbvomh1
So it definitely loads something correct, which is the ID of the taxonomy:
https://prnt.sc/2gf4eFlbn8tv
In this case 59
But even if I switch the value as showed in my original post this is still the ID and not the value/term that is showing up.
It works fine with ânormalâ fields:
https://prnt.sc/X–0v2gyJDCc
https://prnt.sc/GwSsYtf4DpfC
But I know this is not the same thing as Taxonomies.
And I am a bit stuck :-/
Salut aussi !
Au cas oĂš dâautres personnes rencontrent le meme problème on continue en Anglais ? đ
I am definitely not a coder/dev and since the latest release of ACF what I am trying, or anyway, achieved so far, has been done without a single bit of code.
My bad, I forgot to specify that I am also using Elementor.
But here is what I have done:
I have created a new taxonomy:
https://prnt.sc/SblxWOHBmACi
https://prnt.sc/QpWKI3Qa41-S
https://prnt.sc/A8kIAtrZXW6m
And here is what I did in Elementor:
https://prnt.sc/kQmfuTbvomh1
So it definitely loads something correct, which is the ID of the taxonomy:
https://prnt.sc/2gf4eFlbn8tv
In this case 59
But even if I switch the value as showed in my original post this is still the ID and not the value/term that is showing up.
It works fine with ânormalâ fields:
https://prnt.sc/X–0v2gyJDCc
https://prnt.sc/GwSsYtf4DpfC
But I know this is not the same thing as Taxonomies.
And I am a bit stuck :-/
I even asked chatgpt to write me a code snippet which looks that it could have done something (I even asked the function to check on a specific url) but it still doesnât work đ
Salut aussi !
Au cas oĂš dâautres personnes rencontrent le meme problème on continue en Anglais ? đ
I am definitely not a coder/dev and since the latest release of ACF what I am trying, or anyway, achieved so far, has been done without a single bit of code.
My bad, I forgot to specify that I am also using Elementor.
But here is what I have done:
I have created a new taxonomy:
https://prnt.sc/SblxWOHBmACi
https://prnt.sc/QpWKI3Qa41-S
https://prnt.sc/A8kIAtrZXW6m
And here is what I did in Elementor:
https://prnt.sc/kQmfuTbvomh1
So it definitely loads something correct, which is the ID of the taxonomy:
https://prnt.sc/2gf4eFlbn8tv
In this case 59
But even if I switch the value as showed in my original post this is still the ID and not the value/term that is showing up.
It works fine with ânormalâ fields:
https://prnt.sc/X–0v2gyJDCc
https://prnt.sc/GwSsYtf4DpfC
But I know this is not the same thing as Taxonomies.
And I am a bit stuck :-/
I even asked chatgpt to write me a code snippet which looks that it could have done something (I even asked the function to check on a specific url) but it still doesnât work đ
function convert_taxonomy_ids_to_terms( $value, $post_id, $field ) {
if ( ! $value ) {
return $value;
}
if ( strpos( $_SERVER[‘REQUEST_URI’], ‘/listing-des-animaux/’ ) !== false ) {
$taxonomies = get_object_taxonomies( ‘animaux’ );
if ( is_array( $value ) ) {
$text_values = array();
foreach ( $value as $id ) {
foreach ( $taxonomies as $taxonomy ) {
$term = get_term_by( ‘id’, $id, $taxonomy );
if ( $term ) {
$text_values[] = $term->name;
}
}
}
return implode( ‘, ‘, $text_values );
} else {
foreach ( $taxonomies as $taxonomy ) {
$term = get_term_by( ‘id’, $value, $taxonomy );
if ( $term ) {
return $term->name;
}
}
return $value;
}
} else {
return $value;
}
}
add_filter( ‘acf/format_value/type=taxonomy’, ‘convert_taxonomy_ids_to_terms’, 10, 3 );
I can’t seem to edit my original message so I’d like to add a few extra details. I get the follow error:
When I look a bit closer it seems like an ajax request is sent but gives a 500 error with the same content as above:
I don’t know if this is default ACF behaviour but it might give an idea as to what is happening. acf_form_head()
is added via the init hook so it’s not a question of not having the correct files enqueued.
Just to confirm that I understand correctly, on the job’s page you want a link to apply for the job?
If that’s the case, why aren’t you passing the post ID of the job as a query variable (e.g. https://yoursite.com/apply-to-jobs/?job=YOUR_JOBS_POST_ID)?
If you want a secondary slug for your jobs (so the URLs are prettier), it is possible to add an additional endpoint to existing URLs using add_rewrite_endpoint
. If you were to go this route you could have a URL that looks like https://yoursite.com/job-a/apply/
You would then use the template_redirect
hook to load a different template that has a form (but you’d still be able to get the original job’s ID) so that you could inject the name of the job in the form.
I am not a developer of ACF. I cannot answer your questions. You would need to contact the developers. The developers do not monitor this forum.
My guess is that they are not going to allow filtering of the form field itself or adding arbitrary attributes.
My suggestion would depend on what you need that attribute for, what are you trying to do?
Ah perfect, thanks John you are a legend! Just in case anyone in the future needs the code, here is my final code
replaced
'post_type' => $post_type,
with
'post_type' => 'inventory',
since my CPT was inventory.
Final code:
add_filter('acf/validate_value/name=inventory_id', 'acf_unique_value_field', 10, 4);
function acf_unique_value_field($valid, $value, $field, $input)
{
if (!$valid) {
return $valid;
}
if (isset($_POST['post_ID'])) {
$post_id = intval($_POST['post_ID']);
} elseif (isset($_POST['post_id'])) {
$post_id = intval($_POST['post_id']);
} else {
$post_id = false;
}
$field_name = $field['name'];
$args = array(
'post_type' => 'inventory',
'post_status' => 'publish, draft, trash',
'meta_query' => array(
array(
'key' => $field_name,
'value' => $value
)
)
);
if (!empty($post_id)) {
$args['post__not_in'] = array($post_id);
}
$query = new WP_Query($args);
if (count($query->posts)) {
return 'This Value is not Unique. Please enter a unique ' . $field['label'];
}
return true;
}
There is also a problem with this that I missed
$post_type = get_post_type($post_id);
You are going to have to hard code the post type instead of depending on getting the value. If the post type is empty then it defaults to “post” in the query.
Thank you for your patience.
I actually meant that I get the complete nested array of a repeater with get_field() with field keys instead of field names.
After researching for a while, I realized that the last parameter format does exactly that. This gives me field keys instead of names.
I have now found a solution that works quite well:
1.) I use acf_get_field_group() to read in the field group that I would like to display in my boxes.
2) With acf_get_fields() I get the corresponding fields in an array and can cycle through them.
3) With acf_get_field() I get the field object in the loop that I need later to display the field.
4) With get_field() and the last parameter set to false, I get the representation of the data that has already been saved for this field
5) I pass all this to acf_render_field_wrap() and so get the representation of the control in my box
Finally, I need to make it possible to have several boxes with the nested fields at the same time. At the moment it is only possible with one box.
The values isset($_POST[‘post_ID’] or $_POST[‘post_id’] are not set on the front end when creating a new post with acf_form().
You’re going to have to alter the code to account for not having a post ID
add_filter('acf/validate_value/name=inventory_id', 'acf_unique_value_field', 10, 4);
function acf_unique_value_field($valid, $value, $field, $input) {
if (!$valid) {
return $valid;
}
if (isset($_POST['post_ID'])) {
$post_id = intval($_POST['post_ID']);
} elseif (isset($_POST['post_id'])) {
$post_id = intval($_POST['post_id']);
} else {
$post_id = false;
}
$post_type = get_post_type($post_id);
$field_name = $field['name'];
$args = array(
'post_type' => $post_type,
'post_status' => 'publish, draft, trash',
'meta_query' => array(
array(
'key' => $field_name,
'value' => $value
)
)
);
if (!empty($post_id) {
$args['post__not_in'] = array($post_id);
}
$query = new WP_Query($args);
if (count($query->posts)){
return 'This Value is not Unique. Please enter a unique '.$field['label'];
}
return true;
}
A field that is hidden by conditional logic should not be required even when it is marked as required. ACF does not validate or submit fields that are hidden by conditional logic unless this has been disabled by adding custom JS that removes the “disabled” attribute from the hidden fields.
Yeah, I got this error when i click to edit the field:
select2.min.js?ver=1.0:1 Uncaught Error: No select2/compat/dropdownCss
at j (select2.min.js?ver=1.0:1:1396)
at n (select2.min.js?ver=1.0:1:2682)
at select2.min.js?ver=1.0:1:1168
at D.apply (select2.min.js?ver=1.0:2:16454)
at new e (select2.min.js?ver=1.0:2:18920)
at new e (select2.min.js?ver=1.0:2:20939)
at HTMLSelectElement.<anonymous> (select2.min.js?ver=1.0:2:28843)
at Function.each (load-scripts.php?c=1&load%5Bchunk_0%5D=jquery-core,jquery-migrate,utils,wp-polyfill-inert,regenerator-runtime,wp-polyfill,wp-hooks&ver=6.4.2:2:3129)
at e.<computed>.each (load-scripts.php?c=1&load%5Bchunk_0%5D=jquery-core,jquery-migrate,utils,wp-polyfill-inert,regenerator-runtime,wp-polyfill,wp-hooks&ver=6.4.2:2:1594)
at a.fn.select2 (select2.min.js?ver=1.0:2:28802)
And this error when i click to edit the fields groups (but this works fine)
dataTables.responsive.min.js?ver=1.0:42 Uncaught TypeError: Cannot read properties of undefined (reading 'Api')
at dataTables.responsive.min.js?ver=1.0:42:68
at dataTables.responsive.min.js?ver=1.0:18:281
at dataTables.responsive.min.js?ver=1.0:18:308
What is the return format of your date fields?
DateTime Requires that ACF returns the date in a valid format
After our exchange yesterday, I thought everything through again today.
I have created a new field based on the boilerplate.
I now use a single field group that I want to display in my boxes for editing. In the render_field() function, I can read the field group with acf_get_field_group() and output the fields accordingly in my boxes with acf_render_field_wrap().
For saving, I retrieve the data from $_POST and place my box identifier, e.g. {$box_field_name}_{$field_name}, in front of the post_meta keys. This works with simple text fields, but reading in and out repeaters is more difficult.
The correct number of lines are displayed and saved, but the values remain empty. What could be the reason for this?
if(isset($field_object['sub_fields'])){
foreach ($field_object['sub_fields'] as $sub_field) {
$field_value = get_field($sub_field['key'], $id);
$acf_render_subfield_attributes[] =
array(
'type' => $sub_field['type'],
'name' => $sub_field['name'],
'value' => $field_value,
'key' => $sub_field['key'],
'label' => $sub_field['label'],
'instructions' => $sub_field['instructions'],
'required' => $sub_field['required']
);
}
}
$acf_render_attributes['sub_fields'] = $acf_render_subfield_attributes
Thanks John worked it out from your input.
Here’s the code if anyone else needs help as I looked around for quite a while before raising a ticket.
add_action (‘acf/save_post’, ‘add_role_on_selection’);
function add_role_on_selection ($post_id) {
// Get newly saved values.
$values = get_fields( $post_id );
// Check the new value of a specific field.
$selected = get_field(‘stall_catergory’, $post_id);
$user = wp_get_current_user();
if( $selected == ‘general’) {
$user->add_role(‘general’);
}
if( $selected == ‘food’) {
$user->add_role(‘food’);
}
if( $selected == ‘hot food’) {
$user->add_role(‘hot_food’);
}
}
Yes, if you put the repeated fields as sub fields in any type of field allows this, as long as the parent field name is unique or you are using a repeater. Also the clone field can be set up to prepend the clone field name to the cloned fields.
meta keys follow these rules
// repeaters and flex fields
"{$parent_name}_{$row_index}_{$sub_field_name}"
// group fields
"{$parent_name}_{$sub_field_name}"
// clone fields set to prefix field names
"{$clone_name}_{$cloned_field_name}"
Thank you John for your feedback.
What I’m reading here is that each box needs a unique parent assignment in ACF, much like a repeater field. As I understand it, it would therefore make sense to create the layout as a separate ACF field.
The repeater function is in itself a good basis for the idea I have in mind, except that each row can have different attributes, not just the index.
Is it possible to create a field directly on the repeater field, or to extend it and customize functions?
I have already created my own fields, but no fields with nested field groups inside.
ACF adds fields for posts on the “add_meta_boxes” run by WP. From what you describe there would be no way to distinguish between your content boxes.
In addition to this it would alter the DOM that ACF expects and this will likely cause none of the ACF JS or CSS to work properly.
There is also the matter of using the same fields in multiple times. All fields on the page must have unique names (meta_key) for every field. If you include the same field group multiple times than all of the fields would have the same names and keys, each time it is saved it will overwrite the previous value and when done all of them would have the same value.
Honestly, I don’t know why it’s not working, unless it has something to do with the mix of meta settings. Try this
$today = date('Ymd');
$thePosts = new WP_Query(array(
'post_type' => 'post',
'posts_per_page' => 10,
'meta_query' => array(
array(
'key' => 'event_end',
'value' => '".$today."',
'compare' => '>'
),
'date_clause' => array(
'key' => 'event_start'
'compare' => 'EXISTS'
)
),
'orderby' => array('date_clause' => 'DESC'),
'post_status' => 'publish',
));
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.