treehouse : what would you like to learn today?
Web Design Web Development iOS Development

"csstricks like" texteditor

  • hi it's me again.

    i want to create a css-tricks like texteditor with javascript and jQuary. everything works great till i found out that my codes doesnt work in IE! here is my code for italic button:

    var textComponent = document.getElementById('comment'); //"coment" is id of the textarea
    var selectedText;
    
    if (textComponent.selectionStart != undefined) //means if browser is not IE
    {
      var startPos = textComponent.selectionStart; //selects index of selected text's start position
      var endPos = textComponent.selectionEnd;     //selects index of selected text's end postion
      selectedText = textComponent.value.substring(startPos, endPos);  //cuts selected text
      
            if ( selectedText != "" )     //if selected text is not empty
      {    
        var strLen = selectedText.length;     //gets selected text lenght
    
                     //selects everything before selected text
        var tempFirst = textComponent.value.slice(0,startPos);
         
                    //selects everything after selected text:
                    var tempSecond = textComponent.value.slice( startPos + strLen, textComponent.value.length);
        
        var n = tempFirst + "*" + selectedText + "*" + tempSecond; //adds markdown for italic to selected text
                    
        document.getElementById("comment").value=n;
      }
     }
    

    i wrote this code for determining that user browser is IE:

    else if (document.selection != undefined){  //if user browser is IE
         ...
    }
    

    everything in IE version is ok(because it's javascript!!) but the problem is you can not find startPos and endPos of selected text in IE with this method. i googled and found nothing! createTextRange() or createRange() dont work! after 2day search in google i can get startPos but i need endPos too. this is the code for IE:

    else if (document.selection != undefined){  //if user browser is IE
         textComponent.focus();
    
         var r = document.selection.createRange();
    
        var re = textComponent.createTextRange(),
         rc = re.duplicate();
                
        re.moveToBookmark(r.getBookmark());
        rc.setEndPoint('EndToStart', re);
                
        startPos = rc.text.length;
        endPos = ????? // :'(
    }
    

    updated:

    here is the code pen: My Code Pen To this Code

  • A demo or link to an active site that uses this would be useful to troubleshoot

  • yes guys i'll do so, thanks

  • thanks @chrisburton, i'm processing forums-ck.js to understand that and find out how can i change for mine ;)

  • I wish I could help you further but Javascript is definitely not my area. Sorry!

  • that was not the file i need Chris. i'm a newbie in JS and don't say that you are very welcome.

  • I think it is the file for the functionality you're talking about. @chriscoyier is using Markdown so it adheres to those specific characters needed to change the style of the text.

  • @mostafaghanbari I grabbed this code from the Kirby panel and it seems to work.

    Demo: http://codepen.io/chrisburton/pen/Jmqdi

  • @chrisburton sadly it doesnt work in IE :( i dont know why IE is always different from any other browsers even it's old versions! appreciate that but i opened your work in IE and nothing happend! even in IE8(using browserstack.com and IE developers tools)!! i worked 72hours for fixing this but till now i got nothing! :( and again appreciate Chris for your help.

  • I got this from Stackoverflow:

    function wrapText(elementID, openTag, closeTag) {
        var textArea = $('#' + elementID);
        var len = textArea.val().length;
        var start = textArea[0].selectionStart;
        var end = textArea[0].selectionEnd;
        var selectedText = textArea.val().substring(start, end);
        var replacement = openTag + selectedText + closeTag;
        textArea.val(textArea.val().substring(0, start) + replacement + textArea.val().substring(end, len));
    }
    
    // usage: wrapText('textarea-id', '<strong>', '</strong>');

    The $('#' + elementID) is a JQuery selector. You may change that into document.getElementById(elementID) and textArea.val() into textArea.value

    http://jsfiddle.net/tovic/bd4np/

    By the way, does anybody know how to replace part of the selected text with something. For example, replace all \n character in the selected text with \n\t for indentation like in Stackoverflow?

    Edit 25 Feb: My English
  • @Hompimpa yes anybody know how to replace part of the selected text with something but your code doesn't work in IE like mine!! dont test it on jsfiddle.net because it runs on their server not on your web browser! so you test jsfiddle version with IE and think it works! you can test it on codepen and see the resualts. the problem is selectionStart and selectionEnd doesn't work in God damn IE!

  • UPDATE 2: Doesn't work in IE on CodePen, but works on my live site:

    
    function getSelection(input)
    {
      input.focus();
      if(typeof document.selection != 'undefined') {
        var range = document.selection.createRange();
        return range.text;
      }
      /* für neuere auf Gecko basierende Browser */
      else if(typeof input.selectionStart != 'undefined')
      {
        return input.value.substring(input.selectionStart, input.selectionEnd);
      }
      return "";
    }
    
    function setSelectionText(input, text)
    {
      /* für Internet Explorer */
      input.focus();
      if(typeof document.selection != 'undefined') {
        /* Einfügen des Formatierungscodes */
        var range = document.selection.createRange();
        range.text = text;
        /* Anpassen der Cursorposition */
        //range = document.selection.createRange();
        if (insText.length == 0) {
          range.move('character', 0);
        } else {
          range.moveStart('character', -shortLength(text));      
          //range.moveEnd('character', -eTag.length);      
          range.moveEnd('character', 0);      
        }
        range.select();
      }
      /* für neuere auf Gecko basierende Browser */
      else if(typeof input.selectionStart != 'undefined')
      {
        /* Einfügen des Formatierungscodes */
        var start = input.selectionStart;
        var end = input.selectionEnd;
        var insText = input.value.substring(start, end);
        input.value = input.value.substr(0, start) + text + input.value.substr(end);
        /* Anpassen der Cursorposition */
        input.selectionStart = start;
        input.selectionEnd = start + shortLength(text);
      }
      /* für die übrigen Browser */
      else
      {
      // einfach am Ende einfügen
        input.value = input.value + aTag + eTag;
      }
    }
    
    function insert(input, aTag, eTag)
    {
      /* für Internet Explorer */
      input.focus();
      if(typeof document.selection != 'undefined') {
        /* Einfügen des Formatierungscodes */
        var range = document.selection.createRange();
        var insText = range.text;
        var text = aTag + insText + eTag
        range.text = text;
        /* Anpassen der Cursorposition */
        //range = document.selection.createRange();
        if (insText.length == 0) {
          range.move('character', -shortLength(eTag));
        } else {
          range.moveStart('character', -shortLength(insText) -shortLength(eTag));      
          //range.moveEnd('character', -eTag.length);      
          range.moveEnd('character', -shortLength(eTag));      
        }
        range.select();
      }
      /* für neuere auf Gecko basierende Browser */
      else if(typeof input.selectionStart != 'undefined')
      {
        /* Einfügen des Formatierungscodes */
        var start = input.selectionStart;
        var end = input.selectionEnd;
        var insText = input.value.substring(start, end);
        input.value = input.value.substr(0, start) + aTag + insText + eTag + input.value.substr(end);
        /* Anpassen der Cursorposition */
        var pos;
        if (insText.length == 0) {
          pos = start + shortLength(aTag);
        } else {
          pos = start + shortLength(aTag);
        }
        input.selectionStart = pos;
        input.selectionEnd = pos + insText.length;
      }
      /* für die übrigen Browser */
      else
      {
      // einfach am Ende einfügen
        input.value = input.value + aTag + eTag;
      }
    }
    

    getSelection(input) returns the selected text for a given input-element setSelectionText(input, text) replaces the selected text in a given input-element with text insert(input, aTag, eTag) surrounds the selected text in input with aTag and eTag

  • @dgriesel thanks but i test your getSelection(input) method and insert(input, aTag, eTag) function and nothing happened in IE! the insert method doesnt recognize selected text!

  • Ok, now I'm confused. Where did you try it? When I used it in IE8 on CodePen, nothing worked. Then I opened the website I've been using it on and it worked.

  • @dgriesel i used your code directly into my site and nothing happend! after 3day work on this the closest code i have found is this link:

    stack overflow

    with this code you get what you want in codepen but the end point doesn't work in IE!! i mean it just show current cursor position!!

  • I like this website

  • @mostafaghanbari that's odd. If you like, you could give me a link to your site, so I can have a look where the problem is.

  • sorry @dgriesel but its a local host site! :( on odd thing about it is that defiantly it works in IE but it doesnt work in my wordpress!! :( i'm implementing comment-template.php here is comment-template.php file(related codes not all of them):

    
    $required_text = sprintf( ' ' . __('Required fields are marked %s'), '<span class="required">*</span>' );
      $defaults = array(
        'fields'               => apply_filters( 'comment_form_default_fields', $fields ),
        'comment_field'        => '<p class="comment-form-comment"><label for="comment">' . _x( 'Comment', 'noun' ) . '</label><div class="newCommentCommandBar"><p class="alignleft" onclick="textBold();">Bold</p>  <p class="alignleft" onclick="textItalic();">Italic</p>  <p class="alignleft" onclick="getLink();">Link</p>  <p id="getCode" class="alignleft" onclick="getCode();">Code</p><p id="newCommentHelpText" class="alignright">راهنما</p></div><div style="clear: both;"></div><textarea id="comment" name="comment" cols="45" rows="8" aria-required="true"></textarea><p class="newCommentTip" dir="rtl">برای نوشتن میتوانید از markdown استفاده کنید</p></p>',
        'must_log_in'          => '<p class="must-log-in">' . sprintf( __( 'You must be <a href="%s">logged in</a> to post a comment.' ), wp_login_url( apply_filters( 'the_permalink', get_permalink( $post_id ) ) ) ) . '</p>',
        'logged_in_as'         => '<p class="logged-in-as">' . sprintf( __( 'Logged in as <a href="%1$s">%2$s</a>. <a href="%3$s" title="Log out of this account">Log out?</a>' ), get_edit_user_link(), $user_identity, wp_logout_url( apply_filters( 'the_permalink', get_permalink( $post_id ) ) ) ) . '</p>',
        'comment_notes_before' => '<p class="comment-notes">' . __( 'Your email address will not be published.' ) . ( $req ? $required_text : '' ) . '</p>',
        'comment_notes_after'  => '<p class="form-allowed-tags">' . sprintf( __( 'You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: %s' ), ' <code>' . allowed_tags() . '</code>' ) . '</p>',
        'id_form'              => 'commentform',
        'id_submit'            => 'submit',
        'title_reply'          => __( 'Leave a Reply' ),
        'title_reply_to'       => __( 'Leave a Reply to %s' ),
        'cancel_reply_link'    => __( 'Cancel reply' ),
        'label_submit'         => __( 'Post Comment' ),
      );
    
      $args = wp_parse_args( $args, apply_filters( 'comment_form_defaults', $defaults ) );
    
      ?>
    
    function getInputSelection(el) {
            var start = 0, end = 0, normalizedValue, range,
              textInputRange, len, endRange;
    
              range = document.selection.createRange();
    
              if (range && range.parentElement() == el) {
                len = el.value.length;
                normalizedValue = el.value.replace(/\r\n/g, "\n");
    
                // Create a working TextRange that lives only in the input
                textInputRange = el.createTextRange();
                textInputRange.moveToBookmark(range.getBookmark());
    
                // Check if the start and end of the selection are at the very end
                // of the input, since moveStart/moveEnd doesn't return what we want
                // in those cases
                endRange = el.createTextRange();
                endRange.collapse(false);
    
                if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                  start = end = len;
                } else {
                  start = -textInputRange.moveStart("character", -len);
                  start += normalizedValue.slice(0, start).split("\n").length - 1;
    
                  if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                  } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                  }
                }
              }
    
            return {
              start: start,
              end: end
            };
          }
          
          
          function textItalic(){
              var textComponent = document.getElementById('comment');
              var selectedText;
              // IE version
              if (document.selection != undefined)
              {
              textComponent.focus();
              var sel = getInputSelection(textComponent);
    
                                            //this is where this code doesnt work
              alert(sel.start + ", " + sel.end);
              selectedText = textComponent.value.substring(sel.start, sel.end);
              
              if ( selectedText != "" )
                {
                  var strLen = selectedText.length;
                  var lastCharacter = selectedText.slice(strLen-1,strLen);
                  var flagForSpace= "false";
                  
                  if (lastCharacter==" "){
                    selectedText = selectedText.slice(0,strLen-1);
                    flagForSpace = "true";
                  }
                  
                  var tempFirst = textComponent.value.slice(0,startPos);
                  var tempSecond = textComponent.value.slice( startPos + strLen, textComponent.value.length);
                  if ( flagForSpace=="true" )
                    var n = tempFirst + "*" + selectedText + "* " + tempSecond;
                  else
                    var n = tempFirst + "*" + selectedText + "*" + tempSecond;
                    
                  document.getElementById("comment").value=n;
                }
              
              }
              // Mozilla version
              else if (textComponent.selectionStart != undefined)
              {
              var startPos = textComponent.selectionStart;
              var endPos = textComponent.selectionEnd;
              selectedText = textComponent.value.substring(startPos, endPos);
              if ( selectedText != "" )
                {    
                  var strLen = selectedText.length;
                  var lastCharacter = selectedText.slice(strLen-1,strLen);
                  var flagForSpace= "false";
                  
                  if (lastCharacter==" "){
                    selectedText = selectedText.slice(0,strLen-1);
                    flagForSpace = "true";
                  }
                  
                  var tempFirst = textComponent.value.slice(0,startPos);
                  var tempSecond = textComponent.value.slice( startPos + strLen, textComponent.value.length);
                  if ( flagForSpace=="true" )
                    var n = tempFirst + "*" + selectedText + "* " + tempSecond;
                  else
                    var n = tempFirst + "*" + selectedText + "*" + tempSecond;
                    
                  document.getElementById("comment").value=n;
                }
              }
          }
    
  • I finally had the time to check your code. One problem was that in your IE if-block, startPos was never defined. I changed the logic a bit. Now getInputSelection distinguishes between IE and the rest, so you don't have to duplicate the insertion code.

    Check this CodePen, it works for me even in IE.