meyerweb.com

Skip to: site navigation/presentation
Skip to: Thoughts From Eric

Archive: July 2005

Security Checks

Wednesday morning, as I stood in line to buy a bagel from a street kiosk on the corner of 39th Street and Lexington Avenue, I observed a pair of policemen with a bomb-sniffing dog who were checking out a pair of propane tanks sitting in a box on the sidewalk.  Standing nearby were two soldiers, one carrying an assault rifle in an alert guard position, his finger laid next to the trigger.  He watched the crowds streaming past with a grim, almost dead expression.  It may have been the heat that oppressed us all was affecting him doubly, in his full camouflage dress and carrying a pack and weapon, a cap upon his head.  It may have been his awareness that if this were a real bomb, he’d be only the fifth of many to die, milliseconds after the policemen, their dog, and his comrade.  He may simply have been bored by yet another false alarm.

Thursday morning, I heard the news from London—another series of explosions, patterned much like the ones that came before, but mercifully less damaging.  I remembered how, while in London six weeks earlier, an abandoned package at the station near Picadilly Circus had triggered a security alert, shutting down the Central Line we were riding at the time and forcing us into the cloud-softened sunlight above.  I wondered how many suicide bombers England could produce.  Later in the day came the news that London police had shot to death a man on the subway.  It seems not so long ago that the stereotype of an English policeman was that his only weapon was to shout, “Stop!  Or I’ll say stop again!”

Friday afternoon, I took a cab to Penn Station and caught the train to Newark Liberty International Airport, where the security lines were surprisingly short.  As I rolled my suitcase through the concourse, the daily tabloids all screamed that random baggage searches were being conducted on New York City’s subway system.

This morning, as Carolyn climbed the stairs of her favorite slide at the local playground, I stood below and struggled to moderate my instinct to protect her from any possible harm, knowing that a few honest scrapes and bruises are a part of growing up—maybe an essential part—and that she would almost certainly get down the slide, smiling in delight, without hurting herself in any way.

But I still ask myself and will ask myself how much pain is too much, and how much protection is too much, every day of her life.

A Family Loss

In the week leading up to the Independence Day (U.S.) holiday, my father’s side of the family gathered for its annual reunion.  This was a big year, with practically everyone there—my father and his siblings, and their assorted children and grandchildren.  There were only two people out of 33 that did not plan to be there.  Even my father’s mother, a 97-year-old widow with very limited mobility and physical reserves, made the trek to upstate New York to be a part of the festivities.

In the week before the reunion, one of my father’s sisters-in-law—aunt to me and my cousins—fell and cut her leg.  Complications, including a pulmonary clot, put her in the hospital for a few days.  So it looked as though aunt Audrey and her husband Tren, my father’s brother, would miss the reunion.

In the end, Tren did come to the reunion after all, but not as any of us would have wished:  Audrey died the morning of the second day of the reunion.

On the first day of July, with almost the entire family present, from my grandmother down to her many great-grandchildren, we held a memorial service for Audrey.  We were able, thanks to some fantastic coincidences, to secure some wonderful musicians to play a small selection of tunes.  The service was held with the family in a circle, sitting in a room facing a cliff that dropped into a glacial lake.  The sun was bright in a cloud-dotted sky as various family members shared their thoughts and memories of Audrey.

With my attention on Carolyn and some of the other little ones, I did not manage to speak up, but there is little I could have said besides this small thing, to Tren and Audrey’s son, Don: It is a terrible thing to lose a mother, but a truly wonderful thing to have had, for however brief a time all those years may seem, a mother as loving as she.

Yesterday, we gathered again in Tren and Audrey’s home town of Cincinnati to wish her farewell along with the congregation of her church.  Afterward, I gave Tren a card which I hope gave him some comfort.  It read:

When you look up tonight, don’t think of them as stars.  Think of them as porch lights welcoming your loved one home.

Working With Google Maps

As I worked on HYDEsim, I discovered some interesting things about the Google Maps API.  Well, let’s call them what they are: limitations.

(And let me say right up front that if I missed ways to get around these limitations, then I’ll happily be corrected.  Either way, these are the impressions of someone whose first project in the API took about two days, and was in the end basically a success, which speaks volumes to the quality of the API.)

The first and most important limitation was that the Google Maps API permits the creation of two types of objects.  The first type is icons, the most obvious example of which are those little push-pin symbols in Google Maps that mark locations.  The second is polylines, which are how Google Maps draws the “get from here to there” routes on the maps.  You get both any time you ask for driving directions, like these from Norwalk, CT to New York City, NY.

