HTML: How come the EventListener isn't refreshing the Button?

I am attempting to create a field that displays the count of selected (highlighted) characters. However, I am encountering an issue where it does not work as intended. Specifically, the line

document.getElementById('selectedCountBtn').textContent = "B" + selectedText.length;
appears to never be applied. Initially, there was an issue with the button push deselecting the text, resulting in always counting 0 characters. I thought I had resolved this problem. I have noticed that the selectedCharCount variable is not being utilized for any purpose. It may be a remnant from a previous version of the functionality. Admittedly, I am not very proficient in HTML.

Edit: Could it be that the updateSelectedCharCount function is not being executed?

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Text Field</title>
<style>
  body, html {
    margin: 0;
    height: 100%;
    font-family: Arial, sans-serif;
  }
  #container {
    display: flex;
    height: 100vh; /* Ensure the container fills the entire height of the viewport */
    padding: 10px;
    box-sizing: border-box;
  }
  textarea {
    flex: 1;
    resize: none; /* Disables resizing to ensure it's always 100% height */
    margin-right: 10px;
    box-sizing: border-box;
  }
  #sidebar {
    display: flex;
    flex-direction: column;
    justify-content: space-between; /* Pushes #bottomContainer to the bottom */
    height: calc(100% - 20px); /* Account for padding */
  }
  #bottomContainer {
    <!--position: fixed; /* Fixed positioning relative to the viewport */
    bottom: 10px;    /* Distance from the bottom of the viewport */
    right: 10px;     /* Distance from the right of the viewport */
    display: flex;
    flex-direction: column;
    align-items: flex-end; /* Aligns the children (buttons, input) to the right */-->
  }
  #counters {
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  #charCounter, #wordCounter, .button {
    width: 60px; /* Width adjusted to make all elements similar */
    padding: 5px;
    margin-bottom: 5px; /* Space between elements */
    cursor: pointer;
    text-align: center;
    border: 1px solid #ddd;
    box-shadow: 1px 1px 2px rgba(0,0,0,0.1);
  }
  #filename {
    width: 60px;
    margin-top: 20px; /* Ensures space above the filename input regardless of wordCounter margin */
  }
  .button, #filename {
    margin-bottom: 5px; /* Adds space between input field and buttons */
  }
  #wordCounter {
    margin-bottom: 20px; /* Adds extra space below the wordCounter element and above filename */
  }
}
</style>
<script>
let charCountingEnabled = true;
let wordCountingEnabled = true;
var selectedCharCount = 0; // Variable to keep track of the selected character count

function updateCounters() {
  
    var textarea = document.getElementById('textArea');
  let text = textarea.value.trim();
  
  if (charCountingEnabled) {
    document.getElementById('charCounter').textContent = text.length;
  }
  
  if (wordCountingEnabled) {
    let words = text.length > 0 ? text.split(/\s+/) : [];
    document.getElementById('wordCounter').textContent = words.length;
  }
}

function toggleCharCounter() {
  charCountingEnabled = !charCountingEnabled;
  updateCounters();
}

function toggleWordCounter() {
  wordCountingEnabled = !wordCountingEnabled;
  updateCounters();
}

// Save text to file
function saveToFile() {
  var text = document.getElementById('textArea').value;
  var filename = document.getElementById('filename').value;
  if (!filename) {
    filename = 'snippet';
  }
  filename += '.txt'; // Append .txt to the filename
  var blob = new Blob([text], {type: 'text/plain'});

  // Create an anchor element and trigger a download
  var downloadLink = document.createElement("a");
  downloadLink.href = URL.createObjectURL(blob);
  downloadLink.download = filename;
  document.body.appendChild(downloadLink);
  downloadLink.click();
  document.body.removeChild(downloadLink);
}

function updateSelectedCharCount() {
  var selectedText = '';
  if (window.getSelection) {
    selectedText = window.getSelection().toString();
  } else if (document.selection && document.selection.type != "Control") {
    selectedText = document.selection.createRange().text;
  }
  // Update the button directly here
  document.getElementById('selectedCountBtn').textContent = "B" + selectedText.length;
}

