First Demonstration:
After reading the figure, let's go directly to the Code. There are several dead places in the code. I am prompted to change it.
// @ Display the user list (function ($ ){
// Determine whether it is a child element
Function isparent (OBJ, pobj ){
While (OBJ! = Undefined & OBJ! = NULL & obj. tagname. touppercase ()! = 'Body '){
If (OBJ = pobj ){
Return true;
}
OBJ = obj. parentnode;
}
Return false;
}
$. FN. showatusers = function () {if ($ ("# at_textarea "). length = 0) {$ ("body "). append ("<PRE id = 'at _ textarea '> </PRE> <Div id = 'at _ userslist'> </div> ");
// First, simulate an input box and a div that displays the user list. Some people say that pre will display the content with a carriage return, which is the same as the original one. But after the test, the @ location is still incorrect, is pre a legend...} Return this. each (function () {var T = NULL, li_index = 1, $ at_textarea = $ ("# at_textarea"), $ at_userslist = $ ("# at_userslist "); $ (this ). on ("keydown click", function (e) {// keydown is required; otherwise, the cursor moves VaR _ key = E. keycode, textarea = this; if ($ at_userslist.is (": visible") & (_ key = 40 | _ key = 38 | _ key = 13 )) {tipliselect (textarea, _ key); Return false;} else {If (T! = NULL) {cleartimeout (t);} t = setTimeout (function () {drawtextarea (textarea); getat (textarea) ;}, 300 );}}); $ ("body "). on ("click", function (e) {If (! Isparent(e.tar get, $ at_userslist [0]) {hiddentip () ;}}); // obtain the cursor var getcursor = function (textarea) {var rangedata = {start: 0, end: 0, text: ""}; textarea. focus (); If (textarea. setselectionrange) {// W3C rangedata. start = textarea. selectionstart; rangedata. end = textarea. selectionend; rangedata. TEXT = textarea. value. substring (0, rangedata. end);} else if (document. selection) {// ie var I, OS = do Cument. selection. createRange (), OR = document. body. createTextRange (); or. movetoelementtext (textarea); rangedata. TEXT = OS. text; rangedata. bookmark = OS. getbookmark (); for (I = 0; or. compareendpoints ('startstart', OS) <0 & OS. movestart ("character",-1 )! = 0; I ++) {If (textarea. value. charat (I) = '\ n') {I ++ ;}} rangedata. start = I; rangedata. end = rangedata. text. length + rangedata. start; rangedata. TEXT = textarea. value. substring (0, I) ;}return rangedata ;}, // set the cursor setcursor = function (textarea, rangedata) {textarea. focus (); If (textarea. setselectionrange) {// W3C textarea. setselectionrange (rangedata. start, rangedata. end);} else if (textarea. createTextRange) {// ie var OR = textarea. createTextRange (); If (textarea. value. length === rangedata. start) {or. collapse (false); or. select ();} else {or. movetobookmark (rangedata. bookmark); or. select ();}}},
// Insert the selected user name Add = function (txtdata, object) {var ovalue, atpos, nstart, nend, nvalue, St, Sr, textarea = object. textarea; setcursor (textarea, object. rangedata); ovalue = textarea. value; // the location where the @ character is located. atpos = parseint (object. pos)-parseint (object. len); nvalue = ovalue. substring (0, atpos) + "@" + txtdata + "" + ovalue. substring (object. rangedata. end); nstart = nend = atpos + txtdata. length + 2; ST = textarea. SCR Olltop; textarea. value = nvalue; // After the value is assigned, scrolltop will change back to 0 and reset scrolltop if (textarea. scrolltop! = ST) {textarea. scrolltop = sT;} If (textarea. setselectionrange) {// W3C textarea. setselectionrange (nstart, nend);} else if (textarea. createTextRange ){
// Test the plug-in IE, insert it again, and insert the cursor to the end of name + space. It is not the end. I am not familiar with textrange, so write it as below. It is better to test OK.
// If an expert has a better method, please kindly ask for advice and reply to me. Thank you first. Ovalue = ovalue. substring (object. rangedata. end); // The character ST = ovalue behind the cursor. replace (/\ n/g ,''). length; // Replace the dropped line sr = document. selection. createRange (); Sr. moveend ("character",-St); Sr. select () ;}}, // match @ getat = function (textarea) {VaR _ rangedata = getcursor (textarea); var K = _ value = _ rangedata. text; VaR _ reg =/@ [^ @ \ s] {0, 20} $/g; // match @ followed by 0 to 20 characters if (_ value. indexof ("@")> = 0 & _ value. match (_ reg) {VaR _ postion = _ Rangedata. start; VaR _ ovalue = _ value. match (_ reg) [0]; // find the final matched data VaR _ at ={} in value {}; // store the field information after the input content is intercepted if (_ ovalue = "@") {_ at ['M'] = "namihui "; // modify your favorite markup character, indicating that there is no word behind the input @. I wrote this because I made a website for Nami. _ At ['l'] = _ value. slice (0,-1 ). replace (/\ n/g, '<br>'); // @ the text above, convert the carriage return to br _ at ['R'] = ''; // @ The text behind _ at ['pos'] = _ postion; // cursor position _ at ['len'] = 1; // The length from the cursor position to @ _ at ['rangedata'] = _ rangedata; _ at ['texta'] = textarea; showtip (_ );} else if (/^ @ [a-zA-Z0-9 \ u4e00-\ u9fa5 _-] + $ /. test (_ ovalue )&&! /\ S /. test (_ ovalue) {_ at ['M'] = _ ovalue. slice (1); // The character entered by the user, for example, @ Na Mi Hui, that is, "Na Mi Hui" _ at ['l'] = _ value. slice (0,-_ ovalue. length ). replace (/\ n/g, '<br>'); // @ the text above _ at ['R'] = K. slice (_ postion-_ ovalue. length + 1, K. length); // @ The text behind _ at ['pos'] = _ postion; // cursor position _ at ['len'] = _ ovalue. length; // length from the cursor position to @ _ at ['rangedata'] = _ rangedata; _ at ['texta'] = textarea; showtip (_ );} else {hiddentip () ;}} else {hiddentip () ;}, drawtextarea = function (textarea) {VaR _ left =$ (textarea ). offset (). left + parseint(((textarea).css ("padding-left") + "PX", _ Top = $ (textarea ). offset (). top + parseint(((textarea).css ("padding-top") + "PX", _ width = $ (textarea ). width () + "PX", _lineheight=((textarea).css ("line-height"), tstyle = "line-Height:" + _ lineheight + "; width:" + _ width + "; left: "+ _ left +"; top: "+ _ top; $ at_textarea.attr (" style ", tstyle) ;}showtip = function (OBJ) {var url = 'json2.html '; // you can change the URL to the address for pulling data in the background. The format is later in this article. I have a description of IF (obj. M = "namihui") {// here, another address is written to demonstrate @ matching data returned by the recent contact and the input background, URL of dead data written in two different cases = 'json.html ';} $. ajax ({URL: URL, type: 'post', data: {"key": obj. m}, success: function (result) {buidtip (result, OBJ) ;}}, // create a tip and set the position of the tip to buidtip = function (HTML, OBJ) {VaR _ left, _ top, ttop, citeofs, _ string = "<span>" + OBJ ['l'] + "</span>" + "<cite >@</CITE>" + "<span>" + OBJ ['R'] + "</span> "; $at_textarea.html (_ string); citeofs = $ at_textarea.find ("cite "). offset (); _ left = citeofs. left; _top;citeofs.top;parseint($at_textarea.css ("line-height"); ttop = parseint ($ at_textarea.offset (). top + $ (obj. textarea ). height (); If (_ top> ttop) {_ Top = ttop;} atat_userslist.css ({"Left": _ left, "TOP": _ top, "display ": "Block" )).html ('<ul>' + HTML + '</ul> '). find ("Li "). eq (1 ). addclass ("On"); tiplievent (OBJ); $ (obj. textarea ). data ("at", OBJ) ;}, hiddentip = function () {$ at_userslist.hide (). find ("Li "). off () ;}, // select the List Operation tipliselect = function (textarea, key) {var li = $ at_userslist.find ("Li"), _ Len = Li. length; Switch (key) {Case 40: // down key select li_index ++; If (li_index> _ len-1) {li_index = 1;} li. removeclass ("On "). eq (li_index ). addclass ("On"); break; Case 38: // select li_index --; If (li_index <1) {li_index = _ len-1;} li. removeclass ("On "). eq (li_index ). addclass ("On"); break; Case 13: // enter key var txtdata = Li. filter (". on "). text (), OBJ = $ (textarea ). data ("at"); add (txtdata, OBJ); hiddentip (); break; default: };}, // Add list binding event tiplievent = function (OBJ) {$ at_userslist.find ("Li "). on ("click", function () {if ($ (this ). index () = 0) {obj. textarea. focus ();} else {var txtdata = $ (this ). text (); add (txtdata, OBJ) ;}hiddentip (); Return false ;}). not (": First "). hover (function () {li_index = $ (this ). index (); $ (this ). addclass ("On "). siblings (). removeclass ("On"); Return false ;}, function () {return false ;}) ;}};}) (jquery );
// Bind @ to display the user list
$ ("Textarea"). showatusers ();
The format in json.html is attached:
<Li class = "tit"> select the person closest to @ or directly enter </LI> <li> huafei </LI> <li> Nan Xiaoshu </LI> <li> cangjingkong </LI> <li> looks forward to the year of anti-DDoS </LI> <li> podoino Jieyi </LI> <li> World of Warcraft (Warcraft) </LI> <li> an'an rose </LI>
The format of json2.html is the same, but the text is different. The figure above shows different situations.
Add CSS:
/* The @ friends list prompt in the publish box */# at_userslist {position: absolute; top:-999px; left: 0; display: none; Z-index: 99; width: 180px; overflow: hidden;} # at_userslist ul {border: 1px solid # CCC; padding: 1px; Background-color: # FFF; border-radius: 2px ;} # at_userslist ul Li {width: 100%; Height: 24px; line-Height: 24px; Background-color: # FFF; padding: 0 10px;} # at_userslist ul Li. tit {color: #999; border-bottom: 1px dashed # Eee;} # at_userslist ul Li. on {background-color: # e8e8e8; cursor: pointer; color: #000 ;}# at_textarea {font-family: the font of your release box is the same, otherwise there will be nuances in positioning; position: absolute; overflow: hidden; Z-index:-9999; top:-999px; left: 0 ;}
Finally, I attached some blog posts about textrange, and the code was used:
Http://www.planabc.net/2010/11/17/get_textarea_cursor_position/http://www.cnblogs.com/sweting/archive/2009/07/12/1521782.html