PDA

View Full Version : Using bitwise operators to post different alert messages


mikemalter
08-25-2004, 01:25 AM
I have been looking for a way to give something back to this forum as it has helped me greatly, and I am hoping that this might be of value to someone.

Basically I was just tired of consistantly commenting and uncommenting out alerts in my code so I wrote some code that would allow me to keep my alerts and only show them when I wanted to, and only the types of alerts I wanted to show.

I thought that using bitwise operators would give me the flexibility to specify different options and a quick way of finding out what options were wanted. There are other ways of doing this of course, and this is one approach.

The bitwise OR operator "|" says if one of the two vars has the bit set, then set the bit.
the bitwise AND operator "&" says if both of the two vars has the bit set, then set the bit.

It starts with my bitwise values:
var NONE = new Number(0); // 00000000
var ALL = new Number(1); // 00000001
var INFO = new Number(2); // 00000010
var LOCAL = new Number(4); // 00000100
var PARAM = new Number(8); // 00001000
var COUNT = new Number(16); // 00010000

These values are really important. Earlier I used 0 through 5 and because of the way bitwise operations work, COUNT was equivelant to ALL and PARAM. what you are doing is blending bits and then getting a value. So, in the 0 through 5 approach, COUNT was 00000101 (5). When I OR'd ALL with PARAM I got 00000101 which was a result of 00000001 with 00000100 (4)! So be really careful if you go this route to double check that no combination of vars will equal other vars.

In our constructor we get the value thus:

function FormCheckBase( objForm, blnStateIsDebug, sCulture )
{
this.Form = eval('document.' + objForm);
this.Debug = new Number( blnStateIsDebug );
this.Culture = new String( sCulture );
}

with this call:

objFrm = new FormCheck( 'FormName', INFO | LOCAL | PARAM, sCulture );

Then in the instance methods of the FormCheck class, I wrap my alert boxes.

if ( this.ShowErrorAlert( this.PARAM ) ) // or whatever other value you want.
{
alert( sWhoAmI + "iArrayLength: " + iArrayLength );
alert( sWhoAmI + "blnBlank: " + blnBlank );
}


ShowErrorAlert does a bitwise "AND" to see if we have a match. We are also testing for ALL, and if that is passed originally, we are returning a true to show the alert.

FormCheckBase.prototype.ShowErrorAlert = function( iAlertBit )
{
var bitCompareResult = new Number(0);
var showMe = new Boolean(false);

bitCompareResult = (this.Debug & this.ALL);
showMe = ((bitCompareResult == this.ALL) ? true : false );
alert( showMe );
if ( showMe == true )
return showMe;

bitCompareResult = (this.Debug & iAlertBit);
showMe = ((bitCompareResult == iAlertBit) ? true : false );

return showMe;
};


I also did a couple of helper functions that would change the Debug var before I went into a method and reset it after I was done. Sometimes you might not want every single method to start showing alert boxes. So I did a SetDebugBits that sets the value of Debug and GetDebugBits that gets the current value of Debug. Call GetDebugBits first to store the current value, then call SetDebugBits to set it to whatever you want to use, and then make another call to SetDebugBits with the original value to set it back.

We mostly call our FormCheck constructor with the value of NONE, and then work on a method by method basis as we have lots of methods in the class.

So, I hope this has been presently clearly and is helpful to you.

kansel
08-25-2004, 11:24 PM
Most of what you wrote went way over my head. I really like seeing bitwise operations in javascript, but I'm a little confused on your application in this case. Would it be possible for you to provide a short demo of this in action?

I just want to inquire about one line from your FormCheckBase() constructor.

this.Form = eval('document.' + objForm);

Is there a particular reason you used eval() instead of the following?

this.Form = document[objForm];

mikemalter
08-25-2004, 11:50 PM
kansel,

That part of the code was written long before I got here.

Let me see about distilling the example down to a few lines. Sorry for the confusing context.

Mike

kansel
08-26-2004, 09:35 PM
I see. I've seen lots of "do not use eval()", "eval() slows down your script", etc. From my reading it seems as though eval() might be more useful when trying to catch exceptions and errors (i.e. eval() has some built-in error reporting), but in this case substituting the straight associative array notation is probably better.

Waiting for that demo. :)

