├── .gitignore ├── LICENSE ├── README.md ├── img └── example_logo.png ├── index.html ├── js └── jquery.video-extend.js └── swf └── video-js.swf /.gitignore: -------------------------------------------------------------------------------- 1 | /js/jquery-3.1.1.min.js 2 | /video/Sintel.mp4 3 | /video/Sintel.flv 4 | /video/Sintel_poster.png 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 andchir 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jQuery Video Extend 2 | HTML5 Video Extend 3 | 4 | * Adding a logo. 5 | * Adding markers with labels. 6 | * Playing YouTube video. 7 | * Playing FLV video (basic support). 8 | * Simply make responsive. 9 | 10 | ![](http://andchir.github.io/jquery-video-extend/img/screenshot.png) 11 | 12 | [Wiki](https://github.com/andchir/jquery-video-extend/wiki) 13 | 14 | [Demo](http://andchir.github.io/jquery-video-extend/) 15 | 16 | ``` html 17 | 18 | 19 | ``` 20 | 21 | ``` html 22 | 51 | ``` 52 | 53 | ``` html 54 | 57 | ``` 58 | 59 | ### Another way: 60 | 61 | ``` html 62 | 65 | ``` 66 | Any parameters can be specified by a prefix "data-". The array must be JSON string. 67 | -------------------------------------------------------------------------------- /img/example_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andchir/jquery-video-extend/b85dc4e4e5bba4b3515e92d12cc6914c76fba753/img/example_logo.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | HTML5 Video Extend 9 | 10 | 11 | 12 | 13 | 18 | 19 | 63 | 64 | 65 | 66 |
67 | 68 |

HTML5 Video Extend

69 |

jQuery plugin

70 | 71 | 78 | 79 |
<script src="js/jquery-3.1.1.min.js"></script>
 80 | <script src="js/jquery.video-extend.js"></script>
81 | 82 |

Player with logo and markers

83 | 84 | 87 | 88 |
<script>
 89 |     $(document).ready(function(){
 90 |         
 91 |         $('#video1').videoExtend({
 92 |             logo: 'img/example_logo.png',
 93 |             logoLink: 'http://example.com/',
 94 |             logoSize: [ 60, 40 ],
 95 |             markers: [
 96 |                 {
 97 |                     time: 39,// seconds
 98 |                     text: 'Chapter 1'
 99 |                 },
100 |                 {
101 |                     time: 350,
102 |                     text: 'Chapter 2'
103 |                 },
104 |                 {
105 |                     time: 470,
106 |                     text: 'Chapter 3'
107 |                 },
108 |                 {
109 |                     time: 677,
110 |                     text: 'Chapter 4'
111 |                 }
112 |             ]
113 |         });
114 |         
115 |     });
116 | </script>
117 | <video id="video1" width="640" height="360" poster="video/Sintel_poster.png" controls>
118 |     <source src="video/Sintel.mp4" type="video/mp4">
119 | </video>
120 | 121 |

Another way:

122 | 123 |
<video width="640" height="360" data-logo="img/example_logo.png" data-markers='[{"time":39,"text":"Chapter 1"},{"time":350,"text":"Chapter 2"}]'>
124 |     <source src="video/Sintel.mp4" type="video/mp4">
125 | </video>
126 | 127 |

Any parameters can be specified by a prefix "data-". The array must be JSON string.

128 | 129 |

Play YouTube video

130 | 131 | 134 | 135 |
<script>
136 |     $(document).ready(function(){
137 |         
138 |         $('#video2').videoExtend({
139 |             logo: 'img/example_logo.png',
140 |             logoLink: 'http://example.com/',
141 |             logoSize: [ 60, 40 ],
142 |             logoPosition: [ 'auto', 10, 50, 'auto' ] // top, right, bottom, left
143 |         });
144 |         
145 |     });
146 | </script>
147 | <video id="video2" width="640" height="360" controls>
148 |     <source src="https://www.youtube.com/watch?v=eRsGyueVLvQ" type="video/youtube">
149 | </video>
150 | 151 |

Play FLV video (basic support)

152 | 153 | 156 | 157 |
<script>
158 |     $(document).ready(function(){
159 |         
160 |         $('video.video-extend').videoExtend({
161 |             logo: 'img/example_logo.png',
162 |             logoLink: 'http://example.com/',
163 |             logoSize: [ 60, 40 ],
164 |             swfPath: 'swf/video-js.swf',
165 |             textPlay: 'Play movie'
166 |         });
167 |         
168 |     });
169 | </script>
170 | <video class="video-extend" width="640" height="360" poster="video/Sintel_poster.png" controls>
171 |     <source src="video/Sintel.flv" type="video/flv">
172 | </video>
173 | 174 |

API

175 | 176 |
<script>
177 |     $('#video1').get(0).play();// Play video
178 | </script>
179 | 180 | http://www.w3.org/2010/05/video/mediaevents.html 181 | 182 |
183 | 184 | -------------------------------------------------------------------------------- /js/jquery.video-extend.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * HTML5 Video Extend 4 | * 5 | * jQuery plugin (MIT license) 6 | * 7 | * @version 1.1.3 8 | * @author Andchir 9 | */ 10 | 11 | (function($){ 12 | 13 | "use strict"; 14 | 15 | var videoExtend = function(el, options){ 16 | var base = this; 17 | 18 | // Access to jQuery and DOM versions of element 19 | base.$el = $(el); 20 | base.player = el; 21 | base.timer = null; 22 | 23 | // Add a reverse reference to the DOM object 24 | base.$el.data('videoExtend', base); 25 | 26 | // Initialize 27 | base.init = function(){ 28 | 29 | var attributes = base.getAttributes(); 30 | base.options = $.extend({}, videoExtend.defaultOptions, options, attributes); 31 | base.browser = base.getBrowserName(); 32 | 33 | var video_src = base.$el.attr('src') || base.$el.children('source').attr('src'), 34 | poster = base.$el.attr('poster'); 35 | base.isYouTube = /youtube\.com|youtu\.be/.test( video_src ); 36 | base.isFlashVideo = video_src.substr( video_src.length - 4 ) == '.flv'; 37 | if ( base.isYouTube ) { 38 | base.embedYoutube( video_src ); 39 | } 40 | else if ( base.isFlashVideo ) { 41 | base.embedFlashVideo( video_src ); 42 | } 43 | else { 44 | 45 | base.$el 46 | .css({ 47 | display: 'block', 48 | backgroundColor: base.options.backgroundColor 49 | }) 50 | .bind('play pause mouseover mouseout', base.eventsHandler) 51 | .bind('canplay',function(){ 52 | if ( !base.options.initialized ) { 53 | base.addMarkers(); 54 | } 55 | base.options.initialized = true; 56 | }); 57 | 58 | } 59 | 60 | base.makeResponsive(); 61 | base.addLogo(); 62 | 63 | if ( base.isFlashVideo && poster ) { 64 | base.addPoster( poster ); 65 | } 66 | 67 | }; 68 | 69 | // Get browser name 70 | base.getBrowserName = function(){ 71 | 72 | var userAgent = navigator.userAgent, 73 | browser = 'unknown'; 74 | 75 | if ( /msie/i.test(userAgent) || /edge/i.test(userAgent) || "ActiveXObject" in window ) 76 | browser = 'ie'; 77 | else if ( /firefox/i.test(userAgent) ) 78 | browser = 'firefox'; 79 | else if ( /\x20OPR\//.test(userAgent) ) 80 | browser = 'opera'; 81 | else if ( /chrome|chromium/i.test(userAgent) ) 82 | browser = 'chrome'; 83 | else if ( /safari/i.test(userAgent) ) 84 | browser = 'safari'; 85 | else if ( /iphone/i.test(userAgent) ) { 86 | browser = 'iphone'; 87 | } 88 | else if ( /ipad/i.test(userAgent) ) { 89 | browser = 'ipad'; 90 | } 91 | 92 | return browser; 93 | 94 | }; 95 | 96 | base.getAttributes = function(){ 97 | var attributes = {}; 98 | $.each( base.$el.get(0).attributes, function( index, attr ) { 99 | if( attr.name.indexOf('data-') > -1 ) { 100 | var value = attr.value; 101 | if( /\[(.*)\]/.test( value ) ) 102 | value = $.parseJSON( value ); 103 | attributes[ attr.name.substr(5) ] = value; 104 | } 105 | }); 106 | return attributes; 107 | }; 108 | 109 | base.eventsHandler = function(e){ 110 | 111 | var markers_container; 112 | 113 | switch( e.type ){ 114 | case 'play': 115 | 116 | if ( base.options.logoAutoHide ) { 117 | clearTimeout( base.timer ); 118 | base.timer = setTimeout(function(){ 119 | base.$el.parent().find('.video-extend-logo-container').fadeOut(1000); 120 | },1500); 121 | } 122 | 123 | break; 124 | case 'pause': 125 | 126 | if ( base.options.logoAutoHide ) { 127 | if ( !base.player.seeking ) { 128 | clearTimeout( base.timer ); 129 | base.$el.parent().find('.video-extend-logo-container') 130 | .stop().css('opacity',1).show(); 131 | } 132 | } 133 | 134 | break; 135 | case 'mouseover': 136 | 137 | markers_container = base.$el.parent().find('.video-extend-progress-bar'); 138 | 139 | if ( base.options.markers && markers_container.length > 0 ) { 140 | markers_container.show(); 141 | } 142 | 143 | break; 144 | case 'mouseout': 145 | 146 | markers_container = base.$el.parent().find('.video-extend-progress-bar'); 147 | 148 | if ( base.options.markers && markers_container.length > 0 ) { 149 | markers_container.hide(); 150 | } 151 | 152 | break; 153 | } 154 | 155 | }; 156 | 157 | base.getControlsSize = function( browser ){ 158 | 159 | browser = browser || base.browser; 160 | var size = { left: 120, right: 220, bottom: 20 }; 161 | 162 | switch ( browser ) { 163 | case 'ie': 164 | size.left = 165; 165 | size.right = 140; 166 | size.bottom = 36; 167 | break; 168 | case 'firefox': 169 | size.left = 28; 170 | size.right = 128; 171 | size.bottom = 19; 172 | break; 173 | case 'opera': 174 | size.left = 50; 175 | size.right = 150; 176 | size.bottom = 20; 177 | break; 178 | case 'safari': 179 | size.left = 90; 180 | size.right = 100; 181 | size.bottom = 30; 182 | break; 183 | case 'chrome': 184 | //default 185 | break; 186 | } 187 | 188 | return size; 189 | 190 | }; 191 | 192 | // Add logo 193 | base.addLogo = function(){ 194 | 195 | if ( !base.options.logo ) { 196 | return; 197 | } 198 | 199 | var logo = $('',{ 200 | src: base.options.logo 201 | }) 202 | .css({ 203 | position: 'absolute', 204 | zIndex: 200, 205 | width: base.options.logoSize[0], 206 | height: base.options.logoSize[1], 207 | top: !isNaN( base.options.logoPosition[2] ) 208 | ? base.$el.outerHeight(true) - base.options.logoSize[1] - base.options.logoPosition[2] 209 | : base.options.logoPosition[0], 210 | right: base.options.logoPosition[1], 211 | bottom: 'auto', 212 | left: base.options.logoPosition[3] 213 | }) 214 | .appendTo('
') 215 | .parent() 216 | .addClass('video-extend-logo-container') 217 | .css({ 218 | position: 'relative', 219 | width: base.options.responsive ? '100%' : base.$el.width() 220 | }); 221 | 222 | if ( base.options.logoLink ) { 223 | logo.children('img') 224 | .css('cursor','pointer') 225 | .bind('click',function(){ 226 | var win = window.open(base.options.logoLink, '_blank'); 227 | win.focus(); 228 | }); 229 | } 230 | 231 | base.$el 232 | .before(logo); 233 | 234 | }; 235 | 236 | // Make responsive 237 | base.makeResponsive = function(){ 238 | 239 | if ( !base.options.responsive ) { 240 | return; 241 | } 242 | 243 | var maxWidth = base.$el.attr('width') || base.$el.width(); 244 | 245 | base.$el 246 | .wrap('
') 247 | .css({ 248 | width: '100%' 249 | }) 250 | .parent() 251 | .addClass('video-extend-wrapper') 252 | .css({ 253 | width: '100%', 254 | maxWidth: maxWidth + 'px' 255 | }); 256 | 257 | if ( base.options.alignCenter ) { 258 | base.$el.parent('.video-extend-wrapper') 259 | .css('margin', '0 auto'); 260 | } 261 | 262 | $( window ) 263 | .bind('resize',function(){ 264 | 265 | if ( base.$el.parent().find('.video-extend-progress-bar').length > 0 ) { 266 | 267 | var playerControlsSize = base.getControlsSize(); 268 | base.$el.parent().find('.video-extend-progress-bar') 269 | .css({ 270 | width: base.$el.width() - playerControlsSize.left - playerControlsSize.right 271 | }); 272 | 273 | } 274 | 275 | base.centerPoster(); 276 | 277 | }); 278 | 279 | }; 280 | 281 | // Add markers 282 | base.addMarkers = function(){ 283 | 284 | if ( !base.options.markers || base.options.markers.length == 0 ) { 285 | return; 286 | } 287 | 288 | base.addProgressBarControl(); 289 | 290 | setTimeout(function(){ 291 | 292 | var duration = base.player.duration, 293 | markers_container = base.$el.next('.video-extend-progress-bar'), 294 | playerControlsSize = base.getControlsSize(); 295 | 296 | if ( !duration ) { 297 | return; 298 | } 299 | 300 | base.options.markers.forEach(function(marker){ 301 | 302 | var percent = parseInt( marker.time / duration * 100 ); 303 | var marker_el = $('
',{ 304 | title: marker.text 305 | }) 306 | .css({ 307 | width: 8, 308 | height: 8, 309 | borderRadius: 4, 310 | backgroundColor: '#eee', 311 | border: '1px solid #777', 312 | cursor: 'pointer', 313 | position: 'absolute', 314 | top: '-' + playerControlsSize.bottom + 'px', 315 | left: percent + '%', 316 | marginLeft: '-4px' 317 | }) 318 | .appendTo( markers_container ); 319 | 320 | marker_el 321 | .bind('click', function(){ 322 | base.player.currentTime = marker.time; 323 | }) 324 | .bind('mouseover mouseout', function(){ 325 | markers_container.show(); 326 | }); 327 | 328 | }); 329 | 330 | }, 500); 331 | 332 | }; 333 | 334 | // Add progress bar control 335 | base.addProgressBarControl = function(){ 336 | 337 | var playerWidth = base.$el.width(), 338 | playerControlsSize = base.getControlsSize(); 339 | 340 | $('
') 341 | .insertAfter(base.$el) 342 | .addClass('video-extend-progress-bar') 343 | .css({ 344 | position: 'relative', 345 | left: playerControlsSize.left, 346 | width: playerWidth - playerControlsSize.left - playerControlsSize.right, 347 | height: 0 348 | }); 349 | 350 | }; 351 | 352 | // Embed YouTube video 353 | base.embedYoutube = function( video_src ){ 354 | 355 | var videoWidth = base.$el.width(), 356 | videoHeight = base.$el.height(), 357 | frame_id = 'video' + new Date().getTime(), 358 | video_id = base.getYoutubeVideoId( video_src ); 359 | 360 | var youtubeIframe = $('