You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
6.1 KiB

// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
define(function(require){
"use strict";
var QH = require("notebook/js/quickhelp");
var $ = require("jquery");
/**
* Humanize the action name to be consumed by user.
* internaly the actions anem are of the form
* <namespace>:<description-with-dashes>
* we drop <namesapce> and replace dashes for space.
*/
var humanize_action_id = function(str) {
return str.split(':')[1].replace(/-/g, ' ').replace(/_/g, '-');
};
/**
* given an action id return 'command-shortcut', 'edit-shortcut' or 'no-shortcut'
* for the action. This allows us to tag UI in order to visually distinguish
* wether an action have a keybinding or not.
**/
var get_mode_for_action_id = function(name, notebook) {
var shortcut = notebook.keyboard_manager.command_shortcuts.get_action_shortcut(name);
if (shortcut) {
return 'command-shortcut';
}
shortcut = notebook.keyboard_manager.edit_shortcuts.get_action_shortcut(name);
if (shortcut) {
return 'edit-shortcut';
}
return 'no-shortcut';
};
var CommandPalette = function(notebook) {
if(!notebook){
throw new Error("CommandPalette takes a notebook non-null mandatory arguement");
}
// typeahead lib need a specific layout with specific class names.
// the following just does that
var form = $('<form/>');
var container = $('<div/>').addClass('typeahead-container');
var field = $('<div/>').addClass('typeahead-field');
var input = $('<input/>').attr('type', 'search');
field
.append(
$('<span>').addClass('typeahead-query').append(
input
)
)
.append(
$('<span/>').addClass('typeahead-button').append(
$('<button/>').attr('type', 'submit').append(
$('<span/>').addClass('typeahead-search-icon')
)
)
);
container.append(field);
form.append(container);
var mod = $('<div/>').addClass('modal cmd-palette').append(
$('<div/>').addClass('modal-dialog')
.append(
$('<div/>').addClass('modal-content').append(
$('<div/>').addClass('modal-body')
.append(
form
)
)
)
)
// end setting up right layout
.modal({show: false, backdrop:true})
.on('shown.bs.modal', function () {
// click on button trigger de-focus on mouse up.
// or somethign like that.
setTimeout(function(){input.focus();}, 100);
});
notebook.keyboard_manager.disable();
var before_close = function() {
// little trick to trigger early in onsubmit
// when the action called pop-up a dialog
// insure this function is only called once
if (before_close.ok) {
return;
}
var cell = notebook.get_selected_cell();
if (cell) {
cell.select();
}
if (notebook.keyboard_manager) {
notebook.keyboard_manager.enable();
notebook.keyboard_manager.command_mode();
}
before_close.ok = true; // avoid double call.
};
mod.on("hide.bs.modal", before_close);
// will be trigger when user select action
var onSubmit = function(node, query, result, resultCount) {
if (actions.indexOf(result.key) >= 0) {
before_close();
notebook.keyboard_manager.actions.call(result.key);
} else {
console.warning("No command " + result.key);
}
mod.modal('hide');
};
/* Whenever a result is rendered, if there is only one resulting
* element then automatically select that element.
*/
var onResult = function(node, query, result, resultCount) {
if (resultCount == 1) {
requestAnimationFrame(function() {
$('.typeahead-list > li:nth-child(2)').addClass('active');
});
}
};
// generate structure needed for typeahead layout and ability to search
var src = {};
var actions = Object.keys(notebook.keyboard_manager.actions._actions);
for (var i = 0; i < actions.length; i++) {
var action_id = actions[i];
var action = notebook.keyboard_manager.actions.get(action_id);
var group = action_id.split(':')[0];
src[group] = src[group] || {
data: [],
display: 'display'
};
var short = notebook.keyboard_manager.command_shortcuts.get_action_shortcut(action_id) ||
notebook.keyboard_manager.edit_shortcuts.get_action_shortcut(action_id);
if (short) {
short = QH.humanize_sequence(short);
}
src[group].data.push({
display: humanize_action_id(action_id),
shortcut: short,
mode_shortcut: get_mode_for_action_id(action_id, notebook),
group: group,
icon: action.icon,
help: action.help,
key: action_id,
});
}
// now src is the right structure for typeahead
input.typeahead({
emptyTemplate: "No results found for <pre>{{query}}</pre>",
maxItem: 1e3,
minLength: 0,
hint: true,
group: ["group", "{{group}} command group"],
searchOnFocus: true,
mustSelectItem: true,
template: '<i class="fa fa-icon {{icon}}"></i>{{display}} <div class="pull-right {{mode_shortcut}}">{{shortcut}}</div>',
order: "asc",
source: src,
callback: {
onSubmit: onSubmit,
onClickAfter: onSubmit,
onResult: onResult
},
debug: false,
});
mod.modal('show');
};
return {'CommandPalette': CommandPalette};
});