29 February 2008

Cheating with Web.SiteMap - Two links in one sitemap

A couple of problems I recently ran into is when a client said she wanted two links in the Navigation that point to the same page. Essentially what they wanted is when you click on a MAIN navigation link, it takes you to a default SubMenu link, so when you click on "Products" It takes you to the "All Products" Submenu... highlighting them both.

This was for ALL the Main menu items.

In addition she wanted some pages to be in two places, so e-news would be under products, but a link would exist in the "about us" main menu too.

This problem was solved with some creative naming in web.sitemap and a few other tricks.

Say you have a typical sitemap like so:


<sitemap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
<sitemapnode url="~/default.aspx" title="HiddenRoot">


<sitemapnode url="~/contact/"></sitemapnode>
<sitemapnode url="~/contact/default.aspx">

<sitemapnode url="~/products/enews/"></sitemapnode></span>
</sitemapnode>

<sitemapnode url="~/products/list/" title="Our Products"></sitemapnode>
<sitemapnode url="~/products/list/default.aspx">
<sitemapnode url="~/products/where/default.aspx">
<sitemapnode url="~/products/item/default.aspx">
<sitemapnode url="~/products/enews/default.aspx">
</sitemapnode>

<sitemapnode>url="~/about/"></sitemapnode>
<sitemapnode url="~/about/default.aspx">
<sitemapnode url="~/about/qa/default.aspx">
<sitemapnode url="~/about/research/default.aspx">
</sitemapnode>

</sitemapnode>
</sitemap>


You'll notice above (in bold) that the parent nodes omit "default.aspx" IIS will take the default page when it navigates to these directories and you will actually end up at the Child Node with that actual page.

