├── docs └── api.md ├── .npmignore ├── .gitignore ├── scripts ├── banner.ejs ├── npm-postversion-for-bower.sh ├── npm-preversion-for-bower.sh ├── npm-version-for-bower.sh └── server.js ├── test ├── karma │ ├── ie.js │ ├── chrome.js │ ├── firefox.js │ ├── safari.js │ ├── detected.js │ └── common.js ├── index.html ├── dailymotion.test.js ├── player-proxy.js └── plugin.test.js ├── .travis.yml ├── src ├── plugin.js ├── videojs-dailymotion.js └── dailymotion.js ├── bower.json ├── .editorconfig ├── .jshintrc ├── es5 ├── plugin.js ├── dailymotion.js └── videojs-dailymotion.js ├── index.html ├── README.md ├── package.json └── dist-test └── videojs-dailymotion.js /docs/api.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Exclude everything but the contents of the src and dist directory. 2 | **/* 3 | !dist/** 4 | !src/** -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | dist 4 | 5 | node_modules 6 | bower_components 7 | npm-debug.log 8 | 9 | mongoose*.exe 10 | 11 | *.orig 12 | 13 | *.log -------------------------------------------------------------------------------- /scripts/banner.ejs: -------------------------------------------------------------------------------- 1 | /** 2 | * <%- pkg.name %> 3 | * @version <%- pkg.version %> 4 | * @copyright <%- date.getFullYear() %> <%- pkg.author %> 5 | * @license <%- pkg.license %> 6 | */ 7 | -------------------------------------------------------------------------------- /test/karma/ie.js: -------------------------------------------------------------------------------- 1 | var common = require('./common'); 2 | 3 | module.exports = function(config) { 4 | config.set(common({ 5 | plugins: ['karma-ie-launcher'], 6 | browsers: ['IE'] 7 | })); 8 | }; 9 | -------------------------------------------------------------------------------- /test/karma/chrome.js: -------------------------------------------------------------------------------- 1 | var common = require('./common'); 2 | 3 | module.exports = function(config) { 4 | config.set(common({ 5 | plugins: ['karma-chrome-launcher'], 6 | browsers: ['Chrome'] 7 | })); 8 | }; 9 | -------------------------------------------------------------------------------- /test/karma/firefox.js: -------------------------------------------------------------------------------- 1 | var common = require('./common'); 2 | 3 | module.exports = function(config) { 4 | config.set(common({ 5 | plugins: ['karma-firefox-launcher'], 6 | browsers: ['Firefox'] 7 | })); 8 | }; 9 | -------------------------------------------------------------------------------- /test/karma/safari.js: -------------------------------------------------------------------------------- 1 | var common = require('./common'); 2 | 3 | module.exports = function(config) { 4 | config.set(common({ 5 | plugins: ['karma-safari-launcher'], 6 | browsers: ['Safari'] 7 | })); 8 | }; 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4.2.4" 4 | before_script: 5 | - if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then curl https://gist.githubusercontent.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash; fi 6 | script: npm run build 7 | 8 | -------------------------------------------------------------------------------- /src/plugin.js: -------------------------------------------------------------------------------- 1 | import videojs from 'video.js'; 2 | import chromecast from './videojs-dailymotion'; 3 | 4 | /** 5 | * The video.js Dailymotion plugin. 6 | * 7 | * @param {Object} options 8 | */ 9 | const plugin = function (options) { 10 | dailymotion(this, options); 11 | }; 12 | 13 | videojs.plugin('dailymotion', plugin); 14 | 15 | export default plugin; 16 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "videojs-dailymotion", 3 | "description": "Dailymotion playback technology for Video.js", 4 | "version": "2.0.0", 5 | "main": [ 6 | "dist/videojs-dailymotion.js" 7 | ], 8 | "ignore": [ 9 | "examples", 10 | "sandbox", 11 | "test", 12 | ".editorconfig", 13 | ".gitignore", 14 | ".jshintrc", 15 | ".travis.yml", 16 | "bower.json", 17 | "package.json", 18 | "README.md" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /scripts/npm-postversion-for-bower.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd $( cd "$( dirname "$( dirname "${BASH_SOURCE[0]}" )" )" && pwd ) 4 | 5 | VERSION="$(node -p "require('./package.json').version")" 6 | 7 | if [ -d "./.git" ]; then 8 | ORIGIN=`git remote | grep "^origin$"`; 9 | 10 | if [ "$ORIGIN" != "" ]; then 11 | git reset --hard origin/master 12 | git push origin --tags 13 | fi 14 | 15 | echo "Finished version bump to v$VERSION!" 16 | fi 17 | -------------------------------------------------------------------------------- /scripts/npm-preversion-for-bower.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd $( cd "$( dirname "$( dirname "${BASH_SOURCE[0]}" )" )" && pwd ) 4 | 5 | if [ -d "./.git" ]; then 6 | BRANCH=`git rev-parse --abbrev-ref HEAD` 7 | 8 | if [ "$BRANCH" != "master" ]; then 9 | echo "The current branch should be 'master'; please checkout 'master' before versioning." 10 | exit 1 11 | else 12 | npm test 13 | fi 14 | else 15 | echo "This plugin project is not a Git repository; skipping versioning scripts." 16 | exit 1 17 | fi 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | 23 | [*.coffee] 24 | indent_style = space 25 | indent_size = 2 -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | videojs-dailymotion Unit Tests 6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/dailymotion.test.js: -------------------------------------------------------------------------------- 1 | import window from 'global/window'; 2 | import QUnit from 'qunit'; 3 | import chromecastMaker from '../src/videojs-dailymotion'; 4 | import playerProxy from './player-proxy'; 5 | 6 | QUnit.module('dailymotion', { 7 | 8 | beforeEach() { 9 | this.oldTimeout = window.setTimeout; 10 | window.setTimeout = Function.prototype; 11 | }, 12 | 13 | afterEach() { 14 | window.setTimeout = this.oldTimeout; 15 | } 16 | }); 17 | 18 | QUnit.test( 19 | 'chromecastMaker takes a player and returns a dailymotion plugin', 20 | function (assert) { 21 | let chromecast = chromecastMaker(playerProxy(), {}); 22 | 23 | assert.equal(typeof chromecast, 'object', 'dailymotion is an object'); 24 | } 25 | ); 26 | -------------------------------------------------------------------------------- /test/player-proxy.js: -------------------------------------------------------------------------------- 1 | import extend from 'node.extend'; 2 | import videojs from 'video.js'; 3 | 4 | const proxy = (props) => { 5 | let player = extend(true, {}, videojs.EventTarget.prototype, { 6 | play: Function.prototype, 7 | paused: Function.prototype, 8 | ended: Function.prototype, 9 | poster: Function.prototype, 10 | src: Function.prototype, 11 | addRemoteTextTrack: Function.prototype, 12 | removeRemoteTextTrack: Function.prototype, 13 | remoteTextTracks: Function.prototype, 14 | currentSrc: Function.prototype, 15 | dailymotion: {} 16 | }, props); 17 | 18 | player.constructor = videojs.getComponent('Player'); 19 | player.chromecast.player_ = player; 20 | 21 | return player; 22 | }; 23 | 24 | export default proxy; 25 | -------------------------------------------------------------------------------- /scripts/npm-version-for-bower.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd $( cd "$( dirname "$( dirname "${BASH_SOURCE[0]}" )" )" && pwd ) 4 | 5 | VERSION="$(node -p "require('./package.json').version")" 6 | 7 | if [ -d "./.git" ]; then 8 | ORIGIN=`git remote | grep "^origin$"`; 9 | 10 | # Commit package.json with a new version and push it. 11 | git add package.json 12 | git commit -m "$VERSION" 13 | 14 | if [ "$ORIGIN" != "" ]; then 15 | git push origin master 16 | else 17 | echo "No 'origin' remote was found, so pushing will be skipped!" 18 | fi 19 | 20 | # Build the plugin and force-add dist/ so that npm's commit picks that up 21 | # instead of the package.json change. This is what should be tagged! 22 | npm run build 23 | git add -f dist 24 | fi 25 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "camelcase": true, 3 | "indent": 2, 4 | //"maxlen" : 120, 5 | "trailing": true, 6 | "bitwise": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "forin": true, 10 | "noarg": true, 11 | "noempty": true, 12 | "nonew": true, 13 | "undef": true, 14 | "unused": true, 15 | "devel": true, 16 | "node": false, 17 | "sub": true, 18 | "quotmark": "single", 19 | "predef": [ 20 | // standard 21 | "navigator", 22 | "document", 23 | "window", 24 | "console", 25 | "alert", 26 | "setTimeout", 27 | "toString", 28 | "isNaN", 29 | // mocha 30 | "describe", 31 | "it", 32 | "before", 33 | "beforeEach", 34 | "after", 35 | "afterEach", 36 | // video.js 37 | "videojs" 38 | ] 39 | } 40 | 41 | -------------------------------------------------------------------------------- /test/plugin.test.js: -------------------------------------------------------------------------------- 1 | import QUnit from 'qunit'; 2 | import sinon from 'sinon'; 3 | import videojs from 'video.js'; 4 | import plugin from '../src/plugin'; 5 | 6 | QUnit.test('the environment is sane', function (assert) { 7 | assert.strictEqual(typeof Array.isArray, 'function', 'es5 exists'); 8 | assert.strictEqual(typeof sinon, 'object', 'sinon exists'); 9 | assert.strictEqual(typeof videojs, 'function', 'videojs exists'); 10 | assert.strictEqual(typeof plugin, 'function', 'plugin is a function'); 11 | }); 12 | 13 | QUnit.test('registers itself with video.js', function (assert) { 14 | assert.expect(1); 15 | assert.strictEqual( 16 | videojs.getComponent('Player').prototype.dailymotion, 17 | plugin, 18 | 'videojs-dailymotion plugin was registered' 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /es5/plugin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | 7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8 | 9 | var _videoJs = require('video.js'); 10 | 11 | var _videoJs2 = _interopRequireDefault(_videoJs); 12 | 13 | var _videojsDailymotion = require('./videojs-dailymotion'); 14 | 15 | var _videojsDailymotion2 = _interopRequireDefault(_videojsDailymotion); 16 | 17 | /** 18 | * The video.js Dailymotion plugin. 19 | * 20 | * @param {Object} options 21 | */ 22 | var plugin = function plugin(options) { 23 | dailymotion(this, options); 24 | }; 25 | 26 | _videoJs2['default'].plugin('dailymotion', plugin); 27 | 28 | exports['default'] = plugin; 29 | module.exports = exports['default']; -------------------------------------------------------------------------------- /test/karma/detected.js: -------------------------------------------------------------------------------- 1 | var common = require('./common'); 2 | 3 | // Runs default testing configuration in multiple environments. 4 | 5 | module.exports = function(config) { 6 | 7 | // Travis CI should run in its available Firefox headless browser. 8 | if (process.env.TRAVIS) { 9 | 10 | config.set(common({ 11 | browsers: ['Firefox'], 12 | plugins: ['karma-firefox-launcher'] 13 | })) 14 | } else { 15 | config.set(common({ 16 | 17 | frameworks: ['detectBrowsers'], 18 | 19 | plugins: [ 20 | 'karma-chrome-launcher', 21 | 'karma-detect-browsers', 22 | 'karma-firefox-launcher', 23 | 'karma-ie-launcher', 24 | 'karma-safari-launcher' 25 | ], 26 | 27 | detectBrowsers: { 28 | usePhantomJS: false 29 | } 30 | })); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /scripts/server.js: -------------------------------------------------------------------------------- 1 | import connect from 'connect'; 2 | import cowsay from 'cowsay'; 3 | import path from 'path'; 4 | import portscanner from 'portscanner'; 5 | import serveStatic from 'serve-static'; 6 | 7 | // Configuration for the server. 8 | const PORT = 9999; 9 | const MAX_PORT = PORT + 100; 10 | const HOST = '127.0.0.1'; 11 | 12 | const app = connect(); 13 | 14 | const verbs = [ 15 | 'Chewing the cud', 16 | 'Grazing', 17 | 'Mooing', 18 | 'Lowing', 19 | 'Churning the cream' 20 | ]; 21 | 22 | app.use(serveStatic(path.join(__dirname, '..'))); 23 | 24 | portscanner.findAPortNotInUse(PORT, MAX_PORT, HOST, (error, port) => { 25 | if (error) { 26 | throw error; 27 | } 28 | 29 | process.stdout.write(cowsay.say({ 30 | text: `${verbs[Math.floor(Math.random() * 5)]} on ${HOST}:${port}` 31 | }) + '\n\n'); 32 | 33 | app.listen(port); 34 | }); 35 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | videojs-dailymotion Demo 6 | 7 | 8 | 9 | 10 | 11 | 15 | 18 | 19 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /test/karma/common.js: -------------------------------------------------------------------------------- 1 | var merge = require('lodash-compat/object/merge'); 2 | 3 | var DEFAULTS = { 4 | basePath: '../..', 5 | frameworks: ['browserify', 'qunit'], 6 | 7 | files: [ 8 | 'node_modules/sinon/pkg/sinon.js', 9 | 'node_modules/sinon/pkg/sinon-ie.js', 10 | 'node_modules/video.js/dist/video.js', 11 | 'test/**/*.js' 12 | ], 13 | 14 | exclude: [ 15 | 'test/bundle.js' 16 | ], 17 | 18 | plugins: [ 19 | 'karma-browserify', 20 | 'karma-qunit' 21 | ], 22 | 23 | preprocessors: { 24 | 'test/**/*.js': ['browserify'] 25 | }, 26 | 27 | reporters: ['dots'], 28 | port: 9876, 29 | colors: true, 30 | autoWatch: false, 31 | singleRun: true, 32 | concurrency: Infinity, 33 | 34 | browserify: { 35 | transform: [ 36 | 'babelify', 37 | 'browserify-shim' 38 | ] 39 | } 40 | }; 41 | 42 | /** 43 | * Customizes target/source merging with lodash merge. 44 | * 45 | * @param {Mixed} target 46 | * @param {Mixed} source 47 | * @return {Mixed} 48 | */ 49 | var customizer = function(target, source) { 50 | if (Array.isArray(target)) { 51 | return target.concat(source); 52 | } 53 | }; 54 | 55 | /** 56 | * Generates a new Karma config with a common set of base configuration. 57 | * 58 | * @param {Object} custom 59 | * Configuration that will be deep-merged. Arrays will be 60 | * concatenated. 61 | * @return {Object} 62 | */ 63 | module.exports = function(custom) { 64 | return merge({}, custom, DEFAULTS, customizer); 65 | }; 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* 4 | 5 | - [Video.js - Dailymotion Source Support](#videojs---dailymotion-source-support) 6 | - [How does it work?](#how-does-it-work) 7 | - [Additional Informations](#additional-informations) 8 | - [Special Thank You](#special-thank-you) 9 | 10 | 11 | 12 | # Video.js - Dailymotion Source Support 13 | Allows you to use Dailymotion URL as source with [Video.js](https://github.com/zencoder/video-js/). 14 | 15 | ## How does it work? 16 | Including the script vjs.dailymotion.js will add the Dailymotion as a tech. You just have to add it to your techOrder option. Then, you add the option src with your Dailymotion URL. 17 | 18 | It supports: 19 | - dailymotion.com/ 20 | - Regular URLs: http://www.dailymotion.com/video/xxxasl_fail-compilation-february-2013-tnl_fun 21 | 22 | **You must use the last version of VideoJS available in the folder lib, the current version on CDN will not work until it is updated** 23 | 24 | Here is an example: 25 | 26 | 27 | 28 | 29 | 30 | 31 | ## Additional Informations 32 | dmControls: Display the Dailymotion controls instead of Video.js. 33 | 34 | ##Special Thank You 35 | Thanks to Benoit Tremblay for the original code https://github.com/eXon/videojs-youtube 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "videojs-dailymotion", 3 | "version": "2.0.0", 4 | "description": "Dailymotion playback technology for Video.js", 5 | "main": "es5/plugin.js", 6 | "scripts": { 7 | "prebuild": "npm run clean", 8 | "build": "npm-run-all -p build:*", 9 | "build:js": "npm-run-all mkdirs build:js:babel build:js:browserify build:js:bannerize build:js:uglify", 10 | "build:js:babel": "babel src -d es5", 11 | "build:js:bannerize": "bannerize dist/videojs-dailymotion.js --banner=scripts/banner.ejs", 12 | "build:js:browserify": "browserify . -s videojs-dailymotion -o dist/videojs-dailymotion.js", 13 | "build:js:uglify": "uglifyjs dist/videojs-dailymotion.js --comments --mangle --compress -o dist/videojs-dailymotion.min.js", 14 | "build:test": "npm-run-all mkdirs build:test:browserify", 15 | "build:test:browserify": "browserify `find test -name '*.test.js'` -t babelify -o dist-test/videojs-dailymotion.js", 16 | "copy:font": "cp -R src/fonts dist/fonts", 17 | "copy": "npm-run-all -p copy:*", 18 | "clean": "rm -rf dist dist-test es5", 19 | "docs": "doctoc README.md docs/api.md", 20 | "lint": "vjsstandard", 21 | "mkdirs": "mkdir -p dist dist-test es5", 22 | "prepublish": "npm run build", 23 | "prestart": "npm-run-all -p docs build", 24 | "dev": "npm-run-all -p start watch", 25 | "start": "npm-run-all -p start:serve", 26 | "start:serve": "babel-node --optional es7.functionBind,es7.classProperties,es7.decorators scripts/server.js", 27 | "pretest": "npm-run-all build:test", 28 | "test": "karma start --single-run test/karma/detected.js", 29 | "test:chrome": "npm run pretest && karma start test/karma/chrome.js", 30 | "test:firefox": "npm run pretest && karma start test/karma/firefox.js", 31 | "test:ie": "npm run pretest && karma start test/karma/ie.js", 32 | "test:safari": "npm run pretest && karma start test/karma/safari.js", 33 | "preversion": "./scripts/npm-preversion-for-bower.sh", 34 | "version": "./scripts/npm-version-for-bower.sh", 35 | "postversion": "./scripts/npm-postversion-for-bower.sh", 36 | "watch": "npm run mkdirs && npm-run-all -p watch:*", 37 | "watch:js": "watchify src/plugin.js -t babelify -v -o dist/videojs-dailymotion.js", 38 | "watch:test": "watchify `find test -name '*.test.js'` -t babelify -o dist-test/videojs-dailymotion.js" 39 | }, 40 | "keywords": [ 41 | "dailymotion", 42 | "videojs", 43 | "videojs-plugin" 44 | ], 45 | "author": "Benjipott, Inc.", 46 | "license": "Apache-2.0", 47 | "repository": { 48 | "type": "git", 49 | "url": "https://github.com/benjipott/video.js-dailymotion" 50 | }, 51 | "files": [ 52 | "CONTRIBUTING.md", 53 | "bower.json", 54 | "dist-test/", 55 | "dist/", 56 | "docs/", 57 | "es5/", 58 | "index.html", 59 | "scripts/", 60 | "src/", 61 | "test/" 62 | ], 63 | "babel": { 64 | "optional": [ 65 | "es7.functionBind", 66 | "es7.classProperties", 67 | "es7.decorators" 68 | ] 69 | }, 70 | "devDependencies": { 71 | "babel": "^5.8.0", 72 | "babelify": "^6.0.0", 73 | "bannerize": "^1.0.0", 74 | "browserify": "^11.0.0", 75 | "browserify-shim": "^3.0.0", 76 | "connect": "^3.4.0", 77 | "cowsay": "^1.1.0", 78 | "doctoc": "^0.15.0", 79 | "global": "^4.3.0", 80 | "karma": "^0.13.0", 81 | "karma-browserify": "^4.4.0", 82 | "karma-chrome-launcher": "^0.2.0", 83 | "karma-detect-browsers": "^2.0.0", 84 | "karma-firefox-launcher": "^0.1.0", 85 | "karma-ie-launcher": "^0.2.0", 86 | "karma-qunit": "^0.1.0", 87 | "karma-safari-launcher": "^0.1.0", 88 | "lodash-compat": "^3.10.0", 89 | "minimist": "^1.2.0", 90 | "node-sass": "^3.4.2", 91 | "node.extend": "^1.1.5", 92 | "nodemon": "^1.9.1", 93 | "npm-run-all": "~1.2.0", 94 | "portscanner": "^1.0.0", 95 | "qunitjs": "^1.0.0", 96 | "serve-static": "^1.10.0", 97 | "sinon": "1.14.1", 98 | "uglify-js": "^2.5.0", 99 | "videojs-standard": "^4.0.0", 100 | "watchify": "^3.6.0", 101 | "xhr": "^2.2.0" 102 | }, 103 | "browserify": { 104 | "transform": [ 105 | "browserify-shim" 106 | ] 107 | }, 108 | "browserify-shim": { 109 | "qunit": "global:QUnit", 110 | "sinon": "global:sinon", 111 | "video.js": "global:videojs" 112 | }, 113 | "vjsstandard": { 114 | "ignore": [ 115 | "dist", 116 | "dist-test", 117 | "docs", 118 | "es5", 119 | "test/karma", 120 | "scripts" 121 | ] 122 | }, 123 | "dependencies": { 124 | "object.assign": "^4.0.3", 125 | "video.js": "^5.0.0" 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/videojs-dailymotion.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Dailymotion.js 3 | * Dailymotion Media Controller - Wrapper for HTML5 Media API 4 | */ 5 | import videojs from 'video.js'; 6 | 7 | const Component = videojs.getComponent('Component'); 8 | const Tech = videojs.getComponent('Tech'); 9 | 10 | /** 11 | * Dailymotion Media Controller - Wrapper for HTML5 Media API 12 | * 13 | * @param {Object=} options Object of option names and values 14 | * @param {Function=} ready Ready callback function 15 | * @extends Tech 16 | * @class Dailymotion 17 | */ 18 | 19 | class Dailymotion extends Tech { 20 | constructor(options, ready) { 21 | super(options, ready); 22 | 23 | this.params = { 24 | id: this.options_.techId, 25 | autoplay: (this.player_.options_.autoplay) ? 1 : 0, 26 | chromeless: (this.player_.options_.dmControls) ? 0 : 1, 27 | html: 1, 28 | info: 1, 29 | logo: 1, 30 | controls: 'html', 31 | wmode: 'opaque', 32 | format: 'json', 33 | url: options.source.src 34 | }; 35 | 36 | // If we are not on a server, don't specify the origin (it will crash) 37 | if (window.location.protocol !== 'file:') { 38 | this.params.origin = window.location.protocol + '//' + window.location.hostname; 39 | } 40 | 41 | this.videoId = this.parseSrc(options.source.src); 42 | 43 | if (typeof this.videoId !== 'undefined') { 44 | this.setTimeout(() => { 45 | this.setPoster('//api.dailymotion.com/video/' + this.videoId + '?fields=poster_url&ads=false'); 46 | }, 100); 47 | } 48 | 49 | if (Dailymotion.isApiReady) { 50 | this.loadApi(); 51 | } else { 52 | // Add to the queue because the Dailymotion API is not ready 53 | Dailymotion.apiReadyQueue.push(this); 54 | } 55 | 56 | } 57 | 58 | createEl() { 59 | 60 | let el = videojs.createEl('iframe', { 61 | id: this.options_.techId, 62 | className: 'vjs-tech vjs-tech-dailymotion' 63 | }); 64 | 65 | let iframeContainer = videojs.createEl('iframe', { 66 | scrolling: 'no', 67 | marginWidth: 0, 68 | marginHeight: 0, 69 | frameBorder: 0, 70 | webkitAllowFullScreen: '', 71 | mozallowfullscreen: '', 72 | allowFullScreen: '', 73 | }); 74 | 75 | el.appendChild(iframeContainer); 76 | 77 | if (/MSIE (\d+\.\d+);/.test(navigator.userAgent) || !/(iPad|iPhone|iPod|Android)/g.test(navigator.userAgent)) { 78 | let divBlocker = videojs.createEl('div', 79 | { 80 | className: 'vjs-iframe-blocker', 81 | style: 'position:absolute;top:0;left:0;width:100%;height:100%' 82 | }); 83 | 84 | // In case the blocker is still there and we want to pause 85 | divBlocker.onclick = function () { 86 | this.pause(); 87 | }.bind(this); 88 | 89 | el.appendChild(divBlocker); 90 | } 91 | 92 | return el; 93 | } 94 | 95 | loadApi() { 96 | this.dmPlayer = new DM.player(this.options_.techId, { 97 | video: this.videoId, 98 | width: this.options_.width, 99 | height: this.options_.height, 100 | params: this.params 101 | }); 102 | 103 | this.setupTriggers(); 104 | 105 | this.dmPlayer.vjsTech = this; 106 | } 107 | 108 | parseSrc(src) { 109 | if (src) { 110 | // Regex that parse the video ID for any Dailymotion URL 111 | var regExp = /^.+dailymotion.com\/((video|hub)\/([^_]+))?[^#]*(#video=([^_&]+))?/; 112 | var match = src.match(regExp); 113 | 114 | return match ? match[5] || match[3] : null; 115 | } 116 | } 117 | 118 | setupTriggers() { 119 | this.dmPlayer.listeners = []; 120 | for (var i = Dailymotion.Events.length - 1; i >= 0; i--) { 121 | //videojs.on(this.dmPlayer, Dailymotion.Events[i], videojs.bind(this, this.eventHandler)); 122 | var listener = videojs.bind(this, this.eventHandler); 123 | this.dmPlayer.listeners.push({event: Dailymotion.Events[i], func: listener}); 124 | this.dmPlayer.addEventListener(Dailymotion.Events[i], listener); 125 | } 126 | } 127 | 128 | eventHandler(e) { 129 | this.onStateChange(e); 130 | this.trigger(e); 131 | } 132 | 133 | onStateChange(event) { 134 | let state = event.type; 135 | if (state !== this.lastState) { 136 | switch (state) { 137 | case -1: 138 | break; 139 | 140 | case 'apiready': 141 | this.triggerReady(); 142 | break; 143 | 144 | case 'video_end': 145 | this.trigger('ended'); 146 | break; 147 | 148 | case 'ad_play': 149 | this.trigger('play'); 150 | break; 151 | 152 | case 'video_start': 153 | case 'ad_start': 154 | this.trigger('playing'); 155 | this.trigger('play'); 156 | break; 157 | 158 | case 'play': 159 | break; 160 | 161 | case 'playing': 162 | break; 163 | 164 | case 'pause': 165 | break; 166 | case 'durationchange': 167 | break; 168 | 169 | case 'timeupdate': 170 | break; 171 | case 'progress': 172 | break; 173 | 174 | } 175 | 176 | this.lastState = state; 177 | } 178 | } 179 | 180 | poster() { 181 | return this.poster_; 182 | } 183 | 184 | setPoster(poster) { 185 | this.poster_ = poster; 186 | this.trigger('posterchange'); 187 | } 188 | 189 | /** 190 | * Set video 191 | * 192 | * @param {Object=} src Source object 193 | * @method setSrc 194 | */ 195 | src(src) { 196 | if (typeof src !== 'undefined') { 197 | this.src_ = this.parseSrc(src); 198 | this.dmPlayer.load(this.src_); 199 | } 200 | return this.src_; 201 | } 202 | 203 | currentSrc() { 204 | return this.src_; 205 | } 206 | 207 | play() { 208 | if (this.isReady_) { 209 | this.dmPlayer.play(); 210 | } else { 211 | if (!this.player_.options_.dmControls) { 212 | // Keep the big play button until it plays for real 213 | this.player_.bigPlayButton.show(); 214 | } 215 | } 216 | } 217 | 218 | ended() { 219 | 220 | if (this.isReady_) { 221 | var stateId = this.dmPlayer.getPlayerState(); 222 | return stateId === 0; 223 | } else { 224 | // We will play it when the API will be ready 225 | return false; 226 | } 227 | } 228 | 229 | pause() { 230 | this.dmPlayer.pause(!this.dmPlayer.paused); 231 | } 232 | 233 | paused() { 234 | return this.dmPlayer.paused; 235 | } 236 | 237 | currentTime() { 238 | return (this.dmPlayer && this.dmPlayer.currentTime) ? this.dmPlayer.currentTime : 0; 239 | } 240 | 241 | setCurrentTime(position) { 242 | this.dmPlayer.seek(position); 243 | } 244 | 245 | duration() { 246 | return (this.dmPlayer && this.dmPlayer.duration) ? this.dmPlayer.duration : 0; 247 | } 248 | 249 | volume() { 250 | if (isNaN(this.volume_)) { 251 | this.volume_ = this.dmPlayer.volume; 252 | } 253 | 254 | return this.volume_; 255 | } 256 | 257 | /** 258 | * Request to enter fullscreen 259 | * 260 | * @method enterFullScreen 261 | */ 262 | enterFullScreen() { 263 | this.dmPlayer.setFullscreen(true); 264 | } 265 | 266 | /** 267 | * Request to exit fullscreen 268 | * 269 | * @method exitFullScreen 270 | */ 271 | exitFullScreen() { 272 | this.dmPlayer.setFullscreen(false); 273 | } 274 | 275 | 276 | setVolume(percentAsDecimal) { 277 | if (typeof(percentAsDecimal) !== 'undefined' && percentAsDecimal !== this.volume_) { 278 | this.dmPlayer.setVolume(percentAsDecimal); 279 | this.volume_ = percentAsDecimal; 280 | this.player_.trigger('volumechange'); 281 | } 282 | } 283 | 284 | buffered() { 285 | return []; 286 | } 287 | 288 | controls() { 289 | return false; 290 | } 291 | 292 | muted() { 293 | return this.dmPlayer.muted; 294 | } 295 | 296 | setMuted(muted) { 297 | this.dmPlayer.setMuted(muted); 298 | 299 | this.setTimeout(function () { 300 | this.player_.trigger('volumechange'); 301 | }); 302 | } 303 | 304 | supportsFullScreen() { 305 | return true; 306 | } 307 | 308 | 309 | resetSrc_(callback) { 310 | callback(); 311 | } 312 | 313 | dispose() { 314 | this.resetSrc_(Function.prototype); 315 | super.dispose(this); 316 | } 317 | 318 | } 319 | 320 | Dailymotion.prototype.options_ = {}; 321 | 322 | Dailymotion.apiReadyQueue = []; 323 | 324 | Dailymotion.makeQueryString = function (args) { 325 | let querys = []; 326 | for (var key in args) { 327 | if (args.hasOwnProperty(key)) { 328 | querys.push(encodeURIComponent(key) + '=' + encodeURIComponent(args[key])); 329 | } 330 | } 331 | 332 | return querys.join('&'); 333 | }; 334 | 335 | const injectJs = function () { 336 | let tag = document.createElement('script'); 337 | tag.src = '//api.dmcdn.net/all.js'; 338 | let firstScriptTag = document.getElementsByTagName('script')[0]; 339 | firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 340 | } 341 | 342 | /* Dailymotion Support Testing -------------------------------------------------------- */ 343 | 344 | Dailymotion.isSupported = function () { 345 | return true; 346 | }; 347 | 348 | // Add Source Handler pattern functions to this tech 349 | Tech.withSourceHandlers(Dailymotion); 350 | 351 | /* 352 | * The default native source handler. 353 | * This simply passes the source to the video element. Nothing fancy. 354 | * 355 | * @param {Object} source The source object 356 | * @param {Flash} tech The instance of the Flash tech 357 | */ 358 | Dailymotion.nativeSourceHandler = {}; 359 | 360 | /** 361 | * Check if Flash can play the given videotype 362 | * @param {String} type The mimetype to check 363 | * @return {String} 'probably', 'maybe', or '' (empty string) 364 | */ 365 | Dailymotion.nativeSourceHandler.canPlayType = function (source) { 366 | 367 | const dashExtRE = /^video\/(dailymotion)/i; 368 | 369 | if (dashExtRE.test(source)) { 370 | return 'maybe'; 371 | } else { 372 | return ''; 373 | } 374 | 375 | }; 376 | 377 | /* 378 | * Check Flash can handle the source natively 379 | * 380 | * @param {Object} source The source object 381 | * @return {String} 'probably', 'maybe', or '' (empty string) 382 | */ 383 | Dailymotion.nativeSourceHandler.canHandleSource = function (source) { 384 | 385 | // If a type was provided we should rely on that 386 | if (source.type) { 387 | return Dailymotion.nativeSourceHandler.canPlayType(source.type); 388 | } else if (source.src) { 389 | return Dailymotion.nativeSourceHandler.canPlayType(source.src); 390 | } 391 | 392 | return ''; 393 | }; 394 | 395 | /* 396 | * Pass the source to the flash object 397 | * Adaptive source handlers will have more complicated workflows before passing 398 | * video data to the video element 399 | * 400 | * @param {Object} source The source object 401 | * @param {Flash} tech The instance of the Flash tech 402 | */ 403 | Dailymotion.nativeSourceHandler.handleSource = function (source, tech) { 404 | tech.src(source.src); 405 | }; 406 | 407 | /* 408 | * Clean up the source handler when disposing the player or switching sources.. 409 | * (no cleanup is needed when supporting the format natively) 410 | */ 411 | Dailymotion.nativeSourceHandler.dispose = function () { 412 | }; 413 | 414 | // Register the native source handler 415 | Dailymotion.registerSourceHandler(Dailymotion.nativeSourceHandler); 416 | 417 | 418 | /* 419 | * Set the tech's volume control support status 420 | * 421 | * @type {Boolean} 422 | */ 423 | Dailymotion.prototype['featuresVolumeControl'] = true; 424 | 425 | /* 426 | * Set the tech's playbackRate support status 427 | * 428 | * @type {Boolean} 429 | */ 430 | Dailymotion.prototype['featuresPlaybackRate'] = false; 431 | 432 | /* 433 | * Set the tech's status on moving the video element. 434 | * In iOS, if you move a video element in the DOM, it breaks video playback. 435 | * 436 | * @type {Boolean} 437 | */ 438 | Dailymotion.prototype['movingMediaElementInDOM'] = false; 439 | 440 | /* 441 | * Set the the tech's fullscreen resize support status. 442 | * HTML video is able to automatically resize when going to fullscreen. 443 | * (No longer appears to be used. Can probably be removed.) 444 | */ 445 | Dailymotion.prototype['featuresFullscreenResize'] = false; 446 | 447 | /* 448 | * Set the tech's timeupdate event support status 449 | * (this disables the manual timeupdate events of the Tech) 450 | */ 451 | Dailymotion.prototype['featuresTimeupdateEvents'] = false; 452 | 453 | /* 454 | * Set the tech's progress event support status 455 | * (this disables the manual progress events of the Tech) 456 | */ 457 | Dailymotion.prototype['featuresProgressEvents'] = false; 458 | 459 | /* 460 | * Sets the tech's status on native text track support 461 | * 462 | * @type {Boolean} 463 | */ 464 | Dailymotion.prototype['featuresNativeTextTracks'] = true; 465 | 466 | /* 467 | * Sets the tech's status on native audio track support 468 | * 469 | * @type {Boolean} 470 | */ 471 | Dailymotion.prototype['featuresNativeAudioTracks'] = true; 472 | 473 | /* 474 | * Sets the tech's status on native video track support 475 | * 476 | * @type {Boolean} 477 | */ 478 | Dailymotion.prototype['featuresNativeVideoTracks'] = false; 479 | 480 | Dailymotion.Events = 'apiready,ad_play,ad_start,ad_timeupdate,ad_pause,ad_end,video_start,video_end,play,playing,pause,ended,canplay,canplaythrough,timeupdate,progress,seeking,seeked,volumechange,durationchange,fullscreenchange,error'.split(','); 481 | 482 | videojs.options.Dailymotion = {}; 483 | 484 | Component.registerComponent('Dailymotion', Dailymotion); 485 | Tech.registerTech('Dailymotion', Dailymotion); 486 | 487 | injectJs(); 488 | 489 | // Called when Dailymotion API is ready to be used 490 | window.dmAsyncInit = function () { 491 | var dm; 492 | while ((dm = Dailymotion.apiReadyQueue.shift())) { 493 | dm.loadApi(); 494 | } 495 | Dailymotion.apiReadyQueue = []; 496 | Dailymotion.isApiReady = true; 497 | }; 498 | 499 | export default Dailymotion; 500 | -------------------------------------------------------------------------------- /es5/dailymotion.js: -------------------------------------------------------------------------------- 1 | /* global videojs, DM */ 2 | /** 3 | * @fileoverview Dailymotion Media Controller - Wrapper for Dailymotion Media API 4 | */ 5 | 6 | 'use strict'; 7 | 8 | (function () { 9 | /** 10 | * Dailymotion Media Controller - Wrapper for Dailymotion Media API 11 | * @param {videojs.Player|Object} player 12 | * @param {Object=} options 13 | * @param {Function=} ready 14 | * @constructor 15 | */ 16 | 17 | function addEventListener(element, event, cb) { 18 | if (!element.addEventListener) { 19 | element.attachEvent(event, cb); 20 | } else { 21 | element.addEventListener(event, cb, true); 22 | } 23 | } 24 | 25 | videojs.Dailymotion = videojs.MediaTechController.extend({ 26 | /** @constructor */ 27 | init: function init(player, options, ready) { 28 | videojs.MediaTechController.call(this, player, options, ready); 29 | 30 | this.player_ = player; 31 | this.playerEl_ = this.player_.el(); 32 | 33 | if (typeof this.player_.options().dmControls !== 'undefined') { 34 | var dmC = this.player_.options().dmControls = parseInt(this.player_.options().dmControls) && this.player_.controls(); 35 | 36 | if (dmC && this.player_.controls()) { 37 | this.player_.controls(!dmC); 38 | } 39 | } 40 | 41 | // Copy the Javascript options if they exist 42 | if (typeof options.source !== 'undefined') { 43 | for (var key in options.source) { 44 | if (options['source'].hasOwnProperty(key)) { 45 | this.player_.options()[key] = options.source[key]; 46 | } 47 | } 48 | } 49 | 50 | var self = this; 51 | 52 | this.bindedWaiting = function () { 53 | self.onWaiting(); 54 | }; 55 | this.player_.on('waiting', this.bindedWaiting); 56 | 57 | player.ready(function () { 58 | if (self.playOnReady && !self.player_.options()['dmControls']) { 59 | if (typeof self.player_.loadingSpinner !== 'undefined') { 60 | self.player_.loadingSpinner.show(); 61 | } 62 | if (typeof self.player_.bigPlayButton !== 'undefined') { 63 | self.player_.bigPlayButton.hide(); 64 | } 65 | } 66 | 67 | player.trigger('loadstart'); 68 | }); 69 | 70 | this.videoId = this.parseSrc(this.player_.options().src); 71 | 72 | if (typeof this.videoId !== 'undefined') { 73 | // Show the Dailymotion poster only if we don't use Dailymotion poster 74 | // (otherwise the controls pop, it's not nice) 75 | if (!this.player_.options().dmControls) { 76 | // Set the Dailymotion poster only if none is specified 77 | if (typeof this.player_.poster() === 'undefined') { 78 | // Don't use player.poster(), it will fail here because the tech is still null in constructor 79 | this.player_.poster(); 80 | // Cover the entire iframe to have the same poster than Dailymotion 81 | // Doesn't exist right away because the DOM hasn't created it 82 | setTimeout(function () { 83 | var posterEl = self.playerEl_.querySelectorAll('.vjs-poster')[0]; 84 | posterEl.style.backgroundImage = 'url(//api.dailymotion.com/video/' + self.videoId + '?fields=url&ads=false)'; 85 | posterEl.style.display = ''; 86 | posterEl.style.backgroundSize = 'cover'; 87 | }, 100); 88 | } 89 | } 90 | } 91 | 92 | this.id_ = this.player_.id() + '_dailymotion_api'; 93 | 94 | this.el_ = videojs.Component.prototype.createEl('iframe', { 95 | id: this.id_, 96 | className: 'vjs-tech', 97 | scrolling: 'no', 98 | marginWidth: 0, 99 | marginHeight: 0, 100 | frameBorder: 0, 101 | webkitAllowFullScreen: '', 102 | mozallowfullscreen: '', 103 | allowFullScreen: '' 104 | }); 105 | 106 | this.playerEl_.insertBefore(this.el_, this.playerEl_.firstChild); 107 | 108 | if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { 109 | var ieVersion = Number(RegExp.$1); 110 | this.addIframeBlocker(ieVersion); 111 | } else if (!/(iPad|iPhone|iPod|Android)/g.test(navigator.userAgent)) { 112 | // the pointer-events: none block the mobile player 113 | this.el_.className += ' onDesktop'; 114 | this.addIframeBlocker(); 115 | } 116 | 117 | this.params = { 118 | id: this.id_, 119 | autoplay: this.player_.options().autoplay ? 1 : 0, 120 | chromeless: this.player_.options().dmControls ? 0 : 1, 121 | html: 1, 122 | info: 1, 123 | logo: 1, 124 | controls: 'html', 125 | wmode: 'opaque', 126 | format: 'json', 127 | url: this.player_.options().src 128 | }; 129 | 130 | if (typeof this.params.list === 'undefined') { 131 | delete this.params.list; 132 | } 133 | 134 | // Make autoplay work for iOS 135 | if (this.player_.options().autoplay) { 136 | this.player_.bigPlayButton.hide(); 137 | this.playOnReady = true; 138 | } 139 | 140 | // If we are not on a server, don't specify the origin (it will crash) 141 | if (window.location.protocol !== 'file:') { 142 | this.params.origin = window.location.protocol + '//' + window.location.hostname; 143 | } 144 | 145 | this.el_.src = '//www.dailymotion.com/services/oembed?' + videojs.Dailymotion.makeQueryString(this.params); 146 | 147 | if (videojs.Dailymotion.apiReady) { 148 | this.loadApi(); 149 | } else { 150 | // Add to the queue because the Dailymotion API is not ready 151 | videojs.Dailymotion.loadingQueue.push(this); 152 | 153 | // Load the Dailymotion API if it is the first Dailymotion video 154 | if (!videojs.Dailymotion.apiLoading) { 155 | var tag = document.createElement('script'); 156 | tag.onerror = function (e) { 157 | self.onError(e); 158 | }; 159 | tag.src = '//api.dmcdn.net/all.js'; 160 | var firstScriptTag = document.getElementsByTagName('script')[0]; 161 | firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 162 | videojs.Dailymotion.apiLoading = true; 163 | } 164 | } 165 | } 166 | }); 167 | 168 | videojs.Dailymotion.prototype.params = []; 169 | 170 | videojs.Dailymotion.prototype.onWaiting = function () /*e*/{ 171 | // Make sure to hide the play button while the spinner is there 172 | if (typeof this.player_.bigPlayButton !== 'undefined') { 173 | this.player_.bigPlayButton.hide(); 174 | } 175 | }; 176 | 177 | videojs.Dailymotion.prototype.addIframeBlocker = function (ieVersion) { 178 | 179 | if (this.player_.options().dmControls) { 180 | return false; 181 | } 182 | 183 | this.iframeblocker = videojs.Component.prototype.createEl('div'); 184 | 185 | this.iframeblocker.className = 'iframeblocker'; 186 | 187 | this.iframeblocker.style.position = 'absolute'; 188 | this.iframeblocker.style.left = 0; 189 | this.iframeblocker.style.right = 0; 190 | this.iframeblocker.style.top = 0; 191 | this.iframeblocker.style.bottom = 0; 192 | 193 | // Odd quirk for IE8 (doesn't support rgba) 194 | if (ieVersion && ieVersion < 9) { 195 | this.iframeblocker.style.opacity = 0.01; 196 | } else { 197 | this.iframeblocker.style.background = 'rgba(255, 255, 255, 0.01)'; 198 | } 199 | 200 | var self = this; 201 | 202 | addEventListener(this.iframeblocker, 'mousemove', function (e) { 203 | if (!self.player_.userActive()) { 204 | self.player_.userActive(true); 205 | } 206 | 207 | e.stopPropagation(); 208 | e.preventDefault(); 209 | }); 210 | 211 | addEventListener(this.iframeblocker, 'click', function () /*e*/{ 212 | if (self.paused()) { 213 | self.play(); 214 | } else { 215 | self.pause(); 216 | } 217 | }); 218 | 219 | this.playerEl_.insertBefore(this.iframeblocker, this.el_.nextSibling); 220 | }; 221 | 222 | videojs.Dailymotion.prototype.dispose = function () { 223 | if (this.dmPlayer) { 224 | this.pause(); 225 | for (var i = 0; i < this.dmPlayer.listeners.length; i++) { 226 | var listener = this.dmPlayer.listeners[i]; 227 | this.dmPlayer.removeEventListener(listener.event, listener.func); 228 | } 229 | this.dmPlayer = null; 230 | } 231 | 232 | // Remove the poster 233 | this.playerEl_.querySelectorAll('.vjs-poster')[0].style.backgroundImage = 'none'; 234 | 235 | // If still connected to the DOM, remove it. 236 | var el = document.getElementById(this.id_); 237 | if (el.parentNode) { 238 | el.parentNode.removeChild(el); 239 | } 240 | 241 | if (typeof this.player_.loadingSpinner !== 'undefined') { 242 | this.player_.loadingSpinner.hide(); 243 | } 244 | if (typeof this.player_.bigPlayButton !== 'undefined') { 245 | this.player_.bigPlayButton.hide(); 246 | } 247 | 248 | videojs.MediaTechController.prototype.dispose.call(this); 249 | }; 250 | 251 | videojs.Dailymotion.prototype.src = function (src) { 252 | if (typeof src !== 'undefined') { 253 | this.dmPlayer.load(this.parseSrc(src)); 254 | } 255 | return this.srcVal; 256 | }; 257 | 258 | videojs.Dailymotion.prototype.currentSrc = function () { 259 | return this.srcVal; 260 | }; 261 | 262 | videojs.Dailymotion.prototype.play = function () { 263 | if (this.isReady_) { 264 | this.dmPlayer.play(); 265 | } else { 266 | // We will play it when the API will be ready 267 | this.playOnReady = true; 268 | 269 | if (!this.player_.options.dmControls) { 270 | // Keep the big play button until it plays for real 271 | this.player_.bigPlayButton.show(); 272 | } 273 | } 274 | }; 275 | 276 | videojs.Dailymotion.prototype.ended = function () { 277 | 278 | if (this.isReady_) { 279 | var stateId = this.dmPlayer.getPlayerState(); 280 | return stateId === 0; 281 | } else { 282 | // We will play it when the API will be ready 283 | return false; 284 | } 285 | }; 286 | 287 | videojs.Dailymotion.prototype.pause = function () { 288 | this.dmPlayer.pause(!this.dmPlayer.paused); 289 | }; 290 | 291 | videojs.Dailymotion.prototype.paused = function () { 292 | return this.dmPlayer.paused; 293 | }; 294 | 295 | videojs.Dailymotion.prototype.currentTime = function () { 296 | return this.dmPlayer && this.dmPlayer.currentTime ? this.dmPlayer.currentTime : 0; 297 | }; 298 | 299 | videojs.Dailymotion.prototype.setCurrentTime = function (seconds) { 300 | this.dmPlayer.seek(seconds, true); 301 | this.player_.trigger('timeupdate'); 302 | }; 303 | 304 | videojs.Dailymotion.prototype.duration = function () { 305 | return this.dmPlayer && this.dmPlayer.duration ? this.dmPlayer.duration : 0; 306 | }; 307 | 308 | videojs.Dailymotion.prototype.buffered = function () { 309 | /*var loadedBytes = this.dmPlayer.getVideoBytesLoaded(); 310 | var totalBytes = this.dmPlayer.getVideoBytesTotal(); 311 | if (!loadedBytes || !totalBytes) return 0; 312 | var duration = this.dmPlayer.getDuration(); 313 | var secondsBuffered = (loadedBytes / totalBytes) * duration; 314 | var secondsOffset = (this.dmPlayer.getCurrentTime() / totalBytes) * duration; 315 | return videojs.createTimeRange(secondsOffset, secondsOffset + secondsBuffered);*/ 316 | return []; 317 | }; 318 | 319 | videojs.Dailymotion.prototype.volume = function () { 320 | if (isNaN(this.volumeVal)) { 321 | this.volumeVal = this.dmPlayer.volume; 322 | } 323 | 324 | return this.volumeVal; 325 | }; 326 | 327 | videojs.Dailymotion.prototype.setVolume = function (percentAsDecimal) { 328 | if (typeof percentAsDecimal !== 'undefined' && percentAsDecimal !== this.volumeVal) { 329 | this.dmPlayer.setVolume(percentAsDecimal); 330 | this.volumeVal = percentAsDecimal; 331 | this.player_.trigger('volumechange'); 332 | } 333 | }; 334 | 335 | videojs.Dailymotion.prototype.muted = function () { 336 | return this.dmPlayer.muted; 337 | }; 338 | videojs.Dailymotion.prototype.setMuted = function (muted) { 339 | this.dmPlayer.setMuted(muted); 340 | 341 | var self = this; 342 | setTimeout(function () { 343 | self.player_.trigger('volumechange'); 344 | }, 50); 345 | }; 346 | 347 | videojs.Dailymotion.prototype.onReady = function () { 348 | this.isReady_ = true; 349 | this.player_.trigger('techready'); 350 | 351 | // Hide the poster when ready because Dailymotion has it's own 352 | this.triggerReady(); 353 | this.player_.trigger('durationchange'); 354 | 355 | // Play right away if we clicked before ready 356 | if (this.playOnReady) { 357 | this.dmPlayer.play(); 358 | } 359 | }; 360 | 361 | videojs.Dailymotion.isSupported = function () { 362 | return true; 363 | }; 364 | 365 | videojs.Dailymotion.prototype.supportsFullScreen = function () { 366 | return false; 367 | }; 368 | 369 | videojs.Dailymotion.canPlaySource = function (srcObj) { 370 | return srcObj.type === 'video/dailymotion'; 371 | }; 372 | 373 | // All videos created before Dailymotion API is loaded 374 | videojs.Dailymotion.loadingQueue = []; 375 | 376 | videojs.Dailymotion.prototype.load = function () {}; 377 | 378 | // Create the Dailymotion player 379 | videojs.Dailymotion.prototype.loadApi = function () { 380 | 381 | this.dmPlayer = new DM.player(this.id_, { 382 | video: this.videoId, 383 | width: this.options.width, 384 | height: this.options.height, 385 | params: this.params 386 | }); 387 | 388 | this.setupTriggers(); 389 | 390 | this.dmPlayer.vjsTech = this; 391 | }; 392 | 393 | videojs.Dailymotion.prototype.onStateChange = function (event) { 394 | var state = event.type; 395 | if (state !== this.lastState) { 396 | switch (state) { 397 | case -1: 398 | this.player_.trigger('durationchange'); 399 | break; 400 | 401 | case 'apiready': 402 | this.onReady(); 403 | break; 404 | 405 | case 'ended': 406 | 407 | if (!this.player_.options().dmControls) { 408 | this.player_.bigPlayButton.show(); 409 | } 410 | break; 411 | 412 | case 'play': 413 | this.player_.trigger('play'); 414 | break; 415 | 416 | case 'playing': 417 | break; 418 | 419 | case 'pause': 420 | break; 421 | case 'durationchange': 422 | break; 423 | 424 | case 'timeupdate': 425 | // Hide the waiting spinner since Dailymotion has its own 426 | this.player_.loadingSpinner.hide(); 427 | break; 428 | case 'progress': 429 | break; 430 | 431 | } 432 | 433 | this.lastState = state; 434 | } 435 | }; 436 | 437 | videojs.Dailymotion.prototype.onError = function (error) { 438 | this.player_.error(error); 439 | 440 | if (error === 100 || error === 101 || error === 150) { 441 | this.player_.bigPlayButton.hide(); 442 | this.player_.loadingSpinner.hide(); 443 | this.player_.posterImage.hide(); 444 | } 445 | }; 446 | 447 | videojs.Dailymotion.makeQueryString = function (args) { 448 | var array = []; 449 | for (var key in args) { 450 | if (args.hasOwnProperty(key)) { 451 | array.push(encodeURIComponent(key) + '=' + encodeURIComponent(args[key])); 452 | } 453 | } 454 | 455 | return array.join('&'); 456 | }; 457 | 458 | videojs.Dailymotion.prototype.parseSrc = function (src) { 459 | this.srcVal = src; 460 | 461 | if (src) { 462 | // Regex that parse the video ID for any Dailymotion URL 463 | var regExp = /^.+dailymotion.com\/((video|hub)\/([^_]+))?[^#]*(#video=([^_&]+))?/; 464 | var match = src.match(regExp); 465 | 466 | return match ? match[5] || match[3] : null; 467 | } 468 | }; 469 | 470 | videojs.Dailymotion.parsePlaylist = function (src) { 471 | // Check if we have a playlist 472 | var regExp = /[?&]list=([^#\&\?]+)/; 473 | var match = src.match(regExp); 474 | 475 | if (match !== null && match.length > 1) { 476 | return match[1]; 477 | } 478 | }; 479 | 480 | // Make video events trigger player events 481 | // May seem verbose here, but makes other APIs possible. 482 | videojs.Dailymotion.prototype.setupTriggers = function () { 483 | this.dmPlayer.listeners = []; 484 | for (var i = videojs.Dailymotion.Events.length - 1; i >= 0; i--) { 485 | //videojs.on(this.dmPlayer, videojs.Dailymotion.Events[i], videojs.bind(this, this.eventHandler)); 486 | var listener = videojs.bind(this, this.eventHandler); 487 | this.dmPlayer.listeners.push({ event: videojs.Dailymotion.Events[i], func: listener }); 488 | this.dmPlayer.addEventListener(videojs.Dailymotion.Events[i], listener); 489 | } 490 | }; 491 | // Triggers removed using this.off when disposed 492 | 493 | videojs.Dailymotion.prototype.eventHandler = function (e) { 494 | this.onStateChange(e); 495 | this.trigger(e); 496 | }; 497 | 498 | // List of all HTML5 events (various uses). 499 | videojs.Dailymotion.Events = ('apiready,play,playing,pause,ended,canplay,' + 'canplaythrough,timeupdate,progress,seeking,seeked,volumechange,durationchange,fullscreenchange,error').split(','); 500 | 501 | // Called when Dailymotion API is ready to be used 502 | window.dmAsyncInit = function () { 503 | var dm; 504 | while (dm = videojs.Dailymotion.loadingQueue.shift()) { 505 | dm.loadApi(); 506 | } 507 | videojs.Dailymotion.loadingQueue = []; 508 | videojs.Dailymotion.apiReady = true; 509 | }; 510 | })(); -------------------------------------------------------------------------------- /src/dailymotion.js: -------------------------------------------------------------------------------- 1 | /* global videojs, DM */ 2 | /** 3 | * @fileoverview Dailymotion Media Controller - Wrapper for Dailymotion Media API 4 | */ 5 | 6 | 7 | (function () { 8 | /** 9 | * Dailymotion Media Controller - Wrapper for Dailymotion Media API 10 | * @param {videojs.Player|Object} player 11 | * @param {Object=} options 12 | * @param {Function=} ready 13 | * @constructor 14 | */ 15 | 16 | function addEventListener(element, event, cb) { 17 | if (!element.addEventListener) { 18 | element.attachEvent(event, cb); 19 | } else { 20 | element.addEventListener(event, cb, true); 21 | } 22 | } 23 | 24 | videojs.Dailymotion = videojs.MediaTechController.extend({ 25 | /** @constructor */ 26 | init: function (player, options, ready) { 27 | videojs.MediaTechController.call(this, player, options, ready); 28 | 29 | this.player_ = player; 30 | this.playerEl_ = this.player_.el(); 31 | 32 | if (typeof this.player_.options().dmControls !== 'undefined') { 33 | var dmC = this.player_.options().dmControls = parseInt(this.player_.options().dmControls) && 34 | this.player_.controls(); 35 | 36 | if (dmC && this.player_.controls()) { 37 | this.player_.controls(!dmC); 38 | } 39 | } 40 | 41 | 42 | // Copy the Javascript options if they exist 43 | if (typeof options.source !== 'undefined') { 44 | for (var key in options.source) { 45 | if (options['source'].hasOwnProperty(key)) { 46 | this.player_.options()[key] = options.source[key]; 47 | } 48 | } 49 | } 50 | 51 | var self = this; 52 | 53 | 54 | this.bindedWaiting = function () { 55 | self.onWaiting(); 56 | }; 57 | this.player_.on('waiting', this.bindedWaiting); 58 | 59 | player.ready(function () { 60 | if (self.playOnReady && !self.player_.options()['dmControls']) { 61 | if (typeof self.player_.loadingSpinner !== 'undefined') { 62 | self.player_.loadingSpinner.show(); 63 | } 64 | if (typeof self.player_.bigPlayButton !== 'undefined') { 65 | self.player_.bigPlayButton.hide(); 66 | } 67 | } 68 | 69 | player.trigger('loadstart'); 70 | }); 71 | 72 | this.videoId = this.parseSrc(this.player_.options().src); 73 | 74 | if (typeof this.videoId !== 'undefined') { 75 | // Show the Dailymotion poster only if we don't use Dailymotion poster 76 | // (otherwise the controls pop, it's not nice) 77 | if (!this.player_.options().dmControls) { 78 | // Set the Dailymotion poster only if none is specified 79 | if (typeof this.player_.poster() === 'undefined') { 80 | // Don't use player.poster(), it will fail here because the tech is still null in constructor 81 | this.player_.poster(); 82 | // Cover the entire iframe to have the same poster than Dailymotion 83 | // Doesn't exist right away because the DOM hasn't created it 84 | setTimeout(function () { 85 | var posterEl = self.playerEl_.querySelectorAll('.vjs-poster')[0]; 86 | posterEl.style.backgroundImage = 'url(//api.dailymotion.com/video/' + self.videoId + '?fields=url&ads=false)'; 87 | posterEl.style.display = ''; 88 | posterEl.style.backgroundSize = 'cover'; 89 | }, 100); 90 | } 91 | } 92 | } 93 | 94 | this.id_ = this.player_.id() + '_dailymotion_api'; 95 | 96 | this.el_ = videojs.Component.prototype.createEl('iframe', { 97 | id: this.id_, 98 | className: 'vjs-tech', 99 | scrolling: 'no', 100 | marginWidth: 0, 101 | marginHeight: 0, 102 | frameBorder: 0, 103 | webkitAllowFullScreen: '', 104 | mozallowfullscreen: '', 105 | allowFullScreen: '' 106 | }); 107 | 108 | this.playerEl_.insertBefore(this.el_, this.playerEl_.firstChild); 109 | 110 | if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { 111 | var ieVersion = Number(RegExp.$1); 112 | this.addIframeBlocker(ieVersion); 113 | } else if (!/(iPad|iPhone|iPod|Android)/g.test(navigator.userAgent)) { 114 | // the pointer-events: none block the mobile player 115 | this.el_.className += ' onDesktop'; 116 | this.addIframeBlocker(); 117 | } 118 | 119 | this.params = { 120 | id: this.id_, 121 | autoplay: (this.player_.options().autoplay) ? 1 : 0, 122 | chromeless: (this.player_.options().dmControls) ? 0 : 1, 123 | html: 1, 124 | info: 1, 125 | logo: 1, 126 | controls: 'html', 127 | wmode: 'opaque', 128 | format: 'json', 129 | url: this.player_.options().src 130 | }; 131 | 132 | if (typeof this.params.list === 'undefined') { 133 | delete this.params.list; 134 | } 135 | 136 | // Make autoplay work for iOS 137 | if (this.player_.options().autoplay) { 138 | this.player_.bigPlayButton.hide(); 139 | this.playOnReady = true; 140 | } 141 | 142 | // If we are not on a server, don't specify the origin (it will crash) 143 | if (window.location.protocol !== 'file:') { 144 | this.params.origin = window.location.protocol + '//' + window.location.hostname; 145 | } 146 | 147 | 148 | this.el_.src = '//www.dailymotion.com/services/oembed?' + videojs.Dailymotion.makeQueryString(this.params); 149 | 150 | if (videojs.Dailymotion.apiReady) { 151 | this.loadApi(); 152 | } else { 153 | // Add to the queue because the Dailymotion API is not ready 154 | videojs.Dailymotion.loadingQueue.push(this); 155 | 156 | // Load the Dailymotion API if it is the first Dailymotion video 157 | if (!videojs.Dailymotion.apiLoading) { 158 | var tag = document.createElement('script'); 159 | tag.onerror = function (e) { 160 | self.onError(e); 161 | }; 162 | tag.src = '//api.dmcdn.net/all.js'; 163 | var firstScriptTag = document.getElementsByTagName('script')[0]; 164 | firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 165 | videojs.Dailymotion.apiLoading = true; 166 | } 167 | } 168 | 169 | } 170 | }); 171 | 172 | videojs.Dailymotion.prototype.params = []; 173 | 174 | 175 | videojs.Dailymotion.prototype.onWaiting = function (/*e*/) { 176 | // Make sure to hide the play button while the spinner is there 177 | if (typeof this.player_.bigPlayButton !== 'undefined') { 178 | this.player_.bigPlayButton.hide(); 179 | } 180 | }; 181 | 182 | videojs.Dailymotion.prototype.addIframeBlocker = function (ieVersion) { 183 | 184 | if (this.player_.options().dmControls) { 185 | return false; 186 | } 187 | 188 | this.iframeblocker = videojs.Component.prototype.createEl('div'); 189 | 190 | this.iframeblocker.className = 'iframeblocker'; 191 | 192 | this.iframeblocker.style.position = 'absolute'; 193 | this.iframeblocker.style.left = 0; 194 | this.iframeblocker.style.right = 0; 195 | this.iframeblocker.style.top = 0; 196 | this.iframeblocker.style.bottom = 0; 197 | 198 | // Odd quirk for IE8 (doesn't support rgba) 199 | if (ieVersion && ieVersion < 9) { 200 | this.iframeblocker.style.opacity = 0.01; 201 | } else { 202 | this.iframeblocker.style.background = 'rgba(255, 255, 255, 0.01)'; 203 | } 204 | 205 | var self = this; 206 | 207 | addEventListener(this.iframeblocker, 'mousemove', function (e) { 208 | if (!self.player_.userActive()) { 209 | self.player_.userActive(true); 210 | } 211 | 212 | e.stopPropagation(); 213 | e.preventDefault(); 214 | }); 215 | 216 | addEventListener(this.iframeblocker, 'click', function (/*e*/) { 217 | if (self.paused()) { 218 | self.play(); 219 | } else { 220 | self.pause(); 221 | } 222 | }); 223 | 224 | this.playerEl_.insertBefore(this.iframeblocker, this.el_.nextSibling); 225 | }; 226 | 227 | videojs.Dailymotion.prototype.dispose = function () { 228 | if (this.dmPlayer) { 229 | this.pause(); 230 | for (var i = 0; i < this.dmPlayer.listeners.length; i++) { 231 | var listener = this.dmPlayer.listeners[i]; 232 | this.dmPlayer.removeEventListener(listener.event, listener.func); 233 | } 234 | this.dmPlayer = null; 235 | } 236 | 237 | // Remove the poster 238 | this.playerEl_.querySelectorAll('.vjs-poster')[0].style.backgroundImage = 'none'; 239 | 240 | // If still connected to the DOM, remove it. 241 | var el = document.getElementById(this.id_); 242 | if (el.parentNode) { 243 | el.parentNode.removeChild(el); 244 | } 245 | 246 | if (typeof this.player_.loadingSpinner !== 'undefined') { 247 | this.player_.loadingSpinner.hide(); 248 | } 249 | if (typeof this.player_.bigPlayButton !== 'undefined') { 250 | this.player_.bigPlayButton.hide(); 251 | } 252 | 253 | videojs.MediaTechController.prototype.dispose.call(this); 254 | }; 255 | 256 | videojs.Dailymotion.prototype.src = function (src) { 257 | if (typeof src !== 'undefined') { 258 | this.dmPlayer.load(this.parseSrc(src)); 259 | } 260 | return this.srcVal; 261 | }; 262 | 263 | videojs.Dailymotion.prototype.currentSrc = function () { 264 | return this.srcVal; 265 | }; 266 | 267 | videojs.Dailymotion.prototype.play = function () { 268 | if (this.isReady_) { 269 | this.dmPlayer.play(); 270 | } else { 271 | // We will play it when the API will be ready 272 | this.playOnReady = true; 273 | 274 | if (!this.player_.options.dmControls) { 275 | // Keep the big play button until it plays for real 276 | this.player_.bigPlayButton.show(); 277 | } 278 | } 279 | }; 280 | 281 | videojs.Dailymotion.prototype.ended = function () { 282 | 283 | if (this.isReady_) { 284 | var stateId = this.dmPlayer.getPlayerState(); 285 | return stateId === 0; 286 | } else { 287 | // We will play it when the API will be ready 288 | return false; 289 | } 290 | }; 291 | 292 | videojs.Dailymotion.prototype.pause = function () { 293 | this.dmPlayer.pause(!this.dmPlayer.paused); 294 | }; 295 | 296 | videojs.Dailymotion.prototype.paused = function () { 297 | return this.dmPlayer.paused; 298 | }; 299 | 300 | videojs.Dailymotion.prototype.currentTime = function () { 301 | return (this.dmPlayer && this.dmPlayer.currentTime) ? this.dmPlayer.currentTime : 0; 302 | }; 303 | 304 | videojs.Dailymotion.prototype.setCurrentTime = function (seconds) { 305 | this.dmPlayer.seek(seconds, true); 306 | this.player_.trigger('timeupdate'); 307 | }; 308 | 309 | videojs.Dailymotion.prototype.duration = function () { 310 | return (this.dmPlayer && this.dmPlayer.duration) ? this.dmPlayer.duration : 0; 311 | }; 312 | 313 | videojs.Dailymotion.prototype.buffered = function () { 314 | /*var loadedBytes = this.dmPlayer.getVideoBytesLoaded(); 315 | var totalBytes = this.dmPlayer.getVideoBytesTotal(); 316 | if (!loadedBytes || !totalBytes) return 0; 317 | 318 | var duration = this.dmPlayer.getDuration(); 319 | var secondsBuffered = (loadedBytes / totalBytes) * duration; 320 | var secondsOffset = (this.dmPlayer.getCurrentTime() / totalBytes) * duration; 321 | return videojs.createTimeRange(secondsOffset, secondsOffset + secondsBuffered);*/ 322 | return []; 323 | }; 324 | 325 | videojs.Dailymotion.prototype.volume = function () { 326 | if (isNaN(this.volumeVal)) { 327 | this.volumeVal = this.dmPlayer.volume; 328 | } 329 | 330 | return this.volumeVal; 331 | }; 332 | 333 | videojs.Dailymotion.prototype.setVolume = function (percentAsDecimal) { 334 | if (typeof(percentAsDecimal) !== 'undefined' && percentAsDecimal !== this.volumeVal) { 335 | this.dmPlayer.setVolume(percentAsDecimal); 336 | this.volumeVal = percentAsDecimal; 337 | this.player_.trigger('volumechange'); 338 | } 339 | }; 340 | 341 | videojs.Dailymotion.prototype.muted = function () { 342 | return this.dmPlayer.muted; 343 | }; 344 | videojs.Dailymotion.prototype.setMuted = function (muted) { 345 | this.dmPlayer.setMuted(muted); 346 | 347 | var self = this; 348 | setTimeout(function () { 349 | self.player_.trigger('volumechange'); 350 | }, 50); 351 | }; 352 | 353 | videojs.Dailymotion.prototype.onReady = function () { 354 | this.isReady_ = true; 355 | this.player_.trigger('techready'); 356 | 357 | // Hide the poster when ready because Dailymotion has it's own 358 | this.triggerReady(); 359 | this.player_.trigger('durationchange'); 360 | 361 | // Play right away if we clicked before ready 362 | if (this.playOnReady) { 363 | this.dmPlayer.play(); 364 | } 365 | }; 366 | 367 | 368 | videojs.Dailymotion.isSupported = function () { 369 | return true; 370 | }; 371 | 372 | videojs.Dailymotion.prototype.supportsFullScreen = function () { 373 | return false; 374 | }; 375 | 376 | videojs.Dailymotion.canPlaySource = function (srcObj) { 377 | return (srcObj.type === 'video/dailymotion'); 378 | }; 379 | 380 | // All videos created before Dailymotion API is loaded 381 | videojs.Dailymotion.loadingQueue = []; 382 | 383 | 384 | videojs.Dailymotion.prototype.load = function () { 385 | }; 386 | 387 | // Create the Dailymotion player 388 | videojs.Dailymotion.prototype.loadApi = function () { 389 | 390 | this.dmPlayer = new DM.player(this.id_, { 391 | video: this.videoId, 392 | width: this.options.width, 393 | height: this.options.height, 394 | params: this.params 395 | }); 396 | 397 | 398 | this.setupTriggers(); 399 | 400 | this.dmPlayer.vjsTech = this; 401 | }; 402 | 403 | videojs.Dailymotion.prototype.onStateChange = function (event) { 404 | var state = event.type; 405 | if (state !== this.lastState) { 406 | switch (state) { 407 | case -1: 408 | this.player_.trigger('durationchange'); 409 | break; 410 | 411 | case 'apiready': 412 | this.onReady(); 413 | break; 414 | 415 | case 'ended': 416 | 417 | if (!this.player_.options().dmControls) { 418 | this.player_.bigPlayButton.show(); 419 | } 420 | break; 421 | 422 | case 'play': 423 | this.player_.trigger('play'); 424 | break; 425 | 426 | case 'playing': 427 | break; 428 | 429 | case 'pause': 430 | break; 431 | case 'durationchange': 432 | break; 433 | 434 | case 'timeupdate': 435 | // Hide the waiting spinner since Dailymotion has its own 436 | this.player_.loadingSpinner.hide(); 437 | break; 438 | case 'progress': 439 | break; 440 | 441 | } 442 | 443 | this.lastState = state; 444 | } 445 | }; 446 | 447 | videojs.Dailymotion.prototype.onError = function (error) { 448 | this.player_.error(error); 449 | 450 | if (error === 100 || error === 101 || error === 150) { 451 | this.player_.bigPlayButton.hide(); 452 | this.player_.loadingSpinner.hide(); 453 | this.player_.posterImage.hide(); 454 | } 455 | }; 456 | 457 | videojs.Dailymotion.makeQueryString = function (args) { 458 | var array = []; 459 | for (var key in args) { 460 | if (args.hasOwnProperty(key)) { 461 | array.push(encodeURIComponent(key) + '=' + encodeURIComponent(args[key])); 462 | } 463 | } 464 | 465 | return array.join('&'); 466 | }; 467 | 468 | videojs.Dailymotion.prototype.parseSrc = function (src) { 469 | this.srcVal = src; 470 | 471 | if (src) { 472 | // Regex that parse the video ID for any Dailymotion URL 473 | var regExp = /^.+dailymotion.com\/((video|hub)\/([^_]+))?[^#]*(#video=([^_&]+))?/; 474 | var match = src.match(regExp); 475 | 476 | return match ? match[5] || match[3] : null; 477 | } 478 | }; 479 | 480 | videojs.Dailymotion.parsePlaylist = function (src) { 481 | // Check if we have a playlist 482 | var regExp = /[?&]list=([^#\&\?]+)/; 483 | var match = src.match(regExp); 484 | 485 | if (match !== null && match.length > 1) { 486 | return match[1]; 487 | } 488 | }; 489 | 490 | // Make video events trigger player events 491 | // May seem verbose here, but makes other APIs possible. 492 | videojs.Dailymotion.prototype.setupTriggers = function () { 493 | this.dmPlayer.listeners = []; 494 | for (var i = videojs.Dailymotion.Events.length - 1; i >= 0; i--) { 495 | //videojs.on(this.dmPlayer, videojs.Dailymotion.Events[i], videojs.bind(this, this.eventHandler)); 496 | var listener = videojs.bind(this, this.eventHandler); 497 | this.dmPlayer.listeners.push({event: videojs.Dailymotion.Events[i], func: listener}); 498 | this.dmPlayer.addEventListener(videojs.Dailymotion.Events[i], listener); 499 | } 500 | }; 501 | // Triggers removed using this.off when disposed 502 | 503 | videojs.Dailymotion.prototype.eventHandler = function (e) { 504 | this.onStateChange(e); 505 | this.trigger(e); 506 | }; 507 | 508 | // List of all HTML5 events (various uses). 509 | videojs.Dailymotion.Events = ('apiready,play,playing,pause,ended,canplay,' + 510 | 'canplaythrough,timeupdate,progress,seeking,seeked,volumechange,durationchange,fullscreenchange,error').split(','); 511 | 512 | 513 | // Called when Dailymotion API is ready to be used 514 | window.dmAsyncInit = function () { 515 | var dm; 516 | while ((dm = videojs.Dailymotion.loadingQueue.shift())) { 517 | dm.loadApi(); 518 | } 519 | videojs.Dailymotion.loadingQueue = []; 520 | videojs.Dailymotion.apiReady = true; 521 | }; 522 | })(); 523 | -------------------------------------------------------------------------------- /es5/videojs-dailymotion.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Dailymotion.js 3 | * Dailymotion Media Controller - Wrapper for HTML5 Media API 4 | */ 5 | 'use strict'; 6 | 7 | Object.defineProperty(exports, '__esModule', { 8 | value: true 9 | }); 10 | 11 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 12 | 13 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 16 | 17 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 18 | 19 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 20 | 21 | var _videoJs = require('video.js'); 22 | 23 | var _videoJs2 = _interopRequireDefault(_videoJs); 24 | 25 | var Component = _videoJs2['default'].getComponent('Component'); 26 | var Tech = _videoJs2['default'].getComponent('Tech'); 27 | 28 | /** 29 | * Dailymotion Media Controller - Wrapper for HTML5 Media API 30 | * 31 | * @param {Object=} options Object of option names and values 32 | * @param {Function=} ready Ready callback function 33 | * @extends Tech 34 | * @class Dailymotion 35 | */ 36 | 37 | var Dailymotion = (function (_Tech) { 38 | _inherits(Dailymotion, _Tech); 39 | 40 | function Dailymotion(options, ready) { 41 | var _this = this; 42 | 43 | _classCallCheck(this, Dailymotion); 44 | 45 | _get(Object.getPrototypeOf(Dailymotion.prototype), 'constructor', this).call(this, options, ready); 46 | 47 | this.params = { 48 | id: this.options_.techId, 49 | autoplay: this.player_.options_.autoplay ? 1 : 0, 50 | chromeless: this.player_.options_.dmControls ? 0 : 1, 51 | html: 1, 52 | info: 1, 53 | logo: 1, 54 | controls: 'html', 55 | wmode: 'opaque', 56 | format: 'json', 57 | url: options.source.src 58 | }; 59 | 60 | // If we are not on a server, don't specify the origin (it will crash) 61 | if (window.location.protocol !== 'file:') { 62 | this.params.origin = window.location.protocol + '//' + window.location.hostname; 63 | } 64 | 65 | this.videoId = this.parseSrc(options.source.src); 66 | 67 | if (typeof this.videoId !== 'undefined') { 68 | this.setTimeout(function () { 69 | _this.setPoster('//api.dailymotion.com/video/' + _this.videoId + '?fields=poster_url&ads=false'); 70 | }, 100); 71 | } 72 | 73 | if (Dailymotion.isApiReady) { 74 | this.loadApi(); 75 | } else { 76 | // Add to the queue because the Dailymotion API is not ready 77 | Dailymotion.apiReadyQueue.push(this); 78 | } 79 | } 80 | 81 | _createClass(Dailymotion, [{ 82 | key: 'createEl', 83 | value: function createEl() { 84 | 85 | var el = _videoJs2['default'].createEl('iframe', { 86 | id: this.options_.techId, 87 | className: 'vjs-tech vjs-tech-dailymotion' 88 | }); 89 | 90 | var iframeContainer = _videoJs2['default'].createEl('iframe', { 91 | scrolling: 'no', 92 | marginWidth: 0, 93 | marginHeight: 0, 94 | frameBorder: 0, 95 | webkitAllowFullScreen: '', 96 | mozallowfullscreen: '', 97 | allowFullScreen: '' 98 | }); 99 | 100 | el.appendChild(iframeContainer); 101 | 102 | if (/MSIE (\d+\.\d+);/.test(navigator.userAgent) || !/(iPad|iPhone|iPod|Android)/g.test(navigator.userAgent)) { 103 | var divBlocker = _videoJs2['default'].createEl('div', { 104 | className: 'vjs-iframe-blocker', 105 | style: 'position:absolute;top:0;left:0;width:100%;height:100%' 106 | }); 107 | 108 | // In case the blocker is still there and we want to pause 109 | divBlocker.onclick = (function () { 110 | this.pause(); 111 | }).bind(this); 112 | 113 | el.appendChild(divBlocker); 114 | } 115 | 116 | return el; 117 | } 118 | }, { 119 | key: 'loadApi', 120 | value: function loadApi() { 121 | this.dmPlayer = new DM.player(this.options_.techId, { 122 | video: this.videoId, 123 | width: this.options_.width, 124 | height: this.options_.height, 125 | params: this.params 126 | }); 127 | 128 | this.setupTriggers(); 129 | 130 | this.dmPlayer.vjsTech = this; 131 | } 132 | }, { 133 | key: 'parseSrc', 134 | value: function parseSrc(src) { 135 | if (src) { 136 | // Regex that parse the video ID for any Dailymotion URL 137 | var regExp = /^.+dailymotion.com\/((video|hub)\/([^_]+))?[^#]*(#video=([^_&]+))?/; 138 | var match = src.match(regExp); 139 | 140 | return match ? match[5] || match[3] : null; 141 | } 142 | } 143 | }, { 144 | key: 'setupTriggers', 145 | value: function setupTriggers() { 146 | this.dmPlayer.listeners = []; 147 | for (var i = Dailymotion.Events.length - 1; i >= 0; i--) { 148 | //videojs.on(this.dmPlayer, Dailymotion.Events[i], videojs.bind(this, this.eventHandler)); 149 | var listener = _videoJs2['default'].bind(this, this.eventHandler); 150 | this.dmPlayer.listeners.push({ event: Dailymotion.Events[i], func: listener }); 151 | this.dmPlayer.addEventListener(Dailymotion.Events[i], listener); 152 | } 153 | } 154 | }, { 155 | key: 'eventHandler', 156 | value: function eventHandler(e) { 157 | this.onStateChange(e); 158 | this.trigger(e); 159 | } 160 | }, { 161 | key: 'onStateChange', 162 | value: function onStateChange(event) { 163 | var state = event.type; 164 | if (state !== this.lastState) { 165 | switch (state) { 166 | case -1: 167 | break; 168 | 169 | case 'apiready': 170 | this.triggerReady(); 171 | break; 172 | 173 | case 'video_end': 174 | this.trigger('ended'); 175 | break; 176 | 177 | case 'ad_play': 178 | this.trigger('play'); 179 | break; 180 | 181 | case 'video_start': 182 | case 'ad_start': 183 | this.trigger('playing'); 184 | this.trigger('play'); 185 | break; 186 | 187 | case 'play': 188 | break; 189 | 190 | case 'playing': 191 | break; 192 | 193 | case 'pause': 194 | break; 195 | case 'durationchange': 196 | break; 197 | 198 | case 'timeupdate': 199 | break; 200 | case 'progress': 201 | break; 202 | 203 | } 204 | 205 | this.lastState = state; 206 | } 207 | } 208 | }, { 209 | key: 'poster', 210 | value: function poster() { 211 | return this.poster_; 212 | } 213 | }, { 214 | key: 'setPoster', 215 | value: function setPoster(poster) { 216 | this.poster_ = poster; 217 | this.trigger('posterchange'); 218 | } 219 | 220 | /** 221 | * Set video 222 | * 223 | * @param {Object=} src Source object 224 | * @method setSrc 225 | */ 226 | }, { 227 | key: 'src', 228 | value: function src(_src) { 229 | if (typeof _src !== 'undefined') { 230 | this.src_ = this.parseSrc(_src); 231 | this.dmPlayer.load(this.src_); 232 | } 233 | return this.src_; 234 | } 235 | }, { 236 | key: 'currentSrc', 237 | value: function currentSrc() { 238 | return this.src_; 239 | } 240 | }, { 241 | key: 'play', 242 | value: function play() { 243 | if (this.isReady_) { 244 | this.dmPlayer.play(); 245 | } else { 246 | if (!this.player_.options_.dmControls) { 247 | // Keep the big play button until it plays for real 248 | this.player_.bigPlayButton.show(); 249 | } 250 | } 251 | } 252 | }, { 253 | key: 'ended', 254 | value: function ended() { 255 | 256 | if (this.isReady_) { 257 | var stateId = this.dmPlayer.getPlayerState(); 258 | return stateId === 0; 259 | } else { 260 | // We will play it when the API will be ready 261 | return false; 262 | } 263 | } 264 | }, { 265 | key: 'pause', 266 | value: function pause() { 267 | this.dmPlayer.pause(!this.dmPlayer.paused); 268 | } 269 | }, { 270 | key: 'paused', 271 | value: function paused() { 272 | return this.dmPlayer.paused; 273 | } 274 | }, { 275 | key: 'currentTime', 276 | value: function currentTime() { 277 | return this.dmPlayer && this.dmPlayer.currentTime ? this.dmPlayer.currentTime : 0; 278 | } 279 | }, { 280 | key: 'setCurrentTime', 281 | value: function setCurrentTime(position) { 282 | this.dmPlayer.seek(position); 283 | } 284 | }, { 285 | key: 'duration', 286 | value: function duration() { 287 | return this.dmPlayer && this.dmPlayer.duration ? this.dmPlayer.duration : 0; 288 | } 289 | }, { 290 | key: 'volume', 291 | value: function volume() { 292 | if (isNaN(this.volume_)) { 293 | this.volume_ = this.dmPlayer.volume; 294 | } 295 | 296 | return this.volume_; 297 | } 298 | 299 | /** 300 | * Request to enter fullscreen 301 | * 302 | * @method enterFullScreen 303 | */ 304 | }, { 305 | key: 'enterFullScreen', 306 | value: function enterFullScreen() { 307 | this.dmPlayer.setFullscreen(true); 308 | } 309 | 310 | /** 311 | * Request to exit fullscreen 312 | * 313 | * @method exitFullScreen 314 | */ 315 | }, { 316 | key: 'exitFullScreen', 317 | value: function exitFullScreen() { 318 | this.dmPlayer.setFullscreen(false); 319 | } 320 | }, { 321 | key: 'setVolume', 322 | value: function setVolume(percentAsDecimal) { 323 | if (typeof percentAsDecimal !== 'undefined' && percentAsDecimal !== this.volume_) { 324 | this.dmPlayer.setVolume(percentAsDecimal); 325 | this.volume_ = percentAsDecimal; 326 | this.player_.trigger('volumechange'); 327 | } 328 | } 329 | }, { 330 | key: 'buffered', 331 | value: function buffered() { 332 | return []; 333 | } 334 | }, { 335 | key: 'controls', 336 | value: function controls() { 337 | return false; 338 | } 339 | }, { 340 | key: 'muted', 341 | value: function muted() { 342 | return this.dmPlayer.muted; 343 | } 344 | }, { 345 | key: 'setMuted', 346 | value: function setMuted(muted) { 347 | this.dmPlayer.setMuted(muted); 348 | 349 | this.setTimeout(function () { 350 | this.player_.trigger('volumechange'); 351 | }); 352 | } 353 | }, { 354 | key: 'supportsFullScreen', 355 | value: function supportsFullScreen() { 356 | return true; 357 | } 358 | }, { 359 | key: 'resetSrc_', 360 | value: function resetSrc_(callback) { 361 | callback(); 362 | } 363 | }, { 364 | key: 'dispose', 365 | value: function dispose() { 366 | this.resetSrc_(Function.prototype); 367 | _get(Object.getPrototypeOf(Dailymotion.prototype), 'dispose', this).call(this, this); 368 | } 369 | }]); 370 | 371 | return Dailymotion; 372 | })(Tech); 373 | 374 | Dailymotion.prototype.options_ = {}; 375 | 376 | Dailymotion.apiReadyQueue = []; 377 | 378 | Dailymotion.makeQueryString = function (args) { 379 | var querys = []; 380 | for (var key in args) { 381 | if (args.hasOwnProperty(key)) { 382 | querys.push(encodeURIComponent(key) + '=' + encodeURIComponent(args[key])); 383 | } 384 | } 385 | 386 | return querys.join('&'); 387 | }; 388 | 389 | var injectJs = function injectJs() { 390 | var tag = document.createElement('script'); 391 | tag.src = '//api.dmcdn.net/all.js'; 392 | var firstScriptTag = document.getElementsByTagName('script')[0]; 393 | firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 394 | }; 395 | 396 | /* Dailymotion Support Testing -------------------------------------------------------- */ 397 | 398 | Dailymotion.isSupported = function () { 399 | return true; 400 | }; 401 | 402 | // Add Source Handler pattern functions to this tech 403 | Tech.withSourceHandlers(Dailymotion); 404 | 405 | /* 406 | * The default native source handler. 407 | * This simply passes the source to the video element. Nothing fancy. 408 | * 409 | * @param {Object} source The source object 410 | * @param {Flash} tech The instance of the Flash tech 411 | */ 412 | Dailymotion.nativeSourceHandler = {}; 413 | 414 | /** 415 | * Check if Flash can play the given videotype 416 | * @param {String} type The mimetype to check 417 | * @return {String} 'probably', 'maybe', or '' (empty string) 418 | */ 419 | Dailymotion.nativeSourceHandler.canPlayType = function (source) { 420 | 421 | var dashExtRE = /^video\/(dailymotion)/i; 422 | 423 | if (dashExtRE.test(source)) { 424 | return 'maybe'; 425 | } else { 426 | return ''; 427 | } 428 | }; 429 | 430 | /* 431 | * Check Flash can handle the source natively 432 | * 433 | * @param {Object} source The source object 434 | * @return {String} 'probably', 'maybe', or '' (empty string) 435 | */ 436 | Dailymotion.nativeSourceHandler.canHandleSource = function (source) { 437 | 438 | // If a type was provided we should rely on that 439 | if (source.type) { 440 | return Dailymotion.nativeSourceHandler.canPlayType(source.type); 441 | } else if (source.src) { 442 | return Dailymotion.nativeSourceHandler.canPlayType(source.src); 443 | } 444 | 445 | return ''; 446 | }; 447 | 448 | /* 449 | * Pass the source to the flash object 450 | * Adaptive source handlers will have more complicated workflows before passing 451 | * video data to the video element 452 | * 453 | * @param {Object} source The source object 454 | * @param {Flash} tech The instance of the Flash tech 455 | */ 456 | Dailymotion.nativeSourceHandler.handleSource = function (source, tech) { 457 | tech.src(source.src); 458 | }; 459 | 460 | /* 461 | * Clean up the source handler when disposing the player or switching sources.. 462 | * (no cleanup is needed when supporting the format natively) 463 | */ 464 | Dailymotion.nativeSourceHandler.dispose = function () {}; 465 | 466 | // Register the native source handler 467 | Dailymotion.registerSourceHandler(Dailymotion.nativeSourceHandler); 468 | 469 | /* 470 | * Set the tech's volume control support status 471 | * 472 | * @type {Boolean} 473 | */ 474 | Dailymotion.prototype['featuresVolumeControl'] = true; 475 | 476 | /* 477 | * Set the tech's playbackRate support status 478 | * 479 | * @type {Boolean} 480 | */ 481 | Dailymotion.prototype['featuresPlaybackRate'] = false; 482 | 483 | /* 484 | * Set the tech's status on moving the video element. 485 | * In iOS, if you move a video element in the DOM, it breaks video playback. 486 | * 487 | * @type {Boolean} 488 | */ 489 | Dailymotion.prototype['movingMediaElementInDOM'] = false; 490 | 491 | /* 492 | * Set the the tech's fullscreen resize support status. 493 | * HTML video is able to automatically resize when going to fullscreen. 494 | * (No longer appears to be used. Can probably be removed.) 495 | */ 496 | Dailymotion.prototype['featuresFullscreenResize'] = false; 497 | 498 | /* 499 | * Set the tech's timeupdate event support status 500 | * (this disables the manual timeupdate events of the Tech) 501 | */ 502 | Dailymotion.prototype['featuresTimeupdateEvents'] = false; 503 | 504 | /* 505 | * Set the tech's progress event support status 506 | * (this disables the manual progress events of the Tech) 507 | */ 508 | Dailymotion.prototype['featuresProgressEvents'] = false; 509 | 510 | /* 511 | * Sets the tech's status on native text track support 512 | * 513 | * @type {Boolean} 514 | */ 515 | Dailymotion.prototype['featuresNativeTextTracks'] = true; 516 | 517 | /* 518 | * Sets the tech's status on native audio track support 519 | * 520 | * @type {Boolean} 521 | */ 522 | Dailymotion.prototype['featuresNativeAudioTracks'] = true; 523 | 524 | /* 525 | * Sets the tech's status on native video track support 526 | * 527 | * @type {Boolean} 528 | */ 529 | Dailymotion.prototype['featuresNativeVideoTracks'] = false; 530 | 531 | Dailymotion.Events = 'apiready,ad_play,ad_start,ad_timeupdate,ad_pause,ad_end,video_start,video_end,play,playing,pause,ended,canplay,canplaythrough,timeupdate,progress,seeking,seeked,volumechange,durationchange,fullscreenchange,error'.split(','); 532 | 533 | _videoJs2['default'].options.Dailymotion = {}; 534 | 535 | Component.registerComponent('Dailymotion', Dailymotion); 536 | Tech.registerTech('Dailymotion', Dailymotion); 537 | 538 | injectJs(); 539 | 540 | // Called when Dailymotion API is ready to be used 541 | window.dmAsyncInit = function () { 542 | var dm; 543 | while (dm = Dailymotion.apiReadyQueue.shift()) { 544 | dm.loadApi(); 545 | } 546 | Dailymotion.apiReadyQueue = []; 547 | Dailymotion.isApiReady = true; 548 | }; 549 | 550 | exports['default'] = Dailymotion; 551 | module.exports = exports['default']; -------------------------------------------------------------------------------- /dist-test/videojs-dailymotion.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; 384 | }; 385 | 386 | /** 387 | * Test boolean. 388 | */ 389 | 390 | /** 391 | * is.bool 392 | * Test if `value` is a boolean. 393 | * 394 | * @param {Mixed} value value to test 395 | * @return {Boolean} true if `value` is a boolean, false otherwise 396 | * @api public 397 | */ 398 | 399 | is.bool = is['boolean'] = function (value) { 400 | return toStr.call(value) === '[object Boolean]'; 401 | }; 402 | 403 | /** 404 | * is.false 405 | * Test if `value` is false. 406 | * 407 | * @param {Mixed} value value to test 408 | * @return {Boolean} true if `value` is false, false otherwise 409 | * @api public 410 | */ 411 | 412 | is['false'] = function (value) { 413 | return is.bool(value) && Boolean(Number(value)) === false; 414 | }; 415 | 416 | /** 417 | * is.true 418 | * Test if `value` is true. 419 | * 420 | * @param {Mixed} value value to test 421 | * @return {Boolean} true if `value` is true, false otherwise 422 | * @api public 423 | */ 424 | 425 | is['true'] = function (value) { 426 | return is.bool(value) && Boolean(Number(value)) === true; 427 | }; 428 | 429 | /** 430 | * Test date. 431 | */ 432 | 433 | /** 434 | * is.date 435 | * Test if `value` is a date. 436 | * 437 | * @param {Mixed} value value to test 438 | * @return {Boolean} true if `value` is a date, false otherwise 439 | * @api public 440 | */ 441 | 442 | is.date = function (value) { 443 | return toStr.call(value) === '[object Date]'; 444 | }; 445 | 446 | /** 447 | * Test element. 448 | */ 449 | 450 | /** 451 | * is.element 452 | * Test if `value` is an html element. 453 | * 454 | * @param {Mixed} value value to test 455 | * @return {Boolean} true if `value` is an HTML Element, false otherwise 456 | * @api public 457 | */ 458 | 459 | is.element = function (value) { 460 | return value !== undefined 461 | && typeof HTMLElement !== 'undefined' 462 | && value instanceof HTMLElement 463 | && value.nodeType === 1; 464 | }; 465 | 466 | /** 467 | * Test error. 468 | */ 469 | 470 | /** 471 | * is.error 472 | * Test if `value` is an error object. 473 | * 474 | * @param {Mixed} value value to test 475 | * @return {Boolean} true if `value` is an error object, false otherwise 476 | * @api public 477 | */ 478 | 479 | is.error = function (value) { 480 | return toStr.call(value) === '[object Error]'; 481 | }; 482 | 483 | /** 484 | * Test function. 485 | */ 486 | 487 | /** 488 | * is.fn / is.function (deprecated) 489 | * Test if `value` is a function. 490 | * 491 | * @param {Mixed} value value to test 492 | * @return {Boolean} true if `value` is a function, false otherwise 493 | * @api public 494 | */ 495 | 496 | is.fn = is['function'] = function (value) { 497 | var isAlert = typeof window !== 'undefined' && value === window.alert; 498 | return isAlert || toStr.call(value) === '[object Function]'; 499 | }; 500 | 501 | /** 502 | * Test number. 503 | */ 504 | 505 | /** 506 | * is.number 507 | * Test if `value` is a number. 508 | * 509 | * @param {Mixed} value value to test 510 | * @return {Boolean} true if `value` is a number, false otherwise 511 | * @api public 512 | */ 513 | 514 | is.number = function (value) { 515 | return toStr.call(value) === '[object Number]'; 516 | }; 517 | 518 | /** 519 | * is.infinite 520 | * Test if `value` is positive or negative infinity. 521 | * 522 | * @param {Mixed} value value to test 523 | * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise 524 | * @api public 525 | */ 526 | is.infinite = function (value) { 527 | return value === Infinity || value === -Infinity; 528 | }; 529 | 530 | /** 531 | * is.decimal 532 | * Test if `value` is a decimal number. 533 | * 534 | * @param {Mixed} value value to test 535 | * @return {Boolean} true if `value` is a decimal number, false otherwise 536 | * @api public 537 | */ 538 | 539 | is.decimal = function (value) { 540 | return is.number(value) && !isActualNaN(value) && !is.infinite(value) && value % 1 !== 0; 541 | }; 542 | 543 | /** 544 | * is.divisibleBy 545 | * Test if `value` is divisible by `n`. 546 | * 547 | * @param {Number} value value to test 548 | * @param {Number} n dividend 549 | * @return {Boolean} true if `value` is divisible by `n`, false otherwise 550 | * @api public 551 | */ 552 | 553 | is.divisibleBy = function (value, n) { 554 | var isDividendInfinite = is.infinite(value); 555 | var isDivisorInfinite = is.infinite(n); 556 | var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0; 557 | return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0); 558 | }; 559 | 560 | /** 561 | * is.integer 562 | * Test if `value` is an integer. 563 | * 564 | * @param value to test 565 | * @return {Boolean} true if `value` is an integer, false otherwise 566 | * @api public 567 | */ 568 | 569 | is.integer = is['int'] = function (value) { 570 | return is.number(value) && !isActualNaN(value) && value % 1 === 0; 571 | }; 572 | 573 | /** 574 | * is.maximum 575 | * Test if `value` is greater than 'others' values. 576 | * 577 | * @param {Number} value value to test 578 | * @param {Array} others values to compare with 579 | * @return {Boolean} true if `value` is greater than `others` values 580 | * @api public 581 | */ 582 | 583 | is.maximum = function (value, others) { 584 | if (isActualNaN(value)) { 585 | throw new TypeError('NaN is not a valid value'); 586 | } else if (!is.arraylike(others)) { 587 | throw new TypeError('second argument must be array-like'); 588 | } 589 | var len = others.length; 590 | 591 | while (--len >= 0) { 592 | if (value < others[len]) { 593 | return false; 594 | } 595 | } 596 | 597 | return true; 598 | }; 599 | 600 | /** 601 | * is.minimum 602 | * Test if `value` is less than `others` values. 603 | * 604 | * @param {Number} value value to test 605 | * @param {Array} others values to compare with 606 | * @return {Boolean} true if `value` is less than `others` values 607 | * @api public 608 | */ 609 | 610 | is.minimum = function (value, others) { 611 | if (isActualNaN(value)) { 612 | throw new TypeError('NaN is not a valid value'); 613 | } else if (!is.arraylike(others)) { 614 | throw new TypeError('second argument must be array-like'); 615 | } 616 | var len = others.length; 617 | 618 | while (--len >= 0) { 619 | if (value > others[len]) { 620 | return false; 621 | } 622 | } 623 | 624 | return true; 625 | }; 626 | 627 | /** 628 | * is.nan 629 | * Test if `value` is not a number. 630 | * 631 | * @param {Mixed} value value to test 632 | * @return {Boolean} true if `value` is not a number, false otherwise 633 | * @api public 634 | */ 635 | 636 | is.nan = function (value) { 637 | return !is.number(value) || value !== value; 638 | }; 639 | 640 | /** 641 | * is.even 642 | * Test if `value` is an even number. 643 | * 644 | * @param {Number} value value to test 645 | * @return {Boolean} true if `value` is an even number, false otherwise 646 | * @api public 647 | */ 648 | 649 | is.even = function (value) { 650 | return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0); 651 | }; 652 | 653 | /** 654 | * is.odd 655 | * Test if `value` is an odd number. 656 | * 657 | * @param {Number} value value to test 658 | * @return {Boolean} true if `value` is an odd number, false otherwise 659 | * @api public 660 | */ 661 | 662 | is.odd = function (value) { 663 | return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0); 664 | }; 665 | 666 | /** 667 | * is.ge 668 | * Test if `value` is greater than or equal to `other`. 669 | * 670 | * @param {Number} value value to test 671 | * @param {Number} other value to compare with 672 | * @return {Boolean} 673 | * @api public 674 | */ 675 | 676 | is.ge = function (value, other) { 677 | if (isActualNaN(value) || isActualNaN(other)) { 678 | throw new TypeError('NaN is not a valid value'); 679 | } 680 | return !is.infinite(value) && !is.infinite(other) && value >= other; 681 | }; 682 | 683 | /** 684 | * is.gt 685 | * Test if `value` is greater than `other`. 686 | * 687 | * @param {Number} value value to test 688 | * @param {Number} other value to compare with 689 | * @return {Boolean} 690 | * @api public 691 | */ 692 | 693 | is.gt = function (value, other) { 694 | if (isActualNaN(value) || isActualNaN(other)) { 695 | throw new TypeError('NaN is not a valid value'); 696 | } 697 | return !is.infinite(value) && !is.infinite(other) && value > other; 698 | }; 699 | 700 | /** 701 | * is.le 702 | * Test if `value` is less than or equal to `other`. 703 | * 704 | * @param {Number} value value to test 705 | * @param {Number} other value to compare with 706 | * @return {Boolean} if 'value' is less than or equal to 'other' 707 | * @api public 708 | */ 709 | 710 | is.le = function (value, other) { 711 | if (isActualNaN(value) || isActualNaN(other)) { 712 | throw new TypeError('NaN is not a valid value'); 713 | } 714 | return !is.infinite(value) && !is.infinite(other) && value <= other; 715 | }; 716 | 717 | /** 718 | * is.lt 719 | * Test if `value` is less than `other`. 720 | * 721 | * @param {Number} value value to test 722 | * @param {Number} other value to compare with 723 | * @return {Boolean} if `value` is less than `other` 724 | * @api public 725 | */ 726 | 727 | is.lt = function (value, other) { 728 | if (isActualNaN(value) || isActualNaN(other)) { 729 | throw new TypeError('NaN is not a valid value'); 730 | } 731 | return !is.infinite(value) && !is.infinite(other) && value < other; 732 | }; 733 | 734 | /** 735 | * is.within 736 | * Test if `value` is within `start` and `finish`. 737 | * 738 | * @param {Number} value value to test 739 | * @param {Number} start lower bound 740 | * @param {Number} finish upper bound 741 | * @return {Boolean} true if 'value' is is within 'start' and 'finish' 742 | * @api public 743 | */ 744 | is.within = function (value, start, finish) { 745 | if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) { 746 | throw new TypeError('NaN is not a valid value'); 747 | } else if (!is.number(value) || !is.number(start) || !is.number(finish)) { 748 | throw new TypeError('all arguments must be numbers'); 749 | } 750 | var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish); 751 | return isAnyInfinite || (value >= start && value <= finish); 752 | }; 753 | 754 | /** 755 | * Test object. 756 | */ 757 | 758 | /** 759 | * is.object 760 | * Test if `value` is an object. 761 | * 762 | * @param {Mixed} value value to test 763 | * @return {Boolean} true if `value` is an object, false otherwise 764 | * @api public 765 | */ 766 | 767 | is.object = function (value) { 768 | return toStr.call(value) === '[object Object]'; 769 | }; 770 | 771 | /** 772 | * is.hash 773 | * Test if `value` is a hash - a plain object literal. 774 | * 775 | * @param {Mixed} value value to test 776 | * @return {Boolean} true if `value` is a hash, false otherwise 777 | * @api public 778 | */ 779 | 780 | is.hash = function (value) { 781 | return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval; 782 | }; 783 | 784 | /** 785 | * Test regexp. 786 | */ 787 | 788 | /** 789 | * is.regexp 790 | * Test if `value` is a regular expression. 791 | * 792 | * @param {Mixed} value value to test 793 | * @return {Boolean} true if `value` is a regexp, false otherwise 794 | * @api public 795 | */ 796 | 797 | is.regexp = function (value) { 798 | return toStr.call(value) === '[object RegExp]'; 799 | }; 800 | 801 | /** 802 | * Test string. 803 | */ 804 | 805 | /** 806 | * is.string 807 | * Test if `value` is a string. 808 | * 809 | * @param {Mixed} value value to test 810 | * @return {Boolean} true if 'value' is a string, false otherwise 811 | * @api public 812 | */ 813 | 814 | is.string = function (value) { 815 | return toStr.call(value) === '[object String]'; 816 | }; 817 | 818 | /** 819 | * Test base64 string. 820 | */ 821 | 822 | /** 823 | * is.base64 824 | * Test if `value` is a valid base64 encoded string. 825 | * 826 | * @param {Mixed} value value to test 827 | * @return {Boolean} true if 'value' is a base64 encoded string, false otherwise 828 | * @api public 829 | */ 830 | 831 | is.base64 = function (value) { 832 | return is.string(value) && (!value.length || base64Regex.test(value)); 833 | }; 834 | 835 | /** 836 | * Test base64 string. 837 | */ 838 | 839 | /** 840 | * is.hex 841 | * Test if `value` is a valid hex encoded string. 842 | * 843 | * @param {Mixed} value value to test 844 | * @return {Boolean} true if 'value' is a hex encoded string, false otherwise 845 | * @api public 846 | */ 847 | 848 | is.hex = function (value) { 849 | return is.string(value) && (!value.length || hexRegex.test(value)); 850 | }; 851 | 852 | /** 853 | * is.symbol 854 | * Test if `value` is an ES6 Symbol 855 | * 856 | * @param {Mixed} value value to test 857 | * @return {Boolean} true if `value` is a Symbol, false otherise 858 | * @api public 859 | */ 860 | 861 | is.symbol = function (value) { 862 | return typeof Symbol === 'function' && toStr.call(value) === '[object Symbol]' && typeof symbolValueOf.call(value) === 'symbol'; 863 | }; 864 | 865 | },{}],5:[function(require,module,exports){ 866 | (function (global){ 867 | 'use strict'; 868 | 869 | Object.defineProperty(exports, '__esModule', { 870 | value: true 871 | }); 872 | 873 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 874 | 875 | var _videoJs = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null); 876 | 877 | var _videoJs2 = _interopRequireDefault(_videoJs); 878 | 879 | var _videojsDailymotion = require('./videojs-dailymotion'); 880 | 881 | var _videojsDailymotion2 = _interopRequireDefault(_videojsDailymotion); 882 | 883 | /** 884 | * The video.js Dailymotion plugin. 885 | * 886 | * @param {Object} options 887 | */ 888 | var plugin = function plugin(options) { 889 | dailymotion(this, options); 890 | }; 891 | 892 | _videoJs2['default'].plugin('dailymotion', plugin); 893 | 894 | exports['default'] = plugin; 895 | module.exports = exports['default']; 896 | 897 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 898 | },{"./videojs-dailymotion":6}],6:[function(require,module,exports){ 899 | (function (global){ 900 | /** 901 | * @file Dailymotion.js 902 | * Dailymotion Media Controller - Wrapper for HTML5 Media API 903 | */ 904 | 'use strict'; 905 | 906 | Object.defineProperty(exports, '__esModule', { 907 | value: true 908 | }); 909 | 910 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); 911 | 912 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 913 | 914 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 915 | 916 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 917 | 918 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 919 | 920 | var _videoJs = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null); 921 | 922 | var _videoJs2 = _interopRequireDefault(_videoJs); 923 | 924 | var Component = _videoJs2['default'].getComponent('Component'); 925 | var Tech = _videoJs2['default'].getComponent('Tech'); 926 | 927 | /** 928 | * Dailymotion Media Controller - Wrapper for HTML5 Media API 929 | * 930 | * @param {Object=} options Object of option names and values 931 | * @param {Function=} ready Ready callback function 932 | * @extends Tech 933 | * @class Dailymotion 934 | */ 935 | 936 | var Dailymotion = (function (_Tech) { 937 | _inherits(Dailymotion, _Tech); 938 | 939 | function Dailymotion(options, ready) { 940 | var _this = this; 941 | 942 | _classCallCheck(this, Dailymotion); 943 | 944 | _get(Object.getPrototypeOf(Dailymotion.prototype), 'constructor', this).call(this, options, ready); 945 | 946 | this.params = { 947 | id: this.options_.techId, 948 | autoplay: this.player_.options_.autoplay ? 1 : 0, 949 | chromeless: this.player_.options_.dmControls ? 0 : 1, 950 | html: 1, 951 | info: 1, 952 | logo: 1, 953 | controls: 'html', 954 | wmode: 'opaque', 955 | format: 'json', 956 | url: options.source.src 957 | }; 958 | 959 | // If we are not on a server, don't specify the origin (it will crash) 960 | if (window.location.protocol !== 'file:') { 961 | this.params.origin = window.location.protocol + '//' + window.location.hostname; 962 | } 963 | 964 | this.videoId = this.parseSrc(options.source.src); 965 | 966 | if (typeof this.videoId !== 'undefined') { 967 | this.setTimeout(function () { 968 | _this.setPoster('//api.dailymotion.com/video/' + _this.videoId + '?fields=poster_url&ads=false'); 969 | }, 100); 970 | } 971 | 972 | if (Dailymotion.isApiReady) { 973 | this.loadApi(); 974 | } else { 975 | // Add to the queue because the Dailymotion API is not ready 976 | Dailymotion.apiReadyQueue.push(this); 977 | } 978 | } 979 | 980 | _createClass(Dailymotion, [{ 981 | key: 'createEl', 982 | value: function createEl() { 983 | 984 | var el = _videoJs2['default'].createEl('iframe', { 985 | id: this.options_.techId, 986 | className: 'vjs-tech vjs-tech-dailymotion' 987 | }); 988 | 989 | var iframeContainer = _videoJs2['default'].createEl('iframe', { 990 | scrolling: 'no', 991 | marginWidth: 0, 992 | marginHeight: 0, 993 | frameBorder: 0, 994 | webkitAllowFullScreen: '', 995 | mozallowfullscreen: '', 996 | allowFullScreen: '' 997 | }); 998 | 999 | el.appendChild(iframeContainer); 1000 | 1001 | if (/MSIE (\d+\.\d+);/.test(navigator.userAgent) || !/(iPad|iPhone|iPod|Android)/g.test(navigator.userAgent)) { 1002 | var divBlocker = _videoJs2['default'].createEl('div', { 1003 | className: 'vjs-iframe-blocker', 1004 | style: 'position:absolute;top:0;left:0;width:100%;height:100%' 1005 | }); 1006 | 1007 | // In case the blocker is still there and we want to pause 1008 | divBlocker.onclick = (function () { 1009 | this.pause(); 1010 | }).bind(this); 1011 | 1012 | el.appendChild(divBlocker); 1013 | } 1014 | 1015 | return el; 1016 | } 1017 | }, { 1018 | key: 'loadApi', 1019 | value: function loadApi() { 1020 | this.dmPlayer = new DM.player(this.options_.techId, { 1021 | video: this.videoId, 1022 | width: this.options_.width, 1023 | height: this.options_.height, 1024 | params: this.params 1025 | }); 1026 | 1027 | this.setupTriggers(); 1028 | 1029 | this.dmPlayer.vjsTech = this; 1030 | } 1031 | }, { 1032 | key: 'parseSrc', 1033 | value: function parseSrc(src) { 1034 | if (src) { 1035 | // Regex that parse the video ID for any Dailymotion URL 1036 | var regExp = /^.+dailymotion.com\/((video|hub)\/([^_]+))?[^#]*(#video=([^_&]+))?/; 1037 | var match = src.match(regExp); 1038 | 1039 | return match ? match[5] || match[3] : null; 1040 | } 1041 | } 1042 | }, { 1043 | key: 'setupTriggers', 1044 | value: function setupTriggers() { 1045 | this.dmPlayer.listeners = []; 1046 | for (var i = Dailymotion.Events.length - 1; i >= 0; i--) { 1047 | //videojs.on(this.dmPlayer, Dailymotion.Events[i], videojs.bind(this, this.eventHandler)); 1048 | var listener = _videoJs2['default'].bind(this, this.eventHandler); 1049 | this.dmPlayer.listeners.push({ event: Dailymotion.Events[i], func: listener }); 1050 | this.dmPlayer.addEventListener(Dailymotion.Events[i], listener); 1051 | } 1052 | } 1053 | }, { 1054 | key: 'eventHandler', 1055 | value: function eventHandler(e) { 1056 | this.onStateChange(e); 1057 | this.trigger(e); 1058 | } 1059 | }, { 1060 | key: 'onStateChange', 1061 | value: function onStateChange(event) { 1062 | var state = event.type; 1063 | if (state !== this.lastState) { 1064 | switch (state) { 1065 | case -1: 1066 | break; 1067 | 1068 | case 'apiready': 1069 | this.triggerReady(); 1070 | break; 1071 | 1072 | case 'video_end': 1073 | this.trigger('ended'); 1074 | break; 1075 | 1076 | case 'ad_play': 1077 | this.trigger('play'); 1078 | break; 1079 | 1080 | case 'video_start': 1081 | case 'ad_start': 1082 | this.trigger('playing'); 1083 | this.trigger('play'); 1084 | break; 1085 | 1086 | case 'play': 1087 | break; 1088 | 1089 | case 'playing': 1090 | break; 1091 | 1092 | case 'pause': 1093 | break; 1094 | case 'durationchange': 1095 | break; 1096 | 1097 | case 'timeupdate': 1098 | break; 1099 | case 'progress': 1100 | break; 1101 | 1102 | } 1103 | 1104 | this.lastState = state; 1105 | } 1106 | } 1107 | }, { 1108 | key: 'poster', 1109 | value: function poster() { 1110 | return this.poster_; 1111 | } 1112 | }, { 1113 | key: 'setPoster', 1114 | value: function setPoster(poster) { 1115 | this.poster_ = poster; 1116 | this.trigger('posterchange'); 1117 | } 1118 | 1119 | /** 1120 | * Set video 1121 | * 1122 | * @param {Object=} src Source object 1123 | * @method setSrc 1124 | */ 1125 | }, { 1126 | key: 'src', 1127 | value: function src(_src) { 1128 | if (typeof _src !== 'undefined') { 1129 | this.src_ = this.parseSrc(_src); 1130 | this.dmPlayer.load(this.src_); 1131 | } 1132 | return this.src_; 1133 | } 1134 | }, { 1135 | key: 'currentSrc', 1136 | value: function currentSrc() { 1137 | return this.src_; 1138 | } 1139 | }, { 1140 | key: 'play', 1141 | value: function play() { 1142 | if (this.isReady_) { 1143 | this.dmPlayer.play(); 1144 | } else { 1145 | if (!this.player_.options_.dmControls) { 1146 | // Keep the big play button until it plays for real 1147 | this.player_.bigPlayButton.show(); 1148 | } 1149 | } 1150 | } 1151 | }, { 1152 | key: 'ended', 1153 | value: function ended() { 1154 | 1155 | if (this.isReady_) { 1156 | var stateId = this.dmPlayer.getPlayerState(); 1157 | return stateId === 0; 1158 | } else { 1159 | // We will play it when the API will be ready 1160 | return false; 1161 | } 1162 | } 1163 | }, { 1164 | key: 'pause', 1165 | value: function pause() { 1166 | this.dmPlayer.pause(!this.dmPlayer.paused); 1167 | } 1168 | }, { 1169 | key: 'paused', 1170 | value: function paused() { 1171 | return this.dmPlayer.paused; 1172 | } 1173 | }, { 1174 | key: 'currentTime', 1175 | value: function currentTime() { 1176 | return this.dmPlayer && this.dmPlayer.currentTime ? this.dmPlayer.currentTime : 0; 1177 | } 1178 | }, { 1179 | key: 'setCurrentTime', 1180 | value: function setCurrentTime(position) { 1181 | this.dmPlayer.seek(position); 1182 | } 1183 | }, { 1184 | key: 'duration', 1185 | value: function duration() { 1186 | return this.dmPlayer && this.dmPlayer.duration ? this.dmPlayer.duration : 0; 1187 | } 1188 | }, { 1189 | key: 'volume', 1190 | value: function volume() { 1191 | if (isNaN(this.volume_)) { 1192 | this.volume_ = this.dmPlayer.volume; 1193 | } 1194 | 1195 | return this.volume_; 1196 | } 1197 | 1198 | /** 1199 | * Request to enter fullscreen 1200 | * 1201 | * @method enterFullScreen 1202 | */ 1203 | }, { 1204 | key: 'enterFullScreen', 1205 | value: function enterFullScreen() { 1206 | this.dmPlayer.setFullscreen(true); 1207 | } 1208 | 1209 | /** 1210 | * Request to exit fullscreen 1211 | * 1212 | * @method exitFullScreen 1213 | */ 1214 | }, { 1215 | key: 'exitFullScreen', 1216 | value: function exitFullScreen() { 1217 | this.dmPlayer.setFullscreen(false); 1218 | } 1219 | }, { 1220 | key: 'setVolume', 1221 | value: function setVolume(percentAsDecimal) { 1222 | if (typeof percentAsDecimal !== 'undefined' && percentAsDecimal !== this.volume_) { 1223 | this.dmPlayer.setVolume(percentAsDecimal); 1224 | this.volume_ = percentAsDecimal; 1225 | this.player_.trigger('volumechange'); 1226 | } 1227 | } 1228 | }, { 1229 | key: 'buffered', 1230 | value: function buffered() { 1231 | return []; 1232 | } 1233 | }, { 1234 | key: 'controls', 1235 | value: function controls() { 1236 | return false; 1237 | } 1238 | }, { 1239 | key: 'muted', 1240 | value: function muted() { 1241 | return this.dmPlayer.muted; 1242 | } 1243 | }, { 1244 | key: 'setMuted', 1245 | value: function setMuted(muted) { 1246 | this.dmPlayer.setMuted(muted); 1247 | 1248 | this.setTimeout(function () { 1249 | this.player_.trigger('volumechange'); 1250 | }); 1251 | } 1252 | }, { 1253 | key: 'supportsFullScreen', 1254 | value: function supportsFullScreen() { 1255 | return true; 1256 | } 1257 | }, { 1258 | key: 'resetSrc_', 1259 | value: function resetSrc_(callback) { 1260 | callback(); 1261 | } 1262 | }, { 1263 | key: 'dispose', 1264 | value: function dispose() { 1265 | this.resetSrc_(Function.prototype); 1266 | _get(Object.getPrototypeOf(Dailymotion.prototype), 'dispose', this).call(this, this); 1267 | } 1268 | }]); 1269 | 1270 | return Dailymotion; 1271 | })(Tech); 1272 | 1273 | Dailymotion.prototype.options_ = {}; 1274 | 1275 | Dailymotion.apiReadyQueue = []; 1276 | 1277 | Dailymotion.makeQueryString = function (args) { 1278 | var querys = []; 1279 | for (var key in args) { 1280 | if (args.hasOwnProperty(key)) { 1281 | querys.push(encodeURIComponent(key) + '=' + encodeURIComponent(args[key])); 1282 | } 1283 | } 1284 | 1285 | return querys.join('&'); 1286 | }; 1287 | 1288 | var injectJs = function injectJs() { 1289 | var tag = document.createElement('script'); 1290 | tag.src = '//api.dmcdn.net/all.js'; 1291 | var firstScriptTag = document.getElementsByTagName('script')[0]; 1292 | firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 1293 | }; 1294 | 1295 | /* Dailymotion Support Testing -------------------------------------------------------- */ 1296 | 1297 | Dailymotion.isSupported = function () { 1298 | return true; 1299 | }; 1300 | 1301 | // Add Source Handler pattern functions to this tech 1302 | Tech.withSourceHandlers(Dailymotion); 1303 | 1304 | /* 1305 | * The default native source handler. 1306 | * This simply passes the source to the video element. Nothing fancy. 1307 | * 1308 | * @param {Object} source The source object 1309 | * @param {Flash} tech The instance of the Flash tech 1310 | */ 1311 | Dailymotion.nativeSourceHandler = {}; 1312 | 1313 | /** 1314 | * Check if Flash can play the given videotype 1315 | * @param {String} type The mimetype to check 1316 | * @return {String} 'probably', 'maybe', or '' (empty string) 1317 | */ 1318 | Dailymotion.nativeSourceHandler.canPlayType = function (source) { 1319 | 1320 | var dashExtRE = /^video\/(dailymotion)/i; 1321 | 1322 | if (dashExtRE.test(source)) { 1323 | return 'maybe'; 1324 | } else { 1325 | return ''; 1326 | } 1327 | }; 1328 | 1329 | /* 1330 | * Check Flash can handle the source natively 1331 | * 1332 | * @param {Object} source The source object 1333 | * @return {String} 'probably', 'maybe', or '' (empty string) 1334 | */ 1335 | Dailymotion.nativeSourceHandler.canHandleSource = function (source) { 1336 | 1337 | // If a type was provided we should rely on that 1338 | if (source.type) { 1339 | return Dailymotion.nativeSourceHandler.canPlayType(source.type); 1340 | } else if (source.src) { 1341 | return Dailymotion.nativeSourceHandler.canPlayType(source.src); 1342 | } 1343 | 1344 | return ''; 1345 | }; 1346 | 1347 | /* 1348 | * Pass the source to the flash object 1349 | * Adaptive source handlers will have more complicated workflows before passing 1350 | * video data to the video element 1351 | * 1352 | * @param {Object} source The source object 1353 | * @param {Flash} tech The instance of the Flash tech 1354 | */ 1355 | Dailymotion.nativeSourceHandler.handleSource = function (source, tech) { 1356 | tech.src(source.src); 1357 | }; 1358 | 1359 | /* 1360 | * Clean up the source handler when disposing the player or switching sources.. 1361 | * (no cleanup is needed when supporting the format natively) 1362 | */ 1363 | Dailymotion.nativeSourceHandler.dispose = function () {}; 1364 | 1365 | // Register the native source handler 1366 | Dailymotion.registerSourceHandler(Dailymotion.nativeSourceHandler); 1367 | 1368 | /* 1369 | * Set the tech's volume control support status 1370 | * 1371 | * @type {Boolean} 1372 | */ 1373 | Dailymotion.prototype['featuresVolumeControl'] = true; 1374 | 1375 | /* 1376 | * Set the tech's playbackRate support status 1377 | * 1378 | * @type {Boolean} 1379 | */ 1380 | Dailymotion.prototype['featuresPlaybackRate'] = false; 1381 | 1382 | /* 1383 | * Set the tech's status on moving the video element. 1384 | * In iOS, if you move a video element in the DOM, it breaks video playback. 1385 | * 1386 | * @type {Boolean} 1387 | */ 1388 | Dailymotion.prototype['movingMediaElementInDOM'] = false; 1389 | 1390 | /* 1391 | * Set the the tech's fullscreen resize support status. 1392 | * HTML video is able to automatically resize when going to fullscreen. 1393 | * (No longer appears to be used. Can probably be removed.) 1394 | */ 1395 | Dailymotion.prototype['featuresFullscreenResize'] = false; 1396 | 1397 | /* 1398 | * Set the tech's timeupdate event support status 1399 | * (this disables the manual timeupdate events of the Tech) 1400 | */ 1401 | Dailymotion.prototype['featuresTimeupdateEvents'] = false; 1402 | 1403 | /* 1404 | * Set the tech's progress event support status 1405 | * (this disables the manual progress events of the Tech) 1406 | */ 1407 | Dailymotion.prototype['featuresProgressEvents'] = false; 1408 | 1409 | /* 1410 | * Sets the tech's status on native text track support 1411 | * 1412 | * @type {Boolean} 1413 | */ 1414 | Dailymotion.prototype['featuresNativeTextTracks'] = true; 1415 | 1416 | /* 1417 | * Sets the tech's status on native audio track support 1418 | * 1419 | * @type {Boolean} 1420 | */ 1421 | Dailymotion.prototype['featuresNativeAudioTracks'] = true; 1422 | 1423 | /* 1424 | * Sets the tech's status on native video track support 1425 | * 1426 | * @type {Boolean} 1427 | */ 1428 | Dailymotion.prototype['featuresNativeVideoTracks'] = false; 1429 | 1430 | Dailymotion.Events = 'apiready,ad_play,ad_start,ad_timeupdate,ad_pause,ad_end,video_start,video_end,play,playing,pause,ended,canplay,canplaythrough,timeupdate,progress,seeking,seeked,volumechange,durationchange,fullscreenchange,error'.split(','); 1431 | 1432 | _videoJs2['default'].options.Dailymotion = {}; 1433 | 1434 | Component.registerComponent('Dailymotion', Dailymotion); 1435 | Tech.registerTech('Dailymotion', Dailymotion); 1436 | 1437 | injectJs(); 1438 | 1439 | // Called when Dailymotion API is ready to be used 1440 | window.dmAsyncInit = function () { 1441 | var dm; 1442 | while (dm = Dailymotion.apiReadyQueue.shift()) { 1443 | dm.loadApi(); 1444 | } 1445 | Dailymotion.apiReadyQueue = []; 1446 | Dailymotion.isApiReady = true; 1447 | }; 1448 | 1449 | exports['default'] = Dailymotion; 1450 | module.exports = exports['default']; 1451 | 1452 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1453 | },{}],7:[function(require,module,exports){ 1454 | (function (global){ 1455 | 'use strict'; 1456 | 1457 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 1458 | 1459 | var _globalWindow = require('global/window'); 1460 | 1461 | var _globalWindow2 = _interopRequireDefault(_globalWindow); 1462 | 1463 | var _qunit = (typeof window !== "undefined" ? window['QUnit'] : typeof global !== "undefined" ? global['QUnit'] : null); 1464 | 1465 | var _qunit2 = _interopRequireDefault(_qunit); 1466 | 1467 | var _srcVideojsDailymotion = require('../src/videojs-dailymotion'); 1468 | 1469 | var _srcVideojsDailymotion2 = _interopRequireDefault(_srcVideojsDailymotion); 1470 | 1471 | var _playerProxy = require('./player-proxy'); 1472 | 1473 | var _playerProxy2 = _interopRequireDefault(_playerProxy); 1474 | 1475 | _qunit2['default'].module('dailymotion', { 1476 | 1477 | beforeEach: function beforeEach() { 1478 | this.oldTimeout = _globalWindow2['default'].setTimeout; 1479 | _globalWindow2['default'].setTimeout = Function.prototype; 1480 | }, 1481 | 1482 | afterEach: function afterEach() { 1483 | _globalWindow2['default'].setTimeout = this.oldTimeout; 1484 | } 1485 | }); 1486 | 1487 | _qunit2['default'].test('chromecastMaker takes a player and returns a dailymotion plugin', function (assert) { 1488 | var chromecast = (0, _srcVideojsDailymotion2['default'])((0, _playerProxy2['default'])(), {}); 1489 | 1490 | assert.equal(typeof chromecast, 'object', 'dailymotion is an object'); 1491 | }); 1492 | 1493 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1494 | },{"../src/videojs-dailymotion":6,"./player-proxy":8,"global/window":1}],8:[function(require,module,exports){ 1495 | (function (global){ 1496 | 'use strict'; 1497 | 1498 | Object.defineProperty(exports, '__esModule', { 1499 | value: true 1500 | }); 1501 | 1502 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 1503 | 1504 | var _nodeExtend = require('node.extend'); 1505 | 1506 | var _nodeExtend2 = _interopRequireDefault(_nodeExtend); 1507 | 1508 | var _videoJs = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null); 1509 | 1510 | var _videoJs2 = _interopRequireDefault(_videoJs); 1511 | 1512 | var proxy = function proxy(props) { 1513 | var player = (0, _nodeExtend2['default'])(true, {}, _videoJs2['default'].EventTarget.prototype, { 1514 | play: Function.prototype, 1515 | paused: Function.prototype, 1516 | ended: Function.prototype, 1517 | poster: Function.prototype, 1518 | src: Function.prototype, 1519 | addRemoteTextTrack: Function.prototype, 1520 | removeRemoteTextTrack: Function.prototype, 1521 | remoteTextTracks: Function.prototype, 1522 | currentSrc: Function.prototype, 1523 | dailymotion: {} 1524 | }, props); 1525 | 1526 | player.constructor = _videoJs2['default'].getComponent('Player'); 1527 | player.chromecast.player_ = player; 1528 | 1529 | return player; 1530 | }; 1531 | 1532 | exports['default'] = proxy; 1533 | module.exports = exports['default']; 1534 | 1535 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1536 | },{"node.extend":2}],9:[function(require,module,exports){ 1537 | (function (global){ 1538 | 'use strict'; 1539 | 1540 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 1541 | 1542 | var _qunit = (typeof window !== "undefined" ? window['QUnit'] : typeof global !== "undefined" ? global['QUnit'] : null); 1543 | 1544 | var _qunit2 = _interopRequireDefault(_qunit); 1545 | 1546 | var _sinon = (typeof window !== "undefined" ? window['sinon'] : typeof global !== "undefined" ? global['sinon'] : null); 1547 | 1548 | var _sinon2 = _interopRequireDefault(_sinon); 1549 | 1550 | var _videoJs = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null); 1551 | 1552 | var _videoJs2 = _interopRequireDefault(_videoJs); 1553 | 1554 | var _srcPlugin = require('../src/plugin'); 1555 | 1556 | var _srcPlugin2 = _interopRequireDefault(_srcPlugin); 1557 | 1558 | _qunit2['default'].test('the environment is sane', function (assert) { 1559 | assert.strictEqual(typeof Array.isArray, 'function', 'es5 exists'); 1560 | assert.strictEqual(typeof _sinon2['default'], 'object', 'sinon exists'); 1561 | assert.strictEqual(typeof _videoJs2['default'], 'function', 'videojs exists'); 1562 | assert.strictEqual(typeof _srcPlugin2['default'], 'function', 'plugin is a function'); 1563 | }); 1564 | 1565 | _qunit2['default'].test('registers itself with video.js', function (assert) { 1566 | assert.expect(1); 1567 | assert.strictEqual(_videoJs2['default'].getComponent('Player').prototype.dailymotion, _srcPlugin2['default'], 'videojs-dailymotion plugin was registered'); 1568 | }); 1569 | 1570 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 1571 | },{"../src/plugin":5}]},{},[7,9]); 1572 | --------------------------------------------------------------------------------