Mark contacts/hashtag in typing text with javascript

Asked

Viewed 444 times

5

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

The part of searching for contacts is quiet for me, using Ajax or a preloaded list, what I’m not getting even is that javascript knows when to pick the right word to mark

Can someone help us? Thanks in advance

  • 2

    are you using textarea or input? and how to know that the tag is over? are always single words?

  • You can also give an example of the result you want to have with links?

  • 1

    @Isaiaslima wrote the javascript implementation using jQuery and now updated this implementation to a jQuery plugin for better code reuse.

  • I’m using an editable div @Sergio

4 answers

2

Using jQuery UI Autocomplete, I was able to solve this problem as follows:

Whereas I have the arrays preloaded, usuarios and tags, I use the function startsWith to check if the text starts with "@" or "#". Hence I define which array will be used for suggestion. Then I use the method grep jQuery to filter items starting with text typed from the second character. The return array is what 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 jsFiddle for a working example: http://jsfiddle.net/v6Ldf3aa/

  • I’ll test the implementation here, thanks

2

I wrote the javascript code base with the logic 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>
<input type="text" id="message">
<p>Resultado:</p>    
<div id="console">
    <p id="procurando"/>
    <p id="completo"/>
</div>    

Example in jsfiddle

  • Fine, I’ll do the tests here

2

You can use a regexp to extract output from this text and then iterate 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: http://jsfiddle.net/umf4m41f/

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

  • () capture group/match
  • [#@] one of the characters within []
  • [^\s] whatever character except \s (blank space)
  • + one or more occurrences (of exepro characters \s
  • g every time such a match appears

Then you can iterate these Matches and make replacements or ajax.

  • 1

    I had thought of something like that too, but I don’t have much knowledge of regular expression yet... good time to get acquainted Thanks, I’ll try it here

  • @Isaiaslima takes a look at the first line link, a good tool to work regex.

  • Thanks, I’ll look yes

  • @Isaiaslima added a better explanation to regex.

1

Whereas the search by user or hashtag should start when the cursor is over the keyword started with @ or # I made the code below, it will run a alert() when to start the 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>

  • I will do the tests here Thank you

Browser other questions tagged

You are not signed in. Login or sign up in order to post.