Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pasting from word #124

Closed
worldspawn opened this issue Mar 17, 2014 · 29 comments
Closed

Pasting from word #124

worldspawn opened this issue Mar 17, 2014 · 29 comments

Comments

@worldspawn
Copy link
Contributor

So... inevitably, our clients have started trying to paste msword content in to textAngular. So I am just wondering if this is something that has any support?

@worldspawn
Copy link
Contributor Author

After updating to 1.2.0 i see it does a much better job.

@SimeonC
Copy link
Collaborator

SimeonC commented Mar 17, 2014

Well, I suppose it is a sign it's actually being used! Joking aside - there's a similar issue open #86.

1.2.0 should be doing a better job as it has a strict set of tags it allows - via angular-sanitize/textAngular-Sanitize ngSanitize directive, which will fix most of the weird tags like <o:p>.

On the other hand, 'cleansing' content on paste is a big missing feature so it is on my list, just not directly next.

For Reference when I start work:

@SimeonC SimeonC added this to the 1.2.1 milestone Mar 17, 2014
@mnazwan
Copy link

mnazwan commented Mar 17, 2014

Another potential solution is to use textarea and browsers handle the plain text formatting automatically during pasting. Still trying if this works with textAngular.

@SimeonC
Copy link
Collaborator

SimeonC commented Mar 17, 2014

Yes that's the easiest option, but then from what I've read most people pasting from word will want all that nice pretty formatting they put in. So your solution may do for a good starting point but I have a feeling it won't make the issue go away.

@SimeonC
Copy link
Collaborator

SimeonC commented Mar 28, 2014

As a stop-gap the most recent commit to the repo is stripping out all html tags and inserting only plain text. In theory this should strip out all the ms-word formatting indiscriminately. I'll work on the ms-word parts later.

@worldspawn
Copy link
Contributor Author

@SimeonC i think that commit has broken paste in ie9. I cannot paste anything, effect of pasting is "nothing happens".

@SimeonC
Copy link
Collaborator

SimeonC commented Apr 1, 2014

Bother, thanks for letting me know - I'll have a look. In theory it covered IE, but IE is IE. :(

@worldspawn
Copy link
Contributor Author

Yeh. IE... the reason web developers become project managers.

A little background, I upgraded because of another IE issue we were seeing (before upgrading) where pasting content in wasn't triggering the validator, that is the required field validator for the field wasn't changing to valid. Version 1.2.0 it says in the file. Subsequent manual edits to the field dont fix the validation either, it gets into some kind of bad state...

Hey you should have some donation thing, i feel bad raising ie bugs.

@SimeonC
Copy link
Collaborator

SimeonC commented Apr 1, 2014

No worries about IE bugs - I said we'd support it so I'd better do what I said!
The previous version possibly wasn't updating due to it not reacting the paste event or something - I changed a fair bit of the paste code.

I tested it and can paste in IE fine (using v1.2.1-pre1 and the bundled demo/static-demo.html). Possibly something specific about what you're pasting in? Also of fair importance is do you have jQuery loaded or not? I recently discovered this can cause some very strange issues when you assume jQuery and jQLite both function identically (except the obvious exceptions) which isn't always true...

I'm testing via browser stack (which is slow as a wet week today) so copy-paste for me is a bit limited to plain text it seems.

The code I added in to handle paste is as follows, you might be able to spot anything I've missed as you probably work with IE js more than I do.

var text;
// for non-ie
if(e.clipboardData || (e.originalEvent && e.originalEvent.clipboardData))
    text = (e.originalEvent || e).clipboardData.getData('text/plain');
// for ie
else if($window.clipboardData)
    text = $window.clipboardData.getData('Text');
// if theres non text data and we aren't in read-only do default
if(!text && !_isReadonly) return true;
// prevent the default paste command
e.preventDefault();
if(!_isReadonly){
    var _working = angular.element('<div></div>');
    _working[0].innerHTML = text;
    // this strips out all HTML tags
    text = _working.text();
    document.execCommand('insertText', false, text);
    ngModel.$setViewValue(_compileHtml());
}

@worldspawn
Copy link
Contributor Author

Hi @SimeonC In your test did you happen to check whether required validators were passing after a paste?

@SimeonC
Copy link
Collaborator

SimeonC commented Apr 1, 2014

Yes I did, in /demo/static-demo.html I changed the form test in there to be:

