aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2017-10-02 23:36:54 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2017-10-02 23:36:54 -0400
commitcf8d3f6895ea0db85c848090471235f84ed51579 (patch)
treee829ca710a33a2af154d30115c8762ea2b0f1554
parentUpdate home page video (diff)
downloadsway-cf8d3f6895ea0db85c848090471235f84ed51579.tar.gz
sway-cf8d3f6895ea0db85c848090471235f84ed51579.tar.zst
sway-cf8d3f6895ea0db85c848090471235f84ed51579.zip
Rewrite website
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules3
-rw-r--r--_config.yml2
-rw-r--r--_layouts/master.html89
m---------_sass/bootstrap0
-rw-r--r--assets/patreon.pngbin0 -> 3086 bytes
-rw-r--r--css/master.scss45
-rw-r--r--css/video-js.css1234
-rw-r--r--index.html33
-rw-r--r--js/video.js22383
10 files changed, 23717 insertions, 73 deletions
diff --git a/.gitignore b/.gitignore
index 57510a2b..dc99ca29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
1_site/ 1_site/
2.sass-cache
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..6be3ac41
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
1[submodule "_sass/bootstrap"]
2 path = _sass/bootstrap
3 url = https://github.com/twbs/bootstrap
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 00000000..42f5e4da
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,2 @@
1exclude:
2 - _sass/bootstrap/
diff --git a/_layouts/master.html b/_layouts/master.html
index 3bd18e06..2c94a634 100644
--- a/_layouts/master.html
+++ b/_layouts/master.html
@@ -1,59 +1,38 @@
1<!doctype html> 1<!doctype html>
2<html> 2<html>
3 <head> 3 <head>
4 <meta charset="utf-8" /> 4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1"> 5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css" /> 6 <link rel="stylesheet" href="/css/master.css" />
7 <link rel="stylesheet" href="/css/master.css" /> 7 <title>{{ page.title }}</title>
8 <title>{{ page.title }}</title> 8 </head>
9 </head> 9 <body>
10 <body> 10 <div class="container">
11 <div class="container"> 11 <nav class="navbar navbar-toggleable-md navbar-light">
12 <div class="row"> 12 <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
13 <div class="col-md-4"> 13 <span class="navbar-toggler-icon"></span>
14 <h1> 14 </button>
15 <img src="/assets/logo.png" id="logo" alt="Sway" /> 15 <a class="navbar-brand" href="/">Sway</a>
16 </h1> 16 <div class="collapse navbar-collapse" id="navbarSupportedContent">
17 <p> 17 <ul class="navbar-nav mr-auto">
18 Sway is a drop-in replacement for the <a href="http://i3wm.org/">i3 18 <li class="nav-item">
19 window manager</a>, but for Wayland instead of X11. It works 19 <a class="nav-link" href="https://github.com/swaywm/sway/releases">Releases ≫</a>
20 with your existing i3 configuration and supports most of i3's features, 20 </li>
21 and a few extras. 21 <li class="nav-item">
22 </p> 22 <a class="nav-link" href="https://github.com/swaywm/sway">Source Code ≫</a>
23 </div> 23 </li>
24 <div class="col-md-8"> 24 <li class="nav-item">
25 {{ content }} 25 <a class="nav-link" href="https://github.com/SirCmpwn/sway/wiki">Wiki ≫</a>
26 </div> 26 </li>
27 </div> 27 <li class="nav-item">
28 <a class="nav-link" href="http://webchat.freenode.net/?channels=sway&uio=d4">Support Chat ≫</a>
29 </li>
30 </ul>
28 </div> 31 </div>
29 <nav class="navbar navbar-dark navbar-fixed-bottom"> 32 </nav>
30 <div class="container"> 33 <div class="main">
31 <a href="/" class="navbar-brand">Sway</span> 34 {{ content }}
32 <ul class="nav navbar-nav"> 35 </div>
33 <li class="nav-item"> 36 </div>
34 <a class="nav-link" 37 </body>
35 href="https://github.com/SirCmpwn/sway/releases">Releases</a>
36 </li>
37 <li class="nav-item">
38 <a class="nav-link"
39 href="https://github.com/SirCmpwn/sway">Source code</a>
40 </li>
41 <li class="nav-item">
42 <a class="nav-link"
43 href="/roadmap">Roadmap</a>
44 </li>
45 <li class="nav-item">
46 <a class="nav-link"
47 href="https://github.com/SirCmpwn/sway/wiki">FAQ</a>
48 </li>
49 <li class="nav-item">
50 <a class="nav-link"
51 href="http://webchat.freenode.net/?channels=sway&uio=d4">IRC channel</a>
52 </li>
53 </ul>
54 </div>
55 </nav>
56 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
57 <script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
58 </body>
59</html> 38</html>
diff --git a/_sass/bootstrap b/_sass/bootstrap
new file mode 160000
Subproject 65ffb1c3b6e94440812a2e228cb8e8be512652e
diff --git a/assets/patreon.png b/assets/patreon.png
new file mode 100644
index 00000000..291b7bcf
--- /dev/null
+++ b/assets/patreon.png
Binary files differ
diff --git a/css/master.scss b/css/master.scss
index 2b837d96..cd3fd54f 100644
--- a/css/master.scss
+++ b/css/master.scss
@@ -1,35 +1,46 @@
1--- 1---
2--- 2---
3 3
4body { 4@import "bootstrap/scss/bootstrap";
5 background-color: #000; 5
6 color: #fff; 6html {
7 margin-top: 1rem; 7 height: 100%;
8 margin-bottom: 5rem;
9} 8}
10 9
11video { 10body {
12 max-width: 100%; 11 background: linear-gradient(to bottom right, #75d3e8, #3c84ac);
12 background-size: cover;
13 background-repeat: no-repeat;
14 background-attachment: fixed;
15 margin: 0;
16 height: 100%;
13} 17}
14 18
15.text-center { 19.navbar-light {
16 text-align: center; 20 margin-bottom: 1rem;
21
22 .navbar-nav .nav-link {
23 color: rgba(0, 0, 0, 0.8);
24 text-decoration: underline;
25 }
17} 26}
18 27
19hr { 28.main a {
20 border-color: white; 29 color: darken(#014c8c, 10);
30 text-decoration: underline;
21} 31}
22 32
23.table-success { 33video {
24 background-color: green; 34 max-width: 100%;
35 box-shadow: 0 0 3px 3px #444;
25} 36}
26 37
27.table-danger { 38.text-center {
28 background-color: darken(red, 10); 39 text-align: center;
29} 40}
30 41
31nav { 42hr {
32 background: black; 43 border-color: white;
33} 44}
34 45
35#logo { 46#logo {
diff --git a/css/video-js.css b/css/video-js.css
new file mode 100644
index 00000000..faedac77
--- /dev/null
+++ b/css/video-js.css
@@ -0,0 +1,1234 @@
1.video-js .vjs-big-play-button:before, .video-js .vjs-control:before, .video-js .vjs-modal-dialog, .vjs-modal-dialog .vjs-modal-dialog-content {
2 position: absolute;
3 top: 0;
4 left: 0;
5 width: 100%;
6 height: 100%; }
7
8.video-js .vjs-big-play-button:before, .video-js .vjs-control:before {
9 text-align: center; }
10
11@font-face {
12 font-family: VideoJS;
13 src: url("../font/1.5.1/VideoJS.eot?#iefix") format("eot"); }
14
15@font-face {
16 font-family: VideoJS;
17 src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAA4wAAoAAAAAFfAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAAA9AAAAD4AAABWUZFeBGNtYXAAAAE0AAAAOgAAAUriLxC2Z2x5ZgAAAXAAAAnnAAAO5OV/F/5oZWFkAAALWAAAACsAAAA2C4eUa2hoZWEAAAuEAAAAGAAAACQOogcfaG10eAAAC5wAAAAPAAAAeNIAAABsb2NhAAALrAAAAD4AAAA+MMgtQm1heHAAAAvsAAAAHwAAACABLwB5bmFtZQAADAwAAAElAAACCtXH9aBwb3N0AAANNAAAAPkAAAF5vawAenicY2BkZ2CcwMDKwMFSyPKMgYHhF4RmjmEIZzzHwMDEwMrMgBUEpLmmMDh8ZPwoyw7iLmSHCDOCCADu/Qo9AAB4nGNgYGBmgGAZBkYGEHAB8hjBfBYGDSDNBqQZGZgYGD7K/v8PUvCREUTzM0DVAwEjG8OIBwCOWgbUAAB4nI1XfVBU1xV/574vlsUlj/14grDs48FuAgaR3X2LEnY3UZSgEkTwAySAgkIwI8bRfFDjTszYCWRMW9lNa4y2meokmq+2k5ia0dpkmknbkWgSSW3GyaaNf0RTx0wxX7A3Pe/tQmIgHXf3vXvvueeee+45v3POXQYY/PCD/CBDGAYkIE2sxg+OXSJmhmH1OaFX6MU5C5PDMCZi5Rg2i+ELGSthwM14NCbgYGSBIZfhFA1H6Zu0OS0NDkMVfg+npdFm+maCvigI0JBIQIMg0BdJGdTj9ylj7nr+b97+Hl8C1+H2xNAvjPqxjIgaKtItICkSnIISeo40QQls4xxjlzgHsnGGvi7BxQiMlSlkPMhfCh67rAUEUQ6CHxW2O7JARCkKnlUQ7UEIyAEQZe4MdDW9xr5OPFuKbubpRxcPDY8da4MOelDfAYJLW+sGKn/Vlmjfv5+NdB4oOfTazJn3tGxZtL9xFNZX7PPRUbjcRg/SMB2EL+gblXn7shbO/WUbF9u/H5XQ9eKO8iMMr9tY35qYoRi20wGuXV/CHaGDk2fdgHwCk5HUXQpCcgHfBV2NjV3jkq4PHTSUSBwuOQALvxPAps6fiftk6P6yJpcm5bB4dFkgoh195mbiSTnkL3jupq7jh4ZZdvjQRVB4PPx3SsVTu5D/6kd85RU66ttXAeuuXYN1E/Y2sMMzZkZiZNRZlRS/ynr9Xr8Cql2RVNbutXslYo7B9ngsFqcDbCQO22PxeIxcpgMxkh6PjUdwkvw6hvRpZeoCFKshDQzJVr++DWyLx+hAXJcGp3TJMV1ME45xCNvHLsWRrpOZSduOoG0zERuIIwuIkhNkBREglQKLiODD45FQE0BTiE214xE2wp8zOt9NjH3GRtDMk7Ehoq2tzCzGxdyMEQJuD0qGIrQ58ApoWQE3D2h1h6zwuB14wYFIDAA5CZ11jT+92gFZ7B7/p7+hV8jFxBl4aG03wLiVXtBbCylLfIJzkPUAvWAw0yvsVdKdBbC6nnruP/RFkHqWJLZ2Auxdtgy+6qTf7l1WswTJcJ6mGVxwXj92UtfU2WXUNX+qBUCxK6D4FR4f/cufG1sZbiSkMcwdMdoxBxTTEXIp4SCXMNhHoFjvTTFP4vkoPReNRmPRCTwa+3qY0DR7qn7Vjh612wRRTaI04HWCnZ+gIzvS/ZJP0+mynphCui4hzmG0id6+aLSv2BV3FQMYDTHrlGQ/SZ+q4ZdF8aLa5Ar8GW3tVNKEj13cF0buMaesx1i9CL/Uo1tM0h+74o9HjQ+UcPaxy8mH9ccwK8KpKA3rHdIUjTKpfIBxuokpxUGBIILm84ATvHh8tAIe2iZj8KvYwUOXawHMVNgxZvlwSa0z8Zkokkxn3ey2nYTsbMO3mPh8cji7zklsPLD9a9f2s2w/uSt/FgSytWzw5bmS3PielU1P56aGrlz6NzlnbT8h/Wtb+1OxIqxBbC9g7kINUbtAEDxsKWSCe46eltCPmaiUxy2IrODIB8EmixaQrU4IAQ6THg6BFpAdWsCquT16DkL9ccIC/FGeP5AuiDExe8bx+QtzWVsmHcm0kdzqecdn5IhRkTc/zfNPm3ns5sw4Pq86l9gyofh6jkTF5iFChjYbbzZQWFvYb8qZAWyGiV9ya+5bFgnzpuWt3FuX8KYMmsiYZepPseBgGhZcOMt0+4Q8fDOTftJjHIuhdaLsFXFM9AclTi9jbGRq8ZvIOykZei77kfo53eoppVPovbGiyV63p/p/dkWETTjmhjTIm8RP284b04bcNYlRsvO6Gp2JeaiIueVHsgJGF2aASlCQLuG8EsBomzb++/AXmwhaOoLhL7iQ4/uc449gWJ56/XWDARn74v/PL1bRBB4TBEyYrqezSkUPHaWjPWCm13ogAzJ66LVpbTEuXccDZlyXxBQ/IrzKOPS7gAkkIyZ0N6joE6M246aDsO1kgucTJ/EdFWA5pbAcTfoSP4hJeBCni7nEn5IclL4kpDgmMMuH8Kpk0+WrBUIeKCyWS0nPVz7NW86Hnl55GxR5KB3+9tszL+wVRulXNTUn6D8SJvIl3PzP46eZST/tQTllTDXTzmxCaTYna7eJAqcWuD1ulBXQsMz5fQEBCfowCF5FVDF/2yysB9OW5veVEtRAFOy41FoeJEiAOZhDiFstsKAwJ8Hijs72q1jWvWx+uKU5XFZDLx189OK8ojW1u0By5dtLHUN/rwkte68PnhnYVbt0bvWiub9w1+f4C0L3hIuXZ8+xlVSt0eb3tgQsmVZnem5R3U0uf/fmFdqiLTvY3nPnet5/v4f9pLB6QX2krnnFQ1tXtN+2ePlAaUNWcfiWwrncn4ca9ml3hFeHHm+u2bq4MhxUZs3bMH/3jgaPUtlVunFjg2/8yRzf3cHsssKZqlnOqyCWworWykW9lXnspk0ffrjpfCreIpjPWbwnFxt3PAkcQgkUuH1auUMf+txJQ0hK1k1zsNaqQdaLMxfoq9AGGxtJQ+fGw53cE/TY8pWhJruZHiMAcCexFS/eGDp6hntiXGE/gvI7163b29ExfiHxNsnqub/a6/QmPoAn4GpZ2c9cZRX5/57IWUNYuubiQBAddhuxAKe6PA5vuV5dkk0VXkMM3zk42W3Awrgka8LQgjZY+tQIffd5+vnHasnHL/cczldyS4r79i6su6Nu9oPQ8lbaid2Pt9/bXtTTynevq7bkPkITV47d+3NugOzo4M3y77Zxbnb2nhWrl0T/kO4u3H1ig33e1lD6JDYjiKkCHOioF0pZv6T6gxxipxLNhFc8xERA48vq5ZfXdL/QV6c8W3PfwjIsZyI3Csvo72e4FpTVwTv/UYNAKtY+8MB84vogZ1Xr5lW38iJdPZ74xunzO4Gk7BARIkytjlyCoPVoIb3IluMfAYRhEoAO2aGXKc2TNAJaSwdzQEeq7jC7TWYF2Y2jrEIXlyVEhunBs5t7K62a7Z6qB0923/+vPT2v7mwpqV/mTEsTiCB5zz735HOP9VbVWtKKZK08uDJ7vcQN02HogGegY5iNnKUHh12ti9/zzHvsauy+tx+e375j94LuA64MV/5MQbZVNT95/re7jlxZVaVuW5Nffsd9TXfOpXcv6m2Bn3x6FgXg/oz+P0h/ce8g2mTEWxVTzzQzrTruNCcRdbu6VY87gLVXc4uSjXfosak7XxWM4oyl+ockmzCFhJXaGwK8e6sCW2T3sLmPnh5qSZtx9JHFL6QBHGnsTjdtWQ8PFygWtQTIkrI84NILfQSC65FUMFsnOYFHEoSmUCD49a4rt3985PTsd8GzB/5KEnzmhhORgVOZPM+yb5KmpRu38jQqviH6826Lrdrxx6DZdFPo2fVbTiy9AUpDJ3SxGYvpK7u+Rhz8D4BCxssAeJxjYGRgYABi/vcdWfH8Nl8ZuNkZQODSliXbkWl2BrA4BwMTiAIAKDsJfgB4nGNgZGBgZwCChWASxGZkQAVyABOTANd4nGNnYGBgHwAMADNUANMAAAAAAAAOAFAAZgCyAMYA5gEeAUgBdAGcAfICLgKOAroDCgOOA7AD6gQ4BHwEuAToBQwFogXoBjYGbAbaB3IAAHicY2BkYGCQY8hlYGcAASYg5gJCBob/YD4DABa6AakAeJxdkE1qg0AYhl8Tk9AIoVDaVSmzahcF87PMARLIMoFAl0ZHY1BHdBJIT9AT9AQ9RQ9Qeqy+yteNMzDzfM+88w0K4BY/cNAMB6N2bUaPPBLukybCLvleeAAPj8JD+hfhMV7hC3u4wxs7OO4NzQSZcI/8Ltwnfwi75E/hAR7wJTyk/xYeY49fYQ/PztM+jbTZ7LY6OWdBJdX/pqs6NYWa+zMxa13oKrA6Uoerqi/JwtpYxZXJ1coUVmeZUWVlTjq0/tHacjmdxuL90OR8O0UEDYMNdtiSEpz5XQGqzlm30kzUdAYFFOb8R7NOZk0q2lwAyz1i7oAr1xoXvrOgtYhZx8wY5KRV269JZ5yGpmzPTjQhvY9je6vEElPOuJP3mWKnP5M3V+YAAAB4nG2P2XLCMAxFfYE4CWlZSveFP8hHOY4gHhw79VLav68hMNOH6kG60mg5YhM22pr9b1vGMMEUM2TgyFGgxBwVbnCLBZZYYY07bHCPBzziCc94wSve8I4PbGeDFj/VydVSOakpG0T0VH1ZHXuq+xhoftHaHq+yV+21o1P7brWLWnvpiExNJpBb/i18q8D9ZxSOcj8oY8iVPjZBBU2+kGIIypokuqTI+cx3qXMq7Z6PQIsx1DYGrQxtLul50YV50rVcCiNJc0enX4qdkNRYe8j2g46+SIMHapXJw1GFdIWH2DfalQknZeTDWsRW2bqlBK3ORIz9AqJUapQAAAA=) format("woff"), url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAAKAIAAAwAgT1MvMlGRXgQAAAEoAAAAVmNtYXDiLxC2AAAB+AAAAUpnbHlm5X8X/gAAA4QAAA7kaGVhZAuHlGsAAADQAAAANmhoZWEOogcfAAAArAAAACRobXR40gAAAAAAAYAAAAB4bG9jYTDILUIAAANEAAAAPm1heHABLwB5AAABCAAAACBuYW1l1cf1oAAAEmgAAAIKcG9zdL2sAHoAABR0AAABeQABAAAHAAAAAKEHAAAAAAAHAAABAAAAAAAAAAAAAAAAAAAAHgABAAAAAQAAD+/W/l8PPPUACwcAAAAAANK0pLcAAAAA0rSktwAAAAAHAAcAAAAACAACAAAAAAAAAAEAAAAeAG0ABwAAAAAAAgAAAAoACgAAAP8AAAAAAAAAAQcAAZAABQAIBHEE5gAAAPoEcQTmAAADXABXAc4AAAIABQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUGZFZABA8QHxHQcAAAAAoQcAAAAAAAABAAAAAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAAAAAAAwAAAAMAAAAcAAEAAAAAAEQAAwABAAAAHAAEACgAAAAGAAQAAQACAADxHf//AAAAAPEB//8AAA8AAAEAAAAAAAAAAAEGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AUABmALIAxgDmAR4BSAF0AZwB8gIuAo4CugMKA44DsAPqBDgEfAS4BOgFDAWiBegGNgZsBtoHcgAAAAEAAAAABYsFiwACAAABEQECVQM2BYv76gILAAADAAAAAAZrBmsAAgAOABoAAAkCEwQAAxIABSQAEwIAASYAJzYANxYAFwYAAusBwP5Alf7D/loICAGmAT0BPQGmCAj+Wv7D/f6uBgYBUv39AVIGBv6uAjABUAFQAZsI/lr+w/7D/loICAGmAT0BPQGm+sgGAVL9/QFSBgb+rv39/q4AAAACAAAAAAVABYsAAwAHAAABIREpAREhEQHAASv+1QJVASsBdQQW++oEFgAAAAQAAAAABiAGIAAGABMAJAAnAAABLgEnFRc2NwYHFz4BNSYAJxUWEgEHASERIQERAQYHFT4BNxc3AQcXBNABZVW4A7sCJ3ElKAX+3+Wlzvu3XwFh/p8BKwF1AT5MXU6KO5lf/WCcnAOAZJ4rpbgYGGpbcUacVPQBYziaNP70Aetf/p/+QP6LAfb+wjsdmhJEMZhfBJacnAAAAQAAAAAEqwXWAAUAAAERIQERAQILASoBdv6KBGD+QP6LBKr+iwAAAAIAAAAABWYF1gAGAAwAAAEuAScRPgEBESEBEQEFZQFlVFRl/BEBKwF1/osDgGSeK/2mK54BRP5A/osEqv6LAAADAAAAAAYgBg8ABQAMABoAABMRIQERAQUuAScRPgEDFRYSFwYCBxU2ADcmAOABKwF1/osCxQFlVVVluqXOAwPOpeUBIQUF/t8EYP5A/osEqv6L4GSeK/2mK54C85o0/vS1tf70NJo4AWL19QFiAAAABAAAAAAFiwWLAAUACwARABcAAAEjESE1IwMzNTM1IQEjFSERIwMVMxUzEQILlgF24JaW4P6KA4DgAXaW4OCWAuv+ipYCCuCW/ICWAXYCoJbgAXYABAAAAAAFiwWLAAUACwARABcAAAEzFTMRIRMjFSERIwEzNTM1IRM1IxEhNQF14Jb+iuDgAXaWAcCW4P6KlpYBdgJV4AF2AcCWAXb76uCWAcDg/oqWAAAAAAIAAAAABdYF1gAPABMAAAEhDgEHER4BFyE+ATcRLgEDIREhBUD8gD9VAQFVPwOAP1UBAVU//IADgAXVAVU//IA/VQEBVT8DgD9V++wDgAAABgAAAAAGawZrAAcADAATABsAIAAoAAAJASYnDgEHASUuAScBBSEBNhI3JgUBBgIHFhchBR4BFwEzARYXPgE3AQK+AWROVIfwYQESA4416aH+7gLl/dABelxoAQH8E/7dXGgBAQ4CMP3kNemhARJ4/t1OVIfwYf7uA/ACaBIBAVhQ/id3pfY+/idL/XNkAQGTTU0B+GT+/5NNSEul9j4B2f4IEgEBWFAB2QAAAAUAAAAABmsF1gAPABMAFwAbAB8AAAEhDgEHER4BFyE+ATcRLgEBIRUhASE1IQUhNSE1ITUhBdX7VkBUAgJUQASqQFQCAlT7FgEq/tYC6v0WAuoBwP7WASr9FgLqBdUBVT/8gD9VAQFVPwOAP1X9rJX+1ZWVlZaVAAMAAAAABiAF1gAPACcAPwAAASEOAQcRHgEXIT4BNxEuAQEjNSMVMzUzFRQGByMuAScRPgE3Mx4BFQUjNSMVMzUzFQ4BByMuATURNDY3Mx4BFwWL++o/VAICVD8EFj9UAgJU/WtwlZVwKiDgICoBASog4CAqAgtwlZVwASog4CAqKiDgICoBBdUBVT/8gD9VAQFVPwOAP1X99yXgJUogKgEBKiABKiAqAQEqIEol4CVKICoBASogASogKgEBKiAAAAYAAAAABiAE9gADAAcACwAPABMAFwAAEzM1IxEzNSMRMzUjASE1IREhNSERFSE14JWVlZWVlQErBBX76wQV++sEFQM1lv5AlQHAlf5Alv5AlQJVlZUAAAABAAAAAAYgBmwALgAAASIGBwE2NCcBHgEzPgE3LgEnDgEHFBcBLgEjDgEHHgEXMjY3AQYHHgEXPgE3LgEFQCtKHv3sBwcCDx5OLF9/AgJ/X19/Agf98R5OLF9/AgJ/XyxOHgIUBQEDe1xcewMDewJPHxsBNxk2GQE0HSACf19ffwICf18bGf7NHCACf19ffwIgHP7KFxpcewICe1xdewAAAgAAAAAGWQZrAEMATwAAATY0Jzc+AScDLgEPASYvAS4BJyEOAQ8BBgcnJgYHAwYWHwEGFBcHDgEXEx4BPwEWHwEeARchPgE/ATY3FxY2NxM2JicFLgEnPgE3HgEXDgEFqwUFngoGB5YHGQ26OkQcAxQP/tYPFAIcRTm6DRoHlQcFC50FBZ0LBQeVBxoNujlFHAIUDwEqDxQCHEU5ug0aB5UHBQv9OG+UAgKUb2+UAgKUAzckSiR7CRoNAQMMCQVLLRzGDhEBAREOxhwtSwUJDP79DBsJeyRKJHsJGg3+/QwJBUstHMYOEQEBEQ7GHC1LBQkMAQMMGwlBApRvb5QCApRvb5QAAAAAAQAAAAAGawZrAAsAABMSAAUkABMCACUEAJUIAaYBPQE9AaYICP5a/sP+w/5aA4D+w/5aCAgBpgE9AT0BpggI/loAAAACAAAAAAZrBmsACwAXAAABBAADEgAFJAATAgABJgAnNgA3FgAXBgADgP7D/loICAGmAT0BPQGmCAj+Wv7D/f6uBgYBUv39AVIGBv6uBmsI/lr+w/7D/loICAGmAT0BPQGm+sgGAVL9/QFSBgb+rv39/q4AAAMAAAAABmsGawALABcAIwAAAQQAAxIABSQAEwIAASYAJzYANxYAFwYAAw4BBy4BJz4BNx4BA4D+w/5aCAgBpgE9AT0BpggI/lr+w/3+rgYGAVL9/QFSBgb+rh0Cf19ffwICf19ffwZrCP5a/sP+w/5aCAgBpgE9AT0BpvrIBgFS/f0BUgYG/q79/f6uAk9ffwICf19ffwICfwAAAAQAAAAABiAGIAAPABsAJQApAAABIQ4BBxEeARchPgE3ES4BASM1IxUjETMVMzU7ASEeARcRDgEHITczNSMFi/vqP1QCAlQ/BBY/VAICVP1rcJVwcJVwlgEqICoBASog/tZwlZUGIAJUP/vqP1QCAlQ/BBY/VPyClZUBwLu7ASog/tYgKgFw4AACAAAAAAZrBmsACwAXAAABBAADEgAFJAATAgATBwkBJwkBNwkBFwEDgP7D/loICAGmAT0BPQGmCAj+Wjhp/vT+9GkBC/71aQEMAQxp/vUGawj+Wv7D/sP+WggIAaYBPQE9Aab8EWkBC/71aQEMAQxp/vUBC2n+9AABAAAAAAXWBrYAFgAAAREJAREeARcOAQcuAScjFgAXNgA3JgADgP6LAXW+/QUF/b6+/QWVBgFR/v4BUQYG/q8FiwEq/ov+iwEqBP2/vv0FBf2+/v6vBgYBUf7+AVEAAAABAAAAAAU/BwAAFAAAAREjIgYdASEDIxEhESMRMzU0NjMyBT+dVjwBJSf+/s7//9Ctkwb0/vhISL3+2P0JAvcBKNq6zQAAAAAEAAAAAAaOBwAAMABFAGAAbAAAARQeAxUUBwYEIyImJyY1NDY3NiUuATU0NwYjIiY1NDY3PgEzIQcjHgEVFA4DJzI2NzY1NC4CIyIGBwYVFB4DEzI+AjU0LgEvASYvAiYjIg4DFRQeAgEzFSMVIzUjNTM1MwMfQFtaQDBI/uqfhOU5JVlKgwERIB8VLhaUy0g/TdNwAaKKg0pMMUVGMZImUBo1Ij9qQCpRGS8UKz1ZNjprWzcODxMeChwlThAgNWhvUzZGcX0Da9XVadTUaQPkJEVDUIBOWlN6c1NgPEdRii5SEipAKSQxBMGUUpo2QkBYP4xaSHNHO0A+IRs5ZjqGfVInITtlLmdnUjT8lxo0Xj4ZMCQYIwsXHTgCDiQ4XTtGazsdA2xs29ts2QADAAAAAAaABmwAAwAOACoAAAERIREBFgYrASImNDYyFgERIRE0JiMiBgcGFREhEhAvASEVIz4DMzIWAd3+tgFfAWdUAlJkZ6ZkBI/+t1FWP1UVC/63AgEBAUkCFCpHZz+r0ASP/CED3wEySWJik2Fh/N39yAISaXdFMx4z/dcBjwHwMDCQIDA4H+MAAAEAAAAABpQGAAAxAAABBgcWFRQCDgEEIyAnFjMyNy4BJxYzMjcuAT0BFhcuATU0NxYEFyY1NDYzMhc2NwYHNgaUQ18BTJvW/tKs/vHhIyvhsGmmHyEcKypwk0ROQk4seQFbxgi9hoxgbWAlaV0FaGJFDhyC/v3ut22RBIoCfWEFCxexdQQmAyyOU1hLlbMKJiSGvWYVOXM/CgAAAAEAAAAABYAHAAAiAAABFw4BBwYuAzURIzU+BDc+ATsBESEVIREUHgI3NgUwUBewWWitcE4hqEhyRDAUBQEHBPQBTf6yDSBDME4Bz+0jPgECOFx4eDoCINcaV11vVy0FB/5Y/P36HjQ1HgECAAEAAAAABoAGgABKAAABFAIEIyInNj8BHgEzMj4BNTQuASMiDgMVFBYXFj8BNjc2JyY1NDYzMhYVFAYjIiY3PgI1NCYjIgYVFBcDBhcmAjU0EiQgBBIGgM7+n9FvazsTNhRqPXm+aHfijmm2f1srUE0eCAgGAgYRM9Gpl6mJaz1KDgglFzYyPlYZYxEEzv7OAWEBogFhzgOA0f6fziBdR9MnOYnwlnLIfjpgfYZDaJ4gDCAfGAYXFD1al9mkg6ruVz0jdVkfMkJyVUkx/l5Ga1sBfOnRAWHOzv6fAAAHAAAAAAcABM8ADgAXACoAPQBQAFoAXQAAARE2HgIHDgEHBiYjJyY3FjY3NiYHERQFFjY3PgE3LgEnIwYfAR4BFw4BFxY2Nz4BNy4BJyMGHwEeARcUBhcWNjc+ATcuAScjBh8BHgEXDgEFMz8BFTMRIwYDJRUnAxyEzZRbCA2rgketCAEBqlRoCglxYwF+IiEOIysBAkswHQEECiQ0AgE+YyIhDiIsAQJLMB4BBQokNAE/YyIhDiIsAQJLMB4BBQokNAEBPvmD7kHhqs0s0gEnjgHJAv0FD2a9gIrADwUFAwPDAlVMZ3MF/pUHwgc1HTyWV325PgsJED+oY3G9TAc1HTyWV325PgsJED+oY3G9TAc1HTyWV325PgsJED+oY3G9UmQBZQMMR/61g/kBAAAAAAAQAMYAAQAAAAAAAQAHAAAAAQAAAAAAAgAHAAcAAQAAAAAAAwAHAA4AAQAAAAAABAAHABUAAQAAAAAABQALABwAAQAAAAAABgAHACcAAQAAAAAACgArAC4AAQAAAAAACwATAFkAAwABBAkAAQAOAGwAAwABBAkAAgAOAHoAAwABBAkAAwAOAIgAAwABBAkABAAOAJYAAwABBAkABQAWAKQAAwABBAkABgAOALoAAwABBAkACgBWAMgAAwABBAkACwAmAR5WaWRlb0pTUmVndWxhclZpZGVvSlNWaWRlb0pTVmVyc2lvbiAxLjBWaWRlb0pTR2VuZXJhdGVkIGJ5IHN2ZzJ0dGYgZnJvbSBGb250ZWxsbyBwcm9qZWN0Lmh0dHA6Ly9mb250ZWxsby5jb20AVgBpAGQAZQBvAEoAUwBSAGUAZwB1AGwAYQByAFYAaQBkAGUAbwBKAFMAVgBpAGQAZQBvAEoAUwBWAGUAcgBzAGkAbwBuACAAMQAuADAAVgBpAGQAZQBvAEoAUwBHAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAHMAdgBnADIAdAB0AGYAIABmAHIAbwBtACAARgBvAG4AdABlAGwAbABvACAAcAByAG8AagBlAGMAdAAuAGgAdAB0AHAAOgAvAC8AZgBvAG4AdABlAGwAbABvAC4AYwBvAG0AAAACAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4EcGxheQtwbGF5LWNpcmNsZQVwYXVzZQt2b2x1bWUtbXV0ZQp2b2x1bWUtbG93CnZvbHVtZS1taWQLdm9sdW1lLWhpZ2gQZnVsbHNjcmVlbi1lbnRlcg9mdWxsc2NyZWVuLWV4aXQGc3F1YXJlB3NwaW5uZXIJc3VidGl0bGVzCGNhcHRpb25zCGNoYXB0ZXJzBXNoYXJlA2NvZwZjaXJjbGUOY2lyY2xlLW91dGxpbmUTY2lyY2xlLWlubmVyLWNpcmNsZQJoZAZjYW5jZWwGcmVwbGF5CGZhY2Vib29rBWdwbHVzCGxpbmtlZGluB3R3aXR0ZXIGdHVtYmxyCXBpbnRlcmVzdBFhdWRpby1kZXNjcmlwdGlvbgAAAAAA) format("truetype");
18 font-weight: normal;
19 font-style: normal; }
20
21.vjs-icon-play, .video-js .vjs-big-play-button, .video-js .vjs-play-control {
22 font-family: VideoJS;
23 font-weight: normal;
24 font-style: normal; }
25 .vjs-icon-play:before, .video-js .vjs-big-play-button:before, .video-js .vjs-play-control:before {
26 content: '\f101'; }
27
28.vjs-icon-play-circle {
29 font-family: VideoJS;
30 font-weight: normal;
31 font-style: normal; }
32 .vjs-icon-play-circle:before {
33 content: '\f102'; }
34
35.vjs-icon-pause, .video-js .vjs-play-control.vjs-playing {
36 font-family: VideoJS;
37 font-weight: normal;
38 font-style: normal; }
39 .vjs-icon-pause:before, .video-js .vjs-play-control.vjs-playing:before {
40 content: '\f103'; }
41
42.vjs-icon-volume-mute, .video-js .vjs-mute-control.vjs-vol-0,
43.video-js .vjs-volume-menu-button.vjs-vol-0 {
44 font-family: VideoJS;
45 font-weight: normal;
46 font-style: normal; }
47 .vjs-icon-volume-mute:before, .video-js .vjs-mute-control.vjs-vol-0:before,
48 .video-js .vjs-volume-menu-button.vjs-vol-0:before {
49 content: '\f104'; }
50
51.vjs-icon-volume-low, .video-js .vjs-mute-control.vjs-vol-1,
52.video-js .vjs-volume-menu-button.vjs-vol-1 {
53 font-family: VideoJS;
54 font-weight: normal;
55 font-style: normal; }
56 .vjs-icon-volume-low:before, .video-js .vjs-mute-control.vjs-vol-1:before,
57 .video-js .vjs-volume-menu-button.vjs-vol-1:before {
58 content: '\f105'; }
59
60.vjs-icon-volume-mid, .video-js .vjs-mute-control.vjs-vol-2,
61.video-js .vjs-volume-menu-button.vjs-vol-2 {
62 font-family: VideoJS;
63 font-weight: normal;
64 font-style: normal; }
65 .vjs-icon-volume-mid:before, .video-js .vjs-mute-control.vjs-vol-2:before,
66 .video-js .vjs-volume-menu-button.vjs-vol-2:before {
67 content: '\f106'; }
68
69.vjs-icon-volume-high, .video-js .vjs-mute-control,
70.video-js .vjs-volume-menu-button {
71 font-family: VideoJS;
72 font-weight: normal;
73 font-style: normal; }
74 .vjs-icon-volume-high:before, .video-js .vjs-mute-control:before,
75 .video-js .vjs-volume-menu-button:before {
76 content: '\f107'; }
77
78.vjs-icon-fullscreen-enter, .video-js .vjs-fullscreen-control {
79 font-family: VideoJS;
80 font-weight: normal;
81 font-style: normal; }
82 .vjs-icon-fullscreen-enter:before, .video-js .vjs-fullscreen-control:before {
83 content: '\f108'; }
84
85.vjs-icon-fullscreen-exit, .video-js.vjs-fullscreen .vjs-fullscreen-control {
86 font-family: VideoJS;
87 font-weight: normal;
88 font-style: normal; }
89 .vjs-icon-fullscreen-exit:before, .video-js.vjs-fullscreen .vjs-fullscreen-control:before {
90 content: '\f109'; }
91
92.vjs-icon-square {
93 font-family: VideoJS;
94 font-weight: normal;
95 font-style: normal; }
96 .vjs-icon-square:before {
97 content: '\f10a'; }
98
99.vjs-icon-spinner {
100 font-family: VideoJS;
101 font-weight: normal;
102 font-style: normal; }
103 .vjs-icon-spinner:before {
104 content: '\f10b'; }
105
106.vjs-icon-subtitles, .video-js .vjs-subtitles-button {
107 font-family: VideoJS;
108 font-weight: normal;
109 font-style: normal; }
110 .vjs-icon-subtitles:before, .video-js .vjs-subtitles-button:before {
111 content: '\f10c'; }
112
113.vjs-icon-captions, .video-js .vjs-captions-button {
114 font-family: VideoJS;
115 font-weight: normal;
116 font-style: normal; }
117 .vjs-icon-captions:before, .video-js .vjs-captions-button:before {
118 content: '\f10d'; }
119
120.vjs-icon-chapters, .video-js .vjs-chapters-button {
121 font-family: VideoJS;
122 font-weight: normal;
123 font-style: normal; }
124 .vjs-icon-chapters:before, .video-js .vjs-chapters-button:before {
125 content: '\f10e'; }
126
127.vjs-icon-share {
128 font-family: VideoJS;
129 font-weight: normal;
130 font-style: normal; }
131 .vjs-icon-share:before {
132 content: '\f10f'; }
133
134.vjs-icon-cog {
135 font-family: VideoJS;
136 font-weight: normal;
137 font-style: normal; }
138 .vjs-icon-cog:before {
139 content: '\f110'; }
140
141.vjs-icon-circle, .video-js .vjs-mouse-display, .video-js .vjs-play-progress, .video-js .vjs-volume-level {
142 font-family: VideoJS;
143 font-weight: normal;
144 font-style: normal; }
145 .vjs-icon-circle:before, .video-js .vjs-mouse-display:before, .video-js .vjs-play-progress:before, .video-js .vjs-volume-level:before {
146 content: '\f111'; }
147
148.vjs-icon-circle-outline {
149 font-family: VideoJS;
150 font-weight: normal;
151 font-style: normal; }
152 .vjs-icon-circle-outline:before {
153 content: '\f112'; }
154
155.vjs-icon-circle-inner-circle {
156 font-family: VideoJS;
157 font-weight: normal;
158 font-style: normal; }
159 .vjs-icon-circle-inner-circle:before {
160 content: '\f113'; }
161
162.vjs-icon-hd {
163 font-family: VideoJS;
164 font-weight: normal;
165 font-style: normal; }
166 .vjs-icon-hd:before {
167 content: '\f114'; }
168
169.vjs-icon-cancel, .video-js .vjs-control.vjs-close-button {
170 font-family: VideoJS;
171 font-weight: normal;
172 font-style: normal; }
173 .vjs-icon-cancel:before, .video-js .vjs-control.vjs-close-button:before {
174 content: '\f115'; }
175
176.vjs-icon-replay {
177 font-family: VideoJS;
178 font-weight: normal;
179 font-style: normal; }
180 .vjs-icon-replay:before {
181 content: '\f116'; }
182
183.vjs-icon-facebook {
184 font-family: VideoJS;
185 font-weight: normal;
186 font-style: normal; }
187 .vjs-icon-facebook:before {
188 content: '\f117'; }
189
190.vjs-icon-gplus {
191 font-family: VideoJS;
192 font-weight: normal;
193 font-style: normal; }
194 .vjs-icon-gplus:before {
195 content: '\f118'; }
196
197.vjs-icon-linkedin {
198 font-family: VideoJS;
199 font-weight: normal;
200 font-style: normal; }
201 .vjs-icon-linkedin:before {
202 content: '\f119'; }
203
204.vjs-icon-twitter {
205 font-family: VideoJS;
206 font-weight: normal;
207 font-style: normal; }
208 .vjs-icon-twitter:before {
209 content: '\f11a'; }
210
211.vjs-icon-tumblr {
212 font-family: VideoJS;
213 font-weight: normal;
214 font-style: normal; }
215 .vjs-icon-tumblr:before {
216 content: '\f11b'; }
217
218.vjs-icon-pinterest {
219 font-family: VideoJS;
220 font-weight: normal;
221 font-style: normal; }
222 .vjs-icon-pinterest:before {
223 content: '\f11c'; }
224
225.vjs-icon-audio-description {
226 font-family: VideoJS;
227 font-weight: normal;
228 font-style: normal; }
229 .vjs-icon-audio-description:before {
230 content: '\f11d'; }
231
232.video-js {
233 display: block;
234 vertical-align: top;
235 box-sizing: border-box;
236 color: #fff;
237 background-color: #000;
238 position: relative;
239 padding: 0;
240 font-size: 10px;
241 line-height: 1;
242 font-weight: normal;
243 font-style: normal;
244 font-family: Arial, Helvetica, sans-serif;
245 -webkit-user-select: none;
246 -moz-user-select: none;
247 -ms-user-select: none;
248 user-select: none; }
249 .video-js:-moz-full-screen {
250 position: absolute; }
251 .video-js:-webkit-full-screen {
252 width: 100% !important;
253 height: 100% !important; }
254
255.video-js *,
256.video-js *:before,
257.video-js *:after {
258 box-sizing: inherit; }
259
260.video-js ul {
261 font-family: inherit;
262 font-size: inherit;
263 line-height: inherit;
264 list-style-position: outside;
265 margin-left: 0;
266 margin-right: 0;
267 margin-top: 0;
268 margin-bottom: 0; }
269
270.video-js.vjs-fluid,
271.video-js.vjs-16-9,
272.video-js.vjs-4-3 {
273 width: 100%;
274 max-width: 100%;
275 height: 0; }
276
277.video-js.vjs-16-9 {
278 padding-top: 56.25%; }
279
280.video-js.vjs-4-3 {
281 padding-top: 75%; }
282
283.video-js.vjs-fill {
284 width: 100%;
285 height: 100%; }
286
287.video-js .vjs-tech {
288 position: absolute;
289 top: 0;
290 left: 0;
291 width: 100%;
292 height: 100%; }
293
294body.vjs-full-window {
295 padding: 0;
296 margin: 0;
297 height: 100%;
298 overflow-y: auto; }
299
300.vjs-full-window .video-js.vjs-fullscreen {
301 position: fixed;
302 overflow: hidden;
303 z-index: 1000;
304 left: 0;
305 top: 0;
306 bottom: 0;
307 right: 0; }
308
309.video-js.vjs-fullscreen {
310 width: 100% !important;
311 height: 100% !important;
312 padding-top: 0 !important; }
313
314.video-js.vjs-fullscreen.vjs-user-inactive {
315 cursor: none; }
316
317.vjs-hidden {
318 display: none !important; }
319
320.video-js .vjs-offscreen {
321 height: 1px;
322 left: -9999px;
323 position: absolute;
324 top: 0;
325 width: 1px; }
326
327.vjs-lock-showing {
328 display: block !important;
329 opacity: 1;
330 visibility: visible; }
331
332.vjs-no-js {
333 padding: 20px;
334 color: #fff;
335 background-color: #000;
336 font-size: 18px;
337 font-family: Arial, Helvetica, sans-serif;
338 text-align: center;
339 width: 300px;
340 height: 150px;
341 margin: 0px auto; }
342
343.vjs-no-js a,
344.vjs-no-js a:visited {
345 color: #66A8CC; }
346
347.video-js .vjs-big-play-button {
348 font-size: 3em;
349 line-height: 1.5em;
350 height: 1.5em;
351 width: 3em;
352 display: block;
353 position: absolute;
354 top: 10px;
355 left: 10px;
356 padding: 0;
357 cursor: pointer;
358 opacity: 1;
359 border: 0.06666em solid #fff;
360 background-color: #2B333F;
361 background-color: rgba(43, 51, 63, 0.7);
362 -webkit-border-radius: 0.3em;
363 -moz-border-radius: 0.3em;
364 border-radius: 0.3em;
365 -webkit-transition: all 0.4s;
366 -moz-transition: all 0.4s;
367 -o-transition: all 0.4s;
368 transition: all 0.4s; }
369
370.vjs-big-play-centered .vjs-big-play-button {
371 top: 50%;
372 left: 50%;
373 margin-top: -0.75em;
374 margin-left: -1.5em; }
375
376.video-js:hover .vjs-big-play-button,
377.video-js .vjs-big-play-button:focus {
378 outline: 0;
379 border-color: #fff;
380 background-color: #73859f;
381 background-color: rgba(115, 133, 159, 0.5);
382 -webkit-transition: all 0s;
383 -moz-transition: all 0s;
384 -o-transition: all 0s;
385 transition: all 0s; }
386
387.vjs-controls-disabled .vjs-big-play-button,
388.vjs-has-started .vjs-big-play-button,
389.vjs-using-native-controls .vjs-big-play-button,
390.vjs-error .vjs-big-play-button {
391 display: none; }
392
393.video-js button {
394 background: none;
395 border: none;
396 color: inherit;
397 display: inline-block;
398 overflow: visible;
399 font-size: inherit;
400 line-height: inherit;
401 text-transform: none;
402 text-decoration: none;
403 transition: none;
404 -webkit-appearance: none;
405 -moz-appearance: none;
406 appearance: none; }
407
408.video-js .vjs-control.vjs-close-button {
409 cursor: pointer;
410 height: 3em;
411 position: absolute;
412 right: 0;
413 top: 0.5em;
414 z-index: 2; }
415
416.vjs-menu-button {
417 cursor: pointer; }
418
419.vjs-menu .vjs-menu-content {
420 display: block;
421 padding: 0;
422 margin: 0;
423 overflow: auto; }
424
425.vjs-scrubbing .vjs-menu-button:hover .vjs-menu {
426 display: none; }
427
428.vjs-menu li {
429 list-style: none;
430 margin: 0;
431 padding: 0.2em 0;
432 line-height: 1.4em;
433 font-size: 1.2em;
434 text-align: center;
435 text-transform: lowercase; }
436
437.vjs-menu li:focus,
438.vjs-menu li:hover {
439 outline: 0;
440 background-color: #73859f;
441 background-color: rgba(115, 133, 159, 0.5); }
442
443.vjs-menu li.vjs-selected,
444.vjs-menu li.vjs-selected:focus,
445.vjs-menu li.vjs-selected:hover {
446 background-color: #fff;
447 color: #2B333F; }
448
449.vjs-menu li.vjs-menu-title {
450 text-align: center;
451 text-transform: uppercase;
452 font-size: 1em;
453 line-height: 2em;
454 padding: 0;
455 margin: 0 0 0.3em 0;
456 font-weight: bold;
457 cursor: default; }
458
459.vjs-menu-button-popup .vjs-menu {
460 display: none;
461 position: absolute;
462 bottom: 0;
463 width: 10em;
464 left: -3em;
465 height: 0em;
466 margin-bottom: 1.5em;
467 border-top-color: rgba(43, 51, 63, 0.7); }
468
469.vjs-menu-button-popup .vjs-menu .vjs-menu-content {
470 background-color: #2B333F;
471 background-color: rgba(43, 51, 63, 0.7);
472 position: absolute;
473 width: 100%;
474 bottom: 1.5em;
475 max-height: 15em; }
476
477.vjs-workinghover .vjs-menu-button-popup:hover .vjs-menu,
478.vjs-menu-button-popup .vjs-menu.vjs-lock-showing {
479 display: block; }
480
481.video-js .vjs-menu-button-inline {
482 -webkit-transition: all 0.4s;
483 -moz-transition: all 0.4s;
484 -o-transition: all 0.4s;
485 transition: all 0.4s;
486 overflow: hidden; }
487
488.video-js .vjs-menu-button-inline:before {
489 width: 2.222222222em; }
490
491.video-js .vjs-menu-button-inline:hover,
492.video-js .vjs-menu-button-inline:focus,
493.video-js .vjs-menu-button-inline.vjs-slider-active,
494.video-js.vjs-no-flex .vjs-menu-button-inline {
495 width: 12em; }
496
497.video-js .vjs-menu-button-inline.vjs-slider-active {
498 -webkit-transition: none;
499 -moz-transition: none;
500 -o-transition: none;
501 transition: none; }
502
503.vjs-menu-button-inline .vjs-menu {
504 opacity: 0;
505 height: 100%;
506 width: auto;
507 position: absolute;
508 left: 4em;
509 top: 0;
510 padding: 0;
511 margin: 0;
512 -webkit-transition: all 0.4s;
513 -moz-transition: all 0.4s;
514 -o-transition: all 0.4s;
515 transition: all 0.4s; }
516
517.vjs-menu-button-inline:hover .vjs-menu,
518.vjs-menu-button-inline:focus .vjs-menu,
519.vjs-menu-button-inline.vjs-slider-active .vjs-menu {
520 display: block;
521 opacity: 1; }
522
523.vjs-no-flex .vjs-menu-button-inline .vjs-menu {
524 display: block;
525 opacity: 1;
526 position: relative;
527 width: auto; }
528
529.vjs-no-flex .vjs-menu-button-inline:hover .vjs-menu,
530.vjs-no-flex .vjs-menu-button-inline:focus .vjs-menu,
531.vjs-no-flex .vjs-menu-button-inline.vjs-slider-active .vjs-menu {
532 width: auto; }
533
534.vjs-menu-button-inline .vjs-menu-content {
535 width: auto;
536 height: 100%;
537 margin: 0;
538 overflow: hidden; }
539
540.video-js .vjs-control-bar {
541 display: none;
542 width: 100%;
543 position: absolute;
544 bottom: 0;
545 left: 0;
546 right: 0;
547 height: 3.0em;
548 background-color: #2B333F;
549 background-color: rgba(43, 51, 63, 0.7); }
550
551.vjs-has-started .vjs-control-bar {
552 display: -webkit-box;
553 display: -webkit-flex;
554 display: -ms-flexbox;
555 display: flex;
556 visibility: visible;
557 opacity: 1;
558 -webkit-transition: visibility 0.1s, opacity 0.1s;
559 -moz-transition: visibility 0.1s, opacity 0.1s;
560 -o-transition: visibility 0.1s, opacity 0.1s;
561 transition: visibility 0.1s, opacity 0.1s; }
562
563.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
564 visibility: hidden;
565 opacity: 0;
566 -webkit-transition: visibility 1s, opacity 1s;
567 -moz-transition: visibility 1s, opacity 1s;
568 -o-transition: visibility 1s, opacity 1s;
569 transition: visibility 1s, opacity 1s; }
570
571.vjs-controls-disabled .vjs-control-bar,
572.vjs-using-native-controls .vjs-control-bar,
573.vjs-error .vjs-control-bar {
574 display: none !important; }
575
576.vjs-audio.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
577 opacity: 1;
578 visibility: visible; }
579
580@media \0screen {
581 .vjs-user-inactive.vjs-playing .vjs-control-bar :before {
582 content: ""; } }
583
584.vjs-has-started.vjs-no-flex .vjs-control-bar {
585 display: table; }
586
587.video-js .vjs-control {
588 outline: none;
589 position: relative;
590 text-align: center;
591 margin: 0;
592 padding: 0;
593 height: 100%;
594 width: 4em;
595 -webkit-box-flex: none;
596 -moz-box-flex: none;
597 -webkit-flex: none;
598 -ms-flex: none;
599 flex: none; }
600 .video-js .vjs-control:before {
601 font-size: 1.8em;
602 line-height: 1.67; }
603
604.video-js .vjs-control:focus:before,
605.video-js .vjs-control:hover:before,
606.video-js .vjs-control:focus {
607 text-shadow: 0em 0em 1em white; }
608
609.video-js .vjs-control-text {
610 border: 0;
611 clip: rect(0 0 0 0);
612 height: 1px;
613 margin: -1px;
614 overflow: hidden;
615 padding: 0;
616 position: absolute;
617 width: 1px; }
618
619.vjs-no-flex .vjs-control {
620 display: table-cell;
621 vertical-align: middle; }
622
623.video-js .vjs-custom-control-spacer {
624 display: none; }
625
626.video-js .vjs-progress-control {
627 -webkit-box-flex: auto;
628 -moz-box-flex: auto;
629 -webkit-flex: auto;
630 -ms-flex: auto;
631 flex: auto;
632 display: -webkit-box;
633 display: -webkit-flex;
634 display: -ms-flexbox;
635 display: flex;
636 -webkit-box-align: center;
637 -webkit-align-items: center;
638 -ms-flex-align: center;
639 align-items: center;
640 min-width: 4em; }
641
642.vjs-live .vjs-progress-control {
643 display: none; }
644
645.video-js .vjs-progress-holder {
646 -webkit-box-flex: auto;
647 -moz-box-flex: auto;
648 -webkit-flex: auto;
649 -ms-flex: auto;
650 flex: auto;
651 -webkit-transition: all 0.2s;
652 -moz-transition: all 0.2s;
653 -o-transition: all 0.2s;
654 transition: all 0.2s;
655 height: 0.3em; }
656
657.video-js .vjs-progress-control:hover .vjs-progress-holder {
658 font-size: 1.666666666666666666em; }
659
660/* If we let the font size grow as much as everything else, the current time tooltip ends up
661 ginormous. If you'd like to enable the current time tooltip all the time, this should be disabled
662 to avoid a weird hitch when you roll off the hover. */
663.video-js .vjs-progress-control:hover .vjs-mouse-display:after,
664.video-js .vjs-progress-control:hover .vjs-play-progress:after {
665 display: block;
666 font-size: 0.6em; }
667
668.video-js .vjs-progress-holder .vjs-play-progress,
669.video-js .vjs-progress-holder .vjs-load-progress,
670.video-js .vjs-progress-holder .vjs-load-progress div {
671 position: absolute;
672 display: block;
673 height: 0.3em;
674 margin: 0;
675 padding: 0;
676 width: 0;
677 left: 0;
678 top: 0; }
679
680.video-js .vjs-mouse-display:before {
681 display: none; }
682
683.video-js .vjs-play-progress {
684 background-color: #fff; }
685 .video-js .vjs-play-progress:before {
686 position: absolute;
687 top: -0.333333333333333em;
688 right: -0.5em;
689 font-size: 0.9em; }
690
691.video-js .vjs-mouse-display:after,
692.video-js .vjs-play-progress:after {
693 display: none;
694 position: absolute;
695 top: -3.4em;
696 right: -1.5em;
697 font-size: 0.9em;
698 color: #000;
699 content: attr(data-current-time);
700 padding: 6px 8px 8px 8px;
701 background-color: #fff;
702 background-color: rgba(255, 255, 255, 0.8);
703 -webkit-border-radius: 0.3em;
704 -moz-border-radius: 0.3em;
705 border-radius: 0.3em; }
706
707.video-js .vjs-play-progress:before,
708.video-js .vjs-play-progress:after {
709 z-index: 1; }
710
711.video-js .vjs-load-progress {
712 background: #bfc7d3;
713 background: rgba(115, 133, 159, 0.5); }
714
715.video-js .vjs-load-progress div {
716 background: white;
717 background: rgba(115, 133, 159, 0.75); }
718
719.video-js.vjs-no-flex .vjs-progress-control {
720 width: auto; }
721
722.video-js .vjs-progress-control .vjs-mouse-display {
723 display: none;
724 position: absolute;
725 width: 1px;
726 height: 100%;
727 background-color: #000;
728 z-index: 1; }
729
730.vjs-no-flex .vjs-progress-control .vjs-mouse-display {
731 z-index: 0; }
732
733.video-js .vjs-progress-control:hover .vjs-mouse-display {
734 display: block; }
735
736.video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display,
737.video-js.vjs-user-inactive .vjs-progress-control .vjs-mouse-display:after {
738 visibility: hidden;
739 opacity: 0;
740 -webkit-transition: visibility 1s, opacity 1s;
741 -moz-transition: visibility 1s, opacity 1s;
742 -o-transition: visibility 1s, opacity 1s;
743 transition: visibility 1s, opacity 1s; }
744
745.video-js.vjs-user-inactive.vjs-no-flex .vjs-progress-control .vjs-mouse-display,
746.video-js.vjs-user-inactive.vjs-no-flex .vjs-progress-control .vjs-mouse-display:after {
747 display: none; }
748
749.video-js .vjs-progress-control .vjs-mouse-display:after {
750 color: #fff;
751 background-color: #000;
752 background-color: rgba(0, 0, 0, 0.8); }
753
754.video-js .vjs-slider {
755 outline: 0;
756 position: relative;
757 cursor: pointer;
758 padding: 0;
759 margin: 0 0.45em 0 0.45em;
760 background-color: #73859f;
761 background-color: rgba(115, 133, 159, 0.5); }
762
763.video-js .vjs-slider:focus {
764 text-shadow: 0em 0em 1em white;
765 -webkit-box-shadow: 0 0 1em #fff;
766 -moz-box-shadow: 0 0 1em #fff;
767 box-shadow: 0 0 1em #fff; }
768
769.video-js .vjs-mute-control,
770.video-js .vjs-volume-menu-button {
771 cursor: pointer;
772 -webkit-box-flex: none;
773 -moz-box-flex: none;
774 -webkit-flex: none;
775 -ms-flex: none;
776 flex: none; }
777
778.video-js .vjs-volume-control {
779 width: 5em;
780 -webkit-box-flex: none;
781 -moz-box-flex: none;
782 -webkit-flex: none;
783 -ms-flex: none;
784 flex: none;
785 display: -webkit-box;
786 display: -webkit-flex;
787 display: -ms-flexbox;
788 display: flex;
789 -webkit-box-align: center;
790 -webkit-align-items: center;
791 -ms-flex-align: center;
792 align-items: center; }
793
794.video-js .vjs-volume-bar {
795 margin: 1.35em 0.45em; }
796
797.vjs-volume-bar.vjs-slider-horizontal {
798 width: 5em;
799 height: 0.3em; }
800
801.vjs-volume-bar.vjs-slider-vertical {
802 width: 0.3em;
803 height: 5em;
804 margin: 1.35em auto; }
805
806.video-js .vjs-volume-level {
807 position: absolute;
808 bottom: 0;
809 left: 0;
810 background-color: #fff; }
811 .video-js .vjs-volume-level:before {
812 position: absolute;
813 font-size: 0.9em; }
814
815.vjs-slider-vertical .vjs-volume-level {
816 width: 0.3em; }
817 .vjs-slider-vertical .vjs-volume-level:before {
818 top: -0.5em;
819 left: -0.3em; }
820
821.vjs-slider-horizontal .vjs-volume-level {
822 height: 0.3em; }
823 .vjs-slider-horizontal .vjs-volume-level:before {
824 top: -0.3em;
825 right: -0.5em; }
826
827.vjs-volume-bar.vjs-slider-vertical .vjs-volume-level {
828 height: 100%; }
829
830.vjs-volume-bar.vjs-slider-horizontal .vjs-volume-level {
831 width: 100%; }
832
833.vjs-menu-button-popup.vjs-volume-menu-button .vjs-menu {
834 display: block;
835 width: 0;
836 height: 0;
837 border-top-color: transparent; }
838
839.vjs-menu-button-popup.vjs-volume-menu-button-vertical .vjs-menu {
840 left: 0.5em;
841 height: 8em; }
842
843.vjs-menu-button-popup.vjs-volume-menu-button-horizontal .vjs-menu {
844 left: -2em; }
845
846.vjs-menu-button-popup.vjs-volume-menu-button .vjs-menu-content {
847 height: 0;
848 width: 0;
849 overflow-x: hidden;
850 overflow-y: hidden; }
851
852.vjs-volume-menu-button-vertical:hover .vjs-menu-content,
853.vjs-volume-menu-button-vertical:focus .vjs-menu-content,
854.vjs-volume-menu-button-vertical.vjs-slider-active .vjs-menu-content,
855.vjs-volume-menu-button-vertical .vjs-lock-showing .vjs-menu-content {
856 height: 8em;
857 width: 2.9em; }
858
859.vjs-volume-menu-button-horizontal:hover .vjs-menu-content,
860.vjs-volume-menu-button-horizontal:focus .vjs-menu-content,
861.vjs-volume-menu-button-horizontal .vjs-slider-active .vjs-menu-content,
862.vjs-volume-menu-button-horizontal .vjs-lock-showing .vjs-menu-content {
863 height: 2.9em;
864 width: 8em; }
865
866.vjs-volume-menu-button.vjs-menu-button-inline .vjs-menu-content {
867 background-color: transparent !important; }
868
869.vjs-poster {
870 display: inline-block;
871 vertical-align: middle;
872 background-repeat: no-repeat;
873 background-position: 50% 50%;
874 background-size: contain;
875 cursor: pointer;
876 margin: 0;
877 padding: 0;
878 position: absolute;
879 top: 0;
880 right: 0;
881 bottom: 0;
882 left: 0;
883 height: 100%; }
884
885.vjs-poster img {
886 display: block;
887 vertical-align: middle;
888 margin: 0 auto;
889 max-height: 100%;
890 padding: 0;
891 width: 100%; }
892
893.vjs-has-started .vjs-poster {
894 display: none; }
895
896.vjs-audio.vjs-has-started .vjs-poster {
897 display: block; }
898
899.vjs-controls-disabled .vjs-poster {
900 display: none; }
901
902.vjs-using-native-controls .vjs-poster {
903 display: none; }
904
905.video-js .vjs-live-control {
906 display: -webkit-box;
907 display: -webkit-flex;
908 display: -ms-flexbox;
909 display: flex;
910 -webkit-box-align: flex-start;
911 -webkit-align-items: flex-start;
912 -ms-flex-align: flex-start;
913 align-items: flex-start;
914 -webkit-box-flex: auto;
915 -moz-box-flex: auto;
916 -webkit-flex: auto;
917 -ms-flex: auto;
918 flex: auto;
919 font-size: 1em;
920 line-height: 3em; }
921
922.vjs-no-flex .vjs-live-control {
923 display: table-cell;
924 width: auto;
925 text-align: left; }
926
927.video-js .vjs-time-control {
928 -webkit-box-flex: none;
929 -moz-box-flex: none;
930 -webkit-flex: none;
931 -ms-flex: none;
932 flex: none;
933 font-size: 1em;
934 line-height: 3em;
935 min-width: 2em;
936 width: auto;
937 padding-left: 1em;
938 padding-right: 1em; }
939
940.vjs-live .vjs-time-control {
941 display: none; }
942
943.video-js .vjs-current-time,
944.vjs-no-flex .vjs-current-time {
945 display: none; }
946
947.video-js .vjs-duration,
948.vjs-no-flex .vjs-duration {
949 display: none; }
950
951.vjs-time-divider {
952 display: none;
953 line-height: 3em; }
954
955.vjs-live .vjs-time-divider {
956 display: none; }
957
958.video-js .vjs-play-control {
959 cursor: pointer;
960 -webkit-box-flex: none;
961 -moz-box-flex: none;
962 -webkit-flex: none;
963 -ms-flex: none;
964 flex: none; }
965
966.vjs-text-track-display {
967 position: absolute;
968 bottom: 3em;
969 left: 0;
970 right: 0;
971 top: 0;
972 pointer-events: none; }
973
974.video-js.vjs-user-inactive.vjs-playing .vjs-text-track-display {
975 bottom: 1em; }
976
977.video-js .vjs-text-track {
978 font-size: 1.4em;
979 text-align: center;
980 margin-bottom: 0.1em;
981 background-color: #000;
982 background-color: rgba(0, 0, 0, 0.5); }
983
984.vjs-subtitles {
985 color: #fff; }
986
987.vjs-captions {
988 color: #fc6; }
989
990.vjs-tt-cue {
991 display: block; }
992
993video::-webkit-media-text-track-display {
994 -moz-transform: translateY(-3em);
995 -ms-transform: translateY(-3em);
996 -o-transform: translateY(-3em);
997 -webkit-transform: translateY(-3em);
998 transform: translateY(-3em); }
999
1000.video-js.vjs-user-inactive.vjs-playing video::-webkit-media-text-track-display {
1001 -moz-transform: translateY(-1.5em);
1002 -ms-transform: translateY(-1.5em);
1003 -o-transform: translateY(-1.5em);
1004 -webkit-transform: translateY(-1.5em);
1005 transform: translateY(-1.5em); }
1006
1007.video-js .vjs-fullscreen-control {
1008 cursor: pointer;
1009 -webkit-box-flex: none;
1010 -moz-box-flex: none;
1011 -webkit-flex: none;
1012 -ms-flex: none;
1013 flex: none; }
1014
1015.vjs-playback-rate .vjs-playback-rate-value {
1016 font-size: 1.5em;
1017 line-height: 2;
1018 position: absolute;
1019 top: 0;
1020 left: 0;
1021 width: 100%;
1022 height: 100%;
1023 text-align: center; }
1024
1025.vjs-playback-rate .vjs-menu {
1026 width: 4em;
1027 left: 0em; }
1028
1029.vjs-error .vjs-error-display .vjs-modal-dialog-content {
1030 font-size: 1.4em;
1031 text-align: center; }
1032
1033.vjs-error .vjs-error-display:before {
1034 color: #fff;
1035 content: 'X';
1036 font-family: Arial, Helvetica, sans-serif;
1037 font-size: 4em;
1038 left: 0;
1039 line-height: 1;
1040 margin-top: -0.5em;
1041 position: absolute;
1042 text-shadow: 0.05em 0.05em 0.1em #000;
1043 text-align: center;
1044 top: 50%;
1045 vertical-align: middle;
1046 width: 100%; }
1047
1048.vjs-loading-spinner {
1049 display: none;
1050 position: absolute;
1051 top: 50%;
1052 left: 50%;
1053 margin: -25px 0 0 -25px;
1054 opacity: 0.85;
1055 text-align: left;
1056 border: 6px solid rgba(43, 51, 63, 0.7);
1057 box-sizing: border-box;
1058 background-clip: padding-box;
1059 width: 50px;
1060 height: 50px;
1061 border-radius: 25px; }
1062
1063.vjs-seeking .vjs-loading-spinner,
1064.vjs-waiting .vjs-loading-spinner {
1065 display: block; }
1066
1067.vjs-loading-spinner:before,
1068.vjs-loading-spinner:after {
1069 content: "";
1070 position: absolute;
1071 margin: -6px;
1072 box-sizing: inherit;
1073 width: inherit;
1074 height: inherit;
1075 border-radius: inherit;
1076 opacity: 1;
1077 border: inherit;
1078 border-color: transparent;
1079 border-top-color: white; }
1080
1081.vjs-seeking .vjs-loading-spinner:before,
1082.vjs-seeking .vjs-loading-spinner:after,
1083.vjs-waiting .vjs-loading-spinner:before,
1084.vjs-waiting .vjs-loading-spinner:after {
1085 -webkit-animation: vjs-spinner-spin 1.1s cubic-bezier(0.6, 0.2, 0, 0.8) infinite, vjs-spinner-fade 1.1s linear infinite;
1086 animation: vjs-spinner-spin 1.1s cubic-bezier(0.6, 0.2, 0, 0.8) infinite, vjs-spinner-fade 1.1s linear infinite; }
1087
1088.vjs-seeking .vjs-loading-spinner:before,
1089.vjs-waiting .vjs-loading-spinner:before {
1090 border-top-color: white; }
1091
1092.vjs-seeking .vjs-loading-spinner:after,
1093.vjs-waiting .vjs-loading-spinner:after {
1094 border-top-color: white;
1095 -webkit-animation-delay: 0.44s;
1096 animation-delay: 0.44s; }
1097
1098@keyframes vjs-spinner-spin {
1099 100% {
1100 transform: rotate(360deg); } }
1101
1102@-webkit-keyframes vjs-spinner-spin {
1103 100% {
1104 -webkit-transform: rotate(360deg); } }
1105
1106@keyframes vjs-spinner-fade {
1107 0% {
1108 border-top-color: #73859f; }
1109 20% {
1110 border-top-color: #73859f; }
1111 35% {
1112 border-top-color: white; }
1113 60% {
1114 border-top-color: #73859f; }
1115 100% {
1116 border-top-color: #73859f; } }
1117
1118@-webkit-keyframes vjs-spinner-fade {
1119 0% {
1120 border-top-color: #73859f; }
1121 20% {
1122 border-top-color: #73859f; }
1123 35% {
1124 border-top-color: white; }
1125 60% {
1126 border-top-color: #73859f; }
1127 100% {
1128 border-top-color: #73859f; } }
1129
1130.vjs-chapters-button .vjs-menu ul {
1131 width: 24em; }
1132
1133.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-custom-control-spacer {
1134 -webkit-box-flex: auto;
1135 -moz-box-flex: auto;
1136 -webkit-flex: auto;
1137 -ms-flex: auto;
1138 flex: auto; }
1139
1140.video-js.vjs-layout-tiny:not(.vjs-fullscreen).vjs-no-flex .vjs-custom-control-spacer {
1141 width: auto; }
1142
1143.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-current-time, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-time-divider, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-duration, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-remaining-time,
1144.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-playback-rate, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-progress-control,
1145.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-mute-control, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-volume-control, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-volume-menu-button,
1146.video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-chapters-button, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-captions-button, .video-js.vjs-layout-tiny:not(.vjs-fullscreen) .vjs-subtitles-button {
1147 display: none; }
1148
1149.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-current-time, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-time-divider, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-duration, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-remaining-time,
1150.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-playback-rate,
1151.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-mute-control, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-volume-control, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-volume-menu-button,
1152.video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-chapters-button, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-captions-button, .video-js.vjs-layout-x-small:not(.vjs-fullscreen) .vjs-subtitles-button {
1153 display: none; }
1154
1155.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-current-time, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-time-divider, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-duration, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-remaining-time,
1156.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-playback-rate,
1157.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-mute-control, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-volume-control,
1158.video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-chapters-button, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-captions-button, .video-js.vjs-layout-small:not(.vjs-fullscreen) .vjs-subtitles-button {
1159 display: none; }
1160
1161.vjs-caption-settings {
1162 position: relative;
1163 top: 1em;
1164 background-color: #2B333F;
1165 background-color: rgba(43, 51, 63, 0.75);
1166 color: #fff;
1167 margin: 0 auto;
1168 padding: 0.5em;
1169 height: 15em;
1170 font-size: 12px;
1171 width: 40em; }
1172
1173.vjs-caption-settings .vjs-tracksettings {
1174 top: 0;
1175 bottom: 2em;
1176 left: 0;
1177 right: 0;
1178 position: absolute;
1179 overflow: auto; }
1180
1181.vjs-caption-settings .vjs-tracksettings-colors,
1182.vjs-caption-settings .vjs-tracksettings-font {
1183 float: left; }
1184
1185.vjs-caption-settings .vjs-tracksettings-colors:after,
1186.vjs-caption-settings .vjs-tracksettings-font:after,
1187.vjs-caption-settings .vjs-tracksettings-controls:after {
1188 clear: both; }
1189
1190.vjs-caption-settings .vjs-tracksettings-controls {
1191 position: absolute;
1192 bottom: 1em;
1193 right: 1em; }
1194
1195.vjs-caption-settings .vjs-tracksetting {
1196 margin: 5px;
1197 padding: 3px;
1198 min-height: 40px; }
1199
1200.vjs-caption-settings .vjs-tracksetting label {
1201 display: block;
1202 width: 100px;
1203 margin-bottom: 5px; }
1204
1205.vjs-caption-settings .vjs-tracksetting span {
1206 display: inline;
1207 margin-left: 5px; }
1208
1209.vjs-caption-settings .vjs-tracksetting > div {
1210 margin-bottom: 5px;
1211 min-height: 20px; }
1212
1213.vjs-caption-settings .vjs-tracksetting > div:last-child {
1214 margin-bottom: 0;
1215 padding-bottom: 0;
1216 min-height: 0; }
1217
1218.vjs-caption-settings label > input {
1219 margin-right: 10px; }
1220
1221.vjs-caption-settings input[type="button"] {
1222 width: 40px;
1223 height: 40px; }
1224
1225.video-js .vjs-modal-dialog {
1226 background: rgba(0, 0, 0, 0.8);
1227 background: -webkit-linear-gradient(-90deg, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0));
1228 background: linear-gradient(180deg, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0)); }
1229
1230.vjs-modal-dialog .vjs-modal-dialog-content {
1231 font-size: 1.2em;
1232 line-height: 1.5;
1233 padding: 20px 24px;
1234 z-index: 1; }
diff --git a/index.html b/index.html
index 27866a70..8e73df98 100644
--- a/index.html
+++ b/index.html
@@ -3,4 +3,35 @@ title: Sway
3layout: master 3layout: master
4--- 4---
5 5
6<video src="https://sr.ht/-ssd.webm" controls></video> 6<div class="row">
7 <div class="col-md-4">
8 <h1><img src="/assets/logo.png" id="logo" alt="Sway" /></h1>
9 <p>
10 Sway is tiling Wayland compositor and a drop-in replacement for the
11 <a href="http://i3wm.org/">i3 window manager</a> for X11. It works
12 with your existing i3 configuration and supports most of i3's
13 features, plus a few extras.
14 </p>
15 <p>
16 We also maintain the <a href="https://github.com/swaywm/wlroots">wlroots</a>
17 project to provide a modular basis for Sway and other Wayland compositors
18 to build upon, and we <a href="https://github.com/swaywm/sway-protocols">
19 publish standards</a> for interopable Wayland desktops.
20 </p>
21 <a rel="noopener noreferrer" target="_blank" href="https://patreon.com/sircmpwn">
22 <img src="/assets/patreon.png" alt="Support Sway on Patreon" />
23 </a>
24 </div>
25 <div class="col-md-8">
26 <link rel="stylesheet" href="/css/video-js.css">
27 <script>
28 window.HELP_IMPROVE_VIDEOJS = false;
29 </script>
30 <script src="/js/video.js"></script>
31
32 <video class="video-js vjs-16-9" data-setup="{}" controls>
33 <source src="https://sr.ht/lJ9C.webm" type="video/webm">
34 <p>Your browser does not support HTML5 video.</p>
35 </video>
36 </div>
37</div>
diff --git a/js/video.js b/js/video.js
new file mode 100644
index 00000000..03daf688
--- /dev/null
+++ b/js/video.js
@@ -0,0 +1,22383 @@
1/**
2 * @license
3 * Video.js 5.8.8 <http://videojs.com/>
4 * Copyright Brightcove, Inc. <https://www.brightcove.com/>
5 * Available under Apache License Version 2.0
6 * <https://github.com/videojs/video.js/blob/master/LICENSE>
7 *
8 * Includes vtt.js <https://github.com/mozilla/vtt.js>
9 * Available under Apache License Version 2.0
10 * <https://github.com/mozilla/vtt.js/blob/master/LICENSE>
11 */
12
13(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.videojs = f()}})(function(){var define,module,exports;return (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<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
14(function (global){
15var topLevel = typeof global !== 'undefined' ? global :
16 typeof window !== 'undefined' ? window : {}
17var minDoc = _dereq_('min-document');
18
19if (typeof document !== 'undefined') {
20 module.exports = document;
21} else {
22 var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
23
24 if (!doccy) {
25 doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
26 }
27
28 module.exports = doccy;
29}
30
31}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
32//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9nbG9iYWwvZG9jdW1lbnQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6XG4gICAgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB7fVxudmFyIG1pbkRvYyA9IHJlcXVpcmUoJ21pbi1kb2N1bWVudCcpO1xuXG5pZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG59IGVsc2Uge1xuICAgIHZhciBkb2NjeSA9IHRvcExldmVsWydfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0J107XG5cbiAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbJ19fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDQnXSA9IG1pbkRvYztcbiAgICB9XG5cbiAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xufVxuIl19
33},{"min-document":3}],2:[function(_dereq_,module,exports){
34(function (global){
35if (typeof window !== "undefined") {
36 module.exports = window;
37} else if (typeof global !== "undefined") {
38 module.exports = global;
39} else if (typeof self !== "undefined"){
40 module.exports = self;
41} else {
42 module.exports = {};
43}
44
45}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
46//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9nbG9iYWwvd2luZG93LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IHdpbmRvdztcbn0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsO1xufSBlbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIil7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBzZWxmO1xufSBlbHNlIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IHt9O1xufVxuIl19
47},{}],3:[function(_dereq_,module,exports){
48
49},{}],4:[function(_dereq_,module,exports){
50var getNative = _dereq_('../internal/getNative');
51
52/* Native method references for those with the same name as other `lodash` methods. */
53var nativeNow = getNative(Date, 'now');
54
55/**
56 * Gets the number of milliseconds that have elapsed since the Unix epoch
57 * (1 January 1970 00:00:00 UTC).
58 *
59 * @static
60 * @memberOf _
61 * @category Date
62 * @example
63 *
64 * _.defer(function(stamp) {
65 * console.log(_.now() - stamp);
66 * }, _.now());
67 * // => logs the number of milliseconds it took for the deferred function to be invoked
68 */
69var now = nativeNow || function() {
70 return new Date().getTime();
71};
72
73module.exports = now;
74
75},{"../internal/getNative":20}],5:[function(_dereq_,module,exports){
76var isObject = _dereq_('../lang/isObject'),
77 now = _dereq_('../date/now');
78
79/** Used as the `TypeError` message for "Functions" methods. */
80var FUNC_ERROR_TEXT = 'Expected a function';
81
82/* Native method references for those with the same name as other `lodash` methods. */
83var nativeMax = Math.max;
84
85/**
86 * Creates a debounced function that delays invoking `func` until after `wait`
87 * milliseconds have elapsed since the last time the debounced function was
88 * invoked. The debounced function comes with a `cancel` method to cancel
89 * delayed invocations. Provide an options object to indicate that `func`
90 * should be invoked on the leading and/or trailing edge of the `wait` timeout.
91 * Subsequent calls to the debounced function return the result of the last
92 * `func` invocation.
93 *
94 * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
95 * on the trailing edge of the timeout only if the the debounced function is
96 * invoked more than once during the `wait` timeout.
97 *
98 * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
99 * for details over the differences between `_.debounce` and `_.throttle`.
100 *
101 * @static
102 * @memberOf _
103 * @category Function
104 * @param {Function} func The function to debounce.
105 * @param {number} [wait=0] The number of milliseconds to delay.
106 * @param {Object} [options] The options object.
107 * @param {boolean} [options.leading=false] Specify invoking on the leading
108 * edge of the timeout.
109 * @param {number} [options.maxWait] The maximum time `func` is allowed to be
110 * delayed before it's invoked.
111 * @param {boolean} [options.trailing=true] Specify invoking on the trailing
112 * edge of the timeout.
113 * @returns {Function} Returns the new debounced function.
114 * @example
115 *
116 * // avoid costly calculations while the window size is in flux
117 * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
118 *
119 * // invoke `sendMail` when the click event is fired, debouncing subsequent calls
120 * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
121 * 'leading': true,
122 * 'trailing': false
123 * }));
124 *
125 * // ensure `batchLog` is invoked once after 1 second of debounced calls
126 * var source = new EventSource('/stream');
127 * jQuery(source).on('message', _.debounce(batchLog, 250, {
128 * 'maxWait': 1000
129 * }));
130 *
131 * // cancel a debounced call
132 * var todoChanges = _.debounce(batchLog, 1000);
133 * Object.observe(models.todo, todoChanges);
134 *
135 * Object.observe(models, function(changes) {
136 * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
137 * todoChanges.cancel();
138 * }
139 * }, ['delete']);
140 *
141 * // ...at some point `models.todo` is changed
142 * models.todo.completed = true;
143 *
144 * // ...before 1 second has passed `models.todo` is deleted
145 * // which cancels the debounced `todoChanges` call
146 * delete models.todo;
147 */
148function debounce(func, wait, options) {
149 var args,
150 maxTimeoutId,
151 result,
152 stamp,
153 thisArg,
154 timeoutId,
155 trailingCall,
156 lastCalled = 0,
157 maxWait = false,
158 trailing = true;
159
160 if (typeof func != 'function') {
161 throw new TypeError(FUNC_ERROR_TEXT);
162 }
163 wait = wait < 0 ? 0 : (+wait || 0);
164 if (options === true) {
165 var leading = true;
166 trailing = false;
167 } else if (isObject(options)) {
168 leading = !!options.leading;
169 maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);
170 trailing = 'trailing' in options ? !!options.trailing : trailing;
171 }
172
173 function cancel() {
174 if (timeoutId) {
175 clearTimeout(timeoutId);
176 }
177 if (maxTimeoutId) {
178 clearTimeout(maxTimeoutId);
179 }
180 lastCalled = 0;
181 maxTimeoutId = timeoutId = trailingCall = undefined;
182 }
183
184 function complete(isCalled, id) {
185 if (id) {
186 clearTimeout(id);
187 }
188 maxTimeoutId = timeoutId = trailingCall = undefined;
189 if (isCalled) {
190 lastCalled = now();
191 result = func.apply(thisArg, args);
192 if (!timeoutId && !maxTimeoutId) {
193 args = thisArg = undefined;
194 }
195 }
196 }
197
198 function delayed() {
199 var remaining = wait - (now() - stamp);
200 if (remaining <= 0 || remaining > wait) {
201 complete(trailingCall, maxTimeoutId);
202 } else {
203 timeoutId = setTimeout(delayed, remaining);
204 }
205 }
206
207 function maxDelayed() {
208 complete(trailing, timeoutId);
209 }
210
211 function debounced() {
212 args = arguments;
213 stamp = now();
214 thisArg = this;
215 trailingCall = trailing && (timeoutId || !leading);
216
217 if (maxWait === false) {
218 var leadingCall = leading && !timeoutId;
219 } else {
220 if (!maxTimeoutId && !leading) {
221 lastCalled = stamp;
222 }
223 var remaining = maxWait - (stamp - lastCalled),
224 isCalled = remaining <= 0 || remaining > maxWait;
225
226 if (isCalled) {
227 if (maxTimeoutId) {
228 maxTimeoutId = clearTimeout(maxTimeoutId);
229 }
230 lastCalled = stamp;
231 result = func.apply(thisArg, args);
232 }
233 else if (!maxTimeoutId) {
234 maxTimeoutId = setTimeout(maxDelayed, remaining);
235 }
236 }
237 if (isCalled && timeoutId) {
238 timeoutId = clearTimeout(timeoutId);
239 }
240 else if (!timeoutId && wait !== maxWait) {
241 timeoutId = setTimeout(delayed, wait);
242 }
243 if (leadingCall) {
244 isCalled = true;
245 result = func.apply(thisArg, args);
246 }
247 if (isCalled && !timeoutId && !maxTimeoutId) {
248 args = thisArg = undefined;
249 }
250 return result;
251 }
252 debounced.cancel = cancel;
253 return debounced;
254}
255
256module.exports = debounce;
257
258},{"../date/now":4,"../lang/isObject":33}],6:[function(_dereq_,module,exports){
259/** Used as the `TypeError` message for "Functions" methods. */
260var FUNC_ERROR_TEXT = 'Expected a function';
261
262/* Native method references for those with the same name as other `lodash` methods. */
263var nativeMax = Math.max;
264
265/**
266 * Creates a function that invokes `func` with the `this` binding of the
267 * created function and arguments from `start` and beyond provided as an array.
268 *
269 * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/Web/JavaScript/Reference/Functions/rest_parameters).
270 *
271 * @static
272 * @memberOf _
273 * @category Function
274 * @param {Function} func The function to apply a rest parameter to.
275 * @param {number} [start=func.length-1] The start position of the rest parameter.
276 * @returns {Function} Returns the new function.
277 * @example
278 *
279 * var say = _.restParam(function(what, names) {
280 * return what + ' ' + _.initial(names).join(', ') +
281 * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
282 * });
283 *
284 * say('hello', 'fred', 'barney', 'pebbles');
285 * // => 'hello fred, barney, & pebbles'
286 */
287function restParam(func, start) {
288 if (typeof func != 'function') {
289 throw new TypeError(FUNC_ERROR_TEXT);
290 }
291 start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
292 return function() {
293 var args = arguments,
294 index = -1,
295 length = nativeMax(args.length - start, 0),
296 rest = Array(length);
297
298 while (++index < length) {
299 rest[index] = args[start + index];
300 }
301 switch (start) {
302 case 0: return func.call(this, rest);
303 case 1: return func.call(this, args[0], rest);
304 case 2: return func.call(this, args[0], args[1], rest);
305 }
306 var otherArgs = Array(start + 1);
307 index = -1;
308 while (++index < start) {
309 otherArgs[index] = args[index];
310 }
311 otherArgs[start] = rest;
312 return func.apply(this, otherArgs);
313 };
314}
315
316module.exports = restParam;
317
318},{}],7:[function(_dereq_,module,exports){
319var debounce = _dereq_('./debounce'),
320 isObject = _dereq_('../lang/isObject');
321
322/** Used as the `TypeError` message for "Functions" methods. */
323var FUNC_ERROR_TEXT = 'Expected a function';
324
325/**
326 * Creates a throttled function that only invokes `func` at most once per
327 * every `wait` milliseconds. The throttled function comes with a `cancel`
328 * method to cancel delayed invocations. Provide an options object to indicate
329 * that `func` should be invoked on the leading and/or trailing edge of the
330 * `wait` timeout. Subsequent calls to the throttled function return the
331 * result of the last `func` call.
332 *
333 * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
334 * on the trailing edge of the timeout only if the the throttled function is
335 * invoked more than once during the `wait` timeout.
336 *
337 * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
338 * for details over the differences between `_.throttle` and `_.debounce`.
339 *
340 * @static
341 * @memberOf _
342 * @category Function
343 * @param {Function} func The function to throttle.
344 * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
345 * @param {Object} [options] The options object.
346 * @param {boolean} [options.leading=true] Specify invoking on the leading
347 * edge of the timeout.
348 * @param {boolean} [options.trailing=true] Specify invoking on the trailing
349 * edge of the timeout.
350 * @returns {Function} Returns the new throttled function.
351 * @example
352 *
353 * // avoid excessively updating the position while scrolling
354 * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
355 *
356 * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
357 * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
358 * 'trailing': false
359 * }));
360 *
361 * // cancel a trailing throttled call
362 * jQuery(window).on('popstate', throttled.cancel);
363 */
364function throttle(func, wait, options) {
365 var leading = true,
366 trailing = true;
367
368 if (typeof func != 'function') {
369 throw new TypeError(FUNC_ERROR_TEXT);
370 }
371 if (options === false) {
372 leading = false;
373 } else if (isObject(options)) {
374 leading = 'leading' in options ? !!options.leading : leading;
375 trailing = 'trailing' in options ? !!options.trailing : trailing;
376 }
377 return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing });
378}
379
380module.exports = throttle;
381
382},{"../lang/isObject":33,"./debounce":5}],8:[function(_dereq_,module,exports){
383/**
384 * Copies the values of `source` to `array`.
385 *
386 * @private
387 * @param {Array} source The array to copy values from.
388 * @param {Array} [array=[]] The array to copy values to.
389 * @returns {Array} Returns `array`.
390 */
391function arrayCopy(source, array) {
392 var index = -1,
393 length = source.length;
394
395 array || (array = Array(length));
396 while (++index < length) {
397 array[index] = source[index];
398 }
399 return array;
400}
401
402module.exports = arrayCopy;
403
404},{}],9:[function(_dereq_,module,exports){
405/**
406 * A specialized version of `_.forEach` for arrays without support for callback
407 * shorthands and `this` binding.
408 *
409 * @private
410 * @param {Array} array The array to iterate over.
411 * @param {Function} iteratee The function invoked per iteration.
412 * @returns {Array} Returns `array`.
413 */
414function arrayEach(array, iteratee) {
415 var index = -1,
416 length = array.length;
417
418 while (++index < length) {
419 if (iteratee(array[index], index, array) === false) {
420 break;
421 }
422 }
423 return array;
424}
425
426module.exports = arrayEach;
427
428},{}],10:[function(_dereq_,module,exports){
429/**
430 * Copies properties of `source` to `object`.
431 *
432 * @private
433 * @param {Object} source The object to copy properties from.
434 * @param {Array} props The property names to copy.
435 * @param {Object} [object={}] The object to copy properties to.
436 * @returns {Object} Returns `object`.
437 */
438function baseCopy(source, props, object) {
439 object || (object = {});
440
441 var index = -1,
442 length = props.length;
443
444 while (++index < length) {
445 var key = props[index];
446 object[key] = source[key];
447 }
448 return object;
449}
450
451module.exports = baseCopy;
452
453},{}],11:[function(_dereq_,module,exports){
454var createBaseFor = _dereq_('./createBaseFor');
455
456/**
457 * The base implementation of `baseForIn` and `baseForOwn` which iterates
458 * over `object` properties returned by `keysFunc` invoking `iteratee` for
459 * each property. Iteratee functions may exit iteration early by explicitly
460 * returning `false`.
461 *
462 * @private
463 * @param {Object} object The object to iterate over.
464 * @param {Function} iteratee The function invoked per iteration.
465 * @param {Function} keysFunc The function to get the keys of `object`.
466 * @returns {Object} Returns `object`.
467 */
468var baseFor = createBaseFor();
469
470module.exports = baseFor;
471
472},{"./createBaseFor":18}],12:[function(_dereq_,module,exports){
473var baseFor = _dereq_('./baseFor'),
474 keysIn = _dereq_('../object/keysIn');
475
476/**
477 * The base implementation of `_.forIn` without support for callback
478 * shorthands and `this` binding.
479 *
480 * @private
481 * @param {Object} object The object to iterate over.
482 * @param {Function} iteratee The function invoked per iteration.
483 * @returns {Object} Returns `object`.
484 */
485function baseForIn(object, iteratee) {
486 return baseFor(object, iteratee, keysIn);
487}
488
489module.exports = baseForIn;
490
491},{"../object/keysIn":39,"./baseFor":11}],13:[function(_dereq_,module,exports){
492var arrayEach = _dereq_('./arrayEach'),
493 baseMergeDeep = _dereq_('./baseMergeDeep'),
494 isArray = _dereq_('../lang/isArray'),
495 isArrayLike = _dereq_('./isArrayLike'),
496 isObject = _dereq_('../lang/isObject'),
497 isObjectLike = _dereq_('./isObjectLike'),
498 isTypedArray = _dereq_('../lang/isTypedArray'),
499 keys = _dereq_('../object/keys');
500
501/**
502 * The base implementation of `_.merge` without support for argument juggling,
503 * multiple sources, and `this` binding `customizer` functions.
504 *
505 * @private
506 * @param {Object} object The destination object.
507 * @param {Object} source The source object.
508 * @param {Function} [customizer] The function to customize merged values.
509 * @param {Array} [stackA=[]] Tracks traversed source objects.
510 * @param {Array} [stackB=[]] Associates values with source counterparts.
511 * @returns {Object} Returns `object`.
512 */
513function baseMerge(object, source, customizer, stackA, stackB) {
514 if (!isObject(object)) {
515 return object;
516 }
517 var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)),
518 props = isSrcArr ? undefined : keys(source);
519
520 arrayEach(props || source, function(srcValue, key) {
521 if (props) {
522 key = srcValue;
523 srcValue = source[key];
524 }
525 if (isObjectLike(srcValue)) {
526 stackA || (stackA = []);
527 stackB || (stackB = []);
528 baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
529 }
530 else {
531 var value = object[key],
532 result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
533 isCommon = result === undefined;
534
535 if (isCommon) {
536 result = srcValue;
537 }
538 if ((result !== undefined || (isSrcArr && !(key in object))) &&
539 (isCommon || (result === result ? (result !== value) : (value === value)))) {
540 object[key] = result;
541 }
542 }
543 });
544 return object;
545}
546
547module.exports = baseMerge;
548
549},{"../lang/isArray":30,"../lang/isObject":33,"../lang/isTypedArray":36,"../object/keys":38,"./arrayEach":9,"./baseMergeDeep":14,"./isArrayLike":21,"./isObjectLike":26}],14:[function(_dereq_,module,exports){
550var arrayCopy = _dereq_('./arrayCopy'),
551 isArguments = _dereq_('../lang/isArguments'),
552 isArray = _dereq_('../lang/isArray'),
553 isArrayLike = _dereq_('./isArrayLike'),
554 isPlainObject = _dereq_('../lang/isPlainObject'),
555 isTypedArray = _dereq_('../lang/isTypedArray'),
556 toPlainObject = _dereq_('../lang/toPlainObject');
557
558/**
559 * A specialized version of `baseMerge` for arrays and objects which performs
560 * deep merges and tracks traversed objects enabling objects with circular
561 * references to be merged.
562 *
563 * @private
564 * @param {Object} object The destination object.
565 * @param {Object} source The source object.
566 * @param {string} key The key of the value to merge.
567 * @param {Function} mergeFunc The function to merge values.
568 * @param {Function} [customizer] The function to customize merged values.
569 * @param {Array} [stackA=[]] Tracks traversed source objects.
570 * @param {Array} [stackB=[]] Associates values with source counterparts.
571 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
572 */
573function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
574 var length = stackA.length,
575 srcValue = source[key];
576
577 while (length--) {
578 if (stackA[length] == srcValue) {
579 object[key] = stackB[length];
580 return;
581 }
582 }
583 var value = object[key],
584 result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
585 isCommon = result === undefined;
586
587 if (isCommon) {
588 result = srcValue;
589 if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {
590 result = isArray(value)
591 ? value
592 : (isArrayLike(value) ? arrayCopy(value) : []);
593 }
594 else if (isPlainObject(srcValue) || isArguments(srcValue)) {
595 result = isArguments(value)
596 ? toPlainObject(value)
597 : (isPlainObject(value) ? value : {});
598 }
599 else {
600 isCommon = false;
601 }
602 }
603 // Add the source value to the stack of traversed objects and associate
604 // it with its merged value.
605 stackA.push(srcValue);
606 stackB.push(result);
607
608 if (isCommon) {
609 // Recursively merge objects and arrays (susceptible to call stack limits).
610 object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
611 } else if (result === result ? (result !== value) : (value === value)) {
612 object[key] = result;
613 }
614}
615
616module.exports = baseMergeDeep;
617
618},{"../lang/isArguments":29,"../lang/isArray":30,"../lang/isPlainObject":34,"../lang/isTypedArray":36,"../lang/toPlainObject":37,"./arrayCopy":8,"./isArrayLike":21}],15:[function(_dereq_,module,exports){
619var toObject = _dereq_('./toObject');
620
621/**
622 * The base implementation of `_.property` without support for deep paths.
623 *
624 * @private
625 * @param {string} key The key of the property to get.
626 * @returns {Function} Returns the new function.
627 */
628function baseProperty(key) {
629 return function(object) {
630 return object == null ? undefined : toObject(object)[key];
631 };
632}
633
634module.exports = baseProperty;
635
636},{"./toObject":28}],16:[function(_dereq_,module,exports){
637var identity = _dereq_('../utility/identity');
638
639/**
640 * A specialized version of `baseCallback` which only supports `this` binding
641 * and specifying the number of arguments to provide to `func`.
642 *
643 * @private
644 * @param {Function} func The function to bind.
645 * @param {*} thisArg The `this` binding of `func`.
646 * @param {number} [argCount] The number of arguments to provide to `func`.
647 * @returns {Function} Returns the callback.
648 */
649function bindCallback(func, thisArg, argCount) {
650 if (typeof func != 'function') {
651 return identity;
652 }
653 if (thisArg === undefined) {
654 return func;
655 }
656 switch (argCount) {
657 case 1: return function(value) {
658 return func.call(thisArg, value);
659 };
660 case 3: return function(value, index, collection) {
661 return func.call(thisArg, value, index, collection);
662 };
663 case 4: return function(accumulator, value, index, collection) {
664 return func.call(thisArg, accumulator, value, index, collection);
665 };
666 case 5: return function(value, other, key, object, source) {
667 return func.call(thisArg, value, other, key, object, source);
668 };
669 }
670 return function() {
671 return func.apply(thisArg, arguments);
672 };
673}
674
675module.exports = bindCallback;
676
677},{"../utility/identity":42}],17:[function(_dereq_,module,exports){
678var bindCallback = _dereq_('./bindCallback'),
679 isIterateeCall = _dereq_('./isIterateeCall'),
680 restParam = _dereq_('../function/restParam');
681
682/**
683 * Creates a `_.assign`, `_.defaults`, or `_.merge` function.
684 *
685 * @private
686 * @param {Function} assigner The function to assign values.
687 * @returns {Function} Returns the new assigner function.
688 */
689function createAssigner(assigner) {
690 return restParam(function(object, sources) {
691 var index = -1,
692 length = object == null ? 0 : sources.length,
693 customizer = length > 2 ? sources[length - 2] : undefined,
694 guard = length > 2 ? sources[2] : undefined,
695 thisArg = length > 1 ? sources[length - 1] : undefined;
696
697 if (typeof customizer == 'function') {
698 customizer = bindCallback(customizer, thisArg, 5);
699 length -= 2;
700 } else {
701 customizer = typeof thisArg == 'function' ? thisArg : undefined;
702 length -= (customizer ? 1 : 0);
703 }
704 if (guard && isIterateeCall(sources[0], sources[1], guard)) {
705 customizer = length < 3 ? undefined : customizer;
706 length = 1;
707 }
708 while (++index < length) {
709 var source = sources[index];
710 if (source) {
711 assigner(object, source, customizer);
712 }
713 }
714 return object;
715 });
716}
717
718module.exports = createAssigner;
719
720},{"../function/restParam":6,"./bindCallback":16,"./isIterateeCall":24}],18:[function(_dereq_,module,exports){
721var toObject = _dereq_('./toObject');
722
723/**
724 * Creates a base function for `_.forIn` or `_.forInRight`.
725 *
726 * @private
727 * @param {boolean} [fromRight] Specify iterating from right to left.
728 * @returns {Function} Returns the new base function.
729 */
730function createBaseFor(fromRight) {
731 return function(object, iteratee, keysFunc) {
732 var iterable = toObject(object),
733 props = keysFunc(object),
734 length = props.length,
735 index = fromRight ? length : -1;
736
737 while ((fromRight ? index-- : ++index < length)) {
738 var key = props[index];
739 if (iteratee(iterable[key], key, iterable) === false) {
740 break;
741 }
742 }
743 return object;
744 };
745}
746
747module.exports = createBaseFor;
748
749},{"./toObject":28}],19:[function(_dereq_,module,exports){
750var baseProperty = _dereq_('./baseProperty');
751
752/**
753 * Gets the "length" property value of `object`.
754 *
755 * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
756 * that affects Safari on at least iOS 8.1-8.3 ARM64.
757 *
758 * @private
759 * @param {Object} object The object to query.
760 * @returns {*} Returns the "length" value.
761 */
762var getLength = baseProperty('length');
763
764module.exports = getLength;
765
766},{"./baseProperty":15}],20:[function(_dereq_,module,exports){
767var isNative = _dereq_('../lang/isNative');
768
769/**
770 * Gets the native function at `key` of `object`.
771 *
772 * @private
773 * @param {Object} object The object to query.
774 * @param {string} key The key of the method to get.
775 * @returns {*} Returns the function if it's native, else `undefined`.
776 */
777function getNative(object, key) {
778 var value = object == null ? undefined : object[key];
779 return isNative(value) ? value : undefined;
780}
781
782module.exports = getNative;
783
784},{"../lang/isNative":32}],21:[function(_dereq_,module,exports){
785var getLength = _dereq_('./getLength'),
786 isLength = _dereq_('./isLength');
787
788/**
789 * Checks if `value` is array-like.
790 *
791 * @private
792 * @param {*} value The value to check.
793 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
794 */
795function isArrayLike(value) {
796 return value != null && isLength(getLength(value));
797}
798
799module.exports = isArrayLike;
800
801},{"./getLength":19,"./isLength":25}],22:[function(_dereq_,module,exports){
802/**
803 * Checks if `value` is a host object in IE < 9.
804 *
805 * @private
806 * @param {*} value The value to check.
807 * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
808 */
809var isHostObject = (function() {
810 try {
811 Object({ 'toString': 0 } + '');
812 } catch(e) {
813 return function() { return false; };
814 }
815 return function(value) {
816 // IE < 9 presents many host objects as `Object` objects that can coerce
817 // to strings despite having improperly defined `toString` methods.
818 return typeof value.toString != 'function' && typeof (value + '') == 'string';
819 };
820}());
821
822module.exports = isHostObject;
823
824},{}],23:[function(_dereq_,module,exports){
825/** Used to detect unsigned integer values. */
826var reIsUint = /^\d+$/;
827
828/**
829 * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
830 * of an array-like value.
831 */
832var MAX_SAFE_INTEGER = 9007199254740991;
833
834/**
835 * Checks if `value` is a valid array-like index.
836 *
837 * @private
838 * @param {*} value The value to check.
839 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
840 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
841 */
842function isIndex(value, length) {
843 value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
844 length = length == null ? MAX_SAFE_INTEGER : length;
845 return value > -1 && value % 1 == 0 && value < length;
846}
847
848module.exports = isIndex;
849
850},{}],24:[function(_dereq_,module,exports){
851var isArrayLike = _dereq_('./isArrayLike'),
852 isIndex = _dereq_('./isIndex'),
853 isObject = _dereq_('../lang/isObject');
854
855/**
856 * Checks if the provided arguments are from an iteratee call.
857 *
858 * @private
859 * @param {*} value The potential iteratee value argument.
860 * @param {*} index The potential iteratee index or key argument.
861 * @param {*} object The potential iteratee object argument.
862 * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
863 */
864function isIterateeCall(value, index, object) {
865 if (!isObject(object)) {
866 return false;
867 }
868 var type = typeof index;
869 if (type == 'number'
870 ? (isArrayLike(object) && isIndex(index, object.length))
871 : (type == 'string' && index in object)) {
872 var other = object[index];
873 return value === value ? (value === other) : (other !== other);
874 }
875 return false;
876}
877
878module.exports = isIterateeCall;
879
880},{"../lang/isObject":33,"./isArrayLike":21,"./isIndex":23}],25:[function(_dereq_,module,exports){
881/**
882 * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
883 * of an array-like value.
884 */
885var MAX_SAFE_INTEGER = 9007199254740991;
886
887/**
888 * Checks if `value` is a valid array-like length.
889 *
890 * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
891 *
892 * @private
893 * @param {*} value The value to check.
894 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
895 */
896function isLength(value) {
897 return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
898}
899
900module.exports = isLength;
901
902},{}],26:[function(_dereq_,module,exports){
903/**
904 * Checks if `value` is object-like.
905 *
906 * @private
907 * @param {*} value The value to check.
908 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
909 */
910function isObjectLike(value) {
911 return !!value && typeof value == 'object';
912}
913
914module.exports = isObjectLike;
915
916},{}],27:[function(_dereq_,module,exports){
917var isArguments = _dereq_('../lang/isArguments'),
918 isArray = _dereq_('../lang/isArray'),
919 isIndex = _dereq_('./isIndex'),
920 isLength = _dereq_('./isLength'),
921 isString = _dereq_('../lang/isString'),
922 keysIn = _dereq_('../object/keysIn');
923
924/** Used for native method references. */
925var objectProto = Object.prototype;
926
927/** Used to check objects for own properties. */
928var hasOwnProperty = objectProto.hasOwnProperty;
929
930/**
931 * A fallback implementation of `Object.keys` which creates an array of the
932 * own enumerable property names of `object`.
933 *
934 * @private
935 * @param {Object} object The object to query.
936 * @returns {Array} Returns the array of property names.
937 */
938function shimKeys(object) {
939 var props = keysIn(object),
940 propsLength = props.length,
941 length = propsLength && object.length;
942
943 var allowIndexes = !!length && isLength(length) &&
944 (isArray(object) || isArguments(object) || isString(object));
945
946 var index = -1,
947 result = [];
948
949 while (++index < propsLength) {
950 var key = props[index];
951 if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
952 result.push(key);
953 }
954 }
955 return result;
956}
957
958module.exports = shimKeys;
959
960},{"../lang/isArguments":29,"../lang/isArray":30,"../lang/isString":35,"../object/keysIn":39,"./isIndex":23,"./isLength":25}],28:[function(_dereq_,module,exports){
961var isObject = _dereq_('../lang/isObject'),
962 isString = _dereq_('../lang/isString'),
963 support = _dereq_('../support');
964
965/**
966 * Converts `value` to an object if it's not one.
967 *
968 * @private
969 * @param {*} value The value to process.
970 * @returns {Object} Returns the object.
971 */
972function toObject(value) {
973 if (support.unindexedChars && isString(value)) {
974 var index = -1,
975 length = value.length,
976 result = Object(value);
977
978 while (++index < length) {
979 result[index] = value.charAt(index);
980 }
981 return result;
982 }
983 return isObject(value) ? value : Object(value);
984}
985
986module.exports = toObject;
987
988},{"../lang/isObject":33,"../lang/isString":35,"../support":41}],29:[function(_dereq_,module,exports){
989var isArrayLike = _dereq_('../internal/isArrayLike'),
990 isObjectLike = _dereq_('../internal/isObjectLike');
991
992/** Used for native method references. */
993var objectProto = Object.prototype;
994
995/** Used to check objects for own properties. */
996var hasOwnProperty = objectProto.hasOwnProperty;
997
998/** Native method references. */
999var propertyIsEnumerable = objectProto.propertyIsEnumerable;
1000
1001/**
1002 * Checks if `value` is classified as an `arguments` object.
1003 *
1004 * @static
1005 * @memberOf _
1006 * @category Lang
1007 * @param {*} value The value to check.
1008 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
1009 * @example
1010 *
1011 * _.isArguments(function() { return arguments; }());
1012 * // => true
1013 *
1014 * _.isArguments([1, 2, 3]);
1015 * // => false
1016 */
1017function isArguments(value) {
1018 return isObjectLike(value) && isArrayLike(value) &&
1019 hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
1020}
1021
1022module.exports = isArguments;
1023
1024},{"../internal/isArrayLike":21,"../internal/isObjectLike":26}],30:[function(_dereq_,module,exports){
1025var getNative = _dereq_('../internal/getNative'),
1026 isLength = _dereq_('../internal/isLength'),
1027 isObjectLike = _dereq_('../internal/isObjectLike');
1028
1029/** `Object#toString` result references. */
1030var arrayTag = '[object Array]';
1031
1032/** Used for native method references. */
1033var objectProto = Object.prototype;
1034
1035/**
1036 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
1037 * of values.
1038 */
1039var objToString = objectProto.toString;
1040
1041/* Native method references for those with the same name as other `lodash` methods. */
1042var nativeIsArray = getNative(Array, 'isArray');
1043
1044/**
1045 * Checks if `value` is classified as an `Array` object.
1046 *
1047 * @static
1048 * @memberOf _
1049 * @category Lang
1050 * @param {*} value The value to check.
1051 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
1052 * @example
1053 *
1054 * _.isArray([1, 2, 3]);
1055 * // => true
1056 *
1057 * _.isArray(function() { return arguments; }());
1058 * // => false
1059 */
1060var isArray = nativeIsArray || function(value) {
1061 return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
1062};
1063
1064module.exports = isArray;
1065
1066},{"../internal/getNative":20,"../internal/isLength":25,"../internal/isObjectLike":26}],31:[function(_dereq_,module,exports){
1067var isObject = _dereq_('./isObject');
1068
1069/** `Object#toString` result references. */
1070var funcTag = '[object Function]';
1071
1072/** Used for native method references. */
1073var objectProto = Object.prototype;
1074
1075/**
1076 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
1077 * of values.
1078 */
1079var objToString = objectProto.toString;
1080
1081/**
1082 * Checks if `value` is classified as a `Function` object.
1083 *
1084 * @static
1085 * @memberOf _
1086 * @category Lang
1087 * @param {*} value The value to check.
1088 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
1089 * @example
1090 *
1091 * _.isFunction(_);
1092 * // => true
1093 *
1094 * _.isFunction(/abc/);
1095 * // => false
1096 */
1097function isFunction(value) {
1098 // The use of `Object#toString` avoids issues with the `typeof` operator
1099 // in older versions of Chrome and Safari which return 'function' for regexes
1100 // and Safari 8 which returns 'object' for typed array constructors.
1101 return isObject(value) && objToString.call(value) == funcTag;
1102}
1103
1104module.exports = isFunction;
1105
1106},{"./isObject":33}],32:[function(_dereq_,module,exports){
1107var isFunction = _dereq_('./isFunction'),
1108 isHostObject = _dereq_('../internal/isHostObject'),
1109 isObjectLike = _dereq_('../internal/isObjectLike');
1110
1111/** Used to detect host constructors (Safari > 5). */
1112var reIsHostCtor = /^\[object .+?Constructor\]$/;
1113
1114/** Used for native method references. */
1115var objectProto = Object.prototype;
1116
1117/** Used to resolve the decompiled source of functions. */
1118var fnToString = Function.prototype.toString;
1119
1120/** Used to check objects for own properties. */
1121var hasOwnProperty = objectProto.hasOwnProperty;
1122
1123/** Used to detect if a method is native. */
1124var reIsNative = RegExp('^' +
1125 fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
1126 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
1127);
1128
1129/**
1130 * Checks if `value` is a native function.
1131 *
1132 * @static
1133 * @memberOf _
1134 * @category Lang
1135 * @param {*} value The value to check.
1136 * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
1137 * @example
1138 *
1139 * _.isNative(Array.prototype.push);
1140 * // => true
1141 *
1142 * _.isNative(_);
1143 * // => false
1144 */
1145function isNative(value) {
1146 if (value == null) {
1147 return false;
1148 }
1149 if (isFunction(value)) {
1150 return reIsNative.test(fnToString.call(value));
1151 }
1152 return isObjectLike(value) && (isHostObject(value) ? reIsNative : reIsHostCtor).test(value);
1153}
1154
1155module.exports = isNative;
1156
1157},{"../internal/isHostObject":22,"../internal/isObjectLike":26,"./isFunction":31}],33:[function(_dereq_,module,exports){
1158/**
1159 * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
1160 * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
1161 *
1162 * @static
1163 * @memberOf _
1164 * @category Lang
1165 * @param {*} value The value to check.
1166 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
1167 * @example
1168 *
1169 * _.isObject({});
1170 * // => true
1171 *
1172 * _.isObject([1, 2, 3]);
1173 * // => true
1174 *
1175 * _.isObject(1);
1176 * // => false
1177 */
1178function isObject(value) {
1179 // Avoid a V8 JIT bug in Chrome 19-20.
1180 // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
1181 var type = typeof value;
1182 return !!value && (type == 'object' || type == 'function');
1183}
1184
1185module.exports = isObject;
1186
1187},{}],34:[function(_dereq_,module,exports){
1188var baseForIn = _dereq_('../internal/baseForIn'),
1189 isArguments = _dereq_('./isArguments'),
1190 isHostObject = _dereq_('../internal/isHostObject'),
1191 isObjectLike = _dereq_('../internal/isObjectLike'),
1192 support = _dereq_('../support');
1193
1194/** `Object#toString` result references. */
1195var objectTag = '[object Object]';
1196
1197/** Used for native method references. */
1198var objectProto = Object.prototype;
1199
1200/** Used to check objects for own properties. */
1201var hasOwnProperty = objectProto.hasOwnProperty;
1202
1203/**
1204 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
1205 * of values.
1206 */
1207var objToString = objectProto.toString;
1208
1209/**
1210 * Checks if `value` is a plain object, that is, an object created by the
1211 * `Object` constructor or one with a `[[Prototype]]` of `null`.
1212 *
1213 * **Note:** This method assumes objects created by the `Object` constructor
1214 * have no inherited enumerable properties.
1215 *
1216 * @static
1217 * @memberOf _
1218 * @category Lang
1219 * @param {*} value The value to check.
1220 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
1221 * @example
1222 *
1223 * function Foo() {
1224 * this.a = 1;
1225 * }
1226 *
1227 * _.isPlainObject(new Foo);
1228 * // => false
1229 *
1230 * _.isPlainObject([1, 2, 3]);
1231 * // => false
1232 *
1233 * _.isPlainObject({ 'x': 0, 'y': 0 });
1234 * // => true
1235 *
1236 * _.isPlainObject(Object.create(null));
1237 * // => true
1238 */
1239function isPlainObject(value) {
1240 var Ctor;
1241
1242 // Exit early for non `Object` objects.
1243 if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value) && !isArguments(value)) ||
1244 (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
1245 return false;
1246 }
1247 // IE < 9 iterates inherited properties before own properties. If the first
1248 // iterated property is an object's own property then there are no inherited
1249 // enumerable properties.
1250 var result;
1251 if (support.ownLast) {
1252 baseForIn(value, function(subValue, key, object) {
1253 result = hasOwnProperty.call(object, key);
1254 return false;
1255 });
1256 return result !== false;
1257 }
1258 // In most environments an object's own properties are iterated before
1259 // its inherited properties. If the last iterated property is an object's
1260 // own property then there are no inherited enumerable properties.
1261 baseForIn(value, function(subValue, key) {
1262 result = key;
1263 });
1264 return result === undefined || hasOwnProperty.call(value, result);
1265}
1266
1267module.exports = isPlainObject;
1268
1269},{"../internal/baseForIn":12,"../internal/isHostObject":22,"../internal/isObjectLike":26,"../support":41,"./isArguments":29}],35:[function(_dereq_,module,exports){
1270var isObjectLike = _dereq_('../internal/isObjectLike');
1271
1272/** `Object#toString` result references. */
1273var stringTag = '[object String]';
1274
1275/** Used for native method references. */
1276var objectProto = Object.prototype;
1277
1278/**
1279 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
1280 * of values.
1281 */
1282var objToString = objectProto.toString;
1283
1284/**
1285 * Checks if `value` is classified as a `String` primitive or object.
1286 *
1287 * @static
1288 * @memberOf _
1289 * @category Lang
1290 * @param {*} value The value to check.
1291 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
1292 * @example
1293 *
1294 * _.isString('abc');
1295 * // => true
1296 *
1297 * _.isString(1);
1298 * // => false
1299 */
1300function isString(value) {
1301 return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
1302}
1303
1304module.exports = isString;
1305
1306},{"../internal/isObjectLike":26}],36:[function(_dereq_,module,exports){
1307var isLength = _dereq_('../internal/isLength'),
1308 isObjectLike = _dereq_('../internal/isObjectLike');
1309
1310/** `Object#toString` result references. */
1311var argsTag = '[object Arguments]',
1312 arrayTag = '[object Array]',
1313 boolTag = '[object Boolean]',
1314 dateTag = '[object Date]',
1315 errorTag = '[object Error]',
1316 funcTag = '[object Function]',
1317 mapTag = '[object Map]',
1318 numberTag = '[object Number]',
1319 objectTag = '[object Object]',
1320 regexpTag = '[object RegExp]',
1321 setTag = '[object Set]',
1322 stringTag = '[object String]',
1323 weakMapTag = '[object WeakMap]';
1324
1325var arrayBufferTag = '[object ArrayBuffer]',
1326 float32Tag = '[object Float32Array]',
1327 float64Tag = '[object Float64Array]',
1328 int8Tag = '[object Int8Array]',
1329 int16Tag = '[object Int16Array]',
1330 int32Tag = '[object Int32Array]',
1331 uint8Tag = '[object Uint8Array]',
1332 uint8ClampedTag = '[object Uint8ClampedArray]',
1333 uint16Tag = '[object Uint16Array]',
1334 uint32Tag = '[object Uint32Array]';
1335
1336/** Used to identify `toStringTag` values of typed arrays. */
1337var typedArrayTags = {};
1338typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
1339typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
1340typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
1341typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
1342typedArrayTags[uint32Tag] = true;
1343typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
1344typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
1345typedArrayTags[dateTag] = typedArrayTags[errorTag] =
1346typedArrayTags[funcTag] = typedArrayTags[mapTag] =
1347typedArrayTags[numberTag] = typedArrayTags[objectTag] =
1348typedArrayTags[regexpTag] = typedArrayTags[setTag] =
1349typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
1350
1351/** Used for native method references. */
1352var objectProto = Object.prototype;
1353
1354/**
1355 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
1356 * of values.
1357 */
1358var objToString = objectProto.toString;
1359
1360/**
1361 * Checks if `value` is classified as a typed array.
1362 *
1363 * @static
1364 * @memberOf _
1365 * @category Lang
1366 * @param {*} value The value to check.
1367 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
1368 * @example
1369 *
1370 * _.isTypedArray(new Uint8Array);
1371 * // => true
1372 *
1373 * _.isTypedArray([]);
1374 * // => false
1375 */
1376function isTypedArray(value) {
1377 return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
1378}
1379
1380module.exports = isTypedArray;
1381
1382},{"../internal/isLength":25,"../internal/isObjectLike":26}],37:[function(_dereq_,module,exports){
1383var baseCopy = _dereq_('../internal/baseCopy'),
1384 keysIn = _dereq_('../object/keysIn');
1385
1386/**
1387 * Converts `value` to a plain object flattening inherited enumerable
1388 * properties of `value` to own properties of the plain object.
1389 *
1390 * @static
1391 * @memberOf _
1392 * @category Lang
1393 * @param {*} value The value to convert.
1394 * @returns {Object} Returns the converted plain object.
1395 * @example
1396 *
1397 * function Foo() {
1398 * this.b = 2;
1399 * }
1400 *
1401 * Foo.prototype.c = 3;
1402 *
1403 * _.assign({ 'a': 1 }, new Foo);
1404 * // => { 'a': 1, 'b': 2 }
1405 *
1406 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
1407 * // => { 'a': 1, 'b': 2, 'c': 3 }
1408 */
1409function toPlainObject(value) {
1410 return baseCopy(value, keysIn(value));
1411}
1412
1413module.exports = toPlainObject;
1414
1415},{"../internal/baseCopy":10,"../object/keysIn":39}],38:[function(_dereq_,module,exports){
1416var getNative = _dereq_('../internal/getNative'),
1417 isArrayLike = _dereq_('../internal/isArrayLike'),
1418 isObject = _dereq_('../lang/isObject'),
1419 shimKeys = _dereq_('../internal/shimKeys'),
1420 support = _dereq_('../support');
1421
1422/* Native method references for those with the same name as other `lodash` methods. */
1423var nativeKeys = getNative(Object, 'keys');
1424
1425/**
1426 * Creates an array of the own enumerable property names of `object`.
1427 *
1428 * **Note:** Non-object values are coerced to objects. See the
1429 * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
1430 * for more details.
1431 *
1432 * @static
1433 * @memberOf _
1434 * @category Object
1435 * @param {Object} object The object to query.
1436 * @returns {Array} Returns the array of property names.
1437 * @example
1438 *
1439 * function Foo() {
1440 * this.a = 1;
1441 * this.b = 2;
1442 * }
1443 *
1444 * Foo.prototype.c = 3;
1445 *
1446 * _.keys(new Foo);
1447 * // => ['a', 'b'] (iteration order is not guaranteed)
1448 *
1449 * _.keys('hi');
1450 * // => ['0', '1']
1451 */
1452var keys = !nativeKeys ? shimKeys : function(object) {
1453 var Ctor = object == null ? undefined : object.constructor;
1454 if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
1455 (typeof object == 'function' ? support.enumPrototypes : isArrayLike(object))) {
1456 return shimKeys(object);
1457 }
1458 return isObject(object) ? nativeKeys(object) : [];
1459};
1460
1461module.exports = keys;
1462
1463},{"../internal/getNative":20,"../internal/isArrayLike":21,"../internal/shimKeys":27,"../lang/isObject":33,"../support":41}],39:[function(_dereq_,module,exports){
1464var arrayEach = _dereq_('../internal/arrayEach'),
1465 isArguments = _dereq_('../lang/isArguments'),
1466 isArray = _dereq_('../lang/isArray'),
1467 isFunction = _dereq_('../lang/isFunction'),
1468 isIndex = _dereq_('../internal/isIndex'),
1469 isLength = _dereq_('../internal/isLength'),
1470 isObject = _dereq_('../lang/isObject'),
1471 isString = _dereq_('../lang/isString'),
1472 support = _dereq_('../support');
1473
1474/** `Object#toString` result references. */
1475var arrayTag = '[object Array]',
1476 boolTag = '[object Boolean]',
1477 dateTag = '[object Date]',
1478 errorTag = '[object Error]',
1479 funcTag = '[object Function]',
1480 numberTag = '[object Number]',
1481 objectTag = '[object Object]',
1482 regexpTag = '[object RegExp]',
1483 stringTag = '[object String]';
1484
1485/** Used to fix the JScript `[[DontEnum]]` bug. */
1486var shadowProps = [
1487 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
1488 'toLocaleString', 'toString', 'valueOf'
1489];
1490
1491/** Used for native method references. */
1492var errorProto = Error.prototype,
1493 objectProto = Object.prototype,
1494 stringProto = String.prototype;
1495
1496/** Used to check objects for own properties. */
1497var hasOwnProperty = objectProto.hasOwnProperty;
1498
1499/**
1500 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
1501 * of values.
1502 */
1503var objToString = objectProto.toString;
1504
1505/** Used to avoid iterating over non-enumerable properties in IE < 9. */
1506var nonEnumProps = {};
1507nonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };
1508nonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true };
1509nonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true };
1510nonEnumProps[objectTag] = { 'constructor': true };
1511
1512arrayEach(shadowProps, function(key) {
1513 for (var tag in nonEnumProps) {
1514 if (hasOwnProperty.call(nonEnumProps, tag)) {
1515 var props = nonEnumProps[tag];
1516 props[key] = hasOwnProperty.call(props, key);
1517 }
1518 }
1519});
1520
1521/**
1522 * Creates an array of the own and inherited enumerable property names of `object`.
1523 *
1524 * **Note:** Non-object values are coerced to objects.
1525 *
1526 * @static
1527 * @memberOf _
1528 * @category Object
1529 * @param {Object} object The object to query.
1530 * @returns {Array} Returns the array of property names.
1531 * @example
1532 *
1533 * function Foo() {
1534 * this.a = 1;
1535 * this.b = 2;
1536 * }
1537 *
1538 * Foo.prototype.c = 3;
1539 *
1540 * _.keysIn(new Foo);
1541 * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
1542 */
1543function keysIn(object) {
1544 if (object == null) {
1545 return [];
1546 }
1547 if (!isObject(object)) {
1548 object = Object(object);
1549 }
1550 var length = object.length;
1551
1552 length = (length && isLength(length) &&
1553 (isArray(object) || isArguments(object) || isString(object)) && length) || 0;
1554
1555 var Ctor = object.constructor,
1556 index = -1,
1557 proto = (isFunction(Ctor) && Ctor.prototype) || objectProto,
1558 isProto = proto === object,
1559 result = Array(length),
1560 skipIndexes = length > 0,
1561 skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error),
1562 skipProto = support.enumPrototypes && isFunction(object);
1563
1564 while (++index < length) {
1565 result[index] = (index + '');
1566 }
1567 // lodash skips the `constructor` property when it infers it's iterating
1568 // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]`
1569 // attribute of an existing property and the `constructor` property of a
1570 // prototype defaults to non-enumerable.
1571 for (var key in object) {
1572 if (!(skipProto && key == 'prototype') &&
1573 !(skipErrorProps && (key == 'message' || key == 'name')) &&
1574 !(skipIndexes && isIndex(key, length)) &&
1575 !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
1576 result.push(key);
1577 }
1578 }
1579 if (support.nonEnumShadows && object !== objectProto) {
1580 var tag = object === stringProto ? stringTag : (object === errorProto ? errorTag : objToString.call(object)),
1581 nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag];
1582
1583 if (tag == objectTag) {
1584 proto = objectProto;
1585 }
1586 length = shadowProps.length;
1587 while (length--) {
1588 key = shadowProps[length];
1589 var nonEnum = nonEnums[key];
1590 if (!(isProto && nonEnum) &&
1591 (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) {
1592 result.push(key);
1593 }
1594 }
1595 }
1596 return result;
1597}
1598
1599module.exports = keysIn;
1600
1601},{"../internal/arrayEach":9,"../internal/isIndex":23,"../internal/isLength":25,"../lang/isArguments":29,"../lang/isArray":30,"../lang/isFunction":31,"../lang/isObject":33,"../lang/isString":35,"../support":41}],40:[function(_dereq_,module,exports){
1602var baseMerge = _dereq_('../internal/baseMerge'),
1603 createAssigner = _dereq_('../internal/createAssigner');
1604
1605/**
1606 * Recursively merges own enumerable properties of the source object(s), that
1607 * don't resolve to `undefined` into the destination object. Subsequent sources
1608 * overwrite property assignments of previous sources. If `customizer` is
1609 * provided it's invoked to produce the merged values of the destination and
1610 * source properties. If `customizer` returns `undefined` merging is handled
1611 * by the method instead. The `customizer` is bound to `thisArg` and invoked
1612 * with five arguments: (objectValue, sourceValue, key, object, source).
1613 *
1614 * @static
1615 * @memberOf _
1616 * @category Object
1617 * @param {Object} object The destination object.
1618 * @param {...Object} [sources] The source objects.
1619 * @param {Function} [customizer] The function to customize assigned values.
1620 * @param {*} [thisArg] The `this` binding of `customizer`.
1621 * @returns {Object} Returns `object`.
1622 * @example
1623 *
1624 * var users = {
1625 * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
1626 * };
1627 *
1628 * var ages = {
1629 * 'data': [{ 'age': 36 }, { 'age': 40 }]
1630 * };
1631 *
1632 * _.merge(users, ages);
1633 * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
1634 *
1635 * // using a customizer callback
1636 * var object = {
1637 * 'fruits': ['apple'],
1638 * 'vegetables': ['beet']
1639 * };
1640 *
1641 * var other = {
1642 * 'fruits': ['banana'],
1643 * 'vegetables': ['carrot']
1644 * };
1645 *
1646 * _.merge(object, other, function(a, b) {
1647 * if (_.isArray(a)) {
1648 * return a.concat(b);
1649 * }
1650 * });
1651 * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
1652 */
1653var merge = createAssigner(baseMerge);
1654
1655module.exports = merge;
1656
1657},{"../internal/baseMerge":13,"../internal/createAssigner":17}],41:[function(_dereq_,module,exports){
1658/** Used for native method references. */
1659var arrayProto = Array.prototype,
1660 errorProto = Error.prototype,
1661 objectProto = Object.prototype;
1662
1663/** Native method references. */
1664var propertyIsEnumerable = objectProto.propertyIsEnumerable,
1665 splice = arrayProto.splice;
1666
1667/**
1668 * An object environment feature flags.
1669 *
1670 * @static
1671 * @memberOf _
1672 * @type Object
1673 */
1674var support = {};
1675
1676(function(x) {
1677 var Ctor = function() { this.x = x; },
1678 object = { '0': x, 'length': x },
1679 props = [];
1680
1681 Ctor.prototype = { 'valueOf': x, 'y': x };
1682 for (var key in new Ctor) { props.push(key); }
1683
1684 /**
1685 * Detect if `name` or `message` properties of `Error.prototype` are
1686 * enumerable by default (IE < 9, Safari < 5.1).
1687 *
1688 * @memberOf _.support
1689 * @type boolean
1690 */
1691 support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') ||
1692 propertyIsEnumerable.call(errorProto, 'name');
1693
1694 /**
1695 * Detect if `prototype` properties are enumerable by default.
1696 *
1697 * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
1698 * (if the prototype or a property on the prototype has been set)
1699 * incorrectly set the `[[Enumerable]]` value of a function's `prototype`
1700 * property to `true`.
1701 *
1702 * @memberOf _.support
1703 * @type boolean
1704 */
1705 support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype');
1706
1707 /**
1708 * Detect if properties shadowing those on `Object.prototype` are non-enumerable.
1709 *
1710 * In IE < 9 an object's own properties, shadowing non-enumerable ones,
1711 * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug).
1712 *
1713 * @memberOf _.support
1714 * @type boolean
1715 */
1716 support.nonEnumShadows = !/valueOf/.test(props);
1717
1718 /**
1719 * Detect if own properties are iterated after inherited properties (IE < 9).
1720 *
1721 * @memberOf _.support
1722 * @type boolean
1723 */
1724 support.ownLast = props[0] != 'x';
1725
1726 /**
1727 * Detect if `Array#shift` and `Array#splice` augment array-like objects
1728 * correctly.
1729 *
1730 * Firefox < 10, compatibility modes of IE 8, and IE < 9 have buggy Array
1731 * `shift()` and `splice()` functions that fail to remove the last element,
1732 * `value[0]`, of array-like objects even though the "length" property is
1733 * set to `0`. The `shift()` method is buggy in compatibility modes of IE 8,
1734 * while `splice()` is buggy regardless of mode in IE < 9.
1735 *
1736 * @memberOf _.support
1737 * @type boolean
1738 */
1739 support.spliceObjects = (splice.call(object, 0, 1), !object[0]);
1740
1741 /**
1742 * Detect lack of support for accessing string characters by index.
1743 *
1744 * IE < 8 can't access characters by index. IE 8 can only access characters
1745 * by index on string literals, not string objects.
1746 *
1747 * @memberOf _.support
1748 * @type boolean
1749 */
1750 support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';
1751}(1, 0));
1752
1753module.exports = support;
1754
1755},{}],42:[function(_dereq_,module,exports){
1756/**
1757 * This method returns the first argument provided to it.
1758 *
1759 * @static
1760 * @memberOf _
1761 * @category Utility
1762 * @param {*} value Any value.
1763 * @returns {*} Returns `value`.
1764 * @example
1765 *
1766 * var object = { 'user': 'fred' };
1767 *
1768 * _.identity(object) === object;
1769 * // => true
1770 */
1771function identity(value) {
1772 return value;
1773}
1774
1775module.exports = identity;
1776
1777},{}],43:[function(_dereq_,module,exports){
1778'use strict';
1779
1780var keys = _dereq_('object-keys');
1781
1782module.exports = function hasSymbols() {
1783 if (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; }
1784 if (typeof Symbol.iterator === 'symbol') { return true; }
1785
1786 var obj = {};
1787 var sym = Symbol('test');
1788 if (typeof sym === 'string') { return false; }
1789
1790 // temp disabled per https://github.com/ljharb/object.assign/issues/17
1791 // if (sym instanceof Symbol) { return false; }
1792 // temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4
1793 // if (!(Object(sym) instanceof Symbol)) { return false; }
1794
1795 var symVal = 42;
1796 obj[sym] = symVal;
1797 for (sym in obj) { return false; }
1798 if (keys(obj).length !== 0) { return false; }
1799 if (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; }
1800
1801 if (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; }
1802
1803 var syms = Object.getOwnPropertySymbols(obj);
1804 if (syms.length !== 1 || syms[0] !== sym) { return false; }
1805
1806 if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; }
1807
1808 if (typeof Object.getOwnPropertyDescriptor === 'function') {
1809 var descriptor = Object.getOwnPropertyDescriptor(obj, sym);
1810 if (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; }
1811 }
1812
1813 return true;
1814};
1815
1816},{"object-keys":50}],44:[function(_dereq_,module,exports){
1817'use strict';
1818
1819// modified from https://github.com/es-shims/es6-shim
1820var keys = _dereq_('object-keys');
1821var bind = _dereq_('function-bind');
1822var canBeObject = function (obj) {
1823 return typeof obj !== 'undefined' && obj !== null;
1824};
1825var hasSymbols = _dereq_('./hasSymbols')();
1826var toObject = Object;
1827var push = bind.call(Function.call, Array.prototype.push);
1828var propIsEnumerable = bind.call(Function.call, Object.prototype.propertyIsEnumerable);
1829
1830module.exports = function assign(target, source1) {
1831 if (!canBeObject(target)) { throw new TypeError('target must be an object'); }
1832 var objTarget = toObject(target);
1833 var s, source, i, props, syms, value, key;
1834 for (s = 1; s < arguments.length; ++s) {
1835 source = toObject(arguments[s]);
1836 props = keys(source);
1837 if (hasSymbols && Object.getOwnPropertySymbols) {
1838 syms = Object.getOwnPropertySymbols(source);
1839 for (i = 0; i < syms.length; ++i) {
1840 key = syms[i];
1841 if (propIsEnumerable(source, key)) {
1842 push(props, key);
1843 }
1844 }
1845 }
1846 for (i = 0; i < props.length; ++i) {
1847 key = props[i];
1848 value = source[key];
1849 if (propIsEnumerable(source, key)) {
1850 objTarget[key] = value;
1851 }
1852 }
1853 }
1854 return objTarget;
1855};
1856
1857},{"./hasSymbols":43,"function-bind":49,"object-keys":50}],45:[function(_dereq_,module,exports){
1858'use strict';
1859
1860var defineProperties = _dereq_('define-properties');
1861
1862var implementation = _dereq_('./implementation');
1863var getPolyfill = _dereq_('./polyfill');
1864var shim = _dereq_('./shim');
1865
1866defineProperties(implementation, {
1867 implementation: implementation,
1868 getPolyfill: getPolyfill,
1869 shim: shim
1870});
1871
1872module.exports = implementation;
1873
1874},{"./implementation":44,"./polyfill":52,"./shim":53,"define-properties":46}],46:[function(_dereq_,module,exports){
1875'use strict';
1876
1877var keys = _dereq_('object-keys');
1878var foreach = _dereq_('foreach');
1879var hasSymbols = typeof Symbol === 'function' && typeof Symbol() === 'symbol';
1880
1881var toStr = Object.prototype.toString;
1882
1883var isFunction = function (fn) {
1884 return typeof fn === 'function' && toStr.call(fn) === '[object Function]';
1885};
1886
1887var arePropertyDescriptorsSupported = function () {
1888 var obj = {};
1889 try {
1890 Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
1891 /* eslint-disable no-unused-vars, no-restricted-syntax */
1892 for (var _ in obj) { return false; }
1893 /* eslint-enable no-unused-vars, no-restricted-syntax */
1894 return obj.x === obj;
1895 } catch (e) { /* this is IE 8. */
1896 return false;
1897 }
1898};
1899var supportsDescriptors = Object.defineProperty && arePropertyDescriptorsSupported();
1900
1901var defineProperty = function (object, name, value, predicate) {
1902 if (name in object && (!isFunction(predicate) || !predicate())) {
1903 return;
1904 }
1905 if (supportsDescriptors) {
1906 Object.defineProperty(object, name, {
1907 configurable: true,
1908 enumerable: false,
1909 value: value,
1910 writable: true
1911 });
1912 } else {
1913 object[name] = value;
1914 }
1915};
1916
1917var defineProperties = function (object, map) {
1918 var predicates = arguments.length > 2 ? arguments[2] : {};
1919 var props = keys(map);
1920 if (hasSymbols) {
1921 props = props.concat(Object.getOwnPropertySymbols(map));
1922 }
1923 foreach(props, function (name) {
1924 defineProperty(object, name, map[name], predicates[name]);
1925 });
1926};
1927
1928defineProperties.supportsDescriptors = !!supportsDescriptors;
1929
1930module.exports = defineProperties;
1931
1932},{"foreach":47,"object-keys":50}],47:[function(_dereq_,module,exports){
1933
1934var hasOwn = Object.prototype.hasOwnProperty;
1935var toString = Object.prototype.toString;
1936
1937module.exports = function forEach (obj, fn, ctx) {
1938 if (toString.call(fn) !== '[object Function]') {
1939 throw new TypeError('iterator must be a function');
1940 }
1941 var l = obj.length;
1942 if (l === +l) {
1943 for (var i = 0; i < l; i++) {
1944 fn.call(ctx, obj[i], i, obj);
1945 }
1946 } else {
1947 for (var k in obj) {
1948 if (hasOwn.call(obj, k)) {
1949 fn.call(ctx, obj[k], k, obj);
1950 }
1951 }
1952 }
1953};
1954
1955
1956},{}],48:[function(_dereq_,module,exports){
1957var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
1958var slice = Array.prototype.slice;
1959var toStr = Object.prototype.toString;
1960var funcType = '[object Function]';
1961
1962module.exports = function bind(that) {
1963 var target = this;
1964 if (typeof target !== 'function' || toStr.call(target) !== funcType) {
1965 throw new TypeError(ERROR_MESSAGE + target);
1966 }
1967 var args = slice.call(arguments, 1);
1968
1969 var bound;
1970 var binder = function () {
1971 if (this instanceof bound) {
1972 var result = target.apply(
1973 this,
1974 args.concat(slice.call(arguments))
1975 );
1976 if (Object(result) === result) {
1977 return result;
1978 }
1979 return this;
1980 } else {
1981 return target.apply(
1982 that,
1983 args.concat(slice.call(arguments))
1984 );
1985 }
1986 };
1987
1988 var boundLength = Math.max(0, target.length - args.length);
1989 var boundArgs = [];
1990 for (var i = 0; i < boundLength; i++) {
1991 boundArgs.push('$' + i);
1992 }
1993
1994 bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
1995
1996 if (target.prototype) {
1997 var Empty = function Empty() {};
1998 Empty.prototype = target.prototype;
1999 bound.prototype = new Empty();
2000 Empty.prototype = null;
2001 }
2002
2003 return bound;
2004};
2005
2006},{}],49:[function(_dereq_,module,exports){
2007var implementation = _dereq_('./implementation');
2008
2009module.exports = Function.prototype.bind || implementation;
2010
2011},{"./implementation":48}],50:[function(_dereq_,module,exports){
2012'use strict';
2013
2014// modified from https://github.com/es-shims/es5-shim
2015var has = Object.prototype.hasOwnProperty;
2016var toStr = Object.prototype.toString;
2017var slice = Array.prototype.slice;
2018var isArgs = _dereq_('./isArguments');
2019var hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString');
2020var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype');
2021var dontEnums = [
2022 'toString',
2023 'toLocaleString',
2024 'valueOf',
2025 'hasOwnProperty',
2026 'isPrototypeOf',
2027 'propertyIsEnumerable',
2028 'constructor'
2029];
2030var equalsConstructorPrototype = function (o) {
2031 var ctor = o.constructor;
2032 return ctor && ctor.prototype === o;
2033};
2034var blacklistedKeys = {
2035 $console: true,
2036 $frame: true,
2037 $frameElement: true,
2038 $frames: true,
2039 $parent: true,
2040 $self: true,
2041 $webkitIndexedDB: true,
2042 $webkitStorageInfo: true,
2043 $window: true
2044};
2045var hasAutomationEqualityBug = (function () {
2046 /* global window */
2047 if (typeof window === 'undefined') { return false; }
2048 for (var k in window) {
2049 try {
2050 if (!blacklistedKeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') {
2051 try {
2052 equalsConstructorPrototype(window[k]);
2053 } catch (e) {
2054 return true;
2055 }
2056 }
2057 } catch (e) {
2058 return true;
2059 }
2060 }
2061 return false;
2062}());
2063var equalsConstructorPrototypeIfNotBuggy = function (o) {
2064 /* global window */
2065 if (typeof window === 'undefined' || !hasAutomationEqualityBug) {
2066 return equalsConstructorPrototype(o);
2067 }
2068 try {
2069 return equalsConstructorPrototype(o);
2070 } catch (e) {
2071 return false;
2072 }
2073};
2074
2075var keysShim = function keys(object) {
2076 var isObject = object !== null && typeof object === 'object';
2077 var isFunction = toStr.call(object) === '[object Function]';
2078 var isArguments = isArgs(object);
2079 var isString = isObject && toStr.call(object) === '[object String]';
2080 var theKeys = [];
2081
2082 if (!isObject && !isFunction && !isArguments) {
2083 throw new TypeError('Object.keys called on a non-object');
2084 }
2085
2086 var skipProto = hasProtoEnumBug && isFunction;
2087 if (isString && object.length > 0 && !has.call(object, 0)) {
2088 for (var i = 0; i < object.length; ++i) {
2089 theKeys.push(String(i));
2090 }
2091 }
2092
2093 if (isArguments && object.length > 0) {
2094 for (var j = 0; j < object.length; ++j) {
2095 theKeys.push(String(j));
2096 }
2097 } else {
2098 for (var name in object) {
2099 if (!(skipProto && name === 'prototype') && has.call(object, name)) {
2100 theKeys.push(String(name));
2101 }
2102 }
2103 }
2104
2105 if (hasDontEnumBug) {
2106 var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);
2107
2108 for (var k = 0; k < dontEnums.length; ++k) {
2109 if (!(skipConstructor && dontEnums[k] === 'constructor') && has.call(object, dontEnums[k])) {
2110 theKeys.push(dontEnums[k]);
2111 }
2112 }
2113 }
2114 return theKeys;
2115};
2116
2117keysShim.shim = function shimObjectKeys() {
2118 if (Object.keys) {
2119 var keysWorksWithArguments = (function () {
2120 // Safari 5.0 bug
2121 return (Object.keys(arguments) || '').length === 2;
2122 }(1, 2));
2123 if (!keysWorksWithArguments) {
2124 var originalKeys = Object.keys;
2125 Object.keys = function keys(object) {
2126 if (isArgs(object)) {
2127 return originalKeys(slice.call(object));
2128 } else {
2129 return originalKeys(object);
2130 }
2131 };
2132 }
2133 } else {
2134 Object.keys = keysShim;
2135 }
2136 return Object.keys || keysShim;
2137};
2138
2139module.exports = keysShim;
2140
2141},{"./isArguments":51}],51:[function(_dereq_,module,exports){
2142'use strict';
2143
2144var toStr = Object.prototype.toString;
2145
2146module.exports = function isArguments(value) {
2147 var str = toStr.call(value);
2148 var isArgs = str === '[object Arguments]';
2149 if (!isArgs) {
2150 isArgs = str !== '[object Array]' &&
2151 value !== null &&
2152 typeof value === 'object' &&
2153 typeof value.length === 'number' &&
2154 value.length >= 0 &&
2155 toStr.call(value.callee) === '[object Function]';
2156 }
2157 return isArgs;
2158};
2159
2160},{}],52:[function(_dereq_,module,exports){
2161'use strict';
2162
2163var implementation = _dereq_('./implementation');
2164
2165var lacksProperEnumerationOrder = function () {
2166 if (!Object.assign) {
2167 return false;
2168 }
2169 // v8, specifically in node 4.x, has a bug with incorrect property enumeration order
2170 // note: this does not detect the bug unless there's 20 characters
2171 var str = 'abcdefghijklmnopqrst';
2172 var letters = str.split('');
2173 var map = {};
2174 for (var i = 0; i < letters.length; ++i) {
2175 map[letters[i]] = letters[i];
2176 }
2177 var obj = Object.assign({}, map);
2178 var actual = '';
2179 for (var k in obj) {
2180 actual += k;
2181 }
2182 return str !== actual;
2183};
2184
2185var assignHasPendingExceptions = function () {
2186 if (!Object.assign || !Object.preventExtensions) {
2187 return false;
2188 }
2189 // Firefox 37 still has "pending exception" logic in its Object.assign implementation,
2190 // which is 72% slower than our shim, and Firefox 40's native implementation.
2191 var thrower = Object.preventExtensions({ 1: 2 });
2192 try {
2193 Object.assign(thrower, 'xy');
2194 } catch (e) {
2195 return thrower[1] === 'y';
2196 }
2197};
2198
2199module.exports = function getPolyfill() {
2200 if (!Object.assign) {
2201 return implementation;
2202 }
2203 if (lacksProperEnumerationOrder()) {
2204 return implementation;
2205 }
2206 if (assignHasPendingExceptions()) {
2207 return implementation;
2208 }
2209 return Object.assign;
2210};
2211
2212},{"./implementation":44}],53:[function(_dereq_,module,exports){
2213'use strict';
2214
2215var define = _dereq_('define-properties');
2216var getPolyfill = _dereq_('./polyfill');
2217
2218module.exports = function shimAssign() {
2219 var polyfill = getPolyfill();
2220 define(
2221 Object,
2222 { assign: polyfill },
2223 { assign: function () { return Object.assign !== polyfill; } }
2224 );
2225 return polyfill;
2226};
2227
2228},{"./polyfill":52,"define-properties":46}],54:[function(_dereq_,module,exports){
2229module.exports = SafeParseTuple
2230
2231function SafeParseTuple(obj, reviver) {
2232 var json
2233 var error = null
2234
2235 try {
2236 json = JSON.parse(obj, reviver)
2237 } catch (err) {
2238 error = err
2239 }
2240
2241 return [error, json]
2242}
2243
2244},{}],55:[function(_dereq_,module,exports){
2245function clean (s) {
2246 return s.replace(/\n\r?\s*/g, '')
2247}
2248
2249
2250module.exports = function tsml (sa) {
2251 var s = ''
2252 , i = 0
2253
2254 for (; i < arguments.length; i++)
2255 s += clean(sa[i]) + (arguments[i + 1] || '')
2256
2257 return s
2258}
2259},{}],56:[function(_dereq_,module,exports){
2260"use strict";
2261var window = _dereq_("global/window")
2262var once = _dereq_("once")
2263var isFunction = _dereq_("is-function")
2264var parseHeaders = _dereq_("parse-headers")
2265var xtend = _dereq_("xtend")
2266
2267module.exports = createXHR
2268createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
2269createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest
2270
2271forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
2272 createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
2273 options = initParams(uri, options, callback)
2274 options.method = method.toUpperCase()
2275 return _createXHR(options)
2276 }
2277})
2278
2279function forEachArray(array, iterator) {
2280 for (var i = 0; i < array.length; i++) {
2281 iterator(array[i])
2282 }
2283}
2284
2285function isEmpty(obj){
2286 for(var i in obj){
2287 if(obj.hasOwnProperty(i)) return false
2288 }
2289 return true
2290}
2291
2292function initParams(uri, options, callback) {
2293 var params = uri
2294
2295 if (isFunction(options)) {
2296 callback = options
2297 if (typeof uri === "string") {
2298 params = {uri:uri}
2299 }
2300 } else {
2301 params = xtend(options, {uri: uri})
2302 }
2303
2304 params.callback = callback
2305 return params
2306}
2307
2308function createXHR(uri, options, callback) {
2309 options = initParams(uri, options, callback)
2310 return _createXHR(options)
2311}
2312
2313function _createXHR(options) {
2314 var callback = options.callback
2315 if(typeof callback === "undefined"){
2316 throw new Error("callback argument missing")
2317 }
2318 callback = once(callback)
2319
2320 function readystatechange() {
2321 if (xhr.readyState === 4) {
2322 loadFunc()
2323 }
2324 }
2325
2326 function getBody() {
2327 // Chrome with requestType=blob throws errors arround when even testing access to responseText
2328 var body = undefined
2329
2330 if (xhr.response) {
2331 body = xhr.response
2332 } else if (xhr.responseType === "text" || !xhr.responseType) {
2333 body = xhr.responseText || xhr.responseXML
2334 }
2335
2336 if (isJson) {
2337 try {
2338 body = JSON.parse(body)
2339 } catch (e) {}
2340 }
2341
2342 return body
2343 }
2344
2345 var failureResponse = {
2346 body: undefined,
2347 headers: {},
2348 statusCode: 0,
2349 method: method,
2350 url: uri,
2351 rawRequest: xhr
2352 }
2353
2354 function errorFunc(evt) {
2355 clearTimeout(timeoutTimer)
2356 if(!(evt instanceof Error)){
2357 evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
2358 }
2359 evt.statusCode = 0
2360 callback(evt, failureResponse)
2361 }
2362
2363 // will load the data & process the response in a special response object
2364 function loadFunc() {
2365 if (aborted) return
2366 var status
2367 clearTimeout(timeoutTimer)
2368 if(options.useXDR && xhr.status===undefined) {
2369 //IE8 CORS GET successful response doesn't have a status field, but body is fine
2370 status = 200
2371 } else {
2372 status = (xhr.status === 1223 ? 204 : xhr.status)
2373 }
2374 var response = failureResponse
2375 var err = null
2376
2377 if (status !== 0){
2378 response = {
2379 body: getBody(),
2380 statusCode: status,
2381 method: method,
2382 headers: {},
2383 url: uri,
2384 rawRequest: xhr
2385 }
2386 if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
2387 response.headers = parseHeaders(xhr.getAllResponseHeaders())
2388 }
2389 } else {
2390 err = new Error("Internal XMLHttpRequest Error")
2391 }
2392 callback(err, response, response.body)
2393
2394 }
2395
2396 var xhr = options.xhr || null
2397
2398 if (!xhr) {
2399 if (options.cors || options.useXDR) {
2400 xhr = new createXHR.XDomainRequest()
2401 }else{
2402 xhr = new createXHR.XMLHttpRequest()
2403 }
2404 }
2405
2406 var key
2407 var aborted
2408 var uri = xhr.url = options.uri || options.url
2409 var method = xhr.method = options.method || "GET"
2410 var body = options.body || options.data || null
2411 var headers = xhr.headers = options.headers || {}
2412 var sync = !!options.sync
2413 var isJson = false
2414 var timeoutTimer
2415
2416 if ("json" in options) {
2417 isJson = true
2418 headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
2419 if (method !== "GET" && method !== "HEAD") {
2420 headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
2421 body = JSON.stringify(options.json)
2422 }
2423 }
2424
2425 xhr.onreadystatechange = readystatechange
2426 xhr.onload = loadFunc
2427 xhr.onerror = errorFunc
2428 // IE9 must have onprogress be set to a unique function.
2429 xhr.onprogress = function () {
2430 // IE must die
2431 }
2432 xhr.ontimeout = errorFunc
2433 xhr.open(method, uri, !sync, options.username, options.password)
2434 //has to be after open
2435 if(!sync) {
2436 xhr.withCredentials = !!options.withCredentials
2437 }
2438 // Cannot set timeout with sync request
2439 // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
2440 // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
2441 if (!sync && options.timeout > 0 ) {
2442 timeoutTimer = setTimeout(function(){
2443 aborted=true//IE9 may still call readystatechange
2444 xhr.abort("timeout")
2445 var e = new Error("XMLHttpRequest timeout")
2446 e.code = "ETIMEDOUT"
2447 errorFunc(e)
2448 }, options.timeout )
2449 }
2450
2451 if (xhr.setRequestHeader) {
2452 for(key in headers){
2453 if(headers.hasOwnProperty(key)){
2454 xhr.setRequestHeader(key, headers[key])
2455 }
2456 }
2457 } else if (options.headers && !isEmpty(options.headers)) {
2458 throw new Error("Headers cannot be set on an XDomainRequest object")
2459 }
2460
2461 if ("responseType" in options) {
2462 xhr.responseType = options.responseType
2463 }
2464
2465 if ("beforeSend" in options &&
2466 typeof options.beforeSend === "function"
2467 ) {
2468 options.beforeSend(xhr)
2469 }
2470
2471 xhr.send(body)
2472
2473 return xhr
2474
2475
2476}
2477
2478function noop() {}
2479
2480},{"global/window":2,"is-function":57,"once":58,"parse-headers":61,"xtend":62}],57:[function(_dereq_,module,exports){
2481module.exports = isFunction
2482
2483var toString = Object.prototype.toString
2484
2485function isFunction (fn) {
2486 var string = toString.call(fn)
2487 return string === '[object Function]' ||
2488 (typeof fn === 'function' && string !== '[object RegExp]') ||
2489 (typeof window !== 'undefined' &&
2490 // IE8 and below
2491 (fn === window.setTimeout ||
2492 fn === window.alert ||
2493 fn === window.confirm ||
2494 fn === window.prompt))
2495};
2496
2497},{}],58:[function(_dereq_,module,exports){
2498module.exports = once
2499
2500once.proto = once(function () {
2501 Object.defineProperty(Function.prototype, 'once', {
2502 value: function () {
2503 return once(this)
2504 },
2505 configurable: true
2506 })
2507})
2508
2509function once (fn) {
2510 var called = false
2511 return function () {
2512 if (called) return
2513 called = true
2514 return fn.apply(this, arguments)
2515 }
2516}
2517
2518},{}],59:[function(_dereq_,module,exports){
2519var isFunction = _dereq_('is-function')
2520
2521module.exports = forEach
2522
2523var toString = Object.prototype.toString
2524var hasOwnProperty = Object.prototype.hasOwnProperty
2525
2526function forEach(list, iterator, context) {
2527 if (!isFunction(iterator)) {
2528 throw new TypeError('iterator must be a function')
2529 }
2530
2531 if (arguments.length < 3) {
2532 context = this
2533 }
2534
2535 if (toString.call(list) === '[object Array]')
2536 forEachArray(list, iterator, context)
2537 else if (typeof list === 'string')
2538 forEachString(list, iterator, context)
2539 else
2540 forEachObject(list, iterator, context)
2541}
2542
2543function forEachArray(array, iterator, context) {
2544 for (var i = 0, len = array.length; i < len; i++) {
2545 if (hasOwnProperty.call(array, i)) {
2546 iterator.call(context, array[i], i, array)
2547 }
2548 }
2549}
2550
2551function forEachString(string, iterator, context) {
2552 for (var i = 0, len = string.length; i < len; i++) {
2553 // no such thing as a sparse string.
2554 iterator.call(context, string.charAt(i), i, string)
2555 }
2556}
2557
2558function forEachObject(object, iterator, context) {
2559 for (var k in object) {
2560 if (hasOwnProperty.call(object, k)) {
2561 iterator.call(context, object[k], k, object)
2562 }
2563 }
2564}
2565
2566},{"is-function":57}],60:[function(_dereq_,module,exports){
2567
2568exports = module.exports = trim;
2569
2570function trim(str){
2571 return str.replace(/^\s*|\s*$/g, '');
2572}
2573
2574exports.left = function(str){
2575 return str.replace(/^\s*/, '');
2576};
2577
2578exports.right = function(str){
2579 return str.replace(/\s*$/, '');
2580};
2581
2582},{}],61:[function(_dereq_,module,exports){
2583var trim = _dereq_('trim')
2584 , forEach = _dereq_('for-each')
2585 , isArray = function(arg) {
2586 return Object.prototype.toString.call(arg) === '[object Array]';
2587 }
2588
2589module.exports = function (headers) {
2590 if (!headers)
2591 return {}
2592
2593 var result = {}
2594
2595 forEach(
2596 trim(headers).split('\n')
2597 , function (row) {
2598 var index = row.indexOf(':')
2599 , key = trim(row.slice(0, index)).toLowerCase()
2600 , value = trim(row.slice(index + 1))
2601
2602 if (typeof(result[key]) === 'undefined') {
2603 result[key] = value
2604 } else if (isArray(result[key])) {
2605 result[key].push(value)
2606 } else {
2607 result[key] = [ result[key], value ]
2608 }
2609 }
2610 )
2611
2612 return result
2613}
2614},{"for-each":59,"trim":60}],62:[function(_dereq_,module,exports){
2615module.exports = extend
2616
2617var hasOwnProperty = Object.prototype.hasOwnProperty;
2618
2619function extend() {
2620 var target = {}
2621
2622 for (var i = 0; i < arguments.length; i++) {
2623 var source = arguments[i]
2624
2625 for (var key in source) {
2626 if (hasOwnProperty.call(source, key)) {
2627 target[key] = source[key]
2628 }
2629 }
2630 }
2631
2632 return target
2633}
2634
2635},{}],63:[function(_dereq_,module,exports){
2636/**
2637 * @file big-play-button.js
2638 */
2639'use strict';
2640
2641exports.__esModule = true;
2642
2643function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2644
2645function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
2646
2647function _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; }
2648
2649var _buttonJs = _dereq_('./button.js');
2650
2651var _buttonJs2 = _interopRequireDefault(_buttonJs);
2652
2653var _componentJs = _dereq_('./component.js');
2654
2655var _componentJs2 = _interopRequireDefault(_componentJs);
2656
2657/**
2658 * Initial play button. Shows before the video has played. The hiding of the
2659 * big play button is done via CSS and player states.
2660 *
2661 * @param {Object} player Main Player
2662 * @param {Object=} options Object of option names and values
2663 * @extends Button
2664 * @class BigPlayButton
2665 */
2666
2667var BigPlayButton = (function (_Button) {
2668 _inherits(BigPlayButton, _Button);
2669
2670 function BigPlayButton(player, options) {
2671 _classCallCheck(this, BigPlayButton);
2672
2673 _Button.call(this, player, options);
2674 }
2675
2676 /**
2677 * Allow sub components to stack CSS class names
2678 *
2679 * @return {String} The constructed class name
2680 * @method buildCSSClass
2681 */
2682
2683 BigPlayButton.prototype.buildCSSClass = function buildCSSClass() {
2684 return 'vjs-big-play-button';
2685 };
2686
2687 /**
2688 * Handles click for play
2689 *
2690 * @method handleClick
2691 */
2692
2693 BigPlayButton.prototype.handleClick = function handleClick() {
2694 this.player_.play();
2695 };
2696
2697 return BigPlayButton;
2698})(_buttonJs2['default']);
2699
2700BigPlayButton.prototype.controlText_ = 'Play Video';
2701
2702_componentJs2['default'].registerComponent('BigPlayButton', BigPlayButton);
2703exports['default'] = BigPlayButton;
2704module.exports = exports['default'];
2705
2706},{"./button.js":64,"./component.js":67}],64:[function(_dereq_,module,exports){
2707/**
2708 * @file button.js
2709 */
2710'use strict';
2711
2712exports.__esModule = true;
2713
2714function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
2715
2716function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2717
2718function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
2719
2720function _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; }
2721
2722var _clickableComponentJs = _dereq_('./clickable-component.js');
2723
2724var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs);
2725
2726var _component = _dereq_('./component');
2727
2728var _component2 = _interopRequireDefault(_component);
2729
2730var _utilsEventsJs = _dereq_('./utils/events.js');
2731
2732var Events = _interopRequireWildcard(_utilsEventsJs);
2733
2734var _utilsFnJs = _dereq_('./utils/fn.js');
2735
2736var Fn = _interopRequireWildcard(_utilsFnJs);
2737
2738var _utilsLogJs = _dereq_('./utils/log.js');
2739
2740var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
2741
2742var _globalDocument = _dereq_('global/document');
2743
2744var _globalDocument2 = _interopRequireDefault(_globalDocument);
2745
2746var _objectAssign = _dereq_('object.assign');
2747
2748var _objectAssign2 = _interopRequireDefault(_objectAssign);
2749
2750/**
2751 * Base class for all buttons
2752 *
2753 * @param {Object} player Main Player
2754 * @param {Object=} options Object of option names and values
2755 * @extends ClickableComponent
2756 * @class Button
2757 */
2758
2759var Button = (function (_ClickableComponent) {
2760 _inherits(Button, _ClickableComponent);
2761
2762 function Button(player, options) {
2763 _classCallCheck(this, Button);
2764
2765 _ClickableComponent.call(this, player, options);
2766 }
2767
2768 /**
2769 * Create the component's DOM element
2770 *
2771 * @param {String=} type Element's node type. e.g. 'div'
2772 * @param {Object=} props An object of properties that should be set on the element
2773 * @param {Object=} attributes An object of attributes that should be set on the element
2774 * @return {Element}
2775 * @method createEl
2776 */
2777
2778 Button.prototype.createEl = function createEl() {
2779 var tag = arguments.length <= 0 || arguments[0] === undefined ? 'button' : arguments[0];
2780 var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
2781 var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
2782
2783 props = _objectAssign2['default']({
2784 className: this.buildCSSClass()
2785 }, props);
2786
2787 if (tag !== 'button') {
2788 _utilsLogJs2['default'].warn('Creating a Button with an HTML element of ' + tag + ' is deprecated; use ClickableComponent instead.');
2789 }
2790
2791 // Add attributes for button element
2792 attributes = _objectAssign2['default']({
2793 type: 'button', // Necessary since the default button type is "submit"
2794 'aria-live': 'polite' // let the screen reader user know that the text of the button may change
2795 }, attributes);
2796
2797 var el = _component2['default'].prototype.createEl.call(this, tag, props, attributes);
2798
2799 this.createControlTextEl(el);
2800
2801 return el;
2802 };
2803
2804 /**
2805 * Adds a child component inside this button
2806 *
2807 * @param {String|Component} child The class name or instance of a child to add
2808 * @param {Object=} options Options, including options to be passed to children of the child.
2809 * @return {Component} The child component (created by this process if a string was used)
2810 * @deprecated
2811 * @method addChild
2812 */
2813
2814 Button.prototype.addChild = function addChild(child) {
2815 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
2816
2817 var className = this.constructor.name;
2818 _utilsLogJs2['default'].warn('Adding an actionable (user controllable) child to a Button (' + className + ') is not supported; use a ClickableComponent instead.');
2819
2820 // Avoid the error message generated by ClickableComponent's addChild method
2821 return _component2['default'].prototype.addChild.call(this, child, options);
2822 };
2823
2824 /**
2825 * Handle KeyPress (document level) - Extend with specific functionality for button
2826 *
2827 * @method handleKeyPress
2828 */
2829
2830 Button.prototype.handleKeyPress = function handleKeyPress(event) {
2831 // Ignore Space (32) or Enter (13) key operation, which is handled by the browser for a button.
2832 if (event.which === 32 || event.which === 13) {} else {
2833 _ClickableComponent.prototype.handleKeyPress.call(this, event); // Pass keypress handling up for unsupported keys
2834 }
2835 };
2836
2837 return Button;
2838})(_clickableComponentJs2['default']);
2839
2840_component2['default'].registerComponent('Button', Button);
2841exports['default'] = Button;
2842module.exports = exports['default'];
2843
2844},{"./clickable-component.js":65,"./component":67,"./utils/events.js":133,"./utils/fn.js":134,"./utils/log.js":137,"global/document":1,"object.assign":45}],65:[function(_dereq_,module,exports){
2845/**
2846 * @file button.js
2847 */
2848'use strict';
2849
2850exports.__esModule = true;
2851
2852function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
2853
2854function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2855
2856function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
2857
2858function _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; }
2859
2860var _component = _dereq_('./component');
2861
2862var _component2 = _interopRequireDefault(_component);
2863
2864var _utilsDomJs = _dereq_('./utils/dom.js');
2865
2866var Dom = _interopRequireWildcard(_utilsDomJs);
2867
2868var _utilsEventsJs = _dereq_('./utils/events.js');
2869
2870var Events = _interopRequireWildcard(_utilsEventsJs);
2871
2872var _utilsFnJs = _dereq_('./utils/fn.js');
2873
2874var Fn = _interopRequireWildcard(_utilsFnJs);
2875
2876var _utilsLogJs = _dereq_('./utils/log.js');
2877
2878var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
2879
2880var _globalDocument = _dereq_('global/document');
2881
2882var _globalDocument2 = _interopRequireDefault(_globalDocument);
2883
2884var _objectAssign = _dereq_('object.assign');
2885
2886var _objectAssign2 = _interopRequireDefault(_objectAssign);
2887
2888/**
2889 * Clickable Component which is clickable or keyboard actionable, but is not a native HTML button
2890 *
2891 * @param {Object} player Main Player
2892 * @param {Object=} options Object of option names and values
2893 * @extends Component
2894 * @class ClickableComponent
2895 */
2896
2897var ClickableComponent = (function (_Component) {
2898 _inherits(ClickableComponent, _Component);
2899
2900 function ClickableComponent(player, options) {
2901 _classCallCheck(this, ClickableComponent);
2902
2903 _Component.call(this, player, options);
2904
2905 this.emitTapEvents();
2906
2907 this.on('tap', this.handleClick);
2908 this.on('click', this.handleClick);
2909 this.on('focus', this.handleFocus);
2910 this.on('blur', this.handleBlur);
2911 }
2912
2913 /**
2914 * Create the component's DOM element
2915 *
2916 * @param {String=} type Element's node type. e.g. 'div'
2917 * @param {Object=} props An object of properties that should be set on the element
2918 * @param {Object=} attributes An object of attributes that should be set on the element
2919 * @return {Element}
2920 * @method createEl
2921 */
2922
2923 ClickableComponent.prototype.createEl = function createEl() {
2924 var tag = arguments.length <= 0 || arguments[0] === undefined ? 'div' : arguments[0];
2925 var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
2926 var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
2927
2928 props = _objectAssign2['default']({
2929 className: this.buildCSSClass(),
2930 tabIndex: 0
2931 }, props);
2932
2933 if (tag === 'button') {
2934 _utilsLogJs2['default'].error('Creating a ClickableComponent with an HTML element of ' + tag + ' is not supported; use a Button instead.');
2935 }
2936
2937 // Add ARIA attributes for clickable element which is not a native HTML button
2938 attributes = _objectAssign2['default']({
2939 role: 'button',
2940 'aria-live': 'polite' // let the screen reader user know that the text of the element may change
2941 }, attributes);
2942
2943 var el = _Component.prototype.createEl.call(this, tag, props, attributes);
2944
2945 this.createControlTextEl(el);
2946
2947 return el;
2948 };
2949
2950 /**
2951 * create control text
2952 *
2953 * @param {Element} el Parent element for the control text
2954 * @return {Element}
2955 * @method controlText
2956 */
2957
2958 ClickableComponent.prototype.createControlTextEl = function createControlTextEl(el) {
2959 this.controlTextEl_ = Dom.createEl('span', {
2960 className: 'vjs-control-text'
2961 });
2962
2963 if (el) {
2964 el.appendChild(this.controlTextEl_);
2965 }
2966
2967 this.controlText(this.controlText_);
2968
2969 return this.controlTextEl_;
2970 };
2971
2972 /**
2973 * Controls text - both request and localize
2974 *
2975 * @param {String} text Text for element
2976 * @return {String}
2977 * @method controlText
2978 */
2979
2980 ClickableComponent.prototype.controlText = function controlText(text) {
2981 if (!text) return this.controlText_ || 'Need Text';
2982
2983 this.controlText_ = text;
2984 this.controlTextEl_.innerHTML = this.localize(this.controlText_);
2985
2986 return this;
2987 };
2988
2989 /**
2990 * Allows sub components to stack CSS class names
2991 *
2992 * @return {String}
2993 * @method buildCSSClass
2994 */
2995
2996 ClickableComponent.prototype.buildCSSClass = function buildCSSClass() {
2997 return 'vjs-control vjs-button ' + _Component.prototype.buildCSSClass.call(this);
2998 };
2999
3000 /**
3001 * Adds a child component inside this clickable-component
3002 *
3003 * @param {String|Component} child The class name or instance of a child to add
3004 * @param {Object=} options Options, including options to be passed to children of the child.
3005 * @return {Component} The child component (created by this process if a string was used)
3006 * @method addChild
3007 */
3008
3009 ClickableComponent.prototype.addChild = function addChild(child) {
3010 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
3011
3012 // TODO: Fix adding an actionable child to a ClickableComponent; currently
3013 // it will cause issues with assistive technology (e.g. screen readers)
3014 // which support ARIA, since an element with role="button" cannot have
3015 // actionable child elements.
3016
3017 //let className = this.constructor.name;
3018 //log.warn(`Adding a child to a ClickableComponent (${className}) can cause issues with assistive technology which supports ARIA, since an element with role="button" cannot have actionable child elements.`);
3019
3020 return _Component.prototype.addChild.call(this, child, options);
3021 };
3022
3023 /**
3024 * Handle Click - Override with specific functionality for component
3025 *
3026 * @method handleClick
3027 */
3028
3029 ClickableComponent.prototype.handleClick = function handleClick() {};
3030
3031 /**
3032 * Handle Focus - Add keyboard functionality to element
3033 *
3034 * @method handleFocus
3035 */
3036
3037 ClickableComponent.prototype.handleFocus = function handleFocus() {
3038 Events.on(_globalDocument2['default'], 'keydown', Fn.bind(this, this.handleKeyPress));
3039 };
3040
3041 /**
3042 * Handle KeyPress (document level) - Trigger click when Space or Enter key is pressed
3043 *
3044 * @method handleKeyPress
3045 */
3046
3047 ClickableComponent.prototype.handleKeyPress = function handleKeyPress(event) {
3048 // Support Space (32) or Enter (13) key operation to fire a click event
3049 if (event.which === 32 || event.which === 13) {
3050 event.preventDefault();
3051 this.handleClick(event);
3052 } else if (_Component.prototype.handleKeyPress) {
3053 _Component.prototype.handleKeyPress.call(this, event); // Pass keypress handling up for unsupported keys
3054 }
3055 };
3056
3057 /**
3058 * Handle Blur - Remove keyboard triggers
3059 *
3060 * @method handleBlur
3061 */
3062
3063 ClickableComponent.prototype.handleBlur = function handleBlur() {
3064 Events.off(_globalDocument2['default'], 'keydown', Fn.bind(this, this.handleKeyPress));
3065 };
3066
3067 return ClickableComponent;
3068})(_component2['default']);
3069
3070_component2['default'].registerComponent('ClickableComponent', ClickableComponent);
3071exports['default'] = ClickableComponent;
3072module.exports = exports['default'];
3073
3074},{"./component":67,"./utils/dom.js":132,"./utils/events.js":133,"./utils/fn.js":134,"./utils/log.js":137,"global/document":1,"object.assign":45}],66:[function(_dereq_,module,exports){
3075'use strict';
3076
3077exports.__esModule = true;
3078
3079function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
3080
3081function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
3082
3083function _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; }
3084
3085var _button = _dereq_('./button');
3086
3087var _button2 = _interopRequireDefault(_button);
3088
3089var _component = _dereq_('./component');
3090
3091var _component2 = _interopRequireDefault(_component);
3092
3093/**
3094 * The `CloseButton` component is a button which fires a "close" event
3095 * when it is activated.
3096 *
3097 * @extends Button
3098 * @class CloseButton
3099 */
3100
3101var CloseButton = (function (_Button) {
3102 _inherits(CloseButton, _Button);
3103
3104 function CloseButton(player, options) {
3105 _classCallCheck(this, CloseButton);
3106
3107 _Button.call(this, player, options);
3108 this.controlText(options && options.controlText || this.localize('Close'));
3109 }
3110
3111 CloseButton.prototype.buildCSSClass = function buildCSSClass() {
3112 return 'vjs-close-button ' + _Button.prototype.buildCSSClass.call(this);
3113 };
3114
3115 CloseButton.prototype.handleClick = function handleClick() {
3116 this.trigger({ type: 'close', bubbles: false });
3117 };
3118
3119 return CloseButton;
3120})(_button2['default']);
3121
3122_component2['default'].registerComponent('CloseButton', CloseButton);
3123exports['default'] = CloseButton;
3124module.exports = exports['default'];
3125
3126},{"./button":64,"./component":67}],67:[function(_dereq_,module,exports){
3127/**
3128 * @file component.js
3129 *
3130 * Player Component - Base class for all UI objects
3131 */
3132
3133'use strict';
3134
3135exports.__esModule = true;
3136
3137function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
3138
3139function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
3140
3141function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
3142
3143var _globalWindow = _dereq_('global/window');
3144
3145var _globalWindow2 = _interopRequireDefault(_globalWindow);
3146
3147var _utilsDomJs = _dereq_('./utils/dom.js');
3148
3149var Dom = _interopRequireWildcard(_utilsDomJs);
3150
3151var _utilsFnJs = _dereq_('./utils/fn.js');
3152
3153var Fn = _interopRequireWildcard(_utilsFnJs);
3154
3155var _utilsGuidJs = _dereq_('./utils/guid.js');
3156
3157var Guid = _interopRequireWildcard(_utilsGuidJs);
3158
3159var _utilsEventsJs = _dereq_('./utils/events.js');
3160
3161var Events = _interopRequireWildcard(_utilsEventsJs);
3162
3163var _utilsLogJs = _dereq_('./utils/log.js');
3164
3165var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
3166
3167var _utilsToTitleCaseJs = _dereq_('./utils/to-title-case.js');
3168
3169var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs);
3170
3171var _objectAssign = _dereq_('object.assign');
3172
3173var _objectAssign2 = _interopRequireDefault(_objectAssign);
3174
3175var _utilsMergeOptionsJs = _dereq_('./utils/merge-options.js');
3176
3177var _utilsMergeOptionsJs2 = _interopRequireDefault(_utilsMergeOptionsJs);
3178
3179/**
3180 * Base UI Component class
3181 * Components are embeddable UI objects that are represented by both a
3182 * javascript object and an element in the DOM. They can be children of other
3183 * components, and can have many children themselves.
3184 * ```js
3185 * // adding a button to the player
3186 * var button = player.addChild('button');
3187 * button.el(); // -> button element
3188 * ```
3189 * ```html
3190 * <div class="video-js">
3191 * <div class="vjs-button">Button</div>
3192 * </div>
3193 * ```
3194 * Components are also event targets.
3195 * ```js
3196 * button.on('click', function(){
3197 * console.log('Button Clicked!');
3198 * });
3199 * button.trigger('customevent');
3200 * ```
3201 *
3202 * @param {Object} player Main Player
3203 * @param {Object=} options Object of option names and values
3204 * @param {Function=} ready Ready callback function
3205 * @class Component
3206 */
3207
3208var Component = (function () {
3209 function Component(player, options, ready) {
3210 _classCallCheck(this, Component);
3211
3212 // The component might be the player itself and we can't pass `this` to super
3213 if (!player && this.play) {
3214 this.player_ = player = this; // eslint-disable-line
3215 } else {
3216 this.player_ = player;
3217 }
3218
3219 // Make a copy of prototype.options_ to protect against overriding defaults
3220 this.options_ = _utilsMergeOptionsJs2['default']({}, this.options_);
3221
3222 // Updated options with supplied options
3223 options = this.options_ = _utilsMergeOptionsJs2['default'](this.options_, options);
3224
3225 // Get ID from options or options element if one is supplied
3226 this.id_ = options.id || options.el && options.el.id;
3227
3228 // If there was no ID from the options, generate one
3229 if (!this.id_) {
3230 // Don't require the player ID function in the case of mock players
3231 var id = player && player.id && player.id() || 'no_player';
3232
3233 this.id_ = id + '_component_' + Guid.newGUID();
3234 }
3235
3236 this.name_ = options.name || null;
3237
3238 // Create element if one wasn't provided in options
3239 if (options.el) {
3240 this.el_ = options.el;
3241 } else if (options.createEl !== false) {
3242 this.el_ = this.createEl();
3243 }
3244
3245 this.children_ = [];
3246 this.childIndex_ = {};
3247 this.childNameIndex_ = {};
3248
3249 // Add any child components in options
3250 if (options.initChildren !== false) {
3251 this.initChildren();
3252 }
3253
3254 this.ready(ready);
3255 // Don't want to trigger ready here or it will before init is actually
3256 // finished for all children that run this constructor
3257
3258 if (options.reportTouchActivity !== false) {
3259 this.enableTouchActivity();
3260 }
3261 }
3262
3263 /**
3264 * Dispose of the component and all child components
3265 *
3266 * @method dispose
3267 */
3268
3269 Component.prototype.dispose = function dispose() {
3270 this.trigger({ type: 'dispose', bubbles: false });
3271
3272 // Dispose all children.
3273 if (this.children_) {
3274 for (var i = this.children_.length - 1; i >= 0; i--) {
3275 if (this.children_[i].dispose) {
3276 this.children_[i].dispose();
3277 }
3278 }
3279 }
3280
3281 // Delete child references
3282 this.children_ = null;
3283 this.childIndex_ = null;
3284 this.childNameIndex_ = null;
3285
3286 // Remove all event listeners.
3287 this.off();
3288
3289 // Remove element from DOM
3290 if (this.el_.parentNode) {
3291 this.el_.parentNode.removeChild(this.el_);
3292 }
3293
3294 Dom.removeElData(this.el_);
3295 this.el_ = null;
3296 };
3297
3298 /**
3299 * Return the component's player
3300 *
3301 * @return {Player}
3302 * @method player
3303 */
3304
3305 Component.prototype.player = function player() {
3306 return this.player_;
3307 };
3308
3309 /**
3310 * Deep merge of options objects
3311 * Whenever a property is an object on both options objects
3312 * the two properties will be merged using mergeOptions.
3313 *
3314 * ```js
3315 * Parent.prototype.options_ = {
3316 * optionSet: {
3317 * 'childOne': { 'foo': 'bar', 'asdf': 'fdsa' },
3318 * 'childTwo': {},
3319 * 'childThree': {}
3320 * }
3321 * }
3322 * newOptions = {
3323 * optionSet: {
3324 * 'childOne': { 'foo': 'baz', 'abc': '123' }
3325 * 'childTwo': null,
3326 * 'childFour': {}
3327 * }
3328 * }
3329 *
3330 * this.options(newOptions);
3331 * ```
3332 * RESULT
3333 * ```js
3334 * {
3335 * optionSet: {
3336 * 'childOne': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' },
3337 * 'childTwo': null, // Disabled. Won't be initialized.
3338 * 'childThree': {},
3339 * 'childFour': {}
3340 * }
3341 * }
3342 * ```
3343 *
3344 * @param {Object} obj Object of new option values
3345 * @return {Object} A NEW object of this.options_ and obj merged
3346 * @method options
3347 */
3348
3349 Component.prototype.options = function options(obj) {
3350 _utilsLogJs2['default'].warn('this.options() has been deprecated and will be moved to the constructor in 6.0');
3351
3352 if (!obj) {
3353 return this.options_;
3354 }
3355
3356 this.options_ = _utilsMergeOptionsJs2['default'](this.options_, obj);
3357 return this.options_;
3358 };
3359
3360 /**
3361 * Get the component's DOM element
3362 * ```js
3363 * var domEl = myComponent.el();
3364 * ```
3365 *
3366 * @return {Element}
3367 * @method el
3368 */
3369
3370 Component.prototype.el = function el() {
3371 return this.el_;
3372 };
3373
3374 /**
3375 * Create the component's DOM element
3376 *
3377 * @param {String=} tagName Element's node type. e.g. 'div'
3378 * @param {Object=} properties An object of properties that should be set
3379 * @param {Object=} attributes An object of attributes that should be set
3380 * @return {Element}
3381 * @method createEl
3382 */
3383
3384 Component.prototype.createEl = function createEl(tagName, properties, attributes) {
3385 return Dom.createEl(tagName, properties, attributes);
3386 };
3387
3388 Component.prototype.localize = function localize(string) {
3389 var code = this.player_.language && this.player_.language();
3390 var languages = this.player_.languages && this.player_.languages();
3391
3392 if (!code || !languages) {
3393 return string;
3394 }
3395
3396 var language = languages[code];
3397
3398 if (language && language[string]) {
3399 return language[string];
3400 }
3401
3402 var primaryCode = code.split('-')[0];
3403 var primaryLang = languages[primaryCode];
3404
3405 if (primaryLang && primaryLang[string]) {
3406 return primaryLang[string];
3407 }
3408
3409 return string;
3410 };
3411
3412 /**
3413 * Return the component's DOM element where children are inserted.
3414 * Will either be the same as el() or a new element defined in createEl().
3415 *
3416 * @return {Element}
3417 * @method contentEl
3418 */
3419
3420 Component.prototype.contentEl = function contentEl() {
3421 return this.contentEl_ || this.el_;
3422 };
3423
3424 /**
3425 * Get the component's ID
3426 * ```js
3427 * var id = myComponent.id();
3428 * ```
3429 *
3430 * @return {String}
3431 * @method id
3432 */
3433
3434 Component.prototype.id = function id() {
3435 return this.id_;
3436 };
3437
3438 /**
3439 * Get the component's name. The name is often used to reference the component.
3440 * ```js
3441 * var name = myComponent.name();
3442 * ```
3443 *
3444 * @return {String}
3445 * @method name
3446 */
3447
3448 Component.prototype.name = function name() {
3449 return this.name_;
3450 };
3451
3452 /**
3453 * Get an array of all child components
3454 * ```js
3455 * var kids = myComponent.children();
3456 * ```
3457 *
3458 * @return {Array} The children
3459 * @method children
3460 */
3461
3462 Component.prototype.children = function children() {
3463 return this.children_;
3464 };
3465
3466 /**
3467 * Returns a child component with the provided ID
3468 *
3469 * @return {Component}
3470 * @method getChildById
3471 */
3472
3473 Component.prototype.getChildById = function getChildById(id) {
3474 return this.childIndex_[id];
3475 };
3476
3477 /**
3478 * Returns a child component with the provided name
3479 *
3480 * @return {Component}
3481 * @method getChild
3482 */
3483
3484 Component.prototype.getChild = function getChild(name) {
3485 return this.childNameIndex_[name];
3486 };
3487
3488 /**
3489 * Adds a child component inside this component
3490 * ```js
3491 * myComponent.el();
3492 * // -> <div class='my-component'></div>
3493 * myComponent.children();
3494 * // [empty array]
3495 *
3496 * var myButton = myComponent.addChild('MyButton');
3497 * // -> <div class='my-component'><div class="my-button">myButton<div></div>
3498 * // -> myButton === myComponent.children()[0];
3499 * ```
3500 * Pass in options for child constructors and options for children of the child
3501 * ```js
3502 * var myButton = myComponent.addChild('MyButton', {
3503 * text: 'Press Me',
3504 * buttonChildExample: {
3505 * buttonChildOption: true
3506 * }
3507 * });
3508 * ```
3509 *
3510 * @param {String|Component} child The class name or instance of a child to add
3511 * @param {Object=} options Options, including options to be passed to children of the child.
3512 * @param {Number} index into our children array to attempt to add the child
3513 * @return {Component} The child component (created by this process if a string was used)
3514 * @method addChild
3515 */
3516
3517 Component.prototype.addChild = function addChild(child) {
3518 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
3519 var index = arguments.length <= 2 || arguments[2] === undefined ? this.children_.length : arguments[2];
3520
3521 var component = undefined;
3522 var componentName = undefined;
3523
3524 // If child is a string, create nt with options
3525 if (typeof child === 'string') {
3526 componentName = child;
3527
3528 // Options can also be specified as a boolean, so convert to an empty object if false.
3529 if (!options) {
3530 options = {};
3531 }
3532
3533 // Same as above, but true is deprecated so show a warning.
3534 if (options === true) {
3535 _utilsLogJs2['default'].warn('Initializing a child component with `true` is deprecated. Children should be defined in an array when possible, but if necessary use an object instead of `true`.');
3536 options = {};
3537 }
3538
3539 // If no componentClass in options, assume componentClass is the name lowercased
3540 // (e.g. playButton)
3541 var componentClassName = options.componentClass || _utilsToTitleCaseJs2['default'](componentName);
3542
3543 // Set name through options
3544 options.name = componentName;
3545
3546 // Create a new object & element for this controls set
3547 // If there's no .player_, this is a player
3548 var ComponentClass = Component.getComponent(componentClassName);
3549
3550 if (!ComponentClass) {
3551 throw new Error('Component ' + componentClassName + ' does not exist');
3552 }
3553
3554 // data stored directly on the videojs object may be
3555 // misidentified as a component to retain
3556 // backwards-compatibility with 4.x. check to make sure the
3557 // component class can be instantiated.
3558 if (typeof ComponentClass !== 'function') {
3559 return null;
3560 }
3561
3562 component = new ComponentClass(this.player_ || this, options);
3563
3564 // child is a component instance
3565 } else {
3566 component = child;
3567 }
3568
3569 this.children_.splice(index, 0, component);
3570
3571 if (typeof component.id === 'function') {
3572 this.childIndex_[component.id()] = component;
3573 }
3574
3575 // If a name wasn't used to create the component, check if we can use the
3576 // name function of the component
3577 componentName = componentName || component.name && component.name();
3578
3579 if (componentName) {
3580 this.childNameIndex_[componentName] = component;
3581 }
3582
3583 // Add the UI object's element to the container div (box)
3584 // Having an element is not required
3585 if (typeof component.el === 'function' && component.el()) {
3586 var childNodes = this.contentEl().children;
3587 var refNode = childNodes[index] || null;
3588 this.contentEl().insertBefore(component.el(), refNode);
3589 }
3590
3591 // Return so it can stored on parent object if desired.
3592 return component;
3593 };
3594
3595 /**
3596 * Remove a child component from this component's list of children, and the
3597 * child component's element from this component's element
3598 *
3599 * @param {Component} component Component to remove
3600 * @method removeChild
3601 */
3602
3603 Component.prototype.removeChild = function removeChild(component) {
3604 if (typeof component === 'string') {
3605 component = this.getChild(component);
3606 }
3607
3608 if (!component || !this.children_) {
3609 return;
3610 }
3611
3612 var childFound = false;
3613
3614 for (var i = this.children_.length - 1; i >= 0; i--) {
3615 if (this.children_[i] === component) {
3616 childFound = true;
3617 this.children_.splice(i, 1);
3618 break;
3619 }
3620 }
3621
3622 if (!childFound) {
3623 return;
3624 }
3625
3626 this.childIndex_[component.id()] = null;
3627 this.childNameIndex_[component.name()] = null;
3628
3629 var compEl = component.el();
3630
3631 if (compEl && compEl.parentNode === this.contentEl()) {
3632 this.contentEl().removeChild(component.el());
3633 }
3634 };
3635
3636 /**
3637 * Add and initialize default child components from options
3638 * ```js
3639 * // when an instance of MyComponent is created, all children in options
3640 * // will be added to the instance by their name strings and options
3641 * MyComponent.prototype.options_ = {
3642 * children: [
3643 * 'myChildComponent'
3644 * ],
3645 * myChildComponent: {
3646 * myChildOption: true
3647 * }
3648 * };
3649 *
3650 * // Or when creating the component
3651 * var myComp = new MyComponent(player, {
3652 * children: [
3653 * 'myChildComponent'
3654 * ],
3655 * myChildComponent: {
3656 * myChildOption: true
3657 * }
3658 * });
3659 * ```
3660 * The children option can also be an array of
3661 * child options objects (that also include a 'name' key).
3662 * This can be used if you have two child components of the
3663 * same type that need different options.
3664 * ```js
3665 * var myComp = new MyComponent(player, {
3666 * children: [
3667 * 'button',
3668 * {
3669 * name: 'button',
3670 * someOtherOption: true
3671 * },
3672 * {
3673 * name: 'button',
3674 * someOtherOption: false
3675 * }
3676 * ]
3677 * });
3678 * ```
3679 *
3680 * @method initChildren
3681 */
3682
3683 Component.prototype.initChildren = function initChildren() {
3684 var _this = this;
3685
3686 var children = this.options_.children;
3687
3688 if (children) {
3689 (function () {
3690 // `this` is `parent`
3691 var parentOptions = _this.options_;
3692
3693 var handleAdd = function handleAdd(child) {
3694 var name = child.name;
3695 var opts = child.opts;
3696
3697 // Allow options for children to be set at the parent options
3698 // e.g. videojs(id, { controlBar: false });
3699 // instead of videojs(id, { children: { controlBar: false });
3700 if (parentOptions[name] !== undefined) {
3701 opts = parentOptions[name];
3702 }
3703
3704 // Allow for disabling default components
3705 // e.g. options['children']['posterImage'] = false
3706 if (opts === false) {
3707 return;
3708 }
3709
3710 // Allow options to be passed as a simple boolean if no configuration
3711 // is necessary.
3712 if (opts === true) {
3713 opts = {};
3714 }
3715
3716 // We also want to pass the original player options to each component as well so they don't need to
3717 // reach back into the player for options later.
3718 opts.playerOptions = _this.options_.playerOptions;
3719
3720 // Create and add the child component.
3721 // Add a direct reference to the child by name on the parent instance.
3722 // If two of the same component are used, different names should be supplied
3723 // for each
3724 var newChild = _this.addChild(name, opts);
3725 if (newChild) {
3726 _this[name] = newChild;
3727 }
3728 };
3729
3730 // Allow for an array of children details to passed in the options
3731 var workingChildren = undefined;
3732 var Tech = Component.getComponent('Tech');
3733
3734 if (Array.isArray(children)) {
3735 workingChildren = children;
3736 } else {
3737 workingChildren = Object.keys(children);
3738 }
3739
3740 workingChildren
3741 // children that are in this.options_ but also in workingChildren would
3742 // give us extra children we do not want. So, we want to filter them out.
3743 .concat(Object.keys(_this.options_).filter(function (child) {
3744 return !workingChildren.some(function (wchild) {
3745 if (typeof wchild === 'string') {
3746 return child === wchild;
3747 } else {
3748 return child === wchild.name;
3749 }
3750 });
3751 })).map(function (child) {
3752 var name = undefined,
3753 opts = undefined;
3754
3755 if (typeof child === 'string') {
3756 name = child;
3757 opts = children[name] || _this.options_[name] || {};
3758 } else {
3759 name = child.name;
3760 opts = child;
3761 }
3762
3763 return { name: name, opts: opts };
3764 }).filter(function (child) {
3765 // we have to make sure that child.name isn't in the techOrder since
3766 // techs are registerd as Components but can't aren't compatible
3767 // See https://github.com/videojs/video.js/issues/2772
3768 var c = Component.getComponent(child.opts.componentClass || _utilsToTitleCaseJs2['default'](child.name));
3769 return c && !Tech.isTech(c);
3770 }).forEach(handleAdd);
3771 })();
3772 }
3773 };
3774
3775 /**
3776 * Allows sub components to stack CSS class names
3777 *
3778 * @return {String} The constructed class name
3779 * @method buildCSSClass
3780 */
3781
3782 Component.prototype.buildCSSClass = function buildCSSClass() {
3783 // Child classes can include a function that does:
3784 // return 'CLASS NAME' + this._super();
3785 return '';
3786 };
3787
3788 /**
3789 * Add an event listener to this component's element
3790 * ```js
3791 * var myFunc = function(){
3792 * var myComponent = this;
3793 * // Do something when the event is fired
3794 * };
3795 *
3796 * myComponent.on('eventType', myFunc);
3797 * ```
3798 * The context of myFunc will be myComponent unless previously bound.
3799 * Alternatively, you can add a listener to another element or component.
3800 * ```js
3801 * myComponent.on(otherElement, 'eventName', myFunc);
3802 * myComponent.on(otherComponent, 'eventName', myFunc);
3803 * ```
3804 * The benefit of using this over `VjsEvents.on(otherElement, 'eventName', myFunc)`
3805 * and `otherComponent.on('eventName', myFunc)` is that this way the listeners
3806 * will be automatically cleaned up when either component is disposed.
3807 * It will also bind myComponent as the context of myFunc.
3808 * **NOTE**: When using this on elements in the page other than window
3809 * and document (both permanent), if you remove the element from the DOM
3810 * you need to call `myComponent.trigger(el, 'dispose')` on it to clean up
3811 * references to it and allow the browser to garbage collect it.
3812 *
3813 * @param {String|Component} first The event type or other component
3814 * @param {Function|String} second The event handler or event type
3815 * @param {Function} third The event handler
3816 * @return {Component}
3817 * @method on
3818 */
3819
3820 Component.prototype.on = function on(first, second, third) {
3821 var _this2 = this;
3822
3823 if (typeof first === 'string' || Array.isArray(first)) {
3824 Events.on(this.el_, first, Fn.bind(this, second));
3825
3826 // Targeting another component or element
3827 } else {
3828 (function () {
3829 var target = first;
3830 var type = second;
3831 var fn = Fn.bind(_this2, third);
3832
3833 // When this component is disposed, remove the listener from the other component
3834 var removeOnDispose = function removeOnDispose() {
3835 return _this2.off(target, type, fn);
3836 };
3837
3838 // Use the same function ID so we can remove it later it using the ID
3839 // of the original listener
3840 removeOnDispose.guid = fn.guid;
3841 _this2.on('dispose', removeOnDispose);
3842
3843 // If the other component is disposed first we need to clean the reference
3844 // to the other component in this component's removeOnDispose listener
3845 // Otherwise we create a memory leak.
3846 var cleanRemover = function cleanRemover() {
3847 return _this2.off('dispose', removeOnDispose);
3848 };
3849
3850 // Add the same function ID so we can easily remove it later
3851 cleanRemover.guid = fn.guid;
3852
3853 // Check if this is a DOM node
3854 if (first.nodeName) {
3855 // Add the listener to the other element
3856 Events.on(target, type, fn);
3857 Events.on(target, 'dispose', cleanRemover);
3858
3859 // Should be a component
3860 // Not using `instanceof Component` because it makes mock players difficult
3861 } else if (typeof first.on === 'function') {
3862 // Add the listener to the other component
3863 target.on(type, fn);
3864 target.on('dispose', cleanRemover);
3865 }
3866 })();
3867 }
3868
3869 return this;
3870 };
3871
3872 /**
3873 * Remove an event listener from this component's element
3874 * ```js
3875 * myComponent.off('eventType', myFunc);
3876 * ```
3877 * If myFunc is excluded, ALL listeners for the event type will be removed.
3878 * If eventType is excluded, ALL listeners will be removed from the component.
3879 * Alternatively you can use `off` to remove listeners that were added to other
3880 * elements or components using `myComponent.on(otherComponent...`.
3881 * In this case both the event type and listener function are REQUIRED.
3882 * ```js
3883 * myComponent.off(otherElement, 'eventType', myFunc);
3884 * myComponent.off(otherComponent, 'eventType', myFunc);
3885 * ```
3886 *
3887 * @param {String=|Component} first The event type or other component
3888 * @param {Function=|String} second The listener function or event type
3889 * @param {Function=} third The listener for other component
3890 * @return {Component}
3891 * @method off
3892 */
3893
3894 Component.prototype.off = function off(first, second, third) {
3895 if (!first || typeof first === 'string' || Array.isArray(first)) {
3896 Events.off(this.el_, first, second);
3897 } else {
3898 var target = first;
3899 var type = second;
3900 // Ensure there's at least a guid, even if the function hasn't been used
3901 var fn = Fn.bind(this, third);
3902
3903 // Remove the dispose listener on this component,
3904 // which was given the same guid as the event listener
3905 this.off('dispose', fn);
3906
3907 if (first.nodeName) {
3908 // Remove the listener
3909 Events.off(target, type, fn);
3910 // Remove the listener for cleaning the dispose listener
3911 Events.off(target, 'dispose', fn);
3912 } else {
3913 target.off(type, fn);
3914 target.off('dispose', fn);
3915 }
3916 }
3917
3918 return this;
3919 };
3920
3921 /**
3922 * Add an event listener to be triggered only once and then removed
3923 * ```js
3924 * myComponent.one('eventName', myFunc);
3925 * ```
3926 * Alternatively you can add a listener to another element or component
3927 * that will be triggered only once.
3928 * ```js
3929 * myComponent.one(otherElement, 'eventName', myFunc);
3930 * myComponent.one(otherComponent, 'eventName', myFunc);
3931 * ```
3932 *
3933 * @param {String|Component} first The event type or other component
3934 * @param {Function|String} second The listener function or event type
3935 * @param {Function=} third The listener function for other component
3936 * @return {Component}
3937 * @method one
3938 */
3939
3940 Component.prototype.one = function one(first, second, third) {
3941 var _this3 = this,
3942 _arguments = arguments;
3943
3944 if (typeof first === 'string' || Array.isArray(first)) {
3945 Events.one(this.el_, first, Fn.bind(this, second));
3946 } else {
3947 (function () {
3948 var target = first;
3949 var type = second;
3950 var fn = Fn.bind(_this3, third);
3951
3952 var newFunc = function newFunc() {
3953 _this3.off(target, type, newFunc);
3954 fn.apply(null, _arguments);
3955 };
3956
3957 // Keep the same function ID so we can remove it later
3958 newFunc.guid = fn.guid;
3959
3960 _this3.on(target, type, newFunc);
3961 })();
3962 }
3963
3964 return this;
3965 };
3966
3967 /**
3968 * Trigger an event on an element
3969 * ```js
3970 * myComponent.trigger('eventName');
3971 * myComponent.trigger({'type':'eventName'});
3972 * myComponent.trigger('eventName', {data: 'some data'});
3973 * myComponent.trigger({'type':'eventName'}, {data: 'some data'});
3974 * ```
3975 *
3976 * @param {Event|Object|String} event A string (the type) or an event object with a type attribute
3977 * @param {Object} [hash] data hash to pass along with the event
3978 * @return {Component} self
3979 * @method trigger
3980 */
3981
3982 Component.prototype.trigger = function trigger(event, hash) {
3983 Events.trigger(this.el_, event, hash);
3984 return this;
3985 };
3986
3987 /**
3988 * Bind a listener to the component's ready state.
3989 * Different from event listeners in that if the ready event has already happened
3990 * it will trigger the function immediately.
3991 *
3992 * @param {Function} fn Ready listener
3993 * @param {Boolean} sync Exec the listener synchronously if component is ready
3994 * @return {Component}
3995 * @method ready
3996 */
3997
3998 Component.prototype.ready = function ready(fn) {
3999 var sync = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
4000
4001 if (fn) {
4002 if (this.isReady_) {
4003 if (sync) {
4004 fn.call(this);
4005 } else {
4006 // Call the function asynchronously by default for consistency
4007 this.setTimeout(fn, 1);
4008 }
4009 } else {
4010 this.readyQueue_ = this.readyQueue_ || [];
4011 this.readyQueue_.push(fn);
4012 }
4013 }
4014 return this;
4015 };
4016
4017 /**
4018 * Trigger the ready listeners
4019 *
4020 * @return {Component}
4021 * @method triggerReady
4022 */
4023
4024 Component.prototype.triggerReady = function triggerReady() {
4025 this.isReady_ = true;
4026
4027 // Ensure ready is triggerd asynchronously
4028 this.setTimeout(function () {
4029 var readyQueue = this.readyQueue_;
4030
4031 // Reset Ready Queue
4032 this.readyQueue_ = [];
4033
4034 if (readyQueue && readyQueue.length > 0) {
4035 readyQueue.forEach(function (fn) {
4036 fn.call(this);
4037 }, this);
4038 }
4039
4040 // Allow for using event listeners also
4041 this.trigger('ready');
4042 }, 1);
4043 };
4044
4045 /**
4046 * Finds a single DOM element matching `selector` within the component's
4047 * `contentEl` or another custom context.
4048 *
4049 * @method $
4050 * @param {String} selector
4051 * A valid CSS selector, which will be passed to `querySelector`.
4052 *
4053 * @param {Element|String} [context=document]
4054 * A DOM element within which to query. Can also be a selector
4055 * string in which case the first matching element will be used
4056 * as context. If missing (or no element matches selector), falls
4057 * back to `document`.
4058 *
4059 * @return {Element|null}
4060 */
4061
4062 Component.prototype.$ = function $(selector, context) {
4063 return Dom.$(selector, context || this.contentEl());
4064 };
4065
4066 /**
4067 * Finds a all DOM elements matching `selector` within the component's
4068 * `contentEl` or another custom context.
4069 *
4070 * @method $$
4071 * @param {String} selector
4072 * A valid CSS selector, which will be passed to `querySelectorAll`.
4073 *
4074 * @param {Element|String} [context=document]
4075 * A DOM element within which to query. Can also be a selector
4076 * string in which case the first matching element will be used
4077 * as context. If missing (or no element matches selector), falls
4078 * back to `document`.
4079 *
4080 * @return {NodeList}
4081 */
4082
4083 Component.prototype.$$ = function $$(selector, context) {
4084 return Dom.$$(selector, context || this.contentEl());
4085 };
4086
4087 /**
4088 * Check if a component's element has a CSS class name
4089 *
4090 * @param {String} classToCheck Classname to check
4091 * @return {Component}
4092 * @method hasClass
4093 */
4094
4095 Component.prototype.hasClass = function hasClass(classToCheck) {
4096 return Dom.hasElClass(this.el_, classToCheck);
4097 };
4098
4099 /**
4100 * Add a CSS class name to the component's element
4101 *
4102 * @param {String} classToAdd Classname to add
4103 * @return {Component}
4104 * @method addClass
4105 */
4106
4107 Component.prototype.addClass = function addClass(classToAdd) {
4108 Dom.addElClass(this.el_, classToAdd);
4109 return this;
4110 };
4111
4112 /**
4113 * Remove a CSS class name from the component's element
4114 *
4115 * @param {String} classToRemove Classname to remove
4116 * @return {Component}
4117 * @method removeClass
4118 */
4119
4120 Component.prototype.removeClass = function removeClass(classToRemove) {
4121 Dom.removeElClass(this.el_, classToRemove);
4122 return this;
4123 };
4124
4125 /**
4126 * Add or remove a CSS class name from the component's element
4127 *
4128 * @param {String} classToToggle
4129 * @param {Boolean|Function} [predicate]
4130 * Can be a function that returns a Boolean. If `true`, the class
4131 * will be added; if `false`, the class will be removed. If not
4132 * given, the class will be added if not present and vice versa.
4133 *
4134 * @return {Component}
4135 * @method toggleClass
4136 */
4137
4138 Component.prototype.toggleClass = function toggleClass(classToToggle, predicate) {
4139 Dom.toggleElClass(this.el_, classToToggle, predicate);
4140 return this;
4141 };
4142
4143 /**
4144 * Show the component element if hidden
4145 *
4146 * @return {Component}
4147 * @method show
4148 */
4149
4150 Component.prototype.show = function show() {
4151 this.removeClass('vjs-hidden');
4152 return this;
4153 };
4154
4155 /**
4156 * Hide the component element if currently showing
4157 *
4158 * @return {Component}
4159 * @method hide
4160 */
4161
4162 Component.prototype.hide = function hide() {
4163 this.addClass('vjs-hidden');
4164 return this;
4165 };
4166
4167 /**
4168 * Lock an item in its visible state
4169 * To be used with fadeIn/fadeOut.
4170 *
4171 * @return {Component}
4172 * @private
4173 * @method lockShowing
4174 */
4175
4176 Component.prototype.lockShowing = function lockShowing() {
4177 this.addClass('vjs-lock-showing');
4178 return this;
4179 };
4180
4181 /**
4182 * Unlock an item to be hidden
4183 * To be used with fadeIn/fadeOut.
4184 *
4185 * @return {Component}
4186 * @private
4187 * @method unlockShowing
4188 */
4189
4190 Component.prototype.unlockShowing = function unlockShowing() {
4191 this.removeClass('vjs-lock-showing');
4192 return this;
4193 };
4194
4195 /**
4196 * Set or get the width of the component (CSS values)
4197 * Setting the video tag dimension values only works with values in pixels.
4198 * Percent values will not work.
4199 * Some percents can be used, but width()/height() will return the number + %,
4200 * not the actual computed width/height.
4201 *
4202 * @param {Number|String=} num Optional width number
4203 * @param {Boolean} skipListeners Skip the 'resize' event trigger
4204 * @return {Component} This component, when setting the width
4205 * @return {Number|String} The width, when getting
4206 * @method width
4207 */
4208
4209 Component.prototype.width = function width(num, skipListeners) {
4210 return this.dimension('width', num, skipListeners);
4211 };
4212
4213 /**
4214 * Get or set the height of the component (CSS values)
4215 * Setting the video tag dimension values only works with values in pixels.
4216 * Percent values will not work.
4217 * Some percents can be used, but width()/height() will return the number + %,
4218 * not the actual computed width/height.
4219 *
4220 * @param {Number|String=} num New component height
4221 * @param {Boolean=} skipListeners Skip the resize event trigger
4222 * @return {Component} This component, when setting the height
4223 * @return {Number|String} The height, when getting
4224 * @method height
4225 */
4226
4227 Component.prototype.height = function height(num, skipListeners) {
4228 return this.dimension('height', num, skipListeners);
4229 };
4230
4231 /**
4232 * Set both width and height at the same time
4233 *
4234 * @param {Number|String} width Width of player
4235 * @param {Number|String} height Height of player
4236 * @return {Component} The component
4237 * @method dimensions
4238 */
4239
4240 Component.prototype.dimensions = function dimensions(width, height) {
4241 // Skip resize listeners on width for optimization
4242 return this.width(width, true).height(height);
4243 };
4244
4245 /**
4246 * Get or set width or height
4247 * This is the shared code for the width() and height() methods.
4248 * All for an integer, integer + 'px' or integer + '%';
4249 * Known issue: Hidden elements officially have a width of 0. We're defaulting
4250 * to the style.width value and falling back to computedStyle which has the
4251 * hidden element issue. Info, but probably not an efficient fix:
4252 * http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/
4253 *
4254 * @param {String} widthOrHeight 'width' or 'height'
4255 * @param {Number|String=} num New dimension
4256 * @param {Boolean=} skipListeners Skip resize event trigger
4257 * @return {Component} The component if a dimension was set
4258 * @return {Number|String} The dimension if nothing was set
4259 * @private
4260 * @method dimension
4261 */
4262
4263 Component.prototype.dimension = function dimension(widthOrHeight, num, skipListeners) {
4264 if (num !== undefined) {
4265 // Set to zero if null or literally NaN (NaN !== NaN)
4266 if (num === null || num !== num) {
4267 num = 0;
4268 }
4269
4270 // Check if using css width/height (% or px) and adjust
4271 if (('' + num).indexOf('%') !== -1 || ('' + num).indexOf('px') !== -1) {
4272 this.el_.style[widthOrHeight] = num;
4273 } else if (num === 'auto') {
4274 this.el_.style[widthOrHeight] = '';
4275 } else {
4276 this.el_.style[widthOrHeight] = num + 'px';
4277 }
4278
4279 // skipListeners allows us to avoid triggering the resize event when setting both width and height
4280 if (!skipListeners) {
4281 this.trigger('resize');
4282 }
4283
4284 // Return component
4285 return this;
4286 }
4287
4288 // Not setting a value, so getting it
4289 // Make sure element exists
4290 if (!this.el_) {
4291 return 0;
4292 }
4293
4294 // Get dimension value from style
4295 var val = this.el_.style[widthOrHeight];
4296 var pxIndex = val.indexOf('px');
4297
4298 if (pxIndex !== -1) {
4299 // Return the pixel value with no 'px'
4300 return parseInt(val.slice(0, pxIndex), 10);
4301 }
4302
4303 // No px so using % or no style was set, so falling back to offsetWidth/height
4304 // If component has display:none, offset will return 0
4305 // TODO: handle display:none and no dimension style using px
4306 return parseInt(this.el_['offset' + _utilsToTitleCaseJs2['default'](widthOrHeight)], 10);
4307 };
4308
4309 /**
4310 * Emit 'tap' events when touch events are supported
4311 * This is used to support toggling the controls through a tap on the video.
4312 * We're requiring them to be enabled because otherwise every component would
4313 * have this extra overhead unnecessarily, on mobile devices where extra
4314 * overhead is especially bad.
4315 *
4316 * @private
4317 * @method emitTapEvents
4318 */
4319
4320 Component.prototype.emitTapEvents = function emitTapEvents() {
4321 // Track the start time so we can determine how long the touch lasted
4322 var touchStart = 0;
4323 var firstTouch = null;
4324
4325 // Maximum movement allowed during a touch event to still be considered a tap
4326 // Other popular libs use anywhere from 2 (hammer.js) to 15, so 10 seems like a nice, round number.
4327 var tapMovementThreshold = 10;
4328
4329 // The maximum length a touch can be while still being considered a tap
4330 var touchTimeThreshold = 200;
4331
4332 var couldBeTap = undefined;
4333
4334 this.on('touchstart', function (event) {
4335 // If more than one finger, don't consider treating this as a click
4336 if (event.touches.length === 1) {
4337 // Copy the touches object to prevent modifying the original
4338 firstTouch = _objectAssign2['default']({}, event.touches[0]);
4339 // Record start time so we can detect a tap vs. "touch and hold"
4340 touchStart = new Date().getTime();
4341 // Reset couldBeTap tracking
4342 couldBeTap = true;
4343 }
4344 });
4345
4346 this.on('touchmove', function (event) {
4347 // If more than one finger, don't consider treating this as a click
4348 if (event.touches.length > 1) {
4349 couldBeTap = false;
4350 } else if (firstTouch) {
4351 // Some devices will throw touchmoves for all but the slightest of taps.
4352 // So, if we moved only a small distance, this could still be a tap
4353 var xdiff = event.touches[0].pageX - firstTouch.pageX;
4354 var ydiff = event.touches[0].pageY - firstTouch.pageY;
4355 var touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
4356
4357 if (touchDistance > tapMovementThreshold) {
4358 couldBeTap = false;
4359 }
4360 }
4361 });
4362
4363 var noTap = function noTap() {
4364 couldBeTap = false;
4365 };
4366
4367 // TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s
4368 this.on('touchleave', noTap);
4369 this.on('touchcancel', noTap);
4370
4371 // When the touch ends, measure how long it took and trigger the appropriate
4372 // event
4373 this.on('touchend', function (event) {
4374 firstTouch = null;
4375 // Proceed only if the touchmove/leave/cancel event didn't happen
4376 if (couldBeTap === true) {
4377 // Measure how long the touch lasted
4378 var touchTime = new Date().getTime() - touchStart;
4379
4380 // Make sure the touch was less than the threshold to be considered a tap
4381 if (touchTime < touchTimeThreshold) {
4382 // Don't let browser turn this into a click
4383 event.preventDefault();
4384 this.trigger('tap');
4385 // It may be good to copy the touchend event object and change the
4386 // type to tap, if the other event properties aren't exact after
4387 // Events.fixEvent runs (e.g. event.target)
4388 }
4389 }
4390 });
4391 };
4392
4393 /**
4394 * Report user touch activity when touch events occur
4395 * User activity is used to determine when controls should show/hide. It's
4396 * relatively simple when it comes to mouse events, because any mouse event
4397 * should show the controls. So we capture mouse events that bubble up to the
4398 * player and report activity when that happens.
4399 * With touch events it isn't as easy. We can't rely on touch events at the
4400 * player level, because a tap (touchstart + touchend) on the video itself on
4401 * mobile devices is meant to turn controls off (and on). User activity is
4402 * checked asynchronously, so what could happen is a tap event on the video
4403 * turns the controls off, then the touchend event bubbles up to the player,
4404 * which if it reported user activity, would turn the controls right back on.
4405 * (We also don't want to completely block touch events from bubbling up)
4406 * Also a touchmove, touch+hold, and anything other than a tap is not supposed
4407 * to turn the controls back on on a mobile device.
4408 * Here we're setting the default component behavior to report user activity
4409 * whenever touch events happen, and this can be turned off by components that
4410 * want touch events to act differently.
4411 *
4412 * @method enableTouchActivity
4413 */
4414
4415 Component.prototype.enableTouchActivity = function enableTouchActivity() {
4416 // Don't continue if the root player doesn't support reporting user activity
4417 if (!this.player() || !this.player().reportUserActivity) {
4418 return;
4419 }
4420
4421 // listener for reporting that the user is active
4422 var report = Fn.bind(this.player(), this.player().reportUserActivity);
4423
4424 var touchHolding = undefined;
4425
4426 this.on('touchstart', function () {
4427 report();
4428 // For as long as the they are touching the device or have their mouse down,
4429 // we consider them active even if they're not moving their finger or mouse.
4430 // So we want to continue to update that they are active
4431 this.clearInterval(touchHolding);
4432 // report at the same interval as activityCheck
4433 touchHolding = this.setInterval(report, 250);
4434 });
4435
4436 var touchEnd = function touchEnd(event) {
4437 report();
4438 // stop the interval that maintains activity if the touch is holding
4439 this.clearInterval(touchHolding);
4440 };
4441
4442 this.on('touchmove', report);
4443 this.on('touchend', touchEnd);
4444 this.on('touchcancel', touchEnd);
4445 };
4446
4447 /**
4448 * Creates timeout and sets up disposal automatically.
4449 *
4450 * @param {Function} fn The function to run after the timeout.
4451 * @param {Number} timeout Number of ms to delay before executing specified function.
4452 * @return {Number} Returns the timeout ID
4453 * @method setTimeout
4454 */
4455
4456 Component.prototype.setTimeout = function setTimeout(fn, timeout) {
4457 fn = Fn.bind(this, fn);
4458
4459 // window.setTimeout would be preferable here, but due to some bizarre issue with Sinon and/or Phantomjs, we can't.
4460 var timeoutId = _globalWindow2['default'].setTimeout(fn, timeout);
4461
4462 var disposeFn = function disposeFn() {
4463 this.clearTimeout(timeoutId);
4464 };
4465
4466 disposeFn.guid = 'vjs-timeout-' + timeoutId;
4467
4468 this.on('dispose', disposeFn);
4469
4470 return timeoutId;
4471 };
4472
4473 /**
4474 * Clears a timeout and removes the associated dispose listener
4475 *
4476 * @param {Number} timeoutId The id of the timeout to clear
4477 * @return {Number} Returns the timeout ID
4478 * @method clearTimeout
4479 */
4480
4481 Component.prototype.clearTimeout = function clearTimeout(timeoutId) {
4482 _globalWindow2['default'].clearTimeout(timeoutId);
4483
4484 var disposeFn = function disposeFn() {};
4485
4486 disposeFn.guid = 'vjs-timeout-' + timeoutId;
4487
4488 this.off('dispose', disposeFn);
4489
4490 return timeoutId;
4491 };
4492
4493 /**
4494 * Creates an interval and sets up disposal automatically.
4495 *
4496 * @param {Function} fn The function to run every N seconds.
4497 * @param {Number} interval Number of ms to delay before executing specified function.
4498 * @return {Number} Returns the interval ID
4499 * @method setInterval
4500 */
4501
4502 Component.prototype.setInterval = function setInterval(fn, interval) {
4503 fn = Fn.bind(this, fn);
4504
4505 var intervalId = _globalWindow2['default'].setInterval(fn, interval);
4506
4507 var disposeFn = function disposeFn() {
4508 this.clearInterval(intervalId);
4509 };
4510
4511 disposeFn.guid = 'vjs-interval-' + intervalId;
4512
4513 this.on('dispose', disposeFn);
4514
4515 return intervalId;
4516 };
4517
4518 /**
4519 * Clears an interval and removes the associated dispose listener
4520 *
4521 * @param {Number} intervalId The id of the interval to clear
4522 * @return {Number} Returns the interval ID
4523 * @method clearInterval
4524 */
4525
4526 Component.prototype.clearInterval = function clearInterval(intervalId) {
4527 _globalWindow2['default'].clearInterval(intervalId);
4528
4529 var disposeFn = function disposeFn() {};
4530
4531 disposeFn.guid = 'vjs-interval-' + intervalId;
4532
4533 this.off('dispose', disposeFn);
4534
4535 return intervalId;
4536 };
4537
4538 /**
4539 * Registers a component
4540 *
4541 * @param {String} name Name of the component to register
4542 * @param {Object} comp The component to register
4543 * @static
4544 * @method registerComponent
4545 */
4546
4547 Component.registerComponent = function registerComponent(name, comp) {
4548 if (!Component.components_) {
4549 Component.components_ = {};
4550 }
4551
4552 Component.components_[name] = comp;
4553 return comp;
4554 };
4555
4556 /**
4557 * Gets a component by name
4558 *
4559 * @param {String} name Name of the component to get
4560 * @return {Component}
4561 * @static
4562 * @method getComponent
4563 */
4564
4565 Component.getComponent = function getComponent(name) {
4566 if (Component.components_ && Component.components_[name]) {
4567 return Component.components_[name];
4568 }
4569
4570 if (_globalWindow2['default'] && _globalWindow2['default'].videojs && _globalWindow2['default'].videojs[name]) {
4571 _utilsLogJs2['default'].warn('The ' + name + ' component was added to the videojs object when it should be registered using videojs.registerComponent(name, component)');
4572 return _globalWindow2['default'].videojs[name];
4573 }
4574 };
4575
4576 /**
4577 * Sets up the constructor using the supplied init method
4578 * or uses the init of the parent object
4579 *
4580 * @param {Object} props An object of properties
4581 * @static
4582 * @deprecated
4583 * @method extend
4584 */
4585
4586 Component.extend = function extend(props) {
4587 props = props || {};
4588
4589 _utilsLogJs2['default'].warn('Component.extend({}) has been deprecated, use videojs.extend(Component, {}) instead');
4590
4591 // Set up the constructor using the supplied init method
4592 // or using the init of the parent object
4593 // Make sure to check the unobfuscated version for external libs
4594 var init = props.init || props.init || this.prototype.init || this.prototype.init || function () {};
4595 // In Resig's simple class inheritance (previously used) the constructor
4596 // is a function that calls `this.init.apply(arguments)`
4597 // However that would prevent us from using `ParentObject.call(this);`
4598 // in a Child constructor because the `this` in `this.init`
4599 // would still refer to the Child and cause an infinite loop.
4600 // We would instead have to do
4601 // `ParentObject.prototype.init.apply(this, arguments);`
4602 // Bleh. We're not creating a _super() function, so it's good to keep
4603 // the parent constructor reference simple.
4604 var subObj = function subObj() {
4605 init.apply(this, arguments);
4606 };
4607
4608 // Inherit from this object's prototype
4609 subObj.prototype = Object.create(this.prototype);
4610 // Reset the constructor property for subObj otherwise
4611 // instances of subObj would have the constructor of the parent Object
4612 subObj.prototype.constructor = subObj;
4613
4614 // Make the class extendable
4615 subObj.extend = Component.extend;
4616
4617 // Extend subObj's prototype with functions and other properties from props
4618 for (var _name in props) {
4619 if (props.hasOwnProperty(_name)) {
4620 subObj.prototype[_name] = props[_name];
4621 }
4622 }
4623
4624 return subObj;
4625 };
4626
4627 return Component;
4628})();
4629
4630Component.registerComponent('Component', Component);
4631exports['default'] = Component;
4632module.exports = exports['default'];
4633
4634},{"./utils/dom.js":132,"./utils/events.js":133,"./utils/fn.js":134,"./utils/guid.js":136,"./utils/log.js":137,"./utils/merge-options.js":138,"./utils/to-title-case.js":141,"global/window":2,"object.assign":45}],68:[function(_dereq_,module,exports){
4635/**
4636 * @file control-bar.js
4637 */
4638'use strict';
4639
4640exports.__esModule = true;
4641
4642function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4643
4644function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
4645
4646function _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; }
4647
4648var _componentJs = _dereq_('../component.js');
4649
4650var _componentJs2 = _interopRequireDefault(_componentJs);
4651
4652// Required children
4653
4654var _playToggleJs = _dereq_('./play-toggle.js');
4655
4656var _playToggleJs2 = _interopRequireDefault(_playToggleJs);
4657
4658var _timeControlsCurrentTimeDisplayJs = _dereq_('./time-controls/current-time-display.js');
4659
4660var _timeControlsCurrentTimeDisplayJs2 = _interopRequireDefault(_timeControlsCurrentTimeDisplayJs);
4661
4662var _timeControlsDurationDisplayJs = _dereq_('./time-controls/duration-display.js');
4663
4664var _timeControlsDurationDisplayJs2 = _interopRequireDefault(_timeControlsDurationDisplayJs);
4665
4666var _timeControlsTimeDividerJs = _dereq_('./time-controls/time-divider.js');
4667
4668var _timeControlsTimeDividerJs2 = _interopRequireDefault(_timeControlsTimeDividerJs);
4669
4670var _timeControlsRemainingTimeDisplayJs = _dereq_('./time-controls/remaining-time-display.js');
4671
4672var _timeControlsRemainingTimeDisplayJs2 = _interopRequireDefault(_timeControlsRemainingTimeDisplayJs);
4673
4674var _liveDisplayJs = _dereq_('./live-display.js');
4675
4676var _liveDisplayJs2 = _interopRequireDefault(_liveDisplayJs);
4677
4678var _progressControlProgressControlJs = _dereq_('./progress-control/progress-control.js');
4679
4680var _progressControlProgressControlJs2 = _interopRequireDefault(_progressControlProgressControlJs);
4681
4682var _fullscreenToggleJs = _dereq_('./fullscreen-toggle.js');
4683
4684var _fullscreenToggleJs2 = _interopRequireDefault(_fullscreenToggleJs);
4685
4686var _volumeControlVolumeControlJs = _dereq_('./volume-control/volume-control.js');
4687
4688var _volumeControlVolumeControlJs2 = _interopRequireDefault(_volumeControlVolumeControlJs);
4689
4690var _volumeMenuButtonJs = _dereq_('./volume-menu-button.js');
4691
4692var _volumeMenuButtonJs2 = _interopRequireDefault(_volumeMenuButtonJs);
4693
4694var _muteToggleJs = _dereq_('./mute-toggle.js');
4695
4696var _muteToggleJs2 = _interopRequireDefault(_muteToggleJs);
4697
4698var _textTrackControlsChaptersButtonJs = _dereq_('./text-track-controls/chapters-button.js');
4699
4700var _textTrackControlsChaptersButtonJs2 = _interopRequireDefault(_textTrackControlsChaptersButtonJs);
4701
4702var _textTrackControlsSubtitlesButtonJs = _dereq_('./text-track-controls/subtitles-button.js');
4703
4704var _textTrackControlsSubtitlesButtonJs2 = _interopRequireDefault(_textTrackControlsSubtitlesButtonJs);
4705
4706var _textTrackControlsCaptionsButtonJs = _dereq_('./text-track-controls/captions-button.js');
4707
4708var _textTrackControlsCaptionsButtonJs2 = _interopRequireDefault(_textTrackControlsCaptionsButtonJs);
4709
4710var _playbackRateMenuPlaybackRateMenuButtonJs = _dereq_('./playback-rate-menu/playback-rate-menu-button.js');
4711
4712var _playbackRateMenuPlaybackRateMenuButtonJs2 = _interopRequireDefault(_playbackRateMenuPlaybackRateMenuButtonJs);
4713
4714var _spacerControlsCustomControlSpacerJs = _dereq_('./spacer-controls/custom-control-spacer.js');
4715
4716var _spacerControlsCustomControlSpacerJs2 = _interopRequireDefault(_spacerControlsCustomControlSpacerJs);
4717
4718/**
4719 * Container of main controls
4720 *
4721 * @extends Component
4722 * @class ControlBar
4723 */
4724
4725var ControlBar = (function (_Component) {
4726 _inherits(ControlBar, _Component);
4727
4728 function ControlBar() {
4729 _classCallCheck(this, ControlBar);
4730
4731 _Component.apply(this, arguments);
4732 }
4733
4734 /**
4735 * Create the component's DOM element
4736 *
4737 * @return {Element}
4738 * @method createEl
4739 */
4740
4741 ControlBar.prototype.createEl = function createEl() {
4742 return _Component.prototype.createEl.call(this, 'div', {
4743 className: 'vjs-control-bar',
4744 dir: 'ltr'
4745 }, {
4746 'role': 'group' // The control bar is a group, so it can contain menuitems
4747 });
4748 };
4749
4750 return ControlBar;
4751})(_componentJs2['default']);
4752
4753ControlBar.prototype.options_ = {
4754 loadEvent: 'play',
4755 children: ['playToggle', 'volumeMenuButton', 'currentTimeDisplay', 'timeDivider', 'durationDisplay', 'progressControl', 'liveDisplay', 'remainingTimeDisplay', 'customControlSpacer', 'playbackRateMenuButton', 'chaptersButton', 'subtitlesButton', 'captionsButton', 'fullscreenToggle']
4756};
4757
4758_componentJs2['default'].registerComponent('ControlBar', ControlBar);
4759exports['default'] = ControlBar;
4760module.exports = exports['default'];
4761
4762},{"../component.js":67,"./fullscreen-toggle.js":69,"./live-display.js":70,"./mute-toggle.js":71,"./play-toggle.js":72,"./playback-rate-menu/playback-rate-menu-button.js":73,"./progress-control/progress-control.js":78,"./spacer-controls/custom-control-spacer.js":80,"./text-track-controls/captions-button.js":83,"./text-track-controls/chapters-button.js":84,"./text-track-controls/subtitles-button.js":87,"./time-controls/current-time-display.js":90,"./time-controls/duration-display.js":91,"./time-controls/remaining-time-display.js":92,"./time-controls/time-divider.js":93,"./volume-control/volume-control.js":95,"./volume-menu-button.js":97}],69:[function(_dereq_,module,exports){
4763/**
4764 * @file fullscreen-toggle.js
4765 */
4766'use strict';
4767
4768exports.__esModule = true;
4769
4770function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4771
4772function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
4773
4774function _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; }
4775
4776var _buttonJs = _dereq_('../button.js');
4777
4778var _buttonJs2 = _interopRequireDefault(_buttonJs);
4779
4780var _componentJs = _dereq_('../component.js');
4781
4782var _componentJs2 = _interopRequireDefault(_componentJs);
4783
4784/**
4785 * Toggle fullscreen video
4786 *
4787 * @extends Button
4788 * @class FullscreenToggle
4789 */
4790
4791var FullscreenToggle = (function (_Button) {
4792 _inherits(FullscreenToggle, _Button);
4793
4794 function FullscreenToggle() {
4795 _classCallCheck(this, FullscreenToggle);
4796
4797 _Button.apply(this, arguments);
4798 }
4799
4800 /**
4801 * Allow sub components to stack CSS class names
4802 *
4803 * @return {String} The constructed class name
4804 * @method buildCSSClass
4805 */
4806
4807 FullscreenToggle.prototype.buildCSSClass = function buildCSSClass() {
4808 return 'vjs-fullscreen-control ' + _Button.prototype.buildCSSClass.call(this);
4809 };
4810
4811 /**
4812 * Handles click for full screen
4813 *
4814 * @method handleClick
4815 */
4816
4817 FullscreenToggle.prototype.handleClick = function handleClick() {
4818 if (!this.player_.isFullscreen()) {
4819 this.player_.requestFullscreen();
4820 this.controlText('Non-Fullscreen');
4821 } else {
4822 this.player_.exitFullscreen();
4823 this.controlText('Fullscreen');
4824 }
4825 };
4826
4827 return FullscreenToggle;
4828})(_buttonJs2['default']);
4829
4830FullscreenToggle.prototype.controlText_ = 'Fullscreen';
4831
4832_componentJs2['default'].registerComponent('FullscreenToggle', FullscreenToggle);
4833exports['default'] = FullscreenToggle;
4834module.exports = exports['default'];
4835
4836},{"../button.js":64,"../component.js":67}],70:[function(_dereq_,module,exports){
4837/**
4838 * @file live-display.js
4839 */
4840'use strict';
4841
4842exports.__esModule = true;
4843
4844function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
4845
4846function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4847
4848function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
4849
4850function _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; }
4851
4852var _component = _dereq_('../component');
4853
4854var _component2 = _interopRequireDefault(_component);
4855
4856var _utilsDomJs = _dereq_('../utils/dom.js');
4857
4858var Dom = _interopRequireWildcard(_utilsDomJs);
4859
4860/**
4861 * Displays the live indicator
4862 * TODO - Future make it click to snap to live
4863 *
4864 * @extends Component
4865 * @class LiveDisplay
4866 */
4867
4868var LiveDisplay = (function (_Component) {
4869 _inherits(LiveDisplay, _Component);
4870
4871 function LiveDisplay(player, options) {
4872 _classCallCheck(this, LiveDisplay);
4873
4874 _Component.call(this, player, options);
4875
4876 this.updateShowing();
4877 this.on(this.player(), 'durationchange', this.updateShowing);
4878 }
4879
4880 /**
4881 * Create the component's DOM element
4882 *
4883 * @return {Element}
4884 * @method createEl
4885 */
4886
4887 LiveDisplay.prototype.createEl = function createEl() {
4888 var el = _Component.prototype.createEl.call(this, 'div', {
4889 className: 'vjs-live-control vjs-control'
4890 });
4891
4892 this.contentEl_ = Dom.createEl('div', {
4893 className: 'vjs-live-display',
4894 innerHTML: '<span class="vjs-control-text">' + this.localize('Stream Type') + '</span>' + this.localize('LIVE')
4895 }, {
4896 'aria-live': 'off'
4897 });
4898
4899 el.appendChild(this.contentEl_);
4900 return el;
4901 };
4902
4903 LiveDisplay.prototype.updateShowing = function updateShowing() {
4904 if (this.player().duration() === Infinity) {
4905 this.show();
4906 } else {
4907 this.hide();
4908 }
4909 };
4910
4911 return LiveDisplay;
4912})(_component2['default']);
4913
4914_component2['default'].registerComponent('LiveDisplay', LiveDisplay);
4915exports['default'] = LiveDisplay;
4916module.exports = exports['default'];
4917
4918},{"../component":67,"../utils/dom.js":132}],71:[function(_dereq_,module,exports){
4919/**
4920 * @file mute-toggle.js
4921 */
4922'use strict';
4923
4924exports.__esModule = true;
4925
4926function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
4927
4928function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4929
4930function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
4931
4932function _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; }
4933
4934var _button = _dereq_('../button');
4935
4936var _button2 = _interopRequireDefault(_button);
4937
4938var _component = _dereq_('../component');
4939
4940var _component2 = _interopRequireDefault(_component);
4941
4942var _utilsDomJs = _dereq_('../utils/dom.js');
4943
4944var Dom = _interopRequireWildcard(_utilsDomJs);
4945
4946/**
4947 * A button component for muting the audio
4948 *
4949 * @param {Player|Object} player
4950 * @param {Object=} options
4951 * @extends Button
4952 * @class MuteToggle
4953 */
4954
4955var MuteToggle = (function (_Button) {
4956 _inherits(MuteToggle, _Button);
4957
4958 function MuteToggle(player, options) {
4959 _classCallCheck(this, MuteToggle);
4960
4961 _Button.call(this, player, options);
4962
4963 this.on(player, 'volumechange', this.update);
4964
4965 // hide mute toggle if the current tech doesn't support volume control
4966 if (player.tech_ && player.tech_['featuresVolumeControl'] === false) {
4967 this.addClass('vjs-hidden');
4968 }
4969
4970 this.on(player, 'loadstart', function () {
4971 this.update(); // We need to update the button to account for a default muted state.
4972
4973 if (player.tech_['featuresVolumeControl'] === false) {
4974 this.addClass('vjs-hidden');
4975 } else {
4976 this.removeClass('vjs-hidden');
4977 }
4978 });
4979 }
4980
4981 /**
4982 * Allow sub components to stack CSS class names
4983 *
4984 * @return {String} The constructed class name
4985 * @method buildCSSClass
4986 */
4987
4988 MuteToggle.prototype.buildCSSClass = function buildCSSClass() {
4989 return 'vjs-mute-control ' + _Button.prototype.buildCSSClass.call(this);
4990 };
4991
4992 /**
4993 * Handle click on mute
4994 *
4995 * @method handleClick
4996 */
4997
4998 MuteToggle.prototype.handleClick = function handleClick() {
4999 this.player_.muted(this.player_.muted() ? false : true);
5000 };
5001
5002 /**
5003 * Update volume
5004 *
5005 * @method update
5006 */
5007
5008 MuteToggle.prototype.update = function update() {
5009 var vol = this.player_.volume(),
5010 level = 3;
5011
5012 if (vol === 0 || this.player_.muted()) {
5013 level = 0;
5014 } else if (vol < 0.33) {
5015 level = 1;
5016 } else if (vol < 0.67) {
5017 level = 2;
5018 }
5019
5020 // Don't rewrite the button text if the actual text doesn't change.
5021 // This causes unnecessary and confusing information for screen reader users.
5022 // This check is needed because this function gets called every time the volume level is changed.
5023 var toMute = this.player_.muted() ? 'Unmute' : 'Mute';
5024 if (this.controlText() !== toMute) {
5025 this.controlText(toMute);
5026 }
5027
5028 /* TODO improve muted icon classes */
5029 for (var i = 0; i < 4; i++) {
5030 Dom.removeElClass(this.el_, 'vjs-vol-' + i);
5031 }
5032 Dom.addElClass(this.el_, 'vjs-vol-' + level);
5033 };
5034
5035 return MuteToggle;
5036})(_button2['default']);
5037
5038MuteToggle.prototype.controlText_ = 'Mute';
5039
5040_component2['default'].registerComponent('MuteToggle', MuteToggle);
5041exports['default'] = MuteToggle;
5042module.exports = exports['default'];
5043
5044},{"../button":64,"../component":67,"../utils/dom.js":132}],72:[function(_dereq_,module,exports){
5045/**
5046 * @file play-toggle.js
5047 */
5048'use strict';
5049
5050exports.__esModule = true;
5051
5052function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5053
5054function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5055
5056function _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; }
5057
5058var _buttonJs = _dereq_('../button.js');
5059
5060var _buttonJs2 = _interopRequireDefault(_buttonJs);
5061
5062var _componentJs = _dereq_('../component.js');
5063
5064var _componentJs2 = _interopRequireDefault(_componentJs);
5065
5066/**
5067 * Button to toggle between play and pause
5068 *
5069 * @param {Player|Object} player
5070 * @param {Object=} options
5071 * @extends Button
5072 * @class PlayToggle
5073 */
5074
5075var PlayToggle = (function (_Button) {
5076 _inherits(PlayToggle, _Button);
5077
5078 function PlayToggle(player, options) {
5079 _classCallCheck(this, PlayToggle);
5080
5081 _Button.call(this, player, options);
5082
5083 this.on(player, 'play', this.handlePlay);
5084 this.on(player, 'pause', this.handlePause);
5085 }
5086
5087 /**
5088 * Allow sub components to stack CSS class names
5089 *
5090 * @return {String} The constructed class name
5091 * @method buildCSSClass
5092 */
5093
5094 PlayToggle.prototype.buildCSSClass = function buildCSSClass() {
5095 return 'vjs-play-control ' + _Button.prototype.buildCSSClass.call(this);
5096 };
5097
5098 /**
5099 * Handle click to toggle between play and pause
5100 *
5101 * @method handleClick
5102 */
5103
5104 PlayToggle.prototype.handleClick = function handleClick() {
5105 if (this.player_.paused()) {
5106 this.player_.play();
5107 } else {
5108 this.player_.pause();
5109 }
5110 };
5111
5112 /**
5113 * Add the vjs-playing class to the element so it can change appearance
5114 *
5115 * @method handlePlay
5116 */
5117
5118 PlayToggle.prototype.handlePlay = function handlePlay() {
5119 this.removeClass('vjs-paused');
5120 this.addClass('vjs-playing');
5121 this.controlText('Pause'); // change the button text to "Pause"
5122 };
5123
5124 /**
5125 * Add the vjs-paused class to the element so it can change appearance
5126 *
5127 * @method handlePause
5128 */
5129
5130 PlayToggle.prototype.handlePause = function handlePause() {
5131 this.removeClass('vjs-playing');
5132 this.addClass('vjs-paused');
5133 this.controlText('Play'); // change the button text to "Play"
5134 };
5135
5136 return PlayToggle;
5137})(_buttonJs2['default']);
5138
5139PlayToggle.prototype.controlText_ = 'Play';
5140
5141_componentJs2['default'].registerComponent('PlayToggle', PlayToggle);
5142exports['default'] = PlayToggle;
5143module.exports = exports['default'];
5144
5145},{"../button.js":64,"../component.js":67}],73:[function(_dereq_,module,exports){
5146/**
5147 * @file playback-rate-menu-button.js
5148 */
5149'use strict';
5150
5151exports.__esModule = true;
5152
5153function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5154
5155function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5156
5157function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5158
5159function _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; }
5160
5161var _menuMenuButtonJs = _dereq_('../../menu/menu-button.js');
5162
5163var _menuMenuButtonJs2 = _interopRequireDefault(_menuMenuButtonJs);
5164
5165var _menuMenuJs = _dereq_('../../menu/menu.js');
5166
5167var _menuMenuJs2 = _interopRequireDefault(_menuMenuJs);
5168
5169var _playbackRateMenuItemJs = _dereq_('./playback-rate-menu-item.js');
5170
5171var _playbackRateMenuItemJs2 = _interopRequireDefault(_playbackRateMenuItemJs);
5172
5173var _componentJs = _dereq_('../../component.js');
5174
5175var _componentJs2 = _interopRequireDefault(_componentJs);
5176
5177var _utilsDomJs = _dereq_('../../utils/dom.js');
5178
5179var Dom = _interopRequireWildcard(_utilsDomJs);
5180
5181/**
5182 * The component for controlling the playback rate
5183 *
5184 * @param {Player|Object} player
5185 * @param {Object=} options
5186 * @extends MenuButton
5187 * @class PlaybackRateMenuButton
5188 */
5189
5190var PlaybackRateMenuButton = (function (_MenuButton) {
5191 _inherits(PlaybackRateMenuButton, _MenuButton);
5192
5193 function PlaybackRateMenuButton(player, options) {
5194 _classCallCheck(this, PlaybackRateMenuButton);
5195
5196 _MenuButton.call(this, player, options);
5197
5198 this.updateVisibility();
5199 this.updateLabel();
5200
5201 this.on(player, 'loadstart', this.updateVisibility);
5202 this.on(player, 'ratechange', this.updateLabel);
5203 }
5204
5205 /**
5206 * Create the component's DOM element
5207 *
5208 * @return {Element}
5209 * @method createEl
5210 */
5211
5212 PlaybackRateMenuButton.prototype.createEl = function createEl() {
5213 var el = _MenuButton.prototype.createEl.call(this);
5214
5215 this.labelEl_ = Dom.createEl('div', {
5216 className: 'vjs-playback-rate-value',
5217 innerHTML: 1.0
5218 });
5219
5220 el.appendChild(this.labelEl_);
5221
5222 return el;
5223 };
5224
5225 /**
5226 * Allow sub components to stack CSS class names
5227 *
5228 * @return {String} The constructed class name
5229 * @method buildCSSClass
5230 */
5231
5232 PlaybackRateMenuButton.prototype.buildCSSClass = function buildCSSClass() {
5233 return 'vjs-playback-rate ' + _MenuButton.prototype.buildCSSClass.call(this);
5234 };
5235
5236 /**
5237 * Create the playback rate menu
5238 *
5239 * @return {Menu} Menu object populated with items
5240 * @method createMenu
5241 */
5242
5243 PlaybackRateMenuButton.prototype.createMenu = function createMenu() {
5244 var menu = new _menuMenuJs2['default'](this.player());
5245 var rates = this.playbackRates();
5246
5247 if (rates) {
5248 for (var i = rates.length - 1; i >= 0; i--) {
5249 menu.addChild(new _playbackRateMenuItemJs2['default'](this.player(), { 'rate': rates[i] + 'x' }));
5250 }
5251 }
5252
5253 return menu;
5254 };
5255
5256 /**
5257 * Updates ARIA accessibility attributes
5258 *
5259 * @method updateARIAAttributes
5260 */
5261
5262 PlaybackRateMenuButton.prototype.updateARIAAttributes = function updateARIAAttributes() {
5263 // Current playback rate
5264 this.el().setAttribute('aria-valuenow', this.player().playbackRate());
5265 };
5266
5267 /**
5268 * Handle menu item click
5269 *
5270 * @method handleClick
5271 */
5272
5273 PlaybackRateMenuButton.prototype.handleClick = function handleClick() {
5274 // select next rate option
5275 var currentRate = this.player().playbackRate();
5276 var rates = this.playbackRates();
5277
5278 // this will select first one if the last one currently selected
5279 var newRate = rates[0];
5280 for (var i = 0; i < rates.length; i++) {
5281 if (rates[i] > currentRate) {
5282 newRate = rates[i];
5283 break;
5284 }
5285 }
5286 this.player().playbackRate(newRate);
5287 };
5288
5289 /**
5290 * Get possible playback rates
5291 *
5292 * @return {Array} Possible playback rates
5293 * @method playbackRates
5294 */
5295
5296 PlaybackRateMenuButton.prototype.playbackRates = function playbackRates() {
5297 return this.options_['playbackRates'] || this.options_.playerOptions && this.options_.playerOptions['playbackRates'];
5298 };
5299
5300 /**
5301 * Get supported playback rates
5302 *
5303 * @return {Array} Supported playback rates
5304 * @method playbackRateSupported
5305 */
5306
5307 PlaybackRateMenuButton.prototype.playbackRateSupported = function playbackRateSupported() {
5308 return this.player().tech_ && this.player().tech_['featuresPlaybackRate'] && this.playbackRates() && this.playbackRates().length > 0;
5309 };
5310
5311 /**
5312 * Hide playback rate controls when they're no playback rate options to select
5313 *
5314 * @method updateVisibility
5315 */
5316
5317 PlaybackRateMenuButton.prototype.updateVisibility = function updateVisibility() {
5318 if (this.playbackRateSupported()) {
5319 this.removeClass('vjs-hidden');
5320 } else {
5321 this.addClass('vjs-hidden');
5322 }
5323 };
5324
5325 /**
5326 * Update button label when rate changed
5327 *
5328 * @method updateLabel
5329 */
5330
5331 PlaybackRateMenuButton.prototype.updateLabel = function updateLabel() {
5332 if (this.playbackRateSupported()) {
5333 this.labelEl_.innerHTML = this.player().playbackRate() + 'x';
5334 }
5335 };
5336
5337 return PlaybackRateMenuButton;
5338})(_menuMenuButtonJs2['default']);
5339
5340PlaybackRateMenuButton.prototype.controlText_ = 'Playback Rate';
5341
5342_componentJs2['default'].registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton);
5343exports['default'] = PlaybackRateMenuButton;
5344module.exports = exports['default'];
5345
5346},{"../../component.js":67,"../../menu/menu-button.js":104,"../../menu/menu.js":106,"../../utils/dom.js":132,"./playback-rate-menu-item.js":74}],74:[function(_dereq_,module,exports){
5347/**
5348 * @file playback-rate-menu-item.js
5349 */
5350'use strict';
5351
5352exports.__esModule = true;
5353
5354function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5355
5356function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5357
5358function _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; }
5359
5360var _menuMenuItemJs = _dereq_('../../menu/menu-item.js');
5361
5362var _menuMenuItemJs2 = _interopRequireDefault(_menuMenuItemJs);
5363
5364var _componentJs = _dereq_('../../component.js');
5365
5366var _componentJs2 = _interopRequireDefault(_componentJs);
5367
5368/**
5369 * The specific menu item type for selecting a playback rate
5370 *
5371 * @param {Player|Object} player
5372 * @param {Object=} options
5373 * @extends MenuItem
5374 * @class PlaybackRateMenuItem
5375 */
5376
5377var PlaybackRateMenuItem = (function (_MenuItem) {
5378 _inherits(PlaybackRateMenuItem, _MenuItem);
5379
5380 function PlaybackRateMenuItem(player, options) {
5381 _classCallCheck(this, PlaybackRateMenuItem);
5382
5383 var label = options['rate'];
5384 var rate = parseFloat(label, 10);
5385
5386 // Modify options for parent MenuItem class's init.
5387 options['label'] = label;
5388 options['selected'] = rate === 1;
5389 _MenuItem.call(this, player, options);
5390
5391 this.label = label;
5392 this.rate = rate;
5393
5394 this.on(player, 'ratechange', this.update);
5395 }
5396
5397 /**
5398 * Handle click on menu item
5399 *
5400 * @method handleClick
5401 */
5402
5403 PlaybackRateMenuItem.prototype.handleClick = function handleClick() {
5404 _MenuItem.prototype.handleClick.call(this);
5405 this.player().playbackRate(this.rate);
5406 };
5407
5408 /**
5409 * Update playback rate with selected rate
5410 *
5411 * @method update
5412 */
5413
5414 PlaybackRateMenuItem.prototype.update = function update() {
5415 this.selected(this.player().playbackRate() === this.rate);
5416 };
5417
5418 return PlaybackRateMenuItem;
5419})(_menuMenuItemJs2['default']);
5420
5421PlaybackRateMenuItem.prototype.contentElType = 'button';
5422
5423_componentJs2['default'].registerComponent('PlaybackRateMenuItem', PlaybackRateMenuItem);
5424exports['default'] = PlaybackRateMenuItem;
5425module.exports = exports['default'];
5426
5427},{"../../component.js":67,"../../menu/menu-item.js":105}],75:[function(_dereq_,module,exports){
5428/**
5429 * @file load-progress-bar.js
5430 */
5431'use strict';
5432
5433exports.__esModule = true;
5434
5435function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5436
5437function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5438
5439function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5440
5441function _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; }
5442
5443var _componentJs = _dereq_('../../component.js');
5444
5445var _componentJs2 = _interopRequireDefault(_componentJs);
5446
5447var _utilsDomJs = _dereq_('../../utils/dom.js');
5448
5449var Dom = _interopRequireWildcard(_utilsDomJs);
5450
5451/**
5452 * Shows load progress
5453 *
5454 * @param {Player|Object} player
5455 * @param {Object=} options
5456 * @extends Component
5457 * @class LoadProgressBar
5458 */
5459
5460var LoadProgressBar = (function (_Component) {
5461 _inherits(LoadProgressBar, _Component);
5462
5463 function LoadProgressBar(player, options) {
5464 _classCallCheck(this, LoadProgressBar);
5465
5466 _Component.call(this, player, options);
5467 this.on(player, 'progress', this.update);
5468 }
5469
5470 /**
5471 * Create the component's DOM element
5472 *
5473 * @return {Element}
5474 * @method createEl
5475 */
5476
5477 LoadProgressBar.prototype.createEl = function createEl() {
5478 return _Component.prototype.createEl.call(this, 'div', {
5479 className: 'vjs-load-progress',
5480 innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Loaded') + '</span>: 0%</span>'
5481 });
5482 };
5483
5484 /**
5485 * Update progress bar
5486 *
5487 * @method update
5488 */
5489
5490 LoadProgressBar.prototype.update = function update() {
5491 var buffered = this.player_.buffered();
5492 var duration = this.player_.duration();
5493 var bufferedEnd = this.player_.bufferedEnd();
5494 var children = this.el_.children;
5495
5496 // get the percent width of a time compared to the total end
5497 var percentify = function percentify(time, end) {
5498 var percent = time / end || 0; // no NaN
5499 return (percent >= 1 ? 1 : percent) * 100 + '%';
5500 };
5501
5502 // update the width of the progress bar
5503 this.el_.style.width = percentify(bufferedEnd, duration);
5504
5505 // add child elements to represent the individual buffered time ranges
5506 for (var i = 0; i < buffered.length; i++) {
5507 var start = buffered.start(i);
5508 var end = buffered.end(i);
5509 var part = children[i];
5510
5511 if (!part) {
5512 part = this.el_.appendChild(Dom.createEl());
5513 }
5514
5515 // set the percent based on the width of the progress bar (bufferedEnd)
5516 part.style.left = percentify(start, bufferedEnd);
5517 part.style.width = percentify(end - start, bufferedEnd);
5518 }
5519
5520 // remove unused buffered range elements
5521 for (var i = children.length; i > buffered.length; i--) {
5522 this.el_.removeChild(children[i - 1]);
5523 }
5524 };
5525
5526 return LoadProgressBar;
5527})(_componentJs2['default']);
5528
5529_componentJs2['default'].registerComponent('LoadProgressBar', LoadProgressBar);
5530exports['default'] = LoadProgressBar;
5531module.exports = exports['default'];
5532
5533},{"../../component.js":67,"../../utils/dom.js":132}],76:[function(_dereq_,module,exports){
5534/**
5535 * @file mouse-time-display.js
5536 */
5537'use strict';
5538
5539exports.__esModule = true;
5540
5541function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5542
5543function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5544
5545function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5546
5547function _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; }
5548
5549var _componentJs = _dereq_('../../component.js');
5550
5551var _componentJs2 = _interopRequireDefault(_componentJs);
5552
5553var _utilsDomJs = _dereq_('../../utils/dom.js');
5554
5555var Dom = _interopRequireWildcard(_utilsDomJs);
5556
5557var _utilsFnJs = _dereq_('../../utils/fn.js');
5558
5559var Fn = _interopRequireWildcard(_utilsFnJs);
5560
5561var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js');
5562
5563var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs);
5564
5565var _lodashCompatFunctionThrottle = _dereq_('lodash-compat/function/throttle');
5566
5567var _lodashCompatFunctionThrottle2 = _interopRequireDefault(_lodashCompatFunctionThrottle);
5568
5569/**
5570 * The Mouse Time Display component shows the time you will seek to
5571 * when hovering over the progress bar
5572 *
5573 * @param {Player|Object} player
5574 * @param {Object=} options
5575 * @extends Component
5576 * @class MouseTimeDisplay
5577 */
5578
5579var MouseTimeDisplay = (function (_Component) {
5580 _inherits(MouseTimeDisplay, _Component);
5581
5582 function MouseTimeDisplay(player, options) {
5583 var _this = this;
5584
5585 _classCallCheck(this, MouseTimeDisplay);
5586
5587 _Component.call(this, player, options);
5588
5589 this.update(0, 0);
5590
5591 player.on('ready', function () {
5592 _this.on(player.controlBar.progressControl.el(), 'mousemove', _lodashCompatFunctionThrottle2['default'](Fn.bind(_this, _this.handleMouseMove), 25));
5593 });
5594 }
5595
5596 /**
5597 * Create the component's DOM element
5598 *
5599 * @return {Element}
5600 * @method createEl
5601 */
5602
5603 MouseTimeDisplay.prototype.createEl = function createEl() {
5604 return _Component.prototype.createEl.call(this, 'div', {
5605 className: 'vjs-mouse-display'
5606 });
5607 };
5608
5609 MouseTimeDisplay.prototype.handleMouseMove = function handleMouseMove(event) {
5610 var duration = this.player_.duration();
5611 var newTime = this.calculateDistance(event) * duration;
5612 var position = event.pageX - Dom.findElPosition(this.el().parentNode).left;
5613
5614 this.update(newTime, position);
5615 };
5616
5617 MouseTimeDisplay.prototype.update = function update(newTime, position) {
5618 var time = _utilsFormatTimeJs2['default'](newTime, this.player_.duration());
5619
5620 this.el().style.left = position + 'px';
5621 this.el().setAttribute('data-current-time', time);
5622 };
5623
5624 MouseTimeDisplay.prototype.calculateDistance = function calculateDistance(event) {
5625 return Dom.getPointerPosition(this.el().parentNode, event).x;
5626 };
5627
5628 return MouseTimeDisplay;
5629})(_componentJs2['default']);
5630
5631_componentJs2['default'].registerComponent('MouseTimeDisplay', MouseTimeDisplay);
5632exports['default'] = MouseTimeDisplay;
5633module.exports = exports['default'];
5634
5635},{"../../component.js":67,"../../utils/dom.js":132,"../../utils/fn.js":134,"../../utils/format-time.js":135,"lodash-compat/function/throttle":7}],77:[function(_dereq_,module,exports){
5636/**
5637 * @file play-progress-bar.js
5638 */
5639'use strict';
5640
5641exports.__esModule = true;
5642
5643function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5644
5645function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5646
5647function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5648
5649function _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; }
5650
5651var _componentJs = _dereq_('../../component.js');
5652
5653var _componentJs2 = _interopRequireDefault(_componentJs);
5654
5655var _utilsFnJs = _dereq_('../../utils/fn.js');
5656
5657var Fn = _interopRequireWildcard(_utilsFnJs);
5658
5659var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js');
5660
5661var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs);
5662
5663/**
5664 * Shows play progress
5665 *
5666 * @param {Player|Object} player
5667 * @param {Object=} options
5668 * @extends Component
5669 * @class PlayProgressBar
5670 */
5671
5672var PlayProgressBar = (function (_Component) {
5673 _inherits(PlayProgressBar, _Component);
5674
5675 function PlayProgressBar(player, options) {
5676 _classCallCheck(this, PlayProgressBar);
5677
5678 _Component.call(this, player, options);
5679 this.updateDataAttr();
5680 this.on(player, 'timeupdate', this.updateDataAttr);
5681 player.ready(Fn.bind(this, this.updateDataAttr));
5682 }
5683
5684 /**
5685 * Create the component's DOM element
5686 *
5687 * @return {Element}
5688 * @method createEl
5689 */
5690
5691 PlayProgressBar.prototype.createEl = function createEl() {
5692 return _Component.prototype.createEl.call(this, 'div', {
5693 className: 'vjs-play-progress vjs-slider-bar',
5694 innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>'
5695 });
5696 };
5697
5698 PlayProgressBar.prototype.updateDataAttr = function updateDataAttr() {
5699 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
5700 this.el_.setAttribute('data-current-time', _utilsFormatTimeJs2['default'](time, this.player_.duration()));
5701 };
5702
5703 return PlayProgressBar;
5704})(_componentJs2['default']);
5705
5706_componentJs2['default'].registerComponent('PlayProgressBar', PlayProgressBar);
5707exports['default'] = PlayProgressBar;
5708module.exports = exports['default'];
5709
5710},{"../../component.js":67,"../../utils/fn.js":134,"../../utils/format-time.js":135}],78:[function(_dereq_,module,exports){
5711/**
5712 * @file progress-control.js
5713 */
5714'use strict';
5715
5716exports.__esModule = true;
5717
5718function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5719
5720function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5721
5722function _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; }
5723
5724var _componentJs = _dereq_('../../component.js');
5725
5726var _componentJs2 = _interopRequireDefault(_componentJs);
5727
5728var _seekBarJs = _dereq_('./seek-bar.js');
5729
5730var _seekBarJs2 = _interopRequireDefault(_seekBarJs);
5731
5732var _mouseTimeDisplayJs = _dereq_('./mouse-time-display.js');
5733
5734var _mouseTimeDisplayJs2 = _interopRequireDefault(_mouseTimeDisplayJs);
5735
5736/**
5737 * The Progress Control component contains the seek bar, load progress,
5738 * and play progress
5739 *
5740 * @param {Player|Object} player
5741 * @param {Object=} options
5742 * @extends Component
5743 * @class ProgressControl
5744 */
5745
5746var ProgressControl = (function (_Component) {
5747 _inherits(ProgressControl, _Component);
5748
5749 function ProgressControl() {
5750 _classCallCheck(this, ProgressControl);
5751
5752 _Component.apply(this, arguments);
5753 }
5754
5755 /**
5756 * Create the component's DOM element
5757 *
5758 * @return {Element}
5759 * @method createEl
5760 */
5761
5762 ProgressControl.prototype.createEl = function createEl() {
5763 return _Component.prototype.createEl.call(this, 'div', {
5764 className: 'vjs-progress-control vjs-control'
5765 });
5766 };
5767
5768 return ProgressControl;
5769})(_componentJs2['default']);
5770
5771ProgressControl.prototype.options_ = {
5772 children: ['seekBar']
5773};
5774
5775_componentJs2['default'].registerComponent('ProgressControl', ProgressControl);
5776exports['default'] = ProgressControl;
5777module.exports = exports['default'];
5778
5779},{"../../component.js":67,"./mouse-time-display.js":76,"./seek-bar.js":79}],79:[function(_dereq_,module,exports){
5780/**
5781 * @file seek-bar.js
5782 */
5783'use strict';
5784
5785exports.__esModule = true;
5786
5787function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5788
5789function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5790
5791function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5792
5793function _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; }
5794
5795var _sliderSliderJs = _dereq_('../../slider/slider.js');
5796
5797var _sliderSliderJs2 = _interopRequireDefault(_sliderSliderJs);
5798
5799var _componentJs = _dereq_('../../component.js');
5800
5801var _componentJs2 = _interopRequireDefault(_componentJs);
5802
5803var _loadProgressBarJs = _dereq_('./load-progress-bar.js');
5804
5805var _loadProgressBarJs2 = _interopRequireDefault(_loadProgressBarJs);
5806
5807var _playProgressBarJs = _dereq_('./play-progress-bar.js');
5808
5809var _playProgressBarJs2 = _interopRequireDefault(_playProgressBarJs);
5810
5811var _utilsFnJs = _dereq_('../../utils/fn.js');
5812
5813var Fn = _interopRequireWildcard(_utilsFnJs);
5814
5815var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js');
5816
5817var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs);
5818
5819var _objectAssign = _dereq_('object.assign');
5820
5821var _objectAssign2 = _interopRequireDefault(_objectAssign);
5822
5823/**
5824 * Seek Bar and holder for the progress bars
5825 *
5826 * @param {Player|Object} player
5827 * @param {Object=} options
5828 * @extends Slider
5829 * @class SeekBar
5830 */
5831
5832var SeekBar = (function (_Slider) {
5833 _inherits(SeekBar, _Slider);
5834
5835 function SeekBar(player, options) {
5836 _classCallCheck(this, SeekBar);
5837
5838 _Slider.call(this, player, options);
5839 this.on(player, 'timeupdate', this.updateARIAAttributes);
5840 player.ready(Fn.bind(this, this.updateARIAAttributes));
5841 }
5842
5843 /**
5844 * Create the component's DOM element
5845 *
5846 * @return {Element}
5847 * @method createEl
5848 */
5849
5850 SeekBar.prototype.createEl = function createEl() {
5851 return _Slider.prototype.createEl.call(this, 'div', {
5852 className: 'vjs-progress-holder'
5853 }, {
5854 'aria-label': 'video progress bar'
5855 });
5856 };
5857
5858 /**
5859 * Update ARIA accessibility attributes
5860 *
5861 * @method updateARIAAttributes
5862 */
5863
5864 SeekBar.prototype.updateARIAAttributes = function updateARIAAttributes() {
5865 // Allows for smooth scrubbing, when player can't keep up.
5866 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
5867 this.el_.setAttribute('aria-valuenow', (this.getPercent() * 100).toFixed(2)); // machine readable value of progress bar (percentage complete)
5868 this.el_.setAttribute('aria-valuetext', _utilsFormatTimeJs2['default'](time, this.player_.duration())); // human readable value of progress bar (time complete)
5869 };
5870
5871 /**
5872 * Get percentage of video played
5873 *
5874 * @return {Number} Percentage played
5875 * @method getPercent
5876 */
5877
5878 SeekBar.prototype.getPercent = function getPercent() {
5879 var percent = this.player_.currentTime() / this.player_.duration();
5880 return percent >= 1 ? 1 : percent;
5881 };
5882
5883 /**
5884 * Handle mouse down on seek bar
5885 *
5886 * @method handleMouseDown
5887 */
5888
5889 SeekBar.prototype.handleMouseDown = function handleMouseDown(event) {
5890 _Slider.prototype.handleMouseDown.call(this, event);
5891
5892 this.player_.scrubbing(true);
5893
5894 this.videoWasPlaying = !this.player_.paused();
5895 this.player_.pause();
5896 };
5897
5898 /**
5899 * Handle mouse move on seek bar
5900 *
5901 * @method handleMouseMove
5902 */
5903
5904 SeekBar.prototype.handleMouseMove = function handleMouseMove(event) {
5905 var newTime = this.calculateDistance(event) * this.player_.duration();
5906
5907 // Don't let video end while scrubbing.
5908 if (newTime === this.player_.duration()) {
5909 newTime = newTime - 0.1;
5910 }
5911
5912 // Set new time (tell player to seek to new time)
5913 this.player_.currentTime(newTime);
5914 };
5915
5916 /**
5917 * Handle mouse up on seek bar
5918 *
5919 * @method handleMouseUp
5920 */
5921
5922 SeekBar.prototype.handleMouseUp = function handleMouseUp(event) {
5923 _Slider.prototype.handleMouseUp.call(this, event);
5924
5925 this.player_.scrubbing(false);
5926 if (this.videoWasPlaying) {
5927 this.player_.play();
5928 }
5929 };
5930
5931 /**
5932 * Move more quickly fast forward for keyboard-only users
5933 *
5934 * @method stepForward
5935 */
5936
5937 SeekBar.prototype.stepForward = function stepForward() {
5938 this.player_.currentTime(this.player_.currentTime() + 5); // more quickly fast forward for keyboard-only users
5939 };
5940
5941 /**
5942 * Move more quickly rewind for keyboard-only users
5943 *
5944 * @method stepBack
5945 */
5946
5947 SeekBar.prototype.stepBack = function stepBack() {
5948 this.player_.currentTime(this.player_.currentTime() - 5); // more quickly rewind for keyboard-only users
5949 };
5950
5951 return SeekBar;
5952})(_sliderSliderJs2['default']);
5953
5954SeekBar.prototype.options_ = {
5955 children: ['loadProgressBar', 'mouseTimeDisplay', 'playProgressBar'],
5956 'barName': 'playProgressBar'
5957};
5958
5959SeekBar.prototype.playerEvent = 'timeupdate';
5960
5961_componentJs2['default'].registerComponent('SeekBar', SeekBar);
5962exports['default'] = SeekBar;
5963module.exports = exports['default'];
5964
5965},{"../../component.js":67,"../../slider/slider.js":114,"../../utils/fn.js":134,"../../utils/format-time.js":135,"./load-progress-bar.js":75,"./play-progress-bar.js":77,"object.assign":45}],80:[function(_dereq_,module,exports){
5966/**
5967 * @file custom-control-spacer.js
5968 */
5969'use strict';
5970
5971exports.__esModule = true;
5972
5973function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5974
5975function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
5976
5977function _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; }
5978
5979var _spacerJs = _dereq_('./spacer.js');
5980
5981var _spacerJs2 = _interopRequireDefault(_spacerJs);
5982
5983var _componentJs = _dereq_('../../component.js');
5984
5985var _componentJs2 = _interopRequireDefault(_componentJs);
5986
5987/**
5988 * Spacer specifically meant to be used as an insertion point for new plugins, etc.
5989 *
5990 * @extends Spacer
5991 * @class CustomControlSpacer
5992 */
5993
5994var CustomControlSpacer = (function (_Spacer) {
5995 _inherits(CustomControlSpacer, _Spacer);
5996
5997 function CustomControlSpacer() {
5998 _classCallCheck(this, CustomControlSpacer);
5999
6000 _Spacer.apply(this, arguments);
6001 }
6002
6003 /**
6004 * Allow sub components to stack CSS class names
6005 *
6006 * @return {String} The constructed class name
6007 * @method buildCSSClass
6008 */
6009
6010 CustomControlSpacer.prototype.buildCSSClass = function buildCSSClass() {
6011 return 'vjs-custom-control-spacer ' + _Spacer.prototype.buildCSSClass.call(this);
6012 };
6013
6014 /**
6015 * Create the component's DOM element
6016 *
6017 * @return {Element}
6018 * @method createEl
6019 */
6020
6021 CustomControlSpacer.prototype.createEl = function createEl() {
6022 var el = _Spacer.prototype.createEl.call(this, {
6023 className: this.buildCSSClass()
6024 });
6025
6026 // No-flex/table-cell mode requires there be some content
6027 // in the cell to fill the remaining space of the table.
6028 el.innerHTML = '&nbsp;';
6029 return el;
6030 };
6031
6032 return CustomControlSpacer;
6033})(_spacerJs2['default']);
6034
6035_componentJs2['default'].registerComponent('CustomControlSpacer', CustomControlSpacer);
6036exports['default'] = CustomControlSpacer;
6037module.exports = exports['default'];
6038
6039},{"../../component.js":67,"./spacer.js":81}],81:[function(_dereq_,module,exports){
6040/**
6041 * @file spacer.js
6042 */
6043'use strict';
6044
6045exports.__esModule = true;
6046
6047function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6048
6049function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6050
6051function _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; }
6052
6053var _componentJs = _dereq_('../../component.js');
6054
6055var _componentJs2 = _interopRequireDefault(_componentJs);
6056
6057/**
6058 * Just an empty spacer element that can be used as an append point for plugins, etc.
6059 * Also can be used to create space between elements when necessary.
6060 *
6061 * @extends Component
6062 * @class Spacer
6063 */
6064
6065var Spacer = (function (_Component) {
6066 _inherits(Spacer, _Component);
6067
6068 function Spacer() {
6069 _classCallCheck(this, Spacer);
6070
6071 _Component.apply(this, arguments);
6072 }
6073
6074 /**
6075 * Allow sub components to stack CSS class names
6076 *
6077 * @return {String} The constructed class name
6078 * @method buildCSSClass
6079 */
6080
6081 Spacer.prototype.buildCSSClass = function buildCSSClass() {
6082 return 'vjs-spacer ' + _Component.prototype.buildCSSClass.call(this);
6083 };
6084
6085 /**
6086 * Create the component's DOM element
6087 *
6088 * @return {Element}
6089 * @method createEl
6090 */
6091
6092 Spacer.prototype.createEl = function createEl() {
6093 return _Component.prototype.createEl.call(this, 'div', {
6094 className: this.buildCSSClass()
6095 });
6096 };
6097
6098 return Spacer;
6099})(_componentJs2['default']);
6100
6101_componentJs2['default'].registerComponent('Spacer', Spacer);
6102
6103exports['default'] = Spacer;
6104module.exports = exports['default'];
6105
6106},{"../../component.js":67}],82:[function(_dereq_,module,exports){
6107/**
6108 * @file caption-settings-menu-item.js
6109 */
6110'use strict';
6111
6112exports.__esModule = true;
6113
6114function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6115
6116function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6117
6118function _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; }
6119
6120var _textTrackMenuItemJs = _dereq_('./text-track-menu-item.js');
6121
6122var _textTrackMenuItemJs2 = _interopRequireDefault(_textTrackMenuItemJs);
6123
6124var _componentJs = _dereq_('../../component.js');
6125
6126var _componentJs2 = _interopRequireDefault(_componentJs);
6127
6128/**
6129 * The menu item for caption track settings menu
6130 *
6131 * @param {Player|Object} player
6132 * @param {Object=} options
6133 * @extends TextTrackMenuItem
6134 * @class CaptionSettingsMenuItem
6135 */
6136
6137var CaptionSettingsMenuItem = (function (_TextTrackMenuItem) {
6138 _inherits(CaptionSettingsMenuItem, _TextTrackMenuItem);
6139
6140 function CaptionSettingsMenuItem(player, options) {
6141 _classCallCheck(this, CaptionSettingsMenuItem);
6142
6143 options['track'] = {
6144 'kind': options['kind'],
6145 'player': player,
6146 'label': options['kind'] + ' settings',
6147 'selectable': false,
6148 'default': false,
6149 mode: 'disabled'
6150 };
6151
6152 // CaptionSettingsMenuItem has no concept of 'selected'
6153 options['selectable'] = false;
6154
6155 _TextTrackMenuItem.call(this, player, options);
6156 this.addClass('vjs-texttrack-settings');
6157 this.controlText(', opens ' + options['kind'] + ' settings dialog');
6158 }
6159
6160 /**
6161 * Handle click on menu item
6162 *
6163 * @method handleClick
6164 */
6165
6166 CaptionSettingsMenuItem.prototype.handleClick = function handleClick() {
6167 this.player().getChild('textTrackSettings').show();
6168 this.player().getChild('textTrackSettings').el_.focus();
6169 };
6170
6171 return CaptionSettingsMenuItem;
6172})(_textTrackMenuItemJs2['default']);
6173
6174_componentJs2['default'].registerComponent('CaptionSettingsMenuItem', CaptionSettingsMenuItem);
6175exports['default'] = CaptionSettingsMenuItem;
6176module.exports = exports['default'];
6177
6178},{"../../component.js":67,"./text-track-menu-item.js":89}],83:[function(_dereq_,module,exports){
6179/**
6180 * @file captions-button.js
6181 */
6182'use strict';
6183
6184exports.__esModule = true;
6185
6186function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6187
6188function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6189
6190function _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; }
6191
6192var _textTrackButtonJs = _dereq_('./text-track-button.js');
6193
6194var _textTrackButtonJs2 = _interopRequireDefault(_textTrackButtonJs);
6195
6196var _componentJs = _dereq_('../../component.js');
6197
6198var _componentJs2 = _interopRequireDefault(_componentJs);
6199
6200var _captionSettingsMenuItemJs = _dereq_('./caption-settings-menu-item.js');
6201
6202var _captionSettingsMenuItemJs2 = _interopRequireDefault(_captionSettingsMenuItemJs);
6203
6204/**
6205 * The button component for toggling and selecting captions
6206 *
6207 * @param {Object} player Player object
6208 * @param {Object=} options Object of option names and values
6209 * @param {Function=} ready Ready callback function
6210 * @extends TextTrackButton
6211 * @class CaptionsButton
6212 */
6213
6214var CaptionsButton = (function (_TextTrackButton) {
6215 _inherits(CaptionsButton, _TextTrackButton);
6216
6217 function CaptionsButton(player, options, ready) {
6218 _classCallCheck(this, CaptionsButton);
6219
6220 _TextTrackButton.call(this, player, options, ready);
6221 this.el_.setAttribute('aria-label', 'Captions Menu');
6222 }
6223
6224 /**
6225 * Allow sub components to stack CSS class names
6226 *
6227 * @return {String} The constructed class name
6228 * @method buildCSSClass
6229 */
6230
6231 CaptionsButton.prototype.buildCSSClass = function buildCSSClass() {
6232 return 'vjs-captions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
6233 };
6234
6235 /**
6236 * Update caption menu items
6237 *
6238 * @method update
6239 */
6240
6241 CaptionsButton.prototype.update = function update() {
6242 var threshold = 2;
6243 _TextTrackButton.prototype.update.call(this);
6244
6245 // if native, then threshold is 1 because no settings button
6246 if (this.player().tech_ && this.player().tech_['featuresNativeTextTracks']) {
6247 threshold = 1;
6248 }
6249
6250 if (this.items && this.items.length > threshold) {
6251 this.show();
6252 } else {
6253 this.hide();
6254 }
6255 };
6256
6257 /**
6258 * Create caption menu items
6259 *
6260 * @return {Array} Array of menu items
6261 * @method createItems
6262 */
6263
6264 CaptionsButton.prototype.createItems = function createItems() {
6265 var items = [];
6266
6267 if (!(this.player().tech_ && this.player().tech_['featuresNativeTextTracks'])) {
6268 items.push(new _captionSettingsMenuItemJs2['default'](this.player_, { 'kind': this.kind_ }));
6269 }
6270
6271 return _TextTrackButton.prototype.createItems.call(this, items);
6272 };
6273
6274 return CaptionsButton;
6275})(_textTrackButtonJs2['default']);
6276
6277CaptionsButton.prototype.kind_ = 'captions';
6278CaptionsButton.prototype.controlText_ = 'Captions';
6279
6280_componentJs2['default'].registerComponent('CaptionsButton', CaptionsButton);
6281exports['default'] = CaptionsButton;
6282module.exports = exports['default'];
6283
6284},{"../../component.js":67,"./caption-settings-menu-item.js":82,"./text-track-button.js":88}],84:[function(_dereq_,module,exports){
6285/**
6286 * @file chapters-button.js
6287 */
6288'use strict';
6289
6290exports.__esModule = true;
6291
6292function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6293
6294function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6295
6296function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6297
6298function _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; }
6299
6300var _textTrackButtonJs = _dereq_('./text-track-button.js');
6301
6302var _textTrackButtonJs2 = _interopRequireDefault(_textTrackButtonJs);
6303
6304var _componentJs = _dereq_('../../component.js');
6305
6306var _componentJs2 = _interopRequireDefault(_componentJs);
6307
6308var _textTrackMenuItemJs = _dereq_('./text-track-menu-item.js');
6309
6310var _textTrackMenuItemJs2 = _interopRequireDefault(_textTrackMenuItemJs);
6311
6312var _chaptersTrackMenuItemJs = _dereq_('./chapters-track-menu-item.js');
6313
6314var _chaptersTrackMenuItemJs2 = _interopRequireDefault(_chaptersTrackMenuItemJs);
6315
6316var _menuMenuJs = _dereq_('../../menu/menu.js');
6317
6318var _menuMenuJs2 = _interopRequireDefault(_menuMenuJs);
6319
6320var _utilsDomJs = _dereq_('../../utils/dom.js');
6321
6322var Dom = _interopRequireWildcard(_utilsDomJs);
6323
6324var _utilsFnJs = _dereq_('../../utils/fn.js');
6325
6326var Fn = _interopRequireWildcard(_utilsFnJs);
6327
6328var _utilsToTitleCaseJs = _dereq_('../../utils/to-title-case.js');
6329
6330var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs);
6331
6332var _globalWindow = _dereq_('global/window');
6333
6334var _globalWindow2 = _interopRequireDefault(_globalWindow);
6335
6336/**
6337 * The button component for toggling and selecting chapters
6338 * Chapters act much differently than other text tracks
6339 * Cues are navigation vs. other tracks of alternative languages
6340 *
6341 * @param {Object} player Player object
6342 * @param {Object=} options Object of option names and values
6343 * @param {Function=} ready Ready callback function
6344 * @extends TextTrackButton
6345 * @class ChaptersButton
6346 */
6347
6348var ChaptersButton = (function (_TextTrackButton) {
6349 _inherits(ChaptersButton, _TextTrackButton);
6350
6351 function ChaptersButton(player, options, ready) {
6352 _classCallCheck(this, ChaptersButton);
6353
6354 _TextTrackButton.call(this, player, options, ready);
6355 this.el_.setAttribute('aria-label', 'Chapters Menu');
6356 }
6357
6358 /**
6359 * Allow sub components to stack CSS class names
6360 *
6361 * @return {String} The constructed class name
6362 * @method buildCSSClass
6363 */
6364
6365 ChaptersButton.prototype.buildCSSClass = function buildCSSClass() {
6366 return 'vjs-chapters-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
6367 };
6368
6369 /**
6370 * Create a menu item for each text track
6371 *
6372 * @return {Array} Array of menu items
6373 * @method createItems
6374 */
6375
6376 ChaptersButton.prototype.createItems = function createItems() {
6377 var items = [];
6378
6379 var tracks = this.player_.textTracks();
6380
6381 if (!tracks) {
6382 return items;
6383 }
6384
6385 for (var i = 0; i < tracks.length; i++) {
6386 var track = tracks[i];
6387 if (track['kind'] === this.kind_) {
6388 items.push(new _textTrackMenuItemJs2['default'](this.player_, {
6389 'track': track
6390 }));
6391 }
6392 }
6393
6394 return items;
6395 };
6396
6397 /**
6398 * Create menu from chapter buttons
6399 *
6400 * @return {Menu} Menu of chapter buttons
6401 * @method createMenu
6402 */
6403
6404 ChaptersButton.prototype.createMenu = function createMenu() {
6405 var _this = this;
6406
6407 var tracks = this.player_.textTracks() || [];
6408 var chaptersTrack = undefined;
6409 var items = this.items = [];
6410
6411 for (var i = 0, _length = tracks.length; i < _length; i++) {
6412 var track = tracks[i];
6413
6414 if (track['kind'] === this.kind_) {
6415 chaptersTrack = track;
6416
6417 break;
6418 }
6419 }
6420
6421 var menu = this.menu;
6422 if (menu === undefined) {
6423 menu = new _menuMenuJs2['default'](this.player_);
6424 var title = Dom.createEl('li', {
6425 className: 'vjs-menu-title',
6426 innerHTML: _utilsToTitleCaseJs2['default'](this.kind_),
6427 tabIndex: -1
6428 });
6429 menu.children_.unshift(title);
6430 Dom.insertElFirst(title, menu.contentEl());
6431 }
6432
6433 if (chaptersTrack && chaptersTrack.cues == null) {
6434 chaptersTrack['mode'] = 'hidden';
6435
6436 var remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(chaptersTrack);
6437
6438 if (remoteTextTrackEl) {
6439 remoteTextTrackEl.addEventListener('load', function (event) {
6440 return _this.update();
6441 });
6442 }
6443 }
6444
6445 if (chaptersTrack && chaptersTrack.cues && chaptersTrack.cues.length > 0) {
6446 var cues = chaptersTrack['cues'],
6447 cue = undefined;
6448
6449 for (var i = 0, l = cues.length; i < l; i++) {
6450 cue = cues[i];
6451
6452 var mi = new _chaptersTrackMenuItemJs2['default'](this.player_, {
6453 'track': chaptersTrack,
6454 'cue': cue
6455 });
6456
6457 items.push(mi);
6458
6459 menu.addChild(mi);
6460 }
6461
6462 this.addChild(menu);
6463 }
6464
6465 if (this.items.length > 0) {
6466 this.show();
6467 }
6468
6469 return menu;
6470 };
6471
6472 return ChaptersButton;
6473})(_textTrackButtonJs2['default']);
6474
6475ChaptersButton.prototype.kind_ = 'chapters';
6476ChaptersButton.prototype.controlText_ = 'Chapters';
6477
6478_componentJs2['default'].registerComponent('ChaptersButton', ChaptersButton);
6479exports['default'] = ChaptersButton;
6480module.exports = exports['default'];
6481
6482},{"../../component.js":67,"../../menu/menu.js":106,"../../utils/dom.js":132,"../../utils/fn.js":134,"../../utils/to-title-case.js":141,"./chapters-track-menu-item.js":85,"./text-track-button.js":88,"./text-track-menu-item.js":89,"global/window":2}],85:[function(_dereq_,module,exports){
6483/**
6484 * @file chapters-track-menu-item.js
6485 */
6486'use strict';
6487
6488exports.__esModule = true;
6489
6490function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6491
6492function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6493
6494function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6495
6496function _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; }
6497
6498var _menuMenuItemJs = _dereq_('../../menu/menu-item.js');
6499
6500var _menuMenuItemJs2 = _interopRequireDefault(_menuMenuItemJs);
6501
6502var _componentJs = _dereq_('../../component.js');
6503
6504var _componentJs2 = _interopRequireDefault(_componentJs);
6505
6506var _utilsFnJs = _dereq_('../../utils/fn.js');
6507
6508var Fn = _interopRequireWildcard(_utilsFnJs);
6509
6510/**
6511 * The chapter track menu item
6512 *
6513 * @param {Player|Object} player
6514 * @param {Object=} options
6515 * @extends MenuItem
6516 * @class ChaptersTrackMenuItem
6517 */
6518
6519var ChaptersTrackMenuItem = (function (_MenuItem) {
6520 _inherits(ChaptersTrackMenuItem, _MenuItem);
6521
6522 function ChaptersTrackMenuItem(player, options) {
6523 _classCallCheck(this, ChaptersTrackMenuItem);
6524
6525 var track = options['track'];
6526 var cue = options['cue'];
6527 var currentTime = player.currentTime();
6528
6529 // Modify options for parent MenuItem class's init.
6530 options['label'] = cue.text;
6531 options['selected'] = cue['startTime'] <= currentTime && currentTime < cue['endTime'];
6532 _MenuItem.call(this, player, options);
6533
6534 this.track = track;
6535 this.cue = cue;
6536 track.addEventListener('cuechange', Fn.bind(this, this.update));
6537 }
6538
6539 /**
6540 * Handle click on menu item
6541 *
6542 * @method handleClick
6543 */
6544
6545 ChaptersTrackMenuItem.prototype.handleClick = function handleClick() {
6546 _MenuItem.prototype.handleClick.call(this);
6547 this.player_.currentTime(this.cue.startTime);
6548 this.update(this.cue.startTime);
6549 };
6550
6551 /**
6552 * Update chapter menu item
6553 *
6554 * @method update
6555 */
6556
6557 ChaptersTrackMenuItem.prototype.update = function update() {
6558 var cue = this.cue;
6559 var currentTime = this.player_.currentTime();
6560
6561 // vjs.log(currentTime, cue.startTime);
6562 this.selected(cue['startTime'] <= currentTime && currentTime < cue['endTime']);
6563 };
6564
6565 return ChaptersTrackMenuItem;
6566})(_menuMenuItemJs2['default']);
6567
6568_componentJs2['default'].registerComponent('ChaptersTrackMenuItem', ChaptersTrackMenuItem);
6569exports['default'] = ChaptersTrackMenuItem;
6570module.exports = exports['default'];
6571
6572},{"../../component.js":67,"../../menu/menu-item.js":105,"../../utils/fn.js":134}],86:[function(_dereq_,module,exports){
6573/**
6574 * @file off-text-track-menu-item.js
6575 */
6576'use strict';
6577
6578exports.__esModule = true;
6579
6580function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6581
6582function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6583
6584function _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; }
6585
6586var _textTrackMenuItemJs = _dereq_('./text-track-menu-item.js');
6587
6588var _textTrackMenuItemJs2 = _interopRequireDefault(_textTrackMenuItemJs);
6589
6590var _componentJs = _dereq_('../../component.js');
6591
6592var _componentJs2 = _interopRequireDefault(_componentJs);
6593
6594/**
6595 * A special menu item for turning of a specific type of text track
6596 *
6597 * @param {Player|Object} player
6598 * @param {Object=} options
6599 * @extends TextTrackMenuItem
6600 * @class OffTextTrackMenuItem
6601 */
6602
6603var OffTextTrackMenuItem = (function (_TextTrackMenuItem) {
6604 _inherits(OffTextTrackMenuItem, _TextTrackMenuItem);
6605
6606 function OffTextTrackMenuItem(player, options) {
6607 _classCallCheck(this, OffTextTrackMenuItem);
6608
6609 // Create pseudo track info
6610 // Requires options['kind']
6611 options['track'] = {
6612 'kind': options['kind'],
6613 'player': player,
6614 'label': options['kind'] + ' off',
6615 'default': false,
6616 'mode': 'disabled'
6617 };
6618
6619 // MenuItem is selectable
6620 options['selectable'] = true;
6621
6622 _TextTrackMenuItem.call(this, player, options);
6623 this.selected(true);
6624 }
6625
6626 /**
6627 * Handle text track change
6628 *
6629 * @param {Object} event Event object
6630 * @method handleTracksChange
6631 */
6632
6633 OffTextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) {
6634 var tracks = this.player().textTracks();
6635 var selected = true;
6636
6637 for (var i = 0, l = tracks.length; i < l; i++) {
6638 var track = tracks[i];
6639 if (track['kind'] === this.track['kind'] && track['mode'] === 'showing') {
6640 selected = false;
6641 break;
6642 }
6643 }
6644
6645 this.selected(selected);
6646 };
6647
6648 return OffTextTrackMenuItem;
6649})(_textTrackMenuItemJs2['default']);
6650
6651_componentJs2['default'].registerComponent('OffTextTrackMenuItem', OffTextTrackMenuItem);
6652exports['default'] = OffTextTrackMenuItem;
6653module.exports = exports['default'];
6654
6655},{"../../component.js":67,"./text-track-menu-item.js":89}],87:[function(_dereq_,module,exports){
6656/**
6657 * @file subtitles-button.js
6658 */
6659'use strict';
6660
6661exports.__esModule = true;
6662
6663function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6664
6665function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6666
6667function _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; }
6668
6669var _textTrackButtonJs = _dereq_('./text-track-button.js');
6670
6671var _textTrackButtonJs2 = _interopRequireDefault(_textTrackButtonJs);
6672
6673var _componentJs = _dereq_('../../component.js');
6674
6675var _componentJs2 = _interopRequireDefault(_componentJs);
6676
6677/**
6678 * The button component for toggling and selecting subtitles
6679 *
6680 * @param {Object} player Player object
6681 * @param {Object=} options Object of option names and values
6682 * @param {Function=} ready Ready callback function
6683 * @extends TextTrackButton
6684 * @class SubtitlesButton
6685 */
6686
6687var SubtitlesButton = (function (_TextTrackButton) {
6688 _inherits(SubtitlesButton, _TextTrackButton);
6689
6690 function SubtitlesButton(player, options, ready) {
6691 _classCallCheck(this, SubtitlesButton);
6692
6693 _TextTrackButton.call(this, player, options, ready);
6694 this.el_.setAttribute('aria-label', 'Subtitles Menu');
6695 }
6696
6697 /**
6698 * Allow sub components to stack CSS class names
6699 *
6700 * @return {String} The constructed class name
6701 * @method buildCSSClass
6702 */
6703
6704 SubtitlesButton.prototype.buildCSSClass = function buildCSSClass() {
6705 return 'vjs-subtitles-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
6706 };
6707
6708 return SubtitlesButton;
6709})(_textTrackButtonJs2['default']);
6710
6711SubtitlesButton.prototype.kind_ = 'subtitles';
6712SubtitlesButton.prototype.controlText_ = 'Subtitles';
6713
6714_componentJs2['default'].registerComponent('SubtitlesButton', SubtitlesButton);
6715exports['default'] = SubtitlesButton;
6716module.exports = exports['default'];
6717
6718},{"../../component.js":67,"./text-track-button.js":88}],88:[function(_dereq_,module,exports){
6719/**
6720 * @file text-track-button.js
6721 */
6722'use strict';
6723
6724exports.__esModule = true;
6725
6726function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6727
6728function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6729
6730function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6731
6732function _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; }
6733
6734var _menuMenuButtonJs = _dereq_('../../menu/menu-button.js');
6735
6736var _menuMenuButtonJs2 = _interopRequireDefault(_menuMenuButtonJs);
6737
6738var _componentJs = _dereq_('../../component.js');
6739
6740var _componentJs2 = _interopRequireDefault(_componentJs);
6741
6742var _utilsFnJs = _dereq_('../../utils/fn.js');
6743
6744var Fn = _interopRequireWildcard(_utilsFnJs);
6745
6746var _textTrackMenuItemJs = _dereq_('./text-track-menu-item.js');
6747
6748var _textTrackMenuItemJs2 = _interopRequireDefault(_textTrackMenuItemJs);
6749
6750var _offTextTrackMenuItemJs = _dereq_('./off-text-track-menu-item.js');
6751
6752var _offTextTrackMenuItemJs2 = _interopRequireDefault(_offTextTrackMenuItemJs);
6753
6754/**
6755 * The base class for buttons that toggle specific text track types (e.g. subtitles)
6756 *
6757 * @param {Player|Object} player
6758 * @param {Object=} options
6759 * @extends MenuButton
6760 * @class TextTrackButton
6761 */
6762
6763var TextTrackButton = (function (_MenuButton) {
6764 _inherits(TextTrackButton, _MenuButton);
6765
6766 function TextTrackButton(player, options) {
6767 _classCallCheck(this, TextTrackButton);
6768
6769 _MenuButton.call(this, player, options);
6770
6771 var tracks = this.player_.textTracks();
6772
6773 if (this.items.length <= 1) {
6774 this.hide();
6775 }
6776
6777 if (!tracks) {
6778 return;
6779 }
6780
6781 var updateHandler = Fn.bind(this, this.update);
6782 tracks.addEventListener('removetrack', updateHandler);
6783 tracks.addEventListener('addtrack', updateHandler);
6784
6785 this.player_.on('dispose', function () {
6786 tracks.removeEventListener('removetrack', updateHandler);
6787 tracks.removeEventListener('addtrack', updateHandler);
6788 });
6789 }
6790
6791 // Create a menu item for each text track
6792
6793 TextTrackButton.prototype.createItems = function createItems() {
6794 var items = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
6795
6796 // Add an OFF menu item to turn all tracks off
6797 items.push(new _offTextTrackMenuItemJs2['default'](this.player_, { 'kind': this.kind_ }));
6798
6799 var tracks = this.player_.textTracks();
6800
6801 if (!tracks) {
6802 return items;
6803 }
6804
6805 for (var i = 0; i < tracks.length; i++) {
6806 var track = tracks[i];
6807
6808 // only add tracks that are of the appropriate kind and have a label
6809 if (track['kind'] === this.kind_) {
6810 items.push(new _textTrackMenuItemJs2['default'](this.player_, {
6811 // MenuItem is selectable
6812 'selectable': true,
6813 'track': track
6814 }));
6815 }
6816 }
6817
6818 return items;
6819 };
6820
6821 return TextTrackButton;
6822})(_menuMenuButtonJs2['default']);
6823
6824_componentJs2['default'].registerComponent('TextTrackButton', TextTrackButton);
6825exports['default'] = TextTrackButton;
6826module.exports = exports['default'];
6827
6828},{"../../component.js":67,"../../menu/menu-button.js":104,"../../utils/fn.js":134,"./off-text-track-menu-item.js":86,"./text-track-menu-item.js":89}],89:[function(_dereq_,module,exports){
6829/**
6830 * @file text-track-menu-item.js
6831 */
6832'use strict';
6833
6834exports.__esModule = true;
6835
6836function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6837
6838function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6839
6840function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6841
6842function _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; }
6843
6844var _menuMenuItemJs = _dereq_('../../menu/menu-item.js');
6845
6846var _menuMenuItemJs2 = _interopRequireDefault(_menuMenuItemJs);
6847
6848var _componentJs = _dereq_('../../component.js');
6849
6850var _componentJs2 = _interopRequireDefault(_componentJs);
6851
6852var _utilsFnJs = _dereq_('../../utils/fn.js');
6853
6854var Fn = _interopRequireWildcard(_utilsFnJs);
6855
6856var _globalWindow = _dereq_('global/window');
6857
6858var _globalWindow2 = _interopRequireDefault(_globalWindow);
6859
6860var _globalDocument = _dereq_('global/document');
6861
6862var _globalDocument2 = _interopRequireDefault(_globalDocument);
6863
6864/**
6865 * The specific menu item type for selecting a language within a text track kind
6866 *
6867 * @param {Player|Object} player
6868 * @param {Object=} options
6869 * @extends MenuItem
6870 * @class TextTrackMenuItem
6871 */
6872
6873var TextTrackMenuItem = (function (_MenuItem) {
6874 _inherits(TextTrackMenuItem, _MenuItem);
6875
6876 function TextTrackMenuItem(player, options) {
6877 var _this = this;
6878
6879 _classCallCheck(this, TextTrackMenuItem);
6880
6881 var track = options['track'];
6882 var tracks = player.textTracks();
6883
6884 // Modify options for parent MenuItem class's init.
6885 options['label'] = track['label'] || track['language'] || 'Unknown';
6886 options['selected'] = track['default'] || track['mode'] === 'showing';
6887
6888 _MenuItem.call(this, player, options);
6889
6890 this.track = track;
6891
6892 if (tracks) {
6893 (function () {
6894 var changeHandler = Fn.bind(_this, _this.handleTracksChange);
6895
6896 tracks.addEventListener('change', changeHandler);
6897 _this.on('dispose', function () {
6898 tracks.removeEventListener('change', changeHandler);
6899 });
6900 })();
6901 }
6902
6903 // iOS7 doesn't dispatch change events to TextTrackLists when an
6904 // associated track's mode changes. Without something like
6905 // Object.observe() (also not present on iOS7), it's not
6906 // possible to detect changes to the mode attribute and polyfill
6907 // the change event. As a poor substitute, we manually dispatch
6908 // change events whenever the controls modify the mode.
6909 if (tracks && tracks.onchange === undefined) {
6910 (function () {
6911 var event = undefined;
6912
6913 _this.on(['tap', 'click'], function () {
6914 if (typeof _globalWindow2['default'].Event !== 'object') {
6915 // Android 2.3 throws an Illegal Constructor error for window.Event
6916 try {
6917 event = new _globalWindow2['default'].Event('change');
6918 } catch (err) {}
6919 }
6920
6921 if (!event) {
6922 event = _globalDocument2['default'].createEvent('Event');
6923 event.initEvent('change', true, true);
6924 }
6925
6926 tracks.dispatchEvent(event);
6927 });
6928 })();
6929 }
6930 }
6931
6932 /**
6933 * Handle click on text track
6934 *
6935 * @method handleClick
6936 */
6937
6938 TextTrackMenuItem.prototype.handleClick = function handleClick(event) {
6939 var kind = this.track['kind'];
6940 var tracks = this.player_.textTracks();
6941
6942 _MenuItem.prototype.handleClick.call(this, event);
6943
6944 if (!tracks) return;
6945
6946 for (var i = 0; i < tracks.length; i++) {
6947 var track = tracks[i];
6948
6949 if (track['kind'] !== kind) {
6950 continue;
6951 }
6952
6953 if (track === this.track) {
6954 track['mode'] = 'showing';
6955 } else {
6956 track['mode'] = 'disabled';
6957 }
6958 }
6959 };
6960
6961 /**
6962 * Handle text track change
6963 *
6964 * @method handleTracksChange
6965 */
6966
6967 TextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) {
6968 this.selected(this.track['mode'] === 'showing');
6969 };
6970
6971 return TextTrackMenuItem;
6972})(_menuMenuItemJs2['default']);
6973
6974_componentJs2['default'].registerComponent('TextTrackMenuItem', TextTrackMenuItem);
6975exports['default'] = TextTrackMenuItem;
6976module.exports = exports['default'];
6977
6978},{"../../component.js":67,"../../menu/menu-item.js":105,"../../utils/fn.js":134,"global/document":1,"global/window":2}],90:[function(_dereq_,module,exports){
6979/**
6980 * @file current-time-display.js
6981 */
6982'use strict';
6983
6984exports.__esModule = true;
6985
6986function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6987
6988function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6989
6990function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
6991
6992function _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; }
6993
6994var _componentJs = _dereq_('../../component.js');
6995
6996var _componentJs2 = _interopRequireDefault(_componentJs);
6997
6998var _utilsDomJs = _dereq_('../../utils/dom.js');
6999
7000var Dom = _interopRequireWildcard(_utilsDomJs);
7001
7002var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js');
7003
7004var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs);
7005
7006/**
7007 * Displays the current time
7008 *
7009 * @param {Player|Object} player
7010 * @param {Object=} options
7011 * @extends Component
7012 * @class CurrentTimeDisplay
7013 */
7014
7015var CurrentTimeDisplay = (function (_Component) {
7016 _inherits(CurrentTimeDisplay, _Component);
7017
7018 function CurrentTimeDisplay(player, options) {
7019 _classCallCheck(this, CurrentTimeDisplay);
7020
7021 _Component.call(this, player, options);
7022
7023 this.on(player, 'timeupdate', this.updateContent);
7024 }
7025
7026 /**
7027 * Create the component's DOM element
7028 *
7029 * @return {Element}
7030 * @method createEl
7031 */
7032
7033 CurrentTimeDisplay.prototype.createEl = function createEl() {
7034 var el = _Component.prototype.createEl.call(this, 'div', {
7035 className: 'vjs-current-time vjs-time-control vjs-control'
7036 });
7037
7038 this.contentEl_ = Dom.createEl('div', {
7039 className: 'vjs-current-time-display',
7040 // label the current time for screen reader users
7041 innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00'
7042 }, {
7043 // tell screen readers not to automatically read the time as it changes
7044 'aria-live': 'off'
7045 });
7046
7047 el.appendChild(this.contentEl_);
7048 return el;
7049 };
7050
7051 /**
7052 * Update current time display
7053 *
7054 * @method updateContent
7055 */
7056
7057 CurrentTimeDisplay.prototype.updateContent = function updateContent() {
7058 // Allows for smooth scrubbing, when player can't keep up.
7059 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
7060 var localizedText = this.localize('Current Time');
7061 var formattedTime = _utilsFormatTimeJs2['default'](time, this.player_.duration());
7062 if (formattedTime !== this.formattedTime_) {
7063 this.formattedTime_ = formattedTime;
7064 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> ' + formattedTime;
7065 }
7066 };
7067
7068 return CurrentTimeDisplay;
7069})(_componentJs2['default']);
7070
7071_componentJs2['default'].registerComponent('CurrentTimeDisplay', CurrentTimeDisplay);
7072exports['default'] = CurrentTimeDisplay;
7073module.exports = exports['default'];
7074
7075},{"../../component.js":67,"../../utils/dom.js":132,"../../utils/format-time.js":135}],91:[function(_dereq_,module,exports){
7076/**
7077 * @file duration-display.js
7078 */
7079'use strict';
7080
7081exports.__esModule = true;
7082
7083function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
7084
7085function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7086
7087function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
7088
7089function _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; }
7090
7091var _componentJs = _dereq_('../../component.js');
7092
7093var _componentJs2 = _interopRequireDefault(_componentJs);
7094
7095var _utilsDomJs = _dereq_('../../utils/dom.js');
7096
7097var Dom = _interopRequireWildcard(_utilsDomJs);
7098
7099var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js');
7100
7101var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs);
7102
7103/**
7104 * Displays the duration
7105 *
7106 * @param {Player|Object} player
7107 * @param {Object=} options
7108 * @extends Component
7109 * @class DurationDisplay
7110 */
7111
7112var DurationDisplay = (function (_Component) {
7113 _inherits(DurationDisplay, _Component);
7114
7115 function DurationDisplay(player, options) {
7116 _classCallCheck(this, DurationDisplay);
7117
7118 _Component.call(this, player, options);
7119
7120 // this might need to be changed to 'durationchange' instead of 'timeupdate' eventually,
7121 // however the durationchange event fires before this.player_.duration() is set,
7122 // so the value cannot be written out using this method.
7123 // Once the order of durationchange and this.player_.duration() being set is figured out,
7124 // this can be updated.
7125 this.on(player, 'timeupdate', this.updateContent);
7126 this.on(player, 'loadedmetadata', this.updateContent);
7127 }
7128
7129 /**
7130 * Create the component's DOM element
7131 *
7132 * @return {Element}
7133 * @method createEl
7134 */
7135
7136 DurationDisplay.prototype.createEl = function createEl() {
7137 var el = _Component.prototype.createEl.call(this, 'div', {
7138 className: 'vjs-duration vjs-time-control vjs-control'
7139 });
7140
7141 this.contentEl_ = Dom.createEl('div', {
7142 className: 'vjs-duration-display',
7143 // label the duration time for screen reader users
7144 innerHTML: '<span class="vjs-control-text">' + this.localize('Duration Time') + '</span> 0:00'
7145 }, {
7146 // tell screen readers not to automatically read the time as it changes
7147 'aria-live': 'off'
7148 });
7149
7150 el.appendChild(this.contentEl_);
7151 return el;
7152 };
7153
7154 /**
7155 * Update duration time display
7156 *
7157 * @method updateContent
7158 */
7159
7160 DurationDisplay.prototype.updateContent = function updateContent() {
7161 var duration = this.player_.duration();
7162 if (duration && this.duration_ !== duration) {
7163 this.duration_ = duration;
7164 var localizedText = this.localize('Duration Time');
7165 var formattedTime = _utilsFormatTimeJs2['default'](duration);
7166 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> ' + formattedTime; // label the duration time for screen reader users
7167 }
7168 };
7169
7170 return DurationDisplay;
7171})(_componentJs2['default']);
7172
7173_componentJs2['default'].registerComponent('DurationDisplay', DurationDisplay);
7174exports['default'] = DurationDisplay;
7175module.exports = exports['default'];
7176
7177},{"../../component.js":67,"../../utils/dom.js":132,"../../utils/format-time.js":135}],92:[function(_dereq_,module,exports){
7178/**
7179 * @file remaining-time-display.js
7180 */
7181'use strict';
7182
7183exports.__esModule = true;
7184
7185function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
7186
7187function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7188
7189function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
7190
7191function _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; }
7192
7193var _componentJs = _dereq_('../../component.js');
7194
7195var _componentJs2 = _interopRequireDefault(_componentJs);
7196
7197var _utilsDomJs = _dereq_('../../utils/dom.js');
7198
7199var Dom = _interopRequireWildcard(_utilsDomJs);
7200
7201var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js');
7202
7203var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs);
7204
7205/**
7206 * Displays the time left in the video
7207 *
7208 * @param {Player|Object} player
7209 * @param {Object=} options
7210 * @extends Component
7211 * @class RemainingTimeDisplay
7212 */
7213
7214var RemainingTimeDisplay = (function (_Component) {
7215 _inherits(RemainingTimeDisplay, _Component);
7216
7217 function RemainingTimeDisplay(player, options) {
7218 _classCallCheck(this, RemainingTimeDisplay);
7219
7220 _Component.call(this, player, options);
7221
7222 this.on(player, 'timeupdate', this.updateContent);
7223 }
7224
7225 /**
7226 * Create the component's DOM element
7227 *
7228 * @return {Element}
7229 * @method createEl
7230 */
7231
7232 RemainingTimeDisplay.prototype.createEl = function createEl() {
7233 var el = _Component.prototype.createEl.call(this, 'div', {
7234 className: 'vjs-remaining-time vjs-time-control vjs-control'
7235 });
7236
7237 this.contentEl_ = Dom.createEl('div', {
7238 className: 'vjs-remaining-time-display',
7239 // label the remaining time for screen reader users
7240 innerHTML: '<span class="vjs-control-text">' + this.localize('Remaining Time') + '</span> -0:00'
7241 }, {
7242 // tell screen readers not to automatically read the time as it changes
7243 'aria-live': 'off'
7244 });
7245
7246 el.appendChild(this.contentEl_);
7247 return el;
7248 };
7249
7250 /**
7251 * Update remaining time display
7252 *
7253 * @method updateContent
7254 */
7255
7256 RemainingTimeDisplay.prototype.updateContent = function updateContent() {
7257 if (this.player_.duration()) {
7258 var localizedText = this.localize('Remaining Time');
7259 var formattedTime = _utilsFormatTimeJs2['default'](this.player_.remainingTime());
7260 if (formattedTime !== this.formattedTime_) {
7261 this.formattedTime_ = formattedTime;
7262 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> -' + formattedTime;
7263 }
7264 }
7265
7266 // Allows for smooth scrubbing, when player can't keep up.
7267 // var time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
7268 // this.contentEl_.innerHTML = vjs.formatTime(time, this.player_.duration());
7269 };
7270
7271 return RemainingTimeDisplay;
7272})(_componentJs2['default']);
7273
7274_componentJs2['default'].registerComponent('RemainingTimeDisplay', RemainingTimeDisplay);
7275exports['default'] = RemainingTimeDisplay;
7276module.exports = exports['default'];
7277
7278},{"../../component.js":67,"../../utils/dom.js":132,"../../utils/format-time.js":135}],93:[function(_dereq_,module,exports){
7279/**
7280 * @file time-divider.js
7281 */
7282'use strict';
7283
7284exports.__esModule = true;
7285
7286function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7287
7288function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
7289
7290function _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; }
7291
7292var _componentJs = _dereq_('../../component.js');
7293
7294var _componentJs2 = _interopRequireDefault(_componentJs);
7295
7296/**
7297 * The separator between the current time and duration.
7298 * Can be hidden if it's not needed in the design.
7299 *
7300 * @param {Player|Object} player
7301 * @param {Object=} options
7302 * @extends Component
7303 * @class TimeDivider
7304 */
7305
7306var TimeDivider = (function (_Component) {
7307 _inherits(TimeDivider, _Component);
7308
7309 function TimeDivider() {
7310 _classCallCheck(this, TimeDivider);
7311
7312 _Component.apply(this, arguments);
7313 }
7314
7315 /**
7316 * Create the component's DOM element
7317 *
7318 * @return {Element}
7319 * @method createEl
7320 */
7321
7322 TimeDivider.prototype.createEl = function createEl() {
7323 return _Component.prototype.createEl.call(this, 'div', {
7324 className: 'vjs-time-control vjs-time-divider',
7325 innerHTML: '<div><span>/</span></div>'
7326 });
7327 };
7328
7329 return TimeDivider;
7330})(_componentJs2['default']);
7331
7332_componentJs2['default'].registerComponent('TimeDivider', TimeDivider);
7333exports['default'] = TimeDivider;
7334module.exports = exports['default'];
7335
7336},{"../../component.js":67}],94:[function(_dereq_,module,exports){
7337/**
7338 * @file volume-bar.js
7339 */
7340'use strict';
7341
7342exports.__esModule = true;
7343
7344function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
7345
7346function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7347
7348function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
7349
7350function _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; }
7351
7352var _sliderSliderJs = _dereq_('../../slider/slider.js');
7353
7354var _sliderSliderJs2 = _interopRequireDefault(_sliderSliderJs);
7355
7356var _componentJs = _dereq_('../../component.js');
7357
7358var _componentJs2 = _interopRequireDefault(_componentJs);
7359
7360var _utilsFnJs = _dereq_('../../utils/fn.js');
7361
7362var Fn = _interopRequireWildcard(_utilsFnJs);
7363
7364// Required children
7365
7366var _volumeLevelJs = _dereq_('./volume-level.js');
7367
7368var _volumeLevelJs2 = _interopRequireDefault(_volumeLevelJs);
7369
7370/**
7371 * The bar that contains the volume level and can be clicked on to adjust the level
7372 *
7373 * @param {Player|Object} player
7374 * @param {Object=} options
7375 * @extends Slider
7376 * @class VolumeBar
7377 */
7378
7379var VolumeBar = (function (_Slider) {
7380 _inherits(VolumeBar, _Slider);
7381
7382 function VolumeBar(player, options) {
7383 _classCallCheck(this, VolumeBar);
7384
7385 _Slider.call(this, player, options);
7386 this.on(player, 'volumechange', this.updateARIAAttributes);
7387 player.ready(Fn.bind(this, this.updateARIAAttributes));
7388 }
7389
7390 /**
7391 * Create the component's DOM element
7392 *
7393 * @return {Element}
7394 * @method createEl
7395 */
7396
7397 VolumeBar.prototype.createEl = function createEl() {
7398 return _Slider.prototype.createEl.call(this, 'div', {
7399 className: 'vjs-volume-bar vjs-slider-bar'
7400 }, {
7401 'aria-label': 'volume level'
7402 });
7403 };
7404
7405 /**
7406 * Handle mouse move on volume bar
7407 *
7408 * @method handleMouseMove
7409 */
7410
7411 VolumeBar.prototype.handleMouseMove = function handleMouseMove(event) {
7412 this.checkMuted();
7413 this.player_.volume(this.calculateDistance(event));
7414 };
7415
7416 VolumeBar.prototype.checkMuted = function checkMuted() {
7417 if (this.player_.muted()) {
7418 this.player_.muted(false);
7419 }
7420 };
7421
7422 /**
7423 * Get percent of volume level
7424 *
7425 * @retun {Number} Volume level percent
7426 * @method getPercent
7427 */
7428
7429 VolumeBar.prototype.getPercent = function getPercent() {
7430 if (this.player_.muted()) {
7431 return 0;
7432 } else {
7433 return this.player_.volume();
7434 }
7435 };
7436
7437 /**
7438 * Increase volume level for keyboard users
7439 *
7440 * @method stepForward
7441 */
7442
7443 VolumeBar.prototype.stepForward = function stepForward() {
7444 this.checkMuted();
7445 this.player_.volume(this.player_.volume() + 0.1);
7446 };
7447
7448 /**
7449 * Decrease volume level for keyboard users
7450 *
7451 * @method stepBack
7452 */
7453
7454 VolumeBar.prototype.stepBack = function stepBack() {
7455 this.checkMuted();
7456 this.player_.volume(this.player_.volume() - 0.1);
7457 };
7458
7459 /**
7460 * Update ARIA accessibility attributes
7461 *
7462 * @method updateARIAAttributes
7463 */
7464
7465 VolumeBar.prototype.updateARIAAttributes = function updateARIAAttributes() {
7466 // Current value of volume bar as a percentage
7467 var volume = (this.player_.volume() * 100).toFixed(2);
7468 this.el_.setAttribute('aria-valuenow', volume);
7469 this.el_.setAttribute('aria-valuetext', volume + '%');
7470 };
7471
7472 return VolumeBar;
7473})(_sliderSliderJs2['default']);
7474
7475VolumeBar.prototype.options_ = {
7476 children: ['volumeLevel'],
7477 'barName': 'volumeLevel'
7478};
7479
7480VolumeBar.prototype.playerEvent = 'volumechange';
7481
7482_componentJs2['default'].registerComponent('VolumeBar', VolumeBar);
7483exports['default'] = VolumeBar;
7484module.exports = exports['default'];
7485
7486},{"../../component.js":67,"../../slider/slider.js":114,"../../utils/fn.js":134,"./volume-level.js":96}],95:[function(_dereq_,module,exports){
7487/**
7488 * @file volume-control.js
7489 */
7490'use strict';
7491
7492exports.__esModule = true;
7493
7494function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7495
7496function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
7497
7498function _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; }
7499
7500var _componentJs = _dereq_('../../component.js');
7501
7502var _componentJs2 = _interopRequireDefault(_componentJs);
7503
7504// Required children
7505
7506var _volumeBarJs = _dereq_('./volume-bar.js');
7507
7508var _volumeBarJs2 = _interopRequireDefault(_volumeBarJs);
7509
7510/**
7511 * The component for controlling the volume level
7512 *
7513 * @param {Player|Object} player
7514 * @param {Object=} options
7515 * @extends Component
7516 * @class VolumeControl
7517 */
7518
7519var VolumeControl = (function (_Component) {
7520 _inherits(VolumeControl, _Component);
7521
7522 function VolumeControl(player, options) {
7523 _classCallCheck(this, VolumeControl);
7524
7525 _Component.call(this, player, options);
7526
7527 // hide volume controls when they're not supported by the current tech
7528 if (player.tech_ && player.tech_['featuresVolumeControl'] === false) {
7529 this.addClass('vjs-hidden');
7530 }
7531 this.on(player, 'loadstart', function () {
7532 if (player.tech_['featuresVolumeControl'] === false) {
7533 this.addClass('vjs-hidden');
7534 } else {
7535 this.removeClass('vjs-hidden');
7536 }
7537 });
7538 }
7539
7540 /**
7541 * Create the component's DOM element
7542 *
7543 * @return {Element}
7544 * @method createEl
7545 */
7546
7547 VolumeControl.prototype.createEl = function createEl() {
7548 return _Component.prototype.createEl.call(this, 'div', {
7549 className: 'vjs-volume-control vjs-control'
7550 });
7551 };
7552
7553 return VolumeControl;
7554})(_componentJs2['default']);
7555
7556VolumeControl.prototype.options_ = {
7557 children: ['volumeBar']
7558};
7559
7560_componentJs2['default'].registerComponent('VolumeControl', VolumeControl);
7561exports['default'] = VolumeControl;
7562module.exports = exports['default'];
7563
7564},{"../../component.js":67,"./volume-bar.js":94}],96:[function(_dereq_,module,exports){
7565/**
7566 * @file volume-level.js
7567 */
7568'use strict';
7569
7570exports.__esModule = true;
7571
7572function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7573
7574function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
7575
7576function _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; }
7577
7578var _componentJs = _dereq_('../../component.js');
7579
7580var _componentJs2 = _interopRequireDefault(_componentJs);
7581
7582/**
7583 * Shows volume level
7584 *
7585 * @param {Player|Object} player
7586 * @param {Object=} options
7587 * @extends Component
7588 * @class VolumeLevel
7589 */
7590
7591var VolumeLevel = (function (_Component) {
7592 _inherits(VolumeLevel, _Component);
7593
7594 function VolumeLevel() {
7595 _classCallCheck(this, VolumeLevel);
7596
7597 _Component.apply(this, arguments);
7598 }
7599
7600 /**
7601 * Create the component's DOM element
7602 *
7603 * @return {Element}
7604 * @method createEl
7605 */
7606
7607 VolumeLevel.prototype.createEl = function createEl() {
7608 return _Component.prototype.createEl.call(this, 'div', {
7609 className: 'vjs-volume-level',
7610 innerHTML: '<span class="vjs-control-text"></span>'
7611 });
7612 };
7613
7614 return VolumeLevel;
7615})(_componentJs2['default']);
7616
7617_componentJs2['default'].registerComponent('VolumeLevel', VolumeLevel);
7618exports['default'] = VolumeLevel;
7619module.exports = exports['default'];
7620
7621},{"../../component.js":67}],97:[function(_dereq_,module,exports){
7622/**
7623 * @file volume-menu-button.js
7624 */
7625'use strict';
7626
7627exports.__esModule = true;
7628
7629function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7630
7631function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
7632
7633function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
7634
7635function _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; }
7636
7637var _utilsFnJs = _dereq_('../utils/fn.js');
7638
7639var Fn = _interopRequireWildcard(_utilsFnJs);
7640
7641var _componentJs = _dereq_('../component.js');
7642
7643var _componentJs2 = _interopRequireDefault(_componentJs);
7644
7645var _popupPopupJs = _dereq_('../popup/popup.js');
7646
7647var _popupPopupJs2 = _interopRequireDefault(_popupPopupJs);
7648
7649var _popupPopupButtonJs = _dereq_('../popup/popup-button.js');
7650
7651var _popupPopupButtonJs2 = _interopRequireDefault(_popupPopupButtonJs);
7652
7653var _muteToggleJs = _dereq_('./mute-toggle.js');
7654
7655var _muteToggleJs2 = _interopRequireDefault(_muteToggleJs);
7656
7657var _volumeControlVolumeBarJs = _dereq_('./volume-control/volume-bar.js');
7658
7659var _volumeControlVolumeBarJs2 = _interopRequireDefault(_volumeControlVolumeBarJs);
7660
7661var _globalDocument = _dereq_('global/document');
7662
7663var _globalDocument2 = _interopRequireDefault(_globalDocument);
7664
7665/**
7666 * Button for volume popup
7667 *
7668 * @param {Player|Object} player
7669 * @param {Object=} options
7670 * @extends PopupButton
7671 * @class VolumeMenuButton
7672 */
7673
7674var VolumeMenuButton = (function (_PopupButton) {
7675 _inherits(VolumeMenuButton, _PopupButton);
7676
7677 function VolumeMenuButton(player) {
7678 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
7679
7680 _classCallCheck(this, VolumeMenuButton);
7681
7682 // Default to inline
7683 if (options.inline === undefined) {
7684 options.inline = true;
7685 }
7686
7687 // If the vertical option isn't passed at all, default to true.
7688 if (options.vertical === undefined) {
7689 // If an inline volumeMenuButton is used, we should default to using
7690 // a horizontal slider for obvious reasons.
7691 if (options.inline) {
7692 options.vertical = false;
7693 } else {
7694 options.vertical = true;
7695 }
7696 }
7697
7698 // The vertical option needs to be set on the volumeBar as well,
7699 // since that will need to be passed along to the VolumeBar constructor
7700 options.volumeBar = options.volumeBar || {};
7701 options.volumeBar.vertical = !!options.vertical;
7702
7703 _PopupButton.call(this, player, options);
7704
7705 // Same listeners as MuteToggle
7706 this.on(player, 'volumechange', this.volumeUpdate);
7707 this.on(player, 'loadstart', this.volumeUpdate);
7708
7709 // hide mute toggle if the current tech doesn't support volume control
7710 function updateVisibility() {
7711 if (player.tech_ && player.tech_['featuresVolumeControl'] === false) {
7712 this.addClass('vjs-hidden');
7713 } else {
7714 this.removeClass('vjs-hidden');
7715 }
7716 }
7717
7718 updateVisibility.call(this);
7719 this.on(player, 'loadstart', updateVisibility);
7720
7721 this.on(this.volumeBar, ['slideractive', 'focus'], function () {
7722 this.addClass('vjs-slider-active');
7723 });
7724
7725 this.on(this.volumeBar, ['sliderinactive', 'blur'], function () {
7726 this.removeClass('vjs-slider-active');
7727 });
7728
7729 this.on(this.volumeBar, ['focus'], function () {
7730 this.addClass('vjs-lock-showing');
7731 });
7732
7733 this.on(this.volumeBar, ['blur'], function () {
7734 this.removeClass('vjs-lock-showing');
7735 });
7736 }
7737
7738 /**
7739 * Allow sub components to stack CSS class names
7740 *
7741 * @return {String} The constructed class name
7742 * @method buildCSSClass
7743 */
7744
7745 VolumeMenuButton.prototype.buildCSSClass = function buildCSSClass() {
7746 var orientationClass = '';
7747 if (!!this.options_.vertical) {
7748 orientationClass = 'vjs-volume-menu-button-vertical';
7749 } else {
7750 orientationClass = 'vjs-volume-menu-button-horizontal';
7751 }
7752
7753 return 'vjs-volume-menu-button ' + _PopupButton.prototype.buildCSSClass.call(this) + ' ' + orientationClass;
7754 };
7755
7756 /**
7757 * Allow sub components to stack CSS class names
7758 *
7759 * @return {Popup} The volume popup button
7760 * @method createPopup
7761 */
7762
7763 VolumeMenuButton.prototype.createPopup = function createPopup() {
7764 var popup = new _popupPopupJs2['default'](this.player_, {
7765 contentElType: 'div'
7766 });
7767
7768 var vb = new _volumeControlVolumeBarJs2['default'](this.player_, this.options_.volumeBar);
7769
7770 popup.addChild(vb);
7771
7772 this.menuContent = popup;
7773 this.volumeBar = vb;
7774
7775 this.attachVolumeBarEvents();
7776
7777 return popup;
7778 };
7779
7780 /**
7781 * Handle click on volume popup and calls super
7782 *
7783 * @method handleClick
7784 */
7785
7786 VolumeMenuButton.prototype.handleClick = function handleClick() {
7787 _muteToggleJs2['default'].prototype.handleClick.call(this);
7788 _PopupButton.prototype.handleClick.call(this);
7789 };
7790
7791 VolumeMenuButton.prototype.attachVolumeBarEvents = function attachVolumeBarEvents() {
7792 this.menuContent.on(['mousedown', 'touchdown'], Fn.bind(this, this.handleMouseDown));
7793 };
7794
7795 VolumeMenuButton.prototype.handleMouseDown = function handleMouseDown(event) {
7796 this.on(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove));
7797 this.on(_globalDocument2['default'], ['mouseup', 'touchend'], this.handleMouseUp);
7798 };
7799
7800 VolumeMenuButton.prototype.handleMouseUp = function handleMouseUp(event) {
7801 this.off(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove));
7802 };
7803
7804 return VolumeMenuButton;
7805})(_popupPopupButtonJs2['default']);
7806
7807VolumeMenuButton.prototype.volumeUpdate = _muteToggleJs2['default'].prototype.update;
7808VolumeMenuButton.prototype.controlText_ = 'Mute';
7809
7810_componentJs2['default'].registerComponent('VolumeMenuButton', VolumeMenuButton);
7811exports['default'] = VolumeMenuButton;
7812module.exports = exports['default'];
7813
7814},{"../component.js":67,"../popup/popup-button.js":110,"../popup/popup.js":111,"../utils/fn.js":134,"./mute-toggle.js":71,"./volume-control/volume-bar.js":94,"global/document":1}],98:[function(_dereq_,module,exports){
7815/**
7816 * @file error-display.js
7817 */
7818'use strict';
7819
7820exports.__esModule = true;
7821
7822function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
7823
7824function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7825
7826function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
7827
7828function _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; }
7829
7830var _component = _dereq_('./component');
7831
7832var _component2 = _interopRequireDefault(_component);
7833
7834var _modalDialog = _dereq_('./modal-dialog');
7835
7836var _modalDialog2 = _interopRequireDefault(_modalDialog);
7837
7838var _utilsDom = _dereq_('./utils/dom');
7839
7840var Dom = _interopRequireWildcard(_utilsDom);
7841
7842var _utilsMergeOptions = _dereq_('./utils/merge-options');
7843
7844var _utilsMergeOptions2 = _interopRequireDefault(_utilsMergeOptions);
7845
7846/**
7847 * Display that an error has occurred making the video unplayable.
7848 *
7849 * @extends ModalDialog
7850 * @class ErrorDisplay
7851 */
7852
7853var ErrorDisplay = (function (_ModalDialog) {
7854 _inherits(ErrorDisplay, _ModalDialog);
7855
7856 /**
7857 * Constructor for error display modal.
7858 *
7859 * @param {Player} player
7860 * @param {Object} [options]
7861 */
7862
7863 function ErrorDisplay(player, options) {
7864 _classCallCheck(this, ErrorDisplay);
7865
7866 _ModalDialog.call(this, player, options);
7867 this.on(player, 'error', this.open);
7868 }
7869
7870 /**
7871 * Include the old class for backward-compatibility.
7872 *
7873 * This can be removed in 6.0.
7874 *
7875 * @method buildCSSClass
7876 * @deprecated
7877 * @return {String}
7878 */
7879
7880 ErrorDisplay.prototype.buildCSSClass = function buildCSSClass() {
7881 return 'vjs-error-display ' + _ModalDialog.prototype.buildCSSClass.call(this);
7882 };
7883
7884 /**
7885 * Generates the modal content based on the player error.
7886 *
7887 * @return {String|Null}
7888 */
7889
7890 ErrorDisplay.prototype.content = function content() {
7891 var error = this.player().error();
7892 return error ? this.localize(error.message) : '';
7893 };
7894
7895 return ErrorDisplay;
7896})(_modalDialog2['default']);
7897
7898ErrorDisplay.prototype.options_ = _utilsMergeOptions2['default'](_modalDialog2['default'].prototype.options_, {
7899 fillAlways: true,
7900 temporary: false,
7901 uncloseable: true
7902});
7903
7904_component2['default'].registerComponent('ErrorDisplay', ErrorDisplay);
7905exports['default'] = ErrorDisplay;
7906module.exports = exports['default'];
7907
7908},{"./component":67,"./modal-dialog":107,"./utils/dom":132,"./utils/merge-options":138}],99:[function(_dereq_,module,exports){
7909/**
7910 * @file event-target.js
7911 */
7912'use strict';
7913
7914exports.__esModule = true;
7915
7916function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
7917
7918var _utilsEventsJs = _dereq_('./utils/events.js');
7919
7920var Events = _interopRequireWildcard(_utilsEventsJs);
7921
7922var EventTarget = function EventTarget() {};
7923
7924EventTarget.prototype.allowedEvents_ = {};
7925
7926EventTarget.prototype.on = function (type, fn) {
7927 // Remove the addEventListener alias before calling Events.on
7928 // so we don't get into an infinite type loop
7929 var ael = this.addEventListener;
7930 this.addEventListener = Function.prototype;
7931 Events.on(this, type, fn);
7932 this.addEventListener = ael;
7933};
7934EventTarget.prototype.addEventListener = EventTarget.prototype.on;
7935
7936EventTarget.prototype.off = function (type, fn) {
7937 Events.off(this, type, fn);
7938};
7939EventTarget.prototype.removeEventListener = EventTarget.prototype.off;
7940
7941EventTarget.prototype.one = function (type, fn) {
7942 Events.one(this, type, fn);
7943};
7944
7945EventTarget.prototype.trigger = function (event) {
7946 var type = event.type || event;
7947
7948 if (typeof event === 'string') {
7949 event = {
7950 type: type
7951 };
7952 }
7953 event = Events.fixEvent(event);
7954
7955 if (this.allowedEvents_[type] && this['on' + type]) {
7956 this['on' + type](event);
7957 }
7958
7959 Events.trigger(this, event);
7960};
7961// The standard DOM EventTarget.dispatchEvent() is aliased to trigger()
7962EventTarget.prototype.dispatchEvent = EventTarget.prototype.trigger;
7963
7964exports['default'] = EventTarget;
7965module.exports = exports['default'];
7966
7967},{"./utils/events.js":133}],100:[function(_dereq_,module,exports){
7968'use strict';
7969
7970exports.__esModule = true;
7971
7972function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7973
7974var _utilsLog = _dereq_('./utils/log');
7975
7976var _utilsLog2 = _interopRequireDefault(_utilsLog);
7977
7978/*
7979 * @file extend.js
7980 *
7981 * A combination of node inherits and babel's inherits (after transpile).
7982 * Both work the same but node adds `super_` to the subClass
7983 * and Bable adds the superClass as __proto__. Both seem useful.
7984 */
7985var _inherits = function _inherits(subClass, superClass) {
7986 if (typeof superClass !== 'function' && superClass !== null) {
7987 throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
7988 }
7989
7990 subClass.prototype = Object.create(superClass && superClass.prototype, {
7991 constructor: {
7992 value: subClass,
7993 enumerable: false,
7994 writable: true,
7995 configurable: true
7996 }
7997 });
7998
7999 if (superClass) {
8000 // node
8001 subClass.super_ = superClass;
8002 }
8003};
8004
8005/*
8006 * Function for subclassing using the same inheritance that
8007 * videojs uses internally
8008 * ```js
8009 * var Button = videojs.getComponent('Button');
8010 * ```
8011 * ```js
8012 * var MyButton = videojs.extend(Button, {
8013 * constructor: function(player, options) {
8014 * Button.call(this, player, options);
8015 * },
8016 * onClick: function() {
8017 * // doSomething
8018 * }
8019 * });
8020 * ```
8021 */
8022var extendFn = function extendFn(superClass) {
8023 var subClassMethods = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
8024
8025 var subClass = function subClass() {
8026 superClass.apply(this, arguments);
8027 };
8028 var methods = {};
8029
8030 if (typeof subClassMethods === 'object') {
8031 if (typeof subClassMethods.init === 'function') {
8032 _utilsLog2['default'].warn('Constructor logic via init() is deprecated; please use constructor() instead.');
8033 subClassMethods.constructor = subClassMethods.init;
8034 }
8035 if (subClassMethods.constructor !== Object.prototype.constructor) {
8036 subClass = subClassMethods.constructor;
8037 }
8038 methods = subClassMethods;
8039 } else if (typeof subClassMethods === 'function') {
8040 subClass = subClassMethods;
8041 }
8042
8043 _inherits(subClass, superClass);
8044
8045 // Extend subObj's prototype with functions and other properties from props
8046 for (var name in methods) {
8047 if (methods.hasOwnProperty(name)) {
8048 subClass.prototype[name] = methods[name];
8049 }
8050 }
8051
8052 return subClass;
8053};
8054
8055exports['default'] = extendFn;
8056module.exports = exports['default'];
8057
8058},{"./utils/log":137}],101:[function(_dereq_,module,exports){
8059/**
8060 * @file fullscreen-api.js
8061 */
8062'use strict';
8063
8064exports.__esModule = true;
8065
8066function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8067
8068var _globalDocument = _dereq_('global/document');
8069
8070var _globalDocument2 = _interopRequireDefault(_globalDocument);
8071
8072/*
8073 * Store the browser-specific methods for the fullscreen API
8074 * @type {Object|undefined}
8075 * @private
8076 */
8077var FullscreenApi = {};
8078
8079// browser API methods
8080// map approach from Screenful.js - https://github.com/sindresorhus/screenfull.js
8081var apiMap = [
8082// Spec: https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html
8083['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'],
8084// WebKit
8085['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror'],
8086// Old WebKit (Safari 5.1)
8087['webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror'],
8088// Mozilla
8089['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'],
8090// Microsoft
8091['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']];
8092
8093var specApi = apiMap[0];
8094var browserApi = undefined;
8095
8096// determine the supported set of functions
8097for (var i = 0; i < apiMap.length; i++) {
8098 // check for exitFullscreen function
8099 if (apiMap[i][1] in _globalDocument2['default']) {
8100 browserApi = apiMap[i];
8101 break;
8102 }
8103}
8104
8105// map the browser API names to the spec API names
8106if (browserApi) {
8107 for (var i = 0; i < browserApi.length; i++) {
8108 FullscreenApi[specApi[i]] = browserApi[i];
8109 }
8110}
8111
8112exports['default'] = FullscreenApi;
8113module.exports = exports['default'];
8114
8115},{"global/document":1}],102:[function(_dereq_,module,exports){
8116/**
8117 * @file loading-spinner.js
8118 */
8119'use strict';
8120
8121exports.__esModule = true;
8122
8123function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8124
8125function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
8126
8127function _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; }
8128
8129var _component = _dereq_('./component');
8130
8131var _component2 = _interopRequireDefault(_component);
8132
8133/* Loading Spinner
8134================================================================================ */
8135/**
8136 * Loading spinner for waiting events
8137 *
8138 * @extends Component
8139 * @class LoadingSpinner
8140 */
8141
8142var LoadingSpinner = (function (_Component) {
8143 _inherits(LoadingSpinner, _Component);
8144
8145 function LoadingSpinner() {
8146 _classCallCheck(this, LoadingSpinner);
8147
8148 _Component.apply(this, arguments);
8149 }
8150
8151 /**
8152 * Create the component's DOM element
8153 *
8154 * @method createEl
8155 */
8156
8157 LoadingSpinner.prototype.createEl = function createEl() {
8158 return _Component.prototype.createEl.call(this, 'div', {
8159 className: 'vjs-loading-spinner',
8160 dir: 'ltr'
8161 });
8162 };
8163
8164 return LoadingSpinner;
8165})(_component2['default']);
8166
8167_component2['default'].registerComponent('LoadingSpinner', LoadingSpinner);
8168exports['default'] = LoadingSpinner;
8169module.exports = exports['default'];
8170
8171},{"./component":67}],103:[function(_dereq_,module,exports){
8172/**
8173 * @file media-error.js
8174 */
8175'use strict';
8176
8177exports.__esModule = true;
8178
8179function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8180
8181var _objectAssign = _dereq_('object.assign');
8182
8183var _objectAssign2 = _interopRequireDefault(_objectAssign);
8184
8185/*
8186 * Custom MediaError to mimic the HTML5 MediaError
8187 *
8188 * @param {Number} code The media error code
8189 */
8190var MediaError = function MediaError(code) {
8191 if (typeof code === 'number') {
8192 this.code = code;
8193 } else if (typeof code === 'string') {
8194 // default code is zero, so this is a custom error
8195 this.message = code;
8196 } else if (typeof code === 'object') {
8197 // object
8198 _objectAssign2['default'](this, code);
8199 }
8200
8201 if (!this.message) {
8202 this.message = MediaError.defaultMessages[this.code] || '';
8203 }
8204};
8205
8206/*
8207 * The error code that refers two one of the defined
8208 * MediaError types
8209 *
8210 * @type {Number}
8211 */
8212MediaError.prototype.code = 0;
8213
8214/*
8215 * An optional message to be shown with the error.
8216 * Message is not part of the HTML5 video spec
8217 * but allows for more informative custom errors.
8218 *
8219 * @type {String}
8220 */
8221MediaError.prototype.message = '';
8222
8223/*
8224 * An optional status code that can be set by plugins
8225 * to allow even more detail about the error.
8226 * For example the HLS plugin might provide the specific
8227 * HTTP status code that was returned when the error
8228 * occurred, then allowing a custom error overlay
8229 * to display more information.
8230 *
8231 * @type {Array}
8232 */
8233MediaError.prototype.status = null;
8234
8235MediaError.errorTypes = ['MEDIA_ERR_CUSTOM', // = 0
8236'MEDIA_ERR_ABORTED', // = 1
8237'MEDIA_ERR_NETWORK', // = 2
8238'MEDIA_ERR_DECODE', // = 3
8239'MEDIA_ERR_SRC_NOT_SUPPORTED', // = 4
8240'MEDIA_ERR_ENCRYPTED' // = 5
8241];
8242
8243MediaError.defaultMessages = {
8244 1: 'You aborted the media playback',
8245 2: 'A network error caused the media download to fail part-way.',
8246 3: 'The media playback was aborted due to a corruption problem or because the media used features your browser did not support.',
8247 4: 'The media could not be loaded, either because the server or network failed or because the format is not supported.',
8248 5: 'The media is encrypted and we do not have the keys to decrypt it.'
8249};
8250
8251// Add types as properties on MediaError
8252// e.g. MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
8253for (var errNum = 0; errNum < MediaError.errorTypes.length; errNum++) {
8254 MediaError[MediaError.errorTypes[errNum]] = errNum;
8255 // values should be accessible on both the class and instance
8256 MediaError.prototype[MediaError.errorTypes[errNum]] = errNum;
8257}
8258
8259exports['default'] = MediaError;
8260module.exports = exports['default'];
8261
8262},{"object.assign":45}],104:[function(_dereq_,module,exports){
8263/**
8264 * @file menu-button.js
8265 */
8266'use strict';
8267
8268exports.__esModule = true;
8269
8270function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
8271
8272function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8273
8274function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
8275
8276function _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; }
8277
8278var _clickableComponentJs = _dereq_('../clickable-component.js');
8279
8280var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs);
8281
8282var _componentJs = _dereq_('../component.js');
8283
8284var _componentJs2 = _interopRequireDefault(_componentJs);
8285
8286var _menuJs = _dereq_('./menu.js');
8287
8288var _menuJs2 = _interopRequireDefault(_menuJs);
8289
8290var _utilsDomJs = _dereq_('../utils/dom.js');
8291
8292var Dom = _interopRequireWildcard(_utilsDomJs);
8293
8294var _utilsFnJs = _dereq_('../utils/fn.js');
8295
8296var Fn = _interopRequireWildcard(_utilsFnJs);
8297
8298var _utilsToTitleCaseJs = _dereq_('../utils/to-title-case.js');
8299
8300var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs);
8301
8302/**
8303 * A button class with a popup menu
8304 *
8305 * @param {Player|Object} player
8306 * @param {Object=} options
8307 * @extends Button
8308 * @class MenuButton
8309 */
8310
8311var MenuButton = (function (_ClickableComponent) {
8312 _inherits(MenuButton, _ClickableComponent);
8313
8314 function MenuButton(player) {
8315 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
8316
8317 _classCallCheck(this, MenuButton);
8318
8319 _ClickableComponent.call(this, player, options);
8320
8321 this.update();
8322
8323 this.el_.setAttribute('aria-haspopup', true);
8324 this.el_.setAttribute('role', 'menuitem');
8325 this.on('keydown', this.handleSubmenuKeyPress);
8326 }
8327
8328 /**
8329 * Update menu
8330 *
8331 * @method update
8332 */
8333
8334 MenuButton.prototype.update = function update() {
8335 var menu = this.createMenu();
8336
8337 if (this.menu) {
8338 this.removeChild(this.menu);
8339 }
8340
8341 this.menu = menu;
8342 this.addChild(menu);
8343
8344 /**
8345 * Track the state of the menu button
8346 *
8347 * @type {Boolean}
8348 * @private
8349 */
8350 this.buttonPressed_ = false;
8351 this.el_.setAttribute('aria-expanded', false);
8352
8353 if (this.items && this.items.length === 0) {
8354 this.hide();
8355 } else if (this.items && this.items.length > 1) {
8356 this.show();
8357 }
8358 };
8359
8360 /**
8361 * Create menu
8362 *
8363 * @return {Menu} The constructed menu
8364 * @method createMenu
8365 */
8366
8367 MenuButton.prototype.createMenu = function createMenu() {
8368 var menu = new _menuJs2['default'](this.player_);
8369
8370 // Add a title list item to the top
8371 if (this.options_.title) {
8372 var title = Dom.createEl('li', {
8373 className: 'vjs-menu-title',
8374 innerHTML: _utilsToTitleCaseJs2['default'](this.options_.title),
8375 tabIndex: -1
8376 });
8377 menu.children_.unshift(title);
8378 Dom.insertElFirst(title, menu.contentEl());
8379 }
8380
8381 this.items = this['createItems']();
8382
8383 if (this.items) {
8384 // Add menu items to the menu
8385 for (var i = 0; i < this.items.length; i++) {
8386 menu.addItem(this.items[i]);
8387 }
8388 }
8389
8390 return menu;
8391 };
8392
8393 /**
8394 * Create the list of menu items. Specific to each subclass.
8395 *
8396 * @method createItems
8397 */
8398
8399 MenuButton.prototype.createItems = function createItems() {};
8400
8401 /**
8402 * Create the component's DOM element
8403 *
8404 * @return {Element}
8405 * @method createEl
8406 */
8407
8408 MenuButton.prototype.createEl = function createEl() {
8409 return _ClickableComponent.prototype.createEl.call(this, 'div', {
8410 className: this.buildCSSClass()
8411 });
8412 };
8413
8414 /**
8415 * Allow sub components to stack CSS class names
8416 *
8417 * @return {String} The constructed class name
8418 * @method buildCSSClass
8419 */
8420
8421 MenuButton.prototype.buildCSSClass = function buildCSSClass() {
8422 var menuButtonClass = 'vjs-menu-button';
8423
8424 // If the inline option is passed, we want to use different styles altogether.
8425 if (this.options_.inline === true) {
8426 menuButtonClass += '-inline';
8427 } else {
8428 menuButtonClass += '-popup';
8429 }
8430
8431 return 'vjs-menu-button ' + menuButtonClass + ' ' + _ClickableComponent.prototype.buildCSSClass.call(this);
8432 };
8433
8434 /**
8435 * When you click the button it adds focus, which
8436 * will show the menu indefinitely.
8437 * So we'll remove focus when the mouse leaves the button.
8438 * Focus is needed for tab navigation.
8439 * Allow sub components to stack CSS class names
8440 *
8441 * @method handleClick
8442 */
8443
8444 MenuButton.prototype.handleClick = function handleClick() {
8445 this.one('mouseout', Fn.bind(this, function () {
8446 this.menu.unlockShowing();
8447 this.el_.blur();
8448 }));
8449 if (this.buttonPressed_) {
8450 this.unpressButton();
8451 } else {
8452 this.pressButton();
8453 }
8454 };
8455
8456 /**
8457 * Handle key press on menu
8458 *
8459 * @param {Object} event Key press event
8460 * @method handleKeyPress
8461 */
8462
8463 MenuButton.prototype.handleKeyPress = function handleKeyPress(event) {
8464
8465 // Escape (27) key or Tab (9) key unpress the 'button'
8466 if (event.which === 27 || event.which === 9) {
8467 if (this.buttonPressed_) {
8468 this.unpressButton();
8469 }
8470 // Don't preventDefault for Tab key - we still want to lose focus
8471 if (event.which !== 9) {
8472 event.preventDefault();
8473 }
8474 // Up (38) key or Down (40) key press the 'button'
8475 } else if (event.which === 38 || event.which === 40) {
8476 if (!this.buttonPressed_) {
8477 this.pressButton();
8478 event.preventDefault();
8479 }
8480 } else {
8481 _ClickableComponent.prototype.handleKeyPress.call(this, event);
8482 }
8483 };
8484
8485 /**
8486 * Handle key press on submenu
8487 *
8488 * @param {Object} event Key press event
8489 * @method handleSubmenuKeyPress
8490 */
8491
8492 MenuButton.prototype.handleSubmenuKeyPress = function handleSubmenuKeyPress(event) {
8493
8494 // Escape (27) key or Tab (9) key unpress the 'button'
8495 if (event.which === 27 || event.which === 9) {
8496 if (this.buttonPressed_) {
8497 this.unpressButton();
8498 }
8499 // Don't preventDefault for Tab key - we still want to lose focus
8500 if (event.which !== 9) {
8501 event.preventDefault();
8502 }
8503 }
8504 };
8505
8506 /**
8507 * Makes changes based on button pressed
8508 *
8509 * @method pressButton
8510 */
8511
8512 MenuButton.prototype.pressButton = function pressButton() {
8513 this.buttonPressed_ = true;
8514 this.menu.lockShowing();
8515 this.el_.setAttribute('aria-expanded', true);
8516 this.menu.focus(); // set the focus into the submenu
8517 };
8518
8519 /**
8520 * Makes changes based on button unpressed
8521 *
8522 * @method unpressButton
8523 */
8524
8525 MenuButton.prototype.unpressButton = function unpressButton() {
8526 this.buttonPressed_ = false;
8527 this.menu.unlockShowing();
8528 this.el_.setAttribute('aria-expanded', false);
8529 this.el_.focus(); // Set focus back to this menu button
8530 };
8531
8532 return MenuButton;
8533})(_clickableComponentJs2['default']);
8534
8535_componentJs2['default'].registerComponent('MenuButton', MenuButton);
8536exports['default'] = MenuButton;
8537module.exports = exports['default'];
8538
8539},{"../clickable-component.js":65,"../component.js":67,"../utils/dom.js":132,"../utils/fn.js":134,"../utils/to-title-case.js":141,"./menu.js":106}],105:[function(_dereq_,module,exports){
8540/**
8541 * @file menu-item.js
8542 */
8543'use strict';
8544
8545exports.__esModule = true;
8546
8547function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8548
8549function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
8550
8551function _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; }
8552
8553var _clickableComponentJs = _dereq_('../clickable-component.js');
8554
8555var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs);
8556
8557var _componentJs = _dereq_('../component.js');
8558
8559var _componentJs2 = _interopRequireDefault(_componentJs);
8560
8561var _objectAssign = _dereq_('object.assign');
8562
8563var _objectAssign2 = _interopRequireDefault(_objectAssign);
8564
8565/**
8566 * The component for a menu item. `<li>`
8567 *
8568 * @param {Player|Object} player
8569 * @param {Object=} options
8570 * @extends Button
8571 * @class MenuItem
8572 */
8573
8574var MenuItem = (function (_ClickableComponent) {
8575 _inherits(MenuItem, _ClickableComponent);
8576
8577 function MenuItem(player, options) {
8578 _classCallCheck(this, MenuItem);
8579
8580 _ClickableComponent.call(this, player, options);
8581
8582 this.selectable = options['selectable'];
8583
8584 this.selected(options['selected']);
8585
8586 if (this.selectable) {
8587 // TODO: May need to be either menuitemcheckbox or menuitemradio,
8588 // and may need logical grouping of menu items.
8589 this.el_.setAttribute('role', 'menuitemcheckbox');
8590 } else {
8591 this.el_.setAttribute('role', 'menuitem');
8592 }
8593 }
8594
8595 /**
8596 * Create the component's DOM element
8597 *
8598 * @param {String=} type Desc
8599 * @param {Object=} props Desc
8600 * @return {Element}
8601 * @method createEl
8602 */
8603
8604 MenuItem.prototype.createEl = function createEl(type, props, attrs) {
8605 return _ClickableComponent.prototype.createEl.call(this, 'li', _objectAssign2['default']({
8606 className: 'vjs-menu-item',
8607 innerHTML: this.localize(this.options_['label']),
8608 tabIndex: -1
8609 }, props), attrs);
8610 };
8611
8612 /**
8613 * Handle a click on the menu item, and set it to selected
8614 *
8615 * @method handleClick
8616 */
8617
8618 MenuItem.prototype.handleClick = function handleClick() {
8619 this.selected(true);
8620 };
8621
8622 /**
8623 * Set this menu item as selected or not
8624 *
8625 * @param {Boolean} selected
8626 * @method selected
8627 */
8628
8629 MenuItem.prototype.selected = function selected(_selected) {
8630 if (this.selectable) {
8631 if (_selected) {
8632 this.addClass('vjs-selected');
8633 this.el_.setAttribute('aria-checked', true);
8634 // aria-checked isn't fully supported by browsers/screen readers,
8635 // so indicate selected state to screen reader in the control text.
8636 this.controlText(', selected');
8637 } else {
8638 this.removeClass('vjs-selected');
8639 this.el_.setAttribute('aria-checked', false);
8640 // Indicate un-selected state to screen reader
8641 // Note that a space clears out the selected state text
8642 this.controlText(' ');
8643 }
8644 }
8645 };
8646
8647 return MenuItem;
8648})(_clickableComponentJs2['default']);
8649
8650_componentJs2['default'].registerComponent('MenuItem', MenuItem);
8651exports['default'] = MenuItem;
8652module.exports = exports['default'];
8653
8654},{"../clickable-component.js":65,"../component.js":67,"object.assign":45}],106:[function(_dereq_,module,exports){
8655/**
8656 * @file menu.js
8657 */
8658'use strict';
8659
8660exports.__esModule = true;
8661
8662function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
8663
8664function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8665
8666function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
8667
8668function _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; }
8669
8670var _componentJs = _dereq_('../component.js');
8671
8672var _componentJs2 = _interopRequireDefault(_componentJs);
8673
8674var _utilsDomJs = _dereq_('../utils/dom.js');
8675
8676var Dom = _interopRequireWildcard(_utilsDomJs);
8677
8678var _utilsFnJs = _dereq_('../utils/fn.js');
8679
8680var Fn = _interopRequireWildcard(_utilsFnJs);
8681
8682var _utilsEventsJs = _dereq_('../utils/events.js');
8683
8684var Events = _interopRequireWildcard(_utilsEventsJs);
8685
8686/**
8687 * The Menu component is used to build pop up menus, including subtitle and
8688 * captions selection menus.
8689 *
8690 * @extends Component
8691 * @class Menu
8692 */
8693
8694var Menu = (function (_Component) {
8695 _inherits(Menu, _Component);
8696
8697 function Menu(player, options) {
8698 _classCallCheck(this, Menu);
8699
8700 _Component.call(this, player, options);
8701
8702 this.focusedChild_ = -1;
8703
8704 this.on('keydown', this.handleKeyPress);
8705 }
8706
8707 /**
8708 * Add a menu item to the menu
8709 *
8710 * @param {Object|String} component Component or component type to add
8711 * @method addItem
8712 */
8713
8714 Menu.prototype.addItem = function addItem(component) {
8715 this.addChild(component);
8716 component.on('click', Fn.bind(this, function () {
8717 this.unlockShowing();
8718 //TODO: Need to set keyboard focus back to the menuButton
8719 }));
8720 };
8721
8722 /**
8723 * Create the component's DOM element
8724 *
8725 * @return {Element}
8726 * @method createEl
8727 */
8728
8729 Menu.prototype.createEl = function createEl() {
8730 var contentElType = this.options_.contentElType || 'ul';
8731 this.contentEl_ = Dom.createEl(contentElType, {
8732 className: 'vjs-menu-content'
8733 });
8734 this.contentEl_.setAttribute('role', 'menu');
8735 var el = _Component.prototype.createEl.call(this, 'div', {
8736 append: this.contentEl_,
8737 className: 'vjs-menu'
8738 });
8739 el.setAttribute('role', 'presentation');
8740 el.appendChild(this.contentEl_);
8741
8742 // Prevent clicks from bubbling up. Needed for Menu Buttons,
8743 // where a click on the parent is significant
8744 Events.on(el, 'click', function (event) {
8745 event.preventDefault();
8746 event.stopImmediatePropagation();
8747 });
8748
8749 return el;
8750 };
8751
8752 /**
8753 * Handle key press for menu
8754 *
8755 * @param {Object} event Event object
8756 * @method handleKeyPress
8757 */
8758
8759 Menu.prototype.handleKeyPress = function handleKeyPress(event) {
8760 if (event.which === 37 || event.which === 40) {
8761 // Left and Down Arrows
8762 event.preventDefault();
8763 this.stepForward();
8764 } else if (event.which === 38 || event.which === 39) {
8765 // Up and Right Arrows
8766 event.preventDefault();
8767 this.stepBack();
8768 }
8769 };
8770
8771 /**
8772 * Move to next (lower) menu item for keyboard users
8773 *
8774 * @method stepForward
8775 */
8776
8777 Menu.prototype.stepForward = function stepForward() {
8778 var stepChild = 0;
8779
8780 if (this.focusedChild_ !== undefined) {
8781 stepChild = this.focusedChild_ + 1;
8782 }
8783 this.focus(stepChild);
8784 };
8785
8786 /**
8787 * Move to previous (higher) menu item for keyboard users
8788 *
8789 * @method stepBack
8790 */
8791
8792 Menu.prototype.stepBack = function stepBack() {
8793 var stepChild = 0;
8794
8795 if (this.focusedChild_ !== undefined) {
8796 stepChild = this.focusedChild_ - 1;
8797 }
8798 this.focus(stepChild);
8799 };
8800
8801 /**
8802 * Set focus on a menu item in the menu
8803 *
8804 * @param {Object|String} item Index of child item set focus on
8805 * @method focus
8806 */
8807
8808 Menu.prototype.focus = function focus() {
8809 var item = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
8810
8811 var children = this.children().slice();
8812 var haveTitle = children.length && children[0].className && /vjs-menu-title/.test(children[0].className);
8813
8814 if (haveTitle) {
8815 children.shift();
8816 }
8817
8818 if (children.length > 0) {
8819 if (item < 0) {
8820 item = 0;
8821 } else if (item >= children.length) {
8822 item = children.length - 1;
8823 }
8824
8825 this.focusedChild_ = item;
8826
8827 children[item].el_.focus();
8828 }
8829 };
8830
8831 return Menu;
8832})(_componentJs2['default']);
8833
8834_componentJs2['default'].registerComponent('Menu', Menu);
8835exports['default'] = Menu;
8836module.exports = exports['default'];
8837
8838},{"../component.js":67,"../utils/dom.js":132,"../utils/events.js":133,"../utils/fn.js":134}],107:[function(_dereq_,module,exports){
8839/**
8840 * @file modal-dialog.js
8841 */
8842'use strict';
8843
8844exports.__esModule = true;
8845
8846function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
8847
8848function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8849
8850function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
8851
8852function _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; }
8853
8854var _globalDocument = _dereq_('global/document');
8855
8856var _globalDocument2 = _interopRequireDefault(_globalDocument);
8857
8858var _utilsDom = _dereq_('./utils/dom');
8859
8860var Dom = _interopRequireWildcard(_utilsDom);
8861
8862var _utilsFn = _dereq_('./utils/fn');
8863
8864var Fn = _interopRequireWildcard(_utilsFn);
8865
8866var _utilsLog = _dereq_('./utils/log');
8867
8868var _utilsLog2 = _interopRequireDefault(_utilsLog);
8869
8870var _component = _dereq_('./component');
8871
8872var _component2 = _interopRequireDefault(_component);
8873
8874var _closeButton = _dereq_('./close-button');
8875
8876var _closeButton2 = _interopRequireDefault(_closeButton);
8877
8878var MODAL_CLASS_NAME = 'vjs-modal-dialog';
8879var ESC = 27;
8880
8881/**
8882 * The `ModalDialog` displays over the video and its controls, which blocks
8883 * interaction with the player until it is closed.
8884 *
8885 * Modal dialogs include a "Close" button and will close when that button
8886 * is activated - or when ESC is pressed anywhere.
8887 *
8888 * @extends Component
8889 * @class ModalDialog
8890 */
8891
8892var ModalDialog = (function (_Component) {
8893 _inherits(ModalDialog, _Component);
8894
8895 /**
8896 * Constructor for modals.
8897 *
8898 * @param {Player} player
8899 * @param {Object} [options]
8900 * @param {Mixed} [options.content=undefined]
8901 * Provide customized content for this modal.
8902 *
8903 * @param {String} [options.description]
8904 * A text description for the modal, primarily for accessibility.
8905 *
8906 * @param {Boolean} [options.fillAlways=false]
8907 * Normally, modals are automatically filled only the first time
8908 * they open. This tells the modal to refresh its content
8909 * every time it opens.
8910 *
8911 * @param {String} [options.label]
8912 * A text label for the modal, primarily for accessibility.
8913 *
8914 * @param {Boolean} [options.temporary=true]
8915 * If `true`, the modal can only be opened once; it will be
8916 * disposed as soon as it's closed.
8917 *
8918 * @param {Boolean} [options.uncloseable=false]
8919 * If `true`, the user will not be able to close the modal
8920 * through the UI in the normal ways. Programmatic closing is
8921 * still possible.
8922 *
8923 */
8924
8925 function ModalDialog(player, options) {
8926 _classCallCheck(this, ModalDialog);
8927
8928 _Component.call(this, player, options);
8929 this.opened_ = this.hasBeenOpened_ = this.hasBeenFilled_ = false;
8930
8931 this.closeable(!this.options_.uncloseable);
8932 this.content(this.options_.content);
8933
8934 // Make sure the contentEl is defined AFTER any children are initialized
8935 // because we only want the contents of the modal in the contentEl
8936 // (not the UI elements like the close button).
8937 this.contentEl_ = Dom.createEl('div', {
8938 className: MODAL_CLASS_NAME + '-content'
8939 }, {
8940 role: 'document'
8941 });
8942
8943 this.descEl_ = Dom.createEl('p', {
8944 className: MODAL_CLASS_NAME + '-description vjs-offscreen',
8945 id: this.el().getAttribute('aria-describedby')
8946 });
8947
8948 Dom.textContent(this.descEl_, this.description());
8949 this.el_.appendChild(this.descEl_);
8950 this.el_.appendChild(this.contentEl_);
8951 }
8952
8953 /*
8954 * Modal dialog default options.
8955 *
8956 * @type {Object}
8957 * @private
8958 */
8959
8960 /**
8961 * Create the modal's DOM element
8962 *
8963 * @method createEl
8964 * @return {Element}
8965 */
8966
8967 ModalDialog.prototype.createEl = function createEl() {
8968 return _Component.prototype.createEl.call(this, 'div', {
8969 className: this.buildCSSClass(),
8970 tabIndex: -1
8971 }, {
8972 'aria-describedby': this.id() + '_description',
8973 'aria-hidden': 'true',
8974 'aria-label': this.label(),
8975 role: 'dialog'
8976 });
8977 };
8978
8979 /**
8980 * Build the modal's CSS class.
8981 *
8982 * @method buildCSSClass
8983 * @return {String}
8984 */
8985
8986 ModalDialog.prototype.buildCSSClass = function buildCSSClass() {
8987 return MODAL_CLASS_NAME + ' vjs-hidden ' + _Component.prototype.buildCSSClass.call(this);
8988 };
8989
8990 /**
8991 * Handles key presses on the document, looking for ESC, which closes
8992 * the modal.
8993 *
8994 * @method handleKeyPress
8995 * @param {Event} e
8996 */
8997
8998 ModalDialog.prototype.handleKeyPress = function handleKeyPress(e) {
8999 if (e.which === ESC && this.closeable()) {
9000 this.close();
9001 }
9002 };
9003
9004 /**
9005 * Returns the label string for this modal. Primarily used for accessibility.
9006 *
9007 * @return {String}
9008 */
9009
9010 ModalDialog.prototype.label = function label() {
9011 return this.options_.label || this.localize('Modal Window');
9012 };
9013
9014 /**
9015 * Returns the description string for this modal. Primarily used for
9016 * accessibility.
9017 *
9018 * @return {String}
9019 */
9020
9021 ModalDialog.prototype.description = function description() {
9022 var desc = this.options_.description || this.localize('This is a modal window.');
9023
9024 // Append a universal closeability message if the modal is closeable.
9025 if (this.closeable()) {
9026 desc += ' ' + this.localize('This modal can be closed by pressing the Escape key or activating the close button.');
9027 }
9028
9029 return desc;
9030 };
9031
9032 /**
9033 * Opens the modal.
9034 *
9035 * @method open
9036 * @return {ModalDialog}
9037 */
9038
9039 ModalDialog.prototype.open = function open() {
9040 if (!this.opened_) {
9041 var player = this.player();
9042
9043 this.trigger('beforemodalopen');
9044 this.opened_ = true;
9045
9046 // Fill content if the modal has never opened before and
9047 // never been filled.
9048 if (this.options_.fillAlways || !this.hasBeenOpened_ && !this.hasBeenFilled_) {
9049 this.fill();
9050 }
9051
9052 // If the player was playing, pause it and take note of its previously
9053 // playing state.
9054 this.wasPlaying_ = !player.paused();
9055
9056 if (this.wasPlaying_) {
9057 player.pause();
9058 }
9059
9060 if (this.closeable()) {
9061 this.on(_globalDocument2['default'], 'keydown', Fn.bind(this, this.handleKeyPress));
9062 }
9063
9064 player.controls(false);
9065 this.show();
9066 this.el().setAttribute('aria-hidden', 'false');
9067 this.trigger('modalopen');
9068 this.hasBeenOpened_ = true;
9069 }
9070 return this;
9071 };
9072
9073 /**
9074 * Whether or not the modal is opened currently.
9075 *
9076 * @method opened
9077 * @param {Boolean} [value]
9078 * If given, it will open (`true`) or close (`false`) the modal.
9079 *
9080 * @return {Boolean}
9081 */
9082
9083 ModalDialog.prototype.opened = function opened(value) {
9084 if (typeof value === 'boolean') {
9085 this[value ? 'open' : 'close']();
9086 }
9087 return this.opened_;
9088 };
9089
9090 /**
9091 * Closes the modal.
9092 *
9093 * @method close
9094 * @return {ModalDialog}
9095 */
9096
9097 ModalDialog.prototype.close = function close() {
9098 if (this.opened_) {
9099 var player = this.player();
9100
9101 this.trigger('beforemodalclose');
9102 this.opened_ = false;
9103
9104 if (this.wasPlaying_) {
9105 player.play();
9106 }
9107
9108 if (this.closeable()) {
9109 this.off(_globalDocument2['default'], 'keydown', Fn.bind(this, this.handleKeyPress));
9110 }
9111
9112 player.controls(true);
9113 this.hide();
9114 this.el().setAttribute('aria-hidden', 'true');
9115 this.trigger('modalclose');
9116
9117 if (this.options_.temporary) {
9118 this.dispose();
9119 }
9120 }
9121 return this;
9122 };
9123
9124 /**
9125 * Whether or not the modal is closeable via the UI.
9126 *
9127 * @method closeable
9128 * @param {Boolean} [value]
9129 * If given as a Boolean, it will set the `closeable` option.
9130 *
9131 * @return {Boolean}
9132 */
9133
9134 ModalDialog.prototype.closeable = function closeable(value) {
9135 if (typeof value === 'boolean') {
9136 var closeable = this.closeable_ = !!value;
9137 var _close = this.getChild('closeButton');
9138
9139 // If this is being made closeable and has no close button, add one.
9140 if (closeable && !_close) {
9141
9142 // The close button should be a child of the modal - not its
9143 // content element, so temporarily change the content element.
9144 var temp = this.contentEl_;
9145 this.contentEl_ = this.el_;
9146 _close = this.addChild('closeButton');
9147 this.contentEl_ = temp;
9148 this.on(_close, 'close', this.close);
9149 }
9150
9151 // If this is being made uncloseable and has a close button, remove it.
9152 if (!closeable && _close) {
9153 this.off(_close, 'close', this.close);
9154 this.removeChild(_close);
9155 _close.dispose();
9156 }
9157 }
9158 return this.closeable_;
9159 };
9160
9161 /**
9162 * Fill the modal's content element with the modal's "content" option.
9163 *
9164 * The content element will be emptied before this change takes place.
9165 *
9166 * @method fill
9167 * @return {ModalDialog}
9168 */
9169
9170 ModalDialog.prototype.fill = function fill() {
9171 return this.fillWith(this.content());
9172 };
9173
9174 /**
9175 * Fill the modal's content element with arbitrary content.
9176 *
9177 * The content element will be emptied before this change takes place.
9178 *
9179 * @method fillWith
9180 * @param {Mixed} [content]
9181 * The same rules apply to this as apply to the `content` option.
9182 *
9183 * @return {ModalDialog}
9184 */
9185
9186 ModalDialog.prototype.fillWith = function fillWith(content) {
9187 var contentEl = this.contentEl();
9188 var parentEl = contentEl.parentNode;
9189 var nextSiblingEl = contentEl.nextSibling;
9190
9191 this.trigger('beforemodalfill');
9192 this.hasBeenFilled_ = true;
9193
9194 // Detach the content element from the DOM before performing
9195 // manipulation to avoid modifying the live DOM multiple times.
9196 parentEl.removeChild(contentEl);
9197 this.empty();
9198 Dom.insertContent(contentEl, content);
9199 this.trigger('modalfill');
9200
9201 // Re-inject the re-filled content element.
9202 if (nextSiblingEl) {
9203 parentEl.insertBefore(contentEl, nextSiblingEl);
9204 } else {
9205 parentEl.appendChild(contentEl);
9206 }
9207
9208 return this;
9209 };
9210
9211 /**
9212 * Empties the content element.
9213 *
9214 * This happens automatically anytime the modal is filled.
9215 *
9216 * @method empty
9217 * @return {ModalDialog}
9218 */
9219
9220 ModalDialog.prototype.empty = function empty() {
9221 this.trigger('beforemodalempty');
9222 Dom.emptyEl(this.contentEl());
9223 this.trigger('modalempty');
9224 return this;
9225 };
9226
9227 /**
9228 * Gets or sets the modal content, which gets normalized before being
9229 * rendered into the DOM.
9230 *
9231 * This does not update the DOM or fill the modal, but it is called during
9232 * that process.
9233 *
9234 * @method content
9235 * @param {Mixed} [value]
9236 * If defined, sets the internal content value to be used on the
9237 * next call(s) to `fill`. This value is normalized before being
9238 * inserted. To "clear" the internal content value, pass `null`.
9239 *
9240 * @return {Mixed}
9241 */
9242
9243 ModalDialog.prototype.content = function content(value) {
9244 if (typeof value !== 'undefined') {
9245 this.content_ = value;
9246 }
9247 return this.content_;
9248 };
9249
9250 return ModalDialog;
9251})(_component2['default']);
9252
9253ModalDialog.prototype.options_ = {
9254 temporary: true
9255};
9256
9257_component2['default'].registerComponent('ModalDialog', ModalDialog);
9258exports['default'] = ModalDialog;
9259module.exports = exports['default'];
9260
9261},{"./close-button":66,"./component":67,"./utils/dom":132,"./utils/fn":134,"./utils/log":137,"global/document":1}],108:[function(_dereq_,module,exports){
9262/**
9263 * @file player.js
9264 */
9265// Subclasses Component
9266'use strict';
9267
9268exports.__esModule = true;
9269
9270function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
9271
9272function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
9273
9274function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
9275
9276function _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; }
9277
9278var _componentJs = _dereq_('./component.js');
9279
9280var _componentJs2 = _interopRequireDefault(_componentJs);
9281
9282var _globalDocument = _dereq_('global/document');
9283
9284var _globalDocument2 = _interopRequireDefault(_globalDocument);
9285
9286var _globalWindow = _dereq_('global/window');
9287
9288var _globalWindow2 = _interopRequireDefault(_globalWindow);
9289
9290var _utilsEventsJs = _dereq_('./utils/events.js');
9291
9292var Events = _interopRequireWildcard(_utilsEventsJs);
9293
9294var _utilsDomJs = _dereq_('./utils/dom.js');
9295
9296var Dom = _interopRequireWildcard(_utilsDomJs);
9297
9298var _utilsFnJs = _dereq_('./utils/fn.js');
9299
9300var Fn = _interopRequireWildcard(_utilsFnJs);
9301
9302var _utilsGuidJs = _dereq_('./utils/guid.js');
9303
9304var Guid = _interopRequireWildcard(_utilsGuidJs);
9305
9306var _utilsBrowserJs = _dereq_('./utils/browser.js');
9307
9308var browser = _interopRequireWildcard(_utilsBrowserJs);
9309
9310var _utilsLogJs = _dereq_('./utils/log.js');
9311
9312var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
9313
9314var _utilsToTitleCaseJs = _dereq_('./utils/to-title-case.js');
9315
9316var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs);
9317
9318var _utilsTimeRangesJs = _dereq_('./utils/time-ranges.js');
9319
9320var _utilsBufferJs = _dereq_('./utils/buffer.js');
9321
9322var _utilsStylesheetJs = _dereq_('./utils/stylesheet.js');
9323
9324var stylesheet = _interopRequireWildcard(_utilsStylesheetJs);
9325
9326var _fullscreenApiJs = _dereq_('./fullscreen-api.js');
9327
9328var _fullscreenApiJs2 = _interopRequireDefault(_fullscreenApiJs);
9329
9330var _mediaErrorJs = _dereq_('./media-error.js');
9331
9332var _mediaErrorJs2 = _interopRequireDefault(_mediaErrorJs);
9333
9334var _safeJsonParseTuple = _dereq_('safe-json-parse/tuple');
9335
9336var _safeJsonParseTuple2 = _interopRequireDefault(_safeJsonParseTuple);
9337
9338var _objectAssign = _dereq_('object.assign');
9339
9340var _objectAssign2 = _interopRequireDefault(_objectAssign);
9341
9342var _utilsMergeOptionsJs = _dereq_('./utils/merge-options.js');
9343
9344var _utilsMergeOptionsJs2 = _interopRequireDefault(_utilsMergeOptionsJs);
9345
9346var _tracksTextTrackListConverterJs = _dereq_('./tracks/text-track-list-converter.js');
9347
9348var _tracksTextTrackListConverterJs2 = _interopRequireDefault(_tracksTextTrackListConverterJs);
9349
9350// Include required child components (importing also registers them)
9351
9352var _techLoaderJs = _dereq_('./tech/loader.js');
9353
9354var _techLoaderJs2 = _interopRequireDefault(_techLoaderJs);
9355
9356var _posterImageJs = _dereq_('./poster-image.js');
9357
9358var _posterImageJs2 = _interopRequireDefault(_posterImageJs);
9359
9360var _tracksTextTrackDisplayJs = _dereq_('./tracks/text-track-display.js');
9361
9362var _tracksTextTrackDisplayJs2 = _interopRequireDefault(_tracksTextTrackDisplayJs);
9363
9364var _loadingSpinnerJs = _dereq_('./loading-spinner.js');
9365
9366var _loadingSpinnerJs2 = _interopRequireDefault(_loadingSpinnerJs);
9367
9368var _bigPlayButtonJs = _dereq_('./big-play-button.js');
9369
9370var _bigPlayButtonJs2 = _interopRequireDefault(_bigPlayButtonJs);
9371
9372var _controlBarControlBarJs = _dereq_('./control-bar/control-bar.js');
9373
9374var _controlBarControlBarJs2 = _interopRequireDefault(_controlBarControlBarJs);
9375
9376var _errorDisplayJs = _dereq_('./error-display.js');
9377
9378var _errorDisplayJs2 = _interopRequireDefault(_errorDisplayJs);
9379
9380var _tracksTextTrackSettingsJs = _dereq_('./tracks/text-track-settings.js');
9381
9382var _tracksTextTrackSettingsJs2 = _interopRequireDefault(_tracksTextTrackSettingsJs);
9383
9384var _modalDialog = _dereq_('./modal-dialog');
9385
9386var _modalDialog2 = _interopRequireDefault(_modalDialog);
9387
9388// Require html5 tech, at least for disposing the original video tag
9389
9390var _techTechJs = _dereq_('./tech/tech.js');
9391
9392var _techTechJs2 = _interopRequireDefault(_techTechJs);
9393
9394var _techHtml5Js = _dereq_('./tech/html5.js');
9395
9396var _techHtml5Js2 = _interopRequireDefault(_techHtml5Js);
9397
9398/**
9399 * An instance of the `Player` class is created when any of the Video.js setup methods are used to initialize a video.
9400 * ```js
9401 * var myPlayer = videojs('example_video_1');
9402 * ```
9403 * In the following example, the `data-setup` attribute tells the Video.js library to create a player instance when the library is ready.
9404 * ```html
9405 * <video id="example_video_1" data-setup='{}' controls>
9406 * <source src="my-source.mp4" type="video/mp4">
9407 * </video>
9408 * ```
9409 * After an instance has been created it can be accessed globally using `Video('example_video_1')`.
9410 *
9411 * @param {Element} tag The original video tag used for configuring options
9412 * @param {Object=} options Object of option names and values
9413 * @param {Function=} ready Ready callback function
9414 * @extends Component
9415 * @class Player
9416 */
9417
9418var Player = (function (_Component) {
9419 _inherits(Player, _Component);
9420
9421 /**
9422 * player's constructor function
9423 *
9424 * @constructs
9425 * @method init
9426 * @param {Element} tag The original video tag used for configuring options
9427 * @param {Object=} options Player options
9428 * @param {Function=} ready Ready callback function
9429 */
9430
9431 function Player(tag, options, ready) {
9432 var _this = this;
9433
9434 _classCallCheck(this, Player);
9435
9436 // Make sure tag ID exists
9437 tag.id = tag.id || 'vjs_video_' + Guid.newGUID();
9438
9439 // Set Options
9440 // The options argument overrides options set in the video tag
9441 // which overrides globally set options.
9442 // This latter part coincides with the load order
9443 // (tag must exist before Player)
9444 options = _objectAssign2['default'](Player.getTagSettings(tag), options);
9445
9446 // Delay the initialization of children because we need to set up
9447 // player properties first, and can't use `this` before `super()`
9448 options.initChildren = false;
9449
9450 // Same with creating the element
9451 options.createEl = false;
9452
9453 // we don't want the player to report touch activity on itself
9454 // see enableTouchActivity in Component
9455 options.reportTouchActivity = false;
9456
9457 // Run base component initializing with new options
9458 _Component.call(this, null, options, ready);
9459
9460 // if the global option object was accidentally blown away by
9461 // someone, bail early with an informative error
9462 if (!this.options_ || !this.options_.techOrder || !this.options_.techOrder.length) {
9463 throw new Error('No techOrder specified. Did you overwrite ' + 'videojs.options instead of just changing the ' + 'properties you want to override?');
9464 }
9465
9466 this.tag = tag; // Store the original tag used to set options
9467
9468 // Store the tag attributes used to restore html5 element
9469 this.tagAttributes = tag && Dom.getElAttributes(tag);
9470
9471 // Update current language
9472 this.language(this.options_.language);
9473
9474 // Update Supported Languages
9475 if (options.languages) {
9476 (function () {
9477 // Normalise player option languages to lowercase
9478 var languagesToLower = {};
9479
9480 Object.getOwnPropertyNames(options.languages).forEach(function (name) {
9481 languagesToLower[name.toLowerCase()] = options.languages[name];
9482 });
9483 _this.languages_ = languagesToLower;
9484 })();
9485 } else {
9486 this.languages_ = Player.prototype.options_.languages;
9487 }
9488
9489 // Cache for video property values.
9490 this.cache_ = {};
9491
9492 // Set poster
9493 this.poster_ = options.poster || '';
9494
9495 // Set controls
9496 this.controls_ = !!options.controls;
9497
9498 // Original tag settings stored in options
9499 // now remove immediately so native controls don't flash.
9500 // May be turned back on by HTML5 tech if nativeControlsForTouch is true
9501 tag.controls = false;
9502
9503 /*
9504 * Store the internal state of scrubbing
9505 *
9506 * @private
9507 * @return {Boolean} True if the user is scrubbing
9508 */
9509 this.scrubbing_ = false;
9510
9511 this.el_ = this.createEl();
9512
9513 // We also want to pass the original player options to each component and plugin
9514 // as well so they don't need to reach back into the player for options later.
9515 // We also need to do another copy of this.options_ so we don't end up with
9516 // an infinite loop.
9517 var playerOptionsCopy = _utilsMergeOptionsJs2['default'](this.options_);
9518
9519 // Load plugins
9520 if (options.plugins) {
9521 (function () {
9522 var plugins = options.plugins;
9523
9524 Object.getOwnPropertyNames(plugins).forEach(function (name) {
9525 if (typeof this[name] === 'function') {
9526 this[name](plugins[name]);
9527 } else {
9528 _utilsLogJs2['default'].error('Unable to find plugin:', name);
9529 }
9530 }, _this);
9531 })();
9532 }
9533
9534 this.options_.playerOptions = playerOptionsCopy;
9535
9536 this.initChildren();
9537
9538 // Set isAudio based on whether or not an audio tag was used
9539 this.isAudio(tag.nodeName.toLowerCase() === 'audio');
9540
9541 // Update controls className. Can't do this when the controls are initially
9542 // set because the element doesn't exist yet.
9543 if (this.controls()) {
9544 this.addClass('vjs-controls-enabled');
9545 } else {
9546 this.addClass('vjs-controls-disabled');
9547 }
9548
9549 if (this.isAudio()) {
9550 this.addClass('vjs-audio');
9551 }
9552
9553 if (this.flexNotSupported_()) {
9554 this.addClass('vjs-no-flex');
9555 }
9556
9557 // TODO: Make this smarter. Toggle user state between touching/mousing
9558 // using events, since devices can have both touch and mouse events.
9559 // if (browser.TOUCH_ENABLED) {
9560 // this.addClass('vjs-touch-enabled');
9561 // }
9562
9563 // iOS Safari has broken hover handling
9564 if (!browser.IS_IOS) {
9565 this.addClass('vjs-workinghover');
9566 }
9567
9568 // Make player easily findable by ID
9569 Player.players[this.id_] = this;
9570
9571 // When the player is first initialized, trigger activity so components
9572 // like the control bar show themselves if needed
9573 this.userActive(true);
9574 this.reportUserActivity();
9575 this.listenForUserActivity_();
9576
9577 this.on('fullscreenchange', this.handleFullscreenChange_);
9578 this.on('stageclick', this.handleStageClick_);
9579 }
9580
9581 /*
9582 * Global player list
9583 *
9584 * @type {Object}
9585 */
9586
9587 /**
9588 * Destroys the video player and does any necessary cleanup
9589 * ```js
9590 * myPlayer.dispose();
9591 * ```
9592 * This is especially helpful if you are dynamically adding and removing videos
9593 * to/from the DOM.
9594 *
9595 * @method dispose
9596 */
9597
9598 Player.prototype.dispose = function dispose() {
9599 this.trigger('dispose');
9600 // prevent dispose from being called twice
9601 this.off('dispose');
9602
9603 if (this.styleEl_ && this.styleEl_.parentNode) {
9604 this.styleEl_.parentNode.removeChild(this.styleEl_);
9605 }
9606
9607 // Kill reference to this player
9608 Player.players[this.id_] = null;
9609 if (this.tag && this.tag.player) {
9610 this.tag.player = null;
9611 }
9612 if (this.el_ && this.el_.player) {
9613 this.el_.player = null;
9614 }
9615
9616 if (this.tech_) {
9617 this.tech_.dispose();
9618 }
9619
9620 _Component.prototype.dispose.call(this);
9621 };
9622
9623 /**
9624 * Create the component's DOM element
9625 *
9626 * @return {Element}
9627 * @method createEl
9628 */
9629
9630 Player.prototype.createEl = function createEl() {
9631 var el = this.el_ = _Component.prototype.createEl.call(this, 'div');
9632 var tag = this.tag;
9633
9634 // Remove width/height attrs from tag so CSS can make it 100% width/height
9635 tag.removeAttribute('width');
9636 tag.removeAttribute('height');
9637
9638 // Copy over all the attributes from the tag, including ID and class
9639 // ID will now reference player box, not the video tag
9640 var attrs = Dom.getElAttributes(tag);
9641
9642 Object.getOwnPropertyNames(attrs).forEach(function (attr) {
9643 // workaround so we don't totally break IE7
9644 // http://stackoverflow.com/questions/3653444/css-styles-not-applied-on-dynamic-elements-in-internet-explorer-7
9645 if (attr === 'class') {
9646 el.className = attrs[attr];
9647 } else {
9648 el.setAttribute(attr, attrs[attr]);
9649 }
9650 });
9651
9652 // Update tag id/class for use as HTML5 playback tech
9653 // Might think we should do this after embedding in container so .vjs-tech class
9654 // doesn't flash 100% width/height, but class only applies with .video-js parent
9655 tag.playerId = tag.id;
9656 tag.id += '_html5_api';
9657 tag.className = 'vjs-tech';
9658
9659 // Make player findable on elements
9660 tag.player = el.player = this;
9661 // Default state of video is paused
9662 this.addClass('vjs-paused');
9663
9664 // Add a style element in the player that we'll use to set the width/height
9665 // of the player in a way that's still overrideable by CSS, just like the
9666 // video element
9667 this.styleEl_ = stylesheet.createStyleElement('vjs-styles-dimensions');
9668 var defaultsStyleEl = Dom.$('.vjs-styles-defaults');
9669 var head = Dom.$('head');
9670 head.insertBefore(this.styleEl_, defaultsStyleEl ? defaultsStyleEl.nextSibling : head.firstChild);
9671
9672 // Pass in the width/height/aspectRatio options which will update the style el
9673 this.width(this.options_.width);
9674 this.height(this.options_.height);
9675 this.fluid(this.options_.fluid);
9676 this.aspectRatio(this.options_.aspectRatio);
9677
9678 // insertElFirst seems to cause the networkState to flicker from 3 to 2, so
9679 // keep track of the original for later so we can know if the source originally failed
9680 tag.initNetworkState_ = tag.networkState;
9681
9682 // Wrap video tag in div (el/box) container
9683 if (tag.parentNode) {
9684 tag.parentNode.insertBefore(el, tag);
9685 }
9686
9687 // insert the tag as the first child of the player element
9688 // then manually add it to the children array so that this.addChild
9689 // will work properly for other components
9690 Dom.insertElFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup.
9691 this.children_.unshift(tag);
9692
9693 this.el_ = el;
9694
9695 return el;
9696 };
9697
9698 /**
9699 * Get/set player width
9700 *
9701 * @param {Number=} value Value for width
9702 * @return {Number} Width when getting
9703 * @method width
9704 */
9705
9706 Player.prototype.width = function width(value) {
9707 return this.dimension('width', value);
9708 };
9709
9710 /**
9711 * Get/set player height
9712 *
9713 * @param {Number=} value Value for height
9714 * @return {Number} Height when getting
9715 * @method height
9716 */
9717
9718 Player.prototype.height = function height(value) {
9719 return this.dimension('height', value);
9720 };
9721
9722 /**
9723 * Get/set dimension for player
9724 *
9725 * @param {String} dimension Either width or height
9726 * @param {Number=} value Value for dimension
9727 * @return {Component}
9728 * @method dimension
9729 */
9730
9731 Player.prototype.dimension = function dimension(_dimension, value) {
9732 var privDimension = _dimension + '_';
9733
9734 if (value === undefined) {
9735 return this[privDimension] || 0;
9736 }
9737
9738 if (value === '') {
9739 // If an empty string is given, reset the dimension to be automatic
9740 this[privDimension] = undefined;
9741 } else {
9742 var parsedVal = parseFloat(value);
9743
9744 if (isNaN(parsedVal)) {
9745 _utilsLogJs2['default'].error('Improper value "' + value + '" supplied for for ' + _dimension);
9746 return this;
9747 }
9748
9749 this[privDimension] = parsedVal;
9750 }
9751
9752 this.updateStyleEl_();
9753 return this;
9754 };
9755
9756 /**
9757 * Add/remove the vjs-fluid class
9758 *
9759 * @param {Boolean} bool Value of true adds the class, value of false removes the class
9760 * @method fluid
9761 */
9762
9763 Player.prototype.fluid = function fluid(bool) {
9764 if (bool === undefined) {
9765 return !!this.fluid_;
9766 }
9767
9768 this.fluid_ = !!bool;
9769
9770 if (bool) {
9771 this.addClass('vjs-fluid');
9772 } else {
9773 this.removeClass('vjs-fluid');
9774 }
9775 };
9776
9777 /**
9778 * Get/Set the aspect ratio
9779 *
9780 * @param {String=} ratio Aspect ratio for player
9781 * @return aspectRatio
9782 * @method aspectRatio
9783 */
9784
9785 Player.prototype.aspectRatio = function aspectRatio(ratio) {
9786 if (ratio === undefined) {
9787 return this.aspectRatio_;
9788 }
9789
9790 // Check for width:height format
9791 if (!/^\d+\:\d+$/.test(ratio)) {
9792 throw new Error('Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.');
9793 }
9794 this.aspectRatio_ = ratio;
9795
9796 // We're assuming if you set an aspect ratio you want fluid mode,
9797 // because in fixed mode you could calculate width and height yourself.
9798 this.fluid(true);
9799
9800 this.updateStyleEl_();
9801 };
9802
9803 /**
9804 * Update styles of the player element (height, width and aspect ratio)
9805 *
9806 * @method updateStyleEl_
9807 */
9808
9809 Player.prototype.updateStyleEl_ = function updateStyleEl_() {
9810 var width = undefined;
9811 var height = undefined;
9812 var aspectRatio = undefined;
9813 var idClass = undefined;
9814
9815 // The aspect ratio is either used directly or to calculate width and height.
9816 if (this.aspectRatio_ !== undefined && this.aspectRatio_ !== 'auto') {
9817 // Use any aspectRatio that's been specifically set
9818 aspectRatio = this.aspectRatio_;
9819 } else if (this.videoWidth()) {
9820 // Otherwise try to get the aspect ratio from the video metadata
9821 aspectRatio = this.videoWidth() + ':' + this.videoHeight();
9822 } else {
9823 // Or use a default. The video element's is 2:1, but 16:9 is more common.
9824 aspectRatio = '16:9';
9825 }
9826
9827 // Get the ratio as a decimal we can use to calculate dimensions
9828 var ratioParts = aspectRatio.split(':');
9829 var ratioMultiplier = ratioParts[1] / ratioParts[0];
9830
9831 if (this.width_ !== undefined) {
9832 // Use any width that's been specifically set
9833 width = this.width_;
9834 } else if (this.height_ !== undefined) {
9835 // Or calulate the width from the aspect ratio if a height has been set
9836 width = this.height_ / ratioMultiplier;
9837 } else {
9838 // Or use the video's metadata, or use the video el's default of 300
9839 width = this.videoWidth() || 300;
9840 }
9841
9842 if (this.height_ !== undefined) {
9843 // Use any height that's been specifically set
9844 height = this.height_;
9845 } else {
9846 // Otherwise calculate the height from the ratio and the width
9847 height = width * ratioMultiplier;
9848 }
9849
9850 // Ensure the CSS class is valid by starting with an alpha character
9851 if (/^[^a-zA-Z]/.test(this.id())) {
9852 idClass = 'dimensions-' + this.id();
9853 } else {
9854 idClass = this.id() + '-dimensions';
9855 }
9856
9857 // Ensure the right class is still on the player for the style element
9858 this.addClass(idClass);
9859
9860 stylesheet.setTextContent(this.styleEl_, '\n .' + idClass + ' {\n width: ' + width + 'px;\n height: ' + height + 'px;\n }\n\n .' + idClass + '.vjs-fluid {\n padding-top: ' + ratioMultiplier * 100 + '%;\n }\n ');
9861 };
9862
9863 /**
9864 * Load the Media Playback Technology (tech)
9865 * Load/Create an instance of playback technology including element and API methods
9866 * And append playback element in player div.
9867 *
9868 * @param {String} techName Name of the playback technology
9869 * @param {String} source Video source
9870 * @method loadTech_
9871 * @private
9872 */
9873
9874 Player.prototype.loadTech_ = function loadTech_(techName, source) {
9875
9876 // Pause and remove current playback technology
9877 if (this.tech_) {
9878 this.unloadTech_();
9879 }
9880
9881 // get rid of the HTML5 video tag as soon as we are using another tech
9882 if (techName !== 'Html5' && this.tag) {
9883 _techTechJs2['default'].getTech('Html5').disposeMediaElement(this.tag);
9884 this.tag.player = null;
9885 this.tag = null;
9886 }
9887
9888 this.techName_ = techName;
9889
9890 // Turn off API access because we're loading a new tech that might load asynchronously
9891 this.isReady_ = false;
9892
9893 // Grab tech-specific options from player options and add source and parent element to use.
9894 var techOptions = _objectAssign2['default']({
9895 'nativeControlsForTouch': this.options_.nativeControlsForTouch,
9896 'source': source,
9897 'playerId': this.id(),
9898 'techId': this.id() + '_' + techName + '_api',
9899 'textTracks': this.textTracks_,
9900 'autoplay': this.options_.autoplay,
9901 'preload': this.options_.preload,
9902 'loop': this.options_.loop,
9903 'muted': this.options_.muted,
9904 'poster': this.poster(),
9905 'language': this.language(),
9906 'vtt.js': this.options_['vtt.js']
9907 }, this.options_[techName.toLowerCase()]);
9908
9909 if (this.tag) {
9910 techOptions.tag = this.tag;
9911 }
9912
9913 if (source) {
9914 this.currentType_ = source.type;
9915 if (source.src === this.cache_.src && this.cache_.currentTime > 0) {
9916 techOptions.startTime = this.cache_.currentTime;
9917 }
9918
9919 this.cache_.src = source.src;
9920 }
9921
9922 // Initialize tech instance
9923 var techComponent = _techTechJs2['default'].getTech(techName);
9924 // Support old behavior of techs being registered as components.
9925 // Remove once that deprecated behavior is removed.
9926 if (!techComponent) {
9927 techComponent = _componentJs2['default'].getComponent(techName);
9928 }
9929 this.tech_ = new techComponent(techOptions);
9930
9931 // player.triggerReady is always async, so don't need this to be async
9932 this.tech_.ready(Fn.bind(this, this.handleTechReady_), true);
9933
9934 _tracksTextTrackListConverterJs2['default'].jsonToTextTracks(this.textTracksJson_ || [], this.tech_);
9935
9936 // Listen to all HTML5-defined events and trigger them on the player
9937 this.on(this.tech_, 'loadstart', this.handleTechLoadStart_);
9938 this.on(this.tech_, 'waiting', this.handleTechWaiting_);
9939 this.on(this.tech_, 'canplay', this.handleTechCanPlay_);
9940 this.on(this.tech_, 'canplaythrough', this.handleTechCanPlayThrough_);
9941 this.on(this.tech_, 'playing', this.handleTechPlaying_);
9942 this.on(this.tech_, 'ended', this.handleTechEnded_);
9943 this.on(this.tech_, 'seeking', this.handleTechSeeking_);
9944 this.on(this.tech_, 'seeked', this.handleTechSeeked_);
9945 this.on(this.tech_, 'play', this.handleTechPlay_);
9946 this.on(this.tech_, 'firstplay', this.handleTechFirstPlay_);
9947 this.on(this.tech_, 'pause', this.handleTechPause_);
9948 this.on(this.tech_, 'progress', this.handleTechProgress_);
9949 this.on(this.tech_, 'durationchange', this.handleTechDurationChange_);
9950 this.on(this.tech_, 'fullscreenchange', this.handleTechFullscreenChange_);
9951 this.on(this.tech_, 'error', this.handleTechError_);
9952 this.on(this.tech_, 'suspend', this.handleTechSuspend_);
9953 this.on(this.tech_, 'abort', this.handleTechAbort_);
9954 this.on(this.tech_, 'emptied', this.handleTechEmptied_);
9955 this.on(this.tech_, 'stalled', this.handleTechStalled_);
9956 this.on(this.tech_, 'loadedmetadata', this.handleTechLoadedMetaData_);
9957 this.on(this.tech_, 'loadeddata', this.handleTechLoadedData_);
9958 this.on(this.tech_, 'timeupdate', this.handleTechTimeUpdate_);
9959 this.on(this.tech_, 'ratechange', this.handleTechRateChange_);
9960 this.on(this.tech_, 'volumechange', this.handleTechVolumeChange_);
9961 this.on(this.tech_, 'texttrackchange', this.handleTechTextTrackChange_);
9962 this.on(this.tech_, 'loadedmetadata', this.updateStyleEl_);
9963 this.on(this.tech_, 'posterchange', this.handleTechPosterChange_);
9964
9965 this.usingNativeControls(this.techGet_('controls'));
9966
9967 if (this.controls() && !this.usingNativeControls()) {
9968 this.addTechControlsListeners_();
9969 }
9970
9971 // Add the tech element in the DOM if it was not already there
9972 // Make sure to not insert the original video element if using Html5
9973 if (this.tech_.el().parentNode !== this.el() && (techName !== 'Html5' || !this.tag)) {
9974 Dom.insertElFirst(this.tech_.el(), this.el());
9975 }
9976
9977 // Get rid of the original video tag reference after the first tech is loaded
9978 if (this.tag) {
9979 this.tag.player = null;
9980 this.tag = null;
9981 }
9982 };
9983
9984 /**
9985 * Unload playback technology
9986 *
9987 * @method unloadTech_
9988 * @private
9989 */
9990
9991 Player.prototype.unloadTech_ = function unloadTech_() {
9992 // Save the current text tracks so that we can reuse the same text tracks with the next tech
9993 this.textTracks_ = this.textTracks();
9994 this.textTracksJson_ = _tracksTextTrackListConverterJs2['default'].textTracksToJson(this.tech_);
9995
9996 this.isReady_ = false;
9997
9998 this.tech_.dispose();
9999
10000 this.tech_ = false;
10001 };
10002
10003 /**
10004 * Return a reference to the current tech.
10005 * It will only return a reference to the tech if given an object with the
10006 * `IWillNotUseThisInPlugins` property on it. This is try and prevent misuse
10007 * of techs by plugins.
10008 *
10009 * @param {Object}
10010 * @return {Object} The Tech
10011 * @method tech
10012 */
10013
10014 Player.prototype.tech = function tech(safety) {
10015 if (safety && safety.IWillNotUseThisInPlugins) {
10016 return this.tech_;
10017 }
10018 var errorText = '\n Please make sure that you are not using this inside of a plugin.\n To disable this alert and error, please pass in an object with\n `IWillNotUseThisInPlugins` to the `tech` method. See\n https://github.com/videojs/video.js/issues/2617 for more info.\n ';
10019 _globalWindow2['default'].alert(errorText);
10020 throw new Error(errorText);
10021 };
10022
10023 /**
10024 * Set up click and touch listeners for the playback element
10025 *
10026 * On desktops, a click on the video itself will toggle playback,
10027 * on a mobile device a click on the video toggles controls.
10028 * (toggling controls is done by toggling the user state between active and
10029 * inactive)
10030 * A tap can signal that a user has become active, or has become inactive
10031 * e.g. a quick tap on an iPhone movie should reveal the controls. Another
10032 * quick tap should hide them again (signaling the user is in an inactive
10033 * viewing state)
10034 * In addition to this, we still want the user to be considered inactive after
10035 * a few seconds of inactivity.
10036 * Note: the only part of iOS interaction we can't mimic with this setup
10037 * is a touch and hold on the video element counting as activity in order to
10038 * keep the controls showing, but that shouldn't be an issue. A touch and hold
10039 * on any controls will still keep the user active
10040 *
10041 * @private
10042 * @method addTechControlsListeners_
10043 */
10044
10045 Player.prototype.addTechControlsListeners_ = function addTechControlsListeners_() {
10046 // Make sure to remove all the previous listeners in case we are called multiple times.
10047 this.removeTechControlsListeners_();
10048
10049 // Some browsers (Chrome & IE) don't trigger a click on a flash swf, but do
10050 // trigger mousedown/up.
10051 // http://stackoverflow.com/questions/1444562/javascript-onclick-event-over-flash-object
10052 // Any touch events are set to block the mousedown event from happening
10053 this.on(this.tech_, 'mousedown', this.handleTechClick_);
10054
10055 // If the controls were hidden we don't want that to change without a tap event
10056 // so we'll check if the controls were already showing before reporting user
10057 // activity
10058 this.on(this.tech_, 'touchstart', this.handleTechTouchStart_);
10059 this.on(this.tech_, 'touchmove', this.handleTechTouchMove_);
10060 this.on(this.tech_, 'touchend', this.handleTechTouchEnd_);
10061
10062 // The tap listener needs to come after the touchend listener because the tap
10063 // listener cancels out any reportedUserActivity when setting userActive(false)
10064 this.on(this.tech_, 'tap', this.handleTechTap_);
10065 };
10066
10067 /**
10068 * Remove the listeners used for click and tap controls. This is needed for
10069 * toggling to controls disabled, where a tap/touch should do nothing.
10070 *
10071 * @method removeTechControlsListeners_
10072 * @private
10073 */
10074
10075 Player.prototype.removeTechControlsListeners_ = function removeTechControlsListeners_() {
10076 // We don't want to just use `this.off()` because there might be other needed
10077 // listeners added by techs that extend this.
10078 this.off(this.tech_, 'tap', this.handleTechTap_);
10079 this.off(this.tech_, 'touchstart', this.handleTechTouchStart_);
10080 this.off(this.tech_, 'touchmove', this.handleTechTouchMove_);
10081 this.off(this.tech_, 'touchend', this.handleTechTouchEnd_);
10082 this.off(this.tech_, 'mousedown', this.handleTechClick_);
10083 };
10084
10085 /**
10086 * Player waits for the tech to be ready
10087 *
10088 * @method handleTechReady_
10089 * @private
10090 */
10091
10092 Player.prototype.handleTechReady_ = function handleTechReady_() {
10093 this.triggerReady();
10094
10095 // Keep the same volume as before
10096 if (this.cache_.volume) {
10097 this.techCall_('setVolume', this.cache_.volume);
10098 }
10099
10100 // Look if the tech found a higher resolution poster while loading
10101 this.handleTechPosterChange_();
10102
10103 // Update the duration if available
10104 this.handleTechDurationChange_();
10105
10106 // Chrome and Safari both have issues with autoplay.
10107 // In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
10108 // In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
10109 // This fixes both issues. Need to wait for API, so it updates displays correctly
10110 if (this.src() && this.tag && this.options_.autoplay && this.paused()) {
10111 delete this.tag.poster; // Chrome Fix. Fixed in Chrome v16.
10112 this.play();
10113 }
10114 };
10115
10116 /**
10117 * Fired when the user agent begins looking for media data
10118 *
10119 * @private
10120 * @method handleTechLoadStart_
10121 */
10122
10123 Player.prototype.handleTechLoadStart_ = function handleTechLoadStart_() {
10124 // TODO: Update to use `emptied` event instead. See #1277.
10125
10126 this.removeClass('vjs-ended');
10127
10128 // reset the error state
10129 this.error(null);
10130
10131 // If it's already playing we want to trigger a firstplay event now.
10132 // The firstplay event relies on both the play and loadstart events
10133 // which can happen in any order for a new source
10134 if (!this.paused()) {
10135 this.trigger('loadstart');
10136 this.trigger('firstplay');
10137 } else {
10138 // reset the hasStarted state
10139 this.hasStarted(false);
10140 this.trigger('loadstart');
10141 }
10142 };
10143
10144 /**
10145 * Add/remove the vjs-has-started class
10146 *
10147 * @param {Boolean} hasStarted The value of true adds the class the value of false remove the class
10148 * @return {Boolean} Boolean value if has started
10149 * @private
10150 * @method hasStarted
10151 */
10152
10153 Player.prototype.hasStarted = function hasStarted(_hasStarted) {
10154 if (_hasStarted !== undefined) {
10155 // only update if this is a new value
10156 if (this.hasStarted_ !== _hasStarted) {
10157 this.hasStarted_ = _hasStarted;
10158 if (_hasStarted) {
10159 this.addClass('vjs-has-started');
10160 // trigger the firstplay event if this newly has played
10161 this.trigger('firstplay');
10162 } else {
10163 this.removeClass('vjs-has-started');
10164 }
10165 }
10166 return this;
10167 }
10168 return !!this.hasStarted_;
10169 };
10170
10171 /**
10172 * Fired whenever the media begins or resumes playback
10173 *
10174 * @private
10175 * @method handleTechPlay_
10176 */
10177
10178 Player.prototype.handleTechPlay_ = function handleTechPlay_() {
10179 this.removeClass('vjs-ended');
10180 this.removeClass('vjs-paused');
10181 this.addClass('vjs-playing');
10182
10183 // hide the poster when the user hits play
10184 // https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-play
10185 this.hasStarted(true);
10186
10187 this.trigger('play');
10188 };
10189
10190 /**
10191 * Fired whenever the media begins waiting
10192 *
10193 * @private
10194 * @method handleTechWaiting_
10195 */
10196
10197 Player.prototype.handleTechWaiting_ = function handleTechWaiting_() {
10198 var _this2 = this;
10199
10200 this.addClass('vjs-waiting');
10201 this.trigger('waiting');
10202 this.one('timeupdate', function () {
10203 return _this2.removeClass('vjs-waiting');
10204 });
10205 };
10206
10207 /**
10208 * A handler for events that signal that waiting has ended
10209 * which is not consistent between browsers. See #1351
10210 *
10211 * @private
10212 * @method handleTechCanPlay_
10213 */
10214
10215 Player.prototype.handleTechCanPlay_ = function handleTechCanPlay_() {
10216 this.removeClass('vjs-waiting');
10217 this.trigger('canplay');
10218 };
10219
10220 /**
10221 * A handler for events that signal that waiting has ended
10222 * which is not consistent between browsers. See #1351
10223 *
10224 * @private
10225 * @method handleTechCanPlayThrough_
10226 */
10227
10228 Player.prototype.handleTechCanPlayThrough_ = function handleTechCanPlayThrough_() {
10229 this.removeClass('vjs-waiting');
10230 this.trigger('canplaythrough');
10231 };
10232
10233 /**
10234 * A handler for events that signal that waiting has ended
10235 * which is not consistent between browsers. See #1351
10236 *
10237 * @private
10238 * @method handleTechPlaying_
10239 */
10240
10241 Player.prototype.handleTechPlaying_ = function handleTechPlaying_() {
10242 this.removeClass('vjs-waiting');
10243 this.trigger('playing');
10244 };
10245
10246 /**
10247 * Fired whenever the player is jumping to a new time
10248 *
10249 * @private
10250 * @method handleTechSeeking_
10251 */
10252
10253 Player.prototype.handleTechSeeking_ = function handleTechSeeking_() {
10254 this.addClass('vjs-seeking');
10255 this.trigger('seeking');
10256 };
10257
10258 /**
10259 * Fired when the player has finished jumping to a new time
10260 *
10261 * @private
10262 * @method handleTechSeeked_
10263 */
10264
10265 Player.prototype.handleTechSeeked_ = function handleTechSeeked_() {
10266 this.removeClass('vjs-seeking');
10267 this.trigger('seeked');
10268 };
10269
10270 /**
10271 * Fired the first time a video is played
10272 * Not part of the HLS spec, and we're not sure if this is the best
10273 * implementation yet, so use sparingly. If you don't have a reason to
10274 * prevent playback, use `myPlayer.one('play');` instead.
10275 *
10276 * @private
10277 * @method handleTechFirstPlay_
10278 */
10279
10280 Player.prototype.handleTechFirstPlay_ = function handleTechFirstPlay_() {
10281 //If the first starttime attribute is specified
10282 //then we will start at the given offset in seconds
10283 if (this.options_.starttime) {
10284 this.currentTime(this.options_.starttime);
10285 }
10286
10287 this.addClass('vjs-has-started');
10288 this.trigger('firstplay');
10289 };
10290
10291 /**
10292 * Fired whenever the media has been paused
10293 *
10294 * @private
10295 * @method handleTechPause_
10296 */
10297
10298 Player.prototype.handleTechPause_ = function handleTechPause_() {
10299 this.removeClass('vjs-playing');
10300 this.addClass('vjs-paused');
10301 this.trigger('pause');
10302 };
10303
10304 /**
10305 * Fired while the user agent is downloading media data
10306 *
10307 * @private
10308 * @method handleTechProgress_
10309 */
10310
10311 Player.prototype.handleTechProgress_ = function handleTechProgress_() {
10312 this.trigger('progress');
10313 };
10314
10315 /**
10316 * Fired when the end of the media resource is reached (currentTime == duration)
10317 *
10318 * @private
10319 * @method handleTechEnded_
10320 */
10321
10322 Player.prototype.handleTechEnded_ = function handleTechEnded_() {
10323 this.addClass('vjs-ended');
10324 if (this.options_.loop) {
10325 this.currentTime(0);
10326 this.play();
10327 } else if (!this.paused()) {
10328 this.pause();
10329 }
10330
10331 this.trigger('ended');
10332 };
10333
10334 /**
10335 * Fired when the duration of the media resource is first known or changed
10336 *
10337 * @private
10338 * @method handleTechDurationChange_
10339 */
10340
10341 Player.prototype.handleTechDurationChange_ = function handleTechDurationChange_() {
10342 this.duration(this.techGet_('duration'));
10343 };
10344
10345 /**
10346 * Handle a click on the media element to play/pause
10347 *
10348 * @param {Object=} event Event object
10349 * @private
10350 * @method handleTechClick_
10351 */
10352
10353 Player.prototype.handleTechClick_ = function handleTechClick_(event) {
10354 // We're using mousedown to detect clicks thanks to Flash, but mousedown
10355 // will also be triggered with right-clicks, so we need to prevent that
10356 if (event.button !== 0) return;
10357
10358 // When controls are disabled a click should not toggle playback because
10359 // the click is considered a control
10360 if (this.controls()) {
10361 if (this.paused()) {
10362 this.play();
10363 } else {
10364 this.pause();
10365 }
10366 }
10367 };
10368
10369 /**
10370 * Handle a tap on the media element. It will toggle the user
10371 * activity state, which hides and shows the controls.
10372 *
10373 * @private
10374 * @method handleTechTap_
10375 */
10376
10377 Player.prototype.handleTechTap_ = function handleTechTap_() {
10378 this.userActive(!this.userActive());
10379 };
10380
10381 /**
10382 * Handle touch to start
10383 *
10384 * @private
10385 * @method handleTechTouchStart_
10386 */
10387
10388 Player.prototype.handleTechTouchStart_ = function handleTechTouchStart_() {
10389 this.userWasActive = this.userActive();
10390 };
10391
10392 /**
10393 * Handle touch to move
10394 *
10395 * @private
10396 * @method handleTechTouchMove_
10397 */
10398
10399 Player.prototype.handleTechTouchMove_ = function handleTechTouchMove_() {
10400 if (this.userWasActive) {
10401 this.reportUserActivity();
10402 }
10403 };
10404
10405 /**
10406 * Handle touch to end
10407 *
10408 * @private
10409 * @method handleTechTouchEnd_
10410 */
10411
10412 Player.prototype.handleTechTouchEnd_ = function handleTechTouchEnd_(event) {
10413 // Stop the mouse events from also happening
10414 event.preventDefault();
10415 };
10416
10417 /**
10418 * Fired when the player switches in or out of fullscreen mode
10419 *
10420 * @private
10421 * @method handleFullscreenChange_
10422 */
10423
10424 Player.prototype.handleFullscreenChange_ = function handleFullscreenChange_() {
10425 if (this.isFullscreen()) {
10426 this.addClass('vjs-fullscreen');
10427 } else {
10428 this.removeClass('vjs-fullscreen');
10429 }
10430 };
10431
10432 /**
10433 * native click events on the SWF aren't triggered on IE11, Win8.1RT
10434 * use stageclick events triggered from inside the SWF instead
10435 *
10436 * @private
10437 * @method handleStageClick_
10438 */
10439
10440 Player.prototype.handleStageClick_ = function handleStageClick_() {
10441 this.reportUserActivity();
10442 };
10443
10444 /**
10445 * Handle Tech Fullscreen Change
10446 *
10447 * @private
10448 * @method handleTechFullscreenChange_
10449 */
10450
10451 Player.prototype.handleTechFullscreenChange_ = function handleTechFullscreenChange_(event, data) {
10452 if (data) {
10453 this.isFullscreen(data.isFullscreen);
10454 }
10455 this.trigger('fullscreenchange');
10456 };
10457
10458 /**
10459 * Fires when an error occurred during the loading of an audio/video
10460 *
10461 * @private
10462 * @method handleTechError_
10463 */
10464
10465 Player.prototype.handleTechError_ = function handleTechError_() {
10466 var error = this.tech_.error();
10467 this.error(error && error.code);
10468 };
10469
10470 /**
10471 * Fires when the browser is intentionally not getting media data
10472 *
10473 * @private
10474 * @method handleTechSuspend_
10475 */
10476
10477 Player.prototype.handleTechSuspend_ = function handleTechSuspend_() {
10478 this.trigger('suspend');
10479 };
10480
10481 /**
10482 * Fires when the loading of an audio/video is aborted
10483 *
10484 * @private
10485 * @method handleTechAbort_
10486 */
10487
10488 Player.prototype.handleTechAbort_ = function handleTechAbort_() {
10489 this.trigger('abort');
10490 };
10491
10492 /**
10493 * Fires when the current playlist is empty
10494 *
10495 * @private
10496 * @method handleTechEmptied_
10497 */
10498
10499 Player.prototype.handleTechEmptied_ = function handleTechEmptied_() {
10500 this.trigger('emptied');
10501 };
10502
10503 /**
10504 * Fires when the browser is trying to get media data, but data is not available
10505 *
10506 * @private
10507 * @method handleTechStalled_
10508 */
10509
10510 Player.prototype.handleTechStalled_ = function handleTechStalled_() {
10511 this.trigger('stalled');
10512 };
10513
10514 /**
10515 * Fires when the browser has loaded meta data for the audio/video
10516 *
10517 * @private
10518 * @method handleTechLoadedMetaData_
10519 */
10520
10521 Player.prototype.handleTechLoadedMetaData_ = function handleTechLoadedMetaData_() {
10522 this.trigger('loadedmetadata');
10523 };
10524
10525 /**
10526 * Fires when the browser has loaded the current frame of the audio/video
10527 *
10528 * @private
10529 * @method handleTechLoadedData_
10530 */
10531
10532 Player.prototype.handleTechLoadedData_ = function handleTechLoadedData_() {
10533 this.trigger('loadeddata');
10534 };
10535
10536 /**
10537 * Fires when the current playback position has changed
10538 *
10539 * @private
10540 * @method handleTechTimeUpdate_
10541 */
10542
10543 Player.prototype.handleTechTimeUpdate_ = function handleTechTimeUpdate_() {
10544 this.trigger('timeupdate');
10545 };
10546
10547 /**
10548 * Fires when the playing speed of the audio/video is changed
10549 *
10550 * @private
10551 * @method handleTechRateChange_
10552 */
10553
10554 Player.prototype.handleTechRateChange_ = function handleTechRateChange_() {
10555 this.trigger('ratechange');
10556 };
10557
10558 /**
10559 * Fires when the volume has been changed
10560 *
10561 * @private
10562 * @method handleTechVolumeChange_
10563 */
10564
10565 Player.prototype.handleTechVolumeChange_ = function handleTechVolumeChange_() {
10566 this.trigger('volumechange');
10567 };
10568
10569 /**
10570 * Fires when the text track has been changed
10571 *
10572 * @private
10573 * @method handleTechTextTrackChange_
10574 */
10575
10576 Player.prototype.handleTechTextTrackChange_ = function handleTechTextTrackChange_() {
10577 this.trigger('texttrackchange');
10578 };
10579
10580 /**
10581 * Get object for cached values.
10582 *
10583 * @return {Object}
10584 * @method getCache
10585 */
10586
10587 Player.prototype.getCache = function getCache() {
10588 return this.cache_;
10589 };
10590
10591 /**
10592 * Pass values to the playback tech
10593 *
10594 * @param {String=} method Method
10595 * @param {Object=} arg Argument
10596 * @private
10597 * @method techCall_
10598 */
10599
10600 Player.prototype.techCall_ = function techCall_(method, arg) {
10601 // If it's not ready yet, call method when it is
10602 if (this.tech_ && !this.tech_.isReady_) {
10603 this.tech_.ready(function () {
10604 this[method](arg);
10605 }, true);
10606
10607 // Otherwise call method now
10608 } else {
10609 try {
10610 this.tech_[method](arg);
10611 } catch (e) {
10612 _utilsLogJs2['default'](e);
10613 throw e;
10614 }
10615 }
10616 };
10617
10618 /**
10619 * Get calls can't wait for the tech, and sometimes don't need to.
10620 *
10621 * @param {String} method Tech method
10622 * @return {Method}
10623 * @private
10624 * @method techGet_
10625 */
10626
10627 Player.prototype.techGet_ = function techGet_(method) {
10628 if (this.tech_ && this.tech_.isReady_) {
10629
10630 // Flash likes to die and reload when you hide or reposition it.
10631 // In these cases the object methods go away and we get errors.
10632 // When that happens we'll catch the errors and inform tech that it's not ready any more.
10633 try {
10634 return this.tech_[method]();
10635 } catch (e) {
10636 // When building additional tech libs, an expected method may not be defined yet
10637 if (this.tech_[method] === undefined) {
10638 _utilsLogJs2['default']('Video.js: ' + method + ' method not defined for ' + this.techName_ + ' playback technology.', e);
10639 } else {
10640 // When a method isn't available on the object it throws a TypeError
10641 if (e.name === 'TypeError') {
10642 _utilsLogJs2['default']('Video.js: ' + method + ' unavailable on ' + this.techName_ + ' playback technology element.', e);
10643 this.tech_.isReady_ = false;
10644 } else {
10645 _utilsLogJs2['default'](e);
10646 }
10647 }
10648 throw e;
10649 }
10650 }
10651
10652 return;
10653 };
10654
10655 /**
10656 * start media playback
10657 * ```js
10658 * myPlayer.play();
10659 * ```
10660 *
10661 * @return {Player} self
10662 * @method play
10663 */
10664
10665 Player.prototype.play = function play() {
10666 this.techCall_('play');
10667 return this;
10668 };
10669
10670 /**
10671 * Pause the video playback
10672 * ```js
10673 * myPlayer.pause();
10674 * ```
10675 *
10676 * @return {Player} self
10677 * @method pause
10678 */
10679
10680 Player.prototype.pause = function pause() {
10681 this.techCall_('pause');
10682 return this;
10683 };
10684
10685 /**
10686 * Check if the player is paused
10687 * ```js
10688 * var isPaused = myPlayer.paused();
10689 * var isPlaying = !myPlayer.paused();
10690 * ```
10691 *
10692 * @return {Boolean} false if the media is currently playing, or true otherwise
10693 * @method paused
10694 */
10695
10696 Player.prototype.paused = function paused() {
10697 // The initial state of paused should be true (in Safari it's actually false)
10698 return this.techGet_('paused') === false ? false : true;
10699 };
10700
10701 /**
10702 * Returns whether or not the user is "scrubbing". Scrubbing is when the user
10703 * has clicked the progress bar handle and is dragging it along the progress bar.
10704 *
10705 * @param {Boolean} isScrubbing True/false the user is scrubbing
10706 * @return {Boolean} The scrubbing status when getting
10707 * @return {Object} The player when setting
10708 * @method scrubbing
10709 */
10710
10711 Player.prototype.scrubbing = function scrubbing(isScrubbing) {
10712 if (isScrubbing !== undefined) {
10713 this.scrubbing_ = !!isScrubbing;
10714
10715 if (isScrubbing) {
10716 this.addClass('vjs-scrubbing');
10717 } else {
10718 this.removeClass('vjs-scrubbing');
10719 }
10720
10721 return this;
10722 }
10723
10724 return this.scrubbing_;
10725 };
10726
10727 /**
10728 * Get or set the current time (in seconds)
10729 * ```js
10730 * // get
10731 * var whereYouAt = myPlayer.currentTime();
10732 * // set
10733 * myPlayer.currentTime(120); // 2 minutes into the video
10734 * ```
10735 *
10736 * @param {Number|String=} seconds The time to seek to
10737 * @return {Number} The time in seconds, when not setting
10738 * @return {Player} self, when the current time is set
10739 * @method currentTime
10740 */
10741
10742 Player.prototype.currentTime = function currentTime(seconds) {
10743 if (seconds !== undefined) {
10744
10745 this.techCall_('setCurrentTime', seconds);
10746
10747 return this;
10748 }
10749
10750 // cache last currentTime and return. default to 0 seconds
10751 //
10752 // Caching the currentTime is meant to prevent a massive amount of reads on the tech's
10753 // currentTime when scrubbing, but may not provide much performance benefit afterall.
10754 // Should be tested. Also something has to read the actual current time or the cache will
10755 // never get updated.
10756 return this.cache_.currentTime = this.techGet_('currentTime') || 0;
10757 };
10758
10759 /**
10760 * Get the length in time of the video in seconds
10761 * ```js
10762 * var lengthOfVideo = myPlayer.duration();
10763 * ```
10764 * **NOTE**: The video must have started loading before the duration can be
10765 * known, and in the case of Flash, may not be known until the video starts
10766 * playing.
10767 *
10768 * @param {Number} seconds Duration when setting
10769 * @return {Number} The duration of the video in seconds when getting
10770 * @method duration
10771 */
10772
10773 Player.prototype.duration = function duration(seconds) {
10774 if (seconds === undefined) {
10775 return this.cache_.duration || 0;
10776 }
10777
10778 seconds = parseFloat(seconds) || 0;
10779
10780 // Standardize on Inifity for signaling video is live
10781 if (seconds < 0) {
10782 seconds = Infinity;
10783 }
10784
10785 if (seconds !== this.cache_.duration) {
10786 // Cache the last set value for optimized scrubbing (esp. Flash)
10787 this.cache_.duration = seconds;
10788
10789 if (seconds === Infinity) {
10790 this.addClass('vjs-live');
10791 } else {
10792 this.removeClass('vjs-live');
10793 }
10794
10795 this.trigger('durationchange');
10796 }
10797
10798 return this;
10799 };
10800
10801 /**
10802 * Calculates how much time is left.
10803 * ```js
10804 * var timeLeft = myPlayer.remainingTime();
10805 * ```
10806 * Not a native video element function, but useful
10807 *
10808 * @return {Number} The time remaining in seconds
10809 * @method remainingTime
10810 */
10811
10812 Player.prototype.remainingTime = function remainingTime() {
10813 return this.duration() - this.currentTime();
10814 };
10815
10816 // http://dev.w3.org/html5/spec/video.html#dom-media-buffered
10817 // Buffered returns a timerange object.
10818 // Kind of like an array of portions of the video that have been downloaded.
10819
10820 /**
10821 * Get a TimeRange object with the times of the video that have been downloaded
10822 * If you just want the percent of the video that's been downloaded,
10823 * use bufferedPercent.
10824 * ```js
10825 * // Number of different ranges of time have been buffered. Usually 1.
10826 * numberOfRanges = bufferedTimeRange.length,
10827 * // Time in seconds when the first range starts. Usually 0.
10828 * firstRangeStart = bufferedTimeRange.start(0),
10829 * // Time in seconds when the first range ends
10830 * firstRangeEnd = bufferedTimeRange.end(0),
10831 * // Length in seconds of the first time range
10832 * firstRangeLength = firstRangeEnd - firstRangeStart;
10833 * ```
10834 *
10835 * @return {Object} A mock TimeRange object (following HTML spec)
10836 * @method buffered
10837 */
10838
10839 Player.prototype.buffered = function buffered() {
10840 var buffered = this.techGet_('buffered');
10841
10842 if (!buffered || !buffered.length) {
10843 buffered = _utilsTimeRangesJs.createTimeRange(0, 0);
10844 }
10845
10846 return buffered;
10847 };
10848
10849 /**
10850 * Get the percent (as a decimal) of the video that's been downloaded
10851 * ```js
10852 * var howMuchIsDownloaded = myPlayer.bufferedPercent();
10853 * ```
10854 * 0 means none, 1 means all.
10855 * (This method isn't in the HTML5 spec, but it's very convenient)
10856 *
10857 * @return {Number} A decimal between 0 and 1 representing the percent
10858 * @method bufferedPercent
10859 */
10860
10861 Player.prototype.bufferedPercent = function bufferedPercent() {
10862 return _utilsBufferJs.bufferedPercent(this.buffered(), this.duration());
10863 };
10864
10865 /**
10866 * Get the ending time of the last buffered time range
10867 * This is used in the progress bar to encapsulate all time ranges.
10868 *
10869 * @return {Number} The end of the last buffered time range
10870 * @method bufferedEnd
10871 */
10872
10873 Player.prototype.bufferedEnd = function bufferedEnd() {
10874 var buffered = this.buffered(),
10875 duration = this.duration(),
10876 end = buffered.end(buffered.length - 1);
10877
10878 if (end > duration) {
10879 end = duration;
10880 }
10881
10882 return end;
10883 };
10884
10885 /**
10886 * Get or set the current volume of the media
10887 * ```js
10888 * // get
10889 * var howLoudIsIt = myPlayer.volume();
10890 * // set
10891 * myPlayer.volume(0.5); // Set volume to half
10892 * ```
10893 * 0 is off (muted), 1.0 is all the way up, 0.5 is half way.
10894 *
10895 * @param {Number} percentAsDecimal The new volume as a decimal percent
10896 * @return {Number} The current volume when getting
10897 * @return {Player} self when setting
10898 * @method volume
10899 */
10900
10901 Player.prototype.volume = function volume(percentAsDecimal) {
10902 var vol = undefined;
10903
10904 if (percentAsDecimal !== undefined) {
10905 vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); // Force value to between 0 and 1
10906 this.cache_.volume = vol;
10907 this.techCall_('setVolume', vol);
10908
10909 return this;
10910 }
10911
10912 // Default to 1 when returning current volume.
10913 vol = parseFloat(this.techGet_('volume'));
10914 return isNaN(vol) ? 1 : vol;
10915 };
10916
10917 /**
10918 * Get the current muted state, or turn mute on or off
10919 * ```js
10920 * // get
10921 * var isVolumeMuted = myPlayer.muted();
10922 * // set
10923 * myPlayer.muted(true); // mute the volume
10924 * ```
10925 *
10926 * @param {Boolean=} muted True to mute, false to unmute
10927 * @return {Boolean} True if mute is on, false if not when getting
10928 * @return {Player} self when setting mute
10929 * @method muted
10930 */
10931
10932 Player.prototype.muted = function muted(_muted) {
10933 if (_muted !== undefined) {
10934 this.techCall_('setMuted', _muted);
10935 return this;
10936 }
10937 return this.techGet_('muted') || false; // Default to false
10938 };
10939
10940 // Check if current tech can support native fullscreen
10941 // (e.g. with built in controls like iOS, so not our flash swf)
10942 /**
10943 * Check to see if fullscreen is supported
10944 *
10945 * @return {Boolean}
10946 * @method supportsFullScreen
10947 */
10948
10949 Player.prototype.supportsFullScreen = function supportsFullScreen() {
10950 return this.techGet_('supportsFullScreen') || false;
10951 };
10952
10953 /**
10954 * Check if the player is in fullscreen mode
10955 * ```js
10956 * // get
10957 * var fullscreenOrNot = myPlayer.isFullscreen();
10958 * // set
10959 * myPlayer.isFullscreen(true); // tell the player it's in fullscreen
10960 * ```
10961 * NOTE: As of the latest HTML5 spec, isFullscreen is no longer an official
10962 * property and instead document.fullscreenElement is used. But isFullscreen is
10963 * still a valuable property for internal player workings.
10964 *
10965 * @param {Boolean=} isFS Update the player's fullscreen state
10966 * @return {Boolean} true if fullscreen false if not when getting
10967 * @return {Player} self when setting
10968 * @method isFullscreen
10969 */
10970
10971 Player.prototype.isFullscreen = function isFullscreen(isFS) {
10972 if (isFS !== undefined) {
10973 this.isFullscreen_ = !!isFS;
10974 return this;
10975 }
10976 return !!this.isFullscreen_;
10977 };
10978
10979 /**
10980 * Increase the size of the video to full screen
10981 * ```js
10982 * myPlayer.requestFullscreen();
10983 * ```
10984 * In some browsers, full screen is not supported natively, so it enters
10985 * "full window mode", where the video fills the browser window.
10986 * In browsers and devices that support native full screen, sometimes the
10987 * browser's default controls will be shown, and not the Video.js custom skin.
10988 * This includes most mobile devices (iOS, Android) and older versions of
10989 * Safari.
10990 *
10991 * @return {Player} self
10992 * @method requestFullscreen
10993 */
10994
10995 Player.prototype.requestFullscreen = function requestFullscreen() {
10996 var fsApi = _fullscreenApiJs2['default'];
10997
10998 this.isFullscreen(true);
10999
11000 if (fsApi.requestFullscreen) {
11001 // the browser supports going fullscreen at the element level so we can
11002 // take the controls fullscreen as well as the video
11003
11004 // Trigger fullscreenchange event after change
11005 // We have to specifically add this each time, and remove
11006 // when canceling fullscreen. Otherwise if there's multiple
11007 // players on a page, they would all be reacting to the same fullscreen
11008 // events
11009 Events.on(_globalDocument2['default'], fsApi.fullscreenchange, Fn.bind(this, function documentFullscreenChange(e) {
11010 this.isFullscreen(_globalDocument2['default'][fsApi.fullscreenElement]);
11011
11012 // If cancelling fullscreen, remove event listener.
11013 if (this.isFullscreen() === false) {
11014 Events.off(_globalDocument2['default'], fsApi.fullscreenchange, documentFullscreenChange);
11015 }
11016
11017 this.trigger('fullscreenchange');
11018 }));
11019
11020 this.el_[fsApi.requestFullscreen]();
11021 } else if (this.tech_.supportsFullScreen()) {
11022 // we can't take the video.js controls fullscreen but we can go fullscreen
11023 // with native controls
11024 this.techCall_('enterFullScreen');
11025 } else {
11026 // fullscreen isn't supported so we'll just stretch the video element to
11027 // fill the viewport
11028 this.enterFullWindow();
11029 this.trigger('fullscreenchange');
11030 }
11031
11032 return this;
11033 };
11034
11035 /**
11036 * Return the video to its normal size after having been in full screen mode
11037 * ```js
11038 * myPlayer.exitFullscreen();
11039 * ```
11040 *
11041 * @return {Player} self
11042 * @method exitFullscreen
11043 */
11044
11045 Player.prototype.exitFullscreen = function exitFullscreen() {
11046 var fsApi = _fullscreenApiJs2['default'];
11047 this.isFullscreen(false);
11048
11049 // Check for browser element fullscreen support
11050 if (fsApi.requestFullscreen) {
11051 _globalDocument2['default'][fsApi.exitFullscreen]();
11052 } else if (this.tech_.supportsFullScreen()) {
11053 this.techCall_('exitFullScreen');
11054 } else {
11055 this.exitFullWindow();
11056 this.trigger('fullscreenchange');
11057 }
11058
11059 return this;
11060 };
11061
11062 /**
11063 * When fullscreen isn't supported we can stretch the video container to as wide as the browser will let us.
11064 *
11065 * @method enterFullWindow
11066 */
11067
11068 Player.prototype.enterFullWindow = function enterFullWindow() {
11069 this.isFullWindow = true;
11070
11071 // Storing original doc overflow value to return to when fullscreen is off
11072 this.docOrigOverflow = _globalDocument2['default'].documentElement.style.overflow;
11073
11074 // Add listener for esc key to exit fullscreen
11075 Events.on(_globalDocument2['default'], 'keydown', Fn.bind(this, this.fullWindowOnEscKey));
11076
11077 // Hide any scroll bars
11078 _globalDocument2['default'].documentElement.style.overflow = 'hidden';
11079
11080 // Apply fullscreen styles
11081 Dom.addElClass(_globalDocument2['default'].body, 'vjs-full-window');
11082
11083 this.trigger('enterFullWindow');
11084 };
11085
11086 /**
11087 * Check for call to either exit full window or full screen on ESC key
11088 *
11089 * @param {String} event Event to check for key press
11090 * @method fullWindowOnEscKey
11091 */
11092
11093 Player.prototype.fullWindowOnEscKey = function fullWindowOnEscKey(event) {
11094 if (event.keyCode === 27) {
11095 if (this.isFullscreen() === true) {
11096 this.exitFullscreen();
11097 } else {
11098 this.exitFullWindow();
11099 }
11100 }
11101 };
11102
11103 /**
11104 * Exit full window
11105 *
11106 * @method exitFullWindow
11107 */
11108
11109 Player.prototype.exitFullWindow = function exitFullWindow() {
11110 this.isFullWindow = false;
11111 Events.off(_globalDocument2['default'], 'keydown', this.fullWindowOnEscKey);
11112
11113 // Unhide scroll bars.
11114 _globalDocument2['default'].documentElement.style.overflow = this.docOrigOverflow;
11115
11116 // Remove fullscreen styles
11117 Dom.removeElClass(_globalDocument2['default'].body, 'vjs-full-window');
11118
11119 // Resize the box, controller, and poster to original sizes
11120 // this.positionAll();
11121 this.trigger('exitFullWindow');
11122 };
11123
11124 /**
11125 * Check whether the player can play a given mimetype
11126 *
11127 * @param {String} type The mimetype to check
11128 * @return {String} 'probably', 'maybe', or '' (empty string)
11129 * @method canPlayType
11130 */
11131
11132 Player.prototype.canPlayType = function canPlayType(type) {
11133 var can = undefined;
11134
11135 // Loop through each playback technology in the options order
11136 for (var i = 0, j = this.options_.techOrder; i < j.length; i++) {
11137 var techName = _utilsToTitleCaseJs2['default'](j[i]);
11138 var tech = _techTechJs2['default'].getTech(techName);
11139
11140 // Support old behavior of techs being registered as components.
11141 // Remove once that deprecated behavior is removed.
11142 if (!tech) {
11143 tech = _componentJs2['default'].getComponent(techName);
11144 }
11145
11146 // Check if the current tech is defined before continuing
11147 if (!tech) {
11148 _utilsLogJs2['default'].error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.');
11149 continue;
11150 }
11151
11152 // Check if the browser supports this technology
11153 if (tech.isSupported()) {
11154 can = tech.canPlayType(type);
11155
11156 if (can) {
11157 return can;
11158 }
11159 }
11160 }
11161
11162 return '';
11163 };
11164
11165 /**
11166 * Select source based on tech-order or source-order
11167 * Uses source-order selection if `options.sourceOrder` is truthy. Otherwise,
11168 * defaults to tech-order selection
11169 *
11170 * @param {Array} sources The sources for a media asset
11171 * @return {Object|Boolean} Object of source and tech order, otherwise false
11172 * @method selectSource
11173 */
11174
11175 Player.prototype.selectSource = function selectSource(sources) {
11176 // Get only the techs specified in `techOrder` that exist and are supported by the
11177 // current platform
11178 var techs = this.options_.techOrder.map(_utilsToTitleCaseJs2['default']).map(function (techName) {
11179 // `Component.getComponent(...)` is for support of old behavior of techs
11180 // being registered as components.
11181 // Remove once that deprecated behavior is removed.
11182 return [techName, _techTechJs2['default'].getTech(techName) || _componentJs2['default'].getComponent(techName)];
11183 }).filter(function (_ref) {
11184 var techName = _ref[0];
11185 var tech = _ref[1];
11186
11187 // Check if the current tech is defined before continuing
11188 if (tech) {
11189 // Check if the browser supports this technology
11190 return tech.isSupported();
11191 }
11192
11193 _utilsLogJs2['default'].error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.');
11194 return false;
11195 });
11196
11197 // Iterate over each `innerArray` element once per `outerArray` element and execute
11198 // `tester` with both. If `tester` returns a non-falsy value, exit early and return
11199 // that value.
11200 var findFirstPassingTechSourcePair = function findFirstPassingTechSourcePair(outerArray, innerArray, tester) {
11201 var found = undefined;
11202
11203 outerArray.some(function (outerChoice) {
11204 return innerArray.some(function (innerChoice) {
11205 found = tester(outerChoice, innerChoice);
11206
11207 if (found) {
11208 return true;
11209 }
11210 });
11211 });
11212
11213 return found;
11214 };
11215
11216 var foundSourceAndTech = undefined;
11217 var flip = function flip(fn) {
11218 return function (a, b) {
11219 return fn(b, a);
11220 };
11221 };
11222 var finder = function finder(_ref2, source) {
11223 var techName = _ref2[0];
11224 var tech = _ref2[1];
11225
11226 if (tech.canPlaySource(source)) {
11227 return { source: source, tech: techName };
11228 }
11229 };
11230
11231 // Depending on the truthiness of `options.sourceOrder`, we swap the order of techs and sources
11232 // to select from them based on their priority.
11233 if (this.options_.sourceOrder) {
11234 // Source-first ordering
11235 foundSourceAndTech = findFirstPassingTechSourcePair(sources, techs, flip(finder));
11236 } else {
11237 // Tech-first ordering
11238 foundSourceAndTech = findFirstPassingTechSourcePair(techs, sources, finder);
11239 }
11240
11241 return foundSourceAndTech || false;
11242 };
11243
11244 /**
11245 * The source function updates the video source
11246 * There are three types of variables you can pass as the argument.
11247 * **URL String**: A URL to the the video file. Use this method if you are sure
11248 * the current playback technology (HTML5/Flash) can support the source you
11249 * provide. Currently only MP4 files can be used in both HTML5 and Flash.
11250 * ```js
11251 * myPlayer.src("http://www.example.com/path/to/video.mp4");
11252 * ```
11253 * **Source Object (or element):* * A javascript object containing information
11254 * about the source file. Use this method if you want the player to determine if
11255 * it can support the file using the type information.
11256 * ```js
11257 * myPlayer.src({ type: "video/mp4", src: "http://www.example.com/path/to/video.mp4" });
11258 * ```
11259 * **Array of Source Objects:* * To provide multiple versions of the source so
11260 * that it can be played using HTML5 across browsers you can use an array of
11261 * source objects. Video.js will detect which version is supported and load that
11262 * file.
11263 * ```js
11264 * myPlayer.src([
11265 * { type: "video/mp4", src: "http://www.example.com/path/to/video.mp4" },
11266 * { type: "video/webm", src: "http://www.example.com/path/to/video.webm" },
11267 * { type: "video/ogg", src: "http://www.example.com/path/to/video.ogv" }
11268 * ]);
11269 * ```
11270 *
11271 * @param {String|Object|Array=} source The source URL, object, or array of sources
11272 * @return {String} The current video source when getting
11273 * @return {String} The player when setting
11274 * @method src
11275 */
11276
11277 Player.prototype.src = function src(source) {
11278 if (source === undefined) {
11279 return this.techGet_('src');
11280 }
11281
11282 var currentTech = _techTechJs2['default'].getTech(this.techName_);
11283 // Support old behavior of techs being registered as components.
11284 // Remove once that deprecated behavior is removed.
11285 if (!currentTech) {
11286 currentTech = _componentJs2['default'].getComponent(this.techName_);
11287 }
11288
11289 // case: Array of source objects to choose from and pick the best to play
11290 if (Array.isArray(source)) {
11291 this.sourceList_(source);
11292
11293 // case: URL String (http://myvideo...)
11294 } else if (typeof source === 'string') {
11295 // create a source object from the string
11296 this.src({ src: source });
11297
11298 // case: Source object { src: '', type: '' ... }
11299 } else if (source instanceof Object) {
11300 // check if the source has a type and the loaded tech cannot play the source
11301 // if there's no type we'll just try the current tech
11302 if (source.type && !currentTech.canPlaySource(source)) {
11303 // create a source list with the current source and send through
11304 // the tech loop to check for a compatible technology
11305 this.sourceList_([source]);
11306 } else {
11307 this.cache_.src = source.src;
11308 this.currentType_ = source.type || '';
11309
11310 // wait until the tech is ready to set the source
11311 this.ready(function () {
11312
11313 // The setSource tech method was added with source handlers
11314 // so older techs won't support it
11315 // We need to check the direct prototype for the case where subclasses
11316 // of the tech do not support source handlers
11317 if (currentTech.prototype.hasOwnProperty('setSource')) {
11318 this.techCall_('setSource', source);
11319 } else {
11320 this.techCall_('src', source.src);
11321 }
11322
11323 if (this.options_.preload === 'auto') {
11324 this.load();
11325 }
11326
11327 if (this.options_.autoplay) {
11328 this.play();
11329 }
11330
11331 // Set the source synchronously if possible (#2326)
11332 }, true);
11333 }
11334 }
11335
11336 return this;
11337 };
11338
11339 /**
11340 * Handle an array of source objects
11341 *
11342 * @param {Array} sources Array of source objects
11343 * @private
11344 * @method sourceList_
11345 */
11346
11347 Player.prototype.sourceList_ = function sourceList_(sources) {
11348 var sourceTech = this.selectSource(sources);
11349
11350 if (sourceTech) {
11351 if (sourceTech.tech === this.techName_) {
11352 // if this technology is already loaded, set the source
11353 this.src(sourceTech.source);
11354 } else {
11355 // load this technology with the chosen source
11356 this.loadTech_(sourceTech.tech, sourceTech.source);
11357 }
11358 } else {
11359 // We need to wrap this in a timeout to give folks a chance to add error event handlers
11360 this.setTimeout(function () {
11361 this.error({ code: 4, message: this.localize(this.options_.notSupportedMessage) });
11362 }, 0);
11363
11364 // we could not find an appropriate tech, but let's still notify the delegate that this is it
11365 // this needs a better comment about why this is needed
11366 this.triggerReady();
11367 }
11368 };
11369
11370 /**
11371 * Begin loading the src data.
11372 *
11373 * @return {Player} Returns the player
11374 * @method load
11375 */
11376
11377 Player.prototype.load = function load() {
11378 this.techCall_('load');
11379 return this;
11380 };
11381
11382 /**
11383 * Reset the player. Loads the first tech in the techOrder,
11384 * and calls `reset` on the tech`.
11385 *
11386 * @return {Player} Returns the player
11387 * @method reset
11388 */
11389
11390 Player.prototype.reset = function reset() {
11391 this.loadTech_(_utilsToTitleCaseJs2['default'](this.options_.techOrder[0]), null);
11392 this.techCall_('reset');
11393 return this;
11394 };
11395
11396 /**
11397 * Returns the fully qualified URL of the current source value e.g. http://mysite.com/video.mp4
11398 * Can be used in conjuction with `currentType` to assist in rebuilding the current source object.
11399 *
11400 * @return {String} The current source
11401 * @method currentSrc
11402 */
11403
11404 Player.prototype.currentSrc = function currentSrc() {
11405 return this.techGet_('currentSrc') || this.cache_.src || '';
11406 };
11407
11408 /**
11409 * Get the current source type e.g. video/mp4
11410 * This can allow you rebuild the current source object so that you could load the same
11411 * source and tech later
11412 *
11413 * @return {String} The source MIME type
11414 * @method currentType
11415 */
11416
11417 Player.prototype.currentType = function currentType() {
11418 return this.currentType_ || '';
11419 };
11420
11421 /**
11422 * Get or set the preload attribute
11423 *
11424 * @param {Boolean} value Boolean to determine if preload should be used
11425 * @return {String} The preload attribute value when getting
11426 * @return {Player} Returns the player when setting
11427 * @method preload
11428 */
11429
11430 Player.prototype.preload = function preload(value) {
11431 if (value !== undefined) {
11432 this.techCall_('setPreload', value);
11433 this.options_.preload = value;
11434 return this;
11435 }
11436 return this.techGet_('preload');
11437 };
11438
11439 /**
11440 * Get or set the autoplay attribute.
11441 *
11442 * @param {Boolean} value Boolean to determine if video should autoplay
11443 * @return {String} The autoplay attribute value when getting
11444 * @return {Player} Returns the player when setting
11445 * @method autoplay
11446 */
11447
11448 Player.prototype.autoplay = function autoplay(value) {
11449 if (value !== undefined) {
11450 this.techCall_('setAutoplay', value);
11451 this.options_.autoplay = value;
11452 return this;
11453 }
11454 return this.techGet_('autoplay', value);
11455 };
11456
11457 /**
11458 * Get or set the loop attribute on the video element.
11459 *
11460 * @param {Boolean} value Boolean to determine if video should loop
11461 * @return {String} The loop attribute value when getting
11462 * @return {Player} Returns the player when setting
11463 * @method loop
11464 */
11465
11466 Player.prototype.loop = function loop(value) {
11467 if (value !== undefined) {
11468 this.techCall_('setLoop', value);
11469 this.options_['loop'] = value;
11470 return this;
11471 }
11472 return this.techGet_('loop');
11473 };
11474
11475 /**
11476 * Get or set the poster image source url
11477 *
11478 * ##### EXAMPLE:
11479 * ```js
11480 * // get
11481 * var currentPoster = myPlayer.poster();
11482 * // set
11483 * myPlayer.poster('http://example.com/myImage.jpg');
11484 * ```
11485 *
11486 * @param {String=} src Poster image source URL
11487 * @return {String} poster URL when getting
11488 * @return {Player} self when setting
11489 * @method poster
11490 */
11491
11492 Player.prototype.poster = function poster(src) {
11493 if (src === undefined) {
11494 return this.poster_;
11495 }
11496
11497 // The correct way to remove a poster is to set as an empty string
11498 // other falsey values will throw errors
11499 if (!src) {
11500 src = '';
11501 }
11502
11503 // update the internal poster variable
11504 this.poster_ = src;
11505
11506 // update the tech's poster
11507 this.techCall_('setPoster', src);
11508
11509 // alert components that the poster has been set
11510 this.trigger('posterchange');
11511
11512 return this;
11513 };
11514
11515 /**
11516 * Some techs (e.g. YouTube) can provide a poster source in an
11517 * asynchronous way. We want the poster component to use this
11518 * poster source so that it covers up the tech's controls.
11519 * (YouTube's play button). However we only want to use this
11520 * soruce if the player user hasn't set a poster through
11521 * the normal APIs.
11522 *
11523 * @private
11524 * @method handleTechPosterChange_
11525 */
11526
11527 Player.prototype.handleTechPosterChange_ = function handleTechPosterChange_() {
11528 if (!this.poster_ && this.tech_ && this.tech_.poster) {
11529 this.poster_ = this.tech_.poster() || '';
11530
11531 // Let components know the poster has changed
11532 this.trigger('posterchange');
11533 }
11534 };
11535
11536 /**
11537 * Get or set whether or not the controls are showing.
11538 *
11539 * @param {Boolean} bool Set controls to showing or not
11540 * @return {Boolean} Controls are showing
11541 * @method controls
11542 */
11543
11544 Player.prototype.controls = function controls(bool) {
11545 if (bool !== undefined) {
11546 bool = !!bool; // force boolean
11547 // Don't trigger a change event unless it actually changed
11548 if (this.controls_ !== bool) {
11549 this.controls_ = bool;
11550
11551 if (this.usingNativeControls()) {
11552 this.techCall_('setControls', bool);
11553 }
11554
11555 if (bool) {
11556 this.removeClass('vjs-controls-disabled');
11557 this.addClass('vjs-controls-enabled');
11558 this.trigger('controlsenabled');
11559
11560 if (!this.usingNativeControls()) {
11561 this.addTechControlsListeners_();
11562 }
11563 } else {
11564 this.removeClass('vjs-controls-enabled');
11565 this.addClass('vjs-controls-disabled');
11566 this.trigger('controlsdisabled');
11567
11568 if (!this.usingNativeControls()) {
11569 this.removeTechControlsListeners_();
11570 }
11571 }
11572 }
11573 return this;
11574 }
11575 return !!this.controls_;
11576 };
11577
11578 /**
11579 * Toggle native controls on/off. Native controls are the controls built into
11580 * devices (e.g. default iPhone controls), Flash, or other techs
11581 * (e.g. Vimeo Controls)
11582 * **This should only be set by the current tech, because only the tech knows
11583 * if it can support native controls**
11584 *
11585 * @param {Boolean} bool True signals that native controls are on
11586 * @return {Player} Returns the player
11587 * @private
11588 * @method usingNativeControls
11589 */
11590
11591 Player.prototype.usingNativeControls = function usingNativeControls(bool) {
11592 if (bool !== undefined) {
11593 bool = !!bool; // force boolean
11594 // Don't trigger a change event unless it actually changed
11595 if (this.usingNativeControls_ !== bool) {
11596 this.usingNativeControls_ = bool;
11597 if (bool) {
11598 this.addClass('vjs-using-native-controls');
11599
11600 /**
11601 * player is using the native device controls
11602 *
11603 * @event usingnativecontrols
11604 * @memberof Player
11605 * @instance
11606 * @private
11607 */
11608 this.trigger('usingnativecontrols');
11609 } else {
11610 this.removeClass('vjs-using-native-controls');
11611
11612 /**
11613 * player is using the custom HTML controls
11614 *
11615 * @event usingcustomcontrols
11616 * @memberof Player
11617 * @instance
11618 * @private
11619 */
11620 this.trigger('usingcustomcontrols');
11621 }
11622 }
11623 return this;
11624 }
11625 return !!this.usingNativeControls_;
11626 };
11627
11628 /**
11629 * Set or get the current MediaError
11630 *
11631 * @param {*} err A MediaError or a String/Number to be turned into a MediaError
11632 * @return {MediaError|null} when getting
11633 * @return {Player} when setting
11634 * @method error
11635 */
11636
11637 Player.prototype.error = function error(err) {
11638 if (err === undefined) {
11639 return this.error_ || null;
11640 }
11641
11642 // restoring to default
11643 if (err === null) {
11644 this.error_ = err;
11645 this.removeClass('vjs-error');
11646 this.errorDisplay.close();
11647 return this;
11648 }
11649
11650 // error instance
11651 if (err instanceof _mediaErrorJs2['default']) {
11652 this.error_ = err;
11653 } else {
11654 this.error_ = new _mediaErrorJs2['default'](err);
11655 }
11656
11657 // add the vjs-error classname to the player
11658 this.addClass('vjs-error');
11659
11660 // log the name of the error type and any message
11661 // ie8 just logs "[object object]" if you just log the error object
11662 _utilsLogJs2['default'].error('(CODE:' + this.error_.code + ' ' + _mediaErrorJs2['default'].errorTypes[this.error_.code] + ')', this.error_.message, this.error_);
11663
11664 // fire an error event on the player
11665 this.trigger('error');
11666
11667 return this;
11668 };
11669
11670 /**
11671 * Returns whether or not the player is in the "ended" state.
11672 *
11673 * @return {Boolean} True if the player is in the ended state, false if not.
11674 * @method ended
11675 */
11676
11677 Player.prototype.ended = function ended() {
11678 return this.techGet_('ended');
11679 };
11680
11681 /**
11682 * Returns whether or not the player is in the "seeking" state.
11683 *
11684 * @return {Boolean} True if the player is in the seeking state, false if not.
11685 * @method seeking
11686 */
11687
11688 Player.prototype.seeking = function seeking() {
11689 return this.techGet_('seeking');
11690 };
11691
11692 /**
11693 * Returns the TimeRanges of the media that are currently available
11694 * for seeking to.
11695 *
11696 * @return {TimeRanges} the seekable intervals of the media timeline
11697 * @method seekable
11698 */
11699
11700 Player.prototype.seekable = function seekable() {
11701 return this.techGet_('seekable');
11702 };
11703
11704 /**
11705 * Report user activity
11706 *
11707 * @param {Object} event Event object
11708 * @method reportUserActivity
11709 */
11710
11711 Player.prototype.reportUserActivity = function reportUserActivity(event) {
11712 this.userActivity_ = true;
11713 };
11714
11715 /**
11716 * Get/set if user is active
11717 *
11718 * @param {Boolean} bool Value when setting
11719 * @return {Boolean} Value if user is active user when getting
11720 * @method userActive
11721 */
11722
11723 Player.prototype.userActive = function userActive(bool) {
11724 if (bool !== undefined) {
11725 bool = !!bool;
11726 if (bool !== this.userActive_) {
11727 this.userActive_ = bool;
11728 if (bool) {
11729 // If the user was inactive and is now active we want to reset the
11730 // inactivity timer
11731 this.userActivity_ = true;
11732 this.removeClass('vjs-user-inactive');
11733 this.addClass('vjs-user-active');
11734 this.trigger('useractive');
11735 } else {
11736 // We're switching the state to inactive manually, so erase any other
11737 // activity
11738 this.userActivity_ = false;
11739
11740 // Chrome/Safari/IE have bugs where when you change the cursor it can
11741 // trigger a mousemove event. This causes an issue when you're hiding
11742 // the cursor when the user is inactive, and a mousemove signals user
11743 // activity. Making it impossible to go into inactive mode. Specifically
11744 // this happens in fullscreen when we really need to hide the cursor.
11745 //
11746 // When this gets resolved in ALL browsers it can be removed
11747 // https://code.google.com/p/chromium/issues/detail?id=103041
11748 if (this.tech_) {
11749 this.tech_.one('mousemove', function (e) {
11750 e.stopPropagation();
11751 e.preventDefault();
11752 });
11753 }
11754
11755 this.removeClass('vjs-user-active');
11756 this.addClass('vjs-user-inactive');
11757 this.trigger('userinactive');
11758 }
11759 }
11760 return this;
11761 }
11762 return this.userActive_;
11763 };
11764
11765 /**
11766 * Listen for user activity based on timeout value
11767 *
11768 * @private
11769 * @method listenForUserActivity_
11770 */
11771
11772 Player.prototype.listenForUserActivity_ = function listenForUserActivity_() {
11773 var mouseInProgress = undefined,
11774 lastMoveX = undefined,
11775 lastMoveY = undefined;
11776
11777 var handleActivity = Fn.bind(this, this.reportUserActivity);
11778
11779 var handleMouseMove = function handleMouseMove(e) {
11780 // #1068 - Prevent mousemove spamming
11781 // Chrome Bug: https://code.google.com/p/chromium/issues/detail?id=366970
11782 if (e.screenX !== lastMoveX || e.screenY !== lastMoveY) {
11783 lastMoveX = e.screenX;
11784 lastMoveY = e.screenY;
11785 handleActivity();
11786 }
11787 };
11788
11789 var handleMouseDown = function handleMouseDown() {
11790 handleActivity();
11791 // For as long as the they are touching the device or have their mouse down,
11792 // we consider them active even if they're not moving their finger or mouse.
11793 // So we want to continue to update that they are active
11794 this.clearInterval(mouseInProgress);
11795 // Setting userActivity=true now and setting the interval to the same time
11796 // as the activityCheck interval (250) should ensure we never miss the
11797 // next activityCheck
11798 mouseInProgress = this.setInterval(handleActivity, 250);
11799 };
11800
11801 var handleMouseUp = function handleMouseUp(event) {
11802 handleActivity();
11803 // Stop the interval that maintains activity if the mouse/touch is down
11804 this.clearInterval(mouseInProgress);
11805 };
11806
11807 // Any mouse movement will be considered user activity
11808 this.on('mousedown', handleMouseDown);
11809 this.on('mousemove', handleMouseMove);
11810 this.on('mouseup', handleMouseUp);
11811
11812 // Listen for keyboard navigation
11813 // Shouldn't need to use inProgress interval because of key repeat
11814 this.on('keydown', handleActivity);
11815 this.on('keyup', handleActivity);
11816
11817 // Run an interval every 250 milliseconds instead of stuffing everything into
11818 // the mousemove/touchmove function itself, to prevent performance degradation.
11819 // `this.reportUserActivity` simply sets this.userActivity_ to true, which
11820 // then gets picked up by this loop
11821 // http://ejohn.org/blog/learning-from-twitter/
11822 var inactivityTimeout = undefined;
11823 var activityCheck = this.setInterval(function () {
11824 // Check to see if mouse/touch activity has happened
11825 if (this.userActivity_) {
11826 // Reset the activity tracker
11827 this.userActivity_ = false;
11828
11829 // If the user state was inactive, set the state to active
11830 this.userActive(true);
11831
11832 // Clear any existing inactivity timeout to start the timer over
11833 this.clearTimeout(inactivityTimeout);
11834
11835 var timeout = this.options_['inactivityTimeout'];
11836 if (timeout > 0) {
11837 // In <timeout> milliseconds, if no more activity has occurred the
11838 // user will be considered inactive
11839 inactivityTimeout = this.setTimeout(function () {
11840 // Protect against the case where the inactivityTimeout can trigger just
11841 // before the next user activity is picked up by the activityCheck loop
11842 // causing a flicker
11843 if (!this.userActivity_) {
11844 this.userActive(false);
11845 }
11846 }, timeout);
11847 }
11848 }
11849 }, 250);
11850 };
11851
11852 /**
11853 * Gets or sets the current playback rate. A playback rate of
11854 * 1.0 represents normal speed and 0.5 would indicate half-speed
11855 * playback, for instance.
11856 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-playbackrate
11857 *
11858 * @param {Number} rate New playback rate to set.
11859 * @return {Number} Returns the new playback rate when setting
11860 * @return {Number} Returns the current playback rate when getting
11861 * @method playbackRate
11862 */
11863
11864 Player.prototype.playbackRate = function playbackRate(rate) {
11865 if (rate !== undefined) {
11866 this.techCall_('setPlaybackRate', rate);
11867 return this;
11868 }
11869
11870 if (this.tech_ && this.tech_['featuresPlaybackRate']) {
11871 return this.techGet_('playbackRate');
11872 } else {
11873 return 1.0;
11874 }
11875 };
11876
11877 /**
11878 * Gets or sets the audio flag
11879 *
11880 * @param {Boolean} bool True signals that this is an audio player.
11881 * @return {Boolean} Returns true if player is audio, false if not when getting
11882 * @return {Player} Returns the player if setting
11883 * @private
11884 * @method isAudio
11885 */
11886
11887 Player.prototype.isAudio = function isAudio(bool) {
11888 if (bool !== undefined) {
11889 this.isAudio_ = !!bool;
11890 return this;
11891 }
11892
11893 return !!this.isAudio_;
11894 };
11895
11896 /**
11897 * Returns the current state of network activity for the element, from
11898 * the codes in the list below.
11899 * - NETWORK_EMPTY (numeric value 0)
11900 * The element has not yet been initialised. All attributes are in
11901 * their initial states.
11902 * - NETWORK_IDLE (numeric value 1)
11903 * The element's resource selection algorithm is active and has
11904 * selected a resource, but it is not actually using the network at
11905 * this time.
11906 * - NETWORK_LOADING (numeric value 2)
11907 * The user agent is actively trying to download data.
11908 * - NETWORK_NO_SOURCE (numeric value 3)
11909 * The element's resource selection algorithm is active, but it has
11910 * not yet found a resource to use.
11911 *
11912 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#network-states
11913 * @return {Number} the current network activity state
11914 * @method networkState
11915 */
11916
11917 Player.prototype.networkState = function networkState() {
11918 return this.techGet_('networkState');
11919 };
11920
11921 /**
11922 * Returns a value that expresses the current state of the element
11923 * with respect to rendering the current playback position, from the
11924 * codes in the list below.
11925 * - HAVE_NOTHING (numeric value 0)
11926 * No information regarding the media resource is available.
11927 * - HAVE_METADATA (numeric value 1)
11928 * Enough of the resource has been obtained that the duration of the
11929 * resource is available.
11930 * - HAVE_CURRENT_DATA (numeric value 2)
11931 * Data for the immediate current playback position is available.
11932 * - HAVE_FUTURE_DATA (numeric value 3)
11933 * Data for the immediate current playback position is available, as
11934 * well as enough data for the user agent to advance the current
11935 * playback position in the direction of playback.
11936 * - HAVE_ENOUGH_DATA (numeric value 4)
11937 * The user agent estimates that enough data is available for
11938 * playback to proceed uninterrupted.
11939 *
11940 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-readystate
11941 * @return {Number} the current playback rendering state
11942 * @method readyState
11943 */
11944
11945 Player.prototype.readyState = function readyState() {
11946 return this.techGet_('readyState');
11947 };
11948
11949 /*
11950 * Text tracks are tracks of timed text events.
11951 * Captions - text displayed over the video for the hearing impaired
11952 * Subtitles - text displayed over the video for those who don't understand language in the video
11953 * Chapters - text displayed in a menu allowing the user to jump to particular points (chapters) in the video
11954 * Descriptions (not supported yet) - audio descriptions that are read back to the user by a screen reading device
11955 */
11956
11957 /**
11958 * Get an array of associated text tracks. captions, subtitles, chapters, descriptions
11959 * http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks
11960 *
11961 * @return {Array} Array of track objects
11962 * @method textTracks
11963 */
11964
11965 Player.prototype.textTracks = function textTracks() {
11966 // cannot use techGet_ directly because it checks to see whether the tech is ready.
11967 // Flash is unlikely to be ready in time but textTracks should still work.
11968 return this.tech_ && this.tech_['textTracks']();
11969 };
11970
11971 /**
11972 * Get an array of remote text tracks
11973 *
11974 * @return {Array}
11975 * @method remoteTextTracks
11976 */
11977
11978 Player.prototype.remoteTextTracks = function remoteTextTracks() {
11979 return this.tech_ && this.tech_['remoteTextTracks']();
11980 };
11981
11982 /**
11983 * Get an array of remote html track elements
11984 *
11985 * @return {HTMLTrackElement[]}
11986 * @method remoteTextTrackEls
11987 */
11988
11989 Player.prototype.remoteTextTrackEls = function remoteTextTrackEls() {
11990 return this.tech_ && this.tech_['remoteTextTrackEls']();
11991 };
11992
11993 /**
11994 * Add a text track
11995 * In addition to the W3C settings we allow adding additional info through options.
11996 * http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-addtexttrack
11997 *
11998 * @param {String} kind Captions, subtitles, chapters, descriptions, or metadata
11999 * @param {String=} label Optional label
12000 * @param {String=} language Optional language
12001 * @method addTextTrack
12002 */
12003
12004 Player.prototype.addTextTrack = function addTextTrack(kind, label, language) {
12005 return this.tech_ && this.tech_['addTextTrack'](kind, label, language);
12006 };
12007
12008 /**
12009 * Add a remote text track
12010 *
12011 * @param {Object} options Options for remote text track
12012 * @method addRemoteTextTrack
12013 */
12014
12015 Player.prototype.addRemoteTextTrack = function addRemoteTextTrack(options) {
12016 return this.tech_ && this.tech_['addRemoteTextTrack'](options);
12017 };
12018
12019 /**
12020 * Remove a remote text track
12021 *
12022 * @param {Object} track Remote text track to remove
12023 * @method removeRemoteTextTrack
12024 */
12025
12026 Player.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) {
12027 this.tech_ && this.tech_['removeRemoteTextTrack'](track);
12028 };
12029
12030 /**
12031 * Get video width
12032 *
12033 * @return {Number} Video width
12034 * @method videoWidth
12035 */
12036
12037 Player.prototype.videoWidth = function videoWidth() {
12038 return this.tech_ && this.tech_.videoWidth && this.tech_.videoWidth() || 0;
12039 };
12040
12041 /**
12042 * Get video height
12043 *
12044 * @return {Number} Video height
12045 * @method videoHeight
12046 */
12047
12048 Player.prototype.videoHeight = function videoHeight() {
12049 return this.tech_ && this.tech_.videoHeight && this.tech_.videoHeight() || 0;
12050 };
12051
12052 // Methods to add support for
12053 // initialTime: function(){ return this.techCall_('initialTime'); },
12054 // startOffsetTime: function(){ return this.techCall_('startOffsetTime'); },
12055 // played: function(){ return this.techCall_('played'); },
12056 // videoTracks: function(){ return this.techCall_('videoTracks'); },
12057 // audioTracks: function(){ return this.techCall_('audioTracks'); },
12058 // defaultPlaybackRate: function(){ return this.techCall_('defaultPlaybackRate'); },
12059 // defaultMuted: function(){ return this.techCall_('defaultMuted'); }
12060
12061 /**
12062 * The player's language code
12063 * NOTE: The language should be set in the player options if you want the
12064 * the controls to be built with a specific language. Changing the lanugage
12065 * later will not update controls text.
12066 *
12067 * @param {String} code The locale string
12068 * @return {String} The locale string when getting
12069 * @return {Player} self when setting
12070 * @method language
12071 */
12072
12073 Player.prototype.language = function language(code) {
12074 if (code === undefined) {
12075 return this.language_;
12076 }
12077
12078 this.language_ = ('' + code).toLowerCase();
12079 return this;
12080 };
12081
12082 /**
12083 * Get the player's language dictionary
12084 * Merge every time, because a newly added plugin might call videojs.addLanguage() at any time
12085 * Languages specified directly in the player options have precedence
12086 *
12087 * @return {Array} Array of languages
12088 * @method languages
12089 */
12090
12091 Player.prototype.languages = function languages() {
12092 return _utilsMergeOptionsJs2['default'](Player.prototype.options_.languages, this.languages_);
12093 };
12094
12095 /**
12096 * Converts track info to JSON
12097 *
12098 * @return {Object} JSON object of options
12099 * @method toJSON
12100 */
12101
12102 Player.prototype.toJSON = function toJSON() {
12103 var options = _utilsMergeOptionsJs2['default'](this.options_);
12104 var tracks = options.tracks;
12105
12106 options.tracks = [];
12107
12108 for (var i = 0; i < tracks.length; i++) {
12109 var track = tracks[i];
12110
12111 // deep merge tracks and null out player so no circular references
12112 track = _utilsMergeOptionsJs2['default'](track);
12113 track.player = undefined;
12114 options.tracks[i] = track;
12115 }
12116
12117 return options;
12118 };
12119
12120 /**
12121 * Creates a simple modal dialog (an instance of the `ModalDialog`
12122 * component) that immediately overlays the player with arbitrary
12123 * content and removes itself when closed.
12124 *
12125 * @param {String|Function|Element|Array|Null} content
12126 * Same as `ModalDialog#content`'s param of the same name.
12127 *
12128 * The most straight-forward usage is to provide a string or DOM
12129 * element.
12130 *
12131 * @param {Object} [options]
12132 * Extra options which will be passed on to the `ModalDialog`.
12133 *
12134 * @return {ModalDialog}
12135 */
12136
12137 Player.prototype.createModal = function createModal(content, options) {
12138 var player = this;
12139
12140 options = options || {};
12141 options.content = content || '';
12142
12143 var modal = new _modalDialog2['default'](player, options);
12144
12145 player.addChild(modal);
12146 modal.on('dispose', function () {
12147 player.removeChild(modal);
12148 });
12149
12150 return modal.open();
12151 };
12152
12153 /**
12154 * Gets tag settings
12155 *
12156 * @param {Element} tag The player tag
12157 * @return {Array} An array of sources and track objects
12158 * @static
12159 * @method getTagSettings
12160 */
12161
12162 Player.getTagSettings = function getTagSettings(tag) {
12163 var baseOptions = {
12164 'sources': [],
12165 'tracks': []
12166 };
12167
12168 var tagOptions = Dom.getElAttributes(tag);
12169 var dataSetup = tagOptions['data-setup'];
12170
12171 // Check if data-setup attr exists.
12172 if (dataSetup !== null) {
12173 // Parse options JSON
12174
12175 var _safeParseTuple = _safeJsonParseTuple2['default'](dataSetup || '{}');
12176
12177 var err = _safeParseTuple[0];
12178 var data = _safeParseTuple[1];
12179
12180 if (err) {
12181 _utilsLogJs2['default'].error(err);
12182 }
12183 _objectAssign2['default'](tagOptions, data);
12184 }
12185
12186 _objectAssign2['default'](baseOptions, tagOptions);
12187
12188 // Get tag children settings
12189 if (tag.hasChildNodes()) {
12190 var children = tag.childNodes;
12191
12192 for (var i = 0, j = children.length; i < j; i++) {
12193 var child = children[i];
12194 // Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
12195 var childName = child.nodeName.toLowerCase();
12196 if (childName === 'source') {
12197 baseOptions.sources.push(Dom.getElAttributes(child));
12198 } else if (childName === 'track') {
12199 baseOptions.tracks.push(Dom.getElAttributes(child));
12200 }
12201 }
12202 }
12203
12204 return baseOptions;
12205 };
12206
12207 return Player;
12208})(_componentJs2['default']);
12209
12210Player.players = {};
12211
12212var navigator = _globalWindow2['default'].navigator;
12213/*
12214 * Player instance options, surfaced using options
12215 * options = Player.prototype.options_
12216 * Make changes in options, not here.
12217 *
12218 * @type {Object}
12219 * @private
12220 */
12221Player.prototype.options_ = {
12222 // Default order of fallback technology
12223 techOrder: ['html5', 'flash'],
12224 // techOrder: ['flash','html5'],
12225
12226 html5: {},
12227 flash: {},
12228
12229 // defaultVolume: 0.85,
12230 defaultVolume: 0.00, // The freakin seaguls are driving me crazy!
12231
12232 // default inactivity timeout
12233 inactivityTimeout: 2000,
12234
12235 // default playback rates
12236 playbackRates: [],
12237 // Add playback rate selection by adding rates
12238 // 'playbackRates': [0.5, 1, 1.5, 2],
12239
12240 // Included control sets
12241 children: ['mediaLoader', 'posterImage', 'textTrackDisplay', 'loadingSpinner', 'bigPlayButton', 'controlBar', 'errorDisplay', 'textTrackSettings'],
12242
12243 language: _globalDocument2['default'].getElementsByTagName('html')[0].getAttribute('lang') || navigator.languages && navigator.languages[0] || navigator.userLanguage || navigator.language || 'en',
12244
12245 // locales and their language translations
12246 languages: {},
12247
12248 // Default message to show when a video cannot be played.
12249 notSupportedMessage: 'No compatible source was found for this media.'
12250};
12251
12252/**
12253 * Fired when the player has initial duration and dimension information
12254 *
12255 * @event loadedmetadata
12256 */
12257Player.prototype.handleLoadedMetaData_;
12258
12259/**
12260 * Fired when the player has downloaded data at the current playback position
12261 *
12262 * @event loadeddata
12263 */
12264Player.prototype.handleLoadedData_;
12265
12266/**
12267 * Fired when the user is active, e.g. moves the mouse over the player
12268 *
12269 * @event useractive
12270 */
12271Player.prototype.handleUserActive_;
12272
12273/**
12274 * Fired when the user is inactive, e.g. a short delay after the last mouse move or control interaction
12275 *
12276 * @event userinactive
12277 */
12278Player.prototype.handleUserInactive_;
12279
12280/**
12281 * Fired when the current playback position has changed *
12282 * During playback this is fired every 15-250 milliseconds, depending on the
12283 * playback technology in use.
12284 *
12285 * @event timeupdate
12286 */
12287Player.prototype.handleTimeUpdate_;
12288
12289/**
12290 * Fired when video playback ends
12291 *
12292 * @event ended
12293 */
12294Player.prototype.handleTechEnded_;
12295
12296/**
12297 * Fired when the volume changes
12298 *
12299 * @event volumechange
12300 */
12301Player.prototype.handleVolumeChange_;
12302
12303/**
12304 * Fired when an error occurs
12305 *
12306 * @event error
12307 */
12308Player.prototype.handleError_;
12309
12310Player.prototype.flexNotSupported_ = function () {
12311 var elem = _globalDocument2['default'].createElement('i');
12312
12313 // Note: We don't actually use flexBasis (or flexOrder), but it's one of the more
12314 // common flex features that we can rely on when checking for flex support.
12315 return !('flexBasis' in elem.style || 'webkitFlexBasis' in elem.style || 'mozFlexBasis' in elem.style || 'msFlexBasis' in elem.style || 'msFlexOrder' in elem.style) /* IE10-specific (2012 flex spec) */;
12316};
12317
12318_componentJs2['default'].registerComponent('Player', Player);
12319exports['default'] = Player;
12320module.exports = exports['default'];
12321// If empty string, make it a parsable json object.
12322
12323},{"./big-play-button.js":63,"./component.js":67,"./control-bar/control-bar.js":68,"./error-display.js":98,"./fullscreen-api.js":101,"./loading-spinner.js":102,"./media-error.js":103,"./modal-dialog":107,"./poster-image.js":112,"./tech/html5.js":117,"./tech/loader.js":118,"./tech/tech.js":119,"./tracks/text-track-display.js":123,"./tracks/text-track-list-converter.js":125,"./tracks/text-track-settings.js":127,"./utils/browser.js":129,"./utils/buffer.js":130,"./utils/dom.js":132,"./utils/events.js":133,"./utils/fn.js":134,"./utils/guid.js":136,"./utils/log.js":137,"./utils/merge-options.js":138,"./utils/stylesheet.js":139,"./utils/time-ranges.js":140,"./utils/to-title-case.js":141,"global/document":1,"global/window":2,"object.assign":45,"safe-json-parse/tuple":54}],109:[function(_dereq_,module,exports){
12324/**
12325 * @file plugins.js
12326 */
12327'use strict';
12328
12329exports.__esModule = true;
12330
12331function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12332
12333var _playerJs = _dereq_('./player.js');
12334
12335var _playerJs2 = _interopRequireDefault(_playerJs);
12336
12337/**
12338 * The method for registering a video.js plugin
12339 *
12340 * @param {String} name The name of the plugin
12341 * @param {Function} init The function that is run when the player inits
12342 * @method plugin
12343 */
12344var plugin = function plugin(name, init) {
12345 _playerJs2['default'].prototype[name] = init;
12346};
12347
12348exports['default'] = plugin;
12349module.exports = exports['default'];
12350
12351},{"./player.js":108}],110:[function(_dereq_,module,exports){
12352/**
12353 * @file popup-button.js
12354 */
12355'use strict';
12356
12357exports.__esModule = true;
12358
12359function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
12360
12361function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12362
12363function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12364
12365function _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; }
12366
12367var _clickableComponentJs = _dereq_('../clickable-component.js');
12368
12369var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs);
12370
12371var _componentJs = _dereq_('../component.js');
12372
12373var _componentJs2 = _interopRequireDefault(_componentJs);
12374
12375var _popupJs = _dereq_('./popup.js');
12376
12377var _popupJs2 = _interopRequireDefault(_popupJs);
12378
12379var _utilsDomJs = _dereq_('../utils/dom.js');
12380
12381var Dom = _interopRequireWildcard(_utilsDomJs);
12382
12383var _utilsFnJs = _dereq_('../utils/fn.js');
12384
12385var Fn = _interopRequireWildcard(_utilsFnJs);
12386
12387var _utilsToTitleCaseJs = _dereq_('../utils/to-title-case.js');
12388
12389var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs);
12390
12391/**
12392 * A button class with a popup control
12393 *
12394 * @param {Player|Object} player
12395 * @param {Object=} options
12396 * @extends ClickableComponent
12397 * @class PopupButton
12398 */
12399
12400var PopupButton = (function (_ClickableComponent) {
12401 _inherits(PopupButton, _ClickableComponent);
12402
12403 function PopupButton(player) {
12404 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
12405
12406 _classCallCheck(this, PopupButton);
12407
12408 _ClickableComponent.call(this, player, options);
12409
12410 this.update();
12411 }
12412
12413 /**
12414 * Update popup
12415 *
12416 * @method update
12417 */
12418
12419 PopupButton.prototype.update = function update() {
12420 var popup = this.createPopup();
12421
12422 if (this.popup) {
12423 this.removeChild(this.popup);
12424 }
12425
12426 this.popup = popup;
12427 this.addChild(popup);
12428
12429 if (this.items && this.items.length === 0) {
12430 this.hide();
12431 } else if (this.items && this.items.length > 1) {
12432 this.show();
12433 }
12434 };
12435
12436 /**
12437 * Create popup - Override with specific functionality for component
12438 *
12439 * @return {Popup} The constructed popup
12440 * @method createPopup
12441 */
12442
12443 PopupButton.prototype.createPopup = function createPopup() {};
12444
12445 /**
12446 * Create the component's DOM element
12447 *
12448 * @return {Element}
12449 * @method createEl
12450 */
12451
12452 PopupButton.prototype.createEl = function createEl() {
12453 return _ClickableComponent.prototype.createEl.call(this, 'div', {
12454 className: this.buildCSSClass()
12455 });
12456 };
12457
12458 /**
12459 * Allow sub components to stack CSS class names
12460 *
12461 * @return {String} The constructed class name
12462 * @method buildCSSClass
12463 */
12464
12465 PopupButton.prototype.buildCSSClass = function buildCSSClass() {
12466 var menuButtonClass = 'vjs-menu-button';
12467
12468 // If the inline option is passed, we want to use different styles altogether.
12469 if (this.options_.inline === true) {
12470 menuButtonClass += '-inline';
12471 } else {
12472 menuButtonClass += '-popup';
12473 }
12474
12475 return 'vjs-menu-button ' + menuButtonClass + ' ' + _ClickableComponent.prototype.buildCSSClass.call(this);
12476 };
12477
12478 return PopupButton;
12479})(_clickableComponentJs2['default']);
12480
12481_componentJs2['default'].registerComponent('PopupButton', PopupButton);
12482exports['default'] = PopupButton;
12483module.exports = exports['default'];
12484
12485},{"../clickable-component.js":65,"../component.js":67,"../utils/dom.js":132,"../utils/fn.js":134,"../utils/to-title-case.js":141,"./popup.js":111}],111:[function(_dereq_,module,exports){
12486/**
12487 * @file popup.js
12488 */
12489'use strict';
12490
12491exports.__esModule = true;
12492
12493function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
12494
12495function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12496
12497function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12498
12499function _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; }
12500
12501var _componentJs = _dereq_('../component.js');
12502
12503var _componentJs2 = _interopRequireDefault(_componentJs);
12504
12505var _utilsDomJs = _dereq_('../utils/dom.js');
12506
12507var Dom = _interopRequireWildcard(_utilsDomJs);
12508
12509var _utilsFnJs = _dereq_('../utils/fn.js');
12510
12511var Fn = _interopRequireWildcard(_utilsFnJs);
12512
12513var _utilsEventsJs = _dereq_('../utils/events.js');
12514
12515var Events = _interopRequireWildcard(_utilsEventsJs);
12516
12517/**
12518 * The Popup component is used to build pop up controls.
12519 *
12520 * @extends Component
12521 * @class Popup
12522 */
12523
12524var Popup = (function (_Component) {
12525 _inherits(Popup, _Component);
12526
12527 function Popup() {
12528 _classCallCheck(this, Popup);
12529
12530 _Component.apply(this, arguments);
12531 }
12532
12533 /**
12534 * Add a popup item to the popup
12535 *
12536 * @param {Object|String} component Component or component type to add
12537 * @method addItem
12538 */
12539
12540 Popup.prototype.addItem = function addItem(component) {
12541 this.addChild(component);
12542 component.on('click', Fn.bind(this, function () {
12543 this.unlockShowing();
12544 }));
12545 };
12546
12547 /**
12548 * Create the component's DOM element
12549 *
12550 * @return {Element}
12551 * @method createEl
12552 */
12553
12554 Popup.prototype.createEl = function createEl() {
12555 var contentElType = this.options_.contentElType || 'ul';
12556 this.contentEl_ = Dom.createEl(contentElType, {
12557 className: 'vjs-menu-content'
12558 });
12559 var el = _Component.prototype.createEl.call(this, 'div', {
12560 append: this.contentEl_,
12561 className: 'vjs-menu'
12562 });
12563 el.appendChild(this.contentEl_);
12564
12565 // Prevent clicks from bubbling up. Needed for Popup Buttons,
12566 // where a click on the parent is significant
12567 Events.on(el, 'click', function (event) {
12568 event.preventDefault();
12569 event.stopImmediatePropagation();
12570 });
12571
12572 return el;
12573 };
12574
12575 return Popup;
12576})(_componentJs2['default']);
12577
12578_componentJs2['default'].registerComponent('Popup', Popup);
12579exports['default'] = Popup;
12580module.exports = exports['default'];
12581
12582},{"../component.js":67,"../utils/dom.js":132,"../utils/events.js":133,"../utils/fn.js":134}],112:[function(_dereq_,module,exports){
12583/**
12584 * @file poster-image.js
12585 */
12586'use strict';
12587
12588exports.__esModule = true;
12589
12590function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
12591
12592function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12593
12594function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12595
12596function _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; }
12597
12598var _clickableComponentJs = _dereq_('./clickable-component.js');
12599
12600var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs);
12601
12602var _componentJs = _dereq_('./component.js');
12603
12604var _componentJs2 = _interopRequireDefault(_componentJs);
12605
12606var _utilsFnJs = _dereq_('./utils/fn.js');
12607
12608var Fn = _interopRequireWildcard(_utilsFnJs);
12609
12610var _utilsDomJs = _dereq_('./utils/dom.js');
12611
12612var Dom = _interopRequireWildcard(_utilsDomJs);
12613
12614var _utilsBrowserJs = _dereq_('./utils/browser.js');
12615
12616var browser = _interopRequireWildcard(_utilsBrowserJs);
12617
12618/**
12619 * The component that handles showing the poster image.
12620 *
12621 * @param {Player|Object} player
12622 * @param {Object=} options
12623 * @extends Button
12624 * @class PosterImage
12625 */
12626
12627var PosterImage = (function (_ClickableComponent) {
12628 _inherits(PosterImage, _ClickableComponent);
12629
12630 function PosterImage(player, options) {
12631 _classCallCheck(this, PosterImage);
12632
12633 _ClickableComponent.call(this, player, options);
12634
12635 this.update();
12636 player.on('posterchange', Fn.bind(this, this.update));
12637 }
12638
12639 /**
12640 * Clean up the poster image
12641 *
12642 * @method dispose
12643 */
12644
12645 PosterImage.prototype.dispose = function dispose() {
12646 this.player().off('posterchange', this.update);
12647 _ClickableComponent.prototype.dispose.call(this);
12648 };
12649
12650 /**
12651 * Create the poster's image element
12652 *
12653 * @return {Element}
12654 * @method createEl
12655 */
12656
12657 PosterImage.prototype.createEl = function createEl() {
12658 var el = Dom.createEl('div', {
12659 className: 'vjs-poster',
12660
12661 // Don't want poster to be tabbable.
12662 tabIndex: -1
12663 });
12664
12665 // To ensure the poster image resizes while maintaining its original aspect
12666 // ratio, use a div with `background-size` when available. For browsers that
12667 // do not support `background-size` (e.g. IE8), fall back on using a regular
12668 // img element.
12669 if (!browser.BACKGROUND_SIZE_SUPPORTED) {
12670 this.fallbackImg_ = Dom.createEl('img');
12671 el.appendChild(this.fallbackImg_);
12672 }
12673
12674 return el;
12675 };
12676
12677 /**
12678 * Event handler for updates to the player's poster source
12679 *
12680 * @method update
12681 */
12682
12683 PosterImage.prototype.update = function update() {
12684 var url = this.player().poster();
12685
12686 this.setSrc(url);
12687
12688 // If there's no poster source we should display:none on this component
12689 // so it's not still clickable or right-clickable
12690 if (url) {
12691 this.show();
12692 } else {
12693 this.hide();
12694 }
12695 };
12696
12697 /**
12698 * Set the poster source depending on the display method
12699 *
12700 * @param {String} url The URL to the poster source
12701 * @method setSrc
12702 */
12703
12704 PosterImage.prototype.setSrc = function setSrc(url) {
12705 if (this.fallbackImg_) {
12706 this.fallbackImg_.src = url;
12707 } else {
12708 var backgroundImage = '';
12709 // Any falsey values should stay as an empty string, otherwise
12710 // this will throw an extra error
12711 if (url) {
12712 backgroundImage = 'url("' + url + '")';
12713 }
12714
12715 this.el_.style.backgroundImage = backgroundImage;
12716 }
12717 };
12718
12719 /**
12720 * Event handler for clicks on the poster image
12721 *
12722 * @method handleClick
12723 */
12724
12725 PosterImage.prototype.handleClick = function handleClick() {
12726 // We don't want a click to trigger playback when controls are disabled
12727 // but CSS should be hiding the poster to prevent that from happening
12728 if (this.player_.paused()) {
12729 this.player_.play();
12730 } else {
12731 this.player_.pause();
12732 }
12733 };
12734
12735 return PosterImage;
12736})(_clickableComponentJs2['default']);
12737
12738_componentJs2['default'].registerComponent('PosterImage', PosterImage);
12739exports['default'] = PosterImage;
12740module.exports = exports['default'];
12741
12742},{"./clickable-component.js":65,"./component.js":67,"./utils/browser.js":129,"./utils/dom.js":132,"./utils/fn.js":134}],113:[function(_dereq_,module,exports){
12743/**
12744 * @file setup.js
12745 *
12746 * Functions for automatically setting up a player
12747 * based on the data-setup attribute of the video tag
12748 */
12749'use strict';
12750
12751exports.__esModule = true;
12752
12753function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12754
12755function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
12756
12757var _utilsEventsJs = _dereq_('./utils/events.js');
12758
12759var Events = _interopRequireWildcard(_utilsEventsJs);
12760
12761var _globalDocument = _dereq_('global/document');
12762
12763var _globalDocument2 = _interopRequireDefault(_globalDocument);
12764
12765var _globalWindow = _dereq_('global/window');
12766
12767var _globalWindow2 = _interopRequireDefault(_globalWindow);
12768
12769var _windowLoaded = false;
12770var videojs = undefined;
12771
12772// Automatically set up any tags that have a data-setup attribute
12773var autoSetup = function autoSetup() {
12774 // One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack*
12775 // var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
12776 // var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
12777 // var mediaEls = vids.concat(audios);
12778
12779 // Because IE8 doesn't support calling slice on a node list, we need to loop through each list of elements
12780 // to build up a new, combined list of elements.
12781 var vids = _globalDocument2['default'].getElementsByTagName('video');
12782 var audios = _globalDocument2['default'].getElementsByTagName('audio');
12783 var mediaEls = [];
12784 if (vids && vids.length > 0) {
12785 for (var i = 0, e = vids.length; i < e; i++) {
12786 mediaEls.push(vids[i]);
12787 }
12788 }
12789 if (audios && audios.length > 0) {
12790 for (var i = 0, e = audios.length; i < e; i++) {
12791 mediaEls.push(audios[i]);
12792 }
12793 }
12794
12795 // Check if any media elements exist
12796 if (mediaEls && mediaEls.length > 0) {
12797
12798 for (var i = 0, e = mediaEls.length; i < e; i++) {
12799 var mediaEl = mediaEls[i];
12800
12801 // Check if element exists, has getAttribute func.
12802 // IE seems to consider typeof el.getAttribute == 'object' instead of 'function' like expected, at least when loading the player immediately.
12803 if (mediaEl && mediaEl.getAttribute) {
12804
12805 // Make sure this player hasn't already been set up.
12806 if (mediaEl['player'] === undefined) {
12807 var options = mediaEl.getAttribute('data-setup');
12808
12809 // Check if data-setup attr exists.
12810 // We only auto-setup if they've added the data-setup attr.
12811 if (options !== null) {
12812 // Create new video.js instance.
12813 var player = videojs(mediaEl);
12814 }
12815 }
12816
12817 // If getAttribute isn't defined, we need to wait for the DOM.
12818 } else {
12819 autoSetupTimeout(1);
12820 break;
12821 }
12822 }
12823
12824 // No videos were found, so keep looping unless page is finished loading.
12825 } else if (!_windowLoaded) {
12826 autoSetupTimeout(1);
12827 }
12828};
12829
12830// Pause to let the DOM keep processing
12831var autoSetupTimeout = function autoSetupTimeout(wait, vjs) {
12832 if (vjs) {
12833 videojs = vjs;
12834 }
12835
12836 setTimeout(autoSetup, wait);
12837};
12838
12839if (_globalDocument2['default'].readyState === 'complete') {
12840 _windowLoaded = true;
12841} else {
12842 Events.one(_globalWindow2['default'], 'load', function () {
12843 _windowLoaded = true;
12844 });
12845}
12846
12847var hasLoaded = function hasLoaded() {
12848 return _windowLoaded;
12849};
12850
12851exports.autoSetup = autoSetup;
12852exports.autoSetupTimeout = autoSetupTimeout;
12853exports.hasLoaded = hasLoaded;
12854
12855},{"./utils/events.js":133,"global/document":1,"global/window":2}],114:[function(_dereq_,module,exports){
12856/**
12857 * @file slider.js
12858 */
12859'use strict';
12860
12861exports.__esModule = true;
12862
12863function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
12864
12865function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12866
12867function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
12868
12869function _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; }
12870
12871var _componentJs = _dereq_('../component.js');
12872
12873var _componentJs2 = _interopRequireDefault(_componentJs);
12874
12875var _utilsDomJs = _dereq_('../utils/dom.js');
12876
12877var Dom = _interopRequireWildcard(_utilsDomJs);
12878
12879var _globalDocument = _dereq_('global/document');
12880
12881var _globalDocument2 = _interopRequireDefault(_globalDocument);
12882
12883var _objectAssign = _dereq_('object.assign');
12884
12885var _objectAssign2 = _interopRequireDefault(_objectAssign);
12886
12887/**
12888 * The base functionality for sliders like the volume bar and seek bar
12889 *
12890 * @param {Player|Object} player
12891 * @param {Object=} options
12892 * @extends Component
12893 * @class Slider
12894 */
12895
12896var Slider = (function (_Component) {
12897 _inherits(Slider, _Component);
12898
12899 function Slider(player, options) {
12900 _classCallCheck(this, Slider);
12901
12902 _Component.call(this, player, options);
12903
12904 // Set property names to bar to match with the child Slider class is looking for
12905 this.bar = this.getChild(this.options_.barName);
12906
12907 // Set a horizontal or vertical class on the slider depending on the slider type
12908 this.vertical(!!this.options_.vertical);
12909
12910 this.on('mousedown', this.handleMouseDown);
12911 this.on('touchstart', this.handleMouseDown);
12912 this.on('focus', this.handleFocus);
12913 this.on('blur', this.handleBlur);
12914 this.on('click', this.handleClick);
12915
12916 this.on(player, 'controlsvisible', this.update);
12917 this.on(player, this.playerEvent, this.update);
12918 }
12919
12920 /**
12921 * Create the component's DOM element
12922 *
12923 * @param {String} type Type of element to create
12924 * @param {Object=} props List of properties in Object form
12925 * @return {Element}
12926 * @method createEl
12927 */
12928
12929 Slider.prototype.createEl = function createEl(type) {
12930 var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
12931 var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
12932
12933 // Add the slider element class to all sub classes
12934 props.className = props.className + ' vjs-slider';
12935 props = _objectAssign2['default']({
12936 tabIndex: 0
12937 }, props);
12938
12939 attributes = _objectAssign2['default']({
12940 'role': 'slider',
12941 'aria-valuenow': 0,
12942 'aria-valuemin': 0,
12943 'aria-valuemax': 100,
12944 tabIndex: 0
12945 }, attributes);
12946
12947 return _Component.prototype.createEl.call(this, type, props, attributes);
12948 };
12949
12950 /**
12951 * Handle mouse down on slider
12952 *
12953 * @param {Object} event Mouse down event object
12954 * @method handleMouseDown
12955 */
12956
12957 Slider.prototype.handleMouseDown = function handleMouseDown(event) {
12958 event.preventDefault();
12959 Dom.blockTextSelection();
12960
12961 this.addClass('vjs-sliding');
12962 this.trigger('slideractive');
12963
12964 this.on(_globalDocument2['default'], 'mousemove', this.handleMouseMove);
12965 this.on(_globalDocument2['default'], 'mouseup', this.handleMouseUp);
12966 this.on(_globalDocument2['default'], 'touchmove', this.handleMouseMove);
12967 this.on(_globalDocument2['default'], 'touchend', this.handleMouseUp);
12968
12969 this.handleMouseMove(event);
12970 };
12971
12972 /**
12973 * To be overridden by a subclass
12974 *
12975 * @method handleMouseMove
12976 */
12977
12978 Slider.prototype.handleMouseMove = function handleMouseMove() {};
12979
12980 /**
12981 * Handle mouse up on Slider
12982 *
12983 * @method handleMouseUp
12984 */
12985
12986 Slider.prototype.handleMouseUp = function handleMouseUp() {
12987 Dom.unblockTextSelection();
12988
12989 this.removeClass('vjs-sliding');
12990 this.trigger('sliderinactive');
12991
12992 this.off(_globalDocument2['default'], 'mousemove', this.handleMouseMove);
12993 this.off(_globalDocument2['default'], 'mouseup', this.handleMouseUp);
12994 this.off(_globalDocument2['default'], 'touchmove', this.handleMouseMove);
12995 this.off(_globalDocument2['default'], 'touchend', this.handleMouseUp);
12996
12997 this.update();
12998 };
12999
13000 /**
13001 * Update slider
13002 *
13003 * @method update
13004 */
13005
13006 Slider.prototype.update = function update() {
13007 // In VolumeBar init we have a setTimeout for update that pops and update to the end of the
13008 // execution stack. The player is destroyed before then update will cause an error
13009 if (!this.el_) return;
13010
13011 // If scrubbing, we could use a cached value to make the handle keep up with the user's mouse.
13012 // On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later.
13013 // var progress = (this.player_.scrubbing()) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration();
13014 var progress = this.getPercent();
13015 var bar = this.bar;
13016
13017 // If there's no bar...
13018 if (!bar) return;
13019
13020 // Protect against no duration and other division issues
13021 if (typeof progress !== 'number' || progress !== progress || progress < 0 || progress === Infinity) {
13022 progress = 0;
13023 }
13024
13025 // Convert to a percentage for setting
13026 var percentage = (progress * 100).toFixed(2) + '%';
13027
13028 // Set the new bar width or height
13029 if (this.vertical()) {
13030 bar.el().style.height = percentage;
13031 } else {
13032 bar.el().style.width = percentage;
13033 }
13034 };
13035
13036 /**
13037 * Calculate distance for slider
13038 *
13039 * @param {Object} event Event object
13040 * @method calculateDistance
13041 */
13042
13043 Slider.prototype.calculateDistance = function calculateDistance(event) {
13044 var position = Dom.getPointerPosition(this.el_, event);
13045 if (this.vertical()) {
13046 return position.y;
13047 }
13048 return position.x;
13049 };
13050
13051 /**
13052 * Handle on focus for slider
13053 *
13054 * @method handleFocus
13055 */
13056
13057 Slider.prototype.handleFocus = function handleFocus() {
13058 this.on(_globalDocument2['default'], 'keydown', this.handleKeyPress);
13059 };
13060
13061 /**
13062 * Handle key press for slider
13063 *
13064 * @param {Object} event Event object
13065 * @method handleKeyPress
13066 */
13067
13068 Slider.prototype.handleKeyPress = function handleKeyPress(event) {
13069 if (event.which === 37 || event.which === 40) {
13070 // Left and Down Arrows
13071 event.preventDefault();
13072 this.stepBack();
13073 } else if (event.which === 38 || event.which === 39) {
13074 // Up and Right Arrows
13075 event.preventDefault();
13076 this.stepForward();
13077 }
13078 };
13079
13080 /**
13081 * Handle on blur for slider
13082 *
13083 * @method handleBlur
13084 */
13085
13086 Slider.prototype.handleBlur = function handleBlur() {
13087 this.off(_globalDocument2['default'], 'keydown', this.handleKeyPress);
13088 };
13089
13090 /**
13091 * Listener for click events on slider, used to prevent clicks
13092 * from bubbling up to parent elements like button menus.
13093 *
13094 * @param {Object} event Event object
13095 * @method handleClick
13096 */
13097
13098 Slider.prototype.handleClick = function handleClick(event) {
13099 event.stopImmediatePropagation();
13100 event.preventDefault();
13101 };
13102
13103 /**
13104 * Get/set if slider is horizontal for vertical
13105 *
13106 * @param {Boolean} bool True if slider is vertical, false is horizontal
13107 * @return {Boolean} True if slider is vertical, false is horizontal
13108 * @method vertical
13109 */
13110
13111 Slider.prototype.vertical = function vertical(bool) {
13112 if (bool === undefined) {
13113 return this.vertical_ || false;
13114 }
13115
13116 this.vertical_ = !!bool;
13117
13118 if (this.vertical_) {
13119 this.addClass('vjs-slider-vertical');
13120 } else {
13121 this.addClass('vjs-slider-horizontal');
13122 }
13123
13124 return this;
13125 };
13126
13127 return Slider;
13128})(_componentJs2['default']);
13129
13130_componentJs2['default'].registerComponent('Slider', Slider);
13131exports['default'] = Slider;
13132module.exports = exports['default'];
13133
13134},{"../component.js":67,"../utils/dom.js":132,"global/document":1,"object.assign":45}],115:[function(_dereq_,module,exports){
13135/**
13136 * @file flash-rtmp.js
13137 */
13138'use strict';
13139
13140exports.__esModule = true;
13141function FlashRtmpDecorator(Flash) {
13142 Flash.streamingFormats = {
13143 'rtmp/mp4': 'MP4',
13144 'rtmp/flv': 'FLV'
13145 };
13146
13147 Flash.streamFromParts = function (connection, stream) {
13148 return connection + '&' + stream;
13149 };
13150
13151 Flash.streamToParts = function (src) {
13152 var parts = {
13153 connection: '',
13154 stream: ''
13155 };
13156
13157 if (!src) return parts;
13158
13159 // Look for the normal URL separator we expect, '&'.
13160 // If found, we split the URL into two pieces around the
13161 // first '&'.
13162 var connEnd = src.search(/&(?!\w+=)/);
13163 var streamBegin = undefined;
13164 if (connEnd !== -1) {
13165 streamBegin = connEnd + 1;
13166 } else {
13167 // If there's not a '&', we use the last '/' as the delimiter.
13168 connEnd = streamBegin = src.lastIndexOf('/') + 1;
13169 if (connEnd === 0) {
13170 // really, there's not a '/'?
13171 connEnd = streamBegin = src.length;
13172 }
13173 }
13174 parts.connection = src.substring(0, connEnd);
13175 parts.stream = src.substring(streamBegin, src.length);
13176
13177 return parts;
13178 };
13179
13180 Flash.isStreamingType = function (srcType) {
13181 return srcType in Flash.streamingFormats;
13182 };
13183
13184 // RTMP has four variations, any string starting
13185 // with one of these protocols should be valid
13186 Flash.RTMP_RE = /^rtmp[set]?:\/\//i;
13187
13188 Flash.isStreamingSrc = function (src) {
13189 return Flash.RTMP_RE.test(src);
13190 };
13191
13192 /**
13193 * A source handler for RTMP urls
13194 * @type {Object}
13195 */
13196 Flash.rtmpSourceHandler = {};
13197
13198 /**
13199 * Check if Flash can play the given videotype
13200 * @param {String} type The mimetype to check
13201 * @return {String} 'probably', 'maybe', or '' (empty string)
13202 */
13203 Flash.rtmpSourceHandler.canPlayType = function (type) {
13204 if (Flash.isStreamingType(type)) {
13205 return 'maybe';
13206 }
13207
13208 return '';
13209 };
13210
13211 /**
13212 * Check if Flash can handle the source natively
13213 * @param {Object} source The source object
13214 * @return {String} 'probably', 'maybe', or '' (empty string)
13215 */
13216 Flash.rtmpSourceHandler.canHandleSource = function (source) {
13217 var can = Flash.rtmpSourceHandler.canPlayType(source.type);
13218
13219 if (can) {
13220 return can;
13221 }
13222
13223 if (Flash.isStreamingSrc(source.src)) {
13224 return 'maybe';
13225 }
13226
13227 return '';
13228 };
13229
13230 /**
13231 * Pass the source to the flash object
13232 * Adaptive source handlers will have more complicated workflows before passing
13233 * video data to the video element
13234 * @param {Object} source The source object
13235 * @param {Flash} tech The instance of the Flash tech
13236 */
13237 Flash.rtmpSourceHandler.handleSource = function (source, tech) {
13238 var srcParts = Flash.streamToParts(source.src);
13239
13240 tech['setRtmpConnection'](srcParts.connection);
13241 tech['setRtmpStream'](srcParts.stream);
13242 };
13243
13244 // Register the native source handler
13245 Flash.registerSourceHandler(Flash.rtmpSourceHandler);
13246
13247 return Flash;
13248}
13249
13250exports['default'] = FlashRtmpDecorator;
13251module.exports = exports['default'];
13252
13253},{}],116:[function(_dereq_,module,exports){
13254/**
13255 * @file flash.js
13256 * VideoJS-SWF - Custom Flash Player with HTML5-ish API
13257 * https://github.com/zencoder/video-js-swf
13258 * Not using setupTriggers. Using global onEvent func to distribute events
13259 */
13260
13261'use strict';
13262
13263exports.__esModule = true;
13264
13265function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
13266
13267function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
13268
13269function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
13270
13271function _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; }
13272
13273var _tech = _dereq_('./tech');
13274
13275var _tech2 = _interopRequireDefault(_tech);
13276
13277var _utilsDomJs = _dereq_('../utils/dom.js');
13278
13279var Dom = _interopRequireWildcard(_utilsDomJs);
13280
13281var _utilsUrlJs = _dereq_('../utils/url.js');
13282
13283var Url = _interopRequireWildcard(_utilsUrlJs);
13284
13285var _utilsTimeRangesJs = _dereq_('../utils/time-ranges.js');
13286
13287var _flashRtmp = _dereq_('./flash-rtmp');
13288
13289var _flashRtmp2 = _interopRequireDefault(_flashRtmp);
13290
13291var _component = _dereq_('../component');
13292
13293var _component2 = _interopRequireDefault(_component);
13294
13295var _globalWindow = _dereq_('global/window');
13296
13297var _globalWindow2 = _interopRequireDefault(_globalWindow);
13298
13299var _objectAssign = _dereq_('object.assign');
13300
13301var _objectAssign2 = _interopRequireDefault(_objectAssign);
13302
13303var navigator = _globalWindow2['default'].navigator;
13304/**
13305 * Flash Media Controller - Wrapper for fallback SWF API
13306 *
13307 * @param {Object=} options Object of option names and values
13308 * @param {Function=} ready Ready callback function
13309 * @extends Tech
13310 * @class Flash
13311 */
13312
13313var Flash = (function (_Tech) {
13314 _inherits(Flash, _Tech);
13315
13316 function Flash(options, ready) {
13317 _classCallCheck(this, Flash);
13318
13319 _Tech.call(this, options, ready);
13320
13321 // Set the source when ready
13322 if (options.source) {
13323 this.ready(function () {
13324 this.setSource(options.source);
13325 }, true);
13326 }
13327
13328 // Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
13329 // This allows resetting the playhead when we catch the reload
13330 if (options.startTime) {
13331 this.ready(function () {
13332 this.load();
13333 this.play();
13334 this.currentTime(options.startTime);
13335 }, true);
13336 }
13337
13338 // Add global window functions that the swf expects
13339 // A 4.x workflow we weren't able to solve for in 5.0
13340 // because of the need to hard code these functions
13341 // into the swf for security reasons
13342 _globalWindow2['default'].videojs = _globalWindow2['default'].videojs || {};
13343 _globalWindow2['default'].videojs.Flash = _globalWindow2['default'].videojs.Flash || {};
13344 _globalWindow2['default'].videojs.Flash.onReady = Flash.onReady;
13345 _globalWindow2['default'].videojs.Flash.onEvent = Flash.onEvent;
13346 _globalWindow2['default'].videojs.Flash.onError = Flash.onError;
13347
13348 this.on('seeked', function () {
13349 this.lastSeekTarget_ = undefined;
13350 });
13351 }
13352
13353 // Create setters and getters for attributes
13354
13355 /**
13356 * Create the component's DOM element
13357 *
13358 * @return {Element}
13359 * @method createEl
13360 */
13361
13362 Flash.prototype.createEl = function createEl() {
13363 var options = this.options_;
13364
13365 // If video.js is hosted locally you should also set the location
13366 // for the hosted swf, which should be relative to the page (not video.js)
13367 // Otherwise this adds a CDN url.
13368 // The CDN also auto-adds a swf URL for that specific version.
13369 if (!options.swf) {
13370 options.swf = '//vjs.zencdn.net/swf/5.0.1/video-js.swf';
13371 }
13372
13373 // Generate ID for swf object
13374 var objId = options.techId;
13375
13376 // Merge default flashvars with ones passed in to init
13377 var flashVars = _objectAssign2['default']({
13378
13379 // SWF Callback Functions
13380 'readyFunction': 'videojs.Flash.onReady',
13381 'eventProxyFunction': 'videojs.Flash.onEvent',
13382 'errorEventProxyFunction': 'videojs.Flash.onError',
13383
13384 // Player Settings
13385 'autoplay': options.autoplay,
13386 'preload': options.preload,
13387 'loop': options.loop,
13388 'muted': options.muted
13389
13390 }, options.flashVars);
13391
13392 // Merge default parames with ones passed in
13393 var params = _objectAssign2['default']({
13394 'wmode': 'opaque', // Opaque is needed to overlay controls, but can affect playback performance
13395 'bgcolor': '#000000' // Using bgcolor prevents a white flash when the object is loading
13396 }, options.params);
13397
13398 // Merge default attributes with ones passed in
13399 var attributes = _objectAssign2['default']({
13400 'id': objId,
13401 'name': objId, // Both ID and Name needed or swf to identify itself
13402 'class': 'vjs-tech'
13403 }, options.attributes);
13404
13405 this.el_ = Flash.embed(options.swf, flashVars, params, attributes);
13406 this.el_.tech = this;
13407
13408 return this.el_;
13409 };
13410
13411 /**
13412 * Play for flash tech
13413 *
13414 * @method play
13415 */
13416
13417 Flash.prototype.play = function play() {
13418 if (this.ended()) {
13419 this.setCurrentTime(0);
13420 }
13421 this.el_.vjs_play();
13422 };
13423
13424 /**
13425 * Pause for flash tech
13426 *
13427 * @method pause
13428 */
13429
13430 Flash.prototype.pause = function pause() {
13431 this.el_.vjs_pause();
13432 };
13433
13434 /**
13435 * Get/set video
13436 *
13437 * @param {Object=} src Source object
13438 * @return {Object}
13439 * @method src
13440 */
13441
13442 Flash.prototype.src = function src(_src) {
13443 if (_src === undefined) {
13444 return this.currentSrc();
13445 }
13446
13447 // Setting src through `src` not `setSrc` will be deprecated
13448 return this.setSrc(_src);
13449 };
13450
13451 /**
13452 * Set video
13453 *
13454 * @param {Object=} src Source object
13455 * @deprecated
13456 * @method setSrc
13457 */
13458
13459 Flash.prototype.setSrc = function setSrc(src) {
13460 // Make sure source URL is absolute.
13461 src = Url.getAbsoluteURL(src);
13462 this.el_.vjs_src(src);
13463
13464 // Currently the SWF doesn't autoplay if you load a source later.
13465 // e.g. Load player w/ no source, wait 2s, set src.
13466 if (this.autoplay()) {
13467 var tech = this;
13468 this.setTimeout(function () {
13469 tech.play();
13470 }, 0);
13471 }
13472 };
13473
13474 /**
13475 * Returns true if the tech is currently seeking.
13476 * @return {boolean} true if seeking
13477 */
13478
13479 Flash.prototype.seeking = function seeking() {
13480 return this.lastSeekTarget_ !== undefined;
13481 };
13482
13483 /**
13484 * Set current time
13485 *
13486 * @param {Number} time Current time of video
13487 * @method setCurrentTime
13488 */
13489
13490 Flash.prototype.setCurrentTime = function setCurrentTime(time) {
13491 var seekable = this.seekable();
13492 if (seekable.length) {
13493 // clamp to the current seekable range
13494 time = time > seekable.start(0) ? time : seekable.start(0);
13495 time = time < seekable.end(seekable.length - 1) ? time : seekable.end(seekable.length - 1);
13496
13497 this.lastSeekTarget_ = time;
13498 this.trigger('seeking');
13499 this.el_.vjs_setProperty('currentTime', time);
13500 _Tech.prototype.setCurrentTime.call(this);
13501 }
13502 };
13503
13504 /**
13505 * Get current time
13506 *
13507 * @param {Number=} time Current time of video
13508 * @return {Number} Current time
13509 * @method currentTime
13510 */
13511
13512 Flash.prototype.currentTime = function currentTime(time) {
13513 // when seeking make the reported time keep up with the requested time
13514 // by reading the time we're seeking to
13515 if (this.seeking()) {
13516 return this.lastSeekTarget_ || 0;
13517 }
13518 return this.el_.vjs_getProperty('currentTime');
13519 };
13520
13521 /**
13522 * Get current source
13523 *
13524 * @method currentSrc
13525 */
13526
13527 Flash.prototype.currentSrc = function currentSrc() {
13528 if (this.currentSource_) {
13529 return this.currentSource_.src;
13530 } else {
13531 return this.el_.vjs_getProperty('currentSrc');
13532 }
13533 };
13534
13535 /**
13536 * Load media into player
13537 *
13538 * @method load
13539 */
13540
13541 Flash.prototype.load = function load() {
13542 this.el_.vjs_load();
13543 };
13544
13545 /**
13546 * Get poster
13547 *
13548 * @method poster
13549 */
13550
13551 Flash.prototype.poster = function poster() {
13552 this.el_.vjs_getProperty('poster');
13553 };
13554
13555 /**
13556 * Poster images are not handled by the Flash tech so make this a no-op
13557 *
13558 * @method setPoster
13559 */
13560
13561 Flash.prototype.setPoster = function setPoster() {};
13562
13563 /**
13564 * Determine if can seek in media
13565 *
13566 * @return {TimeRangeObject}
13567 * @method seekable
13568 */
13569
13570 Flash.prototype.seekable = function seekable() {
13571 var duration = this.duration();
13572 if (duration === 0) {
13573 return _utilsTimeRangesJs.createTimeRange();
13574 }
13575 return _utilsTimeRangesJs.createTimeRange(0, duration);
13576 };
13577
13578 /**
13579 * Get buffered time range
13580 *
13581 * @return {TimeRangeObject}
13582 * @method buffered
13583 */
13584
13585 Flash.prototype.buffered = function buffered() {
13586 var ranges = this.el_.vjs_getProperty('buffered');
13587 if (ranges.length === 0) {
13588 return _utilsTimeRangesJs.createTimeRange();
13589 }
13590 return _utilsTimeRangesJs.createTimeRange(ranges[0][0], ranges[0][1]);
13591 };
13592
13593 /**
13594 * Get fullscreen support -
13595 * Flash does not allow fullscreen through javascript
13596 * so always returns false
13597 *
13598 * @return {Boolean} false
13599 * @method supportsFullScreen
13600 */
13601
13602 Flash.prototype.supportsFullScreen = function supportsFullScreen() {
13603 return false; // Flash does not allow fullscreen through javascript
13604 };
13605
13606 /**
13607 * Request to enter fullscreen
13608 * Flash does not allow fullscreen through javascript
13609 * so always returns false
13610 *
13611 * @return {Boolean} false
13612 * @method enterFullScreen
13613 */
13614
13615 Flash.prototype.enterFullScreen = function enterFullScreen() {
13616 return false;
13617 };
13618
13619 return Flash;
13620})(_tech2['default']);
13621
13622var _api = Flash.prototype;
13623var _readWrite = 'rtmpConnection,rtmpStream,preload,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted'.split(',');
13624var _readOnly = 'networkState,readyState,initialTime,duration,startOffsetTime,paused,ended,videoTracks,audioTracks,videoWidth,videoHeight'.split(',');
13625
13626function _createSetter(attr) {
13627 var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
13628 _api['set' + attrUpper] = function (val) {
13629 return this.el_.vjs_setProperty(attr, val);
13630 };
13631}
13632function _createGetter(attr) {
13633 _api[attr] = function () {
13634 return this.el_.vjs_getProperty(attr);
13635 };
13636}
13637
13638// Create getter and setters for all read/write attributes
13639for (var i = 0; i < _readWrite.length; i++) {
13640 _createGetter(_readWrite[i]);
13641 _createSetter(_readWrite[i]);
13642}
13643
13644// Create getters for read-only attributes
13645for (var i = 0; i < _readOnly.length; i++) {
13646 _createGetter(_readOnly[i]);
13647}
13648
13649/* Flash Support Testing -------------------------------------------------------- */
13650
13651Flash.isSupported = function () {
13652 return Flash.version()[0] >= 10;
13653 // return swfobject.hasFlashPlayerVersion('10');
13654};
13655
13656// Add Source Handler pattern functions to this tech
13657_tech2['default'].withSourceHandlers(Flash);
13658
13659/*
13660 * The default native source handler.
13661 * This simply passes the source to the video element. Nothing fancy.
13662 *
13663 * @param {Object} source The source object
13664 * @param {Flash} tech The instance of the Flash tech
13665 */
13666Flash.nativeSourceHandler = {};
13667
13668/**
13669 * Check if Flash can play the given videotype
13670 * @param {String} type The mimetype to check
13671 * @return {String} 'probably', 'maybe', or '' (empty string)
13672 */
13673Flash.nativeSourceHandler.canPlayType = function (type) {
13674 if (type in Flash.formats) {
13675 return 'maybe';
13676 }
13677
13678 return '';
13679};
13680
13681/*
13682 * Check Flash can handle the source natively
13683 *
13684 * @param {Object} source The source object
13685 * @return {String} 'probably', 'maybe', or '' (empty string)
13686 */
13687Flash.nativeSourceHandler.canHandleSource = function (source) {
13688 var type;
13689
13690 function guessMimeType(src) {
13691 var ext = Url.getFileExtension(src);
13692 if (ext) {
13693 return 'video/' + ext;
13694 }
13695 return '';
13696 }
13697
13698 if (!source.type) {
13699 type = guessMimeType(source.src);
13700 } else {
13701 // Strip code information from the type because we don't get that specific
13702 type = source.type.replace(/;.*/, '').toLowerCase();
13703 }
13704
13705 return Flash.nativeSourceHandler.canPlayType(type);
13706};
13707
13708/*
13709 * Pass the source to the flash object
13710 * Adaptive source handlers will have more complicated workflows before passing
13711 * video data to the video element
13712 *
13713 * @param {Object} source The source object
13714 * @param {Flash} tech The instance of the Flash tech
13715 */
13716Flash.nativeSourceHandler.handleSource = function (source, tech) {
13717 tech.setSrc(source.src);
13718};
13719
13720/*
13721 * Clean up the source handler when disposing the player or switching sources..
13722 * (no cleanup is needed when supporting the format natively)
13723 */
13724Flash.nativeSourceHandler.dispose = function () {};
13725
13726// Register the native source handler
13727Flash.registerSourceHandler(Flash.nativeSourceHandler);
13728
13729Flash.formats = {
13730 'video/flv': 'FLV',
13731 'video/x-flv': 'FLV',
13732 'video/mp4': 'MP4',
13733 'video/m4v': 'MP4'
13734};
13735
13736Flash.onReady = function (currSwf) {
13737 var el = Dom.getEl(currSwf);
13738 var tech = el && el.tech;
13739
13740 // if there is no el then the tech has been disposed
13741 // and the tech element was removed from the player div
13742 if (tech && tech.el()) {
13743 // check that the flash object is really ready
13744 Flash.checkReady(tech);
13745 }
13746};
13747
13748// The SWF isn't always ready when it says it is. Sometimes the API functions still need to be added to the object.
13749// If it's not ready, we set a timeout to check again shortly.
13750Flash.checkReady = function (tech) {
13751 // stop worrying if the tech has been disposed
13752 if (!tech.el()) {
13753 return;
13754 }
13755
13756 // check if API property exists
13757 if (tech.el().vjs_getProperty) {
13758 // tell tech it's ready
13759 tech.triggerReady();
13760 } else {
13761 // wait longer
13762 this.setTimeout(function () {
13763 Flash['checkReady'](tech);
13764 }, 50);
13765 }
13766};
13767
13768// Trigger events from the swf on the player
13769Flash.onEvent = function (swfID, eventName) {
13770 var tech = Dom.getEl(swfID).tech;
13771 tech.trigger(eventName);
13772};
13773
13774// Log errors from the swf
13775Flash.onError = function (swfID, err) {
13776 var tech = Dom.getEl(swfID).tech;
13777
13778 // trigger MEDIA_ERR_SRC_NOT_SUPPORTED
13779 if (err === 'srcnotfound') {
13780 return tech.error(4);
13781 }
13782
13783 // trigger a custom error
13784 tech.error('FLASH: ' + err);
13785};
13786
13787// Flash Version Check
13788Flash.version = function () {
13789 var version = '0,0,0';
13790
13791 // IE
13792 try {
13793 version = new _globalWindow2['default'].ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
13794
13795 // other browsers
13796 } catch (e) {
13797 try {
13798 if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {
13799 version = (navigator.plugins['Shockwave Flash 2.0'] || navigator.plugins['Shockwave Flash']).description.replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
13800 }
13801 } catch (err) {}
13802 }
13803 return version.split(',');
13804};
13805
13806// Flash embedding method. Only used in non-iframe mode
13807Flash.embed = function (swf, flashVars, params, attributes) {
13808 var code = Flash.getEmbedCode(swf, flashVars, params, attributes);
13809
13810 // Get element by embedding code and retrieving created element
13811 var obj = Dom.createEl('div', { innerHTML: code }).childNodes[0];
13812
13813 return obj;
13814};
13815
13816Flash.getEmbedCode = function (swf, flashVars, params, attributes) {
13817 var objTag = '<object type="application/x-shockwave-flash" ';
13818 var flashVarsString = '';
13819 var paramsString = '';
13820 var attrsString = '';
13821
13822 // Convert flash vars to string
13823 if (flashVars) {
13824 Object.getOwnPropertyNames(flashVars).forEach(function (key) {
13825 flashVarsString += key + '=' + flashVars[key] + '&amp;';
13826 });
13827 }
13828
13829 // Add swf, flashVars, and other default params
13830 params = _objectAssign2['default']({
13831 'movie': swf,
13832 'flashvars': flashVarsString,
13833 'allowScriptAccess': 'always', // Required to talk to swf
13834 'allowNetworking': 'all' // All should be default, but having security issues.
13835 }, params);
13836
13837 // Create param tags string
13838 Object.getOwnPropertyNames(params).forEach(function (key) {
13839 paramsString += '<param name="' + key + '" value="' + params[key] + '" />';
13840 });
13841
13842 attributes = _objectAssign2['default']({
13843 // Add swf to attributes (need both for IE and Others to work)
13844 'data': swf,
13845
13846 // Default to 100% width/height
13847 'width': '100%',
13848 'height': '100%'
13849
13850 }, attributes);
13851
13852 // Create Attributes string
13853 Object.getOwnPropertyNames(attributes).forEach(function (key) {
13854 attrsString += key + '="' + attributes[key] + '" ';
13855 });
13856
13857 return '' + objTag + attrsString + '>' + paramsString + '</object>';
13858};
13859
13860// Run Flash through the RTMP decorator
13861_flashRtmp2['default'](Flash);
13862
13863_component2['default'].registerComponent('Flash', Flash);
13864_tech2['default'].registerTech('Flash', Flash);
13865exports['default'] = Flash;
13866module.exports = exports['default'];
13867
13868},{"../component":67,"../utils/dom.js":132,"../utils/time-ranges.js":140,"../utils/url.js":142,"./flash-rtmp":115,"./tech":119,"global/window":2,"object.assign":45}],117:[function(_dereq_,module,exports){
13869/**
13870 * @file html5.js
13871 * HTML5 Media Controller - Wrapper for HTML5 Media API
13872 */
13873
13874'use strict';
13875
13876exports.__esModule = true;
13877
13878function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
13879
13880function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
13881
13882function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
13883
13884function _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; }
13885
13886var _techJs = _dereq_('./tech.js');
13887
13888var _techJs2 = _interopRequireDefault(_techJs);
13889
13890var _component = _dereq_('../component');
13891
13892var _component2 = _interopRequireDefault(_component);
13893
13894var _utilsDomJs = _dereq_('../utils/dom.js');
13895
13896var Dom = _interopRequireWildcard(_utilsDomJs);
13897
13898var _utilsUrlJs = _dereq_('../utils/url.js');
13899
13900var Url = _interopRequireWildcard(_utilsUrlJs);
13901
13902var _utilsFnJs = _dereq_('../utils/fn.js');
13903
13904var Fn = _interopRequireWildcard(_utilsFnJs);
13905
13906var _utilsLogJs = _dereq_('../utils/log.js');
13907
13908var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
13909
13910var _utilsBrowserJs = _dereq_('../utils/browser.js');
13911
13912var browser = _interopRequireWildcard(_utilsBrowserJs);
13913
13914var _globalDocument = _dereq_('global/document');
13915
13916var _globalDocument2 = _interopRequireDefault(_globalDocument);
13917
13918var _globalWindow = _dereq_('global/window');
13919
13920var _globalWindow2 = _interopRequireDefault(_globalWindow);
13921
13922var _objectAssign = _dereq_('object.assign');
13923
13924var _objectAssign2 = _interopRequireDefault(_objectAssign);
13925
13926var _utilsMergeOptionsJs = _dereq_('../utils/merge-options.js');
13927
13928var _utilsMergeOptionsJs2 = _interopRequireDefault(_utilsMergeOptionsJs);
13929
13930/**
13931 * HTML5 Media Controller - Wrapper for HTML5 Media API
13932 *
13933 * @param {Object=} options Object of option names and values
13934 * @param {Function=} ready Ready callback function
13935 * @extends Tech
13936 * @class Html5
13937 */
13938
13939var Html5 = (function (_Tech) {
13940 _inherits(Html5, _Tech);
13941
13942 function Html5(options, ready) {
13943 _classCallCheck(this, Html5);
13944
13945 _Tech.call(this, options, ready);
13946
13947 var source = options.source;
13948
13949 // Set the source if one is provided
13950 // 1) Check if the source is new (if not, we want to keep the original so playback isn't interrupted)
13951 // 2) Check to see if the network state of the tag was failed at init, and if so, reset the source
13952 // anyway so the error gets fired.
13953 if (source && (this.el_.currentSrc !== source.src || options.tag && options.tag.initNetworkState_ === 3)) {
13954 this.setSource(source);
13955 } else {
13956 this.handleLateInit_(this.el_);
13957 }
13958
13959 if (this.el_.hasChildNodes()) {
13960
13961 var nodes = this.el_.childNodes;
13962 var nodesLength = nodes.length;
13963 var removeNodes = [];
13964
13965 while (nodesLength--) {
13966 var node = nodes[nodesLength];
13967 var nodeName = node.nodeName.toLowerCase();
13968
13969 if (nodeName === 'track') {
13970 if (!this.featuresNativeTextTracks) {
13971 // Empty video tag tracks so the built-in player doesn't use them also.
13972 // This may not be fast enough to stop HTML5 browsers from reading the tags
13973 // so we'll need to turn off any default tracks if we're manually doing
13974 // captions and subtitles. videoElement.textTracks
13975 removeNodes.push(node);
13976 } else {
13977 // store HTMLTrackElement and TextTrack to remote list
13978 this.remoteTextTrackEls().addTrackElement_(node);
13979 this.remoteTextTracks().addTrack_(node.track);
13980 }
13981 }
13982 }
13983
13984 for (var i = 0; i < removeNodes.length; i++) {
13985 this.el_.removeChild(removeNodes[i]);
13986 }
13987 }
13988
13989 if (this.featuresNativeTextTracks) {
13990 this.handleTextTrackChange_ = Fn.bind(this, this.handleTextTrackChange);
13991 this.handleTextTrackAdd_ = Fn.bind(this, this.handleTextTrackAdd);
13992 this.handleTextTrackRemove_ = Fn.bind(this, this.handleTextTrackRemove);
13993 this.proxyNativeTextTracks_();
13994 }
13995
13996 // Determine if native controls should be used
13997 // Our goal should be to get the custom controls on mobile solid everywhere
13998 // so we can remove this all together. Right now this will block custom
13999 // controls on touch enabled laptops like the Chrome Pixel
14000 if (browser.TOUCH_ENABLED && options.nativeControlsForTouch === true || browser.IS_IPHONE || browser.IS_NATIVE_ANDROID) {
14001 this.setControls(true);
14002 }
14003
14004 this.triggerReady();
14005 }
14006
14007 /* HTML5 Support Testing ---------------------------------------------------- */
14008
14009 /*
14010 * Element for testing browser HTML5 video capabilities
14011 *
14012 * @type {Element}
14013 * @constant
14014 * @private
14015 */
14016
14017 /**
14018 * Dispose of html5 media element
14019 *
14020 * @method dispose
14021 */
14022
14023 Html5.prototype.dispose = function dispose() {
14024 var tt = this.el().textTracks;
14025 var emulatedTt = this.textTracks();
14026
14027 // remove native event listeners
14028 if (tt && tt.removeEventListener) {
14029 tt.removeEventListener('change', this.handleTextTrackChange_);
14030 tt.removeEventListener('addtrack', this.handleTextTrackAdd_);
14031 tt.removeEventListener('removetrack', this.handleTextTrackRemove_);
14032 }
14033
14034 // clearout the emulated text track list.
14035 var i = emulatedTt.length;
14036
14037 while (i--) {
14038 emulatedTt.removeTrack_(emulatedTt[i]);
14039 }
14040
14041 Html5.disposeMediaElement(this.el_);
14042 _Tech.prototype.dispose.call(this);
14043 };
14044
14045 /**
14046 * Create the component's DOM element
14047 *
14048 * @return {Element}
14049 * @method createEl
14050 */
14051
14052 Html5.prototype.createEl = function createEl() {
14053 var el = this.options_.tag;
14054
14055 // Check if this browser supports moving the element into the box.
14056 // On the iPhone video will break if you move the element,
14057 // So we have to create a brand new element.
14058 if (!el || this['movingMediaElementInDOM'] === false) {
14059
14060 // If the original tag is still there, clone and remove it.
14061 if (el) {
14062 var clone = el.cloneNode(true);
14063 el.parentNode.insertBefore(clone, el);
14064 Html5.disposeMediaElement(el);
14065 el = clone;
14066 } else {
14067 el = _globalDocument2['default'].createElement('video');
14068
14069 // determine if native controls should be used
14070 var tagAttributes = this.options_.tag && Dom.getElAttributes(this.options_.tag);
14071 var attributes = _utilsMergeOptionsJs2['default']({}, tagAttributes);
14072 if (!browser.TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) {
14073 delete attributes.controls;
14074 }
14075
14076 Dom.setElAttributes(el, _objectAssign2['default'](attributes, {
14077 id: this.options_.techId,
14078 'class': 'vjs-tech'
14079 }));
14080 }
14081 }
14082
14083 // Update specific tag settings, in case they were overridden
14084 var settingsAttrs = ['autoplay', 'preload', 'loop', 'muted'];
14085 for (var i = settingsAttrs.length - 1; i >= 0; i--) {
14086 var attr = settingsAttrs[i];
14087 var overwriteAttrs = {};
14088 if (typeof this.options_[attr] !== 'undefined') {
14089 overwriteAttrs[attr] = this.options_[attr];
14090 }
14091 Dom.setElAttributes(el, overwriteAttrs);
14092 }
14093
14094 return el;
14095 // jenniisawesome = true;
14096 };
14097
14098 // If we're loading the playback object after it has started loading
14099 // or playing the video (often with autoplay on) then the loadstart event
14100 // has already fired and we need to fire it manually because many things
14101 // rely on it.
14102
14103 Html5.prototype.handleLateInit_ = function handleLateInit_(el) {
14104 var _this = this;
14105
14106 if (el.networkState === 0 || el.networkState === 3) {
14107 // The video element hasn't started loading the source yet
14108 // or didn't find a source
14109 return;
14110 }
14111
14112 if (el.readyState === 0) {
14113 var _ret = (function () {
14114 // NetworkState is set synchronously BUT loadstart is fired at the
14115 // end of the current stack, usually before setInterval(fn, 0).
14116 // So at this point we know loadstart may have already fired or is
14117 // about to fire, and either way the player hasn't seen it yet.
14118 // We don't want to fire loadstart prematurely here and cause a
14119 // double loadstart so we'll wait and see if it happens between now
14120 // and the next loop, and fire it if not.
14121 // HOWEVER, we also want to make sure it fires before loadedmetadata
14122 // which could also happen between now and the next loop, so we'll
14123 // watch for that also.
14124 var loadstartFired = false;
14125 var setLoadstartFired = function setLoadstartFired() {
14126 loadstartFired = true;
14127 };
14128 _this.on('loadstart', setLoadstartFired);
14129
14130 var triggerLoadstart = function triggerLoadstart() {
14131 // We did miss the original loadstart. Make sure the player
14132 // sees loadstart before loadedmetadata
14133 if (!loadstartFired) {
14134 this.trigger('loadstart');
14135 }
14136 };
14137 _this.on('loadedmetadata', triggerLoadstart);
14138
14139 _this.ready(function () {
14140 this.off('loadstart', setLoadstartFired);
14141 this.off('loadedmetadata', triggerLoadstart);
14142
14143 if (!loadstartFired) {
14144 // We did miss the original native loadstart. Fire it now.
14145 this.trigger('loadstart');
14146 }
14147 });
14148
14149 return {
14150 v: undefined
14151 };
14152 })();
14153
14154 if (typeof _ret === 'object') return _ret.v;
14155 }
14156
14157 // From here on we know that loadstart already fired and we missed it.
14158 // The other readyState events aren't as much of a problem if we double
14159 // them, so not going to go to as much trouble as loadstart to prevent
14160 // that unless we find reason to.
14161 var eventsToTrigger = ['loadstart'];
14162
14163 // loadedmetadata: newly equal to HAVE_METADATA (1) or greater
14164 eventsToTrigger.push('loadedmetadata');
14165
14166 // loadeddata: newly increased to HAVE_CURRENT_DATA (2) or greater
14167 if (el.readyState >= 2) {
14168 eventsToTrigger.push('loadeddata');
14169 }
14170
14171 // canplay: newly increased to HAVE_FUTURE_DATA (3) or greater
14172 if (el.readyState >= 3) {
14173 eventsToTrigger.push('canplay');
14174 }
14175
14176 // canplaythrough: newly equal to HAVE_ENOUGH_DATA (4)
14177 if (el.readyState >= 4) {
14178 eventsToTrigger.push('canplaythrough');
14179 }
14180
14181 // We still need to give the player time to add event listeners
14182 this.ready(function () {
14183 eventsToTrigger.forEach(function (type) {
14184 this.trigger(type);
14185 }, this);
14186 });
14187 };
14188
14189 Html5.prototype.proxyNativeTextTracks_ = function proxyNativeTextTracks_() {
14190 var tt = this.el().textTracks;
14191
14192 if (tt) {
14193 // Add tracks - if player is initialised after DOM loaded, textTracks
14194 // will not trigger addtrack
14195 for (var i = 0; i < tt.length; i++) {
14196 this.textTracks().addTrack_(tt[i]);
14197 }
14198
14199 if (tt.addEventListener) {
14200 tt.addEventListener('change', this.handleTextTrackChange_);
14201 tt.addEventListener('addtrack', this.handleTextTrackAdd_);
14202 tt.addEventListener('removetrack', this.handleTextTrackRemove_);
14203 }
14204 }
14205 };
14206
14207 Html5.prototype.handleTextTrackChange = function handleTextTrackChange(e) {
14208 var tt = this.textTracks();
14209 this.textTracks().trigger({
14210 type: 'change',
14211 target: tt,
14212 currentTarget: tt,
14213 srcElement: tt
14214 });
14215 };
14216
14217 Html5.prototype.handleTextTrackAdd = function handleTextTrackAdd(e) {
14218 this.textTracks().addTrack_(e.track);
14219 };
14220
14221 Html5.prototype.handleTextTrackRemove = function handleTextTrackRemove(e) {
14222 this.textTracks().removeTrack_(e.track);
14223 };
14224
14225 /**
14226 * Play for html5 tech
14227 *
14228 * @method play
14229 */
14230
14231 Html5.prototype.play = function play() {
14232 this.el_.play();
14233 };
14234
14235 /**
14236 * Pause for html5 tech
14237 *
14238 * @method pause
14239 */
14240
14241 Html5.prototype.pause = function pause() {
14242 this.el_.pause();
14243 };
14244
14245 /**
14246 * Paused for html5 tech
14247 *
14248 * @return {Boolean}
14249 * @method paused
14250 */
14251
14252 Html5.prototype.paused = function paused() {
14253 return this.el_.paused;
14254 };
14255
14256 /**
14257 * Get current time
14258 *
14259 * @return {Number}
14260 * @method currentTime
14261 */
14262
14263 Html5.prototype.currentTime = function currentTime() {
14264 return this.el_.currentTime;
14265 };
14266
14267 /**
14268 * Set current time
14269 *
14270 * @param {Number} seconds Current time of video
14271 * @method setCurrentTime
14272 */
14273
14274 Html5.prototype.setCurrentTime = function setCurrentTime(seconds) {
14275 try {
14276 this.el_.currentTime = seconds;
14277 } catch (e) {
14278 _utilsLogJs2['default'](e, 'Video is not ready. (Video.js)');
14279 // this.warning(VideoJS.warnings.videoNotReady);
14280 }
14281 };
14282
14283 /**
14284 * Get duration
14285 *
14286 * @return {Number}
14287 * @method duration
14288 */
14289
14290 Html5.prototype.duration = function duration() {
14291 return this.el_.duration || 0;
14292 };
14293
14294 /**
14295 * Get a TimeRange object that represents the intersection
14296 * of the time ranges for which the user agent has all
14297 * relevant media
14298 *
14299 * @return {TimeRangeObject}
14300 * @method buffered
14301 */
14302
14303 Html5.prototype.buffered = function buffered() {
14304 return this.el_.buffered;
14305 };
14306
14307 /**
14308 * Get volume level
14309 *
14310 * @return {Number}
14311 * @method volume
14312 */
14313
14314 Html5.prototype.volume = function volume() {
14315 return this.el_.volume;
14316 };
14317
14318 /**
14319 * Set volume level
14320 *
14321 * @param {Number} percentAsDecimal Volume percent as a decimal
14322 * @method setVolume
14323 */
14324
14325 Html5.prototype.setVolume = function setVolume(percentAsDecimal) {
14326 this.el_.volume = percentAsDecimal;
14327 };
14328
14329 /**
14330 * Get if muted
14331 *
14332 * @return {Boolean}
14333 * @method muted
14334 */
14335
14336 Html5.prototype.muted = function muted() {
14337 return this.el_.muted;
14338 };
14339
14340 /**
14341 * Set muted
14342 *
14343 * @param {Boolean} If player is to be muted or note
14344 * @method setMuted
14345 */
14346
14347 Html5.prototype.setMuted = function setMuted(muted) {
14348 this.el_.muted = muted;
14349 };
14350
14351 /**
14352 * Get player width
14353 *
14354 * @return {Number}
14355 * @method width
14356 */
14357
14358 Html5.prototype.width = function width() {
14359 return this.el_.offsetWidth;
14360 };
14361
14362 /**
14363 * Get player height
14364 *
14365 * @return {Number}
14366 * @method height
14367 */
14368
14369 Html5.prototype.height = function height() {
14370 return this.el_.offsetHeight;
14371 };
14372
14373 /**
14374 * Get if there is fullscreen support
14375 *
14376 * @return {Boolean}
14377 * @method supportsFullScreen
14378 */
14379
14380 Html5.prototype.supportsFullScreen = function supportsFullScreen() {
14381 if (typeof this.el_.webkitEnterFullScreen === 'function') {
14382 var userAgent = _globalWindow2['default'].navigator.userAgent;
14383 // Seems to be broken in Chromium/Chrome && Safari in Leopard
14384 if (/Android/.test(userAgent) || !/Chrome|Mac OS X 10.5/.test(userAgent)) {
14385 return true;
14386 }
14387 }
14388 return false;
14389 };
14390
14391 /**
14392 * Request to enter fullscreen
14393 *
14394 * @method enterFullScreen
14395 */
14396
14397 Html5.prototype.enterFullScreen = function enterFullScreen() {
14398 var video = this.el_;
14399
14400 if ('webkitDisplayingFullscreen' in video) {
14401 this.one('webkitbeginfullscreen', function () {
14402 this.one('webkitendfullscreen', function () {
14403 this.trigger('fullscreenchange', { isFullscreen: false });
14404 });
14405
14406 this.trigger('fullscreenchange', { isFullscreen: true });
14407 });
14408 }
14409
14410 if (video.paused && video.networkState <= video.HAVE_METADATA) {
14411 // attempt to prime the video element for programmatic access
14412 // this isn't necessary on the desktop but shouldn't hurt
14413 this.el_.play();
14414
14415 // playing and pausing synchronously during the transition to fullscreen
14416 // can get iOS ~6.1 devices into a play/pause loop
14417 this.setTimeout(function () {
14418 video.pause();
14419 video.webkitEnterFullScreen();
14420 }, 0);
14421 } else {
14422 video.webkitEnterFullScreen();
14423 }
14424 };
14425
14426 /**
14427 * Request to exit fullscreen
14428 *
14429 * @method exitFullScreen
14430 */
14431
14432 Html5.prototype.exitFullScreen = function exitFullScreen() {
14433 this.el_.webkitExitFullScreen();
14434 };
14435
14436 /**
14437 * Get/set video
14438 *
14439 * @param {Object=} src Source object
14440 * @return {Object}
14441 * @method src
14442 */
14443
14444 Html5.prototype.src = function src(_src) {
14445 if (_src === undefined) {
14446 return this.el_.src;
14447 } else {
14448 // Setting src through `src` instead of `setSrc` will be deprecated
14449 this.setSrc(_src);
14450 }
14451 };
14452
14453 /**
14454 * Set video
14455 *
14456 * @param {Object} src Source object
14457 * @deprecated
14458 * @method setSrc
14459 */
14460
14461 Html5.prototype.setSrc = function setSrc(src) {
14462 this.el_.src = src;
14463 };
14464
14465 /**
14466 * Load media into player
14467 *
14468 * @method load
14469 */
14470
14471 Html5.prototype.load = function load() {
14472 this.el_.load();
14473 };
14474
14475 /**
14476 * Reset the tech. Removes all sources and calls `load`.
14477 *
14478 * @method reset
14479 */
14480
14481 Html5.prototype.reset = function reset() {
14482 Html5.resetMediaElement(this.el_);
14483 };
14484
14485 /**
14486 * Get current source
14487 *
14488 * @return {Object}
14489 * @method currentSrc
14490 */
14491
14492 Html5.prototype.currentSrc = function currentSrc() {
14493 if (this.currentSource_) {
14494 return this.currentSource_.src;
14495 } else {
14496 return this.el_.currentSrc;
14497 }
14498 };
14499
14500 /**
14501 * Get poster
14502 *
14503 * @return {String}
14504 * @method poster
14505 */
14506
14507 Html5.prototype.poster = function poster() {
14508 return this.el_.poster;
14509 };
14510
14511 /**
14512 * Set poster
14513 *
14514 * @param {String} val URL to poster image
14515 * @method
14516 */
14517
14518 Html5.prototype.setPoster = function setPoster(val) {
14519 this.el_.poster = val;
14520 };
14521
14522 /**
14523 * Get preload attribute
14524 *
14525 * @return {String}
14526 * @method preload
14527 */
14528
14529 Html5.prototype.preload = function preload() {
14530 return this.el_.preload;
14531 };
14532
14533 /**
14534 * Set preload attribute
14535 *
14536 * @param {String} val Value for preload attribute
14537 * @method setPreload
14538 */
14539
14540 Html5.prototype.setPreload = function setPreload(val) {
14541 this.el_.preload = val;
14542 };
14543
14544 /**
14545 * Get autoplay attribute
14546 *
14547 * @return {String}
14548 * @method autoplay
14549 */
14550
14551 Html5.prototype.autoplay = function autoplay() {
14552 return this.el_.autoplay;
14553 };
14554
14555 /**
14556 * Set autoplay attribute
14557 *
14558 * @param {String} val Value for preload attribute
14559 * @method setAutoplay
14560 */
14561
14562 Html5.prototype.setAutoplay = function setAutoplay(val) {
14563 this.el_.autoplay = val;
14564 };
14565
14566 /**
14567 * Get controls attribute
14568 *
14569 * @return {String}
14570 * @method controls
14571 */
14572
14573 Html5.prototype.controls = function controls() {
14574 return this.el_.controls;
14575 };
14576
14577 /**
14578 * Set controls attribute
14579 *
14580 * @param {String} val Value for controls attribute
14581 * @method setControls
14582 */
14583
14584 Html5.prototype.setControls = function setControls(val) {
14585 this.el_.controls = !!val;
14586 };
14587
14588 /**
14589 * Get loop attribute
14590 *
14591 * @return {String}
14592 * @method loop
14593 */
14594
14595 Html5.prototype.loop = function loop() {
14596 return this.el_.loop;
14597 };
14598
14599 /**
14600 * Set loop attribute
14601 *
14602 * @param {String} val Value for loop attribute
14603 * @method setLoop
14604 */
14605
14606 Html5.prototype.setLoop = function setLoop(val) {
14607 this.el_.loop = val;
14608 };
14609
14610 /**
14611 * Get error value
14612 *
14613 * @return {String}
14614 * @method error
14615 */
14616
14617 Html5.prototype.error = function error() {
14618 return this.el_.error;
14619 };
14620
14621 /**
14622 * Get whether or not the player is in the "seeking" state
14623 *
14624 * @return {Boolean}
14625 * @method seeking
14626 */
14627
14628 Html5.prototype.seeking = function seeking() {
14629 return this.el_.seeking;
14630 };
14631
14632 /**
14633 * Get a TimeRanges object that represents the
14634 * ranges of the media resource to which it is possible
14635 * for the user agent to seek.
14636 *
14637 * @return {TimeRangeObject}
14638 * @method seekable
14639 */
14640
14641 Html5.prototype.seekable = function seekable() {
14642 return this.el_.seekable;
14643 };
14644
14645 /**
14646 * Get if video ended
14647 *
14648 * @return {Boolean}
14649 * @method ended
14650 */
14651
14652 Html5.prototype.ended = function ended() {
14653 return this.el_.ended;
14654 };
14655
14656 /**
14657 * Get the value of the muted content attribute
14658 * This attribute has no dynamic effect, it only
14659 * controls the default state of the element
14660 *
14661 * @return {Boolean}
14662 * @method defaultMuted
14663 */
14664
14665 Html5.prototype.defaultMuted = function defaultMuted() {
14666 return this.el_.defaultMuted;
14667 };
14668
14669 /**
14670 * Get desired speed at which the media resource is to play
14671 *
14672 * @return {Number}
14673 * @method playbackRate
14674 */
14675
14676 Html5.prototype.playbackRate = function playbackRate() {
14677 return this.el_.playbackRate;
14678 };
14679
14680 /**
14681 * Returns a TimeRanges object that represents the ranges of the
14682 * media resource that the user agent has played.
14683 * @return {TimeRangeObject} the range of points on the media
14684 * timeline that has been reached through normal playback
14685 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-played
14686 */
14687
14688 Html5.prototype.played = function played() {
14689 return this.el_.played;
14690 };
14691
14692 /**
14693 * Set desired speed at which the media resource is to play
14694 *
14695 * @param {Number} val Speed at which the media resource is to play
14696 * @method setPlaybackRate
14697 */
14698
14699 Html5.prototype.setPlaybackRate = function setPlaybackRate(val) {
14700 this.el_.playbackRate = val;
14701 };
14702
14703 /**
14704 * Get the current state of network activity for the element, from
14705 * the list below
14706 * NETWORK_EMPTY (numeric value 0)
14707 * NETWORK_IDLE (numeric value 1)
14708 * NETWORK_LOADING (numeric value 2)
14709 * NETWORK_NO_SOURCE (numeric value 3)
14710 *
14711 * @return {Number}
14712 * @method networkState
14713 */
14714
14715 Html5.prototype.networkState = function networkState() {
14716 return this.el_.networkState;
14717 };
14718
14719 /**
14720 * Get a value that expresses the current state of the element
14721 * with respect to rendering the current playback position, from
14722 * the codes in the list below
14723 * HAVE_NOTHING (numeric value 0)
14724 * HAVE_METADATA (numeric value 1)
14725 * HAVE_CURRENT_DATA (numeric value 2)
14726 * HAVE_FUTURE_DATA (numeric value 3)
14727 * HAVE_ENOUGH_DATA (numeric value 4)
14728 *
14729 * @return {Number}
14730 * @method readyState
14731 */
14732
14733 Html5.prototype.readyState = function readyState() {
14734 return this.el_.readyState;
14735 };
14736
14737 /**
14738 * Get width of video
14739 *
14740 * @return {Number}
14741 * @method videoWidth
14742 */
14743
14744 Html5.prototype.videoWidth = function videoWidth() {
14745 return this.el_.videoWidth;
14746 };
14747
14748 /**
14749 * Get height of video
14750 *
14751 * @return {Number}
14752 * @method videoHeight
14753 */
14754
14755 Html5.prototype.videoHeight = function videoHeight() {
14756 return this.el_.videoHeight;
14757 };
14758
14759 /**
14760 * Get text tracks
14761 *
14762 * @return {TextTrackList}
14763 * @method textTracks
14764 */
14765
14766 Html5.prototype.textTracks = function textTracks() {
14767 return _Tech.prototype.textTracks.call(this);
14768 };
14769
14770 /**
14771 * Creates and returns a text track object
14772 *
14773 * @param {String} kind Text track kind (subtitles, captions, descriptions
14774 * chapters and metadata)
14775 * @param {String=} label Label to identify the text track
14776 * @param {String=} language Two letter language abbreviation
14777 * @return {TextTrackObject}
14778 * @method addTextTrack
14779 */
14780
14781 Html5.prototype.addTextTrack = function addTextTrack(kind, label, language) {
14782 if (!this['featuresNativeTextTracks']) {
14783 return _Tech.prototype.addTextTrack.call(this, kind, label, language);
14784 }
14785
14786 return this.el_.addTextTrack(kind, label, language);
14787 };
14788
14789 /**
14790 * Creates a remote text track object and returns a html track element
14791 *
14792 * @param {Object} options The object should contain values for
14793 * kind, language, label and src (location of the WebVTT file)
14794 * @return {HTMLTrackElement}
14795 * @method addRemoteTextTrack
14796 */
14797
14798 Html5.prototype.addRemoteTextTrack = function addRemoteTextTrack() {
14799 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
14800
14801 if (!this['featuresNativeTextTracks']) {
14802 return _Tech.prototype.addRemoteTextTrack.call(this, options);
14803 }
14804
14805 var htmlTrackElement = _globalDocument2['default'].createElement('track');
14806
14807 if (options.kind) {
14808 htmlTrackElement.kind = options.kind;
14809 }
14810 if (options.label) {
14811 htmlTrackElement.label = options.label;
14812 }
14813 if (options.language || options.srclang) {
14814 htmlTrackElement.srclang = options.language || options.srclang;
14815 }
14816 if (options['default']) {
14817 htmlTrackElement['default'] = options['default'];
14818 }
14819 if (options.id) {
14820 htmlTrackElement.id = options.id;
14821 }
14822 if (options.src) {
14823 htmlTrackElement.src = options.src;
14824 }
14825
14826 this.el().appendChild(htmlTrackElement);
14827
14828 // store HTMLTrackElement and TextTrack to remote list
14829 this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
14830 this.remoteTextTracks().addTrack_(htmlTrackElement.track);
14831
14832 return htmlTrackElement;
14833 };
14834
14835 /**
14836 * Remove remote text track from TextTrackList object
14837 *
14838 * @param {TextTrackObject} track Texttrack object to remove
14839 * @method removeRemoteTextTrack
14840 */
14841
14842 Html5.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) {
14843 if (!this['featuresNativeTextTracks']) {
14844 return _Tech.prototype.removeRemoteTextTrack.call(this, track);
14845 }
14846
14847 var tracks = undefined,
14848 i = undefined;
14849
14850 var trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track);
14851
14852 // remove HTMLTrackElement and TextTrack from remote list
14853 this.remoteTextTrackEls().removeTrackElement_(trackElement);
14854 this.remoteTextTracks().removeTrack_(track);
14855
14856 tracks = this.$$('track');
14857
14858 i = tracks.length;
14859 while (i--) {
14860 if (track === tracks[i] || track === tracks[i].track) {
14861 this.el().removeChild(tracks[i]);
14862 }
14863 }
14864 };
14865
14866 return Html5;
14867})(_techJs2['default']);
14868
14869Html5.TEST_VID = _globalDocument2['default'].createElement('video');
14870var track = _globalDocument2['default'].createElement('track');
14871track.kind = 'captions';
14872track.srclang = 'en';
14873track.label = 'English';
14874Html5.TEST_VID.appendChild(track);
14875
14876/*
14877 * Check if HTML5 video is supported by this browser/device
14878 *
14879 * @return {Boolean}
14880 */
14881Html5.isSupported = function () {
14882 // IE9 with no Media Player is a LIAR! (#984)
14883 try {
14884 Html5.TEST_VID['volume'] = 0.5;
14885 } catch (e) {
14886 return false;
14887 }
14888
14889 return !!Html5.TEST_VID.canPlayType;
14890};
14891
14892// Add Source Handler pattern functions to this tech
14893_techJs2['default'].withSourceHandlers(Html5);
14894
14895/*
14896 * The default native source handler.
14897 * This simply passes the source to the video element. Nothing fancy.
14898 *
14899 * @param {Object} source The source object
14900 * @param {Html5} tech The instance of the HTML5 tech
14901 */
14902Html5.nativeSourceHandler = {};
14903
14904/*
14905 * Check if the video element can play the given videotype
14906 *
14907 * @param {String} type The mimetype to check
14908 * @return {String} 'probably', 'maybe', or '' (empty string)
14909 */
14910Html5.nativeSourceHandler.canPlayType = function (type) {
14911 // IE9 on Windows 7 without MediaPlayer throws an error here
14912 // https://github.com/videojs/video.js/issues/519
14913 try {
14914 return Html5.TEST_VID.canPlayType(type);
14915 } catch (e) {
14916 return '';
14917 }
14918};
14919
14920/*
14921 * Check if the video element can handle the source natively
14922 *
14923 * @param {Object} source The source object
14924 * @return {String} 'probably', 'maybe', or '' (empty string)
14925 */
14926Html5.nativeSourceHandler.canHandleSource = function (source) {
14927 var match, ext;
14928
14929 // If a type was provided we should rely on that
14930 if (source.type) {
14931 return Html5.nativeSourceHandler.canPlayType(source.type);
14932 } else if (source.src) {
14933 // If no type, fall back to checking 'video/[EXTENSION]'
14934 ext = Url.getFileExtension(source.src);
14935
14936 return Html5.nativeSourceHandler.canPlayType('video/' + ext);
14937 }
14938
14939 return '';
14940};
14941
14942/*
14943 * Pass the source to the video element
14944 * Adaptive source handlers will have more complicated workflows before passing
14945 * video data to the video element
14946 *
14947 * @param {Object} source The source object
14948 * @param {Html5} tech The instance of the Html5 tech
14949 */
14950Html5.nativeSourceHandler.handleSource = function (source, tech) {
14951 tech.setSrc(source.src);
14952};
14953
14954/*
14955* Clean up the source handler when disposing the player or switching sources..
14956* (no cleanup is needed when supporting the format natively)
14957*/
14958Html5.nativeSourceHandler.dispose = function () {};
14959
14960// Register the native source handler
14961Html5.registerSourceHandler(Html5.nativeSourceHandler);
14962
14963/*
14964 * Check if the volume can be changed in this browser/device.
14965 * Volume cannot be changed in a lot of mobile devices.
14966 * Specifically, it can't be changed from 1 on iOS.
14967 *
14968 * @return {Boolean}
14969 */
14970Html5.canControlVolume = function () {
14971 var volume = Html5.TEST_VID.volume;
14972 Html5.TEST_VID.volume = volume / 2 + 0.1;
14973 return volume !== Html5.TEST_VID.volume;
14974};
14975
14976/*
14977 * Check if playbackRate is supported in this browser/device.
14978 *
14979 * @return {Number} [description]
14980 */
14981Html5.canControlPlaybackRate = function () {
14982 var playbackRate = Html5.TEST_VID.playbackRate;
14983 Html5.TEST_VID.playbackRate = playbackRate / 2 + 0.1;
14984 return playbackRate !== Html5.TEST_VID.playbackRate;
14985};
14986
14987/*
14988 * Check to see if native text tracks are supported by this browser/device
14989 *
14990 * @return {Boolean}
14991 */
14992Html5.supportsNativeTextTracks = function () {
14993 var supportsTextTracks;
14994
14995 // Figure out native text track support
14996 // If mode is a number, we cannot change it because it'll disappear from view.
14997 // Browsers with numeric modes include IE10 and older (<=2013) samsung android models.
14998 // Firefox isn't playing nice either with modifying the mode
14999 // TODO: Investigate firefox: https://github.com/videojs/video.js/issues/1862
15000 supportsTextTracks = !!Html5.TEST_VID.textTracks;
15001 if (supportsTextTracks && Html5.TEST_VID.textTracks.length > 0) {
15002 supportsTextTracks = typeof Html5.TEST_VID.textTracks[0]['mode'] !== 'number';
15003 }
15004 if (supportsTextTracks && browser.IS_FIREFOX) {
15005 supportsTextTracks = false;
15006 }
15007 if (supportsTextTracks && !('onremovetrack' in Html5.TEST_VID.textTracks)) {
15008 supportsTextTracks = false;
15009 }
15010
15011 return supportsTextTracks;
15012};
15013
15014/**
15015 * An array of events available on the Html5 tech.
15016 *
15017 * @private
15018 * @type {Array}
15019 */
15020Html5.Events = ['loadstart', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough', 'playing', 'waiting', 'seeking', 'seeked', 'ended', 'durationchange', 'timeupdate', 'progress', 'play', 'pause', 'ratechange', 'volumechange'];
15021
15022/*
15023 * Set the tech's volume control support status
15024 *
15025 * @type {Boolean}
15026 */
15027Html5.prototype['featuresVolumeControl'] = Html5.canControlVolume();
15028
15029/*
15030 * Set the tech's playbackRate support status
15031 *
15032 * @type {Boolean}
15033 */
15034Html5.prototype['featuresPlaybackRate'] = Html5.canControlPlaybackRate();
15035
15036/*
15037 * Set the tech's status on moving the video element.
15038 * In iOS, if you move a video element in the DOM, it breaks video playback.
15039 *
15040 * @type {Boolean}
15041 */
15042Html5.prototype['movingMediaElementInDOM'] = !browser.IS_IOS;
15043
15044/*
15045 * Set the the tech's fullscreen resize support status.
15046 * HTML video is able to automatically resize when going to fullscreen.
15047 * (No longer appears to be used. Can probably be removed.)
15048 */
15049Html5.prototype['featuresFullscreenResize'] = true;
15050
15051/*
15052 * Set the tech's progress event support status
15053 * (this disables the manual progress events of the Tech)
15054 */
15055Html5.prototype['featuresProgressEvents'] = true;
15056
15057/*
15058 * Sets the tech's status on native text track support
15059 *
15060 * @type {Boolean}
15061 */
15062Html5.prototype['featuresNativeTextTracks'] = Html5.supportsNativeTextTracks();
15063
15064// HTML5 Feature detection and Device Fixes --------------------------------- //
15065var canPlayType = undefined;
15066var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
15067var mp4RE = /^video\/mp4/i;
15068
15069Html5.patchCanPlayType = function () {
15070 // Android 4.0 and above can play HLS to some extent but it reports being unable to do so
15071 if (browser.ANDROID_VERSION >= 4.0) {
15072 if (!canPlayType) {
15073 canPlayType = Html5.TEST_VID.constructor.prototype.canPlayType;
15074 }
15075
15076 Html5.TEST_VID.constructor.prototype.canPlayType = function (type) {
15077 if (type && mpegurlRE.test(type)) {
15078 return 'maybe';
15079 }
15080 return canPlayType.call(this, type);
15081 };
15082 }
15083
15084 // Override Android 2.2 and less canPlayType method which is broken
15085 if (browser.IS_OLD_ANDROID) {
15086 if (!canPlayType) {
15087 canPlayType = Html5.TEST_VID.constructor.prototype.canPlayType;
15088 }
15089
15090 Html5.TEST_VID.constructor.prototype.canPlayType = function (type) {
15091 if (type && mp4RE.test(type)) {
15092 return 'maybe';
15093 }
15094 return canPlayType.call(this, type);
15095 };
15096 }
15097};
15098
15099Html5.unpatchCanPlayType = function () {
15100 var r = Html5.TEST_VID.constructor.prototype.canPlayType;
15101 Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType;
15102 canPlayType = null;
15103 return r;
15104};
15105
15106// by default, patch the video element
15107Html5.patchCanPlayType();
15108
15109Html5.disposeMediaElement = function (el) {
15110 if (!el) {
15111 return;
15112 }
15113
15114 if (el.parentNode) {
15115 el.parentNode.removeChild(el);
15116 }
15117
15118 // remove any child track or source nodes to prevent their loading
15119 while (el.hasChildNodes()) {
15120 el.removeChild(el.firstChild);
15121 }
15122
15123 // remove any src reference. not setting `src=''` because that causes a warning
15124 // in firefox
15125 el.removeAttribute('src');
15126
15127 // force the media element to update its loading state by calling load()
15128 // however IE on Windows 7N has a bug that throws an error so need a try/catch (#793)
15129 if (typeof el.load === 'function') {
15130 // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
15131 (function () {
15132 try {
15133 el.load();
15134 } catch (e) {
15135 // not supported
15136 }
15137 })();
15138 }
15139};
15140
15141Html5.resetMediaElement = function (el) {
15142 if (!el) {
15143 return;
15144 }
15145
15146 var sources = el.querySelectorAll('source');
15147 var i = sources.length;
15148 while (i--) {
15149 el.removeChild(sources[i]);
15150 }
15151
15152 // remove any src reference.
15153 // not setting `src=''` because that throws an error
15154 el.removeAttribute('src');
15155
15156 if (typeof el.load === 'function') {
15157 // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
15158 (function () {
15159 try {
15160 el.load();
15161 } catch (e) {}
15162 })();
15163 }
15164};
15165
15166_component2['default'].registerComponent('Html5', Html5);
15167_techJs2['default'].registerTech('Html5', Html5);
15168exports['default'] = Html5;
15169module.exports = exports['default'];
15170
15171},{"../component":67,"../utils/browser.js":129,"../utils/dom.js":132,"../utils/fn.js":134,"../utils/log.js":137,"../utils/merge-options.js":138,"../utils/url.js":142,"./tech.js":119,"global/document":1,"global/window":2,"object.assign":45}],118:[function(_dereq_,module,exports){
15172/**
15173 * @file loader.js
15174 */
15175'use strict';
15176
15177exports.__esModule = true;
15178
15179function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
15180
15181function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
15182
15183function _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; }
15184
15185var _componentJs = _dereq_('../component.js');
15186
15187var _componentJs2 = _interopRequireDefault(_componentJs);
15188
15189var _techJs = _dereq_('./tech.js');
15190
15191var _techJs2 = _interopRequireDefault(_techJs);
15192
15193var _globalWindow = _dereq_('global/window');
15194
15195var _globalWindow2 = _interopRequireDefault(_globalWindow);
15196
15197var _utilsToTitleCaseJs = _dereq_('../utils/to-title-case.js');
15198
15199var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs);
15200
15201/**
15202 * The Media Loader is the component that decides which playback technology to load
15203 * when the player is initialized.
15204 *
15205 * @param {Object} player Main Player
15206 * @param {Object=} options Object of option names and values
15207 * @param {Function=} ready Ready callback function
15208 * @extends Component
15209 * @class MediaLoader
15210 */
15211
15212var MediaLoader = (function (_Component) {
15213 _inherits(MediaLoader, _Component);
15214
15215 function MediaLoader(player, options, ready) {
15216 _classCallCheck(this, MediaLoader);
15217
15218 _Component.call(this, player, options, ready);
15219
15220 // If there are no sources when the player is initialized,
15221 // load the first supported playback technology.
15222
15223 if (!options.playerOptions['sources'] || options.playerOptions['sources'].length === 0) {
15224 for (var i = 0, j = options.playerOptions['techOrder']; i < j.length; i++) {
15225 var techName = _utilsToTitleCaseJs2['default'](j[i]);
15226 var tech = _techJs2['default'].getTech(techName);
15227 // Support old behavior of techs being registered as components.
15228 // Remove once that deprecated behavior is removed.
15229 if (!techName) {
15230 tech = _componentJs2['default'].getComponent(techName);
15231 }
15232
15233 // Check if the browser supports this technology
15234 if (tech && tech.isSupported()) {
15235 player.loadTech_(techName);
15236 break;
15237 }
15238 }
15239 } else {
15240 // // Loop through playback technologies (HTML5, Flash) and check for support.
15241 // // Then load the best source.
15242 // // A few assumptions here:
15243 // // All playback technologies respect preload false.
15244 player.src(options.playerOptions['sources']);
15245 }
15246 }
15247
15248 return MediaLoader;
15249})(_componentJs2['default']);
15250
15251_componentJs2['default'].registerComponent('MediaLoader', MediaLoader);
15252exports['default'] = MediaLoader;
15253module.exports = exports['default'];
15254
15255},{"../component.js":67,"../utils/to-title-case.js":141,"./tech.js":119,"global/window":2}],119:[function(_dereq_,module,exports){
15256/**
15257 * @file tech.js
15258 * Media Technology Controller - Base class for media playback
15259 * technology controllers like Flash and HTML5
15260 */
15261
15262'use strict';
15263
15264exports.__esModule = true;
15265
15266function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
15267
15268function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
15269
15270function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
15271
15272function _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; }
15273
15274var _component = _dereq_('../component');
15275
15276var _component2 = _interopRequireDefault(_component);
15277
15278var _tracksHtmlTrackElement = _dereq_('../tracks/html-track-element');
15279
15280var _tracksHtmlTrackElement2 = _interopRequireDefault(_tracksHtmlTrackElement);
15281
15282var _tracksHtmlTrackElementList = _dereq_('../tracks/html-track-element-list');
15283
15284var _tracksHtmlTrackElementList2 = _interopRequireDefault(_tracksHtmlTrackElementList);
15285
15286var _utilsMergeOptionsJs = _dereq_('../utils/merge-options.js');
15287
15288var _utilsMergeOptionsJs2 = _interopRequireDefault(_utilsMergeOptionsJs);
15289
15290var _tracksTextTrack = _dereq_('../tracks/text-track');
15291
15292var _tracksTextTrack2 = _interopRequireDefault(_tracksTextTrack);
15293
15294var _tracksTextTrackList = _dereq_('../tracks/text-track-list');
15295
15296var _tracksTextTrackList2 = _interopRequireDefault(_tracksTextTrackList);
15297
15298var _utilsFnJs = _dereq_('../utils/fn.js');
15299
15300var Fn = _interopRequireWildcard(_utilsFnJs);
15301
15302var _utilsLogJs = _dereq_('../utils/log.js');
15303
15304var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
15305
15306var _utilsTimeRangesJs = _dereq_('../utils/time-ranges.js');
15307
15308var _utilsBufferJs = _dereq_('../utils/buffer.js');
15309
15310var _mediaErrorJs = _dereq_('../media-error.js');
15311
15312var _mediaErrorJs2 = _interopRequireDefault(_mediaErrorJs);
15313
15314var _globalWindow = _dereq_('global/window');
15315
15316var _globalWindow2 = _interopRequireDefault(_globalWindow);
15317
15318var _globalDocument = _dereq_('global/document');
15319
15320var _globalDocument2 = _interopRequireDefault(_globalDocument);
15321
15322/**
15323 * Base class for media (HTML5 Video, Flash) controllers
15324 *
15325 * @param {Object=} options Options object
15326 * @param {Function=} ready Ready callback function
15327 * @extends Component
15328 * @class Tech
15329 */
15330
15331var Tech = (function (_Component) {
15332 _inherits(Tech, _Component);
15333
15334 function Tech() {
15335 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
15336 var ready = arguments.length <= 1 || arguments[1] === undefined ? function () {} : arguments[1];
15337
15338 _classCallCheck(this, Tech);
15339
15340 // we don't want the tech to report user activity automatically.
15341 // This is done manually in addControlsListeners
15342 options.reportTouchActivity = false;
15343 _Component.call(this, null, options, ready);
15344
15345 // keep track of whether the current source has played at all to
15346 // implement a very limited played()
15347 this.hasStarted_ = false;
15348 this.on('playing', function () {
15349 this.hasStarted_ = true;
15350 });
15351 this.on('loadstart', function () {
15352 this.hasStarted_ = false;
15353 });
15354
15355 this.textTracks_ = options.textTracks;
15356
15357 // Manually track progress in cases where the browser/flash player doesn't report it.
15358 if (!this.featuresProgressEvents) {
15359 this.manualProgressOn();
15360 }
15361
15362 // Manually track timeupdates in cases where the browser/flash player doesn't report it.
15363 if (!this.featuresTimeupdateEvents) {
15364 this.manualTimeUpdatesOn();
15365 }
15366
15367 if (options.nativeCaptions === false || options.nativeTextTracks === false) {
15368 this.featuresNativeTextTracks = false;
15369 }
15370
15371 if (!this.featuresNativeTextTracks) {
15372 this.on('ready', this.emulateTextTracks);
15373 }
15374
15375 this.initTextTrackListeners();
15376
15377 // Turn on component tap events
15378 this.emitTapEvents();
15379 }
15380
15381 /*
15382 * List of associated text tracks
15383 *
15384 * @type {Array}
15385 * @private
15386 */
15387
15388 /* Fallbacks for unsupported event types
15389 ================================================================================ */
15390 // Manually trigger progress events based on changes to the buffered amount
15391 // Many flash players and older HTML5 browsers don't send progress or progress-like events
15392 /**
15393 * Turn on progress events
15394 *
15395 * @method manualProgressOn
15396 */
15397
15398 Tech.prototype.manualProgressOn = function manualProgressOn() {
15399 this.on('durationchange', this.onDurationChange);
15400
15401 this.manualProgress = true;
15402
15403 // Trigger progress watching when a source begins loading
15404 this.one('ready', this.trackProgress);
15405 };
15406
15407 /**
15408 * Turn off progress events
15409 *
15410 * @method manualProgressOff
15411 */
15412
15413 Tech.prototype.manualProgressOff = function manualProgressOff() {
15414 this.manualProgress = false;
15415 this.stopTrackingProgress();
15416
15417 this.off('durationchange', this.onDurationChange);
15418 };
15419
15420 /**
15421 * Track progress
15422 *
15423 * @method trackProgress
15424 */
15425
15426 Tech.prototype.trackProgress = function trackProgress() {
15427 this.stopTrackingProgress();
15428 this.progressInterval = this.setInterval(Fn.bind(this, function () {
15429 // Don't trigger unless buffered amount is greater than last time
15430
15431 var numBufferedPercent = this.bufferedPercent();
15432
15433 if (this.bufferedPercent_ !== numBufferedPercent) {
15434 this.trigger('progress');
15435 }
15436
15437 this.bufferedPercent_ = numBufferedPercent;
15438
15439 if (numBufferedPercent === 1) {
15440 this.stopTrackingProgress();
15441 }
15442 }), 500);
15443 };
15444
15445 /**
15446 * Update duration
15447 *
15448 * @method onDurationChange
15449 */
15450
15451 Tech.prototype.onDurationChange = function onDurationChange() {
15452 this.duration_ = this.duration();
15453 };
15454
15455 /**
15456 * Create and get TimeRange object for buffering
15457 *
15458 * @return {TimeRangeObject}
15459 * @method buffered
15460 */
15461
15462 Tech.prototype.buffered = function buffered() {
15463 return _utilsTimeRangesJs.createTimeRange(0, 0);
15464 };
15465
15466 /**
15467 * Get buffered percent
15468 *
15469 * @return {Number}
15470 * @method bufferedPercent
15471 */
15472
15473 Tech.prototype.bufferedPercent = function bufferedPercent() {
15474 return _utilsBufferJs.bufferedPercent(this.buffered(), this.duration_);
15475 };
15476
15477 /**
15478 * Stops tracking progress by clearing progress interval
15479 *
15480 * @method stopTrackingProgress
15481 */
15482
15483 Tech.prototype.stopTrackingProgress = function stopTrackingProgress() {
15484 this.clearInterval(this.progressInterval);
15485 };
15486
15487 /*! Time Tracking -------------------------------------------------------------- */
15488 /**
15489 * Set event listeners for on play and pause and tracking current time
15490 *
15491 * @method manualTimeUpdatesOn
15492 */
15493
15494 Tech.prototype.manualTimeUpdatesOn = function manualTimeUpdatesOn() {
15495 this.manualTimeUpdates = true;
15496
15497 this.on('play', this.trackCurrentTime);
15498 this.on('pause', this.stopTrackingCurrentTime);
15499 };
15500
15501 /**
15502 * Remove event listeners for on play and pause and tracking current time
15503 *
15504 * @method manualTimeUpdatesOff
15505 */
15506
15507 Tech.prototype.manualTimeUpdatesOff = function manualTimeUpdatesOff() {
15508 this.manualTimeUpdates = false;
15509 this.stopTrackingCurrentTime();
15510 this.off('play', this.trackCurrentTime);
15511 this.off('pause', this.stopTrackingCurrentTime);
15512 };
15513
15514 /**
15515 * Tracks current time
15516 *
15517 * @method trackCurrentTime
15518 */
15519
15520 Tech.prototype.trackCurrentTime = function trackCurrentTime() {
15521 if (this.currentTimeInterval) {
15522 this.stopTrackingCurrentTime();
15523 }
15524 this.currentTimeInterval = this.setInterval(function () {
15525 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
15526 }, 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
15527 };
15528
15529 /**
15530 * Turn off play progress tracking (when paused or dragging)
15531 *
15532 * @method stopTrackingCurrentTime
15533 */
15534
15535 Tech.prototype.stopTrackingCurrentTime = function stopTrackingCurrentTime() {
15536 this.clearInterval(this.currentTimeInterval);
15537
15538 // #1002 - if the video ends right before the next timeupdate would happen,
15539 // the progress bar won't make it all the way to the end
15540 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
15541 };
15542
15543 /**
15544 * Turn off any manual progress or timeupdate tracking
15545 *
15546 * @method dispose
15547 */
15548
15549 Tech.prototype.dispose = function dispose() {
15550 // clear out text tracks because we can't reuse them between techs
15551 var textTracks = this.textTracks();
15552
15553 if (textTracks) {
15554 var i = textTracks.length;
15555 while (i--) {
15556 this.removeRemoteTextTrack(textTracks[i]);
15557 }
15558 }
15559
15560 // Turn off any manual progress or timeupdate tracking
15561 if (this.manualProgress) {
15562 this.manualProgressOff();
15563 }
15564
15565 if (this.manualTimeUpdates) {
15566 this.manualTimeUpdatesOff();
15567 }
15568
15569 _Component.prototype.dispose.call(this);
15570 };
15571
15572 /**
15573 * Reset the tech. Removes all sources and resets readyState.
15574 *
15575 * @method reset
15576 */
15577
15578 Tech.prototype.reset = function reset() {};
15579
15580 /**
15581 * When invoked without an argument, returns a MediaError object
15582 * representing the current error state of the player or null if
15583 * there is no error. When invoked with an argument, set the current
15584 * error state of the player.
15585 * @param {MediaError=} err Optional an error object
15586 * @return {MediaError} the current error object or null
15587 * @method error
15588 */
15589
15590 Tech.prototype.error = function error(err) {
15591 if (err !== undefined) {
15592 if (err instanceof _mediaErrorJs2['default']) {
15593 this.error_ = err;
15594 } else {
15595 this.error_ = new _mediaErrorJs2['default'](err);
15596 }
15597 this.trigger('error');
15598 }
15599 return this.error_;
15600 };
15601
15602 /**
15603 * Return the time ranges that have been played through for the
15604 * current source. This implementation is incomplete. It does not
15605 * track the played time ranges, only whether the source has played
15606 * at all or not.
15607 * @return {TimeRangeObject} a single time range if this video has
15608 * played or an empty set of ranges if not.
15609 * @method played
15610 */
15611
15612 Tech.prototype.played = function played() {
15613 if (this.hasStarted_) {
15614 return _utilsTimeRangesJs.createTimeRange(0, 0);
15615 }
15616 return _utilsTimeRangesJs.createTimeRange();
15617 };
15618
15619 /**
15620 * Set current time
15621 *
15622 * @method setCurrentTime
15623 */
15624
15625 Tech.prototype.setCurrentTime = function setCurrentTime() {
15626 // improve the accuracy of manual timeupdates
15627 if (this.manualTimeUpdates) {
15628 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
15629 }
15630 };
15631
15632 /**
15633 * Initialize texttrack listeners
15634 *
15635 * @method initTextTrackListeners
15636 */
15637
15638 Tech.prototype.initTextTrackListeners = function initTextTrackListeners() {
15639 var textTrackListChanges = Fn.bind(this, function () {
15640 this.trigger('texttrackchange');
15641 });
15642
15643 var tracks = this.textTracks();
15644
15645 if (!tracks) return;
15646
15647 tracks.addEventListener('removetrack', textTrackListChanges);
15648 tracks.addEventListener('addtrack', textTrackListChanges);
15649
15650 this.on('dispose', Fn.bind(this, function () {
15651 tracks.removeEventListener('removetrack', textTrackListChanges);
15652 tracks.removeEventListener('addtrack', textTrackListChanges);
15653 }));
15654 };
15655
15656 /**
15657 * Emulate texttracks
15658 *
15659 * @method emulateTextTracks
15660 */
15661
15662 Tech.prototype.emulateTextTracks = function emulateTextTracks() {
15663 var _this = this;
15664
15665 var tracks = this.textTracks();
15666 if (!tracks) {
15667 return;
15668 }
15669
15670 if (!_globalWindow2['default']['WebVTT'] && this.el().parentNode != null) {
15671 (function () {
15672 var script = _globalDocument2['default'].createElement('script');
15673 script.src = _this.options_['vtt.js'] || 'https://cdn.rawgit.com/gkatsev/vtt.js/vjs-v0.12.1/dist/vtt.min.js';
15674 script.onload = function () {
15675 _this.trigger('vttjsloaded');
15676 };
15677 script.onerror = function () {
15678 _this.trigger('vttjserror');
15679 };
15680 _this.on('dispose', function () {
15681 script.onload = null;
15682 script.onerror = null;
15683 });
15684 _this.el().parentNode.appendChild(script);
15685 _globalWindow2['default']['WebVTT'] = true;
15686 })();
15687 }
15688
15689 var updateDisplay = function updateDisplay() {
15690 return _this.trigger('texttrackchange');
15691 };
15692 var textTracksChanges = function textTracksChanges() {
15693 updateDisplay();
15694
15695 for (var i = 0; i < tracks.length; i++) {
15696 var track = tracks[i];
15697 track.removeEventListener('cuechange', updateDisplay);
15698 if (track.mode === 'showing') {
15699 track.addEventListener('cuechange', updateDisplay);
15700 }
15701 }
15702 };
15703
15704 textTracksChanges();
15705 tracks.addEventListener('change', textTracksChanges);
15706
15707 this.on('dispose', function () {
15708 tracks.removeEventListener('change', textTracksChanges);
15709 });
15710 };
15711
15712 /*
15713 * Provide default methods for text tracks.
15714 *
15715 * Html5 tech overrides these.
15716 */
15717
15718 /**
15719 * Get texttracks
15720 *
15721 * @returns {TextTrackList}
15722 * @method textTracks
15723 */
15724
15725 Tech.prototype.textTracks = function textTracks() {
15726 this.textTracks_ = this.textTracks_ || new _tracksTextTrackList2['default']();
15727 return this.textTracks_;
15728 };
15729
15730 /**
15731 * Get remote texttracks
15732 *
15733 * @returns {TextTrackList}
15734 * @method remoteTextTracks
15735 */
15736
15737 Tech.prototype.remoteTextTracks = function remoteTextTracks() {
15738 this.remoteTextTracks_ = this.remoteTextTracks_ || new _tracksTextTrackList2['default']();
15739 return this.remoteTextTracks_;
15740 };
15741
15742 /**
15743 * Get remote htmltrackelements
15744 *
15745 * @returns {HTMLTrackElementList}
15746 * @method remoteTextTrackEls
15747 */
15748
15749 Tech.prototype.remoteTextTrackEls = function remoteTextTrackEls() {
15750 this.remoteTextTrackEls_ = this.remoteTextTrackEls_ || new _tracksHtmlTrackElementList2['default']();
15751 return this.remoteTextTrackEls_;
15752 };
15753
15754 /**
15755 * Creates and returns a remote text track object
15756 *
15757 * @param {String} kind Text track kind (subtitles, captions, descriptions
15758 * chapters and metadata)
15759 * @param {String=} label Label to identify the text track
15760 * @param {String=} language Two letter language abbreviation
15761 * @return {TextTrackObject}
15762 * @method addTextTrack
15763 */
15764
15765 Tech.prototype.addTextTrack = function addTextTrack(kind, label, language) {
15766 if (!kind) {
15767 throw new Error('TextTrack kind is required but was not provided');
15768 }
15769
15770 return createTrackHelper(this, kind, label, language);
15771 };
15772
15773 /**
15774 * Creates a remote text track object and returns a emulated html track element
15775 *
15776 * @param {Object} options The object should contain values for
15777 * kind, language, label and src (location of the WebVTT file)
15778 * @return {HTMLTrackElement}
15779 * @method addRemoteTextTrack
15780 */
15781
15782 Tech.prototype.addRemoteTextTrack = function addRemoteTextTrack(options) {
15783 var track = _utilsMergeOptionsJs2['default'](options, {
15784 tech: this
15785 });
15786
15787 var htmlTrackElement = new _tracksHtmlTrackElement2['default'](track);
15788
15789 // store HTMLTrackElement and TextTrack to remote list
15790 this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
15791 this.remoteTextTracks().addTrack_(htmlTrackElement.track);
15792
15793 // must come after remoteTextTracks()
15794 this.textTracks().addTrack_(htmlTrackElement.track);
15795
15796 return htmlTrackElement;
15797 };
15798
15799 /**
15800 * Remove remote texttrack
15801 *
15802 * @param {TextTrackObject} track Texttrack to remove
15803 * @method removeRemoteTextTrack
15804 */
15805
15806 Tech.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) {
15807 this.textTracks().removeTrack_(track);
15808
15809 var trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track);
15810
15811 // remove HTMLTrackElement and TextTrack from remote list
15812 this.remoteTextTrackEls().removeTrackElement_(trackElement);
15813 this.remoteTextTracks().removeTrack_(track);
15814 };
15815
15816 /**
15817 * Provide a default setPoster method for techs
15818 * Poster support for techs should be optional, so we don't want techs to
15819 * break if they don't have a way to set a poster.
15820 *
15821 * @method setPoster
15822 */
15823
15824 Tech.prototype.setPoster = function setPoster() {};
15825
15826 /*
15827 * Check if the tech can support the given type
15828 *
15829 * The base tech does not support any type, but source handlers might
15830 * overwrite this.
15831 *
15832 * @param {String} type The mimetype to check
15833 * @return {String} 'probably', 'maybe', or '' (empty string)
15834 */
15835
15836 Tech.prototype.canPlayType = function canPlayType() {
15837 return '';
15838 };
15839
15840 /*
15841 * Return whether the argument is a Tech or not.
15842 * Can be passed either a Class like `Html5` or a instance like `player.tech_`
15843 *
15844 * @param {Object} component An item to check
15845 * @return {Boolean} Whether it is a tech or not
15846 */
15847
15848 Tech.isTech = function isTech(component) {
15849 return component.prototype instanceof Tech || component instanceof Tech || component === Tech;
15850 };
15851
15852 /**
15853 * Registers a Tech
15854 *
15855 * @param {String} name Name of the Tech to register
15856 * @param {Object} tech The tech to register
15857 * @static
15858 * @method registerComponent
15859 */
15860
15861 Tech.registerTech = function registerTech(name, tech) {
15862 if (!Tech.techs_) {
15863 Tech.techs_ = {};
15864 }
15865
15866 if (!Tech.isTech(tech)) {
15867 throw new Error('Tech ' + name + ' must be a Tech');
15868 }
15869
15870 Tech.techs_[name] = tech;
15871 return tech;
15872 };
15873
15874 /**
15875 * Gets a component by name
15876 *
15877 * @param {String} name Name of the component to get
15878 * @return {Component}
15879 * @static
15880 * @method getComponent
15881 */
15882
15883 Tech.getTech = function getTech(name) {
15884 if (Tech.techs_ && Tech.techs_[name]) {
15885 return Tech.techs_[name];
15886 }
15887
15888 if (_globalWindow2['default'] && _globalWindow2['default'].videojs && _globalWindow2['default'].videojs[name]) {
15889 _utilsLogJs2['default'].warn('The ' + name + ' tech was added to the videojs object when it should be registered using videojs.registerTech(name, tech)');
15890 return _globalWindow2['default'].videojs[name];
15891 }
15892 };
15893
15894 return Tech;
15895})(_component2['default']);
15896
15897Tech.prototype.textTracks_;
15898
15899var createTrackHelper = function createTrackHelper(self, kind, label, language) {
15900 var options = arguments.length <= 4 || arguments[4] === undefined ? {} : arguments[4];
15901
15902 var tracks = self.textTracks();
15903
15904 options.kind = kind;
15905
15906 if (label) {
15907 options.label = label;
15908 }
15909 if (language) {
15910 options.language = language;
15911 }
15912 options.tech = self;
15913
15914 var track = new _tracksTextTrack2['default'](options);
15915 tracks.addTrack_(track);
15916
15917 return track;
15918};
15919
15920Tech.prototype.featuresVolumeControl = true;
15921
15922// Resizing plugins using request fullscreen reloads the plugin
15923Tech.prototype.featuresFullscreenResize = false;
15924Tech.prototype.featuresPlaybackRate = false;
15925
15926// Optional events that we can manually mimic with timers
15927// currently not triggered by video-js-swf
15928Tech.prototype.featuresProgressEvents = false;
15929Tech.prototype.featuresTimeupdateEvents = false;
15930
15931Tech.prototype.featuresNativeTextTracks = false;
15932
15933/*
15934 * A functional mixin for techs that want to use the Source Handler pattern.
15935 *
15936 * ##### EXAMPLE:
15937 *
15938 * Tech.withSourceHandlers.call(MyTech);
15939 *
15940 */
15941Tech.withSourceHandlers = function (_Tech) {
15942 /*
15943 * Register a source handler
15944 * Source handlers are scripts for handling specific formats.
15945 * The source handler pattern is used for adaptive formats (HLS, DASH) that
15946 * manually load video data and feed it into a Source Buffer (Media Source Extensions)
15947 * @param {Function} handler The source handler
15948 * @param {Boolean} first Register it before any existing handlers
15949 */
15950 _Tech.registerSourceHandler = function (handler, index) {
15951 var handlers = _Tech.sourceHandlers;
15952
15953 if (!handlers) {
15954 handlers = _Tech.sourceHandlers = [];
15955 }
15956
15957 if (index === undefined) {
15958 // add to the end of the list
15959 index = handlers.length;
15960 }
15961
15962 handlers.splice(index, 0, handler);
15963 };
15964
15965 /*
15966 * Check if the tech can support the given type
15967 * @param {String} type The mimetype to check
15968 * @return {String} 'probably', 'maybe', or '' (empty string)
15969 */
15970 _Tech.canPlayType = function (type) {
15971 var handlers = _Tech.sourceHandlers || [];
15972 var can = undefined;
15973
15974 for (var i = 0; i < handlers.length; i++) {
15975 can = handlers[i].canPlayType(type);
15976
15977 if (can) {
15978 return can;
15979 }
15980 }
15981
15982 return '';
15983 };
15984
15985 /*
15986 * Return the first source handler that supports the source
15987 * TODO: Answer question: should 'probably' be prioritized over 'maybe'
15988 * @param {Object} source The source object
15989 * @returns {Object} The first source handler that supports the source
15990 * @returns {null} Null if no source handler is found
15991 */
15992 _Tech.selectSourceHandler = function (source) {
15993 var handlers = _Tech.sourceHandlers || [];
15994 var can = undefined;
15995
15996 for (var i = 0; i < handlers.length; i++) {
15997 can = handlers[i].canHandleSource(source);
15998
15999 if (can) {
16000 return handlers[i];
16001 }
16002 }
16003
16004 return null;
16005 };
16006
16007 /*
16008 * Check if the tech can support the given source
16009 * @param {Object} srcObj The source object
16010 * @return {String} 'probably', 'maybe', or '' (empty string)
16011 */
16012 _Tech.canPlaySource = function (srcObj) {
16013 var sh = _Tech.selectSourceHandler(srcObj);
16014
16015 if (sh) {
16016 return sh.canHandleSource(srcObj);
16017 }
16018
16019 return '';
16020 };
16021
16022 /*
16023 * When using a source handler, prefer its implementation of
16024 * any function normally provided by the tech.
16025 */
16026 var deferrable = ['seekable', 'duration'];
16027
16028 deferrable.forEach(function (fnName) {
16029 var originalFn = this[fnName];
16030
16031 if (typeof originalFn !== 'function') {
16032 return;
16033 }
16034
16035 this[fnName] = function () {
16036 if (this.sourceHandler_ && this.sourceHandler_[fnName]) {
16037 return this.sourceHandler_[fnName].apply(this.sourceHandler_, arguments);
16038 }
16039 return originalFn.apply(this, arguments);
16040 };
16041 }, _Tech.prototype);
16042
16043 /*
16044 * Create a function for setting the source using a source object
16045 * and source handlers.
16046 * Should never be called unless a source handler was found.
16047 * @param {Object} source A source object with src and type keys
16048 * @return {Tech} self
16049 */
16050 _Tech.prototype.setSource = function (source) {
16051 var sh = _Tech.selectSourceHandler(source);
16052
16053 if (!sh) {
16054 // Fall back to a native source hander when unsupported sources are
16055 // deliberately set
16056 if (_Tech.nativeSourceHandler) {
16057 sh = _Tech.nativeSourceHandler;
16058 } else {
16059 _utilsLogJs2['default'].error('No source hander found for the current source.');
16060 }
16061 }
16062
16063 // Dispose any existing source handler
16064 this.disposeSourceHandler();
16065 this.off('dispose', this.disposeSourceHandler);
16066
16067 this.currentSource_ = source;
16068 this.sourceHandler_ = sh.handleSource(source, this);
16069 this.on('dispose', this.disposeSourceHandler);
16070
16071 return this;
16072 };
16073
16074 /*
16075 * Clean up any existing source handler
16076 */
16077 _Tech.prototype.disposeSourceHandler = function () {
16078 if (this.sourceHandler_ && this.sourceHandler_.dispose) {
16079 this.sourceHandler_.dispose();
16080 }
16081 };
16082};
16083
16084_component2['default'].registerComponent('Tech', Tech);
16085// Old name for Tech
16086_component2['default'].registerComponent('MediaTechController', Tech);
16087Tech.registerTech('Tech', Tech);
16088exports['default'] = Tech;
16089module.exports = exports['default'];
16090
16091},{"../component":67,"../media-error.js":103,"../tracks/html-track-element":121,"../tracks/html-track-element-list":120,"../tracks/text-track":128,"../tracks/text-track-list":126,"../utils/buffer.js":130,"../utils/fn.js":134,"../utils/log.js":137,"../utils/merge-options.js":138,"../utils/time-ranges.js":140,"global/document":1,"global/window":2}],120:[function(_dereq_,module,exports){
16092/**
16093 * @file html-track-element-list.js
16094 */
16095
16096'use strict';
16097
16098exports.__esModule = true;
16099
16100function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16101
16102function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
16103
16104function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
16105
16106var _utilsBrowserJs = _dereq_('../utils/browser.js');
16107
16108var browser = _interopRequireWildcard(_utilsBrowserJs);
16109
16110var _globalDocument = _dereq_('global/document');
16111
16112var _globalDocument2 = _interopRequireDefault(_globalDocument);
16113
16114var HtmlTrackElementList = (function () {
16115 function HtmlTrackElementList() {
16116 var trackElements = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
16117
16118 _classCallCheck(this, HtmlTrackElementList);
16119
16120 var list = this;
16121
16122 if (browser.IS_IE8) {
16123 list = _globalDocument2['default'].createElement('custom');
16124
16125 for (var prop in HtmlTrackElementList.prototype) {
16126 if (prop !== 'constructor') {
16127 list[prop] = HtmlTrackElementList.prototype[prop];
16128 }
16129 }
16130 }
16131
16132 list.trackElements_ = [];
16133
16134 Object.defineProperty(list, 'length', {
16135 get: function get() {
16136 return this.trackElements_.length;
16137 }
16138 });
16139
16140 for (var i = 0, _length = trackElements.length; i < _length; i++) {
16141 list.addTrackElement_(trackElements[i]);
16142 }
16143
16144 if (browser.IS_IE8) {
16145 return list;
16146 }
16147 }
16148
16149 HtmlTrackElementList.prototype.addTrackElement_ = function addTrackElement_(trackElement) {
16150 this.trackElements_.push(trackElement);
16151 };
16152
16153 HtmlTrackElementList.prototype.getTrackElementByTrack_ = function getTrackElementByTrack_(track) {
16154 var trackElement_ = undefined;
16155
16156 for (var i = 0, _length2 = this.trackElements_.length; i < _length2; i++) {
16157 if (track === this.trackElements_[i].track) {
16158 trackElement_ = this.trackElements_[i];
16159
16160 break;
16161 }
16162 }
16163
16164 return trackElement_;
16165 };
16166
16167 HtmlTrackElementList.prototype.removeTrackElement_ = function removeTrackElement_(trackElement) {
16168 for (var i = 0, _length3 = this.trackElements_.length; i < _length3; i++) {
16169 if (trackElement === this.trackElements_[i]) {
16170 this.trackElements_.splice(i, 1);
16171
16172 break;
16173 }
16174 }
16175 };
16176
16177 return HtmlTrackElementList;
16178})();
16179
16180exports['default'] = HtmlTrackElementList;
16181module.exports = exports['default'];
16182
16183},{"../utils/browser.js":129,"global/document":1}],121:[function(_dereq_,module,exports){
16184/**
16185 * @file html-track-element.js
16186 */
16187
16188'use strict';
16189
16190exports.__esModule = true;
16191
16192function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16193
16194function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
16195
16196function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
16197
16198function _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; }
16199
16200var _utilsBrowserJs = _dereq_('../utils/browser.js');
16201
16202var browser = _interopRequireWildcard(_utilsBrowserJs);
16203
16204var _globalDocument = _dereq_('global/document');
16205
16206var _globalDocument2 = _interopRequireDefault(_globalDocument);
16207
16208var _eventTarget = _dereq_('../event-target');
16209
16210var _eventTarget2 = _interopRequireDefault(_eventTarget);
16211
16212var _tracksTextTrack = _dereq_('../tracks/text-track');
16213
16214var _tracksTextTrack2 = _interopRequireDefault(_tracksTextTrack);
16215
16216var NONE = 0;
16217var LOADING = 1;
16218var LOADED = 2;
16219var ERROR = 3;
16220
16221/**
16222 * https://html.spec.whatwg.org/multipage/embedded-content.html#htmltrackelement
16223 *
16224 * interface HTMLTrackElement : HTMLElement {
16225 * attribute DOMString kind;
16226 * attribute DOMString src;
16227 * attribute DOMString srclang;
16228 * attribute DOMString label;
16229 * attribute boolean default;
16230 *
16231 * const unsigned short NONE = 0;
16232 * const unsigned short LOADING = 1;
16233 * const unsigned short LOADED = 2;
16234 * const unsigned short ERROR = 3;
16235 * readonly attribute unsigned short readyState;
16236 *
16237 * readonly attribute TextTrack track;
16238 * };
16239 *
16240 * @param {Object} options TextTrack configuration
16241 * @class HTMLTrackElement
16242 */
16243
16244var HTMLTrackElement = (function (_EventTarget) {
16245 _inherits(HTMLTrackElement, _EventTarget);
16246
16247 function HTMLTrackElement() {
16248 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
16249
16250 _classCallCheck(this, HTMLTrackElement);
16251
16252 _EventTarget.call(this);
16253
16254 var readyState = undefined,
16255 trackElement = this;
16256
16257 if (browser.IS_IE8) {
16258 trackElement = _globalDocument2['default'].createElement('custom');
16259
16260 for (var prop in HTMLTrackElement.prototype) {
16261 if (prop !== 'constructor') {
16262 trackElement[prop] = HTMLTrackElement.prototype[prop];
16263 }
16264 }
16265 }
16266
16267 var track = new _tracksTextTrack2['default'](options);
16268
16269 trackElement.kind = track.kind;
16270 trackElement.src = track.src;
16271 trackElement.srclang = track.language;
16272 trackElement.label = track.label;
16273 trackElement['default'] = track['default'];
16274
16275 Object.defineProperty(trackElement, 'readyState', {
16276 get: function get() {
16277 return readyState;
16278 }
16279 });
16280
16281 Object.defineProperty(trackElement, 'track', {
16282 get: function get() {
16283 return track;
16284 }
16285 });
16286
16287 readyState = NONE;
16288
16289 track.addEventListener('loadeddata', function () {
16290 readyState = LOADED;
16291
16292 trackElement.trigger({
16293 type: 'load',
16294 target: trackElement
16295 });
16296 });
16297
16298 if (browser.IS_IE8) {
16299 return trackElement;
16300 }
16301 }
16302
16303 return HTMLTrackElement;
16304})(_eventTarget2['default']);
16305
16306HTMLTrackElement.prototype.allowedEvents_ = {
16307 load: 'load'
16308};
16309
16310HTMLTrackElement.NONE = NONE;
16311HTMLTrackElement.LOADING = LOADING;
16312HTMLTrackElement.LOADED = LOADED;
16313HTMLTrackElement.ERROR = ERROR;
16314
16315exports['default'] = HTMLTrackElement;
16316module.exports = exports['default'];
16317
16318},{"../event-target":99,"../tracks/text-track":128,"../utils/browser.js":129,"global/document":1}],122:[function(_dereq_,module,exports){
16319/**
16320 * @file text-track-cue-list.js
16321 */
16322'use strict';
16323
16324exports.__esModule = true;
16325
16326function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16327
16328function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
16329
16330function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
16331
16332var _utilsBrowserJs = _dereq_('../utils/browser.js');
16333
16334var browser = _interopRequireWildcard(_utilsBrowserJs);
16335
16336var _globalDocument = _dereq_('global/document');
16337
16338var _globalDocument2 = _interopRequireDefault(_globalDocument);
16339
16340/**
16341 * A List of text track cues as defined in:
16342 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist
16343 *
16344 * interface TextTrackCueList {
16345 * readonly attribute unsigned long length;
16346 * getter TextTrackCue (unsigned long index);
16347 * TextTrackCue? getCueById(DOMString id);
16348 * };
16349 *
16350 * @param {Array} cues A list of cues to be initialized with
16351 * @class TextTrackCueList
16352 */
16353
16354var TextTrackCueList = (function () {
16355 function TextTrackCueList(cues) {
16356 _classCallCheck(this, TextTrackCueList);
16357
16358 var list = this;
16359
16360 if (browser.IS_IE8) {
16361 list = _globalDocument2['default'].createElement('custom');
16362
16363 for (var prop in TextTrackCueList.prototype) {
16364 if (prop !== 'constructor') {
16365 list[prop] = TextTrackCueList.prototype[prop];
16366 }
16367 }
16368 }
16369
16370 TextTrackCueList.prototype.setCues_.call(list, cues);
16371
16372 Object.defineProperty(list, 'length', {
16373 get: function get() {
16374 return this.length_;
16375 }
16376 });
16377
16378 if (browser.IS_IE8) {
16379 return list;
16380 }
16381 }
16382
16383 /**
16384 * A setter for cues in this list
16385 *
16386 * @param {Array} cues an array of cues
16387 * @method setCues_
16388 * @private
16389 */
16390
16391 TextTrackCueList.prototype.setCues_ = function setCues_(cues) {
16392 var oldLength = this.length || 0;
16393 var i = 0;
16394 var l = cues.length;
16395
16396 this.cues_ = cues;
16397 this.length_ = cues.length;
16398
16399 var defineProp = function defineProp(index) {
16400 if (!('' + index in this)) {
16401 Object.defineProperty(this, '' + index, {
16402 get: function get() {
16403 return this.cues_[index];
16404 }
16405 });
16406 }
16407 };
16408
16409 if (oldLength < l) {
16410 i = oldLength;
16411
16412 for (; i < l; i++) {
16413 defineProp.call(this, i);
16414 }
16415 }
16416 };
16417
16418 /**
16419 * Get a cue that is currently in the Cue list by id
16420 *
16421 * @param {String} id
16422 * @method getCueById
16423 * @return {Object} a single cue
16424 */
16425
16426 TextTrackCueList.prototype.getCueById = function getCueById(id) {
16427 var result = null;
16428
16429 for (var i = 0, l = this.length; i < l; i++) {
16430 var cue = this[i];
16431
16432 if (cue.id === id) {
16433 result = cue;
16434 break;
16435 }
16436 }
16437
16438 return result;
16439 };
16440
16441 return TextTrackCueList;
16442})();
16443
16444exports['default'] = TextTrackCueList;
16445module.exports = exports['default'];
16446
16447},{"../utils/browser.js":129,"global/document":1}],123:[function(_dereq_,module,exports){
16448/**
16449 * @file text-track-display.js
16450 */
16451'use strict';
16452
16453exports.__esModule = true;
16454
16455function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
16456
16457function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16458
16459function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
16460
16461function _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; }
16462
16463var _component = _dereq_('../component');
16464
16465var _component2 = _interopRequireDefault(_component);
16466
16467var _menuMenuJs = _dereq_('../menu/menu.js');
16468
16469var _menuMenuJs2 = _interopRequireDefault(_menuMenuJs);
16470
16471var _menuMenuItemJs = _dereq_('../menu/menu-item.js');
16472
16473var _menuMenuItemJs2 = _interopRequireDefault(_menuMenuItemJs);
16474
16475var _menuMenuButtonJs = _dereq_('../menu/menu-button.js');
16476
16477var _menuMenuButtonJs2 = _interopRequireDefault(_menuMenuButtonJs);
16478
16479var _utilsFnJs = _dereq_('../utils/fn.js');
16480
16481var Fn = _interopRequireWildcard(_utilsFnJs);
16482
16483var _globalDocument = _dereq_('global/document');
16484
16485var _globalDocument2 = _interopRequireDefault(_globalDocument);
16486
16487var _globalWindow = _dereq_('global/window');
16488
16489var _globalWindow2 = _interopRequireDefault(_globalWindow);
16490
16491var darkGray = '#222';
16492var lightGray = '#ccc';
16493var fontMap = {
16494 monospace: 'monospace',
16495 sansSerif: 'sans-serif',
16496 serif: 'serif',
16497 monospaceSansSerif: '"Andale Mono", "Lucida Console", monospace',
16498 monospaceSerif: '"Courier New", monospace',
16499 proportionalSansSerif: 'sans-serif',
16500 proportionalSerif: 'serif',
16501 casual: '"Comic Sans MS", Impact, fantasy',
16502 script: '"Monotype Corsiva", cursive',
16503 smallcaps: '"Andale Mono", "Lucida Console", monospace, sans-serif'
16504};
16505
16506/**
16507 * The component for displaying text track cues
16508 *
16509 * @param {Object} player Main Player
16510 * @param {Object=} options Object of option names and values
16511 * @param {Function=} ready Ready callback function
16512 * @extends Component
16513 * @class TextTrackDisplay
16514 */
16515
16516var TextTrackDisplay = (function (_Component) {
16517 _inherits(TextTrackDisplay, _Component);
16518
16519 function TextTrackDisplay(player, options, ready) {
16520 _classCallCheck(this, TextTrackDisplay);
16521
16522 _Component.call(this, player, options, ready);
16523
16524 player.on('loadstart', Fn.bind(this, this.toggleDisplay));
16525 player.on('texttrackchange', Fn.bind(this, this.updateDisplay));
16526
16527 // This used to be called during player init, but was causing an error
16528 // if a track should show by default and the display hadn't loaded yet.
16529 // Should probably be moved to an external track loader when we support
16530 // tracks that don't need a display.
16531 player.ready(Fn.bind(this, function () {
16532 if (player.tech_ && player.tech_['featuresNativeTextTracks']) {
16533 this.hide();
16534 return;
16535 }
16536
16537 player.on('fullscreenchange', Fn.bind(this, this.updateDisplay));
16538
16539 var tracks = this.options_.playerOptions['tracks'] || [];
16540 for (var i = 0; i < tracks.length; i++) {
16541 var track = tracks[i];
16542 this.player_.addRemoteTextTrack(track);
16543 }
16544 }));
16545 }
16546
16547 /**
16548 * Add cue HTML to display
16549 *
16550 * @param {Number} color Hex number for color, like #f0e
16551 * @param {Number} opacity Value for opacity,0.0 - 1.0
16552 * @return {RGBAColor} In the form 'rgba(255, 0, 0, 0.3)'
16553 * @method constructColor
16554 */
16555
16556 /**
16557 * Toggle display texttracks
16558 *
16559 * @method toggleDisplay
16560 */
16561
16562 TextTrackDisplay.prototype.toggleDisplay = function toggleDisplay() {
16563 if (this.player_.tech_ && this.player_.tech_['featuresNativeTextTracks']) {
16564 this.hide();
16565 } else {
16566 this.show();
16567 }
16568 };
16569
16570 /**
16571 * Create the component's DOM element
16572 *
16573 * @return {Element}
16574 * @method createEl
16575 */
16576
16577 TextTrackDisplay.prototype.createEl = function createEl() {
16578 return _Component.prototype.createEl.call(this, 'div', {
16579 className: 'vjs-text-track-display'
16580 });
16581 };
16582
16583 /**
16584 * Clear display texttracks
16585 *
16586 * @method clearDisplay
16587 */
16588
16589 TextTrackDisplay.prototype.clearDisplay = function clearDisplay() {
16590 if (typeof _globalWindow2['default']['WebVTT'] === 'function') {
16591 _globalWindow2['default']['WebVTT']['processCues'](_globalWindow2['default'], [], this.el_);
16592 }
16593 };
16594
16595 /**
16596 * Update display texttracks
16597 *
16598 * @method updateDisplay
16599 */
16600
16601 TextTrackDisplay.prototype.updateDisplay = function updateDisplay() {
16602 var tracks = this.player_.textTracks();
16603
16604 this.clearDisplay();
16605
16606 if (!tracks) {
16607 return;
16608 }
16609
16610 for (var i = 0; i < tracks.length; i++) {
16611 var track = tracks[i];
16612 if (track['mode'] === 'showing') {
16613 this.updateForTrack(track);
16614 }
16615 }
16616 };
16617
16618 /**
16619 * Add texttrack to texttrack list
16620 *
16621 * @param {TextTrackObject} track Texttrack object to be added to list
16622 * @method updateForTrack
16623 */
16624
16625 TextTrackDisplay.prototype.updateForTrack = function updateForTrack(track) {
16626 if (typeof _globalWindow2['default']['WebVTT'] !== 'function' || !track['activeCues']) {
16627 return;
16628 }
16629
16630 var overrides = this.player_['textTrackSettings'].getValues();
16631
16632 var cues = [];
16633 for (var _i = 0; _i < track['activeCues'].length; _i++) {
16634 cues.push(track['activeCues'][_i]);
16635 }
16636
16637 _globalWindow2['default']['WebVTT']['processCues'](_globalWindow2['default'], track['activeCues'], this.el_);
16638
16639 var i = cues.length;
16640 while (i--) {
16641 var cue = cues[i];
16642 if (!cue) {
16643 continue;
16644 }
16645
16646 var cueDiv = cue.displayState;
16647 if (overrides.color) {
16648 cueDiv.firstChild.style.color = overrides.color;
16649 }
16650 if (overrides.textOpacity) {
16651 tryUpdateStyle(cueDiv.firstChild, 'color', constructColor(overrides.color || '#fff', overrides.textOpacity));
16652 }
16653 if (overrides.backgroundColor) {
16654 cueDiv.firstChild.style.backgroundColor = overrides.backgroundColor;
16655 }
16656 if (overrides.backgroundOpacity) {
16657 tryUpdateStyle(cueDiv.firstChild, 'backgroundColor', constructColor(overrides.backgroundColor || '#000', overrides.backgroundOpacity));
16658 }
16659 if (overrides.windowColor) {
16660 if (overrides.windowOpacity) {
16661 tryUpdateStyle(cueDiv, 'backgroundColor', constructColor(overrides.windowColor, overrides.windowOpacity));
16662 } else {
16663 cueDiv.style.backgroundColor = overrides.windowColor;
16664 }
16665 }
16666 if (overrides.edgeStyle) {
16667 if (overrides.edgeStyle === 'dropshadow') {
16668 cueDiv.firstChild.style.textShadow = '2px 2px 3px ' + darkGray + ', 2px 2px 4px ' + darkGray + ', 2px 2px 5px ' + darkGray;
16669 } else if (overrides.edgeStyle === 'raised') {
16670 cueDiv.firstChild.style.textShadow = '1px 1px ' + darkGray + ', 2px 2px ' + darkGray + ', 3px 3px ' + darkGray;
16671 } else if (overrides.edgeStyle === 'depressed') {
16672 cueDiv.firstChild.style.textShadow = '1px 1px ' + lightGray + ', 0 1px ' + lightGray + ', -1px -1px ' + darkGray + ', 0 -1px ' + darkGray;
16673 } else if (overrides.edgeStyle === 'uniform') {
16674 cueDiv.firstChild.style.textShadow = '0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray;
16675 }
16676 }
16677 if (overrides.fontPercent && overrides.fontPercent !== 1) {
16678 var fontSize = _globalWindow2['default'].parseFloat(cueDiv.style.fontSize);
16679 cueDiv.style.fontSize = fontSize * overrides.fontPercent + 'px';
16680 cueDiv.style.height = 'auto';
16681 cueDiv.style.top = 'auto';
16682 cueDiv.style.bottom = '2px';
16683 }
16684 if (overrides.fontFamily && overrides.fontFamily !== 'default') {
16685 if (overrides.fontFamily === 'small-caps') {
16686 cueDiv.firstChild.style.fontVariant = 'small-caps';
16687 } else {
16688 cueDiv.firstChild.style.fontFamily = fontMap[overrides.fontFamily];
16689 }
16690 }
16691 }
16692 };
16693
16694 return TextTrackDisplay;
16695})(_component2['default']);
16696
16697function constructColor(color, opacity) {
16698 return 'rgba(' +
16699 // color looks like "#f0e"
16700 parseInt(color[1] + color[1], 16) + ',' + parseInt(color[2] + color[2], 16) + ',' + parseInt(color[3] + color[3], 16) + ',' + opacity + ')';
16701}
16702
16703/**
16704 * Try to update style
16705 * Some style changes will throw an error, particularly in IE8. Those should be noops.
16706 *
16707 * @param {Element} el The element to be styles
16708 * @param {CSSProperty} style The CSS property to be styled
16709 * @param {CSSStyle} rule The actual style to be applied to the property
16710 * @method tryUpdateStyle
16711 */
16712function tryUpdateStyle(el, style, rule) {
16713 //
16714 try {
16715 el.style[style] = rule;
16716 } catch (e) {}
16717}
16718
16719_component2['default'].registerComponent('TextTrackDisplay', TextTrackDisplay);
16720exports['default'] = TextTrackDisplay;
16721module.exports = exports['default'];
16722
16723},{"../component":67,"../menu/menu-button.js":104,"../menu/menu-item.js":105,"../menu/menu.js":106,"../utils/fn.js":134,"global/document":1,"global/window":2}],124:[function(_dereq_,module,exports){
16724/**
16725 * @file text-track-enums.js
16726 */
16727
16728/**
16729 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackmode
16730 *
16731 * enum TextTrackMode { "disabled", "hidden", "showing" };
16732 */
16733'use strict';
16734
16735exports.__esModule = true;
16736var TextTrackMode = {
16737 disabled: 'disabled',
16738 hidden: 'hidden',
16739 showing: 'showing'
16740};
16741
16742/**
16743 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackkind
16744 *
16745 * enum TextTrackKind {
16746 * "subtitles",
16747 * "captions",
16748 * "descriptions",
16749 * "chapters",
16750 * "metadata"
16751 * };
16752 */
16753var TextTrackKind = {
16754 subtitles: 'subtitles',
16755 captions: 'captions',
16756 descriptions: 'descriptions',
16757 chapters: 'chapters',
16758 metadata: 'metadata'
16759};
16760
16761/* jshint ignore:start */
16762// we ignore jshint here because it does not see
16763// TextTrackMode or TextTrackKind as defined here somehow...
16764exports.TextTrackMode = TextTrackMode;
16765exports.TextTrackKind = TextTrackKind;
16766
16767/* jshint ignore:end */
16768
16769},{}],125:[function(_dereq_,module,exports){
16770/**
16771 * Utilities for capturing text track state and re-creating tracks
16772 * based on a capture.
16773 *
16774 * @file text-track-list-converter.js
16775 */
16776
16777/**
16778 * Examine a single text track and return a JSON-compatible javascript
16779 * object that represents the text track's state.
16780 * @param track {TextTrackObject} the text track to query
16781 * @return {Object} a serializable javascript representation of the
16782 * @private
16783 */
16784'use strict';
16785
16786exports.__esModule = true;
16787var trackToJson_ = function trackToJson_(track) {
16788 var ret = ['kind', 'label', 'language', 'id', 'inBandMetadataTrackDispatchType', 'mode', 'src'].reduce(function (acc, prop, i) {
16789 if (track[prop]) {
16790 acc[prop] = track[prop];
16791 }
16792
16793 return acc;
16794 }, {
16795 cues: track.cues && Array.prototype.map.call(track.cues, function (cue) {
16796 return {
16797 startTime: cue.startTime,
16798 endTime: cue.endTime,
16799 text: cue.text,
16800 id: cue.id
16801 };
16802 })
16803 });
16804
16805 return ret;
16806};
16807
16808/**
16809 * Examine a tech and return a JSON-compatible javascript array that
16810 * represents the state of all text tracks currently configured. The
16811 * return array is compatible with `jsonToTextTracks`.
16812 * @param tech {tech} the tech object to query
16813 * @return {Array} a serializable javascript representation of the
16814 * @function textTracksToJson
16815 */
16816var textTracksToJson = function textTracksToJson(tech) {
16817
16818 var trackEls = tech.$$('track');
16819
16820 var trackObjs = Array.prototype.map.call(trackEls, function (t) {
16821 return t.track;
16822 });
16823 var tracks = Array.prototype.map.call(trackEls, function (trackEl) {
16824 var json = trackToJson_(trackEl.track);
16825 if (trackEl.src) {
16826 json.src = trackEl.src;
16827 }
16828 return json;
16829 });
16830
16831 return tracks.concat(Array.prototype.filter.call(tech.textTracks(), function (track) {
16832 return trackObjs.indexOf(track) === -1;
16833 }).map(trackToJson_));
16834};
16835
16836/**
16837 * Creates a set of remote text tracks on a tech based on an array of
16838 * javascript text track representations.
16839 * @param json {Array} an array of text track representation objects,
16840 * like those that would be produced by `textTracksToJson`
16841 * @param tech {tech} the tech to create text tracks on
16842 * @function jsonToTextTracks
16843 */
16844var jsonToTextTracks = function jsonToTextTracks(json, tech) {
16845 json.forEach(function (track) {
16846 var addedTrack = tech.addRemoteTextTrack(track).track;
16847 if (!track.src && track.cues) {
16848 track.cues.forEach(function (cue) {
16849 return addedTrack.addCue(cue);
16850 });
16851 }
16852 });
16853
16854 return tech.textTracks();
16855};
16856
16857exports['default'] = { textTracksToJson: textTracksToJson, jsonToTextTracks: jsonToTextTracks, trackToJson_: trackToJson_ };
16858module.exports = exports['default'];
16859
16860},{}],126:[function(_dereq_,module,exports){
16861/**
16862 * @file text-track-list.js
16863 */
16864'use strict';
16865
16866exports.__esModule = true;
16867
16868function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
16869
16870function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16871
16872function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
16873
16874function _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; }
16875
16876var _eventTarget = _dereq_('../event-target');
16877
16878var _eventTarget2 = _interopRequireDefault(_eventTarget);
16879
16880var _utilsFnJs = _dereq_('../utils/fn.js');
16881
16882var Fn = _interopRequireWildcard(_utilsFnJs);
16883
16884var _utilsBrowserJs = _dereq_('../utils/browser.js');
16885
16886var browser = _interopRequireWildcard(_utilsBrowserJs);
16887
16888var _globalDocument = _dereq_('global/document');
16889
16890var _globalDocument2 = _interopRequireDefault(_globalDocument);
16891
16892/**
16893 * A text track list as defined in:
16894 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttracklist
16895 *
16896 * interface TextTrackList : EventTarget {
16897 * readonly attribute unsigned long length;
16898 * getter TextTrack (unsigned long index);
16899 * TextTrack? getTrackById(DOMString id);
16900 *
16901 * attribute EventHandler onchange;
16902 * attribute EventHandler onaddtrack;
16903 * attribute EventHandler onremovetrack;
16904 * };
16905 *
16906 * @param {Track[]} tracks A list of tracks to initialize the list with
16907 * @extends EventTarget
16908 * @class TextTrackList
16909 */
16910
16911var TextTrackList = (function (_EventTarget) {
16912 _inherits(TextTrackList, _EventTarget);
16913
16914 function TextTrackList() {
16915 var tracks = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
16916
16917 _classCallCheck(this, TextTrackList);
16918
16919 _EventTarget.call(this);
16920 var list = this;
16921
16922 if (browser.IS_IE8) {
16923 list = _globalDocument2['default'].createElement('custom');
16924
16925 for (var prop in TextTrackList.prototype) {
16926 if (prop !== 'constructor') {
16927 list[prop] = TextTrackList.prototype[prop];
16928 }
16929 }
16930 }
16931
16932 list.tracks_ = [];
16933
16934 Object.defineProperty(list, 'length', {
16935 get: function get() {
16936 return this.tracks_.length;
16937 }
16938 });
16939
16940 for (var i = 0; i < tracks.length; i++) {
16941 list.addTrack_(tracks[i]);
16942 }
16943
16944 if (browser.IS_IE8) {
16945 return list;
16946 }
16947 }
16948
16949 /**
16950 * change - One or more tracks in the track list have been enabled or disabled.
16951 * addtrack - A track has been added to the track list.
16952 * removetrack - A track has been removed from the track list.
16953 */
16954
16955 /**
16956 * Add TextTrack from TextTrackList
16957 *
16958 * @param {TextTrack} track
16959 * @method addTrack_
16960 * @private
16961 */
16962
16963 TextTrackList.prototype.addTrack_ = function addTrack_(track) {
16964 var index = this.tracks_.length;
16965
16966 if (!('' + index in this)) {
16967 Object.defineProperty(this, index, {
16968 get: function get() {
16969 return this.tracks_[index];
16970 }
16971 });
16972 }
16973
16974 track.addEventListener('modechange', Fn.bind(this, function () {
16975 this.trigger('change');
16976 }));
16977
16978 // Do not add duplicate tracks
16979 if (this.tracks_.indexOf(track) === -1) {
16980 this.tracks_.push(track);
16981 this.trigger({
16982 track: track,
16983 type: 'addtrack'
16984 });
16985 }
16986 };
16987
16988 /**
16989 * Remove TextTrack from TextTrackList
16990 * NOTE: Be mindful of what is passed in as it may be a HTMLTrackElement
16991 *
16992 * @param {TextTrack} rtrack
16993 * @method removeTrack_
16994 * @private
16995 */
16996
16997 TextTrackList.prototype.removeTrack_ = function removeTrack_(rtrack) {
16998 var track = undefined;
16999
17000 for (var i = 0, l = this.length; i < l; i++) {
17001 if (this[i] === rtrack) {
17002 track = this[i];
17003 if (track.off) {
17004 track.off();
17005 }
17006
17007 this.tracks_.splice(i, 1);
17008
17009 break;
17010 }
17011 }
17012
17013 if (!track) {
17014 return;
17015 }
17016
17017 this.trigger({
17018 track: track,
17019 type: 'removetrack'
17020 });
17021 };
17022
17023 /**
17024 * Get a TextTrack from TextTrackList by a tracks id
17025 *
17026 * @param {String} id - the id of the track to get
17027 * @method getTrackById
17028 * @return {TextTrack}
17029 * @private
17030 */
17031
17032 TextTrackList.prototype.getTrackById = function getTrackById(id) {
17033 var result = null;
17034
17035 for (var i = 0, l = this.length; i < l; i++) {
17036 var track = this[i];
17037
17038 if (track.id === id) {
17039 result = track;
17040 break;
17041 }
17042 }
17043
17044 return result;
17045 };
17046
17047 return TextTrackList;
17048})(_eventTarget2['default']);
17049
17050TextTrackList.prototype.allowedEvents_ = {
17051 change: 'change',
17052 addtrack: 'addtrack',
17053 removetrack: 'removetrack'
17054};
17055
17056// emulate attribute EventHandler support to allow for feature detection
17057for (var _event in TextTrackList.prototype.allowedEvents_) {
17058 TextTrackList.prototype['on' + _event] = null;
17059}
17060
17061exports['default'] = TextTrackList;
17062module.exports = exports['default'];
17063
17064},{"../event-target":99,"../utils/browser.js":129,"../utils/fn.js":134,"global/document":1}],127:[function(_dereq_,module,exports){
17065/**
17066 * @file text-track-settings.js
17067 */
17068'use strict';
17069
17070exports.__esModule = true;
17071
17072function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
17073
17074function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17075
17076function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
17077
17078function _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; }
17079
17080var _component = _dereq_('../component');
17081
17082var _component2 = _interopRequireDefault(_component);
17083
17084var _utilsEventsJs = _dereq_('../utils/events.js');
17085
17086var Events = _interopRequireWildcard(_utilsEventsJs);
17087
17088var _utilsFnJs = _dereq_('../utils/fn.js');
17089
17090var Fn = _interopRequireWildcard(_utilsFnJs);
17091
17092var _utilsLogJs = _dereq_('../utils/log.js');
17093
17094var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
17095
17096var _safeJsonParseTuple = _dereq_('safe-json-parse/tuple');
17097
17098var _safeJsonParseTuple2 = _interopRequireDefault(_safeJsonParseTuple);
17099
17100var _globalWindow = _dereq_('global/window');
17101
17102var _globalWindow2 = _interopRequireDefault(_globalWindow);
17103
17104/**
17105 * Manipulate settings of texttracks
17106 *
17107 * @param {Object} player Main Player
17108 * @param {Object=} options Object of option names and values
17109 * @extends Component
17110 * @class TextTrackSettings
17111 */
17112
17113var TextTrackSettings = (function (_Component) {
17114 _inherits(TextTrackSettings, _Component);
17115
17116 function TextTrackSettings(player, options) {
17117 _classCallCheck(this, TextTrackSettings);
17118
17119 _Component.call(this, player, options);
17120 this.hide();
17121
17122 // Grab `persistTextTrackSettings` from the player options if not passed in child options
17123 if (options.persistTextTrackSettings === undefined) {
17124 this.options_.persistTextTrackSettings = this.options_.playerOptions.persistTextTrackSettings;
17125 }
17126
17127 Events.on(this.$('.vjs-done-button'), 'click', Fn.bind(this, function () {
17128 this.saveSettings();
17129 this.hide();
17130 }));
17131
17132 Events.on(this.$('.vjs-default-button'), 'click', Fn.bind(this, function () {
17133 this.$('.vjs-fg-color > select').selectedIndex = 0;
17134 this.$('.vjs-bg-color > select').selectedIndex = 0;
17135 this.$('.window-color > select').selectedIndex = 0;
17136 this.$('.vjs-text-opacity > select').selectedIndex = 0;
17137 this.$('.vjs-bg-opacity > select').selectedIndex = 0;
17138 this.$('.vjs-window-opacity > select').selectedIndex = 0;
17139 this.$('.vjs-edge-style select').selectedIndex = 0;
17140 this.$('.vjs-font-family select').selectedIndex = 0;
17141 this.$('.vjs-font-percent select').selectedIndex = 2;
17142 this.updateDisplay();
17143 }));
17144
17145 Events.on(this.$('.vjs-fg-color > select'), 'change', Fn.bind(this, this.updateDisplay));
17146 Events.on(this.$('.vjs-bg-color > select'), 'change', Fn.bind(this, this.updateDisplay));
17147 Events.on(this.$('.window-color > select'), 'change', Fn.bind(this, this.updateDisplay));
17148 Events.on(this.$('.vjs-text-opacity > select'), 'change', Fn.bind(this, this.updateDisplay));
17149 Events.on(this.$('.vjs-bg-opacity > select'), 'change', Fn.bind(this, this.updateDisplay));
17150 Events.on(this.$('.vjs-window-opacity > select'), 'change', Fn.bind(this, this.updateDisplay));
17151 Events.on(this.$('.vjs-font-percent select'), 'change', Fn.bind(this, this.updateDisplay));
17152 Events.on(this.$('.vjs-edge-style select'), 'change', Fn.bind(this, this.updateDisplay));
17153 Events.on(this.$('.vjs-font-family select'), 'change', Fn.bind(this, this.updateDisplay));
17154
17155 if (this.options_.persistTextTrackSettings) {
17156 this.restoreSettings();
17157 }
17158 }
17159
17160 /**
17161 * Create the component's DOM element
17162 *
17163 * @return {Element}
17164 * @method createEl
17165 */
17166
17167 TextTrackSettings.prototype.createEl = function createEl() {
17168 return _Component.prototype.createEl.call(this, 'div', {
17169 className: 'vjs-caption-settings vjs-modal-overlay',
17170 innerHTML: captionOptionsMenuTemplate()
17171 });
17172 };
17173
17174 /**
17175 * Get texttrack settings
17176 * Settings are
17177 * .vjs-edge-style
17178 * .vjs-font-family
17179 * .vjs-fg-color
17180 * .vjs-text-opacity
17181 * .vjs-bg-color
17182 * .vjs-bg-opacity
17183 * .window-color
17184 * .vjs-window-opacity
17185 *
17186 * @return {Object}
17187 * @method getValues
17188 */
17189
17190 TextTrackSettings.prototype.getValues = function getValues() {
17191 var textEdge = getSelectedOptionValue(this.$('.vjs-edge-style select'));
17192 var fontFamily = getSelectedOptionValue(this.$('.vjs-font-family select'));
17193 var fgColor = getSelectedOptionValue(this.$('.vjs-fg-color > select'));
17194 var textOpacity = getSelectedOptionValue(this.$('.vjs-text-opacity > select'));
17195 var bgColor = getSelectedOptionValue(this.$('.vjs-bg-color > select'));
17196 var bgOpacity = getSelectedOptionValue(this.$('.vjs-bg-opacity > select'));
17197 var windowColor = getSelectedOptionValue(this.$('.window-color > select'));
17198 var windowOpacity = getSelectedOptionValue(this.$('.vjs-window-opacity > select'));
17199 var fontPercent = _globalWindow2['default']['parseFloat'](getSelectedOptionValue(this.$('.vjs-font-percent > select')));
17200
17201 var result = {
17202 'backgroundOpacity': bgOpacity,
17203 'textOpacity': textOpacity,
17204 'windowOpacity': windowOpacity,
17205 'edgeStyle': textEdge,
17206 'fontFamily': fontFamily,
17207 'color': fgColor,
17208 'backgroundColor': bgColor,
17209 'windowColor': windowColor,
17210 'fontPercent': fontPercent
17211 };
17212 for (var _name in result) {
17213 if (result[_name] === '' || result[_name] === 'none' || _name === 'fontPercent' && result[_name] === 1.00) {
17214 delete result[_name];
17215 }
17216 }
17217 return result;
17218 };
17219
17220 /**
17221 * Set texttrack settings
17222 * Settings are
17223 * .vjs-edge-style
17224 * .vjs-font-family
17225 * .vjs-fg-color
17226 * .vjs-text-opacity
17227 * .vjs-bg-color
17228 * .vjs-bg-opacity
17229 * .window-color
17230 * .vjs-window-opacity
17231 *
17232 * @param {Object} values Object with texttrack setting values
17233 * @method setValues
17234 */
17235
17236 TextTrackSettings.prototype.setValues = function setValues(values) {
17237 setSelectedOption(this.$('.vjs-edge-style select'), values.edgeStyle);
17238 setSelectedOption(this.$('.vjs-font-family select'), values.fontFamily);
17239 setSelectedOption(this.$('.vjs-fg-color > select'), values.color);
17240 setSelectedOption(this.$('.vjs-text-opacity > select'), values.textOpacity);
17241 setSelectedOption(this.$('.vjs-bg-color > select'), values.backgroundColor);
17242 setSelectedOption(this.$('.vjs-bg-opacity > select'), values.backgroundOpacity);
17243 setSelectedOption(this.$('.window-color > select'), values.windowColor);
17244 setSelectedOption(this.$('.vjs-window-opacity > select'), values.windowOpacity);
17245
17246 var fontPercent = values.fontPercent;
17247
17248 if (fontPercent) {
17249 fontPercent = fontPercent.toFixed(2);
17250 }
17251
17252 setSelectedOption(this.$('.vjs-font-percent > select'), fontPercent);
17253 };
17254
17255 /**
17256 * Restore texttrack settings
17257 *
17258 * @method restoreSettings
17259 */
17260
17261 TextTrackSettings.prototype.restoreSettings = function restoreSettings() {
17262 var err = undefined,
17263 values = undefined;
17264
17265 try {
17266 var _safeParseTuple = _safeJsonParseTuple2['default'](_globalWindow2['default'].localStorage.getItem('vjs-text-track-settings'));
17267
17268 err = _safeParseTuple[0];
17269 values = _safeParseTuple[1];
17270
17271 if (err) {
17272 _utilsLogJs2['default'].error(err);
17273 }
17274 } catch (e) {
17275 _utilsLogJs2['default'].warn(e);
17276 }
17277
17278 if (values) {
17279 this.setValues(values);
17280 }
17281 };
17282
17283 /**
17284 * Save texttrack settings to local storage
17285 *
17286 * @method saveSettings
17287 */
17288
17289 TextTrackSettings.prototype.saveSettings = function saveSettings() {
17290 if (!this.options_.persistTextTrackSettings) {
17291 return;
17292 }
17293
17294 var values = this.getValues();
17295 try {
17296 if (Object.getOwnPropertyNames(values).length > 0) {
17297 _globalWindow2['default'].localStorage.setItem('vjs-text-track-settings', JSON.stringify(values));
17298 } else {
17299 _globalWindow2['default'].localStorage.removeItem('vjs-text-track-settings');
17300 }
17301 } catch (e) {
17302 _utilsLogJs2['default'].warn(e);
17303 }
17304 };
17305
17306 /**
17307 * Update display of texttrack settings
17308 *
17309 * @method updateDisplay
17310 */
17311
17312 TextTrackSettings.prototype.updateDisplay = function updateDisplay() {
17313 var ttDisplay = this.player_.getChild('textTrackDisplay');
17314 if (ttDisplay) {
17315 ttDisplay.updateDisplay();
17316 }
17317 };
17318
17319 return TextTrackSettings;
17320})(_component2['default']);
17321
17322_component2['default'].registerComponent('TextTrackSettings', TextTrackSettings);
17323
17324function getSelectedOptionValue(target) {
17325 var selectedOption = undefined;
17326 // not all browsers support selectedOptions, so, fallback to options
17327 if (target.selectedOptions) {
17328 selectedOption = target.selectedOptions[0];
17329 } else if (target.options) {
17330 selectedOption = target.options[target.options.selectedIndex];
17331 }
17332
17333 return selectedOption.value;
17334}
17335
17336function setSelectedOption(target, value) {
17337 if (!value) {
17338 return;
17339 }
17340
17341 var i = undefined;
17342 for (i = 0; i < target.options.length; i++) {
17343 var option = target.options[i];
17344 if (option.value === value) {
17345 break;
17346 }
17347 }
17348
17349 target.selectedIndex = i;
17350}
17351
17352function captionOptionsMenuTemplate() {
17353 var template = '<div class="vjs-tracksettings">\n <div class="vjs-tracksettings-colors">\n <div class="vjs-fg-color vjs-tracksetting">\n <label class="vjs-label">Foreground</label>\n <select>\n <option value="">---</option>\n <option value="#FFF">White</option>\n <option value="#000">Black</option>\n <option value="#F00">Red</option>\n <option value="#0F0">Green</option>\n <option value="#00F">Blue</option>\n <option value="#FF0">Yellow</option>\n <option value="#F0F">Magenta</option>\n <option value="#0FF">Cyan</option>\n </select>\n <span class="vjs-text-opacity vjs-opacity">\n <select>\n <option value="">---</option>\n <option value="1">Opaque</option>\n <option value="0.5">Semi-Opaque</option>\n </select>\n </span>\n </div> <!-- vjs-fg-color -->\n <div class="vjs-bg-color vjs-tracksetting">\n <label class="vjs-label">Background</label>\n <select>\n <option value="">---</option>\n <option value="#FFF">White</option>\n <option value="#000">Black</option>\n <option value="#F00">Red</option>\n <option value="#0F0">Green</option>\n <option value="#00F">Blue</option>\n <option value="#FF0">Yellow</option>\n <option value="#F0F">Magenta</option>\n <option value="#0FF">Cyan</option>\n </select>\n <span class="vjs-bg-opacity vjs-opacity">\n <select>\n <option value="">---</option>\n <option value="1">Opaque</option>\n <option value="0.5">Semi-Transparent</option>\n <option value="0">Transparent</option>\n </select>\n </span>\n </div> <!-- vjs-bg-color -->\n <div class="window-color vjs-tracksetting">\n <label class="vjs-label">Window</label>\n <select>\n <option value="">---</option>\n <option value="#FFF">White</option>\n <option value="#000">Black</option>\n <option value="#F00">Red</option>\n <option value="#0F0">Green</option>\n <option value="#00F">Blue</option>\n <option value="#FF0">Yellow</option>\n <option value="#F0F">Magenta</option>\n <option value="#0FF">Cyan</option>\n </select>\n <span class="vjs-window-opacity vjs-opacity">\n <select>\n <option value="">---</option>\n <option value="1">Opaque</option>\n <option value="0.5">Semi-Transparent</option>\n <option value="0">Transparent</option>\n </select>\n </span>\n </div> <!-- vjs-window-color -->\n </div> <!-- vjs-tracksettings -->\n <div class="vjs-tracksettings-font">\n <div class="vjs-font-percent vjs-tracksetting">\n <label class="vjs-label">Font Size</label>\n <select>\n <option value="0.50">50%</option>\n <option value="0.75">75%</option>\n <option value="1.00" selected>100%</option>\n <option value="1.25">125%</option>\n <option value="1.50">150%</option>\n <option value="1.75">175%</option>\n <option value="2.00">200%</option>\n <option value="3.00">300%</option>\n <option value="4.00">400%</option>\n </select>\n </div> <!-- vjs-font-percent -->\n <div class="vjs-edge-style vjs-tracksetting">\n <label class="vjs-label">Text Edge Style</label>\n <select>\n <option value="none">None</option>\n <option value="raised">Raised</option>\n <option value="depressed">Depressed</option>\n <option value="uniform">Uniform</option>\n <option value="dropshadow">Dropshadow</option>\n </select>\n </div> <!-- vjs-edge-style -->\n <div class="vjs-font-family vjs-tracksetting">\n <label class="vjs-label">Font Family</label>\n <select>\n <option value="">Default</option>\n <option value="monospaceSerif">Monospace Serif</option>\n <option value="proportionalSerif">Proportional Serif</option>\n <option value="monospaceSansSerif">Monospace Sans-Serif</option>\n <option value="proportionalSansSerif">Proportional Sans-Serif</option>\n <option value="casual">Casual</option>\n <option value="script">Script</option>\n <option value="small-caps">Small Caps</option>\n </select>\n </div> <!-- vjs-font-family -->\n </div>\n </div>\n <div class="vjs-tracksettings-controls">\n <button class="vjs-default-button">Defaults</button>\n <button class="vjs-done-button">Done</button>\n </div>';
17354
17355 return template;
17356}
17357
17358exports['default'] = TextTrackSettings;
17359module.exports = exports['default'];
17360
17361},{"../component":67,"../utils/events.js":133,"../utils/fn.js":134,"../utils/log.js":137,"global/window":2,"safe-json-parse/tuple":54}],128:[function(_dereq_,module,exports){
17362/**
17363 * @file text-track.js
17364 */
17365'use strict';
17366
17367exports.__esModule = true;
17368
17369function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
17370
17371function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17372
17373function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
17374
17375function _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; }
17376
17377var _textTrackCueList = _dereq_('./text-track-cue-list');
17378
17379var _textTrackCueList2 = _interopRequireDefault(_textTrackCueList);
17380
17381var _utilsFnJs = _dereq_('../utils/fn.js');
17382
17383var Fn = _interopRequireWildcard(_utilsFnJs);
17384
17385var _utilsGuidJs = _dereq_('../utils/guid.js');
17386
17387var Guid = _interopRequireWildcard(_utilsGuidJs);
17388
17389var _utilsBrowserJs = _dereq_('../utils/browser.js');
17390
17391var browser = _interopRequireWildcard(_utilsBrowserJs);
17392
17393var _textTrackEnums = _dereq_('./text-track-enums');
17394
17395var TextTrackEnum = _interopRequireWildcard(_textTrackEnums);
17396
17397var _utilsLogJs = _dereq_('../utils/log.js');
17398
17399var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
17400
17401var _eventTarget = _dereq_('../event-target');
17402
17403var _eventTarget2 = _interopRequireDefault(_eventTarget);
17404
17405var _globalDocument = _dereq_('global/document');
17406
17407var _globalDocument2 = _interopRequireDefault(_globalDocument);
17408
17409var _globalWindow = _dereq_('global/window');
17410
17411var _globalWindow2 = _interopRequireDefault(_globalWindow);
17412
17413var _utilsUrlJs = _dereq_('../utils/url.js');
17414
17415var _xhr = _dereq_('xhr');
17416
17417var _xhr2 = _interopRequireDefault(_xhr);
17418
17419/**
17420 * takes a webvtt file contents and parses it into cues
17421 *
17422 * @param {String} srcContent webVTT file contents
17423 * @param {Track} track track to addcues to
17424 */
17425var parseCues = function parseCues(srcContent, track) {
17426 var parser = new _globalWindow2['default'].WebVTT.Parser(_globalWindow2['default'], _globalWindow2['default'].vttjs, _globalWindow2['default'].WebVTT.StringDecoder());
17427
17428 parser.oncue = function (cue) {
17429 track.addCue(cue);
17430 };
17431
17432 parser.onparsingerror = function (error) {
17433 _utilsLogJs2['default'].error(error);
17434 };
17435
17436 parser.onflush = function () {
17437 track.trigger({
17438 type: 'loadeddata',
17439 target: track
17440 });
17441 };
17442
17443 parser.parse(srcContent);
17444 parser.flush();
17445};
17446
17447/**
17448 * load a track from a specifed url
17449 *
17450 * @param {String} src url to load track from
17451 * @param {Track} track track to addcues to
17452 */
17453var loadTrack = function loadTrack(src, track) {
17454 var opts = {
17455 uri: src
17456 };
17457 var crossOrigin = _utilsUrlJs.isCrossOrigin(src);
17458
17459 if (crossOrigin) {
17460 opts.cors = crossOrigin;
17461 }
17462
17463 _xhr2['default'](opts, Fn.bind(this, function (err, response, responseBody) {
17464 if (err) {
17465 return _utilsLogJs2['default'].error(err, response);
17466 }
17467
17468 track.loaded_ = true;
17469
17470 // Make sure that vttjs has loaded, otherwise, wait till it finished loading
17471 // NOTE: this is only used for the alt/video.novtt.js build
17472 if (typeof _globalWindow2['default'].WebVTT !== 'function') {
17473 if (track.tech_) {
17474 (function () {
17475 var loadHandler = function loadHandler() {
17476 return parseCues(responseBody, track);
17477 };
17478 track.tech_.on('vttjsloaded', loadHandler);
17479 track.tech_.on('vttjserror', function () {
17480 _utilsLogJs2['default'].error('vttjs failed to load, stopping trying to process ' + track.src);
17481 track.tech_.off('vttjsloaded', loadHandler);
17482 });
17483 })();
17484 }
17485 } else {
17486 parseCues(responseBody, track);
17487 }
17488 }));
17489};
17490
17491/**
17492 * A single text track as defined in:
17493 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack
17494 *
17495 * interface TextTrack : EventTarget {
17496 * readonly attribute TextTrackKind kind;
17497 * readonly attribute DOMString label;
17498 * readonly attribute DOMString language;
17499 *
17500 * readonly attribute DOMString id;
17501 * readonly attribute DOMString inBandMetadataTrackDispatchType;
17502 *
17503 * attribute TextTrackMode mode;
17504 *
17505 * readonly attribute TextTrackCueList? cues;
17506 * readonly attribute TextTrackCueList? activeCues;
17507 *
17508 * void addCue(TextTrackCue cue);
17509 * void removeCue(TextTrackCue cue);
17510 *
17511 * attribute EventHandler oncuechange;
17512 * };
17513 *
17514 * @param {Object=} options Object of option names and values
17515 * @extends EventTarget
17516 * @class TextTrack
17517 */
17518
17519var TextTrack = (function (_EventTarget) {
17520 _inherits(TextTrack, _EventTarget);
17521
17522 function TextTrack() {
17523 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
17524
17525 _classCallCheck(this, TextTrack);
17526
17527 _EventTarget.call(this);
17528 if (!options.tech) {
17529 throw new Error('A tech was not provided.');
17530 }
17531
17532 var tt = this;
17533
17534 if (browser.IS_IE8) {
17535 tt = _globalDocument2['default'].createElement('custom');
17536
17537 for (var prop in TextTrack.prototype) {
17538 if (prop !== 'constructor') {
17539 tt[prop] = TextTrack.prototype[prop];
17540 }
17541 }
17542 }
17543
17544 tt.tech_ = options.tech;
17545
17546 var mode = TextTrackEnum.TextTrackMode[options.mode] || 'disabled';
17547 var kind = TextTrackEnum.TextTrackKind[options.kind] || 'subtitles';
17548 var label = options.label || '';
17549 var language = options.language || options.srclang || '';
17550 var id = options.id || 'vjs_text_track_' + Guid.newGUID();
17551
17552 if (kind === 'metadata' || kind === 'chapters') {
17553 mode = 'hidden';
17554 }
17555
17556 tt.cues_ = [];
17557 tt.activeCues_ = [];
17558
17559 var cues = new _textTrackCueList2['default'](tt.cues_);
17560 var activeCues = new _textTrackCueList2['default'](tt.activeCues_);
17561 var changed = false;
17562 var timeupdateHandler = Fn.bind(tt, function () {
17563 this.activeCues;
17564 if (changed) {
17565 this.trigger('cuechange');
17566 changed = false;
17567 }
17568 });
17569
17570 if (mode !== 'disabled') {
17571 tt.tech_.on('timeupdate', timeupdateHandler);
17572 }
17573
17574 Object.defineProperty(tt, 'kind', {
17575 get: function get() {
17576 return kind;
17577 },
17578 set: function set() {}
17579 });
17580
17581 Object.defineProperty(tt, 'label', {
17582 get: function get() {
17583 return label;
17584 },
17585 set: function set() {}
17586 });
17587
17588 Object.defineProperty(tt, 'language', {
17589 get: function get() {
17590 return language;
17591 },
17592 set: function set() {}
17593 });
17594
17595 Object.defineProperty(tt, 'id', {
17596 get: function get() {
17597 return id;
17598 },
17599 set: function set() {}
17600 });
17601
17602 Object.defineProperty(tt, 'mode', {
17603 get: function get() {
17604 return mode;
17605 },
17606 set: function set(newMode) {
17607 if (!TextTrackEnum.TextTrackMode[newMode]) {
17608 return;
17609 }
17610 mode = newMode;
17611 if (mode === 'showing') {
17612 this.tech_.on('timeupdate', timeupdateHandler);
17613 }
17614 this.trigger('modechange');
17615 }
17616 });
17617
17618 Object.defineProperty(tt, 'cues', {
17619 get: function get() {
17620 if (!this.loaded_) {
17621 return null;
17622 }
17623
17624 return cues;
17625 },
17626 set: function set() {}
17627 });
17628
17629 Object.defineProperty(tt, 'activeCues', {
17630 get: function get() {
17631 if (!this.loaded_) {
17632 return null;
17633 }
17634
17635 // nothing to do
17636 if (this.cues.length === 0) {
17637 return activeCues;
17638 }
17639
17640 var ct = this.tech_.currentTime();
17641 var active = [];
17642
17643 for (var i = 0, l = this.cues.length; i < l; i++) {
17644 var cue = this.cues[i];
17645
17646 if (cue.startTime <= ct && cue.endTime >= ct) {
17647 active.push(cue);
17648 } else if (cue.startTime === cue.endTime && cue.startTime <= ct && cue.startTime + 0.5 >= ct) {
17649 active.push(cue);
17650 }
17651 }
17652
17653 changed = false;
17654
17655 if (active.length !== this.activeCues_.length) {
17656 changed = true;
17657 } else {
17658 for (var i = 0; i < active.length; i++) {
17659 if (this.activeCues_.indexOf(active[i]) === -1) {
17660 changed = true;
17661 }
17662 }
17663 }
17664
17665 this.activeCues_ = active;
17666 activeCues.setCues_(this.activeCues_);
17667
17668 return activeCues;
17669 },
17670 set: function set() {}
17671 });
17672
17673 if (options.src) {
17674 tt.src = options.src;
17675 loadTrack(options.src, tt);
17676 } else {
17677 tt.loaded_ = true;
17678 }
17679
17680 if (browser.IS_IE8) {
17681 return tt;
17682 }
17683 }
17684
17685 /**
17686 * cuechange - One or more cues in the track have become active or stopped being active.
17687 */
17688
17689 /**
17690 * add a cue to the internal list of cues
17691 *
17692 * @param {Object} cue the cue to add to our internal list
17693 * @method addCue
17694 */
17695
17696 TextTrack.prototype.addCue = function addCue(cue) {
17697 var tracks = this.tech_.textTracks();
17698
17699 if (tracks) {
17700 for (var i = 0; i < tracks.length; i++) {
17701 if (tracks[i] !== this) {
17702 tracks[i].removeCue(cue);
17703 }
17704 }
17705 }
17706
17707 this.cues_.push(cue);
17708 this.cues.setCues_(this.cues_);
17709 };
17710
17711 /**
17712 * remvoe a cue from our internal list
17713 *
17714 * @param {Object} removeCue the cue to remove from our internal list
17715 * @method removeCue
17716 */
17717
17718 TextTrack.prototype.removeCue = function removeCue(_removeCue) {
17719 var removed = false;
17720
17721 for (var i = 0, l = this.cues_.length; i < l; i++) {
17722 var cue = this.cues_[i];
17723
17724 if (cue === _removeCue) {
17725 this.cues_.splice(i, 1);
17726 removed = true;
17727 }
17728 }
17729
17730 if (removed) {
17731 this.cues.setCues_(this.cues_);
17732 }
17733 };
17734
17735 return TextTrack;
17736})(_eventTarget2['default']);
17737
17738TextTrack.prototype.allowedEvents_ = {
17739 cuechange: 'cuechange'
17740};
17741
17742exports['default'] = TextTrack;
17743module.exports = exports['default'];
17744
17745},{"../event-target":99,"../utils/browser.js":129,"../utils/fn.js":134,"../utils/guid.js":136,"../utils/log.js":137,"../utils/url.js":142,"./text-track-cue-list":122,"./text-track-enums":124,"global/document":1,"global/window":2,"xhr":56}],129:[function(_dereq_,module,exports){
17746/**
17747 * @file browser.js
17748 */
17749'use strict';
17750
17751exports.__esModule = true;
17752
17753function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17754
17755var _globalDocument = _dereq_('global/document');
17756
17757var _globalDocument2 = _interopRequireDefault(_globalDocument);
17758
17759var _globalWindow = _dereq_('global/window');
17760
17761var _globalWindow2 = _interopRequireDefault(_globalWindow);
17762
17763var USER_AGENT = _globalWindow2['default'].navigator.userAgent;
17764var webkitVersionMap = /AppleWebKit\/([\d.]+)/i.exec(USER_AGENT);
17765var appleWebkitVersion = webkitVersionMap ? parseFloat(webkitVersionMap.pop()) : null;
17766
17767/*
17768 * Device is an iPhone
17769 *
17770 * @type {Boolean}
17771 * @constant
17772 * @private
17773 */
17774var IS_IPAD = /iPad/i.test(USER_AGENT);
17775
17776exports.IS_IPAD = IS_IPAD;
17777// The Facebook app's UIWebView identifies as both an iPhone and iPad, so
17778// to identify iPhones, we need to exclude iPads.
17779// http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/
17780var IS_IPHONE = /iPhone/i.test(USER_AGENT) && !IS_IPAD;
17781exports.IS_IPHONE = IS_IPHONE;
17782var IS_IPOD = /iPod/i.test(USER_AGENT);
17783exports.IS_IPOD = IS_IPOD;
17784var IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD;
17785
17786exports.IS_IOS = IS_IOS;
17787var IOS_VERSION = (function () {
17788 var match = USER_AGENT.match(/OS (\d+)_/i);
17789 if (match && match[1]) {
17790 return match[1];
17791 }
17792})();
17793
17794exports.IOS_VERSION = IOS_VERSION;
17795var IS_ANDROID = /Android/i.test(USER_AGENT);
17796exports.IS_ANDROID = IS_ANDROID;
17797var ANDROID_VERSION = (function () {
17798 // This matches Android Major.Minor.Patch versions
17799 // ANDROID_VERSION is Major.Minor as a Number, if Minor isn't available, then only Major is returned
17800 var match = USER_AGENT.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i),
17801 major,
17802 minor;
17803
17804 if (!match) {
17805 return null;
17806 }
17807
17808 major = match[1] && parseFloat(match[1]);
17809 minor = match[2] && parseFloat(match[2]);
17810
17811 if (major && minor) {
17812 return parseFloat(match[1] + '.' + match[2]);
17813 } else if (major) {
17814 return major;
17815 } else {
17816 return null;
17817 }
17818})();
17819exports.ANDROID_VERSION = ANDROID_VERSION;
17820// Old Android is defined as Version older than 2.3, and requiring a webkit version of the android browser
17821var IS_OLD_ANDROID = IS_ANDROID && /webkit/i.test(USER_AGENT) && ANDROID_VERSION < 2.3;
17822exports.IS_OLD_ANDROID = IS_OLD_ANDROID;
17823var IS_NATIVE_ANDROID = IS_ANDROID && ANDROID_VERSION < 5 && appleWebkitVersion < 537;
17824
17825exports.IS_NATIVE_ANDROID = IS_NATIVE_ANDROID;
17826var IS_FIREFOX = /Firefox/i.test(USER_AGENT);
17827exports.IS_FIREFOX = IS_FIREFOX;
17828var IS_CHROME = /Chrome/i.test(USER_AGENT);
17829exports.IS_CHROME = IS_CHROME;
17830var IS_IE8 = /MSIE\s8\.0/.test(USER_AGENT);
17831
17832exports.IS_IE8 = IS_IE8;
17833var TOUCH_ENABLED = !!('ontouchstart' in _globalWindow2['default'] || _globalWindow2['default'].DocumentTouch && _globalDocument2['default'] instanceof _globalWindow2['default'].DocumentTouch);
17834exports.TOUCH_ENABLED = TOUCH_ENABLED;
17835var BACKGROUND_SIZE_SUPPORTED = ('backgroundSize' in _globalDocument2['default'].createElement('video').style);
17836exports.BACKGROUND_SIZE_SUPPORTED = BACKGROUND_SIZE_SUPPORTED;
17837
17838},{"global/document":1,"global/window":2}],130:[function(_dereq_,module,exports){
17839/**
17840 * @file buffer.js
17841 */
17842'use strict';
17843
17844exports.__esModule = true;
17845exports.bufferedPercent = bufferedPercent;
17846
17847var _timeRangesJs = _dereq_('./time-ranges.js');
17848
17849/**
17850 * Compute how much your video has been buffered
17851 *
17852 * @param {Object} Buffered object
17853 * @param {Number} Total duration
17854 * @return {Number} Percent buffered of the total duration
17855 * @private
17856 * @function bufferedPercent
17857 */
17858
17859function bufferedPercent(buffered, duration) {
17860 var bufferedDuration = 0,
17861 start,
17862 end;
17863
17864 if (!duration) {
17865 return 0;
17866 }
17867
17868 if (!buffered || !buffered.length) {
17869 buffered = _timeRangesJs.createTimeRange(0, 0);
17870 }
17871
17872 for (var i = 0; i < buffered.length; i++) {
17873 start = buffered.start(i);
17874 end = buffered.end(i);
17875
17876 // buffered end can be bigger than duration by a very small fraction
17877 if (end > duration) {
17878 end = duration;
17879 }
17880
17881 bufferedDuration += end - start;
17882 }
17883
17884 return bufferedDuration / duration;
17885}
17886
17887},{"./time-ranges.js":140}],131:[function(_dereq_,module,exports){
17888'use strict';
17889
17890exports.__esModule = true;
17891
17892function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17893
17894var _logJs = _dereq_('./log.js');
17895
17896var _logJs2 = _interopRequireDefault(_logJs);
17897
17898/**
17899 * Object containing the default behaviors for available handler methods.
17900 *
17901 * @private
17902 * @type {Object}
17903 */
17904var defaultBehaviors = {
17905 get: function get(obj, key) {
17906 return obj[key];
17907 },
17908 set: function set(obj, key, value) {
17909 obj[key] = value;
17910 return true;
17911 }
17912};
17913
17914/**
17915 * Expose private objects publicly using a Proxy to log deprecation warnings.
17916 *
17917 * Browsers that do not support Proxy objects will simply return the `target`
17918 * object, so it can be directly exposed.
17919 *
17920 * @param {Object} target The target object.
17921 * @param {Object} messages Messages to display from a Proxy. Only operations
17922 * with an associated message will be proxied.
17923 * @param {String} [messages.get]
17924 * @param {String} [messages.set]
17925 * @return {Object} A Proxy if supported or the `target` argument.
17926 */
17927
17928exports['default'] = function (target) {
17929 var messages = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
17930
17931 if (typeof Proxy === 'function') {
17932 var _ret = (function () {
17933 var handler = {};
17934
17935 // Build a handler object based on those keys that have both messages
17936 // and default behaviors.
17937 Object.keys(messages).forEach(function (key) {
17938 if (defaultBehaviors.hasOwnProperty(key)) {
17939 handler[key] = function () {
17940 _logJs2['default'].warn(messages[key]);
17941 return defaultBehaviors[key].apply(this, arguments);
17942 };
17943 }
17944 });
17945
17946 return {
17947 v: new Proxy(target, handler)
17948 };
17949 })();
17950
17951 if (typeof _ret === 'object') return _ret.v;
17952 }
17953 return target;
17954};
17955
17956module.exports = exports['default'];
17957
17958},{"./log.js":137}],132:[function(_dereq_,module,exports){
17959/**
17960 * @file dom.js
17961 */
17962'use strict';
17963
17964exports.__esModule = true;
17965exports.getEl = getEl;
17966exports.createEl = createEl;
17967exports.textContent = textContent;
17968exports.insertElFirst = insertElFirst;
17969exports.getElData = getElData;
17970exports.hasElData = hasElData;
17971exports.removeElData = removeElData;
17972exports.hasElClass = hasElClass;
17973exports.addElClass = addElClass;
17974exports.removeElClass = removeElClass;
17975exports.toggleElClass = toggleElClass;
17976exports.setElAttributes = setElAttributes;
17977exports.getElAttributes = getElAttributes;
17978exports.blockTextSelection = blockTextSelection;
17979exports.unblockTextSelection = unblockTextSelection;
17980exports.findElPosition = findElPosition;
17981exports.getPointerPosition = getPointerPosition;
17982exports.isEl = isEl;
17983exports.isTextNode = isTextNode;
17984exports.emptyEl = emptyEl;
17985exports.normalizeContent = normalizeContent;
17986exports.appendContent = appendContent;
17987exports.insertContent = insertContent;
17988
17989var _templateObject = _taggedTemplateLiteralLoose(['Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set ', ' to ', '.'], ['Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set ', ' to ', '.']);
17990
17991function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
17992
17993function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17994
17995function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; }
17996
17997var _globalDocument = _dereq_('global/document');
17998
17999var _globalDocument2 = _interopRequireDefault(_globalDocument);
18000
18001var _globalWindow = _dereq_('global/window');
18002
18003var _globalWindow2 = _interopRequireDefault(_globalWindow);
18004
18005var _guidJs = _dereq_('./guid.js');
18006
18007var Guid = _interopRequireWildcard(_guidJs);
18008
18009var _logJs = _dereq_('./log.js');
18010
18011var _logJs2 = _interopRequireDefault(_logJs);
18012
18013var _tsml = _dereq_('tsml');
18014
18015var _tsml2 = _interopRequireDefault(_tsml);
18016
18017/**
18018 * Detect if a value is a string with any non-whitespace characters.
18019 *
18020 * @param {String} str
18021 * @return {Boolean}
18022 */
18023function isNonBlankString(str) {
18024 return typeof str === 'string' && /\S/.test(str);
18025}
18026
18027/**
18028 * Throws an error if the passed string has whitespace. This is used by
18029 * class methods to be relatively consistent with the classList API.
18030 *
18031 * @param {String} str
18032 * @return {Boolean}
18033 */
18034function throwIfWhitespace(str) {
18035 if (/\s/.test(str)) {
18036 throw new Error('class has illegal whitespace characters');
18037 }
18038}
18039
18040/**
18041 * Produce a regular expression for matching a class name.
18042 *
18043 * @param {String} className
18044 * @return {RegExp}
18045 */
18046function classRegExp(className) {
18047 return new RegExp('(^|\\s)' + className + '($|\\s)');
18048}
18049
18050/**
18051 * Creates functions to query the DOM using a given method.
18052 *
18053 * @function createQuerier
18054 * @private
18055 * @param {String} method
18056 * @return {Function}
18057 */
18058function createQuerier(method) {
18059 return function (selector, context) {
18060 if (!isNonBlankString(selector)) {
18061 return _globalDocument2['default'][method](null);
18062 }
18063 if (isNonBlankString(context)) {
18064 context = _globalDocument2['default'].querySelector(context);
18065 }
18066 return (isEl(context) ? context : _globalDocument2['default'])[method](selector);
18067 };
18068}
18069
18070/**
18071 * Shorthand for document.getElementById()
18072 * Also allows for CSS (jQuery) ID syntax. But nothing other than IDs.
18073 *
18074 * @param {String} id Element ID
18075 * @return {Element} Element with supplied ID
18076 * @function getEl
18077 */
18078
18079function getEl(id) {
18080 if (id.indexOf('#') === 0) {
18081 id = id.slice(1);
18082 }
18083
18084 return _globalDocument2['default'].getElementById(id);
18085}
18086
18087/**
18088 * Creates an element and applies properties.
18089 *
18090 * @param {String} [tagName='div'] Name of tag to be created.
18091 * @param {Object} [properties={}] Element properties to be applied.
18092 * @param {Object} [attributes={}] Element attributes to be applied.
18093 * @return {Element}
18094 * @function createEl
18095 */
18096
18097function createEl() {
18098 var tagName = arguments.length <= 0 || arguments[0] === undefined ? 'div' : arguments[0];
18099 var properties = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
18100 var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
18101
18102 var el = _globalDocument2['default'].createElement(tagName);
18103
18104 Object.getOwnPropertyNames(properties).forEach(function (propName) {
18105 var val = properties[propName];
18106
18107 // See #2176
18108 // We originally were accepting both properties and attributes in the
18109 // same object, but that doesn't work so well.
18110 if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') {
18111 _logJs2['default'].warn(_tsml2['default'](_templateObject, propName, val));
18112 el.setAttribute(propName, val);
18113 } else {
18114 el[propName] = val;
18115 }
18116 });
18117
18118 Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
18119 var val = attributes[attrName];
18120 el.setAttribute(attrName, attributes[attrName]);
18121 });
18122
18123 return el;
18124}
18125
18126/**
18127 * Injects text into an element, replacing any existing contents entirely.
18128 *
18129 * @param {Element} el
18130 * @param {String} text
18131 * @return {Element}
18132 * @function textContent
18133 */
18134
18135function textContent(el, text) {
18136 if (typeof el.textContent === 'undefined') {
18137 el.innerText = text;
18138 } else {
18139 el.textContent = text;
18140 }
18141}
18142
18143/**
18144 * Insert an element as the first child node of another
18145 *
18146 * @param {Element} child Element to insert
18147 * @param {Element} parent Element to insert child into
18148 * @private
18149 * @function insertElFirst
18150 */
18151
18152function insertElFirst(child, parent) {
18153 if (parent.firstChild) {
18154 parent.insertBefore(child, parent.firstChild);
18155 } else {
18156 parent.appendChild(child);
18157 }
18158}
18159
18160/**
18161 * Element Data Store. Allows for binding data to an element without putting it directly on the element.
18162 * Ex. Event listeners are stored here.
18163 * (also from jsninja.com, slightly modified and updated for closure compiler)
18164 *
18165 * @type {Object}
18166 * @private
18167 */
18168var elData = {};
18169
18170/*
18171 * Unique attribute name to store an element's guid in
18172 *
18173 * @type {String}
18174 * @constant
18175 * @private
18176 */
18177var elIdAttr = 'vdata' + new Date().getTime();
18178
18179/**
18180 * Returns the cache object where data for an element is stored
18181 *
18182 * @param {Element} el Element to store data for.
18183 * @return {Object}
18184 * @function getElData
18185 */
18186
18187function getElData(el) {
18188 var id = el[elIdAttr];
18189
18190 if (!id) {
18191 id = el[elIdAttr] = Guid.newGUID();
18192 }
18193
18194 if (!elData[id]) {
18195 elData[id] = {};
18196 }
18197
18198 return elData[id];
18199}
18200
18201/**
18202 * Returns whether or not an element has cached data
18203 *
18204 * @param {Element} el A dom element
18205 * @return {Boolean}
18206 * @private
18207 * @function hasElData
18208 */
18209
18210function hasElData(el) {
18211 var id = el[elIdAttr];
18212
18213 if (!id) {
18214 return false;
18215 }
18216
18217 return !!Object.getOwnPropertyNames(elData[id]).length;
18218}
18219
18220/**
18221 * Delete data for the element from the cache and the guid attr from getElementById
18222 *
18223 * @param {Element} el Remove data for an element
18224 * @private
18225 * @function removeElData
18226 */
18227
18228function removeElData(el) {
18229 var id = el[elIdAttr];
18230
18231 if (!id) {
18232 return;
18233 }
18234
18235 // Remove all stored data
18236 delete elData[id];
18237
18238 // Remove the elIdAttr property from the DOM node
18239 try {
18240 delete el[elIdAttr];
18241 } catch (e) {
18242 if (el.removeAttribute) {
18243 el.removeAttribute(elIdAttr);
18244 } else {
18245 // IE doesn't appear to support removeAttribute on the document element
18246 el[elIdAttr] = null;
18247 }
18248 }
18249}
18250
18251/**
18252 * Check if an element has a CSS class
18253 *
18254 * @function hasElClass
18255 * @param {Element} element Element to check
18256 * @param {String} classToCheck Classname to check
18257 */
18258
18259function hasElClass(element, classToCheck) {
18260 if (element.classList) {
18261 return element.classList.contains(classToCheck);
18262 } else {
18263 throwIfWhitespace(classToCheck);
18264 return classRegExp(classToCheck).test(element.className);
18265 }
18266}
18267
18268/**
18269 * Add a CSS class name to an element
18270 *
18271 * @function addElClass
18272 * @param {Element} element Element to add class name to
18273 * @param {String} classToAdd Classname to add
18274 */
18275
18276function addElClass(element, classToAdd) {
18277 if (element.classList) {
18278 element.classList.add(classToAdd);
18279
18280 // Don't need to `throwIfWhitespace` here because `hasElClass` will do it
18281 // in the case of classList not being supported.
18282 } else if (!hasElClass(element, classToAdd)) {
18283 element.className = (element.className + ' ' + classToAdd).trim();
18284 }
18285
18286 return element;
18287}
18288
18289/**
18290 * Remove a CSS class name from an element
18291 *
18292 * @function removeElClass
18293 * @param {Element} element Element to remove from class name
18294 * @param {String} classToRemove Classname to remove
18295 */
18296
18297function removeElClass(element, classToRemove) {
18298 if (element.classList) {
18299 element.classList.remove(classToRemove);
18300 } else {
18301 throwIfWhitespace(classToRemove);
18302 element.className = element.className.split(/\s+/).filter(function (c) {
18303 return c !== classToRemove;
18304 }).join(' ');
18305 }
18306
18307 return element;
18308}
18309
18310/**
18311 * Adds or removes a CSS class name on an element depending on an optional
18312 * condition or the presence/absence of the class name.
18313 *
18314 * @function toggleElClass
18315 * @param {Element} element
18316 * @param {String} classToToggle
18317 * @param {Boolean|Function} [predicate]
18318 * Can be a function that returns a Boolean. If `true`, the class
18319 * will be added; if `false`, the class will be removed. If not
18320 * given, the class will be added if not present and vice versa.
18321 */
18322
18323function toggleElClass(element, classToToggle, predicate) {
18324
18325 // This CANNOT use `classList` internally because IE does not support the
18326 // second parameter to the `classList.toggle()` method! Which is fine because
18327 // `classList` will be used by the add/remove functions.
18328 var has = hasElClass(element, classToToggle);
18329
18330 if (typeof predicate === 'function') {
18331 predicate = predicate(element, classToToggle);
18332 }
18333
18334 if (typeof predicate !== 'boolean') {
18335 predicate = !has;
18336 }
18337
18338 // If the necessary class operation matches the current state of the
18339 // element, no action is required.
18340 if (predicate === has) {
18341 return;
18342 }
18343
18344 if (predicate) {
18345 addElClass(element, classToToggle);
18346 } else {
18347 removeElClass(element, classToToggle);
18348 }
18349
18350 return element;
18351}
18352
18353/**
18354 * Apply attributes to an HTML element.
18355 *
18356 * @param {Element} el Target element.
18357 * @param {Object=} attributes Element attributes to be applied.
18358 * @private
18359 * @function setElAttributes
18360 */
18361
18362function setElAttributes(el, attributes) {
18363 Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
18364 var attrValue = attributes[attrName];
18365
18366 if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) {
18367 el.removeAttribute(attrName);
18368 } else {
18369 el.setAttribute(attrName, attrValue === true ? '' : attrValue);
18370 }
18371 });
18372}
18373
18374/**
18375 * Get an element's attribute values, as defined on the HTML tag
18376 * Attributes are not the same as properties. They're defined on the tag
18377 * or with setAttribute (which shouldn't be used with HTML)
18378 * This will return true or false for boolean attributes.
18379 *
18380 * @param {Element} tag Element from which to get tag attributes
18381 * @return {Object}
18382 * @private
18383 * @function getElAttributes
18384 */
18385
18386function getElAttributes(tag) {
18387 var obj, knownBooleans, attrs, attrName, attrVal;
18388
18389 obj = {};
18390
18391 // known boolean attributes
18392 // we can check for matching boolean properties, but older browsers
18393 // won't know about HTML5 boolean attributes that we still read from
18394 knownBooleans = ',' + 'autoplay,controls,loop,muted,default' + ',';
18395
18396 if (tag && tag.attributes && tag.attributes.length > 0) {
18397 attrs = tag.attributes;
18398
18399 for (var i = attrs.length - 1; i >= 0; i--) {
18400 attrName = attrs[i].name;
18401 attrVal = attrs[i].value;
18402
18403 // check for known booleans
18404 // the matching element property will return a value for typeof
18405 if (typeof tag[attrName] === 'boolean' || knownBooleans.indexOf(',' + attrName + ',') !== -1) {
18406 // the value of an included boolean attribute is typically an empty
18407 // string ('') which would equal false if we just check for a false value.
18408 // we also don't want support bad code like autoplay='false'
18409 attrVal = attrVal !== null ? true : false;
18410 }
18411
18412 obj[attrName] = attrVal;
18413 }
18414 }
18415
18416 return obj;
18417}
18418
18419/**
18420 * Attempt to block the ability to select text while dragging controls
18421 *
18422 * @return {Boolean}
18423 * @function blockTextSelection
18424 */
18425
18426function blockTextSelection() {
18427 _globalDocument2['default'].body.focus();
18428 _globalDocument2['default'].onselectstart = function () {
18429 return false;
18430 };
18431}
18432
18433/**
18434 * Turn off text selection blocking
18435 *
18436 * @return {Boolean}
18437 * @function unblockTextSelection
18438 */
18439
18440function unblockTextSelection() {
18441 _globalDocument2['default'].onselectstart = function () {
18442 return true;
18443 };
18444}
18445
18446/**
18447 * Offset Left
18448 * getBoundingClientRect technique from
18449 * John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
18450 *
18451 * @function findElPosition
18452 * @param {Element} el Element from which to get offset
18453 * @return {Object}
18454 */
18455
18456function findElPosition(el) {
18457 var box = undefined;
18458
18459 if (el.getBoundingClientRect && el.parentNode) {
18460 box = el.getBoundingClientRect();
18461 }
18462
18463 if (!box) {
18464 return {
18465 left: 0,
18466 top: 0
18467 };
18468 }
18469
18470 var docEl = _globalDocument2['default'].documentElement;
18471 var body = _globalDocument2['default'].body;
18472
18473 var clientLeft = docEl.clientLeft || body.clientLeft || 0;
18474 var scrollLeft = _globalWindow2['default'].pageXOffset || body.scrollLeft;
18475 var left = box.left + scrollLeft - clientLeft;
18476
18477 var clientTop = docEl.clientTop || body.clientTop || 0;
18478 var scrollTop = _globalWindow2['default'].pageYOffset || body.scrollTop;
18479 var top = box.top + scrollTop - clientTop;
18480
18481 // Android sometimes returns slightly off decimal values, so need to round
18482 return {
18483 left: Math.round(left),
18484 top: Math.round(top)
18485 };
18486}
18487
18488/**
18489 * Get pointer position in element
18490 * Returns an object with x and y coordinates.
18491 * The base on the coordinates are the bottom left of the element.
18492 *
18493 * @function getPointerPosition
18494 * @param {Element} el Element on which to get the pointer position on
18495 * @param {Event} event Event object
18496 * @return {Object} This object will have x and y coordinates corresponding to the mouse position
18497 */
18498
18499function getPointerPosition(el, event) {
18500 var position = {};
18501 var box = findElPosition(el);
18502 var boxW = el.offsetWidth;
18503 var boxH = el.offsetHeight;
18504
18505 var boxY = box.top;
18506 var boxX = box.left;
18507 var pageY = event.pageY;
18508 var pageX = event.pageX;
18509
18510 if (event.changedTouches) {
18511 pageX = event.changedTouches[0].pageX;
18512 pageY = event.changedTouches[0].pageY;
18513 }
18514
18515 position.y = Math.max(0, Math.min(1, (boxY - pageY + boxH) / boxH));
18516 position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));
18517
18518 return position;
18519}
18520
18521/**
18522 * Determines, via duck typing, whether or not a value is a DOM element.
18523 *
18524 * @function isEl
18525 * @param {Mixed} value
18526 * @return {Boolean}
18527 */
18528
18529function isEl(value) {
18530 return !!value && typeof value === 'object' && value.nodeType === 1;
18531}
18532
18533/**
18534 * Determines, via duck typing, whether or not a value is a text node.
18535 *
18536 * @param {Mixed} value
18537 * @return {Boolean}
18538 */
18539
18540function isTextNode(value) {
18541 return !!value && typeof value === 'object' && value.nodeType === 3;
18542}
18543
18544/**
18545 * Empties the contents of an element.
18546 *
18547 * @function emptyEl
18548 * @param {Element} el
18549 * @return {Element}
18550 */
18551
18552function emptyEl(el) {
18553 while (el.firstChild) {
18554 el.removeChild(el.firstChild);
18555 }
18556 return el;
18557}
18558
18559/**
18560 * Normalizes content for eventual insertion into the DOM.
18561 *
18562 * This allows a wide range of content definition methods, but protects
18563 * from falling into the trap of simply writing to `innerHTML`, which is
18564 * an XSS concern.
18565 *
18566 * The content for an element can be passed in multiple types and
18567 * combinations, whose behavior is as follows:
18568 *
18569 * - String
18570 * Normalized into a text node.
18571 *
18572 * - Element, TextNode
18573 * Passed through.
18574 *
18575 * - Array
18576 * A one-dimensional array of strings, elements, nodes, or functions (which
18577 * return single strings, elements, or nodes).
18578 *
18579 * - Function
18580 * If the sole argument, is expected to produce a string, element,
18581 * node, or array.
18582 *
18583 * @function normalizeContent
18584 * @param {String|Element|TextNode|Array|Function} content
18585 * @return {Array}
18586 */
18587
18588function normalizeContent(content) {
18589
18590 // First, invoke content if it is a function. If it produces an array,
18591 // that needs to happen before normalization.
18592 if (typeof content === 'function') {
18593 content = content();
18594 }
18595
18596 // Next up, normalize to an array, so one or many items can be normalized,
18597 // filtered, and returned.
18598 return (Array.isArray(content) ? content : [content]).map(function (value) {
18599
18600 // First, invoke value if it is a function to produce a new value,
18601 // which will be subsequently normalized to a Node of some kind.
18602 if (typeof value === 'function') {
18603 value = value();
18604 }
18605
18606 if (isEl(value) || isTextNode(value)) {
18607 return value;
18608 }
18609
18610 if (typeof value === 'string' && /\S/.test(value)) {
18611 return _globalDocument2['default'].createTextNode(value);
18612 }
18613 }).filter(function (value) {
18614 return value;
18615 });
18616}
18617
18618/**
18619 * Normalizes and appends content to an element.
18620 *
18621 * @function appendContent
18622 * @param {Element} el
18623 * @param {String|Element|TextNode|Array|Function} content
18624 * See: `normalizeContent`
18625 * @return {Element}
18626 */
18627
18628function appendContent(el, content) {
18629 normalizeContent(content).forEach(function (node) {
18630 return el.appendChild(node);
18631 });
18632 return el;
18633}
18634
18635/**
18636 * Normalizes and inserts content into an element; this is identical to
18637 * `appendContent()`, except it empties the element first.
18638 *
18639 * @function insertContent
18640 * @param {Element} el
18641 * @param {String|Element|TextNode|Array|Function} content
18642 * See: `normalizeContent`
18643 * @return {Element}
18644 */
18645
18646function insertContent(el, content) {
18647 return appendContent(emptyEl(el), content);
18648}
18649
18650/**
18651 * Finds a single DOM element matching `selector` within the optional
18652 * `context` of another DOM element (defaulting to `document`).
18653 *
18654 * @function $
18655 * @param {String} selector
18656 * A valid CSS selector, which will be passed to `querySelector`.
18657 *
18658 * @param {Element|String} [context=document]
18659 * A DOM element within which to query. Can also be a selector
18660 * string in which case the first matching element will be used
18661 * as context. If missing (or no element matches selector), falls
18662 * back to `document`.
18663 *
18664 * @return {Element|null}
18665 */
18666var $ = createQuerier('querySelector');
18667
18668exports.$ = $;
18669/**
18670 * Finds a all DOM elements matching `selector` within the optional
18671 * `context` of another DOM element (defaulting to `document`).
18672 *
18673 * @function $$
18674 * @param {String} selector
18675 * A valid CSS selector, which will be passed to `querySelectorAll`.
18676 *
18677 * @param {Element|String} [context=document]
18678 * A DOM element within which to query. Can also be a selector
18679 * string in which case the first matching element will be used
18680 * as context. If missing (or no element matches selector), falls
18681 * back to `document`.
18682 *
18683 * @return {NodeList}
18684 */
18685var $$ = createQuerier('querySelectorAll');
18686exports.$$ = $$;
18687
18688},{"./guid.js":136,"./log.js":137,"global/document":1,"global/window":2,"tsml":55}],133:[function(_dereq_,module,exports){
18689/**
18690 * @file events.js
18691 *
18692 * Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/)
18693 * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible)
18694 * This should work very similarly to jQuery's events, however it's based off the book version which isn't as
18695 * robust as jquery's, so there's probably some differences.
18696 */
18697
18698'use strict';
18699
18700exports.__esModule = true;
18701exports.on = on;
18702exports.off = off;
18703exports.trigger = trigger;
18704exports.one = one;
18705exports.fixEvent = fixEvent;
18706
18707function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18708
18709function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
18710
18711var _domJs = _dereq_('./dom.js');
18712
18713var Dom = _interopRequireWildcard(_domJs);
18714
18715var _guidJs = _dereq_('./guid.js');
18716
18717var Guid = _interopRequireWildcard(_guidJs);
18718
18719var _globalWindow = _dereq_('global/window');
18720
18721var _globalWindow2 = _interopRequireDefault(_globalWindow);
18722
18723var _globalDocument = _dereq_('global/document');
18724
18725var _globalDocument2 = _interopRequireDefault(_globalDocument);
18726
18727/**
18728 * Add an event listener to element
18729 * It stores the handler function in a separate cache object
18730 * and adds a generic handler to the element's event,
18731 * along with a unique id (guid) to the element.
18732 *
18733 * @param {Element|Object} elem Element or object to bind listeners to
18734 * @param {String|Array} type Type of event to bind to.
18735 * @param {Function} fn Event listener.
18736 * @method on
18737 */
18738
18739function on(elem, type, fn) {
18740 if (Array.isArray(type)) {
18741 return _handleMultipleEvents(on, elem, type, fn);
18742 }
18743
18744 var data = Dom.getElData(elem);
18745
18746 // We need a place to store all our handler data
18747 if (!data.handlers) data.handlers = {};
18748
18749 if (!data.handlers[type]) data.handlers[type] = [];
18750
18751 if (!fn.guid) fn.guid = Guid.newGUID();
18752
18753 data.handlers[type].push(fn);
18754
18755 if (!data.dispatcher) {
18756 data.disabled = false;
18757
18758 data.dispatcher = function (event, hash) {
18759
18760 if (data.disabled) return;
18761 event = fixEvent(event);
18762
18763 var handlers = data.handlers[event.type];
18764
18765 if (handlers) {
18766 // Copy handlers so if handlers are added/removed during the process it doesn't throw everything off.
18767 var handlersCopy = handlers.slice(0);
18768
18769 for (var m = 0, n = handlersCopy.length; m < n; m++) {
18770 if (event.isImmediatePropagationStopped()) {
18771 break;
18772 } else {
18773 handlersCopy[m].call(elem, event, hash);
18774 }
18775 }
18776 }
18777 };
18778 }
18779
18780 if (data.handlers[type].length === 1) {
18781 if (elem.addEventListener) {
18782 elem.addEventListener(type, data.dispatcher, false);
18783 } else if (elem.attachEvent) {
18784 elem.attachEvent('on' + type, data.dispatcher);
18785 }
18786 }
18787}
18788
18789/**
18790 * Removes event listeners from an element
18791 *
18792 * @param {Element|Object} elem Object to remove listeners from
18793 * @param {String|Array=} type Type of listener to remove. Don't include to remove all events from element.
18794 * @param {Function} fn Specific listener to remove. Don't include to remove listeners for an event type.
18795 * @method off
18796 */
18797
18798function off(elem, type, fn) {
18799 // Don't want to add a cache object through getElData if not needed
18800 if (!Dom.hasElData(elem)) return;
18801
18802 var data = Dom.getElData(elem);
18803
18804 // If no events exist, nothing to unbind
18805 if (!data.handlers) {
18806 return;
18807 }
18808
18809 if (Array.isArray(type)) {
18810 return _handleMultipleEvents(off, elem, type, fn);
18811 }
18812
18813 // Utility function
18814 var removeType = function removeType(t) {
18815 data.handlers[t] = [];
18816 _cleanUpEvents(elem, t);
18817 };
18818
18819 // Are we removing all bound events?
18820 if (!type) {
18821 for (var t in data.handlers) {
18822 removeType(t);
18823 }return;
18824 }
18825
18826 var handlers = data.handlers[type];
18827
18828 // If no handlers exist, nothing to unbind
18829 if (!handlers) return;
18830
18831 // If no listener was provided, remove all listeners for type
18832 if (!fn) {
18833 removeType(type);
18834 return;
18835 }
18836
18837 // We're only removing a single handler
18838 if (fn.guid) {
18839 for (var n = 0; n < handlers.length; n++) {
18840 if (handlers[n].guid === fn.guid) {
18841 handlers.splice(n--, 1);
18842 }
18843 }
18844 }
18845
18846 _cleanUpEvents(elem, type);
18847}
18848
18849/**
18850 * Trigger an event for an element
18851 *
18852 * @param {Element|Object} elem Element to trigger an event on
18853 * @param {Event|Object|String} event A string (the type) or an event object with a type attribute
18854 * @param {Object} [hash] data hash to pass along with the event
18855 * @return {Boolean=} Returned only if default was prevented
18856 * @method trigger
18857 */
18858
18859function trigger(elem, event, hash) {
18860 // Fetches element data and a reference to the parent (for bubbling).
18861 // Don't want to add a data object to cache for every parent,
18862 // so checking hasElData first.
18863 var elemData = Dom.hasElData(elem) ? Dom.getElData(elem) : {};
18864 var parent = elem.parentNode || elem.ownerDocument;
18865 // type = event.type || event,
18866 // handler;
18867
18868 // If an event name was passed as a string, creates an event out of it
18869 if (typeof event === 'string') {
18870 event = { type: event, target: elem };
18871 }
18872 // Normalizes the event properties.
18873 event = fixEvent(event);
18874
18875 // If the passed element has a dispatcher, executes the established handlers.
18876 if (elemData.dispatcher) {
18877 elemData.dispatcher.call(elem, event, hash);
18878 }
18879
18880 // Unless explicitly stopped or the event does not bubble (e.g. media events)
18881 // recursively calls this function to bubble the event up the DOM.
18882 if (parent && !event.isPropagationStopped() && event.bubbles === true) {
18883 trigger.call(null, parent, event, hash);
18884
18885 // If at the top of the DOM, triggers the default action unless disabled.
18886 } else if (!parent && !event.defaultPrevented) {
18887 var targetData = Dom.getElData(event.target);
18888
18889 // Checks if the target has a default action for this event.
18890 if (event.target[event.type]) {
18891 // Temporarily disables event dispatching on the target as we have already executed the handler.
18892 targetData.disabled = true;
18893 // Executes the default action.
18894 if (typeof event.target[event.type] === 'function') {
18895 event.target[event.type]();
18896 }
18897 // Re-enables event dispatching.
18898 targetData.disabled = false;
18899 }
18900 }
18901
18902 // Inform the triggerer if the default was prevented by returning false
18903 return !event.defaultPrevented;
18904}
18905
18906/**
18907 * Trigger a listener only once for an event
18908 *
18909 * @param {Element|Object} elem Element or object to
18910 * @param {String|Array} type Name/type of event
18911 * @param {Function} fn Event handler function
18912 * @method one
18913 */
18914
18915function one(elem, type, fn) {
18916 if (Array.isArray(type)) {
18917 return _handleMultipleEvents(one, elem, type, fn);
18918 }
18919 var func = function func() {
18920 off(elem, type, func);
18921 fn.apply(this, arguments);
18922 };
18923 // copy the guid to the new function so it can removed using the original function's ID
18924 func.guid = fn.guid = fn.guid || Guid.newGUID();
18925 on(elem, type, func);
18926}
18927
18928/**
18929 * Fix a native event to have standard property values
18930 *
18931 * @param {Object} event Event object to fix
18932 * @return {Object}
18933 * @private
18934 * @method fixEvent
18935 */
18936
18937function fixEvent(event) {
18938
18939 function returnTrue() {
18940 return true;
18941 }
18942 function returnFalse() {
18943 return false;
18944 }
18945
18946 // Test if fixing up is needed
18947 // Used to check if !event.stopPropagation instead of isPropagationStopped
18948 // But native events return true for stopPropagation, but don't have
18949 // other expected methods like isPropagationStopped. Seems to be a problem
18950 // with the Javascript Ninja code. So we're just overriding all events now.
18951 if (!event || !event.isPropagationStopped) {
18952 var old = event || _globalWindow2['default'].event;
18953
18954 event = {};
18955 // Clone the old object so that we can modify the values event = {};
18956 // IE8 Doesn't like when you mess with native event properties
18957 // Firefox returns false for event.hasOwnProperty('type') and other props
18958 // which makes copying more difficult.
18959 // TODO: Probably best to create a whitelist of event props
18960 for (var key in old) {
18961 // Safari 6.0.3 warns you if you try to copy deprecated layerX/Y
18962 // Chrome warns you if you try to copy deprecated keyboardEvent.keyLocation
18963 // and webkitMovementX/Y
18964 if (key !== 'layerX' && key !== 'layerY' && key !== 'keyLocation' && key !== 'webkitMovementX' && key !== 'webkitMovementY') {
18965 // Chrome 32+ warns if you try to copy deprecated returnValue, but
18966 // we still want to if preventDefault isn't supported (IE8).
18967 if (!(key === 'returnValue' && old.preventDefault)) {
18968 event[key] = old[key];
18969 }
18970 }
18971 }
18972
18973 // The event occurred on this element
18974 if (!event.target) {
18975 event.target = event.srcElement || _globalDocument2['default'];
18976 }
18977
18978 // Handle which other element the event is related to
18979 if (!event.relatedTarget) {
18980 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
18981 }
18982
18983 // Stop the default browser action
18984 event.preventDefault = function () {
18985 if (old.preventDefault) {
18986 old.preventDefault();
18987 }
18988 event.returnValue = false;
18989 old.returnValue = false;
18990 event.defaultPrevented = true;
18991 };
18992
18993 event.defaultPrevented = false;
18994
18995 // Stop the event from bubbling
18996 event.stopPropagation = function () {
18997 if (old.stopPropagation) {
18998 old.stopPropagation();
18999 }
19000 event.cancelBubble = true;
19001 old.cancelBubble = true;
19002 event.isPropagationStopped = returnTrue;
19003 };
19004
19005 event.isPropagationStopped = returnFalse;
19006
19007 // Stop the event from bubbling and executing other handlers
19008 event.stopImmediatePropagation = function () {
19009 if (old.stopImmediatePropagation) {
19010 old.stopImmediatePropagation();
19011 }
19012 event.isImmediatePropagationStopped = returnTrue;
19013 event.stopPropagation();
19014 };
19015
19016 event.isImmediatePropagationStopped = returnFalse;
19017
19018 // Handle mouse position
19019 if (event.clientX != null) {
19020 var doc = _globalDocument2['default'].documentElement,
19021 body = _globalDocument2['default'].body;
19022
19023 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
19024 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
19025 }
19026
19027 // Handle key presses
19028 event.which = event.charCode || event.keyCode;
19029
19030 // Fix button for mouse clicks:
19031 // 0 == left; 1 == middle; 2 == right
19032 if (event.button != null) {
19033 event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0;
19034 }
19035 }
19036
19037 // Returns fixed-up instance
19038 return event;
19039}
19040
19041/**
19042 * Clean up the listener cache and dispatchers
19043*
19044 * @param {Element|Object} elem Element to clean up
19045 * @param {String} type Type of event to clean up
19046 * @private
19047 * @method _cleanUpEvents
19048 */
19049function _cleanUpEvents(elem, type) {
19050 var data = Dom.getElData(elem);
19051
19052 // Remove the events of a particular type if there are none left
19053 if (data.handlers[type].length === 0) {
19054 delete data.handlers[type];
19055 // data.handlers[type] = null;
19056 // Setting to null was causing an error with data.handlers
19057
19058 // Remove the meta-handler from the element
19059 if (elem.removeEventListener) {
19060 elem.removeEventListener(type, data.dispatcher, false);
19061 } else if (elem.detachEvent) {
19062 elem.detachEvent('on' + type, data.dispatcher);
19063 }
19064 }
19065
19066 // Remove the events object if there are no types left
19067 if (Object.getOwnPropertyNames(data.handlers).length <= 0) {
19068 delete data.handlers;
19069 delete data.dispatcher;
19070 delete data.disabled;
19071 }
19072
19073 // Finally remove the element data if there is no data left
19074 if (Object.getOwnPropertyNames(data).length === 0) {
19075 Dom.removeElData(elem);
19076 }
19077}
19078
19079/**
19080 * Loops through an array of event types and calls the requested method for each type.
19081 *
19082 * @param {Function} fn The event method we want to use.
19083 * @param {Element|Object} elem Element or object to bind listeners to
19084 * @param {String} type Type of event to bind to.
19085 * @param {Function} callback Event listener.
19086 * @private
19087 * @function _handleMultipleEvents
19088 */
19089function _handleMultipleEvents(fn, elem, types, callback) {
19090 types.forEach(function (type) {
19091 //Call the event method for each one of the types
19092 fn(elem, type, callback);
19093 });
19094}
19095
19096},{"./dom.js":132,"./guid.js":136,"global/document":1,"global/window":2}],134:[function(_dereq_,module,exports){
19097/**
19098 * @file fn.js
19099 */
19100'use strict';
19101
19102exports.__esModule = true;
19103
19104var _guidJs = _dereq_('./guid.js');
19105
19106/**
19107 * Bind (a.k.a proxy or Context). A simple method for changing the context of a function
19108 * It also stores a unique id on the function so it can be easily removed from events
19109 *
19110 * @param {*} context The object to bind as scope
19111 * @param {Function} fn The function to be bound to a scope
19112 * @param {Number=} uid An optional unique ID for the function to be set
19113 * @return {Function}
19114 * @private
19115 * @method bind
19116 */
19117var bind = function bind(context, fn, uid) {
19118 // Make sure the function has a unique ID
19119 if (!fn.guid) {
19120 fn.guid = _guidJs.newGUID();
19121 }
19122
19123 // Create the new function that changes the context
19124 var ret = function ret() {
19125 return fn.apply(context, arguments);
19126 };
19127
19128 // Allow for the ability to individualize this function
19129 // Needed in the case where multiple objects might share the same prototype
19130 // IF both items add an event listener with the same function, then you try to remove just one
19131 // it will remove both because they both have the same guid.
19132 // when using this, you need to use the bind method when you remove the listener as well.
19133 // currently used in text tracks
19134 ret.guid = uid ? uid + '_' + fn.guid : fn.guid;
19135
19136 return ret;
19137};
19138exports.bind = bind;
19139
19140},{"./guid.js":136}],135:[function(_dereq_,module,exports){
19141/**
19142 * @file format-time.js
19143 *
19144 * Format seconds as a time string, H:MM:SS or M:SS
19145 * Supplying a guide (in seconds) will force a number of leading zeros
19146 * to cover the length of the guide
19147 *
19148 * @param {Number} seconds Number of seconds to be turned into a string
19149 * @param {Number} guide Number (in seconds) to model the string after
19150 * @return {String} Time formatted as H:MM:SS or M:SS
19151 * @private
19152 * @function formatTime
19153 */
19154'use strict';
19155
19156exports.__esModule = true;
19157function formatTime(seconds) {
19158 var guide = arguments.length <= 1 || arguments[1] === undefined ? seconds : arguments[1];
19159 return (function () {
19160 seconds = seconds < 0 ? 0 : seconds;
19161 var s = Math.floor(seconds % 60);
19162 var m = Math.floor(seconds / 60 % 60);
19163 var h = Math.floor(seconds / 3600);
19164 var gm = Math.floor(guide / 60 % 60);
19165 var gh = Math.floor(guide / 3600);
19166
19167 // handle invalid times
19168 if (isNaN(seconds) || seconds === Infinity) {
19169 // '-' is false for all relational operators (e.g. <, >=) so this setting
19170 // will add the minimum number of fields specified by the guide
19171 h = m = s = '-';
19172 }
19173
19174 // Check if we need to show hours
19175 h = h > 0 || gh > 0 ? h + ':' : '';
19176
19177 // If hours are showing, we may need to add a leading zero.
19178 // Always show at least one digit of minutes.
19179 m = ((h || gm >= 10) && m < 10 ? '0' + m : m) + ':';
19180
19181 // Check if leading zero is need for seconds
19182 s = s < 10 ? '0' + s : s;
19183
19184 return h + m + s;
19185 })();
19186}
19187
19188exports['default'] = formatTime;
19189module.exports = exports['default'];
19190
19191},{}],136:[function(_dereq_,module,exports){
19192/**
19193 * @file guid.js
19194 *
19195 * Unique ID for an element or function
19196 * @type {Number}
19197 * @private
19198 */
19199"use strict";
19200
19201exports.__esModule = true;
19202exports.newGUID = newGUID;
19203var _guid = 1;
19204
19205/**
19206 * Get the next unique ID
19207 *
19208 * @return {String}
19209 * @function newGUID
19210 */
19211
19212function newGUID() {
19213 return _guid++;
19214}
19215
19216},{}],137:[function(_dereq_,module,exports){
19217/**
19218 * @file log.js
19219 */
19220'use strict';
19221
19222exports.__esModule = true;
19223
19224function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19225
19226var _globalWindow = _dereq_('global/window');
19227
19228var _globalWindow2 = _interopRequireDefault(_globalWindow);
19229
19230/**
19231 * Log plain debug messages
19232 */
19233var log = function log() {
19234 _logType(null, arguments);
19235};
19236
19237/**
19238 * Keep a history of log messages
19239 * @type {Array}
19240 */
19241log.history = [];
19242
19243/**
19244 * Log error messages
19245 */
19246log.error = function () {
19247 _logType('error', arguments);
19248};
19249
19250/**
19251 * Log warning messages
19252 */
19253log.warn = function () {
19254 _logType('warn', arguments);
19255};
19256
19257/**
19258 * Log messages to the console and history based on the type of message
19259 *
19260 * @param {String} type The type of message, or `null` for `log`
19261 * @param {Object} args The args to be passed to the log
19262 * @private
19263 * @method _logType
19264 */
19265function _logType(type, args) {
19266 // convert args to an array to get array functions
19267 var argsArray = Array.prototype.slice.call(args);
19268 // if there's no console then don't try to output messages
19269 // they will still be stored in log.history
19270 // Was setting these once outside of this function, but containing them
19271 // in the function makes it easier to test cases where console doesn't exist
19272 var noop = function noop() {};
19273
19274 var console = _globalWindow2['default']['console'] || {
19275 'log': noop,
19276 'warn': noop,
19277 'error': noop
19278 };
19279
19280 if (type) {
19281 // add the type to the front of the message
19282 argsArray.unshift(type.toUpperCase() + ':');
19283 } else {
19284 // default to log with no prefix
19285 type = 'log';
19286 }
19287
19288 // add to history
19289 log.history.push(argsArray);
19290
19291 // add console prefix after adding to history
19292 argsArray.unshift('VIDEOJS:');
19293
19294 // call appropriate log function
19295 if (console[type].apply) {
19296 console[type].apply(console, argsArray);
19297 } else {
19298 // ie8 doesn't allow error.apply, but it will just join() the array anyway
19299 console[type](argsArray.join(' '));
19300 }
19301}
19302
19303exports['default'] = log;
19304module.exports = exports['default'];
19305
19306},{"global/window":2}],138:[function(_dereq_,module,exports){
19307/**
19308 * @file merge-options.js
19309 */
19310'use strict';
19311
19312exports.__esModule = true;
19313exports['default'] = mergeOptions;
19314
19315function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19316
19317var _lodashCompatObjectMerge = _dereq_('lodash-compat/object/merge');
19318
19319var _lodashCompatObjectMerge2 = _interopRequireDefault(_lodashCompatObjectMerge);
19320
19321function isPlain(obj) {
19322 return !!obj && typeof obj === 'object' && obj.toString() === '[object Object]' && obj.constructor === Object;
19323}
19324
19325/**
19326 * Merge customizer. video.js simply overwrites non-simple objects
19327 * (like arrays) instead of attempting to overlay them.
19328 * @see https://lodash.com/docs#merge
19329 */
19330var customizer = function customizer(destination, source) {
19331 // If we're not working with a plain object, copy the value as is
19332 // If source is an array, for instance, it will replace destination
19333 if (!isPlain(source)) {
19334 return source;
19335 }
19336
19337 // If the new value is a plain object but the first object value is not
19338 // we need to create a new object for the first object to merge with.
19339 // This makes it consistent with how merge() works by default
19340 // and also protects from later changes the to first object affecting
19341 // the second object's values.
19342 if (!isPlain(destination)) {
19343 return mergeOptions(source);
19344 }
19345};
19346
19347/**
19348 * Merge one or more options objects, recursively merging **only**
19349 * plain object properties. Previously `deepMerge`.
19350 *
19351 * @param {...Object} source One or more objects to merge
19352 * @returns {Object} a new object that is the union of all
19353 * provided objects
19354 * @function mergeOptions
19355 */
19356
19357function mergeOptions() {
19358 // contruct the call dynamically to handle the variable number of
19359 // objects to merge
19360 var args = Array.prototype.slice.call(arguments);
19361
19362 // unshift an empty object into the front of the call as the target
19363 // of the merge
19364 args.unshift({});
19365
19366 // customize conflict resolution to match our historical merge behavior
19367 args.push(customizer);
19368
19369 _lodashCompatObjectMerge2['default'].apply(null, args);
19370
19371 // return the mutated result object
19372 return args[0];
19373}
19374
19375module.exports = exports['default'];
19376
19377},{"lodash-compat/object/merge":40}],139:[function(_dereq_,module,exports){
19378'use strict';
19379
19380exports.__esModule = true;
19381
19382function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19383
19384var _globalDocument = _dereq_('global/document');
19385
19386var _globalDocument2 = _interopRequireDefault(_globalDocument);
19387
19388var createStyleElement = function createStyleElement(className) {
19389 var style = _globalDocument2['default'].createElement('style');
19390 style.className = className;
19391
19392 return style;
19393};
19394
19395exports.createStyleElement = createStyleElement;
19396var setTextContent = function setTextContent(el, content) {
19397 if (el.styleSheet) {
19398 el.styleSheet.cssText = content;
19399 } else {
19400 el.textContent = content;
19401 }
19402};
19403exports.setTextContent = setTextContent;
19404
19405},{"global/document":1}],140:[function(_dereq_,module,exports){
19406'use strict';
19407
19408exports.__esModule = true;
19409exports.createTimeRanges = createTimeRanges;
19410
19411function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19412
19413var _logJs = _dereq_('./log.js');
19414
19415var _logJs2 = _interopRequireDefault(_logJs);
19416
19417/**
19418 * @file time-ranges.js
19419 *
19420 * Should create a fake TimeRange object
19421 * Mimics an HTML5 time range instance, which has functions that
19422 * return the start and end times for a range
19423 * TimeRanges are returned by the buffered() method
19424 *
19425 * @param {(Number|Array)} Start of a single range or an array of ranges
19426 * @param {Number} End of a single range
19427 * @private
19428 * @method createTimeRanges
19429 */
19430
19431function createTimeRanges(start, end) {
19432 if (Array.isArray(start)) {
19433 return createTimeRangesObj(start);
19434 } else if (start === undefined || end === undefined) {
19435 return createTimeRangesObj();
19436 }
19437 return createTimeRangesObj([[start, end]]);
19438}
19439
19440exports.createTimeRange = createTimeRanges;
19441
19442function createTimeRangesObj(ranges) {
19443 if (ranges === undefined || ranges.length === 0) {
19444 return {
19445 length: 0,
19446 start: function start() {
19447 throw new Error('This TimeRanges object is empty');
19448 },
19449 end: function end() {
19450 throw new Error('This TimeRanges object is empty');
19451 }
19452 };
19453 }
19454 return {
19455 length: ranges.length,
19456 start: getRange.bind(null, 'start', 0, ranges),
19457 end: getRange.bind(null, 'end', 1, ranges)
19458 };
19459}
19460
19461function getRange(fnName, valueIndex, ranges, rangeIndex) {
19462 if (rangeIndex === undefined) {
19463 _logJs2['default'].warn('DEPRECATED: Function \'' + fnName + '\' on \'TimeRanges\' called without an index argument.');
19464 rangeIndex = 0;
19465 }
19466 rangeCheck(fnName, rangeIndex, ranges.length - 1);
19467 return ranges[rangeIndex][valueIndex];
19468}
19469
19470function rangeCheck(fnName, index, maxIndex) {
19471 if (index < 0 || index > maxIndex) {
19472 throw new Error('Failed to execute \'' + fnName + '\' on \'TimeRanges\': The index provided (' + index + ') is greater than or equal to the maximum bound (' + maxIndex + ').');
19473 }
19474}
19475
19476},{"./log.js":137}],141:[function(_dereq_,module,exports){
19477/**
19478 * @file to-title-case.js
19479 *
19480 * Uppercase the first letter of a string
19481 *
19482 * @param {String} string String to be uppercased
19483 * @return {String}
19484 * @private
19485 * @method toTitleCase
19486 */
19487"use strict";
19488
19489exports.__esModule = true;
19490function toTitleCase(string) {
19491 return string.charAt(0).toUpperCase() + string.slice(1);
19492}
19493
19494exports["default"] = toTitleCase;
19495module.exports = exports["default"];
19496
19497},{}],142:[function(_dereq_,module,exports){
19498/**
19499 * @file url.js
19500 */
19501'use strict';
19502
19503exports.__esModule = true;
19504
19505function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19506
19507var _globalDocument = _dereq_('global/document');
19508
19509var _globalDocument2 = _interopRequireDefault(_globalDocument);
19510
19511var _globalWindow = _dereq_('global/window');
19512
19513var _globalWindow2 = _interopRequireDefault(_globalWindow);
19514
19515/**
19516 * Resolve and parse the elements of a URL
19517 *
19518 * @param {String} url The url to parse
19519 * @return {Object} An object of url details
19520 * @method parseUrl
19521 */
19522var parseUrl = function parseUrl(url) {
19523 var props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host'];
19524
19525 // add the url to an anchor and let the browser parse the URL
19526 var a = _globalDocument2['default'].createElement('a');
19527 a.href = url;
19528
19529 // IE8 (and 9?) Fix
19530 // ie8 doesn't parse the URL correctly until the anchor is actually
19531 // added to the body, and an innerHTML is needed to trigger the parsing
19532 var addToBody = a.host === '' && a.protocol !== 'file:';
19533 var div = undefined;
19534 if (addToBody) {
19535 div = _globalDocument2['default'].createElement('div');
19536 div.innerHTML = '<a href="' + url + '"></a>';
19537 a = div.firstChild;
19538 // prevent the div from affecting layout
19539 div.setAttribute('style', 'display:none; position:absolute;');
19540 _globalDocument2['default'].body.appendChild(div);
19541 }
19542
19543 // Copy the specific URL properties to a new object
19544 // This is also needed for IE8 because the anchor loses its
19545 // properties when it's removed from the dom
19546 var details = {};
19547 for (var i = 0; i < props.length; i++) {
19548 details[props[i]] = a[props[i]];
19549 }
19550
19551 // IE9 adds the port to the host property unlike everyone else. If
19552 // a port identifier is added for standard ports, strip it.
19553 if (details.protocol === 'http:') {
19554 details.host = details.host.replace(/:80$/, '');
19555 }
19556 if (details.protocol === 'https:') {
19557 details.host = details.host.replace(/:443$/, '');
19558 }
19559
19560 if (addToBody) {
19561 _globalDocument2['default'].body.removeChild(div);
19562 }
19563
19564 return details;
19565};
19566
19567exports.parseUrl = parseUrl;
19568/**
19569 * Get absolute version of relative URL. Used to tell flash correct URL.
19570 * http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
19571 *
19572 * @param {String} url URL to make absolute
19573 * @return {String} Absolute URL
19574 * @private
19575 * @method getAbsoluteURL
19576 */
19577var getAbsoluteURL = function getAbsoluteURL(url) {
19578 // Check if absolute URL
19579 if (!url.match(/^https?:\/\//)) {
19580 // Convert to absolute URL. Flash hosted off-site needs an absolute URL.
19581 var div = _globalDocument2['default'].createElement('div');
19582 div.innerHTML = '<a href="' + url + '">x</a>';
19583 url = div.firstChild.href;
19584 }
19585
19586 return url;
19587};
19588
19589exports.getAbsoluteURL = getAbsoluteURL;
19590/**
19591 * Returns the extension of the passed file name. It will return an empty string if you pass an invalid path
19592 *
19593 * @param {String} path The fileName path like '/path/to/file.mp4'
19594 * @returns {String} The extension in lower case or an empty string if no extension could be found.
19595 * @method getFileExtension
19596 */
19597var getFileExtension = function getFileExtension(path) {
19598 if (typeof path === 'string') {
19599 var splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i;
19600 var pathParts = splitPathRe.exec(path);
19601
19602 if (pathParts) {
19603 return pathParts.pop().toLowerCase();
19604 }
19605 }
19606
19607 return '';
19608};
19609
19610exports.getFileExtension = getFileExtension;
19611/**
19612 * Returns whether the url passed is a cross domain request or not.
19613 *
19614 * @param {String} url The url to check
19615 * @return {Boolean} Whether it is a cross domain request or not
19616 * @method isCrossOrigin
19617 */
19618var isCrossOrigin = function isCrossOrigin(url) {
19619 var winLoc = _globalWindow2['default'].location;
19620 var urlInfo = parseUrl(url);
19621
19622 // IE8 protocol relative urls will return ':' for protocol
19623 var srcProtocol = urlInfo.protocol === ':' ? winLoc.protocol : urlInfo.protocol;
19624
19625 // Check if url is for another domain/origin
19626 // IE8 doesn't know location.origin, so we won't rely on it here
19627 var crossOrigin = srcProtocol + urlInfo.host !== winLoc.protocol + winLoc.host;
19628
19629 return crossOrigin;
19630};
19631exports.isCrossOrigin = isCrossOrigin;
19632
19633},{"global/document":1,"global/window":2}],143:[function(_dereq_,module,exports){
19634/**
19635 * @file video.js
19636 */
19637'use strict';
19638
19639exports.__esModule = true;
19640
19641function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
19642
19643function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19644
19645var _globalDocument = _dereq_('global/document');
19646
19647var _globalDocument2 = _interopRequireDefault(_globalDocument);
19648
19649var _setup = _dereq_('./setup');
19650
19651var setup = _interopRequireWildcard(_setup);
19652
19653var _utilsStylesheetJs = _dereq_('./utils/stylesheet.js');
19654
19655var stylesheet = _interopRequireWildcard(_utilsStylesheetJs);
19656
19657var _component = _dereq_('./component');
19658
19659var _component2 = _interopRequireDefault(_component);
19660
19661var _eventTarget = _dereq_('./event-target');
19662
19663var _eventTarget2 = _interopRequireDefault(_eventTarget);
19664
19665var _utilsEventsJs = _dereq_('./utils/events.js');
19666
19667var Events = _interopRequireWildcard(_utilsEventsJs);
19668
19669var _player = _dereq_('./player');
19670
19671var _player2 = _interopRequireDefault(_player);
19672
19673var _pluginsJs = _dereq_('./plugins.js');
19674
19675var _pluginsJs2 = _interopRequireDefault(_pluginsJs);
19676
19677var _srcJsUtilsMergeOptionsJs = _dereq_('../../src/js/utils/merge-options.js');
19678
19679var _srcJsUtilsMergeOptionsJs2 = _interopRequireDefault(_srcJsUtilsMergeOptionsJs);
19680
19681var _utilsFnJs = _dereq_('./utils/fn.js');
19682
19683var Fn = _interopRequireWildcard(_utilsFnJs);
19684
19685var _tracksTextTrackJs = _dereq_('./tracks/text-track.js');
19686
19687var _tracksTextTrackJs2 = _interopRequireDefault(_tracksTextTrackJs);
19688
19689var _objectAssign = _dereq_('object.assign');
19690
19691var _objectAssign2 = _interopRequireDefault(_objectAssign);
19692
19693var _utilsTimeRangesJs = _dereq_('./utils/time-ranges.js');
19694
19695var _utilsFormatTimeJs = _dereq_('./utils/format-time.js');
19696
19697var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs);
19698
19699var _utilsLogJs = _dereq_('./utils/log.js');
19700
19701var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs);
19702
19703var _utilsDomJs = _dereq_('./utils/dom.js');
19704
19705var Dom = _interopRequireWildcard(_utilsDomJs);
19706
19707var _utilsBrowserJs = _dereq_('./utils/browser.js');
19708
19709var browser = _interopRequireWildcard(_utilsBrowserJs);
19710
19711var _utilsUrlJs = _dereq_('./utils/url.js');
19712
19713var Url = _interopRequireWildcard(_utilsUrlJs);
19714
19715var _extendJs = _dereq_('./extend.js');
19716
19717var _extendJs2 = _interopRequireDefault(_extendJs);
19718
19719var _lodashCompatObjectMerge = _dereq_('lodash-compat/object/merge');
19720
19721var _lodashCompatObjectMerge2 = _interopRequireDefault(_lodashCompatObjectMerge);
19722
19723var _utilsCreateDeprecationProxyJs = _dereq_('./utils/create-deprecation-proxy.js');
19724
19725var _utilsCreateDeprecationProxyJs2 = _interopRequireDefault(_utilsCreateDeprecationProxyJs);
19726
19727var _xhr = _dereq_('xhr');
19728
19729var _xhr2 = _interopRequireDefault(_xhr);
19730
19731// Include the built-in techs
19732
19733var _techTechJs = _dereq_('./tech/tech.js');
19734
19735var _techTechJs2 = _interopRequireDefault(_techTechJs);
19736
19737var _techHtml5Js = _dereq_('./tech/html5.js');
19738
19739var _techHtml5Js2 = _interopRequireDefault(_techHtml5Js);
19740
19741var _techFlashJs = _dereq_('./tech/flash.js');
19742
19743var _techFlashJs2 = _interopRequireDefault(_techFlashJs);
19744
19745// HTML5 Element Shim for IE8
19746if (typeof HTMLVideoElement === 'undefined') {
19747 _globalDocument2['default'].createElement('video');
19748 _globalDocument2['default'].createElement('audio');
19749 _globalDocument2['default'].createElement('track');
19750}
19751
19752/**
19753 * Doubles as the main function for users to create a player instance and also
19754 * the main library object.
19755 * The `videojs` function can be used to initialize or retrieve a player.
19756 * ```js
19757 * var myPlayer = videojs('my_video_id');
19758 * ```
19759 *
19760 * @param {String|Element} id Video element or video element ID
19761 * @param {Object=} options Optional options object for config/settings
19762 * @param {Function=} ready Optional ready callback
19763 * @return {Player} A player instance
19764 * @mixes videojs
19765 * @method videojs
19766 */
19767var videojs = function videojs(id, options, ready) {
19768 var tag = undefined; // Element of ID
19769
19770 // Allow for element or ID to be passed in
19771 // String ID
19772 if (typeof id === 'string') {
19773
19774 // Adjust for jQuery ID syntax
19775 if (id.indexOf('#') === 0) {
19776 id = id.slice(1);
19777 }
19778
19779 // If a player instance has already been created for this ID return it.
19780 if (videojs.getPlayers()[id]) {
19781
19782 // If options or ready funtion are passed, warn
19783 if (options) {
19784 _utilsLogJs2['default'].warn('Player "' + id + '" is already initialised. Options will not be applied.');
19785 }
19786
19787 if (ready) {
19788 videojs.getPlayers()[id].ready(ready);
19789 }
19790
19791 return videojs.getPlayers()[id];
19792
19793 // Otherwise get element for ID
19794 } else {
19795 tag = Dom.getEl(id);
19796 }
19797
19798 // ID is a media element
19799 } else {
19800 tag = id;
19801 }
19802
19803 // Check for a useable element
19804 if (!tag || !tag.nodeName) {
19805 // re: nodeName, could be a box div also
19806 throw new TypeError('The element or ID supplied is not valid. (videojs)'); // Returns
19807 }
19808
19809 // Element may have a player attr referring to an already created player instance.
19810 // If not, set up a new player and return the instance.
19811 return tag['player'] || _player2['default'].players[tag.playerId] || new _player2['default'](tag, options, ready);
19812};
19813
19814// Add default styles
19815var style = Dom.$('.vjs-styles-defaults');
19816if (!style) {
19817 style = stylesheet.createStyleElement('vjs-styles-defaults');
19818 var head = Dom.$('head');
19819 head.insertBefore(style, head.firstChild);
19820 stylesheet.setTextContent(style, '\n .video-js {\n width: 300px;\n height: 150px;\n }\n\n .vjs-fluid {\n padding-top: 56.25%\n }\n ');
19821}
19822
19823// Run Auto-load players
19824// You have to wait at least once in case this script is loaded after your video in the DOM (weird behavior only with minified version)
19825setup.autoSetupTimeout(1, videojs);
19826
19827/*
19828 * Current software version (semver)
19829 *
19830 * @type {String}
19831 */
19832videojs.VERSION = '5.8.8';
19833
19834/**
19835 * The global options object. These are the settings that take effect
19836 * if no overrides are specified when the player is created.
19837 *
19838 * ```js
19839 * videojs.options.autoplay = true
19840 * // -> all players will autoplay by default
19841 * ```
19842 *
19843 * @type {Object}
19844 */
19845videojs.options = _player2['default'].prototype.options_;
19846
19847/**
19848 * Get an object with the currently created players, keyed by player ID
19849 *
19850 * @return {Object} The created players
19851 * @mixes videojs
19852 * @method getPlayers
19853 */
19854videojs.getPlayers = function () {
19855 return _player2['default'].players;
19856};
19857
19858/**
19859 * For backward compatibility, expose players object.
19860 *
19861 * @deprecated
19862 * @memberOf videojs
19863 * @property {Object|Proxy} players
19864 */
19865videojs.players = _utilsCreateDeprecationProxyJs2['default'](_player2['default'].players, {
19866 get: 'Access to videojs.players is deprecated; use videojs.getPlayers instead',
19867 set: 'Modification of videojs.players is deprecated'
19868});
19869
19870/**
19871 * Get a component class object by name
19872 * ```js
19873 * var VjsButton = videojs.getComponent('Button');
19874 * // Create a new instance of the component
19875 * var myButton = new VjsButton(myPlayer);
19876 * ```
19877 *
19878 * @return {Component} Component identified by name
19879 * @mixes videojs
19880 * @method getComponent
19881 */
19882videojs.getComponent = _component2['default'].getComponent;
19883
19884/**
19885 * Register a component so it can referred to by name
19886 * Used when adding to other
19887 * components, either through addChild
19888 * `component.addChild('myComponent')`
19889 * or through default children options
19890 * `{ children: ['myComponent'] }`.
19891 * ```js
19892 * // Get a component to subclass
19893 * var VjsButton = videojs.getComponent('Button');
19894 * // Subclass the component (see 'extend' doc for more info)
19895 * var MySpecialButton = videojs.extend(VjsButton, {});
19896 * // Register the new component
19897 * VjsButton.registerComponent('MySepcialButton', MySepcialButton);
19898 * // (optionally) add the new component as a default player child
19899 * myPlayer.addChild('MySepcialButton');
19900 * ```
19901 * NOTE: You could also just initialize the component before adding.
19902 * `component.addChild(new MyComponent());`
19903 *
19904 * @param {String} The class name of the component
19905 * @param {Component} The component class
19906 * @return {Component} The newly registered component
19907 * @mixes videojs
19908 * @method registerComponent
19909 */
19910videojs.registerComponent = function (name, comp) {
19911 if (_techTechJs2['default'].isTech(comp)) {
19912 _utilsLogJs2['default'].warn('The ' + name + ' tech was registered as a component. It should instead be registered using videojs.registerTech(name, tech)');
19913 }
19914
19915 _component2['default'].registerComponent.call(_component2['default'], name, comp);
19916};
19917
19918/**
19919 * Get a Tech class object by name
19920 * ```js
19921 * var Html5 = videojs.getTech('Html5');
19922 * // Create a new instance of the component
19923 * var html5 = new Html5(options);
19924 * ```
19925 *
19926 * @return {Tech} Tech identified by name
19927 * @mixes videojs
19928 * @method getComponent
19929 */
19930videojs.getTech = _techTechJs2['default'].getTech;
19931
19932/**
19933 * Register a Tech so it can referred to by name.
19934 * This is used in the tech order for the player.
19935 *
19936 * ```js
19937 * // get the Html5 Tech
19938 * var Html5 = videojs.getTech('Html5');
19939 * var MyTech = videojs.extend(Html5, {});
19940 * // Register the new Tech
19941 * VjsButton.registerTech('Tech', MyTech);
19942 * var player = videojs('myplayer', {
19943 * techOrder: ['myTech', 'html5']
19944 * });
19945 * ```
19946 *
19947 * @param {String} The class name of the tech
19948 * @param {Tech} The tech class
19949 * @return {Tech} The newly registered Tech
19950 * @mixes videojs
19951 * @method registerTech
19952 */
19953videojs.registerTech = _techTechJs2['default'].registerTech;
19954
19955/**
19956 * A suite of browser and device tests
19957 *
19958 * @type {Object}
19959 * @private
19960 */
19961videojs.browser = browser;
19962
19963/**
19964 * Whether or not the browser supports touch events. Included for backward
19965 * compatibility with 4.x, but deprecated. Use `videojs.browser.TOUCH_ENABLED`
19966 * instead going forward.
19967 *
19968 * @deprecated
19969 * @type {Boolean}
19970 */
19971videojs.TOUCH_ENABLED = browser.TOUCH_ENABLED;
19972
19973/**
19974 * Subclass an existing class
19975 * Mimics ES6 subclassing with the `extend` keyword
19976 * ```js
19977 * // Create a basic javascript 'class'
19978 * function MyClass(name){
19979 * // Set a property at initialization
19980 * this.myName = name;
19981 * }
19982 * // Create an instance method
19983 * MyClass.prototype.sayMyName = function(){
19984 * alert(this.myName);
19985 * };
19986 * // Subclass the exisitng class and change the name
19987 * // when initializing
19988 * var MySubClass = videojs.extend(MyClass, {
19989 * constructor: function(name) {
19990 * // Call the super class constructor for the subclass
19991 * MyClass.call(this, name)
19992 * }
19993 * });
19994 * // Create an instance of the new sub class
19995 * var myInstance = new MySubClass('John');
19996 * myInstance.sayMyName(); // -> should alert "John"
19997 * ```
19998 *
19999 * @param {Function} The Class to subclass
20000 * @param {Object} An object including instace methods for the new class
20001 * Optionally including a `constructor` function
20002 * @return {Function} The newly created subclass
20003 * @mixes videojs
20004 * @method extend
20005 */
20006videojs.extend = _extendJs2['default'];
20007
20008/**
20009 * Merge two options objects recursively
20010 * Performs a deep merge like lodash.merge but **only merges plain objects**
20011 * (not arrays, elements, anything else)
20012 * Other values will be copied directly from the second object.
20013 * ```js
20014 * var defaultOptions = {
20015 * foo: true,
20016 * bar: {
20017 * a: true,
20018 * b: [1,2,3]
20019 * }
20020 * };
20021 * var newOptions = {
20022 * foo: false,
20023 * bar: {
20024 * b: [4,5,6]
20025 * }
20026 * };
20027 * var result = videojs.mergeOptions(defaultOptions, newOptions);
20028 * // result.foo = false;
20029 * // result.bar.a = true;
20030 * // result.bar.b = [4,5,6];
20031 * ```
20032 *
20033 * @param {Object} defaults The options object whose values will be overriden
20034 * @param {Object} overrides The options object with values to override the first
20035 * @param {Object} etc Any number of additional options objects
20036 *
20037 * @return {Object} a new object with the merged values
20038 * @mixes videojs
20039 * @method mergeOptions
20040 */
20041videojs.mergeOptions = _srcJsUtilsMergeOptionsJs2['default'];
20042
20043/**
20044 * Change the context (this) of a function
20045 *
20046 * videojs.bind(newContext, function(){
20047 * this === newContext
20048 * });
20049 *
20050 * NOTE: as of v5.0 we require an ES5 shim, so you should use the native
20051 * `function(){}.bind(newContext);` instead of this.
20052 *
20053 * @param {*} context The object to bind as scope
20054 * @param {Function} fn The function to be bound to a scope
20055 * @param {Number=} uid An optional unique ID for the function to be set
20056 * @return {Function}
20057 */
20058videojs.bind = Fn.bind;
20059
20060/**
20061 * Create a Video.js player plugin
20062 * Plugins are only initialized when options for the plugin are included
20063 * in the player options, or the plugin function on the player instance is
20064 * called.
20065 * **See the plugin guide in the docs for a more detailed example**
20066 * ```js
20067 * // Make a plugin that alerts when the player plays
20068 * videojs.plugin('myPlugin', function(myPluginOptions) {
20069 * myPluginOptions = myPluginOptions || {};
20070 *
20071 * var player = this;
20072 * var alertText = myPluginOptions.text || 'Player is playing!'
20073 *
20074 * player.on('play', function(){
20075 * alert(alertText);
20076 * });
20077 * });
20078 * // USAGE EXAMPLES
20079 * // EXAMPLE 1: New player with plugin options, call plugin immediately
20080 * var player1 = videojs('idOne', {
20081 * myPlugin: {
20082 * text: 'Custom text!'
20083 * }
20084 * });
20085 * // Click play
20086 * // --> Should alert 'Custom text!'
20087 * // EXAMPLE 3: New player, initialize plugin later
20088 * var player3 = videojs('idThree');
20089 * // Click play
20090 * // --> NO ALERT
20091 * // Click pause
20092 * // Initialize plugin using the plugin function on the player instance
20093 * player3.myPlugin({
20094 * text: 'Plugin added later!'
20095 * });
20096 * // Click play
20097 * // --> Should alert 'Plugin added later!'
20098 * ```
20099 *
20100 * @param {String} name The plugin name
20101 * @param {Function} fn The plugin function that will be called with options
20102 * @mixes videojs
20103 * @method plugin
20104 */
20105videojs.plugin = _pluginsJs2['default'];
20106
20107/**
20108 * Adding languages so that they're available to all players.
20109 * ```js
20110 * videojs.addLanguage('es', { 'Hello': 'Hola' });
20111 * ```
20112 *
20113 * @param {String} code The language code or dictionary property
20114 * @param {Object} data The data values to be translated
20115 * @return {Object} The resulting language dictionary object
20116 * @mixes videojs
20117 * @method addLanguage
20118 */
20119videojs.addLanguage = function (code, data) {
20120 var _merge;
20121
20122 code = ('' + code).toLowerCase();
20123 return _lodashCompatObjectMerge2['default'](videojs.options.languages, (_merge = {}, _merge[code] = data, _merge))[code];
20124};
20125
20126/**
20127 * Log debug messages.
20128 *
20129 * @param {...Object} messages One or more messages to log
20130 */
20131videojs.log = _utilsLogJs2['default'];
20132
20133/**
20134 * Creates an emulated TimeRange object.
20135 *
20136 * @param {Number|Array} start Start time in seconds or an array of ranges
20137 * @param {Number} end End time in seconds
20138 * @return {Object} Fake TimeRange object
20139 * @method createTimeRange
20140 */
20141videojs.createTimeRange = videojs.createTimeRanges = _utilsTimeRangesJs.createTimeRanges;
20142
20143/**
20144 * Format seconds as a time string, H:MM:SS or M:SS
20145 * Supplying a guide (in seconds) will force a number of leading zeros
20146 * to cover the length of the guide
20147 *
20148 * @param {Number} seconds Number of seconds to be turned into a string
20149 * @param {Number} guide Number (in seconds) to model the string after
20150 * @return {String} Time formatted as H:MM:SS or M:SS
20151 * @method formatTime
20152 */
20153videojs.formatTime = _utilsFormatTimeJs2['default'];
20154
20155/**
20156 * Resolve and parse the elements of a URL
20157 *
20158 * @param {String} url The url to parse
20159 * @return {Object} An object of url details
20160 * @method parseUrl
20161 */
20162videojs.parseUrl = Url.parseUrl;
20163
20164/**
20165 * Returns whether the url passed is a cross domain request or not.
20166 *
20167 * @param {String} url The url to check
20168 * @return {Boolean} Whether it is a cross domain request or not
20169 * @method isCrossOrigin
20170 */
20171videojs.isCrossOrigin = Url.isCrossOrigin;
20172
20173/**
20174 * Event target class.
20175 *
20176 * @type {Function}
20177 */
20178videojs.EventTarget = _eventTarget2['default'];
20179
20180/**
20181 * Add an event listener to element
20182 * It stores the handler function in a separate cache object
20183 * and adds a generic handler to the element's event,
20184 * along with a unique id (guid) to the element.
20185 *
20186 * @param {Element|Object} elem Element or object to bind listeners to
20187 * @param {String|Array} type Type of event to bind to.
20188 * @param {Function} fn Event listener.
20189 * @method on
20190 */
20191videojs.on = Events.on;
20192
20193/**
20194 * Trigger a listener only once for an event
20195 *
20196 * @param {Element|Object} elem Element or object to
20197 * @param {String|Array} type Name/type of event
20198 * @param {Function} fn Event handler function
20199 * @method one
20200 */
20201videojs.one = Events.one;
20202
20203/**
20204 * Removes event listeners from an element
20205 *
20206 * @param {Element|Object} elem Object to remove listeners from
20207 * @param {String|Array=} type Type of listener to remove. Don't include to remove all events from element.
20208 * @param {Function} fn Specific listener to remove. Don't include to remove listeners for an event type.
20209 * @method off
20210 */
20211videojs.off = Events.off;
20212
20213/**
20214 * Trigger an event for an element
20215 *
20216 * @param {Element|Object} elem Element to trigger an event on
20217 * @param {Event|Object|String} event A string (the type) or an event object with a type attribute
20218 * @param {Object} [hash] data hash to pass along with the event
20219 * @return {Boolean=} Returned only if default was prevented
20220 * @method trigger
20221 */
20222videojs.trigger = Events.trigger;
20223
20224/**
20225 * A cross-browser XMLHttpRequest wrapper. Here's a simple example:
20226 *
20227 * videojs.xhr({
20228 * body: someJSONString,
20229 * uri: "/foo",
20230 * headers: {
20231 * "Content-Type": "application/json"
20232 * }
20233 * }, function (err, resp, body) {
20234 * // check resp.statusCode
20235 * });
20236 *
20237 * Check out the [full
20238 * documentation](https://github.com/Raynos/xhr/blob/v2.1.0/README.md)
20239 * for more options.
20240 *
20241 * @param {Object} options settings for the request.
20242 * @return {XMLHttpRequest|XDomainRequest} the request object.
20243 * @see https://github.com/Raynos/xhr
20244 */
20245videojs.xhr = _xhr2['default'];
20246
20247/**
20248 * TextTrack class
20249 *
20250 * @type {Function}
20251 */
20252videojs.TextTrack = _tracksTextTrackJs2['default'];
20253
20254/**
20255 * Determines, via duck typing, whether or not a value is a DOM element.
20256 *
20257 * @method isEl
20258 * @param {Mixed} value
20259 * @return {Boolean}
20260 */
20261videojs.isEl = Dom.isEl;
20262
20263/**
20264 * Determines, via duck typing, whether or not a value is a text node.
20265 *
20266 * @method isTextNode
20267 * @param {Mixed} value
20268 * @return {Boolean}
20269 */
20270videojs.isTextNode = Dom.isTextNode;
20271
20272/**
20273 * Creates an element and applies properties.
20274 *
20275 * @method createEl
20276 * @param {String} [tagName='div'] Name of tag to be created.
20277 * @param {Object} [properties={}] Element properties to be applied.
20278 * @param {Object} [attributes={}] Element attributes to be applied.
20279 * @return {Element}
20280 */
20281videojs.createEl = Dom.createEl;
20282
20283/**
20284 * Check if an element has a CSS class
20285 *
20286 * @method hasClass
20287 * @param {Element} element Element to check
20288 * @param {String} classToCheck Classname to check
20289 */
20290videojs.hasClass = Dom.hasElClass;
20291
20292/**
20293 * Add a CSS class name to an element
20294 *
20295 * @method addClass
20296 * @param {Element} element Element to add class name to
20297 * @param {String} classToAdd Classname to add
20298 */
20299videojs.addClass = Dom.addElClass;
20300
20301/**
20302 * Remove a CSS class name from an element
20303 *
20304 * @method removeClass
20305 * @param {Element} element Element to remove from class name
20306 * @param {String} classToRemove Classname to remove
20307 */
20308videojs.removeClass = Dom.removeElClass;
20309
20310/**
20311 * Adds or removes a CSS class name on an element depending on an optional
20312 * condition or the presence/absence of the class name.
20313 *
20314 * @method toggleElClass
20315 * @param {Element} element
20316 * @param {String} classToToggle
20317 * @param {Boolean|Function} [predicate]
20318 * Can be a function that returns a Boolean. If `true`, the class
20319 * will be added; if `false`, the class will be removed. If not
20320 * given, the class will be added if not present and vice versa.
20321 */
20322videojs.toggleClass = Dom.toggleElClass;
20323
20324/**
20325 * Apply attributes to an HTML element.
20326 *
20327 * @method setAttributes
20328 * @param {Element} el Target element.
20329 * @param {Object=} attributes Element attributes to be applied.
20330 */
20331videojs.setAttributes = Dom.setElAttributes;
20332
20333/**
20334 * Get an element's attribute values, as defined on the HTML tag
20335 * Attributes are not the same as properties. They're defined on the tag
20336 * or with setAttribute (which shouldn't be used with HTML)
20337 * This will return true or false for boolean attributes.
20338 *
20339 * @method getAttributes
20340 * @param {Element} tag Element from which to get tag attributes
20341 * @return {Object}
20342 */
20343videojs.getAttributes = Dom.getElAttributes;
20344
20345/**
20346 * Empties the contents of an element.
20347 *
20348 * @method emptyEl
20349 * @param {Element} el
20350 * @return {Element}
20351 */
20352videojs.emptyEl = Dom.emptyEl;
20353
20354/**
20355 * Normalizes and appends content to an element.
20356 *
20357 * The content for an element can be passed in multiple types and
20358 * combinations, whose behavior is as follows:
20359 *
20360 * - String
20361 * Normalized into a text node.
20362 *
20363 * - Element, TextNode
20364 * Passed through.
20365 *
20366 * - Array
20367 * A one-dimensional array of strings, elements, nodes, or functions (which
20368 * return single strings, elements, or nodes).
20369 *
20370 * - Function
20371 * If the sole argument, is expected to produce a string, element,
20372 * node, or array.
20373 *
20374 * @method appendContent
20375 * @param {Element} el
20376 * @param {String|Element|TextNode|Array|Function} content
20377 * @return {Element}
20378 */
20379videojs.appendContent = Dom.appendContent;
20380
20381/**
20382 * Normalizes and inserts content into an element; this is identical to
20383 * `appendContent()`, except it empties the element first.
20384 *
20385 * The content for an element can be passed in multiple types and
20386 * combinations, whose behavior is as follows:
20387 *
20388 * - String
20389 * Normalized into a text node.
20390 *
20391 * - Element, TextNode
20392 * Passed through.
20393 *
20394 * - Array
20395 * A one-dimensional array of strings, elements, nodes, or functions (which
20396 * return single strings, elements, or nodes).
20397 *
20398 * - Function
20399 * If the sole argument, is expected to produce a string, element,
20400 * node, or array.
20401 *
20402 * @method insertContent
20403 * @param {Element} el
20404 * @param {String|Element|TextNode|Array|Function} content
20405 * @return {Element}
20406 */
20407videojs.insertContent = Dom.insertContent;
20408
20409/*
20410 * Custom Universal Module Definition (UMD)
20411 *
20412 * Video.js will never be a non-browser lib so we can simplify UMD a bunch and
20413 * still support requirejs and browserify. This also needs to be closure
20414 * compiler compatible, so string keys are used.
20415 */
20416if (typeof define === 'function' && define['amd']) {
20417 define('videojs', [], function () {
20418 return videojs;
20419 });
20420
20421 // checking that module is an object too because of umdjs/umd#35
20422} else if (typeof exports === 'object' && typeof module === 'object') {
20423 module['exports'] = videojs;
20424 }
20425
20426exports['default'] = videojs;
20427module.exports = exports['default'];
20428
20429},{"../../src/js/utils/merge-options.js":138,"./component":67,"./event-target":99,"./extend.js":100,"./player":108,"./plugins.js":109,"./setup":113,"./tech/flash.js":116,"./tech/html5.js":117,"./tech/tech.js":119,"./tracks/text-track.js":128,"./utils/browser.js":129,"./utils/create-deprecation-proxy.js":131,"./utils/dom.js":132,"./utils/events.js":133,"./utils/fn.js":134,"./utils/format-time.js":135,"./utils/log.js":137,"./utils/stylesheet.js":139,"./utils/time-ranges.js":140,"./utils/url.js":142,"global/document":1,"lodash-compat/object/merge":40,"object.assign":45,"xhr":56}]},{},[143])(143)
20430});
20431
20432
20433//# sourceMappingURL=video.js.map
20434/* vtt.js - v0.12.1 (https://github.com/mozilla/vtt.js) built on 08-07-2015 */
20435
20436(function(root) {
20437 var vttjs = root.vttjs = {};
20438 var cueShim = vttjs.VTTCue;
20439 var regionShim = vttjs.VTTRegion;
20440 var oldVTTCue = root.VTTCue;
20441 var oldVTTRegion = root.VTTRegion;
20442
20443 vttjs.shim = function() {
20444 vttjs.VTTCue = cueShim;
20445 vttjs.VTTRegion = regionShim;
20446 };
20447
20448 vttjs.restore = function() {
20449 vttjs.VTTCue = oldVTTCue;
20450 vttjs.VTTRegion = oldVTTRegion;
20451 };
20452}(this));
20453
20454/**
20455 * Copyright 2013 vtt.js Contributors
20456 *
20457 * Licensed under the Apache License, Version 2.0 (the "License");
20458 * you may not use this file except in compliance with the License.
20459 * You may obtain a copy of the License at
20460 *
20461 * http://www.apache.org/licenses/LICENSE-2.0
20462 *
20463 * Unless required by applicable law or agreed to in writing, software
20464 * distributed under the License is distributed on an "AS IS" BASIS,
20465 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20466 * See the License for the specific language governing permissions and
20467 * limitations under the License.
20468 */
20469
20470(function(root, vttjs) {
20471
20472 var autoKeyword = "auto";
20473 var directionSetting = {
20474 "": true,
20475 "lr": true,
20476 "rl": true
20477 };
20478 var alignSetting = {
20479 "start": true,
20480 "middle": true,
20481 "end": true,
20482 "left": true,
20483 "right": true
20484 };
20485
20486 function findDirectionSetting(value) {
20487 if (typeof value !== "string") {
20488 return false;
20489 }
20490 var dir = directionSetting[value.toLowerCase()];
20491 return dir ? value.toLowerCase() : false;
20492 }
20493
20494 function findAlignSetting(value) {
20495 if (typeof value !== "string") {
20496 return false;
20497 }
20498 var align = alignSetting[value.toLowerCase()];
20499 return align ? value.toLowerCase() : false;
20500 }
20501
20502 function extend(obj) {
20503 var i = 1;
20504 for (; i < arguments.length; i++) {
20505 var cobj = arguments[i];
20506 for (var p in cobj) {
20507 obj[p] = cobj[p];
20508 }
20509 }
20510
20511 return obj;
20512 }
20513
20514 function VTTCue(startTime, endTime, text) {
20515 var cue = this;
20516 var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
20517 var baseObj = {};
20518
20519 if (isIE8) {
20520 cue = document.createElement('custom');
20521 } else {
20522 baseObj.enumerable = true;
20523 }
20524
20525 /**
20526 * Shim implementation specific properties. These properties are not in
20527 * the spec.
20528 */
20529
20530 // Lets us know when the VTTCue's data has changed in such a way that we need
20531 // to recompute its display state. This lets us compute its display state
20532 // lazily.
20533 cue.hasBeenReset = false;
20534
20535 /**
20536 * VTTCue and TextTrackCue properties
20537 * http://dev.w3.org/html5/webvtt/#vttcue-interface
20538 */
20539
20540 var _id = "";
20541 var _pauseOnExit = false;
20542 var _startTime = startTime;
20543 var _endTime = endTime;
20544 var _text = text;
20545 var _region = null;
20546 var _vertical = "";
20547 var _snapToLines = true;
20548 var _line = "auto";
20549 var _lineAlign = "start";
20550 var _position = 50;
20551 var _positionAlign = "middle";
20552 var _size = 50;
20553 var _align = "middle";
20554
20555 Object.defineProperty(cue,
20556 "id", extend({}, baseObj, {
20557 get: function() {
20558 return _id;
20559 },
20560 set: function(value) {
20561 _id = "" + value;
20562 }
20563 }));
20564
20565 Object.defineProperty(cue,
20566 "pauseOnExit", extend({}, baseObj, {
20567 get: function() {
20568 return _pauseOnExit;
20569 },
20570 set: function(value) {
20571 _pauseOnExit = !!value;
20572 }
20573 }));
20574
20575 Object.defineProperty(cue,
20576 "startTime", extend({}, baseObj, {
20577 get: function() {
20578 return _startTime;
20579 },
20580 set: function(value) {
20581 if (typeof value !== "number") {
20582 throw new TypeError("Start time must be set to a number.");
20583 }
20584 _startTime = value;
20585 this.hasBeenReset = true;
20586 }
20587 }));
20588
20589 Object.defineProperty(cue,
20590 "endTime", extend({}, baseObj, {
20591 get: function() {
20592 return _endTime;
20593 },
20594 set: function(value) {
20595 if (typeof value !== "number") {
20596 throw new TypeError("End time must be set to a number.");
20597 }
20598 _endTime = value;
20599 this.hasBeenReset = true;
20600 }
20601 }));
20602
20603 Object.defineProperty(cue,
20604 "text", extend({}, baseObj, {
20605 get: function() {
20606 return _text;
20607 },
20608 set: function(value) {
20609 _text = "" + value;
20610 this.hasBeenReset = true;
20611 }
20612 }));
20613
20614 Object.defineProperty(cue,
20615 "region", extend({}, baseObj, {
20616 get: function() {
20617 return _region;
20618 },
20619 set: function(value) {
20620 _region = value;
20621 this.hasBeenReset = true;
20622 }
20623 }));
20624
20625 Object.defineProperty(cue,
20626 "vertical", extend({}, baseObj, {
20627 get: function() {
20628 return _vertical;
20629 },
20630 set: function(value) {
20631 var setting = findDirectionSetting(value);
20632 // Have to check for false because the setting an be an empty string.
20633 if (setting === false) {
20634 throw new SyntaxError("An invalid or illegal string was specified.");
20635 }
20636 _vertical = setting;
20637 this.hasBeenReset = true;
20638 }
20639 }));
20640
20641 Object.defineProperty(cue,
20642 "snapToLines", extend({}, baseObj, {
20643 get: function() {
20644 return _snapToLines;
20645 },
20646 set: function(value) {
20647 _snapToLines = !!value;
20648 this.hasBeenReset = true;
20649 }
20650 }));
20651
20652 Object.defineProperty(cue,
20653 "line", extend({}, baseObj, {
20654 get: function() {
20655 return _line;
20656 },
20657 set: function(value) {
20658 if (typeof value !== "number" && value !== autoKeyword) {
20659 throw new SyntaxError("An invalid number or illegal string was specified.");
20660 }
20661 _line = value;
20662 this.hasBeenReset = true;
20663 }
20664 }));
20665
20666 Object.defineProperty(cue,
20667 "lineAlign", extend({}, baseObj, {
20668 get: function() {
20669 return _lineAlign;
20670 },
20671 set: function(value) {
20672 var setting = findAlignSetting(value);
20673 if (!setting) {
20674 throw new SyntaxError("An invalid or illegal string was specified.");
20675 }
20676 _lineAlign = setting;
20677 this.hasBeenReset = true;
20678 }
20679 }));
20680
20681 Object.defineProperty(cue,
20682 "position", extend({}, baseObj, {
20683 get: function() {
20684 return _position;
20685 },
20686 set: function(value) {
20687 if (value < 0 || value > 100) {
20688 throw new Error("Position must be between 0 and 100.");
20689 }
20690 _position = value;
20691 this.hasBeenReset = true;
20692 }
20693 }));
20694
20695 Object.defineProperty(cue,
20696 "positionAlign", extend({}, baseObj, {
20697 get: function() {
20698 return _positionAlign;
20699 },
20700 set: function(value) {
20701 var setting = findAlignSetting(value);
20702 if (!setting) {
20703 throw new SyntaxError("An invalid or illegal string was specified.");
20704 }
20705 _positionAlign = setting;
20706 this.hasBeenReset = true;
20707 }
20708 }));
20709
20710 Object.defineProperty(cue,
20711 "size", extend({}, baseObj, {
20712 get: function() {
20713 return _size;
20714 },
20715 set: function(value) {
20716 if (value < 0 || value > 100) {
20717 throw new Error("Size must be between 0 and 100.");
20718 }
20719 _size = value;
20720 this.hasBeenReset = true;
20721 }
20722 }));
20723
20724 Object.defineProperty(cue,
20725 "align", extend({}, baseObj, {
20726 get: function() {
20727 return _align;
20728 },
20729 set: function(value) {
20730 var setting = findAlignSetting(value);
20731 if (!setting) {
20732 throw new SyntaxError("An invalid or illegal string was specified.");
20733 }
20734 _align = setting;
20735 this.hasBeenReset = true;
20736 }
20737 }));
20738
20739 /**
20740 * Other <track> spec defined properties
20741 */
20742
20743 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state
20744 cue.displayState = undefined;
20745
20746 if (isIE8) {
20747 return cue;
20748 }
20749 }
20750
20751 /**
20752 * VTTCue methods
20753 */
20754
20755 VTTCue.prototype.getCueAsHTML = function() {
20756 // Assume WebVTT.convertCueToDOMTree is on the global.
20757 return WebVTT.convertCueToDOMTree(window, this.text);
20758 };
20759
20760 root.VTTCue = root.VTTCue || VTTCue;
20761 vttjs.VTTCue = VTTCue;
20762}(this, (this.vttjs || {})));
20763
20764/**
20765 * Copyright 2013 vtt.js Contributors
20766 *
20767 * Licensed under the Apache License, Version 2.0 (the "License");
20768 * you may not use this file except in compliance with the License.
20769 * You may obtain a copy of the License at
20770 *
20771 * http://www.apache.org/licenses/LICENSE-2.0
20772 *
20773 * Unless required by applicable law or agreed to in writing, software
20774 * distributed under the License is distributed on an "AS IS" BASIS,
20775 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20776 * See the License for the specific language governing permissions and
20777 * limitations under the License.
20778 */
20779
20780(function(root, vttjs) {
20781
20782 var scrollSetting = {
20783 "": true,
20784 "up": true
20785 };
20786
20787 function findScrollSetting(value) {
20788 if (typeof value !== "string") {
20789 return false;
20790 }
20791 var scroll = scrollSetting[value.toLowerCase()];
20792 return scroll ? value.toLowerCase() : false;
20793 }
20794
20795 function isValidPercentValue(value) {
20796 return typeof value === "number" && (value >= 0 && value <= 100);
20797 }
20798
20799 // VTTRegion shim http://dev.w3.org/html5/webvtt/#vttregion-interface
20800 function VTTRegion() {
20801 var _width = 100;
20802 var _lines = 3;
20803 var _regionAnchorX = 0;
20804 var _regionAnchorY = 100;
20805 var _viewportAnchorX = 0;
20806 var _viewportAnchorY = 100;
20807 var _scroll = "";
20808
20809 Object.defineProperties(this, {
20810 "width": {
20811 enumerable: true,
20812 get: function() {
20813 return _width;
20814 },
20815 set: function(value) {
20816 if (!isValidPercentValue(value)) {
20817 throw new Error("Width must be between 0 and 100.");
20818 }
20819 _width = value;
20820 }
20821 },
20822 "lines": {
20823 enumerable: true,
20824 get: function() {
20825 return _lines;
20826 },
20827 set: function(value) {
20828 if (typeof value !== "number") {
20829 throw new TypeError("Lines must be set to a number.");
20830 }
20831 _lines = value;
20832 }
20833 },
20834 "regionAnchorY": {
20835 enumerable: true,
20836 get: function() {
20837 return _regionAnchorY;
20838 },
20839 set: function(value) {
20840 if (!isValidPercentValue(value)) {
20841 throw new Error("RegionAnchorX must be between 0 and 100.");
20842 }
20843 _regionAnchorY = value;
20844 }
20845 },
20846 "regionAnchorX": {
20847 enumerable: true,
20848 get: function() {
20849 return _regionAnchorX;
20850 },
20851 set: function(value) {
20852 if(!isValidPercentValue(value)) {
20853 throw new Error("RegionAnchorY must be between 0 and 100.");
20854 }
20855 _regionAnchorX = value;
20856 }
20857 },
20858 "viewportAnchorY": {
20859 enumerable: true,
20860 get: function() {
20861 return _viewportAnchorY;
20862 },
20863 set: function(value) {
20864 if (!isValidPercentValue(value)) {
20865 throw new Error("ViewportAnchorY must be between 0 and 100.");
20866 }
20867 _viewportAnchorY = value;
20868 }
20869 },
20870 "viewportAnchorX": {
20871 enumerable: true,
20872 get: function() {
20873 return _viewportAnchorX;
20874 },
20875 set: function(value) {
20876 if (!isValidPercentValue(value)) {
20877 throw new Error("ViewportAnchorX must be between 0 and 100.");
20878 }
20879 _viewportAnchorX = value;
20880 }
20881 },
20882 "scroll": {
20883 enumerable: true,
20884 get: function() {
20885 return _scroll;
20886 },
20887 set: function(value) {
20888 var setting = findScrollSetting(value);
20889 // Have to check for false as an empty string is a legal value.
20890 if (setting === false) {
20891 throw new SyntaxError("An invalid or illegal string was specified.");
20892 }
20893 _scroll = setting;
20894 }
20895 }
20896 });
20897 }
20898
20899 root.VTTRegion = root.VTTRegion || VTTRegion;
20900 vttjs.VTTRegion = VTTRegion;
20901}(this, (this.vttjs || {})));
20902
20903/**
20904 * Copyright 2013 vtt.js Contributors
20905 *
20906 * Licensed under the Apache License, Version 2.0 (the "License");
20907 * you may not use this file except in compliance with the License.
20908 * You may obtain a copy of the License at
20909 *
20910 * http://www.apache.org/licenses/LICENSE-2.0
20911 *
20912 * Unless required by applicable law or agreed to in writing, software
20913 * distributed under the License is distributed on an "AS IS" BASIS,
20914 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20915 * See the License for the specific language governing permissions and
20916 * limitations under the License.
20917 */
20918
20919/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
20920/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
20921
20922(function(global) {
20923
20924 var _objCreate = Object.create || (function() {
20925 function F() {}
20926 return function(o) {
20927 if (arguments.length !== 1) {
20928 throw new Error('Object.create shim only accepts one parameter.');
20929 }
20930 F.prototype = o;
20931 return new F();
20932 };
20933 })();
20934
20935 // Creates a new ParserError object from an errorData object. The errorData
20936 // object should have default code and message properties. The default message
20937 // property can be overriden by passing in a message parameter.
20938 // See ParsingError.Errors below for acceptable errors.
20939 function ParsingError(errorData, message) {
20940 this.name = "ParsingError";
20941 this.code = errorData.code;
20942 this.message = message || errorData.message;
20943 }
20944 ParsingError.prototype = _objCreate(Error.prototype);
20945 ParsingError.prototype.constructor = ParsingError;
20946
20947 // ParsingError metadata for acceptable ParsingErrors.
20948 ParsingError.Errors = {
20949 BadSignature: {
20950 code: 0,
20951 message: "Malformed WebVTT signature."
20952 },
20953 BadTimeStamp: {
20954 code: 1,
20955 message: "Malformed time stamp."
20956 }
20957 };
20958
20959 // Try to parse input as a time stamp.
20960 function parseTimeStamp(input) {
20961
20962 function computeSeconds(h, m, s, f) {
20963 return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
20964 }
20965
20966 var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
20967 if (!m) {
20968 return null;
20969 }
20970
20971 if (m[3]) {
20972 // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds]
20973 return computeSeconds(m[1], m[2], m[3].replace(":", ""), m[4]);
20974 } else if (m[1] > 59) {
20975 // Timestamp takes the form of [hours]:[minutes].[milliseconds]
20976 // First position is hours as it's over 59.
20977 return computeSeconds(m[1], m[2], 0, m[4]);
20978 } else {
20979 // Timestamp takes the form of [minutes]:[seconds].[milliseconds]
20980 return computeSeconds(0, m[1], m[2], m[4]);
20981 }
20982 }
20983
20984 // A settings object holds key/value pairs and will ignore anything but the first
20985 // assignment to a specific key.
20986 function Settings() {
20987 this.values = _objCreate(null);
20988 }
20989
20990 Settings.prototype = {
20991 // Only accept the first assignment to any key.
20992 set: function(k, v) {
20993 if (!this.get(k) && v !== "") {
20994 this.values[k] = v;
20995 }
20996 },
20997 // Return the value for a key, or a default value.
20998 // If 'defaultKey' is passed then 'dflt' is assumed to be an object with
20999 // a number of possible default values as properties where 'defaultKey' is
21000 // the key of the property that will be chosen; otherwise it's assumed to be
21001 // a single value.
21002 get: function(k, dflt, defaultKey) {
21003 if (defaultKey) {
21004 return this.has(k) ? this.values[k] : dflt[defaultKey];
21005 }
21006 return this.has(k) ? this.values[k] : dflt;
21007 },
21008 // Check whether we have a value for a key.
21009 has: function(k) {
21010 return k in this.values;
21011 },
21012 // Accept a setting if its one of the given alternatives.
21013 alt: function(k, v, a) {
21014 for (var n = 0; n < a.length; ++n) {
21015 if (v === a[n]) {
21016 this.set(k, v);
21017 break;
21018 }
21019 }
21020 },
21021 // Accept a setting if its a valid (signed) integer.
21022 integer: function(k, v) {
21023 if (/^-?\d+$/.test(v)) { // integer
21024 this.set(k, parseInt(v, 10));
21025 }
21026 },
21027 // Accept a setting if its a valid percentage.
21028 percent: function(k, v) {
21029 var m;
21030 if ((m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/))) {
21031 v = parseFloat(v);
21032 if (v >= 0 && v <= 100) {
21033 this.set(k, v);
21034 return true;
21035 }
21036 }
21037 return false;
21038 }
21039 };
21040
21041 // Helper function to parse input into groups separated by 'groupDelim', and
21042 // interprete each group as a key/value pair separated by 'keyValueDelim'.
21043 function parseOptions(input, callback, keyValueDelim, groupDelim) {
21044 var groups = groupDelim ? input.split(groupDelim) : [input];
21045 for (var i in groups) {
21046 if (typeof groups[i] !== "string") {
21047 continue;
21048 }
21049 var kv = groups[i].split(keyValueDelim);
21050 if (kv.length !== 2) {
21051 continue;
21052 }
21053 var k = kv[0];
21054 var v = kv[1];
21055 callback(k, v);
21056 }
21057 }
21058
21059 function parseCue(input, cue, regionList) {
21060 // Remember the original input if we need to throw an error.
21061 var oInput = input;
21062 // 4.1 WebVTT timestamp
21063 function consumeTimeStamp() {
21064 var ts = parseTimeStamp(input);
21065 if (ts === null) {
21066 throw new ParsingError(ParsingError.Errors.BadTimeStamp,
21067 "Malformed timestamp: " + oInput);
21068 }
21069 // Remove time stamp from input.
21070 input = input.replace(/^[^\sa-zA-Z-]+/, "");
21071 return ts;
21072 }
21073
21074 // 4.4.2 WebVTT cue settings
21075 function consumeCueSettings(input, cue) {
21076 var settings = new Settings();
21077
21078 parseOptions(input, function (k, v) {
21079 switch (k) {
21080 case "region":
21081 // Find the last region we parsed with the same region id.
21082 for (var i = regionList.length - 1; i >= 0; i--) {
21083 if (regionList[i].id === v) {
21084 settings.set(k, regionList[i].region);
21085 break;
21086 }
21087 }
21088 break;
21089 case "vertical":
21090 settings.alt(k, v, ["rl", "lr"]);
21091 break;
21092 case "line":
21093 var vals = v.split(","),
21094 vals0 = vals[0];
21095 settings.integer(k, vals0);
21096 settings.percent(k, vals0) ? settings.set("snapToLines", false) : null;
21097 settings.alt(k, vals0, ["auto"]);
21098 if (vals.length === 2) {
21099 settings.alt("lineAlign", vals[1], ["start", "middle", "end"]);
21100 }
21101 break;
21102 case "position":
21103 vals = v.split(",");
21104 settings.percent(k, vals[0]);
21105 if (vals.length === 2) {
21106 settings.alt("positionAlign", vals[1], ["start", "middle", "end"]);
21107 }
21108 break;
21109 case "size":
21110 settings.percent(k, v);
21111 break;
21112 case "align":
21113 settings.alt(k, v, ["start", "middle", "end", "left", "right"]);
21114 break;
21115 }
21116 }, /:/, /\s/);
21117
21118 // Apply default values for any missing fields.
21119 cue.region = settings.get("region", null);
21120 cue.vertical = settings.get("vertical", "");
21121 cue.line = settings.get("line", "auto");
21122 cue.lineAlign = settings.get("lineAlign", "start");
21123 cue.snapToLines = settings.get("snapToLines", true);
21124 cue.size = settings.get("size", 100);
21125 cue.align = settings.get("align", "middle");
21126 cue.position = settings.get("position", {
21127 start: 0,
21128 left: 0,
21129 middle: 50,
21130 end: 100,
21131 right: 100
21132 }, cue.align);
21133 cue.positionAlign = settings.get("positionAlign", {
21134 start: "start",
21135 left: "start",
21136 middle: "middle",
21137 end: "end",
21138 right: "end"
21139 }, cue.align);
21140 }
21141
21142 function skipWhitespace() {
21143 input = input.replace(/^\s+/, "");
21144 }
21145
21146 // 4.1 WebVTT cue timings.
21147 skipWhitespace();
21148 cue.startTime = consumeTimeStamp(); // (1) collect cue start time
21149 skipWhitespace();
21150 if (input.substr(0, 3) !== "-->") { // (3) next characters must match "-->"
21151 throw new ParsingError(ParsingError.Errors.BadTimeStamp,
21152 "Malformed time stamp (time stamps must be separated by '-->'): " +
21153 oInput);
21154 }
21155 input = input.substr(3);
21156 skipWhitespace();
21157 cue.endTime = consumeTimeStamp(); // (5) collect cue end time
21158
21159 // 4.1 WebVTT cue settings list.
21160 skipWhitespace();
21161 consumeCueSettings(input, cue);
21162 }
21163
21164 var ESCAPE = {
21165 "&amp;": "&",
21166 "&lt;": "<",
21167 "&gt;": ">",
21168 "&lrm;": "\u200e",
21169 "&rlm;": "\u200f",
21170 "&nbsp;": "\u00a0"
21171 };
21172
21173 var TAG_NAME = {
21174 c: "span",
21175 i: "i",
21176 b: "b",
21177 u: "u",
21178 ruby: "ruby",
21179 rt: "rt",
21180 v: "span",
21181 lang: "span"
21182 };
21183
21184 var TAG_ANNOTATION = {
21185 v: "title",
21186 lang: "lang"
21187 };
21188
21189 var NEEDS_PARENT = {
21190 rt: "ruby"
21191 };
21192
21193 // Parse content into a document fragment.
21194 function parseContent(window, input) {
21195 function nextToken() {
21196 // Check for end-of-string.
21197 if (!input) {
21198 return null;
21199 }
21200
21201 // Consume 'n' characters from the input.
21202 function consume(result) {
21203 input = input.substr(result.length);
21204 return result;
21205 }
21206
21207 var m = input.match(/^([^<]*)(<[^>]+>?)?/);
21208 // If there is some text before the next tag, return it, otherwise return
21209 // the tag.
21210 return consume(m[1] ? m[1] : m[2]);
21211 }
21212
21213 // Unescape a string 's'.
21214 function unescape1(e) {
21215 return ESCAPE[e];
21216 }
21217 function unescape(s) {
21218 while ((m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/))) {
21219 s = s.replace(m[0], unescape1);
21220 }
21221 return s;
21222 }
21223
21224 function shouldAdd(current, element) {
21225 return !NEEDS_PARENT[element.localName] ||
21226 NEEDS_PARENT[element.localName] === current.localName;
21227 }
21228
21229 // Create an element for this tag.
21230 function createElement(type, annotation) {
21231 var tagName = TAG_NAME[type];
21232 if (!tagName) {
21233 return null;
21234 }
21235 var element = window.document.createElement(tagName);
21236 element.localName = tagName;
21237 var name = TAG_ANNOTATION[type];
21238 if (name && annotation) {
21239 element[name] = annotation.trim();
21240 }
21241 return element;
21242 }
21243
21244 var rootDiv = window.document.createElement("div"),
21245 current = rootDiv,
21246 t,
21247 tagStack = [];
21248
21249 while ((t = nextToken()) !== null) {
21250 if (t[0] === '<') {
21251 if (t[1] === "/") {
21252 // If the closing tag matches, move back up to the parent node.
21253 if (tagStack.length &&
21254 tagStack[tagStack.length - 1] === t.substr(2).replace(">", "")) {
21255 tagStack.pop();
21256 current = current.parentNode;
21257 }
21258 // Otherwise just ignore the end tag.
21259 continue;
21260 }
21261 var ts = parseTimeStamp(t.substr(1, t.length - 2));
21262 var node;
21263 if (ts) {
21264 // Timestamps are lead nodes as well.
21265 node = window.document.createProcessingInstruction("timestamp", ts);
21266 current.appendChild(node);
21267 continue;
21268 }
21269 var m = t.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/);
21270 // If we can't parse the tag, skip to the next tag.
21271 if (!m) {
21272 continue;
21273 }
21274 // Try to construct an element, and ignore the tag if we couldn't.
21275 node = createElement(m[1], m[3]);
21276 if (!node) {
21277 continue;
21278 }
21279 // Determine if the tag should be added based on the context of where it
21280 // is placed in the cuetext.
21281 if (!shouldAdd(current, node)) {
21282 continue;
21283 }
21284 // Set the class list (as a list of classes, separated by space).
21285 if (m[2]) {
21286 node.className = m[2].substr(1).replace('.', ' ');
21287 }
21288 // Append the node to the current node, and enter the scope of the new
21289 // node.
21290 tagStack.push(m[1]);
21291 current.appendChild(node);
21292 current = node;
21293 continue;
21294 }
21295
21296 // Text nodes are leaf nodes.
21297 current.appendChild(window.document.createTextNode(unescape(t)));
21298 }
21299
21300 return rootDiv;
21301 }
21302
21303 // This is a list of all the Unicode characters that have a strong
21304 // right-to-left category. What this means is that these characters are
21305 // written right-to-left for sure. It was generated by pulling all the strong
21306 // right-to-left characters out of the Unicode data table. That table can
21307 // found at: http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
21308 var strongRTLChars = [0x05BE, 0x05C0, 0x05C3, 0x05C6, 0x05D0, 0x05D1,
21309 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA,
21310 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3,
21311 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05F0, 0x05F1,
21312 0x05F2, 0x05F3, 0x05F4, 0x0608, 0x060B, 0x060D, 0x061B, 0x061E, 0x061F,
21313 0x0620, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
21314 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631,
21315 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A,
21316 0x063B, 0x063C, 0x063D, 0x063E, 0x063F, 0x0640, 0x0641, 0x0642, 0x0643,
21317 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x066D, 0x066E,
21318 0x066F, 0x0671, 0x0672, 0x0673, 0x0674, 0x0675, 0x0676, 0x0677, 0x0678,
21319 0x0679, 0x067A, 0x067B, 0x067C, 0x067D, 0x067E, 0x067F, 0x0680, 0x0681,
21320 0x0682, 0x0683, 0x0684, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689, 0x068A,
21321 0x068B, 0x068C, 0x068D, 0x068E, 0x068F, 0x0690, 0x0691, 0x0692, 0x0693,
21322 0x0694, 0x0695, 0x0696, 0x0697, 0x0698, 0x0699, 0x069A, 0x069B, 0x069C,
21323 0x069D, 0x069E, 0x069F, 0x06A0, 0x06A1, 0x06A2, 0x06A3, 0x06A4, 0x06A5,
21324 0x06A6, 0x06A7, 0x06A8, 0x06A9, 0x06AA, 0x06AB, 0x06AC, 0x06AD, 0x06AE,
21325 0x06AF, 0x06B0, 0x06B1, 0x06B2, 0x06B3, 0x06B4, 0x06B5, 0x06B6, 0x06B7,
21326 0x06B8, 0x06B9, 0x06BA, 0x06BB, 0x06BC, 0x06BD, 0x06BE, 0x06BF, 0x06C0,
21327 0x06C1, 0x06C2, 0x06C3, 0x06C4, 0x06C5, 0x06C6, 0x06C7, 0x06C8, 0x06C9,
21328 0x06CA, 0x06CB, 0x06CC, 0x06CD, 0x06CE, 0x06CF, 0x06D0, 0x06D1, 0x06D2,
21329 0x06D3, 0x06D4, 0x06D5, 0x06E5, 0x06E6, 0x06EE, 0x06EF, 0x06FA, 0x06FB,
21330 0x06FC, 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704,
21331 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070A, 0x070B, 0x070C, 0x070D,
21332 0x070F, 0x0710, 0x0712, 0x0713, 0x0714, 0x0715, 0x0716, 0x0717, 0x0718,
21333 0x0719, 0x071A, 0x071B, 0x071C, 0x071D, 0x071E, 0x071F, 0x0720, 0x0721,
21334 0x0722, 0x0723, 0x0724, 0x0725, 0x0726, 0x0727, 0x0728, 0x0729, 0x072A,
21335 0x072B, 0x072C, 0x072D, 0x072E, 0x072F, 0x074D, 0x074E, 0x074F, 0x0750,
21336 0x0751, 0x0752, 0x0753, 0x0754, 0x0755, 0x0756, 0x0757, 0x0758, 0x0759,
21337 0x075A, 0x075B, 0x075C, 0x075D, 0x075E, 0x075F, 0x0760, 0x0761, 0x0762,
21338 0x0763, 0x0764, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769, 0x076A, 0x076B,
21339 0x076C, 0x076D, 0x076E, 0x076F, 0x0770, 0x0771, 0x0772, 0x0773, 0x0774,
21340 0x0775, 0x0776, 0x0777, 0x0778, 0x0779, 0x077A, 0x077B, 0x077C, 0x077D,
21341 0x077E, 0x077F, 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0786,
21342 0x0787, 0x0788, 0x0789, 0x078A, 0x078B, 0x078C, 0x078D, 0x078E, 0x078F,
21343 0x0790, 0x0791, 0x0792, 0x0793, 0x0794, 0x0795, 0x0796, 0x0797, 0x0798,
21344 0x0799, 0x079A, 0x079B, 0x079C, 0x079D, 0x079E, 0x079F, 0x07A0, 0x07A1,
21345 0x07A2, 0x07A3, 0x07A4, 0x07A5, 0x07B1, 0x07C0, 0x07C1, 0x07C2, 0x07C3,
21346 0x07C4, 0x07C5, 0x07C6, 0x07C7, 0x07C8, 0x07C9, 0x07CA, 0x07CB, 0x07CC,
21347 0x07CD, 0x07CE, 0x07CF, 0x07D0, 0x07D1, 0x07D2, 0x07D3, 0x07D4, 0x07D5,
21348 0x07D6, 0x07D7, 0x07D8, 0x07D9, 0x07DA, 0x07DB, 0x07DC, 0x07DD, 0x07DE,
21349 0x07DF, 0x07E0, 0x07E1, 0x07E2, 0x07E3, 0x07E4, 0x07E5, 0x07E6, 0x07E7,
21350 0x07E8, 0x07E9, 0x07EA, 0x07F4, 0x07F5, 0x07FA, 0x0800, 0x0801, 0x0802,
21351 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B,
21352 0x080C, 0x080D, 0x080E, 0x080F, 0x0810, 0x0811, 0x0812, 0x0813, 0x0814,
21353 0x0815, 0x081A, 0x0824, 0x0828, 0x0830, 0x0831, 0x0832, 0x0833, 0x0834,
21354 0x0835, 0x0836, 0x0837, 0x0838, 0x0839, 0x083A, 0x083B, 0x083C, 0x083D,
21355 0x083E, 0x0840, 0x0841, 0x0842, 0x0843, 0x0844, 0x0845, 0x0846, 0x0847,
21356 0x0848, 0x0849, 0x084A, 0x084B, 0x084C, 0x084D, 0x084E, 0x084F, 0x0850,
21357 0x0851, 0x0852, 0x0853, 0x0854, 0x0855, 0x0856, 0x0857, 0x0858, 0x085E,
21358 0x08A0, 0x08A2, 0x08A3, 0x08A4, 0x08A5, 0x08A6, 0x08A7, 0x08A8, 0x08A9,
21359 0x08AA, 0x08AB, 0x08AC, 0x200F, 0xFB1D, 0xFB1F, 0xFB20, 0xFB21, 0xFB22,
21360 0xFB23, 0xFB24, 0xFB25, 0xFB26, 0xFB27, 0xFB28, 0xFB2A, 0xFB2B, 0xFB2C,
21361 0xFB2D, 0xFB2E, 0xFB2F, 0xFB30, 0xFB31, 0xFB32, 0xFB33, 0xFB34, 0xFB35,
21362 0xFB36, 0xFB38, 0xFB39, 0xFB3A, 0xFB3B, 0xFB3C, 0xFB3E, 0xFB40, 0xFB41,
21363 0xFB43, 0xFB44, 0xFB46, 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C,
21364 0xFB4D, 0xFB4E, 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55,
21365 0xFB56, 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D, 0xFB5E,
21366 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63, 0xFB64, 0xFB65, 0xFB66, 0xFB67,
21367 0xFB68, 0xFB69, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70,
21368 0xFB71, 0xFB72, 0xFB73, 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79,
21369 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81, 0xFB82,
21370 0xFB83, 0xFB84, 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B,
21371 0xFB8C, 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94,
21372 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D,
21373 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3, 0xFBA4, 0xFBA5, 0xFBA6,
21374 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF,
21375 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3, 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8,
21376 0xFBB9, 0xFBBA, 0xFBBB, 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1,
21377 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB,
21378 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3, 0xFBE4,
21379 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB, 0xFBEC, 0xFBED,
21380 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6,
21381 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF,
21382 0xFC00, 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08,
21383 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFC0E, 0xFC0F, 0xFC10, 0xFC11,
21384 0xFC12, 0xFC13, 0xFC14, 0xFC15, 0xFC16, 0xFC17, 0xFC18, 0xFC19, 0xFC1A,
21385 0xFC1B, 0xFC1C, 0xFC1D, 0xFC1E, 0xFC1F, 0xFC20, 0xFC21, 0xFC22, 0xFC23,
21386 0xFC24, 0xFC25, 0xFC26, 0xFC27, 0xFC28, 0xFC29, 0xFC2A, 0xFC2B, 0xFC2C,
21387 0xFC2D, 0xFC2E, 0xFC2F, 0xFC30, 0xFC31, 0xFC32, 0xFC33, 0xFC34, 0xFC35,
21388 0xFC36, 0xFC37, 0xFC38, 0xFC39, 0xFC3A, 0xFC3B, 0xFC3C, 0xFC3D, 0xFC3E,
21389 0xFC3F, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46, 0xFC47,
21390 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0xFC4C, 0xFC4D, 0xFC4E, 0xFC4F, 0xFC50,
21391 0xFC51, 0xFC52, 0xFC53, 0xFC54, 0xFC55, 0xFC56, 0xFC57, 0xFC58, 0xFC59,
21392 0xFC5A, 0xFC5B, 0xFC5C, 0xFC5D, 0xFC5E, 0xFC5F, 0xFC60, 0xFC61, 0xFC62,
21393 0xFC63, 0xFC64, 0xFC65, 0xFC66, 0xFC67, 0xFC68, 0xFC69, 0xFC6A, 0xFC6B,
21394 0xFC6C, 0xFC6D, 0xFC6E, 0xFC6F, 0xFC70, 0xFC71, 0xFC72, 0xFC73, 0xFC74,
21395 0xFC75, 0xFC76, 0xFC77, 0xFC78, 0xFC79, 0xFC7A, 0xFC7B, 0xFC7C, 0xFC7D,
21396 0xFC7E, 0xFC7F, 0xFC80, 0xFC81, 0xFC82, 0xFC83, 0xFC84, 0xFC85, 0xFC86,
21397 0xFC87, 0xFC88, 0xFC89, 0xFC8A, 0xFC8B, 0xFC8C, 0xFC8D, 0xFC8E, 0xFC8F,
21398 0xFC90, 0xFC91, 0xFC92, 0xFC93, 0xFC94, 0xFC95, 0xFC96, 0xFC97, 0xFC98,
21399 0xFC99, 0xFC9A, 0xFC9B, 0xFC9C, 0xFC9D, 0xFC9E, 0xFC9F, 0xFCA0, 0xFCA1,
21400 0xFCA2, 0xFCA3, 0xFCA4, 0xFCA5, 0xFCA6, 0xFCA7, 0xFCA8, 0xFCA9, 0xFCAA,
21401 0xFCAB, 0xFCAC, 0xFCAD, 0xFCAE, 0xFCAF, 0xFCB0, 0xFCB1, 0xFCB2, 0xFCB3,
21402 0xFCB4, 0xFCB5, 0xFCB6, 0xFCB7, 0xFCB8, 0xFCB9, 0xFCBA, 0xFCBB, 0xFCBC,
21403 0xFCBD, 0xFCBE, 0xFCBF, 0xFCC0, 0xFCC1, 0xFCC2, 0xFCC3, 0xFCC4, 0xFCC5,
21404 0xFCC6, 0xFCC7, 0xFCC8, 0xFCC9, 0xFCCA, 0xFCCB, 0xFCCC, 0xFCCD, 0xFCCE,
21405 0xFCCF, 0xFCD0, 0xFCD1, 0xFCD2, 0xFCD3, 0xFCD4, 0xFCD5, 0xFCD6, 0xFCD7,
21406 0xFCD8, 0xFCD9, 0xFCDA, 0xFCDB, 0xFCDC, 0xFCDD, 0xFCDE, 0xFCDF, 0xFCE0,
21407 0xFCE1, 0xFCE2, 0xFCE3, 0xFCE4, 0xFCE5, 0xFCE6, 0xFCE7, 0xFCE8, 0xFCE9,
21408 0xFCEA, 0xFCEB, 0xFCEC, 0xFCED, 0xFCEE, 0xFCEF, 0xFCF0, 0xFCF1, 0xFCF2,
21409 0xFCF3, 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, 0xFCFA, 0xFCFB,
21410 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04,
21411 0xFD05, 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, 0xFD0C, 0xFD0D,
21412 0xFD0E, 0xFD0F, 0xFD10, 0xFD11, 0xFD12, 0xFD13, 0xFD14, 0xFD15, 0xFD16,
21413 0xFD17, 0xFD18, 0xFD19, 0xFD1A, 0xFD1B, 0xFD1C, 0xFD1D, 0xFD1E, 0xFD1F,
21414 0xFD20, 0xFD21, 0xFD22, 0xFD23, 0xFD24, 0xFD25, 0xFD26, 0xFD27, 0xFD28,
21415 0xFD29, 0xFD2A, 0xFD2B, 0xFD2C, 0xFD2D, 0xFD2E, 0xFD2F, 0xFD30, 0xFD31,
21416 0xFD32, 0xFD33, 0xFD34, 0xFD35, 0xFD36, 0xFD37, 0xFD38, 0xFD39, 0xFD3A,
21417 0xFD3B, 0xFD3C, 0xFD3D, 0xFD50, 0xFD51, 0xFD52, 0xFD53, 0xFD54, 0xFD55,
21418 0xFD56, 0xFD57, 0xFD58, 0xFD59, 0xFD5A, 0xFD5B, 0xFD5C, 0xFD5D, 0xFD5E,
21419 0xFD5F, 0xFD60, 0xFD61, 0xFD62, 0xFD63, 0xFD64, 0xFD65, 0xFD66, 0xFD67,
21420 0xFD68, 0xFD69, 0xFD6A, 0xFD6B, 0xFD6C, 0xFD6D, 0xFD6E, 0xFD6F, 0xFD70,
21421 0xFD71, 0xFD72, 0xFD73, 0xFD74, 0xFD75, 0xFD76, 0xFD77, 0xFD78, 0xFD79,
21422 0xFD7A, 0xFD7B, 0xFD7C, 0xFD7D, 0xFD7E, 0xFD7F, 0xFD80, 0xFD81, 0xFD82,
21423 0xFD83, 0xFD84, 0xFD85, 0xFD86, 0xFD87, 0xFD88, 0xFD89, 0xFD8A, 0xFD8B,
21424 0xFD8C, 0xFD8D, 0xFD8E, 0xFD8F, 0xFD92, 0xFD93, 0xFD94, 0xFD95, 0xFD96,
21425 0xFD97, 0xFD98, 0xFD99, 0xFD9A, 0xFD9B, 0xFD9C, 0xFD9D, 0xFD9E, 0xFD9F,
21426 0xFDA0, 0xFDA1, 0xFDA2, 0xFDA3, 0xFDA4, 0xFDA5, 0xFDA6, 0xFDA7, 0xFDA8,
21427 0xFDA9, 0xFDAA, 0xFDAB, 0xFDAC, 0xFDAD, 0xFDAE, 0xFDAF, 0xFDB0, 0xFDB1,
21428 0xFDB2, 0xFDB3, 0xFDB4, 0xFDB5, 0xFDB6, 0xFDB7, 0xFDB8, 0xFDB9, 0xFDBA,
21429 0xFDBB, 0xFDBC, 0xFDBD, 0xFDBE, 0xFDBF, 0xFDC0, 0xFDC1, 0xFDC2, 0xFDC3,
21430 0xFDC4, 0xFDC5, 0xFDC6, 0xFDC7, 0xFDF0, 0xFDF1, 0xFDF2, 0xFDF3, 0xFDF4,
21431 0xFDF5, 0xFDF6, 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, 0xFE70,
21432 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE76, 0xFE77, 0xFE78, 0xFE79, 0xFE7A,
21433 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, 0xFE80, 0xFE81, 0xFE82, 0xFE83,
21434 0xFE84, 0xFE85, 0xFE86, 0xFE87, 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C,
21435 0xFE8D, 0xFE8E, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95,
21436 0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E,
21437 0xFE9F, 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
21438 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, 0xFEB0,
21439 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9,
21440 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, 0xFEC1, 0xFEC2,
21441 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, 0xFECB,
21442 0xFECC, 0xFECD, 0xFECE, 0xFECF, 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4,
21443 0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD,
21444 0xFEDE, 0xFEDF, 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6,
21445 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
21446 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8,
21447 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0x10800, 0x10801, 0x10802, 0x10803,
21448 0x10804, 0x10805, 0x10808, 0x1080A, 0x1080B, 0x1080C, 0x1080D, 0x1080E,
21449 0x1080F, 0x10810, 0x10811, 0x10812, 0x10813, 0x10814, 0x10815, 0x10816,
21450 0x10817, 0x10818, 0x10819, 0x1081A, 0x1081B, 0x1081C, 0x1081D, 0x1081E,
21451 0x1081F, 0x10820, 0x10821, 0x10822, 0x10823, 0x10824, 0x10825, 0x10826,
21452 0x10827, 0x10828, 0x10829, 0x1082A, 0x1082B, 0x1082C, 0x1082D, 0x1082E,
21453 0x1082F, 0x10830, 0x10831, 0x10832, 0x10833, 0x10834, 0x10835, 0x10837,
21454 0x10838, 0x1083C, 0x1083F, 0x10840, 0x10841, 0x10842, 0x10843, 0x10844,
21455 0x10845, 0x10846, 0x10847, 0x10848, 0x10849, 0x1084A, 0x1084B, 0x1084C,
21456 0x1084D, 0x1084E, 0x1084F, 0x10850, 0x10851, 0x10852, 0x10853, 0x10854,
21457 0x10855, 0x10857, 0x10858, 0x10859, 0x1085A, 0x1085B, 0x1085C, 0x1085D,
21458 0x1085E, 0x1085F, 0x10900, 0x10901, 0x10902, 0x10903, 0x10904, 0x10905,
21459 0x10906, 0x10907, 0x10908, 0x10909, 0x1090A, 0x1090B, 0x1090C, 0x1090D,
21460 0x1090E, 0x1090F, 0x10910, 0x10911, 0x10912, 0x10913, 0x10914, 0x10915,
21461 0x10916, 0x10917, 0x10918, 0x10919, 0x1091A, 0x1091B, 0x10920, 0x10921,
21462 0x10922, 0x10923, 0x10924, 0x10925, 0x10926, 0x10927, 0x10928, 0x10929,
21463 0x1092A, 0x1092B, 0x1092C, 0x1092D, 0x1092E, 0x1092F, 0x10930, 0x10931,
21464 0x10932, 0x10933, 0x10934, 0x10935, 0x10936, 0x10937, 0x10938, 0x10939,
21465 0x1093F, 0x10980, 0x10981, 0x10982, 0x10983, 0x10984, 0x10985, 0x10986,
21466 0x10987, 0x10988, 0x10989, 0x1098A, 0x1098B, 0x1098C, 0x1098D, 0x1098E,
21467 0x1098F, 0x10990, 0x10991, 0x10992, 0x10993, 0x10994, 0x10995, 0x10996,
21468 0x10997, 0x10998, 0x10999, 0x1099A, 0x1099B, 0x1099C, 0x1099D, 0x1099E,
21469 0x1099F, 0x109A0, 0x109A1, 0x109A2, 0x109A3, 0x109A4, 0x109A5, 0x109A6,
21470 0x109A7, 0x109A8, 0x109A9, 0x109AA, 0x109AB, 0x109AC, 0x109AD, 0x109AE,
21471 0x109AF, 0x109B0, 0x109B1, 0x109B2, 0x109B3, 0x109B4, 0x109B5, 0x109B6,
21472 0x109B7, 0x109BE, 0x109BF, 0x10A00, 0x10A10, 0x10A11, 0x10A12, 0x10A13,
21473 0x10A15, 0x10A16, 0x10A17, 0x10A19, 0x10A1A, 0x10A1B, 0x10A1C, 0x10A1D,
21474 0x10A1E, 0x10A1F, 0x10A20, 0x10A21, 0x10A22, 0x10A23, 0x10A24, 0x10A25,
21475 0x10A26, 0x10A27, 0x10A28, 0x10A29, 0x10A2A, 0x10A2B, 0x10A2C, 0x10A2D,
21476 0x10A2E, 0x10A2F, 0x10A30, 0x10A31, 0x10A32, 0x10A33, 0x10A40, 0x10A41,
21477 0x10A42, 0x10A43, 0x10A44, 0x10A45, 0x10A46, 0x10A47, 0x10A50, 0x10A51,
21478 0x10A52, 0x10A53, 0x10A54, 0x10A55, 0x10A56, 0x10A57, 0x10A58, 0x10A60,
21479 0x10A61, 0x10A62, 0x10A63, 0x10A64, 0x10A65, 0x10A66, 0x10A67, 0x10A68,
21480 0x10A69, 0x10A6A, 0x10A6B, 0x10A6C, 0x10A6D, 0x10A6E, 0x10A6F, 0x10A70,
21481 0x10A71, 0x10A72, 0x10A73, 0x10A74, 0x10A75, 0x10A76, 0x10A77, 0x10A78,
21482 0x10A79, 0x10A7A, 0x10A7B, 0x10A7C, 0x10A7D, 0x10A7E, 0x10A7F, 0x10B00,
21483 0x10B01, 0x10B02, 0x10B03, 0x10B04, 0x10B05, 0x10B06, 0x10B07, 0x10B08,
21484 0x10B09, 0x10B0A, 0x10B0B, 0x10B0C, 0x10B0D, 0x10B0E, 0x10B0F, 0x10B10,
21485 0x10B11, 0x10B12, 0x10B13, 0x10B14, 0x10B15, 0x10B16, 0x10B17, 0x10B18,
21486 0x10B19, 0x10B1A, 0x10B1B, 0x10B1C, 0x10B1D, 0x10B1E, 0x10B1F, 0x10B20,
21487 0x10B21, 0x10B22, 0x10B23, 0x10B24, 0x10B25, 0x10B26, 0x10B27, 0x10B28,
21488 0x10B29, 0x10B2A, 0x10B2B, 0x10B2C, 0x10B2D, 0x10B2E, 0x10B2F, 0x10B30,
21489 0x10B31, 0x10B32, 0x10B33, 0x10B34, 0x10B35, 0x10B40, 0x10B41, 0x10B42,
21490 0x10B43, 0x10B44, 0x10B45, 0x10B46, 0x10B47, 0x10B48, 0x10B49, 0x10B4A,
21491 0x10B4B, 0x10B4C, 0x10B4D, 0x10B4E, 0x10B4F, 0x10B50, 0x10B51, 0x10B52,
21492 0x10B53, 0x10B54, 0x10B55, 0x10B58, 0x10B59, 0x10B5A, 0x10B5B, 0x10B5C,
21493 0x10B5D, 0x10B5E, 0x10B5F, 0x10B60, 0x10B61, 0x10B62, 0x10B63, 0x10B64,
21494 0x10B65, 0x10B66, 0x10B67, 0x10B68, 0x10B69, 0x10B6A, 0x10B6B, 0x10B6C,
21495 0x10B6D, 0x10B6E, 0x10B6F, 0x10B70, 0x10B71, 0x10B72, 0x10B78, 0x10B79,
21496 0x10B7A, 0x10B7B, 0x10B7C, 0x10B7D, 0x10B7E, 0x10B7F, 0x10C00, 0x10C01,
21497 0x10C02, 0x10C03, 0x10C04, 0x10C05, 0x10C06, 0x10C07, 0x10C08, 0x10C09,
21498 0x10C0A, 0x10C0B, 0x10C0C, 0x10C0D, 0x10C0E, 0x10C0F, 0x10C10, 0x10C11,
21499 0x10C12, 0x10C13, 0x10C14, 0x10C15, 0x10C16, 0x10C17, 0x10C18, 0x10C19,
21500 0x10C1A, 0x10C1B, 0x10C1C, 0x10C1D, 0x10C1E, 0x10C1F, 0x10C20, 0x10C21,
21501 0x10C22, 0x10C23, 0x10C24, 0x10C25, 0x10C26, 0x10C27, 0x10C28, 0x10C29,
21502 0x10C2A, 0x10C2B, 0x10C2C, 0x10C2D, 0x10C2E, 0x10C2F, 0x10C30, 0x10C31,
21503 0x10C32, 0x10C33, 0x10C34, 0x10C35, 0x10C36, 0x10C37, 0x10C38, 0x10C39,
21504 0x10C3A, 0x10C3B, 0x10C3C, 0x10C3D, 0x10C3E, 0x10C3F, 0x10C40, 0x10C41,
21505 0x10C42, 0x10C43, 0x10C44, 0x10C45, 0x10C46, 0x10C47, 0x10C48, 0x1EE00,
21506 0x1EE01, 0x1EE02, 0x1EE03, 0x1EE05, 0x1EE06, 0x1EE07, 0x1EE08, 0x1EE09,
21507 0x1EE0A, 0x1EE0B, 0x1EE0C, 0x1EE0D, 0x1EE0E, 0x1EE0F, 0x1EE10, 0x1EE11,
21508 0x1EE12, 0x1EE13, 0x1EE14, 0x1EE15, 0x1EE16, 0x1EE17, 0x1EE18, 0x1EE19,
21509 0x1EE1A, 0x1EE1B, 0x1EE1C, 0x1EE1D, 0x1EE1E, 0x1EE1F, 0x1EE21, 0x1EE22,
21510 0x1EE24, 0x1EE27, 0x1EE29, 0x1EE2A, 0x1EE2B, 0x1EE2C, 0x1EE2D, 0x1EE2E,
21511 0x1EE2F, 0x1EE30, 0x1EE31, 0x1EE32, 0x1EE34, 0x1EE35, 0x1EE36, 0x1EE37,
21512 0x1EE39, 0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE4D, 0x1EE4E,
21513 0x1EE4F, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B, 0x1EE5D,
21514 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE67, 0x1EE68, 0x1EE69, 0x1EE6A,
21515 0x1EE6C, 0x1EE6D, 0x1EE6E, 0x1EE6F, 0x1EE70, 0x1EE71, 0x1EE72, 0x1EE74,
21516 0x1EE75, 0x1EE76, 0x1EE77, 0x1EE79, 0x1EE7A, 0x1EE7B, 0x1EE7C, 0x1EE7E,
21517 0x1EE80, 0x1EE81, 0x1EE82, 0x1EE83, 0x1EE84, 0x1EE85, 0x1EE86, 0x1EE87,
21518 0x1EE88, 0x1EE89, 0x1EE8B, 0x1EE8C, 0x1EE8D, 0x1EE8E, 0x1EE8F, 0x1EE90,
21519 0x1EE91, 0x1EE92, 0x1EE93, 0x1EE94, 0x1EE95, 0x1EE96, 0x1EE97, 0x1EE98,
21520 0x1EE99, 0x1EE9A, 0x1EE9B, 0x1EEA1, 0x1EEA2, 0x1EEA3, 0x1EEA5, 0x1EEA6,
21521 0x1EEA7, 0x1EEA8, 0x1EEA9, 0x1EEAB, 0x1EEAC, 0x1EEAD, 0x1EEAE, 0x1EEAF,
21522 0x1EEB0, 0x1EEB1, 0x1EEB2, 0x1EEB3, 0x1EEB4, 0x1EEB5, 0x1EEB6, 0x1EEB7,
21523 0x1EEB8, 0x1EEB9, 0x1EEBA, 0x1EEBB, 0x10FFFD];
21524
21525 function determineBidi(cueDiv) {
21526 var nodeStack = [],
21527 text = "",
21528 charCode;
21529
21530 if (!cueDiv || !cueDiv.childNodes) {
21531 return "ltr";
21532 }
21533
21534 function pushNodes(nodeStack, node) {
21535 for (var i = node.childNodes.length - 1; i >= 0; i--) {
21536 nodeStack.push(node.childNodes[i]);
21537 }
21538 }
21539
21540 function nextTextNode(nodeStack) {
21541 if (!nodeStack || !nodeStack.length) {
21542 return null;
21543 }
21544
21545 var node = nodeStack.pop(),
21546 text = node.textContent || node.innerText;
21547 if (text) {
21548 // TODO: This should match all unicode type B characters (paragraph
21549 // separator characters). See issue #115.
21550 var m = text.match(/^.*(\n|\r)/);
21551 if (m) {
21552 nodeStack.length = 0;
21553 return m[0];
21554 }
21555 return text;
21556 }
21557 if (node.tagName === "ruby") {
21558 return nextTextNode(nodeStack);
21559 }
21560 if (node.childNodes) {
21561 pushNodes(nodeStack, node);
21562 return nextTextNode(nodeStack);
21563 }
21564 }
21565
21566 pushNodes(nodeStack, cueDiv);
21567 while ((text = nextTextNode(nodeStack))) {
21568 for (var i = 0; i < text.length; i++) {
21569 charCode = text.charCodeAt(i);
21570 for (var j = 0; j < strongRTLChars.length; j++) {
21571 if (strongRTLChars[j] === charCode) {
21572 return "rtl";
21573 }
21574 }
21575 }
21576 }
21577 return "ltr";
21578 }
21579
21580 function computeLinePos(cue) {
21581 if (typeof cue.line === "number" &&
21582 (cue.snapToLines || (cue.line >= 0 && cue.line <= 100))) {
21583 return cue.line;
21584 }
21585 if (!cue.track || !cue.track.textTrackList ||
21586 !cue.track.textTrackList.mediaElement) {
21587 return -1;
21588 }
21589 var track = cue.track,
21590 trackList = track.textTrackList,
21591 count = 0;
21592 for (var i = 0; i < trackList.length && trackList[i] !== track; i++) {
21593 if (trackList[i].mode === "showing") {
21594 count++;
21595 }
21596 }
21597 return ++count * -1;
21598 }
21599
21600 function StyleBox() {
21601 }
21602
21603 // Apply styles to a div. If there is no div passed then it defaults to the
21604 // div on 'this'.
21605 StyleBox.prototype.applyStyles = function(styles, div) {
21606 div = div || this.div;
21607 for (var prop in styles) {
21608 if (styles.hasOwnProperty(prop)) {
21609 div.style[prop] = styles[prop];
21610 }
21611 }
21612 };
21613
21614 StyleBox.prototype.formatStyle = function(val, unit) {
21615 return val === 0 ? 0 : val + unit;
21616 };
21617
21618 // Constructs the computed display state of the cue (a div). Places the div
21619 // into the overlay which should be a block level element (usually a div).
21620 function CueStyleBox(window, cue, styleOptions) {
21621 var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
21622 var color = "rgba(255, 255, 255, 1)";
21623 var backgroundColor = "rgba(0, 0, 0, 0.8)";
21624
21625 if (isIE8) {
21626 color = "rgb(255, 255, 255)";
21627 backgroundColor = "rgb(0, 0, 0)";
21628 }
21629
21630 StyleBox.call(this);
21631 this.cue = cue;
21632
21633 // Parse our cue's text into a DOM tree rooted at 'cueDiv'. This div will
21634 // have inline positioning and will function as the cue background box.
21635 this.cueDiv = parseContent(window, cue.text);
21636 var styles = {
21637 color: color,
21638 backgroundColor: backgroundColor,
21639 position: "relative",
21640 left: 0,
21641 right: 0,
21642 top: 0,
21643 bottom: 0,
21644 display: "inline"
21645 };
21646
21647 if (!isIE8) {
21648 styles.writingMode = cue.vertical === "" ? "horizontal-tb"
21649 : cue.vertical === "lr" ? "vertical-lr"
21650 : "vertical-rl";
21651 styles.unicodeBidi = "plaintext";
21652 }
21653 this.applyStyles(styles, this.cueDiv);
21654
21655 // Create an absolutely positioned div that will be used to position the cue
21656 // div. Note, all WebVTT cue-setting alignments are equivalent to the CSS
21657 // mirrors of them except "middle" which is "center" in CSS.
21658 this.div = window.document.createElement("div");
21659 styles = {
21660 textAlign: cue.align === "middle" ? "center" : cue.align,
21661 font: styleOptions.font,
21662 whiteSpace: "pre-line",
21663 position: "absolute"
21664 };
21665
21666 if (!isIE8) {
21667 styles.direction = determineBidi(this.cueDiv);
21668 styles.writingMode = cue.vertical === "" ? "horizontal-tb"
21669 : cue.vertical === "lr" ? "vertical-lr"
21670 : "vertical-rl".
21671 stylesunicodeBidi = "plaintext";
21672 }
21673
21674 this.applyStyles(styles);
21675
21676 this.div.appendChild(this.cueDiv);
21677
21678 // Calculate the distance from the reference edge of the viewport to the text
21679 // position of the cue box. The reference edge will be resolved later when
21680 // the box orientation styles are applied.
21681 var textPos = 0;
21682 switch (cue.positionAlign) {
21683 case "start":
21684 textPos = cue.position;
21685 break;
21686 case "middle":
21687 textPos = cue.position - (cue.size / 2);
21688 break;
21689 case "end":
21690 textPos = cue.position - cue.size;
21691 break;
21692 }
21693
21694 // Horizontal box orientation; textPos is the distance from the left edge of the
21695 // area to the left edge of the box and cue.size is the distance extending to
21696 // the right from there.
21697 if (cue.vertical === "") {
21698 this.applyStyles({
21699 left: this.formatStyle(textPos, "%"),
21700 width: this.formatStyle(cue.size, "%")
21701 });
21702 // Vertical box orientation; textPos is the distance from the top edge of the
21703 // area to the top edge of the box and cue.size is the height extending
21704 // downwards from there.
21705 } else {
21706 this.applyStyles({
21707 top: this.formatStyle(textPos, "%"),
21708 height: this.formatStyle(cue.size, "%")
21709 });
21710 }
21711
21712 this.move = function(box) {
21713 this.applyStyles({
21714 top: this.formatStyle(box.top, "px"),
21715 bottom: this.formatStyle(box.bottom, "px"),
21716 left: this.formatStyle(box.left, "px"),
21717 right: this.formatStyle(box.right, "px"),
21718 height: this.formatStyle(box.height, "px"),
21719 width: this.formatStyle(box.width, "px")
21720 });
21721 };
21722 }
21723 CueStyleBox.prototype = _objCreate(StyleBox.prototype);
21724 CueStyleBox.prototype.constructor = CueStyleBox;
21725
21726 // Represents the co-ordinates of an Element in a way that we can easily
21727 // compute things with such as if it overlaps or intersects with another Element.
21728 // Can initialize it with either a StyleBox or another BoxPosition.
21729 function BoxPosition(obj) {
21730 var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
21731
21732 // Either a BoxPosition was passed in and we need to copy it, or a StyleBox
21733 // was passed in and we need to copy the results of 'getBoundingClientRect'
21734 // as the object returned is readonly. All co-ordinate values are in reference
21735 // to the viewport origin (top left).
21736 var lh, height, width, top;
21737 if (obj.div) {
21738 height = obj.div.offsetHeight;
21739 width = obj.div.offsetWidth;
21740 top = obj.div.offsetTop;
21741
21742 var rects = (rects = obj.div.childNodes) && (rects = rects[0]) &&
21743 rects.getClientRects && rects.getClientRects();
21744 obj = obj.div.getBoundingClientRect();
21745 // In certain cases the outter div will be slightly larger then the sum of
21746 // the inner div's lines. This could be due to bold text, etc, on some platforms.
21747 // In this case we should get the average line height and use that. This will
21748 // result in the desired behaviour.
21749 lh = rects ? Math.max((rects[0] && rects[0].height) || 0, obj.height / rects.length)
21750 : 0;
21751
21752 }
21753 this.left = obj.left;
21754 this.right = obj.right;
21755 this.top = obj.top || top;
21756 this.height = obj.height || height;
21757 this.bottom = obj.bottom || (top + (obj.height || height));
21758 this.width = obj.width || width;
21759 this.lineHeight = lh !== undefined ? lh : obj.lineHeight;
21760
21761 if (isIE8 && !this.lineHeight) {
21762 this.lineHeight = 13;
21763 }
21764 }
21765
21766 // Move the box along a particular axis. Optionally pass in an amount to move
21767 // the box. If no amount is passed then the default is the line height of the
21768 // box.
21769 BoxPosition.prototype.move = function(axis, toMove) {
21770 toMove = toMove !== undefined ? toMove : this.lineHeight;
21771 switch (axis) {
21772 case "+x":
21773 this.left += toMove;
21774 this.right += toMove;
21775 break;
21776 case "-x":
21777 this.left -= toMove;
21778 this.right -= toMove;
21779 break;
21780 case "+y":
21781 this.top += toMove;
21782 this.bottom += toMove;
21783 break;
21784 case "-y":
21785 this.top -= toMove;
21786 this.bottom -= toMove;
21787 break;
21788 }
21789 };
21790
21791 // Check if this box overlaps another box, b2.
21792 BoxPosition.prototype.overlaps = function(b2) {
21793 return this.left < b2.right &&
21794 this.right > b2.left &&
21795 this.top < b2.bottom &&
21796 this.bottom > b2.top;
21797 };
21798
21799 // Check if this box overlaps any other boxes in boxes.
21800 BoxPosition.prototype.overlapsAny = function(boxes) {
21801 for (var i = 0; i < boxes.length; i++) {
21802 if (this.overlaps(boxes[i])) {
21803 return true;
21804 }
21805 }
21806 return false;
21807 };
21808
21809 // Check if this box is within another box.
21810 BoxPosition.prototype.within = function(container) {
21811 return this.top >= container.top &&
21812 this.bottom <= container.bottom &&
21813 this.left >= container.left &&
21814 this.right <= container.right;
21815 };
21816
21817 // Check if this box is entirely within the container or it is overlapping
21818 // on the edge opposite of the axis direction passed. For example, if "+x" is
21819 // passed and the box is overlapping on the left edge of the container, then
21820 // return true.
21821 BoxPosition.prototype.overlapsOppositeAxis = function(container, axis) {
21822 switch (axis) {
21823 case "+x":
21824 return this.left < container.left;
21825 case "-x":
21826 return this.right > container.right;
21827 case "+y":
21828 return this.top < container.top;
21829 case "-y":
21830 return this.bottom > container.bottom;
21831 }
21832 };
21833
21834 // Find the percentage of the area that this box is overlapping with another
21835 // box.
21836 BoxPosition.prototype.intersectPercentage = function(b2) {
21837 var x = Math.max(0, Math.min(this.right, b2.right) - Math.max(this.left, b2.left)),
21838 y = Math.max(0, Math.min(this.bottom, b2.bottom) - Math.max(this.top, b2.top)),
21839 intersectArea = x * y;
21840 return intersectArea / (this.height * this.width);
21841 };
21842
21843 // Convert the positions from this box to CSS compatible positions using
21844 // the reference container's positions. This has to be done because this
21845 // box's positions are in reference to the viewport origin, whereas, CSS
21846 // values are in referecne to their respective edges.
21847 BoxPosition.prototype.toCSSCompatValues = function(reference) {
21848 return {
21849 top: this.top - reference.top,
21850 bottom: reference.bottom - this.bottom,
21851 left: this.left - reference.left,
21852 right: reference.right - this.right,
21853 height: this.height,
21854 width: this.width
21855 };
21856 };
21857
21858 // Get an object that represents the box's position without anything extra.
21859 // Can pass a StyleBox, HTMLElement, or another BoxPositon.
21860 BoxPosition.getSimpleBoxPosition = function(obj) {
21861 var height = obj.div ? obj.div.offsetHeight : obj.tagName ? obj.offsetHeight : 0;
21862 var width = obj.div ? obj.div.offsetWidth : obj.tagName ? obj.offsetWidth : 0;
21863 var top = obj.div ? obj.div.offsetTop : obj.tagName ? obj.offsetTop : 0;
21864
21865 obj = obj.div ? obj.div.getBoundingClientRect() :
21866 obj.tagName ? obj.getBoundingClientRect() : obj;
21867 var ret = {
21868 left: obj.left,
21869 right: obj.right,
21870 top: obj.top || top,
21871 height: obj.height || height,
21872 bottom: obj.bottom || (top + (obj.height || height)),
21873 width: obj.width || width
21874 };
21875 return ret;
21876 };
21877
21878 // Move a StyleBox to its specified, or next best, position. The containerBox
21879 // is the box that contains the StyleBox, such as a div. boxPositions are
21880 // a list of other boxes that the styleBox can't overlap with.
21881 function moveBoxToLinePosition(window, styleBox, containerBox, boxPositions) {
21882
21883 // Find the best position for a cue box, b, on the video. The axis parameter
21884 // is a list of axis, the order of which, it will move the box along. For example:
21885 // Passing ["+x", "-x"] will move the box first along the x axis in the positive
21886 // direction. If it doesn't find a good position for it there it will then move
21887 // it along the x axis in the negative direction.
21888 function findBestPosition(b, axis) {
21889 var bestPosition,
21890 specifiedPosition = new BoxPosition(b),
21891 percentage = 1; // Highest possible so the first thing we get is better.
21892
21893 for (var i = 0; i < axis.length; i++) {
21894 while (b.overlapsOppositeAxis(containerBox, axis[i]) ||
21895 (b.within(containerBox) && b.overlapsAny(boxPositions))) {
21896 b.move(axis[i]);
21897 }
21898 // We found a spot where we aren't overlapping anything. This is our
21899 // best position.
21900 if (b.within(containerBox)) {
21901 return b;
21902 }
21903 var p = b.intersectPercentage(containerBox);
21904 // If we're outside the container box less then we were on our last try
21905 // then remember this position as the best position.
21906 if (percentage > p) {
21907 bestPosition = new BoxPosition(b);
21908 percentage = p;
21909 }
21910 // Reset the box position to the specified position.
21911 b = new BoxPosition(specifiedPosition);
21912 }
21913 return bestPosition || specifiedPosition;
21914 }
21915
21916 var boxPosition = new BoxPosition(styleBox),
21917 cue = styleBox.cue,
21918 linePos = computeLinePos(cue),
21919 axis = [];
21920
21921 // If we have a line number to align the cue to.
21922 if (cue.snapToLines) {
21923 var size;
21924 switch (cue.vertical) {
21925 case "":
21926 axis = [ "+y", "-y" ];
21927 size = "height";
21928 break;
21929 case "rl":
21930 axis = [ "+x", "-x" ];
21931 size = "width";
21932 break;
21933 case "lr":
21934 axis = [ "-x", "+x" ];
21935 size = "width";
21936 break;
21937 }
21938
21939 var step = boxPosition.lineHeight,
21940 position = step * Math.round(linePos),
21941 maxPosition = containerBox[size] + step,
21942 initialAxis = axis[0];
21943
21944 // If the specified intial position is greater then the max position then
21945 // clamp the box to the amount of steps it would take for the box to
21946 // reach the max position.
21947 if (Math.abs(position) > maxPosition) {
21948 position = position < 0 ? -1 : 1;
21949 position *= Math.ceil(maxPosition / step) * step;
21950 }
21951
21952 // If computed line position returns negative then line numbers are
21953 // relative to the bottom of the video instead of the top. Therefore, we
21954 // need to increase our initial position by the length or width of the
21955 // video, depending on the writing direction, and reverse our axis directions.
21956 if (linePos < 0) {
21957 position += cue.vertical === "" ? containerBox.height : containerBox.width;
21958 axis = axis.reverse();
21959 }
21960
21961 // Move the box to the specified position. This may not be its best
21962 // position.
21963 boxPosition.move(initialAxis, position);
21964
21965 } else {
21966 // If we have a percentage line value for the cue.
21967 var calculatedPercentage = (boxPosition.lineHeight / containerBox.height) * 100;
21968
21969 switch (cue.lineAlign) {
21970 case "middle":
21971 linePos -= (calculatedPercentage / 2);
21972 break;
21973 case "end":
21974 linePos -= calculatedPercentage;
21975 break;
21976 }
21977
21978 // Apply initial line position to the cue box.
21979 switch (cue.vertical) {
21980 case "":
21981 styleBox.applyStyles({
21982 top: styleBox.formatStyle(linePos, "%")
21983 });
21984 break;
21985 case "rl":
21986 styleBox.applyStyles({
21987 left: styleBox.formatStyle(linePos, "%")
21988 });
21989 break;
21990 case "lr":
21991 styleBox.applyStyles({
21992 right: styleBox.formatStyle(linePos, "%")
21993 });
21994 break;
21995 }
21996
21997 axis = [ "+y", "-x", "+x", "-y" ];
21998
21999 // Get the box position again after we've applied the specified positioning
22000 // to it.
22001 boxPosition = new BoxPosition(styleBox);
22002 }
22003
22004 var bestPosition = findBestPosition(boxPosition, axis);
22005 styleBox.move(bestPosition.toCSSCompatValues(containerBox));
22006 }
22007
22008 function WebVTT() {
22009 // Nothing
22010 }
22011
22012 // Helper to allow strings to be decoded instead of the default binary utf8 data.
22013 WebVTT.StringDecoder = function() {
22014 return {
22015 decode: function(data) {
22016 if (!data) {
22017 return "";
22018 }
22019 if (typeof data !== "string") {
22020 throw new Error("Error - expected string data.");
22021 }
22022 return decodeURIComponent(encodeURIComponent(data));
22023 }
22024 };
22025 };
22026
22027 WebVTT.convertCueToDOMTree = function(window, cuetext) {
22028 if (!window || !cuetext) {
22029 return null;
22030 }
22031 return parseContent(window, cuetext);
22032 };
22033
22034 var FONT_SIZE_PERCENT = 0.05;
22035 var FONT_STYLE = "sans-serif";
22036 var CUE_BACKGROUND_PADDING = "1.5%";
22037
22038 // Runs the processing model over the cues and regions passed to it.
22039 // @param overlay A block level element (usually a div) that the computed cues
22040 // and regions will be placed into.
22041 WebVTT.processCues = function(window, cues, overlay) {
22042 if (!window || !cues || !overlay) {
22043 return null;
22044 }
22045
22046 // Remove all previous children.
22047 while (overlay.firstChild) {
22048 overlay.removeChild(overlay.firstChild);
22049 }
22050
22051 var paddedOverlay = window.document.createElement("div");
22052 paddedOverlay.style.position = "absolute";
22053 paddedOverlay.style.left = "0";
22054 paddedOverlay.style.right = "0";
22055 paddedOverlay.style.top = "0";
22056 paddedOverlay.style.bottom = "0";
22057 paddedOverlay.style.margin = CUE_BACKGROUND_PADDING;
22058 overlay.appendChild(paddedOverlay);
22059
22060 // Determine if we need to compute the display states of the cues. This could
22061 // be the case if a cue's state has been changed since the last computation or
22062 // if it has not been computed yet.
22063 function shouldCompute(cues) {
22064 for (var i = 0; i < cues.length; i++) {
22065 if (cues[i].hasBeenReset || !cues[i].displayState) {
22066 return true;
22067 }
22068 }
22069 return false;
22070 }
22071
22072 // We don't need to recompute the cues' display states. Just reuse them.
22073 if (!shouldCompute(cues)) {
22074 for (var i = 0; i < cues.length; i++) {
22075 paddedOverlay.appendChild(cues[i].displayState);
22076 }
22077 return;
22078 }
22079
22080 var boxPositions = [],
22081 containerBox = BoxPosition.getSimpleBoxPosition(paddedOverlay),
22082 fontSize = Math.round(containerBox.height * FONT_SIZE_PERCENT * 100) / 100;
22083 var styleOptions = {
22084 font: fontSize + "px " + FONT_STYLE
22085 };
22086
22087 (function() {
22088 var styleBox, cue;
22089
22090 for (var i = 0; i < cues.length; i++) {
22091 cue = cues[i];
22092
22093 // Compute the intial position and styles of the cue div.
22094 styleBox = new CueStyleBox(window, cue, styleOptions);
22095 paddedOverlay.appendChild(styleBox.div);
22096
22097 // Move the cue div to it's correct line position.
22098 moveBoxToLinePosition(window, styleBox, containerBox, boxPositions);
22099
22100 // Remember the computed div so that we don't have to recompute it later
22101 // if we don't have too.
22102 cue.displayState = styleBox.div;
22103
22104 boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox));
22105 }
22106 })();
22107 };
22108
22109 WebVTT.Parser = function(window, vttjs, decoder) {
22110 if (!decoder) {
22111 decoder = vttjs;
22112 vttjs = {};
22113 }
22114 if (!vttjs) {
22115 vttjs = {};
22116 }
22117
22118 this.window = window;
22119 this.vttjs = vttjs;
22120 this.state = "INITIAL";
22121 this.buffer = "";
22122 this.decoder = decoder || new TextDecoder("utf8");
22123 this.regionList = [];
22124 };
22125
22126 WebVTT.Parser.prototype = {
22127 // If the error is a ParsingError then report it to the consumer if
22128 // possible. If it's not a ParsingError then throw it like normal.
22129 reportOrThrowError: function(e) {
22130 if (e instanceof ParsingError) {
22131 this.onparsingerror && this.onparsingerror(e);
22132 } else {
22133 throw e;
22134 }
22135 },
22136 parse: function (data) {
22137 var self = this;
22138
22139 // If there is no data then we won't decode it, but will just try to parse
22140 // whatever is in buffer already. This may occur in circumstances, for
22141 // example when flush() is called.
22142 if (data) {
22143 // Try to decode the data that we received.
22144 self.buffer += self.decoder.decode(data, {stream: true});
22145 }
22146
22147 function collectNextLine() {
22148 var buffer = self.buffer;
22149 var pos = 0;
22150 while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') {
22151 ++pos;
22152 }
22153 var line = buffer.substr(0, pos);
22154 // Advance the buffer early in case we fail below.
22155 if (buffer[pos] === '\r') {
22156 ++pos;
22157 }
22158 if (buffer[pos] === '\n') {
22159 ++pos;
22160 }
22161 self.buffer = buffer.substr(pos);
22162 return line;
22163 }
22164
22165 // 3.4 WebVTT region and WebVTT region settings syntax
22166 function parseRegion(input) {
22167 var settings = new Settings();
22168
22169 parseOptions(input, function (k, v) {
22170 switch (k) {
22171 case "id":
22172 settings.set(k, v);
22173 break;
22174 case "width":
22175 settings.percent(k, v);
22176 break;
22177 case "lines":
22178 settings.integer(k, v);
22179 break;
22180 case "regionanchor":
22181 case "viewportanchor":
22182 var xy = v.split(',');
22183 if (xy.length !== 2) {
22184 break;
22185 }
22186 // We have to make sure both x and y parse, so use a temporary
22187 // settings object here.
22188 var anchor = new Settings();
22189 anchor.percent("x", xy[0]);
22190 anchor.percent("y", xy[1]);
22191 if (!anchor.has("x") || !anchor.has("y")) {
22192 break;
22193 }
22194 settings.set(k + "X", anchor.get("x"));
22195 settings.set(k + "Y", anchor.get("y"));
22196 break;
22197 case "scroll":
22198 settings.alt(k, v, ["up"]);
22199 break;
22200 }
22201 }, /=/, /\s/);
22202
22203 // Create the region, using default values for any values that were not
22204 // specified.
22205 if (settings.has("id")) {
22206 var region = new (self.vttjs.VTTRegion || self.window.VTTRegion)();
22207 region.width = settings.get("width", 100);
22208 region.lines = settings.get("lines", 3);
22209 region.regionAnchorX = settings.get("regionanchorX", 0);
22210 region.regionAnchorY = settings.get("regionanchorY", 100);
22211 region.viewportAnchorX = settings.get("viewportanchorX", 0);
22212 region.viewportAnchorY = settings.get("viewportanchorY", 100);
22213 region.scroll = settings.get("scroll", "");
22214 // Register the region.
22215 self.onregion && self.onregion(region);
22216 // Remember the VTTRegion for later in case we parse any VTTCues that
22217 // reference it.
22218 self.regionList.push({
22219 id: settings.get("id"),
22220 region: region
22221 });
22222 }
22223 }
22224
22225 // 3.2 WebVTT metadata header syntax
22226 function parseHeader(input) {
22227 parseOptions(input, function (k, v) {
22228 switch (k) {
22229 case "Region":
22230 // 3.3 WebVTT region metadata header syntax
22231 parseRegion(v);
22232 break;
22233 }
22234 }, /:/);
22235 }
22236
22237 // 5.1 WebVTT file parsing.
22238 try {
22239 var line;
22240 if (self.state === "INITIAL") {
22241 // We can't start parsing until we have the first line.
22242 if (!/\r\n|\n/.test(self.buffer)) {
22243 return this;
22244 }
22245
22246 line = collectNextLine();
22247
22248 var m = line.match(/^WEBVTT([ \t].*)?$/);
22249 if (!m || !m[0]) {
22250 throw new ParsingError(ParsingError.Errors.BadSignature);
22251 }
22252
22253 self.state = "HEADER";
22254 }
22255
22256 var alreadyCollectedLine = false;
22257 while (self.buffer) {
22258 // We can't parse a line until we have the full line.
22259 if (!/\r\n|\n/.test(self.buffer)) {
22260 return this;
22261 }
22262
22263 if (!alreadyCollectedLine) {
22264 line = collectNextLine();
22265 } else {
22266 alreadyCollectedLine = false;
22267 }
22268
22269 switch (self.state) {
22270 case "HEADER":
22271 // 13-18 - Allow a header (metadata) under the WEBVTT line.
22272 if (/:/.test(line)) {
22273 parseHeader(line);
22274 } else if (!line) {
22275 // An empty line terminates the header and starts the body (cues).
22276 self.state = "ID";
22277 }
22278 continue;
22279 case "NOTE":
22280 // Ignore NOTE blocks.
22281 if (!line) {
22282 self.state = "ID";
22283 }
22284 continue;
22285 case "ID":
22286 // Check for the start of NOTE blocks.
22287 if (/^NOTE($|[ \t])/.test(line)) {
22288 self.state = "NOTE";
22289 break;
22290 }
22291 // 19-29 - Allow any number of line terminators, then initialize new cue values.
22292 if (!line) {
22293 continue;
22294 }
22295 self.cue = new (self.vttjs.VTTCue || self.window.VTTCue)(0, 0, "");
22296 self.state = "CUE";
22297 // 30-39 - Check if self line contains an optional identifier or timing data.
22298 if (line.indexOf("-->") === -1) {
22299 self.cue.id = line;
22300 continue;
22301 }
22302 // Process line as start of a cue.
22303 /*falls through*/
22304 case "CUE":
22305 // 40 - Collect cue timings and settings.
22306 try {
22307 parseCue(line, self.cue, self.regionList);
22308 } catch (e) {
22309 self.reportOrThrowError(e);
22310 // In case of an error ignore rest of the cue.
22311 self.cue = null;
22312 self.state = "BADCUE";
22313 continue;
22314 }
22315 self.state = "CUETEXT";
22316 continue;
22317 case "CUETEXT":
22318 var hasSubstring = line.indexOf("-->") !== -1;
22319 // 34 - If we have an empty line then report the cue.
22320 // 35 - If we have the special substring '-->' then report the cue,
22321 // but do not collect the line as we need to process the current
22322 // one as a new cue.
22323 if (!line || hasSubstring && (alreadyCollectedLine = true)) {
22324 // We are done parsing self cue.
22325 self.oncue && self.oncue(self.cue);
22326 self.cue = null;
22327 self.state = "ID";
22328 continue;
22329 }
22330 if (self.cue.text) {
22331 self.cue.text += "\n";
22332 }
22333 self.cue.text += line;
22334 continue;
22335 case "BADCUE": // BADCUE
22336 // 54-62 - Collect and discard the remaining cue.
22337 if (!line) {
22338 self.state = "ID";
22339 }
22340 continue;
22341 }
22342 }
22343 } catch (e) {
22344 self.reportOrThrowError(e);
22345
22346 // If we are currently parsing a cue, report what we have.
22347 if (self.state === "CUETEXT" && self.cue && self.oncue) {
22348 self.oncue(self.cue);
22349 }
22350 self.cue = null;
22351 // Enter BADWEBVTT state if header was not parsed correctly otherwise
22352 // another exception occurred so enter BADCUE state.
22353 self.state = self.state === "INITIAL" ? "BADWEBVTT" : "BADCUE";
22354 }
22355 return this;
22356 },
22357 flush: function () {
22358 var self = this;
22359 try {
22360 // Finish decoding the stream.
22361 self.buffer += self.decoder.decode();
22362 // Synthesize the end of the current cue or region.
22363 if (self.cue || self.state === "HEADER") {
22364 self.buffer += "\n\n";
22365 self.parse();
22366 }
22367 // If we've flushed, parsed, and we're still on the INITIAL state then
22368 // that means we don't have enough of the stream to parse the first
22369 // line.
22370 if (self.state === "INITIAL") {
22371 throw new ParsingError(ParsingError.Errors.BadSignature);
22372 }
22373 } catch(e) {
22374 self.reportOrThrowError(e);
22375 }
22376 self.onflush && self.onflush();
22377 return this;
22378 }
22379 };
22380
22381 global.WebVTT = WebVTT;
22382
22383}(this, (this.vttjs || {})));