document.addEventListener('selectionchange', function() {
  console.log("Selection changed.");
  var selectedText = '';
  if (window.getSelection) {
    selectedText = window.getSelection().toString();
  }
  var selectedCountBtn = document.getElementById('selectedCountBtn');
  selectedCountBtn.textContent = "A" + selectedText.length;
});

</script>
</head>
<body>
<div id="container">
  <textarea id="textArea" oninput="updateCounters();"></textarea>
  <div id="sidebar">
    <div id="counters">
      <div id="charCounter" onclick="toggleCharCounter()">0</div>
      <div id="wordCounter" onclick="toggleWordCounter()">0</div>
      <div class="button" id="selectedCountBtn">Selected</div>
    </div>
    <div id="bottomContainer">
      <input type="text" id="filename" class="button" placeholder="" />
      <div class="button" onclick="saveToFile()">Save</div>
    </div>
  </div>
</div>
</body>
</html>

We appreciate all suggestions and feedback, no matter how small.

Answer №1

It appears that the function updateSelectedCharCount() is not being called from any other part of the code.

I stumbled upon this resource first - How can I get the selected text in a textarea? because I noticed that in Firefox, your current code only changed the text to "A7" if I selected text outside the text area.

You can try using this alternative approach:

function updateSelectedCharCount() {
  selectedText = getSel();
  // Update the button directly here
  document.getElementById('selectedCountBtn').textContent = "B" + selectedText.length;
}

document.addEventListener('selectionchange', function() {
  console.log("Selection changed.");
  var selectedText = getSel();
  var selectedCountBtn = document.getElementById('selectedCountBtn');
  selectedCountBtn.textContent = "A" + selectedText.length;
  updateSelectedCharCount();
});

function getSel() {
    var txtarea = document.getElementById("textArea");
    var start = txtarea.selectionStart;
    var finish = txtarea.selectionEnd;
    var sel = txtarea.value.substring(start, finish);
    return sel;
}

Do you really need an additional new button? The addEventListener already updates that button to "A" + length. By adding the call to updateSelectedCharCount() afterwards, it will change the same button to "B" + length - so having both might be unnecessary.

Answer №2

Would you kindly write some code in this manner-:

const fooButton = document.getElementById('fooBar');

fooButton.addEventListener('click', function() {
    alert('Hello')
});
 <button id="fooBar">Foo</button>

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

The height of the div element is causing issues for the adjacent item in the row

I am facing a styling issue where the height of my avatar image is affecting other inline items located next to it. The images below demonstrate this problem. https://i.sstatic.net/bovge.png https://i.sstatic.net/EsF2R.png As you can see, when I increas ...

Issue with font-size changes using css variables in Angular not updating in browser for specific fields

Utilizing CSS variables, I have implemented a feature that allows users to adjust the font size to small, medium, or large. While this functionality works correctly for most fields, there are certain instances where the value is applied but not displayed. ...

CSS - Text and dropdown misalignment due to spacing issue

I'm looking to decrease the spacing between the text "Allow type of Compartment Option" and the dropdown box. Here is the code snippet being used: .cl-checkbox { padding-left: 20px; padding-bottom: 10px; padding-top: 20px; ...

Learn the process of using calc to rotate images on hover with CSS and Jquery

Is there a way to implement the rotate on hover function for images, similar to what is seen on this website under 'our Latest Publications'? I attempted using calc and skew, however, I was unsuccessful in achieving the desired hovering effect o ...

Can a hashmap variable be declared in HTML code?

Can a hashmap variable be set in HTML code? Here's an example: <form name="f1234"> <input type="text" name="map['foo1']" value="dog" /> <input type="text" name="map['foo2']" value="cat" /> </form> < ...

Material UI does not have built-in functionality for displaying colored text within a multiline textfield component in React

