Init rewrite with bundler

This commit is contained in:
Korbs 2024-02-26 05:21:51 -05:00
parent 782cee4cec
commit 7230dbb084
No known key found for this signature in database
37 changed files with 1974 additions and 4 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
node_modules

View file

@ -1,8 +1,81 @@
# Rewrite
Zorn is still in early stages, yet a rewrite is already happening? This is SudoVanilla's first attempt at a JS library, so I want to get it right and with good practice.
# Zorn
Hopefull this rewrite will go better than what I've been doing, although it was quite functional the codebase was just a mess and I think I can do better.
![Preview of Zorn with default theme set](https://img.sudovanilla.com/dhHcB5l.png)
> Currently in beta stages.
## What is Zorn?
A custom HTMl5 video player for the web using vanilla JavaScript.
## Installation
### Package Manager
With NPM:
```bash
npm install @sudovanilla/bun
```
With Yarn:
```bash
yarn add @sudovanilla/bun
```
With Bun:
```bash
bun add @sudovanilla/bun
```
With PNPM:
```bash
pnpm install @sudovanilla/bun
```
### Yarn PnP
If you are using Yarn it's PnP feature enabled, please unplug Zorn Player, add the following to your package.json file:
```json
"dependenciesMeta": {
"@sudovanilla/zorn": {
"unplugged": true
}
}
```
Also make sure you are setting the correct path to the script and css file when adding them to your website or app.
## Usage
### HTML5
Add Zorn at the bottom of your HTML page:
```html
...
</body>
<script src="/zorn.js"></script>
</html>
```
Then, add a video to the page inside a div with the class name set to `video-container`. Inside this div, will be the video element with the class name set as `zorn-player`.
```html
<div class="video-container">
<video class="zorn-player" src="video.mp4"></video>
</div>
```
___
You check current version by viewing the original [`zorn/dev`](https://sudovanilla.com/code/Korbs/Zorn/src/branch/dev) branch.
### Express
Route the files required for Zorn Player to work in Express (Tested with PokeTube):
```
const ZornDirectory = "./node_modules/@sudovanilla/zorn/"
module.exports = function (app, config, renderTemplate) {
app.get("/player/zorn.js", function (req, res) {res.sendFile("/dist/index.js", { root: ZornDirectory })})
}
```
Add the stylesheet and script:
```html
<script src="/player/index.js"></script>
```
Then, add a video to the page inside a div with the class name set to `video-container`. Inside this div, will be the video element with the class name set as `zorn-player`.
```html
<div class="video-container">
<video class="zorn-player" src="video.mp4"></video>
</div>
```

BIN
bun.lockb Executable file

Binary file not shown.

46
dist/zorn.js vendored Normal file
View file

@ -0,0 +1,46 @@
(() => {
// src/assets/icons/play-solid.svg
var play_solid_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" stroke-width="1.5"><path d="M6.90588 4.53682C6.50592 4.2998 6 4.58808 6 5.05299V18.947C6 19.4119 6.50592 19.7002 6.90588 19.4632L18.629 12.5162C19.0211 12.2838 19.0211 11.7162 18.629 11.4838L6.90588 4.53682Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
// src/get.js
var ZornVideoPlayer = document.querySelector(".zorn-player");
var VideoContainer = document.querySelector(".video-container");
var PlayIcon = play_solid_default;
// src/themes/default.js
var Controls = `
<h2 class="zorn-title hide"></h2>
<div oncontextmenu="return false" class="zorn-player-controls">
<div class="row-1">
<div class="row-1-start">
<button id="play-pause">${PlayIcon}</button>
<button id="skip-back"><i class="fa-solid fa-arrow-rotate-left"></i></button>
<button id="skip-forth"><i class="fa-solid fa-arrow-rotate-right"></i></button>
<div class="volume-controls">
<button data-title="Mute (m)" class="volume-button" id="volume-button"><i class="fa-solid fa-volume-high"></i></button>
<input class="volume" id="volume" value="1" type="range" max="1" min="0" step="0.01">
</div>
</div>
<div class="row-1-center">
<div class="video-progress">
<progress id="progress-bar" value="0" min="0"></progress>
<input class="seek" id="seek" value="0" min="0" type="range" step="1">
<div class="seek-tooltip" id="seek-tooltip">00:00</div>
</div>
</div>
<div class="row-1-end">
<div class="time">
<time id="time-elapsed">00:00</time>
<span> / </span>
<time id="duration">00:00</time>
</div>
<button id="subtitles"><i class="fa-solid fa-subtitles"></i></button>
<button id="fullscreen"><i class="fa-solid fa-expand"></i></button>
</div>
</div>
</div>
`;
// src/index.js
ZornVideoPlayer.insertAdjacentHTML("afterend", Controls);
})();

9
esbuild.config.mjs Normal file
View file

@ -0,0 +1,9 @@
import esbuild from 'esbuild'
import svg from 'esbuild-plugin-svg'
const context = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
outfile: 'dist/zorn.js',
plugins: [svg()]
})

12
esbuild.watch.config.mjs Normal file
View file

@ -0,0 +1,12 @@
import esbuild from 'esbuild'
import svg from 'esbuild-plugin-svg'
const context = await esbuild.context({
entryPoints: ['src/index.js'],
bundle: true,
minify: true,
outfile: 'test/js/zorn.js',
plugins: [svg()]
})
await context.watch()

35
package.json Normal file
View file

@ -0,0 +1,35 @@
{
"name": "zorn",
"version": "2024.02.26",
"description": "HTML5 Web Player",
"main": "src/index.js",
"repository": "https://sudovanilla.com/code/Korbs/Zorn/",
"author": "SudoVanilla <korbs@sudovanilla.com>",
"license": "AGPL-3.0-or-later",
"bugs": {
"url": "https://sudovanilla.com/code/Korbs/Zorn/issues",
"email": "support@sudovanilla.com"
},
"funding": [
{
"type": "individual",
"url": "https://sudovanilla.com/donate/"
}
],
"files": [
"dist/zorn.js",
"README.md",
"LICENSE"
],
"scripts": {
"start": "concurrently \"http-server ./test/\" \"node esbuild.watch.config.mjs\"",
"build": "node esbuild.config.mjs"
},
"devDependencies": {
"concurrently": "^8.2.2",
"esbuild": "^0.20.1",
"esbuild-plugin-svg": "^0.1.0",
"http-server": "^14.1.1",
"sass": "^1.71.1"
}
}

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" stroke-width="1.5" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff"><path d="M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M9 9L9 16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>

After

Width:  |  Height:  |  Size: 869 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M1 15V9C1 5.68629 3.68629 3 7 3H17C20.3137 3 23 5.68629 23 9V15C23 18.3137 20.3137 21 17 21H7C3.68629 21 1 18.3137 1 15Z" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M10.5 10L10.3284 9.82843C9.79799 9.29799 9.07857 9 8.32843 9V9C6.76633 9 5.5 10.2663 5.5 11.8284V12.1716C5.5 13.7337 6.76633 15 8.32843 15V15C9.07857 15 9.79799 14.702 10.3284 14.1716L10.5 14" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M18.5 10L18.3284 9.82843C17.798 9.29799 17.0786 9 16.3284 9V9C14.7663 9 13.5 10.2663 13.5 11.8284V12.1716C13.5 13.7337 14.7663 15 16.3284 15V15C17.0786 15 17.798 14.702 18.3284 14.1716L18.5 14" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" stroke-width="1.5"><path d="M2.95592 5.70436C2.55976 5.41246 2 5.69531 2 6.1874V17.8126C2 18.3047 2.55976 18.5875 2.95592 18.2956L10.8445 12.483C11.1699 12.2432 11.1699 11.7568 10.8445 11.517L2.95592 5.70436Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M13.9559 5.70436C13.5598 5.41246 13 5.69531 13 6.1874V17.8126C13 18.3047 13.5598 18.5875 13.9559 18.2956L21.8445 12.483C22.1699 12.2432 22.1699 11.7568 21.8445 11.517L13.9559 5.70436Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>

After

Width:  |  Height:  |  Size: 773 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" stroke-width="1.5" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff"><path d="M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M9 9L9 16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>

After

Width:  |  Height:  |  Size: 871 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff"><path d="M7 4H4V7" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M17 4H20V7" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 20H4V17" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M17 20H20V17" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>

After

Width:  |  Height:  |  Size: 622 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" stroke-width="1.5" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M6 18.4V5.6C6 5.26863 6.26863 5 6.6 5H9.4C9.73137 5 10 5.26863 10 5.6V18.4C10 18.7314 9.73137 19 9.4 19H6.6C6.26863 19 6 18.7314 6 18.4Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-fill="" data-darkreader-inline-stroke="" style="--darkreader-inline-fill: #ffffff; --darkreader-inline-stroke: #ffffff;"></path><path d="M14 18.4V5.6C14 5.26863 14.2686 5 14.6 5H17.4C17.7314 5 18 5.26863 18 5.6V18.4C18 18.7314 17.7314 19 17.4 19H14.6C14.2686 19 14 18.7314 14 18.4Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-fill="" data-darkreader-inline-stroke="" style="--darkreader-inline-fill: #ffffff; --darkreader-inline-stroke: #ffffff;"></path></svg>

After

Width:  |  Height:  |  Size: 960 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" stroke-width="1.5"><path d="M6.90588 4.53682C6.50592 4.2998 6 4.58808 6 5.05299V18.947C6 19.4119 6.50592 19.7002 6.90588 19.4632L18.629 12.5162C19.0211 12.2838 19.0211 11.7162 18.629 11.4838L6.90588 4.53682Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>

After

Width:  |  Height:  |  Size: 473 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M21.1679 8C19.6247 4.46819 16.1006 2 11.9999 2C6.81459 2 2.55104 5.94668 2.04932 11" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M17 8H21.4C21.7314 8 22 7.73137 22 7.4V3" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M2.88146 16C4.42458 19.5318 7.94874 22 12.0494 22C17.2347 22 21.4983 18.0533 22 13" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M7.04932 16H2.64932C2.31795 16 2.04932 16.2686 2.04932 16.6V21" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" stroke-width="1.5"><path d="M21.0441 5.70436C21.4402 5.41246 22 5.69531 22 6.1874V17.8126C22 18.3047 21.4402 18.5875 21.0441 18.2956L13.1555 12.483C12.8301 12.2432 12.8301 11.7568 13.1555 11.517L21.0441 5.70436Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M10.0441 5.70436C10.4402 5.41246 11 5.69531 11 6.1874V17.8126C11 18.3047 10.4402 18.5875 10.0441 18.2956L2.15555 12.483C1.8301 12.2432 1.8301 11.7568 2.15555 11.517L10.0441 5.70436Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>

After

Width:  |  Height:  |  Size: 774 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M1 13.8571V10.1429C1 9.03829 1.89543 8.14286 3 8.14286H5.9C6.09569 8.14286 6.28708 8.08544 6.45046 7.97772L12.4495 4.02228C13.1144 3.5839 14 4.06075 14 4.85714V19.1429C14 19.9392 13.1144 20.4161 12.4495 19.9777L6.45046 16.0223C6.28708 15.9146 6.09569 15.8571 5.9 15.8571H3C1.89543 15.8571 1 14.9617 1 13.8571Z" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M17.5 7.5C17.5 7.5 19 9 19 11.5C19 14 17.5 15.5 17.5 15.5" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M20.5 4.5C20.5 4.5 23 7 23 11.5C23 16 20.5 18.5 20.5 18.5" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M3.5 13.8571V10.1429C3.5 9.03829 4.39543 8.14286 5.5 8.14286H8.4C8.59569 8.14286 8.78708 8.08544 8.95046 7.97772L14.9495 4.02228C15.6144 3.5839 16.5 4.06075 16.5 4.85714V19.1429C16.5 19.9392 15.6144 20.4161 14.9495 19.9777L8.95046 16.0223C8.78708 15.9146 8.59569 15.8571 8.4 15.8571H5.5C4.39543 15.8571 3.5 14.9617 3.5 13.8571Z" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M20.5 15L20.5 9" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>

After

Width:  |  Height:  |  Size: 883 B

View file

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M18 14L20.0005 12M22 10L20.0005 12M20.0005 12L18 10M20.0005 12L22 14" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M2 13.8571V10.1429C2 9.03829 2.89543 8.14286 4 8.14286H6.9C7.09569 8.14286 7.28708 8.08544 7.45046 7.97772L13.4495 4.02228C14.1144 3.5839 15 4.06075 15 4.85714V19.1429C15 19.9392 14.1144 20.4161 13.4495 19.9777L7.45046 16.0223C7.28708 15.9146 7.09569 15.8571 6.9 15.8571H4C2.89543 15.8571 2 14.9617 2 13.8571Z" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>

After

Width:  |  Height:  |  Size: 942 B

9
src/dialogs/Buffering.js Normal file
View file

@ -0,0 +1,9 @@
import {
RefreshIcon,
} from '../get'
export var BufferDialog = `
<div id="buffering" class="zorn-dialog">
${RefreshIcon}
</div>
`

24
src/events.js Normal file
View file

