7

I have the following div:

<div id="query" style="width:500px; height:200px;border:1px solid black"
 spellcheck="false" contenteditable="true"></div>​

where Clients can write their SQL queries. What I was trying to do is wrap words the client enters right after hitting Space with a span and give this span a certain class according to the word typed:

example

If the client types select i need to wrap this select word like this in the div:

<span class='select'> SELECT </span> <span> emp_name </span>

CSS

.select{color:blue ;text-transform:uppercase;}

It is something very similar to what jsFiddle does. How can i achieve this?

Here is what i have tried so far : jsFiddle

$(function(){
    $('div').focus() ;
    $('div').keyup(function(e){
        //console.log(e.keyCode) ;
        if(e.keyCode == 32){
            var txt = $('div').text() ;
            var x = 'SELECT' ;
            $('div:contains("'+x+'")').wrap("<span style='color:blue ;
      text-transform:uppercase;'>") ;
            if(txt == 'SELECT'){
                console.log('found') ; // why This Doesn't do any thing  ?
            }

        }
    });

});

2 Answers 2

3

I did a proof of concept with some modifications from what you originally had. See below,

DEMO: http://jsfiddle.net/cgy69/

$(function() {
    $('div').focus();
    var x = ['SELECT', 'WHERE', 'FROM'];
    $('div').keyup(function(e) {
        //console.log(e.keyCode) ;
        if (e.keyCode == 32) {

            //using .text() remove prev span inserts
            var text = $.trim($(this).text()).split(' ');            
            $.each(text, function(i, v) {
                $.each(x, function(j, xv) {
                    if (v.toUpperCase() === xv) {
                        text[i] = '<span style="color: blue; text-transform: uppercase;">' + v + '</span>';    
                    }                                        
                });
            });

            $(this).html(text.join(' ') + '&nbsp;');

            setEndOfContenteditable(this);
        }
    });

    function setEndOfContenteditable(contentEditableElement) {
        var range, selection;
        if (document.createRange) //Firefox, Chrome, Opera, Safari, IE 9+
        {
            range = document.createRange(); //Create a range (a range is a like the selection but invisible)
            range.selectNodeContents(contentEditableElement); //Select the entire contents of the element with the range
            range.collapse(false); //collapse the range to the end point. false means collapse to end rather than the start
            selection = window.getSelection(); //get the selection object (allows you to change selection)
            selection.removeAllRanges(); //remove any selections already made
            selection.addRange(range); //make the range you have just created the visible selection
        }
        else if (document.selection) //IE 8 and lower
        {
            range = document.body.createTextRange(); //Create a range (a range is a like the selection but invisible)
            range.moveToElementText(contentEditableElement); //Select the entire contents of the element with the range
            range.collapse(false); //collapse the range to the end point. false means collapse to end rather than the start
            range.select(); //Select the range (make it the visible selection
        }
    }
});

You going to extend this further to handle

  1. Backspace
  2. HTML contents from previous inserts
  3. Cursor position Partially done, editing in the middle would still mess up the caret.

and more..

Sign up to request clarification or add additional context in comments.

5 Comments

thanks .. look good but why does it focus at the beginning of all the span after firing ?
@MinaGabriel The caret goes to beginning after you change the value of textarea using a script. you can fix this by getting the caret position before update and set it after update..
Step two: prevent the caret from jumping.
@MinaGabriel See this blog.vishalon.net/index.php/… for setting/getting caret position
that was really smart of you dude
0

Starting with a contenteditable element we can replace the markup as we need by operating directly on its innerHtml:

$('#query-container').on('keyup', function(e){
  var $this = $(this);
  //(?!\<\/b\>) negative lookahead is used so that anything already wrapped
  //into a markup tag would not get wrapped again
  $this.html($this.html().replace(/(SELECT|UPDATE|DELETE)(?!\<\/b\>)/gi, '<b>$1</b>'));
  setEndOfContenteditable(this);
});

IMO this is a more readable option. Add the rangeselect method from the previous answer and we have a working fiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.