Add class with a span when there is @/#

Asked

Viewed 111 times

1

On Twitter or Facebook, when we type a hashtag the text background turns blue, as in the image below

hashtag

I’m trying to do this on js using the .keyup() in a div[contenteditable=true], I am doing with PHP passing the text by jQuery and returning the text if there is @and adding a class and a span. Works, but always returns the text the text cursor that is in div[contenteditable=true] it always goes back to the beginning (left side) of the DIV and when I start the text (right side) it edits but back to the beginning the cursor (left side) again.

I know there might be another method but I’ve researched it and I haven’t found anything like it.

Code jQuery:

$(document).ready(function(){
        $("#text_publica").keyup(function(){
            var text = $("#text_publica").text();
            var dataString = 'nome='+text;
            $.ajax({
                type: 'post',
                url: 'pages/validate_nm.php',
                data: dataString,
                cache: false,
                success: function(data){
                    $("#text_publica").html(data);
                    $("#text_publica").focus();
                }
            });
        });
    });

PHP code:

<?php
    session_start();
    include('main_bd.php');
    include 'data.class.php';


    if(isset($_POST['nome'])){
        $txt = $_POST['nome'];
        $txt = preg_replace('/\B@([\d\w_]+)/i', '<span class="tag">$0</span>', $txt);
        echo $txt;
    }
?>

It came to me an interest in doing this I had this idea to do with jQuery + PHP I’m not an expert in this area of js but I turn around when I need to. In this case I need your help, if you know how to do otherwise or make the text cursor always be in front of the last character right at the end of the text is already a start.

1 answer

1

You will need to memorize the starting position of the selection in the text, then modify the HTML and then move the selection cart from the text to the old position.

To get the position of the cart you will need the property selectionStart element (does not exist in IE <= 8). If you want to use jQuery you will need an add-on.

See the example of the accepted answer here to change cart position (may not work in old browsers).

Also, it would be faster if you looked up the "@" character index and went through all the characters in front of it until you found a space or until you reached the end of the text, then memorized the end of the hashtag in a variable, so just send to the server what the hashtag contains, or nothing if there is no.

(It would be simple a String.prototype.substring, but would be incomplete because of the various types of spaceamento.)

Example:

/* Essa é a função para definir a posição do carret da resposta mencionada acima */
function setCaretPosition(elemId, caretPos) {
    var elem = document.getElementById(elemId);
    if(elem !== null) {
        if(elem.createTextRange) {
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }else{
            if(elem.selectionStart) {
                elem.focus();
                elem.setSelectionRange(caretPos, caretPos);
            } else elem.focus();
        }
    }
}

var text = $("#text_publica").text();

function searchHashtag() {
    var hashtagIndex = text.indexOf('@');
    if(hashtagIndex >= 0) {
        // Procura a indíce do final da hashtag;
        // O fim acontece quando é encontrado um tipo de espaço ou quebra de linha.
        for(var i = 0, charCode; charCode = text.charCodeAt(i) && charCode !== 9 && charCode !== 10 && charCode !== 13 && charCode !== 32; i ++);
        return {
            start: hashtagIndex,
            end: i + 1
        };
    }else{
        return {};
    }
}

var hashtagPos = searchHashtag();
if(hashtagPos.start) {
    var hashtagSub = text.substring(hashtagPos.start + 1, hashtagPos.end);
    // Envia os digitos da hashtag ao servidor
    $.ajax({
        cache: false,
        data: {
            "nome": hashtagSub
        },
        success: function(data){
            var $text = $("#text_publica");
            $text.html(data);
            $text.focus();
            var carretPos = $text[0].selectionStart;
            // Volta à posição anterior no texto
            setCaretPosition("text_publica", carretPos);
        },
        type: 'POST',
        url: 'pages/validate_nm.php'
    });
}

Then you would have to update the PHP code to look like this:

if(isset($_POST['nome'])){
    $txt = '<span class="tag">' . $_POST['nome'] . '</span>';
    echo $txt;
}
  • Good @klaiderklai, is giving error in Setcaretposition: setCaretPosition is not defined, and another when I start typing with (arroba)Labla with other texts nothing happens, when as normal ex: Hi (arroba)hey, the text erases all, it adds the <span class="tag"></span> only empty and gives the error of Setcaretposition, I tried to solve only not mt good in js as I mentioned in the topic. I use Google Chrome.

  • @Hey, you need to copy the function setCaretPosition answer (I mentioned) in the other question. I will update.

  • This setCaret was solved, as I said, when I start with (Arroba)Gleyson he does not put the span with the class tag, already when I start with: hi (Arroba)kk, goes more or less the first "defect" that it erases the whole text, according to "defect" is that you have to be very quick to say because the moment you put the @it already passes the span and the class with nothing, you have to press ex: @a simultaneously, is another and to put these functions within the $("#text_publica"). keyup(Function(){....});, Thanks in advance.

Browser other questions tagged

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