<form name="validationForm">
    <label for="name">Name:</label> <input type="text" tabindex="1" id="name" ng-model="name">
    <label for="website">Website:</label> <input type="url" tabindex="2" id="website" ng-model="website">
    formValid: {{validationForm.testValidation.$pristine}} {{validationForm.testValidation.$valid}} {{validationForm.testValidation.$dirty}} {{validationForm.testValidation.$invalid}}
    Bio: <div text-angular name="testValidation" ng-model="bio" tabindex="3" required></div>
</form>

That worked fine, I just didn't bother commiting it in yet. There seems to be a problem in IE with it detecting whether it's blank or not when leaving with the wrapping function which in turn causes it not to set invalid.

@worldspawn
Copy link
Contributor Author

OK I am having more success with this code (tested in IE9 and IE10). From I have read here - http://stackoverflow.com/questions/3398378/execcommand-inserthtml-in-internet-explorer this is the way to do it in the IE of yesteryear.

if(document.selection){
    var range = document.selection.createRange();
    range.pasteHTML(text)
}
else{
    document.execCommand('insertText', false, text);
}

If you're testing in IE11 then i guess insertText works in IE11. I tried lots of different text sources including plain text and I could not get paste to work in IE9 at all using insertText. The execCommand fails with "Invalid Argument".

@SimeonC
Copy link
Collaborator

SimeonC commented Apr 2, 2014

OK, I guess then paste is being cheated in browserstack then - that kind of invalidates my testing methods for paste anyway. I'll patch in your fix as is and get it committed up soon.

@markvp
Copy link

markvp commented Apr 11, 2014

+1 for a better solution than both "strip all tags" and "allow all sh*tty tags".

I'm not sure "strip all tags" is always a better solution than "allow all sh*tty tags".

@oldeev
Copy link

oldeev commented Apr 28, 2014

Is it possible change text color? Thanks

@SimeonC
Copy link
Collaborator

SimeonC commented Apr 28, 2014

@oldeev Have a look at the demo in the repo and the work done in #127, it is possible to change the colour but it's not currently built in. In future please open a new issue or find an issue that matches your issue better.

@ShaggyDude
Copy link

Please no! -1

@SimeonC SimeonC removed this from the 1.2.1 milestone May 11, 2014
@SimeonC
Copy link
Collaborator

SimeonC commented May 11, 2014

Pushing this out as I want to get v1.2.1 done as it's taken too long. Once all the bugs as of current are fixed we can look at this for the next version.

SimeonC pushed a commit that referenced this issue Sep 16, 2014
Allow pasting of styles and random trash into the editor by sanitizing the paste event. Needs testing on IE.

Fixes #196, #124, #214, #255.

May invalidate #298 due to drop of `insertText`
@SimeonC
Copy link
Collaborator

SimeonC commented Sep 16, 2014

Re-looking at this later on it doesn't seem that any of the solutions allow for actual conversion from the wierd tags to normal html. The latest master version should allow some copy paste by default but everything else will be cleared out by the sanitizer. Someone care to test this with word and let me know how it goes?

@SimeonC
Copy link
Collaborator

SimeonC commented Oct 5, 2014

Also if we want some better word parsing I'm going to need someone to post up the HTML that it attempts to paste in or a method of converting word xml to html. I don't have word so until someone does that (or just creates a PR with the logic) I can't actually implement this.

@rasmusvhansen
Copy link

Here is a basic word document I copied.

<h1><span lang="EN-US">Header 1<o:p></o:p></span></h1>

<p class="MsoNormal"><span lang="EN-US">Body<o:p></o:p></span></p>

<h2><span lang="EN-US">Header 2<o:p></o:p></span></h2>

<p class="MsoNormal"><span lang="EN-US">Body<o:p></o:p></span></p>

<h3><span lang="EN-US">Header 3<o:p></o:p></span></h3>

<p class="MsoNormal"><span lang="EN-US">Body with <b>bold text, </b><i>and italic, </i><u>and underlined<o:p></o:p></u></span></p>

<p class="MsoListBulletCxSpFirst"><!--[if !supportLists]--><span lang="EN-US" style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
Symbol;mso-ansi-language:EN-US">·<span style="font-stretch: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><span lang="EN-US">UL
-&gt; LI1<o:p></o:p></span></p>

<p class="MsoListBulletCxSpMiddle"><!--[if !supportLists]--><span lang="EN-US" style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
Symbol;mso-ansi-language:EN-US">·<span style="font-stretch: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><span lang="EN-US">UL
-&gt; LI2<o:p></o:p></span></p>

