0

Im trying to create a simple text editor for a web site. I want to add to him something like the code button in this site. So by selecting a specific text, color it's background with gray color. Here is what i have for now but if i have a multi row text selected(rows created by pressing enter) the function test() doesn't work. It works only if i select a row each time.

<!DOCTYPE html>


<html lang="en" xmlns="http://www.w3.org/1999/html"> 
<head>



  <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
  <link rel="stylesheet" href="Awesome/css/font-awesome.css">



</head>
<body onload="InitEditable()">


  <div style="margin-left:10px;">
        <p>
          <div class="btn-group">
           <a class="btn" href="#" onclick="fontEdit('bold')"><i class="icon-bold"></i></a>
           <a class="btn" href="#" onclick="fontEdit('italic')"><i class="icon-italic"></i></a>
           <a class="btn" href="#" onclick="fontEdit('underline')"><i class="icon-underline"></i></a>
           <a class="btn" href="#" onclick="test()"><i class="icon-link"></i></a>
                <a class="btn" href="#" onclick="fontEdit('justifyLeft')"><i class="icon-align-left"></i></a>
                <a class="btn" href="#" onclick="fontEdit('justifyCenter')"><i class="icon-align-center"></i></a>
                <a class="btn" href="#" onclick="fontEdit('justifyRight')"><i class="icon-align-right"></i></a>
                <a class="btn" href="#" onclick="fontEdit('justifyFull')"><i class="icon-align-justify"></i></a>
          </div>
        </p>
  </div>


  <div style="margin-left:10px;"><iframe id="textEditor" style="width:500px;height:170px;font-family:arial;font-size:11px;"></iframe></div>




 <script type="text/javascript">


var editorDoc;
var editor;


function InitEditable() 
{
  editor = document.getElementById("textEditor");
  editorDoc = editor.contentwindow.document;              
  var editorBody = editorDoc.body;


  if ('contentEditable' in editorBody) {
                  // allow contentEditable
          editorBody.contentEditable = true;
  }else {  // Firefox earlier than version 3

          if ('designMode' in editorDoc) {
                          // turn on designMode
                  editorDoc.designMode = "on";                          
          }
  }
}



function fontEdit(x,y)
{
editorDoc.execCommand(x,"",y);
editorDoc.focus();
}


function test(){


  var range = document.getElementById("textEditor").contentwindow.window.getSelection().getRangeAt(0);



  var newNode = document.createElement('div');
  newNode.style.backgroundColor = "gray";


  range.surroundContents(newNode);      
  return false;  


}
</script>


</body>
</html>

There must be a problem with surroundContents() and divs but cannot think something to solve it.

Any idea is welcomed! Thanks in advance.

F.N
  • 401
  • 4
  • 21

2 Answers2

0

One option is the class applier module of my Rangy library (demo)

Live demo: http://jsfiddle.net/D7s5j/

CSS:

.code {
   background-color: #ccc;
   font-family: Courier New, monospace;
}

JS:

var codeApplier = rangy.createCssClassApplier("code");
codeApplier.applyToSelection();
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • Thank you for your answer but is there any other way to do it without using this library? – F.N Feb 12 '13 at 20:35
  • @F.N: Yes: [you can walk the DOM between the selection's boundary points](http://stackoverflow.com/questions/667951/how-to-get-nodes-lying-inside-a-range-with-javascript/7931003#7931003). You may need to split text nodes at each end. Surround text nodes within elements. – Tim Down Feb 13 '13 at 01:01
  • @F.N: Here's an answer that does this: http://stackoverflow.com/a/8456004/96100. I haven't tried it so I can't vouch for it, but the approach is the same and it looks sensible. – Tim Down Feb 13 '13 at 01:03
0

So the problem is that the contenteditable object, creates <div> so this couldn't let surroundContents() work properly and add it's own <div>s around the selected range.

I solve my problem finally by adding this code

$("#textEditor>div").replaceWith(function() { return $(this).contents(); });

which deletes <div>s tags from the contenteditable object.

Also you can add this for create a <br> tag after enter pressed.

$("#textEditor > div").before("<br />").contents().unwrap();

For the second code thank VisioN.

F.N
  • 401
  • 4
  • 21