Alex Vincent
08-27-2004, 07:50 AM
Interesting. The only thing I might wonder about is why you use "new Number(1)" instead of 1. Why construct new objects when literals will do just as well? :)

mikemalter
08-27-2004, 05:41 PM
Kensel,

I am going to check to see if this.Form = document[objForm] behaves the same as this.Form = eval('document.' + objForm).

Here is that demo:

// Create and init your bit vars. Make sure that each value is unique
// and that all combinations are unique.
var NONE = new Number(0); // 00000000
var ALL = new Number(1); // 00000001
var INFO = new Number(2); // 00000010
var LOCAL = new Number(4); // 00000100
var PARAM = new Number(8); // 00001000
var COUNT = new Number(16); // 00010000
var EXTEND = new Number(32); // 00100000

// OR "|" the bits and assign the value to ErrorLevel. If either of the bits
// on any side of this operation are set the bit gets set in ErrorLevel. So
// OR'ing the bits basically just turns them on. This operation sets the
// bits in ErrorLevel according to the chart above. Your value should be the sum
// of the bit vars that have been turned on. This example is deceptive
// because I am only turning on one bit per value. To see how this really
// works, have several bits turned on for each value and then when you sum
// the numbers up that you used to set the bits, the value you get will be
// very different from the actual value. I am not doing a good job of explaining
// this, so play with the bits a bit and you'll see it right awar.
var ErrorLevel = new Number( LOCAL | PARAM | COUNT );
alert( "ErrorLevel( LOCAL | PARAM | COUNT ): " + ErrorLevel );

// Scratch vars.
var bitCompareResult = new Number(0);
var showMe = new Boolean(false);

var iAlertBit = new Number(PARAM);

// Now AND ErrorLevel with one of the known values and look at the
// return.
bitCompareResult = ( ErrorLevel & iAlertBit );
alert( "bitCompareResult: " + bitCompareResult + "\n" + "iAlertBit: " + iAlertBit );

// if the result of the AND equals the test value, then that bit was set.
showMe = ((bitCompareResult == iAlertBit) ? true : false );

mikemalter
08-27-2004, 06:04 PM
Alex,

From what I am seeing, var i = 1 is not exactally equivalent to var i = new Number(1);

From a practical standpoint of values, they are equivelant, but in terms of objects they are different.

On a project I am working on we have run into a very subtle problem involving this difference. That is on our web pages we have a method that returns a boolean to let us know if an error message exists:

if( ErrorMsg() )
{
do something.
}

Now, in the code I am working on are the classes that produce those error messages. In the code for ErrorMsg(), originally, we had a var that was set to indicate wether or not there were any error messages. It was instianted as var i = false, and then assigned in the method.

When I changed the way it was being instantiated to var x = new Boolean(); it broke the pages. We had to do an explicit test for true or false:

if( ErrorMsg() == true )
{
do something.
}

So, there is a difference. Also, I am no expert in javascript, so I don't have an explination for this. Just the experience.

kansel
08-27-2004, 07:36 PM
That's neat, but I was actually looking for a demo of your specific application, the FormCheck object and how you use it to show/not show alerts.

Also is this right? Playing around with this I get the following result:
var iAlertBit = new Number(NONE);
// showMe == true

var iAlertBit = new Number(ALL);
// showMe == false

I only changed the value of iAlertBit and added an alert to show the final value of showMe.

It seems to me you would want the ALL bit to always be true and the NONE bit to always be false.

I think this behavior is unexpected and happens because of the following code:var NONE = new Number(0); // 00000000
var ALL = new Number(1); // 00000001
var INFO = new Number(2); // 00000010
var LOCAL = new Number(4); // 00000100
var PARAM = new Number(8); // 00001000
var COUNT = new Number(16); // 00010000
var EXTEND = new Number(32); // 00100000

var ErrorLevel = new Number( LOCAL | PARAM | COUNT ); // (4 & 8 & 16) = 28

var bitCompareResult = new Number(0);
var iAlertBit = new Number(NONE);

bitCompareResult = ( ErrorLevel & iAlertBit ); // 28 & 0 = 0

showMe = (bitCompareResult == iAlertBit); // 0 == 0 = true
In a way though, this could be useful. If you switch the values of ALL and NONE then you get the desired behavior. Please let me know if I'm way off base.