@ -0,0 +1,24 @@
import { ZornVideoPlayer } from "./get"
export function Events() {
ZornVideoPlayer.addEventListener('error', function(event) {
document.querySelector('#invalid-src').style.display = 'inherit'
document.querySelector('.zorn-player-controls').style.display = 'none'
videoContainer.style.backgroundColor = '#101010'
setTimeout(() => {
ZornVideoPlayer.style.opacity = '0.10'
document.querySelector('#buffering').style.display = 'none'
}, 0o250);
}, true)
ZornVideoPlayer.onwaiting = (event) => {
document.querySelector('#buffering').style.display = 'inherit'
ZornVideoPlayer.style.transition = '5s opacity'
ZornVideoPlayer.style.opacity = '0.25'
}
ZornVideoPlayer.oncanplaythrough = (event) => {
document.querySelector('#buffering').style.display = 'none'
ZornVideoPlayer.style.transition = '0.3s opacity'
ZornVideoPlayer.style.opacity = '1'
}
}

View file

@ -0,0 +1,25 @@
import { VideoContainer } from '../get'
export function Fullscreen() {
const Button_Fullscreen = document.getElementById('fullscreen')
function Toggle_Fullscreen() {
if (document.fullscreenElement) {document.exitFullscreen()}
else if (document.webkitFullscreenElement) {document.webkitExitFullscreen()}
else if (VideoContainer.webkitRequestFullscreen) {VideoContainer.webkitRequestFullscreen()}
else {VideoContainer.requestFullscreen()}
}
Button_Fullscreen.onclick = Toggle_Fullscreen
function Update_FullscreenButton() {
if (document.fullscreenElement) {
Button_Fullscreen.setAttribute('data-title', 'Exit full screen (f)')
Button_Fullscreen.innerHTML = `<i class="fa-solid fa-compress"></i>`
} else {
Button_Fullscreen.setAttribute('data-title', 'Full screen (f)')
Button_Fullscreen.innerHTML = `<i class="fa-solid fa-expand"></i>`
}
}
VideoContainer.addEventListener('fullscreenchange', Update_FullscreenButton)
}

View file

@ -0,0 +1,34 @@
import {
ZornVideoPlayer,
PlayIcon,
PauseIcon
} from '../get'
export function PlayPause() {
const Button_PlayPause = document.querySelector('.zorn-player-controls #play-pause')
Button_PlayPause.addEventListener('click', Toggle_PlayPause)
ZornVideoPlayer.addEventListener('click', Toggle_PlayPause)
ZornVideoPlayer.addEventListener('play', Update_PlayPauseButton)
ZornVideoPlayer.addEventListener('pause', Update_PlayPauseButton)
function Toggle_PlayPause() {
if (ZornVideoPlayer.paused || ZornVideoPlayer.ended) {
ZornVideoPlayer.play()
}
else {
ZornVideoPlayer.pause()
}
}
function Update_PlayPauseButton() {
if (ZornVideoPlayer.paused) {
Button_PlayPause.setAttribute('data-title', 'Play (K)')
Button_PlayPause.innerHTML = `${PlayIcon}`
} else {
Button_PlayPause.setAttribute('data-title', 'Pause (K)')
Button_PlayPause.innerHTML = `${PauseIcon}`
}
}
}

74
src/functions/Seek.js Normal file
View file

@ -0,0 +1,74 @@
import { ZornVideoPlayer } from '../get'
export function Seek() {
// Duration and Length of Video
const timeElapsed = document.getElementById('time-elapsed');
const duration = document.getElementById('duration');
function formatTime(timeInSeconds) {
const result = new Date(timeInSeconds * 1000).toISOString().substr(11, 8);
return {
minutes: result.substr(3, 2),
seconds: result.substr(6, 2),
};
};
function initializeVideo() {
const videoDuration = Math.round(ZornVideoPlayer.duration);
const time = formatTime(videoDuration);
duration.innerText = `${time.minutes}:${time.seconds}`;
duration.setAttribute('datetime', `${time.minutes}m ${time.seconds}s`);
}
ZornVideoPlayer.addEventListener('loadedmetadata', initializeVideo);
function updateTimeElapsed() {
const time = formatTime(Math.round(ZornVideoPlayer.currentTime));
timeElapsed.innerText = `${time.minutes}:${time.seconds}`;
timeElapsed.setAttribute('datetime', `${time.minutes}m ${time.seconds}s`);
}
ZornVideoPlayer.addEventListener('timeupdate', updateTimeElapsed);
// Progress Bar
const progressBar = document.getElementById('progress-bar');
const seek = document.getElementById('seek');
function initializeVideo() {
const videoDuration = Math.round(ZornVideoPlayer.duration);
seek.setAttribute('max', videoDuration);
progressBar.setAttribute('max', videoDuration);
const time = formatTime(videoDuration);
duration.innerText = `${time.minutes}:${time.seconds}`;
duration.setAttribute('datetime', `${time.minutes}m ${time.seconds}s`)
}
function updateProgress() {
seek.value = Math.floor(ZornVideoPlayer.currentTime);
progressBar.value = Math.floor(ZornVideoPlayer.currentTime);
}
ZornVideoPlayer.addEventListener('timeupdate', updateProgress);
const seekTooltip = document.getElementById('seek-tooltip');
function updateSeekTooltip(event) {
const skipTo = Math.round((event.offsetX / event.target.clientWidth) * parseInt(event.target.getAttribute('max'), 10));
seek.setAttribute('data-seek', skipTo)
const t = formatTime(skipTo);
seekTooltip.textContent = `${t.minutes}:${t.seconds}`;
const rect = ZornVideoPlayer.getBoundingClientRect();
seekTooltip.style.left = `${event.pageX - rect.left}px`;
}
seek.addEventListener('mousemove', updateSeekTooltip);
function skipAhead(event) {
const skipTo = event.target.dataset.seek ? event.target.dataset.seek : event.target.value;
ZornVideoPlayer.currentTime = skipTo;
progressBar.value = skipTo;
seek.value = skipTo;
}
seek.addEventListener('input', skipAhead);
initializeVideo()
}

View file

@ -0,0 +1,16 @@
import { ZornVideoPlayer } from '../get'
export function SkipAround() {
const Button_SkipBack = document.querySelector('.zorn-player-controls #skip-back')
const Button_SkipForth = document.querySelector('.zorn-player-controls #skip-forth')
Button_SkipBack.addEventListener('click', Toggle_SkipBack)
Button_SkipForth.addEventListener('click', Toggle_SkipForth)
function Toggle_SkipBack() {Skip(-10)}
function Toggle_SkipForth() {Skip(10)}
function Skip(value) {
ZornVideoPlayer.currentTime += value
}
}

View file

