9

I wonder if it's possible to replace certain words inside an iframe.

I've used jQuery to change the content inside the iframe with the same content, but with replacements. The problem here is that 'the cursor resets' to the start of the input field, so you have to write from start again.

So here is what I did

<html>
<head>
<script>
function iFrameOn(){
    richTextField.document.designMode = 'On';
}

</script>
</head>
<body onLoad="iFrameOn();">

<!-- Hide(but keep)your normal textarea and place in the iFrame replacement for it -->
<textarea style="display:none;" name="myTextArea" id="myTextArea" cols="100" rows="14"></textarea>
<iframe name="richTextField" id="richTextField" style="border:#000000 1px solid; width:100px; height:20px;">
</iframe>
<!--End replacing your normal textarea -->
</p>
<script>
      function ReplaceWords(){
          var textfield = document.getElementById("richTextField");

          textfield.contentWindow.document.body.onkeyup = function(e){
              var content   = textfield.contentWindow.document.body.innerHTML;
              var Fixed_Content = content.replace("hey", "yo");
              $(document).ready(function() {
                  $('#richTextField').contents().find('body').html(Fixed_Content);
              });
          };
        };
      ReplaceWords();
</script>

</body>
</html>

The question is: if you can replace some of the content inside the iframe without the cursor resets, because it's not appreciated when you type and it just starts from start again.

Update: Basically it's not the textarea that is in focus, it's hidden inside the iframe therefore I use document.designMode = 'On';.

I have updated the post again, this is how it should have been from the start.

Link to jsfiddle: https://jsfiddle.net/tqf3v2sk/8/

Frederik
  • 409
  • 1
  • 5
  • 19
  • You have an extra `;`. You call the `Hello()` ahead of defining it. You can use either `onmouseenter` event or set an interval to do this. Showing an example would be great. – Adam Azad Jan 05 '16 at 08:47
  • Thanks, but on mouseenter it wouldn't be realtime, while writing. – Frederik Jan 05 '16 at 21:52
  • If I understood you right in iframe you load input field and when user types you try to replace some parts of entered text. If yes, then you can just replace input field value with updated one neither replace html tags. Because whole document replacement cause of the described issue. Otherwise if tags replacement is exactly what you need you can call focus method on input field after content change. – Mihails Butorins Jan 06 '16 at 01:53
  • Yes, you understood me right. I have edited the code, so it's easier to understand. Can you please provide an example of what you tried to tell me, I'm little confused about 'replacing the html tags'? – Frederik Jan 06 '16 at 02:55
  • 3
    If I understand correctly, you have some input/textarea/contenteditable element and want to modify its contents, but keeping the cursor position (what should happen if the cursor was in the replaced part?). That's a possible duplicate of [Stop cursor from jumping to end of input field in javascript replace](http://stackoverflow.com/q/8219639/1529630). The iframe seems superfluous. – Oriol Jan 10 '16 at 17:14
  • 1
    As @Oriol mentioned, the iframe seems superfluous. I think it would be better if you could provide a working fiddle (through sites like jsfiddle or codepen etc.) – sujit Jan 11 '16 at 17:43
  • The code in your example doesn't make sense. Please provide a fiddle. – andi Jan 11 '16 at 21:24
  • The code should make more sense now. – Frederik Jan 13 '16 at 08:00

1 Answers1

4

Working with iFrames in the same domain is not much different from working with DOM elements. You just have to make sure the methods you use are called on the proper window and document object. But once you target correctly the window and document, you can call them from the parent window pretty much in the same way as if it was in the same window as your script.

As for replacement while you type, there are a couple of ways to to it. One way would be to use document.execCommand('insertText') and Selection. You detect if the key being entered matches last character of the word to replace, if so you select the length of the word to replace and check if it matches. If it matches, you call execCommand and it'll replace it leaving the cursor at the end of the replacement.

function replaceOnKeyDown(e, toReplace, replaceWith) {

  var iptFld = e.target;
  var lastLetter = toReplace[toReplace.length - 1];
  var keyEntered = String.fromCharCode(e.keyCode);
    console.log(keyEntered)
  // To make it more efficient, you can call the rest only if the
  // key just pressed is the same as the last of the word you
  // need to replace.
  if (lastLetter.toLowerCase() === keyEntered.toLowerCase()) {
    // Set selection to your word length
    var range = frameWindow.getSelection().getRangeAt(0);
    var caretPosition = range.startOffset;
    // Since you're on key down, the caret position is before the
    // last letter is entered.
    var toReplaceStart = caretPosition - toReplace.length + 1;

    range.setEnd(range.startContainer, caretPosition);
    range.setStart(range.startContainer, toReplaceStart);
    frameWindow.getSelection().addRange(range);
    // Check if the selection matches the word to replace
    // Since you're on mouse down, the range will only include 
    // up until the letter being entered. So you need to validate
    // that the word without the last letter equals
    // the selection.
    if (range.toString() + lastLetter === toReplace) {

      frameDocument.execCommand('insertText', false, replaceWith);
      // prevent last letter to be entered
      e.preventDefault();

    } else {

      frameWindow.getSelection().collapse(range.startContainer, caretPosition);

    }
  }
}

var textfield = document.getElementById("richTextField");
var frameWindow = textfield.contentWindow
var frameDocument = frameWindow.document
frameDocument.designMode = 'on'
frameDocument.body.onkeydown = function(e) {
  replaceOnKeyDown(e, 'hey', 'yo')
};

https://jsfiddle.net/k0qpmmw1/6/

Julien Grégoire
  • 16,864
  • 4
  • 32
  • 57
  • 1
    Hello, sorry for the late response, but this replaces text inside the – Frederik Jan 13 '16 at 07:58
  • oh, I didn't get that. See edit, you can keep the same logic working with execcommand and selection objects – Julien Grégoire Jan 13 '16 at 13:30
  • Thanks that's it. I just as a little bonus, if you write the word 'hey' and quickly press space, it doesn't replace? Any reason for that – Frederik Jan 13 '16 at 13:52
  • Probably because the key down interferes with the function. Maybe splitting the function in two, validating if replacement should occur on keydown, and then make the actual replacement on keyup would resolve this. I'll try to update later today. – Julien Grégoire Jan 13 '16 at 14:44
  • See edit, finally it can work pretty much the same way with onkeydown instead of onkeyup. The validation needs to be a bit different, but it works pretty much the same. And it's more stable that way. – Julien Grégoire Jan 13 '16 at 18:05