Last active
June 28, 2016 15:59
-
-
Save yamsellem/2241e732cf80591abfc080b19e6ced67 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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">×</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