Attempting to utilize the material ui library in a react app has brought an issue to light. It appears that styling colored text does not work as expected for multiline textfields. Consider the following scenario: import React, { Component } from 'r ...

Endless scrolling results in a full loading rather than a step-by-step one

I'm currently working on implementing infinite scrolling on my website by following a tutorial I came across. However, instead of displaying only a few items at a time and allowing for continuous scrolling, the page loads up with all items at once. I& ...

Firefox not recognizing height attribute in table cells

My dilemma revolves around the fact that my table cells are not displaying at the designated height. Here is the code snippet I am working with: <html> <head> </head> <body> <table style="border: 1px solid black; border-radiu ...

Exploring HTML segments with Python and BeautifulSoup

As a beginner, I am exploring web scraping examples from Automate the Boring Stuff. My goal is to create a Python script that automates downloading images from PHD Comics using the following steps: Identify the image link in the HTML and download it. ...

What is the best way to implement lazy loading of images that have not been downloaded in a JavaFX WebView?

Currently, I am in the process of developing an email client application using JavaFX WebView to showcase email HTML files. In order to enhance its responsiveness and speed, my goal is to display inline images in emails as they are downloaded locally. Duri ...

Enhancing x-axis presentation in D3.js-generated charts

I created a bar chart using D3.js, but I have encountered an issue with one of the values on the x-axis being too long. I attempted to use CSS properties like text-overflow: ellipsis, width: 10px, and overflow: hidden to abbreviate values that exceed a cer ...

Use CSS media queries to swap out the map for an embedded image

Looking to make a change on my index page - swapping out a long Google Map for an embedded image version on mobile. The map displays fine on desktop, but on mobile it's too lengthy and makes scrolling difficult. I already adjusted the JS setting to "s ...

By utilizing the body element as the container instead of a div, the content shifts to the left by eight pixels

When the body is used as the wrapper instead of a div, the content shifts eight pixels to the left (on a 1920×1080 display) when it extends below the fold. The examples below illustrate this difference in code snippets. Please note that the variance is on ...

In the Bootstrap multiselect feature, users will be able to choose whether to display an image or selected text

Is there any way to display an image by default instead of options? Code: <select id="example-post" style="width:120px;!important;" class="footerSelect" name="multiselect[]" multiple="multiple"> <opti ...

Achieving CSS transition effects using the .appendChild function in JavaScript

When using the mouseenter event, I have a JavaScript function applied to an svg path element: const fadeIn = (event, locale) => { event.target.style.fill = 'hwb(' + (120 - score[locale] * 1.2) + ' 0% 0% / 1)' } This function wor ...

Ember's distinctive feature: Named Block Helpers

Can we create "named blocks" in a different way? For instance, {{#customBlock "repeatableBlock"}} {{!-- block containing numerous properties and data that may become messy if hardcoded multiple times --}} {{/customBlock}} Then, elsewhere in the code, {{ ...

What is the best way to dynamically pass props to the styles hook in Material UI?

Looking for a way to dynamically add background images to div elements? I'm currently iterating over an array of objects and returning divs, but I'm not sure how to set the background image based on the image URL in each object. Can anyone help m ...

"Creating a duplicate of an element by utilizing the `next`

I have a dilemma involving two divs within a section of my project - one div is dynamically created while the other exists statically. My goal is to transfer the non-dynamically created div into the one that is generated dynamically. let adContainer = $ ...

Elevate your Material UI Avatar with an added level of

Attempting to give a MUI Avatar component some elevation or shadow according to the documentation provided here. <Avatar alt="Cindy Baker" src="/static/images/avatar/3.jpg" /> Enclosing the Avatar within a paper or Card element increases the size o ...

When hovering over one div, both it and another div should be displayed simultaneously. The second div should continue to be displayed even when hovered over

I am looking to keep another div displayed when hovering over it - in this example, it says "hello." The div I want to remain visible is not a child element of the main div where I initiate the hover event. document.write("<base href=\"" + docum ...