This repository has been archived on 2024-07-27. You can view files and clone it, but cannot push or open issues or pull requests.
keksAccountGUI/node_modulesOLD/vuetify/lib/components/VDataTable/VDataTable.js
2019-08-11 20:48:02 +02:00

558 lines
No EOL
17 KiB
JavaScript

import "../../../src/components/VDataTable/VDataTable.sass"; // Components
import { VData } from '../VData';
import { VDataFooter, VDataIterator } from '../VDataIterator';
import VBtn from '../VBtn';
import VDataTableHeader from './VDataTableHeader'; // import VVirtualTable from './VVirtualTable'
import VIcon from '../VIcon';
import VProgressLinear from '../VProgressLinear';
import Row from './Row';
import RowGroup from './RowGroup';
import VSimpleCheckbox from '../VCheckbox/VSimpleCheckbox';
import VSimpleTable from './VSimpleTable';
import MobileRow from './MobileRow';
import ripple from '../../directives/ripple'; // Helpers
import { deepEqual, getObjectValueByPath, getPrefixedScopedSlots, getSlot, defaultFilter } from '../../util/helpers';
import { breaking } from '../../util/console';
function filterFn(item, search, filter) {
return header => {
const value = getObjectValueByPath(item, header.value);
return header.filter ? header.filter(value, search, item) : filter(value, search, item);
};
}
function searchTableItems(items, search, headersWithCustomFilters, headersWithoutCustomFilters, customFilter) {
let filtered = items;
search = typeof search === 'string' ? search.trim() : null;
if (search && headersWithoutCustomFilters.length) {
filtered = items.filter(item => headersWithoutCustomFilters.some(filterFn(item, search, customFilter)));
}
if (headersWithCustomFilters.length) {
filtered = filtered.filter(item => headersWithCustomFilters.every(filterFn(item, search, defaultFilter)));
}
return filtered;
}
/* @vue/component */
export default VDataIterator.extend({
name: 'v-data-table',
// https://github.com/vuejs/vue/issues/6872
directives: {
ripple
},
props: {
headers: {
type: Array
},
showSelect: Boolean,
showExpand: Boolean,
showGroupBy: Boolean,
// TODO: Fix
// virtualRows: Boolean,
mobileBreakpoint: {
type: Number,
default: 600
},
height: [Number, String],
hideDefaultHeader: Boolean,
caption: String,
dense: Boolean,
headerProps: Object,
calculateWidths: Boolean,
fixedHeader: Boolean,
headersLength: Number,
expandIcon: {
type: String,
default: '$vuetify.icons.expand'
},
customFilter: {
type: Function,
default: defaultFilter
}
},
data() {
return {
internalGroupBy: [],
openCache: {},
widths: []
};
},
computed: {
computedHeaders() {
if (!this.headers) return [];
const headers = this.headers.filter(h => h.value === undefined || !this.internalGroupBy.find(v => v === h.value));
const defaultHeader = {
text: '',
sortable: false,
width: '1px'
};
if (this.showSelect) {
const index = headers.findIndex(h => h.value === 'data-table-select');
if (index < 0) headers.unshift({ ...defaultHeader,
value: 'data-table-select'
});else headers.splice(index, 1, { ...defaultHeader,
...headers[index]
});
}
if (this.showExpand) {
const index = headers.findIndex(h => h.value === 'data-table-expand');
if (index < 0) headers.unshift({ ...defaultHeader,
value: 'data-table-expand'
});else headers.splice(index, 1, { ...defaultHeader,
...headers[index]
});
}
return headers;
},
computedHeadersLength() {
return this.headersLength || this.computedHeaders.length;
},
isMobile() {
return this.$vuetify.breakpoint.width < this.mobileBreakpoint;
},
columnSorters() {
return this.computedHeaders.reduce((acc, header) => {
if (header.sort) acc[header.value] = header.sort;
return acc;
}, {});
},
headersWithCustomFilters() {
return this.computedHeaders.filter(header => header.filter);
},
headersWithoutCustomFilters() {
return this.computedHeaders.filter(header => !header.filter);
}
},
created() {
const breakingProps = [['sort-icon', 'header-props.sort-icon'], ['hide-headers', 'hide-default-header'], ['select-all', 'show-select']];
/* istanbul ignore next */
breakingProps.forEach(([original, replacement]) => {
if (this.$attrs.hasOwnProperty(original)) breaking(original, replacement, this);
});
},
mounted() {
// if ((!this.sortBy || !this.sortBy.length) && (!this.options.sortBy || !this.options.sortBy.length)) {
// const firstSortable = this.headers.find(h => !('sortable' in h) || !!h.sortable)
// if (firstSortable) this.updateOptions({ sortBy: [firstSortable.value], sortDesc: [false] })
// }
if (this.calculateWidths) {
window.addEventListener('resize', this.calcWidths);
this.calcWidths();
}
},
beforeDestroy() {
if (this.calculateWidths) {
window.removeEventListener('resize', this.calcWidths);
}
},
methods: {
calcWidths() {
this.widths = Array.from(this.$el.querySelectorAll('th')).map(e => e.clientWidth);
},
customFilterWithColumns(items, search) {
return searchTableItems(items, search, this.headersWithCustomFilters, this.headersWithoutCustomFilters, this.customFilter);
},
customSortWithHeaders(items, sortBy, sortDesc, locale) {
return this.customSort(items, sortBy, sortDesc, locale, this.columnSorters);
},
createItemProps(item) {
const props = VDataIterator.options.methods.createItemProps.call(this, item);
return Object.assign(props, {
headers: this.computedHeaders
});
},
genCaption(props) {
if (this.caption) return [this.$createElement('caption', [this.caption])];
return getSlot(this, 'caption', props, true);
},
genColgroup(props) {
return this.$createElement('colgroup', this.computedHeaders.map(header => {
return this.$createElement('col', {
class: {
divider: header.divider
},
style: {
width: header.width
}
});
}));
},
genLoading() {
const progress = this.$slots['progress'] ? this.$slots.progress : this.$createElement(VProgressLinear, {
props: {
color: this.loading === true ? 'primary' : this.loading,
height: 2,
indeterminate: true
}
});
const th = this.$createElement('th', {
staticClass: 'column',
attrs: {
colspan: this.computedHeadersLength
}
}, [progress]);
const tr = this.$createElement('tr', {
staticClass: 'v-data-table__progress'
}, [th]);
return this.$createElement('thead', [tr]);
},
genHeaders(props) {
const data = {
props: { ...this.headerProps,
headers: this.computedHeaders,
options: props.options,
mobile: this.isMobile,
showGroupBy: this.showGroupBy,
someItems: this.someItems,
everyItem: this.everyItem,
singleSelect: this.singleSelect,
disableSort: this.disableSort
},
on: {
sort: props.sort,
group: props.group,
'toggle-select-all': this.toggleSelectAll
}
};
const children = [getSlot(this, 'header', data)];
if (!this.hideDefaultHeader) {
const scopedSlots = getPrefixedScopedSlots('header.', this.$scopedSlots);
children.push(this.$createElement(VDataTableHeader, { ...data,
scopedSlots
}));
}
if (this.loading) children.push(this.genLoading());
return children;
},
genEmptyWrapper(content) {
return this.$createElement('tr', [this.$createElement('td', {
attrs: {
colspan: this.computedHeadersLength
}
}, content)]);
},
genItems(items, props) {
const empty = this.genEmpty(props.pagination.itemsLength);
if (empty) return [empty];
return props.groupedItems ? this.genGroupedRows(props.groupedItems, props) : this.genRows(items, props);
},
genGroupedRows(groupedItems, props) {
const groups = Object.keys(groupedItems || {});
return groups.map(group => {
if (!this.openCache.hasOwnProperty(group)) this.$set(this.openCache, group, true);
if (this.$scopedSlots.group) {
return this.$scopedSlots.group({
group,
options: props.options,
items: groupedItems[group],
headers: this.computedHeaders
});
} else {
return this.genDefaultGroupedRow(group, groupedItems[group], props);
}
});
},
genDefaultGroupedRow(group, items, props) {
const isOpen = !!this.openCache[group];
const children = [this.$createElement('template', {
slot: 'row.content'
}, this.genDefaultRows(items, props))];
if (this.$scopedSlots['group.header']) {
children.unshift(this.$createElement('template', {
slot: 'column.header'
}, [this.$scopedSlots['group.header']({
group,
groupBy: props.options.groupBy,
items,
headers: this.computedHeaders
})]));
} else {
const toggle = this.$createElement(VBtn, {
staticClass: 'ma-0',
props: {
icon: true,
small: true
},
on: {
click: () => this.$set(this.openCache, group, !this.openCache[group])
}
}, [this.$createElement(VIcon, [isOpen ? 'remove' : 'add'])]);
const remove = this.$createElement(VBtn, {
staticClass: 'ma-0',
props: {
icon: true,
small: true
},
on: {
click: () => props.updateOptions({
groupBy: [],
groupDesc: []
})
}
}, [this.$createElement(VIcon, ['close'])]);
const column = this.$createElement('td', {
staticClass: 'text-start',
attrs: {
colspan: this.computedHeadersLength
}
}, [toggle, `${props.options.groupBy[0]}: ${group}`, remove]);
children.unshift(this.$createElement('template', {
slot: 'column.header'
}, [column]));
}
if (this.$scopedSlots['group.summary']) {
children.push(this.$createElement('template', {
slot: 'column.summary'
}, [this.$scopedSlots['group.summary']({
group,
groupBy: props.options.groupBy,
items,
headers: this.computedHeaders
})]));
}
return this.$createElement(RowGroup, {
key: group,
props: {
value: isOpen
}
}, children);
},
genRows(items, props) {
return this.$scopedSlots.item ? this.genScopedRows(items, props) : this.genDefaultRows(items, props);
},
genScopedRows(items, props) {
const rows = [];
for (let i = 0; i < items.length; i++) {
const item = items[i];
rows.push(this.$scopedSlots.item(this.createItemProps(item)));
if (this.isExpanded(item)) {
rows.push(this.$scopedSlots['expanded-item']({
item,
headers: this.computedHeaders
}));
}
}
return rows;
},
genDefaultRows(items, props) {
return this.$scopedSlots['expanded-item'] ? items.map(item => this.genDefaultExpandedRow(item)) : items.map(item => this.genDefaultSimpleRow(item));
},
genDefaultExpandedRow(item) {
const isExpanded = this.isExpanded(item);
const headerRow = this.genDefaultSimpleRow(item, isExpanded ? 'expanded expanded__row' : null);
const expandedRow = this.$createElement('tr', {
staticClass: 'expanded expanded__content'
}, [this.$scopedSlots['expanded-item']({
item,
headers: this.computedHeaders
})]);
return this.$createElement(RowGroup, {
props: {
value: isExpanded
}
}, [this.$createElement('template', {
slot: 'row.header'
}, [headerRow]), this.$createElement('template', {
slot: 'row.content'
}, [expandedRow])]);
},
genDefaultSimpleRow(item, classes = null) {
const scopedSlots = getPrefixedScopedSlots('item.', this.$scopedSlots);
const data = this.createItemProps(item);
if (this.showSelect) {
const slot = scopedSlots['data-table-select'];
scopedSlots['data-table-select'] = slot ? () => slot(data) : () => this.$createElement(VSimpleCheckbox, {
staticClass: 'v-data-table__checkbox',
props: {
value: data.isSelected
},
on: {
input: val => data.select(val)
}
});
}
if (this.showExpand) {
const slot = scopedSlots['data-table-expand'];
scopedSlots['data-table-expand'] = slot ? () => slot(data) : () => this.$createElement(VIcon, {
staticClass: 'v-data-table__expand-icon',
class: {
'v-data-table__expand-icon--active': data.isExpanded
},
on: {
click: e => {
e.stopPropagation();
data.expand(!data.isExpanded);
}
}
}, [this.expandIcon]);
}
return this.$createElement(this.isMobile ? MobileRow : Row, {
key: getObjectValueByPath(item, this.itemKey),
class: classes,
props: {
headers: this.computedHeaders,
item,
rtl: this.$vuetify.rtl
},
scopedSlots,
on: {
click: () => this.$emit('click:row', item)
}
});
},
genBody(props) {
const data = { ...props,
isMobile: this.isMobile,
headers: this.computedHeaders
};
if (this.$scopedSlots.body) {
return this.$scopedSlots.body(data);
}
return this.$createElement('tbody', [getSlot(this, 'body.prepend', data, true), this.genItems(props.items, props), getSlot(this, 'body.append', data, true)]);
},
genFooters(props) {
const data = {
props: {
options: props.options,
pagination: props.pagination,
itemsPerPageText: '$vuetify.dataTable.itemsPerPageText',
...this.footerProps
},
on: {
'update:options': value => props.updateOptions(value)
},
widths: this.widths,
headers: this.computedHeaders
};
const children = [getSlot(this, 'footer', data, true)];
if (!this.hideDefaultFooter) {
children.push(this.$createElement(VDataFooter, data));
}
return children;
},
genDefaultScopedSlot(props) {
const simpleProps = {
height: this.height,
fixedHeader: this.fixedHeader,
dense: this.dense
}; // if (this.virtualRows) {
// return this.$createElement(VVirtualTable, {
// props: Object.assign(simpleProps, {
// items: props.items,
// height: this.height,
// rowHeight: this.dense ? 24 : 48,
// headerHeight: this.dense ? 32 : 48,
// // TODO: expose rest of props from virtual table?
// }),
// scopedSlots: {
// items: ({ items }) => this.genItems(items, props) as any,
// },
// }, [
// this.proxySlot('body.before', [this.genCaption(props), this.genHeaders(props)]),
// this.proxySlot('bottom', this.genFooters(props)),
// ])
// }
return this.$createElement(VSimpleTable, {
props: simpleProps
}, [this.proxySlot('top', getSlot(this, 'top', props, true)), this.genCaption(props), this.genColgroup(props), this.genHeaders(props), this.genBody(props), this.proxySlot('bottom', this.genFooters(props))]);
},
proxySlot(slot, content) {
return this.$createElement('template', {
slot
}, content);
}
},
render() {
return this.$createElement(VData, {
props: { ...this.$props,
customFilter: this.customFilterWithColumns,
customSort: this.customSortWithHeaders
},
on: {
'update:options': (v, old) => {
this.internalGroupBy = v.groupBy || [];
!deepEqual(v, old) && this.$emit('update:options', v);
},
'update:page': v => this.$emit('update:page', v),
'update:items-per-page': v => this.$emit('update:items-per-page', v),
'update:sort-by': v => this.$emit('update:sort-by', v),
'update:sort-desc': v => this.$emit('update:sort-desc', v),
'update:group-by': v => this.$emit('update:group-by', v),
'update:group-desc': v => this.$emit('update:group-desc', v),
pagination: (v, old) => !deepEqual(v, old) && this.$emit('pagination', v),
'current-items': v => {
this.internalCurrentItems = v;
this.$emit('current-items', v);
},
'page-count': v => this.$emit('page-count', v)
},
scopedSlots: {
default: this.genDefaultScopedSlot
}
});
}
});
//# sourceMappingURL=VDataTable.js.map