0

I'm reading input field 'name' and 'value' attributes from ul lists. No two lists have the same amount of inputs and the 'name' and 'value' attributes are unknown till read.

<ul id="options_set1">
    <li><input name="width" value="10" /></li>
    <li><input name="height" value="20" /></li>
    <li><input name="depth" value="5" /></li>
</ul>
<ul id="options_set2">
    <li><input name="finish" value="printed" /></li>
    <li><input name="mounting" value="spacer" /></li>
</ul>

I iterate through all the inputs, gathering ul id 'options_set_X' as the literal for my objects, and name:value pairs:

var signState = {}; //My object to be populated

var optionSet = '';
var optionName = '';
var optionValue = '';

$("ul li input").each(function() {
  var optionSet = $(this).parent().parent().attr('id');
  signState[optionSet] = {};
  optionName = $(this).attr('name');
  optionValue = $(this).val();
  signState[optionSet][optionName] = optionValue;
});

What I cannot wrap my head around is how to prevent this loop from replacing any existing name:value pairs in each 'optionSet' literal in the object?

I suspect it is because I restart the signState[optionSet] = {}; literals.

I need a way to add name:value pairs for a given literal without disturbing any existing associations.

Nothing I read online deals with this specific case, because I use variables for both key names and key values - which complicates matters.

11
  • Just wondering.. does checking if the variable is set not work? Just use an if statement like the following: if(signState[option]) return; to skip as soon as you see an existing value. Commented Jun 11, 2015 at 13:32
  • You are reseting your object in each loop iteration signState[optionSet] = {};. Use the that command if signState[optionSet] == 'undefined' Commented Jun 11, 2015 at 13:34
  • Also just curious, where is optionH3 defined? Commented Jun 11, 2015 at 13:36
  • I'm guessing he meant signState[optionSet][optionName] by signState[optionH3][optionName] Commented Jun 11, 2015 at 13:39
  • 1
    When a variable is defined and you call it, it will return its value. If that value is not 0, you can use this to define it: myvalue[myKey] = myvalue[myKey] || 'any value';- if myvalue[myKey] exists, it won't overwrite it, otherwise it will default to the second value. Also, an object does not 'extend' or 'push' - it will always appear alphabetical, so you can't append it at the end. Commented Jun 11, 2015 at 13:47

2 Answers 2

1

Try this:

var signState = {};

$("ul li input").each(function() {
    var set, name, value;
    set    = $(this).parent().parent().attr('id');
    name   = $(this).attr('name');
    value  = $(this).val();

    /* Create a fresh object if it doesn't exist, 
     * otherwise assign it the existing one. */
    signState[set] = signState[set] || {};

    /* Again, assign a fresh value if it was undefined or empty 
     * otherwise assign it the existing one. */
    signState[set][name] = signState[set][name] || value;

});

Now if the value you are setting is false or 0, then it will be overwritten. If you don't want that, you have to use the tertiary operator to ensure you get it right:

signState[set][name] = typeof signState[set][name] !== "undefined"
    ? signState[set][name]
    : value;

The tertiary operator syntax is as follows: definition = when is true ? this : else this; - which can be very useful for this.

Sign up to request clarification or add additional context in comments.

Comments

0

Following from somethinghere's comment and answer, I was able to get perfect results with this:

var signState = {}; //My object to be populated

var optionSet = '';
var optionName = '';
var optionValue = '';

$("ul li input").each(function() {
  optionSet = $(this).parent().parent().attr('id');
  signState[optionSet] = {};
  
  //The solution - because it prevents overriding existing literals, so name:value pairs are neatly written to each literal if they don't already exist
  if(!signState[optionSet]) { 
    signState[optionSet] = {};
  }
  //---------
  
  optionName = $(this).attr('name');
  optionValue = $(this).val();
  signState[optionSet][optionName] = optionValue;
});

1 Comment

Looks like it'll work, but you dont need to declare the variables globally. (This only increases the room for error, and uses global memory for something local). And i really wouldnt use the word option so often as it just looks repetitive, but it works!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.