1

I'm working on an option form. I want each option to have a different color on the scroll down and once an option is selected I want to save it, and display the selection and color.

enter image description here

What I want to be able to do is save the form, come back to the page and see the option I previously selected while displaying the color. In the picture above 2020 shows an example of the options. What I want after I save the form is for my selection to appear (like in 2021) with the selection color(in this case 2021 is medium/yellow). What can I do so that the selected box option takes the color of the option in the scroll down? How can I save this so that the option remains selected the next time I visit the page?

HTML

<form action="" method="post">
{% csrf_token %}
        {% for year in years %}
        <select name="rating" id="{{year.id}}">
        <script src="{% static 'SCS/scripts/script.js' %}"/></script> 
            <option>Choose From List</option>
            <option class=green value="green">High</option>
            <option class=yellow value="yellow">Medium</option>
            <option class=orange value="orange">Low</option>
            <option class=gray value="gray">N/A</option>
        </select> 
            <input type="hidden" name="year" value={{year.fy_year}}>
        {% endfor %}
        <input id=save_cap type="submit" value="Save">
      </form>

CSS

.green{
    background-color: green;
}

.yellow{
    background-color: yellow;
}

.orange{
    background-color: orangered;
}

.gray{
    background-color: gray;
}
Kirill Simonov
  • 7,206
  • 3
  • 15
  • 36

2 Answers2

1

You need some JavaScript to achieve your goals.

To do so that the selected box option takes the color of the option in the scroll down you can write:

document.getElementById("rating").addEventListener("change", function() {
    this.className = this.value;
});

This code takes the selected option value and sets it as a class name of the select. To make it work you have to add some values to your options:

<select name="rating" id="rating">
    <option class=white value="white">Choose From List</option>
    <option class=green value="green">High</option>
    <option class=yellow value="yellow">Medium</option>
    <option class=orange value="orange">Low</option>
    <option class=gray value="gray">N/A</option>
</select>

And to save the selected option you need localStorage:

let selected = localStorage.getItem("selected");
let rating = document.getElementById("rating");

if (selected) {
    rating.selectedIndex = selected;
    rating.className = rating.value;
}

rating.addEventListener("change", function() {
    localStorage.setItem("selected", this.selectedIndex);
    this.className = this.value;
});

Check the working JSFiddle.

Kirill Simonov
  • 7,206
  • 3
  • 15
  • 36
  • Thank you for your help. This works, but only on the first option box. This is inside a loop and its only applying the colors to the first value. I updated my code above. I'm using Django. I'm new to development and this is my first time using js. Your guidance is much appreciated. –  Feb 20 '18 at 01:22
  • @dev_2018 the reason why it works only for one select is that you have duplicate ids when you create those selects in a loop. I suggest you to assign a year to the `id` attribute like this: ` – Kirill Simonov Feb 20 '18 at 01:42
  • Ok. So I understand why I have to use {{year.fy_year}}. But how does js know it needs to go through the loop. Do I write {{year.fy_year}} in the js file? I'm a little confused because in your last example there was a select list for each year. Is that what I need to do? One list per year? I have ten years, so I'm trying not to repeat the same code 10 times. –  Feb 20 '18 at 02:39
  • I tried and neither of them work. –  Feb 20 '18 at 02:58
0

I'm used to jQuery so this has been a learning experience for me but I do have a solution for you. I'll take you through my logic, and the snippet is below (possibly due to cookies I could only get it to work locally and on the w3 demo):

  1. Add values to the options: <option class="green" value="high">High</option> so we can retrieve them and store the values in a cookie

  2. Set a change event listener to change color, s being a : s.addEventListener( 'change', changeColor );

  3. Once we've changed the color with this.className += this.selectedOptions[0].className; more info here

  4. Then we can pass the information to a cookie with setCookie( this.id, this.value ); more info here

  5. Now we've got changing colours and stored cookies, we need to be able to load any stored values on document ready, so here goes:

    let cookie = getCookie ( `select-${s.id}` );
            // if cookie is not empty, set selected option and change color
            if ( cookie != '' ) {
                s.value = cookie;
                s.className += s.selectedOptions[0].className;
            }
    

Now we have:

  • changing colour
  • stored values
  • loaded values

There's definitely (in the other answer actually) a better, more concise way to do this, but I hope that some of the links will help you understand more about what's going on :)

// set up onChange event listeners
function setSelectOnChangeListeners() {
  // select all of your <select>'s
  const selects = document.getElementsByTagName("select");

  // for each of your <select>'s
  for (s of selects) {
    // add an onChange event listener to trigger function changeColor();
    s.addEventListener('change', changeColor);
  }
}

// on <select> onChange event, change color to selected option color based on class
function changeColor() {
  // this is the interesting part, where you can return which item has been selected in your <select>
  console.log(`class = ${this.selectedOptions[0].className}`);

  // clear existing className, note that if you want to have a class on your select, you can set the below equal to that instead of ''
  this.className = '';
  // set <select> className to the selected <option> className
  this.className += this.selectedOptions[0].className;

  // after we've changed the color, we'll change the cookie
  setCookie(this.id, this.value);
}

// set cookies with format "select-<id> = <val>"
function setCookie(id, val) {
  // cookies are stored as key | value pairs
  document.cookie = `select-${ id } = ${ val }`;
  console.log(`cookie set with data ${id}, ${val}`);
}

// w3 get cookie method
function getCookie(cname) {
  var name = cname + "=";
  var ca = document.cookie.split(';');
  for (var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
}

// on document load
document.addEventListener('DOMContentLoaded', function(event) {
  // for each select, try to load cookie data
  const selects = document.getElementsByTagName("select");
  for (s of selects) {
    let id = s.id;
    let cookie = getCookie(`select-${s.id}`);

    // if cookie is not empty, set selected option and change color
    if (cookie != '') {
      s.value = cookie;
      s.className += s.selectedOptions[0].className;
    }
  }

  // set listeners
  setSelectOnChangeListeners();
});
.green {
  background-color: green
}

.yellow {
  background-color: #ff0
}

.orange {
  background-color: #ff4500
}

.gray {
  background-color: gray
}
<select id="2020" name="rating">
   <option>Choose From List</option>
   <option class="green" value="high">High</option>
   <option class="yellow" value="medium">Medium</option>
   <option class="orange" value="low">Low</option>
   <option class="gray" value="none">N/A</option>
</select>

<select id="2021" name="rating">
   <option>Choose From List</option>
   <option class="green" value="high">High</option>
   <option class="yellow" value="medium">Medium</option>
   <option class="orange" value="low">Low</option>
   <option class="gray" value="none">N/A</option>
</select>
Frish
  • 1,105
  • 6
  • 16
  • 1
    Thank you very much for your reply and the thorough explanation. I learned a lot from it. –  Feb 20 '18 at 04:26