Search code examples
jqueryreplacecase-insensitive

Jquery make searching in array with indexOf case insensitive


I have this function which checks if the textarea contains the string :tag: while typing. If does, then it replaces it with [tag] [/tag]. For example, if we type :b:, it will insert [b] [/b].

This works all good, but I want to make this work even if we use uppercase. Like typing :B: would also insert [b] [/b](or [B] [/B], doesn't really matter), but however I try, it just doesn't work.

Naturally, it needs to work with every single tag.

$("textarea").on("input",function(e){
        let textarea=$(this);
        let text = textarea.val();
        let target=e.target;
        let position=target.selectionStart;

        let tags=["B","I","U","S","Q",
        "H1","H2","H3","H4","H5","H6",
        "LEFT","CENTER","RIGHT","SUB","SUP",
        "H","HR","CODE","SPOILER","UL","OL","LI"];

        $.each(tags, function(index, tag) {
            tag=tag.toLowerCase();
            let fullTag=":"+tag+":";
            if(textarea.val().toLowerCase().indexOf(fullTag) > -1 ){
                textarea.val(text.replace(fullTag, "["+tag+"]    [/"+tag+"]"));
                target.selectionEnd=position+2;
            }
        });
     });
textarea{
  width:200px;
  height:100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea></textarea>

I feel like the answer is simple, I have searched a lot, and I've tried many variations, but I still can't figure it out. What can I try next?


Solution

  • From the tags array, I'd construct a case-insensitive regular expression instead, and in the replacer function, check the index of the match in the whole string (the last argument) to identify where to set the new selectionEnd:

    const tags = ["B", "I", "U", "S", "Q",
      "H1", "H2", "H3", "H4", "H5", "H6",
      "LEFT", "CENTER", "RIGHT", "SUB", "SUP",
      "H", "HR", "CODE", "SPOILER", "UL", "OL", "LI"
    ];
    const pattern = new RegExp(tags.map(tag => `:${tag}:`).join('|'), 'i');
    $("textarea").on("input", function(e) {
      let usedIndex = null;
      this.value = this.value.replace(
        pattern,
        (match, index) => {
          const tag = match.match(/\w+/)[0];
          usedIndex = index + tag.length + 4;
          return `[${tag}]    [${tag}]`
        }
      );
      if (usedIndex) {
        this.selectionEnd = usedIndex;
      }
    });
    textarea {
      width: 200px;
      height: 100px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <textarea></textarea>