Merge pull request #75 from videojs/feature/switching
Adaptive-switching simulator
Showing
15 changed files
with
1545 additions
and
2 deletions
... | @@ -66,7 +66,8 @@ module.exports = function(grunt) { | ... | @@ -66,7 +66,8 @@ module.exports = function(grunt) { |
66 | '!test/tsSegment.js', | 66 | '!test/tsSegment.js', |
67 | '!test/fixtures/*.js', | 67 | '!test/fixtures/*.js', |
68 | '!test/manifest/**', | 68 | '!test/manifest/**', |
69 | '!test/muxer/**'] | 69 | '!test/muxer/**', |
70 | '!test/switcher/**'] | ||
70 | } | 71 | } |
71 | }, | 72 | }, |
72 | connect: { | 73 | connect: { | ... | ... |
... | @@ -147,10 +147,17 @@ | ... | @@ -147,10 +147,17 @@ |
147 | return; | 147 | return; |
148 | } | 148 | } |
149 | 149 | ||
150 | |||
151 | |||
150 | loader.state = 'SWITCHING_MEDIA'; | 152 | loader.state = 'SWITCHING_MEDIA'; |
151 | 153 | ||
152 | // abort any outstanding playlist refreshes | 154 | // there is already an outstanding playlist request |
153 | if (request) { | 155 | if (request) { |
156 | if (resolveUrl(loader.master.uri, playlist.uri) === request.url) { | ||
157 | // requesting to switch to the same playlist multiple times | ||
158 | // has no effect after the first | ||
159 | return; | ||
160 | } | ||
154 | request.abort(); | 161 | request.abort(); |
155 | request = null; | 162 | request = null; |
156 | } | 163 | } | ... | ... |
... | @@ -563,6 +563,7 @@ xhr = videojs.Hls.xhr = function(url, callback) { | ... | @@ -563,6 +563,7 @@ xhr = videojs.Hls.xhr = function(url, callback) { |
563 | 563 | ||
564 | request = new window.XMLHttpRequest(); | 564 | request = new window.XMLHttpRequest(); |
565 | request.open(options.method, url); | 565 | request.open(options.method, url); |
566 | request.url = url; | ||
566 | 567 | ||
567 | if (options.responseType) { | 568 | if (options.responseType) { |
568 | request.responseType = options.responseType; | 569 | request.responseType = options.responseType; | ... | ... |
... | @@ -349,6 +349,27 @@ | ... | @@ -349,6 +349,27 @@ |
349 | strictEqual(requests.length, 0, 'no requests is sent'); | 349 | strictEqual(requests.length, 0, 'no requests is sent'); |
350 | }); | 350 | }); |
351 | 351 | ||
352 | test('does not abort requests when the same playlist is re-requested', function() { | ||
353 | var loader = new videojs.Hls.PlaylistLoader('master.m3u8'); | ||
354 | requests.pop().respond(200, null, | ||
355 | '#EXTM3U\n' + | ||
356 | '#EXT-X-STREAM-INF:BANDWIDTH=1\n' + | ||
357 | 'low.m3u8\n' + | ||
358 | '#EXT-X-STREAM-INF:BANDWIDTH=2\n' + | ||
359 | 'high.m3u8\n'); | ||
360 | requests.pop().respond(200, null, | ||
361 | '#EXTM3U\n' + | ||
362 | '#EXT-X-MEDIA-SEQUENCE:0\n' + | ||
363 | '#EXTINF:10,\n' + | ||
364 | 'low-0.ts\n' + | ||
365 | '#EXT-X-ENDLIST\n'); | ||
366 | loader.media('high.m3u8'); | ||
367 | loader.media('high.m3u8'); | ||
368 | |||
369 | strictEqual(requests.length, 1, 'made only one request'); | ||
370 | ok(!requests[0].aborted, 'request not aborted'); | ||
371 | }); | ||
372 | |||
352 | test('throws an error if a media switch is initiated too early', function() { | 373 | test('throws an error if a media switch is initiated too early', function() { |
353 | var loader = new videojs.Hls.PlaylistLoader('master.m3u8'); | 374 | var loader = new videojs.Hls.PlaylistLoader('master.m3u8'); |
354 | 375 | ... | ... |
test/switcher/css/main.css
0 → 100644
1 | /* ========================================================================== | ||
2 | HTML5 Boilerplate styles - h5bp.com (generated via initializr.com) | ||
3 | ========================================================================== */ | ||
4 | |||
5 | html, | ||
6 | button, | ||
7 | input, | ||
8 | select, | ||
9 | textarea { | ||
10 | color: #222; | ||
11 | } | ||
12 | |||
13 | body { | ||
14 | font-size: 1em; | ||
15 | line-height: 1.4; | ||
16 | } | ||
17 | |||
18 | ::-moz-selection { | ||
19 | background: #b3d4fc; | ||
20 | text-shadow: none; | ||
21 | } | ||
22 | |||
23 | ::selection { | ||
24 | background: #b3d4fc; | ||
25 | text-shadow: none; | ||
26 | } | ||
27 | |||
28 | hr { | ||
29 | display: block; | ||
30 | height: 1px; | ||
31 | border: 0; | ||
32 | border-top: 1px solid #ccc; | ||
33 | margin: 1em 0; | ||
34 | padding: 0; | ||
35 | } | ||
36 | |||
37 | img { | ||
38 | vertical-align: middle; | ||
39 | } | ||
40 | |||
41 | fieldset { | ||
42 | border: 0; | ||
43 | margin: 0; | ||
44 | padding: 0; | ||
45 | } | ||
46 | |||
47 | textarea { | ||
48 | resize: vertical; | ||
49 | } | ||
50 | |||
51 | .chromeframe { | ||
52 | margin: 0.2em 0; | ||
53 | background: #ccc; | ||
54 | color: #000; | ||
55 | padding: 0.2em 0; | ||
56 | } | ||
57 | |||
58 | |||
59 | /* ===== Initializr Styles ================================================== | ||
60 | Author: Jonathan Verrecchia - verekia.com/initializr/responsive-template | ||
61 | ========================================================================== */ | ||
62 | |||
63 | body { | ||
64 | font: 16px/26px Helvetica, Helvetica Neue, Arial; | ||
65 | } | ||
66 | |||
67 | .wrapper { | ||
68 | width: 90%; | ||
69 | margin: 0 5%; | ||
70 | } | ||
71 | |||
72 | /* =================== | ||
73 | ALL: Orange Theme | ||
74 | =================== */ | ||
75 | |||
76 | .header-container { | ||
77 | border-bottom: 20px solid #e44d26; | ||
78 | } | ||
79 | |||
80 | .footer-container, | ||
81 | .main aside { | ||
82 | border-top: 20px solid #e44d26; | ||
83 | } | ||
84 | |||
85 | .header-container, | ||
86 | .footer-container, | ||
87 | .main aside { | ||
88 | background: #f16529; | ||
89 | } | ||
90 | |||
91 | .title { | ||
92 | color: white; | ||
93 | } | ||
94 | |||
95 | /* ============== | ||
96 | MOBILE: Menu | ||
97 | ============== */ | ||
98 | |||
99 | nav ul { | ||
100 | margin: 0; | ||
101 | padding: 0; | ||
102 | } | ||
103 | |||
104 | nav a { | ||
105 | display: block; | ||
106 | margin-bottom: 10px; | ||
107 | padding: 15px 0; | ||
108 | |||
109 | text-align: center; | ||
110 | text-decoration: none; | ||
111 | font-weight: bold; | ||
112 | |||
113 | color: white; | ||
114 | background: #e44d26; | ||
115 | } | ||
116 | |||
117 | nav a:hover, | ||
118 | nav a:visited { | ||
119 | color: white; | ||
120 | } | ||
121 | |||
122 | nav a:hover { | ||
123 | text-decoration: underline; | ||
124 | } | ||
125 | |||
126 | /* ============== | ||
127 | MOBILE: Main | ||
128 | ============== */ | ||
129 | |||
130 | .main { | ||
131 | padding: 30px 0; | ||
132 | } | ||
133 | |||
134 | .main article h1 { | ||
135 | font-size: 2em; | ||
136 | } | ||
137 | |||
138 | .main aside { | ||
139 | color: white; | ||
140 | padding: 0px 5% 10px; | ||
141 | } | ||
142 | |||
143 | .footer-container footer { | ||
144 | color: white; | ||
145 | padding: 20px 0; | ||
146 | } | ||
147 | |||
148 | /* =============== | ||
149 | ALL: IE Fixes | ||
150 | =============== */ | ||
151 | |||
152 | .ie7 .title { | ||
153 | padding-top: 20px; | ||
154 | } | ||
155 | |||
156 | /* ========================================================================== | ||
157 | Author's custom styles | ||
158 | ========================================================================== */ | ||
159 | |||
160 | section { | ||
161 | clear: both; | ||
162 | } | ||
163 | |||
164 | form label { | ||
165 | display: block; | ||
166 | } | ||
167 | |||
168 | .result-wrapper { | ||
169 | float: left; | ||
170 | margin: 10px 0; | ||
171 | min-width: 422px; | ||
172 | width: 50%; | ||
173 | } | ||
174 | |||
175 | .result { | ||
176 | border: thin solid #aaa; | ||
177 | border-radius: 5px; | ||
178 | font-size: 10px; | ||
179 | line-height: 15px; | ||
180 | margin: 0 5px; | ||
181 | padding: 0 10px; | ||
182 | } | ||
183 | |||
184 | /* ========================================================================== | ||
185 | Media Queries | ||
186 | ========================================================================== */ | ||
187 | |||
188 | @media only screen and (min-width: 480px) { | ||
189 | |||
190 | /* ==================== | ||
191 | INTERMEDIATE: Menu | ||
192 | ==================== */ | ||
193 | |||
194 | nav a { | ||
195 | float: left; | ||
196 | width: 27%; | ||
197 | margin: 0 1.7%; | ||
198 | padding: 25px 2%; | ||
199 | margin-bottom: 0; | ||
200 | } | ||
201 | |||
202 | nav li:first-child a { | ||
203 | margin-left: 0; | ||
204 | } | ||
205 | |||
206 | nav li:last-child a { | ||
207 | margin-right: 0; | ||
208 | } | ||
209 | |||
210 | /* ======================== | ||
211 | INTERMEDIATE: IE Fixes | ||
212 | ======================== */ | ||
213 | |||
214 | nav ul li { | ||
215 | display: inline; | ||
216 | } | ||
217 | |||
218 | .oldie nav a { | ||
219 | margin: 0 0.7%; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | @media only screen and (min-width: 768px) { | ||
224 | |||
225 | /* ==================== | ||
226 | WIDE: CSS3 Effects | ||
227 | ==================== */ | ||
228 | |||
229 | .header-container, | ||
230 | .main aside { | ||
231 | -webkit-box-shadow: 0 5px 10px #aaa; | ||
232 | -moz-box-shadow: 0 5px 10px #aaa; | ||
233 | box-shadow: 0 5px 10px #aaa; | ||
234 | } | ||
235 | |||
236 | /* ============ | ||
237 | WIDE: Menu | ||
238 | ============ */ | ||
239 | |||
240 | .title { | ||
241 | float: left; | ||
242 | } | ||
243 | |||
244 | nav { | ||
245 | float: right; | ||
246 | width: 38%; | ||
247 | } | ||
248 | |||
249 | /* ============ | ||
250 | WIDE: Main | ||
251 | ============ */ | ||
252 | |||
253 | .main article { | ||
254 | float: left; | ||
255 | width: 100%; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | @media only screen and (min-width: 1140px) { | ||
260 | |||
261 | /* =============== | ||
262 | Maximal Width | ||
263 | =============== */ | ||
264 | |||
265 | .wrapper { | ||
266 | width: 1026px; /* 1140px - 10% for margins */ | ||
267 | margin: 0 auto; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | /* ========================================================================== | ||
272 | Helper classes | ||
273 | ========================================================================== */ | ||
274 | |||
275 | .ir { | ||
276 | background-color: transparent; | ||
277 | border: 0; | ||
278 | overflow: hidden; | ||
279 | *text-indent: -9999px; | ||
280 | } | ||
281 | |||
282 | .ir:before { | ||
283 | content: ""; | ||
284 | display: block; | ||
285 | width: 0; | ||
286 | height: 150%; | ||
287 | } | ||
288 | |||
289 | .hidden { | ||
290 | display: none !important; | ||
291 | visibility: hidden; | ||
292 | } | ||
293 | |||
294 | .visuallyhidden { | ||
295 | border: 0; | ||
296 | clip: rect(0 0 0 0); | ||
297 | height: 1px; | ||
298 | margin: -1px; | ||
299 | overflow: hidden; | ||
300 | padding: 0; | ||
301 | position: absolute; | ||
302 | width: 1px; | ||
303 | } | ||
304 | |||
305 | .visuallyhidden.focusable:active, | ||
306 | .visuallyhidden.focusable:focus { | ||
307 | clip: auto; | ||
308 | height: auto; | ||
309 | margin: 0; | ||
310 | overflow: visible; | ||
311 | position: static; | ||
312 | width: auto; | ||
313 | } | ||
314 | |||
315 | .invisible { | ||
316 | visibility: hidden; | ||
317 | } | ||
318 | |||
319 | .clearfix:before, | ||
320 | .clearfix:after { | ||
321 | content: " "; | ||
322 | display: table; | ||
323 | } | ||
324 | |||
325 | .clearfix:after { | ||
326 | clear: both; | ||
327 | } | ||
328 | |||
329 | .clearfix { | ||
330 | *zoom: 1; | ||
331 | } | ||
332 | |||
333 | /* ========================================================================== | ||
334 | Print styles | ||
335 | ========================================================================== */ | ||
336 | |||
337 | @media print { | ||
338 | * { | ||
339 | background: transparent !important; | ||
340 | color: #000 !important; /* Black prints faster: h5bp.com/s */ | ||
341 | box-shadow: none !important; | ||
342 | text-shadow: none !important; | ||
343 | } | ||
344 | |||
345 | a, | ||
346 | a:visited { | ||
347 | text-decoration: underline; | ||
348 | } | ||
349 | |||
350 | a[href]:after { | ||
351 | content: " (" attr(href) ")"; | ||
352 | } | ||
353 | |||
354 | abbr[title]:after { | ||
355 | content: " (" attr(title) ")"; | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * Don't show links for images, or javascript/internal links | ||
360 | */ | ||
361 | |||
362 | .ir a:after, | ||
363 | a[href^="javascript:"]:after, | ||
364 | a[href^="#"]:after { | ||
365 | content: ""; | ||
366 | } | ||
367 | |||
368 | pre, | ||
369 | blockquote { | ||
370 | border: 1px solid #999; | ||
371 | page-break-inside: avoid; | ||
372 | } | ||
373 | |||
374 | thead { | ||
375 | display: table-header-group; /* h5bp.com/t */ | ||
376 | } | ||
377 | |||
378 | tr, | ||
379 | img { | ||
380 | page-break-inside: avoid; | ||
381 | } | ||
382 | |||
383 | img { | ||
384 | max-width: 100% !important; | ||
385 | } | ||
386 | |||
387 | @page { | ||
388 | margin: 0.5cm; | ||
389 | } | ||
390 | |||
391 | p, | ||
392 | h2, | ||
393 | h3 { | ||
394 | orphans: 3; | ||
395 | widows: 3; | ||
396 | } | ||
397 | |||
398 | h2, | ||
399 | h3 { | ||
400 | page-break-after: avoid; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | /* ========================================================================== | ||
405 | Simulation Chart | ||
406 | ========================================================================== */ | ||
407 | |||
408 | .axis path, | ||
409 | .axis line { | ||
410 | fill: none; | ||
411 | stroke: #000; | ||
412 | shape-rendering: crispEdges; | ||
413 | } | ||
414 | |||
415 | .x.axis path { | ||
416 | display: none; | ||
417 | } | ||
418 | |||
419 | .line { | ||
420 | fill: none; | ||
421 | stroke-width: 1.5px; | ||
422 | } | ||
423 | .line.bandwidth { | ||
424 | stroke: steelblue; | ||
425 | } | ||
426 | .line.buffered { | ||
427 | stroke: #2ca02c; | ||
428 | opacity: 0.25; | ||
429 | } | ||
430 | .line.bitrate { | ||
431 | stroke: #999; | ||
432 | opacity: 0.5; | ||
433 | stroke-dasharray: 5, 5; | ||
434 | } | ||
435 | |||
436 | .timeline { | ||
437 | color: #888; | ||
438 | height: 500px; | ||
439 | margin: 0 auto; | ||
440 | text-align: center; | ||
441 | width: 960px; | ||
442 | } | ||
443 | |||
444 | /* ========================================================================== | ||
445 | Simulation Parameters | ||
446 | ========================================================================== */ | ||
447 | |||
448 | .network-timeline label { | ||
449 | display: inline; | ||
450 | } | ||
451 | .network-timeline .time { | ||
452 | width: 50px; | ||
453 | } | ||
454 | .network-timeline .bandwidth { | ||
455 | width: 140px; | ||
456 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
test/switcher/css/normalize.css
0 → 100644
1 | /*! normalize.css v1.1.2 | MIT License | git.io/normalize */ | ||
2 | |||
3 | /* ========================================================================== | ||
4 | HTML5 display definitions | ||
5 | ========================================================================== */ | ||
6 | |||
7 | /** | ||
8 | * Correct `block` display not defined in IE 6/7/8/9 and Firefox 3. | ||
9 | */ | ||
10 | |||
11 | article, | ||
12 | aside, | ||
13 | details, | ||
14 | figcaption, | ||
15 | figure, | ||
16 | footer, | ||
17 | header, | ||
18 | hgroup, | ||
19 | main, | ||
20 | nav, | ||
21 | section, | ||
22 | summary { | ||
23 | display: block; | ||
24 | } | ||
25 | |||
26 | /** | ||
27 | * Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. | ||
28 | */ | ||
29 | |||
30 | audio, | ||
31 | canvas, | ||
32 | video { | ||
33 | display: inline-block; | ||
34 | *display: inline; | ||
35 | *zoom: 1; | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * Prevent modern browsers from displaying `audio` without controls. | ||
40 | * Remove excess height in iOS 5 devices. | ||
41 | */ | ||
42 | |||
43 | audio:not([controls]) { | ||
44 | display: none; | ||
45 | height: 0; | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Address styling not present in IE 7/8/9, Firefox 3, and Safari 4. | ||
50 | * Known issue: no IE 6 support. | ||
51 | */ | ||
52 | |||
53 | [hidden] { | ||
54 | display: none; | ||
55 | } | ||
56 | |||
57 | /* ========================================================================== | ||
58 | Base | ||
59 | ========================================================================== */ | ||
60 | |||
61 | /** | ||
62 | * 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using | ||
63 | * `em` units. | ||
64 | * 2. Prevent iOS text size adjust after orientation change, without disabling | ||
65 | * user zoom. | ||
66 | */ | ||
67 | |||
68 | html { | ||
69 | font-size: 100%; /* 1 */ | ||
70 | -ms-text-size-adjust: 100%; /* 2 */ | ||
71 | -webkit-text-size-adjust: 100%; /* 2 */ | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * Address `font-family` inconsistency between `textarea` and other form | ||
76 | * elements. | ||
77 | */ | ||
78 | |||
79 | html, | ||
80 | button, | ||
81 | input, | ||
82 | select, | ||
83 | textarea { | ||
84 | font-family: sans-serif; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Address margins handled incorrectly in IE 6/7. | ||
89 | */ | ||
90 | |||
91 | body { | ||
92 | margin: 0; | ||
93 | } | ||
94 | |||
95 | /* ========================================================================== | ||
96 | Links | ||
97 | ========================================================================== */ | ||
98 | |||
99 | /** | ||
100 | * Address `outline` inconsistency between Chrome and other browsers. | ||
101 | */ | ||
102 | |||
103 | a:focus { | ||
104 | outline: thin dotted; | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * Improve readability when focused and also mouse hovered in all browsers. | ||
109 | */ | ||
110 | |||
111 | a:active, | ||
112 | a:hover { | ||
113 | outline: 0; | ||
114 | } | ||
115 | |||
116 | /* ========================================================================== | ||
117 | Typography | ||
118 | ========================================================================== */ | ||
119 | |||
120 | /** | ||
121 | * Address font sizes and margins set differently in IE 6/7. | ||
122 | * Address font sizes within `section` and `article` in Firefox 4+, Safari 5, | ||
123 | * and Chrome. | ||
124 | */ | ||
125 | |||
126 | h1 { | ||
127 | font-size: 2em; | ||
128 | margin: 0.67em 0; | ||
129 | } | ||
130 | |||
131 | h2 { | ||
132 | font-size: 1.5em; | ||
133 | margin: 0.83em 0; | ||
134 | } | ||
135 | |||
136 | h3 { | ||
137 | font-size: 1.17em; | ||
138 | margin: 1em 0; | ||
139 | } | ||
140 | |||
141 | h4 { | ||
142 | font-size: 1em; | ||
143 | margin: 1.33em 0; | ||
144 | } | ||
145 | |||
146 | h5 { | ||
147 | font-size: 0.83em; | ||
148 | margin: 1.67em 0; | ||
149 | } | ||
150 | |||
151 | h6 { | ||
152 | font-size: 0.67em; | ||
153 | margin: 2.33em 0; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * Address styling not present in IE 7/8/9, Safari 5, and Chrome. | ||
158 | */ | ||
159 | |||
160 | abbr[title] { | ||
161 | border-bottom: 1px dotted; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome. | ||
166 | */ | ||
167 | |||
168 | b, | ||
169 | strong { | ||
170 | font-weight: bold; | ||
171 | } | ||
172 | |||
173 | blockquote { | ||
174 | margin: 1em 40px; | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * Address styling not present in Safari 5 and Chrome. | ||
179 | */ | ||
180 | |||
181 | dfn { | ||
182 | font-style: italic; | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * Address differences between Firefox and other browsers. | ||
187 | * Known issue: no IE 6/7 normalization. | ||
188 | */ | ||
189 | |||
190 | hr { | ||
191 | -moz-box-sizing: content-box; | ||
192 | box-sizing: content-box; | ||
193 | height: 0; | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * Address styling not present in IE 6/7/8/9. | ||
198 | */ | ||
199 | |||
200 | mark { | ||
201 | background: #ff0; | ||
202 | color: #000; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * Address margins set differently in IE 6/7. | ||
207 | */ | ||
208 | |||
209 | p, | ||
210 | pre { | ||
211 | margin: 1em 0; | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. | ||
216 | */ | ||
217 | |||
218 | code, | ||
219 | kbd, | ||
220 | pre, | ||
221 | samp { | ||
222 | font-family: monospace, serif; | ||
223 | _font-family: 'courier new', monospace; | ||
224 | font-size: 1em; | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * Improve readability of pre-formatted text in all browsers. | ||
229 | */ | ||
230 | |||
231 | pre { | ||
232 | white-space: pre; | ||
233 | white-space: pre-wrap; | ||
234 | word-wrap: break-word; | ||
235 | } | ||
236 | |||
237 | /** | ||
238 | * Address CSS quotes not supported in IE 6/7. | ||
239 | */ | ||
240 | |||
241 | q { | ||
242 | quotes: none; | ||
243 | } | ||
244 | |||
245 | /** | ||
246 | * Address `quotes` property not supported in Safari 4. | ||
247 | */ | ||
248 | |||
249 | q:before, | ||
250 | q:after { | ||
251 | content: ''; | ||
252 | content: none; | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * Address inconsistent and variable font size in all browsers. | ||
257 | */ | ||
258 | |||
259 | small { | ||
260 | font-size: 80%; | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. | ||
265 | */ | ||
266 | |||
267 | sub, | ||
268 | sup { | ||
269 | font-size: 75%; | ||
270 | line-height: 0; | ||
271 | position: relative; | ||
272 | vertical-align: baseline; | ||
273 | } | ||
274 | |||
275 | sup { | ||
276 | top: -0.5em; | ||
277 | } | ||
278 | |||
279 | sub { | ||
280 | bottom: -0.25em; | ||
281 | } | ||
282 | |||
283 | /* ========================================================================== | ||
284 | Lists | ||
285 | ========================================================================== */ | ||
286 | |||
287 | /** | ||
288 | * Address margins set differently in IE 6/7. | ||
289 | */ | ||
290 | |||
291 | dl, | ||
292 | menu, | ||
293 | ol, | ||
294 | ul { | ||
295 | margin: 1em 0; | ||
296 | } | ||
297 | |||
298 | dd { | ||
299 | margin: 0 0 0 40px; | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * Address paddings set differently in IE 6/7. | ||
304 | */ | ||
305 | |||
306 | menu, | ||
307 | ol, | ||
308 | ul { | ||
309 | padding: 0 0 0 40px; | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * Correct list images handled incorrectly in IE 7. | ||
314 | */ | ||
315 | |||
316 | nav ul, | ||
317 | nav ol { | ||
318 | list-style: none; | ||
319 | list-style-image: none; | ||
320 | } | ||
321 | |||
322 | /* ========================================================================== | ||
323 | Embedded content | ||
324 | ========================================================================== */ | ||
325 | |||
326 | /** | ||
327 | * 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3. | ||
328 | * 2. Improve image quality when scaled in IE 7. | ||
329 | */ | ||
330 | |||
331 | img { | ||
332 | border: 0; /* 1 */ | ||
333 | -ms-interpolation-mode: bicubic; /* 2 */ | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * Correct overflow displayed oddly in IE 9. | ||
338 | */ | ||
339 | |||
340 | svg:not(:root) { | ||
341 | overflow: hidden; | ||
342 | } | ||
343 | |||
344 | /* ========================================================================== | ||
345 | Figures | ||
346 | ========================================================================== */ | ||
347 | |||
348 | /** | ||
349 | * Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11. | ||
350 | */ | ||
351 | |||
352 | figure { | ||
353 | margin: 0; | ||
354 | } | ||
355 | |||
356 | /* ========================================================================== | ||
357 | Forms | ||
358 | ========================================================================== */ | ||
359 | |||
360 | /** | ||
361 | * Correct margin displayed oddly in IE 6/7. | ||
362 | */ | ||
363 | |||
364 | form { | ||
365 | margin: 0; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * Define consistent border, margin, and padding. | ||
370 | */ | ||
371 | |||
372 | fieldset { | ||
373 | border: 1px solid #c0c0c0; | ||
374 | margin: 0 2px; | ||
375 | padding: 0.35em 0.625em 0.75em; | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * 1. Correct color not being inherited in IE 6/7/8/9. | ||
380 | * 2. Correct text not wrapping in Firefox 3. | ||
381 | * 3. Correct alignment displayed oddly in IE 6/7. | ||
382 | */ | ||
383 | |||
384 | legend { | ||
385 | border: 0; /* 1 */ | ||
386 | padding: 0; | ||
387 | white-space: normal; /* 2 */ | ||
388 | *margin-left: -7px; /* 3 */ | ||
389 | } | ||
390 | |||
391 | /** | ||
392 | * 1. Correct font size not being inherited in all browsers. | ||
393 | * 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5, | ||
394 | * and Chrome. | ||
395 | * 3. Improve appearance and consistency in all browsers. | ||
396 | */ | ||
397 | |||
398 | button, | ||
399 | input, | ||
400 | select, | ||
401 | textarea { | ||
402 | font-size: 100%; /* 1 */ | ||
403 | margin: 0; /* 2 */ | ||
404 | vertical-align: baseline; /* 3 */ | ||
405 | *vertical-align: middle; /* 3 */ | ||
406 | } | ||
407 | |||
408 | /** | ||
409 | * Address Firefox 3+ setting `line-height` on `input` using `!important` in | ||
410 | * the UA stylesheet. | ||
411 | */ | ||
412 | |||
413 | button, | ||
414 | input { | ||
415 | line-height: normal; | ||
416 | } | ||
417 | |||
418 | /** | ||
419 | * Address inconsistent `text-transform` inheritance for `button` and `select`. | ||
420 | * All other form control elements do not inherit `text-transform` values. | ||
421 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+. | ||
422 | * Correct `select` style inheritance in Firefox 4+ and Opera. | ||
423 | */ | ||
424 | |||
425 | button, | ||
426 | select { | ||
427 | text-transform: none; | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` | ||
432 | * and `video` controls. | ||
433 | * 2. Correct inability to style clickable `input` types in iOS. | ||
434 | * 3. Improve usability and consistency of cursor style between image-type | ||
435 | * `input` and others. | ||
436 | * 4. Remove inner spacing in IE 7 without affecting normal text inputs. | ||
437 | * Known issue: inner spacing remains in IE 6. | ||
438 | */ | ||
439 | |||
440 | button, | ||
441 | html input[type="button"], /* 1 */ | ||
442 | input[type="reset"], | ||
443 | input[type="submit"] { | ||
444 | -webkit-appearance: button; /* 2 */ | ||
445 | cursor: pointer; /* 3 */ | ||
446 | *overflow: visible; /* 4 */ | ||
447 | } | ||
448 | |||
449 | /** | ||
450 | * Re-set default cursor for disabled elements. | ||
451 | */ | ||
452 | |||
453 | button[disabled], | ||
454 | html input[disabled] { | ||
455 | cursor: default; | ||
456 | } | ||
457 | |||
458 | /** | ||
459 | * 1. Address box sizing set to content-box in IE 8/9. | ||
460 | * 2. Remove excess padding in IE 8/9. | ||
461 | * 3. Remove excess padding in IE 7. | ||
462 | * Known issue: excess padding remains in IE 6. | ||
463 | */ | ||
464 | |||
465 | input[type="checkbox"], | ||
466 | input[type="radio"] { | ||
467 | box-sizing: border-box; /* 1 */ | ||
468 | padding: 0; /* 2 */ | ||
469 | *height: 13px; /* 3 */ | ||
470 | *width: 13px; /* 3 */ | ||
471 | } | ||
472 | |||
473 | /** | ||
474 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. | ||
475 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome | ||
476 | * (include `-moz` to future-proof). | ||
477 | */ | ||
478 | |||
479 | input[type="search"] { | ||
480 | -webkit-appearance: textfield; /* 1 */ | ||
481 | -moz-box-sizing: content-box; | ||
482 | -webkit-box-sizing: content-box; /* 2 */ | ||
483 | box-sizing: content-box; | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * Remove inner padding and search cancel button in Safari 5 and Chrome | ||
488 | * on OS X. | ||
489 | */ | ||
490 | |||
491 | input[type="search"]::-webkit-search-cancel-button, | ||
492 | input[type="search"]::-webkit-search-decoration { | ||
493 | -webkit-appearance: none; | ||
494 | } | ||
495 | |||
496 | /** | ||
497 | * Remove inner padding and border in Firefox 3+. | ||
498 | */ | ||
499 | |||
500 | button::-moz-focus-inner, | ||
501 | input::-moz-focus-inner { | ||
502 | border: 0; | ||
503 | padding: 0; | ||
504 | } | ||
505 | |||
506 | /** | ||
507 | * 1. Remove default vertical scrollbar in IE 6/7/8/9. | ||
508 | * 2. Improve readability and alignment in all browsers. | ||
509 | */ | ||
510 | |||
511 | textarea { | ||
512 | overflow: auto; /* 1 */ | ||
513 | vertical-align: top; /* 2 */ | ||
514 | } | ||
515 | |||
516 | /* ========================================================================== | ||
517 | Tables | ||
518 | ========================================================================== */ | ||
519 | |||
520 | /** | ||
521 | * Remove most spacing between table cells. | ||
522 | */ | ||
523 | |||
524 | table { | ||
525 | border-collapse: collapse; | ||
526 | border-spacing: 0; | ||
527 | } |
test/switcher/css/normalize.min.css
0 → 100644
1 | /*! normalize.css v1.1.2 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}h2{font-size:1.5em;margin:.83em 0}h3{font-size:1.17em;margin:1em 0}h4{font-size:1em;margin:1.33em 0}h5{font-size:.83em;margin:1.67em 0}h6{font-size:.67em;margin:2.33em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:1em 40px}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}p,pre{margin:1em 0}code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:'';content:none}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}dl,menu,ol,ul{margin:1em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0;white-space:normal;*margin-left:-7px}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
test/switcher/index.html
0 → 100644
1 | <!DOCTYPE html> | ||
2 | <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> | ||
3 | <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> | ||
4 | <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> | ||
5 | <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--> | ||
6 | <head> | ||
7 | <meta charset="utf-8"> | ||
8 | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | ||
9 | <title>Playlist Switching Simulator</title> | ||
10 | <meta name="description" content=""> | ||
11 | <meta name="viewport" content="width=device-width"> | ||
12 | |||
13 | <link rel="stylesheet" href="css/normalize.min.css"> | ||
14 | <link rel="stylesheet" href="css/main.css"> | ||
15 | <link rel="stylesheet" href="../../node_modules/video.js/dist/video-js/video-js.css"> | ||
16 | |||
17 | <script src="js/vendor/modernizr-2.6.2.min.js"></script> | ||
18 | </head> | ||
19 | <body> | ||
20 | <!--[if lt IE 7]> | ||
21 | <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p> | ||
22 | <![endif]--> | ||
23 | |||
24 | <div class="header-container"> | ||
25 | <header class="wrapper clearfix"> | ||
26 | <h1 class="title">Playlist Switching Simulator</h1> | ||
27 | </header> | ||
28 | </div> | ||
29 | |||
30 | <div class="main-container"> | ||
31 | <div class="main wrapper clearfix"> | ||
32 | |||
33 | <article> | ||
34 | <header> | ||
35 | <p> | ||
36 | You can use this page to visualize the behavior of the | ||
37 | playlist switcher under different network conditions. It | ||
38 | can helpful to understand how tweaks to the switching | ||
39 | logic will affect playback. | ||
40 | </p> | ||
41 | <p> | ||
42 | Flash security restrictions prevent this page from running | ||
43 | over the file protocol. Run <code>grunt connect</code> and | ||
44 | then <a href="http://localhost:9999/test/switcher">reload.</a> | ||
45 | </p> | ||
46 | </header> | ||
47 | <section> | ||
48 | <h2>Timeline</h2> | ||
49 | <p class=timeline>Simulation results will show up here</p> | ||
50 | <button id=run-simulation type=submit>Run Simulation</button> | ||
51 | </section> | ||
52 | <section> | ||
53 | <h2>Parameters</h2> | ||
54 | <form id=parameters> | ||
55 | <ol class=network-timeline> | ||
56 | <li> | ||
57 | <label> | ||
58 | After <input name=time0 class=time type=number value=0 min=0> seconds, | ||
59 | </label> | ||
60 | <label> | ||
61 | the link capacity is <input name=bandwidth0 class=bandwidth type=number value=921600> bits per second | ||
62 | </label> | ||
63 | </li> | ||
64 | <li> | ||
65 | <label> | ||
66 | After <input name=time1 class=time type=number value=150 min=0> seconds, | ||
67 | </label> | ||
68 | <label> | ||
69 | the link capacity is <input name=bandwidth1 class=bandwidth type=number value=450560> bits per second | ||
70 | </label> | ||
71 | </li> | ||
72 | <li> | ||
73 | <label> | ||
74 | After <input name=time2 class=time type=number value=600 min=0> seconds, | ||
75 | </label> | ||
76 | <label> | ||
77 | the link capacity is <input name=bandwidth2 class=bandwidth type=number value=1843200> bits per second | ||
78 | </label> | ||
79 | </li> | ||
80 | </ol> | ||
81 | <p> | ||
82 | You can simulate more complex network conditions by | ||
83 | changing the bandwidth during the run. Start a new time | ||
84 | period and then define its starting time and link | ||
85 | capacity. | ||
86 | <button type=button class=add-time-period>Add time period</button> | ||
87 | </p> | ||
88 | The video is available at | ||
89 | <ul> | ||
90 | <li><input class=bitrate type=number min=1 value=65536> bits per second</li> | ||
91 | <li><input class=bitrate type=number min=1 value=153600> bits per second</li> | ||
92 | <li><input class=bitrate type=number min=1 value=450560> bits per second</li> | ||
93 | <li><input class=bitrate type=number min=1 value=921600> bits per second</li> | ||
94 | <li><input class=bitrate type=number min=1 value=1536000> bits per second</li> | ||
95 | </ul> | ||
96 | </form> | ||
97 | </section> | ||
98 | </article> | ||
99 | |||
100 | </div> <!-- #main --> | ||
101 | </div> <!-- #main-container --> | ||
102 | |||
103 | <div class="footer-container"> | ||
104 | <footer class="wrapper"> | ||
105 | <h3>videojs-contrib-hls</h3> | ||
106 | </footer> | ||
107 | </div> | ||
108 | <div id=fixture></div> | ||
109 | <script src="../../node_modules/sinon/lib/sinon.js"></script> | ||
110 | <script src="../../node_modules/sinon/lib/sinon/util/event.js"></script> | ||
111 | <script src="../../node_modules/sinon/lib/sinon/util/fake_xml_http_request.js"></script> | ||
112 | <script src="../../node_modules/sinon/lib/sinon/util/xhr_ie.js"></script> | ||
113 | <script src="../../node_modules/sinon/lib/sinon/util/fake_timers.js"></script> | ||
114 | <script src="js/vendor/d3.min.js"></script> | ||
115 | |||
116 | <script src="../../node_modules/video.js/dist/video-js/video.js"></script> | ||
117 | <script src="../../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script> | ||
118 | <script src="../../src/videojs-hls.js"></script> | ||
119 | <script src="../../src/stream.js"></script> | ||
120 | <script src="../../src/m3u8/m3u8-parser.js"></script> | ||
121 | <script src="../../src/playlist-loader.js"></script> | ||
122 | |||
123 | <script src="js/switcher.js"></script> | ||
124 | </body> | ||
125 | </html> |
test/switcher/js/main.js
0 → 100644
test/switcher/js/switcher.js
0 → 100644
1 | (function(window, document) { | ||
2 | 'use strict'; | ||
3 | var segmentDuration = 9, // seconds | ||
4 | segmentCount = 100, | ||
5 | duration = segmentDuration * segmentCount, | ||
6 | propagationDelay = 1, | ||
7 | |||
8 | runSimulation, | ||
9 | playlistResponse, | ||
10 | player, | ||
11 | runButton, | ||
12 | parameters, | ||
13 | addTimePeriod, | ||
14 | networkTimeline, | ||
15 | timePeriod, | ||
16 | timeline, | ||
17 | |||
18 | displayTimeline; | ||
19 | |||
20 | // mock out the environment and dependencies | ||
21 | videojs.options.flash.swf = '../../node_modules/video.js/dist/video-js/video-js.swf'; | ||
22 | videojs.Hls.SegmentParser = function() { | ||
23 | this.getFlvHeader = function() { | ||
24 | return new Uint8Array([]); | ||
25 | }; | ||
26 | this.parseSegmentBinaryData = function() {}; | ||
27 | this.flushTags = function() {}; | ||
28 | this.tagsAvailable = function() { | ||
29 | return false; | ||
30 | }; | ||
31 | }; | ||
32 | |||
33 | // a dynamic number of time-bandwidth pairs may be defined to drive the simulation | ||
34 | addTimePeriod = document.querySelector('.add-time-period'); | ||
35 | networkTimeline = document.querySelector('.network-timeline'); | ||
36 | timePeriod = networkTimeline.cloneNode(true); | ||
37 | addTimePeriod.addEventListener('click', function() { | ||
38 | var clone = timePeriod.cloneNode(true), | ||
39 | fragment = document.createDocumentFragment(), | ||
40 | count = networkTimeline.querySelectorAll('input.bandwidth').length, | ||
41 | time = clone.querySelector('.time'), | ||
42 | bandwidth = clone.querySelector('input.bandwidth'); | ||
43 | |||
44 | time.name = 'time' + count; | ||
45 | bandwidth.name = 'bandwidth' + count; | ||
46 | while (clone.childNodes.length) { | ||
47 | fragment.appendChild(clone.childNodes[0]); | ||
48 | } | ||
49 | networkTimeline.appendChild(fragment); | ||
50 | }); | ||
51 | |||
52 | // collect the simulation parameters | ||
53 | parameters = function() { | ||
54 | var times = Array.prototype.slice.call(document.querySelectorAll('.time')), | ||
55 | bandwidths = document.querySelectorAll('input.bandwidth'), | ||
56 | playlists = Array.prototype.slice.call(document.querySelectorAll('input.bitrate')); | ||
57 | |||
58 | return { | ||
59 | playlists: playlists.map(function(input) { | ||
60 | return +input.value; | ||
61 | }), | ||
62 | bandwidths: times.reduce(function(conditions, time, i) { | ||
63 | return conditions.concat({ | ||
64 | time: +time.value, | ||
65 | bandwidth: +bandwidths[i].value | ||
66 | }); | ||
67 | }, []) | ||
68 | }; | ||
69 | }; | ||
70 | |||
71 | // send a mock playlist response | ||
72 | playlistResponse = function(bitrate) { | ||
73 | var i = segmentCount, | ||
74 | response = '#EXTM3U\n'; | ||
75 | |||
76 | while (i--) { | ||
77 | response += '#EXTINF:' + segmentDuration + ',\n'; | ||
78 | response += bitrate + '-' + (segmentCount - i) + '\n'; | ||
79 | } | ||
80 | response += '#EXT-X-ENDLIST\n'; | ||
81 | |||
82 | return response; | ||
83 | }; | ||
84 | |||
85 | // run the simulation | ||
86 | runSimulation = function(options, done) { | ||
87 | var results = { | ||
88 | bandwidth: [], | ||
89 | playlists: [], | ||
90 | buffered: [], | ||
91 | options: options | ||
92 | }, | ||
93 | bandwidths = options.bandwidths, | ||
94 | fixture = document.getElementById('fixture'), | ||
95 | |||
96 | realSetTimeout = window.setTimeout, | ||
97 | clock, | ||
98 | fakeXhr, | ||
99 | requests, | ||
100 | video, | ||
101 | t = 0, | ||
102 | i = 0; | ||
103 | |||
104 | // clean up the last run if necessary | ||
105 | if (player) { | ||
106 | player.dispose(); | ||
107 | }; | ||
108 | |||
109 | // mock out the environment | ||
110 | clock = sinon.useFakeTimers(); | ||
111 | fakeXhr = sinon.useFakeXMLHttpRequest(); | ||
112 | requests = []; | ||
113 | fakeXhr.onCreate = function(xhr) { | ||
114 | xhr.startTime = +new Date(); | ||
115 | xhr.delivered = 0; | ||
116 | requests.push(xhr); | ||
117 | }; | ||
118 | |||
119 | // initialize the HLS tech | ||
120 | fixture.innerHTML = ''; | ||
121 | video = document.createElement('video'); | ||
122 | video.className = 'video-js vjs-default-skin'; | ||
123 | video.controls = true; | ||
124 | fixture.appendChild(video); | ||
125 | player = videojs(video, { | ||
126 | techOrder: ['hls'], | ||
127 | sources: [{ | ||
128 | src: 'http://example.com/master.m3u8', | ||
129 | type: 'application/x-mpegurl' | ||
130 | }] | ||
131 | }); | ||
132 | |||
133 | player.ready(function() { | ||
134 | // run next tick so that Flash doesn't swallow exceptions | ||
135 | realSetTimeout(function() { | ||
136 | var master = '#EXTM3U\n' + | ||
137 | options.playlists.reduce(function(playlists, value) { | ||
138 | return playlists + | ||
139 | '#EXT-X-STREAM-INF:BANDWIDTH=' + value + '\n' + | ||
140 | 'playlist-' + value + '\n'; | ||
141 | }, ''), | ||
142 | buffered = 0, | ||
143 | currentTime = 0; | ||
144 | |||
145 | // mock out buffered and currentTime | ||
146 | player.buffered = function() { | ||
147 | return videojs.createTimeRange(0, currentTime + buffered); | ||
148 | }; | ||
149 | player.currentTime = function() { | ||
150 | return currentTime; | ||
151 | }; | ||
152 | |||
153 | // respond to the playlist requests | ||
154 | requests.shift().respond(200, null, master); | ||
155 | requests[0].respond(200, null, playlistResponse(+requests[0].url.match(/\d+$/))); | ||
156 | requests.shift(); | ||
157 | |||
158 | bandwidths.sort(function(left, right) { | ||
159 | return left.time - right.time; | ||
160 | }); | ||
161 | |||
162 | // pre-calculate the bandwidth at each second | ||
163 | for (t = i = 0; t < duration; t++) { | ||
164 | while (bandwidths[i + 1] && bandwidths[i + 1].time <= t) { | ||
165 | i++; | ||
166 | } | ||
167 | results.bandwidth.push({ | ||
168 | time: t, | ||
169 | bandwidth: bandwidths[i].bandwidth | ||
170 | }); | ||
171 | } | ||
172 | |||
173 | // advance time and collect simulation results | ||
174 | for (t = 0; t < duration; clock.tick(1000), t++) { | ||
175 | // schedule response deliveries | ||
176 | while (requests.length) { | ||
177 | (function(request) { | ||
178 | var segmentSize; | ||
179 | |||
180 | // playlist responses | ||
181 | if (/playlist-\d+$/.test(request.url)) { | ||
182 | // for simplicity, playlist responses have zero trasmission time | ||
183 | return setTimeout(function() { | ||
184 | request.respond(200, null, playlistResponse(+request.url.match(/\d+$/))); | ||
185 | }, propagationDelay * 1000); | ||
186 | } | ||
187 | |||
188 | // segment responses | ||
189 | segmentSize = +request.url.match(/(\d+)-\d+$/)[1] * segmentDuration; | ||
190 | // segment response headers arrive after the propogation delay | ||
191 | setTimeout(function() { | ||
192 | var arrival = Math.ceil(+new Date() * 0.001); | ||
193 | results.playlists.push({ | ||
194 | time: arrival, | ||
195 | bitrate: +request.url.match(/(\d+)-\d+$/)[1] | ||
196 | }); | ||
197 | request.setResponseHeaders({ | ||
198 | 'Content-Type': 'video/mp2t' | ||
199 | }); | ||
200 | |||
201 | results.bandwidth.slice(arrival).every(function(value, i) { | ||
202 | var remaining = segmentSize - request.delivered; | ||
203 | if (remaining - value.bandwidth <= 0) { | ||
204 | // send the response body once all bytes have been delivered | ||
205 | setTimeout(function() { | ||
206 | buffered += segmentDuration; | ||
207 | request.status = 200; | ||
208 | request.response = new Uint8Array(segmentSize * 0.125); | ||
209 | request.setResponseBody(''); | ||
210 | }, ((remaining / value.bandwidth) + i) * 1000); | ||
211 | return false; | ||
212 | } | ||
213 | // record the bits for this tick | ||
214 | request.delivered += value.bandwidth; | ||
215 | return true; | ||
216 | }); | ||
217 | }, propagationDelay * 1000); | ||
218 | })(requests.shift()); | ||
219 | } | ||
220 | |||
221 | results.buffered.push({ | ||
222 | time: t, | ||
223 | buffered: buffered | ||
224 | }); | ||
225 | |||
226 | // simulate playback | ||
227 | if (buffered > 0) { | ||
228 | buffered--; | ||
229 | currentTime++; | ||
230 | } | ||
231 | player.trigger('timeupdate'); | ||
232 | } | ||
233 | |||
234 | // restore the environment | ||
235 | clock.restore(); | ||
236 | fakeXhr.restore(); | ||
237 | |||
238 | done(null, results); | ||
239 | }, 0); | ||
240 | }); | ||
241 | }; | ||
242 | runButton = document.getElementById('run-simulation'); | ||
243 | runButton.addEventListener('click', function() { | ||
244 | runSimulation(parameters(), displayTimeline); | ||
245 | }); | ||
246 | |||
247 | // render the timeline with d3 | ||
248 | timeline = document.querySelector('.timeline'); | ||
249 | timeline.innerHTML = ''; | ||
250 | (function() { | ||
251 | var margin = { | ||
252 | top: 20, | ||
253 | right: 80, | ||
254 | bottom: 30, | ||
255 | left: 50 | ||
256 | }, | ||
257 | width = 960 - margin.left - margin.right, | ||
258 | height = 500 - margin.top - margin.bottom, | ||
259 | svg; | ||
260 | svg = d3.select('.timeline').append('svg') | ||
261 | .attr('width', width + margin.left + margin.right) | ||
262 | .attr('height', height + margin.top + margin.bottom) | ||
263 | .append('g') | ||
264 | .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); | ||
265 | |||
266 | displayTimeline = function(error, data) { | ||
267 | var x = d3.scale.linear().range([0, width]), | ||
268 | y = d3.scale.linear().range([height, 0]), | ||
269 | y0 = d3.scale.linear().range([height, 0]), | ||
270 | |||
271 | timeAxis = d3.svg.axis().scale(x).orient('bottom'), | ||
272 | tickFormatter = d3.format(',.0f'), | ||
273 | bitrateAxis = d3.svg.axis() | ||
274 | .scale(y) | ||
275 | .tickFormat(function(value) { | ||
276 | return tickFormatter(value / 1024); | ||
277 | }) | ||
278 | .orient('left'), | ||
279 | |||
280 | bandwidthLine = d3.svg.line() | ||
281 | .interpolate('basis') | ||
282 | .x(function(data) { | ||
283 | return x(data.time); | ||
284 | }) | ||
285 | .y(function(data) { | ||
286 | return y(data.bandwidth); | ||
287 | }), | ||
288 | bufferedLine = d3.svg.line() | ||
289 | .interpolate('basis') | ||
290 | .x(function(data) { | ||
291 | return x(data.time); | ||
292 | }) | ||
293 | .y(function(data) { | ||
294 | return y0(data.buffered); | ||
295 | }); | ||
296 | |||
297 | x.domain(d3.extent(data.bandwidth, function(data) { | ||
298 | return data.time; | ||
299 | })); | ||
300 | y.domain([0, Math.max(d3.max(data.bandwidth, function(data) { | ||
301 | return data.bandwidth; | ||
302 | }), d3.max(data.options.playlists))]); | ||
303 | y0.domain([0, d3.max(data.buffered, function(data) { | ||
304 | return data.buffered; | ||
305 | })]); | ||
306 | |||
307 | // time axis | ||
308 | svg.selectAll('.axis').remove(); | ||
309 | svg.append('g') | ||
310 | .attr('class', 'x axis') | ||
311 | .attr('transform', 'translate(0,' + height + ')') | ||
312 | .call(timeAxis); | ||
313 | |||
314 | // bitrate axis | ||
315 | svg.append('g') | ||
316 | .attr('class', 'y axis') | ||
317 | .call(bitrateAxis) | ||
318 | .append('text') | ||
319 | .attr('transform', 'rotate(-90)') | ||
320 | .attr('y', 6) | ||
321 | .attr('dy', '.71em') | ||
322 | .style('text-anchor', 'end') | ||
323 | .text('Bitrate (kb/s)'); | ||
324 | |||
325 | // playlist bitrate lines | ||
326 | svg.selectAll('.line.bitrate') | ||
327 | .data(data.options.playlists) | ||
328 | .enter().append('path') | ||
329 | .attr('class', 'line bitrate') | ||
330 | .attr('d', function(playlist) { | ||
331 | return 'M0,' + y(playlist) + 'L' + width + ',' + y(playlist); | ||
332 | }); | ||
333 | |||
334 | // bandwidth line | ||
335 | svg.selectAll('.bandwidth').remove(); | ||
336 | svg.append('path') | ||
337 | .datum(data.bandwidth) | ||
338 | .attr('class', 'line bandwidth') | ||
339 | .attr('d', bandwidthLine); | ||
340 | |||
341 | svg.append('text') | ||
342 | .attr('class', 'bandwidth label') | ||
343 | .attr('transform', 'translate(' + x(x.range()[1]) + ', ' + y(data.bandwidth.slice(-1)[0].bandwidth) + ')') | ||
344 | .attr('dy', '1.35em') | ||
345 | .text('bandwidth'); | ||
346 | |||
347 | // buffered line | ||
348 | svg.selectAll('.buffered').remove(); | ||
349 | svg.append('path') | ||
350 | .datum(data.buffered) | ||
351 | .attr('class', 'line buffered') | ||
352 | .attr('y', 6) | ||
353 | .attr('d', bufferedLine); | ||
354 | |||
355 | // segment bitrate dots | ||
356 | svg.selectAll('.segment-bitrate').remove(); | ||
357 | svg.selectAll('.segment-bitrate') | ||
358 | .data(data.playlists) | ||
359 | .enter().append('circle') | ||
360 | .attr('class', 'dot segment-bitrate') | ||
361 | .attr('r', 3.5) | ||
362 | .attr('cx', function(playlist) { | ||
363 | return x(playlist.time); | ||
364 | }) | ||
365 | .attr('cy', function(playlist) { | ||
366 | return y(playlist.bitrate); | ||
367 | }); | ||
368 | }; | ||
369 | })(); | ||
370 | |||
371 | runSimulation(parameters(), displayTimeline); | ||
372 | |||
373 | })(window, document); |
test/switcher/js/vendor/LICENSE
0 → 100644
1 | Copyright (c) 2010-2014, Michael Bostock | ||
2 | All rights reserved. | ||
3 | |||
4 | Redistribution and use in source and binary forms, with or without | ||
5 | modification, are permitted provided that the following conditions are met: | ||
6 | |||
7 | * Redistributions of source code must retain the above copyright notice, this | ||
8 | list of conditions and the following disclaimer. | ||
9 | |||
10 | * Redistributions in binary form must reproduce the above copyright notice, | ||
11 | this list of conditions and the following disclaimer in the documentation | ||
12 | and/or other materials provided with the distribution. | ||
13 | |||
14 | * The name Michael Bostock may not be used to endorse or promote products | ||
15 | derived from this software without specific prior written permission. | ||
16 | |||
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
20 | DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, | ||
21 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
22 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | ||
24 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
test/switcher/js/vendor/d3.js
0 → 100644
This diff could not be displayed because it is too large.
test/switcher/js/vendor/d3.min.js
0 → 100644
This diff could not be displayed because it is too large.
test/switcher/js/vendor/d3.zip
0 → 100644
No preview for this file type
1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD | ||
2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load | ||
3 | */ | ||
4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["­",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function p(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return r.shivMethods?n(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+l().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(r,b.frag)}function q(a){a||(a=b);var c=m(a);return r.shivCSS&&!f&&!c.hasCSS&&(c.hasCSS=!!k(a,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")),j||p(a,c),a}var c=a.html5||{},d=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,e=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,f,g="_html5shiv",h=0,i={},j;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))}; |
-
Please register or sign in to post a comment