Shipyard Tasks

The Tasks example app from Shipyard, running in a jsFiddle!

by seanmonstar

CSS

body { font-family:Helvetica, Arial, sans-serif; max-width:800px; margin:0 auto; padding:0 10px; }

     form { overflow:hidden; padding:10px 0; }
             form input { border:1px solid #ccc; display:block; float:left; font-size:110%; height:24px; padding:5px 0; width:80%; }
                 form input:focus { background:#ffe; border-color:#777; outline:none; }
         form button { border:1px solid #aaa; cursor:pointer; background:#eee; display:block; float:right; height:36px; width:18%; -webkit-appearance:none; }
             form button:hover,  form button:focus { border-color:#777; }
             form button:active { background:#f5f5f5; border-color:#000; }

     ul { padding:0; }
     li { list-style:none; margin:10px 0; padding:10px; border:1px solid #ccc; }
     li:hover { background-color:#ffe; }

     li.isDone { text-decoration: line-through; color:#aaa; }
    
         li .title { font-weight:bold; }body { font-family:Helvetica, Arial, sans-serif; max-width:800px; margin:0 auto; }

JavaScript

var Class = require('shipyard/class/Class'),
    model = require('shipyard/model'),
    Syncable = require('shipyard/sync/Syncable'),
    BrowserSync = require('shipyard/sync/Browser');

var Task = new Class({
    
    Extends: model.Model,

    Implements: Syncable,

    Sync: {
        'default': {
            table: 'tasks',
            driver: BrowserSync
        }
    },
    
    fields: {
        id: model.fields.TextField(),
        title: model.fields.TextField(),
        createdAt: model.fields.DateField(),
        isDone: model.fields.BooleanField({ 'default': false })
    },

    toString: function() {
        return this.get('title');
    }
    
});

var View = require('shipyard/view/View'),
    Container = require('shipyard/view/Container'),
    CheckboxView = require('shipyard/view/CheckboxView');

var TaskView = new Class({

    Extends: Container,

    tag: 'li',

    classNames: ['task-view'],

    initialize: function TaskView(options) {
        this.parent(options);

        var checkbox = new CheckboxView({ 'class': 'delete' });
        checkbox.bind(this, { checked: 'isDone' });
        this.addView(checkbox);

        var label = new View({ 'class': 'title' });
        label.bind(this, { content: 'label' });
        this.addView(label);

        this.observe('isDone', this.toggleIsDone);
    },

    toggleIsDone: function(isDone) {
        var element = this.get('element');
        if (element) {
            if (isDone) {
                element.addClass('isDone');
            } else {
                element.removeClass('isDone');
            }
        }
    },

    content: function(task) {
        if (arguments.length === 0) {
            //getter
            return this._task;
        } else {
            //setter
            this._task = task;
        }
    },

    label: View.property(function(label) {
        var content = this.get('content');
        if (!content) {
            return;
        }
        if (arguments.length === 0) {
...