Mark contacts / hashtag when entering text with javascript

5

Good morning In my current project, I need to mark the subject's contacts and / or hashtags in the text, while typing For example, when typing '@' and the first few letters, javascript recognizes that it has to search for users, or by typing '#' with a word, javascript recognizes that it has to mark the word as a search link for it

The part of looking for the contacts is quiet for me, using Ajax or a preloaded list, what I'm not really getting is that javascript knows when to get the right word to mark

Can anyone help? Thank you in advance

    
asked by anonymous 20.05.2015 / 15:13

4 answers

2

Using the jQuery UI AUtocomplete, I was able to resolve this problem as follows:

Considering that I have the preloaded arrays, usuarios and tags , I use the startsWith function to check if the text starts with "@" or "#". From there I define what will be the array used for suggestion. Then, I use the grep method of jQuery to filter the items that begin with the text typed from the second character. The return array is the one that will be used to autocomplete:

$("#txt").autocomplete({
    source: function (req, responseFn) {
        var source = [];
        if (req.term.startsWith("@")) 
            source = usuarios;
        else if (req.term.startsWith("#"))
            source = tags;

        var encontrados = $.grep(source, function (item, index) {                
            return item.toLowerCase().startsWith(req.term.substring(1).toLowerCase());
        });
        responseFn(encontrados);
    }
});

See the jsFiddle of a working example: link

    
20.05.2015 / 15:57
2

I wrote the base of the javascript code with the logic that you will need to search the server using AJAX, I used the jQuery library to abstract some things.

(function($) {
    $.fn.hashtag = function(options) {
        var settings = $.extend({
            searchingValue: function() {},
            completeValue: function() {}
        }, options);

        var Hastag = {
            implementationKeyUp: function() {
                var inValue, lastPos, lastChar, hashPos, hashValue;
                lastPos = this.selectionStart - 1;
                inValue = $(this).val().slice(0, lastPos + 1)
                lastChar = inValue[lastPos];
                hashPos = inValue.lastIndexOf("#");
                hashValue = inValue.slice(hashPos);
                if (lastChar == "#") {
                    $(this).data({
                        "searching": true,
                        "currentHashPos": lastPos
                    });
                } else if (lastChar == String.fromCharCode(32) && $(this).data("searching")) { //verifica espaço
                    $(this).data("searching", false);
                    settings.completeValue.call(this, hashValue);
                } else if ($(this).data("searching") && lastChar != String.fromCharCode(32))
                    settings.searchingValue.call(this, hashValue);

                if ($(this).data("currentHashPos") > lastPos || this.selectionStart < $(this).data("currentHashPos"))
                    $(this).data("searching", false);
            },
            implementationKeyDow: function(e) {
                var keyCode = e.keyCode;
                if ($(this).data("searching") && keyCode == 35)
                    return false;
            }
        };
        this.each(function() {
            $(this)
                .on("keyup", Hastag.implementationKeyUp)
                .on("keydown", Hastag.implementationKeyDow)
                .data({
                    "searching": false,
                    "currentHashPos": null
                });
        });
    }
}(jQuery));

var events = {
    searchingValue: function(hashValue) {
        console.log("Procurando: " + hashValue);
        $("#procurando").text("Procurando: " + hashValue);
    },
    completeValue: function(hashValue) {
        console.log("Completo: " + hashValue);
        $("#completo").text("Completo: " + hashValue);
    }
}

$("#message").hashtag(events);
// by @TuyoshiVinicius
p{
    padding:0;
    margin:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><inputtype="text" id="message">
<p>Resultado:</p>    
<div id="console">
    <p id="procurando"/>
    <p id="completo"/>
</div>    
  

Example on jsfiddle

    
20.05.2015 / 16:07
2

You can use a regexp to extract the result of that text and then iterate through the results:

var textarea = document.querySelector('textarea');
textarea.addEventListener('keyup', function () {
    var text = this.value;
    var matches = text.match(/([#@][^\s]+)/g);
    if (matches) matches.forEach(function (match) {
        var tag = match.slice(0, 1);
        var texto = match.slice(1);
        console.log(tag, texto); // fazer algo com tag e texto
    });
});

jsFiddle: link

A regex /(\[#@\]\[^\s\]+)/g explained :

  • () catch / match group
  • % with% of one of the characters present within [#@]
  • [] any character except [^\s] (whitespace)
  • \s one or more occurrences (of exepro +
  • \s every time such a match appears

Then you can iterate through these matches and make substitutions or ajax.

    
20.05.2015 / 16:34
1
Since the search by user or hashtag should start when the cursor is over the keyword beginning with @ or # I made the code below, it will execute a alert() when it should start search.

// busca a palavra em que o cursor está
var getSelectedWord = function(textarea) {
  var text = textarea.value;
  var start = 0;
  var size = text.length;
  var index;
  if (textarea.selectionEnd === textarea.selectionStart) {
    index = text.substr(0, textarea.selectionStart).lastIndexOf(' ');
    if (index > 0) {
      start = index + 1;
      size -= start;
    }
    index = text.indexOf(' ', textarea.selectionEnd);
    if (index > 0) {
      size = index - start;
    }
    return text.substr(start, size);
  }
  return false;
}
document.querySelector('textarea').addEventListener('keyup', function(){
  var selectedWord = getSelectedWord(this);
  // a palavra selecionada tem 3 caracteres ou mais depois do @ ou #
  if (selectedWord && selectedWord.length > 3) {
    if (selectedWord.startsWith('#')) {
      alert('pesquisa hashtag: ' + selectedWord);
    } else if (selectedWord.startsWith('@')) {
      alert('pesquisa usuário: ' + selectedWord);
    }
  }
}, false);
textarea {
  width: 100%;
  min-height: 50px;
}
<textarea placeholder="digite @foo ou #bar"></textarea>
    
20.05.2015 / 16:53