StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
706 lines
20 KiB
706 lines
20 KiB
import Vue from '../../utils/vue';
|
|
import KeyCodes from '../../utils/key-codes';
|
|
import noop from '../../utils/noop';
|
|
import observeDom from '../../utils/observe-dom';
|
|
import { getComponentConfig } from '../../utils/config';
|
|
import { selectAll, reflow, addClass, removeClass, setAttr } from '../../utils/dom';
|
|
import { isBrowser, hasTouchSupport, hasPointerEventSupport } from '../../utils/env';
|
|
import { EVENT_OPTIONS_NO_CAPTURE, eventOn, eventOff } from '../../utils/events';
|
|
import { isUndefined } from '../../utils/inspect';
|
|
import { toInteger } from '../../utils/number';
|
|
import idMixin from '../../mixins/id';
|
|
import normalizeSlotMixin from '../../mixins/normalize-slot';
|
|
var NAME = 'BCarousel'; // Slide directional classes
|
|
|
|
var DIRECTION = {
|
|
next: {
|
|
dirClass: 'carousel-item-left',
|
|
overlayClass: 'carousel-item-next'
|
|
},
|
|
prev: {
|
|
dirClass: 'carousel-item-right',
|
|
overlayClass: 'carousel-item-prev'
|
|
}
|
|
}; // Fallback Transition duration (with a little buffer) in ms
|
|
|
|
var TRANS_DURATION = 600 + 50; // Time for mouse compat events to fire after touch
|
|
|
|
var TOUCH_EVENT_COMPAT_WAIT = 500; // Number of pixels to consider touch move a swipe
|
|
|
|
var SWIPE_THRESHOLD = 40; // PointerEvent pointer types
|
|
|
|
var PointerType = {
|
|
TOUCH: 'touch',
|
|
PEN: 'pen'
|
|
}; // Transition Event names
|
|
|
|
var TransitionEndEvents = {
|
|
WebkitTransition: 'webkitTransitionEnd',
|
|
MozTransition: 'transitionend',
|
|
OTransition: 'otransitionend oTransitionEnd',
|
|
transition: 'transitionend'
|
|
}; // Return the browser specific transitionEnd event name
|
|
|
|
var getTransitionEndEvent = function getTransitionEndEvent(el) {
|
|
for (var name in TransitionEndEvents) {
|
|
if (!isUndefined(el.style[name])) {
|
|
return TransitionEndEvents[name];
|
|
}
|
|
} // Fallback
|
|
|
|
/* istanbul ignore next */
|
|
|
|
|
|
return null;
|
|
}; // @vue/component
|
|
|
|
|
|
export var BCarousel =
|
|
/*#__PURE__*/
|
|
Vue.extend({
|
|
name: NAME,
|
|
mixins: [idMixin, normalizeSlotMixin],
|
|
provide: function provide() {
|
|
return {
|
|
bvCarousel: this
|
|
};
|
|
},
|
|
model: {
|
|
prop: 'value',
|
|
event: 'input'
|
|
},
|
|
props: {
|
|
labelPrev: {
|
|
type: String,
|
|
default: function _default() {
|
|
return getComponentConfig(NAME, 'labelPrev');
|
|
}
|
|
},
|
|
labelNext: {
|
|
type: String,
|
|
default: function _default() {
|
|
return getComponentConfig(NAME, 'labelNext');
|
|
}
|
|
},
|
|
labelGotoSlide: {
|
|
type: String,
|
|
default: function _default() {
|
|
return getComponentConfig(NAME, 'labelGotoSlide');
|
|
}
|
|
},
|
|
labelIndicators: {
|
|
type: String,
|
|
default: function _default() {
|
|
return getComponentConfig(NAME, 'labelIndicators');
|
|
}
|
|
},
|
|
interval: {
|
|
type: Number,
|
|
default: 5000
|
|
},
|
|
indicators: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
controls: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
noAnimation: {
|
|
// Disable slide/fade animation
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
fade: {
|
|
// Enable cross-fade animation instead of slide animation
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
noWrap: {
|
|
// Disable wrapping/looping when start/end is reached
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
noTouch: {
|
|
// Sniffed by carousel-slide
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
noHoverPause: {
|
|
// Disable pause on hover
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
imgWidth: {
|
|
// Sniffed by carousel-slide
|
|
type: [Number, String] // default: undefined
|
|
|
|
},
|
|
imgHeight: {
|
|
// Sniffed by carousel-slide
|
|
type: [Number, String] // default: undefined
|
|
|
|
},
|
|
background: {
|
|
type: String // default: undefined
|
|
|
|
},
|
|
value: {
|
|
type: Number,
|
|
default: 0
|
|
}
|
|
},
|
|
data: function data() {
|
|
return {
|
|
index: this.value || 0,
|
|
isSliding: false,
|
|
transitionEndEvent: null,
|
|
slides: [],
|
|
direction: null,
|
|
isPaused: !(toInteger(this.interval) > 0),
|
|
// Touch event handling values
|
|
touchStartX: 0,
|
|
touchDeltaX: 0
|
|
};
|
|
},
|
|
computed: {
|
|
numSlides: function numSlides() {
|
|
return this.slides.length;
|
|
}
|
|
},
|
|
watch: {
|
|
value: function value(newVal, oldVal) {
|
|
if (newVal !== oldVal) {
|
|
this.setSlide(toInteger(newVal) || 0);
|
|
}
|
|
},
|
|
interval: function interval(newVal, oldVal) {
|
|
if (newVal === oldVal) {
|
|
/* istanbul ignore next */
|
|
return;
|
|
}
|
|
|
|
if (!newVal) {
|
|
// Pausing slide show
|
|
this.pause(false);
|
|
} else {
|
|
// Restarting or Changing interval
|
|
this.pause(true);
|
|
this.start(false);
|
|
}
|
|
},
|
|
isPaused: function isPaused(newVal, oldVal) {
|
|
if (newVal !== oldVal) {
|
|
this.$emit(newVal ? 'paused' : 'unpaused');
|
|
}
|
|
},
|
|
index: function index(to, from) {
|
|
if (to === from || this.isSliding) {
|
|
/* istanbul ignore next */
|
|
return;
|
|
}
|
|
|
|
this.doSlide(to, from);
|
|
}
|
|
},
|
|
created: function created() {
|
|
// Create private non-reactive props
|
|
this._intervalId = null;
|
|
this._animationTimeout = null;
|
|
this._touchTimeout = null; // Set initial paused state
|
|
|
|
this.isPaused = !(toInteger(this.interval) > 0);
|
|
},
|
|
mounted: function mounted() {
|
|
// Cache current browser transitionend event name
|
|
this.transitionEndEvent = getTransitionEndEvent(this.$el) || null; // Get all slides
|
|
|
|
this.updateSlides(); // Observe child changes so we can update slide list
|
|
|
|
observeDom(this.$refs.inner, this.updateSlides.bind(this), {
|
|
subtree: false,
|
|
childList: true,
|
|
attributes: true,
|
|
attributeFilter: ['id']
|
|
});
|
|
},
|
|
beforeDestroy: function beforeDestroy() {
|
|
clearTimeout(this._animationTimeout);
|
|
clearTimeout(this._touchTimeout);
|
|
clearInterval(this._intervalId);
|
|
this._intervalId = null;
|
|
this._animationTimeout = null;
|
|
this._touchTimeout = null;
|
|
},
|
|
methods: {
|
|
// Set slide
|
|
setSlide: function setSlide(slide) {
|
|
var _this = this;
|
|
|
|
var direction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
|
|
// Don't animate when page is not visible
|
|
|
|
/* istanbul ignore if: difficult to test */
|
|
if (isBrowser && document.visibilityState && document.hidden) {
|
|
return;
|
|
}
|
|
|
|
var noWrap = this.noWrap;
|
|
var numSlides = this.numSlides; // Make sure we have an integer (you never know!)
|
|
|
|
slide = Math.floor(slide); // Don't do anything if nothing to slide to
|
|
|
|
if (numSlides === 0) {
|
|
return;
|
|
} // Don't change slide while transitioning, wait until transition is done
|
|
|
|
|
|
if (this.isSliding) {
|
|
// Schedule slide after sliding complete
|
|
this.$once('sliding-end', function () {
|
|
return _this.setSlide(slide, direction);
|
|
});
|
|
return;
|
|
}
|
|
|
|
this.direction = direction; // Set new slide index
|
|
// Wrap around if necessary (if no-wrap not enabled)
|
|
|
|
this.index = slide >= numSlides ? noWrap ? numSlides - 1 : 0 : slide < 0 ? noWrap ? 0 : numSlides - 1 : slide; // Ensure the v-model is synched up if no-wrap is enabled
|
|
// and user tried to slide pass either ends
|
|
|
|
if (noWrap && this.index !== slide && this.index !== this.value) {
|
|
this.$emit('input', this.index);
|
|
}
|
|
},
|
|
// Previous slide
|
|
prev: function prev() {
|
|
this.setSlide(this.index - 1, 'prev');
|
|
},
|
|
// Next slide
|
|
next: function next() {
|
|
this.setSlide(this.index + 1, 'next');
|
|
},
|
|
// Pause auto rotation
|
|
pause: function pause(evt) {
|
|
if (!evt) {
|
|
this.isPaused = true;
|
|
}
|
|
|
|
if (this._intervalId) {
|
|
clearInterval(this._intervalId);
|
|
this._intervalId = null;
|
|
}
|
|
},
|
|
// Start auto rotate slides
|
|
start: function start(evt) {
|
|
if (!evt) {
|
|
this.isPaused = false;
|
|
}
|
|
/* istanbul ignore next: most likely will never happen, but just in case */
|
|
|
|
|
|
if (this._intervalId) {
|
|
clearInterval(this._intervalId);
|
|
this._intervalId = null;
|
|
} // Don't start if no interval, or less than 2 slides
|
|
|
|
|
|
if (this.interval && this.numSlides > 1) {
|
|
this._intervalId = setInterval(this.next, Math.max(1000, this.interval));
|
|
}
|
|
},
|
|
// Restart auto rotate slides when focus/hover leaves the carousel
|
|
restart: function restart()
|
|
/* istanbul ignore next: difficult to test */
|
|
{
|
|
if (!this.$el.contains(document.activeElement)) {
|
|
this.start();
|
|
}
|
|
},
|
|
doSlide: function doSlide(to, from) {
|
|
var _this2 = this;
|
|
|
|
var isCycling = Boolean(this.interval); // Determine sliding direction
|
|
|
|
var direction = this.calcDirection(this.direction, from, to);
|
|
var overlayClass = direction.overlayClass;
|
|
var dirClass = direction.dirClass; // Determine current and next slides
|
|
|
|
var currentSlide = this.slides[from];
|
|
var nextSlide = this.slides[to]; // Don't do anything if there aren't any slides to slide to
|
|
|
|
if (!currentSlide || !nextSlide) {
|
|
/* istanbul ignore next */
|
|
return;
|
|
} // Start animating
|
|
|
|
|
|
this.isSliding = true;
|
|
|
|
if (isCycling) {
|
|
this.pause(false);
|
|
}
|
|
|
|
this.$emit('sliding-start', to); // Update v-model
|
|
|
|
this.$emit('input', this.index);
|
|
|
|
if (this.noAnimation) {
|
|
addClass(nextSlide, 'active');
|
|
removeClass(currentSlide, 'active');
|
|
this.isSliding = false; // Notify ourselves that we're done sliding (slid)
|
|
|
|
this.$nextTick(function () {
|
|
return _this2.$emit('sliding-end', to);
|
|
});
|
|
} else {
|
|
addClass(nextSlide, overlayClass); // Trigger a reflow of next slide
|
|
|
|
reflow(nextSlide);
|
|
addClass(currentSlide, dirClass);
|
|
addClass(nextSlide, dirClass); // Transition End handler
|
|
|
|
var called = false;
|
|
/* istanbul ignore next: difficult to test */
|
|
|
|
var onceTransEnd = function onceTransEnd() {
|
|
if (called) {
|
|
return;
|
|
}
|
|
|
|
called = true;
|
|
/* istanbul ignore if: transition events cant be tested in JSDOM */
|
|
|
|
if (_this2.transitionEndEvent) {
|
|
var events = _this2.transitionEndEvent.split(/\s+/);
|
|
|
|
events.forEach(function (evt) {
|
|
return eventOff(currentSlide, evt, onceTransEnd, EVENT_OPTIONS_NO_CAPTURE);
|
|
});
|
|
}
|
|
|
|
_this2._animationTimeout = null;
|
|
removeClass(nextSlide, dirClass);
|
|
removeClass(nextSlide, overlayClass);
|
|
addClass(nextSlide, 'active');
|
|
removeClass(currentSlide, 'active');
|
|
removeClass(currentSlide, dirClass);
|
|
removeClass(currentSlide, overlayClass);
|
|
setAttr(currentSlide, 'aria-current', 'false');
|
|
setAttr(nextSlide, 'aria-current', 'true');
|
|
setAttr(currentSlide, 'aria-hidden', 'true');
|
|
setAttr(nextSlide, 'aria-hidden', 'false');
|
|
_this2.isSliding = false;
|
|
_this2.direction = null; // Notify ourselves that we're done sliding (slid)
|
|
|
|
_this2.$nextTick(function () {
|
|
return _this2.$emit('sliding-end', to);
|
|
});
|
|
}; // Set up transitionend handler
|
|
|
|
/* istanbul ignore if: transition events cant be tested in JSDOM */
|
|
|
|
|
|
if (this.transitionEndEvent) {
|
|
var events = this.transitionEndEvent.split(/\s+/);
|
|
events.forEach(function (event) {
|
|
return eventOn(currentSlide, event, onceTransEnd, EVENT_OPTIONS_NO_CAPTURE);
|
|
});
|
|
} // Fallback to setTimeout()
|
|
|
|
|
|
this._animationTimeout = setTimeout(onceTransEnd, TRANS_DURATION);
|
|
}
|
|
|
|
if (isCycling) {
|
|
this.start(false);
|
|
}
|
|
},
|
|
// Update slide list
|
|
updateSlides: function updateSlides() {
|
|
this.pause(true); // Get all slides as DOM elements
|
|
|
|
this.slides = selectAll('.carousel-item', this.$refs.inner);
|
|
var numSlides = this.slides.length; // Keep slide number in range
|
|
|
|
var index = Math.max(0, Math.min(Math.floor(this.index), numSlides - 1));
|
|
this.slides.forEach(function (slide, idx) {
|
|
var n = idx + 1;
|
|
|
|
if (idx === index) {
|
|
addClass(slide, 'active');
|
|
setAttr(slide, 'aria-current', 'true');
|
|
} else {
|
|
removeClass(slide, 'active');
|
|
setAttr(slide, 'aria-current', 'false');
|
|
}
|
|
|
|
setAttr(slide, 'aria-posinset', String(n));
|
|
setAttr(slide, 'aria-setsize', String(numSlides));
|
|
}); // Set slide as active
|
|
|
|
this.setSlide(index);
|
|
this.start(this.isPaused);
|
|
},
|
|
calcDirection: function calcDirection() {
|
|
var direction = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
var curIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
var nextIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
|
|
if (!direction) {
|
|
return nextIndex > curIndex ? DIRECTION.next : DIRECTION.prev;
|
|
}
|
|
|
|
return DIRECTION[direction];
|
|
},
|
|
handleClick: function handleClick(evt, fn) {
|
|
var keyCode = evt.keyCode;
|
|
|
|
if (evt.type === 'click' || keyCode === KeyCodes.SPACE || keyCode === KeyCodes.ENTER) {
|
|
evt.preventDefault();
|
|
evt.stopPropagation();
|
|
fn();
|
|
}
|
|
},
|
|
handleSwipe: function handleSwipe()
|
|
/* istanbul ignore next: JSDOM doesn't support touch events */
|
|
{
|
|
var absDeltaX = Math.abs(this.touchDeltaX);
|
|
|
|
if (absDeltaX <= SWIPE_THRESHOLD) {
|
|
return;
|
|
}
|
|
|
|
var direction = absDeltaX / this.touchDeltaX; // Reset touch delta X
|
|
// https://github.com/twbs/bootstrap/pull/28558
|
|
|
|
this.touchDeltaX = 0;
|
|
|
|
if (direction > 0) {
|
|
// Swipe left
|
|
this.prev();
|
|
} else if (direction < 0) {
|
|
// Swipe right
|
|
this.next();
|
|
}
|
|
},
|
|
touchStart: function touchStart(evt)
|
|
/* istanbul ignore next: JSDOM doesn't support touch events */
|
|
{
|
|
if (hasPointerEventSupport && PointerType[evt.pointerType.toUpperCase()]) {
|
|
this.touchStartX = evt.clientX;
|
|
} else if (!hasPointerEventSupport) {
|
|
this.touchStartX = evt.touches[0].clientX;
|
|
}
|
|
},
|
|
touchMove: function touchMove(evt)
|
|
/* istanbul ignore next: JSDOM doesn't support touch events */
|
|
{
|
|
// Ensure swiping with one touch and not pinching
|
|
if (evt.touches && evt.touches.length > 1) {
|
|
this.touchDeltaX = 0;
|
|
} else {
|
|
this.touchDeltaX = evt.touches[0].clientX - this.touchStartX;
|
|
}
|
|
},
|
|
touchEnd: function touchEnd(evt)
|
|
/* istanbul ignore next: JSDOM doesn't support touch events */
|
|
{
|
|
if (hasPointerEventSupport && PointerType[evt.pointerType.toUpperCase()]) {
|
|
this.touchDeltaX = evt.clientX - this.touchStartX;
|
|
}
|
|
|
|
this.handleSwipe(); // If it's a touch-enabled device, mouseenter/leave are fired as
|
|
// part of the mouse compatibility events on first tap - the carousel
|
|
// would stop cycling until user tapped out of it;
|
|
// here, we listen for touchend, explicitly pause the carousel
|
|
// (as if it's the second time we tap on it, mouseenter compat event
|
|
// is NOT fired) and after a timeout (to allow for mouse compatibility
|
|
// events to fire) we explicitly restart cycling
|
|
|
|
this.pause(false);
|
|
|
|
if (this._touchTimeout) {
|
|
clearTimeout(this._touchTimeout);
|
|
}
|
|
|
|
this._touchTimeout = setTimeout(this.start, TOUCH_EVENT_COMPAT_WAIT + Math.max(1000, this.interval));
|
|
}
|
|
},
|
|
render: function render(h) {
|
|
var _this3 = this;
|
|
|
|
// Wrapper for slides
|
|
var inner = h('div', {
|
|
ref: 'inner',
|
|
class: ['carousel-inner'],
|
|
attrs: {
|
|
id: this.safeId('__BV_inner_'),
|
|
role: 'list'
|
|
}
|
|
}, [this.normalizeSlot('default')]); // Prev and next controls
|
|
|
|
var controls = h();
|
|
|
|
if (this.controls) {
|
|
var prevHandler = function prevHandler(evt) {
|
|
/* istanbul ignore next */
|
|
if (!_this3.isSliding) {
|
|
_this3.handleClick(evt, _this3.prev);
|
|
} else {
|
|
evt.preventDefault();
|
|
}
|
|
};
|
|
|
|
var nextHandler = function nextHandler(evt) {
|
|
/* istanbul ignore next */
|
|
if (!_this3.isSliding) {
|
|
_this3.handleClick(evt, _this3.next);
|
|
} else {
|
|
evt.preventDefault();
|
|
}
|
|
};
|
|
|
|
controls = [h('a', {
|
|
class: ['carousel-control-prev'],
|
|
attrs: {
|
|
href: '#',
|
|
role: 'button',
|
|
'aria-controls': this.safeId('__BV_inner_'),
|
|
'aria-disabled': this.isSliding ? 'true' : null
|
|
},
|
|
on: {
|
|
click: prevHandler,
|
|
keydown: prevHandler
|
|
}
|
|
}, [h('span', {
|
|
class: ['carousel-control-prev-icon'],
|
|
attrs: {
|
|
'aria-hidden': 'true'
|
|
}
|
|
}), h('span', {
|
|
class: ['sr-only']
|
|
}, [this.labelPrev])]), h('a', {
|
|
class: ['carousel-control-next'],
|
|
attrs: {
|
|
href: '#',
|
|
role: 'button',
|
|
'aria-controls': this.safeId('__BV_inner_'),
|
|
'aria-disabled': this.isSliding ? 'true' : null
|
|
},
|
|
on: {
|
|
click: nextHandler,
|
|
keydown: nextHandler
|
|
}
|
|
}, [h('span', {
|
|
class: ['carousel-control-next-icon'],
|
|
attrs: {
|
|
'aria-hidden': 'true'
|
|
}
|
|
}), h('span', {
|
|
class: ['sr-only']
|
|
}, [this.labelNext])])];
|
|
} // Indicators
|
|
|
|
|
|
var indicators = h('ol', {
|
|
class: ['carousel-indicators'],
|
|
directives: [{
|
|
name: 'show',
|
|
rawName: 'v-show',
|
|
value: this.indicators,
|
|
expression: 'indicators'
|
|
}],
|
|
attrs: {
|
|
id: this.safeId('__BV_indicators_'),
|
|
'aria-hidden': this.indicators ? 'false' : 'true',
|
|
'aria-label': this.labelIndicators,
|
|
'aria-owns': this.safeId('__BV_inner_')
|
|
}
|
|
}, this.slides.map(function (slide, n) {
|
|
return h('li', {
|
|
key: "slide_".concat(n),
|
|
class: {
|
|
active: n === _this3.index
|
|
},
|
|
attrs: {
|
|
role: 'button',
|
|
id: _this3.safeId("__BV_indicator_".concat(n + 1, "_")),
|
|
tabindex: _this3.indicators ? '0' : '-1',
|
|
'aria-current': n === _this3.index ? 'true' : 'false',
|
|
'aria-label': "".concat(_this3.labelGotoSlide, " ").concat(n + 1),
|
|
'aria-describedby': _this3.slides[n].id || null,
|
|
'aria-controls': _this3.safeId('__BV_inner_')
|
|
},
|
|
on: {
|
|
click: function click(evt) {
|
|
_this3.handleClick(evt, function () {
|
|
_this3.setSlide(n);
|
|
});
|
|
},
|
|
keydown: function keydown(evt) {
|
|
_this3.handleClick(evt, function () {
|
|
_this3.setSlide(n);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}));
|
|
var on = {
|
|
mouseenter: this.noHoverPause ? noop : this.pause,
|
|
mouseleave: this.noHoverPause ? noop : this.restart,
|
|
focusin: this.pause,
|
|
focusout: this.restart,
|
|
keydown: function keydown(evt) {
|
|
if (/input|textarea/i.test(evt.target.tagName)) {
|
|
/* istanbul ignore next */
|
|
return;
|
|
}
|
|
|
|
var keyCode = evt.keyCode;
|
|
|
|
if (keyCode === KeyCodes.LEFT || keyCode === KeyCodes.RIGHT) {
|
|
evt.preventDefault();
|
|
evt.stopPropagation();
|
|
|
|
_this3[keyCode === KeyCodes.LEFT ? 'prev' : 'next']();
|
|
}
|
|
}
|
|
}; // Touch support event handlers for environment
|
|
|
|
if (!this.noTouch && hasTouchSupport) {
|
|
// Attach appropriate listeners (prepend event name with '&' for passive mode)
|
|
|
|
/* istanbul ignore next: JSDOM doesn't support touch events */
|
|
if (hasPointerEventSupport) {
|
|
on['&pointerdown'] = this.touchStart;
|
|
on['&pointerup'] = this.touchEnd;
|
|
} else {
|
|
on['&touchstart'] = this.touchStart;
|
|
on['&touchmove'] = this.touchMove;
|
|
on['&touchend'] = this.touchEnd;
|
|
}
|
|
} // Return the carousel
|
|
|
|
|
|
return h('div', {
|
|
staticClass: 'carousel',
|
|
class: {
|
|
slide: !this.noAnimation,
|
|
'carousel-fade': !this.noAnimation && this.fade,
|
|
'pointer-event': !this.noTouch && hasTouchSupport && hasPointerEventSupport
|
|
},
|
|
style: {
|
|
background: this.background
|
|
},
|
|
attrs: {
|
|
role: 'region',
|
|
id: this.safeId(),
|
|
'aria-busy': this.isSliding ? 'true' : 'false'
|
|
},
|
|
on: on
|
|
}, [inner, controls, indicators]);
|
|
}
|
|
}); |