Show More
The requested changes are too big and content was truncated. Show full diff
@@ -0,0 +1,75 b'' | |||||
|
1 | //---------------------------------------------------------------------------- | |||
|
2 | // Copyright (C) 2013 The IPython Development Team | |||
|
3 | // | |||
|
4 | // Distributed under the terms of the BSD License. The full license is in | |||
|
5 | // the file COPYING, distributed as part of this software. | |||
|
6 | //---------------------------------------------------------------------------- | |||
|
7 | ||||
|
8 | //============================================================================ | |||
|
9 | // Utility for modal dialogs with bootstrap | |||
|
10 | //============================================================================ | |||
|
11 | ||||
|
12 | IPython.namespace('IPython.dialog'); | |||
|
13 | ||||
|
14 | IPython.dialog = (function (IPython) { | |||
|
15 | ||||
|
16 | var modal = function (options) { | |||
|
17 | var dialog = $("<div/>").addClass("modal").attr("role", "dialog"); | |||
|
18 | dialog.append( | |||
|
19 | $("<div/>") | |||
|
20 | .addClass("modal-header") | |||
|
21 | .append($("<button>") | |||
|
22 | .addClass("close") | |||
|
23 | .attr("data-dismiss", "modal") | |||
|
24 | .html("×") | |||
|
25 | ).append( | |||
|
26 | $("<h3/>").text(options.title || "") | |||
|
27 | ) | |||
|
28 | ).append( | |||
|
29 | $("<div/>").addClass("modal-body").append( | |||
|
30 | options.body || $("<p/>") | |||
|
31 | ) | |||
|
32 | ); | |||
|
33 | ||||
|
34 | var footer = $("<div/>").addClass("modal-footer"); | |||
|
35 | ||||
|
36 | for (var label in options.buttons) { | |||
|
37 | var btn_opts = options.buttons[label]; | |||
|
38 | var button = $("<button/>") | |||
|
39 | .addClass("btn") | |||
|
40 | .attr("data-dismiss", "modal") | |||
|
41 | .text(label); | |||
|
42 | if (btn_opts.click) { | |||
|
43 | button.click($.proxy(btn_opts.click, dialog)); | |||
|
44 | } | |||
|
45 | if (btn_opts.class) { | |||
|
46 | button.addClass(btn_opts.class); | |||
|
47 | } | |||
|
48 | footer.append(button); | |||
|
49 | } | |||
|
50 | dialog.append(footer); | |||
|
51 | // hook up on-open event | |||
|
52 | dialog.on("shown", function() { | |||
|
53 | setTimeout(function() { | |||
|
54 | footer.find("button").last().focus(); | |||
|
55 | if (options.open) { | |||
|
56 | $.proxy(options.open, dialog)(); | |||
|
57 | } | |||
|
58 | }, 0); | |||
|
59 | }); | |||
|
60 | ||||
|
61 | // destroy dialog on hide, unless explicitly asked not to | |||
|
62 | if (options.destroy == undefined || options.destroy) { | |||
|
63 | dialog.on("hidden", function () { | |||
|
64 | dialog.remove(); | |||
|
65 | }); | |||
|
66 | } | |||
|
67 | ||||
|
68 | return dialog.modal(options); | |||
|
69 | } | |||
|
70 | ||||
|
71 | return { | |||
|
72 | modal : modal, | |||
|
73 | }; | |||
|
74 | ||||
|
75 | }(IPython)); |
@@ -1,22 +1,21 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // On document ready |
|
9 | // On document ready | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 |
|
12 | |||
13 | $(document).ready(function () { |
|
13 | $(document).ready(function () { | |
14 |
|
14 | |||
15 | IPython.page = new IPython.Page(); |
|
15 | IPython.page = new IPython.Page(); | |
16 |
$(' |
|
16 | $('button#login_submit').addClass("btn"); | |
17 | $('#ipython-main-app').addClass('border-box-sizing ui-widget'); |
|
|||
18 | IPython.page.show(); |
|
17 | IPython.page.show(); | |
19 | $('input#password_input').focus(); |
|
18 | $('input#password_input').focus(); | |
20 |
|
19 | |||
21 | }); |
|
20 | }); | |
22 |
|
21 |
@@ -1,46 +1,45 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Login button |
|
9 | // Login button | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | var IPython = (function (IPython) { |
|
12 | var IPython = (function (IPython) { | |
13 |
|
13 | |||
14 | var LoginWidget = function (selector, options) { |
|
14 | var LoginWidget = function (selector, options) { | |
15 | var options = options || {}; |
|
15 | var options = options || {}; | |
16 | this.base_url = options.baseProjectUrl || $('body').data('baseProjectUrl') ; |
|
16 | this.base_url = options.baseProjectUrl || $('body').data('baseProjectUrl') ; | |
17 | this.selector = selector; |
|
17 | this.selector = selector; | |
18 | if (this.selector !== undefined) { |
|
18 | if (this.selector !== undefined) { | |
19 | this.element = $(selector); |
|
19 | this.element = $(selector); | |
20 | this.style(); |
|
20 | this.style(); | |
21 | this.bind_events(); |
|
21 | this.bind_events(); | |
22 | } |
|
22 | } | |
23 | }; |
|
23 | }; | |
24 |
|
24 | |||
25 | LoginWidget.prototype.style = function () { |
|
25 | LoginWidget.prototype.style = function () { | |
26 |
this.element.find( |
|
26 | this.element.find("button").addClass("btn btn-small"); | |
27 | this.element.find('button#login').button(); |
|
|||
28 | }; |
|
27 | }; | |
29 |
|
28 | |||
30 |
|
29 | |||
31 | LoginWidget.prototype.bind_events = function () { |
|
30 | LoginWidget.prototype.bind_events = function () { | |
32 | var that = this; |
|
31 | var that = this; | |
33 | this.element.find("button#logout").click(function () { |
|
32 | this.element.find("button#logout").click(function () { | |
34 | window.location = that.base_url+"logout"; |
|
33 | window.location = that.base_url+"logout"; | |
35 | }); |
|
34 | }); | |
36 | this.element.find("button#login").click(function () { |
|
35 | this.element.find("button#login").click(function () { | |
37 | window.location = that.base_url+"login"; |
|
36 | window.location = that.base_url+"login"; | |
38 | }); |
|
37 | }); | |
39 | }; |
|
38 | }; | |
40 |
|
39 | |||
41 | // Set module variables |
|
40 | // Set module variables | |
42 | IPython.LoginWidget = LoginWidget; |
|
41 | IPython.LoginWidget = LoginWidget; | |
43 |
|
42 | |||
44 | return IPython; |
|
43 | return IPython; | |
45 |
|
44 | |||
46 | }(IPython)); |
|
45 | }(IPython)); |
@@ -1,20 +1,20 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // On document ready |
|
9 | // On document ready | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 |
|
12 | |||
13 | $(document).ready(function () { |
|
13 | $(document).ready(function () { | |
14 |
|
14 | |||
15 | IPython.page = new IPython.Page(); |
|
15 | IPython.page = new IPython.Page(); | |
16 |
$('#ipython-main-app').addClass('border-box-sizing |
|
16 | $('#ipython-main-app').addClass('border-box-sizing'); | |
17 | IPython.page.show(); |
|
17 | IPython.page.show(); | |
18 |
|
18 | |||
19 | }); |
|
19 | }); | |
20 |
|
20 |
@@ -1,1 +1,6 b'' | |||||
1 | // Custom styles for login.html No newline at end of file |
|
1 | // Custom styles for login.html | |
|
2 | .center-nav { | |||
|
3 | display: inline-block; | |||
|
4 | // pull the lower margin back | |||
|
5 | margin-bottom: -4px; | |||
|
6 | } No newline at end of file |
@@ -1,59 +1,55 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Global header/site setup. |
|
9 | // Global header/site setup. | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | var IPython = (function (IPython) { |
|
12 | var IPython = (function (IPython) { | |
13 |
|
13 | |||
14 | var Page = function () { |
|
14 | var Page = function () { | |
15 | this.style(); |
|
15 | this.style(); | |
16 | this.bind_events(); |
|
16 | this.bind_events(); | |
17 | }; |
|
17 | }; | |
18 |
|
18 | |||
19 | Page.prototype.style = function () { |
|
19 | Page.prototype.style = function () { | |
20 |
$('div#header').addClass('border-box-sizing') |
|
20 | $('div#header').addClass('border-box-sizing'); | |
21 | addClass('ui-widget-content'). |
|
21 | $('div#site').addClass('border-box-sizing'); | |
22 | css('border-top-style','none'). |
|
|||
23 | css('border-left-style','none'). |
|
|||
24 | css('border-right-style','none'); |
|
|||
25 | $('div#site').addClass('border-box-sizing') |
|
|||
26 | }; |
|
22 | }; | |
27 |
|
23 | |||
28 |
|
24 | |||
29 | Page.prototype.bind_events = function () { |
|
25 | Page.prototype.bind_events = function () { | |
30 | }; |
|
26 | }; | |
31 |
|
27 | |||
32 |
|
28 | |||
33 | Page.prototype.show = function () { |
|
29 | Page.prototype.show = function () { | |
34 | // The header and site divs start out hidden to prevent FLOUC. |
|
30 | // The header and site divs start out hidden to prevent FLOUC. | |
35 | // Main scripts should call this method after styling everything. |
|
31 | // Main scripts should call this method after styling everything. | |
36 | this.show_header(); |
|
32 | this.show_header(); | |
37 | this.show_site(); |
|
33 | this.show_site(); | |
38 | }; |
|
34 | }; | |
39 |
|
35 | |||
40 |
|
36 | |||
41 | Page.prototype.show_header = function () { |
|
37 | Page.prototype.show_header = function () { | |
42 | // The header and site divs start out hidden to prevent FLOUC. |
|
38 | // The header and site divs start out hidden to prevent FLOUC. | |
43 | // Main scripts should call this method after styling everything. |
|
39 | // Main scripts should call this method after styling everything. | |
44 | $('div#header').css('display','block'); |
|
40 | $('div#header').css('display','block'); | |
45 | }; |
|
41 | }; | |
46 |
|
42 | |||
47 |
|
43 | |||
48 | Page.prototype.show_site = function () { |
|
44 | Page.prototype.show_site = function () { | |
49 | // The header and site divs start out hidden to prevent FLOUC. |
|
45 | // The header and site divs start out hidden to prevent FLOUC. | |
50 | // Main scripts should call this method after styling everything. |
|
46 | // Main scripts should call this method after styling everything. | |
51 | $('div#site').css('display','block'); |
|
47 | $('div#site').css('display','block'); | |
52 | }; |
|
48 | }; | |
53 |
|
49 | |||
54 |
|
50 | |||
55 | IPython.Page = Page; |
|
51 | IPython.Page = Page; | |
56 |
|
52 | |||
57 | return IPython; |
|
53 | return IPython; | |
58 |
|
54 | |||
59 | }(IPython)); |
|
55 | }(IPython)); |
@@ -1,70 +1,73 b'' | |||||
1 | /** |
|
1 | /** | |
2 | * Primary styles |
|
2 | * Primary styles | |
3 | * |
|
3 | * | |
4 | * Author: IPython Development Team |
|
4 | * Author: IPython Development Team | |
5 | */ |
|
5 | */ | |
6 |
|
6 | |||
7 |
|
7 | |||
8 | body { |
|
8 | body { | |
9 | background-color: white; |
|
9 | background-color: white; | |
10 | /* This makes sure that the body covers the entire window and needs to |
|
10 | /* This makes sure that the body covers the entire window and needs to | |
11 | be in a different element than the display: box in wrapper below */ |
|
11 | be in a different element than the display: box in wrapper below */ | |
12 | position: absolute; |
|
12 | position: absolute; | |
13 | left: 0px; |
|
13 | left: 0px; | |
14 | right: 0px; |
|
14 | right: 0px; | |
15 | top: 0px; |
|
15 | top: 0px; | |
16 | bottom: 0px; |
|
16 | bottom: 0px; | |
17 | overflow: visible; |
|
17 | overflow: visible; | |
18 | } |
|
18 | } | |
19 |
|
19 | |||
20 |
|
||||
21 | div#header { |
|
20 | div#header { | |
22 | /* Initially hidden to prevent FLOUC */ |
|
21 | /* Initially hidden to prevent FLOUC */ | |
23 | display: none; |
|
22 | display: none; | |
24 | position: relative; |
|
|||
25 | height: 40px; |
|
|||
26 | padding: 5px; |
|
|||
27 | margin: 0px; |
|
|||
28 | width: 100%; |
|
|||
29 | } |
|
23 | } | |
30 |
|
24 | |||
31 |
|
|
25 | #ipython_notebook { | |
32 | position: absolute; |
|
26 | padding-left: 16px; | |
33 | padding: 2px 2px 2px 5px; |
|
|||
34 | } |
|
27 | } | |
35 |
|
28 | |||
36 |
|
|
29 | #ipython_notebook img { | |
37 | font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; |
|
30 | font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; | |
38 | height: 24px; |
|
31 | height: 24px; | |
39 | text-decoration:none; |
|
32 | text-decoration:none; | |
40 | display: inline; |
|
|||
41 | color: black; |
|
33 | color: black; | |
42 | } |
|
34 | } | |
43 |
|
35 | |||
44 | #site { |
|
36 | #site { | |
45 | width: 100%; |
|
37 | width: 100%; | |
46 | display: none; |
|
38 | display: none; | |
47 | } |
|
39 | } | |
48 |
|
40 | |||
49 | /* We set the fonts by hand here to override the values in the theme */ |
|
|||
50 | .ui-widget { |
|
|||
51 | font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif; |
|
|||
52 | } |
|
|||
53 |
|
||||
54 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { |
|
|||
55 | font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif; |
|
|||
56 | } |
|
|||
57 |
|
||||
58 | /* Smaller buttons */ |
|
41 | /* Smaller buttons */ | |
59 | .ui-button .ui-button-text { |
|
42 | .ui-button .ui-button-text { | |
60 | padding: 0.2em 0.8em; |
|
43 | padding: 0.2em 0.8em; | |
61 | font-size: 77%; |
|
44 | font-size: 77%; | |
62 | } |
|
45 | } | |
63 |
|
46 | |||
64 | input.ui-button { |
|
47 | input.ui-button { | |
65 | padding: 0.3em 0.9em; |
|
48 | padding: 0.3em 0.9em; | |
66 | } |
|
49 | } | |
|
50 | .navbar span { | |||
|
51 | margin-top: 3px; | |||
|
52 | } | |||
67 |
|
53 | |||
68 | span#login_widget { |
|
54 | span#login_widget { | |
69 | float: right; |
|
55 | float: right; | |
70 | } |
|
56 | } | |
|
57 | ||||
|
58 | .nav-header { | |||
|
59 | text-transform: none; | |||
|
60 | } | |||
|
61 | ||||
|
62 | .navbar-nobg { | |||
|
63 | background-color: transparent; | |||
|
64 | background-image: none; | |||
|
65 | } | |||
|
66 | ||||
|
67 | #header > span { | |||
|
68 | margin-top: 10px; | |||
|
69 | } | |||
|
70 | ||||
|
71 | .modal-body { | |||
|
72 | max-height: 500px; | |||
|
73 | } |
@@ -1,4 +1,6 b'' | |||||
1 | @import "../base/less/variables.less"; |
|
1 | @import "../base/less/variables.less"; | |
2 | @import "../base/less/mixins.less"; |
|
2 | @import "../base/less/mixins.less"; | |
3 | @import "../base/less/flexbox.less"; |
|
3 | @import "../base/less/flexbox.less"; | |
4 | @import "../base/less/page.less"; |
|
4 | @import "../base/less/page.less"; | |
|
5 | @import "../components/font-awesome/build/assets/font-awesome/less/font-awesome.less"; | |||
|
6 | @FontAwesomePath: "../components/font-awesome/build/assets/font-awesome/font"; |
@@ -1,10 +1,11 b'' | |||||
1 | // Our customizations to bootstrap go here. |
|
1 | // Our customizations to bootstrap go here. | |
2 |
|
2 | |||
3 | @textColor: @black; |
|
3 | @textColor: @black; | |
4 | @baseFontSize: 13px; |
|
4 | @baseFontSize: 13px; | |
5 | @baseLineHeight: 1.231; |
|
5 | @monoFontFamily: monospace; // to allow user to customize their fonts | |
6 | @monoFontFamily: monospace; // to allow user to customize their fonts |
|
6 | @navbarHeight: 36px; | |
7 |
|
7 | |||
8 | // Our own global variables for all pages go here |
|
8 | // Our own global variables for all pages go here | |
9 |
|
9 | |||
10 |
@corner_radius: |
|
10 | @corner_radius: 4px; | |
|
11 | @code_line_height: 1.231em; |
@@ -1,9 +1,8 b'' | |||||
1 | /*This file contains any manual css for this page that needs to override the global styles. |
|
1 | /*This file contains any manual css for this page that needs to override the global styles. | |
2 | This is only required when different pages style the same element differently. This is just |
|
2 | This is only required when different pages style the same element differently. This is just | |
3 | a hack to deal with our current css styles and no new styling should be added in this file.*/ |
|
3 | a hack to deal with our current css styles and no new styling should be added in this file.*/ | |
4 |
|
4 | |||
5 | #ipython-main-app { |
|
5 | #ipython-main-app { | |
6 | width: 100%; |
|
|||
7 | position: relative; |
|
6 | position: relative; | |
8 | font-size: 110%; |
|
7 | font-size: 110%; | |
9 | } No newline at end of file |
|
8 | } |
@@ -1,94 +1,90 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2012 The IPython Development Team |
|
2 | // Copyright (C) 2012 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // CellToolbar Default |
|
9 | // CellToolbar Default | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | /** |
|
12 | /** | |
13 | * Example Use for the CellToolbar library |
|
13 | * Example Use for the CellToolbar library | |
14 | */ |
|
14 | */ | |
15 | // IIFE without asignement, we don't modifiy the IPython namespace |
|
15 | // IIFE without asignement, we don't modifiy the IPython namespace | |
16 | (function (IPython) { |
|
16 | (function (IPython) { | |
17 | "use strict"; |
|
17 | "use strict"; | |
18 |
|
18 | |||
19 | var CellToolbar = IPython.CellToolbar; |
|
19 | var CellToolbar = IPython.CellToolbar; | |
20 |
|
20 | |||
21 | var raw_edit = function(cell){ |
|
21 | var raw_edit = function(cell){ | |
22 |
|
22 | |||
23 | var md = cell.metadata |
|
23 | var md = cell.metadata | |
24 | var error_div = $('<div/>').css('color','red') |
|
24 | var error_div = $('<div/>').css('color','red') | |
25 |
|
25 | |||
26 | var textarea = $('<textarea/>') |
|
26 | var textarea = $('<textarea/>') | |
27 | .attr('rows','13') |
|
27 | .attr('rows','13') | |
28 | .attr('cols','75') |
|
28 | .attr('cols','75') | |
29 | .attr('name','metadata') |
|
29 | .attr('name','metadata') | |
30 | .text(JSON.stringify(md, null,4)||''); |
|
30 | .text(JSON.stringify(md, null,4)||''); | |
31 | var dialogform = $('<div/>').attr('title','Edit the metadata') |
|
31 | var dialogform = $('<div/>').attr('title','Edit the metadata') | |
32 | .append( |
|
32 | .append( | |
33 | $('<form/>').append( |
|
33 | $('<form/>').append( | |
34 | $('<fieldset/>').append( |
|
34 | $('<fieldset/>').append( | |
35 | $('<label/>') |
|
35 | $('<label/>') | |
36 | .attr('for','metadata') |
|
36 | .attr('for','metadata') | |
37 | .text("Manually edit the JSON below to manipulate the metadata for this cell. This assumes you know what you are doing and won't complain if it breaks your notebook. We also recommend putting your metadata attributes in an appropriately named sub-structure, so they don't conflict with those of others.") |
|
37 | .text("Manually edit the JSON below to manipulate the metadata for this cell. This assumes you know what you are doing and won't complain if it breaks your notebook. We also recommend putting your metadata attributes in an appropriately named sub-structure, so they don't conflict with those of others.") | |
38 | ) |
|
38 | ) | |
39 | .append(error_div) |
|
39 | .append(error_div) | |
40 | .append($('<br/>')) |
|
40 | .append($('<br/>')) | |
41 | .append( |
|
41 | .append( | |
42 | textarea |
|
42 | textarea | |
43 | ) |
|
43 | ) | |
44 | ) |
|
44 | ) | |
45 | ); |
|
45 | ); | |
46 | var editor = CodeMirror.fromTextArea(textarea[0], { |
|
46 | var editor = CodeMirror.fromTextArea(textarea[0], { | |
47 | lineNumbers: true, |
|
47 | lineNumbers: true, | |
48 | matchBrackets: true, |
|
48 | matchBrackets: true, | |
49 | }); |
|
49 | }); | |
50 |
|
|
50 | IPython.dialog.modal({ | |
51 | autoOpen: true, |
|
51 | title: "Edit Cell Metadata", | |
52 | height: 300, |
|
52 | body: dialogform, | |
53 | width: 650, |
|
|||
54 | modal: true, |
|
|||
55 | buttons: { |
|
53 | buttons: { | |
56 |
"O |
|
54 | "OK": { class : "btn-primary", | |
|
55 | click: function() { | |||
57 | //validate json and set it |
|
56 | //validate json and set it | |
58 | try { |
|
57 | try { | |
59 | var json = JSON.parse(editor.getValue()); |
|
58 | var json = JSON.parse(editor.getValue()); | |
60 | cell.metadata = json; |
|
59 | cell.metadata = json; | |
61 | $( this ).dialog( "close" ); |
|
60 | } catch(e) { | |
62 | } |
|
|||
63 | catch(e) |
|
|||
64 | { |
|
|||
65 | error_div.text('Warning, invalid json, not saved'); |
|
61 | error_div.text('Warning, invalid json, not saved'); | |
|
62 | return false; | |||
66 | } |
|
63 | } | |
67 | }, |
|
64 | }}, | |
68 |
Cancel: |
|
65 | Cancel: {} | |
69 | $( this ).dialog( "close" ); |
|
|||
70 | } |
|
|||
71 | }, |
|
|||
72 | close: function() { |
|
|||
73 | //cleanup on close |
|
|||
74 | $(this).remove(); |
|
|||
75 | } |
|
66 | } | |
76 | }); |
|
67 | }); | |
77 | editor.refresh(); |
|
68 | editor.refresh(); | |
78 | } |
|
69 | } | |
79 |
|
70 | |||
80 | var add_raw_edit_button = function(div, cell) { |
|
71 | var add_raw_edit_button = function(div, cell) { | |
81 | var button_container = div |
|
72 | var button_container = div; | |
82 |
var button = $('< |
|
73 | var button = $('<button/>') | |
83 | .click(function(){raw_edit(cell); return false;}) |
|
74 | .addClass("btn btn-mini") | |
|
75 | .text("Raw Edit") | |||
|
76 | .click( function () { | |||
|
77 | raw_edit(cell); | |||
|
78 | return false; | |||
|
79 | }); | |||
84 | button_container.append(button); |
|
80 | button_container.append(button); | |
85 | } |
|
81 | } | |
86 |
|
82 | |||
87 | CellToolbar.register_callback('default.rawedit',add_raw_edit_button); |
|
83 | CellToolbar.register_callback('default.rawedit',add_raw_edit_button); | |
88 | var example_preset = [] |
|
84 | var example_preset = [] | |
89 | example_preset.push('default.rawedit'); |
|
85 | example_preset.push('default.rawedit'); | |
90 |
|
86 | |||
91 | CellToolbar.register_preset('Default',example_preset); |
|
87 | CellToolbar.register_preset('Default',example_preset); | |
92 | console.log('Default extension for metadata editing loaded.'); |
|
88 | console.log('Default extension for metadata editing loaded.'); | |
93 |
|
89 | |||
94 | }(IPython)); |
|
90 | }(IPython)); |
@@ -1,439 +1,440 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // CodeCell |
|
9 | // CodeCell | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 | /** |
|
11 | /** | |
12 | * An extendable module that provide base functionnality to create cell for notebook. |
|
12 | * An extendable module that provide base functionnality to create cell for notebook. | |
13 | * @module IPython |
|
13 | * @module IPython | |
14 | * @namespace IPython |
|
14 | * @namespace IPython | |
15 | * @submodule CodeCell |
|
15 | * @submodule CodeCell | |
16 | */ |
|
16 | */ | |
17 |
|
17 | |||
18 |
|
18 | |||
19 | /* local util for codemirror */ |
|
19 | /* local util for codemirror */ | |
20 | var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;} |
|
20 | var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;} | |
21 |
|
21 | |||
22 | /** |
|
22 | /** | |
23 | * |
|
23 | * | |
24 | * function to delete until previous non blanking space character |
|
24 | * function to delete until previous non blanking space character | |
25 | * or first multiple of 4 tabstop. |
|
25 | * or first multiple of 4 tabstop. | |
26 | * @private |
|
26 | * @private | |
27 | */ |
|
27 | */ | |
28 | CodeMirror.commands.delSpaceToPrevTabStop = function(cm){ |
|
28 | CodeMirror.commands.delSpaceToPrevTabStop = function(cm){ | |
29 | var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); |
|
29 | var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); | |
30 | if (!posEq(from, to)) {cm.replaceRange("", from, to); return} |
|
30 | if (!posEq(from, to)) {cm.replaceRange("", from, to); return} | |
31 | var cur = cm.getCursor(), line = cm.getLine(cur.line); |
|
31 | var cur = cm.getCursor(), line = cm.getLine(cur.line); | |
32 | var tabsize = cm.getOption('tabSize'); |
|
32 | var tabsize = cm.getOption('tabSize'); | |
33 | var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize; |
|
33 | var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize; | |
34 | var from = {ch:cur.ch-chToPrevTabStop,line:cur.line} |
|
34 | var from = {ch:cur.ch-chToPrevTabStop,line:cur.line} | |
35 | var select = cm.getRange(from,cur) |
|
35 | var select = cm.getRange(from,cur) | |
36 | if( select.match(/^\ +$/) != null){ |
|
36 | if( select.match(/^\ +$/) != null){ | |
37 | cm.replaceRange("",from,cur) |
|
37 | cm.replaceRange("",from,cur) | |
38 | } else { |
|
38 | } else { | |
39 | cm.deleteH(-1,"char") |
|
39 | cm.deleteH(-1,"char") | |
40 | } |
|
40 | } | |
41 | }; |
|
41 | }; | |
42 |
|
42 | |||
43 |
|
43 | |||
44 | var IPython = (function (IPython) { |
|
44 | var IPython = (function (IPython) { | |
45 | "use strict"; |
|
45 | "use strict"; | |
46 |
|
46 | |||
47 | var utils = IPython.utils; |
|
47 | var utils = IPython.utils; | |
48 | var key = IPython.utils.keycodes; |
|
48 | var key = IPython.utils.keycodes; | |
49 | CodeMirror.modeURL = "/static/components/codemirror/mode/%N/%N.js"; |
|
49 | CodeMirror.modeURL = "/static/components/codemirror/mode/%N/%N.js"; | |
50 |
|
50 | |||
51 | /** |
|
51 | /** | |
52 | * A Cell conceived to write code. |
|
52 | * A Cell conceived to write code. | |
53 | * |
|
53 | * | |
54 | * The kernel doesn't have to be set at creation time, in that case |
|
54 | * The kernel doesn't have to be set at creation time, in that case | |
55 | * it will be null and set_kernel has to be called later. |
|
55 | * it will be null and set_kernel has to be called later. | |
56 | * @class CodeCell |
|
56 | * @class CodeCell | |
57 | * @extends IPython.Cell |
|
57 | * @extends IPython.Cell | |
58 | * |
|
58 | * | |
59 | * @constructor |
|
59 | * @constructor | |
60 | * @param {Object|null} kernel |
|
60 | * @param {Object|null} kernel | |
61 | * @param {object|undefined} [options] |
|
61 | * @param {object|undefined} [options] | |
62 | * @param [options.cm_config] {object} config to pass to CodeMirror |
|
62 | * @param [options.cm_config] {object} config to pass to CodeMirror | |
63 | */ |
|
63 | */ | |
64 | var CodeCell = function (kernel, options) { |
|
64 | var CodeCell = function (kernel, options) { | |
65 | this.kernel = kernel || null; |
|
65 | this.kernel = kernel || null; | |
66 | this.code_mirror = null; |
|
66 | this.code_mirror = null; | |
67 | this.input_prompt_number = null; |
|
67 | this.input_prompt_number = null; | |
68 | this.collapsed = false; |
|
68 | this.collapsed = false; | |
69 | this.default_mode = 'ipython'; |
|
69 | this.default_mode = 'ipython'; | |
|
70 | this.cell_type = "code"; | |||
70 |
|
71 | |||
71 |
|
72 | |||
72 | var cm_overwrite_options = { |
|
73 | var cm_overwrite_options = { | |
73 | onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this) |
|
74 | onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this) | |
74 | }; |
|
75 | }; | |
75 |
|
76 | |||
76 | options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options}); |
|
77 | options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options}); | |
77 |
|
78 | |||
78 | IPython.Cell.apply(this,[options]); |
|
79 | IPython.Cell.apply(this,[options]); | |
79 |
|
80 | |||
80 | var that = this; |
|
81 | var that = this; | |
81 | this.element.focusout( |
|
82 | this.element.focusout( | |
82 | function() { that.auto_highlight(); } |
|
83 | function() { that.auto_highlight(); } | |
83 | ); |
|
84 | ); | |
84 | }; |
|
85 | }; | |
85 |
|
86 | |||
86 | CodeCell.options_default = { |
|
87 | CodeCell.options_default = { | |
87 | cm_config : { |
|
88 | cm_config : { | |
88 | extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"}, |
|
89 | extraKeys: {"Tab": "indentMore","Shift-Tab" : "indentLess",'Backspace':"delSpaceToPrevTabStop"}, | |
89 | mode: 'ipython', |
|
90 | mode: 'ipython', | |
90 | theme: 'ipython', |
|
91 | theme: 'ipython', | |
91 | matchBrackets: true |
|
92 | matchBrackets: true | |
92 | } |
|
93 | } | |
93 | }; |
|
94 | }; | |
94 |
|
95 | |||
95 |
|
96 | |||
96 | CodeCell.prototype = new IPython.Cell(); |
|
97 | CodeCell.prototype = new IPython.Cell(); | |
97 |
|
98 | |||
98 | /** |
|
99 | /** | |
99 | * @method auto_highlight |
|
100 | * @method auto_highlight | |
100 | */ |
|
101 | */ | |
101 | CodeCell.prototype.auto_highlight = function () { |
|
102 | CodeCell.prototype.auto_highlight = function () { | |
102 | this._auto_highlight(IPython.config.cell_magic_highlight) |
|
103 | this._auto_highlight(IPython.config.cell_magic_highlight) | |
103 | }; |
|
104 | }; | |
104 |
|
105 | |||
105 | /** @method create_element */ |
|
106 | /** @method create_element */ | |
106 | CodeCell.prototype.create_element = function () { |
|
107 | CodeCell.prototype.create_element = function () { | |
107 | IPython.Cell.prototype.create_element.apply(this, arguments); |
|
108 | IPython.Cell.prototype.create_element.apply(this, arguments); | |
108 |
|
109 | |||
109 | var cell = $('<div></div>').addClass('cell border-box-sizing code_cell'); |
|
110 | var cell = $('<div></div>').addClass('cell border-box-sizing code_cell'); | |
110 | cell.attr('tabindex','2'); |
|
111 | cell.attr('tabindex','2'); | |
111 |
|
112 | |||
112 | this.celltoolbar = new IPython.CellToolbar(this); |
|
113 | this.celltoolbar = new IPython.CellToolbar(this); | |
113 |
|
114 | |||
114 | var input = $('<div></div>').addClass('input'); |
|
115 | var input = $('<div></div>').addClass('input'); | |
115 | var vbox = $('<div/>').addClass('vbox box-flex1') |
|
116 | var vbox = $('<div/>').addClass('vbox box-flex1') | |
116 | input.append($('<div/>').addClass('prompt input_prompt')); |
|
117 | input.append($('<div/>').addClass('prompt input_prompt')); | |
117 | vbox.append(this.celltoolbar.element); |
|
118 | vbox.append(this.celltoolbar.element); | |
118 | var input_area = $('<div/>').addClass('input_area'); |
|
119 | var input_area = $('<div/>').addClass('input_area'); | |
119 | this.code_mirror = CodeMirror(input_area.get(0), this.cm_config); |
|
120 | this.code_mirror = CodeMirror(input_area.get(0), this.cm_config); | |
120 | $(this.code_mirror.getInputField()).attr("spellcheck", "false"); |
|
121 | $(this.code_mirror.getInputField()).attr("spellcheck", "false"); | |
121 | vbox.append(input_area); |
|
122 | vbox.append(input_area); | |
122 | input.append(vbox); |
|
123 | input.append(vbox); | |
123 | var output = $('<div></div>'); |
|
124 | var output = $('<div></div>'); | |
124 | cell.append(input).append(output); |
|
125 | cell.append(input).append(output); | |
125 | this.element = cell; |
|
126 | this.element = cell; | |
126 | this.output_area = new IPython.OutputArea(output, true); |
|
127 | this.output_area = new IPython.OutputArea(output, true); | |
127 |
|
128 | |||
128 | // construct a completer only if class exist |
|
129 | // construct a completer only if class exist | |
129 | // otherwise no print view |
|
130 | // otherwise no print view | |
130 | if (IPython.Completer !== undefined) |
|
131 | if (IPython.Completer !== undefined) | |
131 | { |
|
132 | { | |
132 | this.completer = new IPython.Completer(this); |
|
133 | this.completer = new IPython.Completer(this); | |
133 | } |
|
134 | } | |
134 | }; |
|
135 | }; | |
135 |
|
136 | |||
136 | /** |
|
137 | /** | |
137 | * This method gets called in CodeMirror's onKeyDown/onKeyPress |
|
138 | * This method gets called in CodeMirror's onKeyDown/onKeyPress | |
138 | * handlers and is used to provide custom key handling. Its return |
|
139 | * handlers and is used to provide custom key handling. Its return | |
139 | * value is used to determine if CodeMirror should ignore the event: |
|
140 | * value is used to determine if CodeMirror should ignore the event: | |
140 | * true = ignore, false = don't ignore. |
|
141 | * true = ignore, false = don't ignore. | |
141 | * @method handle_codemirror_keyevent |
|
142 | * @method handle_codemirror_keyevent | |
142 | */ |
|
143 | */ | |
143 | CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { |
|
144 | CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { | |
144 |
|
145 | |||
145 | if (this.read_only){ |
|
146 | if (this.read_only){ | |
146 | return false; |
|
147 | return false; | |
147 | } |
|
148 | } | |
148 |
|
149 | |||
149 | var that = this; |
|
150 | var that = this; | |
150 | // whatever key is pressed, first, cancel the tooltip request before |
|
151 | // whatever key is pressed, first, cancel the tooltip request before | |
151 | // they are sent, and remove tooltip if any, except for tab again |
|
152 | // they are sent, and remove tooltip if any, except for tab again | |
152 | if (event.type === 'keydown' && event.which != key.TAB ) { |
|
153 | if (event.type === 'keydown' && event.which != key.TAB ) { | |
153 | IPython.tooltip.remove_and_cancel_tooltip(); |
|
154 | IPython.tooltip.remove_and_cancel_tooltip(); | |
154 | }; |
|
155 | }; | |
155 |
|
156 | |||
156 | var cur = editor.getCursor(); |
|
157 | var cur = editor.getCursor(); | |
157 | if (event.keyCode === key.ENTER){ |
|
158 | if (event.keyCode === key.ENTER){ | |
158 | this.auto_highlight(); |
|
159 | this.auto_highlight(); | |
159 | } |
|
160 | } | |
160 |
|
161 | |||
161 | if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) { |
|
162 | if (event.keyCode === key.ENTER && (event.shiftKey || event.ctrlKey)) { | |
162 | // Always ignore shift-enter in CodeMirror as we handle it. |
|
163 | // Always ignore shift-enter in CodeMirror as we handle it. | |
163 | return true; |
|
164 | return true; | |
164 | } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) { |
|
165 | } else if (event.which === 40 && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) { | |
165 | // triger on keypress (!) otherwise inconsistent event.which depending on plateform |
|
166 | // triger on keypress (!) otherwise inconsistent event.which depending on plateform | |
166 | // browser and keyboard layout ! |
|
167 | // browser and keyboard layout ! | |
167 | // Pressing '(' , request tooltip, don't forget to reappend it |
|
168 | // Pressing '(' , request tooltip, don't forget to reappend it | |
168 | IPython.tooltip.pending(that); |
|
169 | IPython.tooltip.pending(that); | |
169 | } else if (event.which === key.UPARROW && event.type === 'keydown') { |
|
170 | } else if (event.which === key.UPARROW && event.type === 'keydown') { | |
170 | // If we are not at the top, let CM handle the up arrow and |
|
171 | // If we are not at the top, let CM handle the up arrow and | |
171 | // prevent the global keydown handler from handling it. |
|
172 | // prevent the global keydown handler from handling it. | |
172 | if (!that.at_top()) { |
|
173 | if (!that.at_top()) { | |
173 | event.stop(); |
|
174 | event.stop(); | |
174 | return false; |
|
175 | return false; | |
175 | } else { |
|
176 | } else { | |
176 | return true; |
|
177 | return true; | |
177 | }; |
|
178 | }; | |
178 | } else if (event.which === key.ESC) { |
|
179 | } else if (event.which === key.ESC) { | |
179 | IPython.tooltip.remove_and_cancel_tooltip(true); |
|
180 | IPython.tooltip.remove_and_cancel_tooltip(true); | |
180 | return true; |
|
181 | return true; | |
181 | } else if (event.which === key.DOWNARROW && event.type === 'keydown') { |
|
182 | } else if (event.which === key.DOWNARROW && event.type === 'keydown') { | |
182 | // If we are not at the bottom, let CM handle the down arrow and |
|
183 | // If we are not at the bottom, let CM handle the down arrow and | |
183 | // prevent the global keydown handler from handling it. |
|
184 | // prevent the global keydown handler from handling it. | |
184 | if (!that.at_bottom()) { |
|
185 | if (!that.at_bottom()) { | |
185 | event.stop(); |
|
186 | event.stop(); | |
186 | return false; |
|
187 | return false; | |
187 | } else { |
|
188 | } else { | |
188 | return true; |
|
189 | return true; | |
189 | }; |
|
190 | }; | |
190 | } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) { |
|
191 | } else if (event.keyCode === key.TAB && event.type == 'keydown' && event.shiftKey) { | |
191 | if (editor.somethingSelected()){ |
|
192 | if (editor.somethingSelected()){ | |
192 | var anchor = editor.getCursor("anchor"); |
|
193 | var anchor = editor.getCursor("anchor"); | |
193 | var head = editor.getCursor("head"); |
|
194 | var head = editor.getCursor("head"); | |
194 | if( anchor.line != head.line){ |
|
195 | if( anchor.line != head.line){ | |
195 | return false; |
|
196 | return false; | |
196 | } |
|
197 | } | |
197 | } |
|
198 | } | |
198 | IPython.tooltip.request(that); |
|
199 | IPython.tooltip.request(that); | |
199 | event.stop(); |
|
200 | event.stop(); | |
200 | return true; |
|
201 | return true; | |
201 | } else if (event.keyCode === key.TAB && event.type == 'keydown') { |
|
202 | } else if (event.keyCode === key.TAB && event.type == 'keydown') { | |
202 | // Tab completion. |
|
203 | // Tab completion. | |
203 | //Do not trim here because of tooltip |
|
204 | //Do not trim here because of tooltip | |
204 | if (editor.somethingSelected()){return false} |
|
205 | if (editor.somethingSelected()){return false} | |
205 | var pre_cursor = editor.getRange({line:cur.line,ch:0},cur); |
|
206 | var pre_cursor = editor.getRange({line:cur.line,ch:0},cur); | |
206 | if (pre_cursor.trim() === "") { |
|
207 | if (pre_cursor.trim() === "") { | |
207 | // Don't autocomplete if the part of the line before the cursor |
|
208 | // Don't autocomplete if the part of the line before the cursor | |
208 | // is empty. In this case, let CodeMirror handle indentation. |
|
209 | // is empty. In this case, let CodeMirror handle indentation. | |
209 | return false; |
|
210 | return false; | |
210 | } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) { |
|
211 | } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && IPython.config.tooltip_on_tab ) { | |
211 | IPython.tooltip.request(that); |
|
212 | IPython.tooltip.request(that); | |
212 | // Prevent the event from bubbling up. |
|
213 | // Prevent the event from bubbling up. | |
213 | event.stop(); |
|
214 | event.stop(); | |
214 | // Prevent CodeMirror from handling the tab. |
|
215 | // Prevent CodeMirror from handling the tab. | |
215 | return true; |
|
216 | return true; | |
216 | } else { |
|
217 | } else { | |
217 | event.stop(); |
|
218 | event.stop(); | |
218 | this.completer.startCompletion(); |
|
219 | this.completer.startCompletion(); | |
219 | return true; |
|
220 | return true; | |
220 | }; |
|
221 | }; | |
221 | } else { |
|
222 | } else { | |
222 | // keypress/keyup also trigger on TAB press, and we don't want to |
|
223 | // keypress/keyup also trigger on TAB press, and we don't want to | |
223 | // use those to disable tab completion. |
|
224 | // use those to disable tab completion. | |
224 | return false; |
|
225 | return false; | |
225 | }; |
|
226 | }; | |
226 | return false; |
|
227 | return false; | |
227 | }; |
|
228 | }; | |
228 |
|
229 | |||
229 |
|
230 | |||
230 | // Kernel related calls. |
|
231 | // Kernel related calls. | |
231 |
|
232 | |||
232 | CodeCell.prototype.set_kernel = function (kernel) { |
|
233 | CodeCell.prototype.set_kernel = function (kernel) { | |
233 | this.kernel = kernel; |
|
234 | this.kernel = kernel; | |
234 | } |
|
235 | } | |
235 |
|
236 | |||
236 | /** |
|
237 | /** | |
237 | * Execute current code cell to the kernel |
|
238 | * Execute current code cell to the kernel | |
238 | * @method execute |
|
239 | * @method execute | |
239 | */ |
|
240 | */ | |
240 | CodeCell.prototype.execute = function () { |
|
241 | CodeCell.prototype.execute = function () { | |
241 | this.output_area.clear_output(true, true, true); |
|
242 | this.output_area.clear_output(true, true, true); | |
242 | this.set_input_prompt('*'); |
|
243 | this.set_input_prompt('*'); | |
243 | this.element.addClass("running"); |
|
244 | this.element.addClass("running"); | |
244 | var callbacks = { |
|
245 | var callbacks = { | |
245 | 'execute_reply': $.proxy(this._handle_execute_reply, this), |
|
246 | 'execute_reply': $.proxy(this._handle_execute_reply, this), | |
246 | 'output': $.proxy(this.output_area.handle_output, this.output_area), |
|
247 | 'output': $.proxy(this.output_area.handle_output, this.output_area), | |
247 | 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area), |
|
248 | 'clear_output': $.proxy(this.output_area.handle_clear_output, this.output_area), | |
248 | 'set_next_input': $.proxy(this._handle_set_next_input, this), |
|
249 | 'set_next_input': $.proxy(this._handle_set_next_input, this), | |
249 | 'input_request': $.proxy(this._handle_input_request, this) |
|
250 | 'input_request': $.proxy(this._handle_input_request, this) | |
250 | }; |
|
251 | }; | |
251 | var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false}); |
|
252 | var msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false}); | |
252 | }; |
|
253 | }; | |
253 |
|
254 | |||
254 | /** |
|
255 | /** | |
255 | * @method _handle_execute_reply |
|
256 | * @method _handle_execute_reply | |
256 | * @private |
|
257 | * @private | |
257 | */ |
|
258 | */ | |
258 | CodeCell.prototype._handle_execute_reply = function (content) { |
|
259 | CodeCell.prototype._handle_execute_reply = function (content) { | |
259 | this.set_input_prompt(content.execution_count); |
|
260 | this.set_input_prompt(content.execution_count); | |
260 | this.element.removeClass("running"); |
|
261 | this.element.removeClass("running"); | |
261 | $([IPython.events]).trigger('set_dirty.Notebook', {value: true}); |
|
262 | $([IPython.events]).trigger('set_dirty.Notebook', {value: true}); | |
262 | } |
|
263 | } | |
263 |
|
264 | |||
264 | /** |
|
265 | /** | |
265 | * @method _handle_set_next_input |
|
266 | * @method _handle_set_next_input | |
266 | * @private |
|
267 | * @private | |
267 | */ |
|
268 | */ | |
268 | CodeCell.prototype._handle_set_next_input = function (text) { |
|
269 | CodeCell.prototype._handle_set_next_input = function (text) { | |
269 | var data = {'cell': this, 'text': text} |
|
270 | var data = {'cell': this, 'text': text} | |
270 | $([IPython.events]).trigger('set_next_input.Notebook', data); |
|
271 | $([IPython.events]).trigger('set_next_input.Notebook', data); | |
271 | } |
|
272 | } | |
272 |
|
273 | |||
273 | /** |
|
274 | /** | |
274 | * @method _handle_input_request |
|
275 | * @method _handle_input_request | |
275 | * @private |
|
276 | * @private | |
276 | */ |
|
277 | */ | |
277 | CodeCell.prototype._handle_input_request = function (content) { |
|
278 | CodeCell.prototype._handle_input_request = function (content) { | |
278 | this.output_area.append_raw_input(content); |
|
279 | this.output_area.append_raw_input(content); | |
279 | } |
|
280 | } | |
280 |
|
281 | |||
281 |
|
282 | |||
282 | // Basic cell manipulation. |
|
283 | // Basic cell manipulation. | |
283 |
|
284 | |||
284 | CodeCell.prototype.select = function () { |
|
285 | CodeCell.prototype.select = function () { | |
285 | IPython.Cell.prototype.select.apply(this); |
|
286 | IPython.Cell.prototype.select.apply(this); | |
286 | this.code_mirror.refresh(); |
|
287 | this.code_mirror.refresh(); | |
287 | this.code_mirror.focus(); |
|
288 | this.code_mirror.focus(); | |
288 | this.auto_highlight(); |
|
289 | this.auto_highlight(); | |
289 | // We used to need an additional refresh() after the focus, but |
|
290 | // We used to need an additional refresh() after the focus, but | |
290 | // it appears that this has been fixed in CM. This bug would show |
|
291 | // it appears that this has been fixed in CM. This bug would show | |
291 | // up on FF when a newly loaded markdown cell was edited. |
|
292 | // up on FF when a newly loaded markdown cell was edited. | |
292 | }; |
|
293 | }; | |
293 |
|
294 | |||
294 |
|
295 | |||
295 | CodeCell.prototype.select_all = function () { |
|
296 | CodeCell.prototype.select_all = function () { | |
296 | var start = {line: 0, ch: 0}; |
|
297 | var start = {line: 0, ch: 0}; | |
297 | var nlines = this.code_mirror.lineCount(); |
|
298 | var nlines = this.code_mirror.lineCount(); | |
298 | var last_line = this.code_mirror.getLine(nlines-1); |
|
299 | var last_line = this.code_mirror.getLine(nlines-1); | |
299 | var end = {line: nlines-1, ch: last_line.length}; |
|
300 | var end = {line: nlines-1, ch: last_line.length}; | |
300 | this.code_mirror.setSelection(start, end); |
|
301 | this.code_mirror.setSelection(start, end); | |
301 | }; |
|
302 | }; | |
302 |
|
303 | |||
303 |
|
304 | |||
304 | CodeCell.prototype.collapse = function () { |
|
305 | CodeCell.prototype.collapse = function () { | |
305 | this.collapsed = true; |
|
306 | this.collapsed = true; | |
306 | this.output_area.collapse(); |
|
307 | this.output_area.collapse(); | |
307 | }; |
|
308 | }; | |
308 |
|
309 | |||
309 |
|
310 | |||
310 | CodeCell.prototype.expand = function () { |
|
311 | CodeCell.prototype.expand = function () { | |
311 | this.collapsed = false; |
|
312 | this.collapsed = false; | |
312 | this.output_area.expand(); |
|
313 | this.output_area.expand(); | |
313 | }; |
|
314 | }; | |
314 |
|
315 | |||
315 |
|
316 | |||
316 | CodeCell.prototype.toggle_output = function () { |
|
317 | CodeCell.prototype.toggle_output = function () { | |
317 | this.collapsed = Boolean(1 - this.collapsed); |
|
318 | this.collapsed = Boolean(1 - this.collapsed); | |
318 | this.output_area.toggle_output(); |
|
319 | this.output_area.toggle_output(); | |
319 | }; |
|
320 | }; | |
320 |
|
321 | |||
321 |
|
322 | |||
322 | CodeCell.prototype.toggle_output_scroll = function () { |
|
323 | CodeCell.prototype.toggle_output_scroll = function () { | |
323 | this.output_area.toggle_scroll(); |
|
324 | this.output_area.toggle_scroll(); | |
324 | }; |
|
325 | }; | |
325 |
|
326 | |||
326 |
|
327 | |||
327 | CodeCell.input_prompt_classical = function (prompt_value, lines_number) { |
|
328 | CodeCell.input_prompt_classical = function (prompt_value, lines_number) { | |
328 | var ns = prompt_value || " "; |
|
329 | var ns = prompt_value || " "; | |
329 | return 'In [' + ns + ']:' |
|
330 | return 'In [' + ns + ']:' | |
330 | }; |
|
331 | }; | |
331 |
|
332 | |||
332 | CodeCell.input_prompt_continuation = function (prompt_value, lines_number) { |
|
333 | CodeCell.input_prompt_continuation = function (prompt_value, lines_number) { | |
333 | var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)]; |
|
334 | var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)]; | |
334 | for(var i=1; i < lines_number; i++){html.push(['...:'])}; |
|
335 | for(var i=1; i < lines_number; i++){html.push(['...:'])}; | |
335 | return html.join('</br>') |
|
336 | return html.join('</br>') | |
336 | }; |
|
337 | }; | |
337 |
|
338 | |||
338 | CodeCell.input_prompt_function = CodeCell.input_prompt_classical; |
|
339 | CodeCell.input_prompt_function = CodeCell.input_prompt_classical; | |
339 |
|
340 | |||
340 |
|
341 | |||
341 | CodeCell.prototype.set_input_prompt = function (number) { |
|
342 | CodeCell.prototype.set_input_prompt = function (number) { | |
342 | var nline = 1 |
|
343 | var nline = 1 | |
343 | if( this.code_mirror != undefined) { |
|
344 | if( this.code_mirror != undefined) { | |
344 | nline = this.code_mirror.lineCount(); |
|
345 | nline = this.code_mirror.lineCount(); | |
345 | } |
|
346 | } | |
346 | this.input_prompt_number = number; |
|
347 | this.input_prompt_number = number; | |
347 | var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline); |
|
348 | var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline); | |
348 | this.element.find('div.input_prompt').html(prompt_html); |
|
349 | this.element.find('div.input_prompt').html(prompt_html); | |
349 | }; |
|
350 | }; | |
350 |
|
351 | |||
351 |
|
352 | |||
352 | CodeCell.prototype.clear_input = function () { |
|
353 | CodeCell.prototype.clear_input = function () { | |
353 | this.code_mirror.setValue(''); |
|
354 | this.code_mirror.setValue(''); | |
354 | }; |
|
355 | }; | |
355 |
|
356 | |||
356 |
|
357 | |||
357 | CodeCell.prototype.get_text = function () { |
|
358 | CodeCell.prototype.get_text = function () { | |
358 | return this.code_mirror.getValue(); |
|
359 | return this.code_mirror.getValue(); | |
359 | }; |
|
360 | }; | |
360 |
|
361 | |||
361 |
|
362 | |||
362 | CodeCell.prototype.set_text = function (code) { |
|
363 | CodeCell.prototype.set_text = function (code) { | |
363 | return this.code_mirror.setValue(code); |
|
364 | return this.code_mirror.setValue(code); | |
364 | }; |
|
365 | }; | |
365 |
|
366 | |||
366 |
|
367 | |||
367 | CodeCell.prototype.at_top = function () { |
|
368 | CodeCell.prototype.at_top = function () { | |
368 | var cursor = this.code_mirror.getCursor(); |
|
369 | var cursor = this.code_mirror.getCursor(); | |
369 | if (cursor.line === 0 && cursor.ch === 0) { |
|
370 | if (cursor.line === 0 && cursor.ch === 0) { | |
370 | return true; |
|
371 | return true; | |
371 | } else { |
|
372 | } else { | |
372 | return false; |
|
373 | return false; | |
373 | } |
|
374 | } | |
374 | }; |
|
375 | }; | |
375 |
|
376 | |||
376 |
|
377 | |||
377 | CodeCell.prototype.at_bottom = function () { |
|
378 | CodeCell.prototype.at_bottom = function () { | |
378 | var cursor = this.code_mirror.getCursor(); |
|
379 | var cursor = this.code_mirror.getCursor(); | |
379 | if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) { |
|
380 | if (cursor.line === (this.code_mirror.lineCount()-1) && cursor.ch === this.code_mirror.getLine(cursor.line).length) { | |
380 | return true; |
|
381 | return true; | |
381 | } else { |
|
382 | } else { | |
382 | return false; |
|
383 | return false; | |
383 | } |
|
384 | } | |
384 | }; |
|
385 | }; | |
385 |
|
386 | |||
386 |
|
387 | |||
387 | CodeCell.prototype.clear_output = function (stdout, stderr, other) { |
|
388 | CodeCell.prototype.clear_output = function (stdout, stderr, other) { | |
388 | this.output_area.clear_output(stdout, stderr, other); |
|
389 | this.output_area.clear_output(stdout, stderr, other); | |
389 | }; |
|
390 | }; | |
390 |
|
391 | |||
391 |
|
392 | |||
392 | // JSON serialization |
|
393 | // JSON serialization | |
393 |
|
394 | |||
394 | CodeCell.prototype.fromJSON = function (data) { |
|
395 | CodeCell.prototype.fromJSON = function (data) { | |
395 | IPython.Cell.prototype.fromJSON.apply(this, arguments); |
|
396 | IPython.Cell.prototype.fromJSON.apply(this, arguments); | |
396 | if (data.cell_type === 'code') { |
|
397 | if (data.cell_type === 'code') { | |
397 | if (data.input !== undefined) { |
|
398 | if (data.input !== undefined) { | |
398 | this.set_text(data.input); |
|
399 | this.set_text(data.input); | |
399 | // make this value the starting point, so that we can only undo |
|
400 | // make this value the starting point, so that we can only undo | |
400 | // to this state, instead of a blank cell |
|
401 | // to this state, instead of a blank cell | |
401 | this.code_mirror.clearHistory(); |
|
402 | this.code_mirror.clearHistory(); | |
402 | this.auto_highlight(); |
|
403 | this.auto_highlight(); | |
403 | } |
|
404 | } | |
404 | if (data.prompt_number !== undefined) { |
|
405 | if (data.prompt_number !== undefined) { | |
405 | this.set_input_prompt(data.prompt_number); |
|
406 | this.set_input_prompt(data.prompt_number); | |
406 | } else { |
|
407 | } else { | |
407 | this.set_input_prompt(); |
|
408 | this.set_input_prompt(); | |
408 | }; |
|
409 | }; | |
409 | this.output_area.fromJSON(data.outputs); |
|
410 | this.output_area.fromJSON(data.outputs); | |
410 | if (data.collapsed !== undefined) { |
|
411 | if (data.collapsed !== undefined) { | |
411 | if (data.collapsed) { |
|
412 | if (data.collapsed) { | |
412 | this.collapse(); |
|
413 | this.collapse(); | |
413 | } else { |
|
414 | } else { | |
414 | this.expand(); |
|
415 | this.expand(); | |
415 | }; |
|
416 | }; | |
416 | }; |
|
417 | }; | |
417 | }; |
|
418 | }; | |
418 | }; |
|
419 | }; | |
419 |
|
420 | |||
420 |
|
421 | |||
421 | CodeCell.prototype.toJSON = function () { |
|
422 | CodeCell.prototype.toJSON = function () { | |
422 | var data = IPython.Cell.prototype.toJSON.apply(this); |
|
423 | var data = IPython.Cell.prototype.toJSON.apply(this); | |
423 | data.input = this.get_text(); |
|
424 | data.input = this.get_text(); | |
424 | data.cell_type = 'code'; |
|
425 | data.cell_type = 'code'; | |
425 | if (this.input_prompt_number) { |
|
426 | if (this.input_prompt_number) { | |
426 | data.prompt_number = this.input_prompt_number; |
|
427 | data.prompt_number = this.input_prompt_number; | |
427 | }; |
|
428 | }; | |
428 | var outputs = this.output_area.toJSON(); |
|
429 | var outputs = this.output_area.toJSON(); | |
429 | data.outputs = outputs; |
|
430 | data.outputs = outputs; | |
430 | data.language = 'python'; |
|
431 | data.language = 'python'; | |
431 | data.collapsed = this.collapsed; |
|
432 | data.collapsed = this.collapsed; | |
432 | return data; |
|
433 | return data; | |
433 | }; |
|
434 | }; | |
434 |
|
435 | |||
435 |
|
436 | |||
436 | IPython.CodeCell = CodeCell; |
|
437 | IPython.CodeCell = CodeCell; | |
437 |
|
438 | |||
438 | return IPython; |
|
439 | return IPython; | |
439 | }(IPython)); |
|
440 | }(IPython)); |
@@ -1,62 +1,62 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Layout |
|
9 | // Layout | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | var IPython = (function (IPython) { |
|
12 | var IPython = (function (IPython) { | |
13 |
|
13 | |||
14 | var LayoutManager = function () { |
|
14 | var LayoutManager = function () { | |
15 | this.bind_events(); |
|
15 | this.bind_events(); | |
16 | }; |
|
16 | }; | |
17 |
|
17 | |||
18 |
|
18 | |||
19 | LayoutManager.prototype.bind_events = function () { |
|
19 | LayoutManager.prototype.bind_events = function () { | |
20 | $(window).resize($.proxy(this.do_resize,this)); |
|
20 | $(window).resize($.proxy(this.do_resize,this)); | |
21 | }; |
|
21 | }; | |
22 |
|
22 | |||
23 | LayoutManager.prototype.app_height = function() { |
|
23 | LayoutManager.prototype.app_height = function() { | |
24 | var win = $(window); |
|
24 | var win = $(window); | |
25 | var w = win.width(); |
|
25 | var w = win.width(); | |
26 | var h = win.height(); |
|
26 | var h = win.height(); | |
27 | var header_height; |
|
27 | var header_height; | |
28 | if ($('div#header').css('display') === 'none') { |
|
28 | if ($('div#header').css('display') === 'none') { | |
29 | header_height = 0; |
|
29 | header_height = 0; | |
30 | } else { |
|
30 | } else { | |
31 | header_height = $('div#header').outerHeight(true); |
|
31 | header_height = $('div#header').outerHeight(true); | |
32 | } |
|
32 | } | |
33 | var menubar_height = $('div#menubar').outerHeight(true); |
|
33 | var menubar_height = $('div#menubar').outerHeight(true); | |
34 | var toolbar_height; |
|
34 | var toolbar_height; | |
35 | if ($('div#maintoolbar').css('display') === 'none') { |
|
35 | if ($('div#maintoolbar').css('display') === 'none') { | |
36 | toolbar_height = 0; |
|
36 | toolbar_height = 0; | |
37 | } else { |
|
37 | } else { | |
38 | toolbar_height = $('div#maintoolbar').outerHeight(true); |
|
38 | toolbar_height = $('div#maintoolbar').outerHeight(true); | |
39 | } |
|
39 | } | |
40 | return h-header_height-menubar_height-toolbar_height; // content height |
|
40 | return h-header_height-menubar_height-toolbar_height; // content height | |
41 | } |
|
41 | } | |
42 |
|
42 | |||
43 | LayoutManager.prototype.do_resize = function () { |
|
43 | LayoutManager.prototype.do_resize = function () { | |
44 | var app_height = this.app_height() // content height |
|
44 | var app_height = this.app_height() // content height | |
45 |
|
45 | |||
46 | $('#ipython-main-app').height(app_height); // content+padding+border height |
|
46 | $('#ipython-main-app').height(app_height); // content+padding+border height | |
47 |
|
47 | |||
48 | var pager_height = IPython.pager.percentage_height*app_height; |
|
48 | var pager_height = IPython.pager.percentage_height*app_height; | |
49 | var pager_splitter_height = $('div#pager_splitter').outerHeight(true); |
|
49 | var pager_splitter_height = $('div#pager_splitter').outerHeight(true); | |
50 |
$('div#pager'). |
|
50 | $('div#pager').outerHeight(pager_height); | |
51 | if (IPython.pager.expanded) { |
|
51 | if (IPython.pager.expanded) { | |
52 |
$('div#notebook'). |
|
52 | $('div#notebook').outerHeight(app_height-pager_height-pager_splitter_height); | |
53 | } else { |
|
53 | } else { | |
54 |
$('div#notebook'). |
|
54 | $('div#notebook').outerHeight(app_height-pager_splitter_height); | |
55 | } |
|
55 | } | |
56 | }; |
|
56 | }; | |
57 |
|
57 | |||
58 | IPython.LayoutManager = LayoutManager; |
|
58 | IPython.LayoutManager = LayoutManager; | |
59 |
|
59 | |||
60 | return IPython; |
|
60 | return IPython; | |
61 |
|
61 | |||
62 | }(IPython)); |
|
62 | }(IPython)); |
@@ -1,125 +1,123 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2011 The IPython Development Team |
|
2 | // Copyright (C) 2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // On document ready |
|
9 | // On document ready | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 | "use strict"; |
|
11 | "use strict"; | |
12 |
|
12 | |||
13 | // for the time beeing, we have to pass marked as a parameter here, |
|
13 | // for the time beeing, we have to pass marked as a parameter here, | |
14 | // as injecting require.js make marked not to put itself in the globals, |
|
14 | // as injecting require.js make marked not to put itself in the globals, | |
15 | // which make both this file fail at setting marked configuration, and textcell.js |
|
15 | // which make both this file fail at setting marked configuration, and textcell.js | |
16 | // which search marked into global. |
|
16 | // which search marked into global. | |
17 | require(['components/marked/lib/marked'], |
|
17 | require(['components/marked/lib/marked'], | |
18 |
|
18 | |||
19 | function (marked) { |
|
19 | function (marked) { | |
20 |
|
20 | |||
21 | window.marked = marked |
|
21 | window.marked = marked | |
22 |
|
22 | |||
23 | // monkey patch CM to be able to syntax highlight cell magics |
|
23 | // monkey patch CM to be able to syntax highlight cell magics | |
24 | // bug reported upstream, |
|
24 | // bug reported upstream, | |
25 | // see https://github.com/marijnh/CodeMirror2/issues/670 |
|
25 | // see https://github.com/marijnh/CodeMirror2/issues/670 | |
26 | if(CodeMirror.getMode(1,'text/plain').indent == undefined ){ |
|
26 | if(CodeMirror.getMode(1,'text/plain').indent == undefined ){ | |
27 | console.log('patching CM for undefined indent'); |
|
27 | console.log('patching CM for undefined indent'); | |
28 | CodeMirror.modes.null = function() { |
|
28 | CodeMirror.modes.null = function() { | |
29 | return {token: function(stream) {stream.skipToEnd();},indent : function(){return 0}} |
|
29 | return {token: function(stream) {stream.skipToEnd();},indent : function(){return 0}} | |
30 | } |
|
30 | } | |
31 | } |
|
31 | } | |
32 |
|
32 | |||
33 | CodeMirror.patchedGetMode = function(config, mode){ |
|
33 | CodeMirror.patchedGetMode = function(config, mode){ | |
34 | var cmmode = CodeMirror.getMode(config, mode); |
|
34 | var cmmode = CodeMirror.getMode(config, mode); | |
35 | if(cmmode.indent == null) |
|
35 | if(cmmode.indent == null) | |
36 | { |
|
36 | { | |
37 | console.log('patch mode "' , mode, '" on the fly'); |
|
37 | console.log('patch mode "' , mode, '" on the fly'); | |
38 | cmmode.indent = function(){return 0}; |
|
38 | cmmode.indent = function(){return 0}; | |
39 | } |
|
39 | } | |
40 | return cmmode; |
|
40 | return cmmode; | |
41 | } |
|
41 | } | |
42 | // end monkey patching CodeMirror |
|
42 | // end monkey patching CodeMirror | |
43 |
|
43 | |||
44 | IPython.mathjaxutils.init(); |
|
44 | IPython.mathjaxutils.init(); | |
45 |
|
45 | |||
46 | IPython.read_only = $('body').data('readOnly') === 'True'; |
|
46 | IPython.read_only = $('body').data('readOnly') === 'True'; | |
47 | $('#ipython-main-app').addClass('border-box-sizing'); |
|
47 | $('#ipython-main-app').addClass('border-box-sizing'); | |
48 | $('div#notebook_panel').addClass('border-box-sizing'); |
|
48 | $('div#notebook_panel').addClass('border-box-sizing'); | |
49 | // The header's bottom border is provided by the menu bar so we remove it. |
|
|||
50 | $('div#header').css('border-bottom-style','none'); |
|
|||
51 |
|
49 | |||
52 | var baseProjectUrl = $('body').data('baseProjectUrl') |
|
50 | var baseProjectUrl = $('body').data('baseProjectUrl') | |
53 |
|
51 | |||
54 | IPython.page = new IPython.Page(); |
|
52 | IPython.page = new IPython.Page(); | |
55 | IPython.layout_manager = new IPython.LayoutManager(); |
|
53 | IPython.layout_manager = new IPython.LayoutManager(); | |
56 | IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter'); |
|
54 | IPython.pager = new IPython.Pager('div#pager', 'div#pager_splitter'); | |
57 | IPython.quick_help = new IPython.QuickHelp(); |
|
55 | IPython.quick_help = new IPython.QuickHelp(); | |
58 | IPython.login_widget = new IPython.LoginWidget('span#login_widget',{baseProjectUrl:baseProjectUrl}); |
|
56 | IPython.login_widget = new IPython.LoginWidget('span#login_widget',{baseProjectUrl:baseProjectUrl}); | |
59 | IPython.notebook = new IPython.Notebook('div#notebook',{baseProjectUrl:baseProjectUrl, read_only:IPython.read_only}); |
|
57 | IPython.notebook = new IPython.Notebook('div#notebook',{baseProjectUrl:baseProjectUrl, read_only:IPython.read_only}); | |
60 | IPython.save_widget = new IPython.SaveWidget('span#save_widget'); |
|
58 | IPython.save_widget = new IPython.SaveWidget('span#save_widget'); | |
61 | IPython.menubar = new IPython.MenuBar('#menubar',{baseProjectUrl:baseProjectUrl}) |
|
59 | IPython.menubar = new IPython.MenuBar('#menubar',{baseProjectUrl:baseProjectUrl}) | |
62 | IPython.toolbar = new IPython.MainToolBar('#maintoolbar') |
|
60 | IPython.toolbar = new IPython.MainToolBar('#maintoolbar-container') | |
63 | IPython.tooltip = new IPython.Tooltip() |
|
61 | IPython.tooltip = new IPython.Tooltip() | |
64 | IPython.notification_area = new IPython.NotificationArea('#notification_area') |
|
62 | IPython.notification_area = new IPython.NotificationArea('#notification_area') | |
65 | IPython.notification_area.init_notification_widgets(); |
|
63 | IPython.notification_area.init_notification_widgets(); | |
66 |
|
64 | |||
67 | IPython.layout_manager.do_resize(); |
|
65 | IPython.layout_manager.do_resize(); | |
68 |
|
66 | |||
69 | $('body').append('<div id="fonttest"><pre><span id="test1">x</span>'+ |
|
67 | $('body').append('<div id="fonttest"><pre><span id="test1">x</span>'+ | |
70 | '<span id="test2" style="font-weight: bold;">x</span>'+ |
|
68 | '<span id="test2" style="font-weight: bold;">x</span>'+ | |
71 | '<span id="test3" style="font-style: italic;">x</span></pre></div>') |
|
69 | '<span id="test3" style="font-style: italic;">x</span></pre></div>') | |
72 | var nh = $('#test1').innerHeight(); |
|
70 | var nh = $('#test1').innerHeight(); | |
73 | var bh = $('#test2').innerHeight(); |
|
71 | var bh = $('#test2').innerHeight(); | |
74 | var ih = $('#test3').innerHeight(); |
|
72 | var ih = $('#test3').innerHeight(); | |
75 | if(nh != bh || nh != ih) { |
|
73 | if(nh != bh || nh != ih) { | |
76 | $('head').append('<style>.CodeMirror span { vertical-align: bottom; }</style>'); |
|
74 | $('head').append('<style>.CodeMirror span { vertical-align: bottom; }</style>'); | |
77 | } |
|
75 | } | |
78 | $('#fonttest').remove(); |
|
76 | $('#fonttest').remove(); | |
79 |
|
77 | |||
80 | if(IPython.read_only){ |
|
78 | if(IPython.read_only){ | |
81 | // hide various elements from read-only view |
|
79 | // hide various elements from read-only view | |
82 | $('div#pager').remove(); |
|
80 | $('div#pager').remove(); | |
83 | $('div#pager_splitter').remove(); |
|
81 | $('div#pager_splitter').remove(); | |
84 |
|
82 | |||
85 | // set the notebook name field as not modifiable |
|
83 | // set the notebook name field as not modifiable | |
86 | $('#notebook_name').attr('disabled','disabled') |
|
84 | $('#notebook_name').attr('disabled','disabled') | |
87 | } |
|
85 | } | |
88 |
|
86 | |||
89 | IPython.page.show(); |
|
87 | IPython.page.show(); | |
90 |
|
88 | |||
91 | IPython.layout_manager.do_resize(); |
|
89 | IPython.layout_manager.do_resize(); | |
92 | var first_load = function () { |
|
90 | var first_load = function () { | |
93 | IPython.layout_manager.do_resize(); |
|
91 | IPython.layout_manager.do_resize(); | |
94 | var hash = document.location.hash; |
|
92 | var hash = document.location.hash; | |
95 | if (hash) { |
|
93 | if (hash) { | |
96 | document.location.hash = ''; |
|
94 | document.location.hash = ''; | |
97 | document.location.hash = hash; |
|
95 | document.location.hash = hash; | |
98 | } |
|
96 | } | |
99 | IPython.notebook.set_autosave_interval(IPython.notebook.minimum_autosave_interval); |
|
97 | IPython.notebook.set_autosave_interval(IPython.notebook.minimum_autosave_interval); | |
100 | // only do this once |
|
98 | // only do this once | |
101 | $([IPython.events]).off('notebook_loaded.Notebook', first_load); |
|
99 | $([IPython.events]).off('notebook_loaded.Notebook', first_load); | |
102 | }; |
|
100 | }; | |
103 |
|
101 | |||
104 | $([IPython.events]).on('notebook_loaded.Notebook', first_load); |
|
102 | $([IPython.events]).on('notebook_loaded.Notebook', first_load); | |
105 | IPython.notebook.load_notebook($('body').data('notebookId')); |
|
103 | IPython.notebook.load_notebook($('body').data('notebookId')); | |
106 |
|
104 | |||
107 | if (marked) { |
|
105 | if (marked) { | |
108 | marked.setOptions({ |
|
106 | marked.setOptions({ | |
109 | gfm : true, |
|
107 | gfm : true, | |
110 | tables: true, |
|
108 | tables: true, | |
111 | langPrefix: "language-", |
|
109 | langPrefix: "language-", | |
112 | highlight: function(code, lang) { |
|
110 | highlight: function(code, lang) { | |
113 | var highlighted; |
|
111 | var highlighted; | |
114 | try { |
|
112 | try { | |
115 | highlighted = hljs.highlight(lang, code, false); |
|
113 | highlighted = hljs.highlight(lang, code, false); | |
116 | } catch(err) { |
|
114 | } catch(err) { | |
117 | highlighted = hljs.highlightAuto(code); |
|
115 | highlighted = hljs.highlightAuto(code); | |
118 | } |
|
116 | } | |
119 | return highlighted.value; |
|
117 | return highlighted.value; | |
120 | } |
|
118 | } | |
121 | }) |
|
119 | }) | |
122 | } |
|
120 | } | |
123 | } |
|
121 | } | |
124 |
|
122 | |||
125 | ); |
|
123 | ); |
@@ -1,206 +1,206 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2011 The IPython Development Team |
|
2 | // Copyright (C) 2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // ToolBar |
|
9 | // ToolBar | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | var IPython = (function (IPython) { |
|
12 | var IPython = (function (IPython) { | |
13 |
|
13 | |||
14 | var MainToolBar = function (selector) { |
|
14 | var MainToolBar = function (selector) { | |
15 | IPython.ToolBar.apply(this, arguments); |
|
15 | IPython.ToolBar.apply(this, arguments); | |
16 | this.construct(); |
|
16 | this.construct(); | |
17 | this.add_celltype_list(); |
|
17 | this.add_celltype_list(); | |
18 | this.add_celltoolbar_list(); |
|
18 | this.add_celltoolbar_list(); | |
19 | this.bind_events(); |
|
19 | this.bind_events(); | |
20 | }; |
|
20 | }; | |
21 |
|
21 | |||
22 | MainToolBar.prototype = new IPython.ToolBar(); |
|
22 | MainToolBar.prototype = new IPython.ToolBar(); | |
23 |
|
23 | |||
24 | MainToolBar.prototype.construct = function () { |
|
24 | MainToolBar.prototype.construct = function () { | |
25 | this.add_buttons_group([ |
|
25 | this.add_buttons_group([ | |
26 | { |
|
26 | { | |
27 | id : 'save_b', |
|
27 | id : 'save_b', | |
28 | label : 'Save and Checkpoint', |
|
28 | label : 'Save and Checkpoint', | |
29 |
icon : ' |
|
29 | icon : 'icon-hdd', | |
30 | callback : function () { |
|
30 | callback : function () { | |
31 | IPython.notebook.save_checkpoint(); |
|
31 | IPython.notebook.save_checkpoint(); | |
32 | } |
|
32 | } | |
33 | } |
|
33 | } | |
34 | ]); |
|
34 | ]); | |
35 | this.add_buttons_group([ |
|
35 | this.add_buttons_group([ | |
36 | { |
|
36 | { | |
37 | id : 'cut_b', |
|
37 | id : 'cut_b', | |
38 | label : 'Cut Cell', |
|
38 | label : 'Cut Cell', | |
39 |
icon : ' |
|
39 | icon : 'icon-cut', | |
40 | callback : function () { |
|
40 | callback : function () { | |
41 | IPython.notebook.cut_cell(); |
|
41 | IPython.notebook.cut_cell(); | |
42 | } |
|
42 | } | |
43 | }, |
|
43 | }, | |
44 | { |
|
44 | { | |
45 | id : 'copy_b', |
|
45 | id : 'copy_b', | |
46 | label : 'Copy Cell', |
|
46 | label : 'Copy Cell', | |
47 |
icon : ' |
|
47 | icon : 'icon-copy', | |
48 | callback : function () { |
|
48 | callback : function () { | |
49 | IPython.notebook.copy_cell(); |
|
49 | IPython.notebook.copy_cell(); | |
50 | } |
|
50 | } | |
51 | }, |
|
51 | }, | |
52 | { |
|
52 | { | |
53 | id : 'paste_b', |
|
53 | id : 'paste_b', | |
54 | label : 'Paste Cell Below', |
|
54 | label : 'Paste Cell Below', | |
55 |
icon : ' |
|
55 | icon : 'icon-paste', | |
56 | callback : function () { |
|
56 | callback : function () { | |
57 | IPython.notebook.paste_cell_below(); |
|
57 | IPython.notebook.paste_cell_below(); | |
58 | } |
|
58 | } | |
59 | } |
|
59 | } | |
60 | ],'cut_copy_paste'); |
|
60 | ],'cut_copy_paste'); | |
61 |
|
61 | |||
62 | this.add_buttons_group([ |
|
62 | this.add_buttons_group([ | |
63 | { |
|
63 | { | |
64 | id : 'move_up_b', |
|
64 | id : 'move_up_b', | |
65 | label : 'Move Cell Up', |
|
65 | label : 'Move Cell Up', | |
66 |
icon : ' |
|
66 | icon : 'icon-arrow-up', | |
67 | callback : function () { |
|
67 | callback : function () { | |
68 | IPython.notebook.move_cell_up(); |
|
68 | IPython.notebook.move_cell_up(); | |
69 | } |
|
69 | } | |
70 | }, |
|
70 | }, | |
71 | { |
|
71 | { | |
72 | id : 'move_down_b', |
|
72 | id : 'move_down_b', | |
73 | label : 'Move Cell Down', |
|
73 | label : 'Move Cell Down', | |
74 |
icon : ' |
|
74 | icon : 'icon-arrow-down', | |
75 | callback : function () { |
|
75 | callback : function () { | |
76 | IPython.notebook.move_cell_down(); |
|
76 | IPython.notebook.move_cell_down(); | |
77 | } |
|
77 | } | |
78 | } |
|
78 | } | |
79 | ],'move_up_down'); |
|
79 | ],'move_up_down'); | |
80 |
|
80 | |||
81 | this.add_buttons_group([ |
|
81 | this.add_buttons_group([ | |
82 | { |
|
82 | { | |
83 | id : 'insert_above_b', |
|
83 | id : 'insert_above_b', | |
84 | label : 'Insert Cell Above', |
|
84 | label : 'Insert Cell Above', | |
85 |
icon : ' |
|
85 | icon : 'icon-circle-arrow-up', | |
86 | callback : function () { |
|
86 | callback : function () { | |
87 | IPython.notebook.insert_cell_above('code'); |
|
87 | IPython.notebook.insert_cell_above('code'); | |
88 | } |
|
88 | } | |
89 | }, |
|
89 | }, | |
90 | { |
|
90 | { | |
91 | id : 'insert_below_b', |
|
91 | id : 'insert_below_b', | |
92 | label : 'Insert Cell Below', |
|
92 | label : 'Insert Cell Below', | |
93 |
icon : ' |
|
93 | icon : 'icon-circle-arrow-down', | |
94 | callback : function () { |
|
94 | callback : function () { | |
95 | IPython.notebook.insert_cell_below('code'); |
|
95 | IPython.notebook.insert_cell_below('code'); | |
96 | } |
|
96 | } | |
97 | } |
|
97 | } | |
98 | ],'insert_above_below'); |
|
98 | ],'insert_above_below'); | |
99 |
|
99 | |||
100 | this.add_buttons_group([ |
|
100 | this.add_buttons_group([ | |
101 | { |
|
101 | { | |
102 | id : 'run_b', |
|
102 | id : 'run_b', | |
103 | label : 'Run Cell', |
|
103 | label : 'Run Cell', | |
104 |
icon : ' |
|
104 | icon : 'icon-play', | |
105 | callback : function () { |
|
105 | callback : function () { | |
106 | IPython.notebook.execute_selected_cell(); |
|
106 | IPython.notebook.execute_selected_cell(); | |
107 | } |
|
107 | } | |
108 | }, |
|
108 | }, | |
109 | { |
|
109 | { | |
110 | id : 'interrupt_b', |
|
110 | id : 'interrupt_b', | |
111 | label : 'Interrupt', |
|
111 | label : 'Interrupt', | |
112 |
icon : ' |
|
112 | icon : 'icon-stop', | |
113 | callback : function () { |
|
113 | callback : function () { | |
114 | IPython.notebook.kernel.interrupt(); |
|
114 | IPython.notebook.kernel.interrupt(); | |
115 | } |
|
115 | } | |
116 | } |
|
116 | } | |
117 | ],'run_int'); |
|
117 | ],'run_int'); | |
118 | }; |
|
118 | }; | |
119 |
|
119 | |||
120 | MainToolBar.prototype.add_celltype_list = function () { |
|
120 | MainToolBar.prototype.add_celltype_list = function () { | |
121 | this.element |
|
121 | this.element | |
122 | .append($('<select/>') |
|
122 | .append($('<select/>') | |
123 | .attr('id','cell_type') |
|
123 | .attr('id','cell_type') | |
124 | .addClass('ui-widget-content') |
|
124 | // .addClass('ui-widget-content') | |
125 | .append($('<option/>').attr('value','code').text('Code')) |
|
125 | .append($('<option/>').attr('value','code').text('Code')) | |
126 | .append($('<option/>').attr('value','markdown').text('Markdown')) |
|
126 | .append($('<option/>').attr('value','markdown').text('Markdown')) | |
127 | .append($('<option/>').attr('value','raw').text('Raw Text')) |
|
127 | .append($('<option/>').attr('value','raw').text('Raw Text')) | |
128 | .append($('<option/>').attr('value','heading1').text('Heading 1')) |
|
128 | .append($('<option/>').attr('value','heading1').text('Heading 1')) | |
129 | .append($('<option/>').attr('value','heading2').text('Heading 2')) |
|
129 | .append($('<option/>').attr('value','heading2').text('Heading 2')) | |
130 | .append($('<option/>').attr('value','heading3').text('Heading 3')) |
|
130 | .append($('<option/>').attr('value','heading3').text('Heading 3')) | |
131 | .append($('<option/>').attr('value','heading4').text('Heading 4')) |
|
131 | .append($('<option/>').attr('value','heading4').text('Heading 4')) | |
132 | .append($('<option/>').attr('value','heading5').text('Heading 5')) |
|
132 | .append($('<option/>').attr('value','heading5').text('Heading 5')) | |
133 | .append($('<option/>').attr('value','heading6').text('Heading 6')) |
|
133 | .append($('<option/>').attr('value','heading6').text('Heading 6')) | |
134 | ); |
|
134 | ); | |
135 | }; |
|
135 | }; | |
136 |
|
136 | |||
137 |
|
137 | |||
138 | MainToolBar.prototype.add_celltoolbar_list = function () { |
|
138 | MainToolBar.prototype.add_celltoolbar_list = function () { | |
139 |
var label = $('< |
|
139 | var label = $('<span/>').addClass("navbar-text").text('Cell Toolbar:'); | |
140 | var select = $('<select/>') |
|
140 | var select = $('<select/>') | |
141 | .addClass('ui-widget-content') |
|
141 | // .addClass('ui-widget-content') | |
142 | .attr('id', 'ctb_select') |
|
142 | .attr('id', 'ctb_select') | |
143 | .append($('<option/>').attr('value', '').text('None')); |
|
143 | .append($('<option/>').attr('value', '').text('None')); | |
144 | this.element.append(label).append(select); |
|
144 | this.element.append(label).append(select); | |
145 | select.change(function() { |
|
145 | select.change(function() { | |
146 | var val = $(this).val() |
|
146 | var val = $(this).val() | |
147 | if (val =='') { |
|
147 | if (val =='') { | |
148 | IPython.CellToolbar.global_hide(); |
|
148 | IPython.CellToolbar.global_hide(); | |
149 | } else { |
|
149 | } else { | |
150 | IPython.CellToolbar.global_show(); |
|
150 | IPython.CellToolbar.global_show(); | |
151 | IPython.CellToolbar.activate_preset(val); |
|
151 | IPython.CellToolbar.activate_preset(val); | |
152 | } |
|
152 | } | |
153 | }); |
|
153 | }); | |
154 | // Setup the currently registered presets. |
|
154 | // Setup the currently registered presets. | |
155 | var presets = IPython.CellToolbar.list_presets(); |
|
155 | var presets = IPython.CellToolbar.list_presets(); | |
156 | for (var i=0; i<presets.length; i++) { |
|
156 | for (var i=0; i<presets.length; i++) { | |
157 | var name = presets[i]; |
|
157 | var name = presets[i]; | |
158 | select.append($('<option/>').attr('value', name).text(name)); |
|
158 | select.append($('<option/>').attr('value', name).text(name)); | |
159 | } |
|
159 | } | |
160 | // Setup future preset registrations. |
|
160 | // Setup future preset registrations. | |
161 | $([IPython.events]).on('preset_added.CellToolbar', function (event, data) { |
|
161 | $([IPython.events]).on('preset_added.CellToolbar', function (event, data) { | |
162 | var name = data.name; |
|
162 | var name = data.name; | |
163 | select.append($('<option/>').attr('value', name).text(name)); |
|
163 | select.append($('<option/>').attr('value', name).text(name)); | |
164 | }); |
|
164 | }); | |
165 | }; |
|
165 | }; | |
166 |
|
166 | |||
167 |
|
167 | |||
168 | MainToolBar.prototype.bind_events = function () { |
|
168 | MainToolBar.prototype.bind_events = function () { | |
169 | var that = this; |
|
169 | var that = this; | |
170 |
|
170 | |||
171 | this.element.find('#cell_type').change(function () { |
|
171 | this.element.find('#cell_type').change(function () { | |
172 | var cell_type = $(this).val(); |
|
172 | var cell_type = $(this).val(); | |
173 | if (cell_type === 'code') { |
|
173 | if (cell_type === 'code') { | |
174 | IPython.notebook.to_code(); |
|
174 | IPython.notebook.to_code(); | |
175 | } else if (cell_type === 'markdown') { |
|
175 | } else if (cell_type === 'markdown') { | |
176 | IPython.notebook.to_markdown(); |
|
176 | IPython.notebook.to_markdown(); | |
177 | } else if (cell_type === 'raw') { |
|
177 | } else if (cell_type === 'raw') { | |
178 | IPython.notebook.to_raw(); |
|
178 | IPython.notebook.to_raw(); | |
179 | } else if (cell_type === 'heading1') { |
|
179 | } else if (cell_type === 'heading1') { | |
180 | IPython.notebook.to_heading(undefined, 1); |
|
180 | IPython.notebook.to_heading(undefined, 1); | |
181 | } else if (cell_type === 'heading2') { |
|
181 | } else if (cell_type === 'heading2') { | |
182 | IPython.notebook.to_heading(undefined, 2); |
|
182 | IPython.notebook.to_heading(undefined, 2); | |
183 | } else if (cell_type === 'heading3') { |
|
183 | } else if (cell_type === 'heading3') { | |
184 | IPython.notebook.to_heading(undefined, 3); |
|
184 | IPython.notebook.to_heading(undefined, 3); | |
185 | } else if (cell_type === 'heading4') { |
|
185 | } else if (cell_type === 'heading4') { | |
186 | IPython.notebook.to_heading(undefined, 4); |
|
186 | IPython.notebook.to_heading(undefined, 4); | |
187 | } else if (cell_type === 'heading5') { |
|
187 | } else if (cell_type === 'heading5') { | |
188 | IPython.notebook.to_heading(undefined, 5); |
|
188 | IPython.notebook.to_heading(undefined, 5); | |
189 | } else if (cell_type === 'heading6') { |
|
189 | } else if (cell_type === 'heading6') { | |
190 | IPython.notebook.to_heading(undefined, 6); |
|
190 | IPython.notebook.to_heading(undefined, 6); | |
191 | } |
|
191 | } | |
192 | }); |
|
192 | }); | |
193 | $([IPython.events]).on('selected_cell_type_changed.Notebook', function (event, data) { |
|
193 | $([IPython.events]).on('selected_cell_type_changed.Notebook', function (event, data) { | |
194 | if (data.cell_type === 'heading') { |
|
194 | if (data.cell_type === 'heading') { | |
195 | that.element.find('#cell_type').val(data.cell_type+data.level); |
|
195 | that.element.find('#cell_type').val(data.cell_type+data.level); | |
196 | } else { |
|
196 | } else { | |
197 | that.element.find('#cell_type').val(data.cell_type); |
|
197 | that.element.find('#cell_type').val(data.cell_type); | |
198 | } |
|
198 | } | |
199 | }); |
|
199 | }); | |
200 | }; |
|
200 | }; | |
201 |
|
201 | |||
202 | IPython.MainToolBar = MainToolBar; |
|
202 | IPython.MainToolBar = MainToolBar; | |
203 |
|
203 | |||
204 | return IPython; |
|
204 | return IPython; | |
205 |
|
205 | |||
206 | }(IPython)); |
|
206 | }(IPython)); |
@@ -1,242 +1,245 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2012 The IPython Development Team |
|
2 | // Copyright (C) 2008-2012 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // MathJax utility functions |
|
9 | // MathJax utility functions | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | IPython.namespace('IPython.mathjaxutils'); |
|
12 | IPython.namespace('IPython.mathjaxutils'); | |
13 |
|
13 | |||
14 | IPython.mathjaxutils = (function (IPython) { |
|
14 | IPython.mathjaxutils = (function (IPython) { | |
15 |
|
15 | |||
16 | var init = function () { |
|
16 | var init = function () { | |
17 | if (window.MathJax) { |
|
17 | if (window.MathJax) { | |
18 | // MathJax loaded |
|
18 | // MathJax loaded | |
19 | MathJax.Hub.Config({ |
|
19 | MathJax.Hub.Config({ | |
20 | tex2jax: { |
|
20 | tex2jax: { | |
21 | inlineMath: [ ['$','$'], ["\\(","\\)"] ], |
|
21 | inlineMath: [ ['$','$'], ["\\(","\\)"] ], | |
22 | displayMath: [ ['$$','$$'], ["\\[","\\]"] ], |
|
22 | displayMath: [ ['$$','$$'], ["\\[","\\]"] ], | |
23 | processEscapes: true, |
|
23 | processEscapes: true, | |
24 | processEnvironments: true |
|
24 | processEnvironments: true | |
25 | }, |
|
25 | }, | |
26 | displayAlign: 'left', // Change this to 'center' to center equations. |
|
26 | displayAlign: 'left', // Change this to 'center' to center equations. | |
27 | "HTML-CSS": { |
|
27 | "HTML-CSS": { | |
28 | styles: {'.MathJax_Display': {"margin": 0}} |
|
28 | styles: {'.MathJax_Display': {"margin": 0}} | |
29 | } |
|
29 | } | |
30 | }); |
|
30 | }); | |
31 | MathJax.Hub.Configured(); |
|
31 | MathJax.Hub.Configured(); | |
32 | } else if (window.mathjax_url != "") { |
|
32 | } else if (window.mathjax_url != "") { | |
33 | // Don't have MathJax, but should. Show dialog. |
|
33 | // Don't have MathJax, but should. Show dialog. | |
34 |
var |
|
34 | var message = $('<div/>') | |
35 | .append( |
|
35 | .append( | |
36 | $("<p></p>").addClass('dialog').html( |
|
36 | $("<p/></p>").addClass('dialog').html( | |
37 | "Math/LaTeX rendering will be disabled." |
|
37 | "Math/LaTeX rendering will be disabled." | |
38 | ) |
|
38 | ) | |
39 | ).append( |
|
39 | ).append( | |
40 | $("<p></p>").addClass('dialog').html( |
|
40 | $("<p></p>").addClass('dialog').html( | |
41 | "If you have administrative access to the notebook server and" + |
|
41 | "If you have administrative access to the notebook server and" + | |
42 | " a working internet connection, you can install a local copy" + |
|
42 | " a working internet connection, you can install a local copy" + | |
43 | " of MathJax for offline use with the following command on the server" + |
|
43 | " of MathJax for offline use with the following command on the server" + | |
44 | " at a Python or IPython prompt:" |
|
44 | " at a Python or IPython prompt:" | |
45 | ) |
|
45 | ) | |
46 | ).append( |
|
46 | ).append( | |
47 | $("<pre></pre>").addClass('dialog').html( |
|
47 | $("<pre></pre>").addClass('dialog').html( | |
48 | ">>> from IPython.external import mathjax; mathjax.install_mathjax()" |
|
48 | ">>> from IPython.external import mathjax; mathjax.install_mathjax()" | |
49 | ) |
|
49 | ) | |
50 | ).append( |
|
50 | ).append( | |
51 | $("<p></p>").addClass('dialog').html( |
|
51 | $("<p></p>").addClass('dialog').html( | |
52 | "This will try to install MathJax into the IPython source directory." |
|
52 | "This will try to install MathJax into the IPython source directory." | |
53 | ) |
|
53 | ) | |
54 | ).append( |
|
54 | ).append( | |
55 | $("<p></p>").addClass('dialog').html( |
|
55 | $("<p></p>").addClass('dialog').html( | |
56 | "If IPython is installed to a location that requires" + |
|
56 | "If IPython is installed to a location that requires" + | |
57 | " administrative privileges to write, you will need to make this call as" + |
|
57 | " administrative privileges to write, you will need to make this call as" + | |
58 | " an administrator, via 'sudo'." |
|
58 | " an administrator, via 'sudo'." | |
59 | ) |
|
59 | ) | |
60 | ).append( |
|
60 | ).append( | |
61 | $("<p></p>").addClass('dialog').html( |
|
61 | $("<p></p>").addClass('dialog').html( | |
62 | "When you start the notebook server, you can instruct it to disable MathJax support altogether:" |
|
62 | "When you start the notebook server, you can instruct it to disable MathJax support altogether:" | |
63 | ) |
|
63 | ) | |
64 | ).append( |
|
64 | ).append( | |
65 | $("<pre></pre>").addClass('dialog').html( |
|
65 | $("<pre></pre>").addClass('dialog').html( | |
66 | "$ ipython notebook --no-mathjax" |
|
66 | "$ ipython notebook --no-mathjax" | |
67 | ) |
|
67 | ) | |
68 | ).append( |
|
68 | ).append( | |
69 | $("<p></p>").addClass('dialog').html( |
|
69 | $("<p></p>").addClass('dialog').html( | |
70 | "which will prevent this dialog from appearing." |
|
70 | "which will prevent this dialog from appearing." | |
71 | ) |
|
71 | ) | |
72 |
) |
|
72 | ) | |
73 | title: "Failed to retrieve MathJax from '" + window.mathjax_url + "'", |
|
73 | IPython.dialog.modal({ | |
74 | width: "70%", |
|
74 | title : "Failed to retrieve MathJax from '" + window.mathjax_url + "'", | |
75 |
|
|
75 | body : message, | |
76 |
|
|
76 | buttons : { | |
|
77 | OK : {class: "btn-danger"} | |||
|
78 | } | |||
|
79 | }); | |||
77 | } else { |
|
80 | } else { | |
78 | // No MathJax, but none expected. No dialog. |
|
81 | // No MathJax, but none expected. No dialog. | |
79 | }; |
|
82 | }; | |
80 | }; |
|
83 | }; | |
81 |
|
84 | |||
82 | // Some magic for deferring mathematical expressions to MathJax |
|
85 | // Some magic for deferring mathematical expressions to MathJax | |
83 | // by hiding them from the Markdown parser. |
|
86 | // by hiding them from the Markdown parser. | |
84 | // Some of the code here is adapted with permission from Davide Cervone |
|
87 | // Some of the code here is adapted with permission from Davide Cervone | |
85 | // under the terms of the Apache2 license governing the MathJax project. |
|
88 | // under the terms of the Apache2 license governing the MathJax project. | |
86 | // Other minor modifications are also due to StackExchange and are used with |
|
89 | // Other minor modifications are also due to StackExchange and are used with | |
87 | // permission. |
|
90 | // permission. | |
88 |
|
91 | |||
89 | var inline = "$"; // the inline math delimiter |
|
92 | var inline = "$"; // the inline math delimiter | |
90 | var blocks, start, end, last, braces; // used in searching for math |
|
93 | var blocks, start, end, last, braces; // used in searching for math | |
91 | var math; // stores math until pagedown (Markdown parser) is done |
|
94 | var math; // stores math until pagedown (Markdown parser) is done | |
92 |
|
95 | |||
93 | // MATHSPLIT contains the pattern for math delimiters and special symbols |
|
96 | // MATHSPLIT contains the pattern for math delimiters and special symbols | |
94 | // needed for searching for math in the text input. |
|
97 | // needed for searching for math in the text input. | |
95 | var MATHSPLIT = /(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[\\{}$]|[{}]|(?:\n\s*)+|@@\d+@@)/i; |
|
98 | var MATHSPLIT = /(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[\\{}$]|[{}]|(?:\n\s*)+|@@\d+@@)/i; | |
96 |
|
99 | |||
97 | // The math is in blocks i through j, so |
|
100 | // The math is in blocks i through j, so | |
98 | // collect it into one block and clear the others. |
|
101 | // collect it into one block and clear the others. | |
99 | // Replace &, <, and > by named entities. |
|
102 | // Replace &, <, and > by named entities. | |
100 | // For IE, put <br> at the ends of comments since IE removes \n. |
|
103 | // For IE, put <br> at the ends of comments since IE removes \n. | |
101 | // Clear the current math positions and store the index of the |
|
104 | // Clear the current math positions and store the index of the | |
102 | // math, then push the math string onto the storage array. |
|
105 | // math, then push the math string onto the storage array. | |
103 | // The preProcess function is called on all blocks if it has been passed in |
|
106 | // The preProcess function is called on all blocks if it has been passed in | |
104 | var process_math = function (i, j, pre_process) { |
|
107 | var process_math = function (i, j, pre_process) { | |
105 | var hub = MathJax.Hub; |
|
108 | var hub = MathJax.Hub; | |
106 | var block = blocks.slice(i, j + 1).join("").replace(/&/g, "&") // use HTML entity for & |
|
109 | var block = blocks.slice(i, j + 1).join("").replace(/&/g, "&") // use HTML entity for & | |
107 | .replace(/</g, "<") // use HTML entity for < |
|
110 | .replace(/</g, "<") // use HTML entity for < | |
108 | .replace(/>/g, ">") // use HTML entity for > |
|
111 | .replace(/>/g, ">") // use HTML entity for > | |
109 | ; |
|
112 | ; | |
110 | if (hub.Browser.isMSIE) { |
|
113 | if (hub.Browser.isMSIE) { | |
111 | block = block.replace(/(%[^\n]*)\n/g, "$1<br/>\n") |
|
114 | block = block.replace(/(%[^\n]*)\n/g, "$1<br/>\n") | |
112 | } |
|
115 | } | |
113 | while (j > i) { |
|
116 | while (j > i) { | |
114 | blocks[j] = ""; |
|
117 | blocks[j] = ""; | |
115 | j--; |
|
118 | j--; | |
116 | } |
|
119 | } | |
117 | blocks[i] = "@@" + math.length + "@@"; // replace the current block text with a unique tag to find later |
|
120 | blocks[i] = "@@" + math.length + "@@"; // replace the current block text with a unique tag to find later | |
118 | if (pre_process) |
|
121 | if (pre_process) | |
119 | block = pre_process(block); |
|
122 | block = pre_process(block); | |
120 | math.push(block); |
|
123 | math.push(block); | |
121 | start = end = last = null; |
|
124 | start = end = last = null; | |
122 | } |
|
125 | } | |
123 |
|
126 | |||
124 | // Break up the text into its component parts and search |
|
127 | // Break up the text into its component parts and search | |
125 | // through them for math delimiters, braces, linebreaks, etc. |
|
128 | // through them for math delimiters, braces, linebreaks, etc. | |
126 | // Math delimiters must match and braces must balance. |
|
129 | // Math delimiters must match and braces must balance. | |
127 | // Don't allow math to pass through a double linebreak |
|
130 | // Don't allow math to pass through a double linebreak | |
128 | // (which will be a paragraph). |
|
131 | // (which will be a paragraph). | |
129 | // |
|
132 | // | |
130 | var remove_math = function (text) { |
|
133 | var remove_math = function (text) { | |
131 | if (!window.MathJax) { |
|
134 | if (!window.MathJax) { | |
132 | return text; |
|
135 | return text; | |
133 | } |
|
136 | } | |
134 |
|
137 | |||
135 | start = end = last = null; // for tracking math delimiters |
|
138 | start = end = last = null; // for tracking math delimiters | |
136 | math = []; // stores math strings for later |
|
139 | math = []; // stores math strings for later | |
137 |
|
140 | |||
138 | // Except for extreme edge cases, this should catch precisely those pieces of the markdown |
|
141 | // Except for extreme edge cases, this should catch precisely those pieces of the markdown | |
139 | // source that will later be turned into code spans. While MathJax will not TeXify code spans, |
|
142 | // source that will later be turned into code spans. While MathJax will not TeXify code spans, | |
140 | // we still have to consider them at this point; the following issue has happened several times: |
|
143 | // we still have to consider them at this point; the following issue has happened several times: | |
141 | // |
|
144 | // | |
142 | // `$foo` and `$bar` are varibales. --> <code>$foo ` and `$bar</code> are variables. |
|
145 | // `$foo` and `$bar` are varibales. --> <code>$foo ` and `$bar</code> are variables. | |
143 |
|
146 | |||
144 | var hasCodeSpans = /`/.test(text), |
|
147 | var hasCodeSpans = /`/.test(text), | |
145 | de_tilde; |
|
148 | de_tilde; | |
146 | if (hasCodeSpans) { |
|
149 | if (hasCodeSpans) { | |
147 | text = text.replace(/~/g, "~T").replace(/(^|[^\\])(`+)([^\n]*?[^`\n])\2(?!`)/gm, function (wholematch) { |
|
150 | text = text.replace(/~/g, "~T").replace(/(^|[^\\])(`+)([^\n]*?[^`\n])\2(?!`)/gm, function (wholematch) { | |
148 | return wholematch.replace(/\$/g, "~D"); |
|
151 | return wholematch.replace(/\$/g, "~D"); | |
149 | }); |
|
152 | }); | |
150 | de_tilde = function (text) { return text.replace(/~([TD])/g, function (wholematch, character) { return { T: "~", D: "$" }[character]; }) }; |
|
153 | de_tilde = function (text) { return text.replace(/~([TD])/g, function (wholematch, character) { return { T: "~", D: "$" }[character]; }) }; | |
151 | } else { |
|
154 | } else { | |
152 | de_tilde = function (text) { return text; }; |
|
155 | de_tilde = function (text) { return text; }; | |
153 | } |
|
156 | } | |
154 |
|
157 | |||
155 | blocks = IPython.utils.regex_split(text.replace(/\r\n?/g, "\n"),MATHSPLIT); |
|
158 | blocks = IPython.utils.regex_split(text.replace(/\r\n?/g, "\n"),MATHSPLIT); | |
156 |
|
159 | |||
157 | for (var i = 1, m = blocks.length; i < m; i += 2) { |
|
160 | for (var i = 1, m = blocks.length; i < m; i += 2) { | |
158 | var block = blocks[i]; |
|
161 | var block = blocks[i]; | |
159 | if (block.charAt(0) === "@") { |
|
162 | if (block.charAt(0) === "@") { | |
160 | // |
|
163 | // | |
161 | // Things that look like our math markers will get |
|
164 | // Things that look like our math markers will get | |
162 | // stored and then retrieved along with the math. |
|
165 | // stored and then retrieved along with the math. | |
163 | // |
|
166 | // | |
164 | blocks[i] = "@@" + math.length + "@@"; |
|
167 | blocks[i] = "@@" + math.length + "@@"; | |
165 | math.push(block); |
|
168 | math.push(block); | |
166 | } |
|
169 | } | |
167 | else if (start) { |
|
170 | else if (start) { | |
168 | // |
|
171 | // | |
169 | // If we are in math, look for the end delimiter, |
|
172 | // If we are in math, look for the end delimiter, | |
170 | // but don't go past double line breaks, and |
|
173 | // but don't go past double line breaks, and | |
171 | // and balance braces within the math. |
|
174 | // and balance braces within the math. | |
172 | // |
|
175 | // | |
173 | if (block === end) { |
|
176 | if (block === end) { | |
174 | if (braces) { |
|
177 | if (braces) { | |
175 | last = i |
|
178 | last = i | |
176 | } |
|
179 | } | |
177 | else { |
|
180 | else { | |
178 | process_math(start, i, de_tilde) |
|
181 | process_math(start, i, de_tilde) | |
179 | } |
|
182 | } | |
180 | } |
|
183 | } | |
181 | else if (block.match(/\n.*\n/)) { |
|
184 | else if (block.match(/\n.*\n/)) { | |
182 | if (last) { |
|
185 | if (last) { | |
183 | i = last; |
|
186 | i = last; | |
184 | process_math(start, i, de_tilde) |
|
187 | process_math(start, i, de_tilde) | |
185 | } |
|
188 | } | |
186 | start = end = last = null; |
|
189 | start = end = last = null; | |
187 | braces = 0; |
|
190 | braces = 0; | |
188 | } |
|
191 | } | |
189 | else if (block === "{") { |
|
192 | else if (block === "{") { | |
190 | braces++ |
|
193 | braces++ | |
191 | } |
|
194 | } | |
192 | else if (block === "}" && braces) { |
|
195 | else if (block === "}" && braces) { | |
193 | braces-- |
|
196 | braces-- | |
194 | } |
|
197 | } | |
195 | } |
|
198 | } | |
196 | else { |
|
199 | else { | |
197 | // |
|
200 | // | |
198 | // Look for math start delimiters and when |
|
201 | // Look for math start delimiters and when | |
199 | // found, set up the end delimiter. |
|
202 | // found, set up the end delimiter. | |
200 | // |
|
203 | // | |
201 | if (block === inline || block === "$$") { |
|
204 | if (block === inline || block === "$$") { | |
202 | start = i; |
|
205 | start = i; | |
203 | end = block; |
|
206 | end = block; | |
204 | braces = 0; |
|
207 | braces = 0; | |
205 | } |
|
208 | } | |
206 | else if (block.substr(1, 5) === "begin") { |
|
209 | else if (block.substr(1, 5) === "begin") { | |
207 | start = i; |
|
210 | start = i; | |
208 | end = "\\end" + block.substr(6); |
|
211 | end = "\\end" + block.substr(6); | |
209 | braces = 0; |
|
212 | braces = 0; | |
210 | } |
|
213 | } | |
211 | } |
|
214 | } | |
212 | } |
|
215 | } | |
213 | if (last) { |
|
216 | if (last) { | |
214 | process_math(start, last, de_tilde) |
|
217 | process_math(start, last, de_tilde) | |
215 | } |
|
218 | } | |
216 | return de_tilde(blocks.join("")); |
|
219 | return de_tilde(blocks.join("")); | |
217 | } |
|
220 | } | |
218 |
|
221 | |||
219 | // |
|
222 | // | |
220 | // Put back the math strings that were saved, |
|
223 | // Put back the math strings that were saved, | |
221 | // and clear the math array (no need to keep it around). |
|
224 | // and clear the math array (no need to keep it around). | |
222 | // |
|
225 | // | |
223 | var replace_math = function (text) { |
|
226 | var replace_math = function (text) { | |
224 | if (!window.MathJax) { |
|
227 | if (!window.MathJax) { | |
225 | return text; |
|
228 | return text; | |
226 | } |
|
229 | } | |
227 |
|
230 | |||
228 | text = text.replace(/@@(\d+)@@/g, function (match, n) { |
|
231 | text = text.replace(/@@(\d+)@@/g, function (match, n) { | |
229 | return math[n] |
|
232 | return math[n] | |
230 | }); |
|
233 | }); | |
231 | math = null; |
|
234 | math = null; | |
232 | return text; |
|
235 | return text; | |
233 | } |
|
236 | } | |
234 |
|
237 | |||
235 | return { |
|
238 | return { | |
236 | init : init, |
|
239 | init : init, | |
237 | process_math : process_math, |
|
240 | process_math : process_math, | |
238 | remove_math : remove_math, |
|
241 | remove_math : remove_math, | |
239 | replace_math : replace_math |
|
242 | replace_math : replace_math | |
240 | }; |
|
243 | }; | |
241 |
|
244 | |||
242 | }(IPython)); No newline at end of file |
|
245 | }(IPython)); |
@@ -1,264 +1,263 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // MenuBar |
|
9 | // MenuBar | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | /** |
|
12 | /** | |
13 | * @module IPython |
|
13 | * @module IPython | |
14 | * @namespace IPython |
|
14 | * @namespace IPython | |
15 | * @submodule MenuBar |
|
15 | * @submodule MenuBar | |
16 | */ |
|
16 | */ | |
17 |
|
17 | |||
18 |
|
18 | |||
19 | var IPython = (function (IPython) { |
|
19 | var IPython = (function (IPython) { | |
20 |
|
20 | |||
21 | /** |
|
21 | /** | |
22 | * A MenuBar Class to generate the menubar of IPython noteboko |
|
22 | * A MenuBar Class to generate the menubar of IPython noteboko | |
23 | * @Class MenuBar |
|
23 | * @Class MenuBar | |
24 | * |
|
24 | * | |
25 | * @constructor |
|
25 | * @constructor | |
26 | * |
|
26 | * | |
27 | * |
|
27 | * | |
28 | * @param selector {string} selector for the menubar element in DOM |
|
28 | * @param selector {string} selector for the menubar element in DOM | |
29 | * @param {object} [options] |
|
29 | * @param {object} [options] | |
30 | * @param [options.baseProjectUrl] {String} String to use for the |
|
30 | * @param [options.baseProjectUrl] {String} String to use for the | |
31 | * Base Project url, default would be to inspect |
|
31 | * Base Project url, default would be to inspect | |
32 | * $('body').data('baseProjectUrl'); |
|
32 | * $('body').data('baseProjectUrl'); | |
33 | * does not support change for now is set through this option |
|
33 | * does not support change for now is set through this option | |
34 | */ |
|
34 | */ | |
35 | var MenuBar = function (selector, options) { |
|
35 | var MenuBar = function (selector, options) { | |
36 | var options = options || {}; |
|
36 | var options = options || {}; | |
37 | if(options.baseProjectUrl!= undefined){ |
|
37 | if(options.baseProjectUrl!= undefined){ | |
38 | this._baseProjectUrl = options.baseProjectUrl; |
|
38 | this._baseProjectUrl = options.baseProjectUrl; | |
39 | } |
|
39 | } | |
40 | this.selector = selector; |
|
40 | this.selector = selector; | |
41 | if (this.selector !== undefined) { |
|
41 | if (this.selector !== undefined) { | |
42 | this.element = $(selector); |
|
42 | this.element = $(selector); | |
43 | this.style(); |
|
43 | this.style(); | |
44 | this.bind_events(); |
|
44 | this.bind_events(); | |
45 | } |
|
45 | } | |
46 | }; |
|
46 | }; | |
47 |
|
47 | |||
48 | MenuBar.prototype.baseProjectUrl = function(){ |
|
48 | MenuBar.prototype.baseProjectUrl = function(){ | |
49 | return this._baseProjectUrl || $('body').data('baseProjectUrl'); |
|
49 | return this._baseProjectUrl || $('body').data('baseProjectUrl'); | |
50 | }; |
|
50 | }; | |
51 |
|
51 | |||
52 |
|
52 | |||
53 | MenuBar.prototype.style = function () { |
|
53 | MenuBar.prototype.style = function () { | |
54 | this.element.addClass('border-box-sizing'); |
|
54 | this.element.addClass('border-box-sizing'); | |
55 | $('ul#menus').menubar({ |
|
55 | this.element.find("li").click(function (event, ui) { | |
56 | select : function (event, ui) { |
|
|||
57 | // The selected cell loses focus when the menu is entered, so we |
|
56 | // The selected cell loses focus when the menu is entered, so we | |
58 | // re-select it upon selection. |
|
57 | // re-select it upon selection. | |
59 | var i = IPython.notebook.get_selected_index(); |
|
58 | var i = IPython.notebook.get_selected_index(); | |
60 | IPython.notebook.select(i); |
|
59 | IPython.notebook.select(i); | |
61 | } |
|
60 | } | |
62 |
|
|
61 | ); | |
63 | this.element.find("#restore_checkpoint").find("ul").find("li").hide(); |
|
|||
64 | }; |
|
62 | }; | |
65 |
|
63 | |||
66 |
|
64 | |||
67 | MenuBar.prototype.bind_events = function () { |
|
65 | MenuBar.prototype.bind_events = function () { | |
68 | // File |
|
66 | // File | |
69 | var that = this; |
|
67 | var that = this; | |
70 | this.element.find('#new_notebook').click(function () { |
|
68 | this.element.find('#new_notebook').click(function () { | |
71 | window.open(that.baseProjectUrl()+'new'); |
|
69 | window.open(that.baseProjectUrl()+'new'); | |
72 | }); |
|
70 | }); | |
73 | this.element.find('#open_notebook').click(function () { |
|
71 | this.element.find('#open_notebook').click(function () { | |
74 | window.open(that.baseProjectUrl()); |
|
72 | window.open(that.baseProjectUrl()); | |
75 | }); |
|
73 | }); | |
76 | this.element.find('#rename_notebook').click(function () { |
|
74 | this.element.find('#rename_notebook').click(function () { | |
77 | IPython.save_widget.rename_notebook(); |
|
75 | IPython.save_widget.rename_notebook(); | |
78 | }); |
|
76 | }); | |
79 | this.element.find('#copy_notebook').click(function () { |
|
77 | this.element.find('#copy_notebook').click(function () { | |
80 | var notebook_id = IPython.notebook.get_notebook_id(); |
|
78 | var notebook_id = IPython.notebook.get_notebook_id(); | |
81 | var url = that.baseProjectUrl() + notebook_id + '/copy'; |
|
79 | var url = that.baseProjectUrl() + notebook_id + '/copy'; | |
82 | window.open(url,'_blank'); |
|
80 | window.open(url,'_blank'); | |
83 | return false; |
|
81 | return false; | |
84 | }); |
|
82 | }); | |
85 | this.element.find('#save_checkpoint').click(function () { |
|
83 | this.element.find('#save_checkpoint').click(function () { | |
86 | IPython.notebook.save_checkpoint(); |
|
84 | IPython.notebook.save_checkpoint(); | |
87 | }); |
|
85 | }); | |
88 | this.element.find('#restore_checkpoint').click(function () { |
|
86 | this.element.find('#restore_checkpoint').click(function () { | |
89 | }); |
|
87 | }); | |
90 | this.element.find('#download_ipynb').click(function () { |
|
88 | this.element.find('#download_ipynb').click(function () { | |
91 | var notebook_id = IPython.notebook.get_notebook_id(); |
|
89 | var notebook_id = IPython.notebook.get_notebook_id(); | |
92 | var url = that.baseProjectUrl() + 'notebooks/' + |
|
90 | var url = that.baseProjectUrl() + 'notebooks/' + | |
93 | notebook_id + '?format=json'; |
|
91 | notebook_id + '?format=json'; | |
94 | window.location.assign(url); |
|
92 | window.location.assign(url); | |
95 | }); |
|
93 | }); | |
96 | this.element.find('#download_py').click(function () { |
|
94 | this.element.find('#download_py').click(function () { | |
97 | var notebook_id = IPython.notebook.get_notebook_id(); |
|
95 | var notebook_id = IPython.notebook.get_notebook_id(); | |
98 | var url = that.baseProjectUrl() + 'notebooks/' + |
|
96 | var url = that.baseProjectUrl() + 'notebooks/' + | |
99 | notebook_id + '?format=py'; |
|
97 | notebook_id + '?format=py'; | |
100 | window.location.assign(url); |
|
98 | window.location.assign(url); | |
101 | }); |
|
99 | }); | |
102 | this.element.find('#kill_and_exit').click(function () { |
|
100 | this.element.find('#kill_and_exit').click(function () { | |
103 | IPython.notebook.kernel.kill(); |
|
101 | IPython.notebook.kernel.kill(); | |
104 | setTimeout(function(){window.close();}, 200); |
|
102 | setTimeout(function(){window.close();}, 200); | |
105 | }); |
|
103 | }); | |
106 | // Edit |
|
104 | // Edit | |
107 | this.element.find('#cut_cell').click(function () { |
|
105 | this.element.find('#cut_cell').click(function () { | |
108 | IPython.notebook.cut_cell(); |
|
106 | IPython.notebook.cut_cell(); | |
109 | }); |
|
107 | }); | |
110 | this.element.find('#copy_cell').click(function () { |
|
108 | this.element.find('#copy_cell').click(function () { | |
111 | IPython.notebook.copy_cell(); |
|
109 | IPython.notebook.copy_cell(); | |
112 | }); |
|
110 | }); | |
113 | this.element.find('#delete_cell').click(function () { |
|
111 | this.element.find('#delete_cell').click(function () { | |
114 | IPython.notebook.delete_cell(); |
|
112 | IPython.notebook.delete_cell(); | |
115 | }); |
|
113 | }); | |
116 | this.element.find('#undelete_cell').click(function () { |
|
114 | this.element.find('#undelete_cell').click(function () { | |
117 | IPython.notebook.undelete(); |
|
115 | IPython.notebook.undelete(); | |
118 | }); |
|
116 | }); | |
119 | this.element.find('#split_cell').click(function () { |
|
117 | this.element.find('#split_cell').click(function () { | |
120 | IPython.notebook.split_cell(); |
|
118 | IPython.notebook.split_cell(); | |
121 | }); |
|
119 | }); | |
122 | this.element.find('#merge_cell_above').click(function () { |
|
120 | this.element.find('#merge_cell_above').click(function () { | |
123 | IPython.notebook.merge_cell_above(); |
|
121 | IPython.notebook.merge_cell_above(); | |
124 | }); |
|
122 | }); | |
125 | this.element.find('#merge_cell_below').click(function () { |
|
123 | this.element.find('#merge_cell_below').click(function () { | |
126 | IPython.notebook.merge_cell_below(); |
|
124 | IPython.notebook.merge_cell_below(); | |
127 | }); |
|
125 | }); | |
128 | this.element.find('#move_cell_up').click(function () { |
|
126 | this.element.find('#move_cell_up').click(function () { | |
129 | IPython.notebook.move_cell_up(); |
|
127 | IPython.notebook.move_cell_up(); | |
130 | }); |
|
128 | }); | |
131 | this.element.find('#move_cell_down').click(function () { |
|
129 | this.element.find('#move_cell_down').click(function () { | |
132 | IPython.notebook.move_cell_down(); |
|
130 | IPython.notebook.move_cell_down(); | |
133 | }); |
|
131 | }); | |
134 | this.element.find('#select_previous').click(function () { |
|
132 | this.element.find('#select_previous').click(function () { | |
135 | IPython.notebook.select_prev(); |
|
133 | IPython.notebook.select_prev(); | |
136 | }); |
|
134 | }); | |
137 | this.element.find('#select_next').click(function () { |
|
135 | this.element.find('#select_next').click(function () { | |
138 | IPython.notebook.select_next(); |
|
136 | IPython.notebook.select_next(); | |
139 | }); |
|
137 | }); | |
140 | // View |
|
138 | // View | |
141 | this.element.find('#toggle_header').click(function () { |
|
139 | this.element.find('#toggle_header').click(function () { | |
142 | $('div#header').toggle(); |
|
140 | $('div#header').toggle(); | |
143 | IPython.layout_manager.do_resize(); |
|
141 | IPython.layout_manager.do_resize(); | |
144 | }); |
|
142 | }); | |
145 | this.element.find('#toggle_toolbar').click(function () { |
|
143 | this.element.find('#toggle_toolbar').click(function () { | |
146 |
|
|
144 | $('div#maintoolbar').toggle(); | |
|
145 | IPython.layout_manager.do_resize(); | |||
147 | }); |
|
146 | }); | |
148 | // Insert |
|
147 | // Insert | |
149 | this.element.find('#insert_cell_above').click(function () { |
|
148 | this.element.find('#insert_cell_above').click(function () { | |
150 | IPython.notebook.insert_cell_above('code'); |
|
149 | IPython.notebook.insert_cell_above('code'); | |
151 | }); |
|
150 | }); | |
152 | this.element.find('#insert_cell_below').click(function () { |
|
151 | this.element.find('#insert_cell_below').click(function () { | |
153 | IPython.notebook.insert_cell_below('code'); |
|
152 | IPython.notebook.insert_cell_below('code'); | |
154 | }); |
|
153 | }); | |
155 | // Cell |
|
154 | // Cell | |
156 | this.element.find('#run_cell').click(function () { |
|
155 | this.element.find('#run_cell').click(function () { | |
157 | IPython.notebook.execute_selected_cell(); |
|
156 | IPython.notebook.execute_selected_cell(); | |
158 | }); |
|
157 | }); | |
159 | this.element.find('#run_cell_in_place').click(function () { |
|
158 | this.element.find('#run_cell_in_place').click(function () { | |
160 | IPython.notebook.execute_selected_cell({terminal:true}); |
|
159 | IPython.notebook.execute_selected_cell({terminal:true}); | |
161 | }); |
|
160 | }); | |
162 | this.element.find('#run_all_cells').click(function () { |
|
161 | this.element.find('#run_all_cells').click(function () { | |
163 | IPython.notebook.execute_all_cells(); |
|
162 | IPython.notebook.execute_all_cells(); | |
164 | }).attr('title', 'Run all cells in the notebook'); |
|
163 | }).attr('title', 'Run all cells in the notebook'); | |
165 | this.element.find('#run_all_cells_above').click(function () { |
|
164 | this.element.find('#run_all_cells_above').click(function () { | |
166 | IPython.notebook.execute_cells_above(); |
|
165 | IPython.notebook.execute_cells_above(); | |
167 | }).attr('title', 'Run all cells above (but not including) this cell'); |
|
166 | }).attr('title', 'Run all cells above (but not including) this cell'); | |
168 | this.element.find('#run_all_cells_below').click(function () { |
|
167 | this.element.find('#run_all_cells_below').click(function () { | |
169 | IPython.notebook.execute_cells_below(); |
|
168 | IPython.notebook.execute_cells_below(); | |
170 | }).attr('title', 'Run this cell and all cells below it'); |
|
169 | }).attr('title', 'Run this cell and all cells below it'); | |
171 | this.element.find('#to_code').click(function () { |
|
170 | this.element.find('#to_code').click(function () { | |
172 | IPython.notebook.to_code(); |
|
171 | IPython.notebook.to_code(); | |
173 | }); |
|
172 | }); | |
174 | this.element.find('#to_markdown').click(function () { |
|
173 | this.element.find('#to_markdown').click(function () { | |
175 | IPython.notebook.to_markdown(); |
|
174 | IPython.notebook.to_markdown(); | |
176 | }); |
|
175 | }); | |
177 | this.element.find('#to_raw').click(function () { |
|
176 | this.element.find('#to_raw').click(function () { | |
178 | IPython.notebook.to_raw(); |
|
177 | IPython.notebook.to_raw(); | |
179 | }); |
|
178 | }); | |
180 | this.element.find('#to_heading1').click(function () { |
|
179 | this.element.find('#to_heading1').click(function () { | |
181 | IPython.notebook.to_heading(undefined, 1); |
|
180 | IPython.notebook.to_heading(undefined, 1); | |
182 | }); |
|
181 | }); | |
183 | this.element.find('#to_heading2').click(function () { |
|
182 | this.element.find('#to_heading2').click(function () { | |
184 | IPython.notebook.to_heading(undefined, 2); |
|
183 | IPython.notebook.to_heading(undefined, 2); | |
185 | }); |
|
184 | }); | |
186 | this.element.find('#to_heading3').click(function () { |
|
185 | this.element.find('#to_heading3').click(function () { | |
187 | IPython.notebook.to_heading(undefined, 3); |
|
186 | IPython.notebook.to_heading(undefined, 3); | |
188 | }); |
|
187 | }); | |
189 | this.element.find('#to_heading4').click(function () { |
|
188 | this.element.find('#to_heading4').click(function () { | |
190 | IPython.notebook.to_heading(undefined, 4); |
|
189 | IPython.notebook.to_heading(undefined, 4); | |
191 | }); |
|
190 | }); | |
192 | this.element.find('#to_heading5').click(function () { |
|
191 | this.element.find('#to_heading5').click(function () { | |
193 | IPython.notebook.to_heading(undefined, 5); |
|
192 | IPython.notebook.to_heading(undefined, 5); | |
194 | }); |
|
193 | }); | |
195 | this.element.find('#to_heading6').click(function () { |
|
194 | this.element.find('#to_heading6').click(function () { | |
196 | IPython.notebook.to_heading(undefined, 6); |
|
195 | IPython.notebook.to_heading(undefined, 6); | |
197 | }); |
|
196 | }); | |
198 | this.element.find('#toggle_output').click(function () { |
|
197 | this.element.find('#toggle_output').click(function () { | |
199 | IPython.notebook.toggle_output(); |
|
198 | IPython.notebook.toggle_output(); | |
200 | }); |
|
199 | }); | |
201 | this.element.find('#collapse_all_output').click(function () { |
|
200 | this.element.find('#collapse_all_output').click(function () { | |
202 | IPython.notebook.collapse_all_output(); |
|
201 | IPython.notebook.collapse_all_output(); | |
203 | }); |
|
202 | }); | |
204 | this.element.find('#scroll_all_output').click(function () { |
|
203 | this.element.find('#scroll_all_output').click(function () { | |
205 | IPython.notebook.scroll_all_output(); |
|
204 | IPython.notebook.scroll_all_output(); | |
206 | }); |
|
205 | }); | |
207 | this.element.find('#expand_all_output').click(function () { |
|
206 | this.element.find('#expand_all_output').click(function () { | |
208 | IPython.notebook.expand_all_output(); |
|
207 | IPython.notebook.expand_all_output(); | |
209 | }); |
|
208 | }); | |
210 | this.element.find('#clear_all_output').click(function () { |
|
209 | this.element.find('#clear_all_output').click(function () { | |
211 | IPython.notebook.clear_all_output(); |
|
210 | IPython.notebook.clear_all_output(); | |
212 | }); |
|
211 | }); | |
213 | // Kernel |
|
212 | // Kernel | |
214 | this.element.find('#int_kernel').click(function () { |
|
213 | this.element.find('#int_kernel').click(function () { | |
215 | IPython.notebook.kernel.interrupt(); |
|
214 | IPython.notebook.kernel.interrupt(); | |
216 | }); |
|
215 | }); | |
217 | this.element.find('#restart_kernel').click(function () { |
|
216 | this.element.find('#restart_kernel').click(function () { | |
218 | IPython.notebook.restart_kernel(); |
|
217 | IPython.notebook.restart_kernel(); | |
219 | }); |
|
218 | }); | |
220 | // Help |
|
219 | // Help | |
221 | this.element.find('#keyboard_shortcuts').click(function () { |
|
220 | this.element.find('#keyboard_shortcuts').click(function () { | |
222 | IPython.quick_help.show_keyboard_shortcuts(); |
|
221 | IPython.quick_help.show_keyboard_shortcuts(); | |
223 | }); |
|
222 | }); | |
224 |
|
223 | |||
225 | this.update_restore_checkpoint(null); |
|
224 | this.update_restore_checkpoint(null); | |
226 |
|
225 | |||
227 | $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) { |
|
226 | $([IPython.events]).on('checkpoints_listed.Notebook', function (event, data) { | |
228 | that.update_restore_checkpoint(data); |
|
227 | that.update_restore_checkpoint(data); | |
229 | }); |
|
228 | }); | |
230 |
|
229 | |||
231 | $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) { |
|
230 | $([IPython.events]).on('checkpoint_created.Notebook', function (event, data) { | |
232 | that.update_restore_checkpoint([data]); |
|
231 | that.update_restore_checkpoint([data]); | |
233 | }); |
|
232 | }); | |
234 | }; |
|
233 | }; | |
235 |
|
234 | |||
236 | MenuBar.prototype.update_restore_checkpoint = function(checkpoints) { |
|
235 | MenuBar.prototype.update_restore_checkpoint = function(checkpoints) { | |
237 | if (! checkpoints) { |
|
236 | if (! checkpoints) { | |
238 | checkpoints = []; |
|
237 | checkpoints = []; | |
239 | }; |
|
238 | }; | |
240 | this.element.find("#restore_checkpoint").find("ul").find("li").each(function(i) { |
|
239 | this.element.find("#restore_checkpoint").find("ul").find("li").each(function(i) { | |
241 | var li = $(this); |
|
240 | var li = $(this); | |
242 | var a = li.find("a"); |
|
241 | var a = li.find("a"); | |
243 | a.off("click"); |
|
242 | a.off("click"); | |
244 | if (checkpoints.length <= i) { |
|
243 | if (checkpoints.length <= i) { | |
245 | li.hide(); |
|
244 | li.hide(); | |
246 | return; |
|
245 | return; | |
247 | } else { |
|
246 | } else { | |
248 | li.show(); |
|
247 | li.show(); | |
249 | }; |
|
248 | }; | |
250 | var checkpoint = checkpoints[i]; |
|
249 | var checkpoint = checkpoints[i]; | |
251 | var d = new Date(checkpoint.last_modified); |
|
250 | var d = new Date(checkpoint.last_modified); | |
252 | li.find('a').text( |
|
251 | li.find('a').text( | |
253 | d.format("mmm dd HH:MM:ss") |
|
252 | d.format("mmm dd HH:MM:ss") | |
254 | ).click(function () { |
|
253 | ).click(function () { | |
255 | IPython.notebook.restore_checkpoint_dialog(checkpoint); |
|
254 | IPython.notebook.restore_checkpoint_dialog(checkpoint); | |
256 | }); |
|
255 | }); | |
257 | }); |
|
256 | }); | |
258 | }; |
|
257 | }; | |
259 |
|
258 | |||
260 | IPython.MenuBar = MenuBar; |
|
259 | IPython.MenuBar = MenuBar; | |
261 |
|
260 | |||
262 | return IPython; |
|
261 | return IPython; | |
263 |
|
262 | |||
264 | }(IPython)); |
|
263 | }(IPython)); |
@@ -1,2046 +1,2010 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Notebook |
|
9 | // Notebook | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | var IPython = (function (IPython) { |
|
12 | var IPython = (function (IPython) { | |
13 |
|
13 | |||
14 | var utils = IPython.utils; |
|
14 | var utils = IPython.utils; | |
15 | var key = IPython.utils.keycodes; |
|
15 | var key = IPython.utils.keycodes; | |
16 |
|
16 | |||
17 | /** |
|
17 | /** | |
18 | * A notebook contains and manages cells. |
|
18 | * A notebook contains and manages cells. | |
19 | * |
|
19 | * | |
20 | * @class Notebook |
|
20 | * @class Notebook | |
21 | * @constructor |
|
21 | * @constructor | |
22 | * @param {String} selector A jQuery selector for the notebook's DOM element |
|
22 | * @param {String} selector A jQuery selector for the notebook's DOM element | |
23 | * @param {Object} [options] A config object |
|
23 | * @param {Object} [options] A config object | |
24 | */ |
|
24 | */ | |
25 | var Notebook = function (selector, options) { |
|
25 | var Notebook = function (selector, options) { | |
26 | var options = options || {}; |
|
26 | var options = options || {}; | |
27 | this._baseProjectUrl = options.baseProjectUrl; |
|
27 | this._baseProjectUrl = options.baseProjectUrl; | |
28 | this.read_only = options.read_only || IPython.read_only; |
|
28 | this.read_only = options.read_only || IPython.read_only; | |
29 |
|
29 | |||
30 | this.element = $(selector); |
|
30 | this.element = $(selector); | |
31 | this.element.scroll(); |
|
31 | this.element.scroll(); | |
32 | this.element.data("notebook", this); |
|
32 | this.element.data("notebook", this); | |
33 | this.next_prompt_number = 1; |
|
33 | this.next_prompt_number = 1; | |
34 | this.kernel = null; |
|
34 | this.kernel = null; | |
35 | this.clipboard = null; |
|
35 | this.clipboard = null; | |
36 | this.undelete_backup = null; |
|
36 | this.undelete_backup = null; | |
37 | this.undelete_index = null; |
|
37 | this.undelete_index = null; | |
38 | this.undelete_below = false; |
|
38 | this.undelete_below = false; | |
39 | this.paste_enabled = false; |
|
39 | this.paste_enabled = false; | |
40 | this.set_dirty(false); |
|
40 | this.set_dirty(false); | |
41 | this.metadata = {}; |
|
41 | this.metadata = {}; | |
42 | this._checkpoint_after_save = false; |
|
42 | this._checkpoint_after_save = false; | |
43 | this.last_checkpoint = null; |
|
43 | this.last_checkpoint = null; | |
44 | this.autosave_interval = 0; |
|
44 | this.autosave_interval = 0; | |
45 | this.autosave_timer = null; |
|
45 | this.autosave_timer = null; | |
46 | // autosave *at most* every two minutes |
|
46 | // autosave *at most* every two minutes | |
47 | this.minimum_autosave_interval = 120000; |
|
47 | this.minimum_autosave_interval = 120000; | |
48 | // single worksheet for now |
|
48 | // single worksheet for now | |
49 | this.worksheet_metadata = {}; |
|
49 | this.worksheet_metadata = {}; | |
50 | this.control_key_active = false; |
|
50 | this.control_key_active = false; | |
51 | this.notebook_id = null; |
|
51 | this.notebook_id = null; | |
52 | this.notebook_name = null; |
|
52 | this.notebook_name = null; | |
53 | this.notebook_name_blacklist_re = /[\/\\:]/; |
|
53 | this.notebook_name_blacklist_re = /[\/\\:]/; | |
54 | this.nbformat = 3 // Increment this when changing the nbformat |
|
54 | this.nbformat = 3 // Increment this when changing the nbformat | |
55 | this.nbformat_minor = 0 // Increment this when changing the nbformat |
|
55 | this.nbformat_minor = 0 // Increment this when changing the nbformat | |
56 | this.style(); |
|
56 | this.style(); | |
57 | this.create_elements(); |
|
57 | this.create_elements(); | |
58 | this.bind_events(); |
|
58 | this.bind_events(); | |
59 | }; |
|
59 | }; | |
60 |
|
60 | |||
61 | /** |
|
61 | /** | |
62 | * Tweak the notebook's CSS style. |
|
62 | * Tweak the notebook's CSS style. | |
63 | * |
|
63 | * | |
64 | * @method style |
|
64 | * @method style | |
65 | */ |
|
65 | */ | |
66 | Notebook.prototype.style = function () { |
|
66 | Notebook.prototype.style = function () { | |
67 | $('div#notebook').addClass('border-box-sizing'); |
|
67 | $('div#notebook').addClass('border-box-sizing'); | |
68 | }; |
|
68 | }; | |
69 |
|
69 | |||
70 | /** |
|
70 | /** | |
71 | * Get the root URL of the notebook server. |
|
71 | * Get the root URL of the notebook server. | |
72 | * |
|
72 | * | |
73 | * @method baseProjectUrl |
|
73 | * @method baseProjectUrl | |
74 | * @return {String} The base project URL |
|
74 | * @return {String} The base project URL | |
75 | */ |
|
75 | */ | |
76 | Notebook.prototype.baseProjectUrl = function(){ |
|
76 | Notebook.prototype.baseProjectUrl = function(){ | |
77 | return this._baseProjectUrl || $('body').data('baseProjectUrl'); |
|
77 | return this._baseProjectUrl || $('body').data('baseProjectUrl'); | |
78 | }; |
|
78 | }; | |
79 |
|
79 | |||
80 | /** |
|
80 | /** | |
81 | * Create an HTML and CSS representation of the notebook. |
|
81 | * Create an HTML and CSS representation of the notebook. | |
82 | * |
|
82 | * | |
83 | * @method create_elements |
|
83 | * @method create_elements | |
84 | */ |
|
84 | */ | |
85 | Notebook.prototype.create_elements = function () { |
|
85 | Notebook.prototype.create_elements = function () { | |
86 | // We add this end_space div to the end of the notebook div to: |
|
86 | // We add this end_space div to the end of the notebook div to: | |
87 | // i) provide a margin between the last cell and the end of the notebook |
|
87 | // i) provide a margin between the last cell and the end of the notebook | |
88 | // ii) to prevent the div from scrolling up when the last cell is being |
|
88 | // ii) to prevent the div from scrolling up when the last cell is being | |
89 | // edited, but is too low on the page, which browsers will do automatically. |
|
89 | // edited, but is too low on the page, which browsers will do automatically. | |
90 | var that = this; |
|
90 | var that = this; | |
91 | var end_space = $('<div/>').addClass('end_space').height("30%"); |
|
91 | this.container = $("<div/>").addClass("container").attr("id", "notebook-container"); | |
|
92 | var end_space = $('<div/>').addClass('end_space'); | |||
92 | end_space.dblclick(function (e) { |
|
93 | end_space.dblclick(function (e) { | |
93 | if (that.read_only) return; |
|
94 | if (that.read_only) return; | |
94 | var ncells = that.ncells(); |
|
95 | var ncells = that.ncells(); | |
95 | that.insert_cell_below('code',ncells-1); |
|
96 | that.insert_cell_below('code',ncells-1); | |
96 | }); |
|
97 | }); | |
97 |
this.element.append( |
|
98 | this.element.append(this.container); | |
|
99 | this.container.append(end_space); | |||
98 | $('div#notebook').addClass('border-box-sizing'); |
|
100 | $('div#notebook').addClass('border-box-sizing'); | |
99 | }; |
|
101 | }; | |
100 |
|
102 | |||
101 | /** |
|
103 | /** | |
102 | * Bind JavaScript events: key presses and custom IPython events. |
|
104 | * Bind JavaScript events: key presses and custom IPython events. | |
103 | * |
|
105 | * | |
104 | * @method bind_events |
|
106 | * @method bind_events | |
105 | */ |
|
107 | */ | |
106 | Notebook.prototype.bind_events = function () { |
|
108 | Notebook.prototype.bind_events = function () { | |
107 | var that = this; |
|
109 | var that = this; | |
108 |
|
110 | |||
109 | $([IPython.events]).on('set_next_input.Notebook', function (event, data) { |
|
111 | $([IPython.events]).on('set_next_input.Notebook', function (event, data) { | |
110 | var index = that.find_cell_index(data.cell); |
|
112 | var index = that.find_cell_index(data.cell); | |
111 | var new_cell = that.insert_cell_below('code',index); |
|
113 | var new_cell = that.insert_cell_below('code',index); | |
112 | new_cell.set_text(data.text); |
|
114 | new_cell.set_text(data.text); | |
113 | that.dirty = true; |
|
115 | that.dirty = true; | |
114 | }); |
|
116 | }); | |
115 |
|
117 | |||
116 | $([IPython.events]).on('set_dirty.Notebook', function (event, data) { |
|
118 | $([IPython.events]).on('set_dirty.Notebook', function (event, data) { | |
117 | that.dirty = data.value; |
|
119 | that.dirty = data.value; | |
118 | }); |
|
120 | }); | |
119 |
|
121 | |||
120 | $([IPython.events]).on('select.Cell', function (event, data) { |
|
122 | $([IPython.events]).on('select.Cell', function (event, data) { | |
121 | var index = that.find_cell_index(data.cell); |
|
123 | var index = that.find_cell_index(data.cell); | |
122 | that.select(index); |
|
124 | that.select(index); | |
123 | }); |
|
125 | }); | |
124 |
|
126 | |||
125 |
|
127 | |||
126 | $(document).keydown(function (event) { |
|
128 | $(document).keydown(function (event) { | |
127 | // console.log(event); |
|
129 | // console.log(event); | |
128 | if (that.read_only) return true; |
|
130 | if (that.read_only) return true; | |
129 |
|
131 | |||
130 | // Save (CTRL+S) or (AppleKey+S) |
|
132 | // Save (CTRL+S) or (AppleKey+S) | |
131 | //metaKey = applekey on mac |
|
133 | //metaKey = applekey on mac | |
132 | if ((event.ctrlKey || event.metaKey) && event.keyCode==83) { |
|
134 | if ((event.ctrlKey || event.metaKey) && event.keyCode==83) { | |
133 | that.save_checkpoint(); |
|
135 | that.save_checkpoint(); | |
134 | event.preventDefault(); |
|
136 | event.preventDefault(); | |
135 | return false; |
|
137 | return false; | |
136 | } else if (event.which === key.ESC) { |
|
138 | } else if (event.which === key.ESC) { | |
137 | // Intercept escape at highest level to avoid closing |
|
139 | // Intercept escape at highest level to avoid closing | |
138 | // websocket connection with firefox |
|
140 | // websocket connection with firefox | |
139 | IPython.pager.collapse(); |
|
141 | IPython.pager.collapse(); | |
140 | event.preventDefault(); |
|
142 | event.preventDefault(); | |
141 | } else if (event.which === key.SHIFT) { |
|
143 | } else if (event.which === key.SHIFT) { | |
142 | // ignore shift keydown |
|
144 | // ignore shift keydown | |
143 | return true; |
|
145 | return true; | |
144 | } |
|
146 | } | |
145 | if (event.which === key.UPARROW && !event.shiftKey) { |
|
147 | if (event.which === key.UPARROW && !event.shiftKey) { | |
146 | var cell = that.get_selected_cell(); |
|
148 | var cell = that.get_selected_cell(); | |
147 | if (cell && cell.at_top()) { |
|
149 | if (cell && cell.at_top()) { | |
148 | event.preventDefault(); |
|
150 | event.preventDefault(); | |
149 | that.select_prev(); |
|
151 | that.select_prev(); | |
150 | }; |
|
152 | }; | |
151 | } else if (event.which === key.DOWNARROW && !event.shiftKey) { |
|
153 | } else if (event.which === key.DOWNARROW && !event.shiftKey) { | |
152 | var cell = that.get_selected_cell(); |
|
154 | var cell = that.get_selected_cell(); | |
153 | if (cell && cell.at_bottom()) { |
|
155 | if (cell && cell.at_bottom()) { | |
154 | event.preventDefault(); |
|
156 | event.preventDefault(); | |
155 | that.select_next(); |
|
157 | that.select_next(); | |
156 | }; |
|
158 | }; | |
157 | } else if (event.which === key.ENTER && event.shiftKey) { |
|
159 | } else if (event.which === key.ENTER && event.shiftKey) { | |
158 | that.execute_selected_cell(); |
|
160 | that.execute_selected_cell(); | |
159 | return false; |
|
161 | return false; | |
160 | } else if (event.which === key.ENTER && event.altKey) { |
|
162 | } else if (event.which === key.ENTER && event.altKey) { | |
161 | // Execute code cell, and insert new in place |
|
163 | // Execute code cell, and insert new in place | |
162 | that.execute_selected_cell(); |
|
164 | that.execute_selected_cell(); | |
163 | // Only insert a new cell, if we ended up in an already populated cell |
|
165 | // Only insert a new cell, if we ended up in an already populated cell | |
164 | if (/\S/.test(that.get_selected_cell().get_text()) == true) { |
|
166 | if (/\S/.test(that.get_selected_cell().get_text()) == true) { | |
165 | that.insert_cell_above('code'); |
|
167 | that.insert_cell_above('code'); | |
166 | } |
|
168 | } | |
167 | return false; |
|
169 | return false; | |
168 | } else if (event.which === key.ENTER && event.ctrlKey) { |
|
170 | } else if (event.which === key.ENTER && event.ctrlKey) { | |
169 | that.execute_selected_cell({terminal:true}); |
|
171 | that.execute_selected_cell({terminal:true}); | |
170 | return false; |
|
172 | return false; | |
171 | } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) { |
|
173 | } else if (event.which === 77 && event.ctrlKey && that.control_key_active == false) { | |
172 | that.control_key_active = true; |
|
174 | that.control_key_active = true; | |
173 | return false; |
|
175 | return false; | |
174 | } else if (event.which === 88 && that.control_key_active) { |
|
176 | } else if (event.which === 88 && that.control_key_active) { | |
175 | // Cut selected cell = x |
|
177 | // Cut selected cell = x | |
176 | that.cut_cell(); |
|
178 | that.cut_cell(); | |
177 | that.control_key_active = false; |
|
179 | that.control_key_active = false; | |
178 | return false; |
|
180 | return false; | |
179 | } else if (event.which === 67 && that.control_key_active) { |
|
181 | } else if (event.which === 67 && that.control_key_active) { | |
180 | // Copy selected cell = c |
|
182 | // Copy selected cell = c | |
181 | that.copy_cell(); |
|
183 | that.copy_cell(); | |
182 | that.control_key_active = false; |
|
184 | that.control_key_active = false; | |
183 | return false; |
|
185 | return false; | |
184 | } else if (event.which === 86 && that.control_key_active) { |
|
186 | } else if (event.which === 86 && that.control_key_active) { | |
185 | // Paste below selected cell = v |
|
187 | // Paste below selected cell = v | |
186 | that.paste_cell_below(); |
|
188 | that.paste_cell_below(); | |
187 | that.control_key_active = false; |
|
189 | that.control_key_active = false; | |
188 | return false; |
|
190 | return false; | |
189 | } else if (event.which === 68 && that.control_key_active) { |
|
191 | } else if (event.which === 68 && that.control_key_active) { | |
190 | // Delete selected cell = d |
|
192 | // Delete selected cell = d | |
191 | that.delete_cell(); |
|
193 | that.delete_cell(); | |
192 | that.control_key_active = false; |
|
194 | that.control_key_active = false; | |
193 | return false; |
|
195 | return false; | |
194 | } else if (event.which === 65 && that.control_key_active) { |
|
196 | } else if (event.which === 65 && that.control_key_active) { | |
195 | // Insert code cell above selected = a |
|
197 | // Insert code cell above selected = a | |
196 | that.insert_cell_above('code'); |
|
198 | that.insert_cell_above('code'); | |
197 | that.control_key_active = false; |
|
199 | that.control_key_active = false; | |
198 | return false; |
|
200 | return false; | |
199 | } else if (event.which === 66 && that.control_key_active) { |
|
201 | } else if (event.which === 66 && that.control_key_active) { | |
200 | // Insert code cell below selected = b |
|
202 | // Insert code cell below selected = b | |
201 | that.insert_cell_below('code'); |
|
203 | that.insert_cell_below('code'); | |
202 | that.control_key_active = false; |
|
204 | that.control_key_active = false; | |
203 | return false; |
|
205 | return false; | |
204 | } else if (event.which === 89 && that.control_key_active) { |
|
206 | } else if (event.which === 89 && that.control_key_active) { | |
205 | // To code = y |
|
207 | // To code = y | |
206 | that.to_code(); |
|
208 | that.to_code(); | |
207 | that.control_key_active = false; |
|
209 | that.control_key_active = false; | |
208 | return false; |
|
210 | return false; | |
209 | } else if (event.which === 77 && that.control_key_active) { |
|
211 | } else if (event.which === 77 && that.control_key_active) { | |
210 | // To markdown = m |
|
212 | // To markdown = m | |
211 | that.to_markdown(); |
|
213 | that.to_markdown(); | |
212 | that.control_key_active = false; |
|
214 | that.control_key_active = false; | |
213 | return false; |
|
215 | return false; | |
214 | } else if (event.which === 84 && that.control_key_active) { |
|
216 | } else if (event.which === 84 && that.control_key_active) { | |
215 | // To Raw = t |
|
217 | // To Raw = t | |
216 | that.to_raw(); |
|
218 | that.to_raw(); | |
217 | that.control_key_active = false; |
|
219 | that.control_key_active = false; | |
218 | return false; |
|
220 | return false; | |
219 | } else if (event.which === 49 && that.control_key_active) { |
|
221 | } else if (event.which === 49 && that.control_key_active) { | |
220 | // To Heading 1 = 1 |
|
222 | // To Heading 1 = 1 | |
221 | that.to_heading(undefined, 1); |
|
223 | that.to_heading(undefined, 1); | |
222 | that.control_key_active = false; |
|
224 | that.control_key_active = false; | |
223 | return false; |
|
225 | return false; | |
224 | } else if (event.which === 50 && that.control_key_active) { |
|
226 | } else if (event.which === 50 && that.control_key_active) { | |
225 | // To Heading 2 = 2 |
|
227 | // To Heading 2 = 2 | |
226 | that.to_heading(undefined, 2); |
|
228 | that.to_heading(undefined, 2); | |
227 | that.control_key_active = false; |
|
229 | that.control_key_active = false; | |
228 | return false; |
|
230 | return false; | |
229 | } else if (event.which === 51 && that.control_key_active) { |
|
231 | } else if (event.which === 51 && that.control_key_active) { | |
230 | // To Heading 3 = 3 |
|
232 | // To Heading 3 = 3 | |
231 | that.to_heading(undefined, 3); |
|
233 | that.to_heading(undefined, 3); | |
232 | that.control_key_active = false; |
|
234 | that.control_key_active = false; | |
233 | return false; |
|
235 | return false; | |
234 | } else if (event.which === 52 && that.control_key_active) { |
|
236 | } else if (event.which === 52 && that.control_key_active) { | |
235 | // To Heading 4 = 4 |
|
237 | // To Heading 4 = 4 | |
236 | that.to_heading(undefined, 4); |
|
238 | that.to_heading(undefined, 4); | |
237 | that.control_key_active = false; |
|
239 | that.control_key_active = false; | |
238 | return false; |
|
240 | return false; | |
239 | } else if (event.which === 53 && that.control_key_active) { |
|
241 | } else if (event.which === 53 && that.control_key_active) { | |
240 | // To Heading 5 = 5 |
|
242 | // To Heading 5 = 5 | |
241 | that.to_heading(undefined, 5); |
|
243 | that.to_heading(undefined, 5); | |
242 | that.control_key_active = false; |
|
244 | that.control_key_active = false; | |
243 | return false; |
|
245 | return false; | |
244 | } else if (event.which === 54 && that.control_key_active) { |
|
246 | } else if (event.which === 54 && that.control_key_active) { | |
245 | // To Heading 6 = 6 |
|
247 | // To Heading 6 = 6 | |
246 | that.to_heading(undefined, 6); |
|
248 | that.to_heading(undefined, 6); | |
247 | that.control_key_active = false; |
|
249 | that.control_key_active = false; | |
248 | return false; |
|
250 | return false; | |
249 | } else if (event.which === 79 && that.control_key_active) { |
|
251 | } else if (event.which === 79 && that.control_key_active) { | |
250 | // Toggle output = o |
|
252 | // Toggle output = o | |
251 | if (event.shiftKey){ |
|
253 | if (event.shiftKey){ | |
252 | that.toggle_output_scroll(); |
|
254 | that.toggle_output_scroll(); | |
253 | } else { |
|
255 | } else { | |
254 | that.toggle_output(); |
|
256 | that.toggle_output(); | |
255 | } |
|
257 | } | |
256 | that.control_key_active = false; |
|
258 | that.control_key_active = false; | |
257 | return false; |
|
259 | return false; | |
258 | } else if (event.which === 83 && that.control_key_active) { |
|
260 | } else if (event.which === 83 && that.control_key_active) { | |
259 | // Save notebook = s |
|
261 | // Save notebook = s | |
260 | that.save_checkpoint(); |
|
262 | that.save_checkpoint(); | |
261 | that.control_key_active = false; |
|
263 | that.control_key_active = false; | |
262 | return false; |
|
264 | return false; | |
263 | } else if (event.which === 74 && that.control_key_active) { |
|
265 | } else if (event.which === 74 && that.control_key_active) { | |
264 | // Move cell down = j |
|
266 | // Move cell down = j | |
265 | that.move_cell_down(); |
|
267 | that.move_cell_down(); | |
266 | that.control_key_active = false; |
|
268 | that.control_key_active = false; | |
267 | return false; |
|
269 | return false; | |
268 | } else if (event.which === 75 && that.control_key_active) { |
|
270 | } else if (event.which === 75 && that.control_key_active) { | |
269 | // Move cell up = k |
|
271 | // Move cell up = k | |
270 | that.move_cell_up(); |
|
272 | that.move_cell_up(); | |
271 | that.control_key_active = false; |
|
273 | that.control_key_active = false; | |
272 | return false; |
|
274 | return false; | |
273 | } else if (event.which === 80 && that.control_key_active) { |
|
275 | } else if (event.which === 80 && that.control_key_active) { | |
274 | // Select previous = p |
|
276 | // Select previous = p | |
275 | that.select_prev(); |
|
277 | that.select_prev(); | |
276 | that.control_key_active = false; |
|
278 | that.control_key_active = false; | |
277 | return false; |
|
279 | return false; | |
278 | } else if (event.which === 78 && that.control_key_active) { |
|
280 | } else if (event.which === 78 && that.control_key_active) { | |
279 | // Select next = n |
|
281 | // Select next = n | |
280 | that.select_next(); |
|
282 | that.select_next(); | |
281 | that.control_key_active = false; |
|
283 | that.control_key_active = false; | |
282 | return false; |
|
284 | return false; | |
283 | } else if (event.which === 76 && that.control_key_active) { |
|
285 | } else if (event.which === 76 && that.control_key_active) { | |
284 | // Toggle line numbers = l |
|
286 | // Toggle line numbers = l | |
285 | that.cell_toggle_line_numbers(); |
|
287 | that.cell_toggle_line_numbers(); | |
286 | that.control_key_active = false; |
|
288 | that.control_key_active = false; | |
287 | return false; |
|
289 | return false; | |
288 | } else if (event.which === 73 && that.control_key_active) { |
|
290 | } else if (event.which === 73 && that.control_key_active) { | |
289 | // Interrupt kernel = i |
|
291 | // Interrupt kernel = i | |
290 | that.kernel.interrupt(); |
|
292 | that.kernel.interrupt(); | |
291 | that.control_key_active = false; |
|
293 | that.control_key_active = false; | |
292 | return false; |
|
294 | return false; | |
293 | } else if (event.which === 190 && that.control_key_active) { |
|
295 | } else if (event.which === 190 && that.control_key_active) { | |
294 | // Restart kernel = . # matches qt console |
|
296 | // Restart kernel = . # matches qt console | |
295 | that.restart_kernel(); |
|
297 | that.restart_kernel(); | |
296 | that.control_key_active = false; |
|
298 | that.control_key_active = false; | |
297 | return false; |
|
299 | return false; | |
298 | } else if (event.which === 72 && that.control_key_active) { |
|
300 | } else if (event.which === 72 && that.control_key_active) { | |
299 | // Show keyboard shortcuts = h |
|
301 | // Show keyboard shortcuts = h | |
300 | IPython.quick_help.show_keyboard_shortcuts(); |
|
302 | IPython.quick_help.show_keyboard_shortcuts(); | |
301 | that.control_key_active = false; |
|
303 | that.control_key_active = false; | |
302 | return false; |
|
304 | return false; | |
303 | } else if (event.which === 90 && that.control_key_active) { |
|
305 | } else if (event.which === 90 && that.control_key_active) { | |
304 | // Undo last cell delete = z |
|
306 | // Undo last cell delete = z | |
305 | that.undelete(); |
|
307 | that.undelete(); | |
306 | that.control_key_active = false; |
|
308 | that.control_key_active = false; | |
307 | return false; |
|
309 | return false; | |
308 | } else if (that.control_key_active) { |
|
310 | } else if (that.control_key_active) { | |
309 | that.control_key_active = false; |
|
311 | that.control_key_active = false; | |
310 | return true; |
|
312 | return true; | |
311 | } |
|
313 | } | |
312 | return true; |
|
314 | return true; | |
313 | }); |
|
315 | }); | |
314 |
|
316 | |||
315 | var collapse_time = function(time){ |
|
317 | var collapse_time = function(time){ | |
316 | var app_height = $('#ipython-main-app').height(); // content height |
|
318 | var app_height = $('#ipython-main-app').height(); // content height | |
317 | var splitter_height = $('div#pager_splitter').outerHeight(true); |
|
319 | var splitter_height = $('div#pager_splitter').outerHeight(true); | |
318 | var new_height = app_height - splitter_height; |
|
320 | var new_height = app_height - splitter_height; | |
319 | that.element.animate({height : new_height + 'px'}, time); |
|
321 | that.element.animate({height : new_height + 'px'}, time); | |
320 | } |
|
322 | } | |
321 |
|
323 | |||
322 | this.element.bind('collapse_pager', function (event,extrap) { |
|
324 | this.element.bind('collapse_pager', function (event,extrap) { | |
323 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
325 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; | |
324 | collapse_time(time); |
|
326 | collapse_time(time); | |
325 | }); |
|
327 | }); | |
326 |
|
328 | |||
327 | var expand_time = function(time) { |
|
329 | var expand_time = function(time) { | |
328 | var app_height = $('#ipython-main-app').height(); // content height |
|
330 | var app_height = $('#ipython-main-app').height(); // content height | |
329 | var splitter_height = $('div#pager_splitter').outerHeight(true); |
|
331 | var splitter_height = $('div#pager_splitter').outerHeight(true); | |
330 | var pager_height = $('div#pager').outerHeight(true); |
|
332 | var pager_height = $('div#pager').outerHeight(true); | |
331 | var new_height = app_height - pager_height - splitter_height; |
|
333 | var new_height = app_height - pager_height - splitter_height; | |
332 | that.element.animate({height : new_height + 'px'}, time); |
|
334 | that.element.animate({height : new_height + 'px'}, time); | |
333 | } |
|
335 | } | |
334 |
|
336 | |||
335 | this.element.bind('expand_pager', function (event, extrap) { |
|
337 | this.element.bind('expand_pager', function (event, extrap) { | |
336 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
338 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; | |
337 | expand_time(time); |
|
339 | expand_time(time); | |
338 | }); |
|
340 | }); | |
339 |
|
341 | |||
340 | $(window).bind('beforeunload', function () { |
|
342 | $(window).bind('beforeunload', function () { | |
341 | // TODO: Make killing the kernel configurable. |
|
343 | // TODO: Make killing the kernel configurable. | |
342 | var kill_kernel = false; |
|
344 | var kill_kernel = false; | |
343 | if (kill_kernel) { |
|
345 | if (kill_kernel) { | |
344 | that.kernel.kill(); |
|
346 | that.kernel.kill(); | |
345 | } |
|
347 | } | |
346 | // if we are autosaving, trigger an autosave on nav-away |
|
348 | // if we are autosaving, trigger an autosave on nav-away | |
347 | if (that.dirty && that.autosave_interval && ! that.read_only) { |
|
349 | if (that.dirty && that.autosave_interval && ! that.read_only) { | |
348 | that.save_notebook(); |
|
350 | that.save_notebook(); | |
349 | }; |
|
351 | }; | |
350 | // Null is the *only* return value that will make the browser not |
|
352 | // Null is the *only* return value that will make the browser not | |
351 | // pop up the "don't leave" dialog. |
|
353 | // pop up the "don't leave" dialog. | |
352 | return null; |
|
354 | return null; | |
353 | }); |
|
355 | }); | |
354 | }; |
|
356 | }; | |
355 |
|
357 | |||
356 | /** |
|
358 | /** | |
357 | * Set the dirty flag, and trigger the set_dirty.Notebook event |
|
359 | * Set the dirty flag, and trigger the set_dirty.Notebook event | |
358 | * |
|
360 | * | |
359 | * @method set_dirty |
|
361 | * @method set_dirty | |
360 | */ |
|
362 | */ | |
361 | Notebook.prototype.set_dirty = function (value) { |
|
363 | Notebook.prototype.set_dirty = function (value) { | |
362 | if (value === undefined) { |
|
364 | if (value === undefined) { | |
363 | value = true; |
|
365 | value = true; | |
364 | } |
|
366 | } | |
365 | if (this.dirty == value) { |
|
367 | if (this.dirty == value) { | |
366 | return; |
|
368 | return; | |
367 | } |
|
369 | } | |
368 | $([IPython.events]).trigger('set_dirty.Notebook', {value: value}); |
|
370 | $([IPython.events]).trigger('set_dirty.Notebook', {value: value}); | |
369 | }; |
|
371 | }; | |
370 |
|
372 | |||
371 | /** |
|
373 | /** | |
372 | * Scroll the top of the page to a given cell. |
|
374 | * Scroll the top of the page to a given cell. | |
373 | * |
|
375 | * | |
374 | * @method scroll_to_cell |
|
376 | * @method scroll_to_cell | |
375 | * @param {Number} cell_number An index of the cell to view |
|
377 | * @param {Number} cell_number An index of the cell to view | |
376 | * @param {Number} time Animation time in milliseconds |
|
378 | * @param {Number} time Animation time in milliseconds | |
377 | * @return {Number} Pixel offset from the top of the container |
|
379 | * @return {Number} Pixel offset from the top of the container | |
378 | */ |
|
380 | */ | |
379 | Notebook.prototype.scroll_to_cell = function (cell_number, time) { |
|
381 | Notebook.prototype.scroll_to_cell = function (cell_number, time) { | |
380 | var cells = this.get_cells(); |
|
382 | var cells = this.get_cells(); | |
381 | var time = time || 0; |
|
383 | var time = time || 0; | |
382 | cell_number = Math.min(cells.length-1,cell_number); |
|
384 | cell_number = Math.min(cells.length-1,cell_number); | |
383 | cell_number = Math.max(0 ,cell_number); |
|
385 | cell_number = Math.max(0 ,cell_number); | |
384 | var scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ; |
|
386 | var scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ; | |
385 | this.element.animate({scrollTop:scroll_value}, time); |
|
387 | this.element.animate({scrollTop:scroll_value}, time); | |
386 | return scroll_value; |
|
388 | return scroll_value; | |
387 | }; |
|
389 | }; | |
388 |
|
390 | |||
389 | /** |
|
391 | /** | |
390 | * Scroll to the bottom of the page. |
|
392 | * Scroll to the bottom of the page. | |
391 | * |
|
393 | * | |
392 | * @method scroll_to_bottom |
|
394 | * @method scroll_to_bottom | |
393 | */ |
|
395 | */ | |
394 | Notebook.prototype.scroll_to_bottom = function () { |
|
396 | Notebook.prototype.scroll_to_bottom = function () { | |
395 | this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0); |
|
397 | this.element.animate({scrollTop:this.element.get(0).scrollHeight}, 0); | |
396 | }; |
|
398 | }; | |
397 |
|
399 | |||
398 | /** |
|
400 | /** | |
399 | * Scroll to the top of the page. |
|
401 | * Scroll to the top of the page. | |
400 | * |
|
402 | * | |
401 | * @method scroll_to_top |
|
403 | * @method scroll_to_top | |
402 | */ |
|
404 | */ | |
403 | Notebook.prototype.scroll_to_top = function () { |
|
405 | Notebook.prototype.scroll_to_top = function () { | |
404 | this.element.animate({scrollTop:0}, 0); |
|
406 | this.element.animate({scrollTop:0}, 0); | |
405 | }; |
|
407 | }; | |
406 |
|
408 | |||
407 |
|
409 | |||
408 | // Cell indexing, retrieval, etc. |
|
410 | // Cell indexing, retrieval, etc. | |
409 |
|
411 | |||
410 | /** |
|
412 | /** | |
411 | * Get all cell elements in the notebook. |
|
413 | * Get all cell elements in the notebook. | |
412 | * |
|
414 | * | |
413 | * @method get_cell_elements |
|
415 | * @method get_cell_elements | |
414 | * @return {jQuery} A selector of all cell elements |
|
416 | * @return {jQuery} A selector of all cell elements | |
415 | */ |
|
417 | */ | |
416 | Notebook.prototype.get_cell_elements = function () { |
|
418 | Notebook.prototype.get_cell_elements = function () { | |
417 |
return this. |
|
419 | return this.container.children("div.cell"); | |
418 | }; |
|
420 | }; | |
419 |
|
421 | |||
420 | /** |
|
422 | /** | |
421 | * Get a particular cell element. |
|
423 | * Get a particular cell element. | |
422 | * |
|
424 | * | |
423 | * @method get_cell_element |
|
425 | * @method get_cell_element | |
424 | * @param {Number} index An index of a cell to select |
|
426 | * @param {Number} index An index of a cell to select | |
425 | * @return {jQuery} A selector of the given cell. |
|
427 | * @return {jQuery} A selector of the given cell. | |
426 | */ |
|
428 | */ | |
427 | Notebook.prototype.get_cell_element = function (index) { |
|
429 | Notebook.prototype.get_cell_element = function (index) { | |
428 | var result = null; |
|
430 | var result = null; | |
429 | var e = this.get_cell_elements().eq(index); |
|
431 | var e = this.get_cell_elements().eq(index); | |
430 | if (e.length !== 0) { |
|
432 | if (e.length !== 0) { | |
431 | result = e; |
|
433 | result = e; | |
432 | } |
|
434 | } | |
433 | return result; |
|
435 | return result; | |
434 | }; |
|
436 | }; | |
435 |
|
437 | |||
436 | /** |
|
438 | /** | |
437 | * Count the cells in this notebook. |
|
439 | * Count the cells in this notebook. | |
438 | * |
|
440 | * | |
439 | * @method ncells |
|
441 | * @method ncells | |
440 | * @return {Number} The number of cells in this notebook |
|
442 | * @return {Number} The number of cells in this notebook | |
441 | */ |
|
443 | */ | |
442 | Notebook.prototype.ncells = function () { |
|
444 | Notebook.prototype.ncells = function () { | |
443 | return this.get_cell_elements().length; |
|
445 | return this.get_cell_elements().length; | |
444 | }; |
|
446 | }; | |
445 |
|
447 | |||
446 | /** |
|
448 | /** | |
447 | * Get all Cell objects in this notebook. |
|
449 | * Get all Cell objects in this notebook. | |
448 | * |
|
450 | * | |
449 | * @method get_cells |
|
451 | * @method get_cells | |
450 | * @return {Array} This notebook's Cell objects |
|
452 | * @return {Array} This notebook's Cell objects | |
451 | */ |
|
453 | */ | |
452 | // TODO: we are often calling cells as cells()[i], which we should optimize |
|
454 | // TODO: we are often calling cells as cells()[i], which we should optimize | |
453 | // to cells(i) or a new method. |
|
455 | // to cells(i) or a new method. | |
454 | Notebook.prototype.get_cells = function () { |
|
456 | Notebook.prototype.get_cells = function () { | |
455 | return this.get_cell_elements().toArray().map(function (e) { |
|
457 | return this.get_cell_elements().toArray().map(function (e) { | |
456 | return $(e).data("cell"); |
|
458 | return $(e).data("cell"); | |
457 | }); |
|
459 | }); | |
458 | }; |
|
460 | }; | |
459 |
|
461 | |||
460 | /** |
|
462 | /** | |
461 | * Get a Cell object from this notebook. |
|
463 | * Get a Cell object from this notebook. | |
462 | * |
|
464 | * | |
463 | * @method get_cell |
|
465 | * @method get_cell | |
464 | * @param {Number} index An index of a cell to retrieve |
|
466 | * @param {Number} index An index of a cell to retrieve | |
465 | * @return {Cell} A particular cell |
|
467 | * @return {Cell} A particular cell | |
466 | */ |
|
468 | */ | |
467 | Notebook.prototype.get_cell = function (index) { |
|
469 | Notebook.prototype.get_cell = function (index) { | |
468 | var result = null; |
|
470 | var result = null; | |
469 | var ce = this.get_cell_element(index); |
|
471 | var ce = this.get_cell_element(index); | |
470 | if (ce !== null) { |
|
472 | if (ce !== null) { | |
471 | result = ce.data('cell'); |
|
473 | result = ce.data('cell'); | |
472 | } |
|
474 | } | |
473 | return result; |
|
475 | return result; | |
474 | } |
|
476 | } | |
475 |
|
477 | |||
476 | /** |
|
478 | /** | |
477 | * Get the cell below a given cell. |
|
479 | * Get the cell below a given cell. | |
478 | * |
|
480 | * | |
479 | * @method get_next_cell |
|
481 | * @method get_next_cell | |
480 | * @param {Cell} cell The provided cell |
|
482 | * @param {Cell} cell The provided cell | |
481 | * @return {Cell} The next cell |
|
483 | * @return {Cell} The next cell | |
482 | */ |
|
484 | */ | |
483 | Notebook.prototype.get_next_cell = function (cell) { |
|
485 | Notebook.prototype.get_next_cell = function (cell) { | |
484 | var result = null; |
|
486 | var result = null; | |
485 | var index = this.find_cell_index(cell); |
|
487 | var index = this.find_cell_index(cell); | |
486 | if (this.is_valid_cell_index(index+1)) { |
|
488 | if (this.is_valid_cell_index(index+1)) { | |
487 | result = this.get_cell(index+1); |
|
489 | result = this.get_cell(index+1); | |
488 | } |
|
490 | } | |
489 | return result; |
|
491 | return result; | |
490 | } |
|
492 | } | |
491 |
|
493 | |||
492 | /** |
|
494 | /** | |
493 | * Get the cell above a given cell. |
|
495 | * Get the cell above a given cell. | |
494 | * |
|
496 | * | |
495 | * @method get_prev_cell |
|
497 | * @method get_prev_cell | |
496 | * @param {Cell} cell The provided cell |
|
498 | * @param {Cell} cell The provided cell | |
497 | * @return {Cell} The previous cell |
|
499 | * @return {Cell} The previous cell | |
498 | */ |
|
500 | */ | |
499 | Notebook.prototype.get_prev_cell = function (cell) { |
|
501 | Notebook.prototype.get_prev_cell = function (cell) { | |
500 | // TODO: off-by-one |
|
502 | // TODO: off-by-one | |
501 | // nb.get_prev_cell(nb.get_cell(1)) is null |
|
503 | // nb.get_prev_cell(nb.get_cell(1)) is null | |
502 | var result = null; |
|
504 | var result = null; | |
503 | var index = this.find_cell_index(cell); |
|
505 | var index = this.find_cell_index(cell); | |
504 | if (index !== null && index > 1) { |
|
506 | if (index !== null && index > 1) { | |
505 | result = this.get_cell(index-1); |
|
507 | result = this.get_cell(index-1); | |
506 | } |
|
508 | } | |
507 | return result; |
|
509 | return result; | |
508 | } |
|
510 | } | |
509 |
|
511 | |||
510 | /** |
|
512 | /** | |
511 | * Get the numeric index of a given cell. |
|
513 | * Get the numeric index of a given cell. | |
512 | * |
|
514 | * | |
513 | * @method find_cell_index |
|
515 | * @method find_cell_index | |
514 | * @param {Cell} cell The provided cell |
|
516 | * @param {Cell} cell The provided cell | |
515 | * @return {Number} The cell's numeric index |
|
517 | * @return {Number} The cell's numeric index | |
516 | */ |
|
518 | */ | |
517 | Notebook.prototype.find_cell_index = function (cell) { |
|
519 | Notebook.prototype.find_cell_index = function (cell) { | |
518 | var result = null; |
|
520 | var result = null; | |
519 | this.get_cell_elements().filter(function (index) { |
|
521 | this.get_cell_elements().filter(function (index) { | |
520 | if ($(this).data("cell") === cell) { |
|
522 | if ($(this).data("cell") === cell) { | |
521 | result = index; |
|
523 | result = index; | |
522 | }; |
|
524 | }; | |
523 | }); |
|
525 | }); | |
524 | return result; |
|
526 | return result; | |
525 | }; |
|
527 | }; | |
526 |
|
528 | |||
527 | /** |
|
529 | /** | |
528 | * Get a given index , or the selected index if none is provided. |
|
530 | * Get a given index , or the selected index if none is provided. | |
529 | * |
|
531 | * | |
530 | * @method index_or_selected |
|
532 | * @method index_or_selected | |
531 | * @param {Number} index A cell's index |
|
533 | * @param {Number} index A cell's index | |
532 | * @return {Number} The given index, or selected index if none is provided. |
|
534 | * @return {Number} The given index, or selected index if none is provided. | |
533 | */ |
|
535 | */ | |
534 | Notebook.prototype.index_or_selected = function (index) { |
|
536 | Notebook.prototype.index_or_selected = function (index) { | |
535 | var i; |
|
537 | var i; | |
536 | if (index === undefined || index === null) { |
|
538 | if (index === undefined || index === null) { | |
537 | i = this.get_selected_index(); |
|
539 | i = this.get_selected_index(); | |
538 | if (i === null) { |
|
540 | if (i === null) { | |
539 | i = 0; |
|
541 | i = 0; | |
540 | } |
|
542 | } | |
541 | } else { |
|
543 | } else { | |
542 | i = index; |
|
544 | i = index; | |
543 | } |
|
545 | } | |
544 | return i; |
|
546 | return i; | |
545 | }; |
|
547 | }; | |
546 |
|
548 | |||
547 | /** |
|
549 | /** | |
548 | * Get the currently selected cell. |
|
550 | * Get the currently selected cell. | |
549 | * @method get_selected_cell |
|
551 | * @method get_selected_cell | |
550 | * @return {Cell} The selected cell |
|
552 | * @return {Cell} The selected cell | |
551 | */ |
|
553 | */ | |
552 | Notebook.prototype.get_selected_cell = function () { |
|
554 | Notebook.prototype.get_selected_cell = function () { | |
553 | var index = this.get_selected_index(); |
|
555 | var index = this.get_selected_index(); | |
554 | return this.get_cell(index); |
|
556 | return this.get_cell(index); | |
555 | }; |
|
557 | }; | |
556 |
|
558 | |||
557 | /** |
|
559 | /** | |
558 | * Check whether a cell index is valid. |
|
560 | * Check whether a cell index is valid. | |
559 | * |
|
561 | * | |
560 | * @method is_valid_cell_index |
|
562 | * @method is_valid_cell_index | |
561 | * @param {Number} index A cell index |
|
563 | * @param {Number} index A cell index | |
562 | * @return True if the index is valid, false otherwise |
|
564 | * @return True if the index is valid, false otherwise | |
563 | */ |
|
565 | */ | |
564 | Notebook.prototype.is_valid_cell_index = function (index) { |
|
566 | Notebook.prototype.is_valid_cell_index = function (index) { | |
565 | if (index !== null && index >= 0 && index < this.ncells()) { |
|
567 | if (index !== null && index >= 0 && index < this.ncells()) { | |
566 | return true; |
|
568 | return true; | |
567 | } else { |
|
569 | } else { | |
568 | return false; |
|
570 | return false; | |
569 | }; |
|
571 | }; | |
570 | } |
|
572 | } | |
571 |
|
573 | |||
572 | /** |
|
574 | /** | |
573 | * Get the index of the currently selected cell. |
|
575 | * Get the index of the currently selected cell. | |
574 |
|
576 | |||
575 | * @method get_selected_index |
|
577 | * @method get_selected_index | |
576 | * @return {Number} The selected cell's numeric index |
|
578 | * @return {Number} The selected cell's numeric index | |
577 | */ |
|
579 | */ | |
578 | Notebook.prototype.get_selected_index = function () { |
|
580 | Notebook.prototype.get_selected_index = function () { | |
579 | var result = null; |
|
581 | var result = null; | |
580 | this.get_cell_elements().filter(function (index) { |
|
582 | this.get_cell_elements().filter(function (index) { | |
581 | if ($(this).data("cell").selected === true) { |
|
583 | if ($(this).data("cell").selected === true) { | |
582 | result = index; |
|
584 | result = index; | |
583 | }; |
|
585 | }; | |
584 | }); |
|
586 | }); | |
585 | return result; |
|
587 | return result; | |
586 | }; |
|
588 | }; | |
587 |
|
589 | |||
588 |
|
590 | |||
589 | // Cell selection. |
|
591 | // Cell selection. | |
590 |
|
592 | |||
591 | /** |
|
593 | /** | |
592 | * Programmatically select a cell. |
|
594 | * Programmatically select a cell. | |
593 | * |
|
595 | * | |
594 | * @method select |
|
596 | * @method select | |
595 | * @param {Number} index A cell's index |
|
597 | * @param {Number} index A cell's index | |
596 | * @return {Notebook} This notebook |
|
598 | * @return {Notebook} This notebook | |
597 | */ |
|
599 | */ | |
598 | Notebook.prototype.select = function (index) { |
|
600 | Notebook.prototype.select = function (index) { | |
599 | if (this.is_valid_cell_index(index)) { |
|
601 | if (this.is_valid_cell_index(index)) { | |
600 | var sindex = this.get_selected_index() |
|
602 | var sindex = this.get_selected_index() | |
601 | if (sindex !== null && index !== sindex) { |
|
603 | if (sindex !== null && index !== sindex) { | |
602 | this.get_cell(sindex).unselect(); |
|
604 | this.get_cell(sindex).unselect(); | |
603 | }; |
|
605 | }; | |
604 | var cell = this.get_cell(index); |
|
606 | var cell = this.get_cell(index); | |
605 | cell.select(); |
|
607 | cell.select(); | |
606 | if (cell.cell_type === 'heading') { |
|
608 | if (cell.cell_type === 'heading') { | |
607 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', |
|
609 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', | |
608 | {'cell_type':cell.cell_type,level:cell.level} |
|
610 | {'cell_type':cell.cell_type,level:cell.level} | |
609 | ); |
|
611 | ); | |
610 | } else { |
|
612 | } else { | |
611 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', |
|
613 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', | |
612 | {'cell_type':cell.cell_type} |
|
614 | {'cell_type':cell.cell_type} | |
613 | ); |
|
615 | ); | |
614 | }; |
|
616 | }; | |
615 | }; |
|
617 | }; | |
616 | return this; |
|
618 | return this; | |
617 | }; |
|
619 | }; | |
618 |
|
620 | |||
619 | /** |
|
621 | /** | |
620 | * Programmatically select the next cell. |
|
622 | * Programmatically select the next cell. | |
621 | * |
|
623 | * | |
622 | * @method select_next |
|
624 | * @method select_next | |
623 | * @return {Notebook} This notebook |
|
625 | * @return {Notebook} This notebook | |
624 | */ |
|
626 | */ | |
625 | Notebook.prototype.select_next = function () { |
|
627 | Notebook.prototype.select_next = function () { | |
626 | var index = this.get_selected_index(); |
|
628 | var index = this.get_selected_index(); | |
627 | this.select(index+1); |
|
629 | this.select(index+1); | |
628 | return this; |
|
630 | return this; | |
629 | }; |
|
631 | }; | |
630 |
|
632 | |||
631 | /** |
|
633 | /** | |
632 | * Programmatically select the previous cell. |
|
634 | * Programmatically select the previous cell. | |
633 | * |
|
635 | * | |
634 | * @method select_prev |
|
636 | * @method select_prev | |
635 | * @return {Notebook} This notebook |
|
637 | * @return {Notebook} This notebook | |
636 | */ |
|
638 | */ | |
637 | Notebook.prototype.select_prev = function () { |
|
639 | Notebook.prototype.select_prev = function () { | |
638 | var index = this.get_selected_index(); |
|
640 | var index = this.get_selected_index(); | |
639 | this.select(index-1); |
|
641 | this.select(index-1); | |
640 | return this; |
|
642 | return this; | |
641 | }; |
|
643 | }; | |
642 |
|
644 | |||
643 |
|
645 | |||
644 | // Cell movement |
|
646 | // Cell movement | |
645 |
|
647 | |||
646 | /** |
|
648 | /** | |
647 | * Move given (or selected) cell up and select it. |
|
649 | * Move given (or selected) cell up and select it. | |
648 | * |
|
650 | * | |
649 | * @method move_cell_up |
|
651 | * @method move_cell_up | |
650 | * @param [index] {integer} cell index |
|
652 | * @param [index] {integer} cell index | |
651 | * @return {Notebook} This notebook |
|
653 | * @return {Notebook} This notebook | |
652 | **/ |
|
654 | **/ | |
653 | Notebook.prototype.move_cell_up = function (index) { |
|
655 | Notebook.prototype.move_cell_up = function (index) { | |
654 | var i = this.index_or_selected(index); |
|
656 | var i = this.index_or_selected(index); | |
655 | if (this.is_valid_cell_index(i) && i > 0) { |
|
657 | if (this.is_valid_cell_index(i) && i > 0) { | |
656 | var pivot = this.get_cell_element(i-1); |
|
658 | var pivot = this.get_cell_element(i-1); | |
657 | var tomove = this.get_cell_element(i); |
|
659 | var tomove = this.get_cell_element(i); | |
658 | if (pivot !== null && tomove !== null) { |
|
660 | if (pivot !== null && tomove !== null) { | |
659 | tomove.detach(); |
|
661 | tomove.detach(); | |
660 | pivot.before(tomove); |
|
662 | pivot.before(tomove); | |
661 | this.select(i-1); |
|
663 | this.select(i-1); | |
662 | }; |
|
664 | }; | |
663 | this.set_dirty(true); |
|
665 | this.set_dirty(true); | |
664 | }; |
|
666 | }; | |
665 | return this; |
|
667 | return this; | |
666 | }; |
|
668 | }; | |
667 |
|
669 | |||
668 |
|
670 | |||
669 | /** |
|
671 | /** | |
670 | * Move given (or selected) cell down and select it |
|
672 | * Move given (or selected) cell down and select it | |
671 | * |
|
673 | * | |
672 | * @method move_cell_down |
|
674 | * @method move_cell_down | |
673 | * @param [index] {integer} cell index |
|
675 | * @param [index] {integer} cell index | |
674 | * @return {Notebook} This notebook |
|
676 | * @return {Notebook} This notebook | |
675 | **/ |
|
677 | **/ | |
676 | Notebook.prototype.move_cell_down = function (index) { |
|
678 | Notebook.prototype.move_cell_down = function (index) { | |
677 | var i = this.index_or_selected(index); |
|
679 | var i = this.index_or_selected(index); | |
678 | if ( this.is_valid_cell_index(i) && this.is_valid_cell_index(i+1)) { |
|
680 | if ( this.is_valid_cell_index(i) && this.is_valid_cell_index(i+1)) { | |
679 | var pivot = this.get_cell_element(i+1); |
|
681 | var pivot = this.get_cell_element(i+1); | |
680 | var tomove = this.get_cell_element(i); |
|
682 | var tomove = this.get_cell_element(i); | |
681 | if (pivot !== null && tomove !== null) { |
|
683 | if (pivot !== null && tomove !== null) { | |
682 | tomove.detach(); |
|
684 | tomove.detach(); | |
683 | pivot.after(tomove); |
|
685 | pivot.after(tomove); | |
684 | this.select(i+1); |
|
686 | this.select(i+1); | |
685 | }; |
|
687 | }; | |
686 | }; |
|
688 | }; | |
687 | this.set_dirty(); |
|
689 | this.set_dirty(); | |
688 | return this; |
|
690 | return this; | |
689 | }; |
|
691 | }; | |
690 |
|
692 | |||
691 |
|
693 | |||
692 | // Insertion, deletion. |
|
694 | // Insertion, deletion. | |
693 |
|
695 | |||
694 | /** |
|
696 | /** | |
695 | * Delete a cell from the notebook. |
|
697 | * Delete a cell from the notebook. | |
696 | * |
|
698 | * | |
697 | * @method delete_cell |
|
699 | * @method delete_cell | |
698 | * @param [index] A cell's numeric index |
|
700 | * @param [index] A cell's numeric index | |
699 | * @return {Notebook} This notebook |
|
701 | * @return {Notebook} This notebook | |
700 | */ |
|
702 | */ | |
701 | Notebook.prototype.delete_cell = function (index) { |
|
703 | Notebook.prototype.delete_cell = function (index) { | |
702 | var i = this.index_or_selected(index); |
|
704 | var i = this.index_or_selected(index); | |
703 | var cell = this.get_selected_cell(); |
|
705 | var cell = this.get_selected_cell(); | |
704 | this.undelete_backup = cell.toJSON(); |
|
706 | this.undelete_backup = cell.toJSON(); | |
705 | $('#undelete_cell').removeClass('ui-state-disabled'); |
|
707 | $('#undelete_cell').removeClass('ui-state-disabled'); | |
706 | if (this.is_valid_cell_index(i)) { |
|
708 | if (this.is_valid_cell_index(i)) { | |
707 | var ce = this.get_cell_element(i); |
|
709 | var ce = this.get_cell_element(i); | |
708 | ce.remove(); |
|
710 | ce.remove(); | |
709 | if (i === (this.ncells())) { |
|
711 | if (i === (this.ncells())) { | |
710 | this.select(i-1); |
|
712 | this.select(i-1); | |
711 | this.undelete_index = i - 1; |
|
713 | this.undelete_index = i - 1; | |
712 | this.undelete_below = true; |
|
714 | this.undelete_below = true; | |
713 | } else { |
|
715 | } else { | |
714 | this.select(i); |
|
716 | this.select(i); | |
715 | this.undelete_index = i; |
|
717 | this.undelete_index = i; | |
716 | this.undelete_below = false; |
|
718 | this.undelete_below = false; | |
717 | }; |
|
719 | }; | |
718 | this.set_dirty(true); |
|
720 | this.set_dirty(true); | |
719 | }; |
|
721 | }; | |
720 | return this; |
|
722 | return this; | |
721 | }; |
|
723 | }; | |
722 |
|
724 | |||
723 | /** |
|
725 | /** | |
724 | * Insert a cell so that after insertion the cell is at given index. |
|
726 | * Insert a cell so that after insertion the cell is at given index. | |
725 | * |
|
727 | * | |
726 | * Similar to insert_above, but index parameter is mandatory |
|
728 | * Similar to insert_above, but index parameter is mandatory | |
727 | * |
|
729 | * | |
728 | * Index will be brought back into the accissible range [0,n] |
|
730 | * Index will be brought back into the accissible range [0,n] | |
729 | * |
|
731 | * | |
730 | * @method insert_cell_at_index |
|
732 | * @method insert_cell_at_index | |
731 | * @param type {string} in ['code','markdown','heading'] |
|
733 | * @param type {string} in ['code','markdown','heading'] | |
732 | * @param [index] {int} a valid index where to inser cell |
|
734 | * @param [index] {int} a valid index where to inser cell | |
733 | * |
|
735 | * | |
734 | * @return cell {cell|null} created cell or null |
|
736 | * @return cell {cell|null} created cell or null | |
735 | **/ |
|
737 | **/ | |
736 | Notebook.prototype.insert_cell_at_index = function(type, index){ |
|
738 | Notebook.prototype.insert_cell_at_index = function(type, index){ | |
737 |
|
739 | |||
738 | var ncells = this.ncells(); |
|
740 | var ncells = this.ncells(); | |
739 | var index = Math.min(index,ncells); |
|
741 | var index = Math.min(index,ncells); | |
740 | index = Math.max(index,0); |
|
742 | index = Math.max(index,0); | |
741 | var cell = null; |
|
743 | var cell = null; | |
742 |
|
744 | |||
743 | if (ncells === 0 || this.is_valid_cell_index(index) || index === ncells) { |
|
745 | if (ncells === 0 || this.is_valid_cell_index(index) || index === ncells) { | |
744 | if (type === 'code') { |
|
746 | if (type === 'code') { | |
745 | cell = new IPython.CodeCell(this.kernel); |
|
747 | cell = new IPython.CodeCell(this.kernel); | |
746 | cell.set_input_prompt(); |
|
748 | cell.set_input_prompt(); | |
747 | } else if (type === 'markdown') { |
|
749 | } else if (type === 'markdown') { | |
748 | cell = new IPython.MarkdownCell(); |
|
750 | cell = new IPython.MarkdownCell(); | |
749 | } else if (type === 'raw') { |
|
751 | } else if (type === 'raw') { | |
750 | cell = new IPython.RawCell(); |
|
752 | cell = new IPython.RawCell(); | |
751 | } else if (type === 'heading') { |
|
753 | } else if (type === 'heading') { | |
752 | cell = new IPython.HeadingCell(); |
|
754 | cell = new IPython.HeadingCell(); | |
753 | } |
|
755 | } | |
754 |
|
756 | |||
755 | if(this._insert_element_at_index(cell.element,index)){ |
|
757 | if(this._insert_element_at_index(cell.element,index)){ | |
756 | cell.render(); |
|
758 | cell.render(); | |
757 | this.select(this.find_cell_index(cell)); |
|
759 | this.select(this.find_cell_index(cell)); | |
758 | this.set_dirty(true); |
|
760 | this.set_dirty(true); | |
759 | } |
|
761 | } | |
760 | } |
|
762 | } | |
761 | return cell; |
|
763 | return cell; | |
762 |
|
764 | |||
763 | }; |
|
765 | }; | |
764 |
|
766 | |||
765 | /** |
|
767 | /** | |
766 | * Insert an element at given cell index. |
|
768 | * Insert an element at given cell index. | |
767 | * |
|
769 | * | |
768 | * @method _insert_element_at_index |
|
770 | * @method _insert_element_at_index | |
769 | * @param element {dom element} a cell element |
|
771 | * @param element {dom element} a cell element | |
770 | * @param [index] {int} a valid index where to inser cell |
|
772 | * @param [index] {int} a valid index where to inser cell | |
771 | * @private |
|
773 | * @private | |
772 | * |
|
774 | * | |
773 | * return true if everything whent fine. |
|
775 | * return true if everything whent fine. | |
774 | **/ |
|
776 | **/ | |
775 | Notebook.prototype._insert_element_at_index = function(element, index){ |
|
777 | Notebook.prototype._insert_element_at_index = function(element, index){ | |
776 | if (element === undefined){ |
|
778 | if (element === undefined){ | |
777 | return false; |
|
779 | return false; | |
778 | } |
|
780 | } | |
779 |
|
781 | |||
780 | var ncells = this.ncells(); |
|
782 | var ncells = this.ncells(); | |
781 |
|
783 | |||
782 | if (ncells === 0) { |
|
784 | if (ncells === 0) { | |
783 | // special case append if empty |
|
785 | // special case append if empty | |
784 | this.element.find('div.end_space').before(element); |
|
786 | this.element.find('div.end_space').before(element); | |
785 | } else if ( ncells === index ) { |
|
787 | } else if ( ncells === index ) { | |
786 | // special case append it the end, but not empty |
|
788 | // special case append it the end, but not empty | |
787 | this.get_cell_element(index-1).after(element); |
|
789 | this.get_cell_element(index-1).after(element); | |
788 | } else if (this.is_valid_cell_index(index)) { |
|
790 | } else if (this.is_valid_cell_index(index)) { | |
789 | // otherwise always somewhere to append to |
|
791 | // otherwise always somewhere to append to | |
790 | this.get_cell_element(index).before(element); |
|
792 | this.get_cell_element(index).before(element); | |
791 | } else { |
|
793 | } else { | |
792 | return false; |
|
794 | return false; | |
793 | } |
|
795 | } | |
794 |
|
796 | |||
795 | if (this.undelete_index !== null && index <= this.undelete_index) { |
|
797 | if (this.undelete_index !== null && index <= this.undelete_index) { | |
796 | this.undelete_index = this.undelete_index + 1; |
|
798 | this.undelete_index = this.undelete_index + 1; | |
797 | this.set_dirty(true); |
|
799 | this.set_dirty(true); | |
798 | } |
|
800 | } | |
799 | return true; |
|
801 | return true; | |
800 | }; |
|
802 | }; | |
801 |
|
803 | |||
802 | /** |
|
804 | /** | |
803 | * Insert a cell of given type above given index, or at top |
|
805 | * Insert a cell of given type above given index, or at top | |
804 | * of notebook if index smaller than 0. |
|
806 | * of notebook if index smaller than 0. | |
805 | * |
|
807 | * | |
806 | * default index value is the one of currently selected cell |
|
808 | * default index value is the one of currently selected cell | |
807 | * |
|
809 | * | |
808 | * @method insert_cell_above |
|
810 | * @method insert_cell_above | |
809 | * @param type {string} cell type |
|
811 | * @param type {string} cell type | |
810 | * @param [index] {integer} |
|
812 | * @param [index] {integer} | |
811 | * |
|
813 | * | |
812 | * @return handle to created cell or null |
|
814 | * @return handle to created cell or null | |
813 | **/ |
|
815 | **/ | |
814 | Notebook.prototype.insert_cell_above = function (type, index) { |
|
816 | Notebook.prototype.insert_cell_above = function (type, index) { | |
815 | index = this.index_or_selected(index); |
|
817 | index = this.index_or_selected(index); | |
816 | return this.insert_cell_at_index(type, index); |
|
818 | return this.insert_cell_at_index(type, index); | |
817 | }; |
|
819 | }; | |
818 |
|
820 | |||
819 | /** |
|
821 | /** | |
820 | * Insert a cell of given type below given index, or at bottom |
|
822 | * Insert a cell of given type below given index, or at bottom | |
821 | * of notebook if index greater thatn number of cell |
|
823 | * of notebook if index greater thatn number of cell | |
822 | * |
|
824 | * | |
823 | * default index value is the one of currently selected cell |
|
825 | * default index value is the one of currently selected cell | |
824 | * |
|
826 | * | |
825 | * @method insert_cell_below |
|
827 | * @method insert_cell_below | |
826 | * @param type {string} cell type |
|
828 | * @param type {string} cell type | |
827 | * @param [index] {integer} |
|
829 | * @param [index] {integer} | |
828 | * |
|
830 | * | |
829 | * @return handle to created cell or null |
|
831 | * @return handle to created cell or null | |
830 | * |
|
832 | * | |
831 | **/ |
|
833 | **/ | |
832 | Notebook.prototype.insert_cell_below = function (type, index) { |
|
834 | Notebook.prototype.insert_cell_below = function (type, index) { | |
833 | index = this.index_or_selected(index); |
|
835 | index = this.index_or_selected(index); | |
834 | return this.insert_cell_at_index(type, index+1); |
|
836 | return this.insert_cell_at_index(type, index+1); | |
835 | }; |
|
837 | }; | |
836 |
|
838 | |||
837 |
|
839 | |||
838 | /** |
|
840 | /** | |
839 | * Insert cell at end of notebook |
|
841 | * Insert cell at end of notebook | |
840 | * |
|
842 | * | |
841 | * @method insert_cell_at_bottom |
|
843 | * @method insert_cell_at_bottom | |
842 | * @param {String} type cell type |
|
844 | * @param {String} type cell type | |
843 | * |
|
845 | * | |
844 | * @return the added cell; or null |
|
846 | * @return the added cell; or null | |
845 | **/ |
|
847 | **/ | |
846 | Notebook.prototype.insert_cell_at_bottom = function (type){ |
|
848 | Notebook.prototype.insert_cell_at_bottom = function (type){ | |
847 | var len = this.ncells(); |
|
849 | var len = this.ncells(); | |
848 | return this.insert_cell_below(type,len-1); |
|
850 | return this.insert_cell_below(type,len-1); | |
849 | }; |
|
851 | }; | |
850 |
|
852 | |||
851 | /** |
|
853 | /** | |
852 | * Turn a cell into a code cell. |
|
854 | * Turn a cell into a code cell. | |
853 | * |
|
855 | * | |
854 | * @method to_code |
|
856 | * @method to_code | |
855 | * @param {Number} [index] A cell's index |
|
857 | * @param {Number} [index] A cell's index | |
856 | */ |
|
858 | */ | |
857 | Notebook.prototype.to_code = function (index) { |
|
859 | Notebook.prototype.to_code = function (index) { | |
858 | var i = this.index_or_selected(index); |
|
860 | var i = this.index_or_selected(index); | |
859 | if (this.is_valid_cell_index(i)) { |
|
861 | if (this.is_valid_cell_index(i)) { | |
860 | var source_element = this.get_cell_element(i); |
|
862 | var source_element = this.get_cell_element(i); | |
861 | var source_cell = source_element.data("cell"); |
|
863 | var source_cell = source_element.data("cell"); | |
862 | if (!(source_cell instanceof IPython.CodeCell)) { |
|
864 | if (!(source_cell instanceof IPython.CodeCell)) { | |
863 | var target_cell = this.insert_cell_below('code',i); |
|
865 | var target_cell = this.insert_cell_below('code',i); | |
864 | var text = source_cell.get_text(); |
|
866 | var text = source_cell.get_text(); | |
865 | if (text === source_cell.placeholder) { |
|
867 | if (text === source_cell.placeholder) { | |
866 | text = ''; |
|
868 | text = ''; | |
867 | } |
|
869 | } | |
868 | target_cell.set_text(text); |
|
870 | target_cell.set_text(text); | |
869 | // make this value the starting point, so that we can only undo |
|
871 | // make this value the starting point, so that we can only undo | |
870 | // to this state, instead of a blank cell |
|
872 | // to this state, instead of a blank cell | |
871 | target_cell.code_mirror.clearHistory(); |
|
873 | target_cell.code_mirror.clearHistory(); | |
872 | source_element.remove(); |
|
874 | source_element.remove(); | |
873 | this.set_dirty(true); |
|
875 | this.set_dirty(true); | |
874 | }; |
|
876 | }; | |
875 | }; |
|
877 | }; | |
876 | }; |
|
878 | }; | |
877 |
|
879 | |||
878 | /** |
|
880 | /** | |
879 | * Turn a cell into a Markdown cell. |
|
881 | * Turn a cell into a Markdown cell. | |
880 | * |
|
882 | * | |
881 | * @method to_markdown |
|
883 | * @method to_markdown | |
882 | * @param {Number} [index] A cell's index |
|
884 | * @param {Number} [index] A cell's index | |
883 | */ |
|
885 | */ | |
884 | Notebook.prototype.to_markdown = function (index) { |
|
886 | Notebook.prototype.to_markdown = function (index) { | |
885 | var i = this.index_or_selected(index); |
|
887 | var i = this.index_or_selected(index); | |
886 | if (this.is_valid_cell_index(i)) { |
|
888 | if (this.is_valid_cell_index(i)) { | |
887 | var source_element = this.get_cell_element(i); |
|
889 | var source_element = this.get_cell_element(i); | |
888 | var source_cell = source_element.data("cell"); |
|
890 | var source_cell = source_element.data("cell"); | |
889 | if (!(source_cell instanceof IPython.MarkdownCell)) { |
|
891 | if (!(source_cell instanceof IPython.MarkdownCell)) { | |
890 | var target_cell = this.insert_cell_below('markdown',i); |
|
892 | var target_cell = this.insert_cell_below('markdown',i); | |
891 | var text = source_cell.get_text(); |
|
893 | var text = source_cell.get_text(); | |
892 | if (text === source_cell.placeholder) { |
|
894 | if (text === source_cell.placeholder) { | |
893 | text = ''; |
|
895 | text = ''; | |
894 | }; |
|
896 | }; | |
895 | // The edit must come before the set_text. |
|
897 | // The edit must come before the set_text. | |
896 | target_cell.edit(); |
|
898 | target_cell.edit(); | |
897 | target_cell.set_text(text); |
|
899 | target_cell.set_text(text); | |
898 | // make this value the starting point, so that we can only undo |
|
900 | // make this value the starting point, so that we can only undo | |
899 | // to this state, instead of a blank cell |
|
901 | // to this state, instead of a blank cell | |
900 | target_cell.code_mirror.clearHistory(); |
|
902 | target_cell.code_mirror.clearHistory(); | |
901 | source_element.remove(); |
|
903 | source_element.remove(); | |
902 | this.set_dirty(true); |
|
904 | this.set_dirty(true); | |
903 | }; |
|
905 | }; | |
904 | }; |
|
906 | }; | |
905 | }; |
|
907 | }; | |
906 |
|
908 | |||
907 | /** |
|
909 | /** | |
908 | * Turn a cell into a raw text cell. |
|
910 | * Turn a cell into a raw text cell. | |
909 | * |
|
911 | * | |
910 | * @method to_raw |
|
912 | * @method to_raw | |
911 | * @param {Number} [index] A cell's index |
|
913 | * @param {Number} [index] A cell's index | |
912 | */ |
|
914 | */ | |
913 | Notebook.prototype.to_raw = function (index) { |
|
915 | Notebook.prototype.to_raw = function (index) { | |
914 | var i = this.index_or_selected(index); |
|
916 | var i = this.index_or_selected(index); | |
915 | if (this.is_valid_cell_index(i)) { |
|
917 | if (this.is_valid_cell_index(i)) { | |
916 | var source_element = this.get_cell_element(i); |
|
918 | var source_element = this.get_cell_element(i); | |
917 | var source_cell = source_element.data("cell"); |
|
919 | var source_cell = source_element.data("cell"); | |
918 | var target_cell = null; |
|
920 | var target_cell = null; | |
919 | if (!(source_cell instanceof IPython.RawCell)) { |
|
921 | if (!(source_cell instanceof IPython.RawCell)) { | |
920 | target_cell = this.insert_cell_below('raw',i); |
|
922 | target_cell = this.insert_cell_below('raw',i); | |
921 | var text = source_cell.get_text(); |
|
923 | var text = source_cell.get_text(); | |
922 | if (text === source_cell.placeholder) { |
|
924 | if (text === source_cell.placeholder) { | |
923 | text = ''; |
|
925 | text = ''; | |
924 | }; |
|
926 | }; | |
925 | // The edit must come before the set_text. |
|
927 | // The edit must come before the set_text. | |
926 | target_cell.edit(); |
|
928 | target_cell.edit(); | |
927 | target_cell.set_text(text); |
|
929 | target_cell.set_text(text); | |
928 | // make this value the starting point, so that we can only undo |
|
930 | // make this value the starting point, so that we can only undo | |
929 | // to this state, instead of a blank cell |
|
931 | // to this state, instead of a blank cell | |
930 | target_cell.code_mirror.clearHistory(); |
|
932 | target_cell.code_mirror.clearHistory(); | |
931 | source_element.remove(); |
|
933 | source_element.remove(); | |
932 | this.set_dirty(true); |
|
934 | this.set_dirty(true); | |
933 | }; |
|
935 | }; | |
934 | }; |
|
936 | }; | |
935 | }; |
|
937 | }; | |
936 |
|
938 | |||
937 | /** |
|
939 | /** | |
938 | * Turn a cell into a heading cell. |
|
940 | * Turn a cell into a heading cell. | |
939 | * |
|
941 | * | |
940 | * @method to_heading |
|
942 | * @method to_heading | |
941 | * @param {Number} [index] A cell's index |
|
943 | * @param {Number} [index] A cell's index | |
942 | * @param {Number} [level] A heading level (e.g., 1 becomes <h1>) |
|
944 | * @param {Number} [level] A heading level (e.g., 1 becomes <h1>) | |
943 | */ |
|
945 | */ | |
944 | Notebook.prototype.to_heading = function (index, level) { |
|
946 | Notebook.prototype.to_heading = function (index, level) { | |
945 | level = level || 1; |
|
947 | level = level || 1; | |
946 | var i = this.index_or_selected(index); |
|
948 | var i = this.index_or_selected(index); | |
947 | if (this.is_valid_cell_index(i)) { |
|
949 | if (this.is_valid_cell_index(i)) { | |
948 | var source_element = this.get_cell_element(i); |
|
950 | var source_element = this.get_cell_element(i); | |
949 | var source_cell = source_element.data("cell"); |
|
951 | var source_cell = source_element.data("cell"); | |
950 | var target_cell = null; |
|
952 | var target_cell = null; | |
951 | if (source_cell instanceof IPython.HeadingCell) { |
|
953 | if (source_cell instanceof IPython.HeadingCell) { | |
952 | source_cell.set_level(level); |
|
954 | source_cell.set_level(level); | |
953 | } else { |
|
955 | } else { | |
954 | target_cell = this.insert_cell_below('heading',i); |
|
956 | target_cell = this.insert_cell_below('heading',i); | |
955 | var text = source_cell.get_text(); |
|
957 | var text = source_cell.get_text(); | |
956 | if (text === source_cell.placeholder) { |
|
958 | if (text === source_cell.placeholder) { | |
957 | text = ''; |
|
959 | text = ''; | |
958 | }; |
|
960 | }; | |
959 | // The edit must come before the set_text. |
|
961 | // The edit must come before the set_text. | |
960 | target_cell.set_level(level); |
|
962 | target_cell.set_level(level); | |
961 | target_cell.edit(); |
|
963 | target_cell.edit(); | |
962 | target_cell.set_text(text); |
|
964 | target_cell.set_text(text); | |
963 | // make this value the starting point, so that we can only undo |
|
965 | // make this value the starting point, so that we can only undo | |
964 | // to this state, instead of a blank cell |
|
966 | // to this state, instead of a blank cell | |
965 | target_cell.code_mirror.clearHistory(); |
|
967 | target_cell.code_mirror.clearHistory(); | |
966 | source_element.remove(); |
|
968 | source_element.remove(); | |
967 | this.set_dirty(true); |
|
969 | this.set_dirty(true); | |
968 | }; |
|
970 | }; | |
969 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', |
|
971 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', | |
970 | {'cell_type':'heading',level:level} |
|
972 | {'cell_type':'heading',level:level} | |
971 | ); |
|
973 | ); | |
972 | }; |
|
974 | }; | |
973 | }; |
|
975 | }; | |
974 |
|
976 | |||
975 |
|
977 | |||
976 | // Cut/Copy/Paste |
|
978 | // Cut/Copy/Paste | |
977 |
|
979 | |||
978 | /** |
|
980 | /** | |
979 | * Enable UI elements for pasting cells. |
|
981 | * Enable UI elements for pasting cells. | |
980 | * |
|
982 | * | |
981 | * @method enable_paste |
|
983 | * @method enable_paste | |
982 | */ |
|
984 | */ | |
983 | Notebook.prototype.enable_paste = function () { |
|
985 | Notebook.prototype.enable_paste = function () { | |
984 | var that = this; |
|
986 | var that = this; | |
985 | if (!this.paste_enabled) { |
|
987 | if (!this.paste_enabled) { | |
986 | $('#paste_cell_replace').removeClass('ui-state-disabled') |
|
988 | $('#paste_cell_replace').removeClass('ui-state-disabled') | |
987 | .on('click', function () {that.paste_cell_replace();}); |
|
989 | .on('click', function () {that.paste_cell_replace();}); | |
988 | $('#paste_cell_above').removeClass('ui-state-disabled') |
|
990 | $('#paste_cell_above').removeClass('ui-state-disabled') | |
989 | .on('click', function () {that.paste_cell_above();}); |
|
991 | .on('click', function () {that.paste_cell_above();}); | |
990 | $('#paste_cell_below').removeClass('ui-state-disabled') |
|
992 | $('#paste_cell_below').removeClass('ui-state-disabled') | |
991 | .on('click', function () {that.paste_cell_below();}); |
|
993 | .on('click', function () {that.paste_cell_below();}); | |
992 | this.paste_enabled = true; |
|
994 | this.paste_enabled = true; | |
993 | }; |
|
995 | }; | |
994 | }; |
|
996 | }; | |
995 |
|
997 | |||
996 | /** |
|
998 | /** | |
997 | * Disable UI elements for pasting cells. |
|
999 | * Disable UI elements for pasting cells. | |
998 | * |
|
1000 | * | |
999 | * @method disable_paste |
|
1001 | * @method disable_paste | |
1000 | */ |
|
1002 | */ | |
1001 | Notebook.prototype.disable_paste = function () { |
|
1003 | Notebook.prototype.disable_paste = function () { | |
1002 | if (this.paste_enabled) { |
|
1004 | if (this.paste_enabled) { | |
1003 | $('#paste_cell_replace').addClass('ui-state-disabled').off('click'); |
|
1005 | $('#paste_cell_replace').addClass('ui-state-disabled').off('click'); | |
1004 | $('#paste_cell_above').addClass('ui-state-disabled').off('click'); |
|
1006 | $('#paste_cell_above').addClass('ui-state-disabled').off('click'); | |
1005 | $('#paste_cell_below').addClass('ui-state-disabled').off('click'); |
|
1007 | $('#paste_cell_below').addClass('ui-state-disabled').off('click'); | |
1006 | this.paste_enabled = false; |
|
1008 | this.paste_enabled = false; | |
1007 | }; |
|
1009 | }; | |
1008 | }; |
|
1010 | }; | |
1009 |
|
1011 | |||
1010 | /** |
|
1012 | /** | |
1011 | * Cut a cell. |
|
1013 | * Cut a cell. | |
1012 | * |
|
1014 | * | |
1013 | * @method cut_cell |
|
1015 | * @method cut_cell | |
1014 | */ |
|
1016 | */ | |
1015 | Notebook.prototype.cut_cell = function () { |
|
1017 | Notebook.prototype.cut_cell = function () { | |
1016 | this.copy_cell(); |
|
1018 | this.copy_cell(); | |
1017 | this.delete_cell(); |
|
1019 | this.delete_cell(); | |
1018 | } |
|
1020 | } | |
1019 |
|
1021 | |||
1020 | /** |
|
1022 | /** | |
1021 | * Copy a cell. |
|
1023 | * Copy a cell. | |
1022 | * |
|
1024 | * | |
1023 | * @method copy_cell |
|
1025 | * @method copy_cell | |
1024 | */ |
|
1026 | */ | |
1025 | Notebook.prototype.copy_cell = function () { |
|
1027 | Notebook.prototype.copy_cell = function () { | |
1026 | var cell = this.get_selected_cell(); |
|
1028 | var cell = this.get_selected_cell(); | |
1027 | this.clipboard = cell.toJSON(); |
|
1029 | this.clipboard = cell.toJSON(); | |
1028 | this.enable_paste(); |
|
1030 | this.enable_paste(); | |
1029 | }; |
|
1031 | }; | |
1030 |
|
1032 | |||
1031 | /** |
|
1033 | /** | |
1032 | * Replace the selected cell with a cell in the clipboard. |
|
1034 | * Replace the selected cell with a cell in the clipboard. | |
1033 | * |
|
1035 | * | |
1034 | * @method paste_cell_replace |
|
1036 | * @method paste_cell_replace | |
1035 | */ |
|
1037 | */ | |
1036 | Notebook.prototype.paste_cell_replace = function () { |
|
1038 | Notebook.prototype.paste_cell_replace = function () { | |
1037 | if (this.clipboard !== null && this.paste_enabled) { |
|
1039 | if (this.clipboard !== null && this.paste_enabled) { | |
1038 | var cell_data = this.clipboard; |
|
1040 | var cell_data = this.clipboard; | |
1039 | var new_cell = this.insert_cell_above(cell_data.cell_type); |
|
1041 | var new_cell = this.insert_cell_above(cell_data.cell_type); | |
1040 | new_cell.fromJSON(cell_data); |
|
1042 | new_cell.fromJSON(cell_data); | |
1041 | var old_cell = this.get_next_cell(new_cell); |
|
1043 | var old_cell = this.get_next_cell(new_cell); | |
1042 | this.delete_cell(this.find_cell_index(old_cell)); |
|
1044 | this.delete_cell(this.find_cell_index(old_cell)); | |
1043 | this.select(this.find_cell_index(new_cell)); |
|
1045 | this.select(this.find_cell_index(new_cell)); | |
1044 | }; |
|
1046 | }; | |
1045 | }; |
|
1047 | }; | |
1046 |
|
1048 | |||
1047 | /** |
|
1049 | /** | |
1048 | * Paste a cell from the clipboard above the selected cell. |
|
1050 | * Paste a cell from the clipboard above the selected cell. | |
1049 | * |
|
1051 | * | |
1050 | * @method paste_cell_above |
|
1052 | * @method paste_cell_above | |
1051 | */ |
|
1053 | */ | |
1052 | Notebook.prototype.paste_cell_above = function () { |
|
1054 | Notebook.prototype.paste_cell_above = function () { | |
1053 | if (this.clipboard !== null && this.paste_enabled) { |
|
1055 | if (this.clipboard !== null && this.paste_enabled) { | |
1054 | var cell_data = this.clipboard; |
|
1056 | var cell_data = this.clipboard; | |
1055 | var new_cell = this.insert_cell_above(cell_data.cell_type); |
|
1057 | var new_cell = this.insert_cell_above(cell_data.cell_type); | |
1056 | new_cell.fromJSON(cell_data); |
|
1058 | new_cell.fromJSON(cell_data); | |
1057 | }; |
|
1059 | }; | |
1058 | }; |
|
1060 | }; | |
1059 |
|
1061 | |||
1060 | /** |
|
1062 | /** | |
1061 | * Paste a cell from the clipboard below the selected cell. |
|
1063 | * Paste a cell from the clipboard below the selected cell. | |
1062 | * |
|
1064 | * | |
1063 | * @method paste_cell_below |
|
1065 | * @method paste_cell_below | |
1064 | */ |
|
1066 | */ | |
1065 | Notebook.prototype.paste_cell_below = function () { |
|
1067 | Notebook.prototype.paste_cell_below = function () { | |
1066 | if (this.clipboard !== null && this.paste_enabled) { |
|
1068 | if (this.clipboard !== null && this.paste_enabled) { | |
1067 | var cell_data = this.clipboard; |
|
1069 | var cell_data = this.clipboard; | |
1068 | var new_cell = this.insert_cell_below(cell_data.cell_type); |
|
1070 | var new_cell = this.insert_cell_below(cell_data.cell_type); | |
1069 | new_cell.fromJSON(cell_data); |
|
1071 | new_cell.fromJSON(cell_data); | |
1070 | }; |
|
1072 | }; | |
1071 | }; |
|
1073 | }; | |
1072 |
|
1074 | |||
1073 | // Cell undelete |
|
1075 | // Cell undelete | |
1074 |
|
1076 | |||
1075 | /** |
|
1077 | /** | |
1076 | * Restore the most recently deleted cell. |
|
1078 | * Restore the most recently deleted cell. | |
1077 | * |
|
1079 | * | |
1078 | * @method undelete |
|
1080 | * @method undelete | |
1079 | */ |
|
1081 | */ | |
1080 | Notebook.prototype.undelete = function() { |
|
1082 | Notebook.prototype.undelete = function() { | |
1081 | if (this.undelete_backup !== null && this.undelete_index !== null) { |
|
1083 | if (this.undelete_backup !== null && this.undelete_index !== null) { | |
1082 | var current_index = this.get_selected_index(); |
|
1084 | var current_index = this.get_selected_index(); | |
1083 | if (this.undelete_index < current_index) { |
|
1085 | if (this.undelete_index < current_index) { | |
1084 | current_index = current_index + 1; |
|
1086 | current_index = current_index + 1; | |
1085 | } |
|
1087 | } | |
1086 | if (this.undelete_index >= this.ncells()) { |
|
1088 | if (this.undelete_index >= this.ncells()) { | |
1087 | this.select(this.ncells() - 1); |
|
1089 | this.select(this.ncells() - 1); | |
1088 | } |
|
1090 | } | |
1089 | else { |
|
1091 | else { | |
1090 | this.select(this.undelete_index); |
|
1092 | this.select(this.undelete_index); | |
1091 | } |
|
1093 | } | |
1092 | var cell_data = this.undelete_backup; |
|
1094 | var cell_data = this.undelete_backup; | |
1093 | var new_cell = null; |
|
1095 | var new_cell = null; | |
1094 | if (this.undelete_below) { |
|
1096 | if (this.undelete_below) { | |
1095 | new_cell = this.insert_cell_below(cell_data.cell_type); |
|
1097 | new_cell = this.insert_cell_below(cell_data.cell_type); | |
1096 | } else { |
|
1098 | } else { | |
1097 | new_cell = this.insert_cell_above(cell_data.cell_type); |
|
1099 | new_cell = this.insert_cell_above(cell_data.cell_type); | |
1098 | } |
|
1100 | } | |
1099 | new_cell.fromJSON(cell_data); |
|
1101 | new_cell.fromJSON(cell_data); | |
1100 | this.select(current_index); |
|
1102 | this.select(current_index); | |
1101 | this.undelete_backup = null; |
|
1103 | this.undelete_backup = null; | |
1102 | this.undelete_index = null; |
|
1104 | this.undelete_index = null; | |
1103 | } |
|
1105 | } | |
1104 | $('#undelete_cell').addClass('ui-state-disabled'); |
|
1106 | $('#undelete_cell').addClass('ui-state-disabled'); | |
1105 | } |
|
1107 | } | |
1106 |
|
1108 | |||
1107 | // Split/merge |
|
1109 | // Split/merge | |
1108 |
|
1110 | |||
1109 | /** |
|
1111 | /** | |
1110 | * Split the selected cell into two, at the cursor. |
|
1112 | * Split the selected cell into two, at the cursor. | |
1111 | * |
|
1113 | * | |
1112 | * @method split_cell |
|
1114 | * @method split_cell | |
1113 | */ |
|
1115 | */ | |
1114 | Notebook.prototype.split_cell = function () { |
|
1116 | Notebook.prototype.split_cell = function () { | |
1115 | // Todo: implement spliting for other cell types. |
|
1117 | // Todo: implement spliting for other cell types. | |
1116 | var cell = this.get_selected_cell(); |
|
1118 | var cell = this.get_selected_cell(); | |
1117 | if (cell.is_splittable()) { |
|
1119 | if (cell.is_splittable()) { | |
1118 | var texta = cell.get_pre_cursor(); |
|
1120 | var texta = cell.get_pre_cursor(); | |
1119 | var textb = cell.get_post_cursor(); |
|
1121 | var textb = cell.get_post_cursor(); | |
1120 | if (cell instanceof IPython.CodeCell) { |
|
1122 | if (cell instanceof IPython.CodeCell) { | |
1121 | cell.set_text(texta); |
|
1123 | cell.set_text(texta); | |
1122 | var new_cell = this.insert_cell_below('code'); |
|
1124 | var new_cell = this.insert_cell_below('code'); | |
1123 | new_cell.set_text(textb); |
|
1125 | new_cell.set_text(textb); | |
1124 | } else if (cell instanceof IPython.MarkdownCell) { |
|
1126 | } else if (cell instanceof IPython.MarkdownCell) { | |
1125 | cell.set_text(texta); |
|
1127 | cell.set_text(texta); | |
1126 | cell.render(); |
|
1128 | cell.render(); | |
1127 | var new_cell = this.insert_cell_below('markdown'); |
|
1129 | var new_cell = this.insert_cell_below('markdown'); | |
1128 | new_cell.edit(); // editor must be visible to call set_text |
|
1130 | new_cell.edit(); // editor must be visible to call set_text | |
1129 | new_cell.set_text(textb); |
|
1131 | new_cell.set_text(textb); | |
1130 | new_cell.render(); |
|
1132 | new_cell.render(); | |
1131 | } |
|
1133 | } | |
1132 | }; |
|
1134 | }; | |
1133 | }; |
|
1135 | }; | |
1134 |
|
1136 | |||
1135 | /** |
|
1137 | /** | |
1136 | * Combine the selected cell into the cell above it. |
|
1138 | * Combine the selected cell into the cell above it. | |
1137 | * |
|
1139 | * | |
1138 | * @method merge_cell_above |
|
1140 | * @method merge_cell_above | |
1139 | */ |
|
1141 | */ | |
1140 | Notebook.prototype.merge_cell_above = function () { |
|
1142 | Notebook.prototype.merge_cell_above = function () { | |
1141 | var index = this.get_selected_index(); |
|
1143 | var index = this.get_selected_index(); | |
1142 | var cell = this.get_cell(index); |
|
1144 | var cell = this.get_cell(index); | |
1143 | if (index > 0) { |
|
1145 | if (index > 0) { | |
1144 | var upper_cell = this.get_cell(index-1); |
|
1146 | var upper_cell = this.get_cell(index-1); | |
1145 | var upper_text = upper_cell.get_text(); |
|
1147 | var upper_text = upper_cell.get_text(); | |
1146 | var text = cell.get_text(); |
|
1148 | var text = cell.get_text(); | |
1147 | if (cell instanceof IPython.CodeCell) { |
|
1149 | if (cell instanceof IPython.CodeCell) { | |
1148 | cell.set_text(upper_text+'\n'+text); |
|
1150 | cell.set_text(upper_text+'\n'+text); | |
1149 | } else if (cell instanceof IPython.MarkdownCell) { |
|
1151 | } else if (cell instanceof IPython.MarkdownCell) { | |
1150 | cell.edit(); |
|
1152 | cell.edit(); | |
1151 | cell.set_text(upper_text+'\n'+text); |
|
1153 | cell.set_text(upper_text+'\n'+text); | |
1152 | cell.render(); |
|
1154 | cell.render(); | |
1153 | }; |
|
1155 | }; | |
1154 | this.delete_cell(index-1); |
|
1156 | this.delete_cell(index-1); | |
1155 | this.select(this.find_cell_index(cell)); |
|
1157 | this.select(this.find_cell_index(cell)); | |
1156 | }; |
|
1158 | }; | |
1157 | }; |
|
1159 | }; | |
1158 |
|
1160 | |||
1159 | /** |
|
1161 | /** | |
1160 | * Combine the selected cell into the cell below it. |
|
1162 | * Combine the selected cell into the cell below it. | |
1161 | * |
|
1163 | * | |
1162 | * @method merge_cell_below |
|
1164 | * @method merge_cell_below | |
1163 | */ |
|
1165 | */ | |
1164 | Notebook.prototype.merge_cell_below = function () { |
|
1166 | Notebook.prototype.merge_cell_below = function () { | |
1165 | var index = this.get_selected_index(); |
|
1167 | var index = this.get_selected_index(); | |
1166 | var cell = this.get_cell(index); |
|
1168 | var cell = this.get_cell(index); | |
1167 | if (index < this.ncells()-1) { |
|
1169 | if (index < this.ncells()-1) { | |
1168 | var lower_cell = this.get_cell(index+1); |
|
1170 | var lower_cell = this.get_cell(index+1); | |
1169 | var lower_text = lower_cell.get_text(); |
|
1171 | var lower_text = lower_cell.get_text(); | |
1170 | var text = cell.get_text(); |
|
1172 | var text = cell.get_text(); | |
1171 | if (cell instanceof IPython.CodeCell) { |
|
1173 | if (cell instanceof IPython.CodeCell) { | |
1172 | cell.set_text(text+'\n'+lower_text); |
|
1174 | cell.set_text(text+'\n'+lower_text); | |
1173 | } else if (cell instanceof IPython.MarkdownCell) { |
|
1175 | } else if (cell instanceof IPython.MarkdownCell) { | |
1174 | cell.edit(); |
|
1176 | cell.edit(); | |
1175 | cell.set_text(text+'\n'+lower_text); |
|
1177 | cell.set_text(text+'\n'+lower_text); | |
1176 | cell.render(); |
|
1178 | cell.render(); | |
1177 | }; |
|
1179 | }; | |
1178 | this.delete_cell(index+1); |
|
1180 | this.delete_cell(index+1); | |
1179 | this.select(this.find_cell_index(cell)); |
|
1181 | this.select(this.find_cell_index(cell)); | |
1180 | }; |
|
1182 | }; | |
1181 | }; |
|
1183 | }; | |
1182 |
|
1184 | |||
1183 |
|
1185 | |||
1184 | // Cell collapsing and output clearing |
|
1186 | // Cell collapsing and output clearing | |
1185 |
|
1187 | |||
1186 | /** |
|
1188 | /** | |
1187 | * Hide a cell's output. |
|
1189 | * Hide a cell's output. | |
1188 | * |
|
1190 | * | |
1189 | * @method collapse |
|
1191 | * @method collapse | |
1190 | * @param {Number} index A cell's numeric index |
|
1192 | * @param {Number} index A cell's numeric index | |
1191 | */ |
|
1193 | */ | |
1192 | Notebook.prototype.collapse = function (index) { |
|
1194 | Notebook.prototype.collapse = function (index) { | |
1193 | var i = this.index_or_selected(index); |
|
1195 | var i = this.index_or_selected(index); | |
1194 | this.get_cell(i).collapse(); |
|
1196 | this.get_cell(i).collapse(); | |
1195 | this.set_dirty(true); |
|
1197 | this.set_dirty(true); | |
1196 | }; |
|
1198 | }; | |
1197 |
|
1199 | |||
1198 | /** |
|
1200 | /** | |
1199 | * Show a cell's output. |
|
1201 | * Show a cell's output. | |
1200 | * |
|
1202 | * | |
1201 | * @method expand |
|
1203 | * @method expand | |
1202 | * @param {Number} index A cell's numeric index |
|
1204 | * @param {Number} index A cell's numeric index | |
1203 | */ |
|
1205 | */ | |
1204 | Notebook.prototype.expand = function (index) { |
|
1206 | Notebook.prototype.expand = function (index) { | |
1205 | var i = this.index_or_selected(index); |
|
1207 | var i = this.index_or_selected(index); | |
1206 | this.get_cell(i).expand(); |
|
1208 | this.get_cell(i).expand(); | |
1207 | this.set_dirty(true); |
|
1209 | this.set_dirty(true); | |
1208 | }; |
|
1210 | }; | |
1209 |
|
1211 | |||
1210 | /** Toggle whether a cell's output is collapsed or expanded. |
|
1212 | /** Toggle whether a cell's output is collapsed or expanded. | |
1211 | * |
|
1213 | * | |
1212 | * @method toggle_output |
|
1214 | * @method toggle_output | |
1213 | * @param {Number} index A cell's numeric index |
|
1215 | * @param {Number} index A cell's numeric index | |
1214 | */ |
|
1216 | */ | |
1215 | Notebook.prototype.toggle_output = function (index) { |
|
1217 | Notebook.prototype.toggle_output = function (index) { | |
1216 | var i = this.index_or_selected(index); |
|
1218 | var i = this.index_or_selected(index); | |
1217 | this.get_cell(i).toggle_output(); |
|
1219 | this.get_cell(i).toggle_output(); | |
1218 | this.set_dirty(true); |
|
1220 | this.set_dirty(true); | |
1219 | }; |
|
1221 | }; | |
1220 |
|
1222 | |||
1221 | /** |
|
1223 | /** | |
1222 | * Toggle a scrollbar for long cell outputs. |
|
1224 | * Toggle a scrollbar for long cell outputs. | |
1223 | * |
|
1225 | * | |
1224 | * @method toggle_output_scroll |
|
1226 | * @method toggle_output_scroll | |
1225 | * @param {Number} index A cell's numeric index |
|
1227 | * @param {Number} index A cell's numeric index | |
1226 | */ |
|
1228 | */ | |
1227 | Notebook.prototype.toggle_output_scroll = function (index) { |
|
1229 | Notebook.prototype.toggle_output_scroll = function (index) { | |
1228 | var i = this.index_or_selected(index); |
|
1230 | var i = this.index_or_selected(index); | |
1229 | this.get_cell(i).toggle_output_scroll(); |
|
1231 | this.get_cell(i).toggle_output_scroll(); | |
1230 | }; |
|
1232 | }; | |
1231 |
|
1233 | |||
1232 | /** |
|
1234 | /** | |
1233 | * Hide each code cell's output area. |
|
1235 | * Hide each code cell's output area. | |
1234 | * |
|
1236 | * | |
1235 | * @method collapse_all_output |
|
1237 | * @method collapse_all_output | |
1236 | */ |
|
1238 | */ | |
1237 | Notebook.prototype.collapse_all_output = function () { |
|
1239 | Notebook.prototype.collapse_all_output = function () { | |
1238 | var ncells = this.ncells(); |
|
1240 | var ncells = this.ncells(); | |
1239 | var cells = this.get_cells(); |
|
1241 | var cells = this.get_cells(); | |
1240 | for (var i=0; i<ncells; i++) { |
|
1242 | for (var i=0; i<ncells; i++) { | |
1241 | if (cells[i] instanceof IPython.CodeCell) { |
|
1243 | if (cells[i] instanceof IPython.CodeCell) { | |
1242 | cells[i].output_area.collapse(); |
|
1244 | cells[i].output_area.collapse(); | |
1243 | } |
|
1245 | } | |
1244 | }; |
|
1246 | }; | |
1245 | // this should not be set if the `collapse` key is removed from nbformat |
|
1247 | // this should not be set if the `collapse` key is removed from nbformat | |
1246 | this.set_dirty(true); |
|
1248 | this.set_dirty(true); | |
1247 | }; |
|
1249 | }; | |
1248 |
|
1250 | |||
1249 | /** |
|
1251 | /** | |
1250 | * Expand each code cell's output area, and add a scrollbar for long output. |
|
1252 | * Expand each code cell's output area, and add a scrollbar for long output. | |
1251 | * |
|
1253 | * | |
1252 | * @method scroll_all_output |
|
1254 | * @method scroll_all_output | |
1253 | */ |
|
1255 | */ | |
1254 | Notebook.prototype.scroll_all_output = function () { |
|
1256 | Notebook.prototype.scroll_all_output = function () { | |
1255 | var ncells = this.ncells(); |
|
1257 | var ncells = this.ncells(); | |
1256 | var cells = this.get_cells(); |
|
1258 | var cells = this.get_cells(); | |
1257 | for (var i=0; i<ncells; i++) { |
|
1259 | for (var i=0; i<ncells; i++) { | |
1258 | if (cells[i] instanceof IPython.CodeCell) { |
|
1260 | if (cells[i] instanceof IPython.CodeCell) { | |
1259 | cells[i].output_area.expand(); |
|
1261 | cells[i].output_area.expand(); | |
1260 | cells[i].output_area.scroll_if_long(); |
|
1262 | cells[i].output_area.scroll_if_long(); | |
1261 | } |
|
1263 | } | |
1262 | }; |
|
1264 | }; | |
1263 | // this should not be set if the `collapse` key is removed from nbformat |
|
1265 | // this should not be set if the `collapse` key is removed from nbformat | |
1264 | this.set_dirty(true); |
|
1266 | this.set_dirty(true); | |
1265 | }; |
|
1267 | }; | |
1266 |
|
1268 | |||
1267 | /** |
|
1269 | /** | |
1268 | * Expand each code cell's output area, and remove scrollbars. |
|
1270 | * Expand each code cell's output area, and remove scrollbars. | |
1269 | * |
|
1271 | * | |
1270 | * @method expand_all_output |
|
1272 | * @method expand_all_output | |
1271 | */ |
|
1273 | */ | |
1272 | Notebook.prototype.expand_all_output = function () { |
|
1274 | Notebook.prototype.expand_all_output = function () { | |
1273 | var ncells = this.ncells(); |
|
1275 | var ncells = this.ncells(); | |
1274 | var cells = this.get_cells(); |
|
1276 | var cells = this.get_cells(); | |
1275 | for (var i=0; i<ncells; i++) { |
|
1277 | for (var i=0; i<ncells; i++) { | |
1276 | if (cells[i] instanceof IPython.CodeCell) { |
|
1278 | if (cells[i] instanceof IPython.CodeCell) { | |
1277 | cells[i].output_area.expand(); |
|
1279 | cells[i].output_area.expand(); | |
1278 | cells[i].output_area.unscroll_area(); |
|
1280 | cells[i].output_area.unscroll_area(); | |
1279 | } |
|
1281 | } | |
1280 | }; |
|
1282 | }; | |
1281 | // this should not be set if the `collapse` key is removed from nbformat |
|
1283 | // this should not be set if the `collapse` key is removed from nbformat | |
1282 | this.set_dirty(true); |
|
1284 | this.set_dirty(true); | |
1283 | }; |
|
1285 | }; | |
1284 |
|
1286 | |||
1285 | /** |
|
1287 | /** | |
1286 | * Clear each code cell's output area. |
|
1288 | * Clear each code cell's output area. | |
1287 | * |
|
1289 | * | |
1288 | * @method clear_all_output |
|
1290 | * @method clear_all_output | |
1289 | */ |
|
1291 | */ | |
1290 | Notebook.prototype.clear_all_output = function () { |
|
1292 | Notebook.prototype.clear_all_output = function () { | |
1291 | var ncells = this.ncells(); |
|
1293 | var ncells = this.ncells(); | |
1292 | var cells = this.get_cells(); |
|
1294 | var cells = this.get_cells(); | |
1293 | for (var i=0; i<ncells; i++) { |
|
1295 | for (var i=0; i<ncells; i++) { | |
1294 | if (cells[i] instanceof IPython.CodeCell) { |
|
1296 | if (cells[i] instanceof IPython.CodeCell) { | |
1295 | cells[i].clear_output(true,true,true); |
|
1297 | cells[i].clear_output(true,true,true); | |
1296 | // Make all In[] prompts blank, as well |
|
1298 | // Make all In[] prompts blank, as well | |
1297 | // TODO: make this configurable (via checkbox?) |
|
1299 | // TODO: make this configurable (via checkbox?) | |
1298 | cells[i].set_input_prompt(); |
|
1300 | cells[i].set_input_prompt(); | |
1299 | } |
|
1301 | } | |
1300 | }; |
|
1302 | }; | |
1301 | this.set_dirty(true); |
|
1303 | this.set_dirty(true); | |
1302 | }; |
|
1304 | }; | |
1303 |
|
1305 | |||
1304 |
|
1306 | |||
1305 | // Other cell functions: line numbers, ... |
|
1307 | // Other cell functions: line numbers, ... | |
1306 |
|
1308 | |||
1307 | /** |
|
1309 | /** | |
1308 | * Toggle line numbers in the selected cell's input area. |
|
1310 | * Toggle line numbers in the selected cell's input area. | |
1309 | * |
|
1311 | * | |
1310 | * @method cell_toggle_line_numbers |
|
1312 | * @method cell_toggle_line_numbers | |
1311 | */ |
|
1313 | */ | |
1312 | Notebook.prototype.cell_toggle_line_numbers = function() { |
|
1314 | Notebook.prototype.cell_toggle_line_numbers = function() { | |
1313 | this.get_selected_cell().toggle_line_numbers(); |
|
1315 | this.get_selected_cell().toggle_line_numbers(); | |
1314 | }; |
|
1316 | }; | |
1315 |
|
1317 | |||
1316 | // Kernel related things |
|
1318 | // Kernel related things | |
1317 |
|
1319 | |||
1318 | /** |
|
1320 | /** | |
1319 | * Start a new kernel and set it on each code cell. |
|
1321 | * Start a new kernel and set it on each code cell. | |
1320 | * |
|
1322 | * | |
1321 | * @method start_kernel |
|
1323 | * @method start_kernel | |
1322 | */ |
|
1324 | */ | |
1323 | Notebook.prototype.start_kernel = function () { |
|
1325 | Notebook.prototype.start_kernel = function () { | |
1324 | var base_url = $('body').data('baseKernelUrl') + "kernels"; |
|
1326 | var base_url = $('body').data('baseKernelUrl') + "kernels"; | |
1325 | this.kernel = new IPython.Kernel(base_url); |
|
1327 | this.kernel = new IPython.Kernel(base_url); | |
1326 | this.kernel.start(this.notebook_id); |
|
1328 | this.kernel.start(this.notebook_id); | |
1327 | // Now that the kernel has been created, tell the CodeCells about it. |
|
1329 | // Now that the kernel has been created, tell the CodeCells about it. | |
1328 | var ncells = this.ncells(); |
|
1330 | var ncells = this.ncells(); | |
1329 | for (var i=0; i<ncells; i++) { |
|
1331 | for (var i=0; i<ncells; i++) { | |
1330 | var cell = this.get_cell(i); |
|
1332 | var cell = this.get_cell(i); | |
1331 | if (cell instanceof IPython.CodeCell) { |
|
1333 | if (cell instanceof IPython.CodeCell) { | |
1332 | cell.set_kernel(this.kernel) |
|
1334 | cell.set_kernel(this.kernel) | |
1333 | }; |
|
1335 | }; | |
1334 | }; |
|
1336 | }; | |
1335 | }; |
|
1337 | }; | |
1336 |
|
1338 | |||
1337 | /** |
|
1339 | /** | |
1338 | * Prompt the user to restart the IPython kernel. |
|
1340 | * Prompt the user to restart the IPython kernel. | |
1339 | * |
|
1341 | * | |
1340 | * @method restart_kernel |
|
1342 | * @method restart_kernel | |
1341 | */ |
|
1343 | */ | |
1342 | Notebook.prototype.restart_kernel = function () { |
|
1344 | Notebook.prototype.restart_kernel = function () { | |
1343 | var that = this; |
|
1345 | var that = this; | |
1344 | var dialog = $('<div/>'); |
|
1346 | IPython.dialog.modal({ | |
1345 | dialog.html('Do you want to restart the current kernel? You will lose all variables defined in it.'); |
|
1347 | title : "Restart kernel or continue running?", | |
1346 | $(document).append(dialog); |
|
1348 | body : $("<p/>").html( | |
1347 | dialog.dialog({ |
|
1349 | 'Do you want to restart the current kernel? You will lose all variables defined in it.' | |
1348 |
|
|
1350 | ), | |
1349 | modal: true, |
|
|||
1350 | title: "Restart kernel or continue running?", |
|
|||
1351 | closeText: '', |
|
|||
1352 | buttons : { |
|
1351 | buttons : { | |
1353 | "Restart": function () { |
|
1352 | "Continue running" : {}, | |
1354 |
|
|
1353 | "Restart" : { | |
1355 | $(this).dialog('close'); |
|
1354 | "class" : "btn-danger", | |
1356 | }, |
|
1355 | "click" : function() { | |
1357 | "Continue running": function () { |
|
1356 | that.kernel.restart(); | |
1358 |
|
|
1357 | } | |
1359 | } |
|
1358 | } | |
1360 | } |
|
1359 | } | |
1361 | }); |
|
1360 | }); | |
1362 | }; |
|
1361 | }; | |
1363 |
|
1362 | |||
1364 | /** |
|
1363 | /** | |
1365 | * Run the selected cell. |
|
1364 | * Run the selected cell. | |
1366 | * |
|
1365 | * | |
1367 | * Execute or render cell outputs. |
|
1366 | * Execute or render cell outputs. | |
1368 | * |
|
1367 | * | |
1369 | * @method execute_selected_cell |
|
1368 | * @method execute_selected_cell | |
1370 | * @param {Object} options Customize post-execution behavior |
|
1369 | * @param {Object} options Customize post-execution behavior | |
1371 | */ |
|
1370 | */ | |
1372 | Notebook.prototype.execute_selected_cell = function (options) { |
|
1371 | Notebook.prototype.execute_selected_cell = function (options) { | |
1373 | // add_new: should a new cell be added if we are at the end of the nb |
|
1372 | // add_new: should a new cell be added if we are at the end of the nb | |
1374 | // terminal: execute in terminal mode, which stays in the current cell |
|
1373 | // terminal: execute in terminal mode, which stays in the current cell | |
1375 | var default_options = {terminal: false, add_new: true}; |
|
1374 | var default_options = {terminal: false, add_new: true}; | |
1376 | $.extend(default_options, options); |
|
1375 | $.extend(default_options, options); | |
1377 | var that = this; |
|
1376 | var that = this; | |
1378 | var cell = that.get_selected_cell(); |
|
1377 | var cell = that.get_selected_cell(); | |
1379 | var cell_index = that.find_cell_index(cell); |
|
1378 | var cell_index = that.find_cell_index(cell); | |
1380 | if (cell instanceof IPython.CodeCell) { |
|
1379 | if (cell instanceof IPython.CodeCell) { | |
1381 | cell.execute(); |
|
1380 | cell.execute(); | |
1382 | } |
|
1381 | } | |
1383 | if (default_options.terminal) { |
|
1382 | if (default_options.terminal) { | |
1384 | cell.select_all(); |
|
1383 | cell.select_all(); | |
1385 | } else { |
|
1384 | } else { | |
1386 | if ((cell_index === (that.ncells()-1)) && default_options.add_new) { |
|
1385 | if ((cell_index === (that.ncells()-1)) && default_options.add_new) { | |
1387 | that.insert_cell_below('code'); |
|
1386 | that.insert_cell_below('code'); | |
1388 | // If we are adding a new cell at the end, scroll down to show it. |
|
1387 | // If we are adding a new cell at the end, scroll down to show it. | |
1389 | that.scroll_to_bottom(); |
|
1388 | that.scroll_to_bottom(); | |
1390 | } else { |
|
1389 | } else { | |
1391 | that.select(cell_index+1); |
|
1390 | that.select(cell_index+1); | |
1392 | }; |
|
1391 | }; | |
1393 | }; |
|
1392 | }; | |
1394 | this.set_dirty(true); |
|
1393 | this.set_dirty(true); | |
1395 | }; |
|
1394 | }; | |
1396 |
|
1395 | |||
1397 | /** |
|
1396 | /** | |
1398 | * Execute all cells below the selected cell. |
|
1397 | * Execute all cells below the selected cell. | |
1399 | * |
|
1398 | * | |
1400 | * @method execute_cells_below |
|
1399 | * @method execute_cells_below | |
1401 | */ |
|
1400 | */ | |
1402 | Notebook.prototype.execute_cells_below = function () { |
|
1401 | Notebook.prototype.execute_cells_below = function () { | |
1403 | this.execute_cell_range(this.get_selected_index(), this.ncells()); |
|
1402 | this.execute_cell_range(this.get_selected_index(), this.ncells()); | |
1404 | this.scroll_to_bottom(); |
|
1403 | this.scroll_to_bottom(); | |
1405 | }; |
|
1404 | }; | |
1406 |
|
1405 | |||
1407 | /** |
|
1406 | /** | |
1408 | * Execute all cells above the selected cell. |
|
1407 | * Execute all cells above the selected cell. | |
1409 | * |
|
1408 | * | |
1410 | * @method execute_cells_above |
|
1409 | * @method execute_cells_above | |
1411 | */ |
|
1410 | */ | |
1412 | Notebook.prototype.execute_cells_above = function () { |
|
1411 | Notebook.prototype.execute_cells_above = function () { | |
1413 | this.execute_cell_range(0, this.get_selected_index()); |
|
1412 | this.execute_cell_range(0, this.get_selected_index()); | |
1414 | }; |
|
1413 | }; | |
1415 |
|
1414 | |||
1416 | /** |
|
1415 | /** | |
1417 | * Execute all cells. |
|
1416 | * Execute all cells. | |
1418 | * |
|
1417 | * | |
1419 | * @method execute_all_cells |
|
1418 | * @method execute_all_cells | |
1420 | */ |
|
1419 | */ | |
1421 | Notebook.prototype.execute_all_cells = function () { |
|
1420 | Notebook.prototype.execute_all_cells = function () { | |
1422 | this.execute_cell_range(0, this.ncells()); |
|
1421 | this.execute_cell_range(0, this.ncells()); | |
1423 | this.scroll_to_bottom(); |
|
1422 | this.scroll_to_bottom(); | |
1424 | }; |
|
1423 | }; | |
1425 |
|
1424 | |||
1426 | /** |
|
1425 | /** | |
1427 | * Execute a contiguous range of cells. |
|
1426 | * Execute a contiguous range of cells. | |
1428 | * |
|
1427 | * | |
1429 | * @method execute_cell_range |
|
1428 | * @method execute_cell_range | |
1430 | * @param {Number} start Index of the first cell to execute (inclusive) |
|
1429 | * @param {Number} start Index of the first cell to execute (inclusive) | |
1431 | * @param {Number} end Index of the last cell to execute (exclusive) |
|
1430 | * @param {Number} end Index of the last cell to execute (exclusive) | |
1432 | */ |
|
1431 | */ | |
1433 | Notebook.prototype.execute_cell_range = function (start, end) { |
|
1432 | Notebook.prototype.execute_cell_range = function (start, end) { | |
1434 | for (var i=start; i<end; i++) { |
|
1433 | for (var i=start; i<end; i++) { | |
1435 | this.select(i); |
|
1434 | this.select(i); | |
1436 | this.execute_selected_cell({add_new:false}); |
|
1435 | this.execute_selected_cell({add_new:false}); | |
1437 | }; |
|
1436 | }; | |
1438 | }; |
|
1437 | }; | |
1439 |
|
1438 | |||
1440 | // Persistance and loading |
|
1439 | // Persistance and loading | |
1441 |
|
1440 | |||
1442 | /** |
|
1441 | /** | |
1443 | * Getter method for this notebook's ID. |
|
1442 | * Getter method for this notebook's ID. | |
1444 | * |
|
1443 | * | |
1445 | * @method get_notebook_id |
|
1444 | * @method get_notebook_id | |
1446 | * @return {String} This notebook's ID |
|
1445 | * @return {String} This notebook's ID | |
1447 | */ |
|
1446 | */ | |
1448 | Notebook.prototype.get_notebook_id = function () { |
|
1447 | Notebook.prototype.get_notebook_id = function () { | |
1449 | return this.notebook_id; |
|
1448 | return this.notebook_id; | |
1450 | }; |
|
1449 | }; | |
1451 |
|
1450 | |||
1452 | /** |
|
1451 | /** | |
1453 | * Getter method for this notebook's name. |
|
1452 | * Getter method for this notebook's name. | |
1454 | * |
|
1453 | * | |
1455 | * @method get_notebook_name |
|
1454 | * @method get_notebook_name | |
1456 | * @return {String} This notebook's name |
|
1455 | * @return {String} This notebook's name | |
1457 | */ |
|
1456 | */ | |
1458 | Notebook.prototype.get_notebook_name = function () { |
|
1457 | Notebook.prototype.get_notebook_name = function () { | |
1459 | return this.notebook_name; |
|
1458 | return this.notebook_name; | |
1460 | }; |
|
1459 | }; | |
1461 |
|
1460 | |||
1462 | /** |
|
1461 | /** | |
1463 | * Setter method for this notebook's name. |
|
1462 | * Setter method for this notebook's name. | |
1464 | * |
|
1463 | * | |
1465 | * @method set_notebook_name |
|
1464 | * @method set_notebook_name | |
1466 | * @param {String} name A new name for this notebook |
|
1465 | * @param {String} name A new name for this notebook | |
1467 | */ |
|
1466 | */ | |
1468 | Notebook.prototype.set_notebook_name = function (name) { |
|
1467 | Notebook.prototype.set_notebook_name = function (name) { | |
1469 | this.notebook_name = name; |
|
1468 | this.notebook_name = name; | |
1470 | }; |
|
1469 | }; | |
1471 |
|
1470 | |||
1472 | /** |
|
1471 | /** | |
1473 | * Check that a notebook's name is valid. |
|
1472 | * Check that a notebook's name is valid. | |
1474 | * |
|
1473 | * | |
1475 | * @method test_notebook_name |
|
1474 | * @method test_notebook_name | |
1476 | * @param {String} nbname A name for this notebook |
|
1475 | * @param {String} nbname A name for this notebook | |
1477 | * @return {Boolean} True if the name is valid, false if invalid |
|
1476 | * @return {Boolean} True if the name is valid, false if invalid | |
1478 | */ |
|
1477 | */ | |
1479 | Notebook.prototype.test_notebook_name = function (nbname) { |
|
1478 | Notebook.prototype.test_notebook_name = function (nbname) { | |
1480 | nbname = nbname || ''; |
|
1479 | nbname = nbname || ''; | |
1481 | if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) { |
|
1480 | if (this.notebook_name_blacklist_re.test(nbname) == false && nbname.length>0) { | |
1482 | return true; |
|
1481 | return true; | |
1483 | } else { |
|
1482 | } else { | |
1484 | return false; |
|
1483 | return false; | |
1485 | }; |
|
1484 | }; | |
1486 | }; |
|
1485 | }; | |
1487 |
|
1486 | |||
1488 | /** |
|
1487 | /** | |
1489 | * Load a notebook from JSON (.ipynb). |
|
1488 | * Load a notebook from JSON (.ipynb). | |
1490 | * |
|
1489 | * | |
1491 | * This currently handles one worksheet: others are deleted. |
|
1490 | * This currently handles one worksheet: others are deleted. | |
1492 | * |
|
1491 | * | |
1493 | * @method fromJSON |
|
1492 | * @method fromJSON | |
1494 | * @param {Object} data JSON representation of a notebook |
|
1493 | * @param {Object} data JSON representation of a notebook | |
1495 | */ |
|
1494 | */ | |
1496 | Notebook.prototype.fromJSON = function (data) { |
|
1495 | Notebook.prototype.fromJSON = function (data) { | |
1497 | var ncells = this.ncells(); |
|
1496 | var ncells = this.ncells(); | |
1498 | var i; |
|
1497 | var i; | |
1499 | for (i=0; i<ncells; i++) { |
|
1498 | for (i=0; i<ncells; i++) { | |
1500 | // Always delete cell 0 as they get renumbered as they are deleted. |
|
1499 | // Always delete cell 0 as they get renumbered as they are deleted. | |
1501 | this.delete_cell(0); |
|
1500 | this.delete_cell(0); | |
1502 | }; |
|
1501 | }; | |
1503 | // Save the metadata and name. |
|
1502 | // Save the metadata and name. | |
1504 | this.metadata = data.metadata; |
|
1503 | this.metadata = data.metadata; | |
1505 | this.notebook_name = data.metadata.name; |
|
1504 | this.notebook_name = data.metadata.name; | |
1506 | // Only handle 1 worksheet for now. |
|
1505 | // Only handle 1 worksheet for now. | |
1507 | var worksheet = data.worksheets[0]; |
|
1506 | var worksheet = data.worksheets[0]; | |
1508 | if (worksheet !== undefined) { |
|
1507 | if (worksheet !== undefined) { | |
1509 | if (worksheet.metadata) { |
|
1508 | if (worksheet.metadata) { | |
1510 | this.worksheet_metadata = worksheet.metadata; |
|
1509 | this.worksheet_metadata = worksheet.metadata; | |
1511 | } |
|
1510 | } | |
1512 | var new_cells = worksheet.cells; |
|
1511 | var new_cells = worksheet.cells; | |
1513 | ncells = new_cells.length; |
|
1512 | ncells = new_cells.length; | |
1514 | var cell_data = null; |
|
1513 | var cell_data = null; | |
1515 | var new_cell = null; |
|
1514 | var new_cell = null; | |
1516 | for (i=0; i<ncells; i++) { |
|
1515 | for (i=0; i<ncells; i++) { | |
1517 | cell_data = new_cells[i]; |
|
1516 | cell_data = new_cells[i]; | |
1518 | // VERSIONHACK: plaintext -> raw |
|
1517 | // VERSIONHACK: plaintext -> raw | |
1519 | // handle never-released plaintext name for raw cells |
|
1518 | // handle never-released plaintext name for raw cells | |
1520 | if (cell_data.cell_type === 'plaintext'){ |
|
1519 | if (cell_data.cell_type === 'plaintext'){ | |
1521 | cell_data.cell_type = 'raw'; |
|
1520 | cell_data.cell_type = 'raw'; | |
1522 | } |
|
1521 | } | |
1523 |
|
1522 | |||
1524 | new_cell = this.insert_cell_below(cell_data.cell_type); |
|
1523 | new_cell = this.insert_cell_below(cell_data.cell_type); | |
1525 | new_cell.fromJSON(cell_data); |
|
1524 | new_cell.fromJSON(cell_data); | |
1526 | }; |
|
1525 | }; | |
1527 | }; |
|
1526 | }; | |
1528 | if (data.worksheets.length > 1) { |
|
1527 | if (data.worksheets.length > 1) { | |
1529 | var dialog = $('<div/>'); |
|
1528 | IPython.dialog.modal({ | |
1530 | dialog.html("This notebook has " + data.worksheets.length + " worksheets, " + |
|
1529 | title : "Multiple worksheets", | |
1531 | "but this version of IPython can only handle the first. " + |
|
1530 | body : "This notebook has " + data.worksheets.length + " worksheets, " + | |
1532 | "If you save this notebook, worksheets after the first will be lost." |
|
1531 | "but this version of IPython can only handle the first. " + | |
1533 | ); |
|
1532 | "If you save this notebook, worksheets after the first will be lost.", | |
1534 | this.element.append(dialog); |
|
|||
1535 | dialog.dialog({ |
|
|||
1536 | resizable: false, |
|
|||
1537 | modal: true, |
|
|||
1538 | title: "Multiple worksheets", |
|
|||
1539 | closeText: "", |
|
|||
1540 | close: function(event, ui) {$(this).dialog('destroy').remove();}, |
|
|||
1541 | buttons : { |
|
1533 | buttons : { | |
1542 |
|
|
1534 | OK : { | |
1543 |
|
|
1535 | class : "btn-danger" | |
1544 | } |
|
1536 | } | |
1545 |
} |
|
1537 | } | |
1546 | width: 400 |
|
|||
1547 | }); |
|
1538 | }); | |
1548 | } |
|
1539 | } | |
1549 | }; |
|
1540 | }; | |
1550 |
|
1541 | |||
1551 | /** |
|
1542 | /** | |
1552 | * Dump this notebook into a JSON-friendly object. |
|
1543 | * Dump this notebook into a JSON-friendly object. | |
1553 | * |
|
1544 | * | |
1554 | * @method toJSON |
|
1545 | * @method toJSON | |
1555 | * @return {Object} A JSON-friendly representation of this notebook. |
|
1546 | * @return {Object} A JSON-friendly representation of this notebook. | |
1556 | */ |
|
1547 | */ | |
1557 | Notebook.prototype.toJSON = function () { |
|
1548 | Notebook.prototype.toJSON = function () { | |
1558 | var cells = this.get_cells(); |
|
1549 | var cells = this.get_cells(); | |
1559 | var ncells = cells.length; |
|
1550 | var ncells = cells.length; | |
1560 | var cell_array = new Array(ncells); |
|
1551 | var cell_array = new Array(ncells); | |
1561 | for (var i=0; i<ncells; i++) { |
|
1552 | for (var i=0; i<ncells; i++) { | |
1562 | cell_array[i] = cells[i].toJSON(); |
|
1553 | cell_array[i] = cells[i].toJSON(); | |
1563 | }; |
|
1554 | }; | |
1564 | var data = { |
|
1555 | var data = { | |
1565 | // Only handle 1 worksheet for now. |
|
1556 | // Only handle 1 worksheet for now. | |
1566 | worksheets : [{ |
|
1557 | worksheets : [{ | |
1567 | cells: cell_array, |
|
1558 | cells: cell_array, | |
1568 | metadata: this.worksheet_metadata |
|
1559 | metadata: this.worksheet_metadata | |
1569 | }], |
|
1560 | }], | |
1570 | metadata : this.metadata |
|
1561 | metadata : this.metadata | |
1571 | }; |
|
1562 | }; | |
1572 | return data; |
|
1563 | return data; | |
1573 | }; |
|
1564 | }; | |
1574 |
|
1565 | |||
1575 | /** |
|
1566 | /** | |
1576 | * Start an autosave timer, for periodically saving the notebook. |
|
1567 | * Start an autosave timer, for periodically saving the notebook. | |
1577 | * |
|
1568 | * | |
1578 | * @method set_autosave_interval |
|
1569 | * @method set_autosave_interval | |
1579 | * @param {Integer} interval the autosave interval in milliseconds |
|
1570 | * @param {Integer} interval the autosave interval in milliseconds | |
1580 | */ |
|
1571 | */ | |
1581 | Notebook.prototype.set_autosave_interval = function (interval) { |
|
1572 | Notebook.prototype.set_autosave_interval = function (interval) { | |
1582 | var that = this; |
|
1573 | var that = this; | |
1583 | // clear previous interval, so we don't get simultaneous timers |
|
1574 | // clear previous interval, so we don't get simultaneous timers | |
1584 | if (this.autosave_timer) { |
|
1575 | if (this.autosave_timer) { | |
1585 | clearInterval(this.autosave_timer); |
|
1576 | clearInterval(this.autosave_timer); | |
1586 | } |
|
1577 | } | |
1587 |
|
1578 | |||
1588 | this.autosave_interval = this.minimum_autosave_interval = interval; |
|
1579 | this.autosave_interval = this.minimum_autosave_interval = interval; | |
1589 | if (interval) { |
|
1580 | if (interval) { | |
1590 | this.autosave_timer = setInterval(function() { |
|
1581 | this.autosave_timer = setInterval(function() { | |
1591 | if (that.dirty) { |
|
1582 | if (that.dirty) { | |
1592 | that.save_notebook(); |
|
1583 | that.save_notebook(); | |
1593 | } |
|
1584 | } | |
1594 | }, interval); |
|
1585 | }, interval); | |
1595 | $([IPython.events]).trigger("autosave_enabled.Notebook", interval); |
|
1586 | $([IPython.events]).trigger("autosave_enabled.Notebook", interval); | |
1596 | } else { |
|
1587 | } else { | |
1597 | this.autosave_timer = null; |
|
1588 | this.autosave_timer = null; | |
1598 | $([IPython.events]).trigger("autosave_disabled.Notebook"); |
|
1589 | $([IPython.events]).trigger("autosave_disabled.Notebook"); | |
1599 | }; |
|
1590 | }; | |
1600 | }; |
|
1591 | }; | |
1601 |
|
1592 | |||
1602 | /** |
|
1593 | /** | |
1603 | * Save this notebook on the server. |
|
1594 | * Save this notebook on the server. | |
1604 | * |
|
1595 | * | |
1605 | * @method save_notebook |
|
1596 | * @method save_notebook | |
1606 | */ |
|
1597 | */ | |
1607 | Notebook.prototype.save_notebook = function () { |
|
1598 | Notebook.prototype.save_notebook = function () { | |
1608 | // We may want to move the name/id/nbformat logic inside toJSON? |
|
1599 | // We may want to move the name/id/nbformat logic inside toJSON? | |
1609 | var data = this.toJSON(); |
|
1600 | var data = this.toJSON(); | |
1610 | data.metadata.name = this.notebook_name; |
|
1601 | data.metadata.name = this.notebook_name; | |
1611 | data.nbformat = this.nbformat; |
|
1602 | data.nbformat = this.nbformat; | |
1612 | data.nbformat_minor = this.nbformat_minor; |
|
1603 | data.nbformat_minor = this.nbformat_minor; | |
1613 |
|
1604 | |||
1614 | // time the ajax call for autosave tuning purposes. |
|
1605 | // time the ajax call for autosave tuning purposes. | |
1615 | var start = new Date().getTime(); |
|
1606 | var start = new Date().getTime(); | |
1616 |
|
1607 | |||
1617 | // We do the call with settings so we can set cache to false. |
|
1608 | // We do the call with settings so we can set cache to false. | |
1618 | var settings = { |
|
1609 | var settings = { | |
1619 | processData : false, |
|
1610 | processData : false, | |
1620 | cache : false, |
|
1611 | cache : false, | |
1621 | type : "PUT", |
|
1612 | type : "PUT", | |
1622 | data : JSON.stringify(data), |
|
1613 | data : JSON.stringify(data), | |
1623 | headers : {'Content-Type': 'application/json'}, |
|
1614 | headers : {'Content-Type': 'application/json'}, | |
1624 | success : $.proxy(this.save_notebook_success, this, start), |
|
1615 | success : $.proxy(this.save_notebook_success, this, start), | |
1625 | error : $.proxy(this.save_notebook_error, this) |
|
1616 | error : $.proxy(this.save_notebook_error, this) | |
1626 | }; |
|
1617 | }; | |
1627 | $([IPython.events]).trigger('notebook_saving.Notebook'); |
|
1618 | $([IPython.events]).trigger('notebook_saving.Notebook'); | |
1628 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id; |
|
1619 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id; | |
1629 | $.ajax(url, settings); |
|
1620 | $.ajax(url, settings); | |
1630 | }; |
|
1621 | }; | |
1631 |
|
1622 | |||
1632 | /** |
|
1623 | /** | |
1633 | * Success callback for saving a notebook. |
|
1624 | * Success callback for saving a notebook. | |
1634 | * |
|
1625 | * | |
1635 | * @method save_notebook_success |
|
1626 | * @method save_notebook_success | |
1636 | * @param {Integer} start the time when the save request started |
|
1627 | * @param {Integer} start the time when the save request started | |
1637 | * @param {Object} data JSON representation of a notebook |
|
1628 | * @param {Object} data JSON representation of a notebook | |
1638 | * @param {String} status Description of response status |
|
1629 | * @param {String} status Description of response status | |
1639 | * @param {jqXHR} xhr jQuery Ajax object |
|
1630 | * @param {jqXHR} xhr jQuery Ajax object | |
1640 | */ |
|
1631 | */ | |
1641 | Notebook.prototype.save_notebook_success = function (start, data, status, xhr) { |
|
1632 | Notebook.prototype.save_notebook_success = function (start, data, status, xhr) { | |
1642 | this.set_dirty(false); |
|
1633 | this.set_dirty(false); | |
1643 | $([IPython.events]).trigger('notebook_saved.Notebook'); |
|
1634 | $([IPython.events]).trigger('notebook_saved.Notebook'); | |
1644 | this._update_autosave_interval(start); |
|
1635 | this._update_autosave_interval(start); | |
1645 | if (this._checkpoint_after_save) { |
|
1636 | if (this._checkpoint_after_save) { | |
1646 | this.create_checkpoint(); |
|
1637 | this.create_checkpoint(); | |
1647 | this._checkpoint_after_save = false; |
|
1638 | this._checkpoint_after_save = false; | |
1648 | }; |
|
1639 | }; | |
1649 | }; |
|
1640 | }; | |
1650 |
|
1641 | |||
1651 | /** |
|
1642 | /** | |
1652 | * update the autosave interval based on how long the last save took |
|
1643 | * update the autosave interval based on how long the last save took | |
1653 | * |
|
1644 | * | |
1654 | * @method _update_autosave_interval |
|
1645 | * @method _update_autosave_interval | |
1655 | * @param {Integer} timestamp when the save request started |
|
1646 | * @param {Integer} timestamp when the save request started | |
1656 | */ |
|
1647 | */ | |
1657 | Notebook.prototype._update_autosave_interval = function (start) { |
|
1648 | Notebook.prototype._update_autosave_interval = function (start) { | |
1658 | var duration = (new Date().getTime() - start); |
|
1649 | var duration = (new Date().getTime() - start); | |
1659 | if (this.autosave_interval) { |
|
1650 | if (this.autosave_interval) { | |
1660 | // new save interval: higher of 10x save duration or parameter (default 30 seconds) |
|
1651 | // new save interval: higher of 10x save duration or parameter (default 30 seconds) | |
1661 | var interval = Math.max(10 * duration, this.minimum_autosave_interval); |
|
1652 | var interval = Math.max(10 * duration, this.minimum_autosave_interval); | |
1662 | // round to 10 seconds, otherwise we will be setting a new interval too often |
|
1653 | // round to 10 seconds, otherwise we will be setting a new interval too often | |
1663 | interval = 10000 * Math.round(interval / 10000); |
|
1654 | interval = 10000 * Math.round(interval / 10000); | |
1664 | // set new interval, if it's changed |
|
1655 | // set new interval, if it's changed | |
1665 | if (interval != this.autosave_interval) { |
|
1656 | if (interval != this.autosave_interval) { | |
1666 | this.set_autosave_interval(interval); |
|
1657 | this.set_autosave_interval(interval); | |
1667 | } |
|
1658 | } | |
1668 | } |
|
1659 | } | |
1669 | }; |
|
1660 | }; | |
1670 |
|
1661 | |||
1671 | /** |
|
1662 | /** | |
1672 | * Failure callback for saving a notebook. |
|
1663 | * Failure callback for saving a notebook. | |
1673 | * |
|
1664 | * | |
1674 | * @method save_notebook_error |
|
1665 | * @method save_notebook_error | |
1675 | * @param {jqXHR} xhr jQuery Ajax object |
|
1666 | * @param {jqXHR} xhr jQuery Ajax object | |
1676 | * @param {String} status Description of response status |
|
1667 | * @param {String} status Description of response status | |
1677 | * @param {String} error_msg HTTP error message |
|
1668 | * @param {String} error_msg HTTP error message | |
1678 | */ |
|
1669 | */ | |
1679 | Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) { |
|
1670 | Notebook.prototype.save_notebook_error = function (xhr, status, error_msg) { | |
1680 | $([IPython.events]).trigger('notebook_save_failed.Notebook'); |
|
1671 | $([IPython.events]).trigger('notebook_save_failed.Notebook'); | |
1681 | }; |
|
1672 | }; | |
1682 |
|
1673 | |||
1683 | /** |
|
1674 | /** | |
1684 | * Request a notebook's data from the server. |
|
1675 | * Request a notebook's data from the server. | |
1685 | * |
|
1676 | * | |
1686 | * @method load_notebook |
|
1677 | * @method load_notebook | |
1687 | * @param {String} notebook_id A notebook to load |
|
1678 | * @param {String} notebook_id A notebook to load | |
1688 | */ |
|
1679 | */ | |
1689 | Notebook.prototype.load_notebook = function (notebook_id) { |
|
1680 | Notebook.prototype.load_notebook = function (notebook_id) { | |
1690 | var that = this; |
|
1681 | var that = this; | |
1691 | this.notebook_id = notebook_id; |
|
1682 | this.notebook_id = notebook_id; | |
1692 | // We do the call with settings so we can set cache to false. |
|
1683 | // We do the call with settings so we can set cache to false. | |
1693 | var settings = { |
|
1684 | var settings = { | |
1694 | processData : false, |
|
1685 | processData : false, | |
1695 | cache : false, |
|
1686 | cache : false, | |
1696 | type : "GET", |
|
1687 | type : "GET", | |
1697 | dataType : "json", |
|
1688 | dataType : "json", | |
1698 | success : $.proxy(this.load_notebook_success,this), |
|
1689 | success : $.proxy(this.load_notebook_success,this), | |
1699 | error : $.proxy(this.load_notebook_error,this), |
|
1690 | error : $.proxy(this.load_notebook_error,this), | |
1700 | }; |
|
1691 | }; | |
1701 | $([IPython.events]).trigger('notebook_loading.Notebook'); |
|
1692 | $([IPython.events]).trigger('notebook_loading.Notebook'); | |
1702 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id; |
|
1693 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id; | |
1703 | $.ajax(url, settings); |
|
1694 | $.ajax(url, settings); | |
1704 | }; |
|
1695 | }; | |
1705 |
|
1696 | |||
1706 | /** |
|
1697 | /** | |
1707 | * Success callback for loading a notebook from the server. |
|
1698 | * Success callback for loading a notebook from the server. | |
1708 | * |
|
1699 | * | |
1709 | * Load notebook data from the JSON response. |
|
1700 | * Load notebook data from the JSON response. | |
1710 | * |
|
1701 | * | |
1711 | * @method load_notebook_success |
|
1702 | * @method load_notebook_success | |
1712 | * @param {Object} data JSON representation of a notebook |
|
1703 | * @param {Object} data JSON representation of a notebook | |
1713 | * @param {String} status Description of response status |
|
1704 | * @param {String} status Description of response status | |
1714 | * @param {jqXHR} xhr jQuery Ajax object |
|
1705 | * @param {jqXHR} xhr jQuery Ajax object | |
1715 | */ |
|
1706 | */ | |
1716 | Notebook.prototype.load_notebook_success = function (data, status, xhr) { |
|
1707 | Notebook.prototype.load_notebook_success = function (data, status, xhr) { | |
1717 | this.fromJSON(data); |
|
1708 | this.fromJSON(data); | |
1718 | if (this.ncells() === 0) { |
|
1709 | if (this.ncells() === 0) { | |
1719 | this.insert_cell_below('code'); |
|
1710 | this.insert_cell_below('code'); | |
1720 | }; |
|
1711 | }; | |
1721 | this.set_dirty(false); |
|
1712 | this.set_dirty(false); | |
1722 | this.select(0); |
|
1713 | this.select(0); | |
1723 | this.scroll_to_top(); |
|
1714 | this.scroll_to_top(); | |
1724 | if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) { |
|
1715 | if (data.orig_nbformat !== undefined && data.nbformat !== data.orig_nbformat) { | |
1725 | msg = "This notebook has been converted from an older " + |
|
1716 | var msg = "This notebook has been converted from an older " + | |
1726 | "notebook format (v"+data.orig_nbformat+") to the current notebook " + |
|
1717 | "notebook format (v"+data.orig_nbformat+") to the current notebook " + | |
1727 | "format (v"+data.nbformat+"). The next time you save this notebook, the " + |
|
1718 | "format (v"+data.nbformat+"). The next time you save this notebook, the " + | |
1728 | "newer notebook format will be used and older verions of IPython " + |
|
1719 | "newer notebook format will be used and older versions of IPython " + | |
1729 | "may not be able to read it. To keep the older version, close the " + |
|
1720 | "may not be able to read it. To keep the older version, close the " + | |
1730 | "notebook without saving it."; |
|
1721 | "notebook without saving it."; | |
1731 | var dialog = $('<div/>'); |
|
1722 | IPython.dialog.modal({ | |
1732 | dialog.html(msg); |
|
1723 | title : "Notebook converted", | |
1733 | this.element.append(dialog); |
|
1724 | body : msg, | |
1734 | dialog.dialog({ |
|
|||
1735 | resizable: false, |
|
|||
1736 | modal: true, |
|
|||
1737 | title: "Notebook converted", |
|
|||
1738 | closeText: "", |
|
|||
1739 | close: function(event, ui) {$(this).dialog('destroy').remove();}, |
|
|||
1740 | buttons : { |
|
1725 | buttons : { | |
1741 |
|
|
1726 | OK : { | |
1742 | $(this).dialog('close'); |
|
1727 | class : "btn-primary" | |
1743 | } |
|
1728 | } | |
1744 |
} |
|
1729 | } | |
1745 | width: 400 |
|
|||
1746 | }); |
|
1730 | }); | |
1747 | } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) { |
|
1731 | } else if (data.orig_nbformat_minor !== undefined && data.nbformat_minor !== data.orig_nbformat_minor) { | |
1748 | var that = this; |
|
1732 | var that = this; | |
1749 | var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor; |
|
1733 | var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor; | |
1750 | var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor; |
|
1734 | var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor; | |
1751 | var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + |
|
1735 | var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + | |
1752 | this_vs + ". You can still work with this notebook, but some features " + |
|
1736 | this_vs + ". You can still work with this notebook, but some features " + | |
1753 | "introduced in later notebook versions may not be available." |
|
1737 | "introduced in later notebook versions may not be available." | |
1754 |
|
1738 | |||
1755 | var dialog = $('<div/>'); |
|
1739 | IPython.dialog.modal({ | |
1756 | dialog.html(msg); |
|
1740 | title : "Newer Notebook", | |
1757 | this.element.append(dialog); |
|
1741 | body : msg, | |
1758 | dialog.dialog({ |
|
|||
1759 | resizable: false, |
|
|||
1760 | modal: true, |
|
|||
1761 | title: "Newer Notebook", |
|
|||
1762 | closeText: "", |
|
|||
1763 | close: function(event, ui) {$(this).dialog('destroy').remove();}, |
|
|||
1764 | buttons : { |
|
1742 | buttons : { | |
1765 |
|
|
1743 | OK : { | |
1766 |
|
|
1744 | class : "btn-danger" | |
1767 | } |
|
1745 | } | |
1768 |
} |
|
1746 | } | |
1769 | width: 400 |
|
|||
1770 | }); |
|
1747 | }); | |
1771 |
|
1748 | |||
1772 | } |
|
1749 | } | |
1773 |
|
1750 | |||
1774 | // Create the kernel after the notebook is completely loaded to prevent |
|
1751 | // Create the kernel after the notebook is completely loaded to prevent | |
1775 | // code execution upon loading, which is a security risk. |
|
1752 | // code execution upon loading, which is a security risk. | |
1776 | if (! this.read_only) { |
|
1753 | if (! this.read_only) { | |
1777 | this.start_kernel(); |
|
1754 | this.start_kernel(); | |
1778 | // load our checkpoint list |
|
1755 | // load our checkpoint list | |
1779 | IPython.notebook.list_checkpoints(); |
|
1756 | IPython.notebook.list_checkpoints(); | |
1780 | } |
|
1757 | } | |
1781 | $([IPython.events]).trigger('notebook_loaded.Notebook'); |
|
1758 | $([IPython.events]).trigger('notebook_loaded.Notebook'); | |
1782 | }; |
|
1759 | }; | |
1783 |
|
1760 | |||
1784 | /** |
|
1761 | /** | |
1785 | * Failure callback for loading a notebook from the server. |
|
1762 | * Failure callback for loading a notebook from the server. | |
1786 | * |
|
1763 | * | |
1787 | * @method load_notebook_error |
|
1764 | * @method load_notebook_error | |
1788 | * @param {jqXHR} xhr jQuery Ajax object |
|
1765 | * @param {jqXHR} xhr jQuery Ajax object | |
1789 | * @param {String} textStatus Description of response status |
|
1766 | * @param {String} textStatus Description of response status | |
1790 | * @param {String} errorThrow HTTP error message |
|
1767 | * @param {String} errorThrow HTTP error message | |
1791 | */ |
|
1768 | */ | |
1792 | Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) { |
|
1769 | Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) { | |
1793 | if (xhr.status === 500) { |
|
1770 | if (xhr.status === 500) { | |
1794 | var msg = "An error occurred while loading this notebook. Most likely " + |
|
1771 | var msg = "An error occurred while loading this notebook. Most likely " + | |
1795 | "this notebook is in a newer format than is supported by this " + |
|
1772 | "this notebook is in a newer format than is supported by this " + | |
1796 | "version of IPython. This version can load notebook formats " + |
|
1773 | "version of IPython. This version can load notebook formats " + | |
1797 | "v"+this.nbformat+" or earlier."; |
|
1774 | "v"+this.nbformat+" or earlier."; | |
1798 | var dialog = $('<div/>'); |
|
1775 | ||
1799 |
dialog. |
|
1776 | IPython.dialog.modal({ | |
1800 | this.element.append(dialog); |
|
|||
1801 | dialog.dialog({ |
|
|||
1802 | resizable: false, |
|
|||
1803 | modal: true, |
|
|||
1804 | title: "Error loading notebook", |
|
1777 | title: "Error loading notebook", | |
1805 |
|
|
1778 | body : msg, | |
1806 | close: function(event, ui) {$(this).dialog('destroy').remove();}, |
|
|||
1807 | buttons : { |
|
1779 | buttons : { | |
1808 |
"OK": |
|
1780 | "OK": {} | |
1809 | $(this).dialog('close'); |
|
1781 | } | |
1810 | } |
|
|||
1811 | }, |
|
|||
1812 | width: 400 |
|
|||
1813 | }); |
|
1782 | }); | |
1814 | } |
|
1783 | } | |
1815 | } |
|
1784 | } | |
1816 |
|
1785 | |||
1817 | /********************* checkpoint-related *********************/ |
|
1786 | /********************* checkpoint-related *********************/ | |
1818 |
|
1787 | |||
1819 | /** |
|
1788 | /** | |
1820 | * Save the notebook then immediately create a checkpoint. |
|
1789 | * Save the notebook then immediately create a checkpoint. | |
1821 | * |
|
1790 | * | |
1822 | * @method save_checkpoint |
|
1791 | * @method save_checkpoint | |
1823 | */ |
|
1792 | */ | |
1824 | Notebook.prototype.save_checkpoint = function () { |
|
1793 | Notebook.prototype.save_checkpoint = function () { | |
1825 | this._checkpoint_after_save = true; |
|
1794 | this._checkpoint_after_save = true; | |
1826 | this.save_notebook(); |
|
1795 | this.save_notebook(); | |
1827 | }; |
|
1796 | }; | |
1828 |
|
1797 | |||
1829 | /** |
|
1798 | /** | |
1830 | * List checkpoints for this notebook. |
|
1799 | * List checkpoints for this notebook. | |
1831 | * |
|
1800 | * | |
1832 | * @method list_checkpoint |
|
1801 | * @method list_checkpoint | |
1833 | */ |
|
1802 | */ | |
1834 | Notebook.prototype.list_checkpoints = function () { |
|
1803 | Notebook.prototype.list_checkpoints = function () { | |
1835 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints'; |
|
1804 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints'; | |
1836 | $.get(url).done( |
|
1805 | $.get(url).done( | |
1837 | $.proxy(this.list_checkpoints_success, this) |
|
1806 | $.proxy(this.list_checkpoints_success, this) | |
1838 | ).fail( |
|
1807 | ).fail( | |
1839 | $.proxy(this.list_checkpoints_error, this) |
|
1808 | $.proxy(this.list_checkpoints_error, this) | |
1840 | ); |
|
1809 | ); | |
1841 | }; |
|
1810 | }; | |
1842 |
|
1811 | |||
1843 | /** |
|
1812 | /** | |
1844 | * Success callback for listing checkpoints. |
|
1813 | * Success callback for listing checkpoints. | |
1845 | * |
|
1814 | * | |
1846 | * @method list_checkpoint_success |
|
1815 | * @method list_checkpoint_success | |
1847 | * @param {Object} data JSON representation of a checkpoint |
|
1816 | * @param {Object} data JSON representation of a checkpoint | |
1848 | * @param {String} status Description of response status |
|
1817 | * @param {String} status Description of response status | |
1849 | * @param {jqXHR} xhr jQuery Ajax object |
|
1818 | * @param {jqXHR} xhr jQuery Ajax object | |
1850 | */ |
|
1819 | */ | |
1851 | Notebook.prototype.list_checkpoints_success = function (data, status, xhr) { |
|
1820 | Notebook.prototype.list_checkpoints_success = function (data, status, xhr) { | |
1852 | var data = $.parseJSON(data); |
|
1821 | var data = $.parseJSON(data); | |
1853 | if (data.length) { |
|
1822 | if (data.length) { | |
1854 | this.last_checkpoint = data[0]; |
|
1823 | this.last_checkpoint = data[0]; | |
1855 | } else { |
|
1824 | } else { | |
1856 | this.last_checkpoint = null; |
|
1825 | this.last_checkpoint = null; | |
1857 | } |
|
1826 | } | |
1858 | $([IPython.events]).trigger('checkpoints_listed.Notebook', [data]); |
|
1827 | $([IPython.events]).trigger('checkpoints_listed.Notebook', [data]); | |
1859 | }; |
|
1828 | }; | |
1860 |
|
1829 | |||
1861 | /** |
|
1830 | /** | |
1862 | * Failure callback for listing a checkpoint. |
|
1831 | * Failure callback for listing a checkpoint. | |
1863 | * |
|
1832 | * | |
1864 | * @method list_checkpoint_error |
|
1833 | * @method list_checkpoint_error | |
1865 | * @param {jqXHR} xhr jQuery Ajax object |
|
1834 | * @param {jqXHR} xhr jQuery Ajax object | |
1866 | * @param {String} status Description of response status |
|
1835 | * @param {String} status Description of response status | |
1867 | * @param {String} error_msg HTTP error message |
|
1836 | * @param {String} error_msg HTTP error message | |
1868 | */ |
|
1837 | */ | |
1869 | Notebook.prototype.list_checkpoints_error = function (xhr, status, error_msg) { |
|
1838 | Notebook.prototype.list_checkpoints_error = function (xhr, status, error_msg) { | |
1870 | $([IPython.events]).trigger('list_checkpoints_failed.Notebook'); |
|
1839 | $([IPython.events]).trigger('list_checkpoints_failed.Notebook'); | |
1871 | }; |
|
1840 | }; | |
1872 |
|
1841 | |||
1873 | /** |
|
1842 | /** | |
1874 | * Create a checkpoint of this notebook on the server from the most recent save. |
|
1843 | * Create a checkpoint of this notebook on the server from the most recent save. | |
1875 | * |
|
1844 | * | |
1876 | * @method create_checkpoint |
|
1845 | * @method create_checkpoint | |
1877 | */ |
|
1846 | */ | |
1878 | Notebook.prototype.create_checkpoint = function () { |
|
1847 | Notebook.prototype.create_checkpoint = function () { | |
1879 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints'; |
|
1848 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints'; | |
1880 | $.post(url).done( |
|
1849 | $.post(url).done( | |
1881 | $.proxy(this.create_checkpoint_success, this) |
|
1850 | $.proxy(this.create_checkpoint_success, this) | |
1882 | ).fail( |
|
1851 | ).fail( | |
1883 | $.proxy(this.create_checkpoint_error, this) |
|
1852 | $.proxy(this.create_checkpoint_error, this) | |
1884 | ); |
|
1853 | ); | |
1885 | }; |
|
1854 | }; | |
1886 |
|
1855 | |||
1887 | /** |
|
1856 | /** | |
1888 | * Success callback for creating a checkpoint. |
|
1857 | * Success callback for creating a checkpoint. | |
1889 | * |
|
1858 | * | |
1890 | * @method create_checkpoint_success |
|
1859 | * @method create_checkpoint_success | |
1891 | * @param {Object} data JSON representation of a checkpoint |
|
1860 | * @param {Object} data JSON representation of a checkpoint | |
1892 | * @param {String} status Description of response status |
|
1861 | * @param {String} status Description of response status | |
1893 | * @param {jqXHR} xhr jQuery Ajax object |
|
1862 | * @param {jqXHR} xhr jQuery Ajax object | |
1894 | */ |
|
1863 | */ | |
1895 | Notebook.prototype.create_checkpoint_success = function (data, status, xhr) { |
|
1864 | Notebook.prototype.create_checkpoint_success = function (data, status, xhr) { | |
1896 | var data = $.parseJSON(data); |
|
1865 | var data = $.parseJSON(data); | |
1897 | this.last_checkpoint = data; |
|
1866 | this.last_checkpoint = data; | |
1898 | $([IPython.events]).trigger('checkpoint_created.Notebook', data); |
|
1867 | $([IPython.events]).trigger('checkpoint_created.Notebook', data); | |
1899 | }; |
|
1868 | }; | |
1900 |
|
1869 | |||
1901 | /** |
|
1870 | /** | |
1902 | * Failure callback for creating a checkpoint. |
|
1871 | * Failure callback for creating a checkpoint. | |
1903 | * |
|
1872 | * | |
1904 | * @method create_checkpoint_error |
|
1873 | * @method create_checkpoint_error | |
1905 | * @param {jqXHR} xhr jQuery Ajax object |
|
1874 | * @param {jqXHR} xhr jQuery Ajax object | |
1906 | * @param {String} status Description of response status |
|
1875 | * @param {String} status Description of response status | |
1907 | * @param {String} error_msg HTTP error message |
|
1876 | * @param {String} error_msg HTTP error message | |
1908 | */ |
|
1877 | */ | |
1909 | Notebook.prototype.create_checkpoint_error = function (xhr, status, error_msg) { |
|
1878 | Notebook.prototype.create_checkpoint_error = function (xhr, status, error_msg) { | |
1910 | $([IPython.events]).trigger('checkpoint_failed.Notebook'); |
|
1879 | $([IPython.events]).trigger('checkpoint_failed.Notebook'); | |
1911 | }; |
|
1880 | }; | |
1912 |
|
1881 | |||
1913 | Notebook.prototype.restore_checkpoint_dialog = function (checkpoint) { |
|
1882 | Notebook.prototype.restore_checkpoint_dialog = function (checkpoint) { | |
1914 | var that = this; |
|
1883 | var that = this; | |
1915 | var checkpoint = checkpoint || this.last_checkpoint; |
|
1884 | var checkpoint = checkpoint || this.last_checkpoint; | |
1916 | if ( ! checkpoint ) { |
|
1885 | if ( ! checkpoint ) { | |
1917 | console.log("restore dialog, but no checkpoint to restore to!"); |
|
1886 | console.log("restore dialog, but no checkpoint to restore to!"); | |
1918 | return; |
|
1887 | return; | |
1919 | } |
|
1888 | } | |
1920 |
var |
|
1889 | var body = $('<div/>').append( | |
1921 | $('<p/>').addClass("p-space").text( |
|
1890 | $('<p/>').addClass("p-space").text( | |
1922 | "Are you sure you want to revert the notebook to " + |
|
1891 | "Are you sure you want to revert the notebook to " + | |
1923 | "the latest checkpoint?" |
|
1892 | "the latest checkpoint?" | |
1924 | ).append( |
|
1893 | ).append( | |
1925 | $("<strong/>").text( |
|
1894 | $("<strong/>").text( | |
1926 | " This cannot be undone." |
|
1895 | " This cannot be undone." | |
1927 | ) |
|
1896 | ) | |
1928 | ) |
|
1897 | ) | |
1929 | ).append( |
|
1898 | ).append( | |
1930 | $('<p/>').addClass("p-space").text("The checkpoint was last updated at:") |
|
1899 | $('<p/>').addClass("p-space").text("The checkpoint was last updated at:") | |
1931 | ).append( |
|
1900 | ).append( | |
1932 | $('<p/>').addClass("p-space").text( |
|
1901 | $('<p/>').addClass("p-space").text( | |
1933 | Date(checkpoint.last_modified) |
|
1902 | Date(checkpoint.last_modified) | |
1934 | ).css("text-align", "center") |
|
1903 | ).css("text-align", "center") | |
1935 | ); |
|
1904 | ); | |
1936 |
|
1905 | |||
1937 | $(document).append(dialog); |
|
1906 | IPython.dialog.modal({ | |
1938 |
|
1907 | title : "Revert notebook to checkpoint", | ||
1939 | dialog.dialog({ |
|
1908 | body : body, | |
1940 | resizable: false, |
|
|||
1941 | modal: true, |
|
|||
1942 | title: "Revert notebook to checkpoint", |
|
|||
1943 | closeText: '', |
|
|||
1944 | buttons : { |
|
1909 | buttons : { | |
1945 |
|
|
1910 | Revert : { | |
1946 | that.restore_checkpoint(checkpoint.checkpoint_id); |
|
1911 | class : "btn-danger", | |
1947 | $(this).dialog('close'); |
|
1912 | click : function () { | |
|
1913 | that.restore_checkpoint(checkpoint.checkpoint_id); | |||
|
1914 | } | |||
1948 | }, |
|
1915 | }, | |
1949 |
|
|
1916 | Cancel : {} | |
1950 | $(this).dialog('close'); |
|
|||
1951 | } |
|
1917 | } | |
1952 | }, |
|
|||
1953 | width: 400 |
|
|||
1954 | }); |
|
1918 | }); | |
1955 | } |
|
1919 | } | |
1956 |
|
1920 | |||
1957 | /** |
|
1921 | /** | |
1958 | * Restore the notebook to a checkpoint state. |
|
1922 | * Restore the notebook to a checkpoint state. | |
1959 | * |
|
1923 | * | |
1960 | * @method restore_checkpoint |
|
1924 | * @method restore_checkpoint | |
1961 | * @param {String} checkpoint ID |
|
1925 | * @param {String} checkpoint ID | |
1962 | */ |
|
1926 | */ | |
1963 | Notebook.prototype.restore_checkpoint = function (checkpoint) { |
|
1927 | Notebook.prototype.restore_checkpoint = function (checkpoint) { | |
1964 | $([IPython.events]).trigger('notebook_restoring.Notebook', checkpoint); |
|
1928 | $([IPython.events]).trigger('notebook_restoring.Notebook', checkpoint); | |
1965 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints/' + checkpoint; |
|
1929 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints/' + checkpoint; | |
1966 | $.post(url).done( |
|
1930 | $.post(url).done( | |
1967 | $.proxy(this.restore_checkpoint_success, this) |
|
1931 | $.proxy(this.restore_checkpoint_success, this) | |
1968 | ).fail( |
|
1932 | ).fail( | |
1969 | $.proxy(this.restore_checkpoint_error, this) |
|
1933 | $.proxy(this.restore_checkpoint_error, this) | |
1970 | ); |
|
1934 | ); | |
1971 | }; |
|
1935 | }; | |
1972 |
|
1936 | |||
1973 | /** |
|
1937 | /** | |
1974 | * Success callback for restoring a notebook to a checkpoint. |
|
1938 | * Success callback for restoring a notebook to a checkpoint. | |
1975 | * |
|
1939 | * | |
1976 | * @method restore_checkpoint_success |
|
1940 | * @method restore_checkpoint_success | |
1977 | * @param {Object} data (ignored, should be empty) |
|
1941 | * @param {Object} data (ignored, should be empty) | |
1978 | * @param {String} status Description of response status |
|
1942 | * @param {String} status Description of response status | |
1979 | * @param {jqXHR} xhr jQuery Ajax object |
|
1943 | * @param {jqXHR} xhr jQuery Ajax object | |
1980 | */ |
|
1944 | */ | |
1981 | Notebook.prototype.restore_checkpoint_success = function (data, status, xhr) { |
|
1945 | Notebook.prototype.restore_checkpoint_success = function (data, status, xhr) { | |
1982 | $([IPython.events]).trigger('checkpoint_restored.Notebook'); |
|
1946 | $([IPython.events]).trigger('checkpoint_restored.Notebook'); | |
1983 | this.load_notebook(this.notebook_id); |
|
1947 | this.load_notebook(this.notebook_id); | |
1984 | }; |
|
1948 | }; | |
1985 |
|
1949 | |||
1986 | /** |
|
1950 | /** | |
1987 | * Failure callback for restoring a notebook to a checkpoint. |
|
1951 | * Failure callback for restoring a notebook to a checkpoint. | |
1988 | * |
|
1952 | * | |
1989 | * @method restore_checkpoint_error |
|
1953 | * @method restore_checkpoint_error | |
1990 | * @param {jqXHR} xhr jQuery Ajax object |
|
1954 | * @param {jqXHR} xhr jQuery Ajax object | |
1991 | * @param {String} status Description of response status |
|
1955 | * @param {String} status Description of response status | |
1992 | * @param {String} error_msg HTTP error message |
|
1956 | * @param {String} error_msg HTTP error message | |
1993 | */ |
|
1957 | */ | |
1994 | Notebook.prototype.restore_checkpoint_error = function (xhr, status, error_msg) { |
|
1958 | Notebook.prototype.restore_checkpoint_error = function (xhr, status, error_msg) { | |
1995 | $([IPython.events]).trigger('checkpoint_restore_failed.Notebook'); |
|
1959 | $([IPython.events]).trigger('checkpoint_restore_failed.Notebook'); | |
1996 | }; |
|
1960 | }; | |
1997 |
|
1961 | |||
1998 | /** |
|
1962 | /** | |
1999 | * Delete a notebook checkpoint. |
|
1963 | * Delete a notebook checkpoint. | |
2000 | * |
|
1964 | * | |
2001 | * @method delete_checkpoint |
|
1965 | * @method delete_checkpoint | |
2002 | * @param {String} checkpoint ID |
|
1966 | * @param {String} checkpoint ID | |
2003 | */ |
|
1967 | */ | |
2004 | Notebook.prototype.delete_checkpoint = function (checkpoint) { |
|
1968 | Notebook.prototype.delete_checkpoint = function (checkpoint) { | |
2005 | $([IPython.events]).trigger('notebook_restoring.Notebook', checkpoint); |
|
1969 | $([IPython.events]).trigger('notebook_restoring.Notebook', checkpoint); | |
2006 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints/' + checkpoint; |
|
1970 | var url = this.baseProjectUrl() + 'notebooks/' + this.notebook_id + '/checkpoints/' + checkpoint; | |
2007 | $.ajax(url, { |
|
1971 | $.ajax(url, { | |
2008 | type: 'DELETE', |
|
1972 | type: 'DELETE', | |
2009 | success: $.proxy(this.delete_checkpoint_success, this), |
|
1973 | success: $.proxy(this.delete_checkpoint_success, this), | |
2010 | error: $.proxy(this.delete_notebook_error,this) |
|
1974 | error: $.proxy(this.delete_notebook_error,this) | |
2011 | }); |
|
1975 | }); | |
2012 | }; |
|
1976 | }; | |
2013 |
|
1977 | |||
2014 | /** |
|
1978 | /** | |
2015 | * Success callback for deleting a notebook checkpoint |
|
1979 | * Success callback for deleting a notebook checkpoint | |
2016 | * |
|
1980 | * | |
2017 | * @method delete_checkpoint_success |
|
1981 | * @method delete_checkpoint_success | |
2018 | * @param {Object} data (ignored, should be empty) |
|
1982 | * @param {Object} data (ignored, should be empty) | |
2019 | * @param {String} status Description of response status |
|
1983 | * @param {String} status Description of response status | |
2020 | * @param {jqXHR} xhr jQuery Ajax object |
|
1984 | * @param {jqXHR} xhr jQuery Ajax object | |
2021 | */ |
|
1985 | */ | |
2022 | Notebook.prototype.delete_checkpoint_success = function (data, status, xhr) { |
|
1986 | Notebook.prototype.delete_checkpoint_success = function (data, status, xhr) { | |
2023 | $([IPython.events]).trigger('checkpoint_deleted.Notebook', data); |
|
1987 | $([IPython.events]).trigger('checkpoint_deleted.Notebook', data); | |
2024 | this.load_notebook(this.notebook_id); |
|
1988 | this.load_notebook(this.notebook_id); | |
2025 | }; |
|
1989 | }; | |
2026 |
|
1990 | |||
2027 | /** |
|
1991 | /** | |
2028 | * Failure callback for deleting a notebook checkpoint. |
|
1992 | * Failure callback for deleting a notebook checkpoint. | |
2029 | * |
|
1993 | * | |
2030 | * @method delete_checkpoint_error |
|
1994 | * @method delete_checkpoint_error | |
2031 | * @param {jqXHR} xhr jQuery Ajax object |
|
1995 | * @param {jqXHR} xhr jQuery Ajax object | |
2032 | * @param {String} status Description of response status |
|
1996 | * @param {String} status Description of response status | |
2033 | * @param {String} error_msg HTTP error message |
|
1997 | * @param {String} error_msg HTTP error message | |
2034 | */ |
|
1998 | */ | |
2035 | Notebook.prototype.delete_checkpoint_error = function (xhr, status, error_msg) { |
|
1999 | Notebook.prototype.delete_checkpoint_error = function (xhr, status, error_msg) { | |
2036 | $([IPython.events]).trigger('checkpoint_delete_failed.Notebook'); |
|
2000 | $([IPython.events]).trigger('checkpoint_delete_failed.Notebook'); | |
2037 | }; |
|
2001 | }; | |
2038 |
|
2002 | |||
2039 |
|
2003 | |||
2040 | IPython.Notebook = Notebook; |
|
2004 | IPython.Notebook = Notebook; | |
2041 |
|
2005 | |||
2042 |
|
2006 | |||
2043 | return IPython; |
|
2007 | return IPython; | |
2044 |
|
2008 | |||
2045 | }(IPython)); |
|
2009 | }(IPython)); | |
2046 |
|
2010 |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed, binary diff hidden |
|
NO CONTENT: file was removed, binary diff hidden |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now