├── .babelrc
├── .eslintrc
├── .gitignore
├── .idea
└── vcs.xml
├── .npmignore
├── .npmrc
├── DEV_ONLY
└── App.js
├── LICENSE
├── README.md
├── dist
├── vidz.js
├── vidz.js.map
└── vidz.min.js
├── package.json
├── src
├── index.js
└── utils.js
├── test
├── index.js
├── setup-browser-environment.js
└── utils.js
├── webpack.config.dev.js
├── webpack.config.js
├── webpack.config.minified.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["add-module-exports"],
3 | "presets": [["env", { "loose": true }], "react", "stage-2"]
4 | }
5 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["rapid7/browser"],
3 | "parser": "babel-eslint",
4 | "rules": {}
5 | }
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | node_modules/
3 | lib/
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | DEV_ONLY/
3 | node_modules/
4 | src/
5 | test/
6 | dist/
7 | .babelrc
8 | .eslintrc
9 | .gitignore
10 | .npmignore
11 | webpack.config.js
12 | webpack.config.minified.js
13 | webpack.config.dev.js
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | scripts-prepend-node-path=true
--------------------------------------------------------------------------------
/DEV_ONLY/App.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery';
2 | import React, {
3 | Component
4 | } from 'react';
5 | import {
6 | render
7 | } from 'react-dom';
8 |
9 | import vidz from '../src';
10 |
11 | const delayVolumeDown = (instance, shouldDecrease = false, hasRun = false) => {
12 | return new Promise((resolve) => {
13 | setTimeout(() => {
14 | const currentVolume = instance.getVolume();
15 |
16 | if (hasRun && currentVolume === 1) {
17 | resolve()
18 | } else if (!shouldDecrease) {
19 | instance.setVolume(currentVolume + 0.1);
20 |
21 | resolve(delayVolumeDown(instance, false, true));
22 | } else {
23 | instance.setVolume(currentVolume - 0.1);
24 |
25 | resolve(delayVolumeDown(instance, currentVolume >= 0.1, true));
26 | }
27 | }, 250);
28 | });
29 | };
30 |
31 | class App extends Component {
32 | vidzInstance = null;
33 |
34 | componentDidMount() {
35 | let interval = null;
36 |
37 | const $div = $(this.refs.videoContainer);
38 |
39 | this.vidzInstance = vidz($div, {
40 | mp4: 'http://www.html5rocks.com/en/tutorials/video/basics/devstories.mp4',
41 | muted: true,
42 | onTimeUpdate() {
43 | console.log(this.currentTime);
44 | console.log(this.duration);
45 | },
46 | poster: 'https://placeholdit.imgix.net/~text?txtsize=33&txt=350%C3%97150&w=350&h=150',
47 | swf: 'test.swf',
48 | webm: 'http://www.html5rocks.com/en/tutorials/video/basics/devstories.webm'
49 | });
50 |
51 | this.forceUpdate();
52 | }
53 |
54 | state = {
55 | isPlaying: false
56 | };
57 |
58 | onClickPlayPause = () => {
59 | const {
60 | isPlaying
61 | } = this.state;
62 |
63 | if (isPlaying) {
64 | this.vidzInstance.pause();
65 | } else {
66 | this.vidzInstance.play();
67 | }
68 |
69 | this.setState({
70 | isPlaying: !isPlaying
71 | });
72 | };
73 |
74 | render() {
75 | return (
76 |
77 | App
78 |
79 |
83 |
84 |
87 | Toggle play / pause
88 |
89 |
90 | );
91 | }
92 | }
93 |
94 | const div = document.createElement('div');
95 |
96 | div.id = 'app-container';
97 |
98 | render((
99 |
100 | ), div);
101 |
102 | document.body.appendChild(div);
103 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Plant The Idea
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | vidz
2 | ===========
3 |
4 | Tiny library to provide a no-muss, no-fuss HTML5 video element
5 |
6 | #### Purpose
7 |
8 | To introduce a simple, straightforward method to dynamically add well-formatted HTML5 video to the DOM. `vidz` has no dependencies, and is based off of the native DOM elements and selectors, however if you are using jQuery it will also work with elements in jQuery objects.
9 |
10 | #### Installation
11 |
12 | ```
13 | $ npm i vidz --save
14 | ```
15 |
16 | #### Usage
17 |
18 | ```javascript
19 | // ES2015
20 | import vidz from 'vidz';
21 |
22 | // CommonJS
23 | const vidz = require('vidz').default;
24 |
25 | // script
26 | const vidz = window.vidz;
27 |
28 | const vidzInstance = vidz('#video-container', {
29 | mp4: './videos/test.mp4',
30 | ogg: './videos/test.ogg'
31 | });
32 | ```
33 |
34 | This will instantiate a new `vidz` instance, appending a generated `` element to the selector provided. You can also provide the DOM element itself, or a jQuery object if you wish.
35 |
36 | #### Advanced usage
37 |
38 | **vidz(selector: string|HTMLElement|jQueryObject, config: object)**
39 |
40 | ```javascript
41 | const standardSelector = vidz('#video-container', config);
42 | const domElement = vidz(document.querySelector('#video-container'), config);
43 | const jqueryObject = vidz($('#video-container'), config);
44 | ```
45 |
46 | Available options in the config object:
47 | * attributes `{object}` *defaults to {}*
48 | * Additional attributes that you want to pass to the `` element
49 | * autoplay `{boolean}` *defaults to false*
50 | * Whether the video should start playing immediately on load
51 | * controls `{boolean}` *defaults to true*
52 | * Whether the video should have the native controls provided
53 | * height `{number}` *defaults to 400*
54 | * Height in pixels the video container will be
55 | * loop `{boolean}` *defaults to false*
56 | * Whether the video should play on a loop
57 | * mp4 `{string}` *defaults to null*
58 | * The location of the mp4 file on your server relative to the page
59 | * muted `{boolean}` *defaults to false*
60 | * Whether the video should be muted on load
61 | * ogg `{string}` *defaults to null*
62 | * The location of the ogg/ogv file on your server relative to the page
63 | * onCanPlay `{function}` *defaults to null*
64 | * Function called when the `canplay` event is fired
65 | * onCanPlayThrough `{function}` *defaults to null*
66 | * Function called when the `canplaythrough` event is fired
67 | * onEmptied `{function}` *defaults to null*
68 | * Function fired when the `emptied` event is fired
69 | * onEnded `{function}` *defaults to null*
70 | * Function fired when the `ended` event is fired
71 | * onError `{function}` *defaults to null*
72 | * Function fires when the `error` event is fired
73 | * onLoad `{function}` *defaults to null*
74 | * Function fires when the `load` event is fired
75 | * onLoadedData `{function}` *defaults to null*
76 | * Function fires when the `loadeddata` event is fired
77 | * onLoadedMetadata `{function}` *defaults to null*
78 | * Function fires when the `loadingmetadata` event is fired
79 | * onLoadStart `{function}` *defaults to null*
80 | * Function fires when the `loadstart` event is fired
81 | * onPlay `{function}` *defaults to null*
82 | * Function fires when the `playing` event is fired
83 | * onPause `{function}` *defaults to null*
84 | * Function fires when the `pause` event is fired
85 | * onProgress `{function}` *defaults to null*
86 | * Function fires when the `progress` event is fired
87 | * onSeeked `{function}` *defaults to null*
88 | * Function fires when the `seeked` event is fired
89 | * onSeeking `{function}` *defaults to null*
90 | * Function fires when the `seeking` event is fired
91 | * onStalled `{function}` *defaults to null*
92 | * Function fires when the `stalled` event is fired
93 | * onSuspend `{function}` *defaults to null*
94 | * Function fires when the `suspend` event is fired
95 | * onTimeUpdate `{function}` *defaults to null*
96 | * Function fires when the `timeupdate` event is fired
97 | * onVolumeChange `{function}` *defaults to null*
98 | * Function fires when the `volumechange` event is fired
99 | * onWaiting `{function}` *defaults to null*
100 | * Function fires when the `waiting` event is fired
101 | * poster `{string}` *defaults to null*
102 | * The source of the image used as a poster for the video
103 | * preload `{string}` *defaults to "auto"*
104 | * The value for the `preload` attribute applied to the `` tag
105 | * swf `{string}` *defaults to null*
106 | * The location of the swf file on your server relative to the page
107 | * webm `{string}` *defaults to null*
108 | * The location of the webm file on your server relative to the page
109 | * width `{number}` *defaults to 600*
110 | * Width in pixels the video container will be
111 |
112 | #### Methods for the `Vidz` instance
113 |
114 | **add()**
115 |
116 | If the player has been previously removed from the `selector` passed originally, it re-appends the player to the `selector`.
117 |
118 | **canPlayType(format: string)**
119 |
120 | Returns the same format string if it supports the type `format`, else returns an empty string
121 |
122 | **getBuffered()**
123 |
124 | Returns the value of the `buffered` property for the player
125 |
126 | **getCurrentTime()**
127 |
128 | Returns the value of the `currentTime` property for the player
129 |
130 | **getDuration()**
131 |
132 | Returns the value of the `duration` property for the player
133 |
134 | **getFlashObject()**
135 |
136 | Returns the `` element nested in the player (useful for programmatic control of the Flash object)
137 |
138 | **getPercentLoaded()**
139 |
140 | Returns the percent loaded the video is (rounded to two decimal places)
141 |
142 | **getPlaybackRate()**
143 |
144 | Returns the `playbackRate` of the video player (standard `playbackRate` is 1, valid values are between 0.25 and 16)
145 |
146 | **getPlayer()**
147 |
148 | Returns the `` element of the player
149 |
150 | **getSource()**
151 |
152 | Returns an object of `{mp4: string, ogg: string, webm: string}` with the source values for the player
153 |
154 | **getVideoDimensions**
155 |
156 | Returns an object of `{height: number, width: number}` which reflects the height and width of the video (not the `` element
157 |
158 | **getVolume()**
159 |
160 | Returns the `volume` of the player (standard `volume` is 1, valid values are between 0 and 1)
161 |
162 | **load()**
163 |
164 | Triggers a `load` event on the player
165 |
166 | **mute()**
167 |
168 | Mutes the player
169 |
170 | **pause()**
171 |
172 | If the player is playing, it pauses the player
173 |
174 | **play()**
175 |
176 | If the player is paused, it plays the player
177 |
178 | **remove()**
179 |
180 | Removes the player as a child from the `selector` passed originally.
181 |
182 | **restart()**
183 |
184 | Sets the `currentTime` to 0
185 |
186 | **setCurrentTime(value: number)**
187 |
188 | Jumps the `currentTime` to the value provided
189 |
190 | **setPlaybackRate(value: number)** *defaults to 1*
191 |
192 | Sets the `playbackRate` to the value provided
193 |
194 | **setSource({mp4: string, ogg: string, web: string})**
195 |
196 | Sets the players `src` attribute to the value provided
197 |
198 | **setVolume(value: number)** *defaults to 1*
199 |
200 | Sets the player's volume to the value provided (standard `volume` is 1, valid values are between 0 and 1)
201 |
202 | **unmute()**
203 |
204 | If muted, it unmutes the player
205 |
206 | #### Note
207 |
208 | All of the methods above save for `add` and `remove` are specific to the HTML5 video element. Unfortunately we cannot provide the same programmatic controls for the Flash instance, as it is dependent on the SWF file you use. There is a `getFlashObject` convenience function to get the flash object you can control.
209 |
210 | #### Development
211 |
212 | Standard stuff, clone the repo and `npm i` to get the dependencies. npm scripts available:
213 | * `build` => builds the distributed JS with `NODE_ENV=development` and with sourcemaps
214 | * `build-minified` => builds the distributed JS with `NODE_ENV=production` and minified
215 | * `compile-for-publish` => runs the `lint`, `test`, `transpile`, and `dist` scripts
216 | * `dev` => runs the webpack dev server for the playground
217 | * `dist` => runs the `build` and `build-minified`
218 | * `lint` => runs ESLint against files in the `src` folder
219 | * `prepublish` => if in publish, runs `compile-for-publish`
220 | * `test` => runs AVA tests
221 | * `test:watch` => runs AVA tests with persistent watcher
222 | * `transpile` => runs Babel against files in `src` to files in `lib`
223 |
--------------------------------------------------------------------------------
/dist/vidz.js:
--------------------------------------------------------------------------------
1 | (function webpackUniversalModuleDefinition(root, factory) {
2 | if(typeof exports === 'object' && typeof module === 'object')
3 | module.exports = factory();
4 | else if(typeof define === 'function' && define.amd)
5 | define("vidz", [], factory);
6 | else if(typeof exports === 'object')
7 | exports["vidz"] = factory();
8 | else
9 | root["vidz"] = factory();
10 | })(window, function() {
11 | return /******/ (function(modules) { // webpackBootstrap
12 | /******/ // The module cache
13 | /******/ var installedModules = {};
14 | /******/
15 | /******/ // The require function
16 | /******/ function __webpack_require__(moduleId) {
17 | /******/
18 | /******/ // Check if module is in cache
19 | /******/ if(installedModules[moduleId]) {
20 | /******/ return installedModules[moduleId].exports;
21 | /******/ }
22 | /******/ // Create a new module (and put it into the cache)
23 | /******/ var module = installedModules[moduleId] = {
24 | /******/ i: moduleId,
25 | /******/ l: false,
26 | /******/ exports: {}
27 | /******/ };
28 | /******/
29 | /******/ // Execute the module function
30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31 | /******/
32 | /******/ // Flag the module as loaded
33 | /******/ module.l = true;
34 | /******/
35 | /******/ // Return the exports of the module
36 | /******/ return module.exports;
37 | /******/ }
38 | /******/
39 | /******/
40 | /******/ // expose the modules object (__webpack_modules__)
41 | /******/ __webpack_require__.m = modules;
42 | /******/
43 | /******/ // expose the module cache
44 | /******/ __webpack_require__.c = installedModules;
45 | /******/
46 | /******/ // define getter function for harmony exports
47 | /******/ __webpack_require__.d = function(exports, name, getter) {
48 | /******/ if(!__webpack_require__.o(exports, name)) {
49 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
50 | /******/ }
51 | /******/ };
52 | /******/
53 | /******/ // define __esModule on exports
54 | /******/ __webpack_require__.r = function(exports) {
55 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
56 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
57 | /******/ }
58 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
59 | /******/ };
60 | /******/
61 | /******/ // create a fake namespace object
62 | /******/ // mode & 1: value is a module id, require it
63 | /******/ // mode & 2: merge all properties of value into the ns
64 | /******/ // mode & 4: return value when already ns object
65 | /******/ // mode & 8|1: behave like require
66 | /******/ __webpack_require__.t = function(value, mode) {
67 | /******/ if(mode & 1) value = __webpack_require__(value);
68 | /******/ if(mode & 8) return value;
69 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
70 | /******/ var ns = Object.create(null);
71 | /******/ __webpack_require__.r(ns);
72 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
73 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
74 | /******/ return ns;
75 | /******/ };
76 | /******/
77 | /******/ // getDefaultExport function for compatibility with non-harmony modules
78 | /******/ __webpack_require__.n = function(module) {
79 | /******/ var getter = module && module.__esModule ?
80 | /******/ function getDefault() { return module['default']; } :
81 | /******/ function getModuleExports() { return module; };
82 | /******/ __webpack_require__.d(getter, 'a', getter);
83 | /******/ return getter;
84 | /******/ };
85 | /******/
86 | /******/ // Object.prototype.hasOwnProperty.call
87 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
88 | /******/
89 | /******/ // __webpack_public_path__
90 | /******/ __webpack_require__.p = "";
91 | /******/
92 | /******/
93 | /******/ // Load entry module and return exports
94 | /******/ return __webpack_require__(__webpack_require__.s = 0);
95 | /******/ })
96 | /************************************************************************/
97 | /******/ ({
98 |
99 | /***/ "./src/index.js":
100 | /*!**********************!*\
101 | !*** ./src/index.js ***!
102 | \**********************/
103 | /*! no static exports found */
104 | /***/ (function(module, exports, __webpack_require__) {
105 |
106 | "use strict";
107 |
108 |
109 | exports.__esModule = true;
110 | exports.Vidz = exports.setVideoEvents = exports.setElementAttribute = exports.getVideoElement = exports.getSourceElement = exports.getObjectElement = undefined;
111 |
112 | var _utils = __webpack_require__(/*! ./utils */ "./src/utils.js");
113 |
114 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
115 |
116 | var ELEMENT_TYPES = {
117 | IMAGE: 'img',
118 | OBJECT: 'object',
119 | PARAM: 'param',
120 | SOURCE: 'source',
121 | VIDEO: 'video'
122 | };
123 |
124 | var SOURCE_TYPES = {
125 | MP4: 'video/mp4',
126 | OGG: 'video/ogg',
127 | WEBM: 'video/webm'
128 | };
129 |
130 | var DEFAULT_ATTRIBUTES = {
131 | AUTOPLAY: false,
132 | CONTROLS: true,
133 | HEIGHT: 400,
134 | LOOP: false,
135 | MUTED: false,
136 | PRELOAD: 'auto',
137 | WIDTH: 600
138 | };
139 |
140 | /**
141 | * convenience function to set an attribute on an element to value
142 | *
143 | * @param {HTMLElement} element
144 | * @param {string} attribute
145 | * @param {any} value
146 | */
147 | var setElementAttribute = function setElementAttribute(element, attribute, value) {
148 | element.setAttribute(attribute, value);
149 | };
150 |
151 | /**
152 | * convenience function to add an event listener to an element
153 | *
154 | * @param {HTMLElement} element
155 | * @param {string} event
156 | * @param {function} handler
157 | */
158 | var setElementEventListener = function setElementEventListener(element, event, handler) {
159 | element.addEventListener(event, handler);
160 | };
161 |
162 | /**
163 | * create a new source element based on the elementType
164 | * and type, assigning the src to it
165 | *
166 | * @param {string} src
167 | * @param {string} type
168 | * @return {HTMLElement}
169 | */
170 | var getSourceElement = function getSourceElement(src, type) {
171 | var element = (0, _utils.createNewElement)(ELEMENT_TYPES.SOURCE);
172 |
173 | element.src = src;
174 | element.type = type;
175 |
176 | return element;
177 | };
178 |
179 | /**
180 | * create a new object element and populate it with the
181 | * param elements that have the flash-specific values needed
182 | * for the fallback
183 | *
184 | * @param {boolean} autoplay
185 | * @param {boolean} controls
186 | * @param {number} height
187 | * @param {string} mp4
188 | * @param {string} poster
189 | * @param {string} swf
190 | * @param {number} width
191 | * @return {HTMLElement}
192 | */
193 | var getObjectElement = function getObjectElement(_ref) {
194 | var autoplay = _ref.autoplay,
195 | controls = _ref.controls,
196 | height = _ref.height,
197 | mp4 = _ref.mp4,
198 | poster = _ref.poster,
199 | swf = _ref.swf,
200 | width = _ref.width;
201 |
202 | var objectElement = (0, _utils.createNewElement)(ELEMENT_TYPES.OBJECT),
203 | movieParamElement = (0, _utils.createNewElement)(ELEMENT_TYPES.PARAM),
204 | flashvarsParamElement = (0, _utils.createNewElement)(ELEMENT_TYPES.PARAM);
205 |
206 | setElementAttribute(objectElement, 'data', swf);
207 | setElementAttribute(objectElement, 'height', height);
208 | setElementAttribute(objectElement, 'width', width);
209 |
210 | setElementAttribute(movieParamElement, 'name', 'movie');
211 | setElementAttribute(movieParamElement, 'value', swf);
212 |
213 | setElementAttribute(flashvarsParamElement, 'name', 'flashvars');
214 |
215 | var flashvarsObject = {
216 | autostart: autoplay ? true : null,
217 | controlbar: controls ? 'over' : null,
218 | file: mp4,
219 | image: poster
220 | };
221 |
222 | var flashvarsValue = '';
223 |
224 | for (var key in flashvarsObject) {
225 | var value = flashvarsObject[key];
226 |
227 | if (value) {
228 | if (flashvarsValue) {
229 | flashvarsValue += '&';
230 | }
231 |
232 | flashvarsValue += key + '=' + value;
233 | }
234 | }
235 |
236 | setElementAttribute(flashvarsParamElement, 'value', flashvarsValue);
237 |
238 | objectElement.appendChild(movieParamElement);
239 | objectElement.appendChild(flashvarsParamElement);
240 |
241 | if (poster) {
242 | var imageElement = (0, _utils.createNewElement)(ELEMENT_TYPES.IMAGE);
243 |
244 | setElementAttribute(imageElement, 'alt', 'Video is unavailable.');
245 | setElementAttribute(imageElement, 'height', height);
246 | setElementAttribute(imageElement, 'src', poster);
247 | setElementAttribute(imageElement, 'title', 'We cannot provide playback capabilities at this time.');
248 | setElementAttribute(imageElement, 'width', width);
249 |
250 | objectElement.appendChild(imageElement);
251 | }
252 |
253 | return objectElement;
254 | };
255 |
256 | /**
257 | * build the video element that will be injected onto the page
258 | *
259 | * @param {boolean} autoplay
260 | * @param {boolean} controls
261 | * @param {number} height
262 | * @param {boolean} loop
263 | * @param {boolean} muted
264 | * @param {string} preload
265 | * @param {number} width
266 | * @returns {HTMLElement}
267 | */
268 | var getVideoElement = function getVideoElement(_ref2) {
269 | var autoplay = _ref2.autoplay,
270 | controls = _ref2.controls,
271 | height = _ref2.height,
272 | loop = _ref2.loop,
273 | muted = _ref2.muted,
274 | preload = _ref2.preload,
275 | width = _ref2.width;
276 |
277 | var videoElement = (0, _utils.createNewElement)(ELEMENT_TYPES.VIDEO);
278 |
279 | if (autoplay) {
280 | setElementAttribute(videoElement, 'autoplay', '');
281 | }
282 |
283 | if (controls) {
284 | setElementAttribute(videoElement, 'controls', '');
285 | }
286 |
287 | if (loop) {
288 | setElementAttribute(videoElement, 'loop', '');
289 | }
290 |
291 | if (muted) {
292 | setElementAttribute(videoElement, 'muted', '');
293 | }
294 |
295 | setElementAttribute(videoElement, 'height', height);
296 | setElementAttribute(videoElement, 'preload', preload);
297 | setElementAttribute(videoElement, 'width', width);
298 |
299 | return videoElement;
300 | };
301 |
302 | /**
303 | * get the percent loaded if duration is available
304 | *
305 | * @param {HTMLElement} player
306 | * @return {number}
307 | */
308 | var getPercentLoaded = function getPercentLoaded(player) {
309 | var duration = player.duration;
310 |
311 | if (duration) {
312 | var buffered = player.buffered;
313 | var percentLoaded = buffered.end(0) / duration;
314 |
315 | return Math.round(percentLoaded * 10000) / 100;
316 | }
317 |
318 | return 0;
319 | };
320 |
321 | /**
322 | * convenience function to wrap even with explicit this
323 | * as vidzInstance
324 | *
325 | * @param {Vidz} vidzInstance
326 | * @param {function} method
327 | * @return {function(e): void}
328 | */
329 | var wrapSimpleVideoEvent = function wrapSimpleVideoEvent(vidzInstance, method) {
330 | return function (e) {
331 | method.call(vidzInstance, e, vidzInstance);
332 | };
333 | };
334 |
335 | /**
336 | *
337 | * @param {Vidz} vidzInstance
338 | * @param {object} events
339 | * @param {function} [events.onCanPlayThrough]
340 | * @param {function} [events.onEnded]
341 | * @param {function} [events.onError]
342 | * @param {function} [events.onLoadedMetadata]
343 | * @param {function} [events.onPause]
344 | * @param {function} [events.onPlay]
345 | * @param {function} [events.onProgress]
346 | * @param {function} [events.onWaiting]
347 | */
348 | var setVideoEvents = function setVideoEvents(vidzInstance, events) {
349 | var onCanPlay = events.onCanPlay,
350 | onCanPlayThrough = events.onCanPlayThrough,
351 | onDurationChange = events.onDurationChange,
352 | onEmptied = events.onEmptied,
353 | onEnded = events.onEnded,
354 | onError = events.onError,
355 | onLoad = events.onLoad,
356 | onLoadedData = events.onLoadedData,
357 | onLoadedMetadata = events.onLoadedMetadata,
358 | onLoadStart = events.onLoadStart,
359 | onPause = events.onPause,
360 | onPlay = events.onPlay,
361 | onProgress = events.onProgress,
362 | onRateChange = events.onRateChange,
363 | onSeeked = events.onSeeked,
364 | onSeeking = events.onSeeking,
365 | onStalled = events.onStalled,
366 | onSuspend = events.onSuspend,
367 | onTimeUpdate = events.onTimeUpdate,
368 | onVolumeChange = events.onVolumeChange,
369 | onWaiting = events.onWaiting;
370 |
371 |
372 | var videoElement = vidzInstance.player;
373 |
374 | if (onCanPlay) {
375 | setElementEventListener(videoElement, 'canplay', wrapSimpleVideoEvent(vidzInstance, onCanPlay));
376 | }
377 |
378 | if (onCanPlayThrough) {
379 | setElementEventListener(videoElement, 'canplaythrough', wrapSimpleVideoEvent(vidzInstance, onCanPlayThrough));
380 | }
381 |
382 | setElementEventListener(videoElement, 'durationchange', function (e) {
383 | vidzInstance.duration = e.target.duration;
384 | vidzInstance.percentLoaded = getPercentLoaded(e.target);
385 |
386 | if (onDurationChange) {
387 | wrapSimpleVideoEvent(vidzInstance, onDurationChange)(e);
388 | }
389 | });
390 |
391 | if (onEmptied) {
392 | setElementEventListener(videoElement, 'emptied', wrapSimpleVideoEvent(vidzInstance, onEmptied));
393 | }
394 |
395 | if (onEnded) {
396 | setElementEventListener(videoElement, 'ended', wrapSimpleVideoEvent(vidzInstance, onEnded));
397 | }
398 |
399 | if (onError) {
400 | setElementEventListener(videoElement, 'error', wrapSimpleVideoEvent(vidzInstance, onError));
401 | }
402 |
403 | if (onLoad) {
404 | setElementEventListener(videoElement, 'load', wrapSimpleVideoEvent(vidzInstance, onLoad));
405 | }
406 |
407 | if (onLoadedData) {
408 | setElementEventListener(videoElement, 'loadeddata', wrapSimpleVideoEvent(vidzInstance, onLoadedData));
409 | }
410 |
411 | if (onLoadedMetadata) {
412 | setElementEventListener(videoElement, 'loadedmetadata', wrapSimpleVideoEvent(vidzInstance, onLoadedMetadata));
413 | }
414 |
415 | if (onLoadStart) {
416 | setElementEventListener(videoElement, 'loadstart', wrapSimpleVideoEvent(vidzInstance, onLoadStart));
417 | }
418 |
419 | if (onPause) {
420 | setElementEventListener(videoElement, 'pause', function (e) {
421 | if (vidzInstance.playing) {
422 | vidzInstance.playing = false;
423 |
424 | wrapSimpleVideoEvent(vidzInstance, onPause)(e);
425 | }
426 | });
427 | }
428 |
429 | if (onPlay) {
430 | setElementEventListener(videoElement, 'playing', function (e) {
431 | if (!vidzInstance.playing) {
432 | vidzInstance.playing = true;
433 |
434 | wrapSimpleVideoEvent(vidzInstance, onPlay)(e);
435 | }
436 | });
437 | }
438 |
439 | setElementEventListener(videoElement, 'progress', function (e) {
440 | vidzInstance.percentLoaded = getPercentLoaded(e.target);
441 |
442 | if (onProgress) {
443 | wrapSimpleVideoEvent(vidzInstance, onProgress)(e);
444 | }
445 | });
446 |
447 | if (onRateChange) {
448 | setElementEventListener(videoElement, 'ratechange', function (e) {
449 | vidzInstance.playbackRate = e.target.playbackRate;
450 |
451 | if (onRateChange) {
452 | wrapSimpleVideoEvent(vidzInstance, onRateChange)(e);
453 | }
454 | });
455 | }
456 |
457 | if (onSeeked) {
458 | setElementEventListener(videoElement, 'seeked', wrapSimpleVideoEvent(vidzInstance, onSeeked));
459 | }
460 |
461 | if (onSeeking) {
462 | setElementEventListener(videoElement, 'seeking', wrapSimpleVideoEvent(vidzInstance, onSeeking));
463 | }
464 |
465 | if (onStalled) {
466 | setElementEventListener(videoElement, 'stalled', wrapSimpleVideoEvent(vidzInstance, onStalled));
467 | }
468 |
469 | if (onSuspend) {
470 | setElementEventListener(videoElement, 'suspend', wrapSimpleVideoEvent(vidzInstance, onSuspend));
471 | }
472 |
473 | setElementEventListener(videoElement, 'timeupdate', function (e) {
474 | vidzInstance.currentTime = e.target.currentTime;
475 |
476 | if (onTimeUpdate) {
477 | wrapSimpleVideoEvent(vidzInstance, onTimeUpdate)(e);
478 | }
479 | });
480 |
481 | setElementEventListener(videoElement, 'volumechange', function (e) {
482 | vidzInstance.volume = e.target.volume;
483 |
484 | if (onVolumeChange) {
485 | wrapSimpleVideoEvent(vidzInstance, onVolumeChange)(e);
486 | }
487 | });
488 |
489 | if (onWaiting) {
490 | setElementEventListener(videoElement, 'waiting', wrapSimpleVideoEvent(vidzInstance, onWaiting));
491 | }
492 | };
493 |
494 | var Vidz = function () {
495 | /**
496 | * build the vidz instance with the appropriate elements, append the
497 | * elements to the parent provided by the selector, and then return
498 | * the instance
499 | *
500 | * @param {string|HTMLElement} selector
501 | * @param {object} config
502 | * @param {object} [config.attributes]
503 | * @param {boolean} [config.autoplay]
504 | * @param {boolean} [config.controls]
505 | * @param {number} [config.height]
506 | * @param {boolean} [config.loop]
507 | * @param {string} [config.mp4]
508 | * @param {boolean} [config.muted]
509 | * @param {string} [config.ogg]
510 | * @param {function} [config.onCanPlay]
511 | * @param {function} [config.onCanPlayThrough]
512 | * @param {function} [config.onDurationChange]
513 | * @param {function} [config.onEmptied]
514 | * @param {function} [config.onEnded]
515 | * @param {function} [config.onError]
516 | * @param {function} [config.onLoad]
517 | * @param {function} [config.onLoadedData]
518 | * @param {function} [config.onLoadedMetadata]
519 | * @param {function} [config.onLoadStart]
520 | * @param {function} [config.onPause]
521 | * @param {function} [config.onPlay]
522 | * @param {function} [config.onProgress]
523 | * @param {function} [config.onRateChange]
524 | * @param {function} [config.onSeeked]
525 | * @param {function} [config.onSeeking]
526 | * @param {function} [config.onStalled]
527 | * @param {function} [config.onSuspend]
528 | * @param {function} [config.onTimeUpdate]
529 | * @param {function} [config.onVolumeChange]
530 | * @param {function} [config.onWaiting]
531 | * @param {string} [config.poster]
532 | * @param {string} [config.preload]
533 | * @param {string} [config.webm]
534 | * @param {number} [config.width]
535 | * @return {Vidz}
536 | */
537 | function Vidz(selector) {
538 | var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
539 |
540 | _classCallCheck(this, Vidz);
541 |
542 | var element = void 0;
543 |
544 | switch (true) {
545 | case (0, _utils.isElement)(selector):
546 | element = selector;
547 | break;
548 |
549 | case (0, _utils.isString)(selector):
550 | element = document.querySelector(selector);
551 | break;
552 |
553 | case (0, _utils.isJqueryObject)(selector):
554 | element = selector[0];
555 | break;
556 |
557 | default:
558 | throw new Error('Selector passed must be either a DOM element, jQuery object, or string.');
559 | }
560 |
561 | var _config$attributes = config.attributes,
562 | attributes = _config$attributes === undefined ? {} : _config$attributes,
563 | _config$autoplay = config.autoplay,
564 | autoplay = _config$autoplay === undefined ? DEFAULT_ATTRIBUTES.AUTOPLAY : _config$autoplay,
565 | _config$controls = config.controls,
566 | controls = _config$controls === undefined ? DEFAULT_ATTRIBUTES.CONTROLS : _config$controls,
567 | _config$height = config.height,
568 | height = _config$height === undefined ? DEFAULT_ATTRIBUTES.HEIGHT : _config$height,
569 | _config$loop = config.loop,
570 | loop = _config$loop === undefined ? DEFAULT_ATTRIBUTES.LOOP : _config$loop,
571 | _config$mp = config.mp4,
572 | mp4 = _config$mp === undefined ? null : _config$mp,
573 | _config$muted = config.muted,
574 | muted = _config$muted === undefined ? DEFAULT_ATTRIBUTES.MUTED : _config$muted,
575 | _config$ogg = config.ogg,
576 | ogg = _config$ogg === undefined ? null : _config$ogg,
577 | _config$onCanPlay = config.onCanPlay,
578 | onCanPlay = _config$onCanPlay === undefined ? null : _config$onCanPlay,
579 | _config$onCanPlayThro = config.onCanPlayThrough,
580 | onCanPlayThrough = _config$onCanPlayThro === undefined ? null : _config$onCanPlayThro,
581 | _config$onDurationCha = config.onDurationChange,
582 | onDurationChange = _config$onDurationCha === undefined ? null : _config$onDurationCha,
583 | _config$onEmptied = config.onEmptied,
584 | onEmptied = _config$onEmptied === undefined ? null : _config$onEmptied,
585 | _config$onEnded = config.onEnded,
586 | onEnded = _config$onEnded === undefined ? null : _config$onEnded,
587 | _config$onError = config.onError,
588 | onError = _config$onError === undefined ? null : _config$onError,
589 | _config$onLoad = config.onLoad,
590 | onLoad = _config$onLoad === undefined ? null : _config$onLoad,
591 | _config$onLoadedData = config.onLoadedData,
592 | onLoadedData = _config$onLoadedData === undefined ? null : _config$onLoadedData,
593 | _config$onLoadedMetad = config.onLoadedMetadata,
594 | onLoadedMetadata = _config$onLoadedMetad === undefined ? null : _config$onLoadedMetad,
595 | _config$onLoadStart = config.onLoadStart,
596 | onLoadStart = _config$onLoadStart === undefined ? null : _config$onLoadStart,
597 | _config$onPause = config.onPause,
598 | onPause = _config$onPause === undefined ? null : _config$onPause,
599 | _config$onPlay = config.onPlay,
600 | onPlay = _config$onPlay === undefined ? null : _config$onPlay,
601 | _config$onProgress = config.onProgress,
602 | onProgress = _config$onProgress === undefined ? null : _config$onProgress,
603 | _config$onRateChange = config.onRateChange,
604 | onRateChange = _config$onRateChange === undefined ? null : _config$onRateChange,
605 | _config$onSeeked = config.onSeeked,
606 | onSeeked = _config$onSeeked === undefined ? null : _config$onSeeked,
607 | _config$onSeeking = config.onSeeking,
608 | onSeeking = _config$onSeeking === undefined ? null : _config$onSeeking,
609 | _config$onStalled = config.onStalled,
610 | onStalled = _config$onStalled === undefined ? null : _config$onStalled,
611 | _config$onSuspend = config.onSuspend,
612 | onSuspend = _config$onSuspend === undefined ? null : _config$onSuspend,
613 | _config$onTimeUpdate = config.onTimeUpdate,
614 | onTimeUpdate = _config$onTimeUpdate === undefined ? null : _config$onTimeUpdate,
615 | _config$onVolumeChang = config.onVolumeChange,
616 | onVolumeChange = _config$onVolumeChang === undefined ? null : _config$onVolumeChang,
617 | _config$onWaiting = config.onWaiting,
618 | onWaiting = _config$onWaiting === undefined ? null : _config$onWaiting,
619 | _config$poster = config.poster,
620 | poster = _config$poster === undefined ? null : _config$poster,
621 | _config$preload = config.preload,
622 | preload = _config$preload === undefined ? DEFAULT_ATTRIBUTES.PRELOAD : _config$preload,
623 | _config$swf = config.swf,
624 | swf = _config$swf === undefined ? null : _config$swf,
625 | _config$webm = config.webm,
626 | webm = _config$webm === undefined ? null : _config$webm,
627 | _config$width = config.width,
628 | width = _config$width === undefined ? DEFAULT_ATTRIBUTES.WIDTH : _config$width;
629 |
630 |
631 | Object.assign(this, {
632 | attributes: attributes,
633 | autoplay: autoplay,
634 | controls: controls,
635 | height: height,
636 | loop: loop,
637 | mp4: mp4,
638 | muted: muted,
639 | ogg: ogg,
640 | onCanPlay: onCanPlay,
641 | onCanPlayThrough: onCanPlayThrough,
642 | onEmptied: onEmptied,
643 | onEnded: onEnded,
644 | onError: onError,
645 | onLoad: onLoad,
646 | onLoadStart: onLoadStart,
647 | onLoadedData: onLoadedData,
648 | onLoadedMetadata: onLoadedMetadata,
649 | onPause: onPause,
650 | onPlay: onPlay,
651 | onProgress: onProgress,
652 | onRateChange: onRateChange,
653 | onSeeked: onSeeked,
654 | onSeeking: onSeeking,
655 | onStalled: onStalled,
656 | onSuspend: onSuspend,
657 | onTimeUpdate: onTimeUpdate,
658 | onVolumeChange: onVolumeChange,
659 | onWaiting: onWaiting,
660 | poster: poster,
661 | preload: preload,
662 | swf: swf,
663 | webm: webm,
664 | width: width
665 | });
666 |
667 | this.currentTime = 0;
668 | this.duration = null;
669 | this.element = element;
670 | this.height = height;
671 | this.muted = muted;
672 | this.percentLoaded = 0;
673 | this.playing = autoplay;
674 | this.playbackRate = 1;
675 | this.selector = selector;
676 | this.volume = 1;
677 | this.width = width;
678 |
679 | var videoElement = getVideoElement({
680 | autoplay: autoplay,
681 | controls: controls,
682 | height: height,
683 | loop: loop,
684 | muted: muted,
685 | preload: preload,
686 | width: width
687 | });
688 |
689 | for (var key in attributes) {
690 | setElementAttribute(videoElement, key, attributes[key]);
691 | }
692 |
693 | if (poster) {
694 | setElementAttribute(videoElement, 'poster', poster);
695 | }
696 |
697 | if (mp4) {
698 | var mp4Element = getSourceElement(mp4, SOURCE_TYPES.MP4);
699 |
700 | videoElement.appendChild(mp4Element);
701 | }
702 |
703 | if (webm) {
704 | var webmElement = getSourceElement(webm, SOURCE_TYPES.WEBM);
705 |
706 | videoElement.appendChild(webmElement);
707 | }
708 |
709 | if (ogg) {
710 | var oggElement = getSourceElement(ogg, SOURCE_TYPES.OGG);
711 |
712 | videoElement.appendChild(oggElement);
713 | }
714 |
715 | if (swf) {
716 | if (!mp4) {
717 | throw new Error('If you want a Flash fallback, you need to provide a video source in mp4 format.');
718 | }
719 |
720 | var flashFallbackElement = getObjectElement({
721 | autoplay: autoplay,
722 | controls: controls,
723 | height: height,
724 | mp4: mp4,
725 | poster: poster,
726 | swf: swf,
727 | width: width
728 | });
729 |
730 | videoElement.appendChild(flashFallbackElement);
731 | }
732 |
733 | this.player = videoElement;
734 | this.supportsHtml5Video = typeof (0, _utils.createNewElement)(ELEMENT_TYPES.VIDEO).canPlayType !== 'undefined';
735 |
736 | setVideoEvents(this, {
737 | onCanPlay: onCanPlay,
738 | onCanPlayThrough: onCanPlayThrough,
739 | onDurationChange: onDurationChange,
740 | onEmptied: onEmptied,
741 | onEnded: onEnded,
742 | onError: onError,
743 | onLoad: onLoad,
744 | onLoadStart: onLoadStart,
745 | onLoadedData: onLoadedData,
746 | onLoadedMetadata: onLoadedMetadata,
747 | onPause: onPause,
748 | onPlay: onPlay,
749 | onProgress: onProgress,
750 | onRateChange: onRateChange,
751 | onSeeked: onSeeked,
752 | onSeeking: onSeeking,
753 | onStalled: onStalled,
754 | onSuspend: onSuspend,
755 | onTimeUpdate: onTimeUpdate,
756 | onVolumeChange: onVolumeChange,
757 | onWaiting: onWaiting
758 | });
759 |
760 | if (element) {
761 | element.appendChild(videoElement);
762 | }
763 |
764 | return this;
765 | }
766 |
767 | /**
768 | * append the player as a child to the element
769 | *
770 | * @returns {Vidz}
771 | */
772 |
773 |
774 | Vidz.prototype.add = function add() {
775 | if (this.element) {
776 | this.element.appendChild(this.player);
777 | }
778 |
779 | return this;
780 | };
781 |
782 | /**
783 | * returns whether the player has the ability to play
784 | * the format passed
785 | *
786 | * @param {string} format
787 | * @return {boolean}
788 | */
789 |
790 |
791 | Vidz.prototype.canPlayType = function canPlayType(format) {
792 | return this.player.canPlayType(format);
793 | };
794 |
795 | /**
796 | *
797 | * @return {*|TimeRanges}
798 | */
799 |
800 |
801 | Vidz.prototype.getBuffered = function getBuffered() {
802 | return this.player.buffered;
803 | };
804 |
805 | /**
806 | * return the amount of time that has played in the video
807 | *
808 | * @return {number}
809 | */
810 |
811 |
812 | Vidz.prototype.getCurrentTime = function getCurrentTime() {
813 | return this.currentTime;
814 | };
815 |
816 | /**
817 | * return the length of the entire video
818 | *
819 | * @return {number}
820 | */
821 |
822 |
823 | Vidz.prototype.getDuration = function getDuration() {
824 | return this.duration;
825 | };
826 |
827 | /**
828 | * return the flash fallback
829 | *
830 | * @return {HTMLElement}
831 | */
832 |
833 |
834 | Vidz.prototype.getFlashObject = function getFlashObject() {
835 | return this.player.querySelector(ELEMENT_TYPES.OBJECT);
836 | };
837 |
838 | /**
839 | * return the % loaded (rounded to two decimals)
840 | *
841 | * @return {number}
842 | */
843 |
844 |
845 | Vidz.prototype.getPercentLoaded = function getPercentLoaded() {
846 | return this.percentLoaded;
847 | };
848 |
849 | /**
850 | * return the playback rate for the video (1 is standard speed)
851 | *
852 | * @return {number}
853 | */
854 |
855 |
856 | Vidz.prototype.getPlaybackRate = function getPlaybackRate() {
857 | return this.player.playbackRate;
858 | };
859 |
860 | /**
861 | * return the player element
862 | *
863 | * @return {HTMLElement}
864 | */
865 |
866 |
867 | Vidz.prototype.getPlayer = function getPlayer() {
868 | return this.player;
869 | };
870 |
871 | /**
872 | * return the dimensions of the element
873 | *
874 | * @return {{height: number, width: number}}
875 | */
876 |
877 |
878 | Vidz.prototype.getPlayerDimensions = function getPlayerDimensions() {
879 | return {
880 | height: this.height,
881 | width: this.width
882 | };
883 | };
884 |
885 | /**
886 | * get the source file locations for each type
887 | *
888 | * @return {{mp4: string, ogg: string, webm: string}}
889 | */
890 |
891 |
892 | Vidz.prototype.getSource = function getSource() {
893 | return {
894 | mp4: this.mp4,
895 | ogg: this.ogg,
896 | webm: this.webm
897 | };
898 | };
899 |
900 | /**
901 | * get the actual dimensions of the video (not the player)
902 | *
903 | * @return {{height: number, width: number}}
904 | */
905 |
906 |
907 | Vidz.prototype.getVideoDimensions = function getVideoDimensions() {
908 | return {
909 | height: this.player.videoHeight,
910 | width: this.player.videoWidth
911 | };
912 | };
913 |
914 | /**
915 | * return the volume level of the video
916 | *
917 | * @return {number}
918 | */
919 |
920 |
921 | Vidz.prototype.getVolume = function getVolume() {
922 | return this.player.volume;
923 | };
924 |
925 | /**
926 | * load the player sources
927 | *
928 | * @returns {Vidz}
929 | */
930 |
931 |
932 | Vidz.prototype.load = function load() {
933 | this.player.load();
934 |
935 | if (this.onLoad) {
936 | this.onLoad(this);
937 | }
938 |
939 | return this;
940 | };
941 |
942 | /**
943 | * set the player to be muted
944 | *
945 | * @return {Vidz}
946 | */
947 |
948 |
949 | Vidz.prototype.mute = function mute() {
950 | if (!this.muted) {
951 | this.player.muted = true;
952 | this.muted = true;
953 | }
954 |
955 | return this;
956 | };
957 |
958 | /**
959 | * pause the player
960 | *
961 | * @returns {Vidz}
962 | */
963 |
964 |
965 | Vidz.prototype.pause = function pause() {
966 | this.player.pause();
967 |
968 | return this;
969 | };
970 |
971 | /**
972 | * start the player
973 | *
974 | * @returns {Vidz}
975 | */
976 |
977 |
978 | Vidz.prototype.play = function play() {
979 | this.player.play();
980 |
981 | return this;
982 | };
983 |
984 | /**
985 | * remove the player from the parent it was appended to
986 | *
987 | * @returns {Vidz}
988 | */
989 |
990 |
991 | Vidz.prototype.remove = function remove() {
992 | if (this.player.parentNode) {
993 | this.player.parentNode.removeChild(this.player);
994 | }
995 |
996 | return this;
997 | };
998 |
999 | /**
1000 | * restart the video from the beginning
1001 | *
1002 | * @return {Vidz}
1003 | */
1004 |
1005 |
1006 | Vidz.prototype.restart = function restart() {
1007 | return this.setCurrentTime(0);
1008 | };
1009 |
1010 | /**
1011 | * set the place in the video to jump to
1012 | *
1013 | * @param {number} value
1014 | * @return {Vidz}
1015 | */
1016 |
1017 |
1018 | Vidz.prototype.setCurrentTime = function setCurrentTime(value) {
1019 | this.player.currentTime = value;
1020 | this.currentTime = value;
1021 |
1022 | return this;
1023 | };
1024 |
1025 | /**
1026 | * set the playback rate to a value, capping between 0.25 and 16
1027 | *
1028 | * @param {number} value=1
1029 | * @return {Vidz}
1030 | */
1031 |
1032 |
1033 | Vidz.prototype.setPlaybackRate = function setPlaybackRate() {
1034 | var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
1035 |
1036 | var validValue = value;
1037 |
1038 | if (value <= 0.25) {
1039 | validValue = 0.25;
1040 | } else if (value >= 16) {
1041 | validValue = 16;
1042 | }
1043 |
1044 | this.player.playbackRate = validValue;
1045 | this.playbackRate = validValue;
1046 |
1047 | return this;
1048 | };
1049 |
1050 | /**
1051 | * set new height / width values for the player and instance
1052 | *
1053 | * @param {number} height
1054 | * @param {number} width
1055 | * @return {Vidz}
1056 | */
1057 |
1058 |
1059 | Vidz.prototype.setPlayerDimensions = function setPlayerDimensions(_ref3) {
1060 | var height = _ref3.height,
1061 | width = _ref3.width;
1062 |
1063 | if (!(0, _utils.isUndefined)(height)) {
1064 | setElementAttribute(this.player, 'height', height);
1065 |
1066 | this.height = height;
1067 | }
1068 |
1069 | if (!(0, _utils.isUndefined)(width)) {
1070 | setElementAttribute(this.player, 'width', width);
1071 |
1072 | this.width = width;
1073 | }
1074 |
1075 | return this;
1076 | };
1077 |
1078 | /**
1079 | * set the source to the new value and reload it
1080 | *
1081 | * @param {string} mp4
1082 | * @param {string} ogg
1083 | * @param {string} webm
1084 | * @return {Vidz}
1085 | */
1086 |
1087 |
1088 | Vidz.prototype.setSource = function setSource(_ref4) {
1089 | var mp4 = _ref4.mp4,
1090 | ogg = _ref4.ogg,
1091 | webm = _ref4.webm;
1092 |
1093 | var sources = this.player.querySelectorAll('source');
1094 | var length = sources.length;
1095 |
1096 | var index = -1;
1097 |
1098 | while (++index < length) {
1099 | var source = sources[index];
1100 |
1101 | switch (source.type) {
1102 | case SOURCE_TYPES.MP4:
1103 | if (mp4) {
1104 | setElementAttribute(source, 'src', mp4);
1105 | this.mp4 = mp4;
1106 | }
1107 |
1108 | break;
1109 |
1110 | case SOURCE_TYPES.OGG:
1111 | if (ogg) {
1112 | setElementAttribute(source, 'src', ogg);
1113 | this.ogg = ogg;
1114 | }
1115 |
1116 | break;
1117 |
1118 | case SOURCE_TYPES.WEBM:
1119 | if (webm) {
1120 | setElementAttribute(source, 'src', webm);
1121 | this.webm = webm;
1122 | }
1123 |
1124 | break;
1125 | }
1126 | }
1127 |
1128 | if (mp4) {
1129 | var currentObjectElement = this.player.querySelector('object');
1130 | var newObjectElement = getObjectElement({
1131 | autoplay: this.autoplay,
1132 | controls: this.controls,
1133 | height: this.height,
1134 | mp4: mp4,
1135 | poster: this.poster,
1136 | swf: this.swf,
1137 | width: this.width
1138 | });
1139 |
1140 | this.player.removeChild(currentObjectElement);
1141 | this.player.appendChild(newObjectElement);
1142 | }
1143 |
1144 | return this.load();
1145 | };
1146 |
1147 | /**
1148 | * set the volume to a number between 0 and 1
1149 | *
1150 | * @param {number} value=1
1151 | * @return {Vidz}
1152 | */
1153 |
1154 |
1155 | Vidz.prototype.setVolume = function setVolume() {
1156 | var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
1157 |
1158 | var volume = value;
1159 |
1160 | if (value < 0) {
1161 | volume = 0;
1162 | } else if (value > 1) {
1163 | volume = 1;
1164 | }
1165 |
1166 | this.player.volume = volume;
1167 | this.volume = volume;
1168 |
1169 | return this;
1170 | };
1171 |
1172 | /**
1173 | * set the player to be unmuted
1174 | *
1175 | * @return {Vidz}
1176 | */
1177 |
1178 |
1179 | Vidz.prototype.unmute = function unmute() {
1180 | if (this.muted) {
1181 | this.player.muted = false;
1182 | this.muted = false;
1183 | }
1184 |
1185 | return this;
1186 | };
1187 |
1188 | return Vidz;
1189 | }();
1190 |
1191 | /**
1192 | * convenience function, so devs don't need to run new Vidz() every time
1193 | *
1194 | * @param {string} selector
1195 | * @param {object} config
1196 | * @return {Vidz}
1197 | */
1198 |
1199 |
1200 | var vidz = function vidz(selector, config) {
1201 | return new Vidz(selector, config);
1202 | };
1203 |
1204 | exports.getObjectElement = getObjectElement;
1205 | exports.getSourceElement = getSourceElement;
1206 | exports.getVideoElement = getVideoElement;
1207 | exports.setElementAttribute = setElementAttribute;
1208 | exports.setVideoEvents = setVideoEvents;
1209 | exports.Vidz = Vidz;
1210 | exports.default = vidz;
1211 |
1212 | /***/ }),
1213 |
1214 | /***/ "./src/utils.js":
1215 | /*!**********************!*\
1216 | !*** ./src/utils.js ***!
1217 | \**********************/
1218 | /*! no static exports found */
1219 | /***/ (function(module, exports, __webpack_require__) {
1220 |
1221 | "use strict";
1222 |
1223 |
1224 | exports.__esModule = true;
1225 |
1226 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
1227 |
1228 | /**
1229 | * return string form of object type
1230 | *
1231 | * @param {any} object
1232 | * @return {string}
1233 | */
1234 | var toString = function toString(object) {
1235 | return Object.prototype.toString.call(object);
1236 | };
1237 |
1238 | /**
1239 | * create a new element and return it
1240 | *
1241 | * @param {string} element
1242 | * @return {HTMLElement}
1243 | */
1244 | var createNewElement = function createNewElement(element) {
1245 | return document.createElement(element);
1246 | };
1247 |
1248 | /**
1249 | * determine if the object is an HTMLElement
1250 | *
1251 | * @param {any} object
1252 | * @return {boolean}
1253 | */
1254 | var isElement = function isElement(object) {
1255 | return (typeof HTMLElement === 'undefined' ? 'undefined' : _typeof(HTMLElement)) === 'object' ? object instanceof HTMLElement : !!object && (typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object' && object !== null && object.nodeType === 1 && typeof object.nodeName === 'string';
1256 | };
1257 |
1258 | /**
1259 | * determine if the object is a jQuery object
1260 | *
1261 | * @param {any} object
1262 | * @return {boolean}
1263 | */
1264 | var isJqueryObject = function isJqueryObject(object) {
1265 | return 'jquery' in Object(object);
1266 | };
1267 |
1268 | /**
1269 | * determine if object is a string
1270 | *
1271 | * @param {any} object
1272 | * @return {boolean}
1273 | */
1274 | var isString = function isString(object) {
1275 | return toString(object) === '[object String]';
1276 | };
1277 |
1278 | /**
1279 | * determine if object is undefined
1280 | *
1281 | * @param {any} object
1282 | * @return {boolean}
1283 | */
1284 | var isUndefined = function isUndefined(object) {
1285 | return object === void 0;
1286 | };
1287 |
1288 | exports.createNewElement = createNewElement;
1289 | exports.isElement = isElement;
1290 | exports.isJqueryObject = isJqueryObject;
1291 | exports.isString = isString;
1292 | exports.isUndefined = isUndefined;
1293 | exports.toString = toString;
1294 | exports.default = {
1295 | createNewElement: createNewElement,
1296 | isElement: isElement,
1297 | isString: isString,
1298 | isUndefined: isUndefined,
1299 | toString: toString
1300 | };
1301 |
1302 | /***/ }),
1303 |
1304 | /***/ 0:
1305 | /*!****************************!*\
1306 | !*** multi ./src/index.js ***!
1307 | \****************************/
1308 | /*! no static exports found */
1309 | /***/ (function(module, exports, __webpack_require__) {
1310 |
1311 | module.exports = __webpack_require__(/*! /home/tquetano/git/vidz/src/index.js */"./src/index.js");
1312 |
1313 |
1314 | /***/ })
1315 |
1316 | /******/ });
1317 | });
1318 | //# sourceMappingURL=vidz.js.map
--------------------------------------------------------------------------------
/dist/vidz.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://vidz/webpack/universalModuleDefinition","webpack://vidz/webpack/bootstrap","webpack://vidz/./src/index.js","webpack://vidz/./src/utils.js"],"names":["ELEMENT_TYPES","IMAGE","OBJECT","PARAM","SOURCE","VIDEO","SOURCE_TYPES","MP4","OGG","WEBM","DEFAULT_ATTRIBUTES","AUTOPLAY","CONTROLS","HEIGHT","LOOP","MUTED","PRELOAD","WIDTH","setElementAttribute","element","attribute","value","setAttribute","setElementEventListener","event","handler","addEventListener","getSourceElement","src","type","getObjectElement","autoplay","controls","height","mp4","poster","swf","width","objectElement","movieParamElement","flashvarsParamElement","flashvarsObject","autostart","controlbar","file","image","flashvarsValue","key","appendChild","imageElement","getVideoElement","loop","muted","preload","videoElement","getPercentLoaded","player","duration","buffered","percentLoaded","end","Math","round","wrapSimpleVideoEvent","vidzInstance","method","e","call","setVideoEvents","events","onCanPlay","onCanPlayThrough","onDurationChange","onEmptied","onEnded","onError","onLoad","onLoadedData","onLoadedMetadata","onLoadStart","onPause","onPlay","onProgress","onRateChange","onSeeked","onSeeking","onStalled","onSuspend","onTimeUpdate","onVolumeChange","onWaiting","target","playing","playbackRate","currentTime","volume","Vidz","selector","config","document","querySelector","Error","attributes","ogg","webm","Object","assign","mp4Element","webmElement","oggElement","flashFallbackElement","supportsHtml5Video","canPlayType","add","format","getBuffered","getCurrentTime","getDuration","getFlashObject","getPlaybackRate","getPlayer","getPlayerDimensions","getSource","getVideoDimensions","videoHeight","videoWidth","getVolume","load","mute","pause","play","remove","parentNode","removeChild","restart","setCurrentTime","setPlaybackRate","validValue","setPlayerDimensions","setSource","sources","querySelectorAll","length","index","source","currentObjectElement","newObjectElement","setVolume","unmute","vidz","toString","object","prototype","createNewElement","createElement","isElement","HTMLElement","nodeType","nodeName","isJqueryObject","isString","isUndefined"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;ACVA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,kDAA0C,gCAAgC;AAC1E;AACA;;AAEA;AACA;AACA;AACA,gEAAwD,kBAAkB;AAC1E;AACA,yDAAiD,cAAc;AAC/D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAyC,iCAAiC;AAC1E,wHAAgH,mBAAmB,EAAE;AACrI;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;;AAGA;AACA;;;;;;;;;;;;;;;;;;AClFA;;;;AAQA,IAAMA,gBAAgB;AACpBC,SAAO,KADa;AAEpBC,UAAQ,QAFY;AAGpBC,SAAO,OAHa;AAIpBC,UAAQ,QAJY;AAKpBC,SAAO;AALa,CAAtB;;AAQA,IAAMC,eAAe;AACnBC,OAAK,WADc;AAEnBC,OAAK,WAFc;AAGnBC,QAAM;AAHa,CAArB;;AAMA,IAAMC,qBAAqB;AACzBC,YAAU,KADe;AAEzBC,YAAU,IAFe;AAGzBC,UAAQ,GAHiB;AAIzBC,QAAM,KAJmB;AAKzBC,SAAO,KALkB;AAMzBC,WAAS,MANgB;AAOzBC,SAAO;AAPkB,CAA3B;;AAUA;;;;;;;AAOA,IAAMC,sBAAsB,SAAtBA,mBAAsB,CAACC,OAAD,EAAUC,SAAV,EAAqBC,KAArB,EAA+B;AACzDF,UAAQG,YAAR,CAAqBF,SAArB,EAAgCC,KAAhC;AACD,CAFD;;AAIA;;;;;;;AAOA,IAAME,0BAA0B,SAA1BA,uBAA0B,CAACJ,OAAD,EAAUK,KAAV,EAAiBC,OAAjB,EAA6B;AAC3DN,UAAQO,gBAAR,CAAyBF,KAAzB,EAAgCC,OAAhC;AACD,CAFD;;AAIA;;;;;;;;AAQA,IAAME,mBAAmB,SAAnBA,gBAAmB,CAACC,GAAD,EAAMC,IAAN,EAAe;AACtC,MAAIV,UAAU,6BAAiBnB,cAAcI,MAA/B,CAAd;;AAEAe,UAAQS,GAAR,GAAcA,GAAd;AACAT,UAAQU,IAAR,GAAeA,IAAf;;AAEA,SAAOV,OAAP;AACD,CAPD;;AASA;;;;;;;;;;;;;;AAcA,IAAMW,mBAAmB,SAAnBA,gBAAmB,OAA2D;AAAA,MAAzDC,QAAyD,QAAzDA,QAAyD;AAAA,MAA/CC,QAA+C,QAA/CA,QAA+C;AAAA,MAArCC,MAAqC,QAArCA,MAAqC;AAAA,MAA7BC,GAA6B,QAA7BA,GAA6B;AAAA,MAAxBC,MAAwB,QAAxBA,MAAwB;AAAA,MAAhBC,GAAgB,QAAhBA,GAAgB;AAAA,MAAXC,KAAW,QAAXA,KAAW;;AAClF,MAAIC,gBAAgB,6BAAiBtC,cAAcE,MAA/B,CAApB;AAAA,MACIqC,oBAAoB,6BAAiBvC,cAAcG,KAA/B,CADxB;AAAA,MAEIqC,wBAAwB,6BAAiBxC,cAAcG,KAA/B,CAF5B;;AAIAe,sBAAoBoB,aAApB,EAAmC,MAAnC,EAA2CF,GAA3C;AACAlB,sBAAoBoB,aAApB,EAAmC,QAAnC,EAA6CL,MAA7C;AACAf,sBAAoBoB,aAApB,EAAmC,OAAnC,EAA4CD,KAA5C;;AAEAnB,sBAAoBqB,iBAApB,EAAuC,MAAvC,EAA+C,OAA/C;AACArB,sBAAoBqB,iBAApB,EAAuC,OAAvC,EAAgDH,GAAhD;;AAEAlB,sBAAoBsB,qBAApB,EAA2C,MAA3C,EAAmD,WAAnD;;AAEA,MAAMC,kBAAkB;AACtBC,eAAWX,WAAW,IAAX,GAAkB,IADP;AAEtBY,gBAAYX,WAAW,MAAX,GAAoB,IAFV;AAGtBY,UAAMV,GAHgB;AAItBW,WAAOV;AAJe,GAAxB;;AAOA,MAAIW,iBAAiB,EAArB;;AAEA,OAAK,IAAIC,GAAT,IAAgBN,eAAhB,EAAiC;AAC/B,QAAMpB,QAAQoB,gBAAgBM,GAAhB,CAAd;;AAEA,QAAI1B,KAAJ,EAAW;AACT,UAAIyB,cAAJ,EAAoB;AAClBA,0BAAkB,GAAlB;AACD;;AAEDA,wBAAqBC,GAArB,SAA4B1B,KAA5B;AACD;AACF;;AAEDH,sBAAoBsB,qBAApB,EAA2C,OAA3C,EAAoDM,cAApD;;AAEAR,gBAAcU,WAAd,CAA0BT,iBAA1B;AACAD,gBAAcU,WAAd,CAA0BR,qBAA1B;;AAEA,MAAIL,MAAJ,EAAY;AACV,QAAIc,eAAe,6BAAiBjD,cAAcC,KAA/B,CAAnB;;AAEAiB,wBAAoB+B,YAApB,EAAkC,KAAlC,EAAyC,uBAAzC;AACA/B,wBAAoB+B,YAApB,EAAkC,QAAlC,EAA4ChB,MAA5C;AACAf,wBAAoB+B,YAApB,EAAkC,KAAlC,EAAyCd,MAAzC;AACAjB,wBAAoB+B,YAApB,EAAkC,OAAlC,EAA2C,uDAA3C;AACA/B,wBAAoB+B,YAApB,EAAkC,OAAlC,EAA2CZ,KAA3C;;AAEAC,kBAAcU,WAAd,CAA0BC,YAA1B;AACD;;AAED,SAAOX,aAAP;AACD,CArDD;;AAuDA;;;;;;;;;;;;AAYA,IAAMY,kBAAkB,SAAlBA,eAAkB,QAA+D;AAAA,MAA7DnB,QAA6D,SAA7DA,QAA6D;AAAA,MAAnDC,QAAmD,SAAnDA,QAAmD;AAAA,MAAzCC,MAAyC,SAAzCA,MAAyC;AAAA,MAAjCkB,IAAiC,SAAjCA,IAAiC;AAAA,MAA3BC,KAA2B,SAA3BA,KAA2B;AAAA,MAApBC,OAAoB,SAApBA,OAAoB;AAAA,MAAXhB,KAAW,SAAXA,KAAW;;AACrF,MAAIiB,eAAe,6BAAiBtD,cAAcK,KAA/B,CAAnB;;AAEA,MAAI0B,QAAJ,EAAc;AACZb,wBAAoBoC,YAApB,EAAkC,UAAlC,EAA8C,EAA9C;AACD;;AAED,MAAItB,QAAJ,EAAc;AACZd,wBAAoBoC,YAApB,EAAkC,UAAlC,EAA8C,EAA9C;AACD;;AAED,MAAIH,IAAJ,EAAU;AACRjC,wBAAoBoC,YAApB,EAAkC,MAAlC,EAA0C,EAA1C;AACD;;AAED,MAAIF,KAAJ,EAAW;AACTlC,wBAAoBoC,YAApB,EAAkC,OAAlC,EAA2C,EAA3C;AACD;;AAEDpC,sBAAoBoC,YAApB,EAAkC,QAAlC,EAA4CrB,MAA5C;AACAf,sBAAoBoC,YAApB,EAAkC,SAAlC,EAA6CD,OAA7C;AACAnC,sBAAoBoC,YAApB,EAAkC,OAAlC,EAA2CjB,KAA3C;;AAEA,SAAOiB,YAAP;AACD,CAxBD;;AA0BA;;;;;;AAMA,IAAMC,mBAAmB,SAAnBA,gBAAmB,CAACC,MAAD,EAAY;AACnC,MAAMC,WAAWD,OAAOC,QAAxB;;AAEA,MAAIA,QAAJ,EAAc;AACZ,QAAMC,WAAWF,OAAOE,QAAxB;AACA,QAAMC,gBAAgBD,SAASE,GAAT,CAAa,CAAb,IAAkBH,QAAxC;;AAEA,WAAOI,KAAKC,KAAL,CAAWH,gBAAgB,KAA3B,IAAoC,GAA3C;AACD;;AAED,SAAO,CAAP;AACD,CAXD;;AAaA;;;;;;;;AAQA,IAAMI,uBAAuB,SAAvBA,oBAAuB,CAACC,YAAD,EAAeC,MAAf;AAAA,SAA0B,UAACC,CAAD,EAAO;AAC5DD,WAAOE,IAAP,CAAYH,YAAZ,EAA0BE,CAA1B,EAA6BF,YAA7B;AACD,GAF4B;AAAA,CAA7B;;AAIA;;;;;;;;;;;;;AAaA,IAAMI,iBAAiB,SAAjBA,cAAiB,CAACJ,YAAD,EAAeK,MAAf,EAA0B;AAAA,MAE7CC,SAF6C,GAuB3CD,MAvB2C,CAE7CC,SAF6C;AAAA,MAG7CC,gBAH6C,GAuB3CF,MAvB2C,CAG7CE,gBAH6C;AAAA,MAI7CC,gBAJ6C,GAuB3CH,MAvB2C,CAI7CG,gBAJ6C;AAAA,MAK7CC,SAL6C,GAuB3CJ,MAvB2C,CAK7CI,SAL6C;AAAA,MAM7CC,OAN6C,GAuB3CL,MAvB2C,CAM7CK,OAN6C;AAAA,MAO7CC,OAP6C,GAuB3CN,MAvB2C,CAO7CM,OAP6C;AAAA,MAQ7CC,MAR6C,GAuB3CP,MAvB2C,CAQ7CO,MAR6C;AAAA,MAS7CC,YAT6C,GAuB3CR,MAvB2C,CAS7CQ,YAT6C;AAAA,MAU7CC,gBAV6C,GAuB3CT,MAvB2C,CAU7CS,gBAV6C;AAAA,MAW7CC,WAX6C,GAuB3CV,MAvB2C,CAW7CU,WAX6C;AAAA,MAY7CC,OAZ6C,GAuB3CX,MAvB2C,CAY7CW,OAZ6C;AAAA,MAa7CC,MAb6C,GAuB3CZ,MAvB2C,CAa7CY,MAb6C;AAAA,MAc7CC,UAd6C,GAuB3Cb,MAvB2C,CAc7Ca,UAd6C;AAAA,MAe7CC,YAf6C,GAuB3Cd,MAvB2C,CAe7Cc,YAf6C;AAAA,MAgB7CC,QAhB6C,GAuB3Cf,MAvB2C,CAgB7Ce,QAhB6C;AAAA,MAiB7CC,SAjB6C,GAuB3ChB,MAvB2C,CAiB7CgB,SAjB6C;AAAA,MAkB7CC,SAlB6C,GAuB3CjB,MAvB2C,CAkB7CiB,SAlB6C;AAAA,MAmB7CC,SAnB6C,GAuB3ClB,MAvB2C,CAmB7CkB,SAnB6C;AAAA,MAoB7CC,YApB6C,GAuB3CnB,MAvB2C,CAoB7CmB,YApB6C;AAAA,MAqB7CC,cArB6C,GAuB3CpB,MAvB2C,CAqB7CoB,cArB6C;AAAA,MAsB7CC,SAtB6C,GAuB3CrB,MAvB2C,CAsB7CqB,SAtB6C;;;AAyB/C,MAAIpC,eAAeU,aAAaR,MAAhC;;AAEA,MAAIc,SAAJ,EAAe;AACb/C,4BAAwB+B,YAAxB,EAAsC,SAAtC,EAAiDS,qBAAqBC,YAArB,EAAmCM,SAAnC,CAAjD;AACD;;AAED,MAAIC,gBAAJ,EAAsB;AACpBhD,4BAAwB+B,YAAxB,EAAsC,gBAAtC,EAAwDS,qBAAqBC,YAArB,EAAmCO,gBAAnC,CAAxD;AACD;;AAEDhD,0BAAwB+B,YAAxB,EAAsC,gBAAtC,EAAwD,UAACY,CAAD,EAAO;AAC7DF,iBAAaP,QAAb,GAAwBS,EAAEyB,MAAF,CAASlC,QAAjC;AACAO,iBAAaL,aAAb,GAA6BJ,iBAAiBW,EAAEyB,MAAnB,CAA7B;;AAEA,QAAInB,gBAAJ,EAAsB;AACpBT,2BAAqBC,YAArB,EAAmCQ,gBAAnC,EAAqDN,CAArD;AACD;AACF,GAPD;;AASA,MAAIO,SAAJ,EAAe;AACblD,4BAAwB+B,YAAxB,EAAsC,SAAtC,EAAiDS,qBAAqBC,YAArB,EAAmCS,SAAnC,CAAjD;AACD;;AAED,MAAIC,OAAJ,EAAa;AACXnD,4BAAwB+B,YAAxB,EAAsC,OAAtC,EAA+CS,qBAAqBC,YAArB,EAAmCU,OAAnC,CAA/C;AACD;;AAED,MAAIC,OAAJ,EAAa;AACXpD,4BAAwB+B,YAAxB,EAAsC,OAAtC,EAA+CS,qBAAqBC,YAArB,EAAmCW,OAAnC,CAA/C;AACD;;AAED,MAAIC,MAAJ,EAAY;AACVrD,4BAAwB+B,YAAxB,EAAsC,MAAtC,EAA8CS,qBAAqBC,YAArB,EAAmCY,MAAnC,CAA9C;AACD;;AAED,MAAIC,YAAJ,EAAkB;AAChBtD,4BAAwB+B,YAAxB,EAAsC,YAAtC,EAAoDS,qBAAqBC,YAArB,EAAmCa,YAAnC,CAApD;AACD;;AAED,MAAIC,gBAAJ,EAAsB;AACpBvD,4BAAwB+B,YAAxB,EAAsC,gBAAtC,EAAwDS,qBAAqBC,YAArB,EAAmCc,gBAAnC,CAAxD;AACD;;AAED,MAAIC,WAAJ,EAAiB;AACfxD,4BAAwB+B,YAAxB,EAAsC,WAAtC,EAAmDS,qBAAqBC,YAArB,EAAmCe,WAAnC,CAAnD;AACD;;AAED,MAAIC,OAAJ,EAAa;AACXzD,4BAAwB+B,YAAxB,EAAsC,OAAtC,EAA+C,UAACY,CAAD,EAAO;AACpD,UAAIF,aAAa4B,OAAjB,EAA0B;AACxB5B,qBAAa4B,OAAb,GAAuB,KAAvB;;AAEA7B,6BAAqBC,YAArB,EAAmCgB,OAAnC,EAA4Cd,CAA5C;AACD;AACF,KAND;AAOD;;AAED,MAAIe,MAAJ,EAAY;AACV1D,4BAAwB+B,YAAxB,EAAsC,SAAtC,EAAiD,UAACY,CAAD,EAAO;AACtD,UAAI,CAACF,aAAa4B,OAAlB,EAA2B;AACzB5B,qBAAa4B,OAAb,GAAuB,IAAvB;;AAEA7B,6BAAqBC,YAArB,EAAmCiB,MAAnC,EAA2Cf,CAA3C;AACD;AACF,KAND;AAOD;;AAED3C,0BAAwB+B,YAAxB,EAAsC,UAAtC,EAAkD,UAACY,CAAD,EAAO;AACvDF,iBAAaL,aAAb,GAA6BJ,iBAAiBW,EAAEyB,MAAnB,CAA7B;;AAEA,QAAIT,UAAJ,EAAgB;AACdnB,2BAAqBC,YAArB,EAAmCkB,UAAnC,EAA+ChB,CAA/C;AACD;AACF,GAND;;AAQA,MAAIiB,YAAJ,EAAkB;AAChB5D,4BAAwB+B,YAAxB,EAAsC,YAAtC,EAAoD,UAACY,CAAD,EAAO;AACzDF,mBAAa6B,YAAb,GAA4B3B,EAAEyB,MAAF,CAASE,YAArC;;AAEA,UAAIV,YAAJ,EAAkB;AAChBpB,6BAAqBC,YAArB,EAAmCmB,YAAnC,EAAiDjB,CAAjD;AACD;AACF,KAND;AAOD;;AAED,MAAIkB,QAAJ,EAAc;AACZ7D,4BAAwB+B,YAAxB,EAAsC,QAAtC,EAAgDS,qBAAqBC,YAArB,EAAmCoB,QAAnC,CAAhD;AACD;;AAED,MAAIC,SAAJ,EAAe;AACb9D,4BAAwB+B,YAAxB,EAAsC,SAAtC,EAAiDS,qBAAqBC,YAArB,EAAmCqB,SAAnC,CAAjD;AACD;;AAED,MAAIC,SAAJ,EAAe;AACb/D,4BAAwB+B,YAAxB,EAAsC,SAAtC,EAAiDS,qBAAqBC,YAArB,EAAmCsB,SAAnC,CAAjD;AACD;;AAED,MAAIC,SAAJ,EAAe;AACbhE,4BAAwB+B,YAAxB,EAAsC,SAAtC,EAAiDS,qBAAqBC,YAArB,EAAmCuB,SAAnC,CAAjD;AACD;;AAEDhE,0BAAwB+B,YAAxB,EAAsC,YAAtC,EAAoD,UAACY,CAAD,EAAO;AACzDF,iBAAa8B,WAAb,GAA2B5B,EAAEyB,MAAF,CAASG,WAApC;;AAEA,QAAIN,YAAJ,EAAkB;AAChBzB,2BAAqBC,YAArB,EAAmCwB,YAAnC,EAAiDtB,CAAjD;AACD;AACF,GAND;;AAQA3C,0BAAwB+B,YAAxB,EAAsC,cAAtC,EAAsD,UAACY,CAAD,EAAO;AAC3DF,iBAAa+B,MAAb,GAAsB7B,EAAEyB,MAAF,CAASI,MAA/B;;AAEA,QAAIN,cAAJ,EAAoB;AAClB1B,2BAAqBC,YAArB,EAAmCyB,cAAnC,EAAmDvB,CAAnD;AACD;AACF,GAND;;AAQA,MAAIwB,SAAJ,EAAe;AACbnE,4BAAwB+B,YAAxB,EAAsC,SAAtC,EAAiDS,qBAAqBC,YAArB,EAAmC0B,SAAnC,CAAjD;AACD;AACF,CAjJD;;IAmJMM,I;AACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,gBAAYC,QAAZ,EAAmC;AAAA,QAAbC,MAAa,uEAAJ,EAAI;;AAAA;;AACjC,QAAI/E,gBAAJ;;AAEA,YAAQ,IAAR;AACE,WAAK,sBAAU8E,QAAV,CAAL;AACE9E,kBAAU8E,QAAV;AACA;;AAEF,WAAK,qBAASA,QAAT,CAAL;AACE9E,kBAAUgF,SAASC,aAAT,CAAuBH,QAAvB,CAAV;AACA;;AAEF,WAAK,2BAAeA,QAAf,CAAL;AACE9E,kBAAU8E,SAAS,CAAT,CAAV;AACA;;AAEF;AACE,cAAM,IAAII,KAAJ,CAAU,yEAAV,CAAN;AAdJ;;AAHiC,6BAuD7BH,MAvD6B,CAqB/BI,UArB+B;AAAA,QAqB/BA,UArB+B,sCAqBlB,EArBkB;AAAA,2BAuD7BJ,MAvD6B,CAsB/BnE,QAtB+B;AAAA,QAsB/BA,QAtB+B,oCAsBpBrB,mBAAmBC,QAtBC;AAAA,2BAuD7BuF,MAvD6B,CAuB/BlE,QAvB+B;AAAA,QAuB/BA,QAvB+B,oCAuBpBtB,mBAAmBE,QAvBC;AAAA,yBAuD7BsF,MAvD6B,CAwB/BjE,MAxB+B;AAAA,QAwB/BA,MAxB+B,kCAwBtBvB,mBAAmBG,MAxBG;AAAA,uBAuD7BqF,MAvD6B,CAyB/B/C,IAzB+B;AAAA,QAyB/BA,IAzB+B,gCAyBxBzC,mBAAmBI,IAzBK;AAAA,qBAuD7BoF,MAvD6B,CA0B/BhE,GA1B+B;AAAA,QA0B/BA,GA1B+B,8BA0BzB,IA1ByB;AAAA,wBAuD7BgE,MAvD6B,CA2B/B9C,KA3B+B;AAAA,QA2B/BA,KA3B+B,iCA2BvB1C,mBAAmBK,KA3BI;AAAA,sBAuD7BmF,MAvD6B,CA4B/BK,GA5B+B;AAAA,QA4B/BA,GA5B+B,+BA4BzB,IA5ByB;AAAA,4BAuD7BL,MAvD6B,CA6B/B5B,SA7B+B;AAAA,QA6B/BA,SA7B+B,qCA6BnB,IA7BmB;AAAA,gCAuD7B4B,MAvD6B,CA8B/B3B,gBA9B+B;AAAA,QA8B/BA,gBA9B+B,yCA8BZ,IA9BY;AAAA,gCAuD7B2B,MAvD6B,CA+B/B1B,gBA/B+B;AAAA,QA+B/BA,gBA/B+B,yCA+BZ,IA/BY;AAAA,4BAuD7B0B,MAvD6B,CAgC/BzB,SAhC+B;AAAA,QAgC/BA,SAhC+B,qCAgCnB,IAhCmB;AAAA,0BAuD7ByB,MAvD6B,CAiC/BxB,OAjC+B;AAAA,QAiC/BA,OAjC+B,mCAiCrB,IAjCqB;AAAA,0BAuD7BwB,MAvD6B,CAkC/BvB,OAlC+B;AAAA,QAkC/BA,OAlC+B,mCAkCrB,IAlCqB;AAAA,yBAuD7BuB,MAvD6B,CAmC/BtB,MAnC+B;AAAA,QAmC/BA,MAnC+B,kCAmCtB,IAnCsB;AAAA,+BAuD7BsB,MAvD6B,CAoC/BrB,YApC+B;AAAA,QAoC/BA,YApC+B,wCAoChB,IApCgB;AAAA,gCAuD7BqB,MAvD6B,CAqC/BpB,gBArC+B;AAAA,QAqC/BA,gBArC+B,yCAqCZ,IArCY;AAAA,8BAuD7BoB,MAvD6B,CAsC/BnB,WAtC+B;AAAA,QAsC/BA,WAtC+B,uCAsCjB,IAtCiB;AAAA,0BAuD7BmB,MAvD6B,CAuC/BlB,OAvC+B;AAAA,QAuC/BA,OAvC+B,mCAuCrB,IAvCqB;AAAA,yBAuD7BkB,MAvD6B,CAwC/BjB,MAxC+B;AAAA,QAwC/BA,MAxC+B,kCAwCtB,IAxCsB;AAAA,6BAuD7BiB,MAvD6B,CAyC/BhB,UAzC+B;AAAA,QAyC/BA,UAzC+B,sCAyClB,IAzCkB;AAAA,+BAuD7BgB,MAvD6B,CA0C/Bf,YA1C+B;AAAA,QA0C/BA,YA1C+B,wCA0ChB,IA1CgB;AAAA,2BAuD7Be,MAvD6B,CA2C/Bd,QA3C+B;AAAA,QA2C/BA,QA3C+B,oCA2CpB,IA3CoB;AAAA,4BAuD7Bc,MAvD6B,CA4C/Bb,SA5C+B;AAAA,QA4C/BA,SA5C+B,qCA4CnB,IA5CmB;AAAA,4BAuD7Ba,MAvD6B,CA6C/BZ,SA7C+B;AAAA,QA6C/BA,SA7C+B,qCA6CnB,IA7CmB;AAAA,4BAuD7BY,MAvD6B,CA8C/BX,SA9C+B;AAAA,QA8C/BA,SA9C+B,qCA8CnB,IA9CmB;AAAA,+BAuD7BW,MAvD6B,CA+C/BV,YA/C+B;AAAA,QA+C/BA,YA/C+B,wCA+ChB,IA/CgB;AAAA,gCAuD7BU,MAvD6B,CAgD/BT,cAhD+B;AAAA,QAgD/BA,cAhD+B,yCAgDd,IAhDc;AAAA,4BAuD7BS,MAvD6B,CAiD/BR,SAjD+B;AAAA,QAiD/BA,SAjD+B,qCAiDnB,IAjDmB;AAAA,yBAuD7BQ,MAvD6B,CAkD/B/D,MAlD+B;AAAA,QAkD/BA,MAlD+B,kCAkDtB,IAlDsB;AAAA,0BAuD7B+D,MAvD6B,CAmD/B7C,OAnD+B;AAAA,QAmD/BA,OAnD+B,mCAmDrB3C,mBAAmBM,OAnDE;AAAA,sBAuD7BkF,MAvD6B,CAoD/B9D,GApD+B;AAAA,QAoD/BA,GApD+B,+BAoDzB,IApDyB;AAAA,uBAuD7B8D,MAvD6B,CAqD/BM,IArD+B;AAAA,QAqD/BA,IArD+B,gCAqDxB,IArDwB;AAAA,wBAuD7BN,MAvD6B,CAsD/B7D,KAtD+B;AAAA,QAsD/BA,KAtD+B,iCAsDvB3B,mBAAmBO,KAtDI;;;AAyDjCwF,WAAOC,MAAP,CAAc,IAAd,EAAoB;AAClBJ,4BADkB;AAElBvE,wBAFkB;AAGlBC,wBAHkB;AAIlBC,oBAJkB;AAKlBkB,gBALkB;AAMlBjB,cANkB;AAOlBkB,kBAPkB;AAQlBmD,cARkB;AASlBjC,0BATkB;AAUlBC,wCAVkB;AAWlBE,0BAXkB;AAYlBC,sBAZkB;AAalBC,sBAbkB;AAclBC,oBAdkB;AAelBG,8BAfkB;AAgBlBF,gCAhBkB;AAiBlBC,wCAjBkB;AAkBlBE,sBAlBkB;AAmBlBC,oBAnBkB;AAoBlBC,4BApBkB;AAqBlBC,gCArBkB;AAsBlBC,wBAtBkB;AAuBlBC,0BAvBkB;AAwBlBC,0BAxBkB;AAyBlBC,0BAzBkB;AA0BlBC,gCA1BkB;AA2BlBC,oCA3BkB;AA4BlBC,0BA5BkB;AA6BlBvD,oBA7BkB;AA8BlBkB,sBA9BkB;AA+BlBjB,cA/BkB;AAgClBoE,gBAhCkB;AAiClBnE;AAjCkB,KAApB;;AAoCA,SAAKyD,WAAL,GAAmB,CAAnB;AACA,SAAKrC,QAAL,GAAgB,IAAhB;AACA,SAAKtC,OAAL,GAAeA,OAAf;AACA,SAAKc,MAAL,GAAcA,MAAd;AACA,SAAKmB,KAAL,GAAaA,KAAb;AACA,SAAKO,aAAL,GAAqB,CAArB;AACA,SAAKiC,OAAL,GAAe7D,QAAf;AACA,SAAK8D,YAAL,GAAoB,CAApB;AACA,SAAKI,QAAL,GAAgBA,QAAhB;AACA,SAAKF,MAAL,GAAc,CAAd;AACA,SAAK1D,KAAL,GAAaA,KAAb;;AAEA,QAAIiB,eAAeJ,gBAAgB;AACjCnB,wBADiC;AAEjCC,wBAFiC;AAGjCC,oBAHiC;AAIjCkB,gBAJiC;AAKjCC,kBALiC;AAMjCC,sBANiC;AAOjChB;AAPiC,KAAhB,CAAnB;;AAUA,SAAK,IAAIU,GAAT,IAAgBuD,UAAhB,EAA4B;AAC1BpF,0BAAoBoC,YAApB,EAAkCP,GAAlC,EAAuCuD,WAAWvD,GAAX,CAAvC;AACD;;AAED,QAAIZ,MAAJ,EAAY;AACVjB,0BAAoBoC,YAApB,EAAkC,QAAlC,EAA4CnB,MAA5C;AACD;;AAED,QAAID,GAAJ,EAAS;AACP,UAAMyE,aAAahF,iBAAiBO,GAAjB,EAAsB5B,aAAaC,GAAnC,CAAnB;;AAEA+C,mBAAaN,WAAb,CAAyB2D,UAAzB;AACD;;AAED,QAAIH,IAAJ,EAAU;AACR,UAAMI,cAAcjF,iBAAiB6E,IAAjB,EAAuBlG,aAAaG,IAApC,CAApB;;AAEA6C,mBAAaN,WAAb,CAAyB4D,WAAzB;AACD;;AAED,QAAIL,GAAJ,EAAS;AACP,UAAMM,aAAalF,iBAAiB4E,GAAjB,EAAsBjG,aAAaE,GAAnC,CAAnB;;AAEA8C,mBAAaN,WAAb,CAAyB6D,UAAzB;AACD;;AAED,QAAIzE,GAAJ,EAAS;AACP,UAAI,CAACF,GAAL,EAAU;AACR,cAAM,IAAImE,KAAJ,CAAU,iFAAV,CAAN;AACD;;AAED,UAAMS,uBAAuBhF,iBAAiB;AAC5CC,0BAD4C;AAE5CC,0BAF4C;AAG5CC,sBAH4C;AAI5CC,gBAJ4C;AAK5CC,sBAL4C;AAM5CC,gBAN4C;AAO5CC;AAP4C,OAAjB,CAA7B;;AAUAiB,mBAAaN,WAAb,CAAyB8D,oBAAzB;AACD;;AAED,SAAKtD,MAAL,GAAcF,YAAd;AACA,SAAKyD,kBAAL,GAA0B,OAAO,6BAAiB/G,cAAcK,KAA/B,EAAsC2G,WAA7C,KAA6D,WAAvF;;AAEA5C,mBAAe,IAAf,EAAqB;AACnBE,0BADmB;AAEnBC,wCAFmB;AAGnBC,wCAHmB;AAInBC,0BAJmB;AAKnBC,sBALmB;AAMnBC,sBANmB;AAOnBC,oBAPmB;AAQnBG,8BARmB;AASnBF,gCATmB;AAUnBC,wCAVmB;AAWnBE,sBAXmB;AAYnBC,oBAZmB;AAanBC,4BAbmB;AAcnBC,gCAdmB;AAenBC,wBAfmB;AAgBnBC,0BAhBmB;AAiBnBC,0BAjBmB;AAkBnBC,0BAlBmB;AAmBnBC,gCAnBmB;AAoBnBC,oCApBmB;AAqBnBC;AArBmB,KAArB;;AAwBA,QAAIvE,OAAJ,EAAa;AACXA,cAAQ6B,WAAR,CAAoBM,YAApB;AACD;;AAED,WAAO,IAAP;AACD;;AAED;;;;;;;iBAKA2D,G,kBAAM;AACJ,QAAI,KAAK9F,OAAT,EAAkB;AAChB,WAAKA,OAAL,CAAa6B,WAAb,CAAyB,KAAKQ,MAA9B;AACD;;AAED,WAAO,IAAP;AACD,G;;AAED;;;;;;;;;iBAOAwD,W,wBAAYE,M,EAAQ;AAClB,WAAO,KAAK1D,MAAL,CAAYwD,WAAZ,CAAwBE,MAAxB,CAAP;AACD,G;;AAED;;;;;;iBAIAC,W,0BAAc;AACZ,WAAO,KAAK3D,MAAL,CAAYE,QAAnB;AACD,G;;AAED;;;;;;;iBAKA0D,c,6BAAiB;AACf,WAAO,KAAKtB,WAAZ;AACD,G;;AAED;;;;;;;iBAKAuB,W,0BAAc;AACZ,WAAO,KAAK5D,QAAZ;AACD,G;;AAED;;;;;;;iBAKA6D,c,6BAAiB;AACf,WAAO,KAAK9D,MAAL,CAAY4C,aAAZ,CAA0BpG,cAAcE,MAAxC,CAAP;AACD,G;;AAED;;;;;;;iBAKAqD,gB,+BAAmB;AACjB,WAAO,KAAKI,aAAZ;AACD,G;;AAED;;;;;;;iBAKA4D,e,8BAAkB;AAChB,WAAO,KAAK/D,MAAL,CAAYqC,YAAnB;AACD,G;;AAED;;;;;;;iBAKA2B,S,wBAAY;AACV,WAAO,KAAKhE,MAAZ;AACD,G;;AAED;;;;;;;iBAKAiE,mB,kCAAsB;AACpB,WAAO;AACLxF,cAAQ,KAAKA,MADR;AAELI,aAAO,KAAKA;AAFP,KAAP;AAID,G;;AAED;;;;;;;iBAKAqF,S,wBAAY;AACV,WAAO;AACLxF,WAAK,KAAKA,GADL;AAELqE,WAAK,KAAKA,GAFL;AAGLC,YAAM,KAAKA;AAHN,KAAP;AAKD,G;;AAED;;;;;;;iBAKAmB,kB,iCAAqB;AACnB,WAAO;AACL1F,cAAQ,KAAKuB,MAAL,CAAYoE,WADf;AAELvF,aAAO,KAAKmB,MAAL,CAAYqE;AAFd,KAAP;AAID,G;;AAED;;;;;;;iBAKAC,S,wBAAY;AACV,WAAO,KAAKtE,MAAL,CAAYuC,MAAnB;AACD,G;;AAED;;;;;;;iBAKAgC,I,mBAAO;AACL,SAAKvE,MAAL,CAAYuE,IAAZ;;AAEA,QAAI,KAAKnD,MAAT,EAAiB;AACf,WAAKA,MAAL,CAAY,IAAZ;AACD;;AAED,WAAO,IAAP;AACD,G;;AAED;;;;;;;iBAKAoD,I,mBAAO;AACL,QAAI,CAAC,KAAK5E,KAAV,EAAiB;AACf,WAAKI,MAAL,CAAYJ,KAAZ,GAAoB,IAApB;AACA,WAAKA,KAAL,GAAa,IAAb;AACD;;AAED,WAAO,IAAP;AACD,G;;AAED;;;;;;;iBAKA6E,K,oBAAQ;AACN,SAAKzE,MAAL,CAAYyE,KAAZ;;AAEA,WAAO,IAAP;AACD,G;;AAED;;;;;;;iBAKAC,I,mBAAO;AACL,SAAK1E,MAAL,CAAY0E,IAAZ;;AAEA,WAAO,IAAP;AACD,G;;AAED;;;;;;;iBAKAC,M,qBAAS;AACP,QAAI,KAAK3E,MAAL,CAAY4E,UAAhB,EAA4B;AAC1B,WAAK5E,MAAL,CAAY4E,UAAZ,CAAuBC,WAAvB,CAAmC,KAAK7E,MAAxC;AACD;;AAED,WAAO,IAAP;AACD,G;;AAED;;;;;;;iBAKA8E,O,sBAAU;AACR,WAAO,KAAKC,cAAL,CAAoB,CAApB,CAAP;AACD,G;;AAED;;;;;;;;iBAMAA,c,2BAAelH,K,EAAO;AACpB,SAAKmC,MAAL,CAAYsC,WAAZ,GAA0BzE,KAA1B;AACA,SAAKyE,WAAL,GAAmBzE,KAAnB;;AAEA,WAAO,IAAP;AACD,G;;AAED;;;;;;;;iBAMAmH,e,8BAA2B;AAAA,QAAXnH,KAAW,uEAAH,CAAG;;AACzB,QAAIoH,aAAapH,KAAjB;;AAEA,QAAIA,SAAS,IAAb,EAAmB;AACjBoH,mBAAa,IAAb;AACD,KAFD,MAEO,IAAIpH,SAAS,EAAb,EAAiB;AACtBoH,mBAAa,EAAb;AACD;;AAED,SAAKjF,MAAL,CAAYqC,YAAZ,GAA2B4C,UAA3B;AACA,SAAK5C,YAAL,GAAoB4C,UAApB;;AAEA,WAAO,IAAP;AACD,G;;AAED;;;;;;;;;iBAOAC,mB,uCAAqC;AAAA,QAAhBzG,MAAgB,SAAhBA,MAAgB;AAAA,QAARI,KAAQ,SAARA,KAAQ;;AACnC,QAAI,CAAC,wBAAYJ,MAAZ,CAAL,EAA0B;AACxBf,0BAAoB,KAAKsC,MAAzB,EAAiC,QAAjC,EAA2CvB,MAA3C;;AAEA,WAAKA,MAAL,GAAcA,MAAd;AACD;;AAED,QAAI,CAAC,wBAAYI,KAAZ,CAAL,EAAyB;AACvBnB,0BAAoB,KAAKsC,MAAzB,EAAiC,OAAjC,EAA0CnB,KAA1C;;AAEA,WAAKA,KAAL,GAAaA,KAAb;AACD;;AAED,WAAO,IAAP;AACD,G;;AAED;;;;;;;;;;iBAQAsG,S,6BAA4B;AAAA,QAAjBzG,GAAiB,SAAjBA,GAAiB;AAAA,QAAZqE,GAAY,SAAZA,GAAY;AAAA,QAAPC,IAAO,SAAPA,IAAO;;AAC1B,QAAMoC,UAAU,KAAKpF,MAAL,CAAYqF,gBAAZ,CAA6B,QAA7B,CAAhB;AACA,QAAMC,SAASF,QAAQE,MAAvB;;AAEA,QAAIC,QAAQ,CAAC,CAAb;;AAEA,WAAO,EAAEA,KAAF,GAAUD,MAAjB,EAAyB;AACvB,UAAIE,SAASJ,QAAQG,KAAR,CAAb;;AAEA,cAAQC,OAAOnH,IAAf;AACE,aAAKvB,aAAaC,GAAlB;AACE,cAAI2B,GAAJ,EAAS;AACPhB,gCAAoB8H,MAApB,EAA4B,KAA5B,EAAmC9G,GAAnC;AACA,iBAAKA,GAAL,GAAWA,GAAX;AACD;;AAED;;AAEF,aAAK5B,aAAaE,GAAlB;AACE,cAAI+F,GAAJ,EAAS;AACPrF,gCAAoB8H,MAApB,EAA4B,KAA5B,EAAmCzC,GAAnC;AACA,iBAAKA,GAAL,GAAWA,GAAX;AACD;;AAED;;AAEF,aAAKjG,aAAaG,IAAlB;AACE,cAAI+F,IAAJ,EAAU;AACRtF,gCAAoB8H,MAApB,EAA4B,KAA5B,EAAmCxC,IAAnC;AACA,iBAAKA,IAAL,GAAYA,IAAZ;AACD;;AAED;AAvBJ;AAyBD;;AAED,QAAItE,GAAJ,EAAS;AACP,UAAM+G,uBAAuB,KAAKzF,MAAL,CAAY4C,aAAZ,CAA0B,QAA1B,CAA7B;AACA,UAAM8C,mBAAmBpH,iBAAiB;AACxCC,kBAAU,KAAKA,QADyB;AAExCC,kBAAU,KAAKA,QAFyB;AAGxCC,gBAAQ,KAAKA,MAH2B;AAIxCC,gBAJwC;AAKxCC,gBAAQ,KAAKA,MAL2B;AAMxCC,aAAK,KAAKA,GAN8B;AAOxCC,eAAO,KAAKA;AAP4B,OAAjB,CAAzB;;AAUA,WAAKmB,MAAL,CAAY6E,WAAZ,CAAwBY,oBAAxB;AACA,WAAKzF,MAAL,CAAYR,WAAZ,CAAwBkG,gBAAxB;AACD;;AAED,WAAO,KAAKnB,IAAL,EAAP;AACD,G;;AAED;;;;;;;;iBAMAoB,S,wBAAqB;AAAA,QAAX9H,KAAW,uEAAH,CAAG;;AACnB,QAAI0E,SAAS1E,KAAb;;AAEA,QAAIA,QAAQ,CAAZ,EAAe;AACb0E,eAAS,CAAT;AACD,KAFD,MAEO,IAAI1E,QAAQ,CAAZ,EAAe;AACpB0E,eAAS,CAAT;AACD;;AAED,SAAKvC,MAAL,CAAYuC,MAAZ,GAAqBA,MAArB;AACA,SAAKA,MAAL,GAAcA,MAAd;;AAEA,WAAO,IAAP;AACD,G;;AAED;;;;;;;iBAKAqD,M,qBAAS;AACP,QAAI,KAAKhG,KAAT,EAAgB;AACd,WAAKI,MAAL,CAAYJ,KAAZ,GAAoB,KAApB;AACA,WAAKA,KAAL,GAAa,KAAb;AACD;;AAED,WAAO,IAAP;AACD,G;;;;;AAGH;;;;;;;;;AAOA,IAAMiG,OAAO,SAAPA,IAAO,CAACpD,QAAD,EAAWC,MAAX;AAAA,SAAsB,IAAIF,IAAJ,CAASC,QAAT,EAAmBC,MAAnB,CAAtB;AAAA,CAAb;;QAEQpE,gB,GAAAA,gB;QACAH,gB,GAAAA,gB;QACAuB,e,GAAAA,e;QACAhC,mB,GAAAA,mB;QACAkD,c,GAAAA,c;QACA4B,I,GAAAA,I;kBAEOqD,I;;;;;;;;;;;;;;;;;;ACt9Bf;;;;;;AAMA,IAAMC,WAAW,SAAXA,QAAW,CAACC,MAAD;AAAA,SAAY9C,OAAO+C,SAAP,CAAiBF,QAAjB,CAA0BnF,IAA1B,CAA+BoF,MAA/B,CAAZ;AAAA,CAAjB;;AAEA;;;;;;AAMA,IAAME,mBAAmB,SAAnBA,gBAAmB,CAACtI,OAAD;AAAA,SAAagF,SAASuD,aAAT,CAAuBvI,OAAvB,CAAb;AAAA,CAAzB;;AAEA;;;;;;AAMA,IAAMwI,YAAY,SAAZA,SAAY,CAACJ,MAAD;AAAA,SAChB,QAAOK,WAAP,yCAAOA,WAAP,OAAuB,QAAvB,GACIL,kBAAkBK,WADtB,GAEI,CAAC,CAACL,MAAF,IACG,QAAOA,MAAP,yCAAOA,MAAP,OAAkB,QADrB,IAEGA,WAAW,IAFd,IAGGA,OAAOM,QAAP,KAAoB,CAHvB,IAIG,OAAON,OAAOO,QAAd,KAA2B,QAPlB;AAAA,CAAlB;;AASA;;;;;;AAMA,IAAMC,iBAAiB,SAAjBA,cAAiB,CAACR,MAAD;AAAA,SAAY,YAAY9C,OAAO8C,MAAP,CAAxB;AAAA,CAAvB;;AAEA;;;;;;AAMA,IAAMS,WAAW,SAAXA,QAAW,CAACT,MAAD;AAAA,SAAYD,SAASC,MAAT,MAAqB,iBAAjC;AAAA,CAAjB;;AAEA;;;;;;AAMA,IAAMU,cAAc,SAAdA,WAAc,CAACV,MAAD;AAAA,SAAYA,WAAW,KAAK,CAA5B;AAAA,CAApB;;QAEQE,gB,GAAAA,gB;QACAE,S,GAAAA,S;QACAI,c,GAAAA,c;QACAC,Q,GAAAA,Q;QACAC,W,GAAAA,W;QACAX,Q,GAAAA,Q;kBAEO;AACbG,oCADa;AAEbE,sBAFa;AAGbK,oBAHa;AAIbC,0BAJa;AAKbX;AALa,C","file":"vidz.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"vidz\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"vidz\"] = factory();\n\telse\n\t\troot[\"vidz\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","import {\n createNewElement,\n isElement,\n isJqueryObject,\n isString,\n isUndefined,\n} from './utils';\n\nconst ELEMENT_TYPES = {\n IMAGE: 'img',\n OBJECT: 'object',\n PARAM: 'param',\n SOURCE: 'source',\n VIDEO: 'video',\n};\n\nconst SOURCE_TYPES = {\n MP4: 'video/mp4',\n OGG: 'video/ogg',\n WEBM: 'video/webm',\n};\n\nconst DEFAULT_ATTRIBUTES = {\n AUTOPLAY: false,\n CONTROLS: true,\n HEIGHT: 400,\n LOOP: false,\n MUTED: false,\n PRELOAD: 'auto',\n WIDTH: 600,\n};\n\n/**\n * convenience function to set an attribute on an element to value\n *\n * @param {HTMLElement} element\n * @param {string} attribute\n * @param {any} value\n */\nconst setElementAttribute = (element, attribute, value) => {\n element.setAttribute(attribute, value);\n};\n\n/**\n * convenience function to add an event listener to an element\n *\n * @param {HTMLElement} element\n * @param {string} event\n * @param {function} handler\n */\nconst setElementEventListener = (element, event, handler) => {\n element.addEventListener(event, handler);\n};\n\n/**\n * create a new source element based on the elementType\n * and type, assigning the src to it\n *\n * @param {string} src\n * @param {string} type\n * @return {HTMLElement}\n */\nconst getSourceElement = (src, type) => {\n let element = createNewElement(ELEMENT_TYPES.SOURCE);\n\n element.src = src;\n element.type = type;\n\n return element;\n};\n\n/**\n * create a new object element and populate it with the\n * param elements that have the flash-specific values needed\n * for the fallback\n *\n * @param {boolean} autoplay\n * @param {boolean} controls\n * @param {number} height\n * @param {string} mp4\n * @param {string} poster\n * @param {string} swf\n * @param {number} width\n * @return {HTMLElement}\n */\nconst getObjectElement = ({autoplay, controls, height, mp4, poster, swf, width}) => {\n let objectElement = createNewElement(ELEMENT_TYPES.OBJECT),\n movieParamElement = createNewElement(ELEMENT_TYPES.PARAM),\n flashvarsParamElement = createNewElement(ELEMENT_TYPES.PARAM);\n\n setElementAttribute(objectElement, 'data', swf);\n setElementAttribute(objectElement, 'height', height);\n setElementAttribute(objectElement, 'width', width);\n\n setElementAttribute(movieParamElement, 'name', 'movie');\n setElementAttribute(movieParamElement, 'value', swf);\n\n setElementAttribute(flashvarsParamElement, 'name', 'flashvars');\n\n const flashvarsObject = {\n autostart: autoplay ? true : null,\n controlbar: controls ? 'over' : null,\n file: mp4,\n image: poster,\n };\n\n let flashvarsValue = '';\n\n for (let key in flashvarsObject) {\n const value = flashvarsObject[key];\n\n if (value) {\n if (flashvarsValue) {\n flashvarsValue += '&';\n }\n\n flashvarsValue += `${key}=${value}`;\n }\n }\n\n setElementAttribute(flashvarsParamElement, 'value', flashvarsValue);\n\n objectElement.appendChild(movieParamElement);\n objectElement.appendChild(flashvarsParamElement);\n\n if (poster) {\n let imageElement = createNewElement(ELEMENT_TYPES.IMAGE);\n\n setElementAttribute(imageElement, 'alt', 'Video is unavailable.');\n setElementAttribute(imageElement, 'height', height);\n setElementAttribute(imageElement, 'src', poster);\n setElementAttribute(imageElement, 'title', 'We cannot provide playback capabilities at this time.');\n setElementAttribute(imageElement, 'width', width);\n\n objectElement.appendChild(imageElement);\n }\n\n return objectElement;\n};\n\n/**\n * build the video element that will be injected onto the page\n *\n * @param {boolean} autoplay\n * @param {boolean} controls\n * @param {number} height\n * @param {boolean} loop\n * @param {boolean} muted\n * @param {string} preload\n * @param {number} width\n * @returns {HTMLElement}\n */\nconst getVideoElement = ({autoplay, controls, height, loop, muted, preload, width}) => {\n let videoElement = createNewElement(ELEMENT_TYPES.VIDEO);\n\n if (autoplay) {\n setElementAttribute(videoElement, 'autoplay', '');\n }\n\n if (controls) {\n setElementAttribute(videoElement, 'controls', '');\n }\n\n if (loop) {\n setElementAttribute(videoElement, 'loop', '');\n }\n\n if (muted) {\n setElementAttribute(videoElement, 'muted', '');\n }\n\n setElementAttribute(videoElement, 'height', height);\n setElementAttribute(videoElement, 'preload', preload);\n setElementAttribute(videoElement, 'width', width);\n\n return videoElement;\n};\n\n/**\n * get the percent loaded if duration is available\n *\n * @param {HTMLElement} player\n * @return {number}\n */\nconst getPercentLoaded = (player) => {\n const duration = player.duration;\n\n if (duration) {\n const buffered = player.buffered;\n const percentLoaded = buffered.end(0) / duration;\n\n return Math.round(percentLoaded * 10000) / 100;\n }\n\n return 0;\n};\n\n/**\n * convenience function to wrap even with explicit this\n * as vidzInstance\n *\n * @param {Vidz} vidzInstance\n * @param {function} method\n * @return {function(e): void}\n */\nconst wrapSimpleVideoEvent = (vidzInstance, method) => (e) => {\n method.call(vidzInstance, e, vidzInstance);\n};\n\n/**\n *\n * @param {Vidz} vidzInstance\n * @param {object} events\n * @param {function} [events.onCanPlayThrough]\n * @param {function} [events.onEnded]\n * @param {function} [events.onError]\n * @param {function} [events.onLoadedMetadata]\n * @param {function} [events.onPause]\n * @param {function} [events.onPlay]\n * @param {function} [events.onProgress]\n * @param {function} [events.onWaiting]\n */\nconst setVideoEvents = (vidzInstance, events) => {\n const {\n onCanPlay,\n onCanPlayThrough,\n onDurationChange,\n onEmptied,\n onEnded,\n onError,\n onLoad,\n onLoadedData,\n onLoadedMetadata,\n onLoadStart,\n onPause,\n onPlay,\n onProgress,\n onRateChange,\n onSeeked,\n onSeeking,\n onStalled,\n onSuspend,\n onTimeUpdate,\n onVolumeChange,\n onWaiting,\n } = events;\n\n let videoElement = vidzInstance.player;\n\n if (onCanPlay) {\n setElementEventListener(videoElement, 'canplay', wrapSimpleVideoEvent(vidzInstance, onCanPlay));\n }\n\n if (onCanPlayThrough) {\n setElementEventListener(videoElement, 'canplaythrough', wrapSimpleVideoEvent(vidzInstance, onCanPlayThrough));\n }\n\n setElementEventListener(videoElement, 'durationchange', (e) => {\n vidzInstance.duration = e.target.duration;\n vidzInstance.percentLoaded = getPercentLoaded(e.target);\n\n if (onDurationChange) {\n wrapSimpleVideoEvent(vidzInstance, onDurationChange)(e);\n }\n });\n\n if (onEmptied) {\n setElementEventListener(videoElement, 'emptied', wrapSimpleVideoEvent(vidzInstance, onEmptied));\n }\n\n if (onEnded) {\n setElementEventListener(videoElement, 'ended', wrapSimpleVideoEvent(vidzInstance, onEnded));\n }\n\n if (onError) {\n setElementEventListener(videoElement, 'error', wrapSimpleVideoEvent(vidzInstance, onError));\n }\n\n if (onLoad) {\n setElementEventListener(videoElement, 'load', wrapSimpleVideoEvent(vidzInstance, onLoad));\n }\n\n if (onLoadedData) {\n setElementEventListener(videoElement, 'loadeddata', wrapSimpleVideoEvent(vidzInstance, onLoadedData));\n }\n\n if (onLoadedMetadata) {\n setElementEventListener(videoElement, 'loadedmetadata', wrapSimpleVideoEvent(vidzInstance, onLoadedMetadata));\n }\n\n if (onLoadStart) {\n setElementEventListener(videoElement, 'loadstart', wrapSimpleVideoEvent(vidzInstance, onLoadStart));\n }\n\n if (onPause) {\n setElementEventListener(videoElement, 'pause', (e) => {\n if (vidzInstance.playing) {\n vidzInstance.playing = false;\n\n wrapSimpleVideoEvent(vidzInstance, onPause)(e);\n }\n });\n }\n\n if (onPlay) {\n setElementEventListener(videoElement, 'playing', (e) => {\n if (!vidzInstance.playing) {\n vidzInstance.playing = true;\n\n wrapSimpleVideoEvent(vidzInstance, onPlay)(e);\n }\n });\n }\n\n setElementEventListener(videoElement, 'progress', (e) => {\n vidzInstance.percentLoaded = getPercentLoaded(e.target);\n\n if (onProgress) {\n wrapSimpleVideoEvent(vidzInstance, onProgress)(e);\n }\n });\n\n if (onRateChange) {\n setElementEventListener(videoElement, 'ratechange', (e) => {\n vidzInstance.playbackRate = e.target.playbackRate;\n\n if (onRateChange) {\n wrapSimpleVideoEvent(vidzInstance, onRateChange)(e);\n }\n });\n }\n\n if (onSeeked) {\n setElementEventListener(videoElement, 'seeked', wrapSimpleVideoEvent(vidzInstance, onSeeked));\n }\n\n if (onSeeking) {\n setElementEventListener(videoElement, 'seeking', wrapSimpleVideoEvent(vidzInstance, onSeeking));\n }\n\n if (onStalled) {\n setElementEventListener(videoElement, 'stalled', wrapSimpleVideoEvent(vidzInstance, onStalled));\n }\n\n if (onSuspend) {\n setElementEventListener(videoElement, 'suspend', wrapSimpleVideoEvent(vidzInstance, onSuspend));\n }\n\n setElementEventListener(videoElement, 'timeupdate', (e) => {\n vidzInstance.currentTime = e.target.currentTime;\n\n if (onTimeUpdate) {\n wrapSimpleVideoEvent(vidzInstance, onTimeUpdate)(e);\n }\n });\n\n setElementEventListener(videoElement, 'volumechange', (e) => {\n vidzInstance.volume = e.target.volume;\n\n if (onVolumeChange) {\n wrapSimpleVideoEvent(vidzInstance, onVolumeChange)(e);\n }\n });\n\n if (onWaiting) {\n setElementEventListener(videoElement, 'waiting', wrapSimpleVideoEvent(vidzInstance, onWaiting));\n }\n};\n\nclass Vidz {\n /**\n * build the vidz instance with the appropriate elements, append the\n * elements to the parent provided by the selector, and then return\n * the instance\n *\n * @param {string|HTMLElement} selector\n * @param {object} config\n * @param {object} [config.attributes]\n * @param {boolean} [config.autoplay]\n * @param {boolean} [config.controls]\n * @param {number} [config.height]\n * @param {boolean} [config.loop]\n * @param {string} [config.mp4]\n * @param {boolean} [config.muted]\n * @param {string} [config.ogg]\n * @param {function} [config.onCanPlay]\n * @param {function} [config.onCanPlayThrough]\n * @param {function} [config.onDurationChange]\n * @param {function} [config.onEmptied]\n * @param {function} [config.onEnded]\n * @param {function} [config.onError]\n * @param {function} [config.onLoad]\n * @param {function} [config.onLoadedData]\n * @param {function} [config.onLoadedMetadata]\n * @param {function} [config.onLoadStart]\n * @param {function} [config.onPause]\n * @param {function} [config.onPlay]\n * @param {function} [config.onProgress]\n * @param {function} [config.onRateChange]\n * @param {function} [config.onSeeked]\n * @param {function} [config.onSeeking]\n * @param {function} [config.onStalled]\n * @param {function} [config.onSuspend]\n * @param {function} [config.onTimeUpdate]\n * @param {function} [config.onVolumeChange]\n * @param {function} [config.onWaiting]\n * @param {string} [config.poster]\n * @param {string} [config.preload]\n * @param {string} [config.webm]\n * @param {number} [config.width]\n * @return {Vidz}\n */\n constructor(selector, config = {}) {\n let element;\n\n switch (true) {\n case isElement(selector):\n element = selector;\n break;\n\n case isString(selector):\n element = document.querySelector(selector);\n break;\n\n case isJqueryObject(selector):\n element = selector[0];\n break;\n\n default:\n throw new Error('Selector passed must be either a DOM element, jQuery object, or string.');\n }\n\n const {\n attributes = {},\n autoplay = DEFAULT_ATTRIBUTES.AUTOPLAY,\n controls = DEFAULT_ATTRIBUTES.CONTROLS,\n height = DEFAULT_ATTRIBUTES.HEIGHT,\n loop = DEFAULT_ATTRIBUTES.LOOP,\n mp4 = null,\n muted = DEFAULT_ATTRIBUTES.MUTED,\n ogg = null,\n onCanPlay = null,\n onCanPlayThrough = null,\n onDurationChange = null,\n onEmptied = null,\n onEnded = null,\n onError = null,\n onLoad = null,\n onLoadedData = null,\n onLoadedMetadata = null,\n onLoadStart = null,\n onPause = null,\n onPlay = null,\n onProgress = null,\n onRateChange = null,\n onSeeked = null,\n onSeeking = null,\n onStalled = null,\n onSuspend = null,\n onTimeUpdate = null,\n onVolumeChange = null,\n onWaiting = null,\n poster = null,\n preload = DEFAULT_ATTRIBUTES.PRELOAD,\n swf = null,\n webm = null,\n width = DEFAULT_ATTRIBUTES.WIDTH,\n } = config;\n\n Object.assign(this, {\n attributes,\n autoplay,\n controls,\n height,\n loop,\n mp4,\n muted,\n ogg,\n onCanPlay,\n onCanPlayThrough,\n onEmptied,\n onEnded,\n onError,\n onLoad,\n onLoadStart,\n onLoadedData,\n onLoadedMetadata,\n onPause,\n onPlay,\n onProgress,\n onRateChange,\n onSeeked,\n onSeeking,\n onStalled,\n onSuspend,\n onTimeUpdate,\n onVolumeChange,\n onWaiting,\n poster,\n preload,\n swf,\n webm,\n width,\n });\n\n this.currentTime = 0;\n this.duration = null;\n this.element = element;\n this.height = height;\n this.muted = muted;\n this.percentLoaded = 0;\n this.playing = autoplay;\n this.playbackRate = 1;\n this.selector = selector;\n this.volume = 1;\n this.width = width;\n\n let videoElement = getVideoElement({\n autoplay,\n controls,\n height,\n loop,\n muted,\n preload,\n width,\n });\n\n for (let key in attributes) {\n setElementAttribute(videoElement, key, attributes[key]);\n }\n\n if (poster) {\n setElementAttribute(videoElement, 'poster', poster);\n }\n\n if (mp4) {\n const mp4Element = getSourceElement(mp4, SOURCE_TYPES.MP4);\n\n videoElement.appendChild(mp4Element);\n }\n\n if (webm) {\n const webmElement = getSourceElement(webm, SOURCE_TYPES.WEBM);\n\n videoElement.appendChild(webmElement);\n }\n\n if (ogg) {\n const oggElement = getSourceElement(ogg, SOURCE_TYPES.OGG);\n\n videoElement.appendChild(oggElement);\n }\n\n if (swf) {\n if (!mp4) {\n throw new Error('If you want a Flash fallback, you need to provide a video source in mp4 format.');\n }\n\n const flashFallbackElement = getObjectElement({\n autoplay,\n controls,\n height,\n mp4,\n poster,\n swf,\n width,\n });\n\n videoElement.appendChild(flashFallbackElement);\n }\n\n this.player = videoElement;\n this.supportsHtml5Video = typeof createNewElement(ELEMENT_TYPES.VIDEO).canPlayType !== 'undefined';\n\n setVideoEvents(this, {\n onCanPlay,\n onCanPlayThrough,\n onDurationChange,\n onEmptied,\n onEnded,\n onError,\n onLoad,\n onLoadStart,\n onLoadedData,\n onLoadedMetadata,\n onPause,\n onPlay,\n onProgress,\n onRateChange,\n onSeeked,\n onSeeking,\n onStalled,\n onSuspend,\n onTimeUpdate,\n onVolumeChange,\n onWaiting,\n });\n\n if (element) {\n element.appendChild(videoElement);\n }\n\n return this;\n }\n\n /**\n * append the player as a child to the element\n *\n * @returns {Vidz}\n */\n add() {\n if (this.element) {\n this.element.appendChild(this.player);\n }\n\n return this;\n }\n\n /**\n * returns whether the player has the ability to play\n * the format passed\n *\n * @param {string} format\n * @return {boolean}\n */\n canPlayType(format) {\n return this.player.canPlayType(format);\n }\n\n /**\n *\n * @return {*|TimeRanges}\n */\n getBuffered() {\n return this.player.buffered;\n }\n\n /**\n * return the amount of time that has played in the video\n *\n * @return {number}\n */\n getCurrentTime() {\n return this.currentTime;\n }\n\n /**\n * return the length of the entire video\n *\n * @return {number}\n */\n getDuration() {\n return this.duration;\n }\n\n /**\n * return the flash fallback\n *\n * @return {HTMLElement}\n */\n getFlashObject() {\n return this.player.querySelector(ELEMENT_TYPES.OBJECT);\n }\n\n /**\n * return the % loaded (rounded to two decimals)\n *\n * @return {number}\n */\n getPercentLoaded() {\n return this.percentLoaded;\n }\n\n /**\n * return the playback rate for the video (1 is standard speed)\n *\n * @return {number}\n */\n getPlaybackRate() {\n return this.player.playbackRate;\n }\n\n /**\n * return the player element\n *\n * @return {HTMLElement}\n */\n getPlayer() {\n return this.player;\n }\n\n /**\n * return the dimensions of the element\n *\n * @return {{height: number, width: number}}\n */\n getPlayerDimensions() {\n return {\n height: this.height,\n width: this.width,\n };\n }\n\n /**\n * get the source file locations for each type\n *\n * @return {{mp4: string, ogg: string, webm: string}}\n */\n getSource() {\n return {\n mp4: this.mp4,\n ogg: this.ogg,\n webm: this.webm,\n };\n }\n\n /**\n * get the actual dimensions of the video (not the player)\n *\n * @return {{height: number, width: number}}\n */\n getVideoDimensions() {\n return {\n height: this.player.videoHeight,\n width: this.player.videoWidth,\n };\n }\n\n /**\n * return the volume level of the video\n *\n * @return {number}\n */\n getVolume() {\n return this.player.volume;\n }\n\n /**\n * load the player sources\n *\n * @returns {Vidz}\n */\n load() {\n this.player.load();\n\n if (this.onLoad) {\n this.onLoad(this);\n }\n\n return this;\n }\n\n /**\n * set the player to be muted\n *\n * @return {Vidz}\n */\n mute() {\n if (!this.muted) {\n this.player.muted = true;\n this.muted = true;\n }\n\n return this;\n }\n\n /**\n * pause the player\n *\n * @returns {Vidz}\n */\n pause() {\n this.player.pause();\n\n return this;\n }\n\n /**\n * start the player\n *\n * @returns {Vidz}\n */\n play() {\n this.player.play();\n\n return this;\n }\n\n /**\n * remove the player from the parent it was appended to\n *\n * @returns {Vidz}\n */\n remove() {\n if (this.player.parentNode) {\n this.player.parentNode.removeChild(this.player);\n }\n\n return this;\n }\n\n /**\n * restart the video from the beginning\n *\n * @return {Vidz}\n */\n restart() {\n return this.setCurrentTime(0);\n }\n\n /**\n * set the place in the video to jump to\n *\n * @param {number} value\n * @return {Vidz}\n */\n setCurrentTime(value) {\n this.player.currentTime = value;\n this.currentTime = value;\n\n return this;\n }\n\n /**\n * set the playback rate to a value, capping between 0.25 and 16\n *\n * @param {number} value=1\n * @return {Vidz}\n */\n setPlaybackRate(value = 1) {\n let validValue = value;\n\n if (value <= 0.25) {\n validValue = 0.25;\n } else if (value >= 16) {\n validValue = 16;\n }\n\n this.player.playbackRate = validValue;\n this.playbackRate = validValue;\n\n return this;\n }\n\n /**\n * set new height / width values for the player and instance\n *\n * @param {number} height\n * @param {number} width\n * @return {Vidz}\n */\n setPlayerDimensions({height, width}) {\n if (!isUndefined(height)) {\n setElementAttribute(this.player, 'height', height);\n\n this.height = height;\n }\n\n if (!isUndefined(width)) {\n setElementAttribute(this.player, 'width', width);\n\n this.width = width;\n }\n\n return this;\n }\n\n /**\n * set the source to the new value and reload it\n *\n * @param {string} mp4\n * @param {string} ogg\n * @param {string} webm\n * @return {Vidz}\n */\n setSource({mp4, ogg, webm}) {\n const sources = this.player.querySelectorAll('source');\n const length = sources.length;\n\n let index = -1;\n\n while (++index < length) {\n let source = sources[index];\n\n switch (source.type) {\n case SOURCE_TYPES.MP4:\n if (mp4) {\n setElementAttribute(source, 'src', mp4);\n this.mp4 = mp4;\n }\n\n break;\n\n case SOURCE_TYPES.OGG:\n if (ogg) {\n setElementAttribute(source, 'src', ogg);\n this.ogg = ogg;\n }\n\n break;\n\n case SOURCE_TYPES.WEBM:\n if (webm) {\n setElementAttribute(source, 'src', webm);\n this.webm = webm;\n }\n\n break;\n }\n }\n\n if (mp4) {\n const currentObjectElement = this.player.querySelector('object');\n const newObjectElement = getObjectElement({\n autoplay: this.autoplay,\n controls: this.controls,\n height: this.height,\n mp4,\n poster: this.poster,\n swf: this.swf,\n width: this.width,\n });\n\n this.player.removeChild(currentObjectElement);\n this.player.appendChild(newObjectElement);\n }\n\n return this.load();\n }\n\n /**\n * set the volume to a number between 0 and 1\n *\n * @param {number} value=1\n * @return {Vidz}\n */\n setVolume(value = 1) {\n let volume = value;\n\n if (value < 0) {\n volume = 0;\n } else if (value > 1) {\n volume = 1;\n }\n\n this.player.volume = volume;\n this.volume = volume;\n\n return this;\n }\n\n /**\n * set the player to be unmuted\n *\n * @return {Vidz}\n */\n unmute() {\n if (this.muted) {\n this.player.muted = false;\n this.muted = false;\n }\n\n return this;\n }\n}\n\n/**\n * convenience function, so devs don't need to run new Vidz() every time\n *\n * @param {string} selector\n * @param {object} config\n * @return {Vidz}\n */\nconst vidz = (selector, config) => new Vidz(selector, config);\n\nexport {getObjectElement};\nexport {getSourceElement};\nexport {getVideoElement};\nexport {setElementAttribute};\nexport {setVideoEvents};\nexport {Vidz};\n\nexport default vidz;\n","/**\n * return string form of object type\n *\n * @param {any} object\n * @return {string}\n */\nconst toString = (object) => Object.prototype.toString.call(object);\n\n/**\n * create a new element and return it\n *\n * @param {string} element\n * @return {HTMLElement}\n */\nconst createNewElement = (element) => document.createElement(element);\n\n/**\n * determine if the object is an HTMLElement\n *\n * @param {any} object\n * @return {boolean}\n */\nconst isElement = (object) =>\n typeof HTMLElement === 'object'\n ? object instanceof HTMLElement\n : !!object\n && typeof object === 'object'\n && object !== null\n && object.nodeType === 1\n && typeof object.nodeName === 'string';\n\n/**\n * determine if the object is a jQuery object\n *\n * @param {any} object\n * @return {boolean}\n */\nconst isJqueryObject = (object) => 'jquery' in Object(object);\n\n/**\n * determine if object is a string\n *\n * @param {any} object\n * @return {boolean}\n */\nconst isString = (object) => toString(object) === '[object String]';\n\n/**\n * determine if object is undefined\n *\n * @param {any} object\n * @return {boolean}\n */\nconst isUndefined = (object) => object === void 0;\n\nexport {createNewElement};\nexport {isElement};\nexport {isJqueryObject};\nexport {isString};\nexport {isUndefined};\nexport {toString};\n\nexport default {\n createNewElement,\n isElement,\n isString,\n isUndefined,\n toString,\n};\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/dist/vidz.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("vidz",[],t):"object"==typeof exports?exports.vidz=t():e.vidz=t()}(window,function(){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";t.__esModule=!0,t.Vidz=t.setVideoEvents=t.setElementAttribute=t.getVideoElement=t.getSourceElement=t.getObjectElement=void 0;var o=n(2);var r={IMAGE:"img",OBJECT:"object",PARAM:"param",SOURCE:"source",VIDEO:"video"},i={MP4:"video/mp4",OGG:"video/ogg",WEBM:"video/webm"},a={AUTOPLAY:!1,CONTROLS:!0,HEIGHT:400,LOOP:!1,MUTED:!1,PRELOAD:"auto",WIDTH:600},l=function(e,t,n){e.setAttribute(t,n)},u=function(e,t,n){e.addEventListener(t,n)},d=function(e,t){var n=(0,o.createNewElement)(r.SOURCE);return n.src=e,n.type=t,n},s=function(e){var t=e.autoplay,n=e.controls,i=e.height,a=e.mp4,u=e.poster,d=e.swf,s=e.width,p=(0,o.createNewElement)(r.OBJECT),h=(0,o.createNewElement)(r.PARAM),c=(0,o.createNewElement)(r.PARAM);l(p,"data",d),l(p,"height",i),l(p,"width",s),l(h,"name","movie"),l(h,"value",d),l(c,"name","flashvars");var y={autostart:!!t||null,controlbar:n?"over":null,file:a,image:u},f="";for(var m in y){var g=y[m];g&&(f&&(f+="&"),f+=m+"="+g)}if(l(c,"value",f),p.appendChild(h),p.appendChild(c),u){var v=(0,o.createNewElement)(r.IMAGE);l(v,"alt","Video is unavailable."),l(v,"height",i),l(v,"src",u),l(v,"title","We cannot provide playback capabilities at this time."),l(v,"width",s),p.appendChild(v)}return p},p=function(e){var t=e.autoplay,n=e.controls,i=e.height,a=e.loop,u=e.muted,d=e.preload,s=e.width,p=(0,o.createNewElement)(r.VIDEO);return t&&l(p,"autoplay",""),n&&l(p,"controls",""),a&&l(p,"loop",""),u&&l(p,"muted",""),l(p,"height",i),l(p,"preload",d),l(p,"width",s),p},h=function(e){var t=e.duration;if(t){var n=e.buffered.end(0)/t;return Math.round(1e4*n)/100}return 0},c=function(e,t){return function(n){t.call(e,n,e)}},y=function(e,t){var n=t.onCanPlay,o=t.onCanPlayThrough,r=t.onDurationChange,i=t.onEmptied,a=t.onEnded,l=t.onError,d=t.onLoad,s=t.onLoadedData,p=t.onLoadedMetadata,y=t.onLoadStart,f=t.onPause,m=t.onPlay,g=t.onProgress,v=t.onRateChange,b=t.onSeeked,E=t.onSeeking,w=t.onStalled,S=t.onSuspend,P=t.onTimeUpdate,C=t.onVolumeChange,T=t.onWaiting,O=e.player;n&&u(O,"canplay",c(e,n)),o&&u(O,"canplaythrough",c(e,o)),u(O,"durationchange",function(t){e.duration=t.target.duration,e.percentLoaded=h(t.target),r&&c(e,r)(t)}),i&&u(O,"emptied",c(e,i)),a&&u(O,"ended",c(e,a)),l&&u(O,"error",c(e,l)),d&&u(O,"load",c(e,d)),s&&u(O,"loadeddata",c(e,s)),p&&u(O,"loadedmetadata",c(e,p)),y&&u(O,"loadstart",c(e,y)),f&&u(O,"pause",function(t){e.playing&&(e.playing=!1,c(e,f)(t))}),m&&u(O,"playing",function(t){e.playing||(e.playing=!0,c(e,m)(t))}),u(O,"progress",function(t){e.percentLoaded=h(t.target),g&&c(e,g)(t)}),v&&u(O,"ratechange",function(t){e.playbackRate=t.target.playbackRate,v&&c(e,v)(t)}),b&&u(O,"seeked",c(e,b)),E&&u(O,"seeking",c(e,E)),w&&u(O,"stalled",c(e,w)),S&&u(O,"suspend",c(e,S)),u(O,"timeupdate",function(t){e.currentTime=t.target.currentTime,P&&c(e,P)(t)}),u(O,"volumechange",function(t){e.volume=t.target.volume,C&&c(e,C)(t)}),T&&u(O,"waiting",c(e,T))},f=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e);var u=void 0;switch(!0){case(0,o.isElement)(t):u=t;break;case(0,o.isString)(t):u=document.querySelector(t);break;case(0,o.isJqueryObject)(t):u=t[0];break;default:throw new Error("Selector passed must be either a DOM element, jQuery object, or string.")}var h=n.attributes,c=void 0===h?{}:h,f=n.autoplay,m=void 0===f?a.AUTOPLAY:f,g=n.controls,v=void 0===g?a.CONTROLS:g,b=n.height,E=void 0===b?a.HEIGHT:b,w=n.loop,S=void 0===w?a.LOOP:w,P=n.mp4,C=void 0===P?null:P,T=n.muted,O=void 0===T?a.MUTED:T,L=n.ogg,M=void 0===L?null:L,j=n.onCanPlay,k=void 0===j?null:j,D=n.onCanPlayThrough,R=void 0===D?null:D,A=n.onDurationChange,V=void 0===A?null:A,N=n.onEmptied,U=void 0===N?null:N,H=n.onEnded,W=void 0===H?null:H,x=n.onError,G=void 0===x?null:x,I=n.onLoad,_=void 0===I?null:I,q=n.onLoadedData,B=void 0===q?null:q,z=n.onLoadedMetadata,J=void 0===z?null:z,F=n.onLoadStart,Y=void 0===F?null:F,Q=n.onPause,K=void 0===Q?null:Q,X=n.onPlay,Z=void 0===X?null:X,$=n.onProgress,ee=void 0===$?null:$,te=n.onRateChange,ne=void 0===te?null:te,oe=n.onSeeked,re=void 0===oe?null:oe,ie=n.onSeeking,ae=void 0===ie?null:ie,le=n.onStalled,ue=void 0===le?null:le,de=n.onSuspend,se=void 0===de?null:de,pe=n.onTimeUpdate,he=void 0===pe?null:pe,ce=n.onVolumeChange,ye=void 0===ce?null:ce,fe=n.onWaiting,me=void 0===fe?null:fe,ge=n.poster,ve=void 0===ge?null:ge,be=n.preload,Ee=void 0===be?a.PRELOAD:be,we=n.swf,Se=void 0===we?null:we,Pe=n.webm,Ce=void 0===Pe?null:Pe,Te=n.width,Oe=void 0===Te?a.WIDTH:Te;Object.assign(this,{attributes:c,autoplay:m,controls:v,height:E,loop:S,mp4:C,muted:O,ogg:M,onCanPlay:k,onCanPlayThrough:R,onEmptied:U,onEnded:W,onError:G,onLoad:_,onLoadStart:Y,onLoadedData:B,onLoadedMetadata:J,onPause:K,onPlay:Z,onProgress:ee,onRateChange:ne,onSeeked:re,onSeeking:ae,onStalled:ue,onSuspend:se,onTimeUpdate:he,onVolumeChange:ye,onWaiting:me,poster:ve,preload:Ee,swf:Se,webm:Ce,width:Oe}),this.currentTime=0,this.duration=null,this.element=u,this.height=E,this.muted=O,this.percentLoaded=0,this.playing=m,this.playbackRate=1,this.selector=t,this.volume=1,this.width=Oe;var Le=p({autoplay:m,controls:v,height:E,loop:S,muted:O,preload:Ee,width:Oe});for(var Me in c)l(Le,Me,c[Me]);if(ve&&l(Le,"poster",ve),C){var je=d(C,i.MP4);Le.appendChild(je)}if(Ce){var ke=d(Ce,i.WEBM);Le.appendChild(ke)}if(M){var De=d(M,i.OGG);Le.appendChild(De)}if(Se){if(!C)throw new Error("If you want a Flash fallback, you need to provide a video source in mp4 format.");var Re=s({autoplay:m,controls:v,height:E,mp4:C,poster:ve,swf:Se,width:Oe});Le.appendChild(Re)}return this.player=Le,this.supportsHtml5Video=void 0!==(0,o.createNewElement)(r.VIDEO).canPlayType,y(this,{onCanPlay:k,onCanPlayThrough:R,onDurationChange:V,onEmptied:U,onEnded:W,onError:G,onLoad:_,onLoadStart:Y,onLoadedData:B,onLoadedMetadata:J,onPause:K,onPlay:Z,onProgress:ee,onRateChange:ne,onSeeked:re,onSeeking:ae,onStalled:ue,onSuspend:se,onTimeUpdate:he,onVolumeChange:ye,onWaiting:me}),u&&u.appendChild(Le),this}return e.prototype.add=function(){return this.element&&this.element.appendChild(this.player),this},e.prototype.canPlayType=function(e){return this.player.canPlayType(e)},e.prototype.getBuffered=function(){return this.player.buffered},e.prototype.getCurrentTime=function(){return this.currentTime},e.prototype.getDuration=function(){return this.duration},e.prototype.getFlashObject=function(){return this.player.querySelector(r.OBJECT)},e.prototype.getPercentLoaded=function(){return this.percentLoaded},e.prototype.getPlaybackRate=function(){return this.player.playbackRate},e.prototype.getPlayer=function(){return this.player},e.prototype.getPlayerDimensions=function(){return{height:this.height,width:this.width}},e.prototype.getSource=function(){return{mp4:this.mp4,ogg:this.ogg,webm:this.webm}},e.prototype.getVideoDimensions=function(){return{height:this.player.videoHeight,width:this.player.videoWidth}},e.prototype.getVolume=function(){return this.player.volume},e.prototype.load=function(){return this.player.load(),this.onLoad&&this.onLoad(this),this},e.prototype.mute=function(){return this.muted||(this.player.muted=!0,this.muted=!0),this},e.prototype.pause=function(){return this.player.pause(),this},e.prototype.play=function(){return this.player.play(),this},e.prototype.remove=function(){return this.player.parentNode&&this.player.parentNode.removeChild(this.player),this},e.prototype.restart=function(){return this.setCurrentTime(0)},e.prototype.setCurrentTime=function(e){return this.player.currentTime=e,this.currentTime=e,this},e.prototype.setPlaybackRate=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1,t=e;return e<=.25?t=.25:e>=16&&(t=16),this.player.playbackRate=t,this.playbackRate=t,this},e.prototype.setPlayerDimensions=function(e){var t=e.height,n=e.width;return(0,o.isUndefined)(t)||(l(this.player,"height",t),this.height=t),(0,o.isUndefined)(n)||(l(this.player,"width",n),this.width=n),this},e.prototype.setSource=function(e){for(var t=e.mp4,n=e.ogg,o=e.webm,r=this.player.querySelectorAll("source"),a=r.length,u=-1;++u0&&void 0!==arguments[0]?arguments[0]:1,t=e;return e<0?t=0:e>1&&(t=1),this.player.volume=t,this.volume=t,this},e.prototype.unmute=function(){return this.muted&&(this.player.muted=!1,this.muted=!1),this},e}();t.getObjectElement=s,t.getSourceElement=d,t.getVideoElement=p,t.setElementAttribute=l,t.setVideoEvents=y,t.Vidz=f,t.default=function(e,t){return new f(e,t)}},function(e,t,n){"use strict";t.__esModule=!0;var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r=function(e){return Object.prototype.toString.call(e)},i=function(e){return document.createElement(e)},a=function(e){return"object"===("undefined"==typeof HTMLElement?"undefined":o(HTMLElement))?e instanceof HTMLElement:!!e&&"object"===(void 0===e?"undefined":o(e))&&null!==e&&1===e.nodeType&&"string"==typeof e.nodeName},l=function(e){return"[object String]"===r(e)},u=function(e){return void 0===e};t.createNewElement=i,t.isElement=a,t.isJqueryObject=function(e){return"jquery"in Object(e)},t.isString=l,t.isUndefined=u,t.toString=r,t.default={createNewElement:i,isElement:a,isString:l,isUndefined:u,toString:r}}])});
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "planttheidea",
3 | "ava": {
4 | "babel": "inherit",
5 | "failFast": true,
6 | "files": [
7 | "./test/index.js",
8 | "./test/utils.js"
9 | ],
10 | "require": [
11 | "babel-register",
12 | "babel-polyfill",
13 | "./test/setup-browser-environment.js"
14 | ]
15 | },
16 | "bugs": {
17 | "url": "https://github.com/planttheidea/vidz/issues"
18 | },
19 | "devDependencies": {
20 | "ava": "^0.25.0",
21 | "babel-cli": "^6.26.0",
22 | "babel-core": "^6.26.3",
23 | "babel-eslint": "^8.0.1",
24 | "babel-loader": "^7.1.2",
25 | "babel-plugin-add-module-exports": "^0.2.1",
26 | "babel-polyfill": "^6.9.1",
27 | "babel-preset-env": "^1.7.0",
28 | "babel-preset-react": "^6.11.1",
29 | "babel-preset-stage-2": "^6.24.1",
30 | "babel-register": "^6.9.0",
31 | "eslint": "^5.12.0",
32 | "eslint-config-rapid7": "^3.1.0",
33 | "eslint-friendly-formatter": "^4.0.1",
34 | "eslint-loader": "^2.1.1",
35 | "html-webpack-plugin": "^3.2.0",
36 | "in-publish": "^2.0.0",
37 | "jquery": "^3.0.0",
38 | "jsdom": "^9.4.0",
39 | "react": "^16.7.0",
40 | "react-dom": "^16.7.0",
41 | "sinon": "^1.17.4",
42 | "webpack": "^4.28.1",
43 | "webpack-cli": "^3.2.1",
44 | "webpack-dev-server": "^3.1.14"
45 | },
46 | "description": "Bulletproof HTML5 video, with Flash fallback",
47 | "homepage": "https://github.com/planttheidea/vidz#readme",
48 | "keywords": [
49 | "video",
50 | "html5",
51 | "flash"
52 | ],
53 | "license": "MIT",
54 | "main": "lib/index.js",
55 | "name": "vidz",
56 | "repository": {
57 | "type": "git",
58 | "url": "git+https://github.com/planttheidea/vidz.git"
59 | },
60 | "scripts": {
61 | "build": "NODE_ENV=development webpack --progress --profile",
62 | "build-minified": "NODE_ENV=production webpack --progress --profile --config=webpack.config.minified.js",
63 | "compile-for-publish": "npm run lint && npm run test && npm run transpile && npm run dist",
64 | "dev": "NODE_ENV=development webpack-dev-server --progress --config=webpack.config.dev.js",
65 | "dist": "npm run build && npm run build-minified",
66 | "lint": "NODE_ENV=test eslint src",
67 | "prepublish": "if in-publish; then npm run compile-for-publish; fi",
68 | "test": "NODE_ENV=test ava --no-cache",
69 | "test:watch": "NODE_ENV=test ava --no-cache --watch",
70 | "transpile": "./node_modules/babel-cli/bin/babel.js -d lib/ src/"
71 | },
72 | "version": "1.2.5"
73 | }
74 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import {
2 | createNewElement,
3 | isElement,
4 | isJqueryObject,
5 | isString,
6 | isUndefined,
7 | } from './utils';
8 |
9 | const ELEMENT_TYPES = {
10 | IMAGE: 'img',
11 | OBJECT: 'object',
12 | PARAM: 'param',
13 | SOURCE: 'source',
14 | VIDEO: 'video',
15 | };
16 |
17 | const SOURCE_TYPES = {
18 | MP4: 'video/mp4',
19 | OGG: 'video/ogg',
20 | WEBM: 'video/webm',
21 | };
22 |
23 | const DEFAULT_ATTRIBUTES = {
24 | AUTOPLAY: false,
25 | CONTROLS: true,
26 | HEIGHT: 400,
27 | LOOP: false,
28 | MUTED: false,
29 | PRELOAD: 'auto',
30 | WIDTH: 600,
31 | };
32 |
33 | /**
34 | * convenience function to set an attribute on an element to value
35 | *
36 | * @param {HTMLElement} element
37 | * @param {string} attribute
38 | * @param {any} value
39 | */
40 | const setElementAttribute = (element, attribute, value) => {
41 | element.setAttribute(attribute, value);
42 | };
43 |
44 | /**
45 | * convenience function to add an event listener to an element
46 | *
47 | * @param {HTMLElement} element
48 | * @param {string} event
49 | * @param {function} handler
50 | */
51 | const setElementEventListener = (element, event, handler) => {
52 | element.addEventListener(event, handler);
53 | };
54 |
55 | /**
56 | * create a new source element based on the elementType
57 | * and type, assigning the src to it
58 | *
59 | * @param {string} src
60 | * @param {string} type
61 | * @return {HTMLElement}
62 | */
63 | const getSourceElement = (src, type) => {
64 | let element = createNewElement(ELEMENT_TYPES.SOURCE);
65 |
66 | element.src = src;
67 | element.type = type;
68 |
69 | return element;
70 | };
71 |
72 | /**
73 | * create a new object element and populate it with the
74 | * param elements that have the flash-specific values needed
75 | * for the fallback
76 | *
77 | * @param {boolean} autoplay
78 | * @param {boolean} controls
79 | * @param {number} height
80 | * @param {string} mp4
81 | * @param {string} poster
82 | * @param {string} swf
83 | * @param {number} width
84 | * @return {HTMLElement}
85 | */
86 | const getObjectElement = ({autoplay, controls, height, mp4, poster, swf, width}) => {
87 | let objectElement = createNewElement(ELEMENT_TYPES.OBJECT),
88 | movieParamElement = createNewElement(ELEMENT_TYPES.PARAM),
89 | flashvarsParamElement = createNewElement(ELEMENT_TYPES.PARAM);
90 |
91 | setElementAttribute(objectElement, 'data', swf);
92 | setElementAttribute(objectElement, 'height', height);
93 | setElementAttribute(objectElement, 'width', width);
94 |
95 | setElementAttribute(movieParamElement, 'name', 'movie');
96 | setElementAttribute(movieParamElement, 'value', swf);
97 |
98 | setElementAttribute(flashvarsParamElement, 'name', 'flashvars');
99 |
100 | const flashvarsObject = {
101 | autostart: autoplay ? true : null,
102 | controlbar: controls ? 'over' : null,
103 | file: mp4,
104 | image: poster,
105 | };
106 |
107 | let flashvarsValue = '';
108 |
109 | for (let key in flashvarsObject) {
110 | const value = flashvarsObject[key];
111 |
112 | if (value) {
113 | if (flashvarsValue) {
114 | flashvarsValue += '&';
115 | }
116 |
117 | flashvarsValue += `${key}=${value}`;
118 | }
119 | }
120 |
121 | setElementAttribute(flashvarsParamElement, 'value', flashvarsValue);
122 |
123 | objectElement.appendChild(movieParamElement);
124 | objectElement.appendChild(flashvarsParamElement);
125 |
126 | if (poster) {
127 | let imageElement = createNewElement(ELEMENT_TYPES.IMAGE);
128 |
129 | setElementAttribute(imageElement, 'alt', 'Video is unavailable.');
130 | setElementAttribute(imageElement, 'height', height);
131 | setElementAttribute(imageElement, 'src', poster);
132 | setElementAttribute(imageElement, 'title', 'We cannot provide playback capabilities at this time.');
133 | setElementAttribute(imageElement, 'width', width);
134 |
135 | objectElement.appendChild(imageElement);
136 | }
137 |
138 | return objectElement;
139 | };
140 |
141 | /**
142 | * build the video element that will be injected onto the page
143 | *
144 | * @param {boolean} autoplay
145 | * @param {boolean} controls
146 | * @param {number} height
147 | * @param {boolean} loop
148 | * @param {boolean} muted
149 | * @param {string} preload
150 | * @param {number} width
151 | * @returns {HTMLElement}
152 | */
153 | const getVideoElement = ({autoplay, controls, height, loop, muted, preload, width}) => {
154 | let videoElement = createNewElement(ELEMENT_TYPES.VIDEO);
155 |
156 | if (autoplay) {
157 | setElementAttribute(videoElement, 'autoplay', '');
158 | }
159 |
160 | if (controls) {
161 | setElementAttribute(videoElement, 'controls', '');
162 | }
163 |
164 | if (loop) {
165 | setElementAttribute(videoElement, 'loop', '');
166 | }
167 |
168 | if (muted) {
169 | setElementAttribute(videoElement, 'muted', '');
170 | }
171 |
172 | setElementAttribute(videoElement, 'height', height);
173 | setElementAttribute(videoElement, 'preload', preload);
174 | setElementAttribute(videoElement, 'width', width);
175 |
176 | return videoElement;
177 | };
178 |
179 | /**
180 | * get the percent loaded if duration is available
181 | *
182 | * @param {HTMLElement} player
183 | * @return {number}
184 | */
185 | const getPercentLoaded = (player) => {
186 | const duration = player.duration;
187 |
188 | if (duration) {
189 | const buffered = player.buffered;
190 | const percentLoaded = buffered.end(0) / duration;
191 |
192 | return Math.round(percentLoaded * 10000) / 100;
193 | }
194 |
195 | return 0;
196 | };
197 |
198 | /**
199 | * convenience function to wrap even with explicit this
200 | * as vidzInstance
201 | *
202 | * @param {Vidz} vidzInstance
203 | * @param {function} method
204 | * @return {function(e): void}
205 | */
206 | const wrapSimpleVideoEvent = (vidzInstance, method) => (e) => {
207 | method.call(vidzInstance, e, vidzInstance);
208 | };
209 |
210 | /**
211 | *
212 | * @param {Vidz} vidzInstance
213 | * @param {object} events
214 | * @param {function} [events.onCanPlayThrough]
215 | * @param {function} [events.onEnded]
216 | * @param {function} [events.onError]
217 | * @param {function} [events.onLoadedMetadata]
218 | * @param {function} [events.onPause]
219 | * @param {function} [events.onPlay]
220 | * @param {function} [events.onProgress]
221 | * @param {function} [events.onWaiting]
222 | */
223 | const setVideoEvents = (vidzInstance, events) => {
224 | const {
225 | onCanPlay,
226 | onCanPlayThrough,
227 | onDurationChange,
228 | onEmptied,
229 | onEnded,
230 | onError,
231 | onLoad,
232 | onLoadedData,
233 | onLoadedMetadata,
234 | onLoadStart,
235 | onPause,
236 | onPlay,
237 | onProgress,
238 | onRateChange,
239 | onSeeked,
240 | onSeeking,
241 | onStalled,
242 | onSuspend,
243 | onTimeUpdate,
244 | onVolumeChange,
245 | onWaiting,
246 | } = events;
247 |
248 | let videoElement = vidzInstance.player;
249 |
250 | if (onCanPlay) {
251 | setElementEventListener(videoElement, 'canplay', wrapSimpleVideoEvent(vidzInstance, onCanPlay));
252 | }
253 |
254 | if (onCanPlayThrough) {
255 | setElementEventListener(videoElement, 'canplaythrough', wrapSimpleVideoEvent(vidzInstance, onCanPlayThrough));
256 | }
257 |
258 | setElementEventListener(videoElement, 'durationchange', (e) => {
259 | vidzInstance.duration = e.target.duration;
260 | vidzInstance.percentLoaded = getPercentLoaded(e.target);
261 |
262 | if (onDurationChange) {
263 | wrapSimpleVideoEvent(vidzInstance, onDurationChange)(e);
264 | }
265 | });
266 |
267 | if (onEmptied) {
268 | setElementEventListener(videoElement, 'emptied', wrapSimpleVideoEvent(vidzInstance, onEmptied));
269 | }
270 |
271 | if (onEnded) {
272 | setElementEventListener(videoElement, 'ended', wrapSimpleVideoEvent(vidzInstance, onEnded));
273 | }
274 |
275 | if (onError) {
276 | setElementEventListener(videoElement, 'error', wrapSimpleVideoEvent(vidzInstance, onError));
277 | }
278 |
279 | if (onLoad) {
280 | setElementEventListener(videoElement, 'load', wrapSimpleVideoEvent(vidzInstance, onLoad));
281 | }
282 |
283 | if (onLoadedData) {
284 | setElementEventListener(videoElement, 'loadeddata', wrapSimpleVideoEvent(vidzInstance, onLoadedData));
285 | }
286 |
287 | if (onLoadedMetadata) {
288 | setElementEventListener(videoElement, 'loadedmetadata', wrapSimpleVideoEvent(vidzInstance, onLoadedMetadata));
289 | }
290 |
291 | if (onLoadStart) {
292 | setElementEventListener(videoElement, 'loadstart', wrapSimpleVideoEvent(vidzInstance, onLoadStart));
293 | }
294 |
295 | if (onPause) {
296 | setElementEventListener(videoElement, 'pause', (e) => {
297 | if (vidzInstance.playing) {
298 | vidzInstance.playing = false;
299 |
300 | wrapSimpleVideoEvent(vidzInstance, onPause)(e);
301 | }
302 | });
303 | }
304 |
305 | if (onPlay) {
306 | setElementEventListener(videoElement, 'playing', (e) => {
307 | if (!vidzInstance.playing) {
308 | vidzInstance.playing = true;
309 |
310 | wrapSimpleVideoEvent(vidzInstance, onPlay)(e);
311 | }
312 | });
313 | }
314 |
315 | setElementEventListener(videoElement, 'progress', (e) => {
316 | vidzInstance.percentLoaded = getPercentLoaded(e.target);
317 |
318 | if (onProgress) {
319 | wrapSimpleVideoEvent(vidzInstance, onProgress)(e);
320 | }
321 | });
322 |
323 | if (onRateChange) {
324 | setElementEventListener(videoElement, 'ratechange', (e) => {
325 | vidzInstance.playbackRate = e.target.playbackRate;
326 |
327 | if (onRateChange) {
328 | wrapSimpleVideoEvent(vidzInstance, onRateChange)(e);
329 | }
330 | });
331 | }
332 |
333 | if (onSeeked) {
334 | setElementEventListener(videoElement, 'seeked', wrapSimpleVideoEvent(vidzInstance, onSeeked));
335 | }
336 |
337 | if (onSeeking) {
338 | setElementEventListener(videoElement, 'seeking', wrapSimpleVideoEvent(vidzInstance, onSeeking));
339 | }
340 |
341 | if (onStalled) {
342 | setElementEventListener(videoElement, 'stalled', wrapSimpleVideoEvent(vidzInstance, onStalled));
343 | }
344 |
345 | if (onSuspend) {
346 | setElementEventListener(videoElement, 'suspend', wrapSimpleVideoEvent(vidzInstance, onSuspend));
347 | }
348 |
349 | setElementEventListener(videoElement, 'timeupdate', (e) => {
350 | vidzInstance.currentTime = e.target.currentTime;
351 |
352 | if (onTimeUpdate) {
353 | wrapSimpleVideoEvent(vidzInstance, onTimeUpdate)(e);
354 | }
355 | });
356 |
357 | setElementEventListener(videoElement, 'volumechange', (e) => {
358 | vidzInstance.volume = e.target.volume;
359 |
360 | if (onVolumeChange) {
361 | wrapSimpleVideoEvent(vidzInstance, onVolumeChange)(e);
362 | }
363 | });
364 |
365 | if (onWaiting) {
366 | setElementEventListener(videoElement, 'waiting', wrapSimpleVideoEvent(vidzInstance, onWaiting));
367 | }
368 | };
369 |
370 | class Vidz {
371 | /**
372 | * build the vidz instance with the appropriate elements, append the
373 | * elements to the parent provided by the selector, and then return
374 | * the instance
375 | *
376 | * @param {string|HTMLElement} selector
377 | * @param {object} config
378 | * @param {object} [config.attributes]
379 | * @param {boolean} [config.autoplay]
380 | * @param {boolean} [config.controls]
381 | * @param {number} [config.height]
382 | * @param {boolean} [config.loop]
383 | * @param {string} [config.mp4]
384 | * @param {boolean} [config.muted]
385 | * @param {string} [config.ogg]
386 | * @param {function} [config.onCanPlay]
387 | * @param {function} [config.onCanPlayThrough]
388 | * @param {function} [config.onDurationChange]
389 | * @param {function} [config.onEmptied]
390 | * @param {function} [config.onEnded]
391 | * @param {function} [config.onError]
392 | * @param {function} [config.onLoad]
393 | * @param {function} [config.onLoadedData]
394 | * @param {function} [config.onLoadedMetadata]
395 | * @param {function} [config.onLoadStart]
396 | * @param {function} [config.onPause]
397 | * @param {function} [config.onPlay]
398 | * @param {function} [config.onProgress]
399 | * @param {function} [config.onRateChange]
400 | * @param {function} [config.onSeeked]
401 | * @param {function} [config.onSeeking]
402 | * @param {function} [config.onStalled]
403 | * @param {function} [config.onSuspend]
404 | * @param {function} [config.onTimeUpdate]
405 | * @param {function} [config.onVolumeChange]
406 | * @param {function} [config.onWaiting]
407 | * @param {string} [config.poster]
408 | * @param {string} [config.preload]
409 | * @param {string} [config.webm]
410 | * @param {number} [config.width]
411 | * @return {Vidz}
412 | */
413 | constructor(selector, config = {}) {
414 | let element;
415 |
416 | switch (true) {
417 | case isElement(selector):
418 | element = selector;
419 | break;
420 |
421 | case isString(selector):
422 | element = document.querySelector(selector);
423 | break;
424 |
425 | case isJqueryObject(selector):
426 | element = selector[0];
427 | break;
428 |
429 | default:
430 | throw new Error('Selector passed must be either a DOM element, jQuery object, or string.');
431 | }
432 |
433 | const {
434 | attributes = {},
435 | autoplay = DEFAULT_ATTRIBUTES.AUTOPLAY,
436 | controls = DEFAULT_ATTRIBUTES.CONTROLS,
437 | height = DEFAULT_ATTRIBUTES.HEIGHT,
438 | loop = DEFAULT_ATTRIBUTES.LOOP,
439 | mp4 = null,
440 | muted = DEFAULT_ATTRIBUTES.MUTED,
441 | ogg = null,
442 | onCanPlay = null,
443 | onCanPlayThrough = null,
444 | onDurationChange = null,
445 | onEmptied = null,
446 | onEnded = null,
447 | onError = null,
448 | onLoad = null,
449 | onLoadedData = null,
450 | onLoadedMetadata = null,
451 | onLoadStart = null,
452 | onPause = null,
453 | onPlay = null,
454 | onProgress = null,
455 | onRateChange = null,
456 | onSeeked = null,
457 | onSeeking = null,
458 | onStalled = null,
459 | onSuspend = null,
460 | onTimeUpdate = null,
461 | onVolumeChange = null,
462 | onWaiting = null,
463 | poster = null,
464 | preload = DEFAULT_ATTRIBUTES.PRELOAD,
465 | swf = null,
466 | webm = null,
467 | width = DEFAULT_ATTRIBUTES.WIDTH,
468 | } = config;
469 |
470 | Object.assign(this, {
471 | attributes,
472 | autoplay,
473 | controls,
474 | height,
475 | loop,
476 | mp4,
477 | muted,
478 | ogg,
479 | onCanPlay,
480 | onCanPlayThrough,
481 | onEmptied,
482 | onEnded,
483 | onError,
484 | onLoad,
485 | onLoadStart,
486 | onLoadedData,
487 | onLoadedMetadata,
488 | onPause,
489 | onPlay,
490 | onProgress,
491 | onRateChange,
492 | onSeeked,
493 | onSeeking,
494 | onStalled,
495 | onSuspend,
496 | onTimeUpdate,
497 | onVolumeChange,
498 | onWaiting,
499 | poster,
500 | preload,
501 | swf,
502 | webm,
503 | width,
504 | });
505 |
506 | this.currentTime = 0;
507 | this.duration = null;
508 | this.element = element;
509 | this.height = height;
510 | this.muted = muted;
511 | this.percentLoaded = 0;
512 | this.playing = autoplay;
513 | this.playbackRate = 1;
514 | this.selector = selector;
515 | this.volume = 1;
516 | this.width = width;
517 |
518 | let videoElement = getVideoElement({
519 | autoplay,
520 | controls,
521 | height,
522 | loop,
523 | muted,
524 | preload,
525 | width,
526 | });
527 |
528 | for (let key in attributes) {
529 | setElementAttribute(videoElement, key, attributes[key]);
530 | }
531 |
532 | if (poster) {
533 | setElementAttribute(videoElement, 'poster', poster);
534 | }
535 |
536 | if (mp4) {
537 | const mp4Element = getSourceElement(mp4, SOURCE_TYPES.MP4);
538 |
539 | videoElement.appendChild(mp4Element);
540 | }
541 |
542 | if (webm) {
543 | const webmElement = getSourceElement(webm, SOURCE_TYPES.WEBM);
544 |
545 | videoElement.appendChild(webmElement);
546 | }
547 |
548 | if (ogg) {
549 | const oggElement = getSourceElement(ogg, SOURCE_TYPES.OGG);
550 |
551 | videoElement.appendChild(oggElement);
552 | }
553 |
554 | if (swf) {
555 | if (!mp4) {
556 | throw new Error('If you want a Flash fallback, you need to provide a video source in mp4 format.');
557 | }
558 |
559 | const flashFallbackElement = getObjectElement({
560 | autoplay,
561 | controls,
562 | height,
563 | mp4,
564 | poster,
565 | swf,
566 | width,
567 | });
568 |
569 | videoElement.appendChild(flashFallbackElement);
570 | }
571 |
572 | this.player = videoElement;
573 | this.supportsHtml5Video = typeof createNewElement(ELEMENT_TYPES.VIDEO).canPlayType !== 'undefined';
574 |
575 | setVideoEvents(this, {
576 | onCanPlay,
577 | onCanPlayThrough,
578 | onDurationChange,
579 | onEmptied,
580 | onEnded,
581 | onError,
582 | onLoad,
583 | onLoadStart,
584 | onLoadedData,
585 | onLoadedMetadata,
586 | onPause,
587 | onPlay,
588 | onProgress,
589 | onRateChange,
590 | onSeeked,
591 | onSeeking,
592 | onStalled,
593 | onSuspend,
594 | onTimeUpdate,
595 | onVolumeChange,
596 | onWaiting,
597 | });
598 |
599 | if (element) {
600 | element.appendChild(videoElement);
601 | }
602 |
603 | return this;
604 | }
605 |
606 | /**
607 | * append the player as a child to the element
608 | *
609 | * @returns {Vidz}
610 | */
611 | add() {
612 | if (this.element) {
613 | this.element.appendChild(this.player);
614 | }
615 |
616 | return this;
617 | }
618 |
619 | /**
620 | * returns whether the player has the ability to play
621 | * the format passed
622 | *
623 | * @param {string} format
624 | * @return {boolean}
625 | */
626 | canPlayType(format) {
627 | return this.player.canPlayType(format);
628 | }
629 |
630 | /**
631 | *
632 | * @return {*|TimeRanges}
633 | */
634 | getBuffered() {
635 | return this.player.buffered;
636 | }
637 |
638 | /**
639 | * return the amount of time that has played in the video
640 | *
641 | * @return {number}
642 | */
643 | getCurrentTime() {
644 | return this.currentTime;
645 | }
646 |
647 | /**
648 | * return the length of the entire video
649 | *
650 | * @return {number}
651 | */
652 | getDuration() {
653 | return this.duration;
654 | }
655 |
656 | /**
657 | * return the flash fallback
658 | *
659 | * @return {HTMLElement}
660 | */
661 | getFlashObject() {
662 | return this.player.querySelector(ELEMENT_TYPES.OBJECT);
663 | }
664 |
665 | /**
666 | * return the % loaded (rounded to two decimals)
667 | *
668 | * @return {number}
669 | */
670 | getPercentLoaded() {
671 | return this.percentLoaded;
672 | }
673 |
674 | /**
675 | * return the playback rate for the video (1 is standard speed)
676 | *
677 | * @return {number}
678 | */
679 | getPlaybackRate() {
680 | return this.player.playbackRate;
681 | }
682 |
683 | /**
684 | * return the player element
685 | *
686 | * @return {HTMLElement}
687 | */
688 | getPlayer() {
689 | return this.player;
690 | }
691 |
692 | /**
693 | * return the dimensions of the element
694 | *
695 | * @return {{height: number, width: number}}
696 | */
697 | getPlayerDimensions() {
698 | return {
699 | height: this.height,
700 | width: this.width,
701 | };
702 | }
703 |
704 | /**
705 | * get the source file locations for each type
706 | *
707 | * @return {{mp4: string, ogg: string, webm: string}}
708 | */
709 | getSource() {
710 | return {
711 | mp4: this.mp4,
712 | ogg: this.ogg,
713 | webm: this.webm,
714 | };
715 | }
716 |
717 | /**
718 | * get the actual dimensions of the video (not the player)
719 | *
720 | * @return {{height: number, width: number}}
721 | */
722 | getVideoDimensions() {
723 | return {
724 | height: this.player.videoHeight,
725 | width: this.player.videoWidth,
726 | };
727 | }
728 |
729 | /**
730 | * return the volume level of the video
731 | *
732 | * @return {number}
733 | */
734 | getVolume() {
735 | return this.player.volume;
736 | }
737 |
738 | /**
739 | * load the player sources
740 | *
741 | * @returns {Vidz}
742 | */
743 | load() {
744 | this.player.load();
745 |
746 | if (this.onLoad) {
747 | this.onLoad(this);
748 | }
749 |
750 | return this;
751 | }
752 |
753 | /**
754 | * set the player to be muted
755 | *
756 | * @return {Vidz}
757 | */
758 | mute() {
759 | if (!this.muted) {
760 | this.player.muted = true;
761 | this.muted = true;
762 | }
763 |
764 | return this;
765 | }
766 |
767 | /**
768 | * pause the player
769 | *
770 | * @returns {Vidz}
771 | */
772 | pause() {
773 | this.player.pause();
774 |
775 | return this;
776 | }
777 |
778 | /**
779 | * start the player
780 | *
781 | * @returns {Vidz}
782 | */
783 | play() {
784 | this.player.play();
785 |
786 | return this;
787 | }
788 |
789 | /**
790 | * remove the player from the parent it was appended to
791 | *
792 | * @returns {Vidz}
793 | */
794 | remove() {
795 | if (this.player.parentNode) {
796 | this.player.parentNode.removeChild(this.player);
797 | }
798 |
799 | return this;
800 | }
801 |
802 | /**
803 | * restart the video from the beginning
804 | *
805 | * @return {Vidz}
806 | */
807 | restart() {
808 | return this.setCurrentTime(0);
809 | }
810 |
811 | /**
812 | * set the place in the video to jump to
813 | *
814 | * @param {number} value
815 | * @return {Vidz}
816 | */
817 | setCurrentTime(value) {
818 | this.player.currentTime = value;
819 | this.currentTime = value;
820 |
821 | return this;
822 | }
823 |
824 | /**
825 | * set the playback rate to a value, capping between 0.25 and 16
826 | *
827 | * @param {number} value=1
828 | * @return {Vidz}
829 | */
830 | setPlaybackRate(value = 1) {
831 | let validValue = value;
832 |
833 | if (value <= 0.25) {
834 | validValue = 0.25;
835 | } else if (value >= 16) {
836 | validValue = 16;
837 | }
838 |
839 | this.player.playbackRate = validValue;
840 | this.playbackRate = validValue;
841 |
842 | return this;
843 | }
844 |
845 | /**
846 | * set new height / width values for the player and instance
847 | *
848 | * @param {number} height
849 | * @param {number} width
850 | * @return {Vidz}
851 | */
852 | setPlayerDimensions({height, width}) {
853 | if (!isUndefined(height)) {
854 | setElementAttribute(this.player, 'height', height);
855 |
856 | this.height = height;
857 | }
858 |
859 | if (!isUndefined(width)) {
860 | setElementAttribute(this.player, 'width', width);
861 |
862 | this.width = width;
863 | }
864 |
865 | return this;
866 | }
867 |
868 | /**
869 | * set the source to the new value and reload it
870 | *
871 | * @param {string} mp4
872 | * @param {string} ogg
873 | * @param {string} webm
874 | * @return {Vidz}
875 | */
876 | setSource({mp4, ogg, webm}) {
877 | const sources = this.player.querySelectorAll('source');
878 | const length = sources.length;
879 |
880 | let index = -1;
881 |
882 | while (++index < length) {
883 | let source = sources[index];
884 |
885 | switch (source.type) {
886 | case SOURCE_TYPES.MP4:
887 | if (mp4) {
888 | setElementAttribute(source, 'src', mp4);
889 | this.mp4 = mp4;
890 | }
891 |
892 | break;
893 |
894 | case SOURCE_TYPES.OGG:
895 | if (ogg) {
896 | setElementAttribute(source, 'src', ogg);
897 | this.ogg = ogg;
898 | }
899 |
900 | break;
901 |
902 | case SOURCE_TYPES.WEBM:
903 | if (webm) {
904 | setElementAttribute(source, 'src', webm);
905 | this.webm = webm;
906 | }
907 |
908 | break;
909 | }
910 | }
911 |
912 | if (mp4) {
913 | const currentObjectElement = this.player.querySelector('object');
914 | const newObjectElement = getObjectElement({
915 | autoplay: this.autoplay,
916 | controls: this.controls,
917 | height: this.height,
918 | mp4,
919 | poster: this.poster,
920 | swf: this.swf,
921 | width: this.width,
922 | });
923 |
924 | this.player.removeChild(currentObjectElement);
925 | this.player.appendChild(newObjectElement);
926 | }
927 |
928 | return this.load();
929 | }
930 |
931 | /**
932 | * set the volume to a number between 0 and 1
933 | *
934 | * @param {number} value=1
935 | * @return {Vidz}
936 | */
937 | setVolume(value = 1) {
938 | let volume = value;
939 |
940 | if (value < 0) {
941 | volume = 0;
942 | } else if (value > 1) {
943 | volume = 1;
944 | }
945 |
946 | this.player.volume = volume;
947 | this.volume = volume;
948 |
949 | return this;
950 | }
951 |
952 | /**
953 | * set the player to be unmuted
954 | *
955 | * @return {Vidz}
956 | */
957 | unmute() {
958 | if (this.muted) {
959 | this.player.muted = false;
960 | this.muted = false;
961 | }
962 |
963 | return this;
964 | }
965 | }
966 |
967 | /**
968 | * convenience function, so devs don't need to run new Vidz() every time
969 | *
970 | * @param {string} selector
971 | * @param {object} config
972 | * @return {Vidz}
973 | */
974 | const vidz = (selector, config) => new Vidz(selector, config);
975 |
976 | export {getObjectElement};
977 | export {getSourceElement};
978 | export {getVideoElement};
979 | export {setElementAttribute};
980 | export {setVideoEvents};
981 | export {Vidz};
982 |
983 | export default vidz;
984 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * return string form of object type
3 | *
4 | * @param {any} object
5 | * @return {string}
6 | */
7 | const toString = (object) => Object.prototype.toString.call(object);
8 |
9 | /**
10 | * create a new element and return it
11 | *
12 | * @param {string} element
13 | * @return {HTMLElement}
14 | */
15 | const createNewElement = (element) => document.createElement(element);
16 |
17 | /**
18 | * determine if the object is an HTMLElement
19 | *
20 | * @param {any} object
21 | * @return {boolean}
22 | */
23 | const isElement = (object) =>
24 | typeof HTMLElement === 'object'
25 | ? object instanceof HTMLElement
26 | : !!object
27 | && typeof object === 'object'
28 | && object !== null
29 | && object.nodeType === 1
30 | && typeof object.nodeName === 'string';
31 |
32 | /**
33 | * determine if the object is a jQuery object
34 | *
35 | * @param {any} object
36 | * @return {boolean}
37 | */
38 | const isJqueryObject = (object) => 'jquery' in Object(object);
39 |
40 | /**
41 | * determine if object is a string
42 | *
43 | * @param {any} object
44 | * @return {boolean}
45 | */
46 | const isString = (object) => toString(object) === '[object String]';
47 |
48 | /**
49 | * determine if object is undefined
50 | *
51 | * @param {any} object
52 | * @return {boolean}
53 | */
54 | const isUndefined = (object) => object === void 0;
55 |
56 | export {createNewElement};
57 | export {isElement};
58 | export {isJqueryObject};
59 | export {isString};
60 | export {isUndefined};
61 | export {toString};
62 |
63 | export default {
64 | createNewElement,
65 | isElement,
66 | isString,
67 | isUndefined,
68 | toString,
69 | };
70 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import sinon from 'sinon';
3 |
4 | import vidz, {
5 | getObjectElement,
6 | getSourceElement,
7 | getVideoElement,
8 | setElementAttribute,
9 | setVideoEvents,
10 | Vidz,
11 | } from '../src/index';
12 |
13 | import {
14 | createNewElement,
15 | isElement,
16 | } from '../src/utils';
17 |
18 | const sleep = (ms = 0) =>
19 | new Promise((resolve) => {
20 | setTimeout(() => {
21 | resolve();
22 | }, ms);
23 | });
24 |
25 | test('if vidz creates a new Vidz instance', (t) => {
26 | const instance = vidz('#some-selector');
27 |
28 | t.true(instance instanceof Vidz);
29 | });
30 |
31 | test('if getObjectElement returns an object element with params children', (t) => {
32 | const objectElement = getObjectElement({
33 | autoplay: true,
34 | controls: true,
35 | height: 400,
36 | mp4: 'test.mp4',
37 | poster: 'test.jpg',
38 | swf: 'test.swf',
39 | width: 600,
40 | });
41 |
42 | const expectedHtml =
43 | ' ';
44 |
45 | const div = createNewElement('div');
46 |
47 | div.appendChild(objectElement);
48 |
49 | t.is(div.innerHTML, expectedHtml);
50 | });
51 |
52 | test('if getSourceElement returns a source element with appropriate attributes', (t) => {
53 | const sourceElement = getSourceElement('test.mp4', 'video/mp4');
54 | const expectedContents = '';
55 |
56 | const div = createNewElement('div');
57 |
58 | div.appendChild(sourceElement);
59 |
60 | t.is(div.innerHTML, expectedContents);
61 | });
62 |
63 | test('if getVideoElement returns a video element with appropriate children and attributes', (t) => {
64 | const videoElement = getVideoElement({
65 | autoplay: true,
66 | controls: true,
67 | height: 600,
68 | loop: true,
69 | muted: true,
70 | preload: 'auto',
71 | width: 800,
72 | });
73 | const expectedContents =
74 | ' ';
75 |
76 | const div = createNewElement('div');
77 |
78 | div.appendChild(videoElement);
79 |
80 | t.is(div.innerHTML, expectedContents);
81 | });
82 |
83 | test("if setElementAttribute sets an element's attribute correctly", (t) => {
84 | const div = createNewElement('div');
85 | const attributeValue = 'test-attribute-setting';
86 |
87 | setElementAttribute(div, 'id', attributeValue);
88 |
89 | t.is(div.id, attributeValue);
90 | });
91 |
92 | test.skip('if events are bound to player instance', async (t) => {
93 | let onPlayFired = false;
94 |
95 | const div = createNewElement('div');
96 |
97 | document.body.appendChild(div);
98 |
99 | const instance = vidz(div, {
100 | mp4: 'test.mp4',
101 | onPlay() {
102 | console.log('fired');
103 |
104 | onPlayFired = true;
105 | },
106 | });
107 |
108 | instance.play();
109 |
110 | await sleep(1000);
111 |
112 | t.true(onPlayFired);
113 | });
114 |
115 | test('Vidz prototypical methods', (t) => {
116 | const div = createNewElement('div');
117 |
118 | const instance = vidz(div, {
119 | mp4: 'test.mp4',
120 | ogg: 'test.ogv',
121 | swf: 'test.swf',
122 | });
123 |
124 | t.true(isElement(instance.player));
125 |
126 | const instanceHtml =
127 | ' ';
128 |
129 | instance.remove();
130 |
131 | t.is(div.innerHTML, '');
132 |
133 | instance.add();
134 |
135 | t.is(div.innerHTML, instanceHtml);
136 | t.is(instance.getCurrentTime(), 0);
137 | t.is(instance.getFlashObject(), instance.player.querySelector('object'));
138 | t.is(instance.getPlaybackRate(), 1);
139 | t.is(instance.getPlayer(), instance.player);
140 | t.deepEqual(instance.getPlayerDimensions(), {
141 | height: 400,
142 | width: 600,
143 | });
144 | t.deepEqual(instance.getSource(), {
145 | mp4: 'test.mp4',
146 | ogg: 'test.ogv',
147 | webm: null,
148 | });
149 | t.is(instance.getVolume(), 1);
150 |
151 | // dimensions are 0 because the file doesn't exist
152 | t.deepEqual(instance.getVideoDimensions(), {
153 | height: 0,
154 | width: 0,
155 | });
156 |
157 | t.is(instance.getVolume(), 1);
158 |
159 | const loadSpy = sinon.spy(instance, 'load');
160 | const playSpy = sinon.spy(instance, 'play');
161 | const pauseSpy = sinon.spy(instance, 'pause');
162 |
163 | instance.load();
164 | instance.play();
165 | instance.pause();
166 |
167 | t.true(loadSpy.calledOnce);
168 | t.true(playSpy.calledOnce);
169 | t.true(pauseSpy.calledOnce);
170 |
171 | loadSpy.restore();
172 | playSpy.restore();
173 | pauseSpy.restore();
174 |
175 | instance.setPlayerDimensions({
176 | height: 320,
177 | width: 600,
178 | });
179 |
180 | t.deepEqual(instance.getPlayerDimensions(), {
181 | height: 320,
182 | width: 600,
183 | });
184 |
185 | instance.setSource({
186 | mp4: 'test2.mp4',
187 | });
188 |
189 | const newInstanceHtml =
190 | ' ';
191 |
192 | const anotherDiv = createNewElement('div');
193 |
194 | anotherDiv.appendChild(instance.player);
195 |
196 | t.is(anotherDiv.innerHTML, newInstanceHtml);
197 | });
198 |
--------------------------------------------------------------------------------
/test/setup-browser-environment.js:
--------------------------------------------------------------------------------
1 | import jsdom from 'jsdom';
2 |
3 | global.document = jsdom.jsdom('');
4 | global.window = document.defaultView;
5 | global.navigator = window.navigator;
6 |
--------------------------------------------------------------------------------
/test/utils.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 |
3 | import $ from 'jquery';
4 |
5 | import {
6 | createNewElement,
7 | isElement,
8 | isJqueryObject,
9 | isString,
10 | isUndefined,
11 | toString,
12 | } from '../src/utils';
13 |
14 | const ARRAY_TOSTRING_VALUE = '[object Array]';
15 | const OBJECT_TOSTRING_VALUE = '[object Object]';
16 | const STRING_TOSTRING_VALUE = '[object String]';
17 |
18 | let div;
19 |
20 | test('if createNewElement successfully creates an HTMLElement', (t) => {
21 | div = createNewElement('div');
22 |
23 | t.is(div.nodeType, 1);
24 | });
25 |
26 | test('if isElement validates that the div is an HTMLElement but no other object is', (t) => {
27 | t.true(isElement(div));
28 | t.false(isElement('div'));
29 | t.false(isElement(true));
30 | t.false(isElement(undefined));
31 | t.false(isElement(null));
32 | t.false(isElement(1));
33 | t.false(isElement({}));
34 | t.false(isElement([]));
35 | t.false(isElement($('
')));
36 | });
37 |
38 | test('if isJqueryObject validates that the jQuery-built div is a jQuery object but no other object is', (t) => {
39 | t.false(isJqueryObject(div));
40 | t.false(isJqueryObject('div'));
41 | t.false(isJqueryObject(true));
42 | t.false(isJqueryObject(undefined));
43 | t.false(isJqueryObject(null));
44 | t.false(isJqueryObject(1));
45 | t.false(isJqueryObject({}));
46 | t.true(isJqueryObject($('
')));
47 | });
48 |
49 | test('if isString validates that the string is a string but no other object is', (t) => {
50 | t.false(isString(div));
51 | t.true(isString('div'));
52 | t.false(isString(true));
53 | t.false(isString(undefined));
54 | t.false(isString(null));
55 | t.false(isString(1));
56 | t.false(isString({}));
57 | t.false(isString($('
')));
58 | });
59 |
60 | test('if isUndefined validates the undefined value as undefined but no other object is', (t) => {
61 | t.false(isUndefined(div));
62 | t.false(isUndefined('div'));
63 | t.false(isUndefined(true));
64 | t.true(isUndefined(undefined));
65 | t.false(isUndefined(null));
66 | t.false(isUndefined(1));
67 | t.false(isUndefined({}));
68 | t.false(isUndefined($('
')));
69 | });
70 |
71 | test('if toString returns the correct values', (t) => {
72 | const string = toString('test');
73 | const object = toString({});
74 | const array = toString([]);
75 |
76 | t.is(array, ARRAY_TOSTRING_VALUE);
77 | t.is(object, OBJECT_TOSTRING_VALUE);
78 | t.is(string, STRING_TOSTRING_VALUE);
79 | });
80 |
--------------------------------------------------------------------------------
/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const HtmlWebpackPlugin = require('html-webpack-plugin');
5 |
6 | const defaultConfig = require('./webpack.config');
7 |
8 | const PORT = 3000;
9 | const ROOT = path.join(__dirname, '..');
10 |
11 | module.exports = Object.assign({}, defaultConfig, {
12 | devServer: {
13 | compress: true,
14 | contentBase: './dist',
15 | host: 'localhost',
16 | port: PORT
17 | },
18 |
19 | entry: [path.join(ROOT, 'DEV_ONLY', 'App.js')],
20 |
21 | externals: undefined,
22 |
23 | module: Object.assign({}, defaultConfig.module, {
24 | rules: defaultConfig.module.rules.map((rule) => {
25 | if (rule.loader !== 'babel-loader') {
26 | return rule;
27 | }
28 |
29 | return Object.assign({}, rule, {
30 | include: rule.include.concat([path.join(ROOT, 'DEV_ONLY')])
31 | });
32 | })
33 | }),
34 |
35 | output: Object.assign({}, defaultConfig.output, {
36 | publicPath: `http://localhost:${PORT}/`
37 | }),
38 |
39 | plugins: defaultConfig.plugins.concat([new HtmlWebpackPlugin()])
40 | });
41 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const webpack = require('webpack');
5 |
6 | module.exports = {
7 | devtool: '#source-map',
8 |
9 | entry: [path.resolve(__dirname, 'src', 'index.js')],
10 |
11 | mode: 'development',
12 |
13 | module: {
14 | rules: [
15 | {
16 | enforce: 'pre',
17 | include: [path.resolve(__dirname, 'src')],
18 | loader: 'eslint-loader',
19 | options: {
20 | configFile: '.eslintrc',
21 | emitError: true,
22 | failOnError: true,
23 | failOnWarning: true,
24 | formatter: require('eslint-friendly-formatter')
25 | },
26 | test: /\.js$/
27 | },
28 | {
29 | include: [path.resolve(__dirname, 'src')],
30 | loader: 'babel-loader',
31 | test: /\.js$/
32 | }
33 | ]
34 | },
35 |
36 | output: {
37 | filename: 'vidz.js',
38 | library: 'vidz',
39 | libraryTarget: 'umd',
40 | path: path.resolve(__dirname, 'dist'),
41 | umdNamedDefine: true
42 | },
43 |
44 | plugins: [new webpack.EnvironmentPlugin(['NODE_ENV'])]
45 | };
46 |
--------------------------------------------------------------------------------
/webpack.config.minified.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const webpack = require('webpack');
5 | const defaultConfig = require('./webpack.config');
6 |
7 | module.exports = Object.assign({}, defaultConfig, {
8 | devtool: undefined,
9 |
10 | mode: 'production',
11 |
12 | output: Object.assign({}, defaultConfig.output, {
13 | filename: 'vidz.min.js'
14 | })
15 | });
16 |
--------------------------------------------------------------------------------