Sunday, December 9, 2007

Data transmission and rendering techniques implemented over a client-server system

I was writing some Javascript the other day that accepted a JSON structure assembled on the server and generated HTML client-side.

The whole process seemed like deja vu and I remembered that I had come up with such a technique back in 1999 while working for Webvan.  I called it "client-side ASP" and what it did, exactly, was to accept just the data formatted for use by Javascript as:

var data=[
  {"id":1234567,"d":"Purple Ketchup","p":2.89, "q":4,"i":"1234567sm.jpg"},
  {"id":1234527,"d":"Pink Ketchup","p":2.29, "q":2,"i":"1234527sm.jpg"}
  ];

etc.  That format is now commonly called JSON, I think.  I am not sure what the exact timeline is/was when that term was coined but that is the exact format I used back in 1999 to transmit compressed data over the internet to client-side Javascript that then parsed (or rather eval'ed) the data and then used the data to generate the repetitive HTML required to display it. 

Recall that Webvan was like Amazon or even eBay in that it had many products that would be displayed under a particular category of food, so the HTML (in those days TABLEs) was of a known structure.  Using this technique (of just transmitted the data rather than the HTML and then generating the HTML on the client) reduced the average data required to display a page from, say 50KB to .5KB - or a hundredfold compression.  That's pretty significant, in my book.

If you are going to implement this technique, obviously, do not use multiple document.write's as that is generally considered "bad manners."  Rather, generate one bigString containing all of the HTML you like and then do one foo.innerHTML=bigString at the end.

This is basic stuff, IMHO, but I rarely, if ever see this technique used on the internet.

Here is a link to my patent:

Data-transmission-and-rendering-techniques-implemented-over-a-client-server-system


It's funny how patents go.  None of those other guys listed had anything at all to do with this technique.  they just happened to be in the same building, I guess.

Shannon Norrell


Never miss a thing. Make Yahoo your homepage.

Tuesday, October 23, 2007

Answers to Meebo Puzzlers

A company named Meebo was looking for a "Javascript Ninja".

Being the Javascript Ninja Master that I am (and a humble one , too), I was sought out by a headhunter to interview for the role. I checked them out and thought they were doing some cool DHTML things, so I agreed to interview with them.

Meebo gives a set of "puzzler" questions to candidates to test their Javascript acumen before speaking with them.

A couple of the questions were pretty good ones that made me go "hmmmmmm...?".

I believe I answered them as close to correctly as possible. The interview went well but it became apparent that Meebo was really interested in a Full-Time Employee (FTE) rather than a contractor, which is what I was looking for at the time (due to the whole circumnavigation thing).

Anyway, the puzzler questions, and my answers are presented here.

My apologies to Meebo if they have to come up with fresh ones due to this posting!

Shannon Norrell

Puzzlers


(1.) When does div.setAttribute(”###”) not equal div.###?

Having never found much use for setAttribute() - I always use direct assignment (div.foo=###) - I put together a "test harness" of sorts to test the behavior of setAttribute() so I could answer this question intelligently. Here is the code:

//////////////////////////////////////////////////////////////////////////////////
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
#sampleDiv, #sampleDiv2 { background-color: #FF0000; height: 40px; }
button { background-color: #CCCCCC;}
.comparison { float:left; border:solid 1px green; width:48%; top:0px; margin:5px;}
</style>
<script type="text/javascript">
function doSetup() {
var div = document.getElementById("sampleDiv");
var aStr = "sampleDiv<br/>DIV.Property= example DIV <br/>";
div.innerHTML = aStr;
div.arbitraryProperty="Hello";
div.arbitraryFunction= function() { alert('This is a test'); }
div.onclick = function() { alert('sampleDiv onClick'); }
div.style.backgroundColor='#00FF00';

var div2 = document.getElementById("sampleDiv2");
var aStr = "sampleDiv2<br/>DIV.SetAttribute() example DIV <br/>";
div2.innerHTML = aStr;

if ( navigator.userAgent.toLowerCase().indexOf("firefox") != -1 ) {
div2.createAttribute('arbitraryProperty');
div2.createAttribute('arbitraryFunction');
div2.createAttribute('onclick');
div2.style.createAttribute('backgroundColor');
}
div2.setAttribute('arbitraryProperty',"Hello");
div2.setAttribute('arbitraryFunction', function() { alert('This is a test'); });
div2.setAttribute('onclick', function() { alert('sampleDiv2 onClick'); });
div2.style.setAttribute('backgroundColor','#00FF00');
}

function doEnumeration( anHTMLElement, anOutputContainer ) {
var div = document.getElementById( anHTMLElement );
var aStr = "Enumerated Properties of " + anHTMLElement + "<br/>";
for (property in div) {
aStr += anHTMLElement + '.' + property + ' = '+ div[property] + '<br/>';
}
document.getElementById( anOutputContainer ).innerHTML = aStr;

}

function showDiv2Stuff() {
var div = document.getElementById('sampleDiv2');
alert(div.arbitraryProperty);
}
</script>
</head>
<body onload="doSetup()">
<div class="comparison">
<button onclick="doEnumeration('sampleDiv', 'valuesProperty')">Click to Enumerate</button>
<div id="sampleDiv"></div>
<div id="valuesProperty">Property Values</div>
</div>
<div class="comparison">
<button onclick="doEnumeration('sampleDiv2', 'valuesSetAttribute')">Click to Enumerate</button>
<div id="sampleDiv2"></div>
<div id="valuesSetAttribute">Property Values</div>
</div>
<button onclick="showDiv2Stuff()">
show sampleDiv2 stuff</div>
</body>
///////////////////////////////////////////////////////////////////////////////////////////////

I tested in IE7 and in Firefox 2 and my findings were that using setAttribute() does not work at all as expected in Firefox (even after adding conditional code to use createAttribute() before calling setAttribute() for FF).

So the short answer for this question would be:
div.setAttribute(”###”) does not equal div.### when running under Firefox
It is also interesting to note that arbitrary property assignments appear at the top of the DOM stack for Firefox and at the bottom in IE. Not sure what the implication of this is, as the assignment values resolve identically for either browser.


(2.) What’s the difference between these two statements:

a. var x = 3;
b. x = 3;

a. has local scope, b. has global scope


(3.) What’s the difference between:

a. !!(obj1 && obj2)
b. (obj1 && obj2)


a. will always evaluate to true (why you would have this line of code I can't imagine)


(4.) Write a one-line piece of JavaScript code that concatenates all strings passed into a function:
function concatenate(/*any number of strings*/) {



var string = ""; for (var i=0; i < arguments.length; i++) { string+=arguments[i]; };return string;}

Note - if there were a way to cast the Arguments object into a String object, one could then use .join("")



(5.) What do these two examples have in common?
Example 1:
var obj = document.getElementById(’adiv’);
document.getElementById(’adiv’).ptr = obj;

Example 2:

function assignClick() {
var el = document.createElement(’div’);

function handleClick() {
el.innerHTML = ‘clicked!’;
}

el.attachEvent(”onclick”, handleClick);
}


They both append values to the DOM
They both have potential for leaking memory
They both create closures
(actually Example 2 is a true closure - if it were this.innerHTML = 'clicked' it would be better)
(Example 1 might be called a quasi closure, although I have never seen it named as such)


Shannon Norrell 08/17/2007





Friday, September 28, 2007

Setting up Vista IIS7 to Serve PHP Pages

Having written part of Vista (the weather gadget), you would think that I knew everything there was to know about the operating system. Of course the answer to that is "no way!"

Yesterday I had a bit of fun (interspersed with periodic cursing and much gnashing of teeth) trying to get my Vista box to serve up PHP pages. I thought I would share the experience and what I learned in the process.

Enable Internet Information Server IIS7



Enable ISAPI Extensions


Download PHP
Go to www.php.net/downloads.php to get the latest binary release. Choose the .ZIP version as we won't be running an installer.


Extract the PHP .zip file to c:\php


Copy php.ini-dist to c:\windows\php.ini
Start / Run / cmd (you can also use the little Windows Key + R, then cmd)

From the command line, do the following:

cd \php
copy php.ini-dist c:\windows\php.ini

If you want to enable MySQL, Edit c:\windows\php.ini
(Otherwise skip to this step)

Since you're still in a command window, just type:

notepad c:\windows\php.ini



In notepad, Ctrl+F to find the following line:
;extension=php_mysql.dll

remove the semi-colon (to uncomment it)

Now, Ctrl+F to find the following line:
extension_dir = "./"

change it to
extension_dir = "c:\php\ext"

and save the file.

Copy php_mysql.dll to c:\windows\system32
Since you still have an open command window, go there and type:

cd \php\ext
copy php_mysql.dll c:\windows\system32

I used a new window for the sake of screenshot clarity.


Configure IIS7

Launch InetMgr (Start / Run / Inetmgr)


Click on Handler Mappings

Click on "Add Module Mapping"


Click on "Add Script Map"

Add a Script Map
Request path: *.php
Executable: C:\PHP\php5isapi.dll
Name: PHP


Click Yes on the warning dialog that follows



At this point, actualy, you are done getting PHP to work with IIS7. However, if you are also interested in getting mySql working, there are a few more steps.

Before we download and install mySql, we need to open a port.

Modify the Windows Vista Firewall

Start / Control Panel / Windows Firewall (using classic view)

(HINT) A quick way to get to the Firewall is to use the quick search box above the Vista icon as follows:



Open port 3306 for mySql
Choose "Change Settings"

Click the Exceptions tab
Click the "Add port..." button

Create the following entry

Name: mySql
Port number: 3306
Protocol: TCP


Download the MySQL Installer
I used MySQL 5.1 located at: http://dev.mysql.com/downloads/mysql/5.1.html#win32

Run the Installer

You should be good to go!

Create a test File
To test that all of this effort has been worth the, well, effort, create the following file:

notepad c:\inetpub\wwwroot\phpTest.php

And put the following contents in it:

<?
phpinfo();
?>



Now, test using the following hyperlink:
http://localhost/phpTest.php


Bob's your uncle!

Shannon Norrell

Thursday, September 27, 2007

3jam

Doing some consulting for a company called 3jam, which does "Reply to All" SMS text messaging.
 
Here are some of the press received this week.
 
shannon norrell
 
Virgin Mobile Lights Up Text 2.0 Powered by 3Jam
http://us.blognation.com/2007/09/20/virgin-mobile-lights-up-text-20-powered-by-3jam/ 
Blognation
USA
 
Virgin Mobile Offers Reply-All SMS through 3jam
http://mashable.com/2007/09/20/virgin-mobile-3jam/
Mashable
 
Virgin Mobile Launches New SMS Service
http://www.wirelessweek.com/article.aspx?id=153464
Wireless Week
 


Tonight's top picks. What will you watch tonight? Preview the hottest shows on Yahoo! TV.

Tuesday, September 25, 2007

Answer to Cross-Domain Scripting for XMLHttpRequest?

Came across this method of avoiding the cross-domain scripting limitation preventing XMLHttpRequest from requesting data from domains outside of your own.
 
it involves adding a dynamic <SCRIPT> tag.
 
Seems pretty slick, although I have not tried it as of yet:
 


Moody friends. Drama queens. Your life? Nope! - their life, your story.
Play Sims Stories at Yahoo! Games.

Interesting Satellite DSL Provider

In doing some consulting for a Telecom-related startup, I ran across this satellite phone service provider that also has DSL. 
 
 
Too bad they don't cover the Carribean!
 
Shannon Norrell
 


Don't let your dream ride pass you by. Make it a reality with Yahoo! Autos.

Thursday, September 20, 2007

Meebo Widget

I will post the answers to Meebo's (in)famous "puzzler" questions later in this blog. Let me know if you're ~puzzling over them...


Want to talk with visitors on your page? Go to http://www.meebome.com/ and get your widget!


Source code


<embed src="http://widget.meebo.com/mm.swf?IwyOglgOmB" type="application/x-shockwave-flash" wmode="transparent" width="160" height="250"></embed>





Friday, August 24, 2007

Cayman Island Software Development Ninja

I have been offered a job in the Cayman Islands.
 
The name of the company is "Cayman Free Press" and they publish the Cayman Compass (daily newspaper) and several other periodic publications.  Three of the five magazines on the coffee table in my room were published by them.
 
I met with several people yesterday, got a tour of the printing presses and of their surprisingly sophisticated editorial facilities - everyone's got flat panels, running on the latest hardware.  They have the capability of creating content in Photoshop, Illustrator, Pagemaker or whatever and of creating the metal plates ultimately used for four-color printing.  Pretty interesting, somewhat analog stuff.
 
This all dovetails nicely in with my plans for circumnavigating the world - it could be considered the first stop of the trip.
 
As I get back to work there will, of course, be more postings to this blog as I again turn my attentions to technology.  I am actually kind of excited!
 
Shannon Norrell


Be a better Heartthrob. Get better relationship answers from someone who knows.
Yahoo! Answers - Check it out.

Monday, July 2, 2007

Winds Aloft algorithm for computing True Airspeed

This algorithm should produce an adjusted airspeed taking into account
Winds Aloft speed and angle. It is somewhat "pseudo-code" due to
limitations with capitalization on my Sidekick as I type this on an
airplane. Total time to derive and code 1hr, 15minutes.

-shannon norrell
////////////////////////////////////////////////////
Tas=400; //True airspeed
Was=50; //Winds aloft speed
Waa=10; //Winds aloft angle (plug various vals here to test)
Adj=0; //Covers cases of Waa==90 and Waa=270

Switch(true) {
Case((Waa==0) || (Waa==360)):
Adj=-Was;
Break;
Case(Waa==180):
Adj=+Was;
Break;
Case((Waa>0)&&(Waa<90)):
Adj=-((90-Waa))\90)*Was;
Break;
Case((Waa>90)&&(Waa<180)):
Adj=((Waa-90)\90)*Was;
Break;
Case((Waa>180)&&(Waa<270)):
Adj=(1-((Waa-180)/90))*Was;
Break;
Case((Waa>270)&&(Waa<360)):
Adj=-((Waa-270)\90)*Was;
Break;
}
Aas=Tas+Adj; //Adjusted airspeed
--webdood

Thursday, June 28, 2007

ASP.NET 2.0 and red box appearing

Ran into an issue today with a red box appearing inside of an <input type="image"> tag (which I rarely, if ever, use).  Anyway, I had it set up to use a css class that had a background-image declaration.  Apparently, there is an issue/bug with the <input type=image> tag in that you have to specify a "src=" value in the HTML to get an image to display.
 
Therefore, this will display a broken image link and does not work:
 
css declaration:
.imagelink {
  background-image: url(foo.gif);
  width:20px;
  height:20px;
}
 
html:
<input type=image class=imagelink/>
 
This does work:
<input type=image src=foo.gif />
shannon norrell


Now that's room service! Choose from over 150,000 hotels
in 45,000 destinations on Yahoo! Travel
to find your fit.

Wednesday, June 27, 2007

How to mount an ISO disk image using Windows Vista

Use MagicDisc to mount an iso image on Vista http://www.magiciso.com/tutorials/miso-magicdisc-overview.htm.  Don't worry about the "Known Compatability" warning; the thing works.
 
shannon norrell

Thursday, June 7, 2007

Javascript Example code for creating "Private" member variables using closures and JSON notation:

Title: Javascript Example code for creating Objects with Public and Private “member” variables, using closures and JSON notation:

 

Wrote this bit of cool code today to rotate through a series of third party quotes .  Figured I should make a post of this most excellent function structure.

 

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////

// SETTINGS - change these values to alter the behavior of how,what and when QuoteSwapper displays quotes

// --------

var g_FirstQuoteToDisplay = 4;          // Sets what quote number is first displayed when the page loads

var g_QuoteRotationEnabled = true;      // Setting this to false will prevent QuoteSwapper from rotating and will; only display the first quote specified

var g_SecondsToDisplayEachQuote = 3;    // How many seconds each quote is displayed before rotating to the next

var g_Quotes = [

  { // Quote #1                

    quoteText: "thanks to thinkingVOICE's Call Tracking Platform we can demonstrate added value to our participating merchants every day",

    quoteSource: "Kendall Fargo CEO",

    quoteLogo: "logo_stepupCommerce.gif",

    quoteLogoX: 101,

    quoteLogoY: 53,

    quoteLogoAlt: "StepUp Logo (an Intuit Company)",

    quoteURL: "http://www.stepup.com/",

    quoteTagLine: "an Intuit Company",

    specialFrameAction : null  

  },

  { // Quote #2

   quoteText: "ThinkingVoice enables Commercial Direct to qualify leads to our sales reps and close the deal quickly. By offering timeliness and convenience to our prospects, thinkingVoice has paid off big time",

   quoteSource: "Jonathan Mirabito",

   quoteLogo: "logo_commercialdirect.jpg",

   quoteLogoX: 160,

   quoteLogoY: 52,

   quoteLogoAlt: "Commercial Direct Loans Logo",

   quoteURL: "http://www.commercialdirectloans.com/index.jsp?pageId=home",

   quoteTagLine: "",  

   specialFrameAction : null  

  },

  { // Quote #3

   quoteText: "With a simple click, potential customers connect to a live sales representative, get immediate answers to their questions and can register for a WebEx Live! service with confidence",

   quoteSource: "Alfred Pong",

   quoteLogo: "logo_webex.gif",

   quoteLogoX: 160,

   quoteLogoY: 60,

   quoteLogoAlt: "WebEx Logo",

   quoteURL: "http://www.webex.com/",

   quoteTagLine: "",

   specialFrameAction : null     

  },

  { // Quote #4

   quoteText: "adding thinkingVOICE to my email signature just makes good business sense.  And it works so easy with PLAXO.",

   quoteSource: "Mark Goldstein",

   quoteLogo: "logo_loyaltylab.gif",

   quoteLogoX: 160,

   quoteLogoY: 42,

   quoteLogoAlt: "LoyaltyLab, a division of InStoreCard",

   quoteURL: "http://www.instorecard.com/",

   quoteTagLine: ""  

  },

  { // Quote #5  

   quoteText: '<span style="font-weight:bolder;color:brown;font-family:arial mt rounded; font-size:1em;line-height:.9em;text-align:center;vertical-align:baseline;">Breaking News<br/></span><span style="line-height:1em; font-size:10px; font-family:lucida sans unicode, tahoma;margin:0;">ThinkingVoice announces deals with <a href="http://www.clearchanneloutdoor.com/" target="top" class="announcement_link">ClearChannel Outdoor</a>, <a href="http://www.servicemagic.com/" target="_top" class="announcement_link">Service Magic</a></span>',

   quoteSource: '',

   quoteLogoX: 194,

   quoteLogoY: 290,

   quoteLogo: "images/CLearChannelBillboard.gif",

   quoteLogoAlt: "ThinkingVoice announces deals with ClearChannel outdoor and Service Magic",

   quoteURL: "http://sev.prnewswire.com/advertising/20070605/AQTU18605062007-1.html",

   quoteTagLine: "source: prnewswire",

   specialFrameAction : null  

  }

]

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////

// QUOTESWAPPER - this Object cycles through and displays an array of quotes, images and hyperlinks.

// ============   DO NOT MODIFY CODE IN THIS SECTION  

var QuoteSwapper = function() {

  var self = this;

  var _swapperThread = null;

  var _bRotationEnabled = g_QuoteRotationEnabled;

  var _currentItem = g_FirstQuoteToDisplay;

 

  function public() {}

 

  public.displayQuote = function( itemToDisplay ) {

    itemToDisplay = (("" + itemToDisplay!="undefined") ? itemToDisplay : g_FirstQuoteToDisplay ) % g_Quotes.length;  // stay within limits of array

    document.getElementById('quoteText').innerHTML = (g_Quotes[ itemToDisplay ].quoteText.length > 0) ? g_Quotes[ itemToDisplay ].quoteText : "";

    document.getElementById('quoteSource').innerText = (g_Quotes[ itemToDisplay ].quoteSource.length > 0) ? " - " + g_Quotes[ itemToDisplay ].quoteSource : "";

    document.getElementById('quoteLogo').src = g_Quotes[ itemToDisplay ].quoteLogo;

    document.getElementById('quoteLogo').width = g_Quotes[ itemToDisplay ].quoteLogoX;

    document.getElementById('quoteLogo').height = g_Quotes[ itemToDisplay ].quoteLogoY;

    document.getElementById('quoteLogo').alt = g_Quotes[ itemToDisplay ].quoteLogoAlt;

    document.getElementById('quoteURL').href = g_Quotes[ itemToDisplay ].quoteURL;

    document.getElementById('quoteTagLine').innerHtml = g_Quotes[ itemToDisplay ].quoteTagLine;

    _currentItem = itemToDisplay;

  }

 

  public.start = function() {

    clearInterval( _swapperThread );

    if ( _bRotationEnabled ) {

      _swapperThread = setInterval("QuoteSwapper.next()", g_SecondsToDisplayEachQuote * 1000);   

    }

    this.displayQuote( g_FirstQuoteToDisplay );   

  }

 

  public.next = function() {

    this.displayQuote( _currentItem + 1 )

  }

 

  public.stop = function() {   

    clearInterval( _swapperThread );

  }

 

  return public

}();

Sunday, June 3, 2007

Windows XP File Association Fixes - .reg files for

My Explorer Window kept on opening up to a search dialog whenever I clicked on certain types of file folder icons. I would have to right-click and choose "Explore" every time I wanted to open a folder. As annoying as this was, I continued to live with it for a number of days.


Here is a great resource for .reg files that help you to reset file associations for Windows XP.

http://www.dougknox.com/xp/file_assoc.htm


I used the one for "Directory" and all was corrected!

-shannon norrell

--
_______________________________________________
Surf the Web in a faster, safer and easier way:
Download Opera 9 at http://www.opera.com

Powered by Outblaze

Saturday, June 2, 2007

My thoughts on interfacing with Amazon.com through mobile devices



theWebDood <thewebdood@yahoo.com> wrote:
Date: Sat, 2 Jun 2007 19:23:37 -0700 (PDT)
From: theWebDood <thewebdood@yahoo.com>
Subject: RE:
To: "Amacker, Matthew" <mamacker@amazon.com>

No worries mate.
 
Hey, I was thinking about mobile.  
 
I think that to have the broadest coverage (pun intended), there should be two basic modalities developed for interfacing with Amazon.com through a mobile phone.
 
The first would be, as I think you mentioned, a lightweight version of Amazon.com designed and coded specifically for mobile phone web browsers.  It would be sleak and slim and have only the minimum features required for customers to easily check price and availability on a specific book, to do simple searches, and to be able to select a book and add it to their wishlist or complete checkout right there in the mobile web page.  Call this one "mobile.amazon.com"
 
The second, which you may not have considered, is an SMS-based interface that lets users quickly check prices, do simple searches, add a book to their cart and to (possibly) check out by sending a text message to 26296 (AMAZN).  
 
For example:
 
p lord fouls bane   - query for the price of "Lord Fouls Bane"
 
When query results come back they are identified as 1st, 2nd, 3rd, etc.
 
example:
"Lord Foul's Bane", by Stephen R. Donaldson, 1978.  Choices are:
  1st) Hardback, NEW, $42.95
  2nd) Paperback, used   $8.25
  3rd) Hardback, used $12.95
 
Using that information, a user could potentially reply with:
 
buy 2nd item
 
An SMS dialog may continue where we ask for their account number, etc. 
 
There are limitations, to be sure, but the experience is such that a user can find and buy a book through Amazon.com entirely through text messaging using his or her cell phone.  Call this variant "Amazon SMS"
 
- - -
Anyway, that's a brain dump of my thought stream on mobile at the moment for Amazon.
 
shannon norrell
 
 
 
Only a We support only a very few "verbs address.
 
maybe to direct that an email be sent  by sending a text message s and availability and, perhaps, to do a more aprices on books SMS interface
 

"Amacker, Matthew" <mamacker@amazon.com> wrote:
Hi Shannon,
 
    Bennett went on vacation.  So you might have sent him a note just after he headed out - so it was never passed on to the secondary.  We are very interested in getting you in here to talk to some more folks.
 
    Bennett gets back on Monday which is probably when he will respond to your note and we can get things rolling again.
 
Sorry for the delays.
 
-Matt


From: theWebDood [mailto:thewebdood@yahoo.com]
Sent: Thursday, May 31, 2007 12:00 PM
To: Amacker, Matthew
Subject: RE:

Matt:
 
I agree.  I think that we would along famously and have a lot of fun putting out some cool tech together.
 
I got an email from Bennett last week regarding scheduling an interview but things seem to have stalled or otherwise fallen into a black hole.
 
Do you know what is up?
 
-shannon
650-200-5044

"Amacker, Matthew" <mamacker@amazon.com> wrote:
Thanks for the links!
 
You should have already heard from Bennett so I hope to see you in the offices sometime soon!
 
Please let me know if you need more information about this group or the company - I think we could have a lot of fun.
 
I hope your allergies leave you alone for a bit.
 
Sincerely,
  Matt


From: theWebDood [mailto:thewebdood@yahoo.com]
Sent: Tuesday, May 22, 2007 3:24 PM
To: Amacker, Matthew
Subject: RE:

Matt:
 
Thanks for the call.  You seem like a cool guy.
 
Sorry my brain is cloudy with the allergy meds.  That site I was trying to remember is called "AListApart.com."  As we get older and more experienced as web devs, it becomes harder to find sites that actually teach us or talk about topics we are not already familiar with.  A ranomd example I just pulled up is: http://www.alistapart.com/articles/crossbrowserscripting
 
Another site I frequent is jibbering.com.  You have probably already read his famous article on closures
 
Anyhow, I think I am going home to bed. 
My head feels like it has been stuffed with cotton balls.
 
TTYL
 
shannon


"Amacker, Matthew" <mamacker@amazon.com> wrote:
Sounds good.  I'll give you a call at 2PM at 650 200 5044.
 
If for some reason I miss you please feel free to give me a call back at: 530 400 7823
 
Thanks,
  Matt


From: theWebDood [mailto:thewebdood@yahoo.com]
Sent: Monday, May 21, 2007 2:59 PM
To: Amacker, Matthew
Subject: Re:

Sure, call me sometime tomorrow.  You should definitely put me on the OSX Widgets and Vista Gadgets.  Not sure if there are many people out there who have developed both for major production distribution.  You should see some of the ones I did that weren't released.
 
-shannon
 
ps - great job with the flyouts on the A9 search box on Amazon site.  I see you did not use scrollbars and instead used Previous and Next links at the bottom.  I feel your pain.  Scrollbars are incredibly difficult to produce uysing DHTML alone; particularly cross-browser versions.  I think I may have tackled this issue, but only after much agony and bloodshed.  the reality is that < > is better so you don't have to pull down as much data for a search (since they will probably click on something from the first page anyway), it's just that UI is kind of clunky.

"Amacker, Matthew" <mamacker@amazon.com> wrote:
Hello Shannon,
        You have a great resume.  I'd like to talk to you about it and give you a better picture of the position I'm trying to fill.
        I'm available anytime tomorrow for a phone call and there are spots available on Wednesday.  Is: 650 200 5044 the best number?
        I'm glad you liked my posting.  I hope this finds you well.
Sincerely,
  Matt @ a9.com
P.S.  To give you an early taste.  My group's tasks:
            A9 Websearch on Amazon: Look at the upper right hand corner of Amazon.com for the A9 search box.
            A9.com: All UI and backend support for the A9.com site is handled by this group.
            Clickriver: All text ads on Amazon are this group.
            Mobile: Client that runs on mobile devices - not yet started.
            Desktops: OSX and Vista widgets that are soon to be released.
            Greasemonkey and bookmarklets: coming soon that will expand the reach of all A9.com properties.


Take the Internet to Go: Yahoo!Go puts the Internet in your pocket: mail, news, photos & more.


You snooze, you lose. Get messages ASAP with AutoCheck
in the all-new Yahoo! Mail Beta.


Get the free Yahoo! toolbar and rest assured with the added security of spyware protection.


Got a little couch potato?
Check out fun summer activities for kids.


Get the Yahoo! toolbar and be alerted to new email wherever you're surfing.

Friday, June 1, 2007

getSimilarityScore() - uses Levenshtein Distance between two strings

I came up with this while working for Microsoft developing the Vista
Weather gadget. It was to be used to handle mis-spelings and to
otherwise find strings that were as close as possible to what had been
typed in.

This is useful code that is good to have around. It is a Perfect
Example of what I am trying to accomplish with this blog - - an archive
of Shannon Norrell cool webdood code. I write so much of it that lots
of little gems like this fall through the cracks. Half the time I don't
even remember that I wrote something, let alone recall how it was
written.

Enjoy.

-shannon norrell

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>getSimilarityScore</title>
<script language="javascript" type="text/javascript">
String.prototype.getSimilarityScore = function(c){
// Uses Levenshtein Distance between two strings algorithm
var s, that=c, l = (s = this.split("")).length, t = (c =
c.split("")).length, i, j, m, n, dis, maxLen, retVal=.95;
if(!(l || t)) {
dis = Math.max(l, t);
} else {
for(var a = [], i = l + 1; i; a[--i] = [i]);
for(i = t + 1; a[0][--i] = i;);
for(i = -1, m = s.length; ++i < m;)
for(j = -1, n = c.length; ++j < n;)
a[(i *= 1) + 1][(j *= 1) + 1] = Math.min(a[i][j + 1] +
1, a[i + 1][j] + 1, a[i][j] + (s[i] != c[j]));
dis = a[l][t];
}
maxLen = Math.max( this.length, that.length );
if (maxLen > 0) {
retVal = (1 - dis/maxLen);
}
return retVal;
};

var foo="Newcastle,wa";
alert( foo.getSimilarityScore('castel') );

</script>
</head>
<body>

</body>
</html>

My Conclusion on Best Practice HTML for eMail Marketing Campaigns

I have been asked to come up with a new twist on the banner ad - one with a real HTML text input box that a user can type his/her phone number into and a button that, once clicked, will call a SIP softswitch that will in turn ring both the advertiser's number and the customer's.

This was all well and good until I was asked if I could provide the same functionality as the banner ad, only as something that can be emailed.

Having vehemently avoided all advertising-related WebDev work for the past 12+ years, I assumed this would be an easy task and we could just send out the same HTML+CSS+Javascript that I had already coded up. Well, I was wrong.

Here are my conclusions as to the best practices for writing HTML for email campaings, such that it has the largest reach and covers the largest number of users' email clients:

  1. Create your own container DIV into which all content for your email exists. Don't count on the BODY tag existing or having any particular settings.

  2. Avoid designs that require positioning (ie no position:absolute; top:20px; left:20px; etc)

  3. Do not use background images - neither CSS (background-image) or HTML-based (bgImage).

  4. Use IMAGE tags, however, not to convey anything important

  5. Use ALT tags on every image.

  6. Always add HEIGHT and WIDTH to every image

  7. Design for images being turned off. Over 50% of today's email clientys have images turned off.

  8. Add a tag at the top of your email. "Having trouble reading this email? click here.

  9. Use in-line styles. Do not make use of the <style> tag.

  10. Message window should be 570px or less wide

  11. Design for the preview pane - make sure most of the message gets acrossin the top 300px of the email. This is the approximate height of the horizontal preview pane in most email clients.



I will try to post what I end up with as the final markup when I get finished with it.



- Shannon Norrell

Too much information? Some brand-new Data Visualization techniques that might help us sift through it

I stumbled across an interesting new Data Visualization technique that may prove particularly useful as we all must discover new ways of consuming, the vast quantities of data that swirl around us.

Though not particularly useful for my current research, (a genetic algorithm that learns keyword and keyword phrase relevancy to information requests over time), I felt that this was just too useful to forget about as I powered ahead..

sparklines
sparklines are tiny, word-like diagrams or graphs of data that are so small as to be meaningfully used as a sentence within a paragraph of text.

I didn't get it at first either, but what caught my eye was a small section of bar graphs representing the current google adsense activity:


This is powerful in that it conveys a lot of information about data in a small space and can also be realtime and dynamic. I could see diagrams of this sort as cells in a spreadsheet or as simply another column of data in a report.


Here is another Data Visualization technique that, frankly, I don't really get at the moment. instinct tells me I should make a note of it as well in light of the above-mentioned:

elastic lists
elastic lists enhance "facet browsing" as proposed by The Flamenco Search Interface Project that visualize the relative proportions (weights) of metadata values by size and that visualize the "unusualness" of a metadata weight by brightness as a user "drills down" though a large dataset, mining for answers or creating ad-hoc metadata report filters

Here is an interesting interactive demonstration of Elastic Lists


-shannon norrell

Thursday, May 31, 2007

Augmented Video Overlay

I came up with the idea of having a transparent overlay, a dynamic image
map, if you will, that could be displayed over the top of video
playback, synchronised at the frame level, several years ago.

Think of the overlay track as a clear tape that has been placed over a
spool of existing film. For every frame of film, you have a transparent
overlay frame.

. . . More on this in a later posting . . .

Shannon Norrell
(C) 05/31/2007
--webdood

Tuesday, May 29, 2007

How to set up Windows Explorer to "Open to a Command Prompt" without installing Power Toys or manually editing the registry

How to set up “Open to Command Prompt” without installing Power Toys or manually editing the registry (which is what I usually do):

1.      In explorer, open Tools, Folder Options.

2.      Select the File Types tab.

3.      For Windows XP: Go to NONE / Folder.

4.      For Windows 2000: Press n to scroll to the N/A section.

5.      For Windows NT/98/95: Press f to scroll to the Folders section.

6.      Select the entry labeled Folder

7.      For Windows 2000/XP: Press Advanced button.

8.      For Windows NT/98/95: Press Edit button.

9.      Select New

10.  In the action block type "Command Prompt" without the quotes.

11.  In the app block type "cmd.exe" without the quotes.

12.  Save and exit Folder Options.

 

It’s somehow comforting to find that there are things that I didn’t already know about configuring Microsoft Windows.

 

I came across this one on Petri