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.

225 lines
4.7 KiB

import * as Hammer from 'hammerjs'
/**
* Mixin for extends Riot-Component
*
* @author Björn Hase
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/slider
*
*/
export default {
/**
*
*
*/
state: {
position: 0,
max: 0,
slides: undefined,
classes: {
item: 'tiny-slider__item'
}
},
/**
*
*
*/
onMounted() {
if (this.props.slides) {
this.state.slides = this.props.slides
}
// start and add resize listener
window.addEventListener('resize', this.update.bind(this))
setTimeout(() => {
this.update()
}, 100)
// Create a manager to manager the element
const manager = new Hammer(this.root)
manager.on('swipe', (event) => {
if (event.direction === 4) {
this.handlePrevious(event)
} else if (event.direction === 2) {
this.handleNext(event)
}
})
},
/**
* remove resize listener before unmount
*
*/
onBeforeUnmount() {
window.removeEventListener('resize', this.update.bind(this))
},
/**
* before update view, calculate values
*
* @param {object} props
* @param {object} state
*
*/
onBeforeUpdate(props, state) {
// getting current max
const max = this.state.max
// setting max to show visible
this.state.max = 0
this.state.width = this.$('.' + this.state.classes.item).offsetWidth
// check how many elements can visible in element
this.$$('.' + this.state.classes.item).forEach((element, index) => {
if (element.offsetLeft < this.root.offsetWidth) {
this.state.max++;
}
})
// change position to fit new max value
const value = Math.abs(this.state.max - max)
// @TODO check this, at 0 it makes me mad
if (this.state.position >= value && this.state.position > 1) {
this.state.position -= value
}
},
/**
* set current position
*
*
*/
handleSelect(event, position) {
event.preventDefault()
if (this.state.position !== position) {
this.update({
position: position
})
}
},
/**
* set next postion
*
*
*/
handlePrevious(event) {
event.preventDefault()
if (this.state.position > 0) {
this.update({
position: --this.state.position
})
}
},
/**
* set next postion
*
*
* @param {object} event
*
*/
handleNext(event) {
event.preventDefault()
if (this.state.position < (this.props.slides.length - 1)) {
this.update({
position: ++this.state.position
})
}
},
/**
* getting classes for next-button,
* show button only
*
*
* @return {string}
*
*/
getPreviousClasses() {
const classes = [
'tiny-slider__button',
'tiny-slider__button--previous'
]
if (this.state.position > 0) {
classes.push('visibility-visible')
} else {
classes.push('visibility-hidden')
}
return classes.join(' ')
},
/**
* getting classes for next-button,
* show button unless length is smaller then max
*
* @return {string}
*
*/
getNextClasses() {
const classes = [
'tiny-slider__button',
'tiny-slider__button--next'
]
if (this.state.position <= (this.props.slides.length - this.state.max)) {
classes.push('visibility-visible')
} else {
classes.push('visibility-hidden')
}
return classes.join(' ')
},
/**
* getting classes for select,
* adding current-class if postion and state.postion are equal
*
* @param {integer} position
* @return {string}
*
*/
getSelectClasses(position) {
const classes = [
'tiny-slider__select-item'
]
if (this.state.position === position) {
classes.push('tiny-slider__select-item--current')
}
return classes.join(' ')
},
/**
* set translate with position and witdh
*
*
* @return {string}
*
*/
getContentStyles() {
// getting value for position
const value = (-(this.state.position * this.state.width));
return this.styles({
transform: 'translate(' + value + 'px, 0px)'
})
}
}