JSFiddle - React, Tailwind, and code Playground

by Nicolas PUJOL

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular-sanitize.js"></script>
<div ng-app="app">
    <div ng-controller="ctrl as ctrlito">
        <label>Model (non-editable):</label>
        <pre id="output">{{ model }}</pre>
        <hr>
        <label>Contenteditable View (1):</label>
        <div id="input" contenteditable ng-model="model"></div>
        <hr>
        <!--
      <label>Contenteditable View (2):</label>
      <div id="input2" contenteditable="true" ng-model="model"></div>
      <hr>
      <label>Contenteditable View (3):</label>
      <div id="input3" contenteditable="TRUE" ng-model="model"></div>
      <hr>
      <label>non-contenteditable View:</label>
      <div id="non-editable" contenteditable="false" ng-model="model"></div>
      <hr>
      <label>Input (edit verbatim)</label>
      <input ng-model="model" style="width:100%">
      <hr>
      <label>Contenteditable without Model</label>
      <div contenteditable>Edit me - I don't affect anything</div>
      -->
    </div>
</div>

CSS

[contenteditable] {
    border-bottom: 1px solid black;
    background-color: white;
    min-height: 20px;
}

.ng-invalid {
    border: 1px solid red;
}

JavaScript

angular.module('app', ['contenteditable']);
angular.module('contenteditable', []).directive('contenteditable', ['$timeout', function($timeout) {
        return {
            restrict: 'A',
            require: '?ngModel',
            link: function(scope, element, attrs, ngModel) {
                // don't do anything unless this is actually bound to a model
                if (!ngModel) {
                    return
                }

                // options
                var opts = {}
                angular.forEach([
                    'stripBr',
                    'noLineBreaks',
                    'selectNonEditable',
                    'moveCaretToEndOnChange',
                    'stripTags'
                ], function(opt) {
                    var o = attrs[opt];
                    opts[opt] = o && o !== 'false'
                    console.log(opt + ' -> ' + opts[opt]);
                })

                // view -> model
                element.bind('input', function(e) {
                    scope.$apply(function() {
                        var html, html2, rerender
                        html = element.html()
                        rerender = false
                            /*
                            if (opts.stripBr) {
                              html = html.replace(/<br>$/, '')
                            }
                            if (opts.noLineBreaks) {
                              html2 = html.replace(/<div>/g, '').replace(/<br>/g, '').replace(/<\/div>/g, '')
                              if (html2 !== html) {
                                rerender = true
                                html = html2
                              }
                            }
                            if (opts.stripTags) {
                              rerender = true
                              html = html.replace(/<\S[^><]*>/g, '')
                            }
                            */
                       ...