Populating one select option with localStorage is unsuccessful

No matter how many times I type Javascript: before the line, Chrome strips it out, sorry.

I have a script on another page running the following to fill a textarea…

var aboutSetupOne = localStorage.getItem(‘aboutSetupOne’);
form2.summaries.value += "SUMMARIES
" + aboutSetupOne;

… and it’s filled in with a string, no problem there.

OK THIS WORKS!!

<select size=“1” name=“testingSetup” id=“testingSetup” onchange=“document.formTesting.testingSetupLoad.value = this.value”>
<option value=“”>choose setup</option>
<option value=“setup 1”>setup 1</option>
<option value=“setup 2”>setup 2</option>
</select>

<script type=“text/javascript”>
var aboutSetupOne = localStorage ? localStorage.getItem( ‘aboutSetupOne’ ) : null;

if( aboutSetupOne )
document.getElementById( “testingSetup” ).options.add( new Option( aboutSetupOne, aboutSetupOne ) );

// localStorage.setItem( ‘aboutSetupOne’, ‘aboutSetupOne’ );

Thank you very much!
</script>

Now for some cleaning up.

Move the onchange event out of the HTML code, and in to the scripting where it belongs.
Remove the id attribute from select. When the select field is within the form, it should be accessed from the form’s elements collection.
Removing also the size attribute, since that is only used when the multiple attribute is also given.


<select name="testingSetup">
    ...
</select>

Also, assigning testingSetup to a local variable, since we’re now using it from multiple places


var form = document.getElementById('formTesting'),
    testingSetup = form.elements.testingSetup,
...
testingSetup.onchange = function () {
    ...
};

Assuming that the form has an id of “formTesting” on it, that is the point of access we should use in order to access all of the form elements.
When we’re already within the form, we can use this.form to easily access the form instead.


testingSetup.onchange = function () {
    var form = this.form;
    form.elements.testingSetupLoad.value = this.value;
};

Next with aboutSetupOne, there is no given benefit to assign null to the value, so instead of using a ternary operator, we can use a guard condition which serves the same purpose, and makes our intentions crystal clear - that we are protecting against situations where localStorage is not supported.


var ...,
    aboutSetupOne = localStorage && localStorage.getItem( 'aboutSetupOne' );

Lastly, always use braces for statement blocks, even if there is only one statement within them.
Not only does that protect you when you add another line to it, but it’s also a consistant behaviour, which when missing acts as an instant warning of potential issues.


if (aboutSetupOne) {
    testingSetup.options.add(new Option(aboutSetupOne, aboutSetupOne)); 
}

Which means that we end up with something like this:


<form id="formTesting">
    <select name="testingSetup">
        <option value="">choose setup</option>
        <option value="setup 1">setup 1</option>
        <option value="setup 2">setup 2</option>
    </select>
    ...
    <input name="testingSetupLoad">
</form>


var form = document.getElementById('formTesting'),
    testingSetup = form.elements.testingSetup,
    aboutSetupOne = localStorage && localStorage.getItem('aboutSetupOne');

if (aboutSetupOne) {
    testingSetup.options.add(new Option(aboutSetupOne, aboutSetupOne)); 
}

// localStorage.setItem('aboutSetupOne', 'aboutSetupOne');

testingSetup.onchange = function () {
    var form = this.form;
    form.elements.testingSetupLoad.value = this.value;
};

It’s a good practice that avoids having to use typeof to avoid the error if( aboutSetupOne ), where the operand is undefined.

so instead of using a ternary operator, we can use a guard condition which serves the same purpose, and makes our intentions crystal clear - that we are protecting against situations where localStorage is not supported.


var ...,
    aboutSetupOne = localStorage && localStorage.getItem( 'aboutSetupOne' );

We need to guard against doing that, because ANDing operands that could be undefined will generate an error:

aboutSetupOne = _localStorage && _localStorage.getItem( 'aboutSetupOne' );  //ERROR

When the operand is undefined, if(aboutSetupOne) is still falsy - there’s no need to define the variable as being null.

No they won’t. With:

aboutSetupOne = localStorage && localStorage.getItem( 'aboutSetupOne' );

JavaScript checks the first operand, and only if it’s truthy does JavaScript then check the second operand. No errors are generated.
This is why in JavaScript the && operator is also called the “guard operator”.

Please try to not bring inappropriate practices from other programming languages in to your JavaScript coding.
English spoken with a French accept can be quite wonderful. JavaScript written with influences from other languages isn’t.

Thank you very much, you guys!

If you do that in the global scope as per the example in question, an undefined operand generates an error unless you explicitly state its parent object.


if( window.aboutSetupOne )
 ...

With:

aboutSetupOne = localStorage && localStorage.getItem( 'aboutSetupOne' );

JavaScript checks the first operand, and only if it’s truthy does JavaScript then check the second operand. No errors are generated.
This is why in JavaScript the && operator is also called the “guard operator”.

You can do that with undefined operands using || not with &&. Why don’t you try the example I gave for the purpose, which will always be undefined?

Please try to not bring inappropriate practices from other programming languages in to your JavaScript coding.
English spoken with a French accept can be quite wonderful. JavaScript written with influences from other languages isn’t.

Just what do you consider to be an inappropriate practice?

Kudo’s, just ran you code and it definitely throws an error. And using window._localStorage && window._localStorage.getItem(‘aboutSetupOne’); definitely fixes it too.

Ahh, good catch. This is also why doing things in the global scope with global variables is not a good idea.

If a variable such as localStorage is intended to be accessed globally, it’s best to make it explicit, for example by using window.localStorage
After looking at the Local Storage documentation, I see that the compatibility code that they have there uses window.localStorage too, which helps to add further weight to it being the more effective technique to use.

Many times people come across to programming in JavaScript from a background of Java, or PHP, or C++, where those different environments have practices that can be simulated by JavaScript, but also have other more efficient ways of being done.

This is where following certain code conventions can help, as well as reading up on books like [url=“http://shop.oreilly.com/product/9780596517748.do”]JavaScript: The Good Parts