To get a better understanding of how this module can be useful, let's take a look at a real world use case.

You have a CSV formatted data file that was exported from a spreadsheet. This is a particular kind of spreadsheet, where the first column stores the id for localized string resources, and the second column stores their translations. The entire spreadsheet contains translations for a number of resources, for a single language. We'd like to parse the CSV file and ultimately produce a hash table that we can use to look up localized translations for given resource strings. We can parse the CSV file, using the Uize.Data.Csv module, to produce a records array. Then we'd like to convert that records array into a lookup hash. We can do this with the Uize.Data.NameValueRecords.toHash method, as follows...

CSV FILE

welcomeMessage,"Welcome, {firstName} of {state}, {country}"
deleteSingular,Are you sure you would like to delete this item?
deletePlural,Are you sure you would like to delete these {totalItems} items?

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}

With object type name/value records, each record is an object containing properties for the name and value of a name/value pair.

EXAMPLE

[
{
name:'welcomeMessage',
value:'Welcome, {firstName} of {state}, {country}'
},
{
name:'deleteSingular',
value:'Are you sure you would like to delete this item?'
},
{
name:'deletePlural',
value:'Are you sure you would like to delete these {totalItems} items?'
}
]

By default, and typically, the property used for specifying the name out of a name/value pair is called name, and the property used for specifying the value out of a name/value pair is called value, but this does not have to be the case.

The methods of the Uize.Data.NameValueRecords module support object type name/value records where the name/value records use different property names for defining name/value pairs. Consider the following example...

EXAMPLE

[
{
stringId:'welcomeMessage',
translation:'Welcome, {firstName} of {state}, {country}'
},
{
stringId:'deleteSingular',
translation:'Are you sure you would like to delete this item?'
},
{
stringId:'deletePlural',
translation:'Are you sure you would like to delete these {totalItems} items?'
}
]

In the above example, stringId is used for the name property, and translation is used for the value property. This is an extreme example. Maybe more reasonable would be to use key and value, but this illustrates the point. The Uize.Data.NameValueRecords.fromHash and Uize.Data.NameValueRecords.toHash methods let you work with an object type name/value records array that has non-standard name/value properties, with their optional namePropertySTRorINT and valuePropertySTRorINT parameters.

With array type name/value records, each record is an array containing elements for the name and value of a name/value pair.

EXAMPLE

[
[
'welcomeMessage',
'Welcome, {firstName} of {state}, {country}'
],
[
'deleteSingular',
'Are you sure you would like to delete this item?'
],
[
'deletePlural',
'Are you sure you would like to delete these {totalItems} items?'
]
]

By default, and typically, the first element of array type name/value records is used for specifying the name out of a name/value pair, and the second element is used for specifying the value out of a name/value pair, but this does not have to be the case.

The methods of the Uize.Data.NameValueRecords module support array type name/value records where different elements of the name/value records are used for defining name/value pairs. Consider the following example...

EXAMPLE

[
[
'Welcome, {firstName} of {state}, {country}',
'welcomeMessage'
],
[
'Are you sure you would like to delete this item?',
'deleteSingular'
],
[
'Are you sure you would like to delete these {totalItems} items?',
'deletePlural'
]
]

For object type name/value records, properties that aren't the name or value properties for name/value pairs are simply ignored. For array type name/value records, elements that aren't the name or value elements for name/value pairs will also be ignored, provided the first element remains the name element and the second element remains the value element. If the presence of extraneous elements in array type name/value records interferes with the order of the name and value elements, then you will have to use the optional namePropertySTRorINT and valuePropertySTRorINT parameters to indicate the indices of the name and value elements.

Uize.Data.NameValueRecords.toHash (
[
{
name:'welcomeMessage',
value:'Welcome, {firstName} of {state}, {country}'
},
{
name:'deleteSingular',
value:'Are you sure you would like to delete this item?'
},
{
name:'deletePlural',
value:'Are you sure you would like to delete these {totalItems} items?'
}
]
);

In the above example, an array of name/value records defines a dictionary of localized string id to translation mappings. This name/value records array is converted to a dictionary hash, for easy lookup, using the Uize.Data.NameValueRecords.toHash. The above method call would produce the following result...

OUTPUT

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}

Uize.Data.NameValueRecords.fromHash (
{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}
);

In the above example, a dictionary of localized string id to translation mappings is being converted to an array of name/value records, where each record is an object containing name and value properties. The above method call would produce the following result...

OUTPUT

[
{
name:'welcomeMessage',
value:'Welcome, {firstName} of {state}, {country}'
},
{
name:'deleteSingular',
value:'Are you sure you would like to delete this item?'
},
{
name:'deletePlural',
value:'Are you sure you would like to delete these {totalItems} items?'
}
]

Uize.Data.NameValueRecords.toHash (
Uize.Data.NameValueRecords.fromHash (
{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}
)
);

OUTPUT

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}

[
[
'welcomeMessage',
'Welcome, {firstName} of {state}, {country}'
],
[
'deleteSingular',
'Are you sure you would like to delete this item?'
],
[
'deletePlural',
'Are you sure you would like to delete these {totalItems} items?'
]
]

