React home and share pages working isomorphically
This commit is contained in:
parent
0b00b190fc
commit
a2148dc00a
21 changed files with 482 additions and 658 deletions
34
app.js
34
app.js
|
@ -17,6 +17,10 @@ var search = require('./routes/search');
|
|||
var share = require('./routes/share');
|
||||
var itunesProxy = require('./routes/itunes-proxy');
|
||||
|
||||
var React = require('react');
|
||||
var nodejsx = require('node-jsx').install({extension: '.jsx'});
|
||||
var ErrorView = React.createFactory(require('./views/error.jsx'));
|
||||
|
||||
var browserify = require('connect-browserify');
|
||||
|
||||
var app = express();
|
||||
|
@ -50,7 +54,7 @@ app.use(function(req, res, next) {
|
|||
|
||||
if (development) {
|
||||
app.get('/javascript/bundle.js',
|
||||
browserify('./client/index.jsx', {
|
||||
browserify('./views/app.jsx', {
|
||||
debug: true,
|
||||
watch: true
|
||||
}));
|
||||
|
@ -75,9 +79,17 @@ app.get('*', function(req,res,next) {
|
|||
|
||||
app.get('/', index);
|
||||
app.post('/search', search);
|
||||
app.get('/:service/:type/:id.json', share.json);
|
||||
app.get('/:service/:type/:id', share.html);
|
||||
app.get('/:service/:type/:id', share);
|
||||
app.get('/itunes/*', itunesProxy);
|
||||
app.get('/recent', function(req, res, next) {
|
||||
req.db.matches.find().sort({created_at:-1}).limit(6).toArray().then(function(docs){
|
||||
var recents = [];
|
||||
docs.forEach(function(doc) {
|
||||
recents.push(doc.services[doc._id.split("$$")[0]]);
|
||||
});
|
||||
res.json({recents:recents});
|
||||
});
|
||||
});
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
|
@ -93,11 +105,9 @@ app.use(function(req, res, next) {
|
|||
if (app.get('env') === 'development') {
|
||||
app.use(function(err, req, res, next) {
|
||||
res.status(err.status || 500);
|
||||
res.render('error', {
|
||||
page: "error",
|
||||
message: err.message,
|
||||
error: err
|
||||
});
|
||||
|
||||
var content = React.renderToString(ErrorView({status: err.status || 500, message: err.message, error: err}));
|
||||
res.send('<!doctype html>\n' + content);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -105,11 +115,9 @@ if (app.get('env') === 'development') {
|
|||
// no stacktraces leaked to user
|
||||
app.use(function(err, req, res, next) {
|
||||
res.status(err.status || 500);
|
||||
res.render('error', {
|
||||
page: "error",
|
||||
message: err.message,
|
||||
error: {status: err.status || 500}
|
||||
});
|
||||
|
||||
var content = React.renderToString(ErrorView({status: err.status || 500, message: err.message, error: {status: err.status || 500}}));
|
||||
res.send('<!doctype html>\n' + content);
|
||||
});
|
||||
|
||||
|
||||
|
|
155
client/index.jsx
155
client/index.jsx
|
@ -1,155 +0,0 @@
|
|||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var request = require('superagent');
|
||||
var ga = require('react-google-analytics');
|
||||
var GAInitiailizer = ga.Initializer;
|
||||
|
||||
var Head = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Match Audio</title>
|
||||
<meta name="description" content="" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@MatchAudio" />
|
||||
<meta name="twitter:title" property="og:title" content="" />
|
||||
<meta name="twitter:description" property="og:description" content="We've matched this music on Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes so you can open it in the service you use." />
|
||||
<meta name="twitter:image:src" property="og:image" content="" />
|
||||
<meta property="og:url" content="" />
|
||||
<link rel="shortcut icon" href="/images/favicon.png" />
|
||||
<link href='//fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css' />
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/stylesheets/style.css" />
|
||||
</head>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Foot = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<footer>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className={this.props.page == "home" ? "col-md-6 col-md-offset-3" : "col-md-12"}>
|
||||
<a href="https://twitter.com/MatchAudio">Tweet</a> or <a href="https://github.com/kudos/match.audio">Fork</a>. A work in progress by <a href="http://crem.in">this guy</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var Recent = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (<div className="row">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<h2>Recently Shared</h2>
|
||||
<div className="row recent">
|
||||
{this.props.items.map(function(item, i){
|
||||
return (<RecentItem item={item} key={i} />);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var RecentItem = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="col-sm-4 col-xs-6">
|
||||
<a href={"/" + this.props.item.service + "/" + this.props.item.type + "/" + this.props.item.id}><img src={this.props.item.artwork.small} width="100%" /></a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var SearchForm = React.createClass({
|
||||
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var url = this.refs.url.getDOMNode().value.trim();
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
request.post('/search').send({url:url}).end(function(res) {
|
||||
window.location = "/" + res.body.service + "/" + res.body.type + "/" + res.body.id
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<form role="form" method="post" action="/search" onSubmit={this.handleSubmit}>
|
||||
<div className="input-group input-group-lg">
|
||||
<input type="text" name="url" placeholder="Paste link here" className="form-control" autofocus ref="url" />
|
||||
<span className="input-group-btn">
|
||||
<input type="submit" className="btn btn-lg btn-custom" value="Share Music" />
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Home = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<html>
|
||||
<Head />
|
||||
<body className="home">
|
||||
<div className="page-wrap">
|
||||
<header>
|
||||
<h1><a href="/">match<span className="audio-lighten">.audio</span></a></h1>
|
||||
</header>
|
||||
<div className="container">
|
||||
<div className="row share-form">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<SearchForm />
|
||||
</div>
|
||||
</div>
|
||||
<div className="row blurb">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<p>Make sharing from music services better.
|
||||
We match album and track links from Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes and give you back a link with all of them.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Recent items={this.props.recent} />
|
||||
</div>
|
||||
</div>
|
||||
<Foot page="home" />
|
||||
<GAInitiailizer />
|
||||
<script src="/javascript/bundle.js" />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports.Home = Home;
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.onload = function() {
|
||||
React.render(<Home recent={recent} />, document);
|
||||
ga('create', 'UA-66209-8', 'auto');
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
}
|
153
client/share.jsx
153
client/share.jsx
|
@ -1,153 +0,0 @@
|
|||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var request = require('superagent');
|
||||
var ga = require('react-google-analytics');
|
||||
var GAInitiailizer = ga.Initializer;
|
||||
|
||||
var Head = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Match Audio</title>
|
||||
<meta name="description" content="" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@MatchAudio" />
|
||||
<meta name="twitter:title" property="og:title" content="" />
|
||||
<meta name="twitter:description" property="og:description" content="We've matched this music on Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes so you can open it in the service you use." />
|
||||
<meta name="twitter:image:src" property="og:image" content="" />
|
||||
<meta property="og:url" content="" />
|
||||
<link rel="shortcut icon" href="/images/favicon.png" />
|
||||
<link href='//fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css' />
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/stylesheets/style.css" />
|
||||
</head>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Foot = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<footer>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className={this.props.page == "home" ? "col-md-6 col-md-offset-3" : "col-md-12"}>
|
||||
<a href="https://twitter.com/MatchAudio">Tweet</a> or <a href="https://github.com/kudos/match.audio">Fork</a>. A work in progress by <a href="http://crem.in">this guy</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var Recent = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (<div className="row">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<h2>Recently Shared</h2>
|
||||
<div className="row recent">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var RecentItem = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="col-sm-4 col-xs-6">
|
||||
<a href={"/" + this.props.item.service + "/" + this.props.item.type + "/" + this.props.item.id}><img src={this.props.item.artwork.small} width="100%" /></a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var SearchForm = React.createClass({
|
||||
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var url = this.refs.url.getDOMNode().value.trim();
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
request.post('/search').send({url:url}).end(function(res) {
|
||||
window.location = "/" + res.body.service + "/" + res.body.type + "/" + res.body.id
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<form role="form" method="post" action="/search" onSubmit={this.handleSubmit}>
|
||||
<div className="input-group input-group-lg">
|
||||
<input type="text" name="url" placeholder="Paste link here" className="form-control" autofocus ref="url" />
|
||||
<span className="input-group-btn">
|
||||
<input type="submit" className="btn btn-lg btn-custom" value="Share Music" />
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Share = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<html>
|
||||
<Head />
|
||||
<body className="home">
|
||||
<div className="page-wrap">
|
||||
<header>
|
||||
<h1><a href="/">match<span className="audio-lighten">.audio</span></a></h1>
|
||||
</header>
|
||||
<div className="container">
|
||||
<div className="row share-form">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<h1>share</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row blurb">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<p>Make sharing from music services better.
|
||||
We match album and track links from Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes and give you back a link with all of them.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Recent items={this.props.recent} />
|
||||
</div>
|
||||
</div>
|
||||
<Foot page="home" />
|
||||
<GAInitiailizer />
|
||||
<script src="/javascript/bundle.js" />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports.Share = Share;
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.onload = function() {
|
||||
React.render(<Share items={items} />, document);
|
||||
ga('create', 'UA-66209-8', 'auto');
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
}
|
|
@ -43,8 +43,8 @@ var formatResponse = function(res) {
|
|||
streamUrl: result.Link,
|
||||
purchaseUrl: null,
|
||||
artwork: {
|
||||
small: result.ImageUrl.replace("http://", "https://") + "?w=250",
|
||||
large: result.ImageUrl.replace("http://", "https://") + "?w=500"
|
||||
small: result.ImageUrl.replace("http://", "https://") + "&w=250&h=250",
|
||||
large: result.ImageUrl.replace("http://", "https://") + "&w=500&h=250"
|
||||
},
|
||||
artist: {
|
||||
name: result.Artists[0].Artist.Name
|
||||
|
|
|
@ -37,11 +37,10 @@
|
|||
"node-jsx": "^0.12.4",
|
||||
"node-uuid": "^1.4.2",
|
||||
"promised-mongo": "^0.11.1",
|
||||
"querystring": "^0.2.0",
|
||||
"rdio": "^1.5.2",
|
||||
"react": "^0.12.1",
|
||||
"react-google-analytics": "^0.2.0",
|
||||
"react-router": "^0.11.4",
|
||||
"react-router": "^0.11.6",
|
||||
"serve-favicon": "~2.1.3",
|
||||
"spotify": "^0.3.0",
|
||||
"superagent": "^0.21.0",
|
||||
|
|
|
@ -60,7 +60,7 @@ header h1 a:hover, header h1 a:focus{
|
|||
outline: 0 none;
|
||||
}
|
||||
|
||||
.album header h1, .track header h1 {
|
||||
.share header h1, .share header h1 {
|
||||
text-align: left;
|
||||
font-size: 1.5em;
|
||||
line-height: 36px;
|
||||
|
|
|
@ -2,18 +2,23 @@
|
|||
|
||||
var React = require('react');
|
||||
var nodejsx = require('node-jsx').install({extension: '.jsx'});
|
||||
var Home = React.createFactory(require('../client/index.jsx').Home);
|
||||
var Router = require('react-router');
|
||||
var routes = require('../views/app.jsx').routes;
|
||||
|
||||
module.exports = function(req, res, next) {
|
||||
|
||||
req.db.matches.find().sort({created_at:-1}).limit(6).toArray().then(function(docs){
|
||||
var recent = [];
|
||||
var recents = [];
|
||||
docs.forEach(function(doc) {
|
||||
recent.push(doc.services[doc._id.split("$$")[0]]);
|
||||
})
|
||||
recents.push(doc.services[doc._id.split("$$")[0]]);
|
||||
});
|
||||
|
||||
var home = Home({recent: recent});
|
||||
res.send('<!doctype html>\n' + React.renderToString(home).replace("</body></html>", "<script>var recent = " + JSON.stringify(recent) + "</script></body></html>"));
|
||||
//res.render('index', { page: "home", recent: docs, error: req.flash('search-error') });
|
||||
Router.run(routes, req.url, function (Handler) {
|
||||
var App = React.createFactory(Handler);
|
||||
var content = React.renderToString(App({recents: recents}));
|
||||
res.send('<!doctype html>\n' + content.replace("</body></html>", "<script>var recents = " + JSON.stringify(recents) + "</script></body></html>"));
|
||||
});
|
||||
}).catch(function(err) {
|
||||
console.log(err)
|
||||
});
|
||||
}
|
|
@ -29,14 +29,14 @@ module.exports = function(req, res, next) {
|
|||
searching = true;
|
||||
services[id].parseUrl(req.body.url).timeout(10000).then(function(result) {
|
||||
if (!result.id) {
|
||||
req.flash('search-error', 'No match found for this link');
|
||||
res.redirect('/');
|
||||
res.json({error:{message:"No match found for url"}});
|
||||
} else {
|
||||
services[id].lookupId(result.id, result.type).then(function(item) {
|
||||
items[id] = item;
|
||||
req.db.matches.save({_id:id + "$$" + result.id, created_at: new Date(), services:items}).then(function() {
|
||||
res.json(item);
|
||||
//res.redirect("/" + id + "/" + result.type + "/" + result.id);
|
||||
setTimeout(function() {
|
||||
res.json(item);
|
||||
}, 1000)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -50,8 +50,7 @@ module.exports = function(req, res, next) {
|
|||
error.status = 500;
|
||||
next(error);
|
||||
} else if (error.status == 404){
|
||||
req.flash('search-error', 'No match found for this link');
|
||||
res.redirect('/');
|
||||
res.json({error:{message:"No match found for url"}});
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
@ -59,7 +58,6 @@ module.exports = function(req, res, next) {
|
|||
}
|
||||
}
|
||||
if (url.host && !searching) {
|
||||
req.flash('search-error', 'No match found for this link');
|
||||
res.redirect('/');
|
||||
res.json({error:{message:"No match found for url"}});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,8 +5,9 @@ var util = require('util');
|
|||
|
||||
var browserify = require('connect-browserify');
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var nodejsx = require('node-jsx').install();
|
||||
var Share = React.createFactory(require('../client/share').Share);
|
||||
var routes = require('../views/app.jsx').routes;
|
||||
|
||||
var services = {};
|
||||
|
||||
|
@ -18,7 +19,7 @@ require("fs").readdirSync(path.join(__dirname, "..", "lib", "services")).forEach
|
|||
});
|
||||
|
||||
|
||||
module.exports.html = function(req, res, next) {
|
||||
module.exports = function(req, res, next) {
|
||||
var serviceId = req.params.service;
|
||||
var type = req.params.type;
|
||||
var itemId = req.params.id;
|
||||
|
@ -32,11 +33,13 @@ module.exports.html = function(req, res, next) {
|
|||
req.db.matches.findOne({_id:serviceId + "$$" + itemId}, function(err, doc) {
|
||||
if (err) {
|
||||
return next(new Error());
|
||||
} else if (!doc) {
|
||||
return next();
|
||||
}
|
||||
var items = [];
|
||||
var shares = [];
|
||||
for (var docService in Object.keys(services)) {
|
||||
var loopServiceId = Object.keys(services)[docService];
|
||||
items.push(doc.services[loopServiceId]);
|
||||
shares.push(doc.services[loopServiceId]);
|
||||
if (doc.services[loopServiceId].id === undefined) {
|
||||
services[loopServiceId].search(doc.services[serviceId]).timeout(15000).then(function(item) {
|
||||
if (!item.id) {
|
||||
|
@ -52,11 +55,11 @@ module.exports.html = function(req, res, next) {
|
|||
}
|
||||
}
|
||||
|
||||
var items = items.filter(function(item) {
|
||||
var shares = shares.filter(function(item) {
|
||||
return item.service != serviceId;
|
||||
});
|
||||
|
||||
items.sort(function(a, b) {
|
||||
shares.sort(function(a, b) {
|
||||
return !a.id || !b.id;
|
||||
}).sort(function(a, b) {
|
||||
return !a.streamUrl || b.streamUrl;
|
||||
|
@ -64,33 +67,18 @@ module.exports.html = function(req, res, next) {
|
|||
return a.type == "video" && b.type != "video";
|
||||
});
|
||||
|
||||
items.unshift(doc.services[serviceId]);
|
||||
|
||||
var share = Share({items: items});
|
||||
res.send('<!doctype html>\n' + React.renderToString(share).replace("</body></html>", "<script>var items = " + JSON.stringify(items) + "</script></body></html>"));
|
||||
|
||||
// res.render(type, {
|
||||
// page: type,
|
||||
// title: doc.services[serviceId].name + " by " + doc.services[serviceId].artist.name,
|
||||
// matching: doc.services[serviceId],
|
||||
// matches: items,
|
||||
// thisUrl: req.userProtocol + '://' + req.get('host') + req.originalUrl
|
||||
// });
|
||||
shares.unshift(doc.services[serviceId]);
|
||||
if (req.accepts(['html', 'json']) === 'json') {
|
||||
req.db.matches.findOne({_id:serviceId + "$$" + itemId}, function(err, doc) {
|
||||
res.json({shares:shares});
|
||||
});
|
||||
} else {
|
||||
Router.run(routes, req.url, function (Handler) {
|
||||
var App = React.createFactory(Handler);
|
||||
var content = React.renderToString(App({shares: shares}));
|
||||
res.send('<!doctype html>\n' + content.replace("</body></html>", "<script>var shares = " + JSON.stringify(shares) + "</script></body></html>"));
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.json = function(req, res, next) {
|
||||
var serviceId = req.params.service;
|
||||
var type = req.params.type;
|
||||
var itemId = req.params.id;
|
||||
var promises = [];
|
||||
|
||||
if (!services[serviceId] || (type != "album" && type != "track")) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
req.db.matches.findOne({_id:serviceId + "$$" + itemId}, function(err, doc) {
|
||||
res.json(doc);
|
||||
});
|
||||
};
|
|
@ -1,88 +0,0 @@
|
|||
<% include header.ejs %>
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1><a href="/">match<span class="audio-lighten">.audio</span></a></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-9 col-sm-8 col-xs-12">
|
||||
<h3>Matched albums for</h3>
|
||||
<h2><%= matching.name %> <span class="artist-lighten">- <%= matching.artist.name %></span></h2>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-4 hidden-xs">
|
||||
<ul class="list-inline share-tools">
|
||||
<li>Share this</li>
|
||||
<li><a href="http://twitter.com/intent/tweet/?text=Check out <%= matching.name + " by " + matching.artist.name %>&url=<%= thisUrl %>&via=MatchAudio" class="share-dialog"><img src="/images/twitter.png" alt="Twitter" /></a></li>
|
||||
<li><a href="http://www.facebook.com/sharer/sharer.php?p[url]=<%= thisUrl %>" class="share-dialog"><img src="/images/facebook.png" alt="Facebook" /></a></li>
|
||||
<li><a href="https://plus.google.com/share?url=<%= thisUrl %>" class="share-dialog"><img src="/images/googleplus.png" alt="Google+" /></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<% for (var i=0;i < matches.length;i++) { var album = matches[i]; %>
|
||||
<% if (album.type != "video") { %><div class="col-md-3 col-xs-6"><% } else { %><div class="col-md-6 col-xs-12"><% } %>
|
||||
<div class="service <%= i==0 ? "source-service" : "" %>">
|
||||
<div class="matching-from hidden-xs"><%= i==0 ? "Found matches using this link" : "" %></div>
|
||||
<% if (album.type == "video") { %>
|
||||
<div class="js-video widescreen">
|
||||
<iframe width="100%" src="//www.youtube.com/embed/<%= album.id %>" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
<a href="https://www.youtube.com/results?search_query=<%= matching.name %> <%= matching.artist.name %>">More Youtube matches</a>
|
||||
<% } else if (album.streamUrl) { %>
|
||||
<a href="<%= album.streamUrl %>"><img src="<%= album.artwork.small %>" class="img-rounded album-artwork" width="100%"></a>
|
||||
<div class="service-link">
|
||||
<a href="<%= album.streamUrl %>"><img src="/images/<%= album.service %>.png" class="img-rounded"></a>
|
||||
</div>
|
||||
<% } else if (album.purchaseUrl) { %>
|
||||
<a href="<%= album.purchaseUrl %>"><img src="<%= album.artwork.small %>" class="img-rounded album-artwork" width="100%"></a>
|
||||
<div class="service-link">
|
||||
<a href="<%= album.purchaseUrl %>"><img src="/images/<%= album.service %>.png" class="img-rounded"></a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<img src="<%= matching.artwork.small %>" class="img-rounded album-artwork not-found" width="100%"></a>
|
||||
<div class="service-link">
|
||||
<img src="/images/<%= album.service %>.png" class="img-rounded not-found">
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div><% if((i+1)%4 == 0) { %></div><div class="row"><% } %>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="row visible-xs-block">
|
||||
<div class="col-md-12">
|
||||
<ul class="list-inline share-tools">
|
||||
<li>Share this</li>
|
||||
<li><a href="http://twitter.com/intent/tweet/?text=Check out <%= matching.name + " by " + matching.artist.name %>&url=<%= thisUrl %>&via=MatchAudio" class="share-dialog"><img src="/images/twitter.png" alt="Twitter" /></a></li>
|
||||
<li><a href="http://www.facebook.com/sharer/sharer.php?p[url]=<%= thisUrl %>" class="share-dialog"><img src="/images/facebook.png" alt="Facebook" /></a></li>
|
||||
<li><a href="https://plus.google.com/share?url=<%= thisUrl %>" class="share-dialog"><img src="/images/googleplus.png" alt="Google+" /></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
Array.prototype.forEach.call(document.querySelectorAll(".share-dialog"), function(dialog){
|
||||
dialog.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
var w = 845;
|
||||
var h = 670;
|
||||
var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left;
|
||||
var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top;
|
||||
|
||||
width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
||||
height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
||||
|
||||
var left = ((width / 2) - (w / 2)) + dualScreenLeft;
|
||||
var top = ((height / 2) - (h / 2)) + dualScreenTop;
|
||||
var newWindow = window.open(dialog.href, "Share Music", 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
|
||||
if (window.focus) {
|
||||
newwindow.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<% include footer.ejs %>
|
62
views/app.jsx
Normal file
62
views/app.jsx
Normal file
|
@ -0,0 +1,62 @@
|
|||
'use strict';
|
||||
|
||||
var request = require('superagent');
|
||||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var Route = require('react-router').Route;
|
||||
var DefaultRoute = require('react-router').DefaultRoute;
|
||||
var NotFoundRoute = require('react-router').NotFoundRoute;
|
||||
var RouteHandler = require('react-router').RouteHandler;
|
||||
var Home = require('./home.jsx');
|
||||
var Share = require('./share.jsx');
|
||||
var Error = require('./error.jsx');
|
||||
var Head = require('./head.jsx');
|
||||
var ga = require('react-google-analytics');
|
||||
var GAInitiailizer = ga.Initializer;
|
||||
|
||||
var App = React.createClass({
|
||||
|
||||
render: function () {
|
||||
|
||||
return (
|
||||
<html>
|
||||
<Head />
|
||||
<body className="home">
|
||||
<RouteHandler {...this.props} />
|
||||
<GAInitiailizer />
|
||||
<script src="/javascript/bundle.js" />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var NotFound = React.createClass({
|
||||
render: function () {
|
||||
return <h2>Not found</h2>;
|
||||
}
|
||||
});
|
||||
|
||||
var routes = (
|
||||
<Route name="home" handler={App} path="/">
|
||||
<DefaultRoute handler={Home} />
|
||||
<Route name="share" path=":service/:type/:id" handler={Share}/>
|
||||
<NotFoundRoute handler={NotFound}/>
|
||||
</Route>
|
||||
);
|
||||
|
||||
module.exports.routes = routes;
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.onload = function() {
|
||||
Router.run(routes, Router.HistoryLocation, function (Handler) {
|
||||
if (typeof recents !== "undefined") {
|
||||
React.render(<Handler recents={recents} />, document);
|
||||
} else if (typeof shares !== "undefined") {
|
||||
React.render(<Handler shares={shares} />, document);
|
||||
}
|
||||
});
|
||||
ga('create', 'UA-66209-8', 'auto');
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
<% include header.ejs %>
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1><a href="/">match<span class="audio-lighten">.audio</span></a></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container main">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<h2><%= error.status %></h2>
|
||||
<h1><%= message %></h1>
|
||||
<% if (error.stack) { %><pre><%= error.stack %></pre><% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% include footer.ejs %>
|
39
views/error.jsx
Normal file
39
views/error.jsx
Normal file
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var Head = require('./head.jsx');
|
||||
var Foot = require('./foot.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<html>
|
||||
<Head />
|
||||
<body>
|
||||
<div className="error">
|
||||
<header>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<h1><a href="/">match<span className="audio-lighten">.audio</span></a></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div className="container main">
|
||||
<div className="row">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<h2>{this.props.status}</h2>
|
||||
<h1>{this.props.message}</h1>
|
||||
<pre>{this.props.error.stack || ""}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Foot page="error" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
});
|
20
views/foot.jsx
Normal file
20
views/foot.jsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<footer>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className={this.props.page == "home" || this.props.page == "error" ? "col-md-6 col-md-offset-3" : "col-md-12"}>
|
||||
<a href="https://twitter.com/MatchAudio">Tweet</a> or <a href="https://github.com/kudos/match.audio">Fork</a>. A work in progress by <a href="http://crem.in">this guy</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
</div>
|
||||
<footer>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<% if (page == "home") { %><div class="col-md-6 col-md-offset-3"><% } else { %><div class="col-md-12"><% } %>
|
||||
<a href="https://twitter.com/MatchAudio">Tweet</a> or <a href="https://github.com/kudos/match.audio">Fork</a>. A work in progress by <a href="http://crem.in">this guy</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-66209-8', 'match.audio');
|
||||
ga('require', 'displayfeatures');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
28
views/head.jsx
Normal file
28
views/head.jsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Match Audio</title>
|
||||
<meta name="description" content="" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@MatchAudio" />
|
||||
<meta name="twitter:title" property="og:title" content="" />
|
||||
<meta name="twitter:description" property="og:description" content="We've matched this music on Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes so you can open it in the service you use." />
|
||||
<meta name="twitter:image:src" property="og:image" content="" />
|
||||
<meta property="og:url" content="" />
|
||||
<link rel="shortcut icon" href="/images/favicon.png" />
|
||||
<link href='//fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css' />
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/stylesheets/style.css" />
|
||||
</head>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -1,23 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title><% if (locals.title) { %><%= title %> - <% } %>Match Audio</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<% if (locals.items) { var item = items[0] %>
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:site" content="@MatchAudio">
|
||||
<meta name="twitter:title" property="og:title" content="<%= item.name + " by " + item.artist.name %>">
|
||||
<meta name="twitter:description" property="og:description" content="We've matched this music on Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes so you can open it in the service you use." />
|
||||
<meta name="twitter:image:src" property="og:image" content="<%= item.artwork.large %>" />
|
||||
<meta property="og:url" content="<%= thisUrl %>" />
|
||||
<% } %>
|
||||
<link rel="shortcut icon" href="/images/favicon.png">
|
||||
<link href='//fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/stylesheets/style.css">
|
||||
</head>
|
||||
<body class="<%= page %>">
|
||||
<div class="page-wrap">
|
114
views/home.jsx
Normal file
114
views/home.jsx
Normal file
|
@ -0,0 +1,114 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var request = require('superagent');
|
||||
var Router = require('react-router');
|
||||
var Link = require('react-router').Link;
|
||||
var Foot = require('./foot.jsx');
|
||||
|
||||
var Recent = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (<div className="row">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<h2>Recently Shared</h2>
|
||||
<div className="row recent">
|
||||
{this.props.recents.map(function(item, i){
|
||||
return (<RecentItem item={item} key={i} />);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var RecentItem = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="col-sm-4 col-xs-6">
|
||||
<Link to="share" params={this.props.item}><img src={this.props.item.artwork.small} width="100%" /></Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var SearchForm = React.createClass({
|
||||
|
||||
mixins: [ Router.Navigation, Router.State ],
|
||||
|
||||
handleSubmit: function(e) {
|
||||
var that = this;
|
||||
e.preventDefault();
|
||||
var url = this.refs.url.getDOMNode().value.trim();
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
request.post('/search').send({url:url}).end(function(res) {
|
||||
console.log(res)
|
||||
that.transitionTo("/" + res.body.service + "/" + res.body.type + "/" + res.body.id);
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<form role="form" method="post" action="/search" onSubmit={this.handleSubmit}>
|
||||
<div className="input-group input-group-lg">
|
||||
<input type="text" name="url" placeholder="Paste link here" className="form-control" autofocus ref="url" />
|
||||
<span className="input-group-btn">
|
||||
<input type="submit" className="btn btn-lg btn-custom" value="Share Music" />
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
recents: this.props.recents
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function () {
|
||||
if (!this.props.recents) {
|
||||
request.get('/recent').set('Accept', 'application/json').end(function(res) {
|
||||
this.setState({
|
||||
recents: res.body.recents
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div className="page-wrap">
|
||||
<header>
|
||||
<h1><Link to="home">match<span className="audio-lighten">.audio</span></Link></h1>
|
||||
</header>
|
||||
<div className="container">
|
||||
<div className="row share-form">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<SearchForm />
|
||||
</div>
|
||||
</div>
|
||||
<div className="row blurb">
|
||||
<div className="col-md-6 col-md-offset-3">
|
||||
<p>Make sharing from music services better.
|
||||
We match album and track links from Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes and give you back a link with all of them.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Recent recents={this.props.recents} />
|
||||
</div>
|
||||
</div>
|
||||
<Foot page="home" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
<% include header.ejs %>
|
||||
<header>
|
||||
<h1><a href="/">match<span class="audio-lighten">.audio</span></a></h1>
|
||||
</header>
|
||||
<div class="container">
|
||||
|
||||
<div class="row share-form">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<form role="form" method="post" action="/search">
|
||||
<div class="input-group input-group-lg">
|
||||
<input type="text" name="url" placeholder="Paste link here" class="form-control" autofocus>
|
||||
<span class="input-group-btn">
|
||||
<input type="submit" class="btn btn-lg btn-custom" value="Share Music">
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
<% if (error.length > 0) { %>
|
||||
<p class="alert alert-danger"><%= error %></p>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row blurb">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<p>Make sharing from music services better.
|
||||
We match album and track links from Rdio, Spotify, Deezer, Beats Music, Google Music and iTunes and give you back a link with all of them.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<% if (recent.length) { %><h2>Recently Shared</h2><% } %>
|
||||
<div class="row recent">
|
||||
<% for (var i=0;i < recent.length;i++) { var item = recent[i].services[recent[i]._id.split('$$')[0]]; %>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<a href="/<%= item.service.replace("playmusic", "") %>/<%= item.type %>/<%= item.id %>"><img src="<%= item.artwork.small ? item.artwork.small : item.artwork %>" width="100%"></a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% include footer.ejs %>
|
154
views/share.jsx
Normal file
154
views/share.jsx
Normal file
|
@ -0,0 +1,154 @@
|
|||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var request = require('superagent');
|
||||
var Router = require('react-router');
|
||||
var Link = require('react-router').Link;
|
||||
var Foot = require('./foot.jsx');
|
||||
|
||||
var MusicItem = React.createClass({
|
||||
|
||||
render: function() {
|
||||
if (!this.props.item.name) {
|
||||
return (
|
||||
<div className="col-md-3 col-xs-6">
|
||||
<div className="service">
|
||||
<div className="matching-from hidden-xs"></div>
|
||||
<img src={this.props.items[0].artwork.small} className="img-rounded album-artwork not-found" width="100%" />
|
||||
<div className="service-link">
|
||||
<img src={"/images/" + this.props.item.service + ".png"} className="img-rounded" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className="col-md-3 col-xs-6">
|
||||
<div className="service">
|
||||
<div className="matching-from hidden-xs"></div>
|
||||
<a href={this.props.item.streamUrl || this.props.item.purchaseUrl}>
|
||||
<img src={this.props.item.artwork.small} className="img-rounded album-artwork" width="100%" /></a>
|
||||
<div className="service-link">
|
||||
<a href={this.props.item.streamUrl || this.props.item.purchaseUrl}>
|
||||
<img src={"/images/" + this.props.item.service + ".png"} className="img-rounded" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var VideoItem = React.createClass({
|
||||
|
||||
render: function() {
|
||||
if (this.props.item.id) {
|
||||
return (
|
||||
<div className="col-md-6 col-xs-12">
|
||||
<div className="service">
|
||||
<div className="js-video widescreen">
|
||||
<iframe width="100%" src={"//www.youtube.com/embed/" + this.props.item.id} frameBorder="0" allowFullScreen></iframe>
|
||||
</div>
|
||||
<a href={"https://www.youtube.com/results?search_query=" + this.props.items[0].name + " " + this.props.items[0].artist.name}>More Youtube matches</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (<div />);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
mixins: [ Router.State ],
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
name: this.props.shares[0].name || "",
|
||||
artist: this.props.shares[0].artist.name || "",
|
||||
shares: this.props.shares || []
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function () {
|
||||
if (!this.props.shares) {
|
||||
request.get(this.getPathname()).set('Accept', 'application/json').end(function(res) {
|
||||
var shares = res.body.shares;
|
||||
this.setState({
|
||||
name: shares[0].name,
|
||||
artist: shares[0].artist.name,
|
||||
shares: shares
|
||||
});
|
||||
}.bind(this))
|
||||
}
|
||||
|
||||
// Some hacks to pop open the Twitter/Facebook/Google Plus sharing dialogs without using their code.
|
||||
Array.prototype.forEach.call(document.querySelectorAll(".share-dialog"), function(dialog){
|
||||
dialog.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
var w = 845;
|
||||
var h = 670;
|
||||
var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left;
|
||||
var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top;
|
||||
|
||||
var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
||||
var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
||||
|
||||
var left = ((width / 2) - (w / 2)) + dualScreenLeft;
|
||||
var top = ((height / 2) - (h / 2)) + dualScreenTop;
|
||||
var newWindow = window.open(dialog.href, "Share Music", 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
|
||||
if (window.focus) {
|
||||
newWindow.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
<div className="page-wrap share">
|
||||
<header>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<h1><Link to="home">match<span className="audio-lighten">.audio</span></Link></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-md-9 col-sm-8 col-xs-12">
|
||||
<h3>Matched {this.state.shares[0] ? this.state.shares[0].type + "s" : ""} for</h3>
|
||||
<h2>{this.state.name} <span className="artist-lighten">- {this.state.artist}</span></h2>
|
||||
</div>
|
||||
<div className="col-md-3 col-sm-4 hidden-xs">
|
||||
<ul className="list-inline share-tools">
|
||||
<li>Share this</li>
|
||||
<li><a href={"http://twitter.com/intent/tweet/?text=Check out " + this.state.name + " by " + this.state.artist + "&via=MatchAudio"} className="share-dialog"><img src="/images/twitter.png" alt="Twitter" /></a></li>
|
||||
<li><a href="http://www.facebook.com/sharer/sharer.php" className="share-dialog"><img src="/images/facebook.png" alt="Facebook" /></a></li>
|
||||
<li><a href="https://plus.google.com/share" className="share-dialog"><img src="/images/googleplus.png" alt="Google+" /></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
{this.state.shares.map(function(item, i){
|
||||
if (item.service == "youtube") {
|
||||
return (<VideoItem items={this.state.shares} item={item} inc={i} key={i} />);
|
||||
} else {
|
||||
return (<MusicItem items={this.state.shares} item={item} inc={i} key={i} />);
|
||||
}
|
||||
}.bind(this))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Foot page="share" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -1,88 +0,0 @@
|
|||
<% include header.ejs %>
|
||||
<header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1><a href="/">match<span class="audio-lighten">.audio</span></a></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-9 col-sm-8 col-xs-12">
|
||||
<h3>Matched tracks for</h3>
|
||||
<h2><%= items[0].name %> <span class="artist-lighten">- <%= items[0].artist.name %></span></h2>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-4 hidden-xs">
|
||||
<ul class="list-inline share-tools">
|
||||
<li>Share this</li>
|
||||
<li><a href="http://twitter.com/intent/tweet/?text=Check out <%= items[0].name + " by " + items[0].artist.name %>&url=<%= thisUrl %>&via=MatchAudio" class="share-dialog"><img src="/images/twitter.png" alt="Twitter" /></a></li>
|
||||
<li><a href="http://www.facebook.com/sharer/sharer.php?p[url]=<%= thisUrl %>" class="share-dialog"><img src="/images/facebook.png" alt="Facebook" /></a></li>
|
||||
<li><a href="https://plus.google.com/share?url=<%= thisUrl %>" class="share-dialog"><img src="/images/googleplus.png" alt="Google+" /></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<% for (var i=0;i < items.length;i++) { var track = items[i]; %>
|
||||
<% if (track.type != "video") { %><div class="col-md-3 col-xs-6"><% } else { %><div class="col-md-6 col-xs-12"><% } %>
|
||||
<div class="service <%= i==0 ? "source-service" : "" %>">
|
||||
<div class="matching-from hidden-xs"><%= i==0 ? "Found matches using this link" : "" %></div>
|
||||
<% if (track.type == "video") { %>
|
||||
<div class="js-video widescreen">
|
||||
<iframe width="100%" src="//www.youtube.com/embed/<%= track.id %>" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
<a href="https://www.youtube.com/results?search_query=<%= items[0].name %> <%= items[0].artist.name %>">More Youtube matches</a>
|
||||
<% } else if (track.streamUrl) { %>
|
||||
<a href="<%= track.streamUrl %>"><img src="<%= track.artwork.small %>" class="img-rounded album-artwork" width="100%"></a>
|
||||
<div class="service-link">
|
||||
<a href="<%= track.streamUrl %>"><img src="/images/<%= track.service %>.png" class="img-rounded"></a>
|
||||
</div>
|
||||
<% } else if (track.purchaseUrl) { %>
|
||||
<a href="<%= track.purchaseUrl %>"><img src="<%= track.artwork.small %>" class="img-rounded album-artwork" width="100%"></a>
|
||||
<div class="service-link">
|
||||
<a href="<%= track.purchaseUrl %>"><img src="/images/<%= track.service %>.png" class="img-rounded"></a>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<img src="<%= items[0].artwork.small %>" class="img-rounded album-artwork not-found" width="100%"></a>
|
||||
<div class="service-link">
|
||||
<img src="/images/<%= track.service %>.png" class="img-rounded not-found">
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div><% if((i+1)%4 == 0) { %></div><div class="row"><% } %>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="row visible-xs-block">
|
||||
<div class="col-md-12">
|
||||
<ul class="list-inline share-tools">
|
||||
<li>Share this</li>
|
||||
<li><a href="http://twitter.com/intent/tweet/?text=Check out <%= items[0].name + " by " + items[0].artist.name %>&url=<%= thisUrl %>&via=MatchAudio" class="share-dialog"><img src="/images/twitter.png" alt="Twitter" /></a></li>
|
||||
<li><a href="http://www.facebook.com/sharer/sharer.php?p[url]=<%= thisUrl %>" class="share-dialog"><img src="/images/facebook.png" alt="Facebook" /></a></li>
|
||||
<li><a href="https://plus.google.com/share?url=<%= thisUrl %>" class="share-dialog"><img src="/images/googleplus.png" alt="Google+" /></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
Array.prototype.forEach.call(document.querySelectorAll(".share-dialog"), function(dialog){
|
||||
dialog.addEventListener("click", function(event) {
|
||||
event.preventDefault();
|
||||
var w = 845;
|
||||
var h = 670;
|
||||
var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left;
|
||||
var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top;
|
||||
|
||||
width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
|
||||
height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
|
||||
|
||||
var left = ((width / 2) - (w / 2)) + dualScreenLeft;
|
||||
var top = ((height / 2) - (h / 2)) + dualScreenTop;
|
||||
var newWindow = window.open(dialog.href, "Share Music", 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
|
||||
if (window.focus) {
|
||||
newwindow.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<% include footer.ejs %>
|
Loading…
Add table
Add a link
Reference in a new issue