How to retrieve key with value - javascript

When I submit a form, one of the fields being submitted is an ID (number) instead of the name for easier processing by the server. Like so:
HTML dropdown select
<select ng-model="myColor" class="form-control"
ng-options = "color.ID as color.color for color in $parent.colorSelection">
</select>
AngularJS
$scope.colorSelection = [{"color": "Red", "ID": "7011"}, {"color": "Blue", "ID": "7012"}];
So the server sends a JSON back
res.json({
Color: req.query.color,
});
And now when I get the results back, I want to display the name instead of the ID number which is what the server sends back to me. So instead of showing "7011", I want to show "Red". How do I do this? Doing the following doesn't work.
{{results.Color.color}}

Since colorSelection is an array, you'll have to loop through it, directly or by using one of the array functions that does.
In this case, find is probably what you want (you may need a shim on older browsers, if Angular doesn't already shim it for you):
var entry = $scope.colorSelection.find(function(entry) { return entry.ID == results.Color.color; });
var color = entry && entry.color;
color will be either null (not found) or the color name.
It's a bit less clunky with ES2015:
let entry = $scope.colorSelection.find(entry => entry.ID == results.Color.color);
let color = entry && entry.color;
Another approach would be to have a reusable map of color IDs to names:
In ES5, you'd probably use an object:
// One-time initialization of the map, just after you create
// $scope.colorSelection
$scope.colorSelectionMap = Object.create(null);
$scope.colorSelection.forEach(function(entry) {
$scope.colorSelectionMap[entry.ID] = entry.color;
});
then
var color = $scope.colorSelectionMap[results.Color.color];
In ES2015, you could still do that, or you could use a Map:
// One-time initialization of the map, just after you create
// $scope.colorSelection
$scope.colorSelectionMap = new Map(
$scope.colorSelection.map(entry => [entry.ID, entry.color])
);
then
var color = $scope.colorSelectionMap.get(results.Color.color);

You need to use like below code for select
<select ng-model="myColor" class="form-control"
ng-options = "colorSelection as colorSelection.color for colorSelection in colorSelection ">

Related

JS map to translate values back and forth

I'm trying to figure out the best way to approach mapping values back and forward as a sort of translation process. The use case is having to process a non SEO friendly attribute code into a nicer format and display that on the frontend, but i also need to be able to process the nice attribute label back into original code so i can use that in my script. In the following example, i'd want to be able to look up myMap to check if a string value exists in the object, and if it does, pull out its corresponding label.
var myString = 'color_attr_code'; // Want to be able to extract 'color' from the map
var myAltString = 'color'; // Want to be able to extract 'color_attr_code'
var myMap = {
'color_attr_code': 'color'
}
Thanks for any help.
You're on the right track, though in modern environments you might use a Map rather than an object, or at least create the object without a prototype so there aren't false matches on toString or valueOf or other things the default object prototype provides.
You'd have two maps, one going each direction, probably best derived from the same source data:
const mappings = [
["color_attr_code", "color"],
["blah_attr_code", "blah"],
// ...
];
const attrToLabel = new Map(mappings);
const labelToAttr = new Map(mappings.map(([key, value]) => [value, key]));
Then you use attrToLabel.get("color_attr_code") to get the corresponding label, and labelToAttr.get("color") to get the corresponding code.
Live Example:
const mappings = [
["color_attr_code", "color"],
["blah_attr_code", "blah"],
// ...
];
const attrToLabel = new Map(mappings);
const labelToAttr = new Map(mappings.map(([key, value]) => [value, key]));
console.log(`Label for "color_attr_code": ${attrToLabel.get("color_attr_code")}`);
console.log(`Code for "color": ${labelToAttr.get("color")}`);
Or in ES5 (although really, in today's world, there's no reason to write ES5 manually — write modern code and transpile with Babel or similar) and objects:
var mappings = [
["color_attr_code", "color"],
["blah_attr_code", "blah"],
// ...
];
var attrToLabel = Object.create(null);
var labelToAttr = Object.create(null);
mappings.forEach(function(mapping) {
var code = mapping[0], label = mapping[1];
attrToLabel[code] = label;
labelToAttr[label] = code;
});
Then you use attrToLabel["color_attr_code"] to get the corresponding label, and labelToAttr["color"] to get the corresponding code.
Of course, all of this assumes there are always just 1:1 mappings, that there aren't (for instance) two codes that both map to the same label.

Can I get the list of Caman.js filters?

Is there any way to return the list of all the built-in filters within the library.
For example:
var caman_Default_List = [];
Caman('myCanvas', function(){
caman_Default_List= this.getAllFilters();
});
For now I'm using this and it works okay:
var filters =
[
"vintage", "lomo", "clarity", "sinCity", "sunrise",
"crossProcess", "orangePeel", "love", "grungy", "jarques", "pinhole",
"oldBoot", "glowingSun", "hazyDays", "herMajesty", "nostalgia",
"hemingway", "concentrate"
];
myList.push(filters[ some filters ]);
Caman("#myCanvas", function(){
this[myList[index]]().render();
});
But I was wondering if there is a way to get the values of the filters without delcaring them customly. (eg. list = [ "vintage", "lomo", ......... ])
I was looking through their docs, but could not find anything helpful for the data you are trying to get. I took a look at their code and came up with the below for you.
I am not sure I would 100% trust the code, because the order of properties might change, but at least it gives you what you wanted.
console.log(Object.keys(Caman.prototype).slice(75, 93))
<script src="https://cdnjs.cloudflare.com/ajax/libs/camanjs/4.1.2/caman.full.min.js"></script>
I used the code below to achieve what I wanted as #AndrewLohr stated:
//Declare lists to store filter names
var list4,list5,list6,list7 = [];
//Get Caman Filters (Samples : "vintage", "clarity", ... )
list4 = (Object.keys(Caman.prototype).slice(75, 93));
list5 = list4.toString().toUpperCase(); //To upper Case as string value (use as Label Button Name)
//Get Caman Filters (Customs : "brightness", "saturation")
list6 = Object.keys(Caman.prototype).slice(45, 55);
//Add some more elements in the list
list6.push("clip", "stuckBlur", "exposure", "noise", "sharpen");
list7 = list6.toString().toUpperCase(); //To upper Case as string value (use as Slider Name)
//Print lists
console.log(list4);console.log(list5);console.log(list6);console.log(list7);
<script src="https://cdnjs.cloudflare.com/ajax/libs/camanjs/4.1.2/caman.full.min.js"></script>

Passing Hash Table/Dictionary with a loop in JavaScript

However, I want pass an "ID" into the option "value" field with a corresponding string as the option text.
So, if ID for Black = 1, White = 2, Blue = 3, then the html would look something like this:
<option value ='1'> Black </option>
This JSFiddle is similar to what I'm trying to accomplish:
http://jsfiddle.net/e6hzj8gx/4/
Except that I want to send only the value and use a key to call it.
I'm basically building a dropdown with Django that is dependent on what the user selects in another dropdown - there isn't really an elegant way of doing this in Django and it seems that serializing my data to json and then using javascript to build the drop down is the way to go.
My Django data is just a dict:
data = {1: 'Black', 2 = 'White', 3 = 'Blue'}
There are a few ways to loop through a javascript object. When working with a parsed JSON object, you can use:
for (var propName in obj) {
// access data using obj[propName]
}
In more complicated cases, you might have to check if the property isn't inherited from some other prototype using:
if (obj.hasOwnProperty(propName) { /* ... */ }
Furthermore, you can create DOM elements using document.createElement("option")
All together, it'll be something like this:
var obj = JSON.parse(serverData);
for (var propName in obj) {
var jsonValue = obj[propName];
if (jsonValue && (typeof jsonValue === "string")) {
var option = document.createElement("option");
option.value = propName;
option.innerText = jsonValue;
// Add created option to a select element
// ...
}
}
Let me know if I got your question right...

JS and ExpressionEngine - Remove KV pairs by duplicate values only?

We're building a site with ExpressionEngine. We are running a SQL query to gather up all member IDs for a specific member group. After that, we are using EE tags to get data from a custom member field for each member ID.
The ID and field data need to stay paired, as we will be populating a drop-down so that the ID is the value and the field data is the text, so we are currently putting them into a JS array as key/value pairs. The call is as follows:
var array= [
{exp:query sql="SELECT * FROM exp_members WHERE group_id = 5"}
{exp:member:custom_profile_data
member_id="{member_id}"}
{if company != ''}
{{member_id}:"{company}"},
{/if}
{/exp:member:custom_profile_data}
{/exp:query}
};
This gives us the output:
var array = [
{1:"name01"},
{2:"name02"},
{3:"name01"},
{4:"name03"}
];
Now, our problem. We need to remove objects based on duplicate field data (values) only, so the above array would look like this:
var array = [
{1:"name01"},
{2:"name02"},
{4:"name03"}
];
None of these IDs (keys) will ever be the same, but the field data (values) can be. So we want to keep the first KV pair that comes through with a unique value, but remove any subsequent dupes of that value - despite the fact that they will not be true "duplicate values" due to a different ID (key).
Keeping in mind that the KV pairs are all dynamic, is there any possible way to do this via JS so we can create a new array for the cleaned data to pass to the drop-down?
You could handle the duplications by modifying your MySQL query. (In my example, my custom field ID was 1.)
var myArray = [];
{exp:query sql="SELECT MIN(m.member_id) AS co_member_id, d.m_field_id_1 AS company FROM exp_members m INNER JOIN exp_member_data d ON m.member_id = d.member_id WHERE d.m_field_id_1 != '' AND m.group_id > 0 GROUP BY d.m_field_id_1;"}
myArray.push({{co_member_id}: "{company}"});
{/exp:query}
This query would use the first (in the ordinal sense) member_id found; you could also change the MIN to MAX and get the last.
This will give you a clean output in your source, without the need for any additional JS processing. I'd also recommend changing the names of the variables you're outputting as to not conflict in EE's parsing.
I would do it like...
function removeDups(arry){
var tmp = {}, retainIdx=[], newArry=[];
arry.forEach(function(obj, idx){
var val = obj[Object.keys(obj)[0]];
if(val && !tmp[val]){
retainIdx.push(idx);
tmp[val] = true;
}
});
retainIdx.forEach(function(i){
newArry.push(arry[i]);
});
return newArry;
};

Creating Select Box from options stored in a variable

I want to create a select box from options stored in a variable (the values will change based on the user).
For now, I'm just trying to get it to work with this variable in my javascript file:
var resp = {"streams": [ {"sweet":"cookies"}, {"savory":"pizza"}]}
In the html file, I have a select id "selectedStream"
How do I invoke, both the select id from html and the variable from javascript to create the select box?
I've seen examples such as the one below, but I don't understand how to link the id and the variable to the box.
$("option:selected", myVar).text()
I hope this was coherent! Thanks
I think what you are trying to do is append option html nodes to an existing select element on your screen with an id of 'selectedStream'. You want to use the data from the 'resp' variable to populate the text and value of the option nodes that you are appending. If this is correct, I have implemented that functionality with this jsfiddle. The javascript is also below:
$(function(){
var resp = {"streams": [ {"sweet":"cookies", "savory":"pizza"}]};
var streamData = resp.streams[0];
var optionTemplate = "<option value=\"{0}\">{1}</option>";
for(var key in streamData){
var value = streamData[key];
var currentOptionTemplate = optionTemplate;
currentOptionTemplate = currentOptionTemplate.replace("{0}", key);
currentOptionTemplate = currentOptionTemplate.replace("{1}", value);
$("#selectedStream").append($(currentOptionTemplate));
}
});
Is that array necessary? If you're just trying to display the keys within that object I'd create a for loop:
var resp = { "streams": {"sweet": "cookies", "savory": "pizza"} }
for (property in resp.streams) {
$('#selectStream').append($('<option/>', {text: property, value: property}));
}
JSFiddle: http://jsfiddle.net/pWFNb/

Categories

Resources