1

I'm using a Sass framework based on modular CSS principles, which outputs all my variables and configuration for each Sass "module" into JSON format in the DOM, which I have successfully retrieved in my JS. My JSON is in the following format:

{  
   "billboard":{  
      "selector-type":"flex",
      "extend-settings":true,
      "name":"billboard",
      "full-screen":false,
      "overlay":true,
      "bg-color":"#232627",
      "bg-image":"../../images/billboard-1.jpg",
      "overlay-color":"#9B58B5",
      "overlay-opacity":0.6,
      "color":"#ffffff",
      "text-align":"center",
      "min-height":"500px",
      "wrapper-width":"940px"
   },
   "navigation":{  
      "selector-type":"flex",
      "extend-settings":true,
      "name":"navigation",
      "item-color":"#ffffff",
      "item-bg":"transparent",
      "item-border":[  
         "1px",
         "solid",
         "transparent"
      ],
      "item-hover-color":null,
      "item-hover-bg":"transparent",
      "item-hover-border":[  
         "1px",
         "solid",
         "#ffffff"
      ]
      "header-dark":{  
         "default":false,
         "item-color":"#6f777b",
         "item-border":[  
            "1px",
            "solid",
            "#ffffff"
         ],
         "item-bg-color":"transparent",
         "item-hover-color":null,
         "item-hover-border":[  
            "1px",
            "solid",
            "#ffffff"
         ],
         "item-hover-bg-color":"#9B58B5"
      },
      "style":false,
      "no-icons":true,
      "link-color":"#ffffff"
   }
}

Each first level set will always be a Sass "module" (e.g., "header"), which will then contain the module's configuration, which can be of any depth.

I'd like to write a function to retrieve the value of the key I specify. Since not all keys are unique, and the only guaranteed uniqueness is in the module name, my requirements are to be able to select the value by specifying the parents.

Here's what I have so far, where "stylesConfig" is my array of JSON data:

function module(module, option) {
    var mValue;
    $.each(stylesConfig, function(id, param) {
        if(id == module) {
            $.each(param, function(key, value) {
                if (key == option) {
                    mValue = value;
                    return false;
                }
            });
        }
    });
    return mValue;
}

This works perfectly using:

module("navigation", "selector-type");

Which would return "flex" using the above JSON example. The problem is that it doesn't work recursively, so doesn't work on nested options. I would like to be able to expand upon what I already have to be able to do something like:

module("navigation", ["header-dark", "item-color"]);

To return "#6f777b".

Coming from a design background, I frankly have no idea what I'm doing. My programming capabilities are limited to what I have learned using Sass.

Michael Laszlo
  • 12,009
  • 2
  • 29
  • 47
ESR
  • 1,669
  • 1
  • 18
  • 22
  • What does this have to do with Sass? – cimmanon Aug 18 '15 at 12:34
  • Well the background to the question is very much Sass related. It wouldn't surprise me if in the future the presence of Sass tags helps someone who is in a similar boat to me. Isn't that the purpose of tags? – ESR Aug 18 '15 at 12:42
  • No, you only use the tag if it is relevant to the problem (is a Sass expert going to be able to help?). You may as well have put tags like "browsers" or "chrome" (or "firefox"), since you used those things, too, right? – cimmanon Aug 18 '15 at 12:43
  • I see your point. But when searching for the answer to this question myself, seeing a Sass tag would have told me I was looking in the right direction. The context for me was very important. The context in this question is really about accessing Sass maps using JS. I appreciate you must probably track all Sass questions and have had your time wasted reading this one, so I apologies. – ESR Aug 18 '15 at 12:48
  • 1
    But you don't have a Sass mapping, you have a JSON object. Sass doesn't support JSON out of the box, and the fact that you used a 3rd party library to generate the JSON from your Sass is irrelevant. If your question can be answered without any knowledge of where the JSON object came from, then the sass tag is inappropriate. – cimmanon Aug 18 '15 at 12:51

4 Answers4

2

If your function is written correctly, you could do this:

var headerDark = module("navigation", "header-dark");
var itemColor = headerDark["item-color"];

But you don't need that function it would seem, just store the JSON in a variable and access the objects by key name and they're children.

Like so...

yourJSONObject.navigation["header-dark"]["item-color"];
Coffee'd Up Hacker
  • 1,356
  • 11
  • 23
  • Interesting, had no idea I could do this. This definitely seems like a more suitable approach. – ESR Aug 18 '15 at 12:58
0

Here's one way to do it

var stylesConfig = {
    "billboard": {
        "selector-type": "flex",
        ...

function module(module, option) {
    // array
    if (option instanceof Array)
    {
        var i = stylesConfig[module];
        // recursively navigate stylesConfig using the array elements
        option.forEach(function (e) {
            i = i[e];
        })
        return i;
    }
    // string
    else
    {
        return stylesConfig[module][option];
    }
}


console.log(module("navigation", "selector-type"));   // flex
console.log(module("navigation", ["header-dark", "item-color"]));  // #6f777b
potatopeelings
  • 40,709
  • 7
  • 95
  • 119
  • Seems to work just like I was expecting. I marked this as the correct answer as it answers the question I asked, but Coffee'd Up Hacker's answer was actually more beneficial. Turns out I didn't need such a function to achieve what I'm after. – ESR Aug 18 '15 at 13:05
0

you are traversing whole json tree to find out the value you need. you have the keys so you dont need to traverse the whole tree.

{  
 "billboard":{  
  "selector-type":"flex",
  "extend-settings":true,
  "name":"billboard",
  "full-screen":false,
  "overlay":true,
  "bg-color":"#232627",
  "bg-image":"../../images/billboard-1.jpg",
  "overlay-color":"#9B58B5",
  "overlay-opacity":0.6,
  "color":"#ffffff",
  "text-align":"center",
  "min-height":"500px",
  "wrapper-width":"940px"
  },
  "navigation":{  
  "selector-type":"flex",
  "extend-settings":true,
  "name":"navigation",
  "item-color":"#ffffff",
  "item-bg":"transparent",
  "item-border":[  
     "1px",
     "solid",
     "transparent"
  ],
  "item-hover-color":null,
  "item-hover-bg":"transparent",
  "item-hover-border":[  
     "1px",
     "solid",
     "#ffffff"
  ]
  "header-dark":{  
     "default":false,
     "item-color":"#6f777b",
     "item-border":[  
        "1px",
        "solid",
        "#ffffff"
     ],
     "item-bg-color":"transparent",
     "item-hover-color":null,
     "item-hover-border":[  
        "1px",
        "solid",
        "#ffffff"
     ],
     "item-hover-bg-color":"#9B58B5"
  },
  "style":false,
  "no-icons":true,
  "link-color":"#ffffff"
   }
};

 return a['navigation']['selector-type'];// gives you 'flex'

I am assuming you are being able to put this json in some form of variable and after that it's like normal array traversing

Siddharth
  • 859
  • 8
  • 16
0

If you want to search recursively through a JSON object, a recursive function is a good approach:

function find(json, parents, index) {
  if (parents === undefined) {
    return undefined;
  }
  if (index === undefined) {
    index = 0;
  }
  if (index == parents.length - 1) {
    return json[parents[index]];
  }
  return find(json[parents[index]], parents, index + 1);
}

var styles = {  
   "billboard":{  
      "selector-type":"flex",
      "extend-settings":true,
      "name":"billboard",
      "full-screen":false,
      "overlay":true,
      "bg-color":"#232627",
      "bg-image":"../../images/billboard-1.jpg",
      "overlay-color":"#9B58B5",
      "overlay-opacity":0.6,
      "color":"#ffffff",
      "text-align":"center",
      "min-height":"500px",
      "wrapper-width":"940px"
   },
   "navigation":{  
      "selector-type":"flex",
      "extend-settings":true,
      "name":"navigation",
      "item-color":"#ffffff",
      "item-bg":"transparent",
      "item-border":[  
         "1px",
         "solid",
         "transparent"
      ],
      "item-hover-color":null,
      "item-hover-bg":"transparent",
      "item-hover-border":[  
         "1px",
         "solid",
         "#ffffff"
      ],
      "header-dark":{  
         "default":false,
         "item-color":"#6f777b",
         "item-border":[  
            "1px",
            "solid",
            "#ffffff"
         ],
         "item-bg-color":"transparent",
         "item-hover-color":null,
         "item-hover-border":[  
            "1px",
            "solid",
            "#ffffff"
         ],
         "item-hover-bg-color":"#9B58B5"
      },
      "style":false,
      "no-icons":true,
      "link-color":"#ffffff"
   }
};

function print(s) {
  document.write(s + '<br />');
}

print(find(styles, ['navigation', 'selector-type']));
print(find(styles, ['navigation', 'header-dark', 'item-color']));
Michael Laszlo
  • 12,009
  • 2
  • 29
  • 47