@ -0,0 +1,51 @@
import { VideoContainer, ZornVideoPlayer } from '../get'
export function Subtitles() {
var subtitles = document.querySelector('.zorn-player-controls #subtitles')
var subtitleMenuButtons = []
var createMenuItem = function(id, lang, label) {
var listItem = document.createElement('li')
var button = listItem.appendChild(document.createElement('button'))
button.setAttribute('id', id)
button.className = 'subtitles-button'
if (lang.length > 0) button.setAttribute('lang', lang)
button.value = label
button.setAttribute('data-state', 'inactive')
button.appendChild(document.createTextNode(label))
button.addEventListener('click', function(e) {
subtitleMenuButtons.map(function(v, i, a) {
subtitleMenuButtons[i].setAttribute('data-state', 'inactive')
})
var lang = this.getAttribute('lang')
for (var i = 0; i < ZornVideoPlayer.textTracks.length; i++) {
if (ZornVideoPlayer.textTracks[i].language == lang) {
ZornVideoPlayer.textTracks[i].mode = 'showing'
this.setAttribute('data-state', 'active')
}
else {
ZornVideoPlayer.textTracks[i].mode = 'hidden'
}
}
subtitlesMenu.style.display = 'none'
})
subtitleMenuButtons.push(button)
return listItem
}
var subtitlesMenu
if (ZornVideoPlayer.textTracks) {
var df = document.createDocumentFragment()
var subtitlesMenu = df.appendChild(document.createElement('ul'))
subtitlesMenu.className = 'subtitles-menu'
subtitlesMenu.appendChild(createMenuItem('subtitles-off', '', 'Off'))
for (var i = 0; i < ZornVideoPlayer.textTracks.length; i++) {
subtitlesMenu.appendChild(createMenuItem('subtitles-' + ZornVideoPlayer.textTracks[i].language, ZornVideoPlayer.textTracks[i].language, ZornVideoPlayer.textTracks[i].label))
}
VideoContainer.appendChild(subtitlesMenu)
}
subtitles.addEventListener('click', function(e) {
if (subtitlesMenu) {
subtitlesMenu.style.display = (subtitlesMenu.style.display == 'block' ? 'none' : 'block')
}
})
}

46
src/functions/Volume.js Normal file
View file

@ -0,0 +1,46 @@
import {
ZornVideoPlayer,
VolumeOffIcon,
VolumeMinIcon,
VolumeHighIcon
} from '../get'
export function Volume() {
const Button_Volume = document.getElementById('volume-button')
const volume = document.getElementById('volume')
function Update_Volme() {
if (ZornVideoPlayer.muted) {
ZornVideoPlayer.muted = false
}
ZornVideoPlayer.volume = volume.value
}
volume.addEventListener('input', Update_Volme)
function Update_Volume_Icon() {
Button_Volume.setAttribute('data-title', 'Mute (M)')
if (ZornVideoPlayer.muted || ZornVideoPlayer.volume === 0) {
Button_Volume.innerHTML = `${VolumeOffIcon}`
Button_Volume.setAttribute('data-title', 'Unmute (M)')
} else if (ZornVideoPlayer.volume > 0 && ZornVideoPlayer.volume <= 0.5) {
Button_Volume.innerHTML = `${VolumeMinIcon}`
} else {
Button_Volume.innerHTML = `${VolumeHighIcon}`
}
}
ZornVideoPlayer.addEventListener('volumechange', Update_Volume_Icon)
function Toggle_Mute() {
ZornVideoPlayer.muted = !ZornVideoPlayer.muted
if (ZornVideoPlayer.muted) {
volume.setAttribute('data-volume', volume.value)
volume.value = 0
} else {
volume.value = volume.dataset.volume
}
}
Button_Volume.addEventListener('click', Toggle_Mute)
}

28
src/get.js Normal file
View file

@ -0,0 +1,28 @@
// Set Variables for required video container and video player
export var ZornVideoPlayer = document.querySelector('.zorn-player')
export var VideoContainer = document.querySelector('.video-container')
// Icons - Iconoir.com
/// Get Icons
import PlaySVG from './assets/icons/play-solid.svg'
import PauseSVG from './assets/icons/pause-solid.svg'
import FullcreenSVG from './assets/icons/maximize.svg'
import CaptionsSVG from './assets/icons/closed-captions-tag.svg'
import Backward15SVG from './assets/icons/backward15-seconds.svg'
import Forward15SVG from './assets/icons/forward15-seconds.svg'
import VolumeHighSVG from './assets/icons/sound-high.svg'
import VolumeMinSVG from './assets/icons/sound-min.svg'
import VolumeOffSVG from './assets/icons/sound-off.svg'
import RefreshSVG from './assets/icons/refresh-double.svg'
/// Set Icons
export var PlayIcon = PlaySVG
export var PauseIcon = PauseSVG
export var FullcreenIcon = FullcreenSVG
export var CaptionsIcon = CaptionsSVG
export var Backward15Icon = Backward15SVG
export var Forward15Icon = Forward15SVG
export var VolumeHighIcon = VolumeHighSVG
export var VolumeMinIcon = VolumeMinSVG
export var VolumeOffIcon = VolumeOffSVG
export var RefreshIcon = RefreshSVG

26
src/index.js Normal file
View file

@ -0,0 +1,26 @@
import { ZornVideoPlayer } from "./get"
import { Controls } from "./themes/default"
// Import Functions
import { Events } from './events'
import { PlayPause } from "./functions/PlayPause"
import { SkipAround } from "./functions/SkipAround"
import { Fullscreen } from "./functions/Fullscreen"
import { Subtitles } from "./functions/Subtitles"
import { Volume } from "./functions/Volume"
import { Seek } from "./functions/Seek"
import { BufferDialog } from "./dialogs/Buffering"
// Apply Controls
ZornVideoPlayer.insertAdjacentHTML("afterend", Controls)
ZornVideoPlayer.insertAdjacentHTML("afterend", BufferDialog)
// Init Functions
Events()
PlayPause()
SkipAround()
Fullscreen()
Subtitles()
Volume()
Seek()
Buffering()

365
src/themes/default.js Normal file
View file

