bootstrap-view
Version:
With more than 85 components, over 45 available plugins, several directives, and 1000+ icons, BootstrapVue provides one of the most comprehensive implementations of the Bootstrap v4 component and grid system available for Vue.js v2.6, complete with extens
268 lines (260 loc) • 12.7 kB
JavaScript
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { extend } from '../../../vue';
import { EVENT_NAME_HEAD_CLICKED, EVENT_NAME_SORT_CHANGED, MODEL_EVENT_NAME_PREFIX } from '../../../constants/events';
import { PROP_TYPE_ARRAY_STRING, PROP_TYPE_BOOLEAN, PROP_TYPE_FUNCTION, PROP_TYPE_OBJECT, PROP_TYPE_STRING } from '../../../constants/props';
import { arrayIncludes } from '../../../utils/array';
import { isFunction, isUndefinedOrNull } from '../../../utils/inspect';
import { makeProp } from '../../../utils/props';
import { safeVueInstance } from '../../../utils/safe-vue-instance';
import { stableSort } from '../../../utils/stable-sort';
import { trim } from '../../../utils/string';
import { defaultSortCompare } from './default-sort-compare';
// --- Constants ---
var MODEL_PROP_NAME_SORT_BY = 'sortBy';
var MODEL_EVENT_NAME_SORT_BY = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_SORT_BY;
var MODEL_PROP_NAME_SORT_DESC = 'sortDesc';
var MODEL_EVENT_NAME_SORT_DESC = MODEL_EVENT_NAME_PREFIX + MODEL_PROP_NAME_SORT_DESC;
var SORT_DIRECTION_ASC = 'asc';
var SORT_DIRECTION_DESC = 'desc';
var SORT_DIRECTION_LAST = 'last';
var SORT_DIRECTIONS = [SORT_DIRECTION_ASC, SORT_DIRECTION_DESC, SORT_DIRECTION_LAST];
// --- Props ---
export var props = _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({
labelSortAsc: makeProp(PROP_TYPE_STRING, 'Click to sort ascending'),
labelSortClear: makeProp(PROP_TYPE_STRING, 'Click to clear sorting'),
labelSortDesc: makeProp(PROP_TYPE_STRING, 'Click to sort descending'),
noFooterSorting: makeProp(PROP_TYPE_BOOLEAN, false),
noLocalSorting: makeProp(PROP_TYPE_BOOLEAN, false),
// Another prop that should have had a better name
// It should be `noSortClear` (on non-sortable headers)
// We will need to make sure the documentation is clear on what
// this prop does (as well as in the code for future reference)
noSortReset: makeProp(PROP_TYPE_BOOLEAN, false)
}, MODEL_PROP_NAME_SORT_BY, makeProp(PROP_TYPE_STRING)), "sortCompare", makeProp(PROP_TYPE_FUNCTION)), "sortCompareLocale", makeProp(PROP_TYPE_ARRAY_STRING)), "sortCompareOptions", makeProp(PROP_TYPE_OBJECT, {
numeric: true
})), MODEL_PROP_NAME_SORT_DESC, makeProp(PROP_TYPE_BOOLEAN, false)), "sortDirection", makeProp(PROP_TYPE_STRING, SORT_DIRECTION_ASC, function (value) {
return arrayIncludes(SORT_DIRECTIONS, value);
})), "sortIconLeft", makeProp(PROP_TYPE_BOOLEAN, false)), "sortNullLast", makeProp(PROP_TYPE_BOOLEAN, false));
// --- Mixin ---
// @vue/component
export var sortingMixin = extend({
props: props,
data: function data() {
return {
localSortBy: this[MODEL_PROP_NAME_SORT_BY] || '',
localSortDesc: this[MODEL_PROP_NAME_SORT_DESC] || false
};
},
computed: {
localSorting: function localSorting() {
return this.hasProvider ? !!this.noProviderSorting : !this.noLocalSorting;
},
isSortable: function isSortable() {
return this.computedFields.some(function (f) {
return f.sortable;
});
},
// Sorts the filtered items and returns a new array of the sorted items
// When not sorted, the original items array will be returned
sortedItems: function sortedItems() {
var _safeVueInstance = safeVueInstance(this),
sortBy = _safeVueInstance.localSortBy,
sortDesc = _safeVueInstance.localSortDesc,
locale = _safeVueInstance.sortCompareLocale,
nullLast = _safeVueInstance.sortNullLast,
sortCompare = _safeVueInstance.sortCompare,
localSorting = _safeVueInstance.localSorting,
filteredItems = _safeVueInstance.filteredItems,
localItems = _safeVueInstance.localItems;
var items = (filteredItems || localItems || []).slice();
var localeOptions = _objectSpread(_objectSpread({}, this.sortCompareOptions), {}, {
usage: 'sort'
});
if (sortBy && localSorting) {
var field = this.computedFieldsObj[sortBy] || {};
var sortByFormatted = field.sortByFormatted;
var formatter = isFunction(sortByFormatted) ? /* istanbul ignore next */sortByFormatted : sortByFormatted ? this.getFieldFormatter(sortBy) : undefined;
// `stableSort` returns a new array, and leaves the original array intact
return stableSort(items, function (a, b) {
var result = null;
// Call user provided `sortCompare` routine first
if (isFunction(sortCompare)) {
// TODO:
// Change the `sortCompare` signature to the one of `defaultSortCompare`
// with the next major version bump
result = sortCompare(a, b, sortBy, sortDesc, formatter, localeOptions, locale);
}
// Fallback to built-in `defaultSortCompare` if `sortCompare`
// is not defined or returns `null`/`false`
if (isUndefinedOrNull(result) || result === false) {
result = defaultSortCompare(a, b, {
sortBy: sortBy,
formatter: formatter,
locale: locale,
localeOptions: localeOptions,
nullLast: nullLast
});
}
// Negate result if sorting in descending order
return (result || 0) * (sortDesc ? -1 : 1);
});
}
return items;
}
},
watch: _defineProperty(_defineProperty(_defineProperty(_defineProperty({
/* istanbul ignore next: pain in the butt to test */isSortable: function isSortable(newValue) {
if (newValue) {
if (this.isSortable) {
this.$on(EVENT_NAME_HEAD_CLICKED, this.handleSort);
}
} else {
this.$off(EVENT_NAME_HEAD_CLICKED, this.handleSort);
}
}
}, MODEL_PROP_NAME_SORT_DESC, function (newValue) {
/* istanbul ignore next */
if (newValue === this.localSortDesc) {
return;
}
this.localSortDesc = newValue || false;
}), MODEL_PROP_NAME_SORT_BY, function (newValue) {
/* istanbul ignore next */
if (newValue === this.localSortBy) {
return;
}
this.localSortBy = newValue || '';
}), "localSortDesc", function localSortDesc(newValue, oldValue) {
// Emit update to sort-desc.sync
if (newValue !== oldValue) {
this.$emit(MODEL_EVENT_NAME_SORT_DESC, newValue);
}
}), "localSortBy", function localSortBy(newValue, oldValue) {
if (newValue !== oldValue) {
this.$emit(MODEL_EVENT_NAME_SORT_BY, newValue);
}
}),
created: function created() {
if (this.isSortable) {
this.$on(EVENT_NAME_HEAD_CLICKED, this.handleSort);
}
},
methods: {
// Handlers
// Need to move from thead-mixin
handleSort: function handleSort(key, field, event, isFoot) {
var _this = this;
if (!this.isSortable) {
/* istanbul ignore next */
return;
}
if (isFoot && this.noFooterSorting) {
return;
}
// TODO: make this tri-state sorting
// cycle desc => asc => none => desc => ...
var sortChanged = false;
var toggleLocalSortDesc = function toggleLocalSortDesc() {
var sortDirection = field.sortDirection || _this.sortDirection;
if (sortDirection === SORT_DIRECTION_ASC) {
_this.localSortDesc = false;
} else if (sortDirection === SORT_DIRECTION_DESC) {
_this.localSortDesc = true;
} else {
// sortDirection === 'last'
// Leave at last sort direction from previous column
}
};
if (field.sortable) {
var sortKey = !this.localSorting && field.sortKey ? field.sortKey : key;
if (this.localSortBy === sortKey) {
// Change sorting direction on current column
this.localSortDesc = !this.localSortDesc;
} else {
// Start sorting this column ascending
this.localSortBy = sortKey;
// this.localSortDesc = false
toggleLocalSortDesc();
}
sortChanged = true;
} else if (this.localSortBy && !this.noSortReset) {
this.localSortBy = '';
toggleLocalSortDesc();
sortChanged = true;
}
if (sortChanged) {
// Sorting parameters changed
this.$emit(EVENT_NAME_SORT_CHANGED, this.context);
}
},
// methods to compute classes and attrs for thead>th cells
sortTheadThClasses: function sortTheadThClasses(key, field, isFoot) {
return {
// If sortable and sortIconLeft are true, then place sort icon on the left
'b-table-sort-icon-left': field.sortable && this.sortIconLeft && !(isFoot && this.noFooterSorting)
};
},
sortTheadThAttrs: function sortTheadThAttrs(key, field, isFoot) {
var _field$sortKey;
var isSortable = this.isSortable,
noFooterSorting = this.noFooterSorting,
localSortDesc = this.localSortDesc,
localSortBy = this.localSortBy,
localSorting = this.localSorting;
if (!isSortable || isFoot && noFooterSorting) {
// No attributes if not a sortable table
return {};
}
var sortable = field.sortable;
var sortKey = !localSorting ? (_field$sortKey = field.sortKey) !== null && _field$sortKey !== void 0 ? _field$sortKey : key : key;
// Assemble the aria-sort attribute value
var ariaSort = sortable && localSortBy === sortKey ? localSortDesc ? 'descending' : 'ascending' : sortable ? 'none' : null;
// Return the attribute
return {
'aria-sort': ariaSort
};
},
// A label to be placed in an `.sr-only` element in the header cell
sortTheadThLabel: function sortTheadThLabel(key, field, isFoot) {
// No label if not a sortable table
if (!this.isSortable || isFoot && this.noFooterSorting) {
return null;
}
var localSortBy = this.localSortBy,
localSortDesc = this.localSortDesc,
labelSortAsc = this.labelSortAsc,
labelSortDesc = this.labelSortDesc;
var sortable = field.sortable;
// The correctness of these labels is very important for screen reader users
var labelSorting = '';
if (sortable) {
if (localSortBy === key) {
// Currently sorted sortable column
labelSorting = localSortDesc ? labelSortAsc : labelSortDesc;
} else {
// Not currently sorted sortable column
// Not using nested ternary's here for clarity/readability
// Default for `aria-label`
labelSorting = localSortDesc ? labelSortDesc : labelSortAsc;
// Handle `sortDirection` setting
var sortDirection = this.sortDirection || field.sortDirection;
if (sortDirection === SORT_DIRECTION_ASC) {
labelSorting = labelSortAsc;
} else if (sortDirection === SORT_DIRECTION_DESC) {
labelSorting = labelSortDesc;
}
}
} else if (!this.noSortReset) {
// Non sortable column
labelSorting = localSortBy ? this.labelSortClear : '';
}
// Return the `.sr-only` sort label or `null` if no label
return trim(labelSorting) || null;
}
}
});