Reprint Please specify: theviper http://www.cnblogs.com/TheViper
In the input box @ Friends This feature is very common, the specific effect is probably two:
1. Like JS implementation @ mention friend, enter @ in the input box, according to the character after the @, pop up the corresponding friend menu.
2. Add a button and click on the pop-up layer containing all your friends.
This article describes some of the pits that the cock walked through at the time of realization of the second @. In order to be simple, which of the pop-up layers, pull the data will not say.
First, ask:
1. When you add a @ friend, the @ friend is added to the previous focus regardless of the focus of the editor, and the effect and the simpler editor insert the picture from the cursor (which can still be inserted in the original position after losing focus).
2. After adding to the previous focus position, the cursor automatically appears after the @ friend, regardless of the focus of the editor.
3. If you want to delete @, you must be a @+ friend a piece of delete, like the QQ space comment on the reply to a little research to delete the same friend. The picture is QQ space comment box
4. Similar to 2, after deleting the whole block @ friend, the cursor pauses to the position in front of the @ friend.
5. Compatible with FIREFOX,CHROME,IE6 7 8.
1th and 2nd inserting a picture from the cursor with a simpler editor (which can still be inserted in the original position after losing focus) is easy to implement, except that it is not an IMG SRC address, but HTML. The incoming HTML, or the Firefox incoming tag.
Html= " ";
IE and chrome incoming <button> tag.
Html= "<button onclick=" return false; ' class= ' mention ' contenteditable= ' false ' >@ ' +name+ ' </button>& nbsp; ";
In addition, the Insert method for the Editor object needs to be like the previous one, making some changes so that after inserting the HTML at the original cursor position, the cursor immediately follows.
For the 3rd, if you do not write other code look at the effect of more than a pit dad.
Firefox
You can see that when the cursor moves behind the @ friend, pressing BACKSPACE will not remove it.
Chrome
You can see that the cursor will not only jump to the @ friend, even the right mouse click on the @ friends.
Ie8
Can see IE8 incredibly to meet all the requirements, IE6,IE7 results are the same, not posted out.
First solve the 3rd, @ friend must be the whole block delete.
This is the idea of adding the KeyDown event to the editor for the reason see JS implementation @ refer to a friend. When the backspace is pressed, the lastchild of the HTML before the cursor is not the corresponding package @ the friend's tag (Firefox ,ie Chrome <button>), if so, the label is deleted. Specific to
Get the HTML before the cursor, this in the JS implementation @ mentioned in the friend has appeared, here because the back to use its range, so the range also returned.
functionGettextbeforecursor (containerel) {varPrecedingchar = "", SEL, range, Precedingrange; if(window.getselection) {sel=window.getselection (); if(Sel.rangecount > 0) {Range= Sel.getrangeat (0). Clonerange (); Range.collapse (true); Range.setstart (Containerel,0); Precedingchar=range.clonecontents (); } } Else if(sel =document.selection)) {range=Sel.createrange (); Precedingrange=range.duplicate (); Precedingrange.movetoelementtext (Containerel); Precedingrange.setendpoint ("Endtostart", Range); Precedingchar=Precedingrange.htmltext; } return[Precedingchar,range]; }
In modern browsers, this function returns fragmentdocument. Then delete the lastchild in the Fragmentdocument, which is the corresponding package @ friend's tag, and put it back in front of the cursor.
Check_key:function(e) {varHtmlbeforecursor=gettextbeforecursor ($ (' editor ')), frag=htmlbeforecursor[0],range=htmlbeforecursor[1], Last_node=Frag.lastchild; if(last_node!=NULL&&last_node.nodetype==3&&last_node.nodevalue== "") Last_node=last_node.previoussibling; if(last_node!=NULL&&last_node.classname== ' mention '){ if(last_node.nodename== ' IMG ' | | last_node.nodename== ' BUTTON ') {frag.removechild (Last_node) range.deletecontents (); $(' editor '). InsertBefore (frag,$ (' Editor '). Childnodes[0]) E.preventdefault (); } } }
The first if is excluded from the deletion process and may be more textnode than the value "".
Of course, there are other ways to find the corresponding package @ friend's tag, and then RemoveChild () Delete.
Effect
Firefox
can see the corresponding package @ friend's tag is the whole block can be deleted, but after the deletion of the cursor to go to the front.
Chrome
As with Firefox, the whole block can be deleted successfully, but after this deletion, the editor has no focus.
3rd seems to be solved, the following resolution 4th, after deleting the whole block, the cursor jumps to the delete block before.
Notice the previous article in Document.execcommand ("inserthtml", false,html), which can be followed by the cursor immediately after insertion.
this. insertimage=function(HTML) { this. restoreselection (); if (document.selection) currentrange.pastehtml (HTML); Else { container.focus (); Document.execcommand ("inserthtml",false, HTML); Currentrange.collapse (); } Saveselection (); };
This is done with the fragmentdocument of the package label, not the previous $ (' editor '). InsertBefore (frag,$ (' Editor '). Childnodes[0]). Specific,
Check_key:function(e) {varHtmlbeforecursor=gettextbeforecursor ($ (' editor ')), frag=htmlbeforecursor[0],range=htmlbeforecursor[1], Last_node=Frag.lastchild; if(last_node!=NULL&&last_node.nodetype==3&&last_node.nodevalue== "") Last_node=last_node.previoussibling; if(last_node!=NULL&&last_node.classname== ' mention '){ if(last_node.nodename== ' IMG ' | | last_node.nodename== ' BUTTON ') {frag.removechild (Last_node) range.deletecontents (); varDiv=document.createelement (' div '); Div.appendchild (Frag); Document.execcommand ("Inserthtml",false, div.innerhtml); Div=NULL; E.preventdefault (); } } }
Create a DIV element, add the fragmentdocument to the inside, and then use the innerHTML of the DIV element to get the HTML to delete the parcel label, and finally Document.execcommand (" Inserthtml ", false,html);
Effect
Firefox
You can see that Firefox is up to the requirements.
Chrome
You can see the deletion is successful, the cursor position is no problem, is a lot of meaningless empty parcel label. This is because Chrome is Document.execcommand ("inserthtml", false,html), and the contenteditable attribute of the <button> tag is deleted automatically by the pit daddy. Even if you go back to setattribute, adding the Contenteditable property is useless. And in Firefox there is no such problem, tag still has the Contenteditable property, so that the cursor does not jump into the label.
How to solve? Only for Chrome do not Document.execcommand ("inserthtml", false,html);. However, Document.execcommand ("inserthtml", false,html) is also used in the method of inserting @ friends at the cursor. No way, only to rewrite chrome at the cursor to insert the @ Friends section, here is always in the listening editor and at any time in the changing editor package in the Currentrange.
if (ischrome) { html= ' <button onclick= ' return false; ' class= ' mention ' contenteditable= ' false ' >@ ' + Name+ "</button> " ; $ (' editor '). focus (); var sel=window.getselection (), Range=at_editor.getrange (), node=avalon.parsehtml (HTML); Range.insertnode (node); Range.collapse (); Sel.removeallranges (); Sel.addrange (range); // at_editor.insertimage (HTML); }
For this reason also expose the Currentrange in the editor package.
this. getrange=function() { return currentrange; }
This will ensure that contenteditable= "false" is present in the added @ friend tag. In addition, it is not necessary to determine whether the fragmentdocument LastChild is a <button> tag when deleting. Because there is contenteditable= "false" in the <button> tag, the cursor will automatically jump to the position in front of the @ friends tab after deletion.
Effect
Finally attached example download
Update:
Firefox, press <-left ARROW to move the cursor, if the left side of the cursor is @ friend tag, will delete the label, so delete the label need to determine whether the key is backspace key.
if (e.keycode==8&&last_node!=null&&last_node.classname== ' mention ') { .... }
JS @ Referring to friends in another scenario