Note that they’re polylines, not polygons.  You could certainly draw a polygonal shape using a polyline, but you couldn’t easily fill it with a color, let alone a translucent color.  And as for a circle… well, if you want to draw enough line segments so that you approximate the roundness of a circle, you certainly can.  It just doesn’t seem like a great idea.  Plus there’s no simple way to fill it in.

So in order to draw the overpressure rings, I created a 1000×1000 pixel 24-bit PNG of a circle.  To create a ring, I first used the Google Maps API to figure out the latitude and longitude boundaries of the map.  From that, I determined the number of miles per degree based on the latitude, and then calculated the number of miles per pixel (mpp) within the view.  From there, I determined how wide a ring needed to be to be the right size, created an icon at that size using the big PNG, and added it as an icon.

Whew.

Okay, so that solved the problem of putting the rings on the map.  What it didn’t solve was what happened if the zoom level changed, because icons (being raster images) don’t zoom with the map.  By default, you wouldn’t want them to: if the pushpin kept growing with the map as you zoomed in, eventually it would get huge and blocky and obscure half the view.

Therefore, the upshot was that every time the zoom level changed, I had to rip away the rings and rebuild them entirely, based on the new mpp value.  It was easy to trigger the process:

GEvent.addListener(map, "zoom", zoomLimit);

That’s the API at work for me.  I just tack a listener onto the zoom event, and I’m ready to go.  Cool.  Rebuilding the icons—well, not so cool, although it doesn’t seem to kill the tool’s performance.

All this zoom handling was necessary because icons, as you might expect, are given dimensions in pixels.  Polylines, on the other hand, have each point defined with longitude/latitude coordinates.  That’s why polylines do scale with change in zoom level—as, again, you’d want them to do by default.  If I could have defined my icons’ sizes using longitude/latitude measures instead of pixels, I could have avoided the whole “recalculate the ring sizes every time the zoom level changes” bit and shaved two or three hours off of my development time.  (Which was, in total, 12 hours or less.)

Of course, if the API provided polygonal primitives, I’d have avoided even more hackery.  If I could have just drawn the circles as circles, using longitudinal degrees as the unit of sizing, then there’d have been even less work and a shorter development time.  Something like this:

var base = new GShape();
base.type = circle;
base.anchor = new GPoint(-73.9971, 40.7223);  // longitude,latitude
base.radius = 0.0273548;  // degrees of latitude

…or something to that effect, with properties for the color and thickness of the outline, and also for the color and transparency of the interior.  And so on.

By doing it this way, the shapes (and there could easily be many other types) would be like filled polylines, and would scale in size along with the map.  That would have made HYDESim a whole lot easier to create.

You might say, “That’s all well and good, Eric, but how many reasons are there to draw circles on a map besides charting widespread destruction?”  I thought of a few possibilities:

  • Explicitly showing the scope of a “show me hotels within this many miles of the specified address” type of request
  • Someone looking to recreate the WIMPUR map in Google Maps
  • Plotting Iridium flare intensities

I’m sure there are countless more.  As well, allowing for actual filled polygons would add extra possibilities to applications like chicagocrime.org, which uses polylines to draw ZIP code boundaries.  With filled polygons, they could shade the ZIP code in question… or shade all other ZIP codes while leaving the current one unshaded, in order to give it some extra visual pop.

There was one other thing I encountered that’s either a limitation, or I just couldn’t figure out how to deal with it.  If you click on a detonation point in HYDESim, it pops up a “blowup” window (their term, not mine!) that shows a zoomed-in view of that point on the map.  The overpressure ring overlays are faithfully reproduced on that map, but they aren’t scaled to its zoom level.  They exactly match the overlays on the main map, and zooming in and out in that window has no scaling effects.

Ideally, I’d just remove the overlays from the zoom window while leaving them in place on the larger map.  I couldn’t find a way to do it.  Failing that, I wanted to have the overlays correctly scaled.  No dice there either.  If there is a way to do either of these and I missed it, hopefully someone will let me know.  If not, it’s something I hope the API adds in the future.

The final observation has to do with the icons and interactivity.  I wanted to set the overpressure rings to be event-transparent.  In other words, I wanted to make it so that the rings didn’t exist as far as the event model was concerned.  That way, you could click-and-drag the map even if there’s a ring underneath the mouse pointer.  This didn’t appear to be possible, although again, maybe I just couldn’t figure out how.  I did play around with the imageMap property, but it didn’t seem to have much effect.  Figuring that out would be nice, though.  I could leave the detonation point active for popping open the blowup window, and make the rest inert.

Other than that, things went as smoothly as you might expect they would for someone with limited JavaScript skills and no prior experience with the Google Maps API.  The examples provided by Google on the documentation page helped immensely, actually, especially the AJAX example.  That let me split the city list into a separate file, thus making it much easier to maintain, and get my first hands-on experience with AJAX programming.  (I’ve seen AJAX applications before—as long as three years ago, actually—but never written any code along those lines.)

Oh, and one more thing—the fact that the Google Maps API key only works for a specific directory, and not any of its subdirectories, drove me up the wall.  Instead of generating a key for meyerweb.com that would cover anything I might do on the site, I’ll have to generate a new key for every new directory.  This is why I set up the directory /eric/tools/gmap/, but that just seems so… confining.  Similarly, it was annoying that the key was completely bound to the full address.  I generated the key for meyerweb.com/eric/tools/gmap/, so if anyone types in www.meyerweb.com/eric/tools/gmap/ they’ll get a key error.  It would be nice if at some future time the keys were a little more flexible than they are now.

Mapping Doomsday

This past Friday night, in conversation with a couple of our friends, the subject of high school fears of annihilation came up.  Ferrett said he’d done a class project showing how, if New York City got hit with a nuclear warhead, his home town of Norwalk, CT would be destroyed as well.

“Wait a minute, that can’t be right,” I said.  “How far is it from Manhattan to Norwalk?”

He didn’t know for sure, so we went to Google Maps for a rough estimate.  49.2 miles, it said, although of course that’s a driving distance, not a straight-line measure.

Still, I felt confident in asserting that no way would Norwalk be destroyed.  Not even with a 20-megaton warhead, which was what he remembered using in his example.  A few windows might get shattered, and of course if the wind were from the southwest they’d be getting a whole lot of fallout.  But flattened?  No.  I was pretty sure not.

“Hold on,” I said, “I’ll be right back.”

I ran up to the library and went straight to the “military and arms control” shelf, where I pulled out my copy of “The Effects of Nuclear Weapons”, 3rd Edition (1977).  In the back, it has this handy “Nuclear Bomb Effects Computer”, a circular slide-rule type of affair.  You can fiddle with an online version of the calculator from the 2nd Edition (1962) of the same book, and the complete text of the 3rd Edition is also available online.  I went back downstairs and pulled out the calculator.

Humming to myself, I slipped and swished the dials until I came up with the answer a bit more severe than expected, but not terribly far off.  At a range of 45 miles, the maximum overpressure for an optimum-altitude air burst with a 20MT yield would be somewhere around 0.8psi.  The calculator actually doesn’t show overpressure figures below 1psi for optimum-altitude bursts, though it goes down to 0.1psi for ground bursts.  It also doesn’t go any higher than a 20MT yield.  A 0.8psi overpressure would shatter most windows, particularly those facing the shock wave, and might cause light damage to some residential homes.  The direct thermal radiation, even assuming line-of-sight to the fireball, would be less than 1 cal/cm2, which isn’t enough to cause any damage.  Otherwise, there would be a brief pulse of 30-mile-per-hour wind as the shock wave passed, and of course there would be EMP effects.  And, you know, fallout.

So it’s not like things would be all peaches and cream for the folks in Norwalk, but the town would still be standing.

At this point, I wondered if there were perhaps a tool online that would show this sort of information more visually.  I Googled a bit more, and came up with the Nuclear Weapon Effects Calculator, which lets you pick from a short list of cities, dial up the yield of your explosion, and click on the image to change the detonation point.  Guess where they got their data for the thermal ring, as well as the 5psi and 2psi thresholds?  Yep: “The Effects of Nuclear Weapons”, 3rd Edition.

That’s when my inner geek kicked into overdrive.  I’d been meaning to dig into the Google Maps API anyway, so I signed up for a key and developed my own version.  I call it HYDESim, which stands for “High-Yield Detonation Effects Simulator”.  You can pick from a list of cities or input any latitude/longitude coordinates Google Maps covers, set the yield you find most interesting, and see what the effects might be.  Each successive ring marks a successive overpressure threshold: 15psi, 5psi, 2psi, 1psi.  I included 0.25psi in the list because it’s the point at which even windows wouldn’t be damaged, but left it off the map because it was too huge.  (I thought about adding a way to switch psi rings on and off, and in the end didn’t feel like doing the necessary hackery.)  15psi is the point at which reinforced-concrete structures might be able to survive with severe damage; 5psi is where homes might start to survive with severe damage; and 2psi is where home damage drops to light.  Roughly speaking.

