diff --git a/README.md b/README.md index fe3ddbc..96fe495 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ In addition, it supports these additional optional options - `format` Format to get content as, i.e. 'raw' for raw HTML, or 'text' for text only. Defaults to 'html'. Documentation [here](http://www.tinymce.com/wiki.php/api4:method.tinymce.Editor.getContent) - `trusted` When `true`, all TinyMCE content that is set to `ngModel` will be whitelisted by `$sce` - `baseURL` This will set [baseURL property on the EditorManager](https://www.tinymce.com/docs/api/class/tinymce.editormanager/) +- `debounce` This will debounce the model update which helps with performance of editors with large text. Defaults to true. This option is only supported when present on the `uiTinymceConfig` global injectable - this injectable needs to be an object. diff --git a/dist/tinymce.min.js b/dist/tinymce.min.js index debf488..cecd364 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:599,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.isDirty()&&(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()}),f.setup&&f.setup(a,{updateView:t}),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:599,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={debounce:!0},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.isDirty()&&(a.save(),t(a))}(d)},a)}}(400),v={setup:function(b){b.on("init",function(){q.$render(),q.$setPristine(),q.$setUntouched(),r&&r.$setPristine()}),b.on("ExecCommand change NodeChange ObjectResized",function(){return s.debounce?void u(b):(b.save(),void t(b))}),b.on("blur",function(){j[0].blur(),q.$setTouched(),a.$$phase||i.$digest()}),b.on("remove",function(){j.remove()}),f.setup&&f.setup(b,{updateView:t}),o.setup&&o.setup(b,{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 139d51c..1ce5c6e 100644 --- a/src/tinymce.js +++ b/src/tinymce.js @@ -22,7 +22,9 @@ angular.module('ui.tinymce', []) var ngModel = ctrls[0], form = ctrls[1] || null; - var expression, options = {}, tinyInstance, + var expression, options = { + debounce: true + }, tinyInstance, updateView = function(editor) { var content = editor.getContent({format: options.format}).trim(); content = $sce.trustAsHtml(content); @@ -79,7 +81,7 @@ angular.module('ui.tinymce', []) ed.on('init', function() { ngModel.$render(); ngModel.$setPristine(); - ngModel.$setUntouched(); + ngModel.$setUntouched(); if (form) { form.$setPristine(); } @@ -91,13 +93,20 @@ angular.module('ui.tinymce', []) // - the node has changed [NodeChange] // - an object has been resized (table, image) [ObjectResized] ed.on('ExecCommand change NodeChange ObjectResized', function() { + if (!options.debounce) { + ed.save(); + updateView(ed); + return; + } debouncedUpdate(ed); }); ed.on('blur', function() { element[0].blur(); ngModel.$setTouched(); - scope.$digest(); + if (!$rootScope.$$phase) { + scope.$digest(); + } }); ed.on('remove', function() {