├── .gitignore ├── Gruntfile.js ├── LICENSE ├── bower.json ├── dist ├── jquery.vimeo.api.js └── jquery.vimeo.api.min.js ├── example.html ├── package.json ├── readme.md ├── src └── jquery.vimeo.api.js └── vimeoapi.jquery.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | // Project configuration. 4 | grunt.initConfig({ 5 | 6 | pkg: grunt.file.readJSON('package.json'), 7 | 8 | // clean tasks 9 | clean: { 10 | // target all output files 11 | all: ['dist/*.*'] 12 | }, 13 | 14 | //lint tasks 15 | jshint: { 16 | files: ['Gruntfile.js', 'src/jquery.vimeo.api.js'], 17 | options: { 18 | globals: { 19 | jQuery: true 20 | } 21 | } 22 | }, 23 | 24 | concat: { 25 | options: { 26 | banner: 27 | '/**!\n' + 28 | ' * <%= pkg.title %> -- By <%= pkg.author.name %>\n' + 29 | ' * \n' + 30 | ' * Description: <%= pkg.description %>\n' + 31 | ' * Author: <%= pkg.author.name %>, <%= pkg.author.email %> \n' + 32 | ' * License: <%= pkg.license %>\n' + 33 | ' * Version: <%= pkg.version %>\n' + 34 | ' */\n' 35 | }, 36 | 37 | dist: { 38 | src: ['src/jquery.vimeo.api.js'], 39 | dest: 'dist/jquery.vimeo.api.js', 40 | } 41 | }, 42 | 43 | uglify: { 44 | options: { 45 | banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' 46 | }, 47 | dist: { 48 | files : { 49 | 'dist/jquery.vimeo.api.min.js': ['<%= concat.dist.dest %>'] 50 | } 51 | } 52 | }, 53 | 54 | //bump version up https://www.npmjs.com/package/grunt-bumpup 55 | bumpup: { 56 | files: [ 57 | 'package.json', 58 | 'bower.json', 59 | 'vimeoapi.jquery.json' 60 | ], 61 | } 62 | 63 | 64 | }); 65 | 66 | grunt.loadNpmTasks('grunt-contrib-clean'); 67 | grunt.loadNpmTasks('grunt-contrib-concat'); 68 | grunt.loadNpmTasks('grunt-contrib-uglify'); 69 | grunt.loadNpmTasks('grunt-contrib-jshint'); 70 | grunt.loadNpmTasks('grunt-bumpup'); 71 | 72 | // Default task(s). 73 | grunt.registerTask('default', ['clean','concat','jshint','uglify']); 74 | 75 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2015 Jeremy Rue 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vimeo-jquery-api", 3 | "version": "0.10.2", 4 | "homepage": "https://github.com/jrue/Vimeo-jQuery-API", 5 | "authors": [ 6 | "Jeremy Rue " 7 | ], 8 | "description": "A jQuery plugin to easily control Vimeo videos through their API.", 9 | "main": [ 10 | "dist/jquery.vimeo.api.js", 11 | "dist/jquery.vimeo.api.min.js" 12 | ], 13 | "keywords": [ 14 | "video", 15 | "Vimeo", 16 | "iframe", 17 | "api", 18 | "javascript", 19 | "jquery-plugin" 20 | ], 21 | "license": "MIT", 22 | "ignore": [ 23 | "**/.*", 24 | "node_modules", 25 | "bower_components", 26 | "test", 27 | "tests", 28 | "example.html", 29 | "src", 30 | "Gruntfile.js", 31 | "LICENSE", 32 | "package.json", 33 | "vimeoapi.jquery.json", 34 | "readme.md", 35 | "bower.json" 36 | ], 37 | "dependencies": { 38 | "jquery": ">=1.7" 39 | } 40 | } -------------------------------------------------------------------------------- /dist/jquery.vimeo.api.js: -------------------------------------------------------------------------------- 1 | /**! 2 | * Simple jQuery Vimeo API -- By Jeremy Rue 3 | * 4 | * Description: A jQuery plugin to easily control Vimeo videos through their API. 5 | * Author: Jeremy Rue, jrue@berkeley.edu 6 | * License: MIT 7 | * Version: 0.10.3 8 | */ 9 | ;(function($, window) { 10 | 11 | var vimeoJqueryAPI = { 12 | 13 | //catches return messages when methods like getVolume are called. 14 | //counter is if multiple calls are made before one returns. 15 | catchMethods : {methodreturn:[], count:0}, 16 | 17 | //This kicks things off on window message event 18 | init : function(d){ 19 | 20 | console.log(d); 21 | 22 | var vimeoVideo, 23 | vimeoAPIurl, 24 | data; 25 | 26 | //is this window message from vimeo? 27 | if(!d.originalEvent.origin.match(/vimeo/ig)){ 28 | return; 29 | } 30 | 31 | //make sure data was sent 32 | if(!("data" in d.originalEvent)){ 33 | return; 34 | } 35 | 36 | 37 | 38 | //store data as JSON object 39 | data = $.type(d.originalEvent.data) === "string" ? $.parseJSON(d.originalEvent.data) : d.originalEvent.data; 40 | 41 | //make sure data is not blank 42 | if(!data){ 43 | return; 44 | } 45 | 46 | //get the id of this vimeo video, hopefully they set it. 47 | vimeoVideo = this.setPlayerID(data); 48 | 49 | //check to see if player_ids were set in query string. If not, wait until next message comes through. 50 | if(vimeoVideo.length){ 51 | 52 | vimeoAPIurl = this.setVimeoAPIurl(vimeoVideo); 53 | 54 | //If this is an event message, like ready or paused 55 | if(data.hasOwnProperty("event")) 56 | this.handleEvent(data, vimeoVideo, vimeoAPIurl); 57 | 58 | //IF this is a return event message, like getVolume or getCurrentTime 59 | if(data.hasOwnProperty("method")) 60 | this.handleMethod(data, vimeoVideo, vimeoAPIurl); 61 | 62 | } 63 | 64 | }, 65 | 66 | setPlayerID : function(d){ 67 | 68 | return $("iframe[src*=" + d.player_id + "]"); 69 | 70 | }, 71 | 72 | setVimeoAPIurl : function(d){ 73 | 74 | //prepend vimeo url with proper protocol 75 | if(d.attr('src').substr(0, 4) !== 'http'){ 76 | return 'https:'+d.attr('src').split('?')[0]; 77 | } else { 78 | return d.attr('src').split('?')[0]; 79 | } 80 | }, 81 | 82 | handleMethod : function(d, vid, api){ 83 | 84 | //If the message is returned from a method call, store it for later. 85 | this.catchMethods.methodreturn.push(d.value); 86 | 87 | }, 88 | 89 | handleEvent : function(d, vid, api){ 90 | 91 | switch (d.event.toLowerCase()) { 92 | case 'ready': 93 | 94 | for(var prop in $._data(vid[0], "events")){ 95 | if(prop.match(/loadProgress|playProgress|play|pause|finish|seek|cuechange/)){ 96 | vid[0].contentWindow.postMessage(JSON.stringify({method: 'addEventListener', value: prop}), api); 97 | } 98 | } 99 | 100 | //if methods are sent before video is ready, call them now 101 | if(vid.data("vimeoAPICall")){ 102 | var vdata = vid.data("vimeoAPICall"); 103 | for(var i=0; i< vdata.length; i++){ 104 | vid[0].contentWindow.postMessage(JSON.stringify(vdata[i].message), vdata[i].api); 105 | } 106 | vid.removeData("vimeoAPICall"); 107 | } 108 | 109 | //this video is ready 110 | vid.data("vimeoReady", true); 111 | vid.triggerHandler("ready"); 112 | 113 | break; 114 | 115 | case 'seek': 116 | vid.triggerHandler("seek", [d.data]); 117 | break; 118 | 119 | case 'loadprogress': 120 | vid.triggerHandler("loadProgress", [d.data]); 121 | break; 122 | 123 | case 'playprogress': 124 | vid.triggerHandler("playProgress", [d.data]); 125 | break; 126 | 127 | case 'pause': 128 | vid.triggerHandler("pause"); 129 | break; 130 | 131 | case 'finish': 132 | vid.triggerHandler("finish"); 133 | break; 134 | 135 | case 'play': 136 | vid.triggerHandler("play"); 137 | break; 138 | 139 | case 'cuechange': 140 | vid.triggerHandler("cuechange"); 141 | break; 142 | } 143 | } 144 | }; 145 | 146 | var loadIframe = $.fn.vimeoLoad = function(){ 147 | 148 | //save the current src attribute 149 | var url = $(this).attr('src'), 150 | change = false; 151 | 152 | if(url.substr(0, 6) !== 'https:'){ 153 | url = url.substr(0,4) === 'http' ? 'https' + url.substr(4) : 'https:' + url; 154 | change = true; 155 | } 156 | 157 | //if they haven't added "player_id" in their query string, let's add one. 158 | if(url.match(/player_id/g) === null){ 159 | 160 | change = true; 161 | 162 | //is there already a query string? If so, use &, otherwise ?. 163 | var firstSeperator = (url.indexOf('?') === -1 ? '?' : '&'); 164 | 165 | //setup a serialized player_id with jQuery (use an unusual name in case someone manually sets the same name) 166 | var param = $.param({"api": 1, "player_id": "vvvvimeoVideo-" + Math.floor((Math.random() * 10000000) + 1).toString()}); 167 | 168 | url = url + firstSeperator + param; 169 | 170 | } 171 | 172 | if(change){ 173 | $(this).attr("src", url); 174 | } 175 | 176 | 177 | return this; 178 | }; 179 | 180 | jQuery(document).ready(function(){ 181 | 182 | //go through every iframe with "vimeo.com" in src attribute, and verify it has "player_id" query string 183 | $("iframe[src*='vimeo.com']").each(function(){loadIframe.call(this);}); 184 | }); 185 | 186 | $(["loadProgress","playProgress","play","pause","finish","seek","cuechange"]).each(function(i,e){ 187 | jQuery.event.special[e] = { 188 | setup: function(data, namespace, eventHandle){ 189 | 190 | var src = $(this).attr("src"); 191 | if($(this).is("iframe") && src.match(/vimeo/gi)){ 192 | 193 | var element = $(this); 194 | 195 | if(typeof element.data("vimeoReady") !== "undefined"){ 196 | element[0].contentWindow.postMessage(JSON.stringify({ 197 | method: 'addEventListener', 198 | value: e 199 | }), vimeoJqueryAPI.setVimeoAPIurl($(this))); 200 | } else { 201 | var _data = typeof element.data("vimeoAPICall") !== "undefined" ? element.data("vimeoAPICall") : []; 202 | _data.push({message:e, api:vimeoJqueryAPI.setVimeoAPIurl(element)}); 203 | element.data("vimeoAPICall", _data); 204 | } 205 | } 206 | } 207 | }; 208 | }); 209 | 210 | 211 | //this is what kicks things off. Whenever Vimeo sends window message to us, was check to see what it is. 212 | $(window).on("message", function(e){ vimeoJqueryAPI.init(e); }); 213 | 214 | /** 215 | * Vimeo jQuery method plugin 216 | * 217 | * @param element {jQuery Object} The element this was called on (verifies it's an iframe) 218 | * @param option1 {string} The method to send to vimeo. 219 | * @param option2 {string|function} If a string, it's the value (i.e. setVolume 2) otherwise, it's a callback function 220 | */ 221 | $.vimeo = function(element, option1, option2) { 222 | 223 | var message = {}, 224 | catchMethodLength = vimeoJqueryAPI.catchMethods.methodreturn.length; 225 | 226 | if(typeof option1 === "string") 227 | message.method = option1; 228 | 229 | if(typeof option2 !== undefined && typeof option2 !== "function") 230 | message.value = option2; 231 | 232 | //call method, but check if video was ready, otherwise cue it up with jQuery data to be called when video is ready 233 | if(element.is('iframe') && message.hasOwnProperty("method")){ 234 | if(element.data("vimeoReady")){ 235 | element[0].contentWindow.postMessage(JSON.stringify(message), vimeoJqueryAPI.setVimeoAPIurl(element)); 236 | } else { 237 | var _data = element.data("vimeoAPICall") ? element.data("vimeoAPICall") : []; 238 | _data.push({message:message, api:vimeoJqueryAPI.setVimeoAPIurl(element)}); 239 | element.data("vimeoAPICall", _data); 240 | } 241 | } 242 | 243 | //If this method will return data, (starts with "get") then use callback once return message comes through 244 | if((option1.toString().substr(0, 3) === "get" || option1.toString() === "paused") && typeof option2 === "function"){ 245 | (function(cml, func, i){ 246 | var interval = window.setInterval(function(){ 247 | 248 | if(vimeoJqueryAPI.catchMethods.methodreturn.length != cml){ 249 | window.clearInterval(interval); 250 | func(vimeoJqueryAPI.catchMethods.methodreturn[i]); 251 | } 252 | }, 10); 253 | })(catchMethodLength, option2, vimeoJqueryAPI.catchMethods.count); 254 | vimeoJqueryAPI.catchMethods.count++; 255 | } 256 | return element; 257 | }; 258 | 259 | $.fn.vimeo = function(option1, option2) { 260 | return $.vimeo(this, option1, option2); 261 | }; 262 | 263 | })(jQuery, window); -------------------------------------------------------------------------------- /dist/jquery.vimeo.api.min.js: -------------------------------------------------------------------------------- 1 | /*! vimeo-jquery-api 2016-05-05 */ 2 | !function(a,b){var c={catchMethods:{methodreturn:[],count:0},init:function(b){console.log(b);var c,d,e;b.originalEvent.origin.match(/vimeo/gi)&&"data"in b.originalEvent&&(e="string"===a.type(b.originalEvent.data)?a.parseJSON(b.originalEvent.data):b.originalEvent.data,e&&(c=this.setPlayerID(e),c.length&&(d=this.setVimeoAPIurl(c),e.hasOwnProperty("event")&&this.handleEvent(e,c,d),e.hasOwnProperty("method")&&this.handleMethod(e,c,d))))},setPlayerID:function(b){return a("iframe[src*="+b.player_id+"]")},setVimeoAPIurl:function(a){return"http"!==a.attr("src").substr(0,4)?"https:"+a.attr("src").split("?")[0]:a.attr("src").split("?")[0]},handleMethod:function(a){this.catchMethods.methodreturn.push(a.value)},handleEvent:function(b,c,d){switch(b.event.toLowerCase()){case"ready":for(var e in a._data(c[0],"events"))e.match(/loadProgress|playProgress|play|pause|finish|seek|cuechange/)&&c[0].contentWindow.postMessage(JSON.stringify({method:"addEventListener",value:e}),d);if(c.data("vimeoAPICall")){for(var f=c.data("vimeoAPICall"),g=0;g 2 | 3 | 4 | Vimeo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 35 | 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vimeo-jquery-api", 3 | "title": "Simple jQuery Vimeo API", 4 | "description": "A jQuery plugin to easily control Vimeo videos through their API.", 5 | "version": "0.10.3", 6 | "homepage": "https://github.com/jrue/Vimeo-jQuery-API", 7 | "author": { 8 | "name": "Jeremy Rue", 9 | "email": "jrue@berkeley.edu" 10 | }, 11 | "main": "dist/jquery.vimeo.api.js", 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/jrue/Vimeo-jQuery-API" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/jrue/Vimeo-jQuery-API/issues" 18 | }, 19 | "license": "MIT", 20 | "dependencies": { 21 | "jquery": ">=1.7" 22 | }, 23 | "keywords": [ 24 | "video", 25 | "vimeo", 26 | "iframe", 27 | "api", 28 | "javascript", 29 | "jquery-plugin" 30 | ], 31 | "devDependencies": { 32 | "grunt": "^0.4.5", 33 | "grunt-bumpup": "^0.6.2", 34 | "grunt-contrib-clean": "^0.6.0", 35 | "grunt-contrib-jshint": "^0.11.0", 36 | "grunt-contrib-uglify": "^0.8.0" 37 | } 38 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Simple Vimeo API jQuery Plugin 2 | ================ 3 | 4 | NOTE: Vimeo published a much improved JavaScript API similar to this one. It's advisable to use the official one instead: [https://github.com/vimeo/player.js](https://github.com/vimeo/player.js) 5 | =============== 6 | 7 | An easy way to control Vimeo videos using standard jQuery event structure and methods. 8 | 9 | 10 | Download 11 | ======== 12 | 13 | You can check out the entire repo, or download the latest release below (production files are in the dist folder): 14 | 15 | [jQuery Vimeo API v0.10.3 (zip)](https://github.com/jrue/Vimeo-jQuery-API/archive/v0.10.3.zip)
16 | [jQuery Vimeo API v0.10.3 (tar.gz)](https://github.com/jrue/Vimeo-jQuery-API/archive/v0.10.3.tar.gz) 17 | 18 | You can also link directly to the file using MaxCDN. 19 | 20 | ```html 21 | 22 | ``` 23 | 24 | Setup 25 | ======== 26 | Make sure to include this plugin's .js file *after* jQuery library. Use the minified version in dist folder for best performance. 27 | 28 | This plugin works with iframe Vimeo embeds only. You can target the iframe using any normal jQuery CSS conventions, but often it's easier to put an id attribute on the iframe to target it specifically. 29 | 30 | ```html 31 | 32 | 33 | 34 | 35 | 36 | 37 | 45 | ``` 46 | 47 | Multiple videos 48 | ======== 49 | For multiple videos, it is recommended to include a query string to the end of the URL of your video with the variables `api=1`, and `player_id=[unique_name]` for each video, like so: 50 | 51 |
<iframe src="//player.vimeo.com/video/00000?&api=1&player_id=vid1" ... </iframe>
52 | 53 | Because of a peculiarity with the way Vimeo sends messages, it's impossible to tell which API messages we receive from Vimeo belong to any specific video on the page. The solution for this is to identify each video by appending a special query string identifier to each video's URL. 54 | 55 | For convenience (and for CMS plugins) this plugin is designed to work without doing this; it will automatically append generic ids to the query strings of the Vimeo embeds on the page. But in doing so, there will be a brief reloading of the video at page load when it changes the src attribute. In order to prevent this, you should manually add your own. 56 | 57 | Dynamically Loading Videos 58 | ======== 59 | When dynamically loading videos after page load, this plugin won't capture them in the event chain. You will have to manually call a special method I added called `.vimeoLoad()` after appending your iframe, so it will be processed by the plugin. 60 | 61 | ```javascript 62 | $("