Show More
@@ -25,12 +25,16 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 |
|
|
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 b'' | |||||
|
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; |
@@ -8902,6 +8902,66 b' ul#new-menu {' | |||||
8902 | header */ |
|
8902 | header */ | |
8903 | margin-bottom: -1px; |
|
8903 | margin-bottom: -1px; | |
8904 | } |
|
8904 | } | |
|
8905 | .dirty-indicator { | |||
|
8906 | display: inline-block; | |||
|
8907 | font: normal normal normal 14px/1 FontAwesome; | |||
|
8908 | font-size: inherit; | |||
|
8909 | text-rendering: auto; | |||
|
8910 | -webkit-font-smoothing: antialiased; | |||
|
8911 | -moz-osx-font-smoothing: grayscale; | |||
|
8912 | width: 20px; | |||
|
8913 | } | |||
|
8914 | .dirty-indicator.pull-left { | |||
|
8915 | margin-right: .3em; | |||
|
8916 | } | |||
|
8917 | .dirty-indicator.pull-right { | |||
|
8918 | margin-left: .3em; | |||
|
8919 | } | |||
|
8920 | .dirty-indicator-dirty { | |||
|
8921 | display: inline-block; | |||
|
8922 | font: normal normal normal 14px/1 FontAwesome; | |||
|
8923 | font-size: inherit; | |||
|
8924 | text-rendering: auto; | |||
|
8925 | -webkit-font-smoothing: antialiased; | |||
|
8926 | -moz-osx-font-smoothing: grayscale; | |||
|
8927 | width: 20px; | |||
|
8928 | } | |||
|
8929 | .dirty-indicator-dirty.pull-left { | |||
|
8930 | margin-right: .3em; | |||
|
8931 | } | |||
|
8932 | .dirty-indicator-dirty.pull-right { | |||
|
8933 | margin-left: .3em; | |||
|
8934 | } | |||
|
8935 | .dirty-indicator-clean { | |||
|
8936 | display: inline-block; | |||
|
8937 | font: normal normal normal 14px/1 FontAwesome; | |||
|
8938 | font-size: inherit; | |||
|
8939 | text-rendering: auto; | |||
|
8940 | -webkit-font-smoothing: antialiased; | |||
|
8941 | -moz-osx-font-smoothing: grayscale; | |||
|
8942 | width: 20px; | |||
|
8943 | } | |||
|
8944 | .dirty-indicator-clean.pull-left { | |||
|
8945 | margin-right: .3em; | |||
|
8946 | } | |||
|
8947 | .dirty-indicator-clean.pull-right { | |||
|
8948 | margin-left: .3em; | |||
|
8949 | } | |||
|
8950 | .dirty-indicator-clean:before { | |||
|
8951 | display: inline-block; | |||
|
8952 | font: normal normal normal 14px/1 FontAwesome; | |||
|
8953 | font-size: inherit; | |||
|
8954 | text-rendering: auto; | |||
|
8955 | -webkit-font-smoothing: antialiased; | |||
|
8956 | -moz-osx-font-smoothing: grayscale; | |||
|
8957 | content: "\f00c"; | |||
|
8958 | } | |||
|
8959 | .dirty-indicator-clean:before.pull-left { | |||
|
8960 | margin-right: .3em; | |||
|
8961 | } | |||
|
8962 | .dirty-indicator-clean:before.pull-right { | |||
|
8963 | margin-left: .3em; | |||
|
8964 | } | |||
8905 | #filename { |
|
8965 | #filename { | |
8906 | font-size: 16pt; |
|
8966 | font-size: 16pt; | |
8907 | display: table; |
|
8967 | display: table; |
General Comments 0
You need to be logged in to leave comments.
Login now