File: src/elements/oreesh-video/oreesh-video.html
<script>
/**
Video element with KnowRe-sh controls
<oreesh-video
width="640"
height="480">
<source src="..." type="...">
<source src="..." type="...">
Your browser doesn't support HTML5 video tag. <!-- fallback message -->
</oreesh-video>
screenfull.js is required.
Note: one-way data flow is used like:
UI event - mutate <video> element - event from <video> element - update UI state
Public attributes are all documented.
The events of HTML5 video element is bubbled, so use them.
- IE spec: https://msdn.microsoft.com/en-us/library/Hh772498(v=vs.85).aspx
- Mozilla spec : https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events
For the details of public API, see the comments on component source code.
@class oreesh-video
**/
/**
Indicates whether video is not ready
@attribute isWating
@type Boolean
**/
/**
Indicates whether user played video
@attribute isPlaying
@type Boolean
**/
/**
Indicates whether video is in fullscreen mode now
@attribute isFullscreen
@type Boolean
**/
/**
Indicates the time video starts at (seconds)
If not set, video starts normally
@attribute startAt
@type Number
@default 0
**/
/**
Indicates whether the controls are hidden
@attribute autoHideControls
@type Boolean
@default false
**/
/**
Indicates the time for which auto hiding of controls is delayed
@attribute autoHideControls
@type Boolean
@default false
**/
/**
Reset the inner video using current media sources.
Must be called if media sources are changed.
@method load
**/
</script>
<!-- FIXME: replace this with custom icon -->
<link rel="import" href="../oreesh-loading-indicator/oreesh-loading-indicator.html">
<dom-module id="oreesh-video">
<template>
<style is="custom-style">
:host {
--font-color: white;
--button-control-height: 46px;
--control-size: 40px;
--border: 2px solid #fff;
--main-color: #39D579;
--main-color-1: #86ffc6;
--background-color-0: rgba(38, 50, 56, 0.9);
--background-color-1: rgba(0, 0, 0, .4);
--number-font-size: 14px;
--volume-control-width: 58px;
--loop-portion-bar-height: 0;
--border-width: 2px;
--no-user-select: {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
};
--transparent-area: {
background-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
};
display: inline-block;
font-family: NanumBarunGothic, sans-serif;
cursor: default;
}
* {
vertical-align: middle;
}
img {
@apply(--no-user-select);
}
#container {
@apply(--no-user-select);
position: relative;
color: var(--font-color);
font-family: Arial, Helvetica, sans-serif;
background-color: var(--background-color-0);
/*overflow: hidden;*/
}
#videocontainer {
position: relative;
line-height: 0;
}
#overlay {
@apply(--transparent-area);
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}
#loadingindicator {
@apply(--layout-horizontal);
@apply(--layout-center);
@apply(--layout-center-justified);
width: 100%;
height: 100%;
background-color: #fff;
opacity: 0.9;
}
#controls {
@apply(--layout-vertical);
}
#controls:before {
content: '';
display: block;
margin-top: -2px;
border-top: var(--border-width) solid rgba(255, 255, 255, 0.4);
border-bottom: var(--border-width) solid rgba(0, 0, 0, 0.6);
}
#bar-controls {
@apply(--layout-flex);
position: absolute;
bottom: calc(var(--button-control-height) - 8px);
left: 0; right: 0;
z-index: 1;
}
#button-controls {
@apply(--layout-horizontal);
@apply(--layout-justified);
height: var(--button-control-height);
line-height: var(--button-control-height);
text-align: center;
background-color: var(--background-color-0);
padding: 0 10px;
}
#button-controls-left {
@apply(--layout-horizontal);
}
#button-controls-right {
@apply(--layout-horizontal);
}
#loop-portion-bar {
position: absolute;
left: 0; right: 0; top: 22px;
display: none;
background-color: var(--background-color-0);
z-index: 1;
}
#loop-portion-bar.active {
display: block;
height: var(--loop-portion-bar-height);
}
#loop-portion {
position: absolute;
background-color: var(--main-color-1);
height: 100%;
}
.loop-portion-handle {
position: absolute;
display: block;
width: var(--control-size);
height: var(--control-size);
bottom: var(--loop-portion-bar-height);
/* hack for ionicon */
line-height: 54px;
font-size: 20px;
}
.loop-portion-handle.left {
left: calc(var(--control-size) / -2);
}
.loop-portion-handle.right {
right: calc(var(--control-size) / -2);
}
#loop-portion.left .loop-portion-handle.left {
color: var(--main-color);
z-index: 2;
}
#loop-portion.right .loop-portion-handle.right {
color: var(--main-color);
z-index: 2;
}
#loop-toggle {
font-size: 14px;
width: 80px;
}
#loop-toggle.active {
color: var(--main-color);
}
#progressbar {
@apply(--transparent-area);
height: 20px;
}
#progress {
position: absolute;
top: 8px;
left: 0;
bottom: 6px;
transition: top .2s;
background-color: var(--main-color);
}
#progressbar:hover #progress {
top: 4px;
}
#playtoggle > img {
display: none;
}
#playtoggle.play > .play {
display: inline;
}
#playtoggle.pause > .pause {
display: inline;
}
#playtoggle, #stop, #skipbackward, #skipforward {
width: var(--control-size);
}
#skipamount {
width: 46px;
background-color: var(--background-color-1);
}
#skipamount > input {
display: inline-block;
border: none;
color: var(--font-color);
background-color: transparent;
height: 100%;
width: 100%;
padding: 0;
text-align: center;
font-size: 16px;
}
#skipamount > input:focus {
outline: none;
}
#skipbackward, #skipamount {
border-right: none !important;
}
#remainingtime {
font-size: 16px;
color: var(--main-color);
margin-right: 10px;
}
#duration {
font-size: 16px;
margin-right: 16px;
}
#rate {
position: relative;
width: 60px;
font-size: 16px;
}
#rate > * {
display: inline-block;
}
#rate-up, #rate-down {
width: 24px;
}
.reactive-btn > .active {
display: none;
}
.reactive-btn:active > .active {
display: inline;
}
.reactive-btn:active > .default {
display: none;
}
#volume {
position: relative;
width: var(--volume-control-width);
margin-left: 10px;
}
#volume:hover > #volume-hover-area {
display: block;
}
#volumeicon > img {
display: none;
}
#volumeicon.on > .on {
display: inline;
}
#volumeicon.mute > .mute {
display: inline;
}
#volume-hover-area {
display: none;
position: absolute;
bottom: 0; left: 0; right: 0;
height: 100px;
padding-bottom: calc(var(--button-control-height) + 2 * var(--border-width));
z-index: 2;
}
#volumeslider {
position: relative;
width: 100%;
height: 100px;
background-color: var(--background-color-1);
}
#volumecursor {
position: absolute;
background-color: var(--main-color);
bottom: 0px; left: 0; right: 0;
}
#fullscreen {
width: 50px;
}
#fullscreen > img {
display: none;
}
#fullscreen.shrink > .shrink {
display: inline;
}
#fullscreen.expand > .expand {
display: inline;
}
#overlay,
#playtoggle,
#stop,
#skipbackward,
#skipforward,
#progressbar,
#rate-up,
#rate-down,
#fullscreen,
#volumecontrol,
#loop-toggle,
.loop-portion-handle,
#volume-hover-area {
cursor: pointer;
}
.hidden {
display: none !important;
}
#container.fullscreen {
position: fixed;
top: 0; right: 0; bottom: 0; left: 0;
background-color: black !important;
}
#container.fullscreen #videocontainer {
height: 100%;
}
#container.fullscreen #video {
height: 100%;
width: 100%;
}
#controls.auto-hide {
position: absolute;
bottom: 0;
left: 0; right: 0;
opacity: 0;
transition: bottom 0.2s, opacity 0.2s;
}
#container.mousemoved #controls.auto-hide,
#controls.auto-hide:hover {
opacity: 1 !important;
}
#blinker {
width: 100%;
height: 100%;
font-size: 80px;
@apply(--layout-horizontal);
@apply(--layout-center);
@apply(--layout-center-justified);
}
</style>
<div id="container"
class$="[[_computeContainerClass(isFullscreen, forceHiddenControlsToShow, _mousemoved)]]"
on-mousemove="_onMousemove"
on-selectstart="_nullHandler"
on-mouseleave="_onMouseleave"
>
<div id="videocontainer">
<video id="video"
width="[[width]]"
height="[[height]]"
on-ratechange="_onRatechange"
on-volumechange="_onVolumechange"
on-timeupdate="_onTimeupdate"
on-waiting="_onWaiting"
on-playing="_onPlaying"
on-seeking="_onSeeking"
on-seeked="_onSeeked"
on-ended="_onEnded"
on-play="_onPlay"
on-pause="_onPause"
>
<content></content>
</video>
<div id="overlay" on-tap="playToggle"> <!-- FIXME: not working in IE10 -->
<div id="loadingindicator"
class$="[[_computeLoadingIndicatorClass(isWaiting)]]"
>
<oreesh-loading-indicator></oreesh-loading-indicator>
</div>
</div>
</div>
<div id="controls" class$="[[_computeControlsClass(_reallyAutoHideControls)]]">
<div id="bar-controls">
<div
id="loop-portion-bar"
class$="[[_computeLoopPortionBarClass(_loopEnabled)]]"
on-mousemove="_onMousemoveLoopPortion"
on-track="_onTrackLoopPortion"
on-mouseleave="_onMouseleaveLoopPortion"
>
<div id="loop-portion" class$="[[_computeLoopPortionClass(_activatedLoopPortion)]]">
<img source="<%- svg.bt_repeat_area %>" class="loop-portion-handle left">
<img source="<%- svg.bt_repeat_area %>" class="loop-portion-handle right">
</div>
</div>
<div id="progressbar" on-down="_onTrackProgressBar" on-track="_onTrackProgressBar">
<div id="progress"></div>
</div>
</div>
<div id="button-controls">
<div id="button-controls-left">
<div id="playtoggle" on-tap="_onTapPlayToggle" class$="[[_computePlayButtonClass(isPlaying)]]">
<img source="<%- svg.bt_play %>" class="play">
<img source="<%- svg.bt_pause %>" class="pause">
</div>
<div id="stop" on-tap="_onTapStop">
<img source="<%- svg.bt_stop %>">
</div>
<div id="skipbackward" class="reactive-btn" on-tap="_onTapSkipbackward">
<img source="<%- svg.bt_rew_nor %>" class="default">
<img source="<%- svg.bt_rew_act %>" class="active">
</div>
<div id="skipamount">
<input on-input="_onInputSkipamount" value="[[_skipAmount]]">
</div>
<div id="skipforward" class="reactive-btn" on-tap="_onTapSkipforward">
<img source="<%- svg.bt_ff_nor %>" class="default">
<img source="<%- svg.bt_ff_act %>" class="active">
</div>
<div
id="loop-toggle"
class$="[[_computeLoopToggleClass(_loopEnabled)]]"
on-tap="_onTapLoopToggle"
>
구간반복
</div>
</div>
<div id="button-controls-right">
<div id="remainingtime">[[_computeRemainingTimeText(_currentTime)]]</div>
<div id="duration">[[_computeRemainingTimeText(_duration)]]</div>
<div id="rate-down" class="reactive-btn" on-tap="_onTapRateDown">
<img source="<%- svg.bt_minus_nor%>" class="default">
<img source="<%- svg.bt_minus_act%>" class="active">
</div>
<div id="rate">
[[_computePlaybackRateText(_playbackRate)]]배속
</div>
<div id="rate-up" class="reactive-btn" on-tap="_onTapRateUp">
<img source="<%- svg.bt_plus_nor %>" class="default">
<img source="<%- svg.bt_plus_act %>" class="active">
</div>
<div id="volume">
<div id="volumeicon" class$="[[_computeVolumeIconClass(_volume)]]">
<img source="<%- svg.bt_volume_on %>" class="on">
<img source="<%- svg.bt_volume_mute %>" class="mute">
</div>
<div id="volume-hover-area">
<div id="volumeslider"
on-tap="_onTrackVolume"
on-track="_onTrackVolume"
>
<div id="volumecursor"></div>
</div>
</div>
</div>
<div id="fullscreen" on-tap="_onTapFullscreenToggle" class$="[[_computeFullscreenToggleClass(isFullscreen)]]">
<img source="<%- svg.bt_ex_screen %>" class="expand">
<img source="<%- svg.bt_sm_screen %>" class="shrink">
</div>
</div>
</div>
</div>
</div>
</template>
<script src="./oreesh-video.js"></script>
</dom-module>