Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions css/d3-context-menu.css
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/1140/2.0/1140.css">
<link rel="stylesheet" href="css/explaingit.css">
<link rel="stylesheet" href="css/d3-context-menu.css">
</head>
<body>
<a href="https://github.com/onlywei/explain-git-with-d3" id="fork-me">
Expand Down
99 changes: 99 additions & 0 deletions js/d3-context-menu.js
Original file line number Diff line number Diff line change
@@ -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 '<hr>';
}
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();
};
};
}
));
12 changes: 11 additions & 1 deletion js/explaingit.js
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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);
Expand Down
26 changes: 25 additions & 1 deletion js/historyview.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
define(['d3'], function () {
define(['d3', 'd3.contextMenu'], function (d3, contextMenu) {
"use strict";

var REG_MARKER_END = 'url(#triangle)',
Expand All @@ -7,6 +7,7 @@ define(['d3'], function () {

preventOverlap,
applyBranchlessClass,
openContextMenu,
cx, cy, fixCirclePosition,
px1, py1, fixPointerStartPosition,
px2, py2, fixPointerEndPosition,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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')
Expand Down
7 changes: 6 additions & 1 deletion js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
}
});