Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9CC171001E for ; Mon, 23 Feb 2015 12:23:54 +0000 (UTC) Received: (qmail 69587 invoked by uid 500); 23 Feb 2015 12:23:54 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 69485 invoked by uid 500); 23 Feb 2015 12:23:54 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 69400 invoked by uid 99); 23 Feb 2015 12:23:54 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 23 Feb 2015 12:23:54 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 585CBE08DB; Mon, 23 Feb 2015 12:23:54 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: robertkowalski@apache.org To: commits@couchdb.apache.org Date: Mon, 23 Feb 2015 12:23:55 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/2] fauxton commit: updated refs/heads/master to 5752c48 backbone.layoutmanager@0.9.5 src: https://raw.githubusercontent.com/tbranyen/backbone.layoutmanager/e5daf4d1112daa727aba348722ff5e44cef232d0/backbone.layoutmanager.js Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/be661fb1 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/be661fb1 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/be661fb1 Branch: refs/heads/master Commit: be661fb11f657700af2c524ff2626da680617698 Parents: c2cb64f Author: Robert Kowalski Authored: Fri Feb 20 14:12:35 2015 +0100 Committer: Robert Kowalski Committed: Mon Feb 23 13:23:15 2015 +0100 ---------------------------------------------------------------------- assets/js/plugins/backbone.layoutmanager.js | 214 +++-------------------- 1 file changed, 29 insertions(+), 185 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/be661fb1/assets/js/plugins/backbone.layoutmanager.js ---------------------------------------------------------------------- diff --git a/assets/js/plugins/backbone.layoutmanager.js b/assets/js/plugins/backbone.layoutmanager.js index e20bf5a..fa80ade 100644 --- a/assets/js/plugins/backbone.layoutmanager.js +++ b/assets/js/plugins/backbone.layoutmanager.js @@ -5,31 +5,18 @@ */ (function(window, factory) { "use strict"; + var Backbone = window.Backbone; // AMD. Register as an anonymous module. Wrap in function so we have access // to root via `this`. if (typeof define === "function" && define.amd) { - define(["backbone", "underscore", "jquery"], function() { + return define(["backbone", "underscore", "jquery"], function() { return factory.apply(window, arguments); }); } - // Node. Does not work with strict CommonJS, but only CommonJS-like - // environments that support module.exports, like Node. - else if (typeof exports === "object") { - var Backbone = require("backbone"); - var _ = require("underscore"); - // In a browserify build, since this is the entry point, Backbone.$ - // is not bound. Ensure that it is. - Backbone.$ = Backbone.$ || require("jquery"); - - module.exports = factory.call(window, Backbone, _, Backbone.$); - } - // Browser globals. - else { - factory.call(window, window.Backbone, window._, window.Backbone.$); - } + Backbone.Layout = factory.call(window, Backbone, window._, Backbone.$); }(typeof global === "object" ? global : this, function (Backbone, _, $) { "use strict"; @@ -249,33 +236,20 @@ var LayoutManager = Backbone.View.extend({ return this.__manager__.renderDeferred.promise(); }, - // Proxy `then` for easier invocation. - then: function() { - return this.promise().then.apply(this, arguments); - }, - // Sometimes it's desirable to only render the child views under the parent. // This is typical for a layout that does not change. This method will - // iterate over the provided views or delegate to `getViews` to fetch child - // Views and aggregate all render promises and return the parent View. - // The internal `promise()` method will return the aggregate promise that - // resolves once all children have completed their render. - renderViews: function(views) { + // iterate over the child Views and aggregate all child render promises and + // return the parent View. The internal `promise()` method will return the + // aggregate promise that resolves once all children have completed their + // render. + renderViews: function() { var root = this; var manager = root.__manager__; var newDeferred = root.deferred(); - // If the caller provided an array of views then render those, otherwise - // delegate to getViews. - if (views && _.isArray(views)) { - views = _.chain(views); - } else { - views = root.getViews(views); - } - // Collect all promises from rendering the child views and wait till they // all complete. - var promises = views.map(function(view) { + var promises = root.getViews().map(function(view) { return view.render().__manager__.renderDeferred; }).value(); @@ -472,6 +446,7 @@ var LayoutManager = Backbone.View.extend({ // Triggered once the render has succeeded. function resolve() { + var next; // Insert all subViews into the parent at once. _.each(root.views, function(views, selector) { @@ -495,24 +470,21 @@ var LayoutManager = Backbone.View.extend({ // Set this View as successfully rendered. root.hasRendered = true; - manager.renderInProgress = false; - - // Clear triggeredByRAF flag. - delete manager.triggeredByRAF; // Only process the queue if it exists. - if (manager.queue && manager.queue.length) { + if (next = manager.queue.shift()) { // Ensure that the next render is only called after all other // `done` handlers have completed. This will prevent `render` // callbacks from firing out of order. - (manager.queue.shift())(); + next(); } else { // Once the queue is depleted, remove it, the render process has // completed. delete manager.queue; } - // Reusable function for triggering the afterRender callback and event. + // Reusable function for triggering the afterRender callback and event + // and setting the hasRendered flag. function completeRender() { var console = window.console; var afterRender = root.afterRender; @@ -543,10 +515,10 @@ var LayoutManager = Backbone.View.extend({ // If the parent is currently rendering, wait until it has completed // until calling the nested View's `afterRender`. - if (rentManager && (rentManager.renderInProgress || rentManager.queue)) { + if (rentManager && rentManager.queue) { // Wait until the parent View has finished rendering, which could be // asynchronous, and trigger afterRender on this View once it has - // completed. + // compeleted. parent.once("afterRender", completeRender); } else { // This View and its parent have both rendered. @@ -597,21 +569,23 @@ var LayoutManager = Backbone.View.extend({ }); } - // Mark this render as in progress. This will prevent - // afterRender from being fired until the entire chain has rendered. - manager.renderInProgress = true; + // Another render is currently happening if there is an existing queue, so + // push a closure to render later into the queue. + if (manager.queue) { + aPush.call(manager.queue, actuallyRender); + } else { + manager.queue = []; - // Start the render. - // Register this request & cancel any that conflict. - root._registerWithRAF(actuallyRender, def); + // This the first `render`, preceeding the `queue` so render + // immediately. + actuallyRender(root, def); + } // Put the deferred inside of the `__manager__` object, since we don't want // end users accessing this directly anymore in favor of the `afterRender` // event. So instead of doing `render().then(...` do // `render().once("afterRender", ...`. - // FIXME: I think we need to move back to promises so that we don't - // miss events, regardless of sync/async (useRAF setting) - manager.renderDeferred = def; + root.__manager__.renderDeferred = def; // Return the actual View for chainability purposes. return root; @@ -624,75 +598,6 @@ var LayoutManager = Backbone.View.extend({ // Call the original remove function. return this._remove.apply(this, arguments); - }, - - // Register a view render with RAF. - _registerWithRAF: function(callback, deferred) { - var root = this; - var manager = root.__manager__; - var rentManager = manager.parent && manager.parent.__manager__; - - // Allow RAF processing to be shut off using `useRAF`:false. - if (this.useRAF === false) { - if (manager.queue) { - aPush.call(manager.queue, callback); - } else { - manager.queue = []; - callback(); - } - return; - } - - // Keep track of all deferreds so we can resolve them. - manager.deferreds = manager.deferreds || []; - manager.deferreds.push(deferred); - - // Schedule resolving all deferreds that are waiting. - deferred.done(resolveDeferreds); - - // Cancel any other renders on this view that are queued to execute. - this._cancelQueuedRAFRender(); - - // Trigger immediately if the parent was triggered by RAF. - // The flag propagates downward so this view's children are also - // rendered immediately. - if (rentManager && rentManager.triggeredByRAF) { - return finish(); - } - - // Register this request with requestAnimationFrame. - manager.rafID = root.requestAnimationFrame(finish); - - function finish() { - // Remove this ID as it is no longer valid. - manager.rafID = null; - - // Set flag (will propagate to children) so they render - // without waiting for RAF. - manager.triggeredByRAF = true; - - // Call original cb. - callback(); - } - - // Resolve all deferreds that were cancelled previously, if any. - // This allows the user to bind callbacks to any render callback, - // even if it was cancelled above. - function resolveDeferreds() { - for (var i = 0; i < manager.deferreds.length; i++){ - manager.deferreds[i].resolveWith(root, [root]); - } - manager.deferreds = []; - } - }, - - // Cancel any queued render requests. - _cancelQueuedRAFRender: function() { - var root = this; - var manager = root.__manager__; - if (manager.rafID != null) { - root.cancelAnimationFrame(manager.rafID); - } } }, @@ -742,9 +647,6 @@ var LayoutManager = Backbone.View.extend({ // Remove the View completely. view.$el.remove(); - // Cancel any pending renders, if present. - view._cancelQueuedRAFRender(); - // Bail out early if no parent exists. if (!manager.parent) { return; } @@ -828,11 +730,6 @@ var LayoutManager = Backbone.View.extend({ if (options.suppressWarnings === true) { Backbone.View.prototype.suppressWarnings = true; } - - // Allow global configuration of `useRAF`. - if (options.useRAF === false) { - Backbone.View.prototype.useRAF = false; - } }, // Configure a View to work with the LayoutManager plugin. @@ -925,7 +822,7 @@ Backbone.Layout = LayoutManager; // Override _configure to provide extra functionality that is necessary in // order for the render function reference to be bound during initialize. -Backbone.View.prototype.constructor = function(options) { +Backbone.View = function(options) { var noel; // Ensure options is always an object. @@ -953,8 +850,6 @@ Backbone.View.prototype.constructor = function(options) { ViewConstructor.apply(this, arguments); }; -Backbone.View = Backbone.View.prototype.constructor; - // Copy over the extend method. Backbone.View.extend = ViewConstructor.extend; @@ -966,10 +861,6 @@ var defaultOptions = { // Prefix template/layout paths. prefix: "", - // Use requestAnimationFrame to queue up view rendering and cancel - // repeat requests. Leave on for better performance. - useRAF: true, - // Can be used to supply a different deferred implementation. deferred: function() { return $.Deferred(); @@ -1069,54 +960,7 @@ var defaultOptions = { // A method to determine if a View contains another. contains: function(parent, child) { return $.contains(parent, child); - }, - - // Based on: - // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and - // Tino Zijdel. - requestAnimationFrame: (function() { - var lastTime = 0; - var vendors = ["ms", "moz", "webkit", "o"]; - var requestAnimationFrame = window.requestAnimationFrame; - - for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { - requestAnimationFrame = window[vendors[i] + "RequestAnimationFrame"]; - } - - if (!requestAnimationFrame){ - requestAnimationFrame = function(callback) { - var currTime = new Date().getTime(); - var timeToCall = Math.max(0, 16 - (currTime - lastTime)); - var id = window.setTimeout(function() { - callback(currTime + timeToCall); - }, timeToCall); - lastTime = currTime + timeToCall; - return id; - }; - } - - return _.bind(requestAnimationFrame, window); - })(), - - cancelAnimationFrame: (function() { - var vendors = ["ms", "moz", "webkit", "o"]; - var cancelAnimationFrame = window.cancelAnimationFrame; - - for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { - cancelAnimationFrame = - window[vendors[i] + "CancelAnimationFrame"] || - window[vendors[i] + "CancelRequestAnimationFrame"]; - } - - if (!cancelAnimationFrame) { - cancelAnimationFrame = function(id) { - clearTimeout(id); - }; - } - - return _.bind(cancelAnimationFrame, window); - })() + } }; // Extend LayoutManager with default options.