@ -0,0 +1,365 @@
import {
PlayIcon,
PauseIcon,
FullcreenIcon,
CaptionsIcon,
Backward15Icon,
Forward15Icon,
VolumeHighIcon
} from '../get'
export var Controls = `
<h2 class="zorn-title hide"></h2>
<div oncontextmenu="return false" class="zorn-player-controls">
<div class="row-2">
<div class="video-progress">
<progress id="progress-bar" value="0" min="0"></progress>
<input class="seek" id="seek" value="0" min="0" type="range" step="1">
<div class="seek-tooltip" id="seek-tooltip">00:00</div>
</div>
</div>
<div class="row-1">
<div class="row-1-start">
<div class="volume-controls">
<button data-title="Mute (m)" class="volume-button" id="volume-button">${VolumeHighIcon}</button>
<input class="volume" id="volume" value="1" type="range" max="1" min="0" step="0.01"/>
</div>
<div class="time">
<time id="time-elapsed">00:00</time>
<span> / </span>
<time id="duration">00:00</time>
</div>
</div>
<div class="row-1-center">
<button id="skip-back">${Backward15Icon}</button>
<button id="play-pause">${PlayIcon}</button>
<button id="skip-forth">${Forward15Icon}</button>
</div>
<div class="row-1-end">
<button id="subtitles">${CaptionsIcon}</button>
<button id="fullscreen">${FullcreenIcon}</button>
</div>
</div>
</div>
<style>
:root {
--zorn-progress-bar-bg: rgba(100, 100, 100, 0.5);
--zorn-progress-bar: rgba(255, 0, 0, 0.5);
--zorn-thumb: red;
--zorn-rounded-corners: 4px;
}
.zorn-context-menu {
background: linear-gradient(45deg, #0a141c 0%, rgba(10, 20, 28, 1) 100%);
border-radius: 6px;
border: 1px rgba(255, 255, 255, 0.08) solid;
}
.zorn-context-menu ul {
list-style: none;
margin: 0px;
padding: 0px;
}
.zorn-context-menu ul li {
padding: 8px 32px 8px 16px;
margin: 4px;
border-radius: 4px;
font-family: arial;
}
.zorn-context-menu ul li:hover {
background: rgba(255, 255, 255, 0.1);
cursor: pointer;
}
.zorn-context-menu ul li i {
font-size: 14px;
margin-right: 12px;
width: 12px;
}
.video-container {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
font-family: Arial, Helvetica, sans-serif;
color: white;
}
.video-container .zorn-player-dialogs #buffering {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 0px 24px;
border-radius: 6px;
}
.video-container .zorn-player-dialogs #buffering h2 {
font-size: 52px;
}
.video-container .zorn-player-dialogs #invalid-src {
display: none;
position: absolute;
top: 50%;
left: 24px;
transform: translate(0px, -50%);
padding: 0px 24px;
border-radius: 6px;
}
.video-container .zorn-player-dialogs #invalid-src h2 {
font-size: 52px;
}
.video-container .zorn-player {
display: inline-flex;
}
.video-container .zorn-title {
display: none;
position: absolute;
top: 0px;
background: #000;
width: auto;
margin: 12px;
padding: 12px 24px;
border-radius: 10px;
font-size: 18px;
}
.video-container .hide {
opacity: 0;
pointer-events: none;
}
.video-container .zorn-player-title {
position: absolute;
top: 0px;
width: 100%;
background-image: linear-gradient(to top, rgba(12, 12, 12, 0), rgba(12, 12, 12, 0.75));
padding: 12px 24px;
font-size: 18px;
font-weight: bold;
}
.video-container .subtitles-menu {
display: none;
position: absolute;
right: 60px;
bottom: 50px;
background: #000 9;
list-style: none;
padding: 6px;
border-radius: 6px;
}
.video-container .subtitles-menu button {
background-color: transparent;
color: white;
border: none;
border-radius: 4px;
width: 100%;
text-align: left;
padding: 6px 12px;
cursor: pointer;
}
.video-container .subtitles-menu button:hover {
background: #fff 29;
}
.video-container .subtitles-menu .hide {
opacity: 0;
pointer-events: none;
}
.video-container .zorn-player-controls {
display: inline-flex;
right: 0;
left: 0;
padding: 10px;
position: absolute;
bottom: -1px;
transition: all 0.2s ease;
background-image: linear-gradient(to bottom, rgba(12, 12, 12, 0), rgba(12, 12, 12, 0.75));
flex-direction: inherit;
}
.video-container .zorn-player-controls .row-1 {
display: flex;
justify-content: space-between;
width: 100%;
}
.video-container .zorn-player-controls .row-1-start {
display: flex;
align-items: center;
}
.video-container .zorn-player-controls .row-1-center {
display: flex;
justify-content: center;
}
.video-container .zorn-player-controls .row-1-end {
display: flex;
align-items: center;
}
.video-container .zorn-player-controls button {
aspect-ratio: 1;
height: 32px;
width: 32px;
color: white;
background-color: transparent;
border: none;
margin: 0px 6px;
}
.video-container .zorn-player-controls button:hover {
background: rgba(44, 44, 44, 0.6);
border-radius: 6px;
}
.video-container .zorn-player-controls .volume-controls:hover > #volume {
opacity: 1;
transition: 0.3s opacity, 0.3s width;
margin: 0px;
width: 72px;
}
.video-container .zorn-player-controls #volume {
opacity: 0;
transition: 0.3s opacity, 0.3s width;
margin: 0px -6px;
width: 0px;
}
.video-container .zorn-player-controls #volume-button svg {
aspect-ratio: 1;
height: 16px;
width: 16px;
fill: white;
padding: 3px 0px 0px 0px;
}
.video-container .zorn-player-controls .video-progress {
position: relative;
height: 6.4px;
margin: 24px 0px;
width: 100%;
}
.video-container .zorn-player-controls progress {
border-radius: 1rem;
width: 100%;
height: 8.4px;
position: absolute;
top: 0;
}
.video-container .zorn-player-controls progress::-webkit-progress-bar {
border-radius: 1rem;
background: var(--zorn-progress-bar-bg);
}
.video-container .zorn-player-controls progress::-webkit-progress-value {
background: var(--zorn-progress-bar);
border-radius: 1rem;
}
.video-container .zorn-player-controls progress::-moz-progress-bar {
border-radius: 1rem;
background: var(--zorn-progress-bar-bg);
}
.video-container .zorn-player-controls .seek {
position: absolute;
top: 0;
width: 100%;
cursor: pointer;
margin: 0;
}
.video-container .zorn-player-controls .seek:hover + .seek-tooltip {
display: block;
}
.video-container .zorn-player-controls .seek-tooltip {
display: none;
position: relative;
top: -32px;
margin-left: -30px;
font-size: 12px;
content: attr(data-title);
font-weight: bold;
color: #fff;
background-color: rgba(0, 0, 0, .5);
border-radius: 4px;
padding: 6px;
width: fit-content;
}
.video-container .zorn-player-controls input[type=range] {
height: 8.4px;
background: transparent;
cursor: pointer;
opacity: 0;
}
.video-container .zorn-player-controls input[type=range]:focus {
outline: none;
}
.video-container .zorn-player-controls input[type=range]:focus::-webkit-slider-runnable-track {
background: transparent;
}
.video-container .zorn-player-controls input[type=range]:focus::-moz-range-track {
outline: none;
}
.video-container .zorn-player-controls input[type=range]::-webkit-slider-runnable-track {
width: 100%;
cursor: pointer;
border-radius: 1.3px;
-webkit-appearance: none;
transition: all 0.4s ease;
}
.video-container .zorn-player-controls input[type=range]::-webkit-slider-thumb {
height: 12px;
width: 12px;
border-radius: 10px;
background: var(--zorn-thumb);
cursor: pointer;
-webkit-appearance: none;
margin-left: -1px;
}
.video-container .zorn-player-controls input[type=range]::-moz-range-track {
width: 100%;
height: 8.4px;
cursor: pointer;
border: 1px solid transparent;
background: transparent;
border-radius: 0;
}
.video-container .zorn-player-controls input[type=range].volume {
height: 5px;
background-color: #fff;
}
.video-container .zorn-player-controls input[type=range].volume::-webkit-slider-runnable-track {
background-color: transparent;
}
.video-container .zorn-player-controls input[type=range].volume::-webkit-slider-thumb {
margin-left: 0;
height: 14px;
width: 14px;
background: #fff;
}
.video-container .zorn-player-controls input[type=range].volume::-moz-range-thumb {
border: 1px solid #fff;
background: #fff;
}
.video-container .zorn-player-controls input[type="range"]::-moz-range-thumb {
height: 12px;
width: 12px;
border-radius: 10px;
border: none;
background: var(--zorn-thumb);
cursor: pointer;
}
.video-container .zorn-player-controls .hide {
opacity: 0;
pointer-events: none;
}
.video-container .zorn-player-controls #progress-bar {
background: var(--zorn-progress-bar-bg);
border: none;
border-radius: 10px;
}
div#buffering {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 90%;
display: flex;
align-items: center;
justify-content: center;
animation: 1s spin linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg)
}
to {
transform: rotate(360deg)
}
}
</style>
`

