Rich Text compatibility problem induction (win)

Source: Internet
Author: User

Last week, I took the time to rewrite the rich text written last year, and wrap it up as a basic UI component that can be reused outside of the chat box. I think rich text is one of the most compatible modules, especially the document is not a few, the Mozilla API document and IE DOM API about the selection and range of a look, a try, and finally found a barely able to use the method.

In fact, before the rich text code is too messy, and there are many bugs, but the product manager does not give time to change, o__o "...

This rich text does not use an IFRAME to do the input box, for two reasons:

    1. IFrame is the most consumed performance in all DOM nodes, more than a few IE6/7 will get stuck;
    2. Because WEBQQ is a multi-window chat, when the cursor clicks into the input box, the IFRAME will capture mouse events, notify the Chat window settings style;

So I used a div, set contenteditable= "true", this property basic browser support, in addition to firefox2.0 (but there are still users are still using ff2.0 ⊙﹏⊙ b Khan)

This revision found a lot of egg pain compatibility problems, pick a few summed up:

1. Save/Restore the cursor position

Rich text A large part of the compatibility issue is where the cursor is saved and restored. Speaking of the cursor position, there is a need to pay attention to the point is not to call the focus method, two consecutive calls to focus will cause the cursor to lose , with the effect of calling Blur, the best way is to let the caller at the time of the call to ensure that the cursor in the input box, Do not call focus in the internal code.

Save will not say, keyup/mouseup time to save the current range ( there is a performance problem, but the Blur event is not used, when the event, the cursor has been moved elsewhere ), but to ensure that the cursor in the input box, Otherwise, range is the document.

Note here that IE9 supports the Window.getselection method, but the Range object it gets has no Createcontextualfragment method, which can pass in an HTML string, Directly generated DOM node, and pastehtml a bit similar, specific instructions can click here to view. So the GetSelection method of encapsulation, put document.selection in front.

To restore the cursor position, for advanced browsers, add the original range directly to selection, like this

Double-click to select Source code
12 selection.removeAllRanges();selection.addRange(this._lastRange);

There are two ways of IE:

  1. GetBookmark and MoveToBookmark tbody>
    double-click to select the source code
    123 var range = Richeditor.getrange (); range.movetobookmark ( this . _lastbookmark); range.select ();
  2. setEndPoint
    Double-click to select Source code
    1234 range.setEndPoint(‘EndToStart‘, this._lastRange);range.collapse(false);range.setEndPoint(‘EndToEnd‘, this._lastRange);range.select();

Here is the principle of setendpoint:

    1. Save Lastrange First, such as "CDE" in "ABCDEFG"
    2. Move the end of the new range to the beginning of the Lastrange (the left side of "C")
    3. Then call collapse (false) to move the insertion point of the cursor to the end of the range, that is, to merge the beginning and end of the range together, and not to do so, and then select "AB" (that is, all content before "C" is selected) after the call to select
    4. Move the end of range to the end of the Lastrange (the right side of "E")
    5. Select the range to restore the last saved selection ("CDE" is selected)
2. Line-Wrapping processing

When you press ENTER in the input box, IE generates a new <p></p> paragraph tag, and FF is <br>,chrome <div></div>. This is not a big problem, but it will cause trouble in the subsequent processing, the ideal situation is that any browser input box content is the same. So here to monitor the KeyDown event of the input box, if it is a carriage return, block the default behavior of the browser, use the code to insert a newline label <br>.

Note 1: Opera's KeyDown event is no way to block the default behavior, use the KeyPress event instead.

NOTE 2: when Chrome's cursor is at the end of a line, inserting a <br/> does not allow the cursor to move to the next line, and you need to insert an extra node behind <br/> to jump to the next. So you can insert the <br/>&nbsp first, and then put the HTML space "&nbsp;" Delete.

3. Delete processing (IE)

IE, if you select a picture or input nodes, press the BACKSPACE, will trigger the browser back processing, and call History.back () the same effect, you can judge the type of the selection when KeyDown, if the control type, block the browser's behavior, Use code removal.

