mirror of
https://github.com/jupyter/notebook.git
synced 2024-12-27 04:20:22 +08:00
Merge pull request #6700 from Carreau/actions-2
Use notebook actions in toolbar
This commit is contained in:
commit
982a742112
@ -38,6 +38,14 @@ define([
|
||||
// for this particular combination
|
||||
this.element.addClass('notification_widget btn btn-xs navbar-btn');
|
||||
};
|
||||
|
||||
/**
|
||||
* hide the widget and empty the text
|
||||
**/
|
||||
NotificationWidget.prototype.hide = function () {
|
||||
var that = this;
|
||||
this.element.fadeOut(100, function(){that.inner.text('');});
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the notification widget message to display for a certain
|
||||
|
@ -2,11 +2,12 @@
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
define([
|
||||
'require',
|
||||
'base/js/namespace',
|
||||
'jquery',
|
||||
'notebook/js/toolbar',
|
||||
'notebook/js/celltoolbar',
|
||||
], function(IPython, $, toolbar, celltoolbar) {
|
||||
'./toolbar',
|
||||
'./celltoolbar'
|
||||
], function(require, IPython, $, toolbar, celltoolbar) {
|
||||
"use strict";
|
||||
|
||||
var MainToolBar = function (selector, options) {
|
||||
@ -19,141 +20,97 @@ define([
|
||||
* Dictionary of keyword arguments.
|
||||
* events: $(Events) instance
|
||||
* notebook: Notebook instance
|
||||
*/
|
||||
toolbar.ToolBar.apply(this, arguments);
|
||||
**/
|
||||
toolbar.ToolBar.apply(this, [selector, options] );
|
||||
this.events = options.events;
|
||||
this.notebook = options.notebook;
|
||||
this.construct();
|
||||
this.add_celltype_list();
|
||||
this.add_celltoolbar_list();
|
||||
this.bind_events();
|
||||
this._make();
|
||||
Object.seal(this);
|
||||
};
|
||||
|
||||
MainToolBar.prototype = Object.create(toolbar.ToolBar.prototype);
|
||||
|
||||
MainToolBar.prototype.construct = function () {
|
||||
var that = this;
|
||||
this.add_buttons_group([
|
||||
{
|
||||
id : 'save_b',
|
||||
label : 'Save and Checkpoint',
|
||||
icon : 'fa-save',
|
||||
callback : function () {
|
||||
that.notebook.save_checkpoint();
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
this.add_buttons_group([
|
||||
{
|
||||
id : 'insert_below_b',
|
||||
label : 'Insert Cell Below',
|
||||
icon : 'fa-plus',
|
||||
callback : function () {
|
||||
that.notebook.insert_cell_below('code');
|
||||
that.notebook.select_next();
|
||||
that.notebook.focus_cell();
|
||||
}
|
||||
}
|
||||
],'insert_above_below');
|
||||
|
||||
this.add_buttons_group([
|
||||
{
|
||||
id : 'cut_b',
|
||||
label : 'Cut Cell',
|
||||
icon : 'fa-cut',
|
||||
callback : function () {
|
||||
that.notebook.cut_cell();
|
||||
}
|
||||
},
|
||||
{
|
||||
id : 'copy_b',
|
||||
label : 'Copy Cell',
|
||||
icon : 'fa-copy',
|
||||
callback : function () {
|
||||
that.notebook.copy_cell();
|
||||
}
|
||||
},
|
||||
{
|
||||
id : 'paste_b',
|
||||
label : 'Paste Cell Below',
|
||||
icon : 'fa-paste',
|
||||
callback : function () {
|
||||
that.notebook.paste_cell_below();
|
||||
}
|
||||
}
|
||||
],'cut_copy_paste');
|
||||
|
||||
this.add_buttons_group([
|
||||
{
|
||||
id : 'move_up_b',
|
||||
label : 'Move Cell Up',
|
||||
icon : 'fa-arrow-up',
|
||||
callback : function () {
|
||||
that.notebook.move_cell_up();
|
||||
}
|
||||
},
|
||||
{
|
||||
id : 'move_down_b',
|
||||
label : 'Move Cell Down',
|
||||
icon : 'fa-arrow-down',
|
||||
callback : function () {
|
||||
that.notebook.move_cell_down();
|
||||
}
|
||||
}
|
||||
],'move_up_down');
|
||||
|
||||
|
||||
this.add_buttons_group([
|
||||
{
|
||||
id : 'run_b',
|
||||
label : 'Run Cell',
|
||||
icon : 'fa-play',
|
||||
callback : function () {
|
||||
/**
|
||||
* emulate default shift-enter behavior
|
||||
*/
|
||||
that.notebook.execute_cell_and_select_below();
|
||||
}
|
||||
},
|
||||
{
|
||||
id : 'interrupt_b',
|
||||
label : 'Interrupt',
|
||||
icon : 'fa-stop',
|
||||
callback : function () {
|
||||
that.notebook.kernel.interrupt();
|
||||
}
|
||||
},
|
||||
{
|
||||
id : 'repeat_b',
|
||||
label : 'Restart Kernel',
|
||||
icon : 'fa-repeat',
|
||||
callback : function () {
|
||||
that.notebook.restart_kernel();
|
||||
}
|
||||
}
|
||||
],'run_int');
|
||||
MainToolBar.prototype._make = function () {
|
||||
var grps = [
|
||||
[
|
||||
['ipython.save-notebook'],
|
||||
'save-notbook'
|
||||
],
|
||||
[
|
||||
['ipython.insert-cell-after'],
|
||||
'insert_above_below'],
|
||||
[
|
||||
['ipython.cut-selected-cell',
|
||||
'ipython.copy-selected-cell',
|
||||
'ipython.paste-cell-after'
|
||||
] ,
|
||||
'cut_copy_paste'],
|
||||
[
|
||||
['ipython.move-selected-cell-up',
|
||||
'ipython.move-selected-cell-down'
|
||||
],
|
||||
'move_up_down'],
|
||||
[ ['ipython.run-select-next',
|
||||
'ipython.interrupt-kernel',
|
||||
'ipython.restart-kernel'
|
||||
],
|
||||
'run_int'],
|
||||
['<add_celltype_list>'],
|
||||
['<add_celltoolbar_list>']
|
||||
];
|
||||
this.construct(grps);
|
||||
};
|
||||
|
||||
MainToolBar.prototype.add_celltype_list = function () {
|
||||
this.element
|
||||
.append($('<select/>')
|
||||
.attr('id','cell_type')
|
||||
.addClass('form-control select-xs')
|
||||
.append($('<option/>').attr('value','code').text('Code'))
|
||||
.append($('<option/>').attr('value','markdown').text('Markdown'))
|
||||
.append($('<option/>').attr('value','raw').text('Raw NBConvert'))
|
||||
.append($('<option/>').attr('value','heading').text('Heading'))
|
||||
);
|
||||
// add a cell type drop down to the maintoolbar.
|
||||
// triggered when the pseudo action `<add_celltype_list>` is
|
||||
// encountered when building a toolbar.
|
||||
MainToolBar.prototype._pseudo_actions.add_celltype_list = function () {
|
||||
var that = this;
|
||||
var sel = $('<select/>')
|
||||
.attr('id','cell_type')
|
||||
.addClass('form-control select-xs')
|
||||
.append($('<option/>').attr('value','code').text('Code'))
|
||||
.append($('<option/>').attr('value','markdown').text('Markdown'))
|
||||
.append($('<option/>').attr('value','raw').text('Raw NBConvert'))
|
||||
.append($('<option/>').attr('value','heading').text('Heading'));
|
||||
this.events.on('selected_cell_type_changed.Notebook', function (event, data) {
|
||||
if (data.cell_type === 'heading') {
|
||||
sel.val('Markdown');
|
||||
} else {
|
||||
sel.val(data.cell_type);
|
||||
}
|
||||
});
|
||||
sel.change(function () {
|
||||
var cell_type = $(this).val();
|
||||
switch (cell_type) {
|
||||
case 'code':
|
||||
that.notebook.to_code();
|
||||
break;
|
||||
case 'markdown':
|
||||
that.notebook.to_markdown();
|
||||
break;
|
||||
case 'raw':
|
||||
that.notebook.to_raw();
|
||||
break;
|
||||
case 'heading':
|
||||
that.notebook._warn_heading();
|
||||
that.notebook.to_heading();
|
||||
sel.val('markdown');
|
||||
break;
|
||||
default:
|
||||
console.log("unrecognized cell type:", cell_type);
|
||||
}
|
||||
});
|
||||
return sel;
|
||||
|
||||
};
|
||||
|
||||
MainToolBar.prototype.add_celltoolbar_list = function () {
|
||||
MainToolBar.prototype._pseudo_actions.add_celltoolbar_list = function () {
|
||||
var label = $('<span/>').addClass("navbar-text").text('Cell Toolbar:');
|
||||
var select = $('<select/>')
|
||||
.attr('id', 'ctb_select')
|
||||
.addClass('form-control select-xs')
|
||||
.append($('<option/>').attr('value', '').text('None'));
|
||||
this.element.append(label).append(select);
|
||||
var that = this;
|
||||
select.change(function() {
|
||||
var val = $(this).val();
|
||||
@ -182,42 +139,13 @@ define([
|
||||
if (select.val() !== data.name)
|
||||
select.val(data.name);
|
||||
});
|
||||
|
||||
var wrapper = $('<div/>').addClass('btn-group');
|
||||
wrapper.append(label).append(select);
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
MainToolBar.prototype.bind_events = function () {
|
||||
var that = this;
|
||||
|
||||
this.element.find('#cell_type').change(function () {
|
||||
var cell_type = $(this).val();
|
||||
switch (cell_type) {
|
||||
case 'code':
|
||||
that.notebook.to_code();
|
||||
break;
|
||||
case 'markdown':
|
||||
that.notebook.to_markdown();
|
||||
break;
|
||||
case 'raw':
|
||||
that.notebook.to_raw();
|
||||
break;
|
||||
case 'heading':
|
||||
that.notebook._warn_heading();
|
||||
that.notebook.to_heading();
|
||||
that.element.find('#cell_type').val("markdown");
|
||||
break;
|
||||
default:
|
||||
console.log("unrecognized cell type:", cell_type);
|
||||
}
|
||||
});
|
||||
this.events.on('selected_cell_type_changed.Notebook', function (event, data) {
|
||||
if (data.cell_type === 'heading') {
|
||||
that.element.find('#cell_type').val(data.cell_type+data.level);
|
||||
} else {
|
||||
that.element.find('#cell_type').val(data.cell_type);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Backwards compatability.
|
||||
// Backwards compatibility.
|
||||
IPython.MainToolBar = MainToolBar;
|
||||
|
||||
return {'MainToolBar': MainToolBar};
|
||||
|
@ -65,6 +65,86 @@ define([
|
||||
{ shortcut: cmd_ctrl + "Shift-z", help:"redo" },
|
||||
{ shortcut: cmd_ctrl + "y", help:"redo" },
|
||||
].concat( platform_specific );
|
||||
|
||||
var mac_humanize_map = {
|
||||
// all these are unicode, will probably display badly on anything except macs.
|
||||
// these are the standard symbol that are used in MacOS native menus
|
||||
// cf http://apple.stackexchange.com/questions/55727/
|
||||
// for htmlentities and/or unicode value
|
||||
'cmd':'⌘',
|
||||
'shift':'⇧',
|
||||
'alt':'⌥',
|
||||
'up':'↑',
|
||||
'down':'↓',
|
||||
'left':'←',
|
||||
'right':'→',
|
||||
'eject':'⏏',
|
||||
'tab':'⇥',
|
||||
'backtab':'⇤',
|
||||
'capslock':'⇪',
|
||||
'esc':'⎋',
|
||||
'ctrl':'⌃',
|
||||
'enter':'↩',
|
||||
'pageup':'⇞',
|
||||
'pagedown':'⇟',
|
||||
'home':'↖',
|
||||
'end':'↘',
|
||||
'altenter':'⌤',
|
||||
'space':'␣',
|
||||
'delete':'⌦',
|
||||
'backspace':'⌫',
|
||||
'apple':'',
|
||||
};
|
||||
|
||||
var default_humanize_map = {
|
||||
'shift':'Shift',
|
||||
'alt':'Alt',
|
||||
'up':'Up',
|
||||
'down':'Down',
|
||||
'left':'Left',
|
||||
'right':'Right',
|
||||
'tab':'Tab',
|
||||
'capslock':'Caps Lock',
|
||||
'esc':'Esc',
|
||||
'ctrl':'Ctrl',
|
||||
'enter':'Enter',
|
||||
'pageup':'Page Up',
|
||||
'pagedown':'Page Down',
|
||||
'home':'Home',
|
||||
'end':'End',
|
||||
'space':'Space',
|
||||
'backspace':'Backspace',
|
||||
};
|
||||
|
||||
var humanize_map;
|
||||
|
||||
if (platform === 'MacOS'){
|
||||
humanize_map = mac_humanize_map;
|
||||
} else {
|
||||
humanize_map = default_humanize_map;
|
||||
}
|
||||
|
||||
function humanize_key(key){
|
||||
if (key.length === 1){
|
||||
key = key.toUpperCase();
|
||||
}
|
||||
return humanize_map[key.toLowerCase()]||key;
|
||||
}
|
||||
|
||||
function humanize_sequence(sequence){
|
||||
var joinchar = ',';
|
||||
var hum = _.map(sequence.replace(/meta/g, 'cmd').split(','), humanize_shortcut).join(joinchar);
|
||||
return hum;
|
||||
}
|
||||
|
||||
function humanize_shortcut(shortcut){
|
||||
var joinchar = '-';
|
||||
if (platform === 'MacOS'){
|
||||
joinchar = '';
|
||||
}
|
||||
var sh = _.map(shortcut.split('-'), humanize_key ).join(joinchar);
|
||||
return sh;
|
||||
}
|
||||
|
||||
|
||||
QuickHelp.prototype.show_keyboard_shortcuts = function () {
|
||||
@ -157,7 +237,10 @@ define([
|
||||
|
||||
var build_one = function (s) {
|
||||
var help = s.help;
|
||||
var shortcut = prettify(s.shortcut);
|
||||
var shortcut = '';
|
||||
if(s.shortcut){
|
||||
shortcut = prettify(humanize_sequence(s.shortcut));
|
||||
}
|
||||
return $('<div>').addClass('quickhelp').
|
||||
append($('<span/>').addClass('shortcut_key').append($(shortcut))).
|
||||
append($('<span/>').addClass('shortcut_descr').text(' : ' + help));
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
define([
|
||||
'base/js/namespace',
|
||||
'jquery',
|
||||
'jquery'
|
||||
], function(IPython, $) {
|
||||
"use strict";
|
||||
|
||||
@ -11,22 +11,52 @@ define([
|
||||
* A generic toolbar on which one can add button
|
||||
* @class ToolBar
|
||||
* @constructor
|
||||
* @param {Dom object} selector
|
||||
* @param {Dom_object} selector
|
||||
*/
|
||||
var ToolBar = function (selector) {
|
||||
var ToolBar = function (selector, options) {
|
||||
this.selector = selector;
|
||||
this.actions = (options||{}).actions;
|
||||
if (this.selector !== undefined) {
|
||||
this.element = $(selector);
|
||||
this.style();
|
||||
}
|
||||
};
|
||||
|
||||
ToolBar.prototype._pseudo_actions={};
|
||||
|
||||
|
||||
ToolBar.prototype.construct = function (config) {
|
||||
for(var k in config){
|
||||
this.add_buttons_group(config[k][0],k[1]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* add a group of button into the current toolbar.
|
||||
* Add a group of button into the current toolbar.
|
||||
*
|
||||
* Use a [dict of [list of action name]] to trigger
|
||||
* on click to the button
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ... todo, maybe use a list of list to keep ordering.
|
||||
*
|
||||
* [
|
||||
* [
|
||||
* [
|
||||
* action_name_1,
|
||||
* action_name_2,
|
||||
* action_name_3,
|
||||
* ],
|
||||
* optional_group_name
|
||||
* ],
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* For backward compatibility this also support the
|
||||
* old methods of adding busson directly bound to callbacks:
|
||||
* @example
|
||||
* # deprecate, do not use
|
||||
* IPython.toolbar.add_buttons_group([
|
||||
* {
|
||||
* label:'my button',
|
||||
@ -52,27 +82,62 @@ define([
|
||||
* @param [list.id] {String} id to give to the button
|
||||
* @param [group_id] {String} optionnal id to give to the group
|
||||
*
|
||||
*
|
||||
* for private usage, the key can also be strings starting with '<' and ending with '>' to inject custom element that cannot
|
||||
* be bound to an action.
|
||||
*
|
||||
*/
|
||||
// TODO JUPYTER:
|
||||
// get rid of legacy code that handle things that are not actions.
|
||||
ToolBar.prototype.add_buttons_group = function (list, group_id) {
|
||||
// handle custom call of pseudoaction binding.
|
||||
if(typeof(list) === 'string' && list.slice(0,1) === '<' && list.slice(-1) === '>'){
|
||||
var _pseudo_action;
|
||||
try{
|
||||
_pseudo_action = list.slice(1,-1);
|
||||
this.element.append(this._pseudo_actions[_pseudo_action].call(this));
|
||||
} catch (e) {
|
||||
console.warn('ouch, calling ', _pseudo_action, 'does not seem to work...:', e);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
var that = this;
|
||||
var btn_group = $('<div/>').addClass("btn-group");
|
||||
if( group_id !== undefined ) {
|
||||
btn_group.attr('id',group_id);
|
||||
}
|
||||
var el;
|
||||
for(var i=0; i < list.length; i++) {
|
||||
el = list[i];
|
||||
var button = $('<button/>')
|
||||
.addClass('btn btn-default')
|
||||
.attr("title", el.label)
|
||||
.append(
|
||||
$("<i/>").addClass(el.icon).addClass('fa')
|
||||
);
|
||||
var id = el.id;
|
||||
if( id !== undefined )
|
||||
button.attr('id',id);
|
||||
var fun = el.callback;
|
||||
button.click(fun);
|
||||
btn_group.append(button);
|
||||
|
||||
// IIFE because javascript don't have loop scope so
|
||||
// action_name would otherwise be the same on all iteration
|
||||
// of the loop
|
||||
(function(i,list){
|
||||
var el = list[i];
|
||||
var action_name;
|
||||
var action;
|
||||
if(typeof(el) === 'string'){
|
||||
action = that.actions.get(el);
|
||||
action_name = el;
|
||||
|
||||
}
|
||||
var button = $('<button/>')
|
||||
.addClass('btn btn-default')
|
||||
.attr("title", el.label||action.help)
|
||||
.append(
|
||||
$("<i/>").addClass(el.icon||action.icon).addClass('fa')
|
||||
);
|
||||
var id = el.id;
|
||||
if( id !== undefined ){
|
||||
button.attr('id',id);
|
||||
}
|
||||
button.attr('data-jupyter-action', action_name);
|
||||
var fun = el.callback|| function(){
|
||||
that.actions.call(action_name);
|
||||
};
|
||||
button.click(fun);
|
||||
btn_group.append(button);
|
||||
})(i,list);
|
||||
// END IIFE
|
||||
}
|
||||
$(this.selector).append(btn_group);
|
||||
};
|
||||
|
@ -66,7 +66,7 @@ casper.notebook_test(function () {
|
||||
IPython.notebook.select(0);
|
||||
cell.clear_output();
|
||||
cell.set_text('a=13; print(a)');
|
||||
$('#run_b').click();
|
||||
$("button[data-jupyter-action='ipython.run-select-next']")[0].click()
|
||||
});
|
||||
|
||||
this.wait_for_output(0);
|
||||
|
@ -29,7 +29,7 @@ casper.notebook_test(function () {
|
||||
$('#cell_type').val('markdown').change();
|
||||
var cell = IPython.notebook.get_selected_cell();
|
||||
cell.set_text('*Baz*');
|
||||
$('#run_b').click();
|
||||
$("button[data-jupyter-action='ipython.run-select-next']")[0].click();
|
||||
return cell.get_rendered();
|
||||
});
|
||||
this.test.assertEquals(output.trim(), '<p><em>Baz</em></p>', 'Markdown toolbar items work.');
|
||||
|
Loading…
Reference in New Issue
Block a user