diff --git a/bower.json b/bower.json index a7a62a6..73948ba 100644 --- a/bower.json +++ b/bower.json @@ -1,9 +1,9 @@ { "name": "angular-medium-editor", - "version": "0.1.1", + "version": "1.1.0", "dependencies": { "angular": "1.3.*", - "medium-editor": "4.4.*" + "medium-editor": "5.*" }, "main": "./dist/angular-medium-editor.js" } diff --git a/demo/interactive.html b/demo/interactive.html new file mode 100644 index 0000000..83a511a --- /dev/null +++ b/demo/interactive.html @@ -0,0 +1,39 @@ + + + + + angularjs medium editor | demo + + + + + + + +
+

Medium Editor for AngularJS

+

Type Here:

+
+
+
+ +

Validation:

+
{{demo.text.$error}}
+

Model:

+
{{text}}
+
+ + + + + + + diff --git a/dist/angular-medium-editor.js b/dist/angular-medium-editor.js index b10bb54..213caa0 100644 --- a/dist/angular-medium-editor.js +++ b/dist/angular-medium-editor.js @@ -1,84 +1,51 @@ +/*global MediumEditor */ 'use strict'; angular.module('angular-medium-editor', []) .directive('mediumEditor', function() { + function toInnerText(value) { + var tempEl = document.createElement('div'), + text; + tempEl.innerHTML = value; + text = tempEl.textContent || ''; + return text.trim(); + } + return { require: 'ngModel', restrict: 'AE', scope: { bindOptions: '=' }, - link: function(scope, iElement, iAttrs, ctrl) { + link: function(scope, iElement, iAttrs, ngModel) { angular.element(iElement).addClass('angular-medium-editor'); - // Parse options - var opts = {}, - placeholder = ''; - var prepOpts = function() { - if (iAttrs.options) { - opts = scope.$eval(iAttrs.options); - } - var bindOpts = {}; - if (scope.bindOptions !== undefined) { - bindOpts = scope.bindOptions; - } - opts = angular.extend(opts, bindOpts); - }; - prepOpts(); - placeholder = opts.placeholder; - scope.$watch('bindOptions', function() { - // in case options are provided after mediumEditor directive has been compiled and linked (and after $render function executed) - // we need to re-initialize - if (ctrl.editor) { - ctrl.editor.destroy(); - } - prepOpts(); - // Hide placeholder when the model is not empty - if (!ctrl.$isEmpty(ctrl.$viewValue)) { - opts.placeholder = ''; - } - ctrl.editor = new MediumEditor(iElement, opts); - }); - - var onChange = function() { - - scope.$apply(function() { + // Global MediumEditor + ngModel.editor = new MediumEditor(iElement, scope.bindOptions); - // If user cleared the whole text, we have to reset the editor because MediumEditor - // lacks an API method to alter placeholder after initialization - if (iElement.html() === '


' || iElement.html() === '') { - opts.placeholder = placeholder; - var editor = new MediumEditor(iElement, opts); - } - - ctrl.$setViewValue(iElement.html()); - }); + ngModel.$render = function() { + iElement.html(ngModel.$viewValue || ""); + ngModel.editor.getExtensionByName('placeholder').updatePlaceholder(iElement[0]); }; - // view -> model - iElement.on('blur', onChange); - iElement.on('input', onChange); - iElement.on('paste', onChange); - - // model -> view - ctrl.$render = function() { - - if (!this.editor) { - // Hide placeholder when the model is not empty - if (!ctrl.$isEmpty(ctrl.$viewValue)) { - opts.placeholder = ''; - } - - this.editor = new MediumEditor(iElement, opts); + ngModel.$isEmpty = function(value) { + if (/[<>]/.test(value)) { + return toInnerText(value).length === 0; + } else if (value) { + return value.length === 0; + } else { + return true; } - - iElement.html(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); - - // hide placeholder when view is not empty - if(!ctrl.$isEmpty(ctrl.$viewValue)) angular.element(iElement).removeClass('medium-editor-placeholder'); }; + ngModel.editor.subscribe('editableInput', function (event, editable) { + ngModel.$setViewValue(editable.innerHTML.trim()); + }); + + scope.$watch('bindOptions', function(bindOptions) { + ngModel.editor.init(iElement, bindOptions); + }); } }; diff --git a/dist/angular-medium-editor.min.js b/dist/angular-medium-editor.min.js index 3539a84..158804a 100644 --- a/dist/angular-medium-editor.min.js +++ b/dist/angular-medium-editor.min.js @@ -1,8 +1,8 @@ /** * angular-medium-editor - * @version v0.1.1 - 2015-11-23 + * @version v1.1.0 - 2015-11-23 * @link https://github.com/thijsw/angular-medium-editor * @author Thijs Wijnmaalen * @license MIT License, http://www.opensource.org/licenses/MIT */ -"use strict";angular.module("angular-medium-editor",[]).directive("mediumEditor",function(){return{require:"ngModel",restrict:"AE",scope:{bindOptions:"="},link:function(a,b,c,d){angular.element(b).addClass("angular-medium-editor");var e={},f="",g=function(){c.options&&(e=a.$eval(c.options));var b={};void 0!==a.bindOptions&&(b=a.bindOptions),e=angular.extend(e,b)};g(),f=e.placeholder,a.$watch("bindOptions",function(){d.editor&&d.editor.destroy(),g(),d.$isEmpty(d.$viewValue)||(e.placeholder=""),d.editor=new MediumEditor(b,e)});var h=function(){a.$apply(function(){if("


"===b.html()||""===b.html()){e.placeholder=f;{new MediumEditor(b,e)}}d.$setViewValue(b.html())})};b.on("blur",h),b.on("input",h),b.on("paste",h),d.$render=function(){this.editor||(d.$isEmpty(d.$viewValue)||(e.placeholder=""),this.editor=new MediumEditor(b,e)),b.html(d.$isEmpty(d.$viewValue)?"":d.$viewValue),d.$isEmpty(d.$viewValue)||angular.element(b).removeClass("medium-editor-placeholder")}}}}); \ No newline at end of file +"use strict";angular.module("angular-medium-editor",[]).directive("mediumEditor",function(){function a(a){var b,c=document.createElement("div");return c.innerHTML=a,b=c.textContent||"",b.trim()}return{require:"ngModel",restrict:"AE",scope:{bindOptions:"="},link:function(b,c,d,e){angular.element(c).addClass("angular-medium-editor"),e.editor=new MediumEditor(c,b.bindOptions),e.$render=function(){c.html(e.$viewValue||""),e.editor.getExtensionByName("placeholder").updatePlaceholder(c[0])},e.$isEmpty=function(b){return/[<>]/.test(b)?0===a(b).length:b?0===b.length:!0},e.editor.subscribe("editableInput",function(a,b){e.$setViewValue(b.innerHTML.trim())}),b.$watch("bindOptions",function(a){e.editor.init(c,a)})}}}); \ No newline at end of file diff --git a/package.json b/package.json index 33a6a37..225a297 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-medium-editor", - "version": "0.1.1", + "version": "1.1.0", "description": "AngularJS directive for Medium.com editor clone", "keywords": [ "angular", diff --git a/src/angular-medium-editor.js b/src/angular-medium-editor.js index b10bb54..213caa0 100644 --- a/src/angular-medium-editor.js +++ b/src/angular-medium-editor.js @@ -1,84 +1,51 @@ +/*global MediumEditor */ 'use strict'; angular.module('angular-medium-editor', []) .directive('mediumEditor', function() { + function toInnerText(value) { + var tempEl = document.createElement('div'), + text; + tempEl.innerHTML = value; + text = tempEl.textContent || ''; + return text.trim(); + } + return { require: 'ngModel', restrict: 'AE', scope: { bindOptions: '=' }, - link: function(scope, iElement, iAttrs, ctrl) { + link: function(scope, iElement, iAttrs, ngModel) { angular.element(iElement).addClass('angular-medium-editor'); - // Parse options - var opts = {}, - placeholder = ''; - var prepOpts = function() { - if (iAttrs.options) { - opts = scope.$eval(iAttrs.options); - } - var bindOpts = {}; - if (scope.bindOptions !== undefined) { - bindOpts = scope.bindOptions; - } - opts = angular.extend(opts, bindOpts); - }; - prepOpts(); - placeholder = opts.placeholder; - scope.$watch('bindOptions', function() { - // in case options are provided after mediumEditor directive has been compiled and linked (and after $render function executed) - // we need to re-initialize - if (ctrl.editor) { - ctrl.editor.destroy(); - } - prepOpts(); - // Hide placeholder when the model is not empty - if (!ctrl.$isEmpty(ctrl.$viewValue)) { - opts.placeholder = ''; - } - ctrl.editor = new MediumEditor(iElement, opts); - }); - - var onChange = function() { - - scope.$apply(function() { + // Global MediumEditor + ngModel.editor = new MediumEditor(iElement, scope.bindOptions); - // If user cleared the whole text, we have to reset the editor because MediumEditor - // lacks an API method to alter placeholder after initialization - if (iElement.html() === '


' || iElement.html() === '') { - opts.placeholder = placeholder; - var editor = new MediumEditor(iElement, opts); - } - - ctrl.$setViewValue(iElement.html()); - }); + ngModel.$render = function() { + iElement.html(ngModel.$viewValue || ""); + ngModel.editor.getExtensionByName('placeholder').updatePlaceholder(iElement[0]); }; - // view -> model - iElement.on('blur', onChange); - iElement.on('input', onChange); - iElement.on('paste', onChange); - - // model -> view - ctrl.$render = function() { - - if (!this.editor) { - // Hide placeholder when the model is not empty - if (!ctrl.$isEmpty(ctrl.$viewValue)) { - opts.placeholder = ''; - } - - this.editor = new MediumEditor(iElement, opts); + ngModel.$isEmpty = function(value) { + if (/[<>]/.test(value)) { + return toInnerText(value).length === 0; + } else if (value) { + return value.length === 0; + } else { + return true; } - - iElement.html(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); - - // hide placeholder when view is not empty - if(!ctrl.$isEmpty(ctrl.$viewValue)) angular.element(iElement).removeClass('medium-editor-placeholder'); }; + ngModel.editor.subscribe('editableInput', function (event, editable) { + ngModel.$setViewValue(editable.innerHTML.trim()); + }); + + scope.$watch('bindOptions', function(bindOptions) { + ngModel.editor.init(iElement, bindOptions); + }); } };