├── .gitignore ├── README.md ├── ROADMAP.md ├── TODO.md ├── build ├── copywrite ├── jquery-youtube-player-0.1a.zip ├── jquery-youtube-player-0.1a1.zip ├── jslint.js └── release.sh ├── css └── youtube-player.css ├── examples ├── css │ ├── example.css │ └── jcarousel-youtube-player │ │ ├── credits.txt │ │ ├── next-horizontal.png │ │ ├── prev-horizontal.png │ │ └── skin.css ├── img │ └── ajax-loader.gif ├── js │ └── jquery.jcarousel.min.js ├── player-advanced.html ├── player-blog.html ├── player-custom-playlist.html ├── player-data-source.html ├── player-embedded.html ├── player-hash-history.html ├── player-html.html ├── player-ian.html ├── player-kurtjx.html ├── player-multiple-players.html ├── player-multiple-playlists.html ├── player-options.html ├── player-positioning.html ├── player-states.html ├── player-themes.html ├── player-toolbar-buttons.html └── player.html ├── index.html ├── js ├── jquery.youtube.player.js └── jquery.youtube.player.min.js └── tests ├── api.js ├── destroy.js ├── events.js ├── index.html └── setup.js /.gitignore: -------------------------------------------------------------------------------- 1 | png/ 2 | apache/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This jQuery plugin builds a youtube video player. 2 | 3 | **Player consists of:** 4 | 5 | * The chromeless or embedded Youtube player (Flash 8) 6 | * Optional customizable toolbar 7 | * Playlist area 8 | 9 | **Dependencies:** 10 | 11 | * Flash plugin installed on browser 12 | * swfobject 13 | * jQuery UI CSS theme 14 | 15 | **Playlists** 16 | 17 | The plugin accepts 4 types of playlists: 18 | 19 | * Custom playlist (define the vidoes by youtube video id's) 20 | * Youtube playlist (Youtube playlist id) 21 | * Youtube latest videos by user (Youtube username) 22 | * Collection of youtube links 23 | 24 | **Wiki** 25 | 26 | * [Installation and usage](http://github.com/badsyntax/jquery-youtube-player/wiki/Installation-and-usage) 27 | * [Screenshots](http://github.com/badsyntax/jquery-youtube-player/wiki/Screenshots) 28 | 29 | **Examples:** 30 | 31 | * [Basic example](http://badsyntax.github.com/jquery-youtube-player/examples/player.html) 32 | * [Advanced example](http://badsyntax.github.com/jquery-youtube-player/examples/player-advanced.html) 33 | * [All examples](http://badsyntax.github.com/jquery-youtube-player/) 34 | * Original concept: [http://dubstep.uk.net](http://dubstep.uk.net) 35 | 36 | This plugin is being actively developed. Feel free to use the latest revision. 37 | Suggestions, feedback, bugs, anything is appreciated. Please use the [Issue Tracker](http://github.com/badsyntax/jquery-youtube-player/issues) to post project related feedback, or send an email to willis.rh@gmail.com 38 | -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | V1 2 | * The plugin should have well written unit tests. At the very least the documented public API and event callbacks should be unit-tested. 3 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | * HD button 2 | * Fullscreen button 3 | * Seek bar 4 | * Time progress 5 | * Buffer progress 6 | * Toggle buttons (for play/pause) 7 | * Video thumbnails for playlist 8 | * Default browser scrollbar in playlist area 9 | * Add fields for loading playlists in the api example file 10 | * Route events to toolbar button states 11 | * Solid cross browser testing 12 | * Update documentation 13 | * Add screenshots page 14 | * Option setter and getter 15 | * Multiple players on same page 16 | * Repeat all videos in playlist 17 | * Get track info by id (so user doesn't have to supply title in custom playlist) 18 | * Custom playlistBuilder click handler option 19 | * Add option to use chromed youtube video player and no custom toolbar 20 | * Hash history 21 | * Create build script 22 | * Reduce file size 23 | * Show examples how to add to blog posts / cms etc 24 | * Make it accessible (also keyboard events) 25 | -------------------------------------------------------------------------------- /build/copywrite: -------------------------------------------------------------------------------- 1 | /* 2 | * jquery.youtube.min.js v${ver} - a jquery youtube player 3 | * Copyright (c) 2010 Richard Willis 4 | * MIT license : http://www.opensource.org/licenses/mit-license.php 5 | * Project : http://github.com/badsyntax/jquery-youtube-player 6 | * Contact : willis.rh@gmail.com | badsyntax.co.uk 7 | * Build time : ${time} 8 | */ 9 | -------------------------------------------------------------------------------- /build/jquery-youtube-player-0.1a.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badsyntax/jquery-youtube-player/188652925753dd2946af4a39e7f955e804107e0b/build/jquery-youtube-player-0.1a.zip -------------------------------------------------------------------------------- /build/jquery-youtube-player-0.1a1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badsyntax/jquery-youtube-player/188652925753dd2946af4a39e7f955e804107e0b/build/jquery-youtube-player-0.1a1.zip -------------------------------------------------------------------------------- /build/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # @description : this BASH script is used to build the jquery youtube player plugin 4 | # @author : Richard Willis 5 | # @project : http://github.com/badsyntax/jquery-youtube-player 6 | # @requirements : curl, zip, git, rhino 7 | 8 | echo -n "Enter the version for this release: " 9 | 10 | read ver 11 | 12 | if [ ! $ver ]; then 13 | 14 | echo "Invalid version." 15 | 16 | exit 17 | fi 18 | 19 | #echo "Checking.." 20 | 21 | #lint=$(js jslint.js ../js/jquery.youtube.player.js) 22 | 23 | echo "Building.." 24 | 25 | name=jquery-youtube-player 26 | in=../js/jquery.youtube.player.js 27 | out=../js/jquery.youtube.player.min.js 28 | thedate=$(date) 29 | 30 | cat copywrite | sed "s/\${ver}/$ver/g;s/\${time}/$thedate/g" > $out 31 | 32 | curl -s \ 33 | -d compilation_level=SIMPLE_OPTIMIZATIONS \ 34 | -d output_format=text \ 35 | -d output_info=compiled_code \ 36 | --data-urlencode "js_code@${in}" \ 37 | http://closure-compiler.appspot.com/compile \ 38 | >> $out 39 | 40 | git add $out && git commit -m "added ${ver} min version" 41 | 42 | rm -rf "${name}-${ver}" && mkdir "${name}-${ver}" && cd "${name}-${ver}" 43 | 44 | cp -r ../../js/ . 45 | cp -r ../../css/ . 46 | cp -r ../../examples/ . 47 | cp ../../index.html . 48 | cp ../../README.md . 49 | 50 | cd ../ 51 | 52 | zip -r "${name}-${ver}.zip" "${name}-${ver}" 53 | 54 | rm -rf "${name}-${ver}" 55 | 56 | git add "${name}-${ver}.zip" && git commit -m "added v${ver} release archive" && git push 57 | 58 | cd ../ 59 | 60 | git tag -a $ver -m "tagged version ${ver}" && git push --tags 61 | 62 | echo "done." 63 | -------------------------------------------------------------------------------- /css/youtube-player.css: -------------------------------------------------------------------------------- 1 | .youtube-player { 2 | font-size: 86%; 3 | position: relative; 4 | } 5 | .youtube-player-toolbar { 6 | background: #111; 7 | margin: .1em 0 0 0; 8 | } 9 | .youtube-player-toolbar li.youtube-player-time { 10 | float: right; 11 | font-weight: normal; 12 | font-size: 10px; 13 | line-height: 28px; 14 | margin: 0pt 5px 0pt 0pt; 15 | padding: 0; 16 | display: none; 17 | cursor: default; 18 | } 19 | .youtube-player-object { 20 | border: 1px solid #282828; 21 | } 22 | .youtube-player-toolbar li { 23 | cursor: pointer; 24 | float: left; 25 | list-style: none outside none; 26 | margin: 2px; 27 | padding: 4px 0; 28 | } 29 | .youtube-player-toolbar li span.ui-icon { 30 | float: left; 31 | margin: 0 4px; 32 | } 33 | .youtube-player-playlist-container { 34 | border: 1px solid #282828; 35 | margin-top: .2em; 36 | position: relative; 37 | display: none; 38 | } 39 | .youtube-player-playlist { 40 | list-style: decimal; 41 | overflow: auto; 42 | margin: 2px; 43 | padding: 0; 44 | } 45 | .youtube-player-playlist li { 46 | overflow-x: hidden; 47 | border: 0; 48 | cursor: pointer; 49 | text-decoration: none; 50 | list-style-type: decimal; 51 | padding: 2px 4px 2px; 52 | white-space: nowrap; 53 | font-size: 13px; 54 | } 55 | .youtube-player-playlist .youtube-player-thumb { 56 | float: left; 57 | height: 90px; 58 | width: 124px; 59 | list-style: none; 60 | overflow: hidden; 61 | } 62 | .youtube-player-playlist .youtube-player-thumb img { 63 | height: 90px; 64 | width: 124px; 65 | } 66 | .ui-state-default, .ui-widget-content .ui-state-default { 67 | background-position: -9999px -9999px; 68 | } 69 | .ui-state-hover, 70 | .ui-widget-content .ui-state-hover, 71 | .ui-widget-header .ui-state-hover, 72 | .ui-state-focus, 73 | .ui-widget-content .ui-state-focus, 74 | .ui-widget-header .ui-state-focus { 75 | background-position: 50% 50%; 76 | } 77 | .ui-state-default, 78 | .ui-widget-content .ui-state-default, 79 | .ui-widget-header .ui-state-default { 80 | border-color: #333; 81 | } 82 | -------------------------------------------------------------------------------- /examples/css/example.css: -------------------------------------------------------------------------------- 1 | /* this stylesheet is used by the example files, it is not required by the jquery youtube player */ 2 | body { font: normal 90% Arial; background: #ddd; margin: 1em 1em 3em 1em; text-align: center; } 3 | a, a:visited { color: #7D000F; text-decoration: underline; } 4 | a:hover { text-decoration: none; } 5 | #github-ribbon { position: absolute; top: 0; right: 1px; border: 0; } 6 | #theme-switcher { position: absolute; right: 1em; top: 1em; } 7 | #centered{ width: 425px; margin: 2em auto 0 auto; text-align: left; } 8 | .advanced #centered{ width: 780px;} 9 | .index #centered{ width: 700px; } 10 | #events{ border: 1px solid #aaa; padding: 1em; max-height: 6em; overflow: auto } 11 | h1 { font-size: 1.5em; font-family: 'Droid Sans', arial, serif; } 12 | h1 a, h1 a:visited { padding: .8em .2em 0 0; text-decoration: none; -moz-text-shadow: none; -webkit-text-shadow: none; text-shadow: none;} 13 | h2 { font-family: 'Droid Sans', arial, serif; } 14 | h1,h2,h3{-moz-text-shadow: 0.1em 0.1em 0 #EEEEEE; -webkit-text-shadow: 0.1em 0.1em 0 #EEEEEE; text-shadow: 0.1em 0.1em 0 #EEEEEE; margin: .8em 0 .5em 0;} 15 | img { border: 0;} 16 | label { padding: .2em 0; display: block; position: relative; cursor: pointer; float: left; clear: left; } 17 | label input { position: absolute; left: 130px; top: 0; cursor: pointer; } 18 | button { clear: left; overflow: visible; white-space: nowrap; padding: .5em; cursor: pointer; border: 1px solid #bbb; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; -moz-box-shadow: #bbb 0 1px 4px; -webkit-box-shadow: #bbb 0 1px 4px; box-shadow: #bbb 0 1px 4px; color: #333; -moz-text-shadow: 1px 1px 0 #FFFFFF; -webkit-text-shadow: 1px 1px 0 #FFFFFF; text-shadow: 1px 1px 0 #FFFFFF; font: bold 12px helvetica,arial,freesans,clean,sans-serif; background: #f4f4f4; background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#ddd)); background: -moz-linear-gradient(top, #fff, #ddd); } 19 | button.mousedown, button:active { background: -webkit-gradient(linear, left top, left bottom, from(#ddd), to(#eee)); background: -moz-linear-gradient(top, #ddd, #eee); } 20 | button.mouseenter, button.focus, button:hover { color: #000; border-color: #888; outline: none; } 21 | .multiple-playlists #centered {width:660px;} 22 | .playlists { width:200px; margin-left: 30px;} 23 | .playlists ol { border: 1px solid #111; margin: 0; padding-left: 2.4em; } 24 | .playlists li { } 25 | .playlists a { color: #000; padding: .3em 0; display: block; } 26 | .playlists a:hover { color: #990000; } 27 | .field-row { padding: .3em 0; } 28 | #footer { border-top: 1px solid #aaa; margin-top: 3em; padding-top: .5em; font-size: .9em; color: #888; clear: both; } 29 | #footer a { color: #888; text-decoration: none;} 30 | #footer a:hover { text-decoration: underline; } 31 | .helper-left { float: left; } 32 | .helper-right { float: right; } 33 | .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } 34 | .clearfix { display: inline-block; } 35 | html .clearfix { height:1%; } 36 | * .clearfix { display:block; } 37 | #nav { display: block; margin: 0 0 2em 0; background: transparent url(img/nav_bg.jpg) repeat-x center bottom; border: 1px solid #ccc; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; -moz-box-shadow: 2px 2px 2px #999; -webkit-box-shadow: 2px 2px 2px #999; box-shadow: 2px 2px 2px #999; text-align: center; } 38 | #nav ul { margin: 0; padding: 0; width: auto; border-right: 1px solid #ddd; } 39 | #nav ul li { list-style: none; margin: 0; padding: 0; width: 116px; float: left; } 40 | #nav ul li a { display: block; padding: .5em 1.5em; text-decoration: none; text-align: center; font-size: 80%; text-transform: uppercase; border-left: 1px solid #ddd; border-right: 1px solid #fff; outline: none; } 41 | #nav ul li a.first { border-left: 0; } 42 | #nav ul li a.selected { text-decoration: underline; } 43 | #nav ul li a:hover { border: 1px solid #aaa; border-width: 0 1px; -moz-box-shadow: 0 0 3px #888; -webkit-box-shadow: 0 0 3px #888; box-shadow: 0 0 3px #888; text-shadow: 1px 1px 1px #ccc; } 44 | #nav ul li a:active { -moz-box-shadow: 0 0 4px #333; -webkit-box-shadow: 0 0 4px #333; box-shadow: 0 0 4px #333; } 45 | .gist .gist-file .gist-data { font-size: 85% !important; } 46 | .gist { border: 1px solid #aaa; } 47 | .gist .gist-file { margin-bottom: 0 !important; } 48 | .gist .gist-file .gist-data { height: 350px !important; } 49 | -------------------------------------------------------------------------------- /examples/css/jcarousel-youtube-player/credits.txt: -------------------------------------------------------------------------------- 1 | Button images copyright by Tango Icon Library Team (http://tango.freedesktop.org/Tango_Icon_Library) -------------------------------------------------------------------------------- /examples/css/jcarousel-youtube-player/next-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badsyntax/jquery-youtube-player/188652925753dd2946af4a39e7f955e804107e0b/examples/css/jcarousel-youtube-player/next-horizontal.png -------------------------------------------------------------------------------- /examples/css/jcarousel-youtube-player/prev-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badsyntax/jquery-youtube-player/188652925753dd2946af4a39e7f955e804107e0b/examples/css/jcarousel-youtube-player/prev-horizontal.png -------------------------------------------------------------------------------- /examples/css/jcarousel-youtube-player/skin.css: -------------------------------------------------------------------------------- 1 | .jcarousel-skin-youtube-player .jcarousel-container { 2 | -moz-border-radius: 10px; 3 | border: 1px solid #000; 4 | background: #000; 5 | } 6 | 7 | .jcarousel-skin-youtube-player .jcarousel-direction-rtl { 8 | direction: rtl; 9 | } 10 | 11 | .jcarousel-skin-youtube-player .jcarousel-container-horizontal { 12 | width: 340px; 13 | padding: 4px 40px; 14 | } 15 | 16 | .jcarousel-skin-youtube-player .jcarousel-container-vertical { 17 | width: 75px; 18 | height: 245px; 19 | padding: 40px 20px; 20 | } 21 | 22 | .jcarousel-skin-youtube-player .jcarousel-clip-horizontal { 23 | width: 340px; 24 | height: 75px; 25 | } 26 | 27 | .jcarousel-skin-youtube-player .jcarousel-clip-vertical { 28 | width: 75px; 29 | height: 245px; 30 | } 31 | 32 | .jcarousel-skin-youtube-player .jcarousel-item { 33 | width: 75px; 34 | height: 75px; 35 | } 36 | 37 | .jcarousel-skin-youtube-player .jcarousel-item-horizontal { 38 | margin-left: 0; 39 | margin-right: 10px; 40 | cursor: pointer; 41 | } 42 | 43 | .jcarousel-skin-youtube-player .jcarousel-direction-rtl .jcarousel-item-horizontal { 44 | margin-left: 10px; 45 | margin-right: 0; 46 | } 47 | 48 | .jcarousel-skin-youtube-player .jcarousel-item-vertical { 49 | margin-bottom: 10px; 50 | } 51 | 52 | .jcarousel-skin-youtube-player .jcarousel-item-placeholder { 53 | background: #fff; 54 | color: #000; 55 | } 56 | 57 | /** 58 | * Horizontal Buttons 59 | */ 60 | .jcarousel-skin-youtube-player .jcarousel-next-horizontal { 61 | position: absolute; 62 | top: 24px; 63 | right: 5px; 64 | width: 32px; 65 | height: 32px; 66 | cursor: pointer; 67 | background: transparent url(next-horizontal.png) no-repeat 0 0; 68 | } 69 | 70 | .jcarousel-skin-youtube-player .jcarousel-direction-rtl .jcarousel-next-horizontal { 71 | left: 5px; 72 | right: auto; 73 | background-image: url(prev-horizontal.png); 74 | } 75 | 76 | .jcarousel-skin-youtube-player .jcarousel-next-horizontal:hover { 77 | background-position: -32px 0; 78 | } 79 | 80 | .jcarousel-skin-youtube-player .jcarousel-next-horizontal:active { 81 | background-position: -64px 0; 82 | } 83 | 84 | .jcarousel-skin-youtube-player .jcarousel-next-disabled-horizontal, 85 | .jcarousel-skin-youtube-player .jcarousel-next-disabled-horizontal:hover, 86 | .jcarousel-skin-youtube-player .jcarousel-next-disabled-horizontal:active { 87 | cursor: default; 88 | background-position: -96px 0; 89 | } 90 | 91 | .jcarousel-skin-youtube-player .jcarousel-prev-horizontal { 92 | position: absolute; 93 | top: 24px; 94 | left: 5px; 95 | width: 32px; 96 | height: 32px; 97 | cursor: pointer; 98 | background: transparent url(prev-horizontal.png) no-repeat 0 0; 99 | } 100 | 101 | .jcarousel-skin-youtube-player .jcarousel-direction-rtl .jcarousel-prev-horizontal { 102 | left: auto; 103 | right: 5px; 104 | background-image: url(next-horizontal.png); 105 | } 106 | 107 | .jcarousel-skin-youtube-player .jcarousel-prev-horizontal:hover { 108 | background-position: -32px 0; 109 | } 110 | 111 | .jcarousel-skin-youtube-player .jcarousel-prev-horizontal:active { 112 | background-position: -64px 0; 113 | } 114 | 115 | .jcarousel-skin-youtube-player .jcarousel-prev-disabled-horizontal, 116 | .jcarousel-skin-youtube-player .jcarousel-prev-disabled-horizontal:hover, 117 | .jcarousel-skin-youtube-player .jcarousel-prev-disabled-horizontal:active { 118 | cursor: default; 119 | background-position: -96px 0; 120 | } 121 | 122 | /** 123 | * Vertical Buttons 124 | */ 125 | .jcarousel-skin-youtube-player .jcarousel-next-vertical { 126 | position: absolute; 127 | bottom: 5px; 128 | left: 43px; 129 | width: 32px; 130 | height: 32px; 131 | cursor: pointer; 132 | background: transparent url(next-vertical.png) no-repeat 0 0; 133 | } 134 | 135 | .jcarousel-skin-youtube-player .jcarousel-next-vertical:hover { 136 | background-position: 0 -32px; 137 | } 138 | 139 | .jcarousel-skin-youtube-player .jcarousel-next-vertical:active { 140 | background-position: 0 -64px; 141 | } 142 | 143 | .jcarousel-skin-youtube-player .jcarousel-next-disabled-vertical, 144 | .jcarousel-skin-youtube-player .jcarousel-next-disabled-vertical:hover, 145 | .jcarousel-skin-youtube-player .jcarousel-next-disabled-vertical:active { 146 | cursor: default; 147 | background-position: 0 -96px; 148 | } 149 | 150 | .jcarousel-skin-youtube-player .jcarousel-prev-vertical { 151 | position: absolute; 152 | top: 5px; 153 | left: 43px; 154 | width: 32px; 155 | height: 32px; 156 | cursor: pointer; 157 | background: transparent url(prev-vertical.png) no-repeat 0 0; 158 | } 159 | 160 | .jcarousel-skin-youtube-player .jcarousel-prev-vertical:hover { 161 | background-position: 0 -32px; 162 | } 163 | 164 | .jcarousel-skin-youtube-player .jcarousel-prev-vertical:active { 165 | background-position: 0 -64px; 166 | } 167 | 168 | .jcarousel-skin-youtube-player .jcarousel-prev-disabled-vertical, 169 | .jcarousel-skin-youtube-player .jcarousel-prev-disabled-vertical:hover, 170 | .jcarousel-skin-youtube-player .jcarousel-prev-disabled-vertical:active { 171 | cursor: default; 172 | background-position: 0 -96px; 173 | } 174 | -------------------------------------------------------------------------------- /examples/img/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/badsyntax/jquery-youtube-player/188652925753dd2946af4a39e7f955e804107e0b/examples/img/ajax-loader.gif -------------------------------------------------------------------------------- /examples/js/jquery.jcarousel.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jCarousel - Riding carousels with jQuery 3 | * http://sorgalla.com/jcarousel/ 4 | * 5 | * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com) 6 | * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 7 | * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 8 | * 9 | * Built on top of the jQuery library 10 | * http://jquery.com 11 | * 12 | * Inspired by the "Carousel Component" by Bill Scott 13 | * http://billwscott.com/carousel/ 14 | */ 15 | 16 | (function(i){var q={vertical:false,rtl:false,start:1,offset:1,size:null,scroll:3,visible:null,animation:"normal",easing:"swing",auto:0,wrap:null,initCallback:null,reloadCallback:null,itemLoadCallback:null,itemFirstInCallback:null,itemFirstOutCallback:null,itemLastInCallback:null,itemLastOutCallback:null,itemVisibleInCallback:null,itemVisibleOutCallback:null,buttonNextHTML:"
",buttonPrevHTML:"
",buttonNextEvent:"click",buttonPrevEvent:"click",buttonNextCallback:null,buttonPrevCallback:null, itemFallbackDimension:null},r=false;i(window).bind("load.jcarousel",function(){r=true});i.jcarousel=function(a,c){this.options=i.extend({},q,c||{});this.autoStopped=this.locked=false;this.buttonPrevState=this.buttonNextState=this.buttonPrev=this.buttonNext=this.list=this.clip=this.container=null;if(!c||c.rtl===undefined)this.options.rtl=(i(a).attr("dir")||i("html").attr("dir")||"").toLowerCase()=="rtl";this.wh=!this.options.vertical?"width":"height";this.lt=!this.options.vertical?this.options.rtl? "right":"left":"top";for(var b="",d=a.className.split(" "),f=0;f");this.container=this.container.parent()}else if(!this.container.hasClass("jcarousel-container"))this.container= this.list.wrap("
").parent()}else{this.container=i(a);this.list=this.container.find("ul,ol").eq(0)}b!==""&&this.container.parent()[0].className.indexOf("jcarousel-skin")==-1&&this.container.wrap('
');this.clip=this.list.parent();if(!this.clip.length||!this.clip.hasClass("jcarousel-clip"))this.clip=this.list.wrap("
").parent();this.buttonNext=i(".jcarousel-next",this.container);if(this.buttonNext.size()===0&&this.options.buttonNextHTML!==null)this.buttonNext= this.clip.after(this.options.buttonNextHTML).next();this.buttonNext.addClass(this.className("jcarousel-next"));this.buttonPrev=i(".jcarousel-prev",this.container);if(this.buttonPrev.size()===0&&this.options.buttonPrevHTML!==null)this.buttonPrev=this.clip.after(this.options.buttonPrevHTML).next();this.buttonPrev.addClass(this.className("jcarousel-prev"));this.clip.addClass(this.className("jcarousel-clip")).css({overflow:"hidden",position:"relative"});this.list.addClass(this.className("jcarousel-list")).css({overflow:"hidden", position:"relative",top:0,margin:0,padding:0}).css(this.options.rtl?"right":"left",0);this.container.addClass(this.className("jcarousel-container")).css({position:"relative"});!this.options.vertical&&this.options.rtl&&this.container.addClass("jcarousel-direction-rtl").attr("dir","rtl");var j=this.options.visible!==null?Math.ceil(this.clipping()/this.options.visible):null;b=this.list.children("li");var e=this;if(b.size()>0){var g=0,k=this.options.offset;b.each(function(){e.format(this,k++);g+=e.dimension(this, j)});this.list.css(this.wh,g+100+"px");if(!c||c.size===undefined)this.options.size=b.size()}this.container.css("display","block");this.buttonNext.css("display","block");this.buttonPrev.css("display","block");this.funcNext=function(){e.next()};this.funcPrev=function(){e.prev()};this.funcResize=function(){e.reload()};this.options.initCallback!==null&&this.options.initCallback(this,"init");if(!r&&i.browser.safari){this.buttons(false,false);i(window).bind("load.jcarousel",function(){e.setup()})}else this.setup()}; var h=i.jcarousel;h.fn=h.prototype={jcarousel:"0.2.7"};h.fn.extend=h.extend=i.extend;h.fn.extend({setup:function(){this.prevLast=this.prevFirst=this.last=this.first=null;this.animating=false;this.tail=this.timer=null;this.inTail=false;if(!this.locked){this.list.css(this.lt,this.pos(this.options.offset)+"px");var a=this.pos(this.options.start,true);this.prevFirst=this.prevLast=null;this.animate(a,false);i(window).unbind("resize.jcarousel",this.funcResize).bind("resize.jcarousel",this.funcResize)}}, reset:function(){this.list.empty();this.list.css(this.lt,"0px");this.list.css(this.wh,"10px");this.options.initCallback!==null&&this.options.initCallback(this,"reset");this.setup()},reload:function(){this.tail!==null&&this.inTail&&this.list.css(this.lt,h.intval(this.list.css(this.lt))+this.tail);this.tail=null;this.inTail=false;this.options.reloadCallback!==null&&this.options.reloadCallback(this);if(this.options.visible!==null){var a=this,c=Math.ceil(this.clipping()/this.options.visible),b=0,d=0; this.list.children("li").each(function(f){b+=a.dimension(this,c);if(f+1this.options.size)c=this.options.size;for(var b= a;b<=c;b++){var d=this.get(b);if(!d.length||d.hasClass("jcarousel-item-placeholder"))return false}return true},get:function(a){return i(".jcarousel-item-"+a,this.list)},add:function(a,c){var b=this.get(a),d=0,f=i(c);if(b.length===0){var j,e=h.intval(a);for(b=this.create(a);;){j=this.get(--e);if(e<=0||j.length){e<=0?this.list.prepend(b):j.after(b);break}}}else d=this.dimension(b);if(f.get(0).nodeName.toUpperCase()=="LI"){b.replaceWith(f);b=f}else b.empty().append(c);this.format(b.removeClass(this.className("jcarousel-item-placeholder")), a);f=this.options.visible!==null?Math.ceil(this.clipping()/this.options.visible):null;d=this.dimension(b,f)-d;a>0&&a=this.first&&a<=this.last)){var b=this.dimension(c);athis.options.size?this.options.size:a;for(var d= this.first>a,f=this.options.wrap!="circular"&&this.first<=1?1:this.first,j=d?this.get(f):this.get(this.last),e=d?f:f-1,g=null,k=0,l=false,m=0;d?--e>=a:++ethis.options.size)){j=this.get(this.index(e));if(j.length)g=this.add(e,j.clone(true))}}j=g;m=this.dimension(g);if(l)k+= m;if(this.first!==null&&(this.options.wrap=="circular"||e>=1&&(this.options.size===null||e<=this.options.size)))b=d?b+m:b-m}f=this.clipping();var p=[],o=0,n=0;j=this.get(a-1);for(e=a;++o;){g=this.get(e);l=!g.length;if(g.length===0){g=this.create(e).addClass(this.className("jcarousel-item-placeholder"));j.length===0?this.list.prepend(g):j[d?"before":"after"](g);if(this.first!==null&&this.options.wrap=="circular"&&this.options.size!==null&&(e<=0||e>this.options.size)){j=this.get(this.index(e));if(j.length)g= this.add(e,j.clone(true))}}j=g;m=this.dimension(g);if(m===0)throw Error("jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...");if(this.options.wrap!="circular"&&this.options.size!==null&&e>this.options.size)p.push(g);else if(l)k+=m;n+=m;if(n>=f)break;e++}for(g=0;g0){this.list.css(this.wh,this.dimension(this.list)+k+"px");if(d){b-=k;this.list.css(this.lt,h.intval(this.list.css(this.lt))-k+"px")}}k=a+o-1;if(this.options.wrap!="circular"&& this.options.size&&k>this.options.size)k=this.options.size;if(e>k){o=0;e=k;for(n=0;++o;){g=this.get(e--);if(!g.length)break;n+=this.dimension(g);if(n>=f)break}}e=k-o+1;if(this.options.wrap!="circular"&&e<1)e=1;if(this.inTail&&d){b+=this.tail;this.inTail=false}this.tail=null;if(this.options.wrap!="circular"&&k==this.options.size&&k-o+1>=1){d=h.margin(this.get(k),!this.options.vertical?"marginRight":"marginBottom");if(n-d>f)this.tail=n-f-d}if(c&&a===this.options.size&&this.tail){b-=this.tail;this.inTail= true}for(;a-- >e;)b+=this.dimension(this.get(a));this.prevFirst=this.first;this.prevLast=this.last;this.first=e;this.last=k;return b},animate:function(a,c){if(!(this.locked||this.animating)){this.animating=true;var b=this,d=function(){b.animating=false;a===0&&b.list.css(b.lt,0);if(!b.autoStopped&&(b.options.wrap=="circular"||b.options.wrap=="both"||b.options.wrap=="last"||b.options.size===null||b.last=b.first&&f<=b.last)&&(f<1||f>b.options.size))b.remove(f)};this.notify("onBeforeAnimation");if(!this.options.animation||c===false){this.list.css(this.lt,a+"px");d()}else this.list.animate(!this.options.vertical?this.options.rtl?{right:a}:{left:a}:{top:a},this.options.animation,this.options.easing,d)}},startAuto:function(a){if(a!==undefined)this.options.auto=a;if(this.options.auto===0)return this.stopAuto(); if(this.timer===null){this.autoStopped=false;var c=this;this.timer=window.setTimeout(function(){c.next()},this.options.auto*1E3)}},stopAuto:function(){this.pauseAuto();this.autoStopped=true},pauseAuto:function(){if(this.timer!==null){window.clearTimeout(this.timer);this.timer=null}},buttons:function(a,c){if(a==null){a=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="first"||this.options.size===null||this.last=this.options.size)a=this.tail!==null&&!this.inTail}if(c==null){c=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="last"||this.first>1);if(!this.locked&&(!this.options.wrap||this.options.wrap=="last")&&this.options.size!==null&&this.first==1)c=this.tail!==null&&this.inTail}var b=this;if(this.buttonNext.size()>0){this.buttonNext.unbind(this.options.buttonNextEvent+".jcarousel",this.funcNext);a&&this.buttonNext.bind(this.options.buttonNextEvent+ ".jcarousel",this.funcNext);this.buttonNext[a?"removeClass":"addClass"](this.className("jcarousel-next-disabled")).attr("disabled",a?false:true);this.options.buttonNextCallback!==null&&this.buttonNext.data("jcarouselstate")!=a&&this.buttonNext.each(function(){b.options.buttonNextCallback(b,this,a)}).data("jcarouselstate",a)}else this.options.buttonNextCallback!==null&&this.buttonNextState!=a&&this.options.buttonNextCallback(b,null,a);if(this.buttonPrev.size()>0){this.buttonPrev.unbind(this.options.buttonPrevEvent+ ".jcarousel",this.funcPrev);c&&this.buttonPrev.bind(this.options.buttonPrevEvent+".jcarousel",this.funcPrev);this.buttonPrev[c?"removeClass":"addClass"](this.className("jcarousel-prev-disabled")).attr("disabled",c?false:true);this.options.buttonPrevCallback!==null&&this.buttonPrev.data("jcarouselstate")!=c&&this.buttonPrev.each(function(){b.options.buttonPrevCallback(b,this,c)}).data("jcarouselstate",c)}else this.options.buttonPrevCallback!==null&&this.buttonPrevState!=c&&this.options.buttonPrevCallback(b, null,c);this.buttonNextState=a;this.buttonPrevState=c},notify:function(a){var c=this.prevFirst===null?"init":this.prevFirst=j&&l<=e)&&a(l)}}}},create:function(a){return this.format("
  • ",a)},format:function(a,c){a=i(a);for(var b=a.get(0).className.split(" "),d=0;d 2 | 3 | 4 | jQuery Youtube Player API Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |

    31 | The plugin has many options and events you can use to customize your player. View the 32 | usage guide for a full list of the 33 | available plugin options and events. 34 |

    35 | 36 |
    37 | 38 |
    39 | 40 |
    41 |
    42 |
    43 | You need Flash player 8+ and JavaScript enabled to view this video. 44 |
    45 |
    46 |
    47 | 48 |
    49 | 50 |
    51 | 52 |
    53 |
    54 | 55 |
    56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96 | 100 |
    101 | 102 | 105 | 106 | 109 |
    110 |
    111 | 112 |

    Methods:

    113 | 114 |
    115 | 116 | 119 | 120 | 123 | 124 | 127 | 128 | 131 |
    132 | 133 |
    134 | 135 | 138 |
    139 | 140 |
    141 | 142 | 145 |
    146 | 147 |

    Events:

    148 |
    149 | 150 |
    151 |
    152 |
    153 | 154 | 305 | 306 | 307 | -------------------------------------------------------------------------------- /examples/player-blog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - Blog integration example 5 | 6 | 7 | 8 | 9 | 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
    24 | 25 | Fork me on GitHub 26 | 27 |
    28 | 29 |
    30 | 31 |

    32 | 33 | jQuery Youtube Player 34 | 35 |

    36 | 37 |

    38 | This example will convert all the specified youtube links to 39 | youtube players. 40 |

    41 | 42 |
    43 |

    44 | This is my first blog entry. 45 |

    46 | The All Seeing I - Beat Goes On HQ 47 |
    48 | 49 |
    50 |

    51 | This is my second blog entry. 52 |

    53 | All Online Data Lost After Internet Crash 54 |
    55 |
    56 | 57 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /examples/player-custom-playlist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - Custom Playlist 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 | 20 | Fork me on GitHub 21 | 22 |
    23 | 24 |
    25 | 26 |

    27 | 28 | jQuery Youtube Player 29 | 30 |

    31 | 32 |

    33 | This example file demonstrates how to create a custom playlist using the playlistBuilder option. 34 |

    35 | 36 |
    37 |
    38 |
    39 | You need Flash player 8+ and JavaScript enabled to view this video. 40 |
    41 |
    42 |
    43 | 44 |
    45 | 46 |
    47 |
    48 | 49 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /examples/player-data-source.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - HTML Playlist Data Source 5 | 6 | 7 | 8 | 9 | 10 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
    34 | 35 | Fork me on GitHub 36 | 37 |
    38 | 39 |
    40 | 41 |

    42 | 43 | jQuery Youtube Player 44 | 45 |

    46 | 47 |

    48 | This example reads the playlist from HTML. 49 | All you need to do is specify a list with links to youtube videos, and the plugin will convert it into the video playlist area. 50 | The player is embedded and uses a custom toolbar and custom playlist area. 51 |

    52 | 53 |
    54 |
    55 |
    56 | You need Flash player 8+ and JavaScript enabled to view this video. 57 |
    58 |
    59 |
      60 |
    1. MIT Leg Lab Robots
    2. 61 |
    3. Boston Dynamics BIGDOG Robot
    4. 62 |
    5. PETMAN Prototype
    6. 63 |
    7. RHEX - KodLab (long)
    8. 64 |
    9. Boston Dynamics RiSE V2 and V3
    10. 65 |
    11. Rotundus GroundBot
    12. 66 |
    67 |
    68 |
    69 | 70 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /examples/player-embedded.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - Embedded Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |

    31 | It's real easy to set up a default youtube embedded video with an (optionally) attached playlist. 32 |

    33 | 34 |
    35 |
    36 |
    37 | You need Flash player 8+ and JavaScript enabled to view this video. 38 |
    39 |
    40 |
    41 |
    42 | 43 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /examples/player-hash-history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - Hash History Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
    18 | 19 | Fork me on GitHub 20 | 21 |
    22 | 23 |
    24 | 25 |

    26 | 27 | jQuery Youtube Player 28 | 29 |

    30 | 31 |

    32 | Hash history is not a core feature of the plugin, but it's real easy to integrate a third party 33 | hash history plugin. This example uses the excellent jquery-hashchange plugin. 34 |

    35 |

    36 | Note: You can only load videos that exist in the playlist, you can't load arbitrary videos via the hash. 37 |

    38 | 39 |
    40 |
    41 |
    42 | You need Flash player 8+ and JavaScript enabled to view this video. 43 |
    44 |
    45 |
    46 |
    47 | 48 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /examples/player-html.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
    13 | 14 | Fork me on GitHub 15 | 16 |
    17 | 18 |
    19 | 20 |

    21 | 22 | jQuery Youtube Player 23 | 24 |

    25 | 26 |

    27 | This file shows the final markup of the player, toolbar and playlist. 28 |

    29 | 30 |
    31 |
    32 |
    33 | 39 | 40 | 41 | 42 |
    43 |
      44 |
    • 45 |
    • 46 |
    • 47 |
    • 48 |
    • 49 |
    • 50 |
    • 51 |
    • 0:00 / 3:02
    • 52 |
    53 |
    54 |
      55 |
    1. The All Seeing I - Beat Goes On HQ
    2. 56 |
    3. Dai Mahou Touge - Vegetable Suicide
    4. 57 |
    5. Maru the cat
    6. 58 |
    7. All Online Data Lost After Internet Crash
    8. 59 |
    9. Mr. Oizo Flat Beat
    10. 60 |
    11. Most incredible volcano footage ever
    12. 61 |
    13. Wingsuit BASE jumping in Baffin Island
    14. 62 |
    63 |
    64 |
    65 |
    66 | 67 | 68 | -------------------------------------------------------------------------------- /examples/player-ian.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |
    31 |
    32 |
    33 | You need Flash player 8+ and JavaScript enabled to view this video. 34 |
    35 |
    36 |
    37 | 38 |
    39 | 42 | 43 | 46 | 47 | 50 | 51 |
    52 |
    53 | 54 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /examples/player-kurtjx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - kurtjx Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |
    31 |
    32 |
    33 | You need Flash player 8+ and JavaScript enabled to view this video. 34 |
    35 |
    36 |
    37 | 38 |
    39 | 40 | 43 |
    44 | 45 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /examples/player-multiple-players.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - Multiple Players Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |

    31 | The plugin will work with multiple players in the page. 32 |

    33 | 34 |
    35 |
    36 |
    37 | You need Flash player 8+ and JavaScript enabled to view this video. 38 |
    39 |
    40 |
    41 | 42 |

    43 | 44 |
    45 |
    46 |
    47 | You need Flash player 8+ and JavaScript enabled to view this video. 48 |
    49 |
    50 |
    51 |
    52 | 53 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /examples/player-multiple-playlists.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - Multiple Playlists 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
    18 | 19 | Fork me on GitHub 20 | 21 |
    22 | 23 |
    24 | 25 |

    26 | 27 | jQuery Youtube Player 28 | 29 |

    30 | 31 |

    32 | The plugin API allows you to easily hook into the base functions. 33 | The example demonstrates how to load different playlists, and use 34 | the callback events. 35 |

    36 | 37 |
    38 |
    39 | 40 | 41 |
    42 |
    43 |
    44 | You need Flash player 8+ and JavaScript enabled to view this video. 45 |
    46 |
    47 |
    48 |
    49 | 50 |
    51 | 52 |

    Playlists:

    53 | 54 |
      55 |
    1. Playlist 1
    2. 56 |
    3. Playlist 2
    4. 57 |
    5. Playlist 3
    6. 58 |
    7. Playlist 4
    8. 59 |
    60 | 61 | 62 |
    63 |
    64 |
    65 | 66 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /examples/player-options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player Options 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |
    31 |
    32 |
    33 | You need Flash player 8+ and JavaScript enabled to view this video. 34 |
    35 |
    36 |
    37 |
    38 | 39 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /examples/player-positioning.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player Example - Positioning 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |

    31 | This example demonstrates custom positioning of the video elements. 32 | You can specifiy where the elements should be appended into the DOM. 33 |

    34 | 35 |
    36 |
    37 |
    38 | You need Flash player 8+ and JavaScript enabled to view this video. 39 |
    40 |
    41 |
    42 | 43 |

    44 | 45 | Toolbar:
    46 |
    47 | 48 |
    49 | 50 | Playlist:
    51 |
    52 | 53 |
    54 | 55 | Time:
    56 |
    57 | 58 |
    59 | 60 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /examples/player-states.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |
    31 |
    32 |
    33 | You need Flash player 8+ and JavaScript enabled to view this video. 34 |
    35 |
    36 |
    37 | 38 |
    39 | 42 | 43 |
    44 |
    45 | 46 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /examples/player-themes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player Example - Themes 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |

    31 | Use the themeswitcher to choose a new jQuery UI theme. 32 |

    33 | 34 |
    35 |
    36 |
    37 | You need Flash player 8+ and JavaScript enabled to view this video. 38 |
    39 |
    40 |
    41 | 42 |
    43 | 44 |
    45 |
    46 | 47 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /examples/player-toolbar-buttons.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player - Customm Toolbar Buttons 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |

    31 | Use the options to pass in custom buttons and toolbar definitions. 32 |

    33 | 34 |

    35 |
    36 |
    37 | You need Flash player 8+ and JavaScript enabled to view this video. 38 |
    39 |
    40 |
    41 |
    42 | 43 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /examples/player.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | 18 | Fork me on GitHub 19 | 20 |
    21 | 22 |
    23 | 24 |

    25 | 26 | jQuery Youtube Player 27 | 28 |

    29 | 30 |

    31 | The default player is chromeless with a custom toolbar and playlist area. 32 | The player, toolbar and playlist are completely customizable. 33 |

    34 | 35 |
    36 |
    37 |
    38 | You need Flash player 8+ and JavaScript enabled to view this video. 39 |
    40 |
    41 |
    42 |
    43 | 44 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
    13 | 14 | Fork me on GitHub 15 | 16 |
    17 | 18 |
    19 | 20 |

    21 | jQuery Youtube Player 22 |

    23 | 24 |

    25 | The jQuery Youtube Player plugin builds a custom youtube video player, toolbar and playlist area. 26 |

    27 | 28 |

    Examples:

    29 | 30 | 44 | 45 |

    Wiki

    46 | 47 | 51 | 52 |

    Issues/Feature requests

    53 | 54 |

    If you notice the plugin is working as expected, or would like to request new features, please use the issue tracker.

    55 |

    Tested on: FF3.6; IE 6, 7 and 8; Chrome 7; Safari 5

    56 | 57 |

    Source

    58 | 59 |

    View the source files on github.

    60 | 61 |

    Download

    62 | 63 | 66 | 67 |

    Contact

    68 | 69 |

    Send emails to willis.rh@gmail.com

    70 |
    71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /js/jquery.youtube.player.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jquery.youtube.js v0.1a1 - a jquery youtube player 3 | * Copyright (c) 2010 Richard Willis 4 | * MIT license : http://www.opensource.org/licenses/mit-license.php 5 | * Project : http://github.com/badsyntax/jquery-youtube-player 6 | * Contact : willis.rh@gmail.com | badsyntax.co.uk 7 | */ 8 | 9 | (function($, window, document, undefined){ 10 | 11 | $.fn.player = function(method){ 12 | 13 | var pluginName = 'jquery-youtube-player', args = arguments, val = undefined; 14 | 15 | this.each(function(){ 16 | 17 | // get plugin reference 18 | var obj = $.data( this, pluginName ); 19 | 20 | if ( obj && obj[method]) { 21 | 22 | // execute a public method, store the return value 23 | val = obj[method].apply( obj, Array.prototype.slice.call( args, 1 ) ); 24 | 25 | // only the 'plugin' public method is allowed to return a value 26 | val = (method == 'plugin') ? val : undefined; 27 | } 28 | else if ( !obj && ( typeof method === 'object' || ! method ) ) { 29 | 30 | // initiate the plugin 31 | $.data( this, pluginName, new player(this, method, pluginName) ); 32 | } 33 | }); 34 | 35 | // return the value from a method, or the jQuery object 36 | return val || this; 37 | } 38 | 39 | // player constuctor 40 | function player(element, options, pluginName){ 41 | 42 | var self = this; 43 | 44 | this._pluginName = pluginName; 45 | 46 | this.element = $( element ).addClass('ui-widget'); 47 | 48 | this.options = $.extend({ 49 | width: 425, // player width (integer or string) 50 | height: 356, // player height (integer or string) 51 | swfobject: window.swfobject, // swfobject object 52 | playlist: {}, // playlist object (object literal) 53 | showPlaylist: 1, // show playlist on plugin init (boolean) 54 | showTime: 1, // show current time and duration in toolbar (boolean) 55 | videoThumbs: 0, // show videos as thumbnails in the playlist area (boolean) (experimental) 56 | randomStart: 0, // show random video on plugin init (boolean) 57 | autoStart: 0, // auto play the video after the player as been built (boolean) 58 | autoPlay: 0, // auto play the video when loading it via the playlist or toolbar controls (boolean) 59 | repeat: 1, // repeat videos (boolean) 60 | repeatPlaylist: 0, // repeat the playlist (boolean) 61 | shuffle: 0, // shuffle the play list (boolean) 62 | chromeless: 1, // chromeless player (boolean) 63 | highDef: 0, // high definition quality or normal quality (boolean) 64 | playlistHeight: 5, // height of the playlist (integer) (N * playlist item height) 65 | playlistBuilder: null, // custom playlist builder function (null or function) see http://github.com/badsyntax/jquery-youtube-player/wiki/Installation-and-usage#fn9 66 | playlistBuilderClickHandler: null, // custom playlist video click event handler, useful if you want to prevent default click event (null or function) 67 | playlistAnimation: { 68 | height: 'show', 69 | opacity: 'show' 70 | }, 71 | playlistSpeed: 550, // speed of playlist show/hide animate 72 | toolbarAppendTo: null, // element to append the toolbar to (selector or null) 73 | playlistAppendTo: null, // element to append the playlist to (selector or null) 74 | timeAppendTo: null, // elemend to append to time to (selector or null) 75 | videoParams: { // video params (object literal) 76 | allowfullscreen: 'true', 77 | allowScriptAccess: 'always', 78 | wmode: 'transparent' 79 | }, 80 | showToolbar: null, // show or hide the custom toolbar (null, true or false) 81 | toolbarButtons: {}, // custom toolbar buttons 82 | toolbar: 'play,prev,next,shuffle,repeat,mute,playlistToggle', // comma separated list of toolbar buttons 83 | toolbarAnimation: { 84 | opacity: 1 85 | }, 86 | toolbarSpeed: 500 87 | }, options); 88 | 89 | if (!this.options.chromeless && this.options.showToolbar != true) this.options.showToolbar = 0; 90 | 91 | // these initial states are the youtube player states 92 | // button states will be added to this object 93 | this._states = { 94 | 'unstarted': -1, 95 | 'ended': 0, 96 | 'play': 1, 97 | 'paused': 2, 98 | 'buffering': 3, 99 | 'cued': 5 100 | }; 101 | 102 | // munge youtube video id from any url 103 | this._youtubeIdExp = /^[^v]+v.(.{11}).*/; 104 | 105 | // extend the default toolbar buttons with user specified buttons (specified buttons will override default) 106 | this.buttons = $.extend({}, this.defaultToolbarButtons, this.options.toolbarButtons); 107 | 108 | // convert inks to vidoes 109 | if (this.element.is('a')) { 110 | 111 | var anchor = this.element; 112 | 113 | this.element = $('
    '); 114 | var 115 | playerVideo = $('
    ').appendTo(this.element), 116 | playerObject = $('
    ').appendTo(playerVideo), 117 | playlist = $('
    ') 118 | .find('li') 119 | .append( anchor.clone() ) 120 | .end() 121 | .appendTo(this.element); 122 | 123 | anchor.after( this.element ).hide(); 124 | } 125 | 126 | // store common elements 127 | this.elements = { 128 | player: this.element, 129 | playerVideo: this.element.find('.youtube-player-video'), 130 | playerObject: this.element.find('.youtube-player-object') 131 | }; 132 | 133 | // swfobject will destroy the video object
    , so we clone it to use it to restore it when destroy()ing the plugin 134 | this.elements.playerObjectClone = this.elements.playerObject.clone(); 135 | 136 | this.keys = { video: 0 }; 137 | 138 | // swfobject requires the video object
    to have an id set 139 | var id; 140 | do { 141 | id = 'jqueryyoutubeplayer' + Math.floor( Math.random() * 101 ).toString(); 142 | 143 | } while( document.getElementById(id) ); 144 | 145 | this.elements.playerObject[0].id = id; 146 | 147 | (this.options.swfobject.getFlashPlayerVersion().major >= 8) 148 | 149 | && this.loadPlaylist(null, null, null, function(){ 150 | 151 | // build everything and set event handlers 152 | self 153 | ._bindYoutubeEventHandlers() 154 | ._createToolbar() 155 | ._createTimeArea() 156 | ._createPlayer(); 157 | }); 158 | } 159 | 160 | // public members 161 | player.prototype = { 162 | 163 | _activeStates: [], timer: {}, videoIds: [], 164 | 165 | _trigger : function(scope, callback, arg){ 166 | 167 | var type = typeof callback; 168 | 169 | arg = arg || []; 170 | 171 | if ( type === 'string' && this.options[ callback ] && $.isFunction(this.options[ callback ]) ) { 172 | 173 | return this.options[ callback ].apply( scope, arg ); 174 | 175 | } else if ( type === 'function' ) { 176 | 177 | callback.apply( scope, arg ); 178 | } 179 | }, 180 | 181 | _bindYoutubeEventHandlers : function(){ 182 | 183 | var self = this; 184 | 185 | function ready(id){ 186 | 187 | self.youtubePlayer = document.getElementById(id); 188 | 189 | self._trigger(self, 'onPlayerReady', [ id ]); 190 | 191 | self.loadVideo(false, true); 192 | 193 | self.elements.toolbar.container 194 | .animate(self.options.toolbarAnimation, self.options.toolbarSpeed, function(){ 195 | 196 | self._trigger(self, 'onReady', [ id ]); 197 | }); 198 | 199 | self._showPlaylist(function(){ 200 | 201 | ( self.keys.play ) && self.playVideo(); 202 | }); 203 | } 204 | 205 | function videoPaused(){ 206 | 207 | self._trigger(this, 'onVideoPaused', [ self._getVideo() ]); 208 | } 209 | 210 | function videoEnded(){ 211 | 212 | self.buttons.play.element && self.buttons.play.element.trigger( 'off' ); 213 | 214 | if (self.options.repeat) { 215 | 216 | self.nextVideo(); 217 | } 218 | } 219 | 220 | function error(state){ 221 | 222 | switch(state){ 223 | case 100: 224 | msg = 'This video has been removed from Youtube.'; 225 | break; 226 | case 101: 227 | case 150: 228 | msg = 'This video does not allow playback outside of Youtube.'; 229 | break; 230 | default: 231 | msg = 'Unknown error'; 232 | } 233 | if (self._trigger(this, 'onError', [msg]) === undefined){ 234 | 235 | alert( 'There was an error loading this video. ' + msg ); 236 | } 237 | } 238 | 239 | function videoCued(){ 240 | 241 | self._updatePlaylist(); 242 | 243 | self.elements.toolbar.updateStates(); 244 | 245 | self._trigger(this, 'onVideoCue', arguments); 246 | } 247 | 248 | function videoBuffer(){ 249 | 250 | self._trigger(this, 'onBuffer', [ self._getVideo() ]); 251 | } 252 | 253 | function videoPlay(){ 254 | 255 | self._updatePlaylist(); 256 | 257 | self._addState('play'); 258 | 259 | self.elements.toolbar.updateStates(); 260 | 261 | self._updateTime(); 262 | 263 | // update the location hash 264 | 265 | self._trigger(this, 'onVideoPlay', [ self._getVideo() ]); 266 | } 267 | 268 | var id = this.elements.playerObject[0].id; 269 | 270 | window['onytplayerStateChange' + id] = function(state){ 271 | 272 | // reset the youtube player states every time an event is executed 273 | self._removeStates([ -1, 0, 1, 2, 3, 5, 100, 101, 150, 9 ]); 274 | 275 | // add a new youtube state 276 | self._addState(state, true); 277 | 278 | switch(state) { 279 | case 0 : videoEnded(); break; 280 | case 1 : videoPlay(); break; 281 | case 2 : videoPaused(); break; 282 | case 3 : videoBuffer(); break; 283 | case 9 : ready(id); break; 284 | case 5 : videoCued(); break; 285 | case 100: case 101: case 150: error( state ); break; 286 | } 287 | 288 | self._trigger(self, 'onYoutubeStateChange', [ state ]); 289 | }; 290 | 291 | if ( !window.onYouTubePlayerReady ){ 292 | 293 | window.onYouTubePlayerReady = function(id){ 294 | 295 | var player = document.getElementById(id); 296 | 297 | player.addEventListener("onStateChange", 'onytplayerStateChange' + id); 298 | 299 | player.addEventListener('onError', 'onytplayerStateChange' + id); 300 | 301 | window['onytplayerStateChange' + id](9); 302 | }; 303 | } 304 | 305 | return this; 306 | }, 307 | 308 | _createPlayer : function(){ 309 | 310 | // set the player dimensions 311 | this.elements.player.width( this.options.width ); 312 | this.elements.playerVideo.height( this.options.height ); 313 | 314 | var 315 | id = this.options.playlist.videos[this.keys.video].id, 316 | apiid = this.elements.playerObject[0].id, 317 | swfpath = 318 | this.options.chromeless 319 | ? 'http://www.youtube.com/apiplayer?enablejsapi=1&version=3&playerapiid='+apiid+'&hd=' + this.options.highDef + '&showinfo=0' 320 | : 'http://www.youtube.com/v/' + id + '?enablejsapi=1&playerapiid='+apiid+'&version=3'; 321 | 322 | this._trigger(this, 'onBeforePlayerBuild'); 323 | 324 | // embed the youtube player 325 | this.options.swfobject.embedSWF( swfpath, this.elements.playerObject[0].id, '100%', '100%', '8', null, null, this.options.videoParams); 326 | 327 | return this; 328 | }, 329 | 330 | _createToolbar : function(){ 331 | 332 | var self = this; 333 | 334 | this.elements.toolbar = { 335 | container: $('
      ') 336 | .addClass('youtube-player-toolbar ui-widget ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all') 337 | .css('opacity', 0), 338 | updateStates : function(){ 339 | 340 | self.elements.toolbar.container.find('li').each(function(){ 341 | 342 | var button = $(this).removeClass('ui-state-active').data('button'); 343 | 344 | if (!button) return true; 345 | 346 | (self._state(button.val)) && 347 | (button.toggle) && 348 | $(this).addClass('ui-state-active'); 349 | 350 | (self._state(button.val) && button.toggleButton) && $(this).trigger('on'); 351 | }); 352 | } 353 | }; 354 | 355 | ( this.options.showToolbar != null && !this.options.showToolbar ) 356 | && this.elements.toolbar.container.hide(); 357 | 358 | $.each(this.options.toolbar.split(','), function(key, val) { 359 | 360 | var button = self.buttons[val]; 361 | 362 | if (!button || !button.text) return true; 363 | 364 | button.val = val; 365 | 366 | self._states[val] = self._states[val] || val; 367 | 368 | $('
    • ') 369 | .addClass('ui-state-default ui-corner-all') 370 | .append('') 371 | .attr('title', button.text) 372 | .data('button', button) 373 | .bind('mouseenter mouseleave', function(){ 374 | 375 | $(this).toggleClass('ui-state-hover'); 376 | }) 377 | .bind('off', function(){ 378 | 379 | var elem = $(this), button = elem.data('button'), toggle = 1; 380 | 381 | elem.data('toggle', toggle); 382 | 383 | self._removeState(val); 384 | 385 | elem.find('.ui-icon') 386 | .removeClass( button.toggleButton.icon ) 387 | .addClass( button.icon ) 388 | .end() 389 | .attr('title', button.text); 390 | 391 | self._trigger(self, button.toggleButton.action, [ button ] ); 392 | }) 393 | .bind('on', function(){ 394 | 395 | var elem = $(this), button = elem.data('button'), toggle = 0; 396 | 397 | elem.data('toggle', toggle); 398 | 399 | self._addState(val); 400 | 401 | elem 402 | .find('.ui-icon') 403 | .removeClass( button.icon ) 404 | .addClass( button.toggleButton.icon ) 405 | .end() 406 | .attr('title', button.toggleButton.text) 407 | 408 | self._trigger(self, button.action, [ button ] ); 409 | }) 410 | .bind('toggle', function(){ 411 | 412 | var toggle = $(this).data('toggle'); 413 | 414 | ( toggle || toggle == undefined) ? $(this).trigger('on') : $(this).trigger('off'); 415 | }) 416 | .click(function(){ 417 | 418 | var button = $(this).data('button'), 419 | state = self._state(val); 420 | 421 | if (button.toggleButton) { 422 | 423 | $(this).trigger('toggle'); 424 | } else { 425 | 426 | self._trigger(self, button.action, [ button ] ); 427 | 428 | ( !button.toggle || ( button.toggle && state ) ) 429 | ? self._removeState(val) 430 | : self._addState(val); 431 | 432 | self.elements.toolbar.updateStates(); 433 | } 434 | }) 435 | .appendTo(self.elements.toolbar.container); 436 | }); 437 | 438 | (this.options.toolbarAppendTo) ? 439 | this.elements.toolbar.container.appendTo( this.options.toolbarAppendTo ) : 440 | this.elements.playerVideo.after( this.elements.toolbar.container ); 441 | 442 | return this; 443 | }, 444 | 445 | _createTimeArea : function(){ 446 | 447 | this.elements.toolbar.time = 448 | this.options.timeAppendTo 449 | ? $('').appendTo( this.options.timeAppendTo ) 450 | : $('
    • ').addClass('youtube-player-time').appendTo( this.elements.toolbar.container ); 451 | 452 | this.elements.toolbar.timeCurrent = $('').html('0:00').appendTo(this.elements.toolbar.time); 453 | 454 | this.elements.toolbar.timeDuration = $('').appendTo(this.elements.toolbar.time); 455 | 456 | return this; 457 | }, 458 | 459 | _createPlaylist : function(){ 460 | 461 | var self = this; 462 | 463 | function videoClickHandler(){ 464 | 465 | // try get the video object from element data 466 | var videoData = $( this ).data( 'video' ); 467 | if (!videoData) return; 468 | 469 | // set the video key 470 | self.keys.video = $.inArray( videoData.id, self.videoIds ); 471 | 472 | // reset state 473 | self._removeState('play'); 474 | 475 | // update the playlist now that the new video has been selected 476 | self._updatePlaylist(); 477 | 478 | // load the video into the flash player 479 | self.loadVideo(); 480 | 481 | // play it 482 | self.playVideo(); 483 | } 484 | 485 | function buildPlaylist(){ 486 | 487 | self.elements.playlist = self.elements.playlist 488 | || $('
        ').addClass('youtube-player-playlist ui-helper-reset'); 489 | 490 | self.elements.playlistContainer = self.elements.playlistContainer 491 | || $('
        ') 492 | .addClass('youtube-player-playlist-container ui-widget-content ui-corner-all') 493 | .html( self.elements.playlist ); 494 | }; 495 | 496 | this._addVideosToPlaylist = function(cue){ 497 | 498 | // get this list of vidoes to add to the playlist 499 | // if cueing, we only want to add 1 video, so we find the last video added to playlist 500 | var videos = cue 501 | ? [ self.options.playlist.videos[self.options.playlist.videos.length - 1] ] 502 | : self.options.playlist.videos; 503 | 504 | 505 | // if we're not cueing the videos then we empty the playlist and reset the video id list 506 | if (!cue) { 507 | 508 | self.elements.playlist.empty(); 509 | 510 | self.videoIds = []; 511 | } 512 | 513 | $.each(videos, function(){ 514 | 515 | self.videoIds.push(this.id); 516 | 517 | $('
      1. ') 518 | .data('video', this) 519 | .append( self.options.videoThumbs ? '' + this.title + '' : this.title) 520 | .addClass('ui-state-default') 521 | .addClass( self.options.videoThumbs ? 'youtube-player-thumb' : '' ) 522 | .bind('mouseenter mouseleave', function(){ 523 | 524 | $( this ).toggleClass( 'ui-state-hover' ); 525 | }) 526 | .appendTo(self.elements.playlist); 527 | }); 528 | 529 | self._trigger(self, 'onAfterVideosAddedToPlaylist'); 530 | }; 531 | 532 | this._bindPlaylistClickHandler = function(playlist){ 533 | 534 | playlist 535 | .items 536 | .click(function(){ 537 | 538 | self._trigger(this, videoClickHandler, arguments); 539 | 540 | self._trigger(self, 'playlistBuilderClickHandler', arguments); 541 | }); 542 | }; 543 | 544 | var playlistBuilder; 545 | 546 | if ( !$.isFunction( this.options.playlistBuilder )){ 547 | 548 | buildPlaylist(); 549 | 550 | this._addVideosToPlaylist(); 551 | 552 | (this.options.playlistAppendTo) 553 | // append playlist to specified element 554 | ? this.elements.playlistContainer.appendTo( this.options.playlistAppendTo ) 555 | // insert playlist after the toolbar 556 | : this.elements.toolbar.container.after( this.elements.playlistContainer ); 557 | 558 | playlistBuilder = function(){ 559 | return { 560 | items: self.elements.playlist.find('li'), 561 | container: self.elements.playlistContainer 562 | } 563 | }; 564 | 565 | } else { 566 | 567 | playlistBuilder = this.options.playlistBuilder; 568 | } 569 | 570 | // reset the list of video ids 571 | $.each(this.options.playlist.videos, function(){ 572 | 573 | self.videoIds.push( this.id ); 574 | }); 575 | 576 | // build the playlist 577 | var playlist = playlistBuilder.call(this, this.options.playlist.videos); 578 | 579 | // add the playlist to the DOM 580 | this.elements.playlistContainer = playlist.container; 581 | 582 | // bind video click handler 583 | this._bindPlaylistClickHandler(playlist); 584 | 585 | return this; 586 | }, 587 | 588 | _updateTime : function(){ 589 | 590 | if (!this.options.showTime) return; 591 | 592 | var self = this, duration = Number( this.youtubePlayer.getDuration() ); 593 | 594 | function timeFormat(seconds) { 595 | 596 | var m = Math.floor( seconds / 60), s = (seconds % 60).toFixed(0); 597 | 598 | return m + ':' + ( s < 10 ? '0' + s : s); 599 | } 600 | 601 | this.elements.toolbar.timeDuration.html( ' / ' + timeFormat( duration )); 602 | 603 | this.elements.toolbar.time.fadeIn(); 604 | 605 | this.timeInterval = setInterval(function(){ 606 | 607 | ( !self.youtubePlayer.getCurrentTime ) 608 | ? clearInterval( self.timeInterval ) 609 | : self.elements.toolbar.timeCurrent.html( timeFormat( self.youtubePlayer.getCurrentTime() ) ); 610 | }, 100); 611 | }, 612 | 613 | _removeStates : function(states){ 614 | 615 | var newArray = []; 616 | 617 | $.each(this._activeStates, function(key, value){ 618 | 619 | ($.inArray(value, states) === -1 620 | && $.inArray(value, newArray) === -1) 621 | && newArray.push(value); 622 | }); 623 | 624 | this._activeStates = newArray; 625 | }, 626 | 627 | _removeState : function(state){ 628 | 629 | state = typeof state === 'string' ? this._states[ state ] : state; 630 | 631 | this._removeStates([ state ]); 632 | }, 633 | 634 | _state : function(state, remove){ 635 | 636 | state = this._states[ state ]; 637 | 638 | return $.inArray(state, this._activeStates) !== -1 ? true : false; 639 | }, 640 | 641 | _addState : function(state, stateID){ 642 | 643 | if (stateID) { 644 | 645 | $.inArray(state, this._activeStates) === -1 646 | && this._activeStates.push( state ); 647 | 648 | } else { 649 | 650 | this._states[ state ] 651 | && $.inArray(this._states[ state ], this._activeStates) === -1 652 | && this._activeStates.push( this._states[ state ] ); 653 | } 654 | }, 655 | 656 | _setVideoKey : function(val){ 657 | 658 | this.keys.video = this.options.shuffle ? this.options.randomVideo() : val || 0; 659 | }, 660 | 661 | _getVideo : function(){ 662 | 663 | return this.options.playlist.videos[ this.keys.video ]; 664 | }, 665 | 666 | _findVideo : function(id){ 667 | 668 | var index = -1; 669 | 670 | $.each(this.options.playlist.videos, function(key, val){ 671 | 672 | if (id == val.id) { 673 | 674 | index = key; 675 | 676 | return false; // break 677 | } 678 | }); 679 | 680 | return index; 681 | }, 682 | 683 | _getPlaylistData : function(success, error){ 684 | 685 | var self = this, playlist = this.options.playlist; 686 | 687 | if (playlist.user || playlist.playlist) { 688 | 689 | function ajaxSuccess(json){ 690 | 691 | if (!json) { 692 | error.call( self ); 693 | return; 694 | } 695 | 696 | // replace playlist ID with json array 697 | self.options.playlist = { 698 | title: json.feed.title.$t, 699 | id: playlist, 700 | videos: [] 701 | }; 702 | 703 | $.each(json.feed.entry, function(key, vid){ 704 | self.options.playlist.videos.push({ 705 | id: vid.link[0].href.replace(self._youtubeIdExp, '$1'), // munge video id from href 706 | title: vid.title.$t 707 | }); 708 | }); 709 | 710 | self.elements.playerObject.fadeOut(180, function(){ success.call( self ); }); 711 | } 712 | 713 | var url = playlist.user 714 | ? 'http://gdata.youtube.com/feeds/api/videos' 715 | : 'http://gdata.youtube.com/feeds/api/playlists/' + playlist.playlist; 716 | 717 | url += '?callback=?'; 718 | 719 | var data = { alt: 'json', format: '5' }; 720 | 721 | if (playlist.user){ data.author = playlist.user; } 722 | 723 | this._trigger(this, 'onBeforePlaylistLoaded', [ playlist ]); 724 | 725 | $.ajax({ 726 | type: 'GET', 727 | url: url, 728 | data: data, 729 | dataType: 'json', 730 | error: function(){ 731 | 732 | self._trigger(self, 'onAfterPlaylistLoaded', [ playlist ]); 733 | 734 | self._trigger(self, error); 735 | }, 736 | success: function(){ 737 | 738 | self._trigger(self, 'onAfterPlaylistLoaded', [ playlist ]); 739 | 740 | self._trigger(self, ajaxSuccess, arguments); 741 | } 742 | }); 743 | 744 | return; 745 | 746 | } else if (!playlist.videos){ 747 | 748 | var videos = this.elements.player.find('.youtube-player-playlist li a'); 749 | 750 | if (videos.length) { 751 | 752 | self.options.playlist.videos = []; 753 | 754 | videos.each(function(){ 755 | self.options.playlist.videos.push({ 756 | id: this.href.replace(self._youtubeIdExp, '$1'), 757 | title: $(this).html(), 758 | element: this 759 | }); 760 | }); 761 | } 762 | } 763 | 764 | self._trigger(self, 'onAfterPlaylistLoaded', [ playlist ]); 765 | 766 | self._trigger(self, success); 767 | }, 768 | 769 | _updatePlaylist : function(){ 770 | 771 | var self = this; 772 | 773 | (this.elements.playlist) && 774 | 775 | this.elements.playlist 776 | .find('li') 777 | .removeClass('ui-state-active') 778 | .each(function(key){ 779 | 780 | if ( self.options.playlist.videos[self.keys.video].id == $(this).data('video').id) { 781 | 782 | var height = $( this ).addClass('ui-state-active').outerHeight(); 783 | 784 | if ( !self.options.videoThumbs ){ 785 | 786 | var pos = (key * height) - ( Math.floor(self.options.playlistHeight / 2) * height); 787 | 788 | self.elements.playlist.scrollTop( pos ); 789 | } 790 | 791 | return false; 792 | } 793 | }); 794 | }, 795 | 796 | _showPlaylist : function(callback) { 797 | 798 | var show = this.options.showPlaylist; 799 | 800 | ( show ) && this.elements.playlistContainer.show(); 801 | 802 | var 803 | oldHeight = this.elements.playlist.height(), 804 | scrollerHeight = this.elements.playlist.css('height', 'auto').height(), 805 | videoHeight = this.elements.playlist.find('li:first').outerHeight(), 806 | newHeight = videoHeight * this.options.playlistHeight, 807 | height = newHeight < scrollerHeight ? newHeight : scrollerHeight; 808 | 809 | ( show ) && this.elements.playlistContainer.hide(); 810 | 811 | if ( !this.elements.playlist.children().length ) { 812 | 813 | this.elements.playlistContainer.hide(); 814 | 815 | this._trigger(this, callback); 816 | 817 | } else if ( height ) { 818 | 819 | this.elements.playlist.height( height ); 820 | 821 | if (this.options.showPlaylist || show) { 822 | 823 | this.elements.playlistContainer.animate(this.options.playlistAnimation, this.options.playlistSpeed, callback); 824 | 825 | } else { 826 | 827 | this._trigger(this, callback); 828 | } 829 | } 830 | }, 831 | 832 | loadVideo : function(video, cue){ 833 | 834 | var self = this; 835 | 836 | function load(videoID){ 837 | 838 | ( cue ) 839 | ? self.cueVideo(videoID) 840 | : self.youtubePlayer.loadVideoById(videoID, 0); 841 | 842 | self._trigger(self, 'onVideoLoad', [ self._getVideo() ]); 843 | } 844 | 845 | if (video && video.id) { 846 | 847 | video = { 848 | id: video.id, 849 | title: video.title 850 | }; 851 | 852 | this.videoIds = cue ? this.videoIds : []; 853 | 854 | if (cue) { 855 | 856 | // append video to video list 857 | this.options.playlist.videos.push(video); 858 | } else { 859 | 860 | // add video to video list only if a title is present 861 | this.options.playlist.videos = video.title ? [ video ] : []; 862 | } 863 | 864 | // add video/s to playlist 865 | this._addVideosToPlaylist(cue); 866 | 867 | // update the height of the playlist, but don't explicidly show it 868 | //this._showPlaylist(false); 869 | 870 | (!cue) && 871 | // load and play the video 872 | load(video.id); 873 | 874 | } else if (video) { 875 | 876 | // you can't load videos that aren't in the current playlist 877 | 878 | var index = this._findVideo( video ); 879 | 880 | if (index !== -1) { 881 | 882 | this.keys.video = index; 883 | 884 | load( video ); 885 | } 886 | 887 | } else { 888 | 889 | // try load the next video 890 | load( this.options.playlist.videos[this.keys.video].id ); 891 | } 892 | }, 893 | 894 | loadPlaylist: function(playlist, play, show, success){ 895 | 896 | show = show === undefined ? true : show; 897 | 898 | if ( playlist ) { 899 | 900 | this.options.playlist = playlist; 901 | } 902 | 903 | this._getPlaylistData( 904 | function(){ // success 905 | 906 | this.keys.video = this.options.randomStart ? this.randomVideo() : 0; 907 | 908 | this._trigger(this, success); 909 | 910 | this._createPlaylist(); 911 | 912 | (show) && this._showPlaylist(); 913 | }, 914 | function(){ // error 915 | 916 | var msg = 'There was an error loading the playlist.'; 917 | 918 | this.elements.playerObject.html( msg ); 919 | 920 | this._trigger(this, 'onError', [msg]); 921 | } 922 | ); 923 | }, 924 | 925 | pauseVideo : function(){ 926 | 927 | this.youtubePlayer.pauseVideo(); 928 | }, 929 | 930 | shufflePlaylist : function(){ 931 | 932 | this.randomVideo(); 933 | 934 | this.playVideo(); 935 | }, 936 | 937 | muteVideo : function(button){ 938 | 939 | this._state('mute') ? this.youtubePlayer.unMute() : this.youtubePlayer.mute(); 940 | }, 941 | 942 | // FIXME 943 | repeat : function(){ 944 | 945 | this.options.repeat = 1; 946 | }, 947 | 948 | playVideo : function(){ 949 | 950 | this.youtubePlayer.playVideo(); 951 | }, 952 | 953 | cueVideo : function(videoID, startTime){ 954 | 955 | return this.youtubePlayer.cueVideoById( videoID || this.options.playlist.videos[this.keys.video].id, startTime || 0); 956 | }, 957 | 958 | randomVideo : function(){ 959 | 960 | this.keys.video = Math.floor(Math.random() * this.options.playlist.videos.length); 961 | 962 | return this.keys.video; 963 | }, 964 | 965 | prevVideo : function(){ 966 | 967 | if (this.keys.video > 0) { 968 | 969 | this._setVideoKey( --this.keys.video ); 970 | 971 | } else if ( this.options.repeatPlaylist ) { 972 | 973 | this._setVideoKey( this.videoIds.length - 1 ); 974 | 975 | } else return; 976 | 977 | this.loadVideo(null, this._state('play') || this.options.autoPlay ? false : true); 978 | }, 979 | 980 | nextVideo : function(){ 981 | 982 | if (this.keys.video < this.options.playlist.videos.length-1) { 983 | 984 | this._setVideoKey( ++this.keys.video ); 985 | 986 | } else if ( this.options.repeatPlaylist ) { 987 | 988 | this._trigger(this, 'onEndPlaylist'); 989 | 990 | this._setVideoKey( 0 ); 991 | 992 | } else return; 993 | 994 | this.loadVideo(null, this._state('play') || this.options.autoPlay ? false : true); 995 | }, 996 | 997 | playlistToggle : function(button){ 998 | 999 | (this.elements.playlistContainer.find('li').length) && 1000 | 1001 | this.elements 1002 | .playlistContainer 1003 | .animate({ 1004 | height: 'toggle', 1005 | opacity: 'toggle' 1006 | }, this.options.playlistSpeed); 1007 | }, 1008 | 1009 | // return the plugin object 1010 | plugin : function(){ return this; }, 1011 | 1012 | // return an array of current player states 1013 | state : function(){ 1014 | 1015 | var self = this, states = []; 1016 | 1017 | $.each(this._activeStates, function(key, val){ 1018 | 1019 | $.each(self._states, function(k, v){ 1020 | 1021 | (val === v) && states.push(k); 1022 | }); 1023 | }); 1024 | 1025 | return states; 1026 | }, 1027 | 1028 | videos : function(){ 1029 | 1030 | return this.options.playlist.videos; 1031 | }, 1032 | 1033 | videoIndex : function(){ 1034 | 1035 | return this.keys.video; 1036 | }, 1037 | 1038 | destroy: function(){ 1039 | 1040 | clearInterval( this.timeInterval ); 1041 | 1042 | this.element.removeClass('ui-widget').removeAttr('style'); 1043 | 1044 | this.elements.playerVideo.removeAttr('style'); 1045 | 1046 | this.elements.playlistContainer.remove(); 1047 | 1048 | this.elements.toolbar.container.remove(); 1049 | 1050 | this.options.swfobject.removeSWF(this.elements.playerObject[0].id); 1051 | 1052 | this.elements.playerObjectClone.appendTo( this.elements.playerVideo ); 1053 | 1054 | $.removeData( this.element[0], this._pluginName ); 1055 | } 1056 | }; 1057 | 1058 | player.prototype.defaultToolbarButtons = { 1059 | play: { 1060 | text: 'Play', 1061 | icon: 'ui-icon-play', 1062 | toggleButton: { 1063 | text: 'Pause', 1064 | icon: 'ui-icon-pause', 1065 | action: function(){ 1066 | 1067 | this.pauseVideo(); 1068 | } 1069 | }, 1070 | action: function(){ 1071 | 1072 | this.playVideo(); 1073 | } 1074 | }, 1075 | prev: { 1076 | text: 'Prev', 1077 | icon: 'ui-icon-seek-prev', 1078 | action: function(){ 1079 | 1080 | this.prevVideo(); 1081 | } 1082 | }, 1083 | next: { 1084 | text: 'Next', 1085 | icon: 'ui-icon-seek-next', 1086 | action: function(){ 1087 | 1088 | this.nextVideo(); 1089 | } 1090 | }, 1091 | shuffle: { 1092 | text: 'Shuffle/Random', 1093 | icon: 'ui-icon-shuffle', 1094 | toggle: 1, 1095 | action: function(){ 1096 | 1097 | this.shufflePlaylist(); 1098 | } 1099 | }, 1100 | repeat: { 1101 | text: 'Repeat playlist', 1102 | icon: 'ui-icon-refresh', 1103 | toggle: 1, 1104 | action: function(){ 1105 | 1106 | this.repeat(); 1107 | } 1108 | }, 1109 | mute: { 1110 | text: 'Mute', 1111 | icon: 'ui-icon-volume-on', 1112 | toggle: 1, 1113 | action: function(button){ 1114 | 1115 | this.muteVideo(button); 1116 | } 1117 | }, 1118 | playlistToggle: { 1119 | text: 'Toggle playlist', 1120 | icon: 'ui-icon-script', 1121 | action: function(){ 1122 | 1123 | this.playlistToggle(); 1124 | } 1125 | } 1126 | }; 1127 | 1128 | })(this.jQuery, this, document); 1129 | -------------------------------------------------------------------------------- /js/jquery.youtube.player.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jquery.youtube.min.js v0.1a1 - a jquery youtube player 3 | * Copyright (c) 2010 Richard Willis 4 | * MIT license : http://www.opensource.org/licenses/mit-license.php 5 | * Project : http://github.com/badsyntax/jquery-youtube-player 6 | * Contact : willis.rh@gmail.com | badsyntax.co.uk 7 | * Build time : Tue Nov 2 22:42:07 GMT 2010 8 | */ 9 | (function(e,k,n,l){function o(a,b,c){var d=this;this._pluginName=c;this.element=e(a).addClass("ui-widget");this.options=e.extend({width:425,height:356,swfobject:k.swfobject,playlist:{},showPlaylist:1,showTime:1,videoThumbs:0,randomStart:0,autoStart:0,autoPlay:0,repeat:1,repeatPlaylist:0,shuffle:0,chromeless:1,highDef:0,playlistHeight:5,playlistBuilder:null,playlistBuilderClickHandler:null,playlistAnimation:{height:"show",opacity:"show"},playlistSpeed:550,toolbarAppendTo:null,playlistAppendTo:null, 10 | timeAppendTo:null,videoParams:{allowfullscreen:"true",allowScriptAccess:"always",wmode:"transparent"},showToolbar:null,toolbarButtons:{},toolbar:"play,prev,next,shuffle,repeat,mute,playlistToggle",toolbarAnimation:{opacity:1},toolbarSpeed:500},b);if(!this.options.chromeless&&this.options.showToolbar!=true)this.options.showToolbar=0;this._states={unstarted:-1,ended:0,play:1,paused:2,buffering:3,cued:5};this._youtubeIdExp=/^[^v]+v.(.{11}).*/;this.buttons=e.extend({},this.defaultToolbarButtons,this.options.toolbarButtons); 11 | if(this.element.is("a")){a=this.element;this.element=e('
        ');b=e('
        ').appendTo(this.element);e('
        ').appendTo(b);e('
        ').find("li").append(a.clone()).end().appendTo(this.element);a.after(this.element).hide()}this.elements={player:this.element,playerVideo:this.element.find(".youtube-player-video"),playerObject:this.element.find(".youtube-player-object")}; 12 | this.elements.playerObjectClone=this.elements.playerObject.clone();this.keys={video:0};do a="jqueryyoutubeplayer"+Math.floor(Math.random()*101).toString();while(n.getElementById(a));this.elements.playerObject[0].id=a;this.options.swfobject.getFlashPlayerVersion().major>=8&&this.loadPlaylist(null,null,null,function(){d._bindYoutubeEventHandlers()._createToolbar()._createTimeArea()._createPlayer()})}e.fn.player=function(a){var b=arguments,c=l;this.each(function(){var d=e.data(this,"jquery-youtube-player"); 13 | if(d&&d[a]){c=d[a].apply(d,Array.prototype.slice.call(b,1));c=a=="plugin"?c:l}else if(!d&&(typeof a==="object"||!a))e.data(this,"jquery-youtube-player",new o(this,a,"jquery-youtube-player"))});return c||this};o.prototype={_activeStates:[],timer:{},videoIds:[],_trigger:function(a,b,c){var d=typeof b;c=c||[];if(d==="string"&&this.options[b]&&e.isFunction(this.options[b]))return this.options[b].apply(a,c);else d==="function"&&b.apply(a,c)},_bindYoutubeEventHandlers:function(){function a(i){f.youtubePlayer= 14 | n.getElementById(i);f._trigger(f,"onPlayerReady",[i]);f.loadVideo(false,true);f.elements.toolbar.container.animate(f.options.toolbarAnimation,f.options.toolbarSpeed,function(){f._trigger(f,"onReady",[i])});f._showPlaylist(function(){f.keys.play&&f.playVideo()})}function b(){f._trigger(this,"onVideoPaused",[f._getVideo()])}function c(i){switch(i){case 100:msg="This video has been removed from Youtube.";break;case 101:case 150:msg="This video does not allow playback outside of Youtube.";break;default:msg= 15 | "Unknown error"}f._trigger(this,"onError",[msg])===l&&alert("There was an error loading this video. "+msg)}function d(){f._updatePlaylist();f.elements.toolbar.updateStates();f._trigger(this,"onVideoCue",arguments)}function g(){f._trigger(this,"onBuffer",[f._getVideo()])}function h(){f._updatePlaylist();f._addState("play");f.elements.toolbar.updateStates();f._updateTime();f._trigger(this,"onVideoPlay",[f._getVideo()])}var f=this,j=this.elements.playerObject[0].id;k["onytplayerStateChange"+j]=function(i){f._removeStates([-1, 16 | 0,1,2,3,5,100,101,150,9]);f._addState(i,true);switch(i){case 0:f.buttons.play.element&&f.buttons.play.element.trigger("off");f.options.repeat&&f.nextVideo();break;case 1:h();break;case 2:b();break;case 3:g();break;case 9:a(j);break;case 5:d();break;case 100:case 101:case 150:c(i)}f._trigger(f,"onYoutubeStateChange",[i])};if(!k.onYouTubePlayerReady)k.onYouTubePlayerReady=function(i){var m=n.getElementById(i);m.addEventListener("onStateChange","onytplayerStateChange"+i);m.addEventListener("onError", 17 | "onytplayerStateChange"+i);k["onytplayerStateChange"+i](9)};return this},_createPlayer:function(){this.elements.player.width(this.options.width);this.elements.playerVideo.height(this.options.height);var a=this.options.playlist.videos[this.keys.video].id,b=this.elements.playerObject[0].id;a=this.options.chromeless?"http://www.youtube.com/apiplayer?enablejsapi=1&version=3&playerapiid="+b+"&hd="+this.options.highDef+"&showinfo=0":"http://www.youtube.com/v/"+a+"?enablejsapi=1&playerapiid="+b+"&version=3"; 18 | this._trigger(this,"onBeforePlayerBuild");this.options.swfobject.embedSWF(a,this.elements.playerObject[0].id,"100%","100%","8",null,null,this.options.videoParams);return this},_createToolbar:function(){var a=this;this.elements.toolbar={container:e("
          ").addClass("youtube-player-toolbar ui-widget ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").css("opacity",0),updateStates:function(){a.elements.toolbar.container.find("li").each(function(){var b=e(this).removeClass("ui-state-active").data("button"); 19 | if(!b)return true;a._state(b.val)&&b.toggle&&e(this).addClass("ui-state-active");a._state(b.val)&&b.toggleButton&&e(this).trigger("on")})}};this.options.showToolbar!=null&&!this.options.showToolbar&&this.elements.toolbar.container.hide();e.each(this.options.toolbar.split(","),function(b,c){var d=a.buttons[c];if(!d||!d.text)return true;d.val=c;a._states[c]=a._states[c]||c;e("
        • ").addClass("ui-state-default ui-corner-all").append('').attr("title",d.text).data("button", 20 | d).bind("mouseenter mouseleave",function(){e(this).toggleClass("ui-state-hover")}).bind("off",function(){var g=e(this),h=g.data("button");g.data("toggle",1);a._removeState(c);g.find(".ui-icon").removeClass(h.toggleButton.icon).addClass(h.icon).end().attr("title",h.text);a._trigger(a,h.toggleButton.action,[h])}).bind("on",function(){var g=e(this),h=g.data("button");g.data("toggle",0);a._addState(c);g.find(".ui-icon").removeClass(h.icon).addClass(h.toggleButton.icon).end().attr("title",h.toggleButton.text); 21 | a._trigger(a,h.action,[h])}).bind("toggle",function(){var g=e(this).data("toggle");g||g==l?e(this).trigger("on"):e(this).trigger("off")}).click(function(){var g=e(this).data("button"),h=a._state(c);if(g.toggleButton)e(this).trigger("toggle");else{a._trigger(a,g.action,[g]);!g.toggle||g.toggle&&h?a._removeState(c):a._addState(c);a.elements.toolbar.updateStates()}}).appendTo(a.elements.toolbar.container)});this.options.toolbarAppendTo?this.elements.toolbar.container.appendTo(this.options.toolbarAppendTo): 22 | this.elements.playerVideo.after(this.elements.toolbar.container);return this},_createTimeArea:function(){this.elements.toolbar.time=this.options.timeAppendTo?e("").appendTo(this.options.timeAppendTo):e("
        • ").addClass("youtube-player-time").appendTo(this.elements.toolbar.container);this.elements.toolbar.timeCurrent=e("").html("0:00").appendTo(this.elements.toolbar.time);this.elements.toolbar.timeDuration=e("").appendTo(this.elements.toolbar.time);return this},_createPlaylist:function(){function a(){var d= 23 | e(this).data("video");if(d){b.keys.video=e.inArray(d.id,b.videoIds);b._removeState("play");b._updatePlaylist();b.loadVideo();b.playVideo()}}var b=this;this._addVideosToPlaylist=function(d){var g=d?[b.options.playlist.videos[b.options.playlist.videos.length-1]]:b.options.playlist.videos;if(!d){b.elements.playlist.empty();b.videoIds=[]}e.each(g,function(){b.videoIds.push(this.id);e("
        • ").data("video",this).append(b.options.videoThumbs?''+this.title+'':this.title).addClass("ui-state-default").addClass(b.options.videoThumbs?"youtube-player-thumb":"").bind("mouseenter mouseleave",function(){e(this).toggleClass("ui-state-hover")}).appendTo(b.elements.playlist)});b._trigger(b,"onAfterVideosAddedToPlaylist")};this._bindPlaylistClickHandler=function(d){d.items.click(function(){b._trigger(this,a,arguments);b._trigger(b,"playlistBuilderClickHandler",arguments)})};var c;if(e.isFunction(this.options.playlistBuilder))c=this.options.playlistBuilder; 25 | else{b.elements.playlist=b.elements.playlist||e("
            ").addClass("youtube-player-playlist ui-helper-reset");b.elements.playlistContainer=b.elements.playlistContainer||e("
            ").addClass("youtube-player-playlist-container ui-widget-content ui-corner-all").html(b.elements.playlist);this._addVideosToPlaylist();this.options.playlistAppendTo?this.elements.playlistContainer.appendTo(this.options.playlistAppendTo):this.elements.toolbar.container.after(this.elements.playlistContainer);c=function(){return{items:b.elements.playlist.find("li"), 26 | container:b.elements.playlistContainer}}}e.each(this.options.playlist.videos,function(){b.videoIds.push(this.id)});c=c.call(this,this.options.playlist.videos);this.elements.playlistContainer=c.container;this._bindPlaylistClickHandler(c);return this},_updateTime:function(){function a(d){var g=Math.floor(d/60);d=(d%60).toFixed(0);return g+":"+(d<10?"0"+d:d)}if(this.options.showTime){var b=this,c=Number(this.youtubePlayer.getDuration());this.elements.toolbar.timeDuration.html(" / "+a(c));this.elements.toolbar.time.fadeIn(); 27 | this.timeInterval=setInterval(function(){!b.youtubePlayer.getCurrentTime?clearInterval(b.timeInterval):b.elements.toolbar.timeCurrent.html(a(b.youtubePlayer.getCurrentTime()))},100)}},_removeStates:function(a){var b=[];e.each(this._activeStates,function(c,d){e.inArray(d,a)===-1&&e.inArray(d,b)===-1&&b.push(d)});this._activeStates=b},_removeState:function(a){a=typeof a==="string"?this._states[a]:a;this._removeStates([a])},_state:function(a){a=this._states[a];return e.inArray(a,this._activeStates)!== 28 | -1?true:false},_addState:function(a,b){if(b)e.inArray(a,this._activeStates)===-1&&this._activeStates.push(a);else this._states[a]&&e.inArray(this._states[a],this._activeStates)===-1&&this._activeStates.push(this._states[a])},_setVideoKey:function(a){this.keys.video=this.options.shuffle?this.options.randomVideo():a||0},_getVideo:function(){return this.options.playlist.videos[this.keys.video]},_findVideo:function(a){var b=-1;e.each(this.options.playlist.videos,function(c,d){if(a==d.id){b=c;return false}}); 29 | return b},_getPlaylistData:function(a,b){var c=this,d=this.options.playlist;if(d.user||d.playlist){var g=function(j){if(j){c.options.playlist={title:j.feed.title.$t,id:d,videos:[]};e.each(j.feed.entry,function(i,m){c.options.playlist.videos.push({id:m.link[0].href.replace(c._youtubeIdExp,"$1"),title:m.title.$t})});c.elements.playerObject.fadeOut(180,function(){a.call(c)})}else b.call(c)},h=d.user?"http://gdata.youtube.com/feeds/api/videos":"http://gdata.youtube.com/feeds/api/playlists/"+d.playlist; 30 | h+="?callback=?";var f={alt:"json",format:"5"};if(d.user)f.author=d.user;this._trigger(this,"onBeforePlaylistLoaded",[d]);e.ajax({type:"GET",url:h,data:f,dataType:"json",error:function(){c._trigger(c,"onAfterPlaylistLoaded",[d]);c._trigger(c,b)},success:function(){c._trigger(c,"onAfterPlaylistLoaded",[d]);c._trigger(c,g,arguments)}})}else{if(!d.videos){h=this.elements.player.find(".youtube-player-playlist li a");if(h.length){c.options.playlist.videos=[];h.each(function(){c.options.playlist.videos.push({id:this.href.replace(c._youtubeIdExp, 31 | "$1"),title:e(this).html(),element:this})})}}c._trigger(c,"onAfterPlaylistLoaded",[d]);c._trigger(c,a)}},_updatePlaylist:function(){var a=this;this.elements.playlist&&this.elements.playlist.find("li").removeClass("ui-state-active").each(function(b){if(a.options.playlist.videos[a.keys.video].id==e(this).data("video").id){var c=e(this).addClass("ui-state-active").outerHeight();a.options.videoThumbs||a.elements.playlist.scrollTop(b*c-Math.floor(a.options.playlistHeight/2)*c);return false}})},_showPlaylist:function(a){var b= 32 | this.options.showPlaylist;b&&this.elements.playlistContainer.show();this.elements.playlist.height();var c=this.elements.playlist.css("height","auto").height(),d=this.elements.playlist.find("li:first").outerHeight()*this.options.playlistHeight;c=d 36 | 0)this._setVideoKey(--this.keys.video);else if(this.options.repeatPlaylist)this._setVideoKey(this.videoIds.length-1);else return;this.loadVideo(null,this._state("play")||this.options.autoPlay?false:true)},nextVideo:function(){if(this.keys.video tag shouldn\'t exist'); 23 | 24 | start(); 25 | 26 | }, 1000); 27 | }); 28 | -------------------------------------------------------------------------------- /tests/events.js: -------------------------------------------------------------------------------- 1 | /* 2 | * events.js - part of the jquery youtube player testsuite 3 | * @author: Richard Willis 4 | * @note: This test should be the last run, it would be pointless to test these events if parts of the API are broken 5 | * as we need to use the API methods to trigger some of these events. 6 | */ 7 | 8 | 9 | module('events'); 10 | 11 | var playlist = { title: 'test playlist', videos: [ { id: 'wDowSzVgjXI', title: 'The All Seeing I - Beat Goes On HQ' } ] }; 12 | 13 | test('onPlayerReady()', function(){ 14 | 15 | stop(1000); 16 | 17 | $('.player').player({ 18 | playlist: playlist, 19 | onPlayerReady: function(){ 20 | 21 | ok(true, 'Flash player has been built and Youtube API is ready to be used.'); 22 | 23 | start(); 24 | 25 | this.destroy(); 26 | } 27 | }); 28 | }); 29 | 30 | test('onReady()', function(){ 31 | 32 | stop(1000); 33 | 34 | $('.player').player({ 35 | playlist: playlist, 36 | onReady: function(){ 37 | 38 | ok(true, 'Player and toolbar have been constructed and animated, first video has been cued.'); 39 | 40 | start(); 41 | 42 | this.destroy(); 43 | } 44 | }); 45 | }); 46 | 47 | test('onYoutubeStateChange()', function(){}); 48 | test('onVideoLoad()', function(){}); 49 | test('onVideoCue()', function(){}); 50 | test('onVideoPlay()', function(){}) 51 | test('onVideoPaused()', function(){}); 52 | test('onBuffer()', function(){}); 53 | test('onError()', function(){}); 54 | test('onBeforePlaylistLoaded()', function(){}); 55 | test('onAfterPlaylistLoaded()', function(){}); 56 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jQuery Youtube Player Test Suite 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 |

            jQuery Youtube Player Test Suite

            21 |

            22 |
            23 |

            24 |
              25 | 26 | 27 | 28 |
              29 |
              30 |
               
              31 |
              32 |
              33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /tests/setup.js: -------------------------------------------------------------------------------- 1 | module('setup'); 2 | 3 | test('expected scripts', function(){ 4 | 5 | expect(3); 6 | 7 | ok( window.jQuery, 'jQuery should exist' ); 8 | ok( window.swfobject, 'swfobject should exist' ); 9 | ok( window.jQuery.fn.player, 'player plugin should exist' ); 10 | }); 11 | 12 | var playlist = { title: 'test playlist', videos: [ { id: 'wDowSzVgjXI', title: 'The All Seeing I - Beat Goes On HQ' } ] }; 13 | 14 | test('expected markup', function(){ 15 | 16 | expect(3); 17 | 18 | ok( $('.player').length, 'player container' ); 19 | ok( $('.youtube-player-video').length, 'player video container' ); 20 | ok( $('.youtube-player-object').length, 'player object container' ); 21 | }); 22 | 23 | test('expected css', function(){ 24 | 25 | ok(true, 'not testing this for now'); 26 | }); 27 | 28 | test('plugin init', function(){ 29 | 30 | var v1 = $('.player').player({ playlist: playlist }).player('plugin'); 31 | var v2 = $('.player').player({ playlist: playlist }).player('plugin'); 32 | 33 | equals( v1, v2, 'Calling player() multiple times must return the same plugin instance' ); 34 | 35 | stop(); 36 | 37 | setTimeout(function(){ 38 | 39 | var hasObject = $('.player').find('object').length 40 | 41 | ok(hasObject, ' tag should exist'); 42 | 43 | $('.player').player('destroy'); 44 | 45 | start(); 46 | 47 | }, 1000); 48 | }); 49 | --------------------------------------------------------------------------------