<p class="MsoListBulletCxSpMiddle"><!--[if !supportLists]--><span lang="EN-US" style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
Symbol;mso-ansi-language:EN-US">·<span style="font-stretch: normal; font-size: 7pt; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span><!--[endif]--><span lang="EN-US">UL
-&gt; LI3<o:p></o:p></span></p>

<p class="MsoListBulletCxSpLast"><span lang="EN-US">&nbsp;</span></p>

<p class="MsoListNumberCxSpFirst"><!--[if !supportLists]--><span lang="EN-US">1.<span style="font-stretch: normal; font-size: 7pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span lang="EN-US">OL -&gt; LI1<o:p></o:p></span></p>

<p class="MsoListNumberCxSpMiddle"><!--[if !supportLists]--><span lang="EN-US">2.<span style="font-stretch: normal; font-size: 7pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span lang="EN-US">OL -&gt; LI2<o:p></o:p></span></p>

<p class="MsoListNumberCxSpMiddle"><!--[if !supportLists]--><span lang="EN-US">3.<span style="font-stretch: normal; font-size: 7pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span lang="EN-US">OL -&gt; LI3<o:p></o:p></span></p>

<p class="MsoListNumberCxSpMiddle" style="margin-left:39.6pt;mso-add-space:auto;
text-indent:-21.6pt;mso-list:l2 level2 lfo3;tab-stops:65.2pt"><!--[if !supportLists]--><span lang="EN-US">3.1.<span style="font-stretch: normal; font-size: 7pt;">&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span lang="EN-US">OL -&gt; LI3.1<o:p></o:p></span></p>

<p class="MsoListNumberCxSpMiddle" style="margin-left:61.2pt;mso-add-space:auto;
text-indent:-25.2pt;mso-list:l2 level3 lfo3;tab-stops:65.2pt"><!--[if !supportLists]--><span lang="EN-US">3.1.1.<span style="font-stretch: normal; font-size: 7pt;"> </span></span><!--[endif]--><span lang="EN-US">&nbsp;OL -&gt; LI3.1.1<o:p></o:p></span></p>

<p class="MsoListNumberCxSpLast"><!--[if !supportLists]--><span lang="EN-US">4.<span style="font-stretch: normal; font-size: 7pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><!--[endif]--><span lang="EN-US">OL -&gt; LI4&nbsp; &nbsp;&nbsp;<o:p></o:p></span></p>

It should look something like

<h1>Header 1</h1>
<p>Body</p>
<h2>Header 2</h2>
<p>Body</p>
<h3>Header 3</h3>
<p>Body with <strong>bold text, </strong><em>and italic, </em><u>and underlined</u></p>
<ul>
<li>UL -&gt; LI1</li>
<li>UL -&gt; LI2</li>
<li>UL -&gt; LI3</li>
</ul>
<p>&nbsp;</p>
<ol>
<li>OL -&gt; LI1</li>
<li>OL -&gt; LI2</li>
<li>OL -&gt; LI3
<ol>
<li>OL -&gt; LI3.1
<ol>
<li>OL -&gt; LI3.1.1</li>
</ol>
</li>
</ol>
</li>
</ol>
<ol start="4">
<li>OL -&gt; LI4</li>
</ol>

Hope that helps

@SimeonC
Copy link
Collaborator

SimeonC commented Oct 16, 2014

@rasmusvhansen Thanks, it helped as it's a slightly different formatting than what I got out of Word for Mac.
Just as an update this will be in 1.3.0 as the guys over at smartorg.com have kindly sponsored it.

@kotmatpockuh
Copy link

<span class="announcementsPostTimestamp" id="afterPageTitleHideDuringEdit" style="color: rgb(102, 102, 102);">posted<span class="Apple-converted-space">&nbsp;</span><span xmlns="http://www.w3.org/1999/xhtml" dir="ltr">Dec 1, 2011, 4:34 AM</span><span class="Apple-converted-space">&nbsp;</span>by me &nbsp;<span class="Apple-converted-space">&nbsp;</span><span id="sites-announcement-updated-time" class="updatedTime"><b>[ updated<span class="Apple-converted-space">&nbsp;</span><span xmlns="http://www.w3.org/1999/xhtml" dir="ltr">Dec 6, 2011, 4:36 AM</span><span class="Apple-converted-space">&nbsp;</span>]</b></span></span>

