Skip to content

Instantly share code, notes, and snippets.

@DriftwoodJP
Created June 23, 2016 12:15
Show Gist options
  • Save DriftwoodJP/c793bbc224462edcaf153916bbed8aa4 to your computer and use it in GitHub Desktop.
Save DriftwoodJP/c793bbc224462edcaf153916bbed8aa4 to your computer and use it in GitHub Desktop.
ドットインストール「Backbone.js入門」後半
'use strict';
require('babel-polyfill');
const _ = require('underscore');
const $ = require('jquery');
const Backbone = require('backbone');
/**
* Backbone.js入門 (全22回) - プログラミングならドットインストール
* http://dotinstall.com/lessons/basic_backbonejs
*/
// Model
class Task extends Backbone.Model {
constructor(options) {
_.defaults(options, {
defaults: {
title: 'do something',
completed: false
}
});
super(options);
this.on('invalid', (model, error) => {
$('#error').html(error);
});
}
validate(attrs) {
if (_.isEmpty(attrs.title)) {
return 'Title must not be empty.';
}
}
}
// Collection
class Tasks extends Backbone.Collection {
constructor(options) {
_.defaults(options, {
model: Task
});
super(options);
}
}
// View
class TaskView extends Backbone.View {
constructor(options) {
_.defaults(options, {
tagName: 'li',
events: {
'click .delete': 'destroy',
'click .toggle': 'toggle'
}
});
super(options);
this.listenTo(this.model, 'destroy', this.remove);
this.listenTo(this.model, 'change', this.render);
this.template = _.template($('#task-template').html());
}
render() {
let template = this.template(this.model.toJSON());
this.$el.html(template);
return this;
}
destroy() {
/* eslint no-alert: 0 */
let yesDelete = confirm('Are you sure?');
if (yesDelete) {
this.model.destroy();
}
}
remove() {
this.$el.remove();
}
toggle() {
this.model.set('completed', !this.model.get('completed'));
}
}
class TasksView extends Backbone.View {
constructor(options) {
_.defaults(options, {
tagName: 'ul'
});
super(options);
this.listenTo(this.collection, 'add', this.addNew);
this.listenTo(this.collection, 'change', this.updateCount);
this.listenTo(this.collection, 'destroy', this.updateCount);
}
render() {
this.collection.each(task => {
let taskView = new TaskView({model: task});
this.$el.append(taskView.render().el);
}, this);
this.updateCount();
return this;
}
addNew(task) {
let taskView = new TaskView({model: task});
this.$el.append(taskView.render().el);
$('#title').val('').focus();
this.updateCount();
}
updateCount() {
let uncompletedTasks = this.collection.filter(task => {
return !task.get('completed');
});
$('#count').html(uncompletedTasks.length);
}
}
class AddTaskView extends Backbone.View {
constructor(options) {
_.defaults(options, {
el: '#addTask',
events: {
submit: 'submit'
}
});
super(options);
}
submit(e) {
e.preventDefault();
let task = new Task();
if (task.set({title: $('#title').val()}, {validate: true})) {
this.collection.add(task);
$('#error').empty();
}
}
}
(() => {
let tasks = new Tasks([
{title: 'task1', completed: true},
{title: 'task2'},
{title: 'task3'}
]);
let tasksView = new TasksView({collection: tasks});
let addTaskView = new AddTaskView({collection: tasks});
$('#tasks').html(tasksView.render().el);
})();
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>training-backbonejs</title>
<style>
.completed { text-decoration: line-through; color: gray; }
</style>
</head>
<body>
<h1>Tasks</h1>
<form id="addTask">
<input type="text" id="title">
<input type="submit" value="add">
<span id="error"></span>
</form>
<div id="tasks"></div>
<p>Tasks left: <span id="count"></span></p>
<script type="text/template" id="task-template">
<input type="checkbox" class="toggle" <%= this.model.attributes.completed ? 'checked' : '' %>>
<span class="<%= this.model.attributes.completed ? 'completed' : '' %>"><%- title %></span>
<span class="delete">[x]</span>
</script>
<script src="/lib/basic.js"></script>
<noscript>JavaScript が利用できません。</noscript>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment