Link to home
Start Free TrialLog in
Avatar of Alfahane
Alfahane

asked on

Duplicate <SELECT> just one time

I have huge forms that use SELECTs with identical data (size list) for stock list. The html is reaching 4 mb. Each SELECT have a preselected value when the page loads.

I want to duplicate the data with javascript but only when a select is clicked/onfocus to prevent unnecessary duplication for SELECTs where user have not selected a new OPTION. Also, for each SELECT the duplication should be done only once in case of multiple click/onfocus on the same SELECT.

I've tried like this:

Have a hidden SELECT with all the values
<select style="display:none;" id="sizeOptions">
<option id="1">Text1</option>
...
<option id="200">Text200</option>
</select>

Open in new window


Have visible SELECTs that contain only the preselected value and a "0" value
<select class="sizeList" id="sizeList1">
<option id="0">-- empty --</option>
<option id="25" selected="selected">Text25</option>
</select>
<select class="sizeList" id="sizeList2">
<option id="0">-- empty --</option>
<option id="43" selected="selected">Text43</option>
</select>

Open in new window


I have tried with

function popSize(id) {
id.innerHTML = id.innerHTML+document.getElementById("sizeOptions").innerHTML
;}
...
<select onfocus="popSize(this);" id="sizeList">
<option id="0">-- empty --</option>
<option id="25" selected="selected">Text25</option>
</select>

Open in new window


2 things happen. Naturally, the SELECT grows on every onFocus. But worse, the SELECTED attribute is not respected, which is potentially catastrofic.

I'm using Firefox 15.0.1


I took a look at jQuery but I cant get that to work either.
Avatar of Scott Fell
Scott Fell
Flag of United States of America image

Are you trying to do a chained select where the selection of one effects the outcome of the other?  http://www.appelsiini.net/2010/jquery-chained-selects.  This jquery add on allows this by making the class= of the 2nd select the same value of the first.
<select id="mark">
  <option value="">--</option>
  <option value="bmw">BMW</option>
  <option value="audi">Audi</option>
</select>
<select id="series">
  <option value="">--</option>
  <option value="series-3" class="bmw">3 series</option>
  <option value="series-5" class="bmw">5 series</option>
  <option value="series-6" class="bmw">6 series</option>
  <option value="a3" class="audi">A3</option>
  <option value="a4" class="audi">A4</option>
  <option value="a5" class="audi">A5</option>
</select>

<script src=jquery.js></script>
<script>$("#series").chained("#mark"); </script>

Open in new window

On another note, if your html is 4 megs, that sounds kind of high.  Besides possibly splitting up your form to multiple pages, some small changes might help like minifying your html.
<select style="display:none;" id="sizeOptions"><option id="1">Text1</option><option id="200">Text200</option></select>

Open in new window

The problem with this approach is that the click / focus events don't allow you to select the selected value so it shows in the select box.
There are two options.
1 just popuplate all selects when the page loads
2. Do it on the mouseover event
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
var lastval = 0;
$(function() {
// Populate from master on page load
  $('select.empty').each(function() {
    var val = $(this).val();
    $(this).html($('#master').html());
    $(this).val(val);
  });
});
</script>
<style type="text/css">
</style>
</head>
<body>
<a>Test</a>
<select name="master" id="master" style="display: none">
  <option value="0">--empty--</option>
  <option value="1">Text1</option>
  <option value="2">Text2</option>
  <option value="3">Text3</option>
  <option value="4">Text4</option>
  <option value="5">Text5</option>
  <option value="6">Text6</option>
</select>
<select class="empty" name="field1">
  <option value="0">--empty--</option>
  <option value="5" selected="selected">Text5</option>
</select>
<select class="empty" name="field2">
  <option value="0">--empty--</option>
  <option value="6" selected="selected">Text6</option>
</select>
<select class="empty" name="field3">
  <option value="0">--empty--</option>
  <option value="3" selected="selected">Text3</option>
</select>

</body>
</html>

Open in new window

Mouseover solution
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
var lastval = 0;
$(function() {
  $('select.empty').mouseover(function() {
    var val = $(this).val();
    $(this).html($('#master').html());
    $(this).val(val);
  });
});
</script>
<style type="text/css">
</style>
</head>
<body>
<a>Test</a>
<select name="master" id="master" style="display: auto">
  <option value="0">--empty--</option>
  <option value="1" selected="selected">Text1</option>
  <option value="2">Text2</option>
  <option value="3">Text3</option>
  <option value="4">Text4</option>
  <option value="5">Text5</option>
  <option value="6">Text6</option>