When I return Sitemap.CurrentNode() it returns the child... even though I clicked the parent. This allows me to highlight both with a CssClass dynamically (I'm using CSS friendly adapters from CodePlex for the Rendering of a MEnu Control)

Clicking : ~/about/
will take you to : ~/about/default.aspx

You'll notice that I do the same in the contact menu. The link reads /products/enews/
but the actual link in the products menu is /products/enews/default.aspx

In addition
... I strip "default.aspx" off the end of ANY link in the main menu just to keep the url clean... with this code which also makes sure the Parent Node is selected :

protected void mnuNav_MenuItemDataBound(object sender, MenuEventArgs e) {

//strips default.aspx (not necessary... just for clean urls.

e.Item.NavigateUrl = e.Item.NavigateUrl.Replace("default.aspx", "");

if (SiteMap.CurrentNode != null && SiteMap.CurrentNode != SiteMap.RootNode) {
if (e.Item.Text == SiteMap.CurrentNode.ParentNode.Title)
e.Item.Selected = true;
}
}

27 February 2008

Enabling Script Debugging in IE7 and JINQ

I found a really cool new screen capture program called "jinq" and to demonstrate it, I will now post something I just made... How to enable Script Debugging for Visual Studio 2008 in IE7. (not that I use IE7 much anyway)

20 December 2007

Calculating a Checkdigit using Math.Ceiling

Calculating Checkdigits


So, something I've been wanting to do is calculate a checkdigit for a UPC-A code in Code. In case you didn't know, the check digit is the final digit on a Standard 12 digits or 14 digit UPC and can be calculated from the preceding digits



The reasoning behind this is if a barcode reader scans a barcode wrong it will internally do a calculation and see if the result matches the checkdigit. If it matches all is good. The UPC is made up of a manufacturer code and a product code. So, for example: 0-12345-67890-5 :


  • 0-12345 marks the manufacturer

  • 67890 identifies the product

  • 5 is the check digit

Anyway, we want to enable people to enter 67890 as a check-digit, and then have the program automatically calculate the UPC to be entered in to the database.


To Calculate the Checkdigit “5” is fairly straight forward to do for human calculators (the brain) but presents some challenges for computers.

The calculation goes as follows,


  1. Add up all the odd position digits
  2. multiply that by 3
  3. add the even position digits
  4. Take the total and whatever you need to get to the nearest 10 is the checkdigit.
  5. To illustrate:
    1. 0-12345-67899-?
    2. (0 + 2 + 4 +6 + 8 + 9) * 3 = 87
    3. 87 + (1 + 3 + 5 + 7 + 9) = 112
    4. 112 + x = 120 (next multiple of 10)
    5. x = 8


Simple Right? It's basic addition and subtraction.


However, the computer doesn't know how to get 120 from.

However, essentially, what we want to do it go (10 - 2)

MODULUS to the rescue!!!



Modulus is basically an operator that lets you calculate the remainder. If you remember back in Grade school, before you learned fractions or decimals, 10 / 3 = 3 Remainder 1, 3R1

In C# the Modulus Operator is %

Well, If we take the total (112) and do (112 % 10) we end up with a remainder of 2... so All we need to do is this: 10 - (total % 10) = 8 DONE! Right?

But not so fast...



There is a problem. If we end up with a total which IS a multiple of 10, our remainder = 0 (110 % 10) = 0 Rem. And since 10 - 0 = 10, this won't work (the checkdigit should be 0, not 10)

So, just write an IF statement, right? If it's 10, set it to 0, if not, subtract from 10.

The if statement could be written like so:
int checkdigit = (total % 10 == 0)? 0 : 10 - (total % 10);

However, I prefer a purely mathematical approach if I can. The first approach we came up with used the Math.Ceiling function. What this function does is basically returns the next whole number. So, Math.Ceiling(11.2) would return 12.0. How can we use this?

Well, our total 112 / 10 actually = 11.2, If we take the Ceiling of that number, we end up with 12. and 12 x 10 = 120. And 120 - 112 = 8! This also works if we end up with a total that is a multiple of 10. Since Math.Ceiling(11.0) returns 11, 11 x 10 = 110. 110 - 110 = 0!

So, here's the code to do that:

int checkdigit = (int)Math.Ceiling(total / 10.0d) * 10 - total;
Where total = 112

  1. 112 / 10.0d = 11.2
  2. Ceiling of 11.2 = 12.0
  3. 12 * 10 = 120

  4. 120 - 112 = 8



  1. 110 / 10.0d = 11.0

  2. Ceiling of 11.0 = 11.0

  3. 11 * 10 = 110

  4. 110 - 110 = 0


It Works!

Note, Ceiling returns a decimal, but since we will always have a whole number, we can safely cast this as an int.



But yes... there is a 3rd way.... if you're satisfied with this method so far, that's fine. This was our first solution, and it's kind of cool. BUT after looking at the mod function again, we came up with another solution. It doesn't need any casting as int either, is shorter and perhaps faster, I'm not sure.... here's the formula:



int checkdigit = (10 – total % 10) % 10;

What's going on here? Well

  1. 112 % 10 = 2 (remainder)

  2. 10 - 2 = 8

  3. 8 % 10 = 8



  1. 110 % 10 = 0

  2. 10 - 0 = 10

  3. 10 % 10 = 0


Short, concise, easy to read, and I'd imagine... fast.



Here's the enture C# Code for your perusal:



public static int CheckDigit(string strUpc)
{
// strip all non-numeric characters
string upc = System.Text.RegularExpressions.Regex.Replace(strUpc, @"\D", string.Empty);
int total = 0;

//add the odd position digits
for (int x = 0; x < (upc.Length); x += 2) { total += Convert.ToInt32(upc[x].ToString()); } total = total * 3; //add the even position digits for (int x = 1; x < (upc.Length); x += 2) { total += Convert.ToInt32(upc[x].ToString()); } //calculate the checkdigit return (int)Math.Ceiling(total / 10.0d) * 10 - total; /************************ // could also be written: //AS A condensed IF STATEMENT return (total % 10 == 10) ? 0 : 10 - (total % 10); //That is... if total mod 10 = 10 return 0, else 10 - (total mod 10) //or... using MOD the MOD return (10 – total % 10) % 10 *************************/ }
Just stick this into your utility class or anywhere else in your application, and you're good to go.

16 August 2007

29 December 2006

Wii Safety Video

Beware... Wii owners... beware.

19 December 2006

Beware, the Sushi Police are coming.

I found this really well written article about how the Japanese Government, the ministry of Agriculture, is going to create a Japanese restaurant certification. Now this may not sound like a bad thing at all... except when you realize that this is a ministry that is certifying restaurants abroad.

I highly recommend the article, but here's the synopsis:

What this means is that a team of Japanese could come to Vancouver, and having gone into a restaurant where !gasp! BC Rolls, California Rolls and Dynamite Rolls are being served, they could decide that since these are not Japanese foods, that this restaurant is not an official Japan sanctioned restaurant. Of course, this is really only meant for Japanese nationals, who are travelling. I suppose they want to create a list of certified authentic Japanese food around the world that Japanese tourists around the world will feel comfortable going to.

I admit there are some bad sushi restaurants, but there are also some very good combinations that even many in Japan would like. I know my wife seems to like rolls with Cream Cheese in them... even though they're definitely NOT Japanese.

I think fusion foods can really bring out the best in a cuisine and if you want my advice, check out "Wild Rice" close to tinseltown downtown for some of the best fusion Chinese you'll ever have.

Sidenote: I wonder if the Japanese Ministry of Agriculture realize that tempura comes from Europe?

12 December 2006

Today's Comedy Test

Your mission... watch this video and comment on whether it is funny. If not funny, watch it again. If still not funny, go see doctor.

07 December 2006

Comic Life

Hehe... I made this comic with a cool program called Comic Life... by Plasq It's really cool. Seriously, i was done in less than minutes. You'll often find this kind of easy to use, quick to learn software for the mac. This was the first time using it and i actually did something cool in 5 minutes. I highly recommend THIS link.

Mentos and Coke? Again?

Well, apparently a couple of guys are doing some viral marketing for coke and Mentos. Pretty cool stuff. I hope these guys are getting paid for this work, it's some pretty creative stuff. Looks like a lot of fun too.