Show the chosen option when the textarea is no longer in focus

My form includes a text box and a button:

<p><textarea rows="4" cols="30">Aliquam erat volutpat.</textarea></p>
<p><input type="button" value="Submit"></p>

When the user selects text in the textarea and then clicks on the submit button, the selection disappears once the textarea loses focus. Is there a way to keep the selected text visible? It doesn't need to be interactive (e.g., typing should not remove the selection or Ctrl+C to copy it), but I would like some visual indication that text is selected within the textarea.

Answer №1

Delving into jsFiddle, I came across CodeMirror, a tool that provides all the necessary elements to create a highly personalized textarea. Although primarily designed for coding, with a simple trick it can be adapted for general textareas as well.

Take a look at the DEMO

To start off, set up a textarea:

<textarea id="a">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</textarea>

Next, add the following script below it to transform the textarea into a CodeMirror textarea and apply extra configurations to revert it back to a regular textarea.

  • mode: In this case, I'm using "none" to eliminate syntax highlighting.
  • lineWrapping: Set it to true for automatic line wrapping on long lines.
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("a"), {
    mode: "none",
    lineWrapping: true
});

Lastly, employ CSS to adjust the dimensions and mimic the appearance of a standard textarea:

.CodeMirror {
    font-family: monospace;
    font-size: 12px;
    width: 300px;
    height: 100px;
    border: solid 1px #000;
}

Answer №2

<textarea onblur="this.focus()">this is a test</textarea>
<p><input type="button" value="Click me"></p>

Functioning properly in IE and Chrome, but not in FF.


Here's a universal fix:

<textarea onblur="doBlur(this)">this is a test</textarea>
<p><input type="button" value="Click me"></p>

<script>
function doBlur(obj) {
  setTimeout(function() { obj.focus(); }, 10);
}
</script>

Answer №3

Although this might not be exactly what you were looking for, I'm going to take a shortcut.

Javascript:

var textarea = document.getElementById('textarea');
var div = document.getElementById('holder');

var original_value = textarea.value;
textarea.onblur = function () {
    var start = textarea.selectionStart;
    var end = textarea.selectionEnd;
    textarea.style.display = "none";
    div.innerHTML = textarea.value.splice(end, 0, "</span>").splice(start, 0, "<span>");
    div.style.display = "block";
}

div.onclick = function () {
    div.style.display = "none";
    textarea.style.display = "block";
    textarea.value = original_value;
}

String.prototype.splice = function( idx, rem, s ) {
    return (this.slice(0,idx) + s + this.slice(idx + Math.abs(rem)));
};

HTML:

<p><textarea id="textarea" rows="4" cols="30">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</textarea></p>
<div id="holder"></div>
<p><input id="click" type="button" value="Click me"></p>

CSS:

textarea, #holder{
    height: 120px;
    width: 300px;
    border: 1px solid black;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 3px;
    font-size: 10pt;
    font-family: Arial;
}
#holder{    
    display: none;
}
#holder span{
    background-color: #b4d5ff;
}

demo: http://jsfiddle.net/Mb89X/4/

Answer №4

You may consider enclosing the textarea in an iframe, allowing the selection to still be visible within the frame upon clicking the button.

This particular demonstration makes use of the srcdoc attribute, which is only compatible with Chrome and Safari 6. However, you can opt for using an iframe without relying on that attribute.

UPDATE: Check out this alternative fiddle that employs jQuery to insert the iframe; it functions effectively in Chrome and Firefox (since Internet Explorer restricts data URIs in an iframe due to security concerns).

Answer №5

It is not achievable with a textarea to accomplish what you are attempting.

Instead of utilizing a textarea, my recommendation would be to use a div with contenteditable="true" along with rangy. Then you can wrap the selected text or choose the text during focus and blur events.

This rangy demo illustrates how to select text:

Answer №6

Given inspiration from @Prisoner, my goal is to enhance the functionality until it seamlessly integrates with scrolling and resizing.

The core concept remains unchanged. I have also developed a comprehensive demonstration with annotations here. Below is a repost for the context of this discussion.

var input = document.getElementById('input');
var div = document.getElementById('holder');

function synchronizeSize() {
    div.style.width = (input.scrollWidth - 4) + "px";
    div.style.height = input.style.height;
}

new MutationObserver(synchronizeSize).observe(input, {
    attributes: true,
    attributeFilter: ["style"]
});

synchronizeSize();

input.onchange = () => synchronizeSize();

input.onblur = () => {
    var start = input.selectionStart;
    var end = input.selectionEnd;
    var text = input.value;
    div.innerHTML = text.substring(0, start) +
        "<span>" + text.substring(start, end) +
        "</span>" + text.substring(end);
    div.style.display = "block";
}

input.onfocus = () => div.style.display = "none";

input.onscroll = () => div.style.top = -input.scrollTop + "px";

input.value = "Lorem ipsum dolor sit amet";

input.select();
#container {
  position: relative; 
  overflow: hidden;
}

#input {
  width: 400px;
  height: 150px;
}

#holder, #input {
    padding: 2px;
    font: 400 13.3333px monospace;
    border: 1px solid #a9a9a9;
    white-space: pre-wrap;
    word-wrap: break-word;
}

#holder {
    display: none;
    position: absolute;
    left: 0;
    top: 0;
    color: transparent;
    pointer-events: none;
    border-color: transparent;
}

#holder span {
    background-color: #c8c8c8;
    color: black;
}
<div id="container">
  <textarea id="input"></textarea>
  <div id="holder"></div>
</div>

Answer №7

In case the button's :focus is not important, this alternative can be considered:

$('input[type=button]').click(function () {
    $('textarea').focus();
});

You can find a working example on this link.

Answer №8

Give this a shot:

const textElement = document.getElementById('text');
if (textElement.setSelectionRange) {
    textElement.focus();
    textElement.setSelectionRange(2, 10);    
} else if (textElement.createTextRange) {
    const selRange = textElement.createTextRange();
    selRange.collapse(true);
    selRange.moveStart('character', 2);
    selRange.moveEnd('character', 10);
    selRange.select();
    textElement.focus();
} else if (typeof textElement.selectionStart !== 'undefined') {
    textElement.selectionStart = 2;
    textElement.selectionEnd = 10;
    textElement.focus();
}

Check it out here!

Answer №9

Developed a custom jQuery plugin that enhances a specified <textarea> element by adding a subtle grayed out selection when the element is not in focus.

// Created a jQuery plugin to enhance visibility of textarea selection when unfocused.                                                                                                                        
// This is achieved by overlaying the selected text with <mark> tags within an underlay                                                                                                                       
$.fn.selectionShadow = function () {
  const $input = this
  const prop = n => parseInt($input.css(n))
  const $wrap = $input.wrap('<div>').parent()   // wrapper                                                                                                                                               
    .css({
      ...Object.fromEntries(
        'display width height font background resize margin overflowWrap'
          .split(' ').map(x => [x, $input.css(x)])),
      position: 'relative',
      overflow: 'hidden',
      border: 0,
      padding: ['top', 'right', 'bottom', 'left'].map(
        x => prop(`padding-${x}`) + prop(`border-${x}-width`) + 'px'
      ).join(' '),
    })
  const $shadow = $('<span>').prependTo($wrap)  // shadow-selection                                                                                                                                      
    .css({ color: 'transparent' })
  $input                                        // input element                                                                                                                                         
    .on('focusin',  () => $shadow.hide())       //   hide shadow if focused                                                                                                                              
    .on('focusout', () => $shadow.show())
    .on('select', evt => {                      //   if selection change                                                                                                                                 
      const i = evt.target                      //     update shadow                                                                                                                                     
      const [x, s, a] = [i.value ?? '', i.selectionStart, i.selectionEnd]
      $shadow.html(x.slice(0, s) + '<mark class=selectionShadow>' +
                   x.slice(s, a) + '</mark>' + x.slice(a))
    })
    .css({
      boxSizing: 'border-box',
      position: 'absolute', top: 0, left: 0, bottom: 0, right: 0,
      overflow: 'hidden',
      display: 'block',
      background: 'transparent',
      resize: 'none',
      margin: 0,
    })
  $('head').append(
    `<style>mark.selectionShadow { background: #0003; color: transparent }`)
}

To activate the plugin, use $('textarea').selectionShadow().

The plugin adds an 'underlay' layer to the textarea and ensures it matches the padding, font style, and word wrapping settings. This way, the textarea and underlay text align perfectly. The underlay updates alongside the textarea's selection, highlighting the current selection using <mark> tags with a gray background (text color set to transparent to avoid interference with text edges).

This implementation was crafted for personal web projects, feel free to utilize!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

axio. to retrieve the information stored in an alternate document

