0

I've finally found a script that can add undo/redo functionality on programmatic inserted text, which is from here.

Here is the original script demo

Here is the original script

// http://stackoverflow.com/a/9851769/529024
// Opera 8.0+
var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;

// Firefox 1.0+
var isFirefox = typeof InstallTrigger !== 'undefined';

// Safari 3.0+ "[object HTMLElementConstructor]" 
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || (function(p) {
  return p.toString() === "[object SafariRemoteNotification]";
})(!window['safari'] || safari.pushNotification);

// Internet Explorer 6-11
var isIE = /*@cc_on!@*/ false || !!document.documentMode;

// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;

// Chrome 1+
var isChrome = !!window.chrome && !!window.chrome.webstore;



var position = 0;

// text to anser
var text = 'Inserted Text';

// Just for fun :)
if (isFirefox)
  text = "  __ Firefox __ ";
else if (isIE)
  text = "  __ IE __ ";
else if (isEdge)
  text = "  __ Edge __ ";
else if (isSafari)
  text = "  __ Safari __ ";
else if (isOpera)
  text = "  __ Opera __ ";
else if (isChrome)
  text = "  __ Chrome __ ";

/* Adding text on click based on browser */
jQuery(".addText").on("click", function() {
  if (isFirefox) {
    // Firefox
    var val = jQuery(".textArea").val();

    var firstText = val.substring(0, position);
    var secondText = val.substring(position);

    jQuery(".textArea").val(firstText + text + secondText);
  } else {

    jQuery(".textArea").focus();
    var val = jQuery(".textArea").val();

    jQuery(".textArea")[0].selectionStart = position;
    jQuery(".textArea")[0].selectionEnd = position;

    document.execCommand('insertText', false, text);
  }
});

