Skip to content

Instantly share code, notes, and snippets.

@yamsellem
Last active June 28, 2016 15:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yamsellem/2241e732cf80591abfc080b19e6ced67 to your computer and use it in GitHub Desktop.
Save yamsellem/2241e732cf80591abfc080b19e6ced67 to your computer and use it in GitHub Desktop.
"use strict";
$(function() {
$('a').on('click', function(e) {
e.preventDefault();
Backbone.history.navigate(
$(e.currentTarget).attr('href'),
{trigger: true}
);
});
var Musician = Backbone.Model.extend({
urlRoot: '/musician'
});
var Musicians = Backbone.Collection.extend({
url: '/musician'
});
var ItemView = Backbone.View.extend({
tagName: 'div',
className: 'large-4 small-6 columns',
template: Handlebars.compile(`
<img class="face" src="{{picture}}">
<div class="panel">
<h5>{{name}}</h5>
<h6 class="subheader">{{bio}}</h6>
</div>
`),
events: {
mouseenter: function() {
this.state.set('overed', true);
},
mouseleave: function() {
this.state.set('overed', false);
},
click: function() {
this.model.destroy({wait: true});
}
},
initialize: function() {
this.state = new Backbone.Model({
'overed': false
});
this.render();
this.listenTo(this.model, 'destroy', this.remove);
this.listenTo(this.state, 'change', this.render);
},
render: function() {
var data = this.model.toJSON();
var html = this.template(data);
this.$el.html(html);
this.$el.toggleClass('delete', this.state.get('overed'));
}
});
var ListView = Backbone.View.extend({
template: Handlebars.compile($('#musician-list-template').html()),
initialize: function() {
this.collection.fetch();
this.listenTo(this.collection, 'sync', this.render);
},
render: function() {
this.collection.each(function(model) {
var item = new ItemView({model: model});
this.el.appendChild(item.el);
}.bind(this))
}
});
var MessageView = Backbone.View.extend({
template: Handlebars.compile($('#notification-template').html()),
initialize: function() {
this.state = new Backbone.Model({visible: false});
this.listenTo(this.state, 'change', this.render);
this.listenTo(this.collection, 'remove', function() {
this.state.set('visible', true);
});
},
render: function() {
this.$el
.toggle(this.state.get('visible'))
.html(this.template('Wahou !'));
},
events: {
'click .js-close': 'close'
},
close: function() {
this.state.set('visible', false);
}
})
var Pictures = Backbone.Collection.extend({
url: '/picture'
});
var FormItemView = Backbone.View.extend({
template: Handlebars.compile($('#musician-faces-template').html()),
initialize: function() {
this.render();
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
},
events: {
'click': function() {
this.trigger('selection', this);
this.$('img').addClass('selected');
}
},
deselect: function() {
this.$('img').removeClass('selected');
}
});
var FormListView = Backbone.View.extend({
initialize: function() {
this.collection = new Pictures();
this.collection.fetch();
this.listenTo(this.collection, 'sync', this.render);
},
render: function() {
var subviews = [];
this.collection.forEach(function(model) {
var item = new FormItemView({model: model});
this.listenTo(item, 'selection', function() {
subviews.forEach(function(view) {
view.deselect();
})
});
this.$el.append(item.el);
subviews.push(item);
}.bind(this));
}
});
var MusicianCreationView = Backbone.View.extend({
template: Handlebars.compile($('#musician-creation-template').html()),
initialize: function() {
this.render();
this.model = new Musician();
this.listenTo(this.model, 'sync', this.render);
},
render: function() {
this.$el.html(this.template);
var faces = new FormListView();
this.$('.musician-faces').html(faces.el);
},
events: {
'submit': 'create'
},
create: function(e) {
e.preventDefault();
this.model.save({
name: this.$('input[name=name]').val(),
bio: this.$('textarea[name=bio]').val(),
picture: ''
});
}
})
var User = Backbone.Model.extend({
url: '/user',
sign: function(url, data) {
this.url = url;
return this.save(data)
.always(function() {
this.url = '/user';
}.bind(this));
},
signin: function(data) {
return this.sign('/user/signin', data);
},
signout: function(options) {
return this.sign('/user/signout');
}
})
var LoginView = Backbone.View.extend({
loginTemplate: Handlebars.compile($('#login-template').html()),
loggedTemplate: Handlebars.compile($('#logged-template').html()),
initialize: function() {
this.model = new User();
this.model
.fetch()
.done(this.renderLogged.bind(this))
.fail(this.renderLogin.bind(this));
},
renderLogin: function() {
this.$el.html(this.loginTemplate());
},
renderLogged: function() {
this.$el.html(this.loggedTemplate(this.model.toJSON()));
},
events: {
'click .js-creation': function(e) {
e.preventDefault();
this.model.signin({
name: this.$('input[name=name]').val(),
password: this.$('input[name=password]').val()
})
.done(this.renderLogged.bind(this))
},
'click .js-logout': function(e) {
e.preventDefault();
this.model.signout()
.done(this.renderLogin.bind(this));
}
}
})
var Router = Backbone.Router.extend({
routes: {
'creation': 'creation',
'login': 'login',
'*joker': 'home'
},
home: function(options, qs) {
qs = qs || '';
var query = _
.chain(qs.split('&'))
.map(function(params) {
var p = params.split('=');
return [p[0], decodeURIComponent(p[1])];
})
.object()
.value();
this.cleanup();
var collection = new Musicians();
var messageView = new MessageView({collection: collection});
var view = new ListView({collection: collection});
$('.js-notification').html(messageView.el);
$('.js-layout').html(view.el);
this.views = [messageView, view];
},
creation: function() {
this.cleanup();
var collection = new Musicians();
var view = new MusicianCreationView();
this.views = [view];
$('.js-layout').html(view.el);
},
login: function() {
this.cleanup();
var view = new LoginView();
this.views = [view];
$('.js-layout').html(view.el);
},
cleanup: function() {
if (!this.views) return;
this.views.forEach(function(view) {
view.remove()
})
}
});
new Router();
Backbone.history.start();
})
///
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>rock'on</title>
<link rel="icon" type="image/png" href="./css/logo.png" sizes="16x16">
<link rel="stylesheet" href="./bower_components/foundation/css/foundation.css">
<link rel="stylesheet" href="./css/basic.css">
<script src="./bower_components/jquery/dist/jquery.js"></script>
<script src="./bower_components/underscore/underscore.js"></script>
<script src="./bower_components/backbone/backbone.js"></script>
<script src="./bower_components/handlebars/handlebars.js"></script>
<script src="./js/app.js"></script>
</head>
<body>
<nav class="top-bar" data-topbar>
<div class="row">
<a class="large-12 columns" href="">
<img src="./css/logo.png">
<h3>rock'on</h3>
<p>Here is a collection of famous musicians<br>Every addition is a blessing</p>
</a>
<ul class="button-group">
<li><a href="creation" class="button radius success">Add an artist</a></li>
<li><a href="login" class="button radius">Login</a></li>
</ul>
</div>
</nav>
<div class="tools"></div>
<div class="row">
<div class="large-12 columns js-notification"></div>
</div>
<div class="row">
<div class="large-12 columns js-layout"></div>
</div>
<div class="pagination-centered"></div>
<footer class="row">
<div class="large-12 columns"><hr/>
<p>Made with ♥ while listening Wolf People's Steeple album.</p>
</div>
</footer>
<script id="musician-creation-template" type="text/x-handlebars-template">
<div class="row">
<div class="large-4 large-offset-4 columns">
<p>Which musician would you like to add?</p>
</div>
</div>
<form>
<input type="hidden" name="picture">
<div class="musician-faces"></div>
<div class="row">
<div class="large-4 large-offset-4 columns">
<div class="row collapse prefix-radius">
<div class="small-3 columns">
<span class="prefix">Name</span>
</div>
<div class="small-9 columns">
<input type="text" name="name" placeholder="ex. Paul">
</div>
</div>
</div>
</div>
<div class="row">
<div class="large-4 large-offset-4 columns">
<div class="row collapse prefix-radius">
<div class="small-3 columns">
<span class="prefix textarea">Bio</span>
</div>
<div class="small-9 columns">
<textarea name="bio" placeholder="ex. Death Metal lead singer "></textarea>
</div>
</div>
</div>
</div>
<div class="row">
<div class="large-4 large-offset-4 columns">
<input type="submit" class="button radius success small js-creation" value="Add">
</div>
</div>
</form>
</script>
<script id="login-template" type="text/x-handlebars-template">
<div class="row">
<div class="large-4 large-offset-4 columns">
<p>Please, enter your credentials</p>
</div>
</div>
<form>
<div class="row">
<div class="large-4 large-offset-4 columns">
<div class="row collapse prefix-radius">
<div class="small-3 columns">
<span class="prefix">Login</span>
</div>
<div class="small-9 columns">
<input type="text" name="name">
</div>
</div>
</div>
</div>
<div class="row">
<div class="large-4 large-offset-4 columns">
<div class="row collapse prefix-radius">
<div class="small-3 columns">
<span class="prefix">Password</span>
</div>
<div class="small-9 columns">
<input type="password" name="password">
</div>
</div>
</div>
</div>
<div class="row">
<div class="large-4 large-offset-4 columns">
<input type="submit" class="button radius success small js-creation" value="Login">
</div>
</div>
</form>
</script>
<script id="logged-template" type="text/x-handlebars-template">
<div class="row">
<div class="large-4 large-offset-4 columns">
<p>Welcome on board <span class="label secondary">{{name}}</span></p>
<form>
<input type="submit" class="button radius js-logout" value="Logout">
</form>
</div>
</div>
</script>
<script id="musician-faces-template" type="text/x-handlebars-template">
<div class="large-2 columns">
<img src="{{picture}}" class="black-and-white">
</div>
</script>
<script id="notification-template" type="text/x-handlebars-template">
<div class="row">
<div class="large-12 columns">
<div class="alert-box radius">
{{.}}
<a href="#" class="close js-close">&times;</a>
</div>
</div>
</div>
</script>
<script id="musician-list-template" type="text/x-handlebars-template">
<div class="row"></div>
</script>
<script id="musician-item-template" type="text/x-handlebars-template">
<img class="face" src="{{picture}}">
<div class="panel">
<h5>{{name}}</h5>
<h6 class="subheader">{{bio}}</h6>
</div>
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment