[editor] mark unsaved changes

Put indicator before time, change title.

And cleanup implementation.
This commit is contained in:
Bussonnier Matthias 2015-01-25 14:27:59 +01:00 committed by Matthias Bussonnier
parent 22f8c7929d
commit 4513aae2b9
4 changed files with 115 additions and 3 deletions

View File

@ -25,12 +25,16 @@ function($,
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.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
@ -49,7 +53,11 @@ function($,
);
that._set_codemirror_options(cmopts);
that.events.trigger('config_changed.Editor', {config: that.config});
that._clean_state();
});
this.clean_sel = $('<div/>');
$('.last_modified').before(this.clean_sel);
this.clean_sel.addClass('dirty-indicator-dirty');
};
// default CodeMirror options
@ -78,6 +86,7 @@ function($,
that.save_enabled = true;
that.generation = cm.changeGeneration();
that.events.trigger("file_loaded.Editor", model);
that._clean_state();
}).catch(
function(error) {
that.events.trigger("file_load_failed.Editor", error);
@ -147,6 +156,7 @@ function($,
that.file_path = model.path;
that.events.trigger('file_renamed.Editor', model);
that._set_mode_for_model(model);
that._clean_state();
}
);
};
@ -169,9 +179,26 @@ function($,
that.events.trigger("file_saving.Editor");
return this.contents.save(this.file_path, model).then(function(data) {
that.events.trigger("file_saved.Editor", data);
that._clean_state();
});
};
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;
@ -181,6 +208,7 @@ function($,
}
codemirror.setOption(opt, value);
});
var that = this;
};
Editor.prototype.update_codemirror_options = function (options) {

View File

@ -17,6 +17,7 @@ define([
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);
@ -30,6 +31,12 @@ define([
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);
@ -104,8 +111,11 @@ define([
this.element.find('span.filename').text(filename);
};
SaveWidget.prototype.update_document_title = function (filename) {
document.title = filename;
SaveWidget.prototype.update_document_title = function (filename, dirty) {
if(filename){
this._filename = filename;
}
document.title = (dirty?'*':'')+this._filename;
};
SaveWidget.prototype.update_address_bar = function (path) {

View File

@ -1,3 +1,17 @@
.dirty-indicator{
.fa();
width:20px;
}
.dirty-indicator-dirty{
.dirty-indicator();
}
.dirty-indicator-clean{
.dirty-indicator();
&:before{
.icon(@fa-var-check);
}
}
#filename {
font-size: 16pt;

View File

@ -8870,6 +8870,66 @@ ul#new-menu {
header */
margin-bottom: -1px;
}
.dirty-indicator {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 20px;
}
.dirty-indicator.pull-left {
margin-right: .3em;
}
.dirty-indicator.pull-right {
margin-left: .3em;
}
.dirty-indicator-dirty {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 20px;
}
.dirty-indicator-dirty.pull-left {
margin-right: .3em;
}
.dirty-indicator-dirty.pull-right {
margin-left: .3em;
}
.dirty-indicator-clean {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 20px;
}
.dirty-indicator-clean.pull-left {
margin-right: .3em;
}
.dirty-indicator-clean.pull-right {
margin-left: .3em;
}
.dirty-indicator-clean:before {
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
content: "\f00c";
}
.dirty-indicator-clean:before.pull-left {
margin-right: .3em;
}
.dirty-indicator-clean:before.pull-right {
margin-left: .3em;
}
#filename {
font-size: 16pt;
display: table;