Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8911473
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T03:57:12+00:00 2026-06-15T03:57:12+00:00

The title is a bit misleading maybe; my spellchecker focuses more on format than

  • 0

The title is a bit misleading maybe; my spellchecker focuses more on format than spelling (caps, punctuation and spaces, apostrophes, converting internet slang to full words, oft-scrambled words etc.). However the basic principles apply.

Basically, the JS/jQuery checker I’m building would correct words as they are typed (after a space or punctuation has been typed after the word).

However, much like any autocorrecting, it’s bound to run into mistakes. I’m not even considering creating functionality that would determine whether “its” or “it’s” is more appropriate in a given case (though if such a plugin or code snippet exists, do point me to one).

So I want to make it a “yielding” autocorrect (for the lack of the knowledge of a better name). Basically;

  1. User types in a word that would set off the checker, and types a
    space.
  2. The checker corrects the word.
  3. The user deems this a mistake
    and corrects it back (by Backspacing the whole word, or parts of it,
    or highlighting it or however they feel comfortable editing it).
  4. The
    user continues typing, and the checker doesn’t touch that instance of that word again.

Now easiest of course would be to disable the check for that word entirely, but I want the checker to correct future instances of it. What I’m looking for would detect a user editing an autocorrected word (regardless whether right after typing or later) back to what it was before being autocorrected, and then learning to leave that specific instance of that word alone.

I don’t even know where to begin with this. I’m thinking a contenteditable with each word wrapped in a span, autocorrected ones having a special class and a data-* attribute containing the original one, listen for edits on the autocorrected words, and if it’s edited back to equaling the data-* value, add a class that leaves it out of future autocorrect rounds.

