0

I'm trying to write a simple web text editor. what I want to do is let the user type on a textarea (or a textarea-like input) and select text with the mouse or with shift key and click a button to apply a color based effects. my questions are such:

  1. how do I capture the selection in a way it's not lost when the button is clicked
  2. how to save the text and the selection
  3. how to make it WYSIWYG

p.s. I don't want a full rich text editor. I need only one effect

thanks

akiva
  • 2,677
  • 3
  • 31
  • 40

2 Answers2

2
  • how do I capture the selection in a way it's not lost when the button is clicked

  • how to save the text and the selection

I credit this completely to @TimDown's answer to a different question here. It replace the current selection with another string.

We create the string by taking the value of the color picker and putting it in a span tag and inserting the current selected text.

  • how to make it WYSIWYG

Use a contenteditable div and funnel the output to a hidden textarea when the form submits.

Here it is all together. Again, the first function replaceSelection() is not my code.

document.getElementById('color').onchange = function() {
    var replace = document.createElement('span');
    replace.style.color = this.value;
    replace.textContent = window.getSelection().toString();
    replaceSelection(replace.outerHTML, true);
}

document.getElementById('wysiwyg').onsubmit = function() {
    document.getElementById('result').textContent = document.getElementById('#input').innerHTML;
}


// @TimDown
function replaceSelection(html, selectInserted) {
    var sel, range, fragment;    
    sel = window.getSelection();
    
    // Test that the Selection object contains at least one Range
    if (sel.getRangeAt && sel.rangeCount) {
        // Get the first Range (only Firefox supports more than one)
        range = window.getSelection().getRangeAt(0);
        range.deleteContents();
        
        // Create a DocumentFragment to insert and populate it with HTML
        // Need to test for the existence of range.createContextualFragment
        // because it's non-standard and IE 9 does not support it
        if (range.createContextualFragment) {
            fragment = range.createContextualFragment(html);
        } else {
            // In IE 9 we need to use innerHTML of a temporary element
            var div = document.createElement("div"), child;
            div.innerHTML = html;
            fragment = document.createDocumentFragment();
            while ( (child = div.firstChild) ) {
                fragment.appendChild(child);
            }
        }
        var firstInsertedNode = fragment.firstChild;
        var lastInsertedNode = fragment.lastChild;
        range.insertNode(fragment);
        if (selectInserted) {
            if (firstInsertedNode) {
                range.setStartBefore(firstInsertedNode);
                range.setEndAfter(lastInsertedNode);
            }
            sel.removeAllRanges();
            sel.addRange(range);
        }
    }
}
#input {
    min-height: 100px; 
    border-radius: 5px; 
    border: 1px solid #ccc;
    padding: 5px;
    margin-bottom: 1px;
}
#result {
    display: none;
}
#wysiwyg input[type="submit"] {
    height: 2em;
    float: right;
}
<form action="" method="post" id="wysiwyg">
    <div id="input" contenteditable="true"></div>
    <textarea name="result" id="result"></textarea>
    <input type="color" id="color" />
    <input type="submit" value="submit" />
</form>
Community
  • 1
  • 1
1

how do I capture the selection in a way it's not lost when the button is clicked

You can get the selected text by using window.getSelection method.

how to save the text and the selection

Save it in a variable.

Ex: var selection = window.getSelection().toString();

how to make it WYSIWYG

You can perform different actions like bolding, underlining or italizing the text (and many other actions) by using window.execCommand method.

I created a simple wysiwyg editor which does bold, underline and italic the selected text.

Check it here.

Mr_Green
  • 40,727
  • 45
  • 159
  • 271