LoginSignup
5
5

More than 5 years have passed since last update.

Force.comで動かすBackbone.jsのサンプル

Last updated at Posted at 2014-03-26

Backbone.jsについて少し勉強したのでSalesforceのVisualforceで動かしてみました。

2014-03-26_223123.png

Backbone.jsを使うときは下記のサイトから必要なファイルをダウンロードする必要があります。

Backbonejs.org
http://backbonejs.org/

このサイト内にGitHubへのリンクが用意されています。
そちらから必要なファイル一式をダウンロードできます。

GitHub Repository
https://github.com/jashkenas/backbone

今回必要なファイルは以下の3ファイルです。
- backbone.js
- jquery.js
- underscore.js

このファイルをZip形式で圧縮してSalesforceの静的リソースにアップロードします。

2014-03-26_224708.png

これでBackbone.jsを動かすのに必要なファイルの準備が完了です。
次のコードでBackbone.jsをつかったサンプルページを確認できると思います。

まずベースとなるページです。

BackBoneJsTaskApp.page
<apex:page title="Backbone.js" showHeader="true" sidebar="false">

    <apex:include pageName="BackBoneJsTaskAppCss" />

    <div id="vf-page">

        <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 Count: <span id='count'></span></p>

        <script type="text/template" id="task-template">
            <input type="checkbox" class="toggle" <%= completed ? 'checked': '' %>></input>
            <span class="<%= completed ? 'completed' : '' %>">
                <%- title %>
                <span class="delete">[x]</span>
            </span>
        </script>
    </div>

    <apex:includeScript value="{!URLFOR($Resource.BackBoneJS, 'js/underscore.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.BackBoneJS, 'js/jquery.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.BackBoneJS, 'js/backbone.js')}" />
    <apex:include pageName="BackBoneJsTaskAppScript"/>
</apex:page>

つぎにJavaScriptの処理を記載したページです。Backbone.jsの処理はこの中で行っています。

BackBoneJsTaskAppScript.page
<apex:page >
    <script type="text/javascript">
        (function() {

            // Model
            var Task = Backbone.Model.extend({
                defaults: {
                    title: 'do something',
                    completed: false
                },
                validate: function(attrs) {
                    if ( _.isEmpty(attrs.title)) {
                        return 'title must not be empty';
                    }
                },
                initialize: function() {
                    this.on('invalid', function(model, error) {
                        $('#error').html(error);
                    })
                }
            });
            var Tasks = Backbone.Collection.extend({ model: Task});

            // View
            var TaskView = Backbone.View.extend({
                tagName: 'li',
                initialize: function() {
                    this.model.on('destroy', this.remove, this);
                    this.model.on('change', this.render, this);
                },
                events: {
                    'click .delete': 'destroy',
                    'click .toggle': 'toggle'
                },
                toggle: function() {
                    this.model.set('completed', !this.model.get('completed'));
                },
                destroy: function() {
                    if (confirm('are you sure?')) {
                        this.model.destroy();
                    }
                },
                remove: function() {
                    this.$el.remove();
                },
                template: _.template($('#task-template').html()),
                render: function() {
                    var template = this.template(this.model.toJSON());
                    this.$el.html(template);
                    return this;
                }
            });
            var TasksView = Backbone.View.extend({
                tagName: 'ul',
                initialize: function() {
                    this.collection.on('add', this.addNew, this);
                    this.collection.on('change', this.updateCount, this);
                    this.collection.on('destroy', this.updateCount, this);
                },
                addNew: function(task) {
                    var taskView = new TaskView({model: task});
                    this.$el.append(taskView.render().el);
                    $('#title').val('').focus();
                    this.updateCount();
                },
                updateCount: function() {
                    var uncompletedTasks = this.collection.filter(function(task) {
                        return !task.get('completed');
                    });
                    $('#count').html(uncompletedTasks.length);
                },
                render: function() {
                    this.collection.each(function(task) {
                        var taskView = new TaskView({model: task});
                        this.$el.append(taskView.render().el);
                    }, this);
                    this.updateCount();
                    return this;
                }
            });

            var AddTaskView = Backbone.View.extend({
                el : '#addTask',
                events: {
                    'submit': 'submit'
                },
                submit: function(e) {
                    e.preventDefault();
                    //var task = new Task({title: $('#title').val()});
                    var task = new Task();
                    if (task.set({title: $('#title').val()}, {validate: true})) {
                        this.collection.add(task);
                        $('#error').empty();
                    }
                }
            });

            var tasks = new Tasks([
                {
                    title: 'task1',
                    completed: true
                },
                {
                    title: 'task2'
                },
                {
                    title: 'task3'
                }
            ]);

            var tasksView = new TasksView({collection: tasks});
            var addTaskView = new AddTaskView({collection: tasks});

            $('#tasks').html(tasksView.render().el);
        })();
    </script>
</apex:page>

最後にCSSの処理を記載したページです。

BackBoneJsTaskAppCss.page
<apex:page >
    <style type="text/css">
        #vf-page * {
            font-family: 'メイリオ', sans-serif;
            font-size: 18px;
        }

        #vf-page input[type=text] {
            font-size: 14px;
            padding: 5px;
            width: 200px;
        }

        #vf-page ul li {
            list-style-type: none;
        }

        #vf-page .completed {
            text-decoration: line-through;
            color: gray;
        }

        #error {
            color: red;
        }
    </style>
</apex:page>

CSSやJSの処理は外出しにした方がいいと思うのですが、静的リソースとして扱うと編集や管理がすこし面倒になると思います。そこでCSSやJSは別ページとして作成して、apex:inculdeで読み込む方法で試してみました。この方法でも問題なく動作してくれます。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5