Html Editor Paste Content filtering Technology detailed _ Web editor

Source: Internet
Author: User
Author: Tony Qu
Recently in the resolution of data paste has made a lot of progress, as an HTML online editor must have the technology, here in detail to introduce and provide implementation reference. In the research process, I did go a lot of detours, tried N way, because the United States pm always feel that some of the things that affect the user experience is unacceptable, resulting in several proposals were denied, but the harvest is still very rich.
I'm writing code now like demand driven let's take a look at the main requirements of this technology
* Able to filter the user posted in plain text data
* Ability to filter HTML data posted by user (without HTML encoding)
* Can filter the Word data that the user pasted in, and can keep most word format.
* In this process try not to let users know that we are doing filtration
* Do not prompt the user whether to enable a certain kind of permission
This example applies to an HTML editor implemented using an IFRAME, rather than a text box (textarea or type text input).

In the research process, I mainly refer to the TINYMCE, CKEditor, but finally I chose the TINYMCE implementation, the specific reason after you read the following paragraph of text will understand.
CKEditor is implemented by fetching data from the Clipboard when the Onpaste event is triggered, processing the retrieved text, and then depositing the processed text into the Clipboard. It was said that then I can in the Onpaste directly cancel the paste action, and then I get the content into the IFRAME, I did it, but the result is unexpected, directly from the Clipboard to take out the data is not included in the format of the text, especially from Word pasted from the data, Plain text, color, layout, and other data do not exist, so that your users can only paste the data is not formatted, and then again in the HTML editor to edit. However, if the browser to do the paste, formatting information will be retained, the browser will automatically convert word paste data into XML data, into the DOM. So in order to preserve the formatting information, we're afraid we can only do this with the help of the browser's standard pasting behavior.
In addition, the implementation of CKEditor in Firefox has a fatal weakness, if you want to read and write data from the Clipboard, you must prompt the user to set a permission called Signed.applets.codebase_principal_support, JavaScript scripts do not have permissions to set, although this is normal from a technician's point of view, but many product managers cannot accept this, at least as my product manager thinks.
Here is the code for CKEditor to get and set up the clipboard for your reference.
Copy Code code as follows:

function SetClipboard (maintext) {
if (window.clipboarddata) {
Return (Window.clipboardData.setData ("Text", Maintext));
}
else if (Window.netscape) {
Netscape.security.PrivilegeManager.enablePrivilege (' Universalxpconnect ');
var clip = components.classes[' @mozilla. Org/widget/clipboard;1 '].createinstance ( Components.interfaces.nsIClipboard);
if (!clip) return;
var trans = components.classes[' @mozilla. Org/widget/transferable;1 '].createinstance ( Components.interfaces.nsITransferable);
if (!trans) return;
Trans.adddataflavor (' Text/unicode ');
var str = new Object ();
var len = new Object ();
var str = components.classes["@mozilla. Org/supports-string;1"].createinstance ( Components.interfaces.nsISupportsString);
var Copytext=maintext;
Str.data=copytext;
Trans.settransferdata ("Text/unicode", str,copytext.length*2);
var Clipid=components.interfaces.nsiclipboard;
if (!clip) return false;
Clip.setdata (Trans,null,clipid.kglobalclipboard);
return true;
}
return false;
}
function Getclipboard () {
if (window.clipboarddata) {
Return (Window.clipboardData.getData (' Text '));
}
else if (Window.netscape) {
Netscape.security.PrivilegeManager.enablePrivilege (' Universalxpconnect ');
var clip = components.classes[' @mozilla. Org/widget/clipboard;1 '].createinstance ( Components.interfaces.nsIClipboard);
if (!clip) return;
var trans = components.classes[' @mozilla. Org/widget/transferable;1 '].createinstance ( Components.interfaces.nsITransferable);
if (!trans) return;
Trans.adddataflavor (' Text/unicode ');
Clip.getdata (Trans,clip.kglobalclipboard);
var str = new Object ();
var len = new Object ();
try {
Trans.gettransferdata (' Text/unicode ', Str,len);
}
catch (Error) {
return null;
}
if (str) {
if (Components.interfaces.nsISupportsWString) Str=str.value.queryinterface ( Components.interfaces.nsISupportsWString);
else if (Components.interfaces.nsISupportsString) Str=str.value.queryinterface ( Components.interfaces.nsISupportsString);
else str = NULL;
}
if (str) {
Return (str.data.substring (0,LEN.VALUE/2));
}
}
return null;
}

