##// END OF EJS Templates
Merge pull request #7263 from takluyver/nb-common-config...
Min RK -
r20023:982ae339 merge
parent child Browse files
Show More
@@ -1,866 +1,884 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 define([
4 define([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'codemirror/lib/codemirror',
7 'codemirror/lib/codemirror',
8 'moment',
8 'moment',
9 // silently upgrades CodeMirror
9 // silently upgrades CodeMirror
10 'codemirror/mode/meta',
10 'codemirror/mode/meta',
11 ], function(IPython, $, CodeMirror, moment){
11 ], function(IPython, $, CodeMirror, moment){
12 "use strict";
12 "use strict";
13
13
14 IPython.load_extensions = function () {
14 var load_extensions = function () {
15 // load one or more IPython notebook extensions with requirejs
15 // load one or more IPython notebook extensions with requirejs
16
16
17 var extensions = [];
17 var extensions = [];
18 var extension_names = arguments;
18 var extension_names = arguments;
19 for (var i = 0; i < extension_names.length; i++) {
19 for (var i = 0; i < extension_names.length; i++) {
20 extensions.push("nbextensions/" + arguments[i]);
20 extensions.push("nbextensions/" + arguments[i]);
21 }
21 }
22
22
23 require(extensions,
23 require(extensions,
24 function () {
24 function () {
25 for (var i = 0; i < arguments.length; i++) {
25 for (var i = 0; i < arguments.length; i++) {
26 var ext = arguments[i];
26 var ext = arguments[i];
27 var ext_name = extension_names[i];
27 var ext_name = extension_names[i];
28 // success callback
28 // success callback
29 console.log("Loaded extension: " + ext_name);
29 console.log("Loaded extension: " + ext_name);
30 if (ext && ext.load_ipython_extension !== undefined) {
30 if (ext && ext.load_ipython_extension !== undefined) {
31 ext.load_ipython_extension();
31 ext.load_ipython_extension();
32 }
32 }
33 }
33 }
34 },
34 },
35 function (err) {
35 function (err) {
36 // failure callback
36 // failure callback
37 console.log("Failed to load extension(s):", err.requireModules, err);
37 console.log("Failed to load extension(s):", err.requireModules, err);
38 }
38 }
39 );
39 );
40 };
40 };
41
42 IPython.load_extensions = load_extensions;
43
44 /**
45 * Wait for a config section to load, and then load the extensions specified
46 * in a 'load_extensions' key inside it.
47 */
48 function load_extensions_from_config(section) {
49 section.loaded.then(function() {
50 if (section.data.load_extensions) {
51 var nbextension_paths = Object.getOwnPropertyNames(
52 section.data.load_extensions);
53 load_extensions.apply(this, nbextension_paths);
54 }
55 });
56 }
41
57
42 //============================================================================
58 //============================================================================
43 // Cross-browser RegEx Split
59 // Cross-browser RegEx Split
44 //============================================================================
60 //============================================================================
45
61
46 // This code has been MODIFIED from the code licensed below to not replace the
62 // This code has been MODIFIED from the code licensed below to not replace the
47 // default browser split. The license is reproduced here.
63 // default browser split. The license is reproduced here.
48
64
49 // see http://blog.stevenlevithan.com/archives/cross-browser-split for more info:
65 // see http://blog.stevenlevithan.com/archives/cross-browser-split for more info:
50 /*!
66 /*!
51 * Cross-Browser Split 1.1.1
67 * Cross-Browser Split 1.1.1
52 * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
68 * Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
53 * Available under the MIT License
69 * Available under the MIT License
54 * ECMAScript compliant, uniform cross-browser split method
70 * ECMAScript compliant, uniform cross-browser split method
55 */
71 */
56
72
57 /**
73 /**
58 * Splits a string into an array of strings using a regex or string
74 * Splits a string into an array of strings using a regex or string
59 * separator. Matches of the separator are not included in the result array.
75 * separator. Matches of the separator are not included in the result array.
60 * However, if `separator` is a regex that contains capturing groups,
76 * However, if `separator` is a regex that contains capturing groups,
61 * backreferences are spliced into the result each time `separator` is
77 * backreferences are spliced into the result each time `separator` is
62 * matched. Fixes browser bugs compared to the native
78 * matched. Fixes browser bugs compared to the native
63 * `String.prototype.split` and can be used reliably cross-browser.
79 * `String.prototype.split` and can be used reliably cross-browser.
64 * @param {String} str String to split.
80 * @param {String} str String to split.
65 * @param {RegExp} separator Regex to use for separating
81 * @param {RegExp} separator Regex to use for separating
66 * the string.
82 * the string.
67 * @param {Number} [limit] Maximum number of items to include in the result
83 * @param {Number} [limit] Maximum number of items to include in the result
68 * array.
84 * array.
69 * @returns {Array} Array of substrings.
85 * @returns {Array} Array of substrings.
70 * @example
86 * @example
71 *
87 *
72 * // Basic use
88 * // Basic use
73 * regex_split('a b c d', ' ');
89 * regex_split('a b c d', ' ');
74 * // -> ['a', 'b', 'c', 'd']
90 * // -> ['a', 'b', 'c', 'd']
75 *
91 *
76 * // With limit
92 * // With limit
77 * regex_split('a b c d', ' ', 2);
93 * regex_split('a b c d', ' ', 2);
78 * // -> ['a', 'b']
94 * // -> ['a', 'b']
79 *
95 *
80 * // Backreferences in result array
96 * // Backreferences in result array
81 * regex_split('..word1 word2..', /([a-z]+)(\d+)/i);
97 * regex_split('..word1 word2..', /([a-z]+)(\d+)/i);
82 * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
98 * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
83 */
99 */
84 var regex_split = function (str, separator, limit) {
100 var regex_split = function (str, separator, limit) {
85 var output = [],
101 var output = [],
86 flags = (separator.ignoreCase ? "i" : "") +
102 flags = (separator.ignoreCase ? "i" : "") +
87 (separator.multiline ? "m" : "") +
103 (separator.multiline ? "m" : "") +
88 (separator.extended ? "x" : "") + // Proposed for ES6
104 (separator.extended ? "x" : "") + // Proposed for ES6
89 (separator.sticky ? "y" : ""), // Firefox 3+
105 (separator.sticky ? "y" : ""), // Firefox 3+
90 lastLastIndex = 0,
106 lastLastIndex = 0,
91 separator2, match, lastIndex, lastLength;
107 separator2, match, lastIndex, lastLength;
92 // Make `global` and avoid `lastIndex` issues by working with a copy
108 // Make `global` and avoid `lastIndex` issues by working with a copy
93 separator = new RegExp(separator.source, flags + "g");
109 separator = new RegExp(separator.source, flags + "g");
94
110
95 var compliantExecNpcg = typeof(/()??/.exec("")[1]) === "undefined";
111 var compliantExecNpcg = typeof(/()??/.exec("")[1]) === "undefined";
96 if (!compliantExecNpcg) {
112 if (!compliantExecNpcg) {
97 // Doesn't need flags gy, but they don't hurt
113 // Doesn't need flags gy, but they don't hurt
98 separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
114 separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
99 }
115 }
100 /* Values for `limit`, per the spec:
116 /* Values for `limit`, per the spec:
101 * If undefined: 4294967295 // Math.pow(2, 32) - 1
117 * If undefined: 4294967295 // Math.pow(2, 32) - 1
102 * If 0, Infinity, or NaN: 0
118 * If 0, Infinity, or NaN: 0
103 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
119 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
104 * If negative number: 4294967296 - Math.floor(Math.abs(limit))
120 * If negative number: 4294967296 - Math.floor(Math.abs(limit))
105 * If other: Type-convert, then use the above rules
121 * If other: Type-convert, then use the above rules
106 */
122 */
107 limit = typeof(limit) === "undefined" ?
123 limit = typeof(limit) === "undefined" ?
108 -1 >>> 0 : // Math.pow(2, 32) - 1
124 -1 >>> 0 : // Math.pow(2, 32) - 1
109 limit >>> 0; // ToUint32(limit)
125 limit >>> 0; // ToUint32(limit)
110 for (match = separator.exec(str); match; match = separator.exec(str)) {
126 for (match = separator.exec(str); match; match = separator.exec(str)) {
111 // `separator.lastIndex` is not reliable cross-browser
127 // `separator.lastIndex` is not reliable cross-browser
112 lastIndex = match.index + match[0].length;
128 lastIndex = match.index + match[0].length;
113 if (lastIndex > lastLastIndex) {
129 if (lastIndex > lastLastIndex) {
114 output.push(str.slice(lastLastIndex, match.index));
130 output.push(str.slice(lastLastIndex, match.index));
115 // Fix browsers whose `exec` methods don't consistently return `undefined` for
131 // Fix browsers whose `exec` methods don't consistently return `undefined` for
116 // nonparticipating capturing groups
132 // nonparticipating capturing groups
117 if (!compliantExecNpcg && match.length > 1) {
133 if (!compliantExecNpcg && match.length > 1) {
118 match[0].replace(separator2, function () {
134 match[0].replace(separator2, function () {
119 for (var i = 1; i < arguments.length - 2; i++) {
135 for (var i = 1; i < arguments.length - 2; i++) {
120 if (typeof(arguments[i]) === "undefined") {
136 if (typeof(arguments[i]) === "undefined") {
121 match[i] = undefined;
137 match[i] = undefined;
122 }
138 }
123 }
139 }
124 });
140 });
125 }
141 }
126 if (match.length > 1 && match.index < str.length) {
142 if (match.length > 1 && match.index < str.length) {
127 Array.prototype.push.apply(output, match.slice(1));
143 Array.prototype.push.apply(output, match.slice(1));
128 }
144 }
129 lastLength = match[0].length;
145 lastLength = match[0].length;
130 lastLastIndex = lastIndex;
146 lastLastIndex = lastIndex;
131 if (output.length >= limit) {
147 if (output.length >= limit) {
132 break;
148 break;
133 }
149 }
134 }
150 }
135 if (separator.lastIndex === match.index) {
151 if (separator.lastIndex === match.index) {
136 separator.lastIndex++; // Avoid an infinite loop
152 separator.lastIndex++; // Avoid an infinite loop
137 }
153 }
138 }
154 }
139 if (lastLastIndex === str.length) {
155 if (lastLastIndex === str.length) {
140 if (lastLength || !separator.test("")) {
156 if (lastLength || !separator.test("")) {
141 output.push("");
157 output.push("");
142 }
158 }
143 } else {
159 } else {
144 output.push(str.slice(lastLastIndex));
160 output.push(str.slice(lastLastIndex));
145 }
161 }
146 return output.length > limit ? output.slice(0, limit) : output;
162 return output.length > limit ? output.slice(0, limit) : output;
147 };
163 };
148
164
149 //============================================================================
165 //============================================================================
150 // End contributed Cross-browser RegEx Split
166 // End contributed Cross-browser RegEx Split
151 //============================================================================
167 //============================================================================
152
168
153
169
154 var uuid = function () {
170 var uuid = function () {
155 /**
171 /**
156 * http://www.ietf.org/rfc/rfc4122.txt
172 * http://www.ietf.org/rfc/rfc4122.txt
157 */
173 */
158 var s = [];
174 var s = [];
159 var hexDigits = "0123456789ABCDEF";
175 var hexDigits = "0123456789ABCDEF";
160 for (var i = 0; i < 32; i++) {
176 for (var i = 0; i < 32; i++) {
161 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
177 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
162 }
178 }
163 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
179 s[12] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
164 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
180 s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
165
181
166 var uuid = s.join("");
182 var uuid = s.join("");
167 return uuid;
183 return uuid;
168 };
184 };
169
185
170
186
171 //Fix raw text to parse correctly in crazy XML
187 //Fix raw text to parse correctly in crazy XML
172 function xmlencode(string) {
188 function xmlencode(string) {
173 return string.replace(/\&/g,'&'+'amp;')
189 return string.replace(/\&/g,'&'+'amp;')
174 .replace(/</g,'&'+'lt;')
190 .replace(/</g,'&'+'lt;')
175 .replace(/>/g,'&'+'gt;')
191 .replace(/>/g,'&'+'gt;')
176 .replace(/\'/g,'&'+'apos;')
192 .replace(/\'/g,'&'+'apos;')
177 .replace(/\"/g,'&'+'quot;')
193 .replace(/\"/g,'&'+'quot;')
178 .replace(/`/g,'&'+'#96;');
194 .replace(/`/g,'&'+'#96;');
179 }
195 }
180
196
181
197
182 //Map from terminal commands to CSS classes
198 //Map from terminal commands to CSS classes
183 var ansi_colormap = {
199 var ansi_colormap = {
184 "01":"ansibold",
200 "01":"ansibold",
185
201
186 "30":"ansiblack",
202 "30":"ansiblack",
187 "31":"ansired",
203 "31":"ansired",
188 "32":"ansigreen",
204 "32":"ansigreen",
189 "33":"ansiyellow",
205 "33":"ansiyellow",
190 "34":"ansiblue",
206 "34":"ansiblue",
191 "35":"ansipurple",
207 "35":"ansipurple",
192 "36":"ansicyan",
208 "36":"ansicyan",
193 "37":"ansigray",
209 "37":"ansigray",
194
210
195 "40":"ansibgblack",
211 "40":"ansibgblack",
196 "41":"ansibgred",
212 "41":"ansibgred",
197 "42":"ansibggreen",
213 "42":"ansibggreen",
198 "43":"ansibgyellow",
214 "43":"ansibgyellow",
199 "44":"ansibgblue",
215 "44":"ansibgblue",
200 "45":"ansibgpurple",
216 "45":"ansibgpurple",
201 "46":"ansibgcyan",
217 "46":"ansibgcyan",
202 "47":"ansibggray"
218 "47":"ansibggray"
203 };
219 };
204
220
205 function _process_numbers(attrs, numbers) {
221 function _process_numbers(attrs, numbers) {
206 // process ansi escapes
222 // process ansi escapes
207 var n = numbers.shift();
223 var n = numbers.shift();
208 if (ansi_colormap[n]) {
224 if (ansi_colormap[n]) {
209 if ( ! attrs["class"] ) {
225 if ( ! attrs["class"] ) {
210 attrs["class"] = ansi_colormap[n];
226 attrs["class"] = ansi_colormap[n];
211 } else {
227 } else {
212 attrs["class"] += " " + ansi_colormap[n];
228 attrs["class"] += " " + ansi_colormap[n];
213 }
229 }
214 } else if (n == "38" || n == "48") {
230 } else if (n == "38" || n == "48") {
215 // VT100 256 color or 24 bit RGB
231 // VT100 256 color or 24 bit RGB
216 if (numbers.length < 2) {
232 if (numbers.length < 2) {
217 console.log("Not enough fields for VT100 color", numbers);
233 console.log("Not enough fields for VT100 color", numbers);
218 return;
234 return;
219 }
235 }
220
236
221 var index_or_rgb = numbers.shift();
237 var index_or_rgb = numbers.shift();
222 var r,g,b;
238 var r,g,b;
223 if (index_or_rgb == "5") {
239 if (index_or_rgb == "5") {
224 // 256 color
240 // 256 color
225 var idx = parseInt(numbers.shift(), 10);
241 var idx = parseInt(numbers.shift(), 10);
226 if (idx < 16) {
242 if (idx < 16) {
227 // indexed ANSI
243 // indexed ANSI
228 // ignore bright / non-bright distinction
244 // ignore bright / non-bright distinction
229 idx = idx % 8;
245 idx = idx % 8;
230 var ansiclass = ansi_colormap[n[0] + (idx % 8).toString()];
246 var ansiclass = ansi_colormap[n[0] + (idx % 8).toString()];
231 if ( ! attrs["class"] ) {
247 if ( ! attrs["class"] ) {
232 attrs["class"] = ansiclass;
248 attrs["class"] = ansiclass;
233 } else {
249 } else {
234 attrs["class"] += " " + ansiclass;
250 attrs["class"] += " " + ansiclass;
235 }
251 }
236 return;
252 return;
237 } else if (idx < 232) {
253 } else if (idx < 232) {
238 // 216 color 6x6x6 RGB
254 // 216 color 6x6x6 RGB
239 idx = idx - 16;
255 idx = idx - 16;
240 b = idx % 6;
256 b = idx % 6;
241 g = Math.floor(idx / 6) % 6;
257 g = Math.floor(idx / 6) % 6;
242 r = Math.floor(idx / 36) % 6;
258 r = Math.floor(idx / 36) % 6;
243 // convert to rgb
259 // convert to rgb
244 r = (r * 51);
260 r = (r * 51);
245 g = (g * 51);
261 g = (g * 51);
246 b = (b * 51);
262 b = (b * 51);
247 } else {
263 } else {
248 // grayscale
264 // grayscale
249 idx = idx - 231;
265 idx = idx - 231;
250 // it's 1-24 and should *not* include black or white,
266 // it's 1-24 and should *not* include black or white,
251 // so a 26 point scale
267 // so a 26 point scale
252 r = g = b = Math.floor(idx * 256 / 26);
268 r = g = b = Math.floor(idx * 256 / 26);
253 }
269 }
254 } else if (index_or_rgb == "2") {
270 } else if (index_or_rgb == "2") {
255 // Simple 24 bit RGB
271 // Simple 24 bit RGB
256 if (numbers.length > 3) {
272 if (numbers.length > 3) {
257 console.log("Not enough fields for RGB", numbers);
273 console.log("Not enough fields for RGB", numbers);
258 return;
274 return;
259 }
275 }
260 r = numbers.shift();
276 r = numbers.shift();
261 g = numbers.shift();
277 g = numbers.shift();
262 b = numbers.shift();
278 b = numbers.shift();
263 } else {
279 } else {
264 console.log("unrecognized control", numbers);
280 console.log("unrecognized control", numbers);
265 return;
281 return;
266 }
282 }
267 if (r !== undefined) {
283 if (r !== undefined) {
268 // apply the rgb color
284 // apply the rgb color
269 var line;
285 var line;
270 if (n == "38") {
286 if (n == "38") {
271 line = "color: ";
287 line = "color: ";
272 } else {
288 } else {
273 line = "background-color: ";
289 line = "background-color: ";
274 }
290 }
275 line = line + "rgb(" + r + "," + g + "," + b + ");";
291 line = line + "rgb(" + r + "," + g + "," + b + ");";
276 if ( !attrs.style ) {
292 if ( !attrs.style ) {
277 attrs.style = line;
293 attrs.style = line;
278 } else {
294 } else {
279 attrs.style += " " + line;
295 attrs.style += " " + line;
280 }
296 }
281 }
297 }
282 }
298 }
283 }
299 }
284
300
285 function ansispan(str) {
301 function ansispan(str) {
286 // ansispan function adapted from github.com/mmalecki/ansispan (MIT License)
302 // ansispan function adapted from github.com/mmalecki/ansispan (MIT License)
287 // regular ansi escapes (using the table above)
303 // regular ansi escapes (using the table above)
288 var is_open = false;
304 var is_open = false;
289 return str.replace(/\033\[(0?[01]|22|39)?([;\d]+)?m/g, function(match, prefix, pattern) {
305 return str.replace(/\033\[(0?[01]|22|39)?([;\d]+)?m/g, function(match, prefix, pattern) {
290 if (!pattern) {
306 if (!pattern) {
291 // [(01|22|39|)m close spans
307 // [(01|22|39|)m close spans
292 if (is_open) {
308 if (is_open) {
293 is_open = false;
309 is_open = false;
294 return "</span>";
310 return "</span>";
295 } else {
311 } else {
296 return "";
312 return "";
297 }
313 }
298 } else {
314 } else {
299 is_open = true;
315 is_open = true;
300
316
301 // consume sequence of color escapes
317 // consume sequence of color escapes
302 var numbers = pattern.match(/\d+/g);
318 var numbers = pattern.match(/\d+/g);
303 var attrs = {};
319 var attrs = {};
304 while (numbers.length > 0) {
320 while (numbers.length > 0) {
305 _process_numbers(attrs, numbers);
321 _process_numbers(attrs, numbers);
306 }
322 }
307
323
308 var span = "<span ";
324 var span = "<span ";
309 Object.keys(attrs).map(function (attr) {
325 Object.keys(attrs).map(function (attr) {
310 span = span + " " + attr + '="' + attrs[attr] + '"';
326 span = span + " " + attr + '="' + attrs[attr] + '"';
311 });
327 });
312 return span + ">";
328 return span + ">";
313 }
329 }
314 });
330 });
315 }
331 }
316
332
317 // Transform ANSI color escape codes into HTML <span> tags with css
333 // Transform ANSI color escape codes into HTML <span> tags with css
318 // classes listed in the above ansi_colormap object. The actual color used
334 // classes listed in the above ansi_colormap object. The actual color used
319 // are set in the css file.
335 // are set in the css file.
320 function fixConsole(txt) {
336 function fixConsole(txt) {
321 txt = xmlencode(txt);
337 txt = xmlencode(txt);
322
338
323 // Strip all ANSI codes that are not color related. Matches
339 // Strip all ANSI codes that are not color related. Matches
324 // all ANSI codes that do not end with "m".
340 // all ANSI codes that do not end with "m".
325 var ignored_re = /(?=(\033\[[\d;=]*[a-ln-zA-Z]{1}))\1(?!m)/g;
341 var ignored_re = /(?=(\033\[[\d;=]*[a-ln-zA-Z]{1}))\1(?!m)/g;
326 txt = txt.replace(ignored_re, "");
342 txt = txt.replace(ignored_re, "");
327
343
328 // color ansi codes
344 // color ansi codes
329 txt = ansispan(txt);
345 txt = ansispan(txt);
330 return txt;
346 return txt;
331 }
347 }
332
348
333 // Remove chunks that should be overridden by the effect of
349 // Remove chunks that should be overridden by the effect of
334 // carriage return characters
350 // carriage return characters
335 function fixCarriageReturn(txt) {
351 function fixCarriageReturn(txt) {
336 var tmp = txt;
352 var tmp = txt;
337 do {
353 do {
338 txt = tmp;
354 txt = tmp;
339 tmp = txt.replace(/\r+\n/gm, '\n'); // \r followed by \n --> newline
355 tmp = txt.replace(/\r+\n/gm, '\n'); // \r followed by \n --> newline
340 tmp = tmp.replace(/^.*\r+/gm, ''); // Other \r --> clear line
356 tmp = tmp.replace(/^.*\r+/gm, ''); // Other \r --> clear line
341 } while (tmp.length < txt.length);
357 } while (tmp.length < txt.length);
342 return txt;
358 return txt;
343 }
359 }
344
360
345 // Locate any URLs and convert them to a anchor tag
361 // Locate any URLs and convert them to a anchor tag
346 function autoLinkUrls(txt) {
362 function autoLinkUrls(txt) {
347 return txt.replace(/(^|\s)(https?|ftp)(:[^'">\s]+)/gi,
363 return txt.replace(/(^|\s)(https?|ftp)(:[^'">\s]+)/gi,
348 "$1<a target=\"_blank\" href=\"$2$3\">$2$3</a>");
364 "$1<a target=\"_blank\" href=\"$2$3\">$2$3</a>");
349 }
365 }
350
366
351 var points_to_pixels = function (points) {
367 var points_to_pixels = function (points) {
352 /**
368 /**
353 * A reasonably good way of converting between points and pixels.
369 * A reasonably good way of converting between points and pixels.
354 */
370 */
355 var test = $('<div style="display: none; width: 10000pt; padding:0; border:0;"></div>');
371 var test = $('<div style="display: none; width: 10000pt; padding:0; border:0;"></div>');
356 $('body').append(test);
372 $('body').append(test);
357 var pixel_per_point = test.width()/10000;
373 var pixel_per_point = test.width()/10000;
358 test.remove();
374 test.remove();
359 return Math.floor(points*pixel_per_point);
375 return Math.floor(points*pixel_per_point);
360 };
376 };
361
377
362 var always_new = function (constructor) {
378 var always_new = function (constructor) {
363 /**
379 /**
364 * wrapper around contructor to avoid requiring `var a = new constructor()`
380 * wrapper around contructor to avoid requiring `var a = new constructor()`
365 * useful for passing constructors as callbacks,
381 * useful for passing constructors as callbacks,
366 * not for programmer laziness.
382 * not for programmer laziness.
367 * from http://programmers.stackexchange.com/questions/118798
383 * from http://programmers.stackexchange.com/questions/118798
368 */
384 */
369 return function () {
385 return function () {
370 var obj = Object.create(constructor.prototype);
386 var obj = Object.create(constructor.prototype);
371 constructor.apply(obj, arguments);
387 constructor.apply(obj, arguments);
372 return obj;
388 return obj;
373 };
389 };
374 };
390 };
375
391
376 var url_path_join = function () {
392 var url_path_join = function () {
377 /**
393 /**
378 * join a sequence of url components with '/'
394 * join a sequence of url components with '/'
379 */
395 */
380 var url = '';
396 var url = '';
381 for (var i = 0; i < arguments.length; i++) {
397 for (var i = 0; i < arguments.length; i++) {
382 if (arguments[i] === '') {
398 if (arguments[i] === '') {
383 continue;
399 continue;
384 }
400 }
385 if (url.length > 0 && url[url.length-1] != '/') {
401 if (url.length > 0 && url[url.length-1] != '/') {
386 url = url + '/' + arguments[i];
402 url = url + '/' + arguments[i];
387 } else {
403 } else {
388 url = url + arguments[i];
404 url = url + arguments[i];
389 }
405 }
390 }
406 }
391 url = url.replace(/\/\/+/, '/');
407 url = url.replace(/\/\/+/, '/');
392 return url;
408 return url;
393 };
409 };
394
410
395 var url_path_split = function (path) {
411 var url_path_split = function (path) {
396 /**
412 /**
397 * Like os.path.split for URLs.
413 * Like os.path.split for URLs.
398 * Always returns two strings, the directory path and the base filename
414 * Always returns two strings, the directory path and the base filename
399 */
415 */
400
416
401 var idx = path.lastIndexOf('/');
417 var idx = path.lastIndexOf('/');
402 if (idx === -1) {
418 if (idx === -1) {
403 return ['', path];
419 return ['', path];
404 } else {
420 } else {
405 return [ path.slice(0, idx), path.slice(idx + 1) ];
421 return [ path.slice(0, idx), path.slice(idx + 1) ];
406 }
422 }
407 };
423 };
408
424
409 var parse_url = function (url) {
425 var parse_url = function (url) {
410 /**
426 /**
411 * an `a` element with an href allows attr-access to the parsed segments of a URL
427 * an `a` element with an href allows attr-access to the parsed segments of a URL
412 * a = parse_url("http://localhost:8888/path/name#hash")
428 * a = parse_url("http://localhost:8888/path/name#hash")
413 * a.protocol = "http:"
429 * a.protocol = "http:"
414 * a.host = "localhost:8888"
430 * a.host = "localhost:8888"
415 * a.hostname = "localhost"
431 * a.hostname = "localhost"
416 * a.port = 8888
432 * a.port = 8888
417 * a.pathname = "/path/name"
433 * a.pathname = "/path/name"
418 * a.hash = "#hash"
434 * a.hash = "#hash"
419 */
435 */
420 var a = document.createElement("a");
436 var a = document.createElement("a");
421 a.href = url;
437 a.href = url;
422 return a;
438 return a;
423 };
439 };
424
440
425 var encode_uri_components = function (uri) {
441 var encode_uri_components = function (uri) {
426 /**
442 /**
427 * encode just the components of a multi-segment uri,
443 * encode just the components of a multi-segment uri,
428 * leaving '/' separators
444 * leaving '/' separators
429 */
445 */
430 return uri.split('/').map(encodeURIComponent).join('/');
446 return uri.split('/').map(encodeURIComponent).join('/');
431 };
447 };
432
448
433 var url_join_encode = function () {
449 var url_join_encode = function () {
434 /**
450 /**
435 * join a sequence of url components with '/',
451 * join a sequence of url components with '/',
436 * encoding each component with encodeURIComponent
452 * encoding each component with encodeURIComponent
437 */
453 */
438 return encode_uri_components(url_path_join.apply(null, arguments));
454 return encode_uri_components(url_path_join.apply(null, arguments));
439 };
455 };
440
456
441
457
442 var splitext = function (filename) {
458 var splitext = function (filename) {
443 /**
459 /**
444 * mimic Python os.path.splitext
460 * mimic Python os.path.splitext
445 * Returns ['base', '.ext']
461 * Returns ['base', '.ext']
446 */
462 */
447 var idx = filename.lastIndexOf('.');
463 var idx = filename.lastIndexOf('.');
448 if (idx > 0) {
464 if (idx > 0) {
449 return [filename.slice(0, idx), filename.slice(idx)];
465 return [filename.slice(0, idx), filename.slice(idx)];
450 } else {
466 } else {
451 return [filename, ''];
467 return [filename, ''];
452 }
468 }
453 };
469 };
454
470
455
471
456 var escape_html = function (text) {
472 var escape_html = function (text) {
457 /**
473 /**
458 * escape text to HTML
474 * escape text to HTML
459 */
475 */
460 return $("<div/>").text(text).html();
476 return $("<div/>").text(text).html();
461 };
477 };
462
478
463
479
464 var get_body_data = function(key) {
480 var get_body_data = function(key) {
465 /**
481 /**
466 * get a url-encoded item from body.data and decode it
482 * get a url-encoded item from body.data and decode it
467 * we should never have any encoded URLs anywhere else in code
483 * we should never have any encoded URLs anywhere else in code
468 * until we are building an actual request
484 * until we are building an actual request
469 */
485 */
470 return decodeURIComponent($('body').data(key));
486 return decodeURIComponent($('body').data(key));
471 };
487 };
472
488
473 var to_absolute_cursor_pos = function (cm, cursor) {
489 var to_absolute_cursor_pos = function (cm, cursor) {
474 /**
490 /**
475 * get the absolute cursor position from CodeMirror's col, ch
491 * get the absolute cursor position from CodeMirror's col, ch
476 */
492 */
477 if (!cursor) {
493 if (!cursor) {
478 cursor = cm.getCursor();
494 cursor = cm.getCursor();
479 }
495 }
480 var cursor_pos = cursor.ch;
496 var cursor_pos = cursor.ch;
481 for (var i = 0; i < cursor.line; i++) {
497 for (var i = 0; i < cursor.line; i++) {
482 cursor_pos += cm.getLine(i).length + 1;
498 cursor_pos += cm.getLine(i).length + 1;
483 }
499 }
484 return cursor_pos;
500 return cursor_pos;
485 };
501 };
486
502
487 var from_absolute_cursor_pos = function (cm, cursor_pos) {
503 var from_absolute_cursor_pos = function (cm, cursor_pos) {
488 /**
504 /**
489 * turn absolute cursor postion into CodeMirror col, ch cursor
505 * turn absolute cursor postion into CodeMirror col, ch cursor
490 */
506 */
491 var i, line;
507 var i, line;
492 var offset = 0;
508 var offset = 0;
493 for (i = 0, line=cm.getLine(i); line !== undefined; i++, line=cm.getLine(i)) {
509 for (i = 0, line=cm.getLine(i); line !== undefined; i++, line=cm.getLine(i)) {
494 if (offset + line.length < cursor_pos) {
510 if (offset + line.length < cursor_pos) {
495 offset += line.length + 1;
511 offset += line.length + 1;
496 } else {
512 } else {
497 return {
513 return {
498 line : i,
514 line : i,
499 ch : cursor_pos - offset,
515 ch : cursor_pos - offset,
500 };
516 };
501 }
517 }
502 }
518 }
503 // reached end, return endpoint
519 // reached end, return endpoint
504 return {
520 return {
505 ch : line.length - 1,
521 ch : line.length - 1,
506 line : i - 1,
522 line : i - 1,
507 };
523 };
508 };
524 };
509
525
510 // http://stackoverflow.com/questions/2400935/browser-detection-in-javascript
526 // http://stackoverflow.com/questions/2400935/browser-detection-in-javascript
511 var browser = (function() {
527 var browser = (function() {
512 if (typeof navigator === 'undefined') {
528 if (typeof navigator === 'undefined') {
513 // navigator undefined in node
529 // navigator undefined in node
514 return 'None';
530 return 'None';
515 }
531 }
516 var N= navigator.appName, ua= navigator.userAgent, tem;
532 var N= navigator.appName, ua= navigator.userAgent, tem;
517 var M= ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
533 var M= ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
518 if (M && (tem= ua.match(/version\/([\.\d]+)/i)) !== null) M[2]= tem[1];
534 if (M && (tem= ua.match(/version\/([\.\d]+)/i)) !== null) M[2]= tem[1];
519 M= M? [M[1], M[2]]: [N, navigator.appVersion,'-?'];
535 M= M? [M[1], M[2]]: [N, navigator.appVersion,'-?'];
520 return M;
536 return M;
521 })();
537 })();
522
538
523 // http://stackoverflow.com/questions/11219582/how-to-detect-my-browser-version-and-operating-system-using-javascript
539 // http://stackoverflow.com/questions/11219582/how-to-detect-my-browser-version-and-operating-system-using-javascript
524 var platform = (function () {
540 var platform = (function () {
525 if (typeof navigator === 'undefined') {
541 if (typeof navigator === 'undefined') {
526 // navigator undefined in node
542 // navigator undefined in node
527 return 'None';
543 return 'None';
528 }
544 }
529 var OSName="None";
545 var OSName="None";
530 if (navigator.appVersion.indexOf("Win")!=-1) OSName="Windows";
546 if (navigator.appVersion.indexOf("Win")!=-1) OSName="Windows";
531 if (navigator.appVersion.indexOf("Mac")!=-1) OSName="MacOS";
547 if (navigator.appVersion.indexOf("Mac")!=-1) OSName="MacOS";
532 if (navigator.appVersion.indexOf("X11")!=-1) OSName="UNIX";
548 if (navigator.appVersion.indexOf("X11")!=-1) OSName="UNIX";
533 if (navigator.appVersion.indexOf("Linux")!=-1) OSName="Linux";
549 if (navigator.appVersion.indexOf("Linux")!=-1) OSName="Linux";
534 return OSName;
550 return OSName;
535 })();
551 })();
536
552
537 var get_url_param = function (name) {
553 var get_url_param = function (name) {
538 // get a URL parameter. I cannot believe we actually need this.
554 // get a URL parameter. I cannot believe we actually need this.
539 // Based on http://stackoverflow.com/a/25359264/938949
555 // Based on http://stackoverflow.com/a/25359264/938949
540 var match = new RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
556 var match = new RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
541 if (match){
557 if (match){
542 return decodeURIComponent(match[1] || '');
558 return decodeURIComponent(match[1] || '');
543 }
559 }
544 };
560 };
545
561
546 var is_or_has = function (a, b) {
562 var is_or_has = function (a, b) {
547 /**
563 /**
548 * Is b a child of a or a itself?
564 * Is b a child of a or a itself?
549 */
565 */
550 return a.has(b).length !==0 || a.is(b);
566 return a.has(b).length !==0 || a.is(b);
551 };
567 };
552
568
553 var is_focused = function (e) {
569 var is_focused = function (e) {
554 /**
570 /**
555 * Is element e, or one of its children focused?
571 * Is element e, or one of its children focused?
556 */
572 */
557 e = $(e);
573 e = $(e);
558 var target = $(document.activeElement);
574 var target = $(document.activeElement);
559 if (target.length > 0) {
575 if (target.length > 0) {
560 if (is_or_has(e, target)) {
576 if (is_or_has(e, target)) {
561 return true;
577 return true;
562 } else {
578 } else {
563 return false;
579 return false;
564 }
580 }
565 } else {
581 } else {
566 return false;
582 return false;
567 }
583 }
568 };
584 };
569
585
570 var mergeopt = function(_class, options, overwrite){
586 var mergeopt = function(_class, options, overwrite){
571 options = options || {};
587 options = options || {};
572 overwrite = overwrite || {};
588 overwrite = overwrite || {};
573 return $.extend(true, {}, _class.options_default, options, overwrite);
589 return $.extend(true, {}, _class.options_default, options, overwrite);
574 };
590 };
575
591
576 var ajax_error_msg = function (jqXHR) {
592 var ajax_error_msg = function (jqXHR) {
577 /**
593 /**
578 * Return a JSON error message if there is one,
594 * Return a JSON error message if there is one,
579 * otherwise the basic HTTP status text.
595 * otherwise the basic HTTP status text.
580 */
596 */
581 if (jqXHR.responseJSON && jqXHR.responseJSON.traceback) {
597 if (jqXHR.responseJSON && jqXHR.responseJSON.traceback) {
582 return jqXHR.responseJSON.traceback;
598 return jqXHR.responseJSON.traceback;
583 } else if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
599 } else if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
584 return jqXHR.responseJSON.message;
600 return jqXHR.responseJSON.message;
585 } else {
601 } else {
586 return jqXHR.statusText;
602 return jqXHR.statusText;
587 }
603 }
588 };
604 };
589 var log_ajax_error = function (jqXHR, status, error) {
605 var log_ajax_error = function (jqXHR, status, error) {
590 /**
606 /**
591 * log ajax failures with informative messages
607 * log ajax failures with informative messages
592 */
608 */
593 var msg = "API request failed (" + jqXHR.status + "): ";
609 var msg = "API request failed (" + jqXHR.status + "): ";
594 console.log(jqXHR);
610 console.log(jqXHR);
595 msg += ajax_error_msg(jqXHR);
611 msg += ajax_error_msg(jqXHR);
596 console.log(msg);
612 console.log(msg);
597 };
613 };
598
614
599 var requireCodeMirrorMode = function (mode, callback, errback) {
615 var requireCodeMirrorMode = function (mode, callback, errback) {
600 /**
616 /**
601 * find a predefined mode or detect from CM metadata then
617 * find a predefined mode or detect from CM metadata then
602 * require and callback with the resolveable mode string: mime or
618 * require and callback with the resolveable mode string: mime or
603 * custom name
619 * custom name
604 */
620 */
605
621
606 var modename = (typeof mode == "string") ? mode :
622 var modename = (typeof mode == "string") ? mode :
607 mode.mode || mode.name;
623 mode.mode || mode.name;
608
624
609 // simplest, cheapest check by mode name: mode may also have config
625 // simplest, cheapest check by mode name: mode may also have config
610 if (CodeMirror.modes.hasOwnProperty(modename)) {
626 if (CodeMirror.modes.hasOwnProperty(modename)) {
611 // return the full mode object, if it has a name
627 // return the full mode object, if it has a name
612 callback(mode.name ? mode : modename);
628 callback(mode.name ? mode : modename);
613 return;
629 return;
614 }
630 }
615
631
616 // *somehow* get back a CM.modeInfo-like object that has .mode and
632 // *somehow* get back a CM.modeInfo-like object that has .mode and
617 // .mime
633 // .mime
618 var info = (mode && mode.mode && mode.mime && mode) ||
634 var info = (mode && mode.mode && mode.mime && mode) ||
619 CodeMirror.findModeByName(modename) ||
635 CodeMirror.findModeByName(modename) ||
620 CodeMirror.findModeByExtension(modename.split(".").slice(-1)) ||
636 CodeMirror.findModeByExtension(modename.split(".").slice(-1)) ||
621 CodeMirror.findModeByMIME(modename) ||
637 CodeMirror.findModeByMIME(modename) ||
622 {mode: modename, mime: modename};
638 {mode: modename, mime: modename};
623
639
624 require([
640 require([
625 // might want to use CodeMirror.modeURL here
641 // might want to use CodeMirror.modeURL here
626 ['codemirror/mode', info.mode, info.mode].join('/'),
642 ['codemirror/mode', info.mode, info.mode].join('/'),
627 ], function() {
643 ], function() {
628 // return the original mode, as from a kernelspec on first load
644 // return the original mode, as from a kernelspec on first load
629 // or the mimetype, as for most highlighting
645 // or the mimetype, as for most highlighting
630 callback(mode.name ? mode : info.mime);
646 callback(mode.name ? mode : info.mime);
631 }, errback
647 }, errback
632 );
648 );
633 };
649 };
634
650
635 /** Error type for wrapped XHR errors. */
651 /** Error type for wrapped XHR errors. */
636 var XHR_ERROR = 'XhrError';
652 var XHR_ERROR = 'XhrError';
637
653
638 /**
654 /**
639 * Wraps an AJAX error as an Error object.
655 * Wraps an AJAX error as an Error object.
640 */
656 */
641 var wrap_ajax_error = function (jqXHR, status, error) {
657 var wrap_ajax_error = function (jqXHR, status, error) {
642 var wrapped_error = new Error(ajax_error_msg(jqXHR));
658 var wrapped_error = new Error(ajax_error_msg(jqXHR));
643 wrapped_error.name = XHR_ERROR;
659 wrapped_error.name = XHR_ERROR;
644 // provide xhr response
660 // provide xhr response
645 wrapped_error.xhr = jqXHR;
661 wrapped_error.xhr = jqXHR;
646 wrapped_error.xhr_status = status;
662 wrapped_error.xhr_status = status;
647 wrapped_error.xhr_error = error;
663 wrapped_error.xhr_error = error;
648 return wrapped_error;
664 return wrapped_error;
649 };
665 };
650
666
651 var promising_ajax = function(url, settings) {
667 var promising_ajax = function(url, settings) {
652 /**
668 /**
653 * Like $.ajax, but returning an ES6 promise. success and error settings
669 * Like $.ajax, but returning an ES6 promise. success and error settings
654 * will be ignored.
670 * will be ignored.
655 */
671 */
656 settings = settings || {};
672 settings = settings || {};
657 return new Promise(function(resolve, reject) {
673 return new Promise(function(resolve, reject) {
658 settings.success = function(data, status, jqXHR) {
674 settings.success = function(data, status, jqXHR) {
659 resolve(data);
675 resolve(data);
660 };
676 };
661 settings.error = function(jqXHR, status, error) {
677 settings.error = function(jqXHR, status, error) {
662 log_ajax_error(jqXHR, status, error);
678 log_ajax_error(jqXHR, status, error);
663 reject(wrap_ajax_error(jqXHR, status, error));
679 reject(wrap_ajax_error(jqXHR, status, error));
664 };
680 };
665 $.ajax(url, settings);
681 $.ajax(url, settings);
666 });
682 });
667 };
683 };
668
684
669 var WrappedError = function(message, error){
685 var WrappedError = function(message, error){
670 /**
686 /**
671 * Wrappable Error class
687 * Wrappable Error class
672 *
688 *
673 * The Error class doesn't actually act on `this`. Instead it always
689 * The Error class doesn't actually act on `this`. Instead it always
674 * returns a new instance of Error. Here we capture that instance so we
690 * returns a new instance of Error. Here we capture that instance so we
675 * can apply it's properties to `this`.
691 * can apply it's properties to `this`.
676 */
692 */
677 var tmp = Error.apply(this, [message]);
693 var tmp = Error.apply(this, [message]);
678
694
679 // Copy the properties of the error over to this.
695 // Copy the properties of the error over to this.
680 var properties = Object.getOwnPropertyNames(tmp);
696 var properties = Object.getOwnPropertyNames(tmp);
681 for (var i = 0; i < properties.length; i++) {
697 for (var i = 0; i < properties.length; i++) {
682 this[properties[i]] = tmp[properties[i]];
698 this[properties[i]] = tmp[properties[i]];
683 }
699 }
684
700
685 // Keep a stack of the original error messages.
701 // Keep a stack of the original error messages.
686 if (error instanceof WrappedError) {
702 if (error instanceof WrappedError) {
687 this.error_stack = error.error_stack;
703 this.error_stack = error.error_stack;
688 } else {
704 } else {
689 this.error_stack = [error];
705 this.error_stack = [error];
690 }
706 }
691 this.error_stack.push(tmp);
707 this.error_stack.push(tmp);
692
708
693 return this;
709 return this;
694 };
710 };
695
711
696 WrappedError.prototype = Object.create(Error.prototype, {});
712 WrappedError.prototype = Object.create(Error.prototype, {});
697
713
698
714
699 var load_class = function(class_name, module_name, registry) {
715 var load_class = function(class_name, module_name, registry) {
700 /**
716 /**
701 * Tries to load a class
717 * Tries to load a class
702 *
718 *
703 * Tries to load a class from a module using require.js, if a module
719 * Tries to load a class from a module using require.js, if a module
704 * is specified, otherwise tries to load a class from the global
720 * is specified, otherwise tries to load a class from the global
705 * registry, if the global registry is provided.
721 * registry, if the global registry is provided.
706 */
722 */
707 return new Promise(function(resolve, reject) {
723 return new Promise(function(resolve, reject) {
708
724
709 // Try loading the view module using require.js
725 // Try loading the view module using require.js
710 if (module_name) {
726 if (module_name) {
711 require([module_name], function(module) {
727 require([module_name], function(module) {
712 if (module[class_name] === undefined) {
728 if (module[class_name] === undefined) {
713 reject(new Error('Class '+class_name+' not found in module '+module_name));
729 reject(new Error('Class '+class_name+' not found in module '+module_name));
714 } else {
730 } else {
715 resolve(module[class_name]);
731 resolve(module[class_name]);
716 }
732 }
717 }, reject);
733 }, reject);
718 } else {
734 } else {
719 if (registry && registry[class_name]) {
735 if (registry && registry[class_name]) {
720 resolve(registry[class_name]);
736 resolve(registry[class_name]);
721 } else {
737 } else {
722 reject(new Error('Class '+class_name+' not found in registry '));
738 reject(new Error('Class '+class_name+' not found in registry '));
723 }
739 }
724 }
740 }
725 });
741 });
726 };
742 };
727
743
728 var resolve_promises_dict = function(d) {
744 var resolve_promises_dict = function(d) {
729 /**
745 /**
730 * Resolve a promiseful dictionary.
746 * Resolve a promiseful dictionary.
731 * Returns a single Promise.
747 * Returns a single Promise.
732 */
748 */
733 var keys = Object.keys(d);
749 var keys = Object.keys(d);
734 var values = [];
750 var values = [];
735 keys.forEach(function(key) {
751 keys.forEach(function(key) {
736 values.push(d[key]);
752 values.push(d[key]);
737 });
753 });
738 return Promise.all(values).then(function(v) {
754 return Promise.all(values).then(function(v) {
739 d = {};
755 d = {};
740 for(var i=0; i<keys.length; i++) {
756 for(var i=0; i<keys.length; i++) {
741 d[keys[i]] = v[i];
757 d[keys[i]] = v[i];
742 }
758 }
743 return d;
759 return d;
744 });
760 });
745 };
761 };
746
762
747 var reject = function(message, log) {
763 var reject = function(message, log) {
748 /**
764 /**
749 * Creates a wrappable Promise rejection function.
765 * Creates a wrappable Promise rejection function.
750 *
766 *
751 * Creates a function that returns a Promise.reject with a new WrappedError
767 * Creates a function that returns a Promise.reject with a new WrappedError
752 * that has the provided message and wraps the original error that
768 * that has the provided message and wraps the original error that
753 * caused the promise to reject.
769 * caused the promise to reject.
754 */
770 */
755 return function(error) {
771 return function(error) {
756 var wrapped_error = new WrappedError(message, error);
772 var wrapped_error = new WrappedError(message, error);
757 if (log) console.error(wrapped_error);
773 if (log) console.error(wrapped_error);
758 return Promise.reject(wrapped_error);
774 return Promise.reject(wrapped_error);
759 };
775 };
760 };
776 };
761
777
762 var typeset = function(element, text) {
778 var typeset = function(element, text) {
763 /**
779 /**
764 * Apply MathJax rendering to an element, and optionally set its text
780 * Apply MathJax rendering to an element, and optionally set its text
765 *
781 *
766 * If MathJax is not available, make no changes.
782 * If MathJax is not available, make no changes.
767 *
783 *
768 * Returns the output any number of typeset elements, or undefined if
784 * Returns the output any number of typeset elements, or undefined if
769 * MathJax was not available.
785 * MathJax was not available.
770 *
786 *
771 * Parameters
787 * Parameters
772 * ----------
788 * ----------
773 * element: Node, NodeList, or jQuery selection
789 * element: Node, NodeList, or jQuery selection
774 * text: option string
790 * text: option string
775 */
791 */
776 var $el = element.jquery ? element : $(element);
792 var $el = element.jquery ? element : $(element);
777 if(arguments.length > 1){
793 if(arguments.length > 1){
778 $el.text(text);
794 $el.text(text);
779 }
795 }
780 if(!window.MathJax){
796 if(!window.MathJax){
781 return;
797 return;
782 }
798 }
783 return $el.map(function(){
799 return $el.map(function(){
784 // MathJax takes a DOM node: $.map makes `this` the context
800 // MathJax takes a DOM node: $.map makes `this` the context
785 return MathJax.Hub.Queue(["Typeset", MathJax.Hub, this]);
801 return MathJax.Hub.Queue(["Typeset", MathJax.Hub, this]);
786 });
802 });
787 };
803 };
788
804
789 var time = {};
805 var time = {};
790 time.milliseconds = {};
806 time.milliseconds = {};
791 time.milliseconds.s = 1000;
807 time.milliseconds.s = 1000;
792 time.milliseconds.m = 60 * time.milliseconds.s;
808 time.milliseconds.m = 60 * time.milliseconds.s;
793 time.milliseconds.h = 60 * time.milliseconds.m;
809 time.milliseconds.h = 60 * time.milliseconds.m;
794 time.milliseconds.d = 24 * time.milliseconds.h;
810 time.milliseconds.d = 24 * time.milliseconds.h;
795
811
796 time.thresholds = {
812 time.thresholds = {
797 // moment.js thresholds in milliseconds
813 // moment.js thresholds in milliseconds
798 s: moment.relativeTimeThreshold('s') * time.milliseconds.s,
814 s: moment.relativeTimeThreshold('s') * time.milliseconds.s,
799 m: moment.relativeTimeThreshold('m') * time.milliseconds.m,
815 m: moment.relativeTimeThreshold('m') * time.milliseconds.m,
800 h: moment.relativeTimeThreshold('h') * time.milliseconds.h,
816 h: moment.relativeTimeThreshold('h') * time.milliseconds.h,
801 d: moment.relativeTimeThreshold('d') * time.milliseconds.d,
817 d: moment.relativeTimeThreshold('d') * time.milliseconds.d,
802 };
818 };
803
819
804 time.timeout_from_dt = function (dt) {
820 time.timeout_from_dt = function (dt) {
805 /** compute a timeout based on dt
821 /** compute a timeout based on dt
806
822
807 input and output both in milliseconds
823 input and output both in milliseconds
808
824
809 use moment's relative time thresholds:
825 use moment's relative time thresholds:
810
826
811 - 10 seconds if in 'seconds ago' territory
827 - 10 seconds if in 'seconds ago' territory
812 - 1 minute if in 'minutes ago'
828 - 1 minute if in 'minutes ago'
813 - 1 hour otherwise
829 - 1 hour otherwise
814 */
830 */
815 if (dt < time.thresholds.s) {
831 if (dt < time.thresholds.s) {
816 return 10 * time.milliseconds.s;
832 return 10 * time.milliseconds.s;
817 } else if (dt < time.thresholds.m) {
833 } else if (dt < time.thresholds.m) {
818 return time.milliseconds.m;
834 return time.milliseconds.m;
819 } else {
835 } else {
820 return time.milliseconds.h;
836 return time.milliseconds.h;
821 }
837 }
822 };
838 };
823
839
824 var utils = {
840 var utils = {
841 load_extensions: load_extensions,
842 load_extensions_from_config: load_extensions_from_config,
825 regex_split : regex_split,
843 regex_split : regex_split,
826 uuid : uuid,
844 uuid : uuid,
827 fixConsole : fixConsole,
845 fixConsole : fixConsole,
828 fixCarriageReturn : fixCarriageReturn,
846 fixCarriageReturn : fixCarriageReturn,
829 autoLinkUrls : autoLinkUrls,
847 autoLinkUrls : autoLinkUrls,
830 points_to_pixels : points_to_pixels,
848 points_to_pixels : points_to_pixels,
831 get_body_data : get_body_data,
849 get_body_data : get_body_data,
832 parse_url : parse_url,
850 parse_url : parse_url,
833 url_path_split : url_path_split,
851 url_path_split : url_path_split,
834 url_path_join : url_path_join,
852 url_path_join : url_path_join,
835 url_join_encode : url_join_encode,
853 url_join_encode : url_join_encode,
836 encode_uri_components : encode_uri_components,
854 encode_uri_components : encode_uri_components,
837 splitext : splitext,
855 splitext : splitext,
838 escape_html : escape_html,
856 escape_html : escape_html,
839 always_new : always_new,
857 always_new : always_new,
840 to_absolute_cursor_pos : to_absolute_cursor_pos,
858 to_absolute_cursor_pos : to_absolute_cursor_pos,
841 from_absolute_cursor_pos : from_absolute_cursor_pos,
859 from_absolute_cursor_pos : from_absolute_cursor_pos,
842 browser : browser,
860 browser : browser,
843 platform: platform,
861 platform: platform,
844 get_url_param: get_url_param,
862 get_url_param: get_url_param,
845 is_or_has : is_or_has,
863 is_or_has : is_or_has,
846 is_focused : is_focused,
864 is_focused : is_focused,
847 mergeopt: mergeopt,
865 mergeopt: mergeopt,
848 ajax_error_msg : ajax_error_msg,
866 ajax_error_msg : ajax_error_msg,
849 log_ajax_error : log_ajax_error,
867 log_ajax_error : log_ajax_error,
850 requireCodeMirrorMode : requireCodeMirrorMode,
868 requireCodeMirrorMode : requireCodeMirrorMode,
851 XHR_ERROR : XHR_ERROR,
869 XHR_ERROR : XHR_ERROR,
852 wrap_ajax_error : wrap_ajax_error,
870 wrap_ajax_error : wrap_ajax_error,
853 promising_ajax : promising_ajax,
871 promising_ajax : promising_ajax,
854 WrappedError: WrappedError,
872 WrappedError: WrappedError,
855 load_class: load_class,
873 load_class: load_class,
856 resolve_promises_dict: resolve_promises_dict,
874 resolve_promises_dict: resolve_promises_dict,
857 reject: reject,
875 reject: reject,
858 typeset: typeset,
876 typeset: typeset,
859 time: time,
877 time: time,
860 };
878 };
861
879
862 // Backwards compatability.
880 // Backwards compatability.
863 IPython.utils = utils;
881 IPython.utils = utils;
864
882
865 return utils;
883 return utils;
866 });
884 });
@@ -1,81 +1,78 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 require([
4 require([
5 'base/js/namespace',
5 'base/js/namespace',
6 'base/js/utils',
6 'base/js/utils',
7 'base/js/page',
7 'base/js/page',
8 'base/js/events',
8 'base/js/events',
9 'contents',
9 'contents',
10 'services/config',
10 'services/config',
11 'edit/js/editor',
11 'edit/js/editor',
12 'edit/js/menubar',
12 'edit/js/menubar',
13 'edit/js/savewidget',
13 'edit/js/savewidget',
14 'edit/js/notificationarea',
14 'edit/js/notificationarea',
15 'custom/custom',
15 'custom/custom',
16 ], function(
16 ], function(
17 IPython,
17 IPython,
18 utils,
18 utils,
19 page,
19 page,
20 events,
20 events,
21 contents,
21 contents,
22 configmod,
22 configmod,
23 editmod,
23 editmod,
24 menubar,
24 menubar,
25 savewidget,
25 savewidget,
26 notificationarea
26 notificationarea
27 ){
27 ){
28 page = new page.Page();
28 page = new page.Page();
29
29
30 var base_url = utils.get_body_data('baseUrl');
30 var base_url = utils.get_body_data('baseUrl');
31 var file_path = utils.get_body_data('filePath');
31 var file_path = utils.get_body_data('filePath');
32 contents = new contents.Contents({base_url: base_url});
32 contents = new contents.Contents({base_url: base_url});
33 var config = new configmod.ConfigSection('edit', {base_url: base_url});
33 var config = new configmod.ConfigSection('edit', {base_url: base_url});
34 config.load();
34 config.load();
35 var common_config = new configmod.ConfigSection('common', {base_url: base_url});
36 common_config.load();
35
37
36 var editor = new editmod.Editor('#texteditor-container', {
38 var editor = new editmod.Editor('#texteditor-container', {
37 base_url: base_url,
39 base_url: base_url,
38 events: events,
40 events: events,
39 contents: contents,
41 contents: contents,
40 file_path: file_path,
42 file_path: file_path,
41 config: config,
43 config: config,
42 });
44 });
43
45
44 // Make it available for debugging
46 // Make it available for debugging
45 IPython.editor = editor;
47 IPython.editor = editor;
46
48
47 var save_widget = new savewidget.SaveWidget('span#save_widget', {
49 var save_widget = new savewidget.SaveWidget('span#save_widget', {
48 editor: editor,
50 editor: editor,
49 events: events,
51 events: events,
50 });
52 });
51
53
52 var menus = new menubar.MenuBar('#menubar', {
54 var menus = new menubar.MenuBar('#menubar', {
53 base_url: base_url,
55 base_url: base_url,
54 editor: editor,
56 editor: editor,
55 events: events,
57 events: events,
56 save_widget: save_widget,
58 save_widget: save_widget,
57 });
59 });
58
60
59 var notification_area = new notificationarea.EditorNotificationArea(
61 var notification_area = new notificationarea.EditorNotificationArea(
60 '#notification_area', {
62 '#notification_area', {
61 events: events,
63 events: events,
62 });
64 });
63 notification_area.init_notification_widgets();
65 notification_area.init_notification_widgets();
64
66
65 config.loaded.then(function() {
67 utils.load_extensions_from_config(config);
66 if (config.data.load_extensions) {
68 utils.load_extensions_from_config(common_config);
67 var nbextension_paths = Object.getOwnPropertyNames(
68 config.data.load_extensions);
69 IPython.load_extensions.apply(this, nbextension_paths);
70 }
71 });
72 editor.load();
69 editor.load();
73 page.show();
70 page.show();
74
71
75 window.onbeforeunload = function () {
72 window.onbeforeunload = function () {
76 if (editor.save_enabled && !editor.codemirror.isClean(editor.generation)) {
73 if (editor.save_enabled && !editor.codemirror.isClean(editor.generation)) {
77 return "Unsaved changes will be lost. Close anyway?";
74 return "Unsaved changes will be lost. Close anyway?";
78 }
75 }
79 };
76 };
80
77
81 });
78 });
@@ -1,162 +1,159 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 require([
4 require([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'notebook/js/notebook',
7 'notebook/js/notebook',
8 'contents',
8 'contents',
9 'services/config',
9 'services/config',
10 'base/js/utils',
10 'base/js/utils',
11 'base/js/page',
11 'base/js/page',
12 'base/js/events',
12 'base/js/events',
13 'auth/js/loginwidget',
13 'auth/js/loginwidget',
14 'notebook/js/maintoolbar',
14 'notebook/js/maintoolbar',
15 'notebook/js/pager',
15 'notebook/js/pager',
16 'notebook/js/quickhelp',
16 'notebook/js/quickhelp',
17 'notebook/js/menubar',
17 'notebook/js/menubar',
18 'notebook/js/notificationarea',
18 'notebook/js/notificationarea',
19 'notebook/js/savewidget',
19 'notebook/js/savewidget',
20 'notebook/js/actions',
20 'notebook/js/actions',
21 'notebook/js/keyboardmanager',
21 'notebook/js/keyboardmanager',
22 'notebook/js/kernelselector',
22 'notebook/js/kernelselector',
23 'codemirror/lib/codemirror',
23 'codemirror/lib/codemirror',
24 'notebook/js/about',
24 'notebook/js/about',
25 // only loaded, not used, please keep sure this is loaded last
25 // only loaded, not used, please keep sure this is loaded last
26 'custom/custom'
26 'custom/custom'
27 ], function(
27 ], function(
28 IPython,
28 IPython,
29 $,
29 $,
30 notebook,
30 notebook,
31 contents,
31 contents,
32 configmod,
32 configmod,
33 utils,
33 utils,
34 page,
34 page,
35 events,
35 events,
36 loginwidget,
36 loginwidget,
37 maintoolbar,
37 maintoolbar,
38 pager,
38 pager,
39 quickhelp,
39 quickhelp,
40 menubar,
40 menubar,
41 notificationarea,
41 notificationarea,
42 savewidget,
42 savewidget,
43 actions,
43 actions,
44 keyboardmanager,
44 keyboardmanager,
45 kernelselector,
45 kernelselector,
46 CodeMirror,
46 CodeMirror,
47 about,
47 about,
48 // please keep sure that even if not used, this is loaded last
48 // please keep sure that even if not used, this is loaded last
49 custom
49 custom
50 ) {
50 ) {
51 "use strict";
51 "use strict";
52
52
53 // compat with old IPython, remove for IPython > 3.0
53 // compat with old IPython, remove for IPython > 3.0
54 window.CodeMirror = CodeMirror;
54 window.CodeMirror = CodeMirror;
55
55
56 var common_options = {
56 var common_options = {
57 ws_url : utils.get_body_data("wsUrl"),
57 ws_url : utils.get_body_data("wsUrl"),
58 base_url : utils.get_body_data("baseUrl"),
58 base_url : utils.get_body_data("baseUrl"),
59 notebook_path : utils.get_body_data("notebookPath"),
59 notebook_path : utils.get_body_data("notebookPath"),
60 notebook_name : utils.get_body_data('notebookName')
60 notebook_name : utils.get_body_data('notebookName')
61 };
61 };
62
62
63 var config_section = new configmod.ConfigSection('notebook', common_options);
63 var config_section = new configmod.ConfigSection('notebook', common_options);
64 config_section.load();
64 config_section.load();
65 var common_config = new configmod.ConfigSection('common', common_options);
66 common_config.load();
65 var page = new page.Page();
67 var page = new page.Page();
66 var pager = new pager.Pager('div#pager', {
68 var pager = new pager.Pager('div#pager', {
67 events: events});
69 events: events});
68 var acts = new actions.init();
70 var acts = new actions.init();
69 var keyboard_manager = new keyboardmanager.KeyboardManager({
71 var keyboard_manager = new keyboardmanager.KeyboardManager({
70 pager: pager,
72 pager: pager,
71 events: events,
73 events: events,
72 actions: acts });
74 actions: acts });
73 var save_widget = new savewidget.SaveWidget('span#save_widget', {
75 var save_widget = new savewidget.SaveWidget('span#save_widget', {
74 events: events,
76 events: events,
75 keyboard_manager: keyboard_manager});
77 keyboard_manager: keyboard_manager});
76 var contents = new contents.Contents($.extend({
78 var contents = new contents.Contents($.extend({
77 events: events, config:config_section},
79 events: events, config:config_section},
78 common_options));
80 common_options));
79 var notebook = new notebook.Notebook('div#notebook', $.extend({
81 var notebook = new notebook.Notebook('div#notebook', $.extend({
80 events: events,
82 events: events,
81 keyboard_manager: keyboard_manager,
83 keyboard_manager: keyboard_manager,
82 save_widget: save_widget,
84 save_widget: save_widget,
83 contents: contents,
85 contents: contents,
84 config: config_section},
86 config: config_section},
85 common_options));
87 common_options));
86 var login_widget = new loginwidget.LoginWidget('span#login_widget', common_options);
88 var login_widget = new loginwidget.LoginWidget('span#login_widget', common_options);
87 var toolbar = new maintoolbar.MainToolBar('#maintoolbar-container', {
89 var toolbar = new maintoolbar.MainToolBar('#maintoolbar-container', {
88 notebook: notebook,
90 notebook: notebook,
89 events: events,
91 events: events,
90 actions: acts});
92 actions: acts});
91 var quick_help = new quickhelp.QuickHelp({
93 var quick_help = new quickhelp.QuickHelp({
92 keyboard_manager: keyboard_manager,
94 keyboard_manager: keyboard_manager,
93 events: events,
95 events: events,
94 notebook: notebook});
96 notebook: notebook});
95 keyboard_manager.set_notebook(notebook);
97 keyboard_manager.set_notebook(notebook);
96 keyboard_manager.set_quickhelp(quick_help);
98 keyboard_manager.set_quickhelp(quick_help);
97 var menubar = new menubar.MenuBar('#menubar', $.extend({
99 var menubar = new menubar.MenuBar('#menubar', $.extend({
98 notebook: notebook,
100 notebook: notebook,
99 contents: contents,
101 contents: contents,
100 events: events,
102 events: events,
101 save_widget: save_widget,
103 save_widget: save_widget,
102 quick_help: quick_help},
104 quick_help: quick_help},
103 common_options));
105 common_options));
104 var notification_area = new notificationarea.NotebookNotificationArea(
106 var notification_area = new notificationarea.NotebookNotificationArea(
105 '#notification_area', {
107 '#notification_area', {
106 events: events,
108 events: events,
107 save_widget: save_widget,
109 save_widget: save_widget,
108 notebook: notebook,
110 notebook: notebook,
109 keyboard_manager: keyboard_manager});
111 keyboard_manager: keyboard_manager});
110 notification_area.init_notification_widgets();
112 notification_area.init_notification_widgets();
111 var kernel_selector = new kernelselector.KernelSelector(
113 var kernel_selector = new kernelselector.KernelSelector(
112 '#kernel_logo_widget', notebook);
114 '#kernel_logo_widget', notebook);
113
115
114 $('body').append('<div id="fonttest"><pre><span id="test1">x</span>'+
116 $('body').append('<div id="fonttest"><pre><span id="test1">x</span>'+
115 '<span id="test2" style="font-weight: bold;">x</span>'+
117 '<span id="test2" style="font-weight: bold;">x</span>'+
116 '<span id="test3" style="font-style: italic;">x</span></pre></div>');
118 '<span id="test3" style="font-style: italic;">x</span></pre></div>');
117 var nh = $('#test1').innerHeight();
119 var nh = $('#test1').innerHeight();
118 var bh = $('#test2').innerHeight();
120 var bh = $('#test2').innerHeight();
119 var ih = $('#test3').innerHeight();
121 var ih = $('#test3').innerHeight();
120 if(nh != bh || nh != ih) {
122 if(nh != bh || nh != ih) {
121 $('head').append('<style>.CodeMirror span { vertical-align: bottom; }</style>');
123 $('head').append('<style>.CodeMirror span { vertical-align: bottom; }</style>');
122 }
124 }
123 $('#fonttest').remove();
125 $('#fonttest').remove();
124
126
125 page.show();
127 page.show();
126
128
127 var first_load = function () {
129 var first_load = function () {
128 var hash = document.location.hash;
130 var hash = document.location.hash;
129 if (hash) {
131 if (hash) {
130 document.location.hash = '';
132 document.location.hash = '';
131 document.location.hash = hash;
133 document.location.hash = hash;
132 }
134 }
133 notebook.set_autosave_interval(notebook.minimum_autosave_interval);
135 notebook.set_autosave_interval(notebook.minimum_autosave_interval);
134 // only do this once
136 // only do this once
135 events.off('notebook_loaded.Notebook', first_load);
137 events.off('notebook_loaded.Notebook', first_load);
136 };
138 };
137 events.on('notebook_loaded.Notebook', first_load);
139 events.on('notebook_loaded.Notebook', first_load);
138
140
139 IPython.page = page;
141 IPython.page = page;
140 IPython.notebook = notebook;
142 IPython.notebook = notebook;
141 IPython.contents = contents;
143 IPython.contents = contents;
142 IPython.pager = pager;
144 IPython.pager = pager;
143 IPython.quick_help = quick_help;
145 IPython.quick_help = quick_help;
144 IPython.login_widget = login_widget;
146 IPython.login_widget = login_widget;
145 IPython.menubar = menubar;
147 IPython.menubar = menubar;
146 IPython.toolbar = toolbar;
148 IPython.toolbar = toolbar;
147 IPython.notification_area = notification_area;
149 IPython.notification_area = notification_area;
148 IPython.keyboard_manager = keyboard_manager;
150 IPython.keyboard_manager = keyboard_manager;
149 IPython.save_widget = save_widget;
151 IPython.save_widget = save_widget;
150 IPython.tooltip = notebook.tooltip;
152 IPython.tooltip = notebook.tooltip;
151
153
152 events.trigger('app_initialized.NotebookApp');
154 events.trigger('app_initialized.NotebookApp');
153 config_section.loaded.then(function() {
155 utils.load_extensions_from_config(config_section);
154 if (config_section.data.load_extensions) {
156 utils.load_extensions_from_config(common_config);
155 var nbextension_paths = Object.getOwnPropertyNames(
156 config_section.data.load_extensions);
157 IPython.load_extensions.apply(this, nbextension_paths);
158 }
159 });
160 notebook.load_notebook(common_options.notebook_path);
157 notebook.load_notebook(common_options.notebook_path);
161
158
162 });
159 });
@@ -1,54 +1,63 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 require([
4 require([
5 'jquery',
5 'jquery',
6 'termjs',
6 'termjs',
7 'base/js/utils',
7 'base/js/utils',
8 'base/js/page',
8 'base/js/page',
9 'services/config',
9 'terminal/js/terminado',
10 'terminal/js/terminado',
10 'custom/custom',
11 'custom/custom',
11 ], function(
12 ], function(
12 $,
13 $,
13 termjs,
14 termjs,
14 utils,
15 utils,
15 page,
16 page,
17 configmod,
16 terminado
18 terminado
17 ){
19 ){
18 "use strict";
20 "use strict";
19 page = new page.Page();
21 page = new page.Page();
22
23 var common_config = new configmod.ConfigSection('common',
24 {base_url: utils.get_body_data('baseUrl')});
25 common_config.load();
26
20 // Test size: 25x80
27 // Test size: 25x80
21 var termRowHeight = function(){ return 1.00 * $("#dummy-screen")[0].offsetHeight / 25;};
28 var termRowHeight = function(){ return 1.00 * $("#dummy-screen")[0].offsetHeight / 25;};
22 // 1.02 here arrived at by trial and error to make the spacing look right
29 // 1.02 here arrived at by trial and error to make the spacing look right
23 var termColWidth = function() { return 1.02 * $("#dummy-screen-rows")[0].offsetWidth / 80;};
30 var termColWidth = function() { return 1.02 * $("#dummy-screen-rows")[0].offsetWidth / 80;};
24
31
25 var base_url = utils.get_body_data('baseUrl');
32 var base_url = utils.get_body_data('baseUrl');
26 var ws_path = utils.get_body_data('wsPath');
33 var ws_path = utils.get_body_data('wsPath');
27 var ws_url = location.protocol.replace('http', 'ws') + "//" + location.host
34 var ws_url = location.protocol.replace('http', 'ws') + "//" + location.host
28 + base_url + ws_path;
35 + base_url + ws_path;
29
36
30 var header = $("#header")[0]
37 var header = $("#header")[0]
31 function calculate_size() {
38 function calculate_size() {
32 var height = window.innerHeight - header.offsetHeight;
39 var height = window.innerHeight - header.offsetHeight;
33 var width = $('#terminado-container').width();
40 var width = $('#terminado-container').width();
34 var rows = Math.min(1000, Math.max(20, Math.floor(height/termRowHeight())-1));
41 var rows = Math.min(1000, Math.max(20, Math.floor(height/termRowHeight())-1));
35 var cols = Math.min(1000, Math.max(40, Math.floor(width/termColWidth())-1));
42 var cols = Math.min(1000, Math.max(40, Math.floor(width/termColWidth())-1));
36 console.log("resize to :", rows , 'rows by ', cols, 'columns');
43 console.log("resize to :", rows , 'rows by ', cols, 'columns');
37 return {rows: rows, cols: cols};
44 return {rows: rows, cols: cols};
38 }
45 }
39
46
40 page.show_header();
47 page.show_header();
41
48
42 var size = calculate_size();
49 var size = calculate_size();
43 var terminal = terminado.make_terminal($("#terminado-container")[0], size, ws_url);
50 var terminal = terminado.make_terminal($("#terminado-container")[0], size, ws_url);
44
51
45 page.show_site();
52 page.show_site();
46
53
54 utils.load_extensions_from_config(common_config);
55
47 window.onresize = function() {
56 window.onresize = function() {
48 var geom = calculate_size();
57 var geom = calculate_size();
49 terminal.term.resize(geom.cols, geom.rows);
58 terminal.term.resize(geom.cols, geom.rows);
50 terminal.socket.send(JSON.stringify(["set_size", geom.rows, geom.cols,
59 terminal.socket.send(JSON.stringify(["set_size", geom.rows, geom.cols,
51 window.innerHeight, window.innerWidth]));
60 window.innerHeight, window.innerWidth]));
52 };
61 };
53
62
54 });
63 });
@@ -1,162 +1,166 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 require([
4 require([
5 'jquery',
5 'jquery',
6 'base/js/namespace',
6 'base/js/namespace',
7 'base/js/dialog',
7 'base/js/dialog',
8 'base/js/events',
8 'base/js/events',
9 'base/js/page',
9 'base/js/page',
10 'base/js/utils',
10 'base/js/utils',
11 'services/config',
11 'services/config',
12 'contents',
12 'contents',
13 'tree/js/notebooklist',
13 'tree/js/notebooklist',
14 'tree/js/clusterlist',
14 'tree/js/clusterlist',
15 'tree/js/sessionlist',
15 'tree/js/sessionlist',
16 'tree/js/kernellist',
16 'tree/js/kernellist',
17 'tree/js/terminallist',
17 'tree/js/terminallist',
18 'tree/js/newnotebook',
18 'tree/js/newnotebook',
19 'auth/js/loginwidget',
19 'auth/js/loginwidget',
20 // only loaded, not used:
20 // only loaded, not used:
21 'jqueryui',
21 'jqueryui',
22 'bootstrap',
22 'bootstrap',
23 'custom/custom',
23 'custom/custom',
24 ], function(
24 ], function(
25 $,
25 $,
26 IPython,
26 IPython,
27 dialog,
27 dialog,
28 events,
28 events,
29 page,
29 page,
30 utils,
30 utils,
31 config,
31 config,
32 contents_service,
32 contents_service,
33 notebooklist,
33 notebooklist,
34 clusterlist,
34 clusterlist,
35 sesssionlist,
35 sesssionlist,
36 kernellist,
36 kernellist,
37 terminallist,
37 terminallist,
38 newnotebook,
38 newnotebook,
39 loginwidget){
39 loginwidget){
40 "use strict";
40 "use strict";
41
41
42 page = new page.Page();
42 page = new page.Page();
43
43
44 var common_options = {
44 var common_options = {
45 base_url: utils.get_body_data("baseUrl"),
45 base_url: utils.get_body_data("baseUrl"),
46 notebook_path: utils.get_body_data("notebookPath"),
46 notebook_path: utils.get_body_data("notebookPath"),
47 };
47 };
48 var cfg = new config.ConfigSection('tree', common_options);
48 var cfg = new config.ConfigSection('tree', common_options);
49 cfg.load();
49 cfg.load();
50 common_options.config = cfg;
50 common_options.config = cfg;
51 var common_config = new config.ConfigSection('common', common_options);
52 common_config.load();
51
53
52 var session_list = new sesssionlist.SesssionList($.extend({
54 var session_list = new sesssionlist.SesssionList($.extend({
53 events: events},
55 events: events},
54 common_options));
56 common_options));
55 var contents = new contents_service.Contents($.extend({
57 var contents = new contents_service.Contents($.extend({
56 events: events},
58 events: events},
57 common_options));
59 common_options));
58 var notebook_list = new notebooklist.NotebookList('#notebook_list', $.extend({
60 var notebook_list = new notebooklist.NotebookList('#notebook_list', $.extend({
59 contents: contents,
61 contents: contents,
60 session_list: session_list},
62 session_list: session_list},
61 common_options));
63 common_options));
62 var cluster_list = new clusterlist.ClusterList('#cluster_list', common_options);
64 var cluster_list = new clusterlist.ClusterList('#cluster_list', common_options);
63 var kernel_list = new kernellist.KernelList('#running_list', $.extend({
65 var kernel_list = new kernellist.KernelList('#running_list', $.extend({
64 session_list: session_list},
66 session_list: session_list},
65 common_options));
67 common_options));
66
68
67 var terminal_list;
69 var terminal_list;
68 if (utils.get_body_data("terminalsAvailable") === "True") {
70 if (utils.get_body_data("terminalsAvailable") === "True") {
69 terminal_list = new terminallist.TerminalList('#terminal_list', common_options);
71 terminal_list = new terminallist.TerminalList('#terminal_list', common_options);
70 }
72 }
71
73
72 var login_widget = new loginwidget.LoginWidget('#login_widget', common_options);
74 var login_widget = new loginwidget.LoginWidget('#login_widget', common_options);
73
75
74 var new_buttons = new newnotebook.NewNotebookWidget("#new-buttons",
76 var new_buttons = new newnotebook.NewNotebookWidget("#new-buttons",
75 $.extend(
77 $.extend(
76 {contents: contents},
78 {contents: contents},
77 common_options
79 common_options
78 )
80 )
79 );
81 );
80
82
81 var interval_id=0;
83 var interval_id=0;
82 // auto refresh every xx secondes, no need to be fast,
84 // auto refresh every xx secondes, no need to be fast,
83 // update is done at least when page get focus
85 // update is done at least when page get focus
84 var time_refresh = 60; // in sec
86 var time_refresh = 60; // in sec
85
87
86 var enable_autorefresh = function(){
88 var enable_autorefresh = function(){
87 /**
89 /**
88 *refresh immediately , then start interval
90 *refresh immediately , then start interval
89 */
91 */
90 session_list.load_sessions();
92 session_list.load_sessions();
91 cluster_list.load_list();
93 cluster_list.load_list();
92 if (terminal_list) {
94 if (terminal_list) {
93 terminal_list.load_terminals();
95 terminal_list.load_terminals();
94 }
96 }
95 if (!interval_id){
97 if (!interval_id){
96 interval_id = setInterval(function(){
98 interval_id = setInterval(function(){
97 session_list.load_sessions();
99 session_list.load_sessions();
98 cluster_list.load_list();
100 cluster_list.load_list();
99 if (terminal_list) {
101 if (terminal_list) {
100 terminal_list.load_terminals();
102 terminal_list.load_terminals();
101 }
103 }
102 }, time_refresh*1000);
104 }, time_refresh*1000);
103 }
105 }
104 };
106 };
105
107
106 var disable_autorefresh = function(){
108 var disable_autorefresh = function(){
107 clearInterval(interval_id);
109 clearInterval(interval_id);
108 interval_id = 0;
110 interval_id = 0;
109 };
111 };
110
112
111 // stop autorefresh when page lose focus
113 // stop autorefresh when page lose focus
112 $(window).blur(function() {
114 $(window).blur(function() {
113 disable_autorefresh();
115 disable_autorefresh();
114 });
116 });
115
117
116 //re-enable when page get focus back
118 //re-enable when page get focus back
117 $(window).focus(function() {
119 $(window).focus(function() {
118 enable_autorefresh();
120 enable_autorefresh();
119 });
121 });
120
122
121 // finally start it, it will refresh immediately
123 // finally start it, it will refresh immediately
122 enable_autorefresh();
124 enable_autorefresh();
123
125
124 page.show();
126 page.show();
125
127
126 // For backwards compatability.
128 // For backwards compatability.
127 IPython.page = page;
129 IPython.page = page;
128 IPython.notebook_list = notebook_list;
130 IPython.notebook_list = notebook_list;
129 IPython.cluster_list = cluster_list;
131 IPython.cluster_list = cluster_list;
130 IPython.session_list = session_list;
132 IPython.session_list = session_list;
131 IPython.kernel_list = kernel_list;
133 IPython.kernel_list = kernel_list;
132 IPython.login_widget = login_widget;
134 IPython.login_widget = login_widget;
133 IPython.new_notebook_widget = new_buttons;
135 IPython.new_notebook_widget = new_buttons;
134
136
135 events.trigger('app_initialized.DashboardApp');
137 events.trigger('app_initialized.DashboardApp');
138 utils.load_extensions_from_config(cfg);
139 utils.load_extensions_from_config(common_config);
136
140
137 // bound the upload method to the on change of the file select list
141 // bound the upload method to the on change of the file select list
138 $("#alternate_upload").change(function (event){
142 $("#alternate_upload").change(function (event){
139 notebook_list.handleFilesUpload(event,'form');
143 notebook_list.handleFilesUpload(event,'form');
140 });
144 });
141
145
142 // set hash on tab click
146 // set hash on tab click
143 $("#tabs").find("a").click(function(e) {
147 $("#tabs").find("a").click(function(e) {
144 // Prevent the document from jumping when the active tab is changed to a
148 // Prevent the document from jumping when the active tab is changed to a
145 // tab that has a lot of content.
149 // tab that has a lot of content.
146 e.preventDefault();
150 e.preventDefault();
147
151
148 // Set the hash without causing the page to jump.
152 // Set the hash without causing the page to jump.
149 // http://stackoverflow.com/a/14690177/2824256
153 // http://stackoverflow.com/a/14690177/2824256
150 var hash = $(this).attr("href");
154 var hash = $(this).attr("href");
151 if(window.history.pushState) {
155 if(window.history.pushState) {
152 window.history.pushState(null, null, hash);
156 window.history.pushState(null, null, hash);
153 } else {
157 } else {
154 window.location.hash = hash;
158 window.location.hash = hash;
155 }
159 }
156 });
160 });
157
161
158 // load tab if url hash
162 // load tab if url hash
159 if (window.location.hash) {
163 if (window.location.hash) {
160 $("#tabs").find("a[href=" + window.location.hash + "]").click();
164 $("#tabs").find("a[href=" + window.location.hash + "]").click();
161 }
165 }
162 });
166 });
General Comments 0
You need to be logged in to leave comments. Login now