[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/model-sync-rest/ -> model-sync-rest.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 Yahoo! Inc. All rights reserved.
   4  Licensed under the BSD License.
   5  http://yuilibrary.com/license/
   6  */
   7  
   8  YUI.add('model-sync-rest', function (Y, NAME) {
   9  
  10  /**
  11  An extension which provides a RESTful XHR sync implementation that can be mixed
  12  into a Model or ModelList subclass.
  13  
  14  @module app
  15  @submodule model-sync-rest
  16  @since 3.6.0
  17  **/
  18  
  19  var Lang = Y.Lang;
  20  
  21  /**
  22  An extension which provides a RESTful XHR sync implementation that can be mixed
  23  into a Model or ModelList subclass.
  24  
  25  This makes it trivial for your Model or ModelList subclasses communicate and
  26  transmit their data via RESTful XHRs. In most cases you'll only need to provide
  27  a value for `root` when sub-classing `Y.Model`.
  28  
  29      Y.User = Y.Base.create('user', Y.Model, [Y.ModelSync.REST], {
  30          root: '/users'
  31      });
  32  
  33      Y.Users = Y.Base.create('users', Y.ModelList, [Y.ModelSync.REST], {
  34          // By convention `Y.User`'s `root` will be used for the lists' URL.
  35          model: Y.User
  36      });
  37  
  38      var users = new Y.Users();
  39  
  40      // GET users list from: "/users"
  41      users.load(function () {
  42          var firstUser = users.item(0);
  43  
  44          firstUser.get('id'); // => "1"
  45  
  46          // PUT updated user data at: "/users/1"
  47          firstUser.set('name', 'Eric').save();
  48      });
  49  
  50  @class ModelSync.REST
  51  @extensionfor Model
  52  @extensionfor ModelList
  53  @since 3.6.0
  54  **/
  55  function RESTSync() {}
  56  
  57  /**
  58  A request authenticity token to validate HTTP requests made by this extension
  59  with the server when the request results in changing persistent state. This
  60  allows you to protect your server from Cross-Site Request Forgery attacks.
  61  
  62  A CSRF token provided by the server can be embedded in the HTML document and
  63  assigned to `YUI.Env.CSRF_TOKEN` like this:
  64  
  65      <script>
  66          YUI.Env.CSRF_TOKEN = {{session.authenticityToken}};
  67      </script>
  68  
  69  The above should come after YUI seed file so that `YUI.Env` will be defined.
  70  
  71  **Note:** This can be overridden on a per-request basis. See `sync()` method.
  72  
  73  When a value for the CSRF token is provided, either statically or via `options`
  74  passed to the `save()` and `destroy()` methods, the applicable HTTP requests
  75  will have a `X-CSRF-Token` header added with the token value.
  76  
  77  @property CSRF_TOKEN
  78  @type String
  79  @default YUI.Env.CSRF_TOKEN
  80  @static
  81  @since 3.6.0
  82  **/
  83  RESTSync.CSRF_TOKEN = YUI.Env.CSRF_TOKEN;
  84  
  85  /**
  86  Static flag to use the HTTP POST method instead of PUT or DELETE.
  87  
  88  If the server-side HTTP framework isn't RESTful, setting this flag to `true`
  89  will cause all PUT and DELETE requests to instead use the POST HTTP method, and
  90  add a `X-HTTP-Method-Override` HTTP header with the value of the method type
  91  which was overridden.
  92  
  93  @property EMULATE_HTTP
  94  @type Boolean
  95  @default false
  96  @static
  97  @since 3.6.0
  98  **/
  99  RESTSync.EMULATE_HTTP = false;
 100  
 101  /**
 102  Default headers used with all XHRs.
 103  
 104  By default the `Accept` and `Content-Type` headers are set to
 105  "application/json", this signals to the HTTP server to process the request
 106  bodies as JSON and send JSON responses. If you're sending and receiving content
 107  other than JSON, you can override these headers and the `parse()` and
 108  `serialize()` methods.
 109  
 110  **Note:** These headers will be merged with any request-specific headers, and
 111  the request-specific headers will take precedence.
 112  
 113  @property HTTP_HEADERS
 114  @type Object
 115  @default
 116      {
 117          "Accept"      : "application/json",
 118          "Content-Type": "application/json"
 119      }
 120  @static
 121  @since 3.6.0
 122  **/
 123  RESTSync.HTTP_HEADERS = {
 124      'Accept'      : 'application/json',
 125      'Content-Type': 'application/json'
 126  };
 127  
 128  /**
 129  Static mapping of RESTful HTTP methods corresponding to CRUD actions.
 130  
 131  @property HTTP_METHODS
 132  @type Object
 133  @default
 134      {
 135          "create": "POST",
 136          "read"  : "GET",
 137          "update": "PUT",
 138          "delete": "DELETE"
 139      }
 140  @static
 141  @since 3.6.0
 142  **/
 143  RESTSync.HTTP_METHODS = {
 144      'create': 'POST',
 145      'read'  : 'GET',
 146      'update': 'PUT',
 147      'delete': 'DELETE'
 148  };
 149  
 150  /**
 151  The number of milliseconds before the XHRs will timeout/abort. This defaults to
 152  30 seconds.
 153  
 154  **Note:** This can be overridden on a per-request basis. See `sync()` method.
 155  
 156  @property HTTP_TIMEOUT
 157  @type Number
 158  @default 30000
 159  @static
 160  @since 3.6.0
 161  **/
 162  RESTSync.HTTP_TIMEOUT = 30000;
 163  
 164  /**
 165  Properties that shouldn't be turned into ad-hoc attributes when passed to a
 166  Model or ModelList constructor.
 167  
 168  @property _NON_ATTRS_CFG
 169  @type Array
 170  @default ["root", "url"]
 171  @static
 172  @protected
 173  @since 3.6.0
 174  **/
 175  RESTSync._NON_ATTRS_CFG = ['root', 'url'];
 176  
 177  RESTSync.prototype = {
 178  
 179      // -- Public Properties ----------------------------------------------------
 180  
 181      /**
 182      A string which represents the root or collection part of the URL which
 183      relates to a Model or ModelList. Usually this value should be same for all
 184      instances of a specific Model/ModelList subclass.
 185  
 186      When sub-classing `Y.Model`, usually you'll only need to override this
 187      property, which lets the URLs for the XHRs be generated by convention. If
 188      the `root` string ends with a trailing-slash, XHR URLs will also end with a
 189      "/", and if the `root` does not end with a slash, neither will the XHR URLs.
 190  
 191      @example
 192          Y.User = Y.Base.create('user', Y.Model, [Y.ModelSync.REST], {
 193              root: '/users'
 194          });
 195  
 196          var currentUser, newUser;
 197  
 198          // GET the user data from: "/users/123"
 199          currentUser = new Y.User({id: '123'}).load();
 200  
 201          // POST the new user data to: "/users"
 202          newUser = new Y.User({name: 'Eric Ferraiuolo'}).save();
 203  
 204      When sub-classing `Y.ModelList`, usually you'll want to ignore configuring
 205      the `root` and simply rely on the build-in convention of the list's
 206      generated URLs defaulting to the `root` specified by the list's `model`.
 207  
 208      @property root
 209      @type String
 210      @default ""
 211      @since 3.6.0
 212      **/
 213      root: '',
 214  
 215      /**
 216      A string which specifies the URL to use when making XHRs, if not value is
 217      provided, the URLs used to make XHRs will be generated by convention.
 218  
 219      While a `url` can be provided for each Model/ModelList instance, usually
 220      you'll want to either rely on the default convention or provide a tokenized
 221      string on the prototype which can be used for all instances.
 222  
 223      When sub-classing `Y.Model`, you will probably be able to rely on the
 224      default convention of generating URLs in conjunction with the `root`
 225      property and whether the model is new or not (i.e. has an `id`). If the
 226      `root` property ends with a trailing-slash, the generated URL for the
 227      specific model will also end with a trailing-slash.
 228  
 229      @example
 230          Y.User = Y.Base.create('user', Y.Model, [Y.ModelSync.REST], {
 231              root: '/users/'
 232          });
 233  
 234          var currentUser, newUser;
 235  
 236          // GET the user data from: "/users/123/"
 237          currentUser = new Y.User({id: '123'}).load();
 238  
 239          // POST the new user data to: "/users/"
 240          newUser = new Y.User({name: 'Eric Ferraiuolo'}).save();
 241  
 242      If a `url` is specified, it will be processed by `Y.Lang.sub()`, which is
 243      useful when the URLs for a Model/ModelList subclass match a specific pattern
 244      and can use simple replacement tokens; e.g.:
 245  
 246      @example
 247          Y.User = Y.Base.create('user', Y.Model, [Y.ModelSync.REST], {
 248              root: '/users',
 249              url : '/users/{username}'
 250          });
 251  
 252      **Note:** String subsitituion of the `url` only use string an number values
 253      provided by this object's attribute and/or the `options` passed to the
 254      `getURL()` method. Do not expect something fancy to happen with Object,
 255      Array, or Boolean values, they will simply be ignored.
 256  
 257      If your URLs have plural roots or collection URLs, while the specific item
 258      resources are under a singular name, e.g. "/users" (plural) and "/user/123"
 259      (singular), you'll probably want to configure the `root` and `url`
 260      properties like this:
 261  
 262      @example
 263          Y.User = Y.Base.create('user', Y.Model, [Y.ModelSync.REST], {
 264              root: '/users',
 265              url : '/user/{id}'
 266          });
 267  
 268          var currentUser, newUser;
 269  
 270          // GET the user data from: "/user/123"
 271          currentUser = new Y.User({id: '123'}).load();
 272  
 273          // POST the new user data to: "/users"
 274          newUser = new Y.User({name: 'Eric Ferraiuolo'}).save();
 275  
 276      When sub-classing `Y.ModelList`, usually you'll be able to rely on the
 277      associated `model` to supply its `root` to be used as the model list's URL.
 278      If this needs to be customized, you can provide a simple string for the
 279      `url` property.
 280  
 281      @example
 282          Y.Users = Y.Base.create('users', Y.ModelList, [Y.ModelSync.REST], {
 283              // Leverages `Y.User`'s `root`, which is "/users".
 284              model: Y.User
 285          });
 286  
 287          // Or specified explicitly...
 288  
 289          Y.Users = Y.Base.create('users', Y.ModelList, [Y.ModelSync.REST], {
 290              model: Y.User,
 291              url  : '/users'
 292          });
 293  
 294      @property url
 295      @type String
 296      @default ""
 297      @since 3.6.0
 298      **/
 299      url: '',
 300  
 301      // -- Lifecycle Methods ----------------------------------------------------
 302  
 303      initializer: function (config) {
 304          config || (config = {});
 305  
 306          // Overrides `root` at the instance level.
 307          if ('root' in config) {
 308              this.root = config.root || '';
 309          }
 310  
 311          // Overrides `url` at the instance level.
 312          if ('url' in config) {
 313              this.url = config.url || '';
 314          }
 315      },
 316  
 317      // -- Public Methods -------------------------------------------------------
 318  
 319      /**
 320      Returns the URL for this model or model list for the given `action` and
 321      `options`, if specified.
 322  
 323      This method correctly handles the variations of `root` and `url` values and
 324      is called by the `sync()` method to get the URLs used to make the XHRs.
 325  
 326      You can override this method if you need to provide a specific
 327      implementation for how the URLs of your Model and ModelList subclasses need
 328      to be generated.
 329  
 330      @method getURL
 331      @param {String} [action] Optional `sync()` action for which to generate the
 332          URL.
 333      @param {Object} [options] Optional options which may be used to help
 334          generate the URL.
 335      @return {String} this model's or model list's URL for the the given
 336          `action` and `options`.
 337      @since 3.6.0
 338      **/
 339      getURL: function (action, options) {
 340          var root = this.root,
 341              url  = this.url;
 342  
 343          // If this is a model list, use its `url` and substitute placeholders,
 344          // but default to the `root` of its `model`. By convention a model's
 345          // `root` is the location to a collection resource.
 346          if (this._isYUIModelList) {
 347              if (!url) {
 348                  return this.model.prototype.root;
 349              }
 350  
 351              return this._substituteURL(url, Y.merge(this.getAttrs(), options));
 352          }
 353  
 354          // Assume `this` is a model.
 355  
 356          // When a model is new, i.e. has no `id`, the `root` should be used. By
 357          // convention a model's `root` is the location to a collection resource.
 358          // The model's `url` will be used as a fallback if `root` isn't defined.
 359          if (root && (action === 'create' || this.isNew())) {
 360              return root;
 361          }
 362  
 363          // When a model's `url` is not provided, we'll generate a URL to use by
 364          // convention. This will combine the model's `id` with its configured
 365          // `root` and add a trailing-slash if the root ends with "/".
 366          if (!url) {
 367              return this._joinURL(this.getAsURL('id') || '');
 368          }
 369  
 370          // Substitute placeholders in the `url` with URL-encoded values from the
 371          // model's attribute values or the specified `options`.
 372          return this._substituteURL(url, Y.merge(this.getAttrs(), options));
 373      },
 374  
 375      /**
 376      Called to parse the response object returned from `Y.io()`. This method
 377      receives the full response object and is expected to "prep" a response which
 378      is suitable to pass to the `parse()` method.
 379  
 380      By default the response body is returned (`responseText`), because it
 381      usually represents the entire entity of this model on the server.
 382  
 383      If you need to parse data out of the response's headers you should do so by
 384      overriding this method. If you'd like the entire response object from the
 385      XHR to be passed to your `parse()` method, you can simply assign this
 386      property to `false`.
 387  
 388      @method parseIOResponse
 389      @param {Object} response Response object from `Y.io()`.
 390      @return {Any} The modified response to pass along to the `parse()` method.
 391      @since 3.7.0
 392      **/
 393      parseIOResponse: function (response) {
 394          return response.responseText;
 395      },
 396  
 397      /**
 398      Serializes `this` model to be used as the HTTP request entity body.
 399  
 400      By default this model will be serialized to a JSON string via its `toJSON()`
 401      method.
 402  
 403      You can override this method when the HTTP server expects a different
 404      representation of this model's data that is different from the default JSON
 405      serialization. If you're sending and receive content other than JSON, be
 406      sure change the `Accept` and `Content-Type` `HTTP_HEADERS` as well.
 407  
 408      **Note:** A model's `toJSON()` method can also be overridden. If you only
 409      need to modify which attributes are serialized to JSON, that's a better
 410      place to start.
 411  
 412      @method serialize
 413      @param {String} [action] Optional `sync()` action for which to generate the
 414          the serialized representation of this model.
 415      @return {String} serialized HTTP request entity body.
 416      @since 3.6.0
 417      **/
 418      serialize: function (action) {
 419          return Y.JSON.stringify(this);
 420      },
 421  
 422      /**
 423      Communicates with a RESTful HTTP server by sending and receiving data via
 424      XHRs. This method is called internally by load(), save(), and destroy().
 425  
 426      The URL used for each XHR will be retrieved by calling the `getURL()` method
 427      and passing it the specified `action` and `options`.
 428  
 429      This method relies heavily on standard RESTful HTTP conventions
 430  
 431      @method sync
 432      @param {String} action Sync action to perform. May be one of the following:
 433  
 434        * `create`: Store a newly-created model for the first time.
 435        * `delete`: Delete an existing model.
 436        * `read`  : Load an existing model.
 437        * `update`: Update an existing model.
 438  
 439      @param {Object} [options] Sync options:
 440        @param {String} [options.csrfToken] The authenticity token used by the
 441          server to verify the validity of this request and protected against CSRF
 442          attacks. This overrides the default value provided by the static
 443          `CSRF_TOKEN` property.
 444        @param {Object} [options.headers] The HTTP headers to mix with the default
 445          headers specified by the static `HTTP_HEADERS` property.
 446        @param {Number} [options.timeout] The number of milliseconds before the
 447          request will timeout and be aborted. This overrides the default provided
 448          by the static `HTTP_TIMEOUT` property.
 449      @param {Function} [callback] Called when the sync operation finishes.
 450        @param {Error|null} callback.err If an error occurred, this parameter will
 451          contain the error. If the sync operation succeeded, _err_ will be
 452          falsy.
 453        @param {Any} [callback.response] The server's response.
 454      **/
 455      sync: function (action, options, callback) {
 456          options || (options = {});
 457  
 458          var url       = this.getURL(action, options),
 459              method    = RESTSync.HTTP_METHODS[action],
 460              headers   = Y.merge(RESTSync.HTTP_HEADERS, options.headers),
 461              timeout   = options.timeout || RESTSync.HTTP_TIMEOUT,
 462              csrfToken = options.csrfToken || RESTSync.CSRF_TOKEN,
 463              entity;
 464  
 465          // Prepare the content if we are sending data to the server.
 466          if (method === 'POST' || method === 'PUT') {
 467              entity = this.serialize(action);
 468          } else {
 469              // Remove header, no content is being sent.
 470              delete headers['Content-Type'];
 471          }
 472  
 473          // Setup HTTP emulation for older servers if we need it.
 474          if (RESTSync.EMULATE_HTTP &&
 475                  (method === 'PUT' || method === 'DELETE')) {
 476  
 477              // Pass along original method type in the headers.
 478              headers['X-HTTP-Method-Override'] = method;
 479  
 480              // Fall-back to using POST method type.
 481              method = 'POST';
 482          }
 483  
 484          // Add CSRF token to HTTP request headers if one is specified and the
 485          // request will cause side effects on the server.
 486          if (csrfToken &&
 487                  (method === 'POST' || method === 'PUT' || method === 'DELETE')) {
 488  
 489              headers['X-CSRF-Token'] = csrfToken;
 490          }
 491  
 492          this._sendSyncIORequest({
 493              action  : action,
 494              callback: callback,
 495              entity  : entity,
 496              headers : headers,
 497              method  : method,
 498              timeout : timeout,
 499              url     : url
 500          });
 501      },
 502  
 503      // -- Protected Methods ----------------------------------------------------
 504  
 505      /**
 506      Joins the `root` URL to the specified `url`, normalizing leading/trailing
 507      "/" characters.
 508  
 509      @example
 510          model.root = '/foo'
 511          model._joinURL('bar');  // => '/foo/bar'
 512          model._joinURL('/bar'); // => '/foo/bar'
 513  
 514          model.root = '/foo/'
 515          model._joinURL('bar');  // => '/foo/bar/'
 516          model._joinURL('/bar'); // => '/foo/bar/'
 517  
 518      @method _joinURL
 519      @param {String} url URL to append to the `root` URL.
 520      @return {String} Joined URL.
 521      @protected
 522      @since 3.6.0
 523      **/
 524      _joinURL: function (url) {
 525          var root = this.root;
 526  
 527          if (!(root || url)) {
 528              return '';
 529          }
 530  
 531          if (url.charAt(0) === '/') {
 532              url = url.substring(1);
 533          }
 534  
 535          // Combines the `root` with the `url` and adds a trailing-slash if the
 536          // `root` has a trailing-slash.
 537          return root && root.charAt(root.length - 1) === '/' ?
 538                  root + url + '/' :
 539                  root + '/' + url;
 540      },
 541  
 542  
 543      /**
 544      Calls both public, overrideable methods: `parseIOResponse()`, then `parse()`
 545      and returns the result.
 546  
 547      This will call into `parseIOResponse()`, if it's defined as a method,
 548      passing it the full response object from the XHR and using its return value
 549      to pass along to the `parse()`. This enables developers to easily parse data
 550      out of the response headers which should be used by the `parse()` method.
 551  
 552      @method _parse
 553      @param {Object} response Response object from `Y.io()`.
 554      @return {Object|Object[]} Attribute hash or Array of model attribute hashes.
 555      @protected
 556      @since 3.7.0
 557      **/
 558      _parse: function (response) {
 559          // When `parseIOResponse` is defined as a method, it will be invoked and
 560          // the result will become the new response object that the `parse()`
 561          // will be invoked with.
 562          if (typeof this.parseIOResponse === 'function') {
 563              response = this.parseIOResponse(response);
 564          }
 565  
 566          return this.parse(response);
 567      },
 568  
 569      /**
 570      Performs the XHR and returns the resulting `Y.io()` request object.
 571  
 572      This method is called by `sync()`.
 573  
 574      @method _sendSyncIORequest
 575      @param {Object} config An object with the following properties:
 576        @param {String} config.action The `sync()` action being performed.
 577        @param {Function} [config.callback] Called when the sync operation
 578          finishes.
 579        @param {String} [config.entity] The HTTP request entity body.
 580        @param {Object} config.headers The HTTP request headers.
 581        @param {String} config.method The HTTP request method.
 582        @param {Number} [config.timeout] Time until the HTTP request is aborted.
 583        @param {String} config.url The URL of the HTTP resource.
 584      @return {Object} The resulting `Y.io()` request object.
 585      @protected
 586      @since 3.6.0
 587      **/
 588      _sendSyncIORequest: function (config) {
 589          return Y.io(config.url, {
 590              'arguments': {
 591                  action  : config.action,
 592                  callback: config.callback,
 593                  url     : config.url
 594              },
 595  
 596              context: this,
 597              data   : config.entity,
 598              headers: config.headers,
 599              method : config.method,
 600              timeout: config.timeout,
 601  
 602              on: {
 603                  start  : this._onSyncIOStart,
 604                  failure: this._onSyncIOFailure,
 605                  success: this._onSyncIOSuccess,
 606                  end    : this._onSyncIOEnd
 607              }
 608          });
 609      },
 610  
 611      /**
 612      Utility which takes a tokenized `url` string and substitutes its
 613      placeholders using a specified `data` object.
 614  
 615      This method will property URL-encode any values before substituting them.
 616      Also, only expect it to work with String and Number values.
 617  
 618      @example
 619          var url = this._substituteURL('/users/{name}', {id: 'Eric F'});
 620          // => "/users/Eric%20F"
 621  
 622      @method _substituteURL
 623      @param {String} url Tokenized URL string to substitute placeholder values.
 624      @param {Object} data Set of data to fill in the `url`'s placeholders.
 625      @return {String} Substituted URL.
 626      @protected
 627      @since 3.6.0
 628      **/
 629      _substituteURL: function (url, data) {
 630          if (!url) {
 631              return '';
 632          }
 633  
 634          var values = {};
 635  
 636          // Creates a hash of the string and number values only to be used to
 637          // replace any placeholders in a tokenized `url`.
 638          Y.Object.each(data, function (v, k) {
 639              if (Lang.isString(v) || Lang.isNumber(v)) {
 640                  // URL-encode any string or number values.
 641                  values[k] = encodeURIComponent(v);
 642              }
 643          });
 644  
 645          return Lang.sub(url, values);
 646      },
 647  
 648      // -- Event Handlers -------------------------------------------------------
 649  
 650      /**
 651      Called when the `Y.io` request has finished, after "success" or "failure"
 652      has been determined.
 653  
 654      This is a no-op by default, but provides a hook for overriding.
 655  
 656      @method _onSyncIOEnd
 657      @param {String} txId The `Y.io` transaction id.
 658      @param {Object} details Extra details carried through from `sync()`:
 659        @param {String} details.action The sync action performed.
 660        @param {Function} [details.callback] The function to call after syncing.
 661        @param {String} details.url The URL of the requested resource.
 662      @protected
 663      @since 3.6.0
 664      **/
 665      _onSyncIOEnd: function (txId, details) {},
 666  
 667      /**
 668      Called when the `Y.io` request has finished unsuccessfully.
 669  
 670      By default this calls the `details.callback` function passing it the HTTP
 671      status code and message as an error object along with the response body.
 672  
 673      @method _onSyncIOFailure
 674      @param {String} txId The `Y.io` transaction id.
 675      @param {Object} res The `Y.io` response object.
 676      @param {Object} details Extra details carried through from `sync()`:
 677        @param {String} details.action The sync action performed.
 678        @param {Function} [details.callback] The function to call after syncing.
 679        @param {String} details.url The URL of the requested resource.
 680      @protected
 681      @since 3.6.0
 682      **/
 683      _onSyncIOFailure: function (txId, res, details) {
 684          var callback = details.callback;
 685  
 686          if (callback) {
 687              callback({
 688                  code: res.status,
 689                  msg : res.statusText
 690              }, res);
 691          }
 692      },
 693  
 694      /**
 695      Called when the `Y.io` request has finished successfully.
 696  
 697      By default this calls the `details.callback` function passing it the
 698      response body.
 699  
 700      @method _onSyncIOSuccess
 701      @param {String} txId The `Y.io` transaction id.
 702      @param {Object} res The `Y.io` response object.
 703      @param {Object} details Extra details carried through from `sync()`:
 704        @param {String} details.action The sync action performed.
 705        @param {Function} [details.callback] The function to call after syncing.
 706        @param {String} details.url The URL of the requested resource.
 707      @protected
 708      @since 3.6.0
 709      **/
 710      _onSyncIOSuccess: function (txId, res, details) {
 711          var callback = details.callback;
 712  
 713          if (callback) {
 714              callback(null, res);
 715          }
 716      },
 717  
 718      /**
 719      Called when the `Y.io` request is made.
 720  
 721      This is a no-op by default, but provides a hook for overriding.
 722  
 723      @method _onSyncIOStart
 724      @param {String} txId The `Y.io` transaction id.
 725      @param {Object} details Extra details carried through from `sync()`:
 726        @param {String} details.action The sync action performed.
 727        @param {Function} [details.callback] The function to call after syncing.
 728        @param {String} details.url The URL of the requested resource.
 729      @protected
 730      @since 3.6.0
 731      **/
 732      _onSyncIOStart: function (txId, details) {}
 733  };
 734  
 735  // -- Namespace ----------------------------------------------------------------
 736  
 737  Y.namespace('ModelSync').REST = RESTSync;
 738  
 739  
 740  }, '3.17.2', {"requires": ["model", "io-base", "json-stringify"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1