From 489f486e49e5a17d7c62406e5ada850dcc6ecae7 Mon Sep 17 00:00:00 2001 From: Jovanni Cutigni Date: Sun, 8 May 2016 13:27:57 -0700 Subject: [PATCH 1/3] Copy in https://github.com/patorjk/d3-context-menu --- css/d3-context-menu.css | 78 ++++++++++++++++++++++++++++++++ js/d3-context-menu.js | 99 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 css/d3-context-menu.css create mode 100644 js/d3-context-menu.js diff --git a/css/d3-context-menu.css b/css/d3-context-menu.css new file mode 100644 index 0000000..334513c --- /dev/null +++ b/css/d3-context-menu.css @@ -0,0 +1,78 @@ +.d3-context-menu { + position: absolute; + display: none; + background-color: #f2f2f2; + border-radius: 4px; + + font-family: Arial, sans-serif; + font-size: 14px; + min-width: 150px; + border: 1px solid #d4d4d4; + + z-index:1200; +} + +.d3-context-menu ul { + list-style-type: none; + margin: 4px 0px; + padding: 0px; + cursor: default; +} + +.d3-context-menu ul li { + padding: 4px 16px; + + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Chrome/Safari/Opera */ + -khtml-user-select: none; /* Konqueror */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; +} + +.d3-context-menu ul li:hover { + background-color: #4677f8; + color: #fefefe; +} + +/* + Header +*/ + +.d3-context-menu ul li.is-header, +.d3-context-menu ul li.is-header:hover { + background-color: #f2f2f2; + color: #444; + font-weight: bold; + font-style: italic; +} + +/* + Disabled +*/ + +.d3-context-menu ul li.is-disabled, +.d3-context-menu ul li.is-disabled:hover { + background-color: #f2f2f2; + color: #888; + cursor: not-allowed; +} + +/* + Divider +*/ + +.d3-context-menu ul li.is-divider { + padding: 0px 0px; +} + +.d3-context-menu ul li.is-divider:hover { + background-color: #f2f2f2; +} + +.d3-context-menu ul hr { + border: 0; + height: 0; + border-top: 1px solid rgba(0, 0, 0, 0.1); + border-bottom: 1px solid rgba(255, 255, 255, 0.3); +} \ No newline at end of file diff --git a/js/d3-context-menu.js b/js/d3-context-menu.js new file mode 100644 index 0000000..366b64d --- /dev/null +++ b/js/d3-context-menu.js @@ -0,0 +1,99 @@ +(function(root, factory) { + if (typeof module === 'object' && module.exports) { + module.exports = function(d3) { + d3.contextMenu = factory(d3); + return d3.contextMenu; + }; + } else { + root.d3.contextMenu = factory(root.d3); + } +}( this, + function(d3) { + return function (menu, opts) { + + var openCallback, + closeCallback; + + if (typeof opts === 'function') { + openCallback = opts; + } else { + opts = opts || {}; + openCallback = opts.onOpen; + closeCallback = opts.onClose; + } + + // create the div element that will hold the context menu + d3.selectAll('.d3-context-menu').data([1]) + .enter() + .append('div') + .attr('class', 'd3-context-menu'); + + // close menu + d3.select('body').on('click.d3-context-menu', function() { + d3.select('.d3-context-menu').style('display', 'none'); + if (closeCallback) { + closeCallback(); + } + }); + + // this gets executed when a contextmenu event occurs + return function(data, index) { + var elm = this; + + d3.selectAll('.d3-context-menu').html(''); + var list = d3.selectAll('.d3-context-menu').append('ul'); + list.selectAll('li').data(typeof menu === 'function' ? menu(data) : menu).enter() + .append('li') + .attr('class', function(d) { + var ret = ''; + if (d.divider) { + ret += ' is-divider'; + } + if (d.disabled) { + ret += ' is-disabled'; + } + if (!d.action) { + ret += ' is-header'; + } + return ret; + }) + .html(function(d) { + if (d.divider) { + return '
'; + } + if (!d.title) { + console.error('No title attribute set. Check the spelling of your options.'); + } + return (typeof d.title === 'string') ? d.title : d.title(data); + }) + .on('click', function(d, i) { + if (d.disabled) return; // do nothing if disabled + if (!d.action) return; // headers have no "action" + d.action(elm, data, index); + d3.select('.d3-context-menu').style('display', 'none'); + + if (closeCallback) { + closeCallback(); + } + }); + + // the openCallback allows an action to fire before the menu is displayed + // an example usage would be closing a tooltip + if (openCallback) { + if (openCallback(data, index) === false) { + return; + } + } + + // display context menu + d3.select('.d3-context-menu') + .style('left', (d3.event.pageX - 2) + 'px') + .style('top', (d3.event.pageY - 2) + 'px') + .style('display', 'block'); + + d3.event.preventDefault(); + d3.event.stopPropagation(); + }; + }; + } +)); From 407ef369169d93adc5c673dc302d9e138c68acf8 Mon Sep 17 00:00:00 2001 From: Jovanni Cutigni Date: Sun, 8 May 2016 17:24:08 -0700 Subject: [PATCH 2/3] Add context menu to commit nodes and branch tags --- index.html | 1 + js/historyview.js | 26 +++++++++++++++++++++++++- js/main.js | 7 ++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index f9741ea..a02d0c1 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,7 @@ + diff --git a/js/historyview.js b/js/historyview.js index 683201e..f3ce159 100644 --- a/js/historyview.js +++ b/js/historyview.js @@ -1,4 +1,4 @@ -define(['d3'], function () { +define(['d3', 'd3.contextMenu'], function (d3, contextMenu) { "use strict"; var REG_MARKER_END = 'url(#triangle)', @@ -7,6 +7,7 @@ define(['d3'], function () { preventOverlap, applyBranchlessClass, + openContextMenu, cx, cy, fixCirclePosition, px1, py1, fixPointerStartPosition, px2, py2, fixPointerEndPosition, @@ -61,6 +62,23 @@ define(['d3'], function () { }); } }; + + openContextMenu = function(canCommit, ref, view) { + var menu = []; + if (canCommit) { + menu = menu.concat([ + {title: "Commit", action: function() { view.commit(); }}, + {divider: true} + ]); + } + menu = menu.concat([ + {title: 'Reset', action: function() { view.reset(ref); }}, + {title: 'Checkout', action: function() { view.checkout(ref); }}, + {title: 'Merge', action: function() { view.merge(ref); }}, + {title: 'Rebase', action: function() { view.rebase(ref); }}, + ]); + contextMenu(menu)(); + } cx = function (commit, view) { var parent = view.getCommit(commit.parent), @@ -486,6 +504,9 @@ define(['d3'], function () { .classed('merge-commit', function (d) { return typeof d.parent2 === 'string'; }) + .on('contextmenu', function(d) { + openContextMenu(d3.select(this).classed('checked-out'), d.id, view); + }) .call(fixCirclePosition) .attr('r', 1) .transition("inflate") @@ -708,6 +729,9 @@ define(['d3'], function () { classes += ' head-tag'; } return classes; + }) + .on('contextmenu', function(d) { + openContextMenu(d3.select(this).classed('head-tag'), d.name, view); }); newTags.append('svg:rect') diff --git a/js/main.js b/js/main.js index 40e03d7..ab4ba65 100644 --- a/js/main.js +++ b/js/main.js @@ -45,11 +45,16 @@ if (!Array.prototype.indexOf) { require.config({ paths: { - 'd3': 'https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.min' + 'd3': 'https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.min', + 'd3.contextMenu' : 'd3-context-menu' }, shim: { 'd3': { exports: 'd3' + }, + 'd3.contextMenu': { + deps: ['d3'], + exports: 'd3.contextMenu' } } }); \ No newline at end of file From a1d2037580b67b9c9f00212d8b4500adb5659bea Mon Sep 17 00:00:00 2001 From: Jovanni Cutigni Date: Sun, 8 May 2016 18:26:22 -0700 Subject: [PATCH 3/3] Add context menu to origin --- js/explaingit.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/js/explaingit.js b/js/explaingit.js index 9501ee3..c5de28e 100644 --- a/js/explaingit.js +++ b/js/explaingit.js @@ -1,4 +1,4 @@ -define(['historyview', 'controlbox', 'd3'], function (HistoryView, ControlBox, d3) { +define(['historyview', 'controlbox', 'd3', 'd3.contextMenu'], function (HistoryView, ControlBox, d3, contextMenu) { var prefix = 'ExplainGit', openSandBoxes = [], open, @@ -37,6 +37,16 @@ define(['historyview', 'controlbox', 'd3'], function (HistoryView, ControlBox, d originView: originView, initialMessage: args.initialMessage }); + + if (originView) { + originView.svg.on('contextmenu', function() { + contextMenu([ + {title: 'Fetch', action: function() { controlBox.command('git fetch');}}, + {title: 'Push', action: function() { controlBox.command('git push origin'); }}, + {title: 'Pull', action: function() { controlBox.command('git pull'); }} + ])(); + }) + } controlBox.render(playground); historyView.render(playground);