In the above example, we're transmuting a name/value records array with object type name/value records into a new one - also with object type records - but where the names of the name/value properties have been remapped from name and value to stringId and translation. After the above code has executed, the value of the transmutedNameValueRecords variable will be as follows...

OUTPUT

[
{
stringId:'welcomeMessage',
translation:'Welcome, {firstName} of {state}, {country}'
},
{
stringId:'deleteSingular',
translation:'Are you sure you would like to delete this item?'
},
{
stringId:'deletePlural',
translation:'Are you sure you would like to delete these {totalItems} items?'
}
]

Other applications for transmuting include deduping and extraneous property removal. Use your imagination to conjure up other ways that name/value records arrays could be transmuted by converting back and forth with different options.

When the optional namePropertySTRorINT and valuePropertySTRorINT parameters are specified, then the key names for the name and value properties of the name/value records can be controlled (by default they are 'name' and 'value'). Specifying number type values for these parameters will cause the generated name/value records to be two element arrays, rather than two property objects.

Uize.Data.NameValueRecords.fromHash (
{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}
);

In the above example, a dictionary of localized string id to translation mappings is being converted to an array of name/value records, where each record is an object containing name and value properties. The above method call would produce the following result...

OUTPUT

[
{
name:'welcomeMessage',
value:'Welcome, {firstName} of {state}, {country}'
},
{
name:'deleteSingular',
value:'Are you sure you would like to delete this item?'
},
{
name:'deletePlural',
value:'Are you sure you would like to delete these {totalItems} items?'
}
]

In this example, we are specifying values for the optional namePropertySTRorINT and valuePropertySTRorINT parameters in order to override the default values of 'name' and 'value'.

EXAMPLE

Uize.Data.NameValueRecords.fromHash (
{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
},
'stringId',
'translation'
);

Here we are specifying 'stringId' for namePropertySTRorINT to override the default of 'name', and 'translation' for valuePropertySTRorINT to override the default of 'value'. The above method call would produce the following result...

OUTPUT

[
{
stringId:'welcomeMessage',
translation:'Welcome, {firstName} of {state}, {country}'
},
{
stringId:'deleteSingular',
translation:'Are you sure you would like to delete this item?'
},
{
stringId:'deletePlural',
translation:'Are you sure you would like to delete these {totalItems} items?'
}
]

By specifying number type values for the namePropertySTRorINT and valuePropertySTRorINT parameters, we can coerce the Uize.Data.NameValueRecords.fromHash method to make the name/value records two element arrays, rather than two property objects.

Specifying the value 0 for namePropertySTRorINT would put the name in the first element of each name/value array, and specifying the value 1 for valuePropertySTRorINT would put the value in the second element. Consider the following example...

EXAMPLE

Uize.Data.NameValueRecords.fromHash (
{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
},
0,
1
);

In the above example we are specifying the values 0 and 1 for the namePropertySTRorINT and valuePropertySTRorINT parameters, respectively. This tells the Uize.Data.NameValueRecords.fromHash to return an array of arrays, rather than an array of objects. The above method call would produce the following result...

OUTPUT

[
[
'welcomeMessage',
'Welcome, {firstName} of {state}, {country}'
],
[
'deleteSingular',
'Are you sure you would like to delete this item?'
],
[
'deletePlural',
'Are you sure you would like to delete these {totalItems} items?'
]
]

You can specify any index values for the namePropertySTRorINT and valuePropertySTRorINT parameters, so you could even swap the name/value order, as in the following example...

EXAMPLE

Uize.Data.NameValueRecords.fromHash (
{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
},
1,
0
);

In the above example we are specifying the values 1 and 0 for the namePropertySTRorINT and valuePropertySTRorINT parameters, respectively. This has the effect of swapping the name/value order in the two element name/value arrays. The above method call would produce the following result...

OUTPUT

[
[
'Welcome, {firstName} of {state}, {country}',
'welcomeMessage'
],
[
'Are you sure you would like to delete this item?',
'deleteSingular'
],
[
'Are you sure you would like to delete these {totalItems} items?',
'deletePlural'
]
]

When the optional namePropertySTRorINT and valuePropertySTRorINT parameters are specified, then you can control which property in the name/value records should be used for the property name in the returned hash object, and which property in the name/value records should be used for the property value. When these parameters are not specified, then the values of these paremeters will be defaulted to ether 'name' and 'value', or 0 and 1, depending on the type of the first name/value record in the array - 'name' and 'value' for object type, and 0 and 1 for array type.

Uize.Data.NameValueRecords.toHash (
[
{
name:'welcomeMessage',
value:'Welcome, {firstName} of {state}, {country}'
},
{
name:'deleteSingular',
value:'Are you sure you would like to delete this item?'
},
{
name:'deletePlural',
value:'Are you sure you would like to delete these {totalItems} items?'
}
]
);