</select>
<select class="empty" name="field1" id="test">
  <option value="0">--empty--</option>
  <option value="5" selected="selected">Text5</option>
</select>
<select class="empty" name="field2">
  <option value="0">--empty--</option>
  <option value="6" selected="selected">Text6</option>
</select>
<select class="empty" name="field3">
  <option value="0">--empty--</option>
  <option value="3" selected="selected">Text3</option>
</select>

</body>
</html>

Open in new window

You could develop a simple function which evaluates the outerHTML (checking how many SELECT you have) and then launch an innerHTML if necessary, under the condition on document.getElementById("sizeOptions").value (or document.getElementById("sizeOptions").options[document.getElementById("sizeOptions").selectedIndex].text).
Avatar of Alfahane
Alfahane

ASKER

No, not chained. The selects are independent of eachother.

The hidden SELECT was just my idea of have a source with all options.

The form consists of product variants where every variant has it's own row with its own select for color and size:
variant 1 |SELECT, size (with current preselected) | SELECT, color (with current preselected)  | change amount | ...
variant 2 |SELECT, size (with current preselected)  | SELECT, color (with current preselected) | change amount | ...
....

Open in new window


There are up to about 250 variants per product. That's, up to 250 selects with sizes, and 250 selects with colors. For example all SELECTs with colors are _identical_ except for the SELECTS's attributes [name] and [id] and which option is pre-selected (althought a variant can have same color as other variants so it _can_ have the same option selected).

Sometimes a size or color for a product variant changes (for example One Size becomes Small/Medium). I dont want to create new variants when this happens because that "breaks" the history of a variant. These changes dont happen often and that's why in most cases loading full selects is unneccessary. So instead of creating 250 color selects server side and waste time while the html is loading I want to save time by using javascript. I've manually edited the final HTML and I get from 4MB to about 0.8MB if I can find a way to reuse the data in the hidden select.

The reason why it's on one page is that when a delivery is made to the warehouse the administrator updates the stock amounts grouped by products (=that exists in many variants) and in these situations having all variants on the same page gives a much better overview.
julianH - Great stuff! But there is a problem. When I use your exact code (exact HTML with your examples) it works fine except for that after I click on the select (focus), just view it with out changing anything the selected option changes to "--- empty ---" by itself. And on unFocus it stays on "--- empty---".
julianH - I ment the mouseOver.

The onLoad works perfect. But that mean that it would populate all selects regardless of it getting used on not.
I don't think you need the hidden select.    What I think you want to do is place your variants in an array. http://www.w3schools.com/js/js_obj_array.asp Then generate your selects from the array as a function.

The way I handle multiple variants of on data type such as size where you could have (mens small, mens medium, mens large, women's small...., dress size 10, dress size 12, shoe size 7, shoe size 8, hat size 10..) is to have a separate table of size types (mens shirts, women's dresses, mens shoes etc) each with an id.   Then a size table with (id, typeid, size).  Now there are a lot of options from here but you could either store the size type id with the product, or have another table that matches product id's with size type id's.

Then in your js, you have a giant array of all sizes that includes the (id, sizetypeid, size).  In your form, you would then generate your <select></select> pulling only the sizetypeid associated with that product.

Personally, I would still generate the arrays server side. What happens if something changes?  Using the array/function, they only have to be written once.  You could also simply generate an outside xml or json page of meta data that either gets created on the fly or each time  you update your color type or size type.  Then use the xml or json to populate your select.
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
julianH - Thank you! This works perfectly. And on FF, IE, Chrome and Opera. Many thanks!


Regarding onload. The scrolling of the page is noticably slower when the HTML gets big. Even on fast computers. I'm not sure what reason. I just thought that minimizing the document, even when content is created by javascript, is good. Maybe I'm wrong. Maybe it's more about the amount of selects rather than total amount of options. Also, I've noticed that Norton Internet Security (used across the organization) dont like huge forms. It seams to validate them and in the process temporarily lock the browser.
Low weight solution. Excellent!
You are welcome - thanks for the points