server/php/basic/public_html/static/lib/backbone/backbone.js
author rougeronj
Wed, 03 Jun 2015 17:27:46 +0200
changeset 471 e0c7be5dc02c
parent 442 adb907bba956
child 498 08d121184a38
permissions -rw-r--r--
Add a router to handle fragment identifier Set up a listener of the router in the scene to update it Start Backbone.history (eventlistener of the router) when all the project is loaded Include router.js to all the test file
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
//     Backbone.js 1.1.2
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
//     (c) 2010-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
//     Backbone may be freely distributed under the MIT license.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
//     For all details and documentation:
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
//     http://backbonejs.org
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
(function(root, factory) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
  // Set up Backbone appropriately for the environment. Start with AMD.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
  if (typeof define === 'function' && define.amd) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
    define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
      // Export global even in AMD case in case this script is loaded with
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
      // others that may still expect a global Backbone.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
      root.Backbone = factory(root, exports, _, $);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
    });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
  // Next for Node.js or CommonJS. jQuery may not be needed as a module.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
  } else if (typeof exports !== 'undefined') {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
    var _ = require('underscore');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
    factory(root, exports, _);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
  // Finally, as a browser global.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
  } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
    root.Backbone = factory(root, {}, root._, (root.jQuery || root.Zepto || root.ender || root.$));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
  }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
}(this, function(root, Backbone, _, $) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
  // Initial Setup
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
  // -------------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
  // Save the previous value of the `Backbone` variable, so that it can be
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
  // restored later on, if `noConflict` is used.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
  var previousBackbone = root.Backbone;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
  // Create local references to array methods we'll want to use later.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
  var array = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
  var push = array.push;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
  var slice = array.slice;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
  var splice = array.splice;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
  // Current version of the library. Keep in sync with `package.json`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
  Backbone.VERSION = '1.1.2';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
  // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
  // the `$` variable.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
  Backbone.$ = $;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
  // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
  // to its previous owner. Returns a reference to this Backbone object.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
  Backbone.noConflict = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
    root.Backbone = previousBackbone;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
    return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
  // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
  // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
  // set a `X-Http-Method-Override` header.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
  Backbone.emulateHTTP = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
  // Turn on `emulateJSON` to support legacy servers that can't deal with direct
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
  // `application/json` requests ... will encode the body as
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
  // `application/x-www-form-urlencoded` instead and will send the model in a
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
  // form param named `model`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
  Backbone.emulateJSON = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
  // Backbone.Events
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
  // ---------------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
  // A module that can be mixed in to *any object* in order to provide it with
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
  // custom events. You may bind with `on` or remove with `off` callback
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
  // functions to an event; `trigger`-ing an event fires all callbacks in
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
  // succession.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
  //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
  //     var object = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
  //     _.extend(object, Backbone.Events);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
  //     object.on('expand', function(){ alert('expanded'); });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
  //     object.trigger('expand');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
  //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
  var Events = Backbone.Events = {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
    // Bind an event to a `callback` function. Passing `"all"` will bind
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
    // the callback to all events fired.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
    on: function(name, callback, context) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
      if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
      this._events || (this._events = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
      var events = this._events[name] || (this._events[name] = []);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
      events.push({callback: callback, context: context, ctx: context || this});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
    // Bind an event to only be triggered a single time. After the first time
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
    // the callback is invoked, it will be removed.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
    once: function(name, callback, context) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
      if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
      var self = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
      var once = _.once(function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
        self.off(name, once);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
        callback.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
      });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
      once._callback = callback;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
      return this.on(name, once, context);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
    // Remove one or many callbacks. If `context` is null, removes all
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
    // callbacks with that function. If `callback` is null, removes all
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
    // callbacks for the event. If `name` is null, removes all bound
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
    // callbacks for all events.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
    off: function(name, callback, context) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
      var retain, ev, events, names, i, l, j, k;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
      if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
      if (!name && !callback && !context) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
        this._events = void 0;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
        return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
      names = name ? [name] : _.keys(this._events);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
      for (i = 0, l = names.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
        name = names[i];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
        if (events = this._events[name]) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
          this._events[name] = retain = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
          if (callback || context) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
            for (j = 0, k = events.length; j < k; j++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
              ev = events[j];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
              if ((callback && callback !== ev.callback && callback !== ev.callback._callback) ||
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
                  (context && context !== ev.context)) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
                retain.push(ev);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
              }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
            }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
          }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
          if (!retain.length) delete this._events[name];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
    // Trigger one or many events, firing all bound callbacks. Callbacks are
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
    // passed the same arguments as `trigger` is, apart from the event name
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
    // (unless you're listening on `"all"`, which will cause your callback to
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
    // receive the true name of the event as the first argument).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
    trigger: function(name) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
      if (!this._events) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
      var args = slice.call(arguments, 1);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
      if (!eventsApi(this, 'trigger', name, args)) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
      var events = this._events[name];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
      var allEvents = this._events.all;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
      if (events) triggerEvents(events, args);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
      if (allEvents) triggerEvents(allEvents, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
    // Tell this object to stop listening to either specific events ... or
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
    // to every object it's currently listening to.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
    stopListening: function(obj, name, callback) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
      var listeningTo = this._listeningTo;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
      if (!listeningTo) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
      var remove = !name && !callback;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
      if (!callback && typeof name === 'object') callback = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
      if (obj) (listeningTo = {})[obj._listenId] = obj;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
      for (var id in listeningTo) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
        obj = listeningTo[id];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
        obj.off(name, callback, this);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
        if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
  // Regular expression used to split event strings.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
  var eventSplitter = /\s+/;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
  // Implement fancy features of the Events API such as multiple event
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
  // names `"change blur"` and jQuery-style event maps `{change: action}`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
  // in terms of the existing API.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
  var eventsApi = function(obj, action, name, rest) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
    if (!name) return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
    // Handle event maps.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
    if (typeof name === 'object') {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
      for (var key in name) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
        obj[action].apply(obj, [key, name[key]].concat(rest));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
      return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
    // Handle space separated event names.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
    if (eventSplitter.test(name)) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
      var names = name.split(eventSplitter);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
      for (var i = 0, l = names.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
        obj[action].apply(obj, [names[i]].concat(rest));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
      return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
    return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
  // A difficult-to-believe, but optimized internal dispatch function for
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
  // triggering events. Tries to keep the usual cases speedy (most internal
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
  // Backbone events have 3 arguments).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
  var triggerEvents = function(events, args) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
    var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
    switch (args.length) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
      case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
      case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
      case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
      case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
      default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
  var listenMethods = {listenTo: 'on', listenToOnce: 'once'};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
  // Inversion-of-control versions of `on` and `once`. Tell *this* object to
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
  // listen to an event in another object ... keeping track of what it's
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
  // listening to.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
  _.each(listenMethods, function(implementation, method) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
    Events[method] = function(obj, name, callback) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
      var listeningTo = this._listeningTo || (this._listeningTo = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
      var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
      listeningTo[id] = obj;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
      if (!callback && typeof name === 'object') callback = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
      obj[implementation](name, callback, this);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
    };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
  // Aliases for backwards compatibility.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
  Events.bind   = Events.on;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
  Events.unbind = Events.off;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
  // Allow the `Backbone` object to serve as a global event bus, for folks who
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
  // want global "pubsub" in a convenient place.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
  _.extend(Backbone, Events);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
  // Backbone.Model
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
  // --------------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
  // Backbone **Models** are the basic data object in the framework --
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
  // frequently representing a row in a table in a database on your server.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
  // A discrete chunk of data and a bunch of useful, related methods for
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
  // performing computations and transformations on that data.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
  // Create a new model with the specified attributes. A client id (`cid`)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
  // is automatically generated and assigned for you.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
  var Model = Backbone.Model = function(attributes, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
    var attrs = attributes || {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
    options || (options = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
    this.cid = _.uniqueId('c');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
    this.attributes = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
    if (options.collection) this.collection = options.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
    if (options.parse) attrs = this.parse(attrs, options) || {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
    attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
    this.set(attrs, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
    this.changed = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
    this.initialize.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
  // Attach all inheritable methods to the Model prototype.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
  _.extend(Model.prototype, Events, {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
    // A hash of attributes whose current and previous value differ.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
    changed: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
    // The value returned during the last failed validation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
    validationError: null,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
    // The default name for the JSON `id` attribute is `"id"`. MongoDB and
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
    // CouchDB users may want to set this to `"_id"`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
    idAttribute: 'id',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
    // Initialize is an empty function by default. Override it with your own
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
    // initialization logic.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
    initialize: function(){},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
    // Return a copy of the model's `attributes` object.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
    toJSON: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
      return _.clone(this.attributes);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
    // Proxy `Backbone.sync` by default -- but override this if you need
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
    // custom syncing semantics for *this* particular model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
    sync: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
      return Backbone.sync.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
    // Get the value of an attribute.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
    get: function(attr) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
      return this.attributes[attr];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
    // Get the HTML-escaped value of an attribute.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
    escape: function(attr) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
      return _.escape(this.get(attr));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
    // Returns `true` if the attribute contains a value that is not null
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
    // or undefined.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
    has: function(attr) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
      return this.get(attr) != null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
    // Set a hash of model attributes on the object, firing `"change"`. This is
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
    // the core primitive operation of a model, updating the data and notifying
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
    // anyone who needs to know about the change in state. The heart of the beast.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
    set: function(key, val, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
      var attr, attrs, unset, changes, silent, changing, prev, current;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
      if (key == null) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
      // Handle both `"key", value` and `{key: value}` -style arguments.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
      if (typeof key === 'object') {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
        attrs = key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
        options = val;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
      } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
        (attrs = {})[key] = val;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
      options || (options = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
      // Run validation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
      if (!this._validate(attrs, options)) return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
      // Extract attributes and options.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
      unset           = options.unset;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
      silent          = options.silent;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
      changes         = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
      changing        = this._changing;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
      this._changing  = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
      if (!changing) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
        this._previousAttributes = _.clone(this.attributes);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
        this.changed = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
      current = this.attributes, prev = this._previousAttributes;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
      // Check for changes of `id`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
      if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
      // For each `set` attribute, update or delete the current value.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
      for (attr in attrs) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
        val = attrs[attr];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
        if (!_.isEqual(current[attr], val)) changes.push(attr);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
        if (!_.isEqual(prev[attr], val)) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
          this.changed[attr] = val;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
        } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
          delete this.changed[attr];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
        unset ? delete current[attr] : current[attr] = val;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
      // Trigger all relevant attribute changes.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
      if (!silent) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
        if (changes.length) this._pending = options;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
        for (var i = 0, l = changes.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
          this.trigger('change:' + changes[i], this, current[changes[i]], options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
      // You might be wondering why there's a `while` loop here. Changes can
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
      // be recursively nested within `"change"` events.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
      if (changing) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
      if (!silent) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
        while (this._pending) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
          options = this._pending;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
          this._pending = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
          this.trigger('change', this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
      this._pending = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
      this._changing = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
    // Remove an attribute from the model, firing `"change"`. `unset` is a noop
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
    // if the attribute doesn't exist.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
    unset: function(attr, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
      return this.set(attr, void 0, _.extend({}, options, {unset: true}));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
    // Clear all attributes on the model, firing `"change"`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
    clear: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
      var attrs = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
      for (var key in this.attributes) attrs[key] = void 0;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
      return this.set(attrs, _.extend({}, options, {unset: true}));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
    // Determine if the model has changed since the last `"change"` event.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
    // If you specify an attribute name, determine if that attribute has changed.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
    hasChanged: function(attr) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
      if (attr == null) return !_.isEmpty(this.changed);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
      return _.has(this.changed, attr);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
    // Return an object containing all the attributes that have changed, or
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
    // false if there are no changed attributes. Useful for determining what
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
    // parts of a view need to be updated and/or what attributes need to be
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
    // persisted to the server. Unset attributes will be set to undefined.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
    // You can also pass an attributes object to diff against the model,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
    // determining if there *would be* a change.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
    changedAttributes: function(diff) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
      if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
      var val, changed = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
      var old = this._changing ? this._previousAttributes : this.attributes;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
      for (var attr in diff) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
        if (_.isEqual(old[attr], (val = diff[attr]))) continue;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
        (changed || (changed = {}))[attr] = val;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
      return changed;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
    // Get the previous value of an attribute, recorded at the time the last
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
    // `"change"` event was fired.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
    previous: function(attr) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
      if (attr == null || !this._previousAttributes) return null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
      return this._previousAttributes[attr];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
    // Get all of the attributes of the model at the time of the previous
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
    // `"change"` event.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
    previousAttributes: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
      return _.clone(this._previousAttributes);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
    // Fetch the model from the server. If the server's representation of the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
    // model differs from its current attributes, they will be overridden,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
    // triggering a `"change"` event.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
    fetch: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
      options = options ? _.clone(options) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
      if (options.parse === void 0) options.parse = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
      var model = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
      var success = options.success;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
      options.success = function(resp) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
        if (!model.set(model.parse(resp, options), options)) return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
        if (success) success(model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
        model.trigger('sync', model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
      wrapError(this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
      return this.sync('read', this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
    // Set a hash of model attributes, and sync the model to the server.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
    // If the server returns an attributes hash that differs, the model's
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   445
    // state will be `set` again.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   446
    save: function(key, val, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   447
      var attrs, method, xhr, attributes = this.attributes;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   448
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   449
      // Handle both `"key", value` and `{key: value}` -style arguments.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   450
      if (key == null || typeof key === 'object') {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   451
        attrs = key;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   452
        options = val;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   453
      } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   454
        (attrs = {})[key] = val;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   455
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   456
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   457
      options = _.extend({validate: true}, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   458
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   459
      // If we're not waiting and attributes exist, save acts as
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   460
      // `set(attr).save(null, opts)` with validation. Otherwise, check if
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   461
      // the model will be valid when the attributes, if any, are set.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   462
      if (attrs && !options.wait) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   463
        if (!this.set(attrs, options)) return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   464
      } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   465
        if (!this._validate(attrs, options)) return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   466
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   467
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   468
      // Set temporary attributes if `{wait: true}`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   469
      if (attrs && options.wait) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   470
        this.attributes = _.extend({}, attributes, attrs);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   471
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   472
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   473
      // After a successful server-side save, the client is (optionally)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   474
      // updated with the server-side state.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   475
      if (options.parse === void 0) options.parse = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   476
      var model = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   477
      var success = options.success;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   478
      options.success = function(resp) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   479
        // Ensure attributes are restored during synchronous saves.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   480
        model.attributes = attributes;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   481
        var serverAttrs = model.parse(resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   482
        if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   483
        if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   484
          return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   485
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   486
        if (success) success(model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   487
        model.trigger('sync', model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   488
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   489
      wrapError(this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   490
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   491
      method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   492
      if (method === 'patch') options.attrs = attrs;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   493
      xhr = this.sync(method, this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   494
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   495
      // Restore attributes.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   496
      if (attrs && options.wait) this.attributes = attributes;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   497
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   498
      return xhr;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   499
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   500
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   501
    // Destroy this model on the server if it was already persisted.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   502
    // Optimistically removes the model from its collection, if it has one.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   503
    // If `wait: true` is passed, waits for the server to respond before removal.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   504
    destroy: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   505
      options = options ? _.clone(options) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   506
      var model = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   507
      var success = options.success;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   508
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   509
      var destroy = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   510
        model.trigger('destroy', model, model.collection, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   511
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   512
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   513
      options.success = function(resp) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   514
        if (options.wait || model.isNew()) destroy();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   515
        if (success) success(model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   516
        if (!model.isNew()) model.trigger('sync', model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   517
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   518
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   519
      if (this.isNew()) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   520
        options.success();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   521
        return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   522
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   523
      wrapError(this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   524
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   525
      var xhr = this.sync('delete', this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   526
      if (!options.wait) destroy();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   527
      return xhr;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   528
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   529
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   530
    // Default URL for the model's representation on the server -- if you're
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   531
    // using Backbone's restful methods, override this to change the endpoint
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   532
    // that will be called.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   533
    url: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   534
      var base =
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   535
        _.result(this, 'urlRoot') ||
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   536
        _.result(this.collection, 'url') ||
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   537
        urlError();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   538
      if (this.isNew()) return base;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   539
      return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   540
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   541
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   542
    // **parse** converts a response into the hash of attributes to be `set` on
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   543
    // the model. The default implementation is just to pass the response along.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   544
    parse: function(resp, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   545
      return resp;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   546
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   547
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   548
    // Create a new model with identical attributes to this one.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   549
    clone: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   550
      return new this.constructor(this.attributes);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   551
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   552
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   553
    // A model is new if it has never been saved to the server, and lacks an id.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   554
    isNew: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   555
      return !this.has(this.idAttribute);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   556
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   557
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   558
    // Check if the model is currently in a valid state.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   559
    isValid: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   560
      return this._validate({}, _.extend(options || {}, { validate: true }));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   561
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   562
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   563
    // Run validation against the next complete set of model attributes,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   564
    // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   565
    _validate: function(attrs, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   566
      if (!options.validate || !this.validate) return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   567
      attrs = _.extend({}, this.attributes, attrs);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   568
      var error = this.validationError = this.validate(attrs, options) || null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   569
      if (!error) return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   570
      this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   571
      return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   572
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   573
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   574
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   575
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   576
  // Underscore methods that we want to implement on the Model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   577
  var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit'];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   578
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   579
  // Mix in each Underscore method as a proxy to `Model#attributes`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   580
  _.each(modelMethods, function(method) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   581
    Model.prototype[method] = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   582
      var args = slice.call(arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   583
      args.unshift(this.attributes);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   584
      return _[method].apply(_, args);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   585
    };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   586
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   587
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   588
  // Backbone.Collection
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   589
  // -------------------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   590
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   591
  // If models tend to represent a single row of data, a Backbone Collection is
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   592
  // more analagous to a table full of data ... or a small slice or page of that
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   593
  // table, or a collection of rows that belong together for a particular reason
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   594
  // -- all of the messages in this particular folder, all of the documents
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   595
  // belonging to this particular author, and so on. Collections maintain
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   596
  // indexes of their models, both in order, and for lookup by `id`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   597
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   598
  // Create a new **Collection**, perhaps to contain a specific type of `model`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   599
  // If a `comparator` is specified, the Collection will maintain
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   600
  // its models in sort order, as they're added and removed.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   601
  var Collection = Backbone.Collection = function(models, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   602
    options || (options = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   603
    if (options.model) this.model = options.model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   604
    if (options.comparator !== void 0) this.comparator = options.comparator;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   605
    this._reset();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   606
    this.initialize.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   607
    if (models) this.reset(models, _.extend({silent: true}, options));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   608
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   609
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   610
  // Default options for `Collection#set`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   611
  var setOptions = {add: true, remove: true, merge: true};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   612
  var addOptions = {add: true, remove: false};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   613
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   614
  // Define the Collection's inheritable methods.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   615
  _.extend(Collection.prototype, Events, {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   616
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   617
    // The default model for a collection is just a **Backbone.Model**.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   618
    // This should be overridden in most cases.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   619
    model: Model,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   620
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   621
    // Initialize is an empty function by default. Override it with your own
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   622
    // initialization logic.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   623
    initialize: function(){},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   624
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   625
    // The JSON representation of a Collection is an array of the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   626
    // models' attributes.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   627
    toJSON: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   628
      return this.map(function(model){ return model.toJSON(options); });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   629
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   630
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   631
    // Proxy `Backbone.sync` by default.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   632
    sync: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   633
      return Backbone.sync.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   634
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   635
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   636
    // Add a model, or list of models to the set.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   637
    add: function(models, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   638
      return this.set(models, _.extend({merge: false}, options, addOptions));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   639
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   640
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   641
    // Remove a model, or a list of models from the set.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   642
    remove: function(models, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   643
      var singular = !_.isArray(models);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   644
      models = singular ? [models] : _.clone(models);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   645
      options || (options = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   646
      var i, l, index, model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   647
      for (i = 0, l = models.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   648
        model = models[i] = this.get(models[i]);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   649
        if (!model) continue;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   650
        delete this._byId[model.id];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   651
        delete this._byId[model.cid];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   652
        index = this.indexOf(model);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   653
        this.models.splice(index, 1);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   654
        this.length--;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   655
        if (!options.silent) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   656
          options.index = index;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   657
          model.trigger('remove', model, this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   658
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   659
        this._removeReference(model, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   660
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   661
      return singular ? models[0] : models;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   662
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   663
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   664
    // Update a collection by `set`-ing a new list of models, adding new ones,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   665
    // removing models that are no longer present, and merging models that
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   666
    // already exist in the collection, as necessary. Similar to **Model#set**,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   667
    // the core operation for updating the data contained by the collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   668
    set: function(models, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   669
      options = _.defaults({}, options, setOptions);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   670
      if (options.parse) models = this.parse(models, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   671
      var singular = !_.isArray(models);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   672
      models = singular ? (models ? [models] : []) : _.clone(models);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   673
      var i, l, id, model, attrs, existing, sort;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   674
      var at = options.at;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   675
      var targetModel = this.model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   676
      var sortable = this.comparator && (at == null) && options.sort !== false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   677
      var sortAttr = _.isString(this.comparator) ? this.comparator : null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   678
      var toAdd = [], toRemove = [], modelMap = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   679
      var add = options.add, merge = options.merge, remove = options.remove;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   680
      var order = !sortable && add && remove ? [] : false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   681
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   682
      // Turn bare objects into model references, and prevent invalid models
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   683
      // from being added.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   684
      for (i = 0, l = models.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   685
        attrs = models[i] || {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   686
        if (attrs instanceof Model) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   687
          id = model = attrs;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   688
        } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   689
          id = attrs[targetModel.prototype.idAttribute || 'id'];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   690
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   691
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   692
        // If a duplicate is found, prevent it from being added and
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   693
        // optionally merge it into the existing model.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   694
        if (existing = this.get(id)) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   695
          if (remove) modelMap[existing.cid] = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   696
          if (merge) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   697
            attrs = attrs === model ? model.attributes : attrs;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   698
            if (options.parse) attrs = existing.parse(attrs, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   699
            existing.set(attrs, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   700
            if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   701
          }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   702
          models[i] = existing;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   703
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   704
        // If this is a new, valid model, push it to the `toAdd` list.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   705
        } else if (add) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   706
          model = models[i] = this._prepareModel(attrs, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   707
          if (!model) continue;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   708
          toAdd.push(model);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   709
          this._addReference(model, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   710
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   711
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   712
        // Do not add multiple models with the same `id`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   713
        model = existing || model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   714
        if (order && (model.isNew() || !modelMap[model.id])) order.push(model);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   715
        modelMap[model.id] = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   716
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   717
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   718
      // Remove nonexistent models if appropriate.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   719
      if (remove) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   720
        for (i = 0, l = this.length; i < l; ++i) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   721
          if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   722
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   723
        if (toRemove.length) this.remove(toRemove, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   724
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   725
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   726
      // See if sorting is needed, update `length` and splice in new models.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   727
      if (toAdd.length || (order && order.length)) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   728
        if (sortable) sort = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   729
        this.length += toAdd.length;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   730
        if (at != null) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   731
          for (i = 0, l = toAdd.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   732
            this.models.splice(at + i, 0, toAdd[i]);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   733
          }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   734
        } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   735
          if (order) this.models.length = 0;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   736
          var orderedModels = order || toAdd;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   737
          for (i = 0, l = orderedModels.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   738
            this.models.push(orderedModels[i]);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   739
          }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   740
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   741
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   742
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   743
      // Silently sort the collection if appropriate.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   744
      if (sort) this.sort({silent: true});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   745
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   746
      // Unless silenced, it's time to fire all appropriate add/sort events.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   747
      if (!options.silent) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   748
        for (i = 0, l = toAdd.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   749
          (model = toAdd[i]).trigger('add', model, this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   750
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   751
        if (sort || (order && order.length)) this.trigger('sort', this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   752
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   753
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   754
      // Return the added (or merged) model (or models).
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   755
      return singular ? models[0] : models;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   756
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   757
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   758
    // When you have more items than you want to add or remove individually,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   759
    // you can reset the entire set with a new list of models, without firing
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   760
    // any granular `add` or `remove` events. Fires `reset` when finished.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   761
    // Useful for bulk operations and optimizations.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   762
    reset: function(models, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   763
      options || (options = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   764
      for (var i = 0, l = this.models.length; i < l; i++) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   765
        this._removeReference(this.models[i], options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   766
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   767
      options.previousModels = this.models;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   768
      this._reset();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   769
      models = this.add(models, _.extend({silent: true}, options));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   770
      if (!options.silent) this.trigger('reset', this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   771
      return models;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   772
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   773
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   774
    // Add a model to the end of the collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   775
    push: function(model, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   776
      return this.add(model, _.extend({at: this.length}, options));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   777
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   778
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   779
    // Remove a model from the end of the collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   780
    pop: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   781
      var model = this.at(this.length - 1);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   782
      this.remove(model, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   783
      return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   784
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   785
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   786
    // Add a model to the beginning of the collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   787
    unshift: function(model, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   788
      return this.add(model, _.extend({at: 0}, options));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   789
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   790
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   791
    // Remove a model from the beginning of the collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   792
    shift: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   793
      var model = this.at(0);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   794
      this.remove(model, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   795
      return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   796
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   797
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   798
    // Slice out a sub-array of models from the collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   799
    slice: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   800
      return slice.apply(this.models, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   801
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   802
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   803
    // Get a model from the set by id.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   804
    get: function(obj) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   805
      if (obj == null) return void 0;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   806
      return this._byId[obj] || this._byId[obj.id] || this._byId[obj.cid];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   807
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   808
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   809
    // Get the model at the given index.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   810
    at: function(index) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   811
      return this.models[index];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   812
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   813
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   814
    // Return models with matching attributes. Useful for simple cases of
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   815
    // `filter`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   816
    where: function(attrs, first) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   817
      if (_.isEmpty(attrs)) return first ? void 0 : [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   818
      return this[first ? 'find' : 'filter'](function(model) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   819
        for (var key in attrs) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   820
          if (attrs[key] !== model.get(key)) return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   821
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   822
        return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   823
      });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   824
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   825
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   826
    // Return the first model with matching attributes. Useful for simple cases
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   827
    // of `find`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   828
    findWhere: function(attrs) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   829
      return this.where(attrs, true);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   830
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   831
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   832
    // Force the collection to re-sort itself. You don't need to call this under
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   833
    // normal circumstances, as the set will maintain sort order as each item
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   834
    // is added.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   835
    sort: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   836
      if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   837
      options || (options = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   838
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   839
      // Run sort based on type of `comparator`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   840
      if (_.isString(this.comparator) || this.comparator.length === 1) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   841
        this.models = this.sortBy(this.comparator, this);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   842
      } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   843
        this.models.sort(_.bind(this.comparator, this));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   844
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   845
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   846
      if (!options.silent) this.trigger('sort', this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   847
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   848
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   849
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   850
    // Pluck an attribute from each model in the collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   851
    pluck: function(attr) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   852
      return _.invoke(this.models, 'get', attr);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   853
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   854
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   855
    // Fetch the default set of models for this collection, resetting the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   856
    // collection when they arrive. If `reset: true` is passed, the response
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   857
    // data will be passed through the `reset` method instead of `set`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   858
    fetch: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   859
      options = options ? _.clone(options) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   860
      if (options.parse === void 0) options.parse = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   861
      var success = options.success;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   862
      var collection = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   863
      options.success = function(resp) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   864
        var method = options.reset ? 'reset' : 'set';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   865
        collection[method](resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   866
        if (success) success(collection, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   867
        collection.trigger('sync', collection, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   868
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   869
      wrapError(this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   870
      return this.sync('read', this, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   871
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   872
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   873
    // Create a new instance of a model in this collection. Add the model to the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   874
    // collection immediately, unless `wait: true` is passed, in which case we
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   875
    // wait for the server to agree.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   876
    create: function(model, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   877
      options = options ? _.clone(options) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   878
      if (!(model = this._prepareModel(model, options))) return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   879
      if (!options.wait) this.add(model, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   880
      var collection = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   881
      var success = options.success;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   882
      options.success = function(model, resp) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   883
        if (options.wait) collection.add(model, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   884
        if (success) success(model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   885
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   886
      model.save(null, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   887
      return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   888
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   889
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   890
    // **parse** converts a response into a list of models to be added to the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   891
    // collection. The default implementation is just to pass it through.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   892
    parse: function(resp, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   893
      return resp;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   894
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   895
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   896
    // Create a new collection with an identical list of models as this one.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   897
    clone: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   898
      return new this.constructor(this.models);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   899
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   900
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   901
    // Private method to reset all internal state. Called when the collection
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   902
    // is first initialized or reset.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   903
    _reset: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   904
      this.length = 0;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   905
      this.models = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   906
      this._byId  = {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   907
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   908
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   909
    // Prepare a hash of attributes (or other model) to be added to this
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   910
    // collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   911
    _prepareModel: function(attrs, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   912
      if (attrs instanceof Model) return attrs;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   913
      options = options ? _.clone(options) : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   914
      options.collection = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   915
      var model = new this.model(attrs, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   916
      if (!model.validationError) return model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   917
      this.trigger('invalid', this, model.validationError, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   918
      return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   919
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   920
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   921
    // Internal method to create a model's ties to a collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   922
    _addReference: function(model, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   923
      this._byId[model.cid] = model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   924
      if (model.id != null) this._byId[model.id] = model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   925
      if (!model.collection) model.collection = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   926
      model.on('all', this._onModelEvent, this);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   927
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   928
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   929
    // Internal method to sever a model's ties to a collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   930
    _removeReference: function(model, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   931
      if (this === model.collection) delete model.collection;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   932
      model.off('all', this._onModelEvent, this);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   933
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   934
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   935
    // Internal method called every time a model in the set fires an event.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   936
    // Sets need to update their indexes when models change ids. All other
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   937
    // events simply proxy through. "add" and "remove" events that originate
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   938
    // in other collections are ignored.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   939
    _onModelEvent: function(event, model, collection, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   940
      if ((event === 'add' || event === 'remove') && collection !== this) return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   941
      if (event === 'destroy') this.remove(model, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   942
      if (model && event === 'change:' + model.idAttribute) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   943
        delete this._byId[model.previous(model.idAttribute)];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   944
        if (model.id != null) this._byId[model.id] = model;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   945
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   946
      this.trigger.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   947
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   948
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   949
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   950
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   951
  // Underscore methods that we want to implement on the Collection.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   952
  // 90% of the core usefulness of Backbone Collections is actually implemented
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   953
  // right here:
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   954
  var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   955
    'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   956
    'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   957
    'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   958
    'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   959
    'lastIndexOf', 'isEmpty', 'chain', 'sample'];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   960
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   961
  // Mix in each Underscore method as a proxy to `Collection#models`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   962
  _.each(methods, function(method) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   963
    Collection.prototype[method] = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   964
      var args = slice.call(arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   965
      args.unshift(this.models);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   966
      return _[method].apply(_, args);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   967
    };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   968
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   969
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   970
  // Underscore methods that take a property name as an argument.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   971
  var attributeMethods = ['groupBy', 'countBy', 'sortBy', 'indexBy'];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   972
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   973
  // Use attributes instead of properties.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   974
  _.each(attributeMethods, function(method) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   975
    Collection.prototype[method] = function(value, context) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   976
      var iterator = _.isFunction(value) ? value : function(model) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   977
        return model.get(value);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   978
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   979
      return _[method](this.models, iterator, context);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   980
    };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   981
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   982
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   983
  // Backbone.View
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   984
  // -------------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   985
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   986
  // Backbone Views are almost more convention than they are actual code. A View
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   987
  // is simply a JavaScript object that represents a logical chunk of UI in the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   988
  // DOM. This might be a single item, an entire list, a sidebar or panel, or
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   989
  // even the surrounding frame which wraps your whole app. Defining a chunk of
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   990
  // UI as a **View** allows you to define your DOM events declaratively, without
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   991
  // having to worry about render order ... and makes it easy for the view to
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   992
  // react to specific changes in the state of your models.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   993
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   994
  // Creating a Backbone.View creates its initial element outside of the DOM,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   995
  // if an existing element is not provided...
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   996
  var View = Backbone.View = function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   997
    this.cid = _.uniqueId('view');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   998
    options || (options = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
   999
    _.extend(this, _.pick(options, viewOptions));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1000
    this._ensureElement();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1001
    this.initialize.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1002
    this.delegateEvents();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1003
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1004
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1005
  // Cached regex to split keys for `delegate`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1006
  var delegateEventSplitter = /^(\S+)\s*(.*)$/;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1007
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1008
  // List of view options to be merged as properties.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1009
  var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1010
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1011
  // Set up all inheritable **Backbone.View** properties and methods.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1012
  _.extend(View.prototype, Events, {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1013
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1014
    // The default `tagName` of a View's element is `"div"`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1015
    tagName: 'div',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1016
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1017
    // jQuery delegate for element lookup, scoped to DOM elements within the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1018
    // current view. This should be preferred to global lookups where possible.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1019
    $: function(selector) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1020
      return this.$el.find(selector);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1021
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1022
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1023
    // Initialize is an empty function by default. Override it with your own
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1024
    // initialization logic.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1025
    initialize: function(){},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1026
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1027
    // **render** is the core function that your view should override, in order
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1028
    // to populate its element (`this.el`), with the appropriate HTML. The
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1029
    // convention is for **render** to always return `this`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1030
    render: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1031
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1032
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1033
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1034
    // Remove this view by taking the element out of the DOM, and removing any
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1035
    // applicable Backbone.Events listeners.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1036
    remove: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1037
      this.$el.remove();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1038
      this.stopListening();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1039
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1040
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1041
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1042
    // Change the view's element (`this.el` property), including event
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1043
    // re-delegation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1044
    setElement: function(element, delegate) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1045
      if (this.$el) this.undelegateEvents();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1046
      this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1047
      this.el = this.$el[0];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1048
      if (delegate !== false) this.delegateEvents();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1049
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1050
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1051
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1052
    // Set callbacks, where `this.events` is a hash of
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1053
    //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1054
    // *{"event selector": "callback"}*
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1055
    //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1056
    //     {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1057
    //       'mousedown .title':  'edit',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1058
    //       'click .button':     'save',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1059
    //       'click .open':       function(e) { ... }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1060
    //     }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1061
    //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1062
    // pairs. Callbacks will be bound to the view, with `this` set properly.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1063
    // Uses event delegation for efficiency.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1064
    // Omitting the selector binds the event to `this.el`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1065
    // This only works for delegate-able events: not `focus`, `blur`, and
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1066
    // not `change`, `submit`, and `reset` in Internet Explorer.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1067
    delegateEvents: function(events) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1068
      if (!(events || (events = _.result(this, 'events')))) return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1069
      this.undelegateEvents();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1070
      for (var key in events) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1071
        var method = events[key];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1072
        if (!_.isFunction(method)) method = this[events[key]];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1073
        if (!method) continue;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1074
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1075
        var match = key.match(delegateEventSplitter);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1076
        var eventName = match[1], selector = match[2];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1077
        method = _.bind(method, this);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1078
        eventName += '.delegateEvents' + this.cid;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1079
        if (selector === '') {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1080
          this.$el.on(eventName, method);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1081
        } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1082
          this.$el.on(eventName, selector, method);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1083
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1084
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1085
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1086
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1087
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1088
    // Clears all callbacks previously bound to the view with `delegateEvents`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1089
    // You usually don't need to use this, but may wish to if you have multiple
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1090
    // Backbone views attached to the same DOM element.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1091
    undelegateEvents: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1092
      this.$el.off('.delegateEvents' + this.cid);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1093
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1094
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1095
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1096
    // Ensure that the View has a DOM element to render into.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1097
    // If `this.el` is a string, pass it through `$()`, take the first
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1098
    // matching element, and re-assign it to `el`. Otherwise, create
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1099
    // an element from the `id`, `className` and `tagName` properties.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1100
    _ensureElement: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1101
      if (!this.el) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1102
        var attrs = _.extend({}, _.result(this, 'attributes'));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1103
        if (this.id) attrs.id = _.result(this, 'id');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1104
        if (this.className) attrs['class'] = _.result(this, 'className');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1105
        var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1106
        this.setElement($el, false);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1107
      } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1108
        this.setElement(_.result(this, 'el'), false);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1109
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1110
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1111
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1112
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1113
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1114
  // Backbone.sync
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1115
  // -------------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1116
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1117
  // Override this function to change the manner in which Backbone persists
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1118
  // models to the server. You will be passed the type of request, and the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1119
  // model in question. By default, makes a RESTful Ajax request
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1120
  // to the model's `url()`. Some possible customizations could be:
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1121
  //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1122
  // * Use `setTimeout` to batch rapid-fire updates into a single request.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1123
  // * Send up the models as XML instead of JSON.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1124
  // * Persist models via WebSockets instead of Ajax.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1125
  //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1126
  // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1127
  // as `POST`, with a `_method` parameter containing the true HTTP method,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1128
  // as well as all requests with the body as `application/x-www-form-urlencoded`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1129
  // instead of `application/json` with the model in a param named `model`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1130
  // Useful when interfacing with server-side languages like **PHP** that make
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1131
  // it difficult to read the body of `PUT` requests.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1132
  Backbone.sync = function(method, model, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1133
    var type = methodMap[method];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1134
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1135
    // Default options, unless specified.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1136
    _.defaults(options || (options = {}), {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1137
      emulateHTTP: Backbone.emulateHTTP,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1138
      emulateJSON: Backbone.emulateJSON
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1139
    });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1140
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1141
    // Default JSON-request options.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1142
    var params = {type: type, dataType: 'json'};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1143
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1144
    // Ensure that we have a URL.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1145
    if (!options.url) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1146
      params.url = _.result(model, 'url') || urlError();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1147
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1148
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1149
    // Ensure that we have the appropriate request data.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1150
    if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1151
      params.contentType = 'application/json';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1152
      params.data = JSON.stringify(options.attrs || model.toJSON(options));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1153
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1154
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1155
    // For older servers, emulate JSON by encoding the request into an HTML-form.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1156
    if (options.emulateJSON) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1157
      params.contentType = 'application/x-www-form-urlencoded';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1158
      params.data = params.data ? {model: params.data} : {};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1159
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1160
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1161
    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1162
    // And an `X-HTTP-Method-Override` header.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1163
    if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1164
      params.type = 'POST';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1165
      if (options.emulateJSON) params.data._method = type;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1166
      var beforeSend = options.beforeSend;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1167
      options.beforeSend = function(xhr) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1168
        xhr.setRequestHeader('X-HTTP-Method-Override', type);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1169
        if (beforeSend) return beforeSend.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1170
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1171
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1172
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1173
    // Don't process data on a non-GET request.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1174
    if (params.type !== 'GET' && !options.emulateJSON) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1175
      params.processData = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1176
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1177
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1178
    // If we're sending a `PATCH` request, and we're in an old Internet Explorer
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1179
    // that still has ActiveX enabled by default, override jQuery to use that
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1180
    // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1181
    if (params.type === 'PATCH' && noXhrPatch) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1182
      params.xhr = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1183
        return new ActiveXObject("Microsoft.XMLHTTP");
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1184
      };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1185
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1186
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1187
    // Make the request, allowing the user to override any Ajax options.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1188
    var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1189
    model.trigger('request', model, xhr, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1190
    return xhr;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1191
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1192
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1193
  var noXhrPatch =
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1194
    typeof window !== 'undefined' && !!window.ActiveXObject &&
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1195
      !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1196
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1197
  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1198
  var methodMap = {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1199
    'create': 'POST',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1200
    'update': 'PUT',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1201
    'patch':  'PATCH',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1202
    'delete': 'DELETE',
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1203
    'read':   'GET'
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1204
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1205
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1206
  // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1207
  // Override this if you'd like to use a different library.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1208
  Backbone.ajax = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1209
    return Backbone.$.ajax.apply(Backbone.$, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1210
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1211
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1212
  // Backbone.Router
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1213
  // ---------------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1214
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1215
  // Routers map faux-URLs to actions, and fire events when routes are
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1216
  // matched. Creating a new one sets its `routes` hash, if not set statically.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1217
  var Router = Backbone.Router = function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1218
    options || (options = {});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1219
    if (options.routes) this.routes = options.routes;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1220
    this._bindRoutes();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1221
    this.initialize.apply(this, arguments);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1222
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1223
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1224
  // Cached regular expressions for matching named param parts and splatted
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1225
  // parts of route strings.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1226
  var optionalParam = /\((.*?)\)/g;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1227
  var namedParam    = /(\(\?)?:\w+/g;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1228
  var splatParam    = /\*\w+/g;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1229
  var escapeRegExp  = /[\-{}\[\]+?.,\\\^$|#\s]/g;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1230
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1231
  // Set up all inheritable **Backbone.Router** properties and methods.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1232
  _.extend(Router.prototype, Events, {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1233
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1234
    // Initialize is an empty function by default. Override it with your own
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1235
    // initialization logic.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1236
    initialize: function(){},
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1237
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1238
    // Manually bind a single named route to a callback. For example:
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1239
    //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1240
    //     this.route('search/:query/p:num', 'search', function(query, num) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1241
    //       ...
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1242
    //     });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1243
    //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1244
    route: function(route, name, callback) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1245
      if (!_.isRegExp(route)) route = this._routeToRegExp(route);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1246
      if (_.isFunction(name)) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1247
        callback = name;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1248
        name = '';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1249
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1250
      if (!callback) callback = this[name];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1251
      var router = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1252
      Backbone.history.route(route, function(fragment) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1253
        var args = router._extractParameters(route, fragment);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1254
        router.execute(callback, args);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1255
        router.trigger.apply(router, ['route:' + name].concat(args));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1256
        router.trigger('route', name, args);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1257
        Backbone.history.trigger('route', router, name, args);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1258
      });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1259
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1260
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1261
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1262
    // Execute a route handler with the provided parameters.  This is an
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1263
    // excellent place to do pre-route setup or post-route cleanup.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1264
    execute: function(callback, args) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1265
      if (callback) callback.apply(this, args);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1266
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1267
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1268
    // Simple proxy to `Backbone.history` to save a fragment into the history.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1269
    navigate: function(fragment, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1270
      Backbone.history.navigate(fragment, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1271
      return this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1272
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1273
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1274
    // Bind all defined routes to `Backbone.history`. We have to reverse the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1275
    // order of the routes here to support behavior where the most general
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1276
    // routes can be defined at the bottom of the route map.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1277
    _bindRoutes: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1278
      if (!this.routes) return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1279
      this.routes = _.result(this, 'routes');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1280
      var route, routes = _.keys(this.routes);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1281
      while ((route = routes.pop()) != null) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1282
        this.route(route, this.routes[route]);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1283
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1284
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1285
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1286
    // Convert a route string into a regular expression, suitable for matching
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1287
    // against the current location hash.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1288
    _routeToRegExp: function(route) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1289
      route = route.replace(escapeRegExp, '\\$&')
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1290
                   .replace(optionalParam, '(?:$1)?')
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1291
                   .replace(namedParam, function(match, optional) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1292
                     return optional ? match : '([^/?]+)';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1293
                   })
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1294
                   .replace(splatParam, '([^?]*?)');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1295
      return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1296
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1297
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1298
    // Given a route, and a URL fragment that it matches, return the array of
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1299
    // extracted decoded parameters. Empty or unmatched parameters will be
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1300
    // treated as `null` to normalize cross-browser behavior.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1301
    _extractParameters: function(route, fragment) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1302
      var params = route.exec(fragment).slice(1);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1303
      return _.map(params, function(param, i) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1304
        // Don't decode the search params.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1305
        if (i === params.length - 1) return param || null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1306
        return param ? decodeURIComponent(param) : null;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1307
      });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1308
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1309
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1310
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1311
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1312
  // Backbone.History
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1313
  // ----------------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1314
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1315
  // Handles cross-browser history management, based on either
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1316
  // [pushState](http://diveintohtml5.info/history.html) and real URLs, or
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1317
  // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1318
  // and URL fragments. If the browser supports neither (old IE, natch),
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1319
  // falls back to polling.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1320
  var History = Backbone.History = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1321
    this.handlers = [];
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1322
    _.bindAll(this, 'checkUrl');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1323
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1324
    // Ensure that `History` can be used outside of the browser.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1325
    if (typeof window !== 'undefined') {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1326
      this.location = window.location;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1327
      this.history = window.history;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1328
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1329
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1330
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1331
  // Cached regex for stripping a leading hash/slash and trailing space.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1332
  var routeStripper = /^[#\/]|\s+$/g;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1333
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1334
  // Cached regex for stripping leading and trailing slashes.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1335
  var rootStripper = /^\/+|\/+$/g;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1336
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1337
  // Cached regex for detecting MSIE.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1338
  var isExplorer = /msie [\w.]+/;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1339
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1340
  // Cached regex for removing a trailing slash.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1341
  var trailingSlash = /\/$/;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1342
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1343
  // Cached regex for stripping urls of hash.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1344
  var pathStripper = /#.*$/;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1345
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1346
  // Has the history handling already been started?
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1347
  History.started = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1348
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1349
  // Set up all inheritable **Backbone.History** properties and methods.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1350
  _.extend(History.prototype, Events, {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1351
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1352
    // The default interval to poll for hash changes, if necessary, is
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1353
    // twenty times a second.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1354
    interval: 50,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1355
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1356
    // Are we at the app root?
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1357
    atRoot: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1358
      return this.location.pathname.replace(/[^\/]$/, '$&/') === this.root;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1359
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1360
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1361
    // Gets the true hash value. Cannot use location.hash directly due to bug
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1362
    // in Firefox where location.hash will always be decoded.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1363
    getHash: function(window) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1364
      var match = (window || this).location.href.match(/#(.*)$/);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1365
      return match ? match[1] : '';
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1366
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1367
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1368
    // Get the cross-browser normalized URL fragment, either from the URL,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1369
    // the hash, or the override.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1370
    getFragment: function(fragment, forcePushState) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1371
      if (fragment == null) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1372
        if (this._hasPushState || !this._wantsHashChange || forcePushState) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1373
          fragment = decodeURI(this.location.pathname + this.location.search);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1374
          var root = this.root.replace(trailingSlash, '');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1375
          if (!fragment.indexOf(root)) fragment = fragment.slice(root.length);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1376
        } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1377
          fragment = this.getHash();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1378
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1379
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1380
      return fragment.replace(routeStripper, '');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1381
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1382
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1383
    // Start the hash change handling, returning `true` if the current URL matches
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1384
    // an existing route, and `false` otherwise.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1385
    start: function(options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1386
      if (History.started) throw new Error("Backbone.history has already been started");
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1387
      History.started = true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1388
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1389
      // Figure out the initial configuration. Do we need an iframe?
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1390
      // Is pushState desired ... is it available?
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1391
      this.options          = _.extend({root: '/'}, this.options, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1392
      this.root             = this.options.root;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1393
      this._wantsHashChange = this.options.hashChange !== false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1394
      this._wantsPushState  = !!this.options.pushState;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1395
      this._hasPushState    = !!(this.options.pushState && this.history && this.history.pushState);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1396
      var fragment          = this.getFragment();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1397
      var docMode           = document.documentMode;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1398
      var oldIE             = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1399
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1400
      // Normalize root to always include a leading and trailing slash.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1401
      this.root = ('/' + this.root + '/').replace(rootStripper, '/');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1402
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1403
      if (oldIE && this._wantsHashChange) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1404
        var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1405
        this.iframe = frame.hide().appendTo('body')[0].contentWindow;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1406
        this.navigate(fragment);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1407
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1408
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1409
      // Depending on whether we're using pushState or hashes, and whether
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1410
      // 'onhashchange' is supported, determine how we check the URL state.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1411
      if (this._hasPushState) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1412
        Backbone.$(window).on('popstate', this.checkUrl);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1413
      } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1414
        Backbone.$(window).on('hashchange', this.checkUrl);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1415
      } else if (this._wantsHashChange) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1416
        this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1417
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1418
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1419
      // Determine if we need to change the base url, for a pushState link
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1420
      // opened by a non-pushState browser.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1421
      this.fragment = fragment;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1422
      var loc = this.location;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1423
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1424
      // Transition from hashChange to pushState or vice versa if both are
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1425
      // requested.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1426
      if (this._wantsHashChange && this._wantsPushState) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1427
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1428
        // If we've started off with a route from a `pushState`-enabled
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1429
        // browser, but we're currently in a browser that doesn't support it...
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1430
        if (!this._hasPushState && !this.atRoot()) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1431
          this.fragment = this.getFragment(null, true);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1432
          this.location.replace(this.root + '#' + this.fragment);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1433
          // Return immediately as browser will do redirect to new url
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1434
          return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1435
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1436
        // Or if we've started out with a hash-based route, but we're currently
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1437
        // in a browser where it could be `pushState`-based instead...
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1438
        } else if (this._hasPushState && this.atRoot() && loc.hash) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1439
          this.fragment = this.getHash().replace(routeStripper, '');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1440
          this.history.replaceState({}, document.title, this.root + this.fragment);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1441
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1442
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1443
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1444
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1445
      if (!this.options.silent) return this.loadUrl();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1446
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1447
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1448
    // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1449
    // but possibly useful for unit testing Routers.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1450
    stop: function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1451
      Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1452
      if (this._checkUrlInterval) clearInterval(this._checkUrlInterval);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1453
      History.started = false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1454
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1455
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1456
    // Add a route to be tested when the fragment changes. Routes added later
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1457
    // may override previous routes.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1458
    route: function(route, callback) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1459
      this.handlers.unshift({route: route, callback: callback});
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1460
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1461
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1462
    // Checks the current URL to see if it has changed, and if it has,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1463
    // calls `loadUrl`, normalizing across the hidden iframe.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1464
    checkUrl: function(e) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1465
      var current = this.getFragment();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1466
      if (current === this.fragment && this.iframe) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1467
        current = this.getFragment(this.getHash(this.iframe));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1468
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1469
      if (current === this.fragment) return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1470
      if (this.iframe) this.navigate(current);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1471
      this.loadUrl();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1472
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1473
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1474
    // Attempt to load the current URL fragment. If a route succeeds with a
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1475
    // match, returns `true`. If no defined routes matches the fragment,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1476
    // returns `false`.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1477
    loadUrl: function(fragment) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1478
      fragment = this.fragment = this.getFragment(fragment);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1479
      return _.any(this.handlers, function(handler) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1480
        if (handler.route.test(fragment)) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1481
          handler.callback(fragment);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1482
          return true;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1483
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1484
      });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1485
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1486
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1487
    // Save a fragment into the hash history, or replace the URL state if the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1488
    // 'replace' option is passed. You are responsible for properly URL-encoding
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1489
    // the fragment in advance.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1490
    //
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1491
    // The options object can contain `trigger: true` if you wish to have the
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1492
    // route callback be fired (not usually desirable), or `replace: true`, if
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1493
    // you wish to modify the current URL without adding an entry to the history.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1494
    navigate: function(fragment, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1495
      if (!History.started) return false;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1496
      if (!options || options === true) options = {trigger: !!options};
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1497
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1498
      var url = this.root + (fragment = this.getFragment(fragment || ''));
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1499
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1500
      // Strip the hash for matching.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1501
      fragment = fragment.replace(pathStripper, '');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1502
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1503
      if (this.fragment === fragment) return;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1504
      this.fragment = fragment;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1505
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1506
      // Don't include a trailing slash on the root.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1507
      if (fragment === '' && url !== '/') url = url.slice(0, -1);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1508
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1509
      // If pushState is available, we use it to set the fragment as a real URL.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1510
      if (this._hasPushState) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1511
        this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1512
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1513
      // If hash changes haven't been explicitly disabled, update the hash
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1514
      // fragment to store history.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1515
      } else if (this._wantsHashChange) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1516
        this._updateHash(this.location, fragment, options.replace);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1517
        if (this.iframe && (fragment !== this.getFragment(this.getHash(this.iframe)))) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1518
          // Opening and closing the iframe tricks IE7 and earlier to push a
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1519
          // history entry on hash-tag change.  When replace is true, we don't
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1520
          // want this.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1521
          if(!options.replace) this.iframe.document.open().close();
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1522
          this._updateHash(this.iframe.location, fragment, options.replace);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1523
        }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1524
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1525
      // If you've told us that you explicitly don't want fallback hashchange-
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1526
      // based history, then `navigate` becomes a page refresh.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1527
      } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1528
        return this.location.assign(url);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1529
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1530
      if (options.trigger) return this.loadUrl(fragment);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1531
    },
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1532
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1533
    // Update the hash location, either replacing the current entry, or adding
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1534
    // a new one to the browser history.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1535
    _updateHash: function(location, fragment, replace) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1536
      if (replace) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1537
        var href = location.href.replace(/(javascript:|#).*$/, '');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1538
        location.replace(href + '#' + fragment);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1539
      } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1540
        // Some browsers require that `hash` contains a leading #.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1541
        location.hash = '#' + fragment;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1542
      }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1543
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1544
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1545
  });
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1546
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1547
  // Create the default Backbone.history.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1548
  Backbone.history = new History;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1549
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1550
  // Helpers
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1551
  // -------
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1552
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1553
  // Helper function to correctly set up the prototype chain, for subclasses.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1554
  // Similar to `goog.inherits`, but uses a hash of prototype properties and
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1555
  // class properties to be extended.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1556
  var extend = function(protoProps, staticProps) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1557
    var parent = this;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1558
    var child;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1559
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1560
    // The constructor function for the new subclass is either defined by you
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1561
    // (the "constructor" property in your `extend` definition), or defaulted
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1562
    // by us to simply call the parent's constructor.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1563
    if (protoProps && _.has(protoProps, 'constructor')) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1564
      child = protoProps.constructor;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1565
    } else {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1566
      child = function(){ return parent.apply(this, arguments); };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1567
    }
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1568
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1569
    // Add static properties to the constructor function, if supplied.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1570
    _.extend(child, parent, staticProps);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1571
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1572
    // Set the prototype chain to inherit from `parent`, without calling
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1573
    // `parent`'s constructor function.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1574
    var Surrogate = function(){ this.constructor = child; };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1575
    Surrogate.prototype = parent.prototype;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1576
    child.prototype = new Surrogate;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1577
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1578
    // Add prototype properties (instance properties) to the subclass,
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1579
    // if supplied.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1580
    if (protoProps) _.extend(child.prototype, protoProps);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1581
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1582
    // Set a convenience property in case the parent's prototype is needed
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1583
    // later.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1584
    child.__super__ = parent.prototype;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1585
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1586
    return child;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1587
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1588
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1589
  // Set up inheritance for the model, collection, router, view and history.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1590
  Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1591
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1592
  // Throw an error when a URL is needed, and none is supplied.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1593
  var urlError = function() {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1594
    throw new Error('A "url" property or function must be specified');
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1595
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1596
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1597
  // Wrap an optional error callback with a fallback error event.
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1598
  var wrapError = function(model, options) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1599
    var error = options.error;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1600
    options.error = function(resp) {
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1601
      if (error) error(model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1602
      model.trigger('error', model, resp, options);
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1603
    };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1604
  };
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1605
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1606
  return Backbone;
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1607
adb907bba956 add server php example
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1608
}));