In the above example, an array of name/value records defines a dictionary of localized string id to translation mappings. This name/value records array is converted to a dictionary hash, for easy lookup, using the Uize.Data.NameValueRecords.toHash. Because the name/value records are objects containing name and value properties, the optional namePropertySTRorINT and valuePropertySTRorINT parameters do not need to be used. The above method call would produce the following result...

OUTPUT

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}

When converting an array of name/value records to an object hash, where the name/value records are objects, the Uize.Data.NameValueRecords.toHash method ignores extraneous properties in the name/value objects.

EXAMPLE

Uize.Data.NameValueRecords.toHash (
[
{
language:'us-english',
name:'welcomeMessage',
value:'Welcome, {firstName} of {state}, {country}'
},
{
name:'deleteSingular',
language:'us-english',
value:'Are you sure you would like to delete this item?'
},
{
name:'deletePlural',
value:'Are you sure you would like to delete these {totalItems} items?',
language:'us-english'
}
]
);

In the above example, each name/value record also contains a language property. Because the name/value records are objects, and because the optional namePropertySTRorINT and valuePropertySTRorINT parameters are not being used, the Uize.Data.NameValueRecords.toHash method uses the name and value properties from each name/value record to populate the returned object hash. So, in this case, the extraneous language property is simply ignored. The above method call would produce the following result...

OUTPUT

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}

When the name/value records are objects whose name and value properties are not named name and value, then the optional namePropertySTRorINT and valuePropertySTRorINT parameters can be used to specify which property should be used as the property name and which should be used as the property value for properties of the returned hash object.

EXAMPLE

Uize.Data.NameValueRecords.toHash (
[
{
stringId:'welcomeMessage',
translation:'Welcome, {firstName} of {state}, {country}'
},
{
stringId:'deleteSingular',
translation:'Are you sure you would like to delete this item?'
},
{
stringId:'deletePlural',
translation:'Are you sure you would like to delete these {totalItems} items?'
}
],
'stringId',
'translation'
);

In this example, the name/value records in our array are not using the standard name and value properties. Instead, we would like to use the stringId property for property names and the translation property for property values in the returned hash object. Therefore, we specify the value 'stringId' for the namePropertySTRorINT parameter, and the value 'translation' for the valuePropertySTRorINT parameter. The above method call would produce the following result...

OUTPUT

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}

Name/value records supplied to the Uize.Data.NameValueRecords.toHash method can also be two element arrays, where the first element represents the property name and the second element represents the property value for properties of the returned hash object.

EXAMPLE

Uize.Data.NameValueRecords.toHash (
[
[
'welcomeMessage',
'Welcome, {firstName} of {state}, {country}'
],
[
'deleteSingular',
'Are you sure you would like to delete this item?'
],
[
'deletePlural',
'Are you sure you would like to delete these {totalItems} items?'
]
]
);

In the above example, the Uize.Data.NameValueRecords.toHash method detects that the first record in the name/value records array is an array. Because the optional namePropertySTRorINT and valuePropertySTRorINT parameters are not used, and because the name/value records are arrays, the Uize.Data.NameValueRecords.toHash method defaults the namePropertySTRorINT and valuePropertySTRorINT parameters to 0 and 1, which results in extracting the first and second elements out of each name/value record when forming the properties of the returned hash object. The above method call would produce the following result...

OUTPUT

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}

You can specify any index values for the namePropertySTRorINT and valuePropertySTRorINT parameters, so you can swap the name/value order when name/value records are arrays containing more than two elements, as in the following example...

EXAMPLE

Uize.Data.NameValueRecords.toHash (
[
[
'Welcome, {firstName} of {state}, {country}',
'welcomeMessage'
],
[
'Are you sure you would like to delete this item?',
'deleteSingular'
],
[
'Are you sure you would like to delete these {totalItems} items?',
'deletePlural'
]
],
1,
0
);

In this example, we know that the name/value records of the array have their name and value elements swapped around. To adjust for this, we can specify the value 1 and 0 for the namePropertySTRorINT and valuePropertySTRorINT parameters, respectively, to map the second element of each name/value record to the property name, and the first element to the property value, when mapping the name/value records to properties of the returned hash object. The above method call would produce the following result...

OUTPUT

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}

Because you can specify any index values for the namePropertySTRorINT and valuePropertySTRorINT parameters, you can use this facility to cherry pick the correct elements from array type name/value records, as in the following example...

In this example, the first element of every name/value record is an extraneous language code element. Now, if we didn't specify values for the optional namePropertySTRorINT and valuePropertySTRorINT parameters, then the returned hash object would be somewhat borked: there would be only one property, having the name us-english, and its value would be 'deletePlural' (because the second element of the last name/value record would win out over the other records).

What we need to do here is specify the value 1 and 2 for the namePropertySTRorINT and valuePropertySTRorINT parameters, respectively, to map the second element of each name/value record to the property name, and the third element to the property value, when mapping the name/value records to properties of the returned hash object. The above method call would produce the following result...

OUTPUT

{
welcomeMessage:'Welcome, {firstName} of {state}, {country}',
deleteSingular:'Are you sure you would like to delete this item?',
deletePlural:'Are you sure you would like to delete these {totalItems} items?'
}