jQuery(".textArea").on("focusout", function(e) {
  position = jQuery(this)[0].selectionStart;
});
textarea {
  padding: 10px;
  font-family: Calibri;
  font-size: 18px;
  line-height: 1.1;
  resize: none;
}
.addText {
  padding: 5px 15px;
  transition: all 0.5s;
  border: 1px solid black;
  border-radius: 2px;
  background-color: #169c16;
  width: 70px;
  margin: 10px 0;
  color: white;
  cursor: pointer;
}
.addText:hover {
  background-color: #2776b9;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea name='textArea' class='textArea' rows="7" cols="50">Suspendisse convallis, metus at laoreet congue, sapien dui ornare magna, a porttitor felis purus a ipsum. Morbi vulputate erat rhoncus, luctus neque ut, lacinia orci. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis
  egestas. Fusce aliquam, nulla nec fringilla ultrices, ipsum lectus maximus nisl, ut laoreet purus lectus eget nisl. Duis blandit cursus nulla. Vestibulum consectetur, nunc non viverra condimentum, neque neque tincidunt diam, nec vestibulum neque nisi
  ac sem. Integer aliquam a leo id laoreet. Mauris ultrices mauris lorem, eu hendrerit odio volutpat ut. Nam eget hendrerit metus.</textarea>
<div class='addText'>
  Add Text
</div>

Now, I've managed to tweak this code to my need and had the script to become like this:

<script>
var isChrome = !!window.chrome && !!window.chrome.webstore;
var text = 'text1';

jQuery("#n101").on("click", function() {
  if (isChrome) {
    var val = jQuery("#codearea1").val();
  } else {

    jQuery("#codearea1").focus();
    var val = jQuery("#codearea1").val();
    document.execCommand('insertText', false, text);
  }
});
</script>

Now, I didn't the CSS so let it go. As for this tweaked script, what is does is, I have a text area above and a button, and when I click that button with id="n101" it will insert text1 and I can also undo/redo it using ctrl + z / ctrl + y

That is all perfect. Until I have to duplicate this technique for about 80 times, where every button is equivalent to 80 different texts.

I am only using this script because I really need the undo/redo feature. I had to rework my entire code just to use this script. Before, I had all the 80 buttons working just fine, but without the undo/redo.

Now, when I try to create at least just 2 buttons using this same script I tweaked, it only pastes the second one.

For example: demo of my script

I have the script and button corresponding to n101 which should yield text1 on the text area when clicked

I also have n102which should yield text2 on the textarea when clicked

<script>
var isChrome = !!window.chrome && !!window.chrome.webstore;
var text = 'text1';

jQuery("#n101").on("click", function() {
  if (isChrome) {
    var val = jQuery("#codearea1").val();
  } else {

    jQuery("#codearea1").focus();
    var val = jQuery("#codearea1").val();
    document.execCommand('insertText', false, text);
  }
});
</script>
<script>
var isChrome = !!window.chrome && !!window.chrome.webstore;
var text = 'text2';

jQuery("#n102").on("click", function() {
  if (isChrome) {
    var val = jQuery("#codearea1").val();
  } else {

    jQuery("#codearea1").focus();
    var val = jQuery("#codearea1").val();
    document.execCommand('insertText', false, text);
  }
});
</script>

However, it is not working like that, which I'm not sure why. I am not so good with javascript that's why I'm not sure what each word on the script means. However, I can make it work sometimes by analyzing it. For this one though, I can't. :(

What's happening in this set up is,

If the only script and button I have is n101, it will yield text1 perfectly

But if I have both or more, it only yield the last one, I believe, which is,

If I clicked n101 or n102, they are only yielding text2

PS. Sorry about my bad english. I hope my question isn't so blurry. Please, I need help. I use this tool for my work, which is template building. Each button saves me and my small team lots of time, and we have about 80+ buttons. Please help me understand this code and how do I fix it?

The Author
  • 193
  • 8
  • 1
    Why do you want `val`? you have `val` variable in your click function. Also what will happen if `isChrome` is true? As `paste` will only be performed if `isChrome` is false – Kiran Shinde Apr 29 '20 at 08:09
  • Hi, honestly, I'm not exactly sure what those are, I'm just keeping it because if I remove it, the script I tweaked is no longer working. I'm not sure how to remove it and have the script still work. Can you please adjust it for me where it will still result in pasting the text? So sorry, i'm not good with javascript, not even with the basics. Just needed this one really quick – The Author Apr 29 '20 at 08:18
  • I wanted to remove the if else, because I only have 1 if anyway. I just don't know how to remove it – The Author Apr 29 '20 at 08:19
  • 1
    Did I understand Your requirement? I have mentioned my understanding below in my answer – Kiran Shinde Apr 29 '20 at 08:21
  • 1
    Or atleast you can make fiddle. https://jsfiddle.net/ Here Paste your code. Hit on save button and share the url. So that we can see actually what is going wrong. By looking at your question, It is really difficult to understand what is wrong – Kiran Shinde Apr 29 '20 at 08:22
  • Hi, I have demo here that you just have toclick run to work. https://www.w3schools.com/code/tryit.asp?filename=GEAOYD90ME14 but I will try the fiddle now – The Author Apr 29 '20 at 08:25
  • [Here is the fiddle demo ](https://jsfiddle.net/s5cud6vm/) – The Author Apr 29 '20 at 08:27

1 Answers1

1

You have the same id for both the textAreas i.e. codearea1

If I did't misunderstood the question, you have a textArea and button (total 80 textArea and button). On clicking of specific button, specific textArea should be filled. So you have to use unique id for each textArea, like you have used for buttons.

If I were you, I would have make code much simpler. Like I would have give attributes class, id to each button, and id to each textArea, and would have keep mapping in my JS

Like

My HTML would be

 <div id='n101' class="fillTextBtn">n101 button</div>
 <div id='n102' class="fillTextBtn">n102 button</div>

Now my JS would have been

<script>

    var mapObj = {
       'n101': 'text1',
       'n102': 'text2'
    }

    jQuery(".fillTextBtn").on("click", function(event) {
       var currButtonId = jQuery(event.target).attr('id');
       var mappedText = mapObj[currButtonId];

       jQuery("#codearea1").focus();
       document.execCommand('insertText', false, mappedText);
    });
</script>

Now you don't have to bind event on each button. We have already binded event to each button using class. And other operations also. No repeated code.

Hope this will help you, and simplify your code.

Fiddle: https://jsfiddle.net/q6rugcvb/

Update

What is happening in your case is

First script tag executed sets text as text1. Then second script tag executed sets text as text2.

So whenever you click on button, text is text2

If you could have put this line in your click function

var text = 'text1';

You would have get desired result.

Like

 jQuery("#n101").on("click", function() {
     var text = 'text1';
Kiran Shinde
  • 5,732
  • 4
  • 24
  • 41
  • Hello @Kenny thank you for taking your time to help me. Actually, I only have one text area, where all the buttons will yield their results, that's why the same #codearea1. Can you please tweak the code you added above again for this? Even just for one button, and I will replicate it for the other buttons. Thank you again. – The Author Apr 29 '20 at 08:23
  • Here is an example of my button: – The Author Apr 29 '20 at 08:31
  • 1
    @TheAuthor I have updated code and also made fiddle. – Kiran Shinde Apr 29 '20 at 08:34
  • 1
    @TheAuthor I have also updated the answer, what you were doing wrong – Kiran Shinde Apr 29 '20 at 08:39
  • Hi @Kenny! Just finished trying and analyzing the code you've provided, and it works perfectly! I can't even ask for more. the "array" type for each text is also better cause I'm having trouble with so many duplicated scripts. You're amazing~ Thank you for patiently reading through my confusing question. Please know how much better me and my team will have our tool now once I've finished updating it. All good now. All thanks to you! :) – The Author Apr 29 '20 at 08:48
  • Hi @Kenny, I've set up my tool completely and it works great! Except for one thing, if I click my ```copy``` button, it copies it and automatically deletes it. But the good is it still copies it. I think it's because of the script you provided, something is clashing. Here is a live demo if you could look into it please: https://jsfiddle.net/pwbfcs65/ – The Author Apr 29 '20 at 16:36
  • What it used to be is that it copies the text and it should stay in the text area until the user deletes it. – The Author Apr 29 '20 at 16:38