I didn’t include rings for thermal effects or electromagnetic pulses: this is strictly about blast wave damage.  It’s also “idealized”, which means that there’s no effort made to account for terrain changes, urban density, ground type, and so on.  The script just uses the formulae and information in the book to calculate maximum-overpressure distances for arbitrary yields, and plops down circles as appropriate.  So the “Simulator” part of the name is probably exceedingly grandiose.  Then again, you never know what a future spate of hacking might bring.

Also: apologies to New Yorkers that your city is the default target, but its destruction and the follow-on physical effects in Norwalk are what got me started on this… and, let’s face it, in any wide-scale nuclear conflict, you’d have been the top city on the target list.

Doing this was an interesting exercise in both Google Maps programming and lightweight AJAX, which I’d also been meaning to investigate; the city list is built from an XML file that sits outside the XHTML document and its scripts.  I’ll have some observations about the Google Maps API in another post— specifically, what I found to be major limitations given what I was trying to do— but for now, here’s your chance to get a slightly more concrete idea of what had us all so scared during the Cold War.  As the simulator demonstrates, even a 1MT (1000KT) device could do a whole lot of damage.

Gatekeeper 1.5 rc4

Now out the door: Gatekeeper 1.5 RC4.  It really does (so far as I can tell) allow pingbacks and trackbacks, as this post’s comments show.  So if you tried to ping or track back to a post here in the last three months, and you really wanted it to show up here, you might want to try again.  If you’re running Gatekeeper and want tracks and pings to work, you should definitely upgrade to RC4.

The auto-addition of the challenge to forms that don’t contain the pose_challenge call is still broken.  ‘Jim’ has more information and some examples of forms that fail to get an auto-added comment if you’d like to take a crack at solving that particular puzzle.

Safari SyntaxError

In pursuit of better JavaScript skills, I’ve encountered a Safari problem that may be a limitation in the browser, or it may be my coding.  I have a temporary test file demonstrating what’s happening.  In Firefox, everything works as I’d hoped it would, but in Safari, all I get is an error on the JavaScript console stating:

SyntaxError – Parse error

Here’s the function in which the error occurs, with the offending line emphasized:

function Test(a,b) {
	this.a = a;
	this.b = b;
	this.c = new (function Inner() {
		this.x = 'woo';
	});
}

As I say, here’s the temporary test file in case you want to see the entire script.

My long experience with CSS and browser handling  of it teaches me that just because something works in one browser, that doesn’t mean it’s supposed to work at all.  Therefore, it could be that Firefox is letting me be sloppy, and Safari is telling me I’ve messed up; or it could be that Firefox is right, and Safari has a problem.

So which is it?  If it’s the former, how can I do the same thing I’m trying to do, except correctly?  If it’s the latter, are there any simple workarounds to get Safari to behave?

Thanks for any help.

Update: Lachlan Hunt rides in to the rescue by pointing out what probably should have been painfully obvious, but like I say, I’m new to this.  The solution here:

function Test(a,b) {
	this.a = a;
	this.b = b;
	this.c = new function() {
		this.x = 'woo';
	};
}

I’m still not 100% certain if this was a case of sloppy authoring or a bad browser, but I’m not so concerned with that right now.  I’ll leave up the post in case anyone else encounters a similar problem.

Update redux: Adrian (and, though I didn’t understand what he was saying at the time, Tim) points out a simpler way to do the same thing.

Track/Ping Testing

So a while back, Gatekeeper was discovered to silently kill off trackbacks and pingbacks without any notification, something I’d have realized if I had stepped back for a second to think about my coding.  So anyway, a solution was proposed, and I thought it fixed the problem.  Only it didn’t, possibly due to me being sloppy.  I’m honestly not sure.

So anyway, I think this time I’ve really fixed the problem, but to find out, I need to have people trackback and pingback this post.  That’s all; just hit this post with one or the other—or, heck, both. Feel free to make the link back to your site to your home page, your favorite post, your most recent post, your about page… whatever.  Thanks.

Oh, and if your attempt to *back the post fails, leave a comment to let me know.  If you see more than a few comments saying it didn’t work without a response from me, then don’t worry about adding another unless you have information that would explain why the failures are occurring.  Thanks again!

Web Page, Mutated

One of the first rules of life is that first-hand information is always better than second-hand information.  You can be more certain of something if you’ve seen it with your own eyes.  Anything else is hearsay, rumor, conjecture—an article of faith, if you will.  At the very minimum, you have to have faith that your source is reliable.  The problems begin when sources aren’t reliable.