4
test/css/index.css Normal file
View file

@ -0,0 +1,4 @@
body {
background-color: #111111;
color: white;
}

0
test/css/index.scss Normal file
View file

19
test/index.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Zorn</title>
<link rel="stylesheet" href="./css/index.css"/>
</head>
<body>
<div class="video-container">
<video class="zorn-player" layout="default" title="Ennie and Yoyki: Ungirly Games">
<!-- Quality changer support has not been worked on yet -->
<source label="720p" src="./media/Ennie-and-Yoyki-Ungirly-Games.mp4" type="video/mp4">
<!-- Subtitles -->
<track src="./media/subtitles/English.vtt" kind="subtitles" srclang="en" label="English">
<track src="./media/subtitles/Russian.vtt" kind="subtitles" srclang="ru" label="Russian">
</video>
</div>
</body>
<script src="./js/zorn.js"></script>
</html>

359
test/js/zorn.js Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -0,0 +1,350 @@
WEBVTT
00:00:00.650 --> 00:00:03.030
[music]
00:00:03.030 --> 00:00:05.220
[applause]
00:00:05.220 --> 00:00:13.880
[music] [
00:00:17.060 --> 00:00:20.750
music]
00:00:20.750 --> 00:00:21.930
bye [
00:00:21.930 --> 00:00:24.430
music]
00:00:24.430 --> 00:00:26.460
00:00:36.720 --> 00:00:40.380
why worry, Im on the mattress
00:00:40.380 --> 00:00:41.540
[music]
00:00:41.540 --> 00:00:43.040
[applause] [
00:00:43.040 --> 00:00:46.180
music]
00:00:47.340 --> 00:00:51.030
this doesnt happen here
00:00:56.340 --> 00:00:59.479
[music]
00:01:01.260 --> 00:01:04.479
now if she grabs you she wont
00:01:04.479 --> 00:01:08.130
catch up with me she ki shes old,
00:01:08.130 --> 00:01:11.220
look at
00:01:13.110 --> 00:01:15.720
you,
00:01:15.720 --> 00:01:18.370
Im buying you myself now
00:01:18.370 --> 00:01:21.579
[music]
00:01:30.750 --> 00:01:33.970
what kind of a mess do you have here, it looks like were on
00:01:33.970 --> 00:01:36.790
that full mom, okay, something came
00:01:36.790 --> 00:01:40.090
and all the water came through the door, youre like, and I almost
00:01:40.090 --> 00:01:43.420
drowned, okay, I need to get ready for
00:01:43.420 --> 00:01:45.939
grandma's arrival and when you've tidied up,
00:01:45.939 --> 00:01:48.430
play some quiet game
00:01:48.430 --> 00:01:51.460
okay mom, we'll clean everything up now and wo
00:01:51.460 --> 00:01:53.259
n't do this again by the way, have you seen
00:01:53.259 --> 00:01:55.730
grandma's soft slippers
00:01:55.730 --> 00:01:57.750
[music] haven't you seen it
00:01:57.750 --> 00:02:01.850
in years? I
00:02:01.850 --> 00:02:05.460
don't want to play a quieter game, how boring is it
00:02:05.460 --> 00:02:09.179
mom? she said it means we need
00:02:09.179 --> 00:02:12.000
to help and not upset her,
00:02:12.000 --> 00:02:14.970
I know one interesting calm game but
00:02:14.970 --> 00:02:18.570
what but but we will play it if only
00:02:18.570 --> 00:02:20.580
you swear not to tell anyone I
00:02:20.580 --> 00:02:23.700
swear why cant you
00:02:23.700 --> 00:02:25.320
tell anyone because
00:02:25.320 --> 00:02:28.410
boys dont play such games like this
00:02:28.410 --> 00:02:32.450
how is it considered that she is girly, what is it like
00:02:32.450 --> 00:02:36.720
for girls, what happens Igor
00:02:36.720 --> 00:02:39.360
especially for girls, this was
00:02:39.360 --> 00:02:42.209
lying around, I didnt notice before that in the
00:02:42.209 --> 00:02:44.630
girls plan, she will see the light
00:02:44.630 --> 00:02:55.130
[music]
00:02:55.130 --> 00:02:58.890
she ki, dont break the childrens bed, otherwise where
00:02:58.890 --> 00:03:01.380
will your brothers sleep and please
00:03:01.380 --> 00:03:05.930
sit down for dinner Weve been calling you for a long time, something
00:03:07.340 --> 00:03:09.860
useful,
00:03:09.860 --> 00:03:12.780
but its more reliable, baby, you can
00:03:12.780 --> 00:03:15.090
order another dish, no, whatever they
00:03:15.090 --> 00:03:19.200
ve prepared, eat it for me, but its better that
00:03:19.200 --> 00:03:21.390
Ill be a dad, who work like this all my life as a
00:03:21.390 --> 00:03:23.600
child and a
00:03:23.600 --> 00:03:26.150
dad,
00:03:26.150 --> 00:03:29.730
the most useful ones for you go to this chicane, it
00:03:29.730 --> 00:03:33.330
contains a lot of vitamin C and vitamin to
00:03:33.330 --> 00:03:38.030
vitamin A and bubbles or nuts that the
00:03:38.030 --> 00:03:40.380
need to run around is all
00:03:40.380 --> 00:03:43.260
wrong in the newspaper its written mom didnt
00:03:43.260 --> 00:03:45.830
00:03:45.830 --> 00:03:49.710
come up with it myself and now its time for the kids to go to bed
00:03:49.710 --> 00:03:58.790
[music]
00:03:58.790 --> 00:04:02.220
dad who puts the kids to bed like that,
00:04:02.220 --> 00:04:05.910
theyll have a concussion duo and I
00:04:05.910 --> 00:04:09.390
think they like it what kind of friend is the media of the same
00:04:09.390 --> 00:04:11.910
soul where are all the children who should you play with
00:04:11.910 --> 00:04:13.730
dear
00:04:13.730 --> 00:04:16.500
ladies let's go visit our neighbors
00:04:16.500 --> 00:04:20.190
there will probably be a couple of kids there it's
00:04:20.190 --> 00:04:22.440
good that the children fell asleep and mom didn't say
00:04:22.440 --> 00:04:24.540
finally we can have a cup of
00:04:24.540 --> 00:04:26.900
coffee
00:04:28.350 --> 00:04:35.839
[music]
00:04:38.090 --> 00:04:40.520
no
00:04:40.520 --> 00:04:44.310
it's yours and not a hat hat yeah but a
00:04:44.310 --> 00:04:45.150
hat
00:04:45.150 --> 00:04:47.000
[music] got it
00:04:47.000 --> 00:04:50.330
win
00:04:50.330 --> 00:04:53.840
watching the cars you
00:04:53.840 --> 00:04:57.210
ll say its also girly and you try sewing a
00:04:57.210 --> 00:05:00.720
telegraph yourself a real mans job yes yes the
00:05:00.720 --> 00:05:04.169
girls cant do it so you know how to
00:05:04.169 --> 00:05:05.720
sew yourself
00:05:05.720 --> 00:05:08.900
[music]
00:05:08.900 --> 00:05:11.730
writing they just came to play with you and
00:05:11.730 --> 00:05:14.430
you later come in, our children are sleeping under the
00:05:14.430 --> 00:05:18.200
cup, well, let it be yours, but its quiet,
00:05:18.200 --> 00:05:21.090
why is it quiet, lets wake up
00:05:21.090 --> 00:05:23.250
your game and they will play loudly together,
00:05:23.250 --> 00:05:26.570
but they just fell asleep,
00:05:26.570 --> 00:05:30.210
its you boys and girls, its our
00:05:30.210 --> 00:05:32.090
twins,
00:05:32.090 --> 00:05:35.870
why did anyone drink something important, its that they have a
00:05:35.870 --> 00:05:38.860
concussion brain happened
00:05:38.860 --> 00:05:41.660
useless of you parents for children
00:05:41.660 --> 00:05:45.250
ingots and it is necessary and you are sitting here drinking tea, its
00:05:45.250 --> 00:05:49.040
not true but a good family and not the
00:05:49.040 --> 00:05:50.380
best mother in the world
00:05:50.380 --> 00:05:53.860
[music]
00:05:53.860 --> 00:05:58.160
not me very much even without let me pour you
00:05:58.160 --> 00:06:01.220
some tea and jetta my couple
00:06:01.220 --> 00:06:04.580
will solve it when its time for me to go home, well, they are harmful
00:06:04.580 --> 00:06:06.790
,
00:06:10.640 --> 00:06:13.690
[music]
00:06:14.410 --> 00:06:17.830
well, thats it
00:06:21.310 --> 00:06:24.389
[music] [
00:06:28.690 --> 00:06:49.230
music]
00:06:49.230 --> 00:06:52.570
you guys have another flood, I
00:06:52.570 --> 00:06:56.910
let him out, sorry mom, he started
00:06:56.910 --> 00:06:59.860
saving our twins again,
00:06:59.860 --> 00:07:03.490
oh well done, what kind of grandmothers daddies found
00:07:03.490 --> 00:07:07.650
she just arrived
00:07:11.310 --> 00:07:14.540
[ music]
00:07:17.430 --> 00:07:18.940
boys
00:07:18.940 --> 00:07:39.520
[music]

