/**
* jQuery.fn.sortElements
* --------------
* @author James Padolsey (http://james.padolsey.com)
* @version 0.11
* @updated 18-MAR-2010
* --------------
* @param Function comparator:
* Exactly the same behaviour as [1,2,3].sort(comparator)
*
* @param Function getSortable
* A function that should return the element that is
* to be sorted. The comparator will run on the
* current collection, but you may want the actual
* resulting sort to occur on a parent or another
* associated element.
*
* E.g. $('td').sortElements(comparator, function(){
* return this.parentNode;
* })
*
* The
's parent (
) will be sorted instead
* of the
itself.
*/
jQuery.fn.sortElements = (function() {
var sort = [].sort;
return function(comparator, getSortable) {
getSortable = getSortable || function() { return this; };
var placements = this.map(function() {
var sortElement = getSortable.call(this),
parentNode = sortElement.parentNode,
// Since the element itself will change position, we have
// to have some way of storing it's original position in
// the DOM. The easiest way is to have a 'flag' node:
nextSibling = parentNode.insertBefore(
document.createTextNode(''),
sortElement.nextSibling
);
return function() {
if (parentNode === this) {
throw new Error(
"You can't sort elements if any one is a descendant of another."
);
}
// Insert before flag:
parentNode.insertBefore(this, nextSibling);
// Remove flag:
parentNode.removeChild(nextSibling);
};
});
return sort.call(this, comparator).each(function(i) {
placements[i].call(getSortable.call(this));
});
};
})();
(function() {
// natural compare
var natcmp = function(s1, s2) {
// 'normalize' the values we're sorting
s1 = s1.replace( /<.*?>/g, "" ).replace('>','<').replace('<','>').replace('&','&');
s2 = s2.replace( /<.*?>/g, "" ).replace('>','<').replace('<','>').replace('&','&');
// do the actual sorting
var n = /^(\d+)(.*)$/;
while (true) {
if (s1 == s2) { return 0; }
if (s1 == '') { return -1; }
if (s2 == '') { return 1; }
var n1 = n.exec(s1);
var n2 = n.exec(s2);
if ( (n1 != null) && (n2 != null) ) {
if (n1[1] != n2[1]) { return n1[1] - n2[1]; }
s1 = n1[2];
s2 = n2[2];
} else {
n1 = s1.charCodeAt(0);
n2 = s2.charCodeAt(0);
if (n1 != n2) { return n1 - n2; }
s1 = s1.substr(1);
s2 = s2.substr(1);
}
}
};
// natural compare right to left (numbers still left to right)
var natcmp_rtl = function(s1, s2) {
// 'normalize' the values we're sorting
s1 = s1.replace( /<.*?>/g, "" ).replace('>','<').replace('<','>').replace('&','&');
s2 = s2.replace( /<.*?>/g, "" ).replace('>','<').replace('<','>').replace('&','&');
// do the actual sorting
var n = /^(.*?)(\d+)$/;
while (true) {
if (s1 == s2) { return 0; }
if (s1 == '') { return -1; }
if (s2 == '') { return 1; }
var n1 = n.exec(s1);
var n2 = n.exec(s2);
if ( (n1 != null) && (n2 != null) ) {
if (n1[2] != n2[2]) { return n1[2] - n2[2]; }
s1 = n1[1];
s2 = n2[1];
} else {
n1 = s1.charCodeAt(s1.length - 1);
n2 = s2.charCodeAt(s2.length - 1);
if (n1 != n2) { return n1 - n2; }
s1 = s1.substr(0, s1.length - 1);
s2 = s2.substr(0, s2.length - 1);
}
}
};
// generic stable unique function
var unique = function(es) {
var temp = {};
var result = [];
for(var i = 0; i < es.length; i++) {
var e = es[i];
if(! (e in temp)) {
result.push(e);
temp[e]=true;
}
}
return result;
};
// multi field compare
var create_item_compare = function(fields, isAscending, sortType) {
return function(item1, item2) {
var valueMap1 = jQuery(item1).data('strata-item-values');
var valueMap2 = jQuery(item2).data('strata-item-values');
for (var i = 0; i < fields.length; i++) {
var d = isAscending[i] ? 1 : -1;
var cmp = (sortType[i] == 'r' ? natcmp_rtl : natcmp);
var values1 = valueMap1[fields[i]];
var values2 = valueMap2[fields[i]];
var length = Math.min(values1.length, values2.length);
for (var j = 0; j < length; j++) {
var c = cmp(values1[j], values2[j]);
if (c != 0) {
return d * c;
}
}
if (values1.length > values2.length) {
return d * 1;
} else if (values1.length < values2.length) {
return d * -1;
}
}
return parseInt(jQuery(item1).attr('data-strata-order')) - parseInt(jQuery(item2).attr('data-strata-order'));
}
};
// Create a filter field of the given type and add it to the given filterElement
var createFilterFieldAndSort = function(filterElement, filterType, filterId, field, sortType, fieldSelector, containerElement, caption, minWidth) {
createItemFilterAndSort(containerElement, filterId, field, fieldSelector, filterType);
if (filterType == 't') {
var input = createFilterTextField(containerElement, filterId, caption);
if (minWidth != undefined) {
jQuery(input).css('min-width', minWidth + 'px');
}
jQuery(filterElement).append(input);
} else if (filterType == 's' || filterType == 'p' || filterType == 'e') {
var cmp = (sortType == 'r' ? natcmp_rtl : natcmp);
var select = createFilterSelect(containerElement, filterId, fieldSelector, caption, cmp);
jQuery(filterElement).append(select);
}
};
// Returns a text input which filters the field belonging to the given filterId
var createFilterTextField = function(element, filterId, caption) {
var input = document.createElement('input');
input.type = 'text';
input.size = 1;
input.title = 'Filter on ' + caption;
jQuery(input).keyup(function() {
var val = jQuery(this).val();
if(val == '') {
delete jQuery(element).data('strata-search')[filterId];
} else {
jQuery(element).data('strata-search')[filterId] = val.toLowerCase();
}
strataFilter(element);
toggleFiltered(this);
});
return input;
};
// Returns a select input which filters the field belonging to the given filterId
var createFilterSelect = function(element, filterId, fieldSelector, caption, cmp) {
var select = document.createElement('select');
jQuery(select).append('');
var values = [];
jQuery(fieldSelector, element).each(function(_,es) {
var vs = jQuery('*.strata-value', es);
if (vs.length) {
vs.each(function(i, v) {
if (values.indexOf(v.textContent) == -1) {
values.push(v.textContent);
}
});
} else if (values.indexOf('') == -1) {
values.push('');
}
});
values.sort(cmp);
jQuery.each(values, function(_,v) {
var option = document.createElement('option');
option.value = v;
option.textContent = v==''?'':v;
if (v == '') {
option.className = 'strata-filter-special';
}
jQuery(select).append(option);
});
jQuery(select).change(function() {
var $option = jQuery(this).find(':selected');
if($option.attr('data-filter') == 'none') {
delete jQuery(element).data('strata-search')[filterId];
} else {
jQuery(element).data('strata-search')[filterId] = jQuery(this).val().toLowerCase();
}
strataFilter(element);
toggleFiltered(this);
});
return select;
};
// Create a filter for every item of the field belonging to the given filterId
var createItemFilterAndSort = function(element, filterId, field, fieldSelector, filterType) {
jQuery('*.strata-item', element).each(function(i, item) {
var values = getValues(item, fieldSelector);
// Create filter
var filter;
if (filterType == 't') { // substring
// must match at least one value
filter = function(search) {
var result = false;
for (var k = 0; !result && k < values.length; k++) {
result = values[k].indexOf(search) != -1;
}
return result;
};
} else if (filterType == 'p') { // prefix
// must match at least one value
filter = function(search) {
if (search == '') return jQuery.inArray('', values) != -1; // Filtering for empty prefix is useless, so do exact match
var result = false;
for (var k = 0; !result && k < values.length; k++) {
result = values[k].substr(0, search.length) == search;
}
return result;
};
} else if (filterType == 'e') { // ending a.k.a. suffix
// must match at least one value
filter = function(search) {
if (search == '') return jQuery.inArray('', values) != -1; // Filtering for empty suffix is useless, so do exact match
var result = false;
for (var k = 0; !result && k < values.length; k++) {
result = values[k].substr(values[k].length - search.length, search.length) == search;
}
return result;
};
} else { // exact
// must match at least one value
filter = function(search) {
return jQuery.inArray(search, values) != -1;
};
}
addToItemMap(item, 'strata-item-values', field, values);
addToItemMap(item, 'strata-item-filter', filterId, filter);
});
};
// Get all values for the fields selected by fieldSelector within the given item
function getValues(item, fieldSelector) {
// Return all values of each field and the empty string for fields without values
return jQuery(fieldSelector, item).map(function(_, es) {
var vs = jQuery('*.strata-value', es);
if (vs.length) {
return jQuery.makeArray(vs.map(function(_, v) {
return v.textContent.toLowerCase();
}));
} else {
return '';
}
});
}
// Store data of the given field for the given item
var addToItemMap = function(item, key, id, values) {
var valueMap = jQuery(item).data(key);
if (valueMap == undefined) {
valueMap = {};
jQuery(item).data(key, valueMap);
}
valueMap[id] = values;
};
var sortGeneric = function(element, fieldlist) {
var fields = [];
var isAscending = [];
var sortType = [];
var items = jQuery('li', fieldlist);
for (var i = 0; i < items.length && jQuery(items[i]).attr('data-field') != undefined; i++) {
fields.push(jQuery(items[i]).attr('data-field'));
isAscending.push(jQuery('.strata-ui-sort-direction', items[i]).attr('data-strata-sort-direction') == 'asc');
sortType.push(jQuery(items[i]).data('strata-sort-type'));
}
jQuery('.strata-item', element).sortElements(create_item_compare(fields, isAscending, sortType));
};
var sortTable = function(element, field, isAdditional) {
var fields = jQuery(element).data('strata-sort-fields');
var isAscending = jQuery(element).data('strata-sort-directions');
var sortType = [];
if (fields[0] == field) {
if (isAscending[0]) { // Change sort direction
isAscending[0] = false;
} else { // Remove from sort
fields.splice(0, 1);
isAscending.splice(0, 1);
}
} else if (isAdditional) { // Add as sort field
var i = fields.indexOf(field);
if (i >= 0) {
fields.splice(i, 1);
isAscending.splice(i, 1);
}
fields.unshift(field);
isAscending.unshift(true);
} else { // Replace sort with given field
fields.splice(0, fields.length, field);
isAscending.splice(0, fields.length, true);
}
var sort = jQuery(element).attr('data-strata-ui-sort');
jQuery('th', element).removeAttr('data-strata-sort').removeAttr('data-strata-sort-direction');
jQuery('td', element).removeAttr('data-strata-sort').removeAttr('data-strata-sort-direction');
for (var i = 0; i < fields.length; i++) {
var col = fields[i];
jQuery('.col' + col, element).attr('data-strata-sort', i);
jQuery('.col' + col, element).attr('data-strata-sort-direction', isAscending[i] ? 'asc' : 'desc');
sortType.push(sort[col]);
}
jQuery('.strata-item', element).sortElements(create_item_compare(fields, isAscending, sortType));
};
// UI initialization
jQuery(document).ready(function() {
// Table UI initialization
jQuery('div.strata-container-table[data-strata-ui-ui="table"]').each(function(i, div) {
// Do not make this a dataTable if a colspan is used somewhere (Colspans are only generated by strata when errors occur)
if (jQuery('table tbody td[colspan][colspan != 1]', div).length > 0) {
return;
}
// Set filter to empty set
jQuery(div).data('strata-search', {});
var filterColumns = jQuery(div).attr('data-strata-ui-filter');
var sortColumns = jQuery(div).attr('data-strata-ui-sort');
// Create sort and filter fields for each column
var tr = document.createElement('tr');
jQuery(tr).addClass('filter');
var thead = jQuery('thead', div);
var headers = jQuery('tr.row0 th', thead);
headers.each(function(i, td) {
var field = jQuery('.strata-caption', td).attr('data-field');
var th = document.createElement('th'); // Filter field
if (field != undefined) { // Is there a field to sort/filter on?
// Create sort
if (sortColumns.charAt(i) != 'n') {
jQuery(td).addClass('sorting');
jQuery(td).click(function(e) {
sortTable(div, i, e.shiftKey);
});
}
// Create filter
var fieldSelector = '.col' + i + ' *.strata-field';
createFilterFieldAndSort(th, filterColumns.charAt(i), i, i, sortColumns.charAt(i), fieldSelector, div, td.textContent);
}
jQuery(tr).append(th);
});
jQuery(thead).append(tr);
// Set column widths
jQuery('thead tr.row0 th', div).each(
function(i, th) {
// Set the width of a column to its initial width, which is the width of the widest row.
// This avoids resizing when filtering hides long rows in the table.
var width = jQuery(th).width();
jQuery(th).css('min-width', width + 'px');
}
);
// Set data for sort
jQuery(div).data('strata-sort-fields', []);
jQuery(div).data('strata-sort-directions', []);
// Allow switching to alternate table view with the meta key
jQuery(thead).click(function(e) {
if (e.metaKey) {
jQuery(div).toggleClass('strata-ui-filter');
}
});
});
// Generic UI initialization
jQuery('div.strata-container[data-strata-ui-ui="generic"]').each(function(i, div) {
// Set filter to empty set
jQuery(div).data('strata-search', {});
var filterColumns = jQuery(div).attr('data-strata-ui-filter');
var sortColumns = jQuery(div).attr('data-strata-ui-sort');
// Create sort and filter fields for each column
var list = document.createElement('ul');
jQuery(list).addClass('filter')
.mouseenter(function(){ jQuery(div).toggleClass('section_highlight', true); })
.mouseleave(function(){ jQuery(div).toggleClass('section_highlight', false); });
var li = document.createElement('li');
jQuery(li).addClass('ui-state-highlight strata-ui-eos');
jQuery(li).append(document.createTextNode('End of sort order'));
jQuery(list).append(li);
var lastSortable = li;
// Collect all sort and filter fields
var fields = {};
var fieldOrder = [];
jQuery('.strata-caption', div).each(function(i, captionElement) {
if (sortColumns.charAt(i) != 'n' || filterColumns.charAt(i) != 'n') {
var field = jQuery(captionElement).attr('data-field');
var minWidth = Math.max.apply(Math, jQuery('*.strata-field[data-field="' + field + '"] .strata-value', div).map(function(_, v) {
return jQuery(v).width();
}));
var f;
if (field in fields) {
f = fields[field];
f.caption.push(captionElement.textContent);
if (f.sortType == 'n') {
f.sortType = sortColumns.charAt(i);
}
f.minWidth = Math.max(f.minWidth, minWidth);
} else {
f = {
'field': field,
'caption': [captionElement.textContent],
'sortType': sortColumns.charAt(i),
'minWidth': minWidth,
'filters': []
};
fields[field] = f;
fieldOrder.push(f);
}
if (filterColumns.charAt(i) != 'n') {
f.filters.push(filterColumns.charAt(i));
}
}
});
// Create the collected fields
for (var i = 0; i < fieldOrder.length; i++) {
var f = fieldOrder[i];
var caption = unique(f.caption).join(' / ');
var li = document.createElement('li');
jQuery(li).addClass('ui-state-default');
jQuery(li).attr('data-field', f.field);
jQuery(li).append(document.createTextNode(caption));
var fieldSelector = '*.strata-field[data-field="' + f.field + '"]';
if (f.filters.length) {
jQuery(li).append(' ');
}
for (var j = 0; j < f.filters.length; j++) {
createFilterFieldAndSort(li, f.filters[j], i + '_' + j, f.field, f.sortType, fieldSelector, div, caption, f.minWidth);
}
if (f.sortType != 'n') {
jQuery(li).data('strata-sort-type', f.sortType);
var span = document.createElement('span');
jQuery(span).addClass('strata-ui-sort-direction');
jQuery(span).attr('data-strata-sort-direction', 'asc');
jQuery(span).append(' ');
jQuery(li).append(span);
jQuery(span).click(function(e) {
var dir = jQuery(this).attr('data-strata-sort-direction') == 'asc' ? 'desc' : 'asc';
jQuery(this).attr('data-strata-sort-direction', dir);
sortGeneric(div, list);
});
if (f.filters.length == 0) { // No sort data was stored yet, do it now
jQuery('*.strata-item', div).each(function(i, item) {
addToItemMap(item, 'strata-item-values', f.field, getValues(item, fieldSelector));
});
}
} else {
jQuery(li).append(' ');
}
if (f.sortType == 'n') {
jQuery(li).addClass('strata-no-sort');
jQuery(list).append(li);
} else {
jQuery(lastSortable).after(li);
lastSortable = li;
}
}
jQuery(div).prepend(list);
// Set data for sort
jQuery(div).data('strata-sort-fields', []);
jQuery(div).data('strata-sort-directions', []);
jQuery(list).sortable({
items: "li:not(.strata-no-sort)",
placeholder: "ui-state-default ui-state-disabled ui-drop-target",
start: function(e, ui) {
jQuery(ui.placeholder).css('min-width', jQuery(ui.item).width() + 'px');
},
update: function(e, ui) {
sortGeneric(div, list);
}
});
});
});
// Filter every strata-item in the given element based on its filter
var strataFilter = function(element) {
var search = jQuery(element).data('strata-search');
// Traverse all items (rows) that can be filtered
jQuery('*.strata-item', element).each(function(_, item) {
// Traverse all fields on which a filter is applied, filter must match all fields
var filterMap = jQuery(item).data('strata-item-filter');
var matchesAllFields = true;
for (filterId in search) {
var filter = filterMap[filterId];
if (!filter(search[filterId])) {
matchesAllFields = false;
break;
}
}
jQuery(item).toggleClass('hidden', !matchesAllFields);
});
};
var toggleFiltered = function(tableElement) {
var tr = jQuery(tableElement).closest('tr.filter');
//console.log(Object.keys(...).length);
var isFiltered = false;
tr.find('input').each(function(_, input) {
isFiltered = isFiltered || (input.value != '');
});
tr.find('select').each(function(_, select) {
isFiltered = isFiltered || (jQuery(select).val() != '');
});
tr.toggleClass('isFiltered', isFiltered);
};
})();
/* DOKUWIKI:include plotly-2.25.2.min.js */