bootstrap-vue
Version:
BootstrapVue provides one of the most comprehensive implementations of Bootstrap 4 components and grid system for Vue.js and with extensive and automated WAI-ARIA accessibility markup.
187 lines (185 loc) • 4.17 kB
JavaScript
import bImg from './img'
import { isVisible, getBCR, eventOn, eventOff } from '../../utils/dom'
const THROTTLE = 100
export default {
components: { bImg },
render (h) {
const t = this
return h(
'b-img',
{
props: {
src: t.computedSrc,
alt: t.alt,
blank: t.computedBlank,
blankColor: t.blankColor,
width: t.computedWidth,
height: t.computedHeight,
fluid: t.fluid,
fluidGrow: t.fluidGrow,
block: t.block,
thumbnail: t.thumbnail,
rounded: t.rounded,
left: t.left,
right: t.right,
center: t.center
}
}
)
},
data () {
return {
isShown: false,
scrollTimeout: null
}
},
props: {
src: {
type: String,
default: null,
required: true
},
alt: {
type: String,
default: null
},
width: {
type: [Number, String],
default: null
},
height: {
type: [Number, String],
default: null
},
blankSrc: {
// If null, a blank image is generated
type: String,
default: null
},
blankColor: {
type: String,
default: 'transparent'
},
blankWidth: {
type: [Number, String],
default: null
},
blankHeight: {
type: [Number, String],
default: null
},
fluid: {
type: Boolean,
default: false
},
fluidGrow: {
type: Boolean,
default: false
},
block: {
type: Boolean,
default: false
},
thumbnail: {
type: Boolean,
default: false
},
rounded: {
type: [Boolean, String],
default: false
},
left: {
type: Boolean,
default: false
},
right: {
type: Boolean,
default: false
},
center: {
type: Boolean,
default: false
},
offset: {
type: [Number, String],
default: 360
},
throttle: {
type: [Number, String],
default: THROTTLE
}
},
computed: {
computedSrc () {
return (!this.blankSrc || this.isShown) ? this.src : this.blankSrc
},
computedBlank () {
return !((this.isShown || this.blankSrc))
},
computedWidth () {
return this.isShown ? this.width : (this.blankWidth || this.width)
},
computedHeight () {
return this.isShown ? this.height : (this.blankHeight || this.height)
}
},
mounted () {
this.setListeners(true)
this.checkView()
},
activated () {
this.setListeners(true)
this.checkView()
},
deactivated () {
this.setListeners(false)
},
beforeDdestroy () {
this.setListeners(false)
},
methods: {
setListeners (on) {
clearTimeout(this.scrollTimer)
this.scrollTimout = null
const root = window
if (on) {
eventOn(root, 'scroll', this.onScroll)
eventOn(root, 'resize', this.onScroll)
eventOn(root, 'orientationchange', this.onScroll)
} else {
eventOff(root, 'scroll', this.onScroll)
eventOff(root, 'resize', this.onScroll)
eventOff(root, 'orientationchange', this.onScroll)
}
},
checkView () {
// check bounding box + offset to see if we should show
if (!isVisible(this.$el)) {
// Element is hidden, so skip for now
return
}
const offset = parseInt(this.offset, 10) || 0
const docElement = document.documentElement
const view = {
l: 0 - offset,
t: 0 - offset,
b: docElement.clientHeight + offset,
r: docElement.clientWidth + offset
}
const box = getBCR(this.$el)
if (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b) {
// image is in view (or about to be in view)
this.isShown = true
this.setListeners(false)
}
},
onScroll () {
if (this.isShown) {
this.setListeners(false)
} else {
clearTimeout(this.scrollTimeout)
this.scrollTimeout = setTimeout(this.checkView, parseInt(this.throttle, 10) || THROTTLE)
}
}
}
}