1

We decided to change our backend CMS to use text-angular's WYSIWYG editor. The content pulls from the database just fine, it gets rendered just fine, but the instant we go to view the HTML source, the text is there for an instant and then it disappears. I've turned off sanitization with the ta-unsafe-sanitizer="true" . The weird thing is, if I manually step through the angular code that does the digesting, eventually the text is rendered and it stays on the screen. If I run it without breakpoints, it clears the text.

I'm not sure if it is sanitization or some sort of race condition inside Angular. Anyone else run into this?

View

<div text-angular ta-toolbar="[['h1','h2','h3'],['bold','italics','underline'],['ul','ol'],['outdent','indent'],['html'],['insertImage']]" ng-model="updatePageTranslation.Content" ta-unsafe-sanitizer="true"></div>

Controller

$scope.updatePageTranslation.Content = 'large html portion here';

The scope of the form is set as follows:

<div class="widget" ng-controller="PageController">

Everything gets loaded fine and other fields of the form show the values correctly. The initial render of the content is correct. It is just when switching to HTML view that it goes blank. Clicking Html again switches back to the visual view, which is correct. But if I save, the value sent to the server is now blank.

I can even copy and paste the value into textangular.com site's demo textbox and have the same issue.

Josh
  • 10,352
  • 12
  • 58
  • 109
  • Can you maybe share portions of the view and the controller? – Hanlet Escaño Oct 21 '15 at 21:49
  • 1
    @HanletEscaño All set – Josh Oct 21 '15 at 21:52
  • 1
    @HanletEscaño The controller is set at the surrounding div's level. Everything on the form loads correctly. – Josh Oct 21 '15 at 21:56
  • I can't replicate it, it always works for me, so there could be something weird with the data perhaps? You said that if you paste it in the textangular.com you get the same issue. Maybe create a fiddle with the HTML that break it so that I can look at it? – Hanlet Escaño Oct 21 '15 at 22:02
  • @HanletEscaño Here's the fiddle: https://jsfiddle.net/tp29y3c4/ Hit the HTML button to view the source. It will blank out. Then hit it again to see the rendered (initial) text – Josh Oct 22 '15 at 13:29
  • 1
    Yeah, it is as I suspected. Read this from the textAngular website: "Important Note: Though textAngular supports the use of all attributes in it's input, please note that angulars ng-bind-html WILL strip out all of your style attributes if you are using angular-sanitize.js." Remove the \ character from your HTML input and the problem will be fixed. https://jsfiddle.net/tp29y3c4/3/ – Hanlet Escaño Oct 22 '15 at 14:29
  • @HanletEscaño I had the \'s in there to make it easier to paste into fiddle. But that got me pointed in the right direction. I had to remove all instances of a double space, ' ', from the content coming from the server. Then I was able to switch back and forth. Seems pretty weird. – Josh Oct 22 '15 at 15:08
  • It is pretty weird indeed. I hope you figure it out man. – Hanlet Escaño Oct 22 '15 at 15:18

2 Answers2

1

This was a strange one to figure out, but thanks to @HanletEscaño, I was able to find my way. When returning the content from the server, I had to do the following in order to pre-sanitize it so that you could switch back and forth between the HTML and rendered view:

Content.Replace(Environment.NewLine, "").Replace("\n", "").Replace("\r", "").Replace("\t", "").Replace("  ", "");

The important one is that last replace, where we replace two spaces with nothing. This seemed to be the final trick. We were coming from a previous WYSIWYG editor where we could make the HTML look nice, but with this editor, everything has to be condensed.

Josh
  • 10,352
  • 12
  • 58
  • 109
0

As mentioned above, this seems to be due to the parser struggling to handle whitespace and newlines correctly.

If you take a look at the textAngular source, in taBind.js, _taBlankTest service seems to returns true when the bound value contains spaces, newlines etc, which in turn causes the model to get set to undefined.

I replaced mine with the following to avoid that situation:

angular.module('textAngular.taBind', ['textAngular.factories', 'textAngular.DOM'])
.service('_taBlankTest', [function(){
    var INLINETAGS_NONBLANK = /<(a|abbr|acronym|bdi|bdo|big|cite|code|del|dfn|img|ins|kbd|label|map|mark|q|ruby|rp|rt|s|samp|time|tt|var)[^>]*(>|$)/i;
    return function(_defaultTest){
        return function(_blankVal){
            if(!_blankVal) return true;
            var _matchVal = _blankVal.replace(/(  |\t|\n)/gm, '');

        // find first non-tag match - ie start of string or after tag that is not whitespace
        var _firstMatch = /(^[^<]|>)[^<]/i.exec(_matchVal);
        var _firstTagIndex;
        if(!_firstMatch){
            // find the end of the first tag removing all the
            // Don't do a global replace as that would be waaayy too long, just replace the first 4 occurences should be enough
            _matchVal = _matchVal.toString().replace(/="[^"]*"/i, '').replace(/="[^"]*"/i, '').replace(/="[^"]*"/i, '').replace(/="[^"]*"/i, '');
            _firstTagIndex = _matchVal.indexOf('>');
        }else{
            _firstTagIndex = _firstMatch.index;
        }
        _matchVal = _matchVal.trim().substring(_firstTagIndex, _firstTagIndex + 100);
        // check for no tags entry
        if(/^[^<>]+$/i.test(_matchVal)) return false;
        // this regex is to match any number of whitespace only between two tags
        if (_matchVal.length === 0 || _matchVal === _defaultTest || /^>(\s|&nbsp;|\n|\t)*<\/[^>]+>$/ig.test(_matchVal)) return true;
        // this regex tests if there is a tag followed by some optional whitespace and some text after that
        else if (/>\s*[^\s<]/i.test(_matchVal) || INLINETAGS_NONBLANK.test(_matchVal)) return false;
        else return true;
    };
};
}])

Hopefully that may help someone out there!

Dominic
  • 11
  • 1