<div id="sites-canvas-main" class="sites-canvas-main">
   <div id="sites-canvas-main-content">
      <table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" class="sites-layout-name-one-column sites-layout-hbox" style="width: 936px;">
         <tbody>
            <tr>
               <td class="sites-layout-tile sites-tile-name-content-1">
                  <div dir="ltr">
                     <span style="color: rgb(0, 0, 0);background-color: rgb(255, 255, 255);">blablabla&nbsp;blablalba</span><br style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);"><br style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);"><span style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);">blablalba&nbsp;</span><span style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);">Заяц попрыгает с ребятами по “льдинкам”, построит blablalba&nbsp;</span><span style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);">blablalba&nbsp;</span><span style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);">blablalba&nbsp;&nbsp;</span><br style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);"><br style="color: rgb(0, 0, 0);background-color: rgb(255, 255, 255);"><span style="color: rgb(0, 0, 0);float: none;background-color: rgb(255, 255, 255);">blablalba:&nbsp;</span><a href="http://" style="color: rgb(85, 26, 139);background-color: rgb(255, 255, 255);">http://</a><span style="color: rgb(0, 0, 0);background-color: rgb(255, 255, 255);">&nbsp;</span><br style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);"><span style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);">Длительность:&nbsp;</span><span style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);">1.5-2 часа&nbsp;</span>
                     <div style="color: rgb(0, 0, 0);background-color: rgb(255, 255, 255);"><span style="text-align: left;"><br></span></div>

             <div style="color: rgb(0, 0, 0);text-align: left;background-color: rgb(255, 255, 255);"><font face="tahoma, arial, verdana, sans-serif, 'Lucida Sans'"><span>blablalba</span></font></div>
          </div>
       </td>
    </tr>
 </tbody>
``` ```

source: http://pastebin.com/z6CAemHV

hello

how could i drop formatting like style's etc when copy-paste from other sources? just leave html tags?

when i send it to server i use regex, but how to be with copy-paste?

@SimeonC
Copy link
Collaborator

SimeonC commented Mar 13, 2015

To intercept the pasted content you want to use ta-paste. e.g. ta-paste="modifyHtml($html)". In this case $html is a generated variable that contains the pasted html/text, the result of the expression, modifyHtml in this case, is what is pasted in.

@jeserkin
Copy link

jeserkin commented May 5, 2015

Capturing paste is an awesome feature, but I have noticed, that depending on formatting in word, text that is pasted sometimes looses spaces for example. So if you have for example Google Ltd. it might be pasted as GoogleLtd.

@markleusink
Copy link

@jeserkin I'm having a similar issue. Did you figure out exactly what formatting is causing it? It might be fixable with a ta-paste function.

@jeserkin
Copy link

@markleusink tried it, but as far as I can see it is sanitizer issue or normal work. There was some workaround posted here in some similar issue, but workaround author isn't sure how will it change the behavior.

@matteoferigo
Copy link

I had troubles on pasting text in Windows (on Mac works perfectly), the escape wasn't added, and the bold isn't displayed.
I solved using ta-paste="modifyHtml($html)" in text-angular tag, then I created the function:

scope.modifyHtml = function(html) {
    // mac paste like html
    if (html.match(/^\<[a-z\!][^\>]+?\>/i)) {
        // sanitize from MS Word for Mac
        html = html.replace(/(\<br\s?\/?\>)|(\<span\sstyle\=\"mso-spacerun\:yes\"\>[^\>]+\<\/span\>)|\r|\n/gi, ' ');
    // windows paste like string
    } else {
        html = html.replace(/\r|\n/, '<br />');
    }
}

This added the line break, but the bold is lost while pasting

@geyang
Copy link
Collaborator

geyang commented Jul 8, 2015

It's likely that some of the built in preprocessor is doing this. I might try to make it more customizable by using angular.value and expose these functions.

On Jul 8, 2015, at 09:44, noldotar notifications@github.com wrote:

I had troubles on pasting text in Windows (on Mac works perfectly), the escape wasn't added, and the bold isn't displayed.
I solved using ta-paste="modifyHtml($html)" in text-angular tag, then I created the function:
scope.modifyHtml = function(html) {
html = html.replace(/\r|\n/gi, '
');
return html;
}
This added the line break, but the bold is lost while pasting


Reply to this email directly or view it on GitHub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests