Explanation of the @ function in the Weibo post box-

Source: Internet
Author: User
People who often use Weibo will find that when we enter @ in the input box and then press a person's name, a tip prompt layer will pop up: Out of curiosity about this function, with a learning attitude, I read some materials and then discussed and studied this Javascript. For this function ...,. Weibo users often find that when we enter @ in the input box and then press a person's name, a tip prompt layer will pop up ,:



Out of curiosity about this function, and with a learning attitude, I read some materials and then explored and studied this Javascript.
This function is analyzed as follows:

1. Determine the cursor position

2. Determine the string @ In the textarea text box

3. tip pop-up events

4. keyboard operation events

5. ajax call

6. text insertion

......

Of course, there are other functions.

Is it complicated to look at it? It doesn't matter. Let's analyze it step by step.

First, determine the cursor position of textarea. In W3C, obtaining the cursor position is relatively simple. selectionStart and selectionEnd can be used. IE does not support these two attributes, but IE has another document. selection object, which can simulate the same function. The Code is as follows:


  1. // First define a basic class to set some global variables
  2. Function demonAt (opts ){
  3. This. elem = opts. elem; // text box
  4. This. at ={}; // temporarily Save the text box content truncation attribute
  5. This. opt = {};
  6. This. searched = ""; // used to determine whether the user's input character is the same as the previous one. If it is the same, skip ajax
  7. This. url = opts. url;
  8. This. index = 1;
  9. }
  10. // Weibo @ Function
  11. DemonAt. prototype = {
  12. GetCursor: function (elem ){
  13. Var _ this = this;
  14. Var rangeData = {
  15. Start: 0,
  16. End: 0,
  17. Text :""
  18. };
  19. If (typeof (this. elem. selectionStart) = "number") {// W3C
  20. RangeData. start = this. elem. selectionStart; // start position of the cursor
  21. RangeData. end = this. elem. selectionEnd; // the position at the end of the cursor.
  22. RangeData. text = this. elem. value. substring (0, this. elem. selectionStart); // obtain the text box value
  23. } Else if (document. selection) {// IE
  24. Var sRange = document. selection. createRange ();
  25. Var oRange = document. body. createTextRange ();
  26. ORange. moveToElementText (this. elem );
  27. RangeData. text = sRange. text;
  28. RangeData. bookmark = sRange. getBookmark ();
  29. For (I = 0; oRange. compareEndPoints ("StartToStart", sRange) <0 & sRange. moveStart ("character",-1 )! = 0; I ++ ){
  30. If (this. elem. value. charAt (I) = '\ R '){
  31. I ++; // special handling of IE. You need to add 1 to the enter key.
  32. }
  33. }
  34. RangeData. start = I;
  35. RangeData. end = rangeData. text. length + rangeData. start;
  36. RangeData. text = this. elem. value. substring (0, I );
  37. }
  38. // Alert (rangeData. text)
  39. Return rangeData;
  40. },
  41. SetCursor: function (elem, start, end) {// set the cursor
  42. If (this. elem. setSelectionRange) {// W3C
  43. This. elem. setSelectionRange (start, end );
  44. } Else if (this. elem. createRange) {// IE
  45. Var range = this. elem. createRange ();
  46. If (this. elem. value. length = rangeData. start ){
  47. Range. collapse (false );
  48. Range. select ();
  49. } Else {
  50. Range. moveToBookmark (rangeData. bookmark );
  51. Range. select ();
  52. }
  53. }
  54. },
  55. Add: function (elem, txtData, nStart, nLen) {// Insert the elements of the text parameter operation, data, start Coordinate Position, user input length
  56. // This. setCursor (this. elem, this. rangeData );
  57. This. elem. focus ();
  58. Var _ range;
  59. If (this. elem. setSelectionRange) {// W3C
  60. _ TValue = this. elem. value; // obtain the text box content.
  61. Var _ start = nStart-nLen, // set the cursor start point cursor position-the text length @
  62. _ End = _ start + txtData. length, // set the end of the cursor, start + Data Text length
  63. _ Value = _ tValue. substring (0, _ start) + txtData + "" + _ tValue. substring (nStart, this. elem. value. length );
  64. This. elem. value = _ value;
  65. This. setCursor (this. elem, _ end + 1, _ end + 1 );
  66. } Else if (this. elem. createTextRange ){
  67. _ Range = document. selection. createRange ();
  68. _ Range. moveStart ("character",-nLen); // move the cursor
  69. _ Range. text = txtData + "";
  70. }
  71. }
  72. }



Customizes A rangeData object and saves the cursor position and the string from the cursor position to the start in the textarea box. This object is used in other functions below. Based on the cursor position, you can write the text insert function add (); with the above function, we can judge the @ character in the textarea box, and then locate and pop up the tip layer, if this is determined, we can use the regular expression:

  1. Var _ reg =/@ [^ @ \ s] {1, 20} $/g;



So positioning is unrealistic if it is determined in textarea, because we cannot obtain the correct left and top values, so we need to simulate a p layer to insert p into the body, locate to the same position as textarea, then obtain the text in textarea, split the string, and add the tag element. In this way, the correct position can be obtained. The following code is more intuitive.

  1. Var _ string = "" + "@ text above" + "" +"@"+" "+" @ Text "+ "";



Many people should understand this sentence and append this paragraph to the p position of the appeal. In this way, we can The tag obtains the offset value. So we wrote the following code:


  1. DemonAt. prototype = {
  2. Init: function () {// first we need to initialize
  3. Var _ body = $ ("body ");
  4. Var _ p = $ ("

    "),
  5. _ Tip = $ ("

    ");
  6. _ Body. append (_ p );
  7. _ Body. append (_ tip );
  8. Var _ left = $ (this. elem). offset (). left + "px ",
  9. _ Top = $ (this. elem). offset (). top + "px ",
  10. _ Width = $ (this. elem). outerWidth () + "px ",
  11. _ Height = $ (this. elem). outerHeight () + "px ",
  12. _Lineheight1_1_(this.elemate.css ("line-height "),
  13. _ Style = "position: absolute; overflow: hidden; z-index:-9999; line-height:" + _ lineHeight + "; width:" + _ width + "; height: "+ _ height +"; left: "+ _ left +"; top: "+ _ top;
  14. _ P. attr ("style", _ style );
  15. This. inset ();
  16. },
  17. GetAt: function (){
  18. Var _ rangeData = this. getCursor ();
  19. Var k = _ value = _ rangeData. text. replace (/\ r/g, ""); // remove the line break
  20. Var _ reg =/@ [^ @ \ s] {} $/g; // regular expression, which contains @ at the end of the value and is within 20 characters
  21. Var _ string = "";
  22. If (_ value. indexOf ("@")> =
  23. 0 & _ value. match (_ reg )){
  24. Var _ postion = _ rangeData. start;
  25. Var _ oValue = _ value. match (_ reg) [0]; // locate the last matched data in the value
  26. Var vReg = new RegExp ("^" + _ oValue + ". * $", "m"); // Regular Expressions matching data are retained temporarily.
  27. _ Value = _ value. slice (0, _ postion); // rewrite _ value string truncation from 0 to cursor position
  28. If (/^ @ [a-zA-Z0-9 \ u4e00-\ u9fa5 _] + $/. test (_ oValue )&&! /\ S/. test (_ oValue )){
  29. This. at ['M'] = _ oValue. slice (1); // The character entered by the user, such as @ decadent little magic, that is, "decadent little magic"
  30. This. at ['l'] = _ value. slice (0,-_ oValue. length-1 ); // @
  31. This. at ['R'] = k. slice (_ postion-_ oValue. length, k. length); // the text following @
  32. This. at ['pos'] = _ postion; // cursor position
  33. This. at ['len'] = _ oValue. length; // the length from the cursor position to @, for example, @ decadent little magic, that is, the length of "decadent little magic"
  34. This. showTip (this. url)
  35. } Else {// alert (1)
  36. This. hiddenTip ()
  37. }
  38. } Else {
  39. This. hiddenTip ()
  40. }
  41. },
  42. BuidTip: function () {// create a tip and set the position of the tip.
  43. Var _ this = this;
  44. $ ("# TWarp"). empty ();
  45. Var _ string = "" + this. format (this. at ['l']) + "" +"@"+" "+ This. format (this. at ['R']) + "";
  46. $ ("# TWarp" pai.html (_ string );
  47. Var _ left = $ ("# tWarp cite"). offset (). left + "px ",
  48. _ Top = $ ("# tWarp cite"). offset (). top + parseInt ($ ("# tWarp" line .css ("line-height") + "px ";
  49. If (parseInt (_ top)> parseInt ($ ("# tWarp"). offset (). top + $ ("# tWarp"). height ())){
  50. _ Top = $ ("# tWarp"). offset (). top + $ ("# tWarp"). height () + "px ";
  51. }
  52. $ ("# TipAt" ).css ({
  53. "Left": _ left,
  54. "Top": _ top,
  55. "Display": "block"
  56. });
  57. $ ("# TipAt li"). eq (1). addClass ("on"). siblings (). removeClass ("on ");
  58. _ This. hover ();
  59. // Cancel keyup binding, bind keydown, and select keyboard operations to avoid conflicts with text box events
  60. $ (_ This. elem). unbind ('keyup'). bind ('keylow', function (e ){
  61. Return _ this. keyMove (e );
  62. });
  63. },
  64. HiddenTip: function (){
  65. Var _ this = this;
  66. $ ("# TipAt" ).css ("display", "none ");
  67. $ ("# TipAt li"). unbind ("click, mouseover ");
  68. }
  69. }



Then we add the keyboard operation. Note that we have bound the keyup event when entering text in textarea. To avoid multiple event bindings, we use the keydown event for tip selection.

  1. DemonAt. prototype = {
  2. KeyMove: function (e) {// keyboard operation
  3. Var _ this = this;
  4. Var _ key = e. keyCode;
  5. Var _ len = $ ("# tipAt li"). length;
  6. Switch (_ key ){
  7. Case 40:
  8. // Lower
  9. _ This. index ++;
  10. If (_ this. index >_len-1 ){
  11. _ This. index = 1;
  12. }
  13. _ This. keyMoveTo (_ this. index );
  14. // Return false must be added. Otherwise, JS will continue to call keyHandler, so that the keyup event is bound, which affects the keydown event of the keyboard.
  15. Return false;
  16. Break;
  17. Case 38:
  18. // Upload
  19. _ This. index --;
  20. If (_ this. index <1 ){
  21. _ This. index = _ len-1;
  22. }
  23. _ This. keyMoveTo (_ this. index );
  24. Return false;
  25. Break;
  26. Case 13:
  27. // Enter
  28. Var txtData = $ (". on"). text ();
  29. _ This. add (_ this. elem, txtData, _ this. at ['pos'], _ this. at ['len'])
  30. _ This. keyHandler ()
  31. Return false;
  32. Break;
  33. Default:
  34. };
  35. _ This. keyHandler ();
  36. },
  37. KeyHandler: function (){
  38. Var _ this = this;
  39. _ This. index = 1;
  40. // Rebind the keyup key after the enter keyboard operation
  41. $ (_ This. elem). unbind ("keydown"). bind ("keyup", function (){
  42. _ This. getAt ();
  43. })
  44. },
  45. KeyMoveTo: function (index ){
  46. $ ("# TipAt li"). removeClass ("on"). eq (index). addClass ("on ");
  47. }
  48. }



Then, add the Click Event and hover event of the tip.

  1. DemonAt. prototype = {
  2. Inset: function () {// bind an event to li,
  3. Var _ this = this;
  4. $ ("# TipAt"). delegate ("li", "click", function () {// event delegate
  5. If ($ (this). index () = 0 ){
  6. _ This. elem. focus ();
  7. Return false;
  8. } Else {
  9. Var txtData = $ (this). text ();
  10. _ This. add (_ this. elem, txtData, _ this. at ['pos'], _ this. at ['len'])
  11. _ This. hiddenTip ()
  12. }
  13. })
  14. },
  15. Hover: function (){
  16. // Hover event
  17. Var _ this = this;
  18. $ ("# TipAt li: not (: first)"). hover (function (){
  19. _ This. index = $ (this). index ();
  20. $ (This). addClass ("hover"). siblings (). removeClass ("on hover ")
  21. }, Function (){
  22. $ (This). removeClass ("hover ");
  23. })
  24. }
  25. }


Here, the @ function of Weibo has been fully explained. I hope you can understand it clearly.



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.