diff --git a/build/bundle.js b/build/bundle.js new file mode 100644 index 00000000..443b9be3 --- /dev/null +++ b/build/bundle.js @@ -0,0 +1,965 @@ +(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"); +})(); diff --git a/src/animationFactory.js b/src/animationFactory.js index d420a2b0..bc6156c1 100644 --- a/src/animationFactory.js +++ b/src/animationFactory.js @@ -249,3 +249,6 @@ AnimationFactory.prototype.genFromToSnapshotAnimation = function( }; }; +exports.AnimationFactory = AnimationFactory; + + diff --git a/src/index.html b/src/index.html index 13bf2313..fb67e28a 100644 --- a/src/index.html +++ b/src/index.html @@ -145,12 +145,18 @@ - + - + + + + + diff --git a/src/main.js b/src/main.js index f6b1fb4b..0f22ab9f 100644 --- a/src/main.js +++ b/src/main.js @@ -1,14 +1,16 @@ +var AnimationFactory = require('./animationFactory').AnimationFactory; + /** * Globals */ var events = _.clone(Backbone.Events); - var ui = null; +var animationFactory = null; /** * Static Classes */ -var animationFactory = new AnimationFactory(); +animationFactory = new AnimationFactory(); /////////////////////////////////////////////////////////////////////// @@ -45,3 +47,7 @@ function UI() { $('#commandTextField').focus(); } +exports.events = events; +exports.ui = ui; +exports.animationFactory = animationFactory; +