Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Javascript blink a select option input if trying to add it again

Overview

As part of an up-and-coming project that will be discussed at a future date, I have been working in javascript and html again. I want a form with a list of attributes, to which the user can add and remove entries. I wanted a way to show that the requested entry was already in the list. Here's what I've got so far.

The code

This one html template file includes css, javascript, and the html form itself.

<html>
<head>
<title>{{ title }}</title>
<style>
@-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
@-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
@keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
.fadeIn {
  -webkit-animation: fadeIn 1s ease-in-out 0s;
  -moz-animation: fadeIn 1s ease-in-out 0s;
  -o-animation: fadeIn 1s ease-in-out 0s;
   animation: fadeIn 1s ease-in-out 0s;
}
</style>
</head>
<form action="#" method="post" id="edit">
<label for="title">Title:</label><input accesskey="t" id="title" name="title" type="text" value="{{ title }}"><br/>
<label for="tag">Tag entry:</label><input id="tag" name="tag" type="text" value=""><br/>
<input type='button' value='add to list' id='add' />
<input type='button' value='remove from list' id='remove' /><br/>
<label for="tags">Tags:</label><select id="tags" name="tags" multiple='multiple'>
{% for i in tags %}<option id="opt_{{ i }}" value="{{ i }}">{{ i }}</option>{% endfor %}</select><br/>
<input accesskey="s" type="submit" value="Submit">
</form>
<script type="text/javascript">
let tag = document.getElementById("tag");
let tags = document.getElementById("tags");
// blink function depends on css above
function blink_once(item) {
   //var item = document.getElementById(item);
   console.log(`Want to blink ${item} with ${item.value}`);
   item.classList.add('fadeIn');
   // remove the class, after the delay, so that the item can blink again if necessary.
   setTimeout(function(){item.classList.remove('fadeIn')},1000);
}
function add_option() {
   let text = tag.value;
   if (text != "" && text.match('[0-9a-zA-Z]') ) {
      var optexists = document.getElementById("opt_"+text);
      if (optexists) {
         // it already exists
         blink_once(optexists);
         } else {
         // need to add it
         var opt = document.createElement('option');
         opt.value = text; opt.innerHTML = text; opt.id = "opt_" + text;
         tags.appendChild(opt);
         tag.value = "";
         return 0;
      }
   }
   return 1;
};
function remove_option() {
   let text = tag.value;
   let opt = document.getElementById("opt_"+text);
   if (opt) { opt.remove(); };
   console.log(`Want to remove item "${text}" from list?`);
};
// When the tags list selection is changed, update the value of the tag entry field
function set_option() {
   let text = tags[tags.selectedIndex].value;
   console.log(`text is "${text}"`);
   tag.value = text;
}
// Behavior of the add and remove buttons
document.getElementById("add").onclick = function(){add_option()};
document.getElementById("remove").onclick = function(){remove_option()};
// Behavior of the tags list
tags.onclick = function(){set_option()};
tags.onchange = function(){set_option()};
tags.onfocus = function(){this.selectedIndex = -1};
// when press enter, run the "add" event.
tag.onkeypress = function(event,value) {
   if (13 == event.which) {
      event.preventDefault(); // this blocks the Enter key from submitting the form, for this field only!
      console.log("Enter was pressed!");
      if (0 == add_option()) {
         console.log("Successful addition!")
      } else {
         console.log(`failed to add "${document.getElementById("tag").value}".`);
      }
   };
}
function submitform() {
   console.log("The submit button was pressed!");
};
</script>
</html>

Walkthrough

I set up a text field, "Tag entry." This value changes to the currently-selected option from the select field. When the user presses enter, the javascript adds the tag to the list of tags. If the tag already exists, it will blink once.

The submit behavior is not complete yet, but that's a separate story for another day.

References

  1. Principal work comes from two answers on the same SO question: javascript - Making a div flash just once Praveen Kumar Prushothaman's answer Srikanth Reddy's answer
  2. https://stackoverflow.com/questions/8674618/adding-options-to-select-with-javascript/8674667#8674667
  3. https://stackoverflow.com/questions/33758595/html-form-run-javascript-on-enter/33758792#33758792
  4. https://stackoverflow.com/questions/647282/is-there-an-onselect-event-or-equivalent-for-html-select/12404521#12404521

Comments