##// END OF EJS Templates
Fix comments...
Bussonnier Matthias -
Show More
@@ -1,260 +1,267
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 5 'base/js/namespace',
6 6 'jquery',
7 7 'base/js/utils',
8 8 'base/js/dialog',
9 9 ], function(IPython, $, utils, dialog) {
10 10 "use strict";
11 11 var platform = utils.platform;
12 12
13 13 var QuickHelp = function (options) {
14 14 /**
15 15 * Constructor
16 16 *
17 17 * Parameters:
18 18 * options: dictionary
19 19 * Dictionary of keyword arguments.
20 20 * events: $(Events) instance
21 21 * keyboard_manager: KeyboardManager instance
22 22 * notebook: Notebook instance
23 23 */
24 24 this.keyboard_manager = options.keyboard_manager;
25 25 this.notebook = options.notebook;
26 26 this.keyboard_manager.quick_help = this;
27 27 this.events = options.events;
28 28 };
29 29
30 30 var cmd_ctrl = 'Ctrl-';
31 31 var platform_specific;
32 32
33 33 if (platform === 'MacOS') {
34 34 // Mac OS X specific
35 35 cmd_ctrl = 'Cmd-';
36 36 platform_specific = [
37 37 { shortcut: "Cmd-Up", help:"go to cell start" },
38 38 { shortcut: "Cmd-Down", help:"go to cell end" },
39 39 { shortcut: "Alt-Left", help:"go one word left" },
40 40 { shortcut: "Alt-Right", help:"go one word right" },
41 41 { shortcut: "Alt-Backspace", help:"del word before" },
42 42 { shortcut: "Alt-Delete", help:"del word after" },
43 43 ];
44 44 } else {
45 45 // PC specific
46 46 platform_specific = [
47 47 { shortcut: "Ctrl-Home", help:"go to cell start" },
48 48 { shortcut: "Ctrl-Up", help:"go to cell start" },
49 49 { shortcut: "Ctrl-End", help:"go to cell end" },
50 50 { shortcut: "Ctrl-Down", help:"go to cell end" },
51 51 { shortcut: "Ctrl-Left", help:"go one word left" },
52 52 { shortcut: "Ctrl-Right", help:"go one word right" },
53 53 { shortcut: "Ctrl-Backspace", help:"del word before" },
54 54 { shortcut: "Ctrl-Delete", help:"del word after" },
55 55 ];
56 56 }
57 57
58 58 var cm_shortcuts = [
59 59 { shortcut:"Tab", help:"code completion or indent" },
60 60 { shortcut:"Shift-Tab", help:"tooltip" },
61 61 { shortcut: cmd_ctrl + "]", help:"indent" },
62 62 { shortcut: cmd_ctrl + "[", help:"dedent" },
63 63 { shortcut: cmd_ctrl + "a", help:"select all" },
64 64 { shortcut: cmd_ctrl + "z", help:"undo" },
65 65 { shortcut: cmd_ctrl + "Shift-z", help:"redo" },
66 66 { shortcut: cmd_ctrl + "y", help:"redo" },
67 67 ].concat( platform_specific );
68
69 var mac_humanize_map = {
70 // all these are unicode, will probably display badly on anything except macs.
71 // these are the standard symbol that are used in MacOS native menus
72 'cmd':'⌘',
73 'shift':'⇧',
74 'alt':'⌥',
75 'up':'↑',
76 'down':'↓',
77 'left':'←',
78 'right':'→',
79 'eject':'⏏',
80 'tab':'⇥',
81 'capslock':'⇧',
82 'esc':'⎋',
83 'ctrl':'⌃',
84 'enter':'↩',
85 'pageup':'⇞',
86 'pagedown':'⇟',
87 'home':'↖',
88 'end':'↘',
89 'altenter':'⌤',
90 'space':'␣',
91 'backspace':'⇤',
92 'apple':'',
93 };
94
95 var default_humanize_map = {
96 'shift':'Shift',
97 'alt':'Alt',
98 'up':'Up',
99 'down':'Down',
100 'left':'Left',
101 'right':'Right',
102 'tab':'Tab',
103 'capslock':'Caps Lock',
104 'esc':'Esc',
105 'ctrl':'Ctrl',
106 'enter':'Enter',
107 'pageup':'Page Up',
108 'pagedown':'Page Down',
109 'home':'Home',
110 'end':'End',
111 'space':'Space',
112 'backspace,':'Backaspace',
113 };
114
115 var humanize_map;
116
117 if (platform === 'MacOS'){
118 humanize_map = mac_humanize_map;
119 } else {
120 humanize_map = default_humanize_map;
121 }
68 122
69 123 function humanize_key(key){
70 if (platform === 'MacOS'){
71 124 if (key.length === 1){
72 125 key = key.toUpperCase();
73 126 }
74 var d= {
75 // all these are unicode, will probably display badly on anything except macs.
76 // these are the standard symbol that are used in MacOS native menus
77 'cmd':'⌘',
78 'shift':'⇧',
79 'alt':'⌥',
80 'up':'↑',
81 'down':'↓',
82 'left':'←',
83 'right':'→',
84 'eject':'⏏',
85 'tab':'⇥',
86 'capslock':'⇧',
87 'esc':'⎋',
88 'ctrl':'⌃',
89 'enter':'↩',
90 'pageup':'⇞',
91 'pagedown':'⇟',
92 'home':'↖',
93 'end':'↘',
94 'altenter':'⌤',
95 'space':'␣',
96 'backspace':'⇤',
97 'apple':'',
98 };
99 } else {
100 var d = {
101 'shift':'Shift',
102 'alt':'Alt',
103 'up':'Up',
104 'down':'Down',
105 'left':'Left',
106 'right':'Right',
107 'tab':'Tab',
108 'capslock':'Caps Lock',
109 'esc':'Esc',
110 'ctrl':'Ctrl',
111 'enter':'Enter',
112 'pageup':'Page Up',
113 'pagedown':'Page Down',
114 'home':'Home',
115 'end':'End',
116 'space':'Space',
117 'backspace,':'Backaspace',
118 };
119 }
120 return d[key.toLowerCase()]||key;
127 return humanize_map[key.toLowerCase()]||key;
121 128 }
122 129
123 130 function humanize_sequence(sequence){
124 131 var joinchar = ',';
125 132 var hum = _.map(sequence.replace(/meta/g, 'cmd').split(','), humanize_shortcut).join(joinchar);
126 133 return hum;
127 134 }
128 135
129 136 function humanize_shortcut(shortcut){
130 137 var joinchar = '-';
131 138 if (platform === 'MacOS'){
132 139 joinchar = '';
133 140 }
134 141 var sh = _.map(shortcut.split('-'), humanize_key ).join(joinchar);
135 142 return sh;
136 143 }
137 144
138 145
139 146 QuickHelp.prototype.show_keyboard_shortcuts = function () {
140 147 /**
141 148 * toggles display of keyboard shortcut dialog
142 149 */
143 150 var that = this;
144 151 if ( this.force_rebuild ) {
145 152 this.shortcut_dialog.remove();
146 153 delete(this.shortcut_dialog);
147 154 this.force_rebuild = false;
148 155 }
149 156 if ( this.shortcut_dialog ){
150 157 // if dialog is already shown, close it
151 158 $(this.shortcut_dialog).modal("toggle");
152 159 return;
153 160 }
154 161 var command_shortcuts = this.keyboard_manager.command_shortcuts.help();
155 162 var edit_shortcuts = this.keyboard_manager.edit_shortcuts.help();
156 163 var help, shortcut;
157 164 var i, half, n;
158 165 var element = $('<div/>');
159 166
160 167 // The documentation
161 168 var doc = $('<div/>').addClass('alert alert-warning');
162 169 doc.append(
163 170 $('<button/>').addClass('close').attr('data-dismiss','alert').html('&times;')
164 171 ).append(
165 172 'The IPython Notebook has two different keyboard input modes. <b>Edit mode</b> '+
166 173 'allows you to type code/text into a cell and is indicated by a green cell '+
167 174 'border. <b>Command mode</b> binds the keyboard to notebook level actions '+
168 175 'and is indicated by a grey cell border.'
169 176 );
170 177 element.append(doc);
171 178
172 179 // Command mode
173 180 var cmd_div = this.build_command_help();
174 181 element.append(cmd_div);
175 182
176 183 // Edit mode
177 184 var edit_div = this.build_edit_help(cm_shortcuts);
178 185 element.append(edit_div);
179 186
180 187 this.shortcut_dialog = dialog.modal({
181 188 title : "Keyboard shortcuts",
182 189 body : element,
183 190 destroy : false,
184 191 buttons : {
185 192 Close : {}
186 193 },
187 194 notebook: this.notebook,
188 195 keyboard_manager: this.keyboard_manager,
189 196 });
190 197 this.shortcut_dialog.addClass("modal_stretch");
191 198
192 199 this.events.on('rebuild.QuickHelp', function() { that.force_rebuild = true;});
193 200 };
194 201
195 202 QuickHelp.prototype.build_command_help = function () {
196 203 var command_shortcuts = this.keyboard_manager.command_shortcuts.help();
197 204 return build_div('<h4>Command Mode (press <code>Esc</code> to enable)</h4>', command_shortcuts);
198 205 };
199 206
200 207 var special_case = { pageup: "PageUp", pagedown: "Page Down", 'minus': '-' };
201 208 var prettify = function (s) {
202 209 s = s.replace(/-$/, 'minus'); // catch shortcuts using '-' key
203 210 var keys = s.split('-');
204 211 var k, i;
205 212 for (i=0; i < keys.length; i++) {
206 213 k = keys[i];
207 214 if ( k.length == 1 ) {
208 215 keys[i] = "<code><strong>" + k + "</strong></code>";
209 216 continue; // leave individual keys lower-cased
210 217 }
211 218 if (k.indexOf(',') === -1){
212 219 keys[i] = ( special_case[k] ? special_case[k] : k.charAt(0).toUpperCase() + k.slice(1) );
213 220 }
214 221 keys[i] = "<code><strong>" + keys[i] + "</strong></code>";
215 222 }
216 223 return keys.join('-');
217 224
218 225
219 226 };
220 227
221 228 QuickHelp.prototype.build_edit_help = function (cm_shortcuts) {
222 229 var edit_shortcuts = this.keyboard_manager.edit_shortcuts.help();
223 230 jQuery.merge(cm_shortcuts, edit_shortcuts);
224 231 return build_div('<h4>Edit Mode (press <code>Enter</code> to enable)</h4>', cm_shortcuts);
225 232 };
226 233
227 234 var build_one = function (s) {
228 235 var help = s.help;
229 236 var shortcut = '';
230 237 if(s.shortcut){
231 238 shortcut = prettify(humanize_sequence(s.shortcut));
232 239 } else {
233 240 console.error('[debug] - nothing for', s)
234 241 }
235 242 return $('<div>').addClass('quickhelp').
236 243 append($('<span/>').addClass('shortcut_key').append($(shortcut))).
237 244 append($('<span/>').addClass('shortcut_descr').text(' : ' + help));
238 245
239 246 };
240 247
241 248 var build_div = function (title, shortcuts) {
242 249 var i, half, n;
243 250 var div = $('<div/>').append($(title));
244 251 var sub_div = $('<div/>').addClass('hbox');
245 252 var col1 = $('<div/>').addClass('box-flex1');
246 253 var col2 = $('<div/>').addClass('box-flex1');
247 254 n = shortcuts.length;
248 255 half = ~~(n/2); // Truncate :)
249 256 for (i=0; i<half; i++) { col1.append( build_one(shortcuts[i]) ); }
250 257 for (i=half; i<n; i++) { col2.append( build_one(shortcuts[i]) ); }
251 258 sub_div.append(col1).append(col2);
252 259 div.append(sub_div);
253 260 return div;
254 261 };
255 262
256 263 // Backwards compatability.
257 264 IPython.QuickHelp = QuickHelp;
258 265
259 266 return {'QuickHelp': QuickHelp};
260 267 });
@@ -1,161 +1,162
1 1 // Copyright (c) IPython Development Team.
2 2 // Distributed under the terms of the Modified BSD License.
3 3
4 4 define([
5 5 'base/js/namespace',
6 'jquery',
6 'jquery'
7 7 ], function(IPython, $) {
8 8 "use strict";
9 9
10 10 /**
11 11 * A generic toolbar on which one can add button
12 12 * @class ToolBar
13 13 * @constructor
14 14 * @param {Dom_object} selector
15 15 */
16 16 var ToolBar = function (selector, options) {
17 17 this.selector = selector;
18 18 this.actions = (options||{}).actions;
19 19 if (this.selector !== undefined) {
20 20 this.element = $(selector);
21 21 this.style();
22 22 }
23 23 };
24 24
25 25
26 26 // thought, this might not be the best way as dict might not keep the right order.
27 27 // Might want to put the group name as second to make it optional
28 28 //
29 29 ToolBar.prototype.construct = function (config) {
30 30 for(var k in config){
31 31 this.add_buttons_group(config[k][0],k[1]);
32 32 }
33 33 };
34 34
35 35 /**
36 36 * Add a group of button into the current toolbar.
37 37 *
38 38 * Use a [dict of [list of action name]] to trigger
39 39 * on click to the button
40 40 *
41 41 * @example
42 42 *
43 43 * ... todo, maybe use a list of list to keep ordering.
44 44 *
45 45 * [
46 46 * [
47 47 * [
48 48 * action_name_1,
49 49 * action_name_2,
50 50 * action_name_3,
51 51 * ],
52 52 * optional_group_name
53 53 * ],
54 54 * ...
55 55 * ]
56 56 *
57 57 * For backward compatibility this also support the
58 58 * old methods of adding busson directly bound to callbacks:
59 59 * @example
60 60 * # deprecate, do not use
61 61 * IPython.toolbar.add_buttons_group([
62 62 * {
63 63 * label:'my button',
64 64 * icon:'icon-hdd',
65 65 * callback:function(){alert('hoho')},
66 66 * id : 'my_button_id', // this is optional
67 67 * },
68 68 * {
69 69 * label:'my second button',
70 70 * icon:'icon-play',
71 71 * callback:function(){alert('be carefull I cut')}
72 72 * }
73 73 * ],
74 74 * "my_button_group_id"
75 75 * )
76 76 *
77 77 * @method add_buttons_group
78 78 * @param list {List}
79 79 * List of button of the group, with the following paramter for each :
80 80 * @param list.label {string} text to show on button hover
81 81 * @param list.icon {string} icon to choose from [Font Awesome](http://fortawesome.github.io/Font-Awesome)
82 82 * @param list.callback {function} function to be called on button click
83 83 * @param [list.id] {String} id to give to the button
84 84 * @param [group_id] {String} optionnal id to give to the group
85 85 *
86 86 *
87 87 * for private usage, the key can also be strings starting with '<' and ending with '>' to inject custom element that cannot
88 88 * be bound to an action.
89 89 *
90 90 */
91 91 // TODO JUPYTER:
92 92 // get rid of legacy code that handle things that are not actions.
93 93 ToolBar.prototype.add_buttons_group = function (list, group_id) {
94 94 // handle custom call of pseudoaction binding.
95 if(typeof(list) == 'string' && list.slice(0,1) == '<' && list.slice(-1) == '>'){
95 if(typeof(list) === 'string' && list.slice(0,1) === '<' && list.slice(-1) === '>'){
96 var _pseudo_action;
96 97 try{
97 var _n = list.slice(1,-1)
98 var fun = this[_n]();
98 _pseudo_action = list.slice(1,-1);
99 this[_pseudo_action]();
99 100 } catch (e) {
100 console.warn('ouch, calling ', _n, 'does not seem to work...:')
101 console.warn('ouch, calling ', _pseudo_action, 'does not seem to work...:');
101 102 }
102 103 return ;
103 104 }
104 105 var that = this;
105 106 var btn_group = $('<div/>').addClass("btn-group");
106 107 if( group_id !== undefined ) {
107 108 btn_group.attr('id',group_id);
108 109 }
109 110 var el;
110 111 for(var i=0; i < list.length; i++) {
111 112
112 // IIFE because Fucking javascript don't have loop scope so
113 // IIFE because javascript don't have loop scope so
113 114 // action_name would otherwise be the same on all iteration
114 115 // of the loop
115 116 // TODO: Indent this thing once reviewed:
116 117 (function(){
117 118 el = list[i];
118 119 var action_name;
119 120 var action;
120 121 if(typeof(el) === 'string'){
121 122 action = that.actions.get(el);
122 123 action_name = el;
123 124
124 125 }
125 126 var button = $('<button/>')
126 127 .addClass('btn btn-default')
127 128 .attr("title", el.label||action.help)
128 129 .append(
129 130 $("<i/>").addClass(el.icon||action.icon).addClass('fa')
130 131 );
131 132 var id = el.id;
132 133 if( id !== undefined )
133 134 button.attr('id',id);
134 135 var fun = el.callback|| function(){
135 136 that.actions.call(action_name);
136 137 };
137 138 button.click(fun);
138 139 btn_group.append(button);
139 140 })();
140 141 // END IIFE
141 142 }
142 143 $(this.selector).append(btn_group);
143 144 };
144 145
145 146 ToolBar.prototype.style = function () {
146 147 this.element.addClass('toolbar');
147 148 };
148 149
149 150 /**
150 151 * Show and hide toolbar
151 152 * @method toggle
152 153 */
153 154 ToolBar.prototype.toggle = function () {
154 155 this.element.toggle();
155 156 };
156 157
157 158 // Backwards compatibility.
158 159 IPython.ToolBar = ToolBar;
159 160
160 161 return {'ToolBar': ToolBar};
161 162 });
@@ -1,78 +1,79
1 1 //
2 2 // Test code cell execution.
3 3 //
4 4 casper.notebook_test(function () {
5 5 this.evaluate(function () {
6 6 var cell = IPython.notebook.get_cell(0);
7 7 cell.set_text('a=10; print(a)');
8 8 cell.execute();
9 9 });
10 10
11 11 this.wait_for_output(0);
12 12
13 13 // refactor this into just a get_output(0)
14 14 this.then(function () {
15 15 var result = this.get_output_cell(0);
16 16 this.test.assertEquals(result.text, '10\n', 'cell execute (using js)');
17 17 });
18 18
19 19
20 20 // do it again with the keyboard shortcut
21 21 this.thenEvaluate(function () {
22 22 var cell = IPython.notebook.get_cell(0);
23 23 cell.set_text('a=11; print(a)');
24 24 cell.clear_output();
25 25 });
26 26
27 27 this.then(function(){
28 28
29 29 this.trigger_keydown('shift-enter');
30 30 });
31 31
32 32 this.wait_for_output(0);
33 33
34 34 this.then(function () {
35 35 var result = this.get_output_cell(0);
36 36 var num_cells = this.get_cells_length();
37 37 this.test.assertEquals(result.text, '11\n', 'cell execute (using ctrl-enter)');
38 38 this.test.assertEquals(num_cells, 2, 'shift-enter adds a new cell at the bottom')
39 39 });
40 40
41 41 // do it again with the keyboard shortcut
42 42 this.thenEvaluate(function () {
43 43 IPython.notebook.select(1);
44 44 IPython.notebook.delete_cell();
45 45 var cell = IPython.notebook.get_cell(0);
46 46 cell.set_text('a=12; print(a)');
47 47 cell.clear_output();
48 48 });
49 49
50 50 this.then(function(){
51 51 this.trigger_keydown('ctrl-enter');
52 52 });
53 53
54 54 this.wait_for_output(0);
55 55
56 56 this.then(function () {
57 57 var result = this.get_output_cell(0);
58 58 var num_cells = this.get_cells_length();
59 59 this.test.assertEquals(result.text, '12\n', 'cell execute (using shift-enter)');
60 60 this.test.assertEquals(num_cells, 1, 'ctrl-enter adds no new cell at the bottom')
61 61 });
62 62
63 63 // press the "play" triangle button in the toolbar
64 64 this.thenEvaluate(function () {
65 65 var cell = IPython.notebook.get_cell(0);
66 66 IPython.notebook.select(0);
67 67 cell.clear_output();
68 68 cell.set_text('a=13; print(a)');
69 // 'run button' is the first of the forth group in default config.
69 70 $('#maintoolbar .btn-group:nth(4) .btn:first').click()
70 71 });
71 72
72 73 this.wait_for_output(0);
73 74
74 75 this.then(function () {
75 76 var result = this.get_output_cell(0);
76 77 this.test.assertEquals(result.text, '13\n', 'cell execute (using "play" toolbar button)')
77 78 });
78 79 });
General Comments 0
You need to be logged in to leave comments. Login now