The following are the code that prompts the user to enable permissions
Copy Code code as follows:

if (Window.netscape)
{
Try
{
Netscape.security.PrivilegeManager.enablePrivilege ("Universalxpconnect");
}
catch (ex)
{
Alert ("If you are want to doing paste, please input ' about:config ' into address bar, then input enter.\n Set \" Signed.applets.codeb Ase_principal_support\ "to" true\ "");
}
}

So I refer to the implementation of the TINYMCE, I look at its code when I pay special attention to it does not need permission to paste under Firefox, and can also keep word format, so carefully read the code. The implementation steps for TINYMCE are different under IE and Firefox:
IE implementation
1. Create a temporary IFRAME in the Onpaste callback function to paste the content, which is placed underneath the body of the main window.
2. Create a range at the current cursor position to hold the cursor position and the selected information.
3. Let the temporary IFRAME get focus, execute the Paste command, that is Document.execcommand ("paste"), the content will be pasted in the temporary IFRAME
4. Obtain the contents of the temporary iframe through innerHTML and filter
5. Let the HTML Editor's IFRAME get the focus, using the Range object created previously to perform the Pastehtml method to paste the filtered content
6. Finally cancel the default paste action
(Temporary iframe can be removed from the DOM based on personal preference, but since this iframe can be shared among multiple htmleditor, my implementation only changes the left and top of the IFRAME to adjust the location of the IFRAME, rather than removing it, The purpose of adjusting left and top is to move the focus to a temporary IFRAME if the HTML editor's IFRAME and temporary iframe are not in one view, the screen scrolls, which causes the screen to flicker without reason. )
Firefox implementation
1. Create a temporary div in the onpaste callback function, which is placed in the IFRAME of the HTML editor, which is the key to bypassing the permissions issue.
2. Save the current cursor and focus position, and then move the cursor to a temporarily created Div
3. Set a callback function via Window.settimeout to execute after the paste action is completed instantaneously
4. Allow Paste action Execution (Onpaste callback function completed)
5. Just set the callback function execution, in which to obtain temporary div innerhtml and filter
6. Restore the cursor and focus position that you just saved and remove the temporary div
7. Post the filtered content to the IFRAME in the HTML editor via the inserthtml Command (execcommand ("inserthtml").

The detailed code is as follows:
Copy Code code as follows:

function GetSel (W)
{
Return w.getselection? W.getselection (): w.document.selection;
}
function SetRange (sel,r)
{
Sel.removeallranges ();
Sel.addrange (R);
}
function Filterpastedata (originaltext)
{
var Newtext=originaltext;
Do something to filter unnecessary data
return newtext;
}
function Block (e)
{
E.preventdefault ();
}
var W,or,divtemp,origintext;
var NewData;
function Pasteclipboarddata (editorid,e)
{
var objeditor = document.getElementById (Editorid);
var eddoc=objeditor.contentwindow.document;
if (Isie)
{
var orrange=objeditor.contentwindow.document.selection.createrange ();
var Ifmtemp=document.getelementbyid ("Ifmtemp");
if (!ifmtemp)
{
Ifmtemp=document.createelement ("IFRAME");
Ifmtemp.id= "Ifmtemp";
Ifmtemp.style.width= "1px";
Ifmtemp.style.height= "1px";
ifmtemp.style.position= "Absolute";
Ifmtemp.style.border= "None";
Ifmtemp.style.left= " -10000px";
Ifmtemp.src= "iframeblankpage.html";
Document.body.appendChild (ifmtemp);
IfmTemp.contentWindow.document.designMode = "on";
IfmTemp.contentWindow.document.open ();
IfmTemp.contentWindow.document.write ("<body></body>");
IfmTemp.contentWindow.document.close ();
}else
{
Ifmtemp.contentwindow.document.body.innerhtml= "";
}
Origintext=objeditor.contentwindow.document.body.innertext;
IfmTemp.contentWindow.focus ();
IfmTemp.contentWindow.document.execCommand ("Paste", false,null);
ObjEditor.contentWindow.focus ();
newdata=ifmtemp.contentwindow.document.body.innerhtml;
Filter the pasted data
Newdata=filterpastedata (NewData);
Ifmtemp.contentwindow.document.body.innerhtml=newdata;
Paste the data into the editor
Orrange.pastehtml (NewData);
Block Default Paste
if (e)
{
E.returnvalue = false;
if (E.preventdefault)
E.preventdefault ();
}
return false;
}else
{
Enablekeydown=false;
Create the temporary HTML editor
var divtemp=eddoc.createelement ("DIV");
Divtemp.id= ' Htmleditor_tempdiv ';
Divtemp.innerhtml= ' \ufeff ';
Divtemp.style.left= " -10000px"; Hide the Div
Divtemp.style.height= "1px";
Divtemp.style.width= "1px";
divtemp.style.position= "Absolute";
Divtemp.style.overflow= "hidden";
EdDoc.body.appendChild (divtemp);
Disable keyup,keypress, MouseDown and KeyDown
ObjEditor.contentWindow.document.addEventListener ("MouseDown", Block,false);
ObjEditor.contentWindow.document.addEventListener ("KeyDown", Block,false);
Enablekeydown=false;
Get current selection;
W=objeditor.contentwindow;
Or=getsel (W). Getrangeat (0);
Move the cursor to into the DIV
var docbody=divtemp.firstchild;
RNG = Eddoc.createrange ();
Rng.setstart (docbody, 0);
Rng.setend (Docbody, 1);
SetRange (GetSel (w), RNG);
Origintext=objeditor.contentwindow.document.body.textcontent;
if (origintext=== ' \ufeff ')
{
Origintext= "";
}
Window.settimeout (function ()
{
Get and filter the "data" after Onpaste was done
if (divtemp.innerhtml=== ' \ufeff ')
{
Newdata= "";
EdDoc.body.removeChild (divtemp);
Return
}
newdata=divtemp.innerhtml;
Restore the old selection
if (or)
{
SetRange (GetSel (w), or);
}
Newdata=filterpastedata (NewData);
Divtemp.innerhtml=newdata;
Paste the new data to the editor
ObjEditor.contentWindow.document.execCommand (' inserthtml ', false, NewData);
EdDoc.body.removeChild (divtemp);
},0);
Enable Keydown,keyup,keypress, MouseDown;
Enablekeydown=true;
ObjEditor.contentWindow.document.removeEventListener ("MouseDown", Block,false);
ObjEditor.contentWindow.document.removeEventListener ("KeyDown", Block,false);
return true;
}
}

The pasteclipboarddata here is used as a onpaste callback function, and to use it, you can add it to the Onpaste event in the HTML Editor's iframe with the following code.
Copy Code code as follows:

var Ifrm=document.getelementbyid ("editor")
if (Isie)
{
Ifrm.contentWindow.document.documentElement.attachEvent ("Onpaste", function (e) {return pasteclipboarddata (ifrm.id , e);});
}
Else
{
Ifrm.contentWindow.document.addEventListener ("Paste", function (e) {return pasteclipboarddata (ifrm.id,e);},false);
}

The Filterpastedata function here is the function we use to do the filtering, specifically how to filter plain text, HTML, and Word data will be explained in the next article.

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.