View file

@ -0,0 +1,352 @@
WEBVTT
Kind: captions
Language: ru
00:00:00.650 --> 00:00:03.030
[музыка]
00:00:03.030 --> 00:00:05.220
[аплодисменты]
00:00:05.220 --> 00:00:17.060
[музыка]
00:00:17.060 --> 00:00:20.750
[музыка]
00:00:20.750 --> 00:00:21.930
пока
00:00:21.930 --> 00:00:24.430
[музыка]
00:00:24.430 --> 00:00:36.720
а
00:00:36.720 --> 00:00:40.380
чего волноваться то я же на матрасе
00:00:40.380 --> 00:00:41.540
[музыка]
00:00:41.540 --> 00:00:43.040
[аплодисменты]
00:00:43.040 --> 00:00:47.340
[музыка]
00:00:47.340 --> 00:00:56.340
тут такого не водится
00:00:56.340 --> 00:01:01.260
[музыка]
00:01:01.260 --> 00:01:04.479
сейчас как цапнет тебя она меня не
00:01:04.479 --> 00:01:08.130
догонит ей ки она же старая
00:01:08.130 --> 00:01:13.110
посмотри на
00:01:13.110 --> 00:01:15.720
тебе
00:01:15.720 --> 00:01:18.370
я тебя сам сейчас покупаю
00:01:18.370 --> 00:01:30.750
[музыка]
00:01:30.750 --> 00:01:33.970
что это у вас тут за беспорядок виду у
00:01:33.970 --> 00:01:36.790
нас по ту full мама хорошо что-то пришло
00:01:36.790 --> 00:01:40.090
и вся вода через дверь вы типа и я чуть
00:01:40.090 --> 00:01:43.420
не утонул ну ладно мне надо готовиться к
00:01:43.420 --> 00:01:45.939
приезду бабушки а вы когда приберетесь
00:01:45.939 --> 00:01:48.430
поиграйте в какую-нибудь спокойную игру
00:01:48.430 --> 00:01:51.460
хорошо мам мы сейчас все уберем и больше
00:01:51.460 --> 00:01:53.259
так не будем кстати вы не видели
00:01:53.259 --> 00:01:55.730
бабушкина мягкие тапочки
00:01:55.730 --> 00:01:57.750
[музыка]
00:01:57.750 --> 00:02:01.850
не лет не видели ли
00:02:01.850 --> 00:02:05.460
не хочу играть спокойнее игры скукотищу
00:02:05.460 --> 00:02:09.179
какая яки раз мама сказала значит надо
00:02:09.179 --> 00:02:12.000
сделать помогли и не расстраивать ее вот
00:02:12.000 --> 00:02:14.970
я знаю одну интересную спокойную игру но
00:02:14.970 --> 00:02:18.570
что но но мы в неё поиграем если только
00:02:18.570 --> 00:02:20.580
ты поклянешься никому они не
00:02:20.580 --> 00:02:23.700
рассказывать клянусь а почему нельзя
00:02:23.700 --> 00:02:25.320
никому рассказывать потому что а
00:02:25.320 --> 00:02:28.410
мальчишки в такие игры не играют как это
00:02:28.410 --> 00:02:32.450
вроде как считается что она девчачья
00:02:32.450 --> 00:02:36.720
какая ну для девочек что бывает игорь
00:02:36.720 --> 00:02:39.360
специально для девочек вот это было
00:02:39.360 --> 00:02:42.209
валяет его раньше не замечал что в плана
00:02:42.209 --> 00:02:44.630
девчачьи на свет увидит
00:02:44.630 --> 00:02:55.130
[музыка]
00:02:55.130 --> 00:02:58.890
ей ки не ломать детям кровать а то где
00:02:58.890 --> 00:03:01.380
будут спать твои братики и пожалуйста
00:03:01.380 --> 00:03:07.340
садись обедать мы тебя уже давно зовем
00:03:07.340 --> 00:03:09.860
полезное около
00:03:09.860 --> 00:03:12.780
но надёжней младенец вообще можно
00:03:12.780 --> 00:03:15.090
заказать другое блюдо нет что
00:03:15.090 --> 00:03:19.200
приготовили то и ешь мне да вот уж лучше
00:03:19.200 --> 00:03:21.390
я папой буду которые так всю жизнь
00:03:21.390 --> 00:03:23.600
ребенком работаю и
00:03:23.600 --> 00:03:26.150
папой
00:03:26.150 --> 00:03:29.730
самые полезные к вы идете это шикана
00:03:29.730 --> 00:03:33.330
много содержится витамин с и витамин к
00:03:33.330 --> 00:03:38.030
витамин а и пузырики или орешка что
00:03:38.030 --> 00:03:40.380
необходимость бегать по это все
00:03:40.380 --> 00:03:43.260
неправильно в газете написано мама не
00:03:43.260 --> 00:03:45.830
сам же я придумал а
00:03:45.830 --> 00:03:49.710
теперь малыши пора ложиться спать
00:03:49.710 --> 00:03:58.790
[музыка]
00:03:58.790 --> 00:04:02.220
папа кто же так детей спать укладывает у
00:04:02.220 --> 00:04:05.910
них же сотрясение мозга будет duo а я
00:04:05.910 --> 00:04:09.390
думаю нравится какая другу сми единой
00:04:09.390 --> 00:04:11.910
души где все дети с кем тебе поиграть
00:04:11.910 --> 00:04:13.730
милые
00:04:13.730 --> 00:04:16.500
дамы к зайдем в гости к нашим соседям
00:04:16.500 --> 00:04:20.190
там наверняка найдется пара детишек как
00:04:20.190 --> 00:04:22.440
хорошо что дети уснули и не говорила
00:04:22.440 --> 00:04:24.540
мама наконец-то можно выпить чашечку
00:04:24.540 --> 00:04:28.350
кофе
00:04:28.350 --> 00:04:38.090
[музыка]
00:04:38.090 --> 00:04:40.520
нет
00:04:40.520 --> 00:04:44.310
это у тебя и не шляпка шляпка ага а
00:04:44.310 --> 00:04:45.150
шляпка
00:04:45.150 --> 00:04:47.000
[музыка]
00:04:47.000 --> 00:04:50.330
поняла выиграть
00:04:50.330 --> 00:04:53.840
смотря машин
00:04:53.840 --> 00:04:57.210
скажешь тоже девчачью а ты попробуй сама
00:04:57.210 --> 00:05:00.720
сшей телеграф настоящая мужская работа
00:05:00.720 --> 00:05:04.169
да да девчонкам это не по силам вот ты
00:05:04.169 --> 00:05:05.720
сама шить на умеешь
00:05:05.720 --> 00:05:08.900
[музыка]
00:05:08.900 --> 00:05:11.730
написание к вам поиграть зашли просто а
00:05:11.730 --> 00:05:14.430
вы попозже заходите наши дети спят под
00:05:14.430 --> 00:05:18.200
cup ну и пусть она твоя играет но тихо
00:05:18.200 --> 00:05:21.090
почему это тихо давайте вы разбудите
00:05:21.090 --> 00:05:23.250
свои дичь и они вместе проиграет громко
00:05:23.250 --> 00:05:26.570
но они только уснули
00:05:26.570 --> 00:05:30.210
это у вас мальчики и девочки это у нас
00:05:30.210 --> 00:05:32.090
близнецы
00:05:32.090 --> 00:05:35.870
а почему любой выпили важный это у них
00:05:35.870 --> 00:05:38.860
сотрясение мозга случилось
00:05:38.860 --> 00:05:41.660
никудышные из вас родителей за детьми
00:05:41.660 --> 00:05:45.250
слитки и надо а вы тут сидите чай пьете
00:05:45.250 --> 00:05:49.040
неправда но хорошая семья а и не самая
00:05:49.040 --> 00:05:50.380
лучшая мама на свете
00:05:50.380 --> 00:05:53.860
[музыка]
00:05:53.860 --> 00:05:58.160
не я очень даже без давайте я вам чаю
00:05:58.160 --> 00:06:01.220
налью немного чай и jetta мой пара
00:06:01.220 --> 00:06:04.580
порешу когда мне домой пора ну и вредные
00:06:04.580 --> 00:06:10.640
,
00:06:10.640 --> 00:06:14.410
[музыка]
00:06:14.410 --> 00:06:21.310
ну все
00:06:21.310 --> 00:06:28.690
[музыка]
00:06:28.690 --> 00:06:49.230
[музыка]
00:06:49.230 --> 00:06:52.570
ребята у вас что опять потоп я же его
00:06:52.570 --> 00:06:56.910
выпустила прости мама он опять начался
00:06:56.910 --> 00:06:59.860
спасти и наших близнецов
00:06:59.860 --> 00:07:03.490
ай молодцы какие папочки бабушкины нашли
00:07:03.490 --> 00:07:11.310
она как раз только что приехала
00:07:11.310 --> 00:07:17.430
[музыка]
00:07:17.430 --> 00:07:18.940
мальчишки
00:07:18.940 --> 00:07:39.520
[музыка]