1

I have various elements that I want to show or hide depending on which activity the user is engaging in. Previously, my setDisplays function had a long list of parameters which needed to be set every time the function was called: e.g.

setDisplays("none","inline","inline","none","none","none","block","none","none","none","none","table","block","block");

Apart from being difficult to read and set, it was also inflexible. So I changed the function to take an array of objects: e.g.

setDisplays([{bingoDisplay:"none"},{bingoScore:"none"},{bingoWords:"none"},{book_overlay:"none"},{choiceDiv:"none"},{errDiv:"none"},{imageDiv:"block"},{livesDispTop:"none"},{phonDisplay:"none"},{score:"none"},{timer:"none"},{phonUSelect:"none"},{numUSelect:"none"},{vocSelect:"table"}]);

The modified function is:

function setDisplays(display) {
    var display_name;
    var display_setting;

    for (var i=0; i<display.length; i++){
        display_name=Object.keys(display[i]);
        display_setting=display[i][display_name];
        document.getElementById(display_name).style.display=display_setting;
    }
}

I've done some initial testing, and it seems to work, but I'm new to objects, so before I commit and move everything over to the new function, could anyone tell me if there are unforeseen problems with this strategy?

I've searched around and could not find an example of an argument like this.

PS: I realise that Object.keys is not supported by older browsers, but I'm using HTML5 audio extensively, so need to create a redirect page for them anyway.

Thailandian
  • 577
  • 5
  • 14
  • 2
    Instead of having an array of one-property objects, did you think of having a single object, such as `{bingoDisplay: "none", bingoScore: "none", ...}`? –  Mar 22 '15 at 09:42
  • single object is far simpler to work with and to inspect while debugging – charlietfl Mar 22 '15 at 09:46
  • you should also not have to pass them all in each time, but only the ones that should be a non-default value. it's also easy to get a polyfill for Object.keys() – dandavis Mar 22 '15 at 09:55

3 Answers3

1

Using an object would be a much simpler solution.

var setDisplays = {
    bingoDisplay: "none", 
    bingoScore: "none", 
    bingoWords: "none"
};

You can then access each property, read or set, by:

setDisplays.bingoScore = "something";
setDisplays.bingoScore; //returns "something"
Mackan
  • 6,200
  • 2
  • 25
  • 45
  • Thanks for the response. Would it be possible to set the display of many elements with a single call with this object? – Thailandian Mar 22 '15 at 10:12
  • A single call, no (not that I'm aware of). Either loop it, or just type out each property explicitly. As it is now, you have 10+ objects stored in an array. It works, but it's simpler to just use the one object (for maintaining and future additions). – Mackan Mar 22 '15 at 10:45
  • Yes I see your point. However, for my purposes, @Tim Osadchiy's solution is more flexible, as I can either set a single element's display, or multiple elements' displays with a single function call. – Thailandian Mar 22 '15 at 11:48
  • It's the same solution, I just didn't type out the entire code for you :) calling a function, that in turn calls the object 10 times, doesn't make it 'one call'. There is no way around that though. Good you found a working solution though. – Mackan Mar 22 '15 at 17:17
0

I would suggest using object as an argument instead of an array. Example:

function setDisplays(obj) {
    var display_name;
    var display_setting;

    for (var i in obj){
        if (!obj.hasOwnProperty(i)) { continue; }
        display_name=i;
        display_setting=obj[i];
        document.getElementById(display_name).style.display=display_setting;
    }
}

setDisplays({bingoDisplay:"none", bingoScore:"none", bingoWords:"none"});

Another version of setDisplays function with Object.keys

function setDisplays(obj) {
    var display_name;
    var display_setting;
    var keys = Object.keys(obj);

    for (var i=0, l=keys.length; i<l; i++){
        key = keys[i];
        display_name=key;
        display_setting=obj[key];
        document.getElementById(display_name).style.display=display_setting;
    }
}
Timur Osadchiy
  • 5,699
  • 2
  • 26
  • 28
  • Thank, that it much cleaner. I've seen a lot of warnings about for (i in obj). Is it OK to use in this instance because there is no proto? – Thailandian Mar 22 '15 at 10:08
  • I think it is OK. Please note that I have added `obj.hasOwnProperty(i)` in a loop, so you won't get `undefined` key. – Timur Osadchiy Mar 22 '15 at 10:16
  • Yes, that should also prevent the for loop from iterating over properties from the prototype chain. – Thailandian Mar 22 '15 at 11:06
  • I've tried your first version and it works fine. Even though, as I mentioned, early browser compatibility is not an issue for me, the version without keys looks cleaner, and the `obj.hasOwnProperty(i)` should make the for-in loop safe. Thanks for the help. – Thailandian Mar 22 '15 at 11:39
0

Using an object will be more intuitive, as compared to array notation, since you can refer to keys directly instead of keeping track of which parameter is at what index, if performance is a priority for your task, look at What is the performance of Objects/Arrays in JavaScript? (specifically for Google V8) ,but I think performance should not be an issue.

Community
  • 1
  • 1
sumeet batheja
  • 329
  • 1
  • 2
  • 13
  • Thanks for the response. Objects are still quite new to me, so straightforward solutions are not always obvious yet. I nearly went with the array because it seemed to work, but I'm glad I checked in here first. – Thailandian Mar 22 '15 at 11:43