Summary: See PHI185. When looking at a revision, you can Command-Click (Mac) symbols to jump to their definitions (provided the symbol index has been built). Currently, the code works on any node inside the changeset list, so it activates when clicking links inside inline comments and opening them in a new window. To avoid this, don't activate if we're inside an inline comment. This technically prevents you from doing a symbol lookup on a symbol inside a codeblock inside an inline, but that seems fine/reasonable. Test Plan: Wrote `Dxxx` in an inline, command-clicked it. Before: got a symbol lookup. After: just a new tab with the revision. Reviewers: amckinley Reviewed By: amckinley Differential Revision: https://secure.phabricator.com/D18753
160 lines
4.0 KiB
JavaScript
160 lines
4.0 KiB
JavaScript
/**
|
|
* @provides javelin-behavior-repository-crossreference
|
|
* @requires javelin-behavior
|
|
* javelin-dom
|
|
* javelin-stratcom
|
|
* javelin-uri
|
|
*/
|
|
|
|
JX.behavior('repository-crossreference', function(config, statics) {
|
|
|
|
var highlighted;
|
|
var linked = [];
|
|
|
|
var isMac = navigator.platform.indexOf('Mac') > -1;
|
|
var signalKey = isMac ? 91 /*COMMAND*/ : 17 /*CTRL*/;
|
|
function isSignalkey(event) {
|
|
return isMac ?
|
|
event.getRawEvent().metaKey :
|
|
event.getRawEvent().ctrlKey;
|
|
}
|
|
|
|
var classHighlight = 'crossreference-item';
|
|
var classMouseCursor = 'crossreference-cursor';
|
|
|
|
// TODO maybe move the dictionary part of this list to the server?
|
|
var class_map = {
|
|
nc : 'class',
|
|
nf : 'function',
|
|
na : null,
|
|
nb : 'builtin',
|
|
n : null,
|
|
};
|
|
|
|
function link(element, lang) {
|
|
JX.DOM.alterClass(element, 'repository-crossreference', true);
|
|
linked.push(element);
|
|
JX.DOM.listen(
|
|
element,
|
|
['mouseover', 'mouseout', 'click'],
|
|
'tag:span',
|
|
function(e) {
|
|
if (e.getType() === 'mouseout') {
|
|
unhighlight();
|
|
return;
|
|
}
|
|
if (!isSignalkey(e)) {
|
|
return;
|
|
}
|
|
|
|
var target = e.getTarget();
|
|
|
|
try {
|
|
// If we're in an inline comment, don't link symbols.
|
|
if (JX.DOM.findAbove(target, 'div', 'differential-inline-comment')) {
|
|
return;
|
|
}
|
|
} catch (ex) {
|
|
// Continue if we're not inside an inline comment.
|
|
}
|
|
|
|
if (e.getType() === 'mouseover') {
|
|
while (target !== document.body) {
|
|
if (JX.DOM.isNode(target, 'span') &&
|
|
(target.className in class_map)) {
|
|
highlighted = target;
|
|
JX.DOM.alterClass(highlighted, classHighlight, true);
|
|
break;
|
|
}
|
|
target = target.parentNode;
|
|
}
|
|
} else if (e.getType() === 'click') {
|
|
openSearch(target, lang);
|
|
}
|
|
});
|
|
}
|
|
function unhighlight() {
|
|
highlighted && JX.DOM.alterClass(highlighted, classHighlight, false);
|
|
highlighted = null;
|
|
}
|
|
|
|
function openSearch(target, lang) {
|
|
var symbol = target.textContent || target.innerText;
|
|
var query = {
|
|
lang : lang,
|
|
repositories : config.repositories.join(','),
|
|
jump : true
|
|
};
|
|
var c = target.className;
|
|
c = c.replace(classHighlight, '').trim();
|
|
if (class_map[c]) {
|
|
query.type = class_map[c];
|
|
}
|
|
if (target.hasAttribute('data-symbol-context')) {
|
|
query.context = target.getAttribute('data-symbol-context');
|
|
}
|
|
if (target.hasAttribute('data-symbol-name')) {
|
|
symbol = target.getAttribute('data-symbol-name');
|
|
}
|
|
var uri = JX.$U('/diffusion/symbol/' + symbol + '/');
|
|
uri.addQueryParams(query);
|
|
window.open(uri);
|
|
}
|
|
|
|
function linkAll() {
|
|
var blocks = JX.DOM.scry(document.body, 'div', 'remarkup-code-block');
|
|
for (var i = 0; i < blocks.length; ++i) {
|
|
if (blocks[i].hasAttribute('data-code-lang')) {
|
|
var lang = blocks[i].getAttribute('data-code-lang');
|
|
link(blocks[i], lang);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (config.container) {
|
|
link(JX.$(config.container), config.lang);
|
|
} else if (config.section) {
|
|
linkAll(JX.$(config.section));
|
|
}
|
|
|
|
JX.Stratcom.listen(
|
|
'differential-preview-update',
|
|
null,
|
|
function(e) {
|
|
linkAll(e.getData().container);
|
|
});
|
|
|
|
|
|
JX.Stratcom.listen(
|
|
['keydown', 'keyup'],
|
|
null,
|
|
function(e) {
|
|
if (e.getRawEvent().keyCode !== signalKey) {
|
|
return;
|
|
}
|
|
setCursorMode(e.getType() === 'keydown');
|
|
|
|
if (!statics.active) {
|
|
unhighlight();
|
|
}
|
|
});
|
|
|
|
JX.Stratcom.listen(
|
|
'blur',
|
|
null,
|
|
function(e) {
|
|
if (e.getTarget()) {
|
|
return;
|
|
}
|
|
unhighlight();
|
|
setCursorMode(false);
|
|
});
|
|
|
|
function setCursorMode(active) {
|
|
statics.active = active;
|
|
linked.forEach(function(element) {
|
|
JX.DOM.alterClass(element, classMouseCursor, statics.active);
|
|
});
|
|
}
|
|
});
|