diff --git a/README.md b/README.md
index c4d9009..779221c 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Installing this component is very easy and it has just one dependency: [React](h
$ bower install --save react-video
```
-- Or if you want to [download the lastest release](https://github.com/pedronauck/react-video/archive/v1.4.0.zip) and put in your website, it will work too!
+- Or if you want to [download the lastest release](https://github.com/pedronauck/react-video/archive/v1.5.0.zip) and put in your website, it will work too!
**NOTICE:** You need just one thing to make the component work. Put the [base component style](./dist/react-video.css) at the `` tag. If you don't wanna use the `.css` extension, you can get the `.styl` or `.scss` extension at the folder `./lib`.
@@ -55,6 +55,19 @@ The property `videoId` is optional, so you can use it or not. If you don't pass
);
```
+To handle errors when something happens, like your video can't be loaded, you can pass a callback with a prop `onError` in the component:
+
+```javascript
+ var _onError = function(err) {
+ console.log(err);
+ };
+
+ React.render(
+
+ document.querySelector('#your-div')
+ );
+```
+
If you decide to use just Javascript without any module loader, you can get the global variable `window.ReactVideo` *(or just `ReactVideo`)*:
```javascript
@@ -97,6 +110,7 @@ Property | Type | Default | Required | Description
-------- | ---- | ------- | -------- |-----------
from | `String` | none | no | Video source: `youtube` or `vimeo`. Leave empty and the service will be detected for you by looking a the id.
videoId | `String` | none | no | The video ID
+onError | `Function` | yes | no | Callback function if the video can't be loaded
## Contributing
diff --git a/bower.json b/bower.json
index 80d8cbd..bdead00 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "react-video",
- "version": "1.4.0",
+ "version": "1.5.0",
"description": "React component to load video from Vimeo or Youtube across any device",
"homepage": "https://github.com/pedronauck/react-video",
"authors": [
diff --git a/dist/react-video.css b/dist/react-video.css
index 65ff08e..dcd4572 100644
--- a/dist/react-video.css
+++ b/dist/react-video.css
@@ -1,6 +1,6 @@
/*
* React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.4.0
+ * @version v1.5.0
* @link https://github.com/pedronauck/react-video
* @license MIT
* @author Pedro Nauck (https://github.com/pedronauck)
diff --git a/dist/react-video.js b/dist/react-video.js
index d1c6b6d..45f51a9 100644
--- a/dist/react-video.js
+++ b/dist/react-video.js
@@ -1,6 +1,6 @@
/*
* React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.4.0
+ * @version v1.5.0
* @link https://github.com/pedronauck/react-video
* @license MIT
* @author Pedro Nauck (https://github.com/pedronauck)
@@ -72,7 +72,8 @@ return /******/ (function(modules) { // webpackBootstrap
displayName: 'Video',
propTypes: {
from: React.PropTypes.oneOf(['youtube', 'vimeo']),
- videoId: React.PropTypes.string.isRequired
+ videoId: React.PropTypes.string.isRequired,
+ onError: React.PropTypes.func
},
getDefaultProps:function() {
return {
@@ -147,28 +148,34 @@ return /******/ (function(modules) { // webpackBootstrap
},
fetchYoutubeData:function() {
var id = this.props.videoId;
- var url = ("//gdata.youtube.com/feeds/api/videos/" + id + "?v=2&alt=json");
- ajax.get(url, function(err, res) {
- var gallery = res.entry['media$group']['media$thumbnail'];
- var thumb = gallery.sort(function(a, b) {return b.width - a.width;})[0].url;
-
- this.setState({
- thumb: thumb,
- imageLoaded: true
- });
- }.bind(this));
+ ajax.get({
+ url: ("//gdata.youtube.com/feeds/api/videos/" + id + "?v=2&alt=json"),
+ onSuccess:function(err, res) {
+ var gallery = res.entry['media$group']['media$thumbnail'];
+ var thumb = gallery.sort(function(a, b) {return b.width - a.width;})[0].url;
+
+ this.setState({
+ thumb: thumb,
+ imageLoaded: true
+ })
+ },
+ onError: this.props.onError
+ });
},
fetchVimeoData:function() {
var id = this.props.videoId;
- var url = ("//vimeo.com/api/v2/video/" + id + ".json");
-
- ajax.get(url, function(err, res) {
- this.setState({
- thumb: res[0].thumbnail_large,
- imageLoaded: true
- });
- }.bind(this));
+
+ ajax.get({
+ url: ("//vimeo.com/api/v2/video/" + id + ".json"),
+ onSuccess:function(err, res) {
+ this.setState({
+ thumb: res[0].thumbnail_large,
+ imageLoaded: true
+ });
+ },
+ onError: this.props.onError
+ });
}
});
@@ -202,43 +209,50 @@ return /******/ (function(modules) { // webpackBootstrap
/* 3 */
/***/ function(module, exports, __webpack_require__) {
- /** @jsx React.DOM */var get = function(url, cb) {
+ /** @jsx React.DOM */exports.get = function(opts) {
+ var url = opts.url;
+ var successCb = opts.onSuccess;
+ var errorCb = opts.onError;
var req = false;
// XDomainRequest onload
- var oldIE = function () {
- cb(null, JSON.parse(req.responseText));
+ var _oldIE = function () {
+ successCb(null, JSON.parse(req.responseText));
};
// XMLHttpRequest onload
- var onLoad = function () {
+ var _onLoad = function () {
if (req.readyState !== 4) return;
- if (req.status === 200) cb(null, JSON.parse(req.responseText));
+ if (req.status === 200) successCb(null, JSON.parse(req.responseText));
else {
- cb({ error: 'Sorry, an error ocurred on the server' }, null);
+ var err = { error: 'Sorry, an error ocurred on the server' };
+
+ if (errorCb && typeof errorCb === 'function') return errorCb(err);
+ successCb(err, null);
}
};
- var onError = function() {
- cb({ error: 'Problem with your internet conection' }, null);
+ var _onError = function() {
+ var err = { error: 'Sorry, an error ocurred on the server' };
+
+ if (errorCb && typeof errorCb === 'function') return errorCb(err);
+ successCb(err, null);
};
try {
req = new XDomainRequest();
- req.onload = oldIE;
+ req.onload = _oldIE;
}
catch (e) {
req = new XMLHttpRequest();
- req.onreadystatechange = onLoad;
+ req.onreadystatechange = _onLoad;
}
- req.onerror = onError;
+ req.onerror = _onError;
req.open('GET', url, true);
req.send();
};
- module.exports = { get: get };
-
/***/ },
/* 4 */
diff --git a/dist/react-video.min.css b/dist/react-video.min.css
index f93c6e7..13ef4b9 100644
--- a/dist/react-video.min.css
+++ b/dist/react-video.min.css
@@ -1,6 +1,6 @@
/*
* React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.4.0
+ * @version v1.5.0
* @link https://github.com/pedronauck/react-video
* @license MIT
* @author Pedro Nauck (https://github.com/pedronauck)
diff --git a/dist/react-video.min.js b/dist/react-video.min.js
index 188159a..e58b4ea 100644
--- a/dist/react-video.min.js
+++ b/dist/react-video.min.js
@@ -1,8 +1,8 @@
/*
* React Video - React component to load video from Vimeo or Youtube across any device
- * @version v1.4.0
+ * @version v1.5.0
* @link https://github.com/pedronauck/react-video
* @license MIT
* @author Pedro Nauck (https://github.com/pedronauck)
*/
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.ReactVideo=t(require("react")):e.ReactVideo=t(e.React)}(this,function(e){return function(e){function t(i){if(o[i])return o[i].exports;var r=o[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){var i=o(1),r=(o(2),o(3)),n=o(4),s=o(5);e.exports=i.createClass({displayName:"Video",propTypes:{from:i.PropTypes.oneOf(["youtube","vimeo"]),videoId:i.PropTypes.string.isRequired},getDefaultProps:function(){return{className:"video"}},getInitialState:function(){return{thumb:null,imageLoaded:!1,showingVideo:!1}},isYoutube:function(){return"youtube"===this.props.from||isNaN(this.props.videoId)},isVimeo:function(){return"vimeo"===this.props.from||!isNaN(this.props.videoId)},componentDidMount:function(){this.isYoutube()&&this.fetchYoutubeData(),this.isVimeo()&&this.fetchVimeoData()},render:function(){return i.DOM.div({className:this.props.className},!this.state.imageLoaded&&s(null),this.renderImage(),this.renderIframe())},renderImage:function(){var e={backgroundImage:"url("+this.state.thumb+")"};return this.state.imageLoaded&&!this.state.showingVideo?i.DOM.div({className:"video-image",style:e},n({onClick:this.playVideo})):void 0},renderIframe:function(){var e={display:this.state.showingVideo?"block":"none",width:"100%",height:"100%"};return this.state.showingVideo?i.DOM.div({className:"video-embed",style:e},i.DOM.iframe({frameborder:"0",src:this.getIframeUrl()})):void 0},playVideo:function(e){this.setState({showingVideo:!0}),e.preventDefault()},getIframeUrl:function(){return this.isYoutube()?"//youtube.com/embed/"+this.props.videoId+"?autoplay=1":this.isVimeo()?"//player.vimeo.com/video/"+this.props.videoId+"?autoplay=1":void 0},fetchYoutubeData:function(){var e=this.props.videoId,t="//gdata.youtube.com/feeds/api/videos/"+e+"?v=2&alt=json";r.get(t,function(e,t){var o=t.entry.media$group.media$thumbnail,i=o.sort(function(e,t){return t.width-e.width})[0].url;this.setState({thumb:i,imageLoaded:!0})}.bind(this))},fetchVimeoData:function(){var e=this.props.videoId,t="//vimeo.com/api/v2/video/"+e+".json";r.get(t,function(e,t){this.setState({thumb:t[0].thumbnail_large,imageLoaded:!0})}.bind(this))}})},function(t){t.exports=e},function(e){e.exports=function(e){return"object"!=typeof e?Array.prototype.join.call(arguments," "):Object.keys(e).filter(function(t){return e[t]}).join(" ")}},function(e){var t=function(e,t){var o=!1,i=function(){t(null,JSON.parse(o.responseText))},r=function(){4===o.readyState&&(200===o.status?t(null,JSON.parse(o.responseText)):t({error:"Sorry, an error ocurred on the server"},null))},n=function(){t({error:"Problem with your internet conection"},null)};try{o=new XDomainRequest,o.onload=i}catch(s){o=new XMLHttpRequest,o.onreadystatechange=r}o.onerror=n,o.open("GET",e,!0),o.send()};e.exports={get:t}},function(e,t,o){var i=o(1);e.exports=i.createClass({displayName:"exports",propTypes:{onClick:i.PropTypes.func},render:function(){return i.DOM.button({type:"button",className:"video-play-button",onClick:this.props.onClick},i.DOM.svg({xmlns:"http://www.w3.org/2000/svg",version:"1.1",viewBox:"0 0 100 100"},i.DOM.path({d:"M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z"})))}})},function(e,t,o){var i=o(1);e.exports=i.createClass({displayName:"exports",render:function(){return i.DOM.div({className:"video-loading"},i.DOM.svg({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",width:"32",height:"32"},i.DOM.path({opacity:".25",d:"M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4"}),i.DOM.path({d:"M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z"})))}})}])});
\ No newline at end of file
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.ReactVideo=t(require("react")):e.ReactVideo=t(e.React)}(this,function(e){return function(e){function t(r){if(o[r])return o[r].exports;var i=o[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,t,o){var r=o(1),i=(o(2),o(3)),n=o(4),s=o(5);e.exports=r.createClass({displayName:"Video",propTypes:{from:r.PropTypes.oneOf(["youtube","vimeo"]),videoId:r.PropTypes.string.isRequired,onError:r.PropTypes.func},getDefaultProps:function(){return{className:"video"}},getInitialState:function(){return{thumb:null,imageLoaded:!1,showingVideo:!1}},isYoutube:function(){return"youtube"===this.props.from||isNaN(this.props.videoId)},isVimeo:function(){return"vimeo"===this.props.from||!isNaN(this.props.videoId)},componentDidMount:function(){this.isYoutube()&&this.fetchYoutubeData(),this.isVimeo()&&this.fetchVimeoData()},render:function(){return r.DOM.div({className:this.props.className},!this.state.imageLoaded&&s(null),this.renderImage(),this.renderIframe())},renderImage:function(){var e={backgroundImage:"url("+this.state.thumb+")"};return this.state.imageLoaded&&!this.state.showingVideo?r.DOM.div({className:"video-image",style:e},n({onClick:this.playVideo})):void 0},renderIframe:function(){var e={display:this.state.showingVideo?"block":"none",width:"100%",height:"100%"};return this.state.showingVideo?r.DOM.div({className:"video-embed",style:e},r.DOM.iframe({frameborder:"0",src:this.getIframeUrl()})):void 0},playVideo:function(e){this.setState({showingVideo:!0}),e.preventDefault()},getIframeUrl:function(){return this.isYoutube()?"//youtube.com/embed/"+this.props.videoId+"?autoplay=1":this.isVimeo()?"//player.vimeo.com/video/"+this.props.videoId+"?autoplay=1":void 0},fetchYoutubeData:function(){var e=this.props.videoId;i.get({url:"//gdata.youtube.com/feeds/api/videos/"+e+"?v=2&alt=json",onSuccess:function(e,t){var o=t.entry.media$group.media$thumbnail,r=o.sort(function(e,t){return t.width-e.width})[0].url;this.setState({thumb:r,imageLoaded:!0})},onError:this.props.onError})},fetchVimeoData:function(){var e=this.props.videoId;i.get({url:"//vimeo.com/api/v2/video/"+e+".json",onSuccess:function(e,t){this.setState({thumb:t[0].thumbnail_large,imageLoaded:!0})},onError:this.props.onError})}})},function(t){t.exports=e},function(e){e.exports=function(e){return"object"!=typeof e?Array.prototype.join.call(arguments," "):Object.keys(e).filter(function(t){return e[t]}).join(" ")}},function(e,t){t.get=function(e){var t=e.url,o=e.onSuccess,r=e.onError,i=!1,n=function(){o(null,JSON.parse(i.responseText))},s=function(){if(4===i.readyState)if(200===i.status)o(null,JSON.parse(i.responseText));else{var e={error:"Sorry, an error ocurred on the server"};if(r&&"function"==typeof r)return r(e);o(e,null)}},a=function(){var e={error:"Sorry, an error ocurred on the server"};return r&&"function"==typeof r?r(e):void o(e,null)};try{i=new XDomainRequest,i.onload=n}catch(u){i=new XMLHttpRequest,i.onreadystatechange=s}i.onerror=a,i.open("GET",t,!0),i.send()}},function(e,t,o){var r=o(1);e.exports=r.createClass({displayName:"exports",propTypes:{onClick:r.PropTypes.func},render:function(){return r.DOM.button({type:"button",className:"video-play-button",onClick:this.props.onClick},r.DOM.svg({xmlns:"http://www.w3.org/2000/svg",version:"1.1",viewBox:"0 0 100 100"},r.DOM.path({d:"M79.674,53.719c2.59-2.046,2.59-5.392,0-7.437L22.566,1.053C19.977-0.993,18,0.035,18,3.335v93.331c0,3.3,1.977,4.326,4.566,2.281L79.674,53.719z"})))}})},function(e,t,o){var r=o(1);e.exports=r.createClass({displayName:"exports",render:function(){return r.DOM.div({className:"video-loading"},r.DOM.svg({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",width:"32",height:"32"},r.DOM.path({opacity:".25",d:"M16 0 A16 16 0 0 0 16 32 A16 16 0 0 0 16 0 M16 4 A12 12 0 0 1 16 28 A12 12 0 0 1 16 4"}),r.DOM.path({d:"M16 0 A16 16 0 0 1 32 16 L28 16 A12 12 0 0 0 16 4z"})))}})}])});
\ No newline at end of file
diff --git a/docs/index.html b/docs/index.html
index 4bca55a..7f4715a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -99,6 +99,20 @@ Usage
document.querySelector('#your-div')
);
+
+ To handle errors when something happens, like your video can't be loaded, you can pass a callback with a prop onError
in the component:
+
+
+ var _onError = function(err) {
+ console.log(err);
+ };
+
+ React.render(
+ <Video onError={_onError} videoId={videoId} />
+ document.querySelector('#your-div')
+ );
+
+
If you decide to use just Javascript without any module loader, you can get the global variable window.ReactVideo
:
diff --git a/lib/react-video.jsx b/lib/react-video.jsx
index 193078c..5d73ccf 100644
--- a/lib/react-video.jsx
+++ b/lib/react-video.jsx
@@ -8,7 +8,8 @@ module.exports = React.createClass({
displayName: 'Video',
propTypes: {
from: React.PropTypes.oneOf(['youtube', 'vimeo']),
- videoId: React.PropTypes.string.isRequired
+ videoId: React.PropTypes.string.isRequired,
+ onError: React.PropTypes.func
},
getDefaultProps() {
return {
@@ -83,27 +84,33 @@ module.exports = React.createClass({
},
fetchYoutubeData() {
var id = this.props.videoId;
- var url = `//gdata.youtube.com/feeds/api/videos/${id}?v=2&alt=json`;
- ajax.get(url, (err, res) => {
- var gallery = res.entry['media$group']['media$thumbnail'];
- var thumb = gallery.sort((a, b) => b.width - a.width)[0].url;
+ ajax.get({
+ url: `//gdata.youtube.com/feeds/api/videos/${id}?v=2&alt=json`,
+ onSuccess(err, res) {
+ var gallery = res.entry['media$group']['media$thumbnail'];
+ var thumb = gallery.sort((a, b) => b.width - a.width)[0].url;
- this.setState({
- thumb: thumb,
- imageLoaded: true
- });
+ this.setState({
+ thumb: thumb,
+ imageLoaded: true
+ })
+ },
+ onError: this.props.onError
});
},
fetchVimeoData() {
var id = this.props.videoId;
- var url = `//vimeo.com/api/v2/video/${id}.json`;
- ajax.get(url, (err, res) => {
- this.setState({
- thumb: res[0].thumbnail_large,
- imageLoaded: true
- });
+ ajax.get({
+ url: `//vimeo.com/api/v2/video/${id}.json`,
+ onSuccess(err, res) {
+ this.setState({
+ thumb: res[0].thumbnail_large,
+ imageLoaded: true
+ });
+ },
+ onError: this.props.onError
});
}
});
diff --git a/package.json b/package.json
index 4183082..afe5b68 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-video",
- "version": "1.4.0",
+ "version": "1.5.0",
"description": "React component to load video from Vimeo or Youtube across any device",
"author": {
"name": "Pedro Nauck",
diff --git a/utils/ajax.js b/utils/ajax.js
index aab6ca4..96967be 100644
--- a/utils/ajax.js
+++ b/utils/ajax.js
@@ -1,36 +1,43 @@
-var get = function(url, cb) {
+exports.get = function(opts) {
+ var url = opts.url;
+ var successCb = opts.onSuccess;
+ var errorCb = opts.onError;
var req = false;
// XDomainRequest onload
- var oldIE = function () {
- cb(null, JSON.parse(req.responseText));
+ var _oldIE = function () {
+ successCb(null, JSON.parse(req.responseText));
};
// XMLHttpRequest onload
- var onLoad = function () {
+ var _onLoad = function () {
if (req.readyState !== 4) return;
- if (req.status === 200) cb(null, JSON.parse(req.responseText));
+ if (req.status === 200) successCb(null, JSON.parse(req.responseText));
else {
- cb({ error: 'Sorry, an error ocurred on the server' }, null);
+ var err = { error: 'Sorry, an error ocurred on the server' };
+
+ if (errorCb && typeof errorCb === 'function') return errorCb(err);
+ successCb(err, null);
}
};
- var onError = function() {
- cb({ error: 'Problem with your internet conection' }, null);
+ var _onError = function() {
+ var err = { error: 'Sorry, an error ocurred on the server' };
+
+ if (errorCb && typeof errorCb === 'function') return errorCb(err);
+ successCb(err, null);
};
try {
req = new XDomainRequest();
- req.onload = oldIE;
+ req.onload = _oldIE;
}
catch (e) {
req = new XMLHttpRequest();
- req.onreadystatechange = onLoad;
+ req.onreadystatechange = _onLoad;
}
- req.onerror = onError;
+ req.onerror = _onError;
req.open('GET', url, true);
req.send();
};
-
-module.exports = { get: get };