2018-07-27 15:31:39 +00:00
|
|
|
<template>
|
|
|
|
<transition
|
2019-05-19 16:58:30 +00:00
|
|
|
id="p-loading-bar"
|
2018-07-27 15:31:39 +00:00
|
|
|
v-on:before-enter="beforeEnter"
|
|
|
|
v-on:enter="enter"
|
|
|
|
v-on:after-enter="afterEnter"
|
|
|
|
v-bind:css="false"
|
|
|
|
>
|
|
|
|
<div class="top-progress" :style="barStyle" v-if="show">
|
|
|
|
<div class="peg" :style="pegStyle">
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</transition>
|
|
|
|
</template>
|
|
|
|
<script>
|
|
|
|
function clamp(n, min, max) {
|
|
|
|
if (n < min) {
|
|
|
|
return min
|
|
|
|
}
|
|
|
|
if (n > max) {
|
|
|
|
return max
|
|
|
|
}
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
let queue = (() => {
|
2019-05-19 15:52:23 +00:00
|
|
|
let pending = [];
|
2018-07-27 15:31:39 +00:00
|
|
|
|
|
|
|
function next() {
|
2019-05-19 15:52:23 +00:00
|
|
|
let fn = pending.shift();
|
|
|
|
|
2018-07-27 15:31:39 +00:00
|
|
|
if (fn) {
|
|
|
|
fn(next)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fn => {
|
2019-05-19 15:52:23 +00:00
|
|
|
pending.push(fn);
|
|
|
|
|
2018-07-27 15:31:39 +00:00
|
|
|
if (pending.length === 1) {
|
|
|
|
next()
|
|
|
|
}
|
|
|
|
}
|
2019-05-19 15:52:23 +00:00
|
|
|
})();
|
2018-07-27 15:31:39 +00:00
|
|
|
|
|
|
|
export default {
|
2019-05-19 16:19:41 +00:00
|
|
|
name: "PLoadingBar",
|
2018-07-27 15:31:39 +00:00
|
|
|
data () {
|
|
|
|
return {
|
|
|
|
error: false,
|
|
|
|
show: false,
|
|
|
|
progress: 0,
|
|
|
|
opacity: 1,
|
|
|
|
status: null,
|
|
|
|
isPaused: false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
mounted () {
|
|
|
|
const overlay = document.createElement("div");
|
2019-05-19 16:58:30 +00:00
|
|
|
overlay.id = 'p-busy-overlay';
|
2018-07-27 15:31:39 +00:00
|
|
|
document.body.appendChild(overlay);
|
|
|
|
|
|
|
|
let stackSize = 0;
|
|
|
|
|
|
|
|
this.$event.subscribe('ajax.start', function () {
|
|
|
|
stackSize++;
|
|
|
|
|
|
|
|
if(stackSize === 1) {
|
|
|
|
this.start();
|
2019-05-19 16:58:30 +00:00
|
|
|
document.getElementById('p-busy-overlay').style.display = 'block';
|
2018-07-27 15:31:39 +00:00
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
this.$event.subscribe('ajax.end', function () {
|
|
|
|
stackSize--;
|
|
|
|
|
|
|
|
if (stackSize === 0) {
|
|
|
|
this.done();
|
2019-05-19 16:58:30 +00:00
|
|
|
document.getElementById('p-busy-overlay').style.display = 'none';
|
2018-07-27 15:31:39 +00:00
|
|
|
}
|
|
|
|
}.bind(this));
|
|
|
|
},
|
|
|
|
|
|
|
|
props: {
|
|
|
|
speed: {
|
|
|
|
type: Number,
|
|
|
|
default: 350
|
|
|
|
},
|
|
|
|
|
|
|
|
color: {
|
|
|
|
type: String,
|
|
|
|
default: '#29d'
|
|
|
|
},
|
|
|
|
|
|
|
|
errorColor: {
|
|
|
|
type: String,
|
|
|
|
default: '#f44336'
|
|
|
|
},
|
|
|
|
|
|
|
|
trickle: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true
|
|
|
|
},
|
|
|
|
|
|
|
|
trickleSpeed: {
|
|
|
|
type: Number,
|
|
|
|
default: 250
|
|
|
|
},
|
|
|
|
|
|
|
|
easing: {
|
|
|
|
type: String,
|
|
|
|
default: 'linear'
|
|
|
|
},
|
|
|
|
|
|
|
|
height: {
|
|
|
|
type: [Number, String],
|
|
|
|
default: 3
|
|
|
|
},
|
|
|
|
|
|
|
|
minimum: {
|
|
|
|
type: Number,
|
|
|
|
default: 0.8
|
|
|
|
},
|
|
|
|
|
|
|
|
maximum: {
|
|
|
|
type: Number,
|
|
|
|
default: 97.5
|
|
|
|
},
|
|
|
|
|
|
|
|
zIndex: {
|
|
|
|
type: Number,
|
|
|
|
default: 9999
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
computed: {
|
|
|
|
progressColor () {
|
|
|
|
return this.error ? this.errorColor : this.color
|
|
|
|
},
|
|
|
|
|
|
|
|
isStarted () {
|
|
|
|
return typeof this.status === 'number'
|
|
|
|
},
|
|
|
|
|
|
|
|
barStyle () {
|
|
|
|
return {
|
|
|
|
position: 'fixed',
|
|
|
|
top: '0',
|
|
|
|
left: '0',
|
|
|
|
right: '0',
|
|
|
|
width: `${this.progress}%`,
|
|
|
|
height: `${this.height}px`,
|
|
|
|
backgroundColor: this.progressColor,
|
|
|
|
transition: `all ${this.speed}ms ${this.easing}`,
|
|
|
|
opacity: `${this.opacity}`,
|
|
|
|
zIndex: `${this.zIndex}`
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
pegStyle () {
|
|
|
|
return {
|
|
|
|
display: 'block',
|
|
|
|
position: 'absolute',
|
|
|
|
right: '0',
|
|
|
|
width: '100px',
|
|
|
|
height: '100%',
|
|
|
|
opacity: this.progress ? '1' : '0',
|
|
|
|
boxShadow: `0 0 10px ${this.progressColor}, 0 0 5px ${this.progressColor}`,
|
|
|
|
transform: 'rotate(3deg) translate(0px, -4px)'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
beforeEnter (el) {
|
|
|
|
this.opacity = 0
|
|
|
|
this.progress = 0
|
|
|
|
this.width = 0
|
|
|
|
},
|
|
|
|
|
|
|
|
enter (el, done) {
|
|
|
|
this.opacity = 1
|
|
|
|
done()
|
|
|
|
},
|
|
|
|
|
|
|
|
afterEnter (el) {
|
|
|
|
this._runStart()
|
|
|
|
},
|
|
|
|
|
|
|
|
_work () {
|
|
|
|
setTimeout(() => {
|
|
|
|
if (!this.isStarted || this.isPaused) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
this.increase()
|
|
|
|
this._work()
|
|
|
|
}, this.trickleSpeed)
|
|
|
|
},
|
|
|
|
|
|
|
|
_runStart () {
|
|
|
|
this.status = (this.progress === 100 ? null : this.progress)
|
|
|
|
|
|
|
|
if (this.trickle) {
|
|
|
|
this._work()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
start () {
|
|
|
|
this.isPaused = false
|
|
|
|
|
|
|
|
if (this.show) {
|
|
|
|
this._runStart()
|
|
|
|
} else {
|
|
|
|
this.show = true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
set (amount) {
|
|
|
|
this.isPaused = false
|
|
|
|
|
|
|
|
let o
|
|
|
|
if (this.isStarted) {
|
|
|
|
o = amount < this.progress
|
|
|
|
? clamp(amount, 0, 100)
|
|
|
|
: clamp(amount, this.minimum, 100)
|
|
|
|
} else {
|
|
|
|
o = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
this.status = (o === 100 ? null : o)
|
|
|
|
|
|
|
|
queue(next => {
|
|
|
|
this.progress = o
|
|
|
|
if (o === 100) {
|
|
|
|
setTimeout(() => {
|
|
|
|
this.opacity = 0
|
|
|
|
setTimeout(() => {
|
|
|
|
this.show = false
|
|
|
|
this.error = false
|
|
|
|
next()
|
|
|
|
}, this.speed)
|
|
|
|
}, this.speed)
|
|
|
|
} else {
|
|
|
|
setTimeout(next, this.speed)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
increase (amount) {
|
|
|
|
let o = this.progress
|
|
|
|
|
|
|
|
if (o < 100 && typeof amount !== 'number') {
|
|
|
|
if (o >= 0 && o < 25) {
|
|
|
|
amount = Math.random() * 3 + 3
|
|
|
|
} else if (o >= 25 && o < 50) {
|
|
|
|
amount = Math.random() * 3
|
|
|
|
} else if (o >= 50 && o < 85) {
|
|
|
|
amount = Math.random() * 2
|
|
|
|
} else if (o >= 85 && o < 99) {
|
|
|
|
amount = 0.5
|
|
|
|
} else {
|
|
|
|
amount = 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.set(clamp(o + amount, 0, this.maximum))
|
|
|
|
},
|
|
|
|
|
|
|
|
decrease (amount) {
|
|
|
|
if (this.progress === 0) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
this.increase(-amount)
|
|
|
|
},
|
|
|
|
|
|
|
|
done () {
|
|
|
|
this.set(100)
|
|
|
|
},
|
|
|
|
|
|
|
|
getProgress () {
|
|
|
|
return this.status ? this.progress : 0
|
|
|
|
},
|
|
|
|
|
|
|
|
pause () {
|
|
|
|
this.isPaused = true
|
|
|
|
},
|
|
|
|
|
|
|
|
fail () {
|
|
|
|
this.error = true
|
|
|
|
this.done()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|