mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-06-25 23:48:34 +02:00
965 lines
27 KiB
JavaScript
965 lines
27 KiB
JavaScript
(function(){var require = function (file, cwd) {
|
|
var resolved = require.resolve(file, cwd || '/');
|
|
var mod = require.modules[resolved];
|
|
if (!mod) throw new Error(
|
|
'Failed to resolve module ' + file + ', tried ' + resolved
|
|
);
|
|
var cached = require.cache[resolved];
|
|
var res = cached? cached.exports : mod();
|
|
return res;
|
|
};
|
|
|
|
require.paths = [];
|
|
require.modules = {};
|
|
require.cache = {};
|
|
require.extensions = [".js",".coffee",".json"];
|
|
|
|
require._core = {
|
|
'assert': true,
|
|
'events': true,
|
|
'fs': true,
|
|
'path': true,
|
|
'vm': true
|
|
};
|
|
|
|
require.resolve = (function () {
|
|
return function (x, cwd) {
|
|
if (!cwd) cwd = '/';
|
|
|
|
if (require._core[x]) return x;
|
|
var path = require.modules.path();
|
|
cwd = path.resolve('/', cwd);
|
|
var y = cwd || '/';
|
|
|
|
if (x.match(/^(?:\.\.?\/|\/)/)) {
|
|
var m = loadAsFileSync(path.resolve(y, x))
|
|
|| loadAsDirectorySync(path.resolve(y, x));
|
|
if (m) return m;
|
|
}
|
|
|
|
var n = loadNodeModulesSync(x, y);
|
|
if (n) return n;
|
|
|
|
throw new Error("Cannot find module '" + x + "'");
|
|
|
|
function loadAsFileSync (x) {
|
|
x = path.normalize(x);
|
|
if (require.modules[x]) {
|
|
return x;
|
|
}
|
|
|
|
for (var i = 0; i < require.extensions.length; i++) {
|
|
var ext = require.extensions[i];
|
|
if (require.modules[x + ext]) return x + ext;
|
|
}
|
|
}
|
|
|
|
function loadAsDirectorySync (x) {
|
|
x = x.replace(/\/+$/, '');
|
|
var pkgfile = path.normalize(x + '/package.json');
|
|
if (require.modules[pkgfile]) {
|
|
var pkg = require.modules[pkgfile]();
|
|
var b = pkg.browserify;
|
|
if (typeof b === 'object' && b.main) {
|
|
var m = loadAsFileSync(path.resolve(x, b.main));
|
|
if (m) return m;
|
|
}
|
|
else if (typeof b === 'string') {
|
|
var m = loadAsFileSync(path.resolve(x, b));
|
|
if (m) return m;
|
|
}
|
|
else if (pkg.main) {
|
|
var m = loadAsFileSync(path.resolve(x, pkg.main));
|
|
if (m) return m;
|
|
}
|
|
}
|
|
|
|
return loadAsFileSync(x + '/index');
|
|
}
|
|
|
|
function loadNodeModulesSync (x, start) {
|
|
var dirs = nodeModulesPathsSync(start);
|
|
for (var i = 0; i < dirs.length; i++) {
|
|
var dir = dirs[i];
|
|
var m = loadAsFileSync(dir + '/' + x);
|
|
if (m) return m;
|
|
var n = loadAsDirectorySync(dir + '/' + x);
|
|
if (n) return n;
|
|
}
|
|
|
|
var m = loadAsFileSync(x);
|
|
if (m) return m;
|
|
}
|
|
|
|
function nodeModulesPathsSync (start) {
|
|
var parts;
|
|
if (start === '/') parts = [ '' ];
|
|
else parts = path.normalize(start).split('/');
|
|
|
|
var dirs = [];
|
|
for (var i = parts.length - 1; i >= 0; i--) {
|
|
if (parts[i] === 'node_modules') continue;
|
|
var dir = parts.slice(0, i + 1).join('/') + '/node_modules';
|
|
dirs.push(dir);
|
|
}
|
|
|
|
return dirs;
|
|
}
|
|
};
|
|
})();
|
|
|
|
require.alias = function (from, to) {
|
|
var path = require.modules.path();
|
|
var res = null;
|
|
try {
|
|
res = require.resolve(from + '/package.json', '/');
|
|
}
|
|
catch (err) {
|
|
res = require.resolve(from, '/');
|
|
}
|
|
var basedir = path.dirname(res);
|
|
|
|
var keys = (Object.keys || function (obj) {
|
|
var res = [];
|
|
for (var key in obj) res.push(key);
|
|
return res;
|
|
})(require.modules);
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var key = keys[i];
|
|
if (key.slice(0, basedir.length + 1) === basedir + '/') {
|
|
var f = key.slice(basedir.length);
|
|
require.modules[to + f] = require.modules[basedir + f];
|
|
}
|
|
else if (key === basedir) {
|
|
require.modules[to] = require.modules[basedir];
|
|
}
|
|
}
|
|
};
|
|
|
|
(function () {
|
|
var process = {};
|
|
var global = typeof window !== 'undefined' ? window : {};
|
|
var definedProcess = false;
|
|
|
|
require.define = function (filename, fn) {
|
|
if (!definedProcess && require.modules.__browserify_process) {
|
|
process = require.modules.__browserify_process();
|
|
definedProcess = true;
|
|
}
|
|
|
|
var dirname = require._core[filename]
|
|
? ''
|
|
: require.modules.path().dirname(filename)
|
|
;
|
|
|
|
var require_ = function (file) {
|
|
var requiredModule = require(file, dirname);
|
|
var cached = require.cache[require.resolve(file, dirname)];
|
|
|
|
if (cached && cached.parent === null) {
|
|
cached.parent = module_;
|
|
}
|
|
|
|
return requiredModule;
|
|
};
|
|
require_.resolve = function (name) {
|
|
return require.resolve(name, dirname);
|
|
};
|
|
require_.modules = require.modules;
|
|
require_.define = require.define;
|
|
require_.cache = require.cache;
|
|
var module_ = {
|
|
id : filename,
|
|
filename: filename,
|
|
exports : {},
|
|
loaded : false,
|
|
parent: null
|
|
};
|
|
|
|
require.modules[filename] = function () {
|
|
require.cache[filename] = module_;
|
|
fn.call(
|
|
module_.exports,
|
|
require_,
|
|
module_,
|
|
module_.exports,
|
|
dirname,
|
|
filename,
|
|
process,
|
|
global
|
|
);
|
|
module_.loaded = true;
|
|
return module_.exports;
|
|
};
|
|
};
|
|
})();
|
|
|
|
|
|
require.define("path",function(require,module,exports,__dirname,__filename,process,global){function filter (xs, fn) {
|
|
var res = [];
|
|
for (var i = 0; i < xs.length; i++) {
|
|
if (fn(xs[i], i, xs)) res.push(xs[i]);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
// resolves . and .. elements in a path array with directory names there
|
|
// must be no slashes, empty elements, or device names (c:\) in the array
|
|
// (so also no leading and trailing slashes - it does not distinguish
|
|
// relative and absolute paths)
|
|
function normalizeArray(parts, allowAboveRoot) {
|
|
// if the path tries to go above the root, `up` ends up > 0
|
|
var up = 0;
|
|
for (var i = parts.length; i >= 0; i--) {
|
|
var last = parts[i];
|
|
if (last == '.') {
|
|
parts.splice(i, 1);
|
|
} else if (last === '..') {
|
|
parts.splice(i, 1);
|
|
up++;
|
|
} else if (up) {
|
|
parts.splice(i, 1);
|
|
up--;
|
|
}
|
|
}
|
|
|
|
// if the path is allowed to go above the root, restore leading ..s
|
|
if (allowAboveRoot) {
|
|
for (; up--; up) {
|
|
parts.unshift('..');
|
|
}
|
|
}
|
|
|
|
return parts;
|
|
}
|
|
|
|
// Regex to split a filename into [*, dir, basename, ext]
|
|
// posix version
|
|
var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
|
|
|
|
// path.resolve([from ...], to)
|
|
// posix version
|
|
exports.resolve = function() {
|
|
var resolvedPath = '',
|
|
resolvedAbsolute = false;
|
|
|
|
for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
|
|
var path = (i >= 0)
|
|
? arguments[i]
|
|
: process.cwd();
|
|
|
|
// Skip empty and invalid entries
|
|
if (typeof path !== 'string' || !path) {
|
|
continue;
|
|
}
|
|
|
|
resolvedPath = path + '/' + resolvedPath;
|
|
resolvedAbsolute = path.charAt(0) === '/';
|
|
}
|
|
|
|
// At this point the path should be resolved to a full absolute path, but
|
|
// handle relative paths to be safe (might happen when process.cwd() fails)
|
|
|
|
// Normalize the path
|
|
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
|
|
return !!p;
|
|
}), !resolvedAbsolute).join('/');
|
|
|
|
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
|
|
};
|
|
|
|
// path.normalize(path)
|
|
// posix version
|
|
exports.normalize = function(path) {
|
|
var isAbsolute = path.charAt(0) === '/',
|
|
trailingSlash = path.slice(-1) === '/';
|
|
|
|
// Normalize the path
|
|
path = normalizeArray(filter(path.split('/'), function(p) {
|
|
return !!p;
|
|
}), !isAbsolute).join('/');
|
|
|
|
if (!path && !isAbsolute) {
|
|
path = '.';
|
|
}
|
|
if (path && trailingSlash) {
|
|
path += '/';
|
|
}
|
|
|
|
return (isAbsolute ? '/' : '') + path;
|
|
};
|
|
|
|
|
|
// posix version
|
|
exports.join = function() {
|
|
var paths = Array.prototype.slice.call(arguments, 0);
|
|
return exports.normalize(filter(paths, function(p, index) {
|
|
return p && typeof p === 'string';
|
|
}).join('/'));
|
|
};
|
|
|
|
|
|
exports.dirname = function(path) {
|
|
var dir = splitPathRe.exec(path)[1] || '';
|
|
var isWindows = false;
|
|
if (!dir) {
|
|
// No dirname
|
|
return '.';
|
|
} else if (dir.length === 1 ||
|
|
(isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
|
|
// It is just a slash or a drive letter with a slash
|
|
return dir;
|
|
} else {
|
|
// It is a full dirname, strip trailing slash
|
|
return dir.substring(0, dir.length - 1);
|
|
}
|
|
};
|
|
|
|
|
|
exports.basename = function(path, ext) {
|
|
var f = splitPathRe.exec(path)[2] || '';
|
|
// TODO: make this comparison case-insensitive on windows?
|
|
if (ext && f.substr(-1 * ext.length) === ext) {
|
|
f = f.substr(0, f.length - ext.length);
|
|
}
|
|
return f;
|
|
};
|
|
|
|
|
|
exports.extname = function(path) {
|
|
return splitPathRe.exec(path)[3] || '';
|
|
};
|
|
|
|
});
|
|
|
|
require.define("__browserify_process",function(require,module,exports,__dirname,__filename,process,global){var process = module.exports = {};
|
|
|
|
process.nextTick = (function () {
|
|
var canSetImmediate = typeof window !== 'undefined'
|
|
&& window.setImmediate;
|
|
var canPost = typeof window !== 'undefined'
|
|
&& window.postMessage && window.addEventListener
|
|
;
|
|
|
|
if (canSetImmediate) {
|
|
return function (f) { return window.setImmediate(f) };
|
|
}
|
|
|
|
if (canPost) {
|
|
var queue = [];
|
|
window.addEventListener('message', function (ev) {
|
|
if (ev.source === window && ev.data === 'browserify-tick') {
|
|
ev.stopPropagation();
|
|
if (queue.length > 0) {
|
|
var fn = queue.shift();
|
|
fn();
|
|
}
|
|
}
|
|
}, true);
|
|
|
|
return function nextTick(fn) {
|
|
queue.push(fn);
|
|
window.postMessage('browserify-tick', '*');
|
|
};
|
|
}
|
|
|
|
return function nextTick(fn) {
|
|
setTimeout(fn, 0);
|
|
};
|
|
})();
|
|
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
|
|
process.binding = function (name) {
|
|
if (name === 'evals') return (require)('vm')
|
|
else throw new Error('No such module. (Possibly not yet loaded)')
|
|
};
|
|
|
|
(function () {
|
|
var cwd = '/';
|
|
var path;
|
|
process.cwd = function () { return cwd };
|
|
process.chdir = function (dir) {
|
|
if (!path) path = require('path');
|
|
cwd = path.resolve(dir, cwd);
|
|
};
|
|
})();
|
|
|
|
});
|
|
|
|
require.define("/animationFactory.js",function(require,module,exports,__dirname,__filename,process,global){/******************
|
|
* This class is responsible for a lot of the heavy lifting around creating an animation at a certain state in time.
|
|
* The tricky thing is that when a new commit has to be "born," say in the middle of a rebase
|
|
* or something, it must animate out from the parent position to it's birth position.
|
|
|
|
* These two positions though may not be where the commit finally ends up. So we actually need to take a snapshot of the tree,
|
|
* store all those positions, take a snapshot of the tree after a layout refresh afterwards, and then animate between those two spots.
|
|
* and then essentially animate the entire tree too.
|
|
*/
|
|
|
|
// essentially a static class
|
|
function AnimationFactory() {
|
|
|
|
}
|
|
|
|
AnimationFactory.prototype.genCommitBirthAnimation = function(animationQueue, commit, gitVisuals) {
|
|
if (!animationQueue) {
|
|
throw new Error("Need animation queue to add closure to!");
|
|
}
|
|
|
|
var time = GRAPHICS.defaultAnimationTime * 1.0;
|
|
var bounceTime = time * 2;
|
|
|
|
// essentially refresh the entire tree, but do a special thing for the commit
|
|
var visNode = commit.get('visNode');
|
|
|
|
var animation = function() {
|
|
// this takes care of refs and all that jazz, and updates all the positions
|
|
gitVisuals.refreshTree(time);
|
|
|
|
visNode.setBirth();
|
|
visNode.parentInFront();
|
|
gitVisuals.visBranchesFront();
|
|
|
|
visNode.animateUpdatedPosition(bounceTime, 'bounce');
|
|
visNode.animateOutgoingEdges(time);
|
|
};
|
|
|
|
animationQueue.add(new Animation({
|
|
closure: animation,
|
|
duration: Math.max(time, bounceTime)
|
|
}));
|
|
};
|
|
|
|
AnimationFactory.prototype.overrideOpacityDepth2 = function(attr, opacity) {
|
|
opacity = (opacity === undefined) ? 1 : opacity;
|
|
|
|
var newAttr = {};
|
|
|
|
_.each(attr, function(partObj, partName) {
|
|
newAttr[partName] = {};
|
|
_.each(partObj, function(val, key) {
|
|
if (key == 'opacity') {
|
|
newAttr[partName][key] = opacity;
|
|
} else {
|
|
newAttr[partName][key] = val;
|
|
}
|
|
});
|
|
});
|
|
return newAttr;
|
|
};
|
|
|
|
AnimationFactory.prototype.overrideOpacityDepth3 = function(snapShot, opacity) {
|
|
var newSnap = {};
|
|
|
|
_.each(snapShot, function(visObj, visID) {
|
|
newSnap[visID] = this.overrideOpacityDepth2(visObj, opacity);
|
|
}, this);
|
|
return newSnap;
|
|
};
|
|
|
|
AnimationFactory.prototype.genCommitBirthClosureFromSnapshot = function(step, gitVisuals) {
|
|
var time = GRAPHICS.defaultAnimationTime * 1.0;
|
|
var bounceTime = time * 1.5;
|
|
|
|
var visNode = step.newCommit.get('visNode');
|
|
var afterAttrWithOpacity = this.overrideOpacityDepth2(step.afterSnapshot[visNode.getID()]);
|
|
var afterSnapWithOpacity = this.overrideOpacityDepth3(step.afterSnapshot);
|
|
|
|
var animation = function() {
|
|
visNode.setBirthFromSnapshot(step.beforeSnapshot);
|
|
visNode.parentInFront();
|
|
gitVisuals.visBranchesFront();
|
|
|
|
visNode.animateToAttr(afterAttrWithOpacity, bounceTime, 'bounce');
|
|
visNode.animateOutgoingEdgesToAttr(afterSnapWithOpacity, bounceTime);
|
|
};
|
|
|
|
return animation;
|
|
};
|
|
|
|
AnimationFactory.prototype.refreshTree = function(animationQueue, gitVisuals) {
|
|
animationQueue.add(new Animation({
|
|
closure: function() {
|
|
gitVisuals.refreshTree();
|
|
}
|
|
}));
|
|
};
|
|
|
|
AnimationFactory.prototype.rebaseAnimation = function(animationQueue, rebaseResponse,
|
|
gitEngine, gitVisuals) {
|
|
|
|
this.rebaseHighlightPart(animationQueue, rebaseResponse, gitEngine);
|
|
this.rebaseBirthPart(animationQueue, rebaseResponse, gitEngine, gitVisuals);
|
|
};
|
|
|
|
AnimationFactory.prototype.rebaseHighlightPart = function(animationQueue, rebaseResponse, gitEngine) {
|
|
var fullTime = GRAPHICS.defaultAnimationTime * 0.66;
|
|
var slowTime = fullTime * 2.0;
|
|
|
|
// we want to highlight all the old commits
|
|
var oldCommits = rebaseResponse.toRebaseArray;
|
|
// we are either highlighting to a visBranch or a visNode
|
|
var visBranch = rebaseResponse.destinationBranch.get('visBranch');
|
|
if (!visBranch) {
|
|
// in the case where we rebase onto a commit
|
|
visBranch = rebaseResponse.destinationBranch.get('visNode');
|
|
}
|
|
|
|
_.each(oldCommits, function(oldCommit) {
|
|
var visNode = oldCommit.get('visNode');
|
|
animationQueue.add(new Animation({
|
|
closure: function() {
|
|
visNode.highlightTo(visBranch, slowTime, 'easeInOut');
|
|
},
|
|
duration: fullTime * 1.5
|
|
}));
|
|
|
|
}, this);
|
|
|
|
this.delay(animationQueue, fullTime * 2);
|
|
};
|
|
|
|
AnimationFactory.prototype.rebaseBirthPart = function(animationQueue, rebaseResponse,
|
|
gitEngine, gitVisuals) {
|
|
var rebaseSteps = rebaseResponse.rebaseSteps;
|
|
|
|
var newVisNodes = [];
|
|
_.each(rebaseSteps, function(step) {
|
|
var visNode = step.newCommit.get('visNode');
|
|
|
|
newVisNodes.push(visNode);
|
|
visNode.setOpacity(0);
|
|
visNode.setOutgoingEdgesOpacity(0);
|
|
}, this);
|
|
|
|
var previousVisNodes = [];
|
|
_.each(rebaseSteps, function(rebaseStep, index) {
|
|
var toOmit = newVisNodes.slice(index + 1);
|
|
|
|
var snapshotPart = this.genFromToSnapshotAnimation(
|
|
rebaseStep.beforeSnapshot,
|
|
rebaseStep.afterSnapshot,
|
|
toOmit,
|
|
previousVisNodes,
|
|
gitVisuals
|
|
);
|
|
var birthPart = this.genCommitBirthClosureFromSnapshot(rebaseStep, gitVisuals);
|
|
|
|
var animation = function() {
|
|
snapshotPart();
|
|
birthPart();
|
|
};
|
|
|
|
animationQueue.add(new Animation({
|
|
closure: animation,
|
|
duration: GRAPHICS.defaultAnimationTime * 1.5
|
|
}));
|
|
|
|
previousVisNodes.push(rebaseStep.newCommit.get('visNode'));
|
|
}, this);
|
|
|
|
// need to delay to let bouncing finish
|
|
this.delay(animationQueue);
|
|
|
|
this.refreshTree(animationQueue, gitVisuals);
|
|
};
|
|
|
|
AnimationFactory.prototype.delay = function(animationQueue, time) {
|
|
time = time || GRAPHICS.defaultAnimationTime;
|
|
animationQueue.add(new Animation({
|
|
closure: function() { },
|
|
duration: time
|
|
}));
|
|
};
|
|
|
|
AnimationFactory.prototype.genSetAllCommitOpacities = function(visNodes, opacity) {
|
|
// need to slice for closure
|
|
var nodesToAnimate = visNodes.slice(0);
|
|
|
|
return function() {
|
|
_.each(nodesToAnimate, function(visNode) {
|
|
visNode.setOpacity(opacity);
|
|
visNode.setOutgoingEdgesOpacity(opacity);
|
|
});
|
|
};
|
|
};
|
|
|
|
AnimationFactory.prototype.stripObjectsFromSnapshot = function(snapShot, toOmit) {
|
|
var ids = [];
|
|
_.each(toOmit, function(obj) {
|
|
ids.push(obj.getID());
|
|
});
|
|
|
|
var newSnapshot = {};
|
|
_.each(snapShot, function(val, key) {
|
|
if (_.include(ids, key)) {
|
|
// omit
|
|
return;
|
|
}
|
|
newSnapshot[key] = val;
|
|
}, this);
|
|
return newSnapshot;
|
|
};
|
|
|
|
AnimationFactory.prototype.genFromToSnapshotAnimation = function(
|
|
beforeSnapshot,
|
|
afterSnapshot,
|
|
commitsToOmit,
|
|
commitsToFixOpacity,
|
|
gitVisuals) {
|
|
|
|
// we want to omit the commit outgoing edges
|
|
var toOmit = [];
|
|
_.each(commitsToOmit, function(visNode) {
|
|
toOmit.push(visNode);
|
|
toOmit = toOmit.concat(visNode.get('outgoingEdges'));
|
|
});
|
|
|
|
var fixOpacity = function(obj) {
|
|
if (!obj) { return; }
|
|
_.each(obj, function(attr, partName) {
|
|
obj[partName].opacity = 1;
|
|
});
|
|
};
|
|
|
|
// HORRIBLE loop to fix opacities all throughout the snapshot
|
|
_.each([beforeSnapshot, afterSnapshot], function(snapShot) {
|
|
_.each(commitsToFixOpacity, function(visNode) {
|
|
fixOpacity(snapShot[visNode.getID()]);
|
|
_.each(visNode.get('outgoingEdges'), function(visEdge) {
|
|
fixOpacity(snapShot[visEdge.getID()]);
|
|
});
|
|
});
|
|
});
|
|
|
|
return function() {
|
|
gitVisuals.animateAllFromAttrToAttr(beforeSnapshot, afterSnapshot, toOmit);
|
|
};
|
|
};
|
|
|
|
exports.AnimationFactory = AnimationFactory;
|
|
|
|
|
|
|
|
});
|
|
|
|
require.define("/main.js",function(require,module,exports,__dirname,__filename,process,global){var AnimationFactory = require('./animationFactory').AnimationFactory;
|
|
|
|
/**
|
|
* Globals
|
|
*/
|
|
var events = _.clone(Backbone.Events);
|
|
var ui = null;
|
|
var animationFactory = null;
|
|
|
|
/**
|
|
* Static Classes
|
|
*/
|
|
animationFactory = new AnimationFactory();
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
$(document).ready(function(){
|
|
ui = new UI();
|
|
mainVis = new Visualization({
|
|
el: $('#canvasWrapper')[0]
|
|
});
|
|
|
|
if (/\?demo/.test(window.location.href)) {
|
|
setTimeout(function() {
|
|
events.trigger('submitCommandValueFromEvent', "gc; git checkout HEAD~1; git commit; git checkout -b bugFix; gc; gc; git rebase master; git checkout master; gc; gc; git merge bugFix");
|
|
}, 500);
|
|
}
|
|
});
|
|
|
|
function UI() {
|
|
// static classes
|
|
this.commandCollection = new CommandCollection();
|
|
|
|
this.commandBuffer = new CommandBuffer({
|
|
collection: this.commandCollection
|
|
});
|
|
|
|
this.commandPromptView = new CommandPromptView({
|
|
el: $('#commandLineBar'),
|
|
collection: this.commandCollection
|
|
});
|
|
this.commandLineHistoryView = new CommandLineHistoryView({
|
|
el: $('#commandLineHistory'),
|
|
collection: this.commandCollection
|
|
});
|
|
|
|
$('#commandTextField').focus();
|
|
}
|
|
|
|
exports.events = events;
|
|
exports.ui = ui;
|
|
exports.animationFactory = animationFactory;
|
|
|
|
|
|
});
|
|
require("/main.js");
|
|
|
|
require.define("/animationFactory.js",function(require,module,exports,__dirname,__filename,process,global){/******************
|
|
* This class is responsible for a lot of the heavy lifting around creating an animation at a certain state in time.
|
|
* The tricky thing is that when a new commit has to be "born," say in the middle of a rebase
|
|
* or something, it must animate out from the parent position to it's birth position.
|
|
|
|
* These two positions though may not be where the commit finally ends up. So we actually need to take a snapshot of the tree,
|
|
* store all those positions, take a snapshot of the tree after a layout refresh afterwards, and then animate between those two spots.
|
|
* and then essentially animate the entire tree too.
|
|
*/
|
|
|
|
// essentially a static class
|
|
function AnimationFactory() {
|
|
|
|
}
|
|
|
|
AnimationFactory.prototype.genCommitBirthAnimation = function(animationQueue, commit, gitVisuals) {
|
|
if (!animationQueue) {
|
|
throw new Error("Need animation queue to add closure to!");
|
|
}
|
|
|
|
var time = GRAPHICS.defaultAnimationTime * 1.0;
|
|
var bounceTime = time * 2;
|
|
|
|
// essentially refresh the entire tree, but do a special thing for the commit
|
|
var visNode = commit.get('visNode');
|
|
|
|
var animation = function() {
|
|
// this takes care of refs and all that jazz, and updates all the positions
|
|
gitVisuals.refreshTree(time);
|
|
|
|
visNode.setBirth();
|
|
visNode.parentInFront();
|
|
gitVisuals.visBranchesFront();
|
|
|
|
visNode.animateUpdatedPosition(bounceTime, 'bounce');
|
|
visNode.animateOutgoingEdges(time);
|
|
};
|
|
|
|
animationQueue.add(new Animation({
|
|
closure: animation,
|
|
duration: Math.max(time, bounceTime)
|
|
}));
|
|
};
|
|
|
|
AnimationFactory.prototype.overrideOpacityDepth2 = function(attr, opacity) {
|
|
opacity = (opacity === undefined) ? 1 : opacity;
|
|
|
|
var newAttr = {};
|
|
|
|
_.each(attr, function(partObj, partName) {
|
|
newAttr[partName] = {};
|
|
_.each(partObj, function(val, key) {
|
|
if (key == 'opacity') {
|
|
newAttr[partName][key] = opacity;
|
|
} else {
|
|
newAttr[partName][key] = val;
|
|
}
|
|
});
|
|
});
|
|
return newAttr;
|
|
};
|
|
|
|
AnimationFactory.prototype.overrideOpacityDepth3 = function(snapShot, opacity) {
|
|
var newSnap = {};
|
|
|
|
_.each(snapShot, function(visObj, visID) {
|
|
newSnap[visID] = this.overrideOpacityDepth2(visObj, opacity);
|
|
}, this);
|
|
return newSnap;
|
|
};
|
|
|
|
AnimationFactory.prototype.genCommitBirthClosureFromSnapshot = function(step, gitVisuals) {
|
|
var time = GRAPHICS.defaultAnimationTime * 1.0;
|
|
var bounceTime = time * 1.5;
|
|
|
|
var visNode = step.newCommit.get('visNode');
|
|
var afterAttrWithOpacity = this.overrideOpacityDepth2(step.afterSnapshot[visNode.getID()]);
|
|
var afterSnapWithOpacity = this.overrideOpacityDepth3(step.afterSnapshot);
|
|
|
|
var animation = function() {
|
|
visNode.setBirthFromSnapshot(step.beforeSnapshot);
|
|
visNode.parentInFront();
|
|
gitVisuals.visBranchesFront();
|
|
|
|
visNode.animateToAttr(afterAttrWithOpacity, bounceTime, 'bounce');
|
|
visNode.animateOutgoingEdgesToAttr(afterSnapWithOpacity, bounceTime);
|
|
};
|
|
|
|
return animation;
|
|
};
|
|
|
|
AnimationFactory.prototype.refreshTree = function(animationQueue, gitVisuals) {
|
|
animationQueue.add(new Animation({
|
|
closure: function() {
|
|
gitVisuals.refreshTree();
|
|
}
|
|
}));
|
|
};
|
|
|
|
AnimationFactory.prototype.rebaseAnimation = function(animationQueue, rebaseResponse,
|
|
gitEngine, gitVisuals) {
|
|
|
|
this.rebaseHighlightPart(animationQueue, rebaseResponse, gitEngine);
|
|
this.rebaseBirthPart(animationQueue, rebaseResponse, gitEngine, gitVisuals);
|
|
};
|
|
|
|
AnimationFactory.prototype.rebaseHighlightPart = function(animationQueue, rebaseResponse, gitEngine) {
|
|
var fullTime = GRAPHICS.defaultAnimationTime * 0.66;
|
|
var slowTime = fullTime * 2.0;
|
|
|
|
// we want to highlight all the old commits
|
|
var oldCommits = rebaseResponse.toRebaseArray;
|
|
// we are either highlighting to a visBranch or a visNode
|
|
var visBranch = rebaseResponse.destinationBranch.get('visBranch');
|
|
if (!visBranch) {
|
|
// in the case where we rebase onto a commit
|
|
visBranch = rebaseResponse.destinationBranch.get('visNode');
|
|
}
|
|
|
|
_.each(oldCommits, function(oldCommit) {
|
|
var visNode = oldCommit.get('visNode');
|
|
animationQueue.add(new Animation({
|
|
closure: function() {
|
|
visNode.highlightTo(visBranch, slowTime, 'easeInOut');
|
|
},
|
|
duration: fullTime * 1.5
|
|
}));
|
|
|
|
}, this);
|
|
|
|
this.delay(animationQueue, fullTime * 2);
|
|
};
|
|
|
|
AnimationFactory.prototype.rebaseBirthPart = function(animationQueue, rebaseResponse,
|
|
gitEngine, gitVisuals) {
|
|
var rebaseSteps = rebaseResponse.rebaseSteps;
|
|
|
|
var newVisNodes = [];
|
|
_.each(rebaseSteps, function(step) {
|
|
var visNode = step.newCommit.get('visNode');
|
|
|
|
newVisNodes.push(visNode);
|
|
visNode.setOpacity(0);
|
|
visNode.setOutgoingEdgesOpacity(0);
|
|
}, this);
|
|
|
|
var previousVisNodes = [];
|
|
_.each(rebaseSteps, function(rebaseStep, index) {
|
|
var toOmit = newVisNodes.slice(index + 1);
|
|
|
|
var snapshotPart = this.genFromToSnapshotAnimation(
|
|
rebaseStep.beforeSnapshot,
|
|
rebaseStep.afterSnapshot,
|
|
toOmit,
|
|
previousVisNodes,
|
|
gitVisuals
|
|
);
|
|
var birthPart = this.genCommitBirthClosureFromSnapshot(rebaseStep, gitVisuals);
|
|
|
|
var animation = function() {
|
|
snapshotPart();
|
|
birthPart();
|
|
};
|
|
|
|
animationQueue.add(new Animation({
|
|
closure: animation,
|
|
duration: GRAPHICS.defaultAnimationTime * 1.5
|
|
}));
|
|
|
|
previousVisNodes.push(rebaseStep.newCommit.get('visNode'));
|
|
}, this);
|
|
|
|
// need to delay to let bouncing finish
|
|
this.delay(animationQueue);
|
|
|
|
this.refreshTree(animationQueue, gitVisuals);
|
|
};
|
|
|
|
AnimationFactory.prototype.delay = function(animationQueue, time) {
|
|
time = time || GRAPHICS.defaultAnimationTime;
|
|
animationQueue.add(new Animation({
|
|
closure: function() { },
|
|
duration: time
|
|
}));
|
|
};
|
|
|
|
AnimationFactory.prototype.genSetAllCommitOpacities = function(visNodes, opacity) {
|
|
// need to slice for closure
|
|
var nodesToAnimate = visNodes.slice(0);
|
|
|
|
return function() {
|
|
_.each(nodesToAnimate, function(visNode) {
|
|
visNode.setOpacity(opacity);
|
|
visNode.setOutgoingEdgesOpacity(opacity);
|
|
});
|
|
};
|
|
};
|
|
|
|
AnimationFactory.prototype.stripObjectsFromSnapshot = function(snapShot, toOmit) {
|
|
var ids = [];
|
|
_.each(toOmit, function(obj) {
|
|
ids.push(obj.getID());
|
|
});
|
|
|
|
var newSnapshot = {};
|
|
_.each(snapShot, function(val, key) {
|
|
if (_.include(ids, key)) {
|
|
// omit
|
|
return;
|
|
}
|
|
newSnapshot[key] = val;
|
|
}, this);
|
|
return newSnapshot;
|
|
};
|
|
|
|
AnimationFactory.prototype.genFromToSnapshotAnimation = function(
|
|
beforeSnapshot,
|
|
afterSnapshot,
|
|
commitsToOmit,
|
|
commitsToFixOpacity,
|
|
gitVisuals) {
|
|
|
|
// we want to omit the commit outgoing edges
|
|
var toOmit = [];
|
|
_.each(commitsToOmit, function(visNode) {
|
|
toOmit.push(visNode);
|
|
toOmit = toOmit.concat(visNode.get('outgoingEdges'));
|
|
});
|
|
|
|
var fixOpacity = function(obj) {
|
|
if (!obj) { return; }
|
|
_.each(obj, function(attr, partName) {
|
|
obj[partName].opacity = 1;
|
|
});
|
|
};
|
|
|
|
// HORRIBLE loop to fix opacities all throughout the snapshot
|
|
_.each([beforeSnapshot, afterSnapshot], function(snapShot) {
|
|
_.each(commitsToFixOpacity, function(visNode) {
|
|
fixOpacity(snapShot[visNode.getID()]);
|
|
_.each(visNode.get('outgoingEdges'), function(visEdge) {
|
|
fixOpacity(snapShot[visEdge.getID()]);
|
|
});
|
|
});
|
|
});
|
|
|
|
return function() {
|
|
gitVisuals.animateAllFromAttrToAttr(beforeSnapshot, afterSnapshot, toOmit);
|
|
};
|
|
};
|
|
|
|
exports.AnimationFactory = AnimationFactory;
|
|
|
|
|
|
|
|
});
|
|
require("/animationFactory.js");
|
|
})();
|