No, this isn’t a rant about the intelligence screw-ups previous to the invasion of Iraq.  Instead, it’s a warning that inspector programs and saving as “Web page, complete” features can lead you astray.

One such example came up recently, shortly after I mentioned the launch of the new Technorati design.  A question came in:

I did want to ask about the use of -x-background-{x,y}-position as opposed to background-position. If I understand correctly, the -x prefix indicates an experimental CSS attribute, so in what circumstances should one use this sort of experimental attribute instead of an official one?

I’d have been glad to answer the question, if only I’d known what the heck he was talking about.  Those certainly weren’t properties I’d added to the style sheets.  They weren’t even properties I’d ever heard of, proprietary or otherwise.

Just to be sure, I loaded the CSS files found on the Technorati site into my browser and searched them for the reported properties.  No results.  I inquired as to where the reporter had seen them, and it turned out they were showing up in Firefox’s DOM Inspector.

Now, the DOM Inspector is an incredibly useful tool.  You can use it to look at the document tree after scripts have run and dynamically added content.  You can get the absolute (that is, root-relative) X and Y coordinates of the top left corner of every element, as well as its computed dimensions in pixels.  You can see the CSS rules that apply to a given element… not just the everyday CSS properties, but the stuff that the Gecko engine maintains internally.

That’s where the problem had come in.  The DOM Inspector was showing special property names, splitting the background-position values into two different pseudo-properties, and not showing the actual background-position declaration.  This, to me, is a flaw in the Inspector.  It should do two things differently:

  1. It should show the declaration found in the style sheet.  There should be a line that shows background-position and bottom left (or whatever), because that’s what the style sheet contains.
  2. It should present the internally-computed information differently than the stuff actually taken from the style sheet.  One possibility would be to show any internal property/value pair as gray italicized text.  I’d also like an option to suppress display of the internal information, so that all I see is what the style sheet contains.

The person who asked why I was using those properties wasn’t stupid.  He was just unaware that his tool was giving him a distorted picture of the style sheet’s contents.

Don’t think Firefox is the only culprit in unreliable reporting, though.  Anyone who uses Internet Explorer’s save as “Web page, complete” feature to create a local copy for testing purposes isn’t getting an actual copy.  Instead of receiving local mirrors of the files found on the Web server, they’re getting a dump from the browser’s internals.  So an external style sheet will actually be what the browser computed, not what the author wrote.  For example, this:

body {margin: 0; padding: 0;
  background: white url(bodybg.gif) 0 0 no-repeat; color: black;
  font: small Verdana, Arial, sans-serif;}

…becomes this:

BODY {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px;
BACKGROUND: url(bodybg.gif) white no-repeat 0px 0px;
PADDING-BOTTOM: 0px; MARGIN: 0px; FONT: small Verdana, Arial, sans-serif;
COLOR: black; PADDING-TOP: 0px
}

Okay, so it destroys the authoring style, but it isn’t like it actually breaks anything, right?  Wrong.  For some reason, despite IE treating the universal selector correctly, any rule that employs a universal selector will lose the universal selector when it’s saved as “Web page, complete”.  Thus, this:

#sidebar {margin: 0 74% 3em 35px; padding: 0;}
#sidebar * {margin: 0; padding: 0;}

…becomes this:

#sidebar {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px;
MARGIN: 0px 74% 3em 35px; PADDING-TOP: 0px
}
#sidebar  {
	PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px;
MARGIN: 0px; PADDING-TOP: 0px
}

Oops.  Not only can this mean the local copy renders very differently as compared to the “live” version, it’s also very confusing for anyone who’s saved the page in order to learn from it.  Why in the world would anyone write two rules in a row with the same selector?  Answer: nobody would.  Your tool simply fooled you into thinking that someone did.

Incidentally, if you want to see the IE-mangled examples I showed in a real live set of files on your hard drive, go save as “Web page, complete” the home page of Complex Spiral Consulting using IE/Win.  And from now on, I’ll always put “Web page, complete” in quotes because it’s an inaccurate label.  It should really say that IE will save as “Web page, mutated”.

So if you’re Inspecting a page, or viewing a saved copy, remember this:  nothing beats seeing the original, actual source with your own eyes.  If you see something odd in your local copy, your first step should be to go to the original source and make sure the oddness is really there, and not an artifact of your tools.

July 2005
SMTWTFS
June August
 12
3456789
10111213141516
17181920212223
24252627282930
31  

Archives

Feeds

Extras