Do you want to cancel editing and lose unsaved changes?
diff --git a/app/app/components/section/base-editor-inline.js b/app/app/components/section/base-editor-inline.js index ce968fc1..2ce3a97a 100644 --- a/app/app/components/section/base-editor-inline.js +++ b/app/app/components/section/base-editor-inline.js @@ -18,7 +18,6 @@ const { export default Ember.Component.extend({ drop: null, - tip: "Short and concise title", busy: false, hasNameError: computed.empty('page.title'), @@ -26,6 +25,14 @@ export default Ember.Component.extend({ let page = this.get('page'); return `page-editor-${page.id}`; }), + cancelId: Ember.computed('page', function () { + let page = this.get('page'); + return `cancel-edits-button-${page.id}`; + }), + dialogId: Ember.computed('page', function () { + let page = this.get('page'); + return `discard-edits-dialog-${page.id}`; + }), didRender() { let self = this; @@ -54,16 +61,16 @@ export default Ember.Component.extend({ actions: { onCancel() { if (this.attrs.isDirty() !== null && this.attrs.isDirty()) { - $(".discard-edits-dialog").css("display", "block"); - - let page = this.get('page'); + $('#' + this.get('dialogId')).css("display", "block"); let drop = new Drop({ - target: $("#editor-cancel" + page.get('id'))[0], - content: $(".cancel-edits-dialog-" + page.get('id'))[0], + target: $('#' + this.get('cancelId'))[0], + content: $('#' + this.get('dialogId'))[0], classes: 'drop-theme-basic', position: "bottom right", openOn: "always", + constrainToWindow: true, + constrainToScrollParent: false, tetherOptions: { offset: "5px 0", targetOffset: "10px 0" @@ -80,11 +87,7 @@ export default Ember.Component.extend({ }, onAction() { - if (this.get('busy')) { - return; - } - - if (is.empty(this.get('page.title'))) { + if (this.get('busy') || is.empty(this.get('page.title'))) { return; } diff --git a/app/app/components/section/code/type-editor.js b/app/app/components/section/code/type-editor.js index dc7e5b78..2bf87e5a 100644 --- a/app/app/components/section/code/type-editor.js +++ b/app/app/components/section/code/type-editor.js @@ -15,9 +15,9 @@ import TooltipMixin from '../../../mixins/tooltip'; export default Ember.Component.extend(TooltipMixin, { isDirty: false, pageBody: "", - codeEditor: null, syntaxOptions: [], codeSyntax: null, + codeEditor: null, editorId: Ember.computed('page', function () { let page = this.get('page'); return `code-editor-${page.id}`; @@ -116,7 +116,7 @@ export default Ember.Component.extend(TooltipMixin, { }, isDirty() { - return this.get('isDirty'); + return this.get('isDirty') || (this.get('codeEditor').getDoc().isClean() === false); }, onCancel() { diff --git a/app/app/components/section/markdown/type-editor.js b/app/app/components/section/markdown/type-editor.js index 6728c85d..f532be08 100644 --- a/app/app/components/section/markdown/type-editor.js +++ b/app/app/components/section/markdown/type-editor.js @@ -10,7 +10,6 @@ // https://documize.com import Ember from 'ember'; -import miscUtil from '../../../utils/misc'; import TooltipMixin from '../../../mixins/tooltip'; const { @@ -19,10 +18,12 @@ const { export default Ember.Component.extend(TooltipMixin, { link: service(), - editMode: true, - isDirty: false, pageBody: "", pagePreview: "", + editMode: true, + codeSyntax: null, + codeEditor: null, + editorId: Ember.computed('page', function () { let page = this.get('page'); return `markdown-editor-${page.id}`; @@ -36,23 +37,89 @@ export default Ember.Component.extend(TooltipMixin, { return `markdown-tooltip-${page.id}`; }), - didReceiveAttrs() { - this.set("pageBody", this.get("meta.rawBody")); - }, + init() { + this._super(...arguments); + + let self = this; + CodeMirror.modeURL = "/codemirror/mode/%N/%N.js"; + + let rawBody = this.get('meta.rawBody'); + let cleanBody = rawBody.replace("", ""); + + cleanBody = cleanBody.replace('
'); + let syntax = { + mode: "markdown", + name: "Markdown" + }; + + if (startPos !== -1) { + syntax = cleanBody.substring(0, startPos); + cleanBody = cleanBody.substring(startPos + 2); + } + + this.set('pageBody', cleanBody); + + let opts = []; + + _.each(_.sortBy(CodeMirror.modeInfo, 'name'), function(item) { + let i = { + mode: item.mode, + name: item.name + }; + opts.pushObject(i); + + if (item.mode === syntax) { + self.set('codeSyntax', i); + } + }); + + this.set('syntaxOptions', opts); + + // default check + if (is.null(this.get("codeSyntax"))) { + this.set("codeSyntax", opts.findBy("mode", "markdown")); + } + }, didInsertElement() { - $("#" + this.get('editorId')).off("keyup").on("keyup", () => { - this.set('isDirty', true); - }); + this.attachEditor(); + }, + + willDestroyElement() { + this.set('codeEditor', null); + this.destroyTooltips(); + // $("#" + this.get('editorId')).off("keyup"); + }, + + getBody() { + return this.get('codeEditor').getDoc().getValue(); }, didRender() { this.addTooltip(document.getElementById(this.get('tooltipId'))); }, - willDestroyElement() { - this.destroyTooltips(); - $("#" + this.get('editorId')).off("keyup"); + attachEditor() { + var editor = CodeMirror.fromTextArea(document.getElementById(this.get('editorId')), { + theme: "solarized light", + lineNumbers: true, + lineWrapping: true, + indentUnit: 4, + tabSize: 4, + value: "", + dragDrop: false, + extraKeys: {"Enter": "newlineAndIndentContinueMarkdownList"} + }); + + this.set('codeEditor', editor); + + let syntax = this.get("codeSyntax"); + + if (is.not.undefined(syntax)) { + CodeMirror.autoLoadMode(editor, syntax.mode); + editor.setOption("mode", syntax.mode); + } }, actions: { @@ -61,12 +128,10 @@ export default Ember.Component.extend(TooltipMixin, { Ember.run.schedule('afterRender', () => { if (this.get('editMode')) { - $("#" + this.get('editorId')).off("keyup").on("keyup", () => { - this.set('isDirty', true); - }); + this.attachEditor(); } else { let md = window.markdownit({ linkify: true }); - let result = md.render(this.get("pageBody")); + let result = md.render(this.getBody()); this.set('pagePreview', result); } @@ -75,15 +140,13 @@ export default Ember.Component.extend(TooltipMixin, { onInsertLink(link) { let linkMarkdown = this.get('link').buildLink(link); - - miscUtil.insertAtCursor($("#" + this.get('editorId'))[0], linkMarkdown); - this.set('pageBody', $("#" + this.get('editorId')).val()); + this.get('codeEditor').getDoc().replaceSelection(linkMarkdown); return true; }, isDirty() { - return this.get('isDirty'); + return this.get('codeEditor').getDoc().isClean() === false; }, onCancel() { @@ -94,7 +157,7 @@ export default Ember.Component.extend(TooltipMixin, { let page = this.get('page'); let meta = this.get('meta'); page.set('title', title); - meta.set('rawBody', this.get("pageBody")); + meta.set('rawBody', this.getBody()); this.attrs.onAction(page, meta); } diff --git a/app/app/styles/section/markdown.scss b/app/app/styles/section/markdown.scss index c2ef35f8..b0546d64 100644 --- a/app/app/styles/section/markdown.scss +++ b/app/app/styles/section/markdown.scss @@ -1,4 +1,4 @@ -.section-markdown-editor, .section-markdown-preview { +.section-markdown-preview { width: 100%; margin: 0; padding: 0; diff --git a/app/app/templates/components/section/base-editor-inline.hbs b/app/app/templates/components/section/base-editor-inline.hbs index 8437a3dc..d853d78e 100644 --- a/app/app/templates/components/section/base-editor-inline.hbs +++ b/app/app/templates/components/section/base-editor-inline.hbs @@ -1,7 +1,7 @@