I'm trying to create an editor which does "syntax highlighting", it is rather simple:
yellow -> <span style="color:yellow">yellow</span>
I'm also using <code contenteditable>
html5 tag to replace <textarea>
, and have color output.
I started from angularjs documentation, and created the following simple directive. It does work, except it do not update the contenteditable
area with the generated html.
If I use a element.html(htmlTrusted)
instead of ngModel.$setViewValue(htmlTrusted)
, everything works, except the cursor jumps to the beginning at each keypress.
directive:
app.directive("contenteditable", function($sce) {
return {
restrict: "A", // only activate on element attribute
require: "?ngModel", // get ng-model, if not provided in html, then null
link: function(scope, element, attrs, ngModel) {
if (!ngModel) {return;} // do nothing if no ng-model
element.on('blur keyup change', function() {
console.log('app.directive->contenteditable->link->element.on()');
//runs at each event inside <div contenteditable>
scope.$evalAsync(read);
});
function read() {
console.log('app.directive->contenteditable->link->read()');
var html = element.html();
// When we clear the content editable the browser leaves a <br> behind
// If strip-br attribute is provided then we strip this out
if ( attrs.stripBr && html == '<br>' ) {
html = '';
}
html = html.replace(/</, '<');
html = html.replace(/>/, '>');
html = html.replace(/<span\ style=\"color:\w+\">(.*?)<\/span>/g, "$1");
html = html.replace('yellow', '<span style="color:yellow">yellow</span>');
html = html.replace('green', '<span style="color:green">green</span>');
html = html.replace('purple', '<span style="color:purple">purple</span>');
html = html.replace('blue', '<span style="color:yellow">blue</span>');
console.log('read()-> html:', html);
var htmlTrusted = $sce.trustAsHtml(html);
ngModel.$setViewValue(htmlTrusted);
}
read(); // INITIALIZATION, run read() when initializing
}
};
});
html:
<body ng-app="MyApp">
<code contenteditable
name="myWidget" ng-model="userContent"
strip-br="true"
required>This <span style="color:purple">text is purple.</span> Change me!</code>
<hr>
<pre>{{userContent}}</pre>
</body>
plunkr: demo (type yellow
, green
or blue
into the change me input area)
I tried scope.$apply()
, ngModel.$render()
but has no effect. I must miss something really obvious...
The links I already read through:
- others' plunker demo 1
- others' plunker demo 2
- angularjs documentation's example
- $sce.trustAsHtml stackoverflow question
- setViewValue stackoverflow question
- setViewValue not updating stackoverflow question
Any help is much appreciated. Please see the plunker demo above.
After almost a year, I finally settled to Codemirror, and I was never happier. I'm doing side-by-side markdown source editing with live update (with syntax highlighting, so even a bit more advanced than stackoverflow's editing page.)
I created a simple codeEditor angular directive, which requires codeMirror, and uses it.
For completeness, here is the component sourcecode:
There is also inside the
components/codeEditor/vendor
directory the full codemirror sourcecode.I can highly recommend codeMirror. It is a rocksolid component, works in every browser combination (firefox, firefox for android, chromium).