Switch to Slider instead of ProgressBar
This commit is contained in:
parent
5f58af7624
commit
e2a6b5ee81
5 changed files with 223 additions and 34 deletions
|
|
@ -49,6 +49,7 @@
|
||||||
"@babel/polyfill": "^7.0.0",
|
"@babel/polyfill": "^7.0.0",
|
||||||
"bootstrap": "3.3.7",
|
"bootstrap": "3.3.7",
|
||||||
"bootstrap-datetime-picker": "2.4.4",
|
"bootstrap-datetime-picker": "2.4.4",
|
||||||
|
"bootstrap-slider": "^10.2.1",
|
||||||
"comment-json": "^1.1.3",
|
"comment-json": "^1.1.3",
|
||||||
"fs.extra": "^1.3.2",
|
"fs.extra": "^1.3.2",
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ let Term = require("term.js-cockpit");
|
||||||
let Journal = require("journal");
|
let Journal = require("journal");
|
||||||
let $ = require("jquery");
|
let $ = require("jquery");
|
||||||
require("console.css");
|
require("console.css");
|
||||||
|
require("bootstrap-slider");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get an object field, verifying its presence and type.
|
* Get an object field, verifying its presence and type.
|
||||||
|
|
@ -460,32 +461,57 @@ let PacketBuffer = class {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let ProgressBar = class extends React.Component {
|
class Slider extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.jumpTo = this.jumpTo.bind(this);
|
this.slideStart = this.slideStart.bind(this);
|
||||||
|
this.slideStop = this.slideStop.bind(this);
|
||||||
|
this.slider = null;
|
||||||
|
this.state = {
|
||||||
|
paused: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
jumpTo(e) {
|
slideStart(e) {
|
||||||
|
this.setState({paused: this.props.paused});
|
||||||
|
this.props.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
slideStop(e) {
|
||||||
if (this.props.fastForwardFunc) {
|
if (this.props.fastForwardFunc) {
|
||||||
let percent = parseInt((e.nativeEvent.offsetX * 100) / e.currentTarget.clientWidth);
|
this.props.fastForwardFunc(e);
|
||||||
let ts = parseInt((this.props.length * percent) / 100);
|
if (this.state.paused === false) {
|
||||||
this.props.fastForwardFunc(ts);
|
this.props.play();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
componentDidMount() {
|
||||||
let progress = {
|
this.slider = $("#slider").slider({
|
||||||
"width": parseInt((this.props.mark * 100) / this.props.length) + "%"
|
value: 0,
|
||||||
};
|
tooltip: "hide",
|
||||||
|
enabled: false,
|
||||||
|
});
|
||||||
|
this.slider.slider('on', 'slideStart', this.slideStart);
|
||||||
|
this.slider.slider('on', 'slideStop', this.slideStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
if (this.props.length) {
|
||||||
|
this.slider.slider('enable');
|
||||||
|
this.slider.slider('setAttribute', 'max', this.props.length);
|
||||||
|
}
|
||||||
|
if (this.props.mark) {
|
||||||
|
this.slider.slider('setValue', this.props.mark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
return (
|
return (
|
||||||
<div id="progress_bar" className="progress" onClick={this.jumpTo}>
|
<input id="slider" type="text" />
|
||||||
<div className="progress-bar" role="progressbar" style={progress} />
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
class InputPlayer extends React.Component {
|
class InputPlayer extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -506,6 +532,8 @@ export class Player extends React.Component {
|
||||||
this.handleTitleChange = this.handleTitleChange.bind(this);
|
this.handleTitleChange = this.handleTitleChange.bind(this);
|
||||||
this.rewindToStart = this.rewindToStart.bind(this);
|
this.rewindToStart = this.rewindToStart.bind(this);
|
||||||
this.playPauseToggle = this.playPauseToggle.bind(this);
|
this.playPauseToggle = this.playPauseToggle.bind(this);
|
||||||
|
this.play = this.play.bind(this);
|
||||||
|
this.pause = this.pause.bind(this);
|
||||||
this.speedUp = this.speedUp.bind(this);
|
this.speedUp = this.speedUp.bind(this);
|
||||||
this.speedDown = this.speedDown.bind(this);
|
this.speedDown = this.speedDown.bind(this);
|
||||||
this.speedReset = this.speedReset.bind(this);
|
this.speedReset = this.speedReset.bind(this);
|
||||||
|
|
@ -769,6 +797,14 @@ export class Player extends React.Component {
|
||||||
this.setState({paused: !this.state.paused});
|
this.setState({paused: !this.state.paused});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
play() {
|
||||||
|
this.setState({paused: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
pause() {
|
||||||
|
this.setState({paused: true});
|
||||||
|
}
|
||||||
|
|
||||||
speedUp() {
|
speedUp() {
|
||||||
let speedExp = this.state.speedExp;
|
let speedExp = this.state.speedExp;
|
||||||
if (speedExp < 4) {
|
if (speedExp < 4) {
|
||||||
|
|
@ -1010,17 +1046,6 @@ export class Player extends React.Component {
|
||||||
"float": "right",
|
"float": "right",
|
||||||
};
|
};
|
||||||
|
|
||||||
const progressbar_style = {
|
|
||||||
'marginTop': '10px',
|
|
||||||
};
|
|
||||||
|
|
||||||
const currentTsPost = function(currentTS, bufLength) {
|
|
||||||
if (currentTS > bufLength) {
|
|
||||||
return bufLength;
|
|
||||||
}
|
|
||||||
return currentTS;
|
|
||||||
};
|
|
||||||
|
|
||||||
let error = "";
|
let error = "";
|
||||||
if (this.state.error) {
|
if (this.state.error) {
|
||||||
error = (
|
error = (
|
||||||
|
|
@ -1047,6 +1072,7 @@ export class Player extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-footer">
|
<div className="panel-footer">
|
||||||
|
<Slider length={this.buf.pos} mark={this.state.currentTsPost} fastForwardFunc={this.fastForwardToTS} play={this.play} pause={this.pause} paused={this.state.paused} />
|
||||||
<button title="Play/Pause - Hotkey: p" type="button" ref="playbtn"
|
<button title="Play/Pause - Hotkey: p" type="button" ref="playbtn"
|
||||||
className="btn btn-default btn-lg margin-right-btn play-btn"
|
className="btn btn-default btn-lg margin-right-btn play-btn"
|
||||||
onClick={this.playPauseToggle}>
|
onClick={this.playPauseToggle}>
|
||||||
|
|
@ -1095,11 +1121,6 @@ export class Player extends React.Component {
|
||||||
onClick={this.zoomOut} disabled={this.state.term_zoom_min}>
|
onClick={this.zoomOut} disabled={this.state.term_zoom_min}>
|
||||||
<i className="fa fa-search-minus" aria-hidden="true" /></button>
|
<i className="fa fa-search-minus" aria-hidden="true" /></button>
|
||||||
</span>
|
</span>
|
||||||
<div style={progressbar_style}>
|
|
||||||
<ProgressBar length={this.buf.pos}
|
|
||||||
mark={currentTsPost(this.state.currentTsPost, this.buf.pos)}
|
|
||||||
fastForwardFunc={this.fastForwardToTS} />
|
|
||||||
</div>
|
|
||||||
<div id="input-player-wrap">
|
<div id="input-player-wrap">
|
||||||
<InputPlayer input={this.state.input} />
|
<InputPlayer input={this.state.input} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -394,6 +394,10 @@ table.listing-ct > thead th:last-child, tr.listing-ct-item td:last-child {
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#progress_bar {
|
#input-player-wrap {
|
||||||
margin-bottom: 10px;
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-footer {
|
||||||
|
padding: 5px 15px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -424,7 +424,8 @@ class Recording extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-3">
|
{player}
|
||||||
|
<div className="col-md-6">
|
||||||
<div className="panel panel-default">
|
<div className="panel panel-default">
|
||||||
<div className="panel-heading">
|
<div className="panel-heading">
|
||||||
<span>{_("Recording")}</span>
|
<span>{_("Recording")}</span>
|
||||||
|
|
@ -473,7 +474,6 @@ class Recording extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{player}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
163
src/slider.html
Normal file
163
src/slider.html
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
<script src="components/bootstrap-slider/dist/bootstrap-slider.js"></script>
|
||||||
|
<input id="slider-one" type="text"
|
||||||
|
data-provide="slider"
|
||||||
|
data-slider-min="0"
|
||||||
|
data-slider-max="100"
|
||||||
|
data-slider-tooltip="show" />
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<input id="slider-two" type="text"
|
||||||
|
data-provide="slider"
|
||||||
|
data-slider-ticks="[1, 2, 3, 4, 5]"
|
||||||
|
data-slider-ticks-labels='["1", "2", "3", "4", "5"]'
|
||||||
|
data-slider-min="1"
|
||||||
|
data-slider-max="5"
|
||||||
|
data-slider-step="1"
|
||||||
|
data-slider-value="3"
|
||||||
|
data-slider-tooltip="show" />
|
||||||
|
|
||||||
|
<h2>Example of a slider in a form</h2>
|
||||||
|
<form class="form-horizontal" role="form">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="size" class="col-sm-2 control-label">Size</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input id="slider" type="text"
|
||||||
|
data-provide="slider"
|
||||||
|
data-slider-ticks="[1, 2, 3, 4, 5]"
|
||||||
|
data-slider-ticks-labels='["1", "2", "3", "4", "5"]'
|
||||||
|
data-slider-min="1"
|
||||||
|
data-slider-max="5"
|
||||||
|
data-slider-step="1"
|
||||||
|
data-slider-value="3"
|
||||||
|
data-slider-tooltip="show" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name" class="col-sm-2 control-label">Name</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" class="form-control" id="name">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="size" class="col-sm-2 control-label">Size</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<div class="slider-pf">
|
||||||
|
<b>0</b>
|
||||||
|
<input id="size" type="text"
|
||||||
|
data-provide="slider"
|
||||||
|
data-slider-min="0"
|
||||||
|
data-slider-max="100"
|
||||||
|
data-slider-tooltip="show" />
|
||||||
|
<b>100</b>
|
||||||
|
<input type="text" size="3" class="slider-input-pf">
|
||||||
|
<span>GB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button type="submit" class="btn btn-default">Sign in</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="slider-pf">
|
||||||
|
<b>0</b>
|
||||||
|
<input id="slider-pf" type="text"
|
||||||
|
data-provide="slider"
|
||||||
|
data-slider-min="0"
|
||||||
|
data-slider-max="100"
|
||||||
|
data-slider-tooltip="show" />
|
||||||
|
<b>100</b>
|
||||||
|
<input type="text" size="3" class="slider-input-pf">
|
||||||
|
<span>GB</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="slider-pf">
|
||||||
|
<b>0</b>
|
||||||
|
<input id="with-stops" type="text"
|
||||||
|
data-provide="slider"
|
||||||
|
data-slider-min="0"
|
||||||
|
data-slider-max="100"
|
||||||
|
data-slider-tooltip="show" />
|
||||||
|
<b>100</b>
|
||||||
|
<input type="text" size="3" class="slider-input-pf">
|
||||||
|
<span class="dropdown">
|
||||||
|
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||||
|
GB
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||||
|
<li><a href="#">GB</a></li>
|
||||||
|
<li><a href="#">MB</a></li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
$('.slider-input-pf').tooltip({ trigger: 'manual' })
|
||||||
|
.on('keyup', function (e) {
|
||||||
|
var $this = $(this);
|
||||||
|
var sd = $this.siblings('[data-provide=slider]').slider();
|
||||||
|
if ($this.val().trim() !== '' && !$.isNumeric(this.value)) {
|
||||||
|
this.value = sd.slider('getValue');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('keypress blur', function (e) {
|
||||||
|
if (e.which == 13 || e.type === 'blur') {
|
||||||
|
e.preventDefault();
|
||||||
|
var $this = $(this);
|
||||||
|
var sd = $this.siblings('[data-provide=slider]').slider();
|
||||||
|
var max = sd.slider('getAttribute', 'max');
|
||||||
|
var min = sd.slider('getAttribute', 'min');
|
||||||
|
if (!$.isNumeric(this.value) || (this.value > max || this.value < min)) {
|
||||||
|
var warningInfo = $.isNumeric(this.value) ? 'Valid value should be between ' + min
|
||||||
|
+ ' and ' + max : 'Valid value should be number';
|
||||||
|
$this.attr('data-original-title', warningInfo).tooltip('show').addClass('warning');
|
||||||
|
this.value = sd.slider('getValue');
|
||||||
|
setTimeout(function(){ $this.tooltip('hide'); }, 3000);
|
||||||
|
} else {
|
||||||
|
if ($this.is('.warning')) {
|
||||||
|
$this.tooltip('hide');
|
||||||
|
}
|
||||||
|
this.value = $this.val().trim();
|
||||||
|
sd.slider('setValue', this.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.siblings('[data-provide=slider]').each(function () {
|
||||||
|
$(this).siblings('.slider-input-pf').val(this.value);
|
||||||
|
$(this).slider().on('slide', function (e) {
|
||||||
|
$(e.target).siblings('.slider-input-pf').val(e.value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.slider = new Slider("input.slider", {
|
||||||
|
value: 0,
|
||||||
|
min: 0,
|
||||||
|
max: 100
|
||||||
|
});
|
||||||
|
console.log(this.slider);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
console.log('slider updated');
|
||||||
|
console.log(this.slider);
|
||||||
|
// this.slider.setAttribute('max', this.props.length);
|
||||||
|
// this.slider.setValue(this.props.mark);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue