Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
370
venv/Lib/site-packages/notebook/static/edit/js/editor.js
Normal file
370
venv/Lib/site-packages/notebook/static/edit/js/editor.js
Normal file
|
@ -0,0 +1,370 @@
|
|||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'base/js/utils',
|
||||
'base/js/i18n',
|
||||
'base/js/dialog',
|
||||
'codemirror/lib/codemirror',
|
||||
'codemirror/mode/meta',
|
||||
'codemirror/addon/comment/comment',
|
||||
'codemirror/addon/dialog/dialog',
|
||||
'codemirror/addon/edit/closebrackets',
|
||||
'codemirror/addon/edit/matchbrackets',
|
||||
'codemirror/addon/search/searchcursor',
|
||||
'codemirror/addon/search/search',
|
||||
'codemirror/keymap/emacs',
|
||||
'codemirror/keymap/sublime',
|
||||
'codemirror/keymap/vim',
|
||||
],
|
||||
function(
|
||||
$,
|
||||
utils,
|
||||
i18n,
|
||||
dialog,
|
||||
CodeMirror
|
||||
) {
|
||||
"use strict";
|
||||
|
||||
var Editor = function(selector, options) {
|
||||
var that = this;
|
||||
this.selector = selector;
|
||||
this.clean = false;
|
||||
this.contents = options.contents;
|
||||
this.events = options.events;
|
||||
this.base_url = options.base_url;
|
||||
this.file_path = options.file_path;
|
||||
this.config = options.config;
|
||||
this.file_extension_modes = options.file_extension_modes || {};
|
||||
this.last_modified = null;
|
||||
this._changed_on_disk_dialog = null;
|
||||
|
||||
this.codemirror = new CodeMirror($(this.selector)[0]);
|
||||
this.codemirror.on('changes', function(cm, changes){
|
||||
that._clean_state();
|
||||
});
|
||||
this.generation = -1;
|
||||
|
||||
// It appears we have to set commands on the CodeMirror class, not the
|
||||
// instance. I'd like to be wrong, but since there should only be one CM
|
||||
// instance on the page, this is good enough for now.
|
||||
CodeMirror.commands.save = $.proxy(this.save, this);
|
||||
|
||||
this.save_enabled = false;
|
||||
|
||||
this.config.loaded.then(function () {
|
||||
// load codemirror config
|
||||
var cfg = that.config.data.Editor || {};
|
||||
var cmopts = $.extend(true, {}, // true = recursive copy
|
||||
Editor.default_codemirror_options,
|
||||
cfg.codemirror_options || {}
|
||||
);
|
||||
that._set_codemirror_options(cmopts);
|
||||
that.events.trigger('config_changed.Editor', {config: that.config});
|
||||
if (cfg.file_extension_modes) {
|
||||
// check for file extension in user preferences
|
||||
var modename = cfg.file_extension_modes[that._get_file_extension()];
|
||||
if (modename) {
|
||||
var modeinfo = CodeMirror.findModeByName(modename);
|
||||
if (modeinfo) {
|
||||
that.set_codemirror_mode(modeinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
that._clean_state();
|
||||
});
|
||||
this.clean_sel = $('<div/>');
|
||||
$('.last_modified').before(this.clean_sel);
|
||||
this.clean_sel.addClass('dirty-indicator-dirty');
|
||||
};
|
||||
|
||||
// default CodeMirror options
|
||||
Editor.default_codemirror_options = {
|
||||
extraKeys: {
|
||||
"Cmd-Right": "goLineRight",
|
||||
"End": "goLineRight",
|
||||
"Cmd-Left": "goLineLeft",
|
||||
"Tab": "indentMore",
|
||||
"Shift-Tab" : "indentLess",
|
||||
"Cmd-/" : "toggleComment",
|
||||
"Ctrl-/" : "toggleComment",
|
||||
},
|
||||
indentUnit: 4,
|
||||
theme: "ipython",
|
||||
lineNumbers: true,
|
||||
lineWrapping: true
|
||||
};
|
||||
|
||||
Editor.prototype.load = function() {
|
||||
/** load the file */
|
||||
var that = this;
|
||||
var cm = this.codemirror;
|
||||
return this.contents.get(this.file_path, {type: 'file', format: 'text'})
|
||||
.then(function(model) {
|
||||
cm.setValue(model.content);
|
||||
|
||||
// Setting the file's initial value creates a history entry,
|
||||
// which we don't want.
|
||||
cm.clearHistory();
|
||||
that._set_mode_for_model(model);
|
||||
that.save_enabled = true;
|
||||
that.generation = cm.changeGeneration();
|
||||
that.events.trigger("file_loaded.Editor", model);
|
||||
that._clean_state();
|
||||
that.last_modified = new Date(model.last_modified);
|
||||
}).catch(
|
||||
function(error) {
|
||||
that.events.trigger("file_load_failed.Editor", error);
|
||||
console.warn('Error loading: ', error);
|
||||
cm.setValue("Error! " + error.message +
|
||||
"\nSaving disabled.\nSee Console for more details.");
|
||||
cm.setOption('readOnly','nocursor');
|
||||
that.save_enabled = false;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
Editor.prototype._set_mode_for_model = function (model) {
|
||||
/** Set the CodeMirror mode based on the file model */
|
||||
|
||||
// Find and load the highlighting mode,
|
||||
// first by mime-type, then by file extension
|
||||
|
||||
var modeinfo;
|
||||
var ext = this._get_file_extension();
|
||||
if (ext) {
|
||||
// check if a mode has been remembered for this extension
|
||||
var modename = this.file_extension_modes[ext];
|
||||
if (modename) {
|
||||
modeinfo = CodeMirror.findModeByName(modename);
|
||||
}
|
||||
}
|
||||
// prioritize CodeMirror's filename identification
|
||||
if (!modeinfo || modeinfo.mode === "null") {
|
||||
modeinfo = CodeMirror.findModeByFileName(model.name);
|
||||
// codemirror's filename identification is case-sensitive.
|
||||
// try once more with lowercase extension
|
||||
if (!modeinfo && ext) {
|
||||
// CodeMirror wants lowercase ext without leading '.'
|
||||
modeinfo = CodeMirror.findModeByExtension(ext.slice(1).toLowerCase());
|
||||
}
|
||||
}
|
||||
if (model.mimetype && (!modeinfo || modeinfo.mode === "null")) {
|
||||
// mimetype is not set on file rename
|
||||
modeinfo = CodeMirror.findModeByMIME(model.mimetype);
|
||||
}
|
||||
if (modeinfo) {
|
||||
this.set_codemirror_mode(modeinfo);
|
||||
}
|
||||
};
|
||||
|
||||
Editor.prototype.set_codemirror_mode = function (modeinfo) {
|
||||
/** set the codemirror mode from a modeinfo struct */
|
||||
var that = this;
|
||||
utils.requireCodeMirrorMode(modeinfo, function () {
|
||||
that.codemirror.setOption('mode', modeinfo.mime);
|
||||
that.events.trigger("mode_changed.Editor", modeinfo);
|
||||
}, function(err) {
|
||||
console.log('Error getting CodeMirror mode: ' + err);
|
||||
});
|
||||
};
|
||||
|
||||
Editor.prototype.save_codemirror_mode = function (modeinfo) {
|
||||
/** save the selected codemirror mode for the current extension in config */
|
||||
var update_mode_map = {};
|
||||
var ext = this._get_file_extension();
|
||||
// no extension, nothing to save
|
||||
// TODO: allow remembering no-extension things like Makefile?
|
||||
if (!ext) return;
|
||||
|
||||
update_mode_map[ext] = modeinfo.name;
|
||||
return this.config.update({
|
||||
Editor: {
|
||||
file_extension_modes: update_mode_map,
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Editor.prototype.get_filename = function () {
|
||||
return utils.url_path_split(this.file_path)[1];
|
||||
};
|
||||
|
||||
Editor.prototype._get_file_extension = function () {
|
||||
/** return file extension *including* .
|
||||
|
||||
Returns undefined if no extension is found.
|
||||
*/
|
||||
var filename = this.get_filename();
|
||||
var ext_idx = filename.lastIndexOf('.');
|
||||
if (ext_idx < 0) {
|
||||
return;
|
||||
} else {
|
||||
return filename.slice(ext_idx);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Rename the file.
|
||||
* @param {string} new_name
|
||||
* @return {Promise} promise that resolves when the file is renamed.
|
||||
*/
|
||||
Editor.prototype.rename = function (new_name) {
|
||||
/** rename the file */
|
||||
var that = this;
|
||||
var parent = utils.url_path_split(this.file_path)[0];
|
||||
var new_path = utils.url_path_join(parent, new_name);
|
||||
return this.contents.rename(this.file_path, new_path).then(
|
||||
function (model) {
|
||||
that.file_path = model.path;
|
||||
that.events.trigger('file_renamed.Editor', model);
|
||||
that.last_modified = new Date(model.last_modified);
|
||||
that._set_mode_for_model(model);
|
||||
that._clean_state();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Save this file on the server.
|
||||
*
|
||||
* @param {boolean} check_last_modified - checks if file has been modified on disk
|
||||
* @return {Promise} - promise that resolves when the notebook is saved.
|
||||
*/
|
||||
Editor.prototype.save = function (check_last_modified) {
|
||||
/** save the file */
|
||||
if (!this.save_enabled) {
|
||||
console.log("Not saving, save disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
// used to check for last modified saves
|
||||
if (check_last_modified === undefined) {
|
||||
check_last_modified = true;
|
||||
}
|
||||
|
||||
var model = {
|
||||
path: this.file_path,
|
||||
type: 'file',
|
||||
format: 'text',
|
||||
content: this.codemirror.getValue(),
|
||||
};
|
||||
var that = this;
|
||||
|
||||
var _save = function () {
|
||||
that.events.trigger("file_saving.Editor");
|
||||
return that.contents.save(that.file_path, model).then(function(data) {
|
||||
// record change generation for isClean
|
||||
that.generation = that.codemirror.changeGeneration();
|
||||
that.events.trigger("file_saved.Editor", data);
|
||||
that.last_modified = new Date(data.last_modified);
|
||||
that._clean_state();
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Gets the current working file, and checks if the file has been modified on disk. If so, it
|
||||
* creates & opens a modal that issues the user a warning and prompts them to overwrite the file.
|
||||
*
|
||||
* If it can't get the working file, it builds a new file and saves.
|
||||
*/
|
||||
if (check_last_modified) {
|
||||
return this.contents.get(that.file_path, {content: false}).then(
|
||||
function check_if_modified(data) {
|
||||
var last_modified = new Date(data.last_modified);
|
||||
// We want to check last_modified (disk) > that.last_modified (our last save)
|
||||
// In some cases the filesystem reports an inconsistent time,
|
||||
// so we allow 0.5 seconds difference before complaining.
|
||||
if ((last_modified.getTime() - that.last_modified.getTime()) > 500) { // 500 ms
|
||||
console.warn("Last saving was done on `"+that.last_modified+"`("+that._last_modified+"), "+
|
||||
"while the current file seem to have been saved on `"+data.last_modified+"`");
|
||||
if (that._changed_on_disk_dialog !== null) {
|
||||
// since the modal's event bindings are removed when destroyed, we reinstate
|
||||
// save & reload callbacks on the confirmation & reload buttons
|
||||
that._changed_on_disk_dialog.find('.save-confirm-btn').click(_save);
|
||||
that._changed_on_disk_dialog.find('.btn-warning').click(function () {window.location.reload()});
|
||||
|
||||
// redisplay existing dialog
|
||||
that._changed_on_disk_dialog.modal('show');
|
||||
} else {
|
||||
// create new dialog
|
||||
that._changed_on_disk_dialog = dialog.modal({
|
||||
keyboard_manager: that.keyboard_manager,
|
||||
title: i18n.msg._("File changed"),
|
||||
body: i18n.msg._("The file has changed on disk since the last time we opened or saved it. "
|
||||
+ "Do you want to overwrite the file on disk with the version open here, or load "
|
||||
+ "the version on disk (reload the page)?"),
|
||||
buttons: {
|
||||
Reload: {
|
||||
class: 'btn-warning',
|
||||
click: function () {
|
||||
window.location.reload();
|
||||
}
|
||||
},
|
||||
Cancel: {},
|
||||
Overwrite: {
|
||||
class: 'btn-danger save-confirm-btn',
|
||||
click: function () {
|
||||
_save();
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return _save();
|
||||
}
|
||||
}, function (error) {
|
||||
console.log(error);
|
||||
// maybe it has been deleted or renamed? Go ahead and save.
|
||||
return _save();
|
||||
})
|
||||
} else {
|
||||
return _save();
|
||||
}
|
||||
};
|
||||
|
||||
Editor.prototype._clean_state = function(){
|
||||
var clean = this.codemirror.isClean(this.generation);
|
||||
if (clean === this.clean){
|
||||
return;
|
||||
} else {
|
||||
this.clean = clean;
|
||||
}
|
||||
if(clean){
|
||||
this.events.trigger("save_status_clean.Editor");
|
||||
this.clean_sel.attr('class','dirty-indicator-clean').attr('title','No changes to save');
|
||||
} else {
|
||||
this.events.trigger("save_status_dirty.Editor");
|
||||
this.clean_sel.attr('class','dirty-indicator-dirty').attr('title','Unsaved changes');
|
||||
}
|
||||
};
|
||||
|
||||
Editor.prototype._set_codemirror_options = function (options) {
|
||||
// update codemirror options from a dict
|
||||
var codemirror = this.codemirror;
|
||||
$.map(options, function (value, opt) {
|
||||
if (value === null) {
|
||||
value = CodeMirror.defaults[opt];
|
||||
}
|
||||
codemirror.setOption(opt, value);
|
||||
});
|
||||
var that = this;
|
||||
};
|
||||
|
||||
Editor.prototype.update_codemirror_options = function (options) {
|
||||
/** update codemirror options locally and save changes in config */
|
||||
var that = this;
|
||||
this._set_codemirror_options(options);
|
||||
return this.config.update({
|
||||
Editor: {
|
||||
codemirror_options: options
|
||||
}
|
||||
}).then(
|
||||
that.events.trigger('config_changed.Editor', {config: that.config})
|
||||
);
|
||||
};
|
||||
|
||||
return {Editor: Editor};
|
||||
});
|
113
venv/Lib/site-packages/notebook/static/edit/js/main.js
Normal file
113
venv/Lib/site-packages/notebook/static/edit/js/main.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
requirejs([
|
||||
'jquery',
|
||||
'contents',
|
||||
'base/js/namespace',
|
||||
'base/js/utils',
|
||||
'base/js/page',
|
||||
'base/js/events',
|
||||
'services/config',
|
||||
'edit/js/editor',
|
||||
'edit/js/menubar',
|
||||
'edit/js/savewidget',
|
||||
'edit/js/notificationarea',
|
||||
'bidi/bidi',
|
||||
'auth/js/loginwidget',
|
||||
], function(
|
||||
$,
|
||||
contents_service,
|
||||
IPython,
|
||||
utils,
|
||||
page,
|
||||
events,
|
||||
configmod,
|
||||
editmod,
|
||||
menubar,
|
||||
savewidget,
|
||||
notificationarea,
|
||||
bidi,
|
||||
loginwidget,
|
||||
){
|
||||
"use strict";
|
||||
|
||||
try {
|
||||
requirejs(['custom/custom'], function() {});
|
||||
bidi.loadLocale();
|
||||
} catch(err) {
|
||||
console.log("Error loading custom.js from edition service. Continuing and logging");
|
||||
console.warn(err);
|
||||
}
|
||||
|
||||
page = new page.Page('div#header', 'div#site');
|
||||
|
||||
var base_url = utils.get_body_data('baseUrl');
|
||||
var file_path = utils.get_body_data('filePath');
|
||||
// This enables logout
|
||||
var login_widget = new loginwidget.LoginWidget('#login_widget', {
|
||||
base_url: base_url
|
||||
});
|
||||
var config = new configmod.ConfigSection('edit', {base_url: base_url});
|
||||
config.load();
|
||||
var common_config = new configmod.ConfigSection('common', {base_url: base_url});
|
||||
common_config.load();
|
||||
var contents = new contents_service.Contents({
|
||||
base_url: base_url,
|
||||
common_config: common_config
|
||||
});
|
||||
|
||||
var editor = new editmod.Editor('#texteditor-container', {
|
||||
base_url: base_url,
|
||||
events: events,
|
||||
contents: contents,
|
||||
file_path: file_path,
|
||||
config: config,
|
||||
});
|
||||
|
||||
// Make it available for debugging
|
||||
IPython.editor = editor;
|
||||
|
||||
var save_widget = new savewidget.SaveWidget('span#save_widget', {
|
||||
editor: editor,
|
||||
events: events,
|
||||
});
|
||||
|
||||
var menus = new menubar.MenuBar('#menubar', {
|
||||
base_url: base_url,
|
||||
editor: editor,
|
||||
events: events,
|
||||
save_widget: save_widget,
|
||||
});
|
||||
|
||||
var notification_area = new notificationarea.EditorNotificationArea(
|
||||
'#notification_area', {
|
||||
events: events,
|
||||
});
|
||||
editor.notification_area = notification_area;
|
||||
notification_area.init_notification_widgets();
|
||||
|
||||
utils.load_extensions_from_config(config);
|
||||
utils.load_extensions_from_config(common_config);
|
||||
editor.load();
|
||||
page.show();
|
||||
|
||||
window.onbeforeunload = function () {
|
||||
if (editor.save_enabled && !editor.codemirror.isClean(editor.generation)) {
|
||||
return "Unsaved changes will be lost. Close anyway?";
|
||||
}
|
||||
};
|
||||
|
||||
// Make sure the codemirror editor is sized appropriately.
|
||||
var _handle_resize = function() {
|
||||
var backdrop = $("#texteditor-backdrop");
|
||||
|
||||
// account for padding on the backdrop wrapper
|
||||
var padding = backdrop.outerHeight(true) - backdrop.height();
|
||||
$('div.CodeMirror').height($("#site").height() - padding);
|
||||
};
|
||||
$(window).resize(_handle_resize);
|
||||
|
||||
// On document ready, resize codemirror.
|
||||
$(document).ready(_handle_resize);
|
||||
});
|
36930
venv/Lib/site-packages/notebook/static/edit/js/main.min.js
vendored
Normal file
36930
venv/Lib/site-packages/notebook/static/edit/js/main.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
167
venv/Lib/site-packages/notebook/static/edit/js/menubar.js
Normal file
167
venv/Lib/site-packages/notebook/static/edit/js/menubar.js
Normal file
|
@ -0,0 +1,167 @@
|
|||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'base/js/namespace',
|
||||
'base/js/utils',
|
||||
'base/js/dialog',
|
||||
'codemirror/lib/codemirror',
|
||||
'codemirror/mode/meta',
|
||||
], function($, IPython, utils, dialog, CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
var MenuBar = function (selector, options) {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* A MenuBar Class to generate the menubar of IPython notebook
|
||||
*
|
||||
* Parameters:
|
||||
* selector: string
|
||||
* options: dictionary
|
||||
* Dictionary of keyword arguments.
|
||||
* codemirror: CodeMirror instance
|
||||
* contents: ContentManager instance
|
||||
* events: $(Events) instance
|
||||
* base_url : string
|
||||
* file_path : string
|
||||
*/
|
||||
options = options || {};
|
||||
this.base_url = options.base_url || utils.get_body_data("baseUrl");
|
||||
this.selector = selector;
|
||||
this.editor = options.editor;
|
||||
this.events = options.events;
|
||||
this.save_widget = options.save_widget;
|
||||
|
||||
if (this.selector !== undefined) {
|
||||
this.element = $(selector);
|
||||
this.bind_events();
|
||||
}
|
||||
this._load_mode_menu();
|
||||
Object.seal(this);
|
||||
};
|
||||
|
||||
MenuBar.prototype.bind_events = function () {
|
||||
var that = this;
|
||||
var editor = that.editor;
|
||||
|
||||
// File
|
||||
this.element.find('#new-file').click(function () {
|
||||
var w = window.open(undefined, IPython._target);
|
||||
// Create a new file in the current directory
|
||||
var parent = utils.url_path_split(editor.file_path)[0];
|
||||
editor.contents.new_untitled(parent, {type: "file"}).then(
|
||||
function (data) {
|
||||
w.location = utils.url_path_join(
|
||||
that.base_url, 'edit', utils.encode_uri_components(data.path)
|
||||
);
|
||||
},
|
||||
function(error) {
|
||||
w.close();
|
||||
dialog.modal({
|
||||
title : 'Creating New File Failed',
|
||||
body : "The error was: " + error.message,
|
||||
buttons : {'OK' : {'class' : 'btn-primary'}}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
this.element.find('#save-file').click(function () {
|
||||
editor.save();
|
||||
});
|
||||
this.element.find('#rename-file').click(function () {
|
||||
that.save_widget.rename();
|
||||
});
|
||||
this.element.find('#download-file').click(function () {
|
||||
window.open(utils.url_path_join(
|
||||
that.base_url, 'files',
|
||||
utils.encode_uri_components(that.editor.file_path)
|
||||
) + '?download=1');
|
||||
});
|
||||
|
||||
// Edit
|
||||
this.element.find('#menu-find').click(function () {
|
||||
editor.codemirror.execCommand("find");
|
||||
});
|
||||
this.element.find('#menu-replace').click(function () {
|
||||
editor.codemirror.execCommand("replace");
|
||||
});
|
||||
this.element.find('#menu-keymap-default').click(function () {
|
||||
editor.update_codemirror_options({
|
||||
vimMode: false,
|
||||
keyMap: 'default'
|
||||
});
|
||||
});
|
||||
this.element.find('#menu-keymap-sublime').click(function () {
|
||||
editor.update_codemirror_options({
|
||||
vimMode: false,
|
||||
keyMap: 'sublime'
|
||||
});
|
||||
});
|
||||
this.element.find('#menu-keymap-emacs').click(function () {
|
||||
editor.update_codemirror_options({
|
||||
vimMode: false,
|
||||
keyMap: 'emacs'
|
||||
});
|
||||
});
|
||||
this.element.find('#menu-keymap-vim').click(function () {
|
||||
editor.update_codemirror_options({
|
||||
vimMode: true,
|
||||
keyMap: 'vim'
|
||||
});
|
||||
});
|
||||
|
||||
// View
|
||||
|
||||
this.element.find('#toggle_header').click(function (){
|
||||
$("#header-container").toggle();
|
||||
});
|
||||
|
||||
this.element.find('#menu-line-numbers').click(function () {
|
||||
var current = editor.codemirror.getOption('lineNumbers');
|
||||
var value = Boolean(1-current);
|
||||
editor.update_codemirror_options({lineNumbers: value});
|
||||
});
|
||||
|
||||
this.events.on("config_changed.Editor", function () {
|
||||
var keyMap = editor.codemirror.getOption('keyMap') || 'default';
|
||||
that.element.find(".selected-keymap").removeClass("selected-keymap");
|
||||
that.element.find("#menu-keymap-" + keyMap).addClass("selected-keymap");
|
||||
});
|
||||
|
||||
this.events.on("mode_changed.Editor", function (evt, modeinfo) {
|
||||
that.element.find("#current-mode")
|
||||
.text(modeinfo.name)
|
||||
.attr(
|
||||
'title',
|
||||
"The current language is " + modeinfo.name
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
MenuBar.prototype._load_mode_menu = function () {
|
||||
var list = this.element.find("#mode-menu");
|
||||
var editor = this.editor;
|
||||
function make_set_mode(info) {
|
||||
return function () {
|
||||
editor.set_codemirror_mode(info);
|
||||
// save codemirror mode for extension when explicitly selected
|
||||
editor.save_codemirror_mode(info);
|
||||
};
|
||||
}
|
||||
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
|
||||
var info = CodeMirror.modeInfo[i];
|
||||
list.append($("<li>").append(
|
||||
$("<a>").attr("href", "#")
|
||||
.text(info.name)
|
||||
.click(make_set_mode(info))
|
||||
.attr('title',
|
||||
"Set language to " + info.name
|
||||
)
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
return {'MenuBar': MenuBar};
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
define([
|
||||
'base/js/notificationarea'
|
||||
], function(notificationarea) {
|
||||
"use strict";
|
||||
var NotificationArea = notificationarea.NotificationArea;
|
||||
|
||||
var EditorNotificationArea = function(selector, options) {
|
||||
NotificationArea.apply(this, [selector, options]);
|
||||
}
|
||||
|
||||
EditorNotificationArea.prototype = Object.create(NotificationArea.prototype);
|
||||
|
||||
/**
|
||||
* Initialize the default set of notification widgets.
|
||||
*
|
||||
* @method init_notification_widgets
|
||||
*/
|
||||
EditorNotificationArea.prototype.init_notification_widgets = function () {
|
||||
var that = this;
|
||||
var savew = this.new_notification_widget('save');
|
||||
|
||||
this.events.on("file_saved.Editor", function() {
|
||||
savew.set_message("File saved", 2000);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return {EditorNotificationArea: EditorNotificationArea};
|
||||
});
|
192
venv/Lib/site-packages/notebook/static/edit/js/savewidget.js
Normal file
192
venv/Lib/site-packages/notebook/static/edit/js/savewidget.js
Normal file
|
@ -0,0 +1,192 @@
|
|||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'base/js/utils',
|
||||
'base/js/dialog',
|
||||
'base/js/keyboard',
|
||||
'moment',
|
||||
'bidi/bidi',
|
||||
], function($, utils, dialog, keyboard, moment, bidi) {
|
||||
"use strict";
|
||||
|
||||
var SaveWidget = function (selector, options) {
|
||||
this.editor = undefined;
|
||||
this.selector = selector;
|
||||
this.events = options.events;
|
||||
this.editor = options.editor;
|
||||
this._last_modified = undefined;
|
||||
this._filename = undefined;
|
||||
this.keyboard_manager = options.keyboard_manager;
|
||||
if (this.selector !== undefined) {
|
||||
this.element = $(selector);
|
||||
this.bind_events();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
SaveWidget.prototype.bind_events = function () {
|
||||
var that = this;
|
||||
this.element.find('span.filename').click(function () {
|
||||
that.rename();
|
||||
});
|
||||
this.events.on('save_status_clean.Editor', function (evt) {
|
||||
that.update_document_title();
|
||||
});
|
||||
this.events.on('save_status_dirty.Editor', function (evt) {
|
||||
that.update_document_title(undefined, true);
|
||||
});
|
||||
this.events.on('file_loaded.Editor', function (evt, model) {
|
||||
that.update_filename(model.name);
|
||||
that.update_document_title(model.name);
|
||||
that.update_last_modified(model.last_modified);
|
||||
});
|
||||
this.events.on('file_saved.Editor', function (evt, model) {
|
||||
that.update_filename(model.name);
|
||||
that.update_document_title(model.name);
|
||||
that.update_last_modified(model.last_modified);
|
||||
});
|
||||
this.events.on('file_renamed.Editor', function (evt, model) {
|
||||
that.update_filename(model.name);
|
||||
that.update_document_title(model.name);
|
||||
that.update_address_bar(model.path);
|
||||
});
|
||||
this.events.on('file_save_failed.Editor', function () {
|
||||
that.set_save_status('Save Failed!');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
SaveWidget.prototype.rename = function (options) {
|
||||
options = options || {};
|
||||
var that = this;
|
||||
var dialog_body = $('<div/>').append(
|
||||
$("<p/>").addClass("rename-message")
|
||||
.text('Enter a new filename:')
|
||||
).append(
|
||||
$("<br/>")
|
||||
).append(
|
||||
$('<input/>').attr('type','text').attr('size','25').addClass('form-control')
|
||||
.val(that.editor.get_filename())
|
||||
);
|
||||
var d = dialog.modal({
|
||||
title: "Rename File",
|
||||
body: dialog_body,
|
||||
default_button: "Cancel",
|
||||
buttons : {
|
||||
"Cancel": {},
|
||||
"OK": {
|
||||
class: "btn-primary",
|
||||
click: function () {
|
||||
var new_name = d.find('input').val();
|
||||
if (!new_name) {
|
||||
// Reset the message
|
||||
d.find('.rename-message').text("Enter a new filename:");
|
||||
return false;
|
||||
}
|
||||
d.find('.rename-message').text("Renaming...");
|
||||
d.find('input[type="text"]').prop('disabled', true);
|
||||
that.editor.rename(new_name).then(
|
||||
function () {
|
||||
d.modal('hide');
|
||||
}, function (error) {
|
||||
d.find('.rename-message').text(error.message || 'Unknown error');
|
||||
d.find('input[type="text"]').prop('disabled', false).focus().select();
|
||||
}
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
open : function () {
|
||||
// Upon ENTER, click the OK button.
|
||||
d.find('input[type="text"]').keydown(function (event) {
|
||||
if (event.which === keyboard.keycodes.enter) {
|
||||
d.find('.btn-primary').first().click();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
d.find('input[type="text"]').focus().select();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
SaveWidget.prototype.update_filename = function (filename) {
|
||||
filename = bidi.applyBidi(filename);
|
||||
this.element.find('span.filename').text(filename);
|
||||
};
|
||||
|
||||
SaveWidget.prototype.update_document_title = function (filename, dirty) {
|
||||
if(filename){
|
||||
this._filename = filename;
|
||||
}
|
||||
document.title = (dirty ? '*' : '') + this._filename + ' - Jupyter Text Editor';
|
||||
};
|
||||
|
||||
SaveWidget.prototype.update_address_bar = function (path) {
|
||||
var state = {path : path};
|
||||
window.history.replaceState(state, "", utils.url_path_join(
|
||||
this.editor.base_url,
|
||||
"edit",
|
||||
utils.encode_uri_components(path)
|
||||
));
|
||||
};
|
||||
|
||||
SaveWidget.prototype.update_last_modified = function (last_modified) {
|
||||
if (last_modified) {
|
||||
this._last_modified = new Date(last_modified);
|
||||
} else {
|
||||
this._last_modified = null;
|
||||
}
|
||||
this._render_last_modified();
|
||||
};
|
||||
|
||||
SaveWidget.prototype._render_last_modified = function () {
|
||||
/** actually set the text in the element, from our _last_modified value
|
||||
|
||||
called directly, and periodically in timeouts.
|
||||
*/
|
||||
this._schedule_render_last_modified();
|
||||
var el = this.element.find('span.last_modified');
|
||||
if (!this._last_modified) {
|
||||
el.text('').attr('title', 'never saved');
|
||||
return;
|
||||
}
|
||||
var chkd = moment(this._last_modified);
|
||||
var long_date = chkd.format('llll');
|
||||
var human_date;
|
||||
var tdelta = Math.ceil(new Date() - this._last_modified);
|
||||
if (tdelta < utils.time.milliseconds.d){
|
||||
// less than 24 hours old, use relative date
|
||||
human_date = chkd.fromNow();
|
||||
} else {
|
||||
// otherwise show calendar
|
||||
// <Today | yesterday|...> at hh,mm,ss
|
||||
human_date = chkd.calendar();
|
||||
}
|
||||
el.text(human_date).attr('title', long_date);
|
||||
};
|
||||
|
||||
SaveWidget.prototype._schedule_render_last_modified = function () {
|
||||
/** schedule the next update to relative date
|
||||
|
||||
periodically updated, so short values like 'a few seconds ago' don't get stale.
|
||||
*/
|
||||
if (!this._last_modified) {
|
||||
return;
|
||||
}
|
||||
if ((this._last_modified_timeout)) {
|
||||
clearTimeout(this._last_modified_timeout);
|
||||
}
|
||||
var dt = Math.ceil(new Date() - this._last_modified);
|
||||
this._last_modified_timeout = setTimeout(
|
||||
$.proxy(this._render_last_modified, this),
|
||||
utils.time.timeout_from_dt(dt)
|
||||
);
|
||||
};
|
||||
|
||||
return {'SaveWidget': SaveWidget};
|
||||
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue