2

Similar to chmod, I would like to use 1, 2, 4 as a way of notifications.

1 = Email 
2 = SMS 
4 = Push notifications

Is there function (preferably in javascript) that can input a number (above) and can return an object with:

{
    email: true,
    sms: true,
    push: false
}

I want the function to not be hard coded. I don't want a bunch of if statements that check for every combination there is. I want a "smart" way to do it.

TIMEX
  • 259,804
  • 351
  • 777
  • 1,080
  • 3
    You need to look at bitwise operators - `&, |, <<, >>, ^`. There are some good tutorials for how to find what bits are set, which is what it sounds like you want. – g.d.d.c Mar 21 '13 at 22:45
  • `opts = { email: 1 << 0, sms: 1 << 1, push: 1 << 2 }` - or any suitable replacement for generating the values. Coupled with `|` for building and `&` for testing: `x = opts.email | opts.sms; if (x & opts.email) { /* here */ }; if (x & opts.push) { /* not here */ }` .. –  Mar 21 '13 at 22:50

3 Answers3

5

How about something like this:

var commsMode = {
    email: 1,
    sms: 2,
    push: 4,
    toObject: function(val){
        var rt = {};

        for (e in commsMode) {
            rt[e] = (val & commsMode[e]) > 0;
        }

        return rt;
    }
};

var obj = commsMode.toObject(3);

Working example here.

Extended example:

var commsMode = {
    email: 1,
    sms: 2,
    push: 4,
    mode4: 8,
    mode5: 16,
    mode6: 32,
    mode7: 64,
    mode8: 128,
    toObject: function(val){
        var rt = {};

        for (e in commsMode) {
            rt[e] = (val & commsMode[e]) > 0;
        }

        return rt;
    }
};

var obj = commsMode.toObject(233);

for (p in obj) {
    alert(p + ': ' + obj[p])
}

Working example here

Paul Fleming
  • 24,238
  • 8
  • 76
  • 113
  • @TIMEX. It certainly is. Simpler than you thought? – Paul Fleming Mar 21 '13 at 22:58
  • It will work up to the [maximum supported JS number](http://stackoverflow.com/questions/307179/what-is-javascripts-max-int-whats-the-highest-integer-value-a-number-can-go-t). Language unspecific: 32bit (signed) would support 31 entries, 64bit (signed) would support 63 entries. – Paul Fleming Mar 21 '13 at 23:00
  • 1
    I don't understand - in your example u send 3 to the function and u get email->true, sms->true, push->false ?! am I missing something here ? it's not what he asked for... – Adidi Mar 21 '13 at 23:02
  • 1
    It's a BitMask. I figured that was obvious given the values 1, 2, and 4. – Paul Fleming Mar 21 '13 at 23:02
2

Try something like this - sorry, this is Python, but the JavaScript translation should be very similar:

def notifications(mask):
    return {
        'email' : mask & 4 != 0,
        'sms'   : mask & 2 != 0,
        'push'  : mask & 1 != 0
    }

notifications(0b111) # same as notifications(7), or notifications(email+sms+push)
=> {'push': True, 'sms': True, 'email': True}

In the above, we're saying that the notifications binary bit mask is 0b111 (or 7, if you prefer to use base-10), meaning that all three notifications are enabled. Similarly, if we had passed as bit mask 0b010 (or 2 in base-10), then the answer would have been:

notifications(0b010) # same as notifications(2), or notifications(sms)
=> {'push': False, 'sms': True, 'email': False}
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • OP asked for a generic method. This requires a new line for every new mode. – Paul Fleming Mar 21 '13 at 22:57
  • @flem no it doesn't, just pack the `answer` in a function that receives a `notification` as a parameter, and return the resulting map – Óscar López Mar 21 '13 at 22:58
  • "I want the function to not be hard coded. I don't want a bunch of if statements that check for every combination there is. I want a "smart" way to do it." – Paul Fleming Mar 21 '13 at 23:02
0

Solution with multiple parameters to send to function:

var states = {
  '1': 'email',
  '2': 'sms',
  '4': 'push'
};

function getStates(){
 var o = {};
 for(var val in states){
   o[states[val]] = false;   
 }

   for(var i=0;i<arguments.length;i++){
     var arg = arguments[i];  
     var state = states[arg];
      if(state){
        o[state] = true;
      }  
  }

  return o;
}

console.log(getStates()); // return {email: false, sms: false, push: false}
console.log(getStates(1,2)); // return {email: true, sms: true, push: false} 

http://jsfiddle.net/ZTA6E/

Adidi
  • 5,097
  • 4
  • 23
  • 30