Is there a way to make a text area partially editable? (make only portions of the text editable)
Asked Answered
H

9

25

I just came across a situation in which it would be an elegant solution to have only portions of a text area (previously loaded with text) be editable while other portions are not ("greyed out", so to speak).

Is this possible at all by using javascript in general?

I would be using jQuery.

Hallelujah answered 26/3, 2011 at 19:48 Comment(4)
will the non-editable content exist in separate portions of the text, or it will be fixed (ex: in the beginning or at the end) ?Averi
@Mohammed The ideal solution given my specific situation would be to have batches of text editable. Those portions would be identifiable by being enclosed between some markers (like @{ } for example)Hallelujah
Hi Kensai, Did you end up implementing a solution? I'd be curious to hear about it because I'm trying to do this now. Thanks!Blindage
@Blindage I'm sorry to say, I haven't. The project died down before I got down to this.Hallelujah
B
6

After searching find it's really hard to make a text area partially editable

Here is my code that i used for this requirement

input
{
  width:100%;
  border:0px solid;
  outline:none
}

 
<!DOCTYPE html>
   <html>     
<div style="padding: 2px;border:1px solid #ccc;width: 82%;max-height:100px;min-height: 51px;overflow:auto;outline: none;resize: both;" contenteditable="true" unselectable="on">    
    

  <input placeholder="enter prefix..." value="editable postfix..." ></input>
  <div id='unEditable' style="background-color:yellow;width: fit-content;padding-left:10px;padding-right:10px;border-radius:10px;height: fit-content;" contenteditable="false" unselectable="off" onkeyup="" >
         fixed content non-editable
        
   </div>
  <input placeholder="enter postfix..." value="editable prefix..." style='width:97%'></input>
    
 </div>
</html>
Barkley answered 29/8, 2019 at 11:4 Comment(0)
C
14

You could do this (just an outlined idea, no code):

Devise a regex that matches your entire text. Use fixed strings for the unmodifiable parts, and use [\s\S]*? for the modifiable parts. Use ^ and $ to anchor your regex.

/^This is fixed text\. Now something editable:[\s\S]*?Now fixed again\.$/

Now react to the keyup event, and probably other events as well (like paste).

With every relevant event, make a check if the regex still matches.

If it doesn't, cancel the event.

Effectively, this should stop modifications to parts that are literal in the regex and thus make certain parts of your text read-only.

Don't forget to test the string on the server side as well after the form post - never trust that the client cannot send invalid values.


EDIT

You can use a regex quote function to dynamically build that regex from strings, this should save you a lot of the hassle.

function regexQuote(s) { return s.replace(/[\[\]^$*+?{}.|\\]/g, "\\$&") }

usage

var re = new Regex(
  "^" + 
  [regexQuote(fixedPart1), regexQuote(fixedPart2)].join("[\\s\\S].*?")
   + "$"
);
Convention answered 26/3, 2011 at 20:10 Comment(2)
Here's an implementation using the "input" event (which sadly isn't fully supported in IE9): jsfiddle.net/un6c950h. Using "keyup" and "paste" events introduces jumpy behaviour where the value changes and then is restored: jsfiddle.net/un6c950h/2Aspergillum
@Aspergillum how can we add one or more constant values (eg. Mr. {Jack} likes {red} color {fruits})Ambary
A
10

If you're using a plain textarea element, you won't be able to style up the required content (based on whether or not that content is editable). At best you'd be able to check to see whether the content your user is trying to change is on either the blacklist or whitelist and then stop the edit or not accordingly. You might also provide some visual feedback like a warning message saying "you can't do that".

My recommendation would be to take advantage of the contenteditable attribute, which might take a bit more time to style but will allow you much greater flexibility in the long run.

You would be able to style up a div element to look much like your required textarea, then use editable spans within that to set whether or not a particular block of text can be edited. You could then use JavaScript commands (refer to the link above) or use a "save" button to retrieve this content, set it as the value for your actual textarea (which you could have hidden) and post your page back as normal.

Use the following code as a rough example.

<div id="editable-content">
    <span id="block1" class="editable" contenteditable="true">This is some editable content which will </span>
    <span id="block2" class="non-editable">quickly be followed by some non-editable content</span>
</div>
<div style="display: none;">
    <textarea id="PostedContent"></textarea>
</div>
<div>
    <input id="save-page" type="submit" value="Save Page" />
</div>

<script type="text/javascript">
    $(function () {
        $('#save-page').click(function () {
            $('#PostedContent').val($('#editable-content').text());
        });
    });
</script>
Accordion answered 26/3, 2011 at 19:57 Comment(3)
+1 this is a nice approach. However, since the form post entirely depends on JavaScript, I would recommend setting contenteditable via JavaScript as well. Also I would dis-recommend popping up message boxes. Flashing the background-color (or something like that) is a lot less intrusive.Convention
This is nice but it has kind of a strange behavior in IE9 with regards to writing something and then deleting it (sometimes the following text goes back and sometimes it stays in its place, leavin this awkward whitespace in between)Hallelujah
Wow. This is genius! I found this: hallojs.org/demo/markdown, and in combination with your approach of using the contenteditable <span> tags, it works beautifully. I thought I was going to have to spend a day or five developing an HTML text editor for what I need, but looks like it only took 5 minutes :)Macromolecule
B
6

After searching find it's really hard to make a text area partially editable

Here is my code that i used for this requirement

input
{
  width:100%;
  border:0px solid;
  outline:none
}

 
<!DOCTYPE html>
   <html>     
<div style="padding: 2px;border:1px solid #ccc;width: 82%;max-height:100px;min-height: 51px;overflow:auto;outline: none;resize: both;" contenteditable="true" unselectable="on">    
    

  <input placeholder="enter prefix..." value="editable postfix..." ></input>
  <div id='unEditable' style="background-color:yellow;width: fit-content;padding-left:10px;padding-right:10px;border-radius:10px;height: fit-content;" contenteditable="false" unselectable="off" onkeyup="" >
         fixed content non-editable
        
   </div>
  <input placeholder="enter postfix..." value="editable prefix..." style='width:97%'></input>
    
 </div>
</html>
Barkley answered 29/8, 2019 at 11:4 Comment(0)
F
2

Well, you could do something like this. This code is very inefficient, I'm just trying to outline the concept.

JS:

$(function () {
            var tb = $("#t").get(0);
            $("#t").keydown(function (event) {
                var start = tb.selectionStart;
                var end = tb.selectionEnd;
                var reg = new RegExp("(@{.+?})", "g");
                var amatch = null;
                while ((amatch = reg.exec(tb.value)) != null) {
                    var thisMatchStart = amatch.index;
                    var thisMatchEnd = amatch.index + amatch[0].length;
                    if (start <= thisMatchStart && end > thisMatchStart) {
                        event.preventDefault();
                        return false;
                    }
                    else if (start > thisMatchStart && start < thisMatchEnd) {
                        event.preventDefault();
                        return false;
                    }
                }
            });
        });

HTML

<textarea id="t" rows=5 cols="80">Hello this is a test @{stuff} 

        this part is editable @{other stuff}     

    </textarea>

This uses your idea of "markers." The general idea is to say ok, is the text range that the user is trying to edit inside of one of our markers? Obviously, using a regexp everytime a key is pressed is not the best way to determine this, I'm not ignoring arrows keys, etc. etc. but this gives you a general idea.

Fortieth answered 26/3, 2011 at 21:31 Comment(0)
C
1

Interesting idea, but sadly, the text within the text area must be treated uniformly, i.e. you can't disable a subsection of the text area contents.

You do have options, however. If you can identify the text that needs to be disabled, you can add it as a DOM element (i.e. a div), and then position it in a way that implies it is inside the text area.

You can imply that this div is inside the text area either by making the text area big and using position: relative/absolute styles to move the div over the text area. Or, you can remove the border on the text area and put it on a container that also contains the div w/ "disabled" text.

Curcuma answered 26/3, 2011 at 19:55 Comment(0)
B
1

I'd suggest, rather than trying to break the contents of an input into sub-strings of editable/non-editable content, you use the contentEditable attribute of an HTML element, and use JavaScript to pass that edited value into a hidden input elsewhere in the page.

Bandoline answered 26/3, 2011 at 19:58 Comment(0)
S
0

In a parent element, you can set the border to 1px solid gray and then inside this, put the

1) textarea (modify the css to not have border) 2) label (no border as well)

In this case, it will look like the both texts inside 1) and 2) are together since they are placed in one box. 1) Is editable though while the other is grayed out.

Subset answered 22/8, 2014 at 8:39 Comment(0)
B
0

I had to do something similar for an input tag but applied it to a textarea tag. You could make a basic JavaScript function that sets the value of the text area to whatever you want if it is under a specific length. This way that text will never be deleted. I used JavaScript so I didn't have to load in jQuery but the same idea could be done with jQuery easy enough.

<textarea name="test-input" maxlength="600" id="test-input" style="width:700px;">Text I don't want to change:</textarea>

var input = document.getElementById("test-input");
input.addEventListener("input", editInputValue);
function editInputValue(e) {
     if (e.target.value.length < 28) {
         e.target.value = "Text I don't want to change:";
     }
}
  
Befool answered 4/8, 2023 at 15:31 Comment(0)
T
-1

I would suggest two textareas one readonly and another editable one, overlapping so it looks like its only one

Teresa answered 28/7, 2017 at 17:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.