I’m thinking though that this might be unnecessarily complicated, or at least not the path of least resistance. What would be the smartest way of doing this?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T03:57:14+00:00Added an answer on June 15, 2026 at 3:57 am

    Your suggested approach (separating each word in a span and storing additional data in it) at first glance seems to be the most sensible approach. On the editor level, you just need to ensure all text is inside some span, and that each of them contains only a single word (splitting it if necessary). On the word level, just listen for changes in the spans (binding input and propertyChange) and act according to its class/data.

    However, the real pain is to keep the caret position consistent. When you change the contents of either a textarea or an element with contentEditable, the caret moves rather unpredictably, and there’s no easy (cross-browser) way of keeping track of the caret. I searched for solutions both here at SO and elsewhere, and the simplest working solution I found was this blog post. Unfortunatly it only applied to textarea, so the “each word in a span” solution couldn’t be used.

    So, I suggest the following approach:

    • Keep a list of words in an Array, where each word stores both the current value and the original;
    • When the contents of the textarea changes, keep the set of unchanged words and redo the rest;
    • Only apply the spell check if the caret is just after a non-word character (room for improvement) and you’re not hitting backspace;
    • If the user was unsatisfied with the correction, hitting backspace once will undo it, and it won’t be checked again unless modified.
      • If many corrections were done at once (for instance, if a lot of text were copy-pasted), each backspace will undo one correction until no one is left.
      • Hitting any other key will commit the correction, so if the user is still unsatisfied he’ll have to go back and change it again.
      • Note: differently from the OP requirements, the changed version will be autocorrected again if the user inputs a non-word character; he’ll need to hit backspace once to “protect” it.

    I created a simple proof-of-concept at jsFiddle. Details below. Note that you can combine it with other approaches (for instance, detecting a “down arrow” key and displaying a menu with some auto-correcting options) etc.


    Steps of the proof-of-concept explained in detail:

    • Keep a list of words in an Array, where each word stores both the current value and the original;

      var words = [];
      

      This regex splits the text into words (each word has a word property and a sp one; the latter stores non-word characters immediatly following it)

      delimiter:/^(\w+)(\W+)(.*)$/,
      ...
      regexSplit:function(regex,text) {
          var ret = [];
          for ( var match = regex.exec(text) ; match ; match = regex.exec(text) ) {
              ret.push({
                  word:match[1],
                  sp:match[2],
                  length:match[1].length + match[2].length
              });
              text = match[3];
          }
          if ( text )
              ret.push({word:text, sp:'', length:text.length});
           return ret;
      }
      
    • When the contents of the textarea changes, keep the set of unchanged words and redo the rest;

          // Split all the text
          var split = $.autocorrect.regexSplit(options.delimiter, $this.val());
          // Find unchanged words in the beginning of the field
          var start = 0;
          while ( start < words.length && start < split.length ) {
              if ( !words[start].equals(split[start]) )
                  break;
              start++;
          }
          // Find unchanged words in the end of the field
          var end = 0;
          while ( 0 < words.length - end && 0 < split.length - end ) {
              if ( !words[words.length-end-1].equals(split[split.length-end-1]) ||
                   words.length-end-1 < start )
                  break;
              end++;
          }
          // Autocorrects words in-between
          var toSplice = [start, words.length-end - start];
          for ( var i = start ; i < split.length-end ; i++ )
              toSplice.push({
                  word:check(split[i], i),
                  sp:split[i].sp,
                  original:split[i].word,
                  equals:function(w) {
                      return this.word == w.word && this.sp == w.sp;
                  }
              });
          words.splice.apply(words, toSplice);
          // Updates the text, preserving the caret position
          updateText();
      
    • Only apply the spell check if the caret is just after a non-word character (room for improvement) and you’re not hitting backspace;

      var caret = doGetCaretPosition(this);
      var atFirstSpace = caret >= 2 &&
                         /\w\W/.test($this.val().substring(caret-2,caret));
      function check(word, index) {
          var w = (atFirstSpace && !backtracking ) ?
                  options.checker(word.word) :
                  word.word;
          if ( w != word.word )
              stack.push(index); // stack stores a list of auto-corrections
          return w;
      }
      
    • If the user was unsatisfied with the correction, hitting backspace once will undo it, and it won’t be checked again unless modified.

      $(this).keydown(function(e) {
          if ( e.which == 8 ) {
              if ( stack.length > 0 ) {
                  var last = stack.pop();
                  words[last].word = words[last].original;
                  updateText(last);
                  return false;
              }
              else
                  backtracking = true;
              stack = [];
          }
      });
      
    • The code for updateText simply joins all words again into a string, and set the value back to the textarea. The caret is preserved if nothing was changed, or placed just after the last autocorrection done/undone, to account for changes in the text length:

      function updateText(undone) {
          var caret = doGetCaretPosition(element);
          var text = "";
          for ( var i = 0 ; i < words.length ; i++ )
              text += words[i].word + words[i].sp;
          $this.val(text);
          // If a word was autocorrected, put the caret right after it
          if ( stack.length > 0 || undone !== undefined ) {
              var last = undone !== undefined ? undone : stack[stack.length-1];
              caret = 0;
              for ( var i = 0 ; i < last ; i++ )
                  caret += words[i].word.length + words[i].sp.length;
              caret += words[last].word.length + 1;
          }
          setCaretPosition(element,caret);
      }
      
    • The final plugin structure:

      $.fn.autocorrect = function(options) {
          options = $.extend({
              delimiter:/^(\w+)(\W+)(.*)$/,
              checker:function(x) { return x; }
          }, options);
          return this.each(function() {
              var element = this, $this = $(this);
              var words = [];
              var stack = [];
              var backtracking = false;
              function updateText(undone) { ... }
              $this.bind("input propertyChange", function() {
                  stack = [];
                  // * Only apply the spell check if the caret...
                  // * When the contents of the `textarea` changes...
                  backtracking = false;
              });
              // * If the user was unsatisfied with the correction...
          });
      };
      $.autocorrect = {
          regexSplit:function(regex,text) { ... }
      };
      
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Well, maybe the title is misleading a bit. All I want you to do
The title of this question may be a bit misleading. I couldn't quite think
The title might be a bit misleading, but I couldn't figure out a better
The title might be a bit misleading, but I don't know how else to
The title of this question is a bit misleading, but I couldn't summarize this
actual problem seems a bit complicated than the Title says .. but hope someone
Okay so the title may be a bit misleading. What I am trying to
The title might be a bit misleading. As you can see, we created a
So the title might be bit misleading, but what I wanted to accomplish is
Maybe a bit of a strange title description, but i basically want to achieve

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.