Search code examples
javascriptjqueryhtmlcsscontenteditable

Apply a CSS class to selected text in Content Editable div


I'm trying to add a class to selected text when a button is pressed. Right now, for some reason my code applies the class to the button when it is pressed but I want it to apply to the selected text itself.

This is what I have:

I need the button to be a div, and that could possibly be the problem, but I just want the highlighted text to get the class, not the button.

Thanks...

function addAnimation() {
  document.execCommand('formatblock', false, 'span');
  selectedElement = window.getSelection().focusNode.parentNode;
  selectedElement.className += "grad";
}
.textField {
  background: #333;
  color: #fff;
  width: 300px;
  height: 300px;
}

.grad {
     -webkit-animation: changeColor 8s ease-in infinite;
   animation: changeColor 8s ease-in infinite;
}

@-webkit-keyframes changeColor {
  0% {color: #ff7473;}
  25% {color: #ffc952;}
  50% {color: #fc913a}
  75% {color: #75D701;}
  100% {color: #ff7473}
}
<div class="textField" contenteditable="true">Hello world. Select this text and press the button</div>

<div onclick="addAnimation()">Animate
            </div>


Solution

  • When you click the virtual button, then the selection is gone. You need to bind to mousedown event this way:

    function addAnimation() {
        selectedElement = window.getSelection().focusNode.parentNode;
        $(selectedElement).addClass('grad');
    }
    $('.animate-selected').on('mousedown', addAnimation);
    .text-field {
        background: #333;
        color: #fff;
        width: 300px;
        height: 100px;
    }
    
    .grad {
        -webkit-animation: changeColor 8s ease-in infinite;
        animation: changeColor 8s ease-in infinite;
    }
    
    .animate-selected{
        margin: 2px 0;
        border: 1px solid blue;
        display: inline-block;
        padding: 0 4px;
        cursor: pointer;
    }
    
    @-webkit-keyframes changeColor {
        0% {
            color: #ff7473;
        }
        25% {
            color: #ffc952;
        }
        50% {
            color: #fc913a
        }
        75% {
            color: #75D701;
        }
        100% {
            color: #ff7473
        }
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="text-field" contenteditable="true">
        Hello world. Select this text and press the button
    </div>
    <div class="animate-selected">
        Animate
    </div>

    Also on JSFiddle.

    In case you want to animate only the selected text, than you do it this way:

    function addAnimation() {
        $('.grad').contents().unwrap(); /* this removes previous animation */
        var selectedText = window.getSelection();
        var container = $(selectedText.anchorNode.parentNode);
        var wrappedText = '<span class="grad">' + selectedText + '</span>'
        container.html(container.html().replace(selectedText, wrappedText));
    }
    $('.animate-selected').on('mousedown', function(e) {
        addAnimation();
    });
    .text-field {
        background: #333;
        color: #fff;
        width: 300px;
        height: 100px;
    }
    
    .grad {
        -webkit-animation: changeColor 8s ease-in infinite;
        animation: changeColor 8s ease-in infinite;
    }
    
    .animate-selected{
        margin: 2px 0;
        border: 1px solid blue;
        display: inline-block;
        padding: 0 4px;
        cursor: pointer;
    }
    
    @-webkit-keyframes changeColor {
        0% {
            color: #ff7473;
        }
        25% {
            color: #ffc952;
        }
        50% {
            color: #fc913a
        }
        75% {
            color: #75D701;
        }
        100% {
            color: #ff7473
        }
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="text-field" contenteditable="true">
        Hello world. Select this text and press the button
    </div>
    <div class="animate-selected">
        Animate
    </div>

    Also on JSFiddle.