From bd45759d155b2f9e57110d6a24893f9e1a4ef7e8 Mon Sep 17 00:00:00 2001 From: Bill Yang Date: Wed, 17 Feb 2016 08:42:06 -0700 Subject: [PATCH] resolve issue #229, when clicking bold/italic button on empty lines, highlight those buttons properly. also make undo button delete whole word/sentence as opposed to one character at a time --- dist/tinymce.min.js | 2 +- src/tinymce.js | 9 +++------ test/tinymce.spec.js | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/dist/tinymce.min.js b/dist/tinymce.min.js index 1b09271..e463890 100644 --- a/dist/tinymce.min.js +++ b/dist/tinymce.min.js @@ -1 +1 @@ -angular.module("ui.tinymce",[]).value("uiTinymceConfig",{}).directive("uiTinymce",["$rootScope","$compile","$timeout","$window","$sce","uiTinymceConfig",function(a,b,c,d,e,f){f=f||{};var g=0,h="ui-tinymce";return f.baseUrl&&(tinymce.baseURL=f.baseUrl),{require:["ngModel","^?form"],priority:999,link:function(i,j,k,l){function m(a){a?(n(),p&&p.getBody().setAttribute("contenteditable",!1)):(n(),p&&!p.settings.readonly&&p.getBody().setAttribute("contenteditable",!0))}function n(){p||(p=tinymce.get(k.id))}if(d.tinymce){var o,p,q=l[0],r=l[1]||null,s={},t=function(b){var c=b.getContent({format:s.format}).trim();c=e.trustAsHtml(c),q.$setViewValue(c),a.$$phase||i.$digest()};k.$set("id",h+"-"+g++),o={},angular.extend(o,i.$eval(k.uiTinymce));var u=function(a){var b;return function(d){c.cancel(b),b=c(function(){return function(a){a.save(),t(a)}(d)},a)}}(400),v={setup:function(a){a.on("init",function(){q.$render(),q.$setPristine(),q.$setUntouched(),r&&r.$setPristine()}),a.on("ExecCommand change NodeChange ObjectResized",function(){u(a)}),a.on("blur",function(){j[0].blur(),q.$setTouched(),i.$digest()}),a.on("remove",function(){j.remove()}),o.setup&&o.setup(a,{updateView:t})},format:o.format||"html",selector:"#"+k.id};angular.extend(s,f,o,v),c(function(){s.baseURL&&(tinymce.baseURL=s.baseURL),tinymce.init(s),m(i.$eval(k.ngDisabled))}),q.$formatters.unshift(function(a){return a?e.trustAsHtml(a):""}),q.$parsers.unshift(function(a){return a?e.getTrustedHtml(a):""}),q.$render=function(){n();var a=q.$viewValue?e.getTrustedHtml(q.$viewValue):"";p&&p.getDoc()&&(p.setContent(a),p.fire("change"))},k.$observe("disabled",m),i.$on("$tinymce:refresh",function(a,c){var d=k.id;if(angular.isUndefined(c)||c===d){var e=j.parent(),f=j.clone();f.removeAttr("id"),f.removeAttr("style"),f.removeAttr("aria-hidden"),tinymce.execCommand("mceRemoveEditor",!1,d),e.append(b(f)(i))}}),i.$on("$destroy",function(){n(),p&&(p.remove(),p=null)})}}}}]); \ No newline at end of file +angular.module("ui.tinymce",[]).value("uiTinymceConfig",{}).directive("uiTinymce",["$rootScope","$compile","$timeout","$window","$sce","uiTinymceConfig",function(a,b,c,d,e,f){f=f||{};var g=0,h="ui-tinymce";return f.baseUrl&&(tinymce.baseURL=f.baseUrl),{require:["ngModel","^?form"],priority:999,link:function(i,j,k,l){function m(a){a?(n(),p&&p.getBody().setAttribute("contenteditable",!1)):(n(),p&&!p.settings.readonly&&p.getBody().setAttribute("contenteditable",!0))}function n(){p||(p=tinymce.get(k.id))}if(d.tinymce){var o,p,q=l[0],r=l[1]||null,s={},t=function(b){var c=b.getContent({format:s.format,no_events:!0}).trim();c=e.trustAsHtml(c),q.$setViewValue(c),a.$$phase||i.$digest()};k.$set("id",h+"-"+g++),o={},angular.extend(o,i.$eval(k.uiTinymce));var u=function(a){var b;return function(d){c.cancel(b),b=c(function(){t(d)},a)}}(400),v={setup:function(a){a.on("init",function(){q.$render(),q.$setPristine(),q.$setUntouched(),r&&r.$setPristine()}),a.on("ExecCommand KeyUp NodeChange ObjectResized",function(b){u(a)}),a.on("blur",function(){j[0].blur(),q.$setTouched(),i.$digest()}),a.on("remove",function(){j.remove()}),o.setup&&o.setup(a,{updateView:t})},format:o.format||"html",selector:"#"+k.id};angular.extend(s,f,o,v),c(function(){s.baseURL&&(tinymce.baseURL=s.baseURL),tinymce.init(s),m(i.$eval(k.ngDisabled))}),q.$formatters.unshift(function(a){return a?e.trustAsHtml(a):""}),q.$parsers.unshift(function(a){return a?e.getTrustedHtml(a):""}),q.$render=function(){n();var a=q.$viewValue?e.getTrustedHtml(q.$viewValue):"";p&&p.getDoc()&&(p.setContent(a),p.fire("change"))},k.$observe("disabled",m),i.$on("$tinymce:refresh",function(a,c){var d=k.id;if(angular.isUndefined(c)||c===d){var e=j.parent(),f=j.clone();f.removeAttr("id"),f.removeAttr("style"),f.removeAttr("aria-hidden"),tinymce.execCommand("mceRemoveEditor",!1,d),e.append(b(f)(i))}}),i.$on("$destroy",function(){n(),p&&(p.remove(),p=null)})}}}}]); \ No newline at end of file diff --git a/src/tinymce.js b/src/tinymce.js index 9381a10..bc06ab6 100644 --- a/src/tinymce.js +++ b/src/tinymce.js @@ -24,7 +24,7 @@ angular.module('ui.tinymce', []) var expression, options = {}, tinyInstance, updateView = function(editor) { - var content = editor.getContent({format: options.format}).trim(); + var content = editor.getContent({format: options.format, no_events: true}).trim(); content = $sce.trustAsHtml(content); ngModel.$setViewValue(content); @@ -62,10 +62,7 @@ angular.module('ui.tinymce', []) return function(ed) { $timeout.cancel(debouncedUpdateTimer); debouncedUpdateTimer = $timeout(function() { - return (function(ed) { - ed.save(); updateView(ed); - })(ed); }, debouncedUpdateDelay); }; })(400); @@ -85,10 +82,10 @@ angular.module('ui.tinymce', []) // Update model when: // - a button has been clicked [ExecCommand] - // - the editor content has been modified [change] + // - the editor content has been modified [KeyUp] // - the node has changed [NodeChange] // - an object has been resized (table, image) [ObjectResized] - ed.on('ExecCommand change NodeChange ObjectResized', function() { + ed.on('ExecCommand KeyUp NodeChange ObjectResized', function(e) { debouncedUpdate(ed); }); diff --git a/test/tinymce.spec.js b/test/tinymce.spec.js index d50175b..09b65e0 100644 --- a/test/tinymce.spec.js +++ b/test/tinymce.spec.js @@ -73,6 +73,30 @@ describe('uiTinymce', function () { element.find("textarea").triggerHandler("blur"); expect(directiveElement.controller('ngModel').$touched).toBe(true); }); + + it('should not trigger event on KeyUp', function() { + compile(); + + var editor = tinymce.editors[1]; + spyOn(editor, 'getContent').and.callThrough(); + editor.fire('KeyUp'); + $timeout.flush(); + + expect(editor.getContent.calls.count()).toEqual(1); + expect(editor.getContent.calls.argsFor(0)[0].no_events).toBe(true); + }); + + it('should not trigger event on ExecCommand', function() { + compile(); + + var editor = tinymce.editors[1]; + spyOn(editor, 'getContent').and.callThrough(); + editor.fire('ExecCommand'); + $timeout.flush(); + + expect(editor.getContent.calls.count()).toEqual(1); + expect(editor.getContent.calls.argsFor(0)[0].no_events).toBe(true); + }); it('should remove tinymce instance on $scope destruction', function() { compile();