Double-click to select Source code
12345 varselection = RichEditor.getSelection();if(selection.type.toLowerCase() === ‘control‘) {    e.preventDefault();    selection.clear();}

PS: This situation only exists in the case of using div to do input box, IFRAME does not.

4. Paste & Drag Handling

Chat window input box is not the same as the general rich text, want to publish the rich text of the article, is allowed to paste HTML fragments in. However, pasting HTML fragments into a chat box can result in a messy style and affect the experience. And the images inside must be uploaded to the server before they can be used. Therefore, the content to be pasted into the filter.

The previous treatment is to directly filter all the content with regular, let go of <br> and some labeled labels, the rest are deleted, and then reinsert the input box. This is a relatively simple process, but it can cause the filtered cursor not to get back to the original place, the experience is not good.

Now is the way of traversing the DOM, traversing the direct child node of the input box, extracting the text from it, creating a textnode, and replacing its parent node, where two more important attributes are used:

    1. Textcontent (Standard browser): Textcontent saves all of its descendants ' text, removing all element nodes
    2. InnerText (IE): IE has no textcontent attribute, but can be replaced with InnerText

Note: Opera does not have a Onpaste event and can only capture the paste behavior of Ctrl + V, and it is surprisingly keypress the KeyCode or 86. Right-click on the No way, even edit the DIV even Oninput event can not trigger O__o "...

5. Insert Processing

Standard browser (non IE) to insert content at the cursor, you can create an HTML fragment with Range.createcontextualfragment and call Range.insertnode insert. When inserted in this way, the cursor disappears and the cursor is repositioned to display.

Double-click to select Source code
123456789 varfragment = range.createContextualFragment(html);var lastNode = fragment.lastChild;range.insertNode(fragment);//插入后把开始和结束位置都放到lastNode后面, 然后添加到selectionrange.setEndAfter(lastNode);range.setStartAfter(lastNode);varselection = RichEditor.getSelection();selection.removeAllRanges();selection.addRange(range);

IE is much simpler, though not necessarily a good thing.

Double-click to select Source code
123 range.pasteHTML(html);range.collapse(false);range.select();
6. Cursor positioning after insertion

After inserting an HTML fragment, if a scroll bar appears, in non-IE browsers, the cursor is already below the viewable area and does not automatically scroll to the viewable area. The workaround is to insert an HTML fragment, add one more width and height to the 0 image, and then calculate whether the position of the picture relative to the input box has exceeded the visual range of the input box. If so, scroll the input box to the picture and then delete the picture.

The reason here is to use the picture, because he is display:inline, the element, does not cause the content to wrap, but also can set the width height, makes it invisible to the user, is in is the kill anyone essential product.

The code is as follows:

JavaScript
12345678 html += ‘‘;var fragment = range.createContextualFragment(html);var lastNode = fragment.lastChild;//..........var divArea = this._divArea;var pos = $D.getRelativeXY(lastNode, divArea);divArea.scrollTop = pos[1] < divArea.scrollHeight ? divArea.scrollHeight : pos[1];document.execCommand(‘Delete‘, false, null);// 删除附加的节点

Here can also use Lastnode.scrollintoview () to scroll to the visible area, but FF if Open Firebug, will lead to WEBQQ style confusion, other sites may be able to test to see.

7. Ensure that range is in the input box

Many of the previous methods are implemented with the current focus in the input box, otherwise if the focus on the document, the inserted HTML will be displayed in the upper left corner of the page, is a big bug.

Determines whether a range is in the input box, and the parent of range can be judged, if its parentnode is an input box or in the input box, it is the correct range. The standard browser can get the parent node with Range.commonancestorcontainer, IE is range.parentelement (). The method of comparison is comparedocumentposition (Internet) and contains (IE), specifically how to use not to say, here is a description and packaged code.

The above problems are Windows platform, Linux also have problems, but not measured, to be continued ...

Rich Text compatibility problem induction (win)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.