vuetify
Version:
Vue Material Component Framework
316 lines (314 loc) • 11.5 kB
JavaScript
// @ts-nocheck
/* eslint-disable */
// Components
import { VData } from "../VData/index.mjs";
import VDataFooter from "./VDataFooter.mjs"; // Mixins
import Mobile from "../../mixins/mobile.mjs";
import Themeable from "../../mixins/themeable.mjs"; // Helpers
import mixins from "../../util/mixins.mjs";
import { deepEqual, getObjectValueByPath, getPrefixedScopedSlots, getSlot, camelizeObjectKeys, keyCodes } from "../../util/helpers.mjs";
import { breaking, removed } from "../../util/console.mjs"; // Types
/* @vue/component */
export default mixins(Mobile, Themeable).extend({
name: 'v-data-iterator',
props: {
...VData.options.props,
// TODO: filter out props not used
itemKey: {
type: String,
default: 'id'
},
value: {
type: Array,
default: () => []
},
singleSelect: Boolean,
expanded: {
type: Array,
default: () => []
},
mobileBreakpoint: {
...Mobile.options.props.mobileBreakpoint,
default: 600
},
singleExpand: Boolean,
loading: [Boolean, String],
noResultsText: {
type: String,
default: '$vuetify.dataIterator.noResultsText'
},
noDataText: {
type: String,
default: '$vuetify.noDataText'
},
loadingText: {
type: String,
default: '$vuetify.dataIterator.loadingText'
},
hideDefaultFooter: Boolean,
footerProps: Object,
selectableKey: {
type: String,
default: 'isSelectable'
}
},
data: () => ({
selection: {},
expansion: {},
internalCurrentItems: [],
shiftKeyDown: false,
lastEntry: -1
}),
computed: {
everyItem() {
return !!this.selectableItems.length && this.selectableItems.every(i => this.isSelected(i));
},
someItems() {
return this.selectableItems.some(i => this.isSelected(i));
},
sanitizedFooterProps() {
return camelizeObjectKeys(this.footerProps);
},
selectableItems() {
return this.internalCurrentItems.filter(item => this.isSelectable(item));
}
},
watch: {
value: {
handler(value) {
this.selection = value.reduce((selection, item) => {
selection[getObjectValueByPath(item, this.itemKey)] = item;
return selection;
}, {});
},
immediate: true
},
selection(value, old) {
if (deepEqual(Object.keys(value), Object.keys(old))) return;
this.$emit('input', Object.values(value));
},
expanded: {
handler(value) {
this.expansion = value.reduce((expansion, item) => {
expansion[getObjectValueByPath(item, this.itemKey)] = true;
return expansion;
}, {});
},
immediate: true
},
expansion(value, old) {
if (deepEqual(value, old)) return;
const keys = Object.keys(value).filter(k => value[k]);
const expanded = !keys.length ? [] : this.items.filter(i => keys.includes(String(getObjectValueByPath(i, this.itemKey))));
this.$emit('update:expanded', expanded);
}
},
created() {
const breakingProps = [['disable-initial-sort', 'sort-by'], ['filter', 'custom-filter'], ['pagination', 'options'], ['total-items', 'server-items-length'], ['hide-actions', 'hide-default-footer'], ['rows-per-page-items', 'footer-props.items-per-page-options'], ['rows-per-page-text', 'footer-props.items-per-page-text'], ['prev-icon', 'footer-props.prev-icon'], ['next-icon', 'footer-props.next-icon']];
/* istanbul ignore next */
breakingProps.forEach(_ref => {
let [original, replacement] = _ref;
if (this.$attrs.hasOwnProperty(original)) breaking(original, replacement, this);
});
const removedProps = ['expand', 'content-class', 'content-props', 'content-tag'];
/* istanbul ignore next */
removedProps.forEach(prop => {
if (this.$attrs.hasOwnProperty(prop)) removed(prop);
});
},
mounted() {
window.addEventListener('keydown', this.onKeyDown);
window.addEventListener('keyup', this.onKeyUp);
},
beforeDestroy() {
window.removeEventListener('keydown', this.onKeyDown);
window.removeEventListener('keyup', this.onKeyUp);
},
methods: {
onKeyDown(e) {
if (e.keyCode !== keyCodes.shift) return;
this.shiftKeyDown = true;
},
onKeyUp(e) {
if (e.keyCode !== keyCodes.shift) return;
this.shiftKeyDown = false;
},
toggleSelectAll(value) {
const selection = Object.assign({}, this.selection);
for (let i = 0; i < this.selectableItems.length; i++) {
const item = this.selectableItems[i];
if (!this.isSelectable(item)) continue;
const key = getObjectValueByPath(item, this.itemKey);
if (value) selection[key] = item;else delete selection[key];
}
this.selection = selection;
this.$emit('toggle-select-all', {
items: this.internalCurrentItems,
value
});
},
isSelectable(item) {
return getObjectValueByPath(item, this.selectableKey) !== false;
},
isSelected(item) {
return !!this.selection[getObjectValueByPath(item, this.itemKey)] || false;
},
select(item) {
let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
let emit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
if (!this.isSelectable(item)) return;
const selection = this.singleSelect ? {} : Object.assign({}, this.selection);
const key = getObjectValueByPath(item, this.itemKey);
if (value) selection[key] = item;else delete selection[key];
const index = this.selectableItems.findIndex(x => getObjectValueByPath(x, this.itemKey) === key);
if (this.lastEntry === -1) this.lastEntry = index;else if (this.shiftKeyDown && !this.singleSelect && emit) {
const lastEntryKey = getObjectValueByPath(this.selectableItems[this.lastEntry], this.itemKey);
const lastEntryKeySelected = Object.keys(this.selection).includes(String(lastEntryKey));
this.multipleSelect(lastEntryKeySelected, emit, selection, index);
}
this.lastEntry = index;
if (this.singleSelect && emit) {
const keys = Object.keys(this.selection);
const old = keys.length && getObjectValueByPath(this.selection[keys[0]], this.itemKey);
old && old !== key && this.$emit('item-selected', {
item: this.selection[old],
value: false
});
}
this.selection = selection;
emit && this.$emit('item-selected', {
item,
value
});
},
multipleSelect() {
let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
let emit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
let selection = arguments.length > 2 ? arguments[2] : undefined;
let index = arguments.length > 3 ? arguments[3] : undefined;
const start = index < this.lastEntry ? index : this.lastEntry;
const end = index < this.lastEntry ? this.lastEntry : index;
for (let i = start; i <= end; i++) {
const currentItem = this.selectableItems[i];
const key = getObjectValueByPath(currentItem, this.itemKey);
if (value) selection[key] = currentItem;else delete selection[key];
emit && this.$emit('item-selected', {
currentItem,
value
});
}
},
isExpanded(item) {
return this.expansion[getObjectValueByPath(item, this.itemKey)] || false;
},
expand(item) {
let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
const expansion = this.singleExpand ? {} : Object.assign({}, this.expansion);
const key = getObjectValueByPath(item, this.itemKey);
if (value) expansion[key] = true;else delete expansion[key];
this.expansion = expansion;
this.$emit('item-expanded', {
item,
value
});
},
createItemProps(item, index) {
return {
item,
index,
select: v => this.select(item, v),
isSelected: this.isSelected(item),
expand: v => this.expand(item, v),
isExpanded: this.isExpanded(item),
isMobile: this.isMobile
};
},
genEmptyWrapper(content) {
return this.$createElement('div', content);
},
genEmpty(originalItemsLength, filteredItemsLength) {
if (originalItemsLength === 0 && this.loading) {
const loading = this.$slots.loading || this.$vuetify.lang.t(this.loadingText);
return this.genEmptyWrapper(loading);
} else if (originalItemsLength === 0) {
const noData = this.$slots['no-data'] || this.$vuetify.lang.t(this.noDataText);
return this.genEmptyWrapper(noData);
} else if (filteredItemsLength === 0) {
const noResults = this.$slots['no-results'] || this.$vuetify.lang.t(this.noResultsText);
return this.genEmptyWrapper(noResults);
}
return null;
},
genItems(props) {
const empty = this.genEmpty(props.originalItemsLength, props.pagination.itemsLength);
if (empty) return [empty];
if (this.$scopedSlots.default) {
return this.$scopedSlots.default({
...props,
isSelected: this.isSelected,
select: this.select,
isExpanded: this.isExpanded,
isMobile: this.isMobile,
expand: this.expand
});
}
if (this.$scopedSlots.item) {
return props.items.map((item, index) => this.$scopedSlots.item(this.createItemProps(item, index)));
}
return [];
},
genFooter(props) {
if (this.hideDefaultFooter) return null;
const data = {
props: {
...this.sanitizedFooterProps,
options: props.options,
pagination: props.pagination
},
on: {
'update:options': value => props.updateOptions(value)
}
};
const scopedSlots = getPrefixedScopedSlots('footer.', this.$scopedSlots);
return this.$createElement(VDataFooter, {
scopedSlots,
...data
});
},
genDefaultScopedSlot(props) {
const outerProps = {
...props,
someItems: this.someItems,
everyItem: this.everyItem,
toggleSelectAll: this.toggleSelectAll
};
return this.$createElement('div', {
staticClass: 'v-data-iterator'
}, [getSlot(this, 'header', outerProps, true), this.genItems(props), this.genFooter(props), getSlot(this, 'footer', outerProps, true)]);
}
},
render() {
return this.$createElement(VData, {
props: this.$props,
on: {
'update:options': (v, old) => !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=VDataIterator.mjs.map