Seeking assistance in utilizing API data in a separate file. I have three files: api.jsx import axios from 'axios'; export const api = (url, data) => { const { path, method } = url; let result ={}; axios({ method: ...

How can I cancel or reset a timeInterval in AngularJS?

In my project demo, I have implemented a feature that fetches data from the server at regular intervals using $interval. Now, I am looking for a way to stop or cancel this process. Can you guide me on how to achieve this? And if I need to restart the proce ...

Seeking assistance in configuring a dynamic payment amount feature on Stripe using Node.js

As a newcomer to node and javascript, I'm seeking guidance on how to proceed with the code below. I have copied it from the Stripe documentation, but I am unsure about the function for the commented token. Initially, everything was working fine with t ...

Calculate the difference in days between two selected dates from an Ajax Datetime Picker using JavaScript

How can I use JavaScript to count the number of days between two selected dates from Ajax date time pickers in my aspx page? The script should automatically input this calculated value into a designated "Number_Of_Days" text box without requiring a page ...

How to keep the bottom of a CSS {position:sticky; top:0} element within the viewport without using JavaScript

I am working on creating a dashboard frame using Bootstrap 5, and I aim to achieve the functionality shown in these two images: Here is my current setup: <html> <body> <div class="pretoolbar">pretoolbar (non-essential inf ...

Transferring information between Flask and JS using AJAX for a Chrome extension

I'm experimenting with AJAX calls to establish communication between my Javascript frontend in a chrome extension and the Flask API where I intend to utilize my Machine Learning algorithms. content.js console.log("Let's get this application ...

Encountering an "undefined" error while implementing a registration system in Node.js and attempting to retrieve

Having recently delved into the world of javascript and nodejs, I am currently working on developing a registration system. The issue I'm facing is related to an error message indicating that "isEmail" is undefined. I have included my form validator a ...

Issue with fading in! The div should fade in only when it is no longer covering the element

I am currently working with two div elements called "#Header_Info" and "article". The "article" div is static and displays information on the page, while the "#Header_Info" div expands to show extra information. However, a problem arises when the "#Header ...

Customizing Ngx-bootstrap Carousel Indicator, Previous, and Next Button Styles

<carousel > <a href=""> <slide *ngFor="let slide of slides"> <img src="{{slide.imgUrl}}" alt="" style="display: block; width: 100%;"> </slide> 1. Is there a way to substitute the indicators with images ...

Having trouble populating a dropdown menu with states based on a selected country in real time

I'm attempting to create a dynamic dropdown where selecting a country will populate the states. I have all the necessary data stored in two tables, but I'm unsure how to proceed. While I can easily generate the initial list of countries, handling ...

Switch your attention to the following input text using AngularJS

In my controller, I have an object variable called `myObject` with 3 input text fields in the user interface. I am looking for a way to automatically shift the focus to the next input field once the current one reaches its maximum length. var myObject = ...

What is the proper way to display the initial content of the menu?

I am currently working on a website design for an upcoming festival. The festival spans over three days, so I have created buttons to navigate and load the content for each day separately. Is there a way for me to make the content for the first day di ...

Achieving opacity solely on the background within a div class can be accomplished by utilizing CSS properties such

Whenever I adjust the opacity of my main-body div class, it results in all elements within also becoming transparent. Ideally, I would like only the gray background to have opacity. See below for the code snippet: <div class="main1"> content </di ...

Chaining Assignments in TypeScript

let a: { m?: string }; let b = a = {}; b.m = ''; // Property 'm' does not exist on type '{}'. let a: { m?: string } = {}; let b = a; b.m = ''; // It's OK Link to TypeScript Playground What occurs ...

Adjusting color of fixed offcanvas navbar to become transparent while scrolling

After creating a navbar with a transparent background, I am now using JavaScript to attempt changing the navigation bar to a solid color once someone scrolls down. The issue is that when scrolling, the box-shadow at the bottom of the navbar changes inste ...

Creating a bootstrap modal with backbone framework

To better illustrate my problem, I believe a code snippet will be helpful. Here is the view: App.Views.ErrorModal = Backbone.View.extend({ template: window.template('errorModal'), render: function(){ this.$el.html(this.template(this.mod ...

Angular allows users to interact with objects in THREE.js by simply clicking on

I've tried numerous solutions, but none of them seem to work - the cube is in the wrong position and only one face is detected. Since the angular event is easy to call. 1. Insert a tag into the HTML code. <div (click)="onClickCanvas($event)"> ...

Exploring the connections among nodes in a Force-Directed Graph using D3.js JavaScript

I am currently working on a complex graph that consists of around 150 nodes using D3 Javascript. The concept behind it is quite intriguing: Each node is interconnected with 100 other nodes. Out of these 100 nodes, 49 are further linked to another set of ...

Using VueJs, create a dynamic css class name to be applied inline

Can VueJs handle a scenario like this? Html: <div class="someStaticClass {{someDynamicClass}}">...</div> JS: var app = new Vue({ data: { someDynamicClass: 'myClassName' }, mounted: function() { ...

Leveraging datatable in node.js applications

I'm attempting to integrate jquery Datatable with Node.js and here is the HTML code snippet I have: <button id="btnSearch" type="submit" class="btn btn-responsive"><i class="icon-search"></i>&nbsp;Search</button> <div ...