##// END OF EJS Templates
[editor] mark unsaved changes...
Bussonnier Matthias -
Show More
@@ -25,12 +25,16 function($,
25 var Editor = function(selector, options) {
25 var Editor = function(selector, options) {
26 var that = this;
26 var that = this;
27 this.selector = selector;
27 this.selector = selector;
28 this.clean = false;
28 this.contents = options.contents;
29 this.contents = options.contents;
29 this.events = options.events;
30 this.events = options.events;
30 this.base_url = options.base_url;
31 this.base_url = options.base_url;
31 this.file_path = options.file_path;
32 this.file_path = options.file_path;
32 this.config = options.config;
33 this.config = options.config;
33 this.codemirror = new CodeMirror($(this.selector)[0]);
34 this.codemirror = new CodeMirror($(this.selector)[0]);
35 this.codemirror.on('changes', function(cm, changes){
36 that._clean_state();
37 });
34 this.generation = -1;
38 this.generation = -1;
35
39
36 // It appears we have to set commands on the CodeMirror class, not the
40 // It appears we have to set commands on the CodeMirror class, not the
@@ -49,7 +53,11 function($,
49 );
53 );
50 that._set_codemirror_options(cmopts);
54 that._set_codemirror_options(cmopts);
51 that.events.trigger('config_changed.Editor', {config: that.config});
55 that.events.trigger('config_changed.Editor', {config: that.config});
56 that._clean_state();
52 });
57 });
58 this.clean_sel = $('<div/>');
59 $('.last_modified').before(this.clean_sel);
60 this.clean_sel.addClass('dirty-indicator-dirty');
53 };
61 };
54
62
55 // default CodeMirror options
63 // default CodeMirror options
@@ -78,6 +86,7 function($,
78 that.save_enabled = true;
86 that.save_enabled = true;
79 that.generation = cm.changeGeneration();
87 that.generation = cm.changeGeneration();
80 that.events.trigger("file_loaded.Editor", model);
88 that.events.trigger("file_loaded.Editor", model);
89 that._clean_state();
81 }).catch(
90 }).catch(
82 function(error) {
91 function(error) {
83 that.events.trigger("file_load_failed.Editor", error);
92 that.events.trigger("file_load_failed.Editor", error);
@@ -147,6 +156,7 function($,
147 that.file_path = model.path;
156 that.file_path = model.path;
148 that.events.trigger('file_renamed.Editor', model);
157 that.events.trigger('file_renamed.Editor', model);
149 that._set_mode_for_model(model);
158 that._set_mode_for_model(model);
159 that._clean_state();
150 }
160 }
151 );
161 );
152 };
162 };
@@ -169,9 +179,26 function($,
169 that.events.trigger("file_saving.Editor");
179 that.events.trigger("file_saving.Editor");
170 return this.contents.save(this.file_path, model).then(function(data) {
180 return this.contents.save(this.file_path, model).then(function(data) {
171 that.events.trigger("file_saved.Editor", data);
181 that.events.trigger("file_saved.Editor", data);
182 that._clean_state();
172 });
183 });
173 };
184 };
174
185
186 Editor.prototype._clean_state = function(){
187 var clean = this.codemirror.isClean(this.generation);
188 if (clean === this.clean){
189 return
190 } else {
191 this.clean = clean;
192 }
193 if(clean){
194 this.events.trigger("save_status_clean.Editor");
195 this.clean_sel.attr('class','dirty-indicator-clean').attr('title','No changes to save');
196 } else {
197 this.events.trigger("save_status_dirty.Editor");
198 this.clean_sel.attr('class','dirty-indicator-dirty').attr('title','Unsaved changes');
199 }
200 };
201
175 Editor.prototype._set_codemirror_options = function (options) {
202 Editor.prototype._set_codemirror_options = function (options) {
176 // update codemirror options from a dict
203 // update codemirror options from a dict
177 var codemirror = this.codemirror;
204 var codemirror = this.codemirror;
@@ -181,6 +208,7 function($,
181 }
208 }
182 codemirror.setOption(opt, value);
209 codemirror.setOption(opt, value);
183 });
210 });
211 var that = this;
184 };
212 };
185
213
186 Editor.prototype.update_codemirror_options = function (options) {
214 Editor.prototype.update_codemirror_options = function (options) {
@@ -17,6 +17,7 define([
17 this.events = options.events;
17 this.events = options.events;
18 this.editor = options.editor;
18 this.editor = options.editor;
19 this._last_modified = undefined;
19 this._last_modified = undefined;
20 this._filename = undefined;
20 this.keyboard_manager = options.keyboard_manager;
21 this.keyboard_manager = options.keyboard_manager;
21 if (this.selector !== undefined) {
22 if (this.selector !== undefined) {
22 this.element = $(selector);
23 this.element = $(selector);
@@ -30,6 +31,12 define([
30 this.element.find('span.filename').click(function () {
31 this.element.find('span.filename').click(function () {
31 that.rename();
32 that.rename();
32 });
33 });
34 this.events.on('save_status_clean.Editor', function (evt) {
35 that.update_document_title();
36 });
37 this.events.on('save_status_dirty.Editor', function (evt) {
38 that.update_document_title(undefined, true);
39 });
33 this.events.on('file_loaded.Editor', function (evt, model) {
40 this.events.on('file_loaded.Editor', function (evt, model) {
34 that.update_filename(model.name);
41 that.update_filename(model.name);
35 that.update_document_title(model.name);
42 that.update_document_title(model.name);
@@ -104,8 +111,11 define([
104 this.element.find('span.filename').text(filename);
111 this.element.find('span.filename').text(filename);
105 };
112 };
106
113
107 SaveWidget.prototype.update_document_title = function (filename) {
114 SaveWidget.prototype.update_document_title = function (filename, dirty) {
108 document.title = filename;
115 if(filename){
116 this._filename = filename;
117 }
118 document.title = (dirty?'*':'')+this._filename;
109 };
119 };
110
120
111 SaveWidget.prototype.update_address_bar = function (path) {
121 SaveWidget.prototype.update_address_bar = function (path) {
@@ -1,3 +1,17
1 .dirty-indicator{
2 .fa();
3 width:20px;
4 }
5 .dirty-indicator-dirty{
6 .dirty-indicator();
7 }
8
9 .dirty-indicator-clean{
10 .dirty-indicator();
11 &:before{
12 .icon(@fa-var-check);
13 }
14 }
1
15
2 #filename {
16 #filename {
3 font-size: 16pt;
17 font-size: 16pt;
@@ -8870,6 +8870,66 ul#new-menu {
8870 header */
8870 header */
8871 margin-bottom: -1px;
8871 margin-bottom: -1px;
8872 }
8872 }
8873 .dirty-indicator {
8874 display: inline-block;
8875 font: normal normal normal 14px/1 FontAwesome;
8876 font-size: inherit;
8877 text-rendering: auto;
8878 -webkit-font-smoothing: antialiased;
8879 -moz-osx-font-smoothing: grayscale;
8880 width: 20px;
8881 }
8882 .dirty-indicator.pull-left {
8883 margin-right: .3em;
8884 }
8885 .dirty-indicator.pull-right {
8886 margin-left: .3em;
8887 }
8888 .dirty-indicator-dirty {
8889 display: inline-block;
8890 font: normal normal normal 14px/1 FontAwesome;
8891 font-size: inherit;
8892 text-rendering: auto;
8893 -webkit-font-smoothing: antialiased;
8894 -moz-osx-font-smoothing: grayscale;
8895 width: 20px;
8896 }
8897 .dirty-indicator-dirty.pull-left {
8898 margin-right: .3em;
8899 }
8900 .dirty-indicator-dirty.pull-right {
8901 margin-left: .3em;
8902 }
8903 .dirty-indicator-clean {
8904 display: inline-block;
8905 font: normal normal normal 14px/1 FontAwesome;
8906 font-size: inherit;
8907 text-rendering: auto;
8908 -webkit-font-smoothing: antialiased;
8909 -moz-osx-font-smoothing: grayscale;
8910 width: 20px;
8911 }
8912 .dirty-indicator-clean.pull-left {
8913 margin-right: .3em;
8914 }
8915 .dirty-indicator-clean.pull-right {
8916 margin-left: .3em;
8917 }
8918 .dirty-indicator-clean:before {
8919 display: inline-block;
8920 font: normal normal normal 14px/1 FontAwesome;
8921 font-size: inherit;
8922 text-rendering: auto;
8923 -webkit-font-smoothing: antialiased;
8924 -moz-osx-font-smoothing: grayscale;
8925 content: "\f00c";
8926 }
8927 .dirty-indicator-clean:before.pull-left {
8928 margin-right: .3em;
8929 }
8930 .dirty-indicator-clean:before.pull-right {
8931 margin-left: .3em;
8932 }
8873 #filename {
8933 #filename {
8874 font-size: 16pt;
8934 font-size: 16pt;
8875 display: table;
8935 display: table;
General Comments 0
You need to be logged in to leave comments. Login now