No Mod Required

Belt and Suspenders- Flash Embed With SWFObject and Conditional Comments

If you’re using Flash and you want the best possible coverage (meaning it works with users who don’t have JS turned on) while still using something like SWFObject where possible to get around the “click here to activate and use this control” ActiveX message in Internet Explorer, then take a look at the ridiculous pattern below.

Warning- not for the squeamish…

Here’s the HTML:

<!--[if IE]>
   <noscript> 
   <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" width="1004" height="281">
      <param name="movie" value="_assets/flash/homepage.swf" />
      <param name="quality" value="high" />
      <embed src="_assets/flash/homepage.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="1004" height="281"></embed>
</object>
</noscript>

<![endif]–>
<!–[if !IE]> <–>
   <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" width="1004" height="281">
      <param name="movie" value="_assets/flash/homepage.swf" />
      <param name="quality" value="high" />
      <embed src="_assets/flash/homepage.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="1004" height="281"></embed>
   </object>
<!–> <![endif]–>

Here’s the SWFObject script served to Internet Explorer and ONLY Internet Explorer

<!--[if IE]>
<script src="_assets/js/swfobject.js" type="text/javascript"></script>
<![endif]–>

And here’s the SWFObject call:

        //use conditional compilation to hide this call from non-IE browsers
	/*@cc_on @*/
        /*@if (@_win32)
	if ($(”home”)){
		var so = new SWFObject(”_assets/flash/homepage.swf”, “mymovie”, “1004″, “281″, “8″, “#336699″);
	   	so.addParam(”wmode”, “transparent”);
	   	so.write(”messaging”);
	}
	/*@end @*/

Before I go further, let me just say I’m counting the days until I can just dump a SWF into the page and be done with it. I hate all of these script based machinations to get a SWF out to the browser. This is code overhead that really bugs me…

Anyway, here’s the HTML logic.

  • We use Microsoft’s conditional comments to show/hide content
  • In the “This is IE” block we use a noscript tag to present a traditional embed to IE users who might have JS turned off.
  • Every other IE user with JS turned on will see the SWF embedded by SWFObject so no “click to activate and use this control” will be visible to the user. Since the majority of people on the web use IE and the majority of them surf with JS turned on, most users will fall into this category.
  • Then, in the “This is not IE” block, we just embed the Flash the old school way. Since the Eolas suit doesn’t come into play with other browsers, embedding the SWF the old way is fine (at least in terms of the “click here…” nonsense.) As an additional benefit there’s no concern over whether or not the user has JavaScript turned on. JavaScript or no, the only issue is whether or not they have the plugin. Whereas with SWFObject there’s a possibility (however slim) that a user could have the Flash plugin installed but be surfing with JavaScript disabled. As I mentioned, this is for the best possible coverage… Also, if they don’t have the plugin they get the “download this plugin” notification. I head reports that that wasn’t happening with SWFObject running* so getting that to work properly is definitely a bonus. It was actually that bug report that got me into this whole mess :)

As for how it works technically, the following

<!--[if IE]>

Is read by IE as a test (if the browser is Internet Explorer.) Every other browser reads it as an open comment. Since it’s an open comment everything up until the close comment (<![endif]–>) will be ignored by non-IE browsers. IE, on the other hand will go ahead and process that markup normally since it recognizes that pattern as a conditional and its test will evaluate to true.

As a note, I don’t like using this stuff all over the place**, but in a situation like this conditional comments are a great option to have.

On the flip side All other browsers read this pattern:

<!–[if !IE]> <–>

As a completed comment, opened and closed on the same line. Therefore everything that follows is rendered normally by Firefox, safari and all the rest. IE, on the other hand, reads it as the beginning of a “If the browser is NOT IE” conditional. Since that resolves to false, everything down to the end of the conditional endif (<!–> <![endif]–>) is ignored by Internet Explorer. That allows us to go back to the future and embed flash in the old school way for everything but IE.

Oh the pain.

Still, if you absolutely need the best possible coverage and want to use SWFObject, this is a way to go. Is it the best? Probably not, since it’s horrifyingly hack-y and won’t validate. But it might be useful for someone out there…

*and I could figure out how to make it happen…
**I mostly use it to attach IE specific style sheets. For those of you keeping track, that looks like this:

<!--[if gte IE 5.5]>
<![if lt IE 7]>
<link rel="STYLESHEET" type="text/css" href="_assets/styles/ie6.css" />
<![endif]>
<![if gte IE 7]>
<link rel="STYLESHEET" type="text/css" href="_assets/styles/ie7.css" />
<![endif]>
<![endif]–>

How Did I Miss This? IE Automatic Component Activation Will Revert to Old Behavior

Hallelujah. Bravo Microsoft! I really don’t like using JS to embed Flash into a page, so this is good news for me. No more SWFObject for me :)

Don’t get me wrong, SWFObject is a great piece of code. I just hate having to think about Flash at all. Unless there’s actual communication between the SWF and the page, I just want to dump it into the doc like any other element and be done with it. I can’t tell you how many problems I’ve had over the past year with Flash and JS embed techniques and bizarre bugs… Pain. Great pain.

IE Automatic Component Activation (Changes to IE ActiveX Update)

Back in April 2006, we made a change to how Internet Explorer handled embedded controls used on some webpages. Some sites required users to “click to activate” before they could interact with the control. Microsoft has now licensed the technologies from Eolas, removing the “click to activate” requirement in Internet Explorer. Because of this, we’re removing the “click to activate” behavior from Internet Explorer!

It’s important (and cool) to note that this change will require no modifications to existing webpages, and no new actions for developers creating new pages. We are simply reverting to the old behavior. Once Internet Explorer is updated, all pages that currently require “click to activate” will no longer require the control to be activated. They’ll just work.

IEBlog : IE Automatic Component Activation (Changes to IE ActiveX Update)

Mad Science… Flash for a page background using JavaScript and CSS

For the current EforAll Expo*1 web site, the designer suggested that we use a flash piece for the background. It’s a kind of hip event, for gamers and other technophiles so we made some assumptions about our user base and decided it was worth a go. The onus fell on me, as these things do, to set up this effect.

I’m not sure whether or not I’m proud or completely ashamed of this one. On the positive side, it was interesting to script and it looks kind of cool. On the negative it adds nothing to the site other than some pizzazz and therefore feels like a goofy script from back in the dHTML days.

I’m sure you all have your own opinions on the matter :)

Whatever side of the fence you fall on, I figured it might be interesting to explain how I got this nasty beast out the door.

My original attempt was to do it with just CSS. I envisioned some perfect voodoo combination of "overflow:hidden;", wmode=transparent and the like combining to create some magic. While I had some success, the amount of time I had to get it to work coupled with the inevitable cross browser problems, made me reconsider that approach. After a glance at the schedule and some thought I decided that if I went with a JavaScript based solution, I could be certain of implementation success and I would be able to do it in a lot less time than I had already spent on the CSS only solution.

I planned to create two DIVs, populate them with the two wings of the flash background and then set the widths of the DIVs dynamically so as to suppress any potential scroll bars. This would create the appearance of flash in the background without having to have the content sit on top of a SWF.

To start off I sketched out a skeleton of the script:

sketching-out-the-script.jpg

I then ported those steps over to Homesite as comments forming the shell of my script. I like doing that sort of preparatory work for any script that would be a new challenge for me, to make sure I have all the logic worked out before I type a single line. It doesn’t always work, fo course, but it saves a lot of headaches later to have a good roadmap in place even for small scripts such as these.

In the end, I created two functions which run onload;

insert_flash() ;
set_dimensions();


set_dimensions()
also runs onresize.

insert_flash() looks like this. Comments explain the code:

function insert_flash() {
  //create a left div
           leftdiv=document.createElement("DIV")
  //give it an ID to hook JS and some styles defined in the  CSS
           leftdiv.setAttribute("id","left-bg");
  //create a right div
           rightdiv=document.createElement("DIV")
  //give it an ID to hook JS and some styles defined in the  CSS
           rightdiv.setAttribute("id","right-bg");
  //dump them into the doc at the bottom of the DOM
           document.getElementsByTagName("body")[0].appendChild(leftdiv)
           document.getElementsByTagName("body")[0].appendChild(rightdiv)                   
  //I use this totally ugly method to get the flash into the  documents. 
  //I know there are better methods. This one is so  straightforward I don’t care about elegance.
           document.getElementById("left-bg").innerHTML=’         <div><object  classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"  codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0"  width="460" height="578"><param name="movie"  value="/themes/idg_assets/flash/bgglow_left.swf" /><param name="quality"  value="high" />; <param name="wmode"  value="transparent"><embed src="/themes/idg_assets/flash/bgglow_left.swf"  quality="high&quot  ;  wmode="transparent" pluginspage="http://www.macromedia.com/go/getflashplayer"  type="application/x-shockwave-flash" width="460"  height="578">;</embed>; </object>;</div>;’;
           document.getElementById  ("right-bg").innerHTML=’     <div><object  classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"  codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0"  width="460" height="578"><param name="movie"  value="/themes/idg_assets/flash/bgglow_right.swf" /><param name="wmode"  value="transparent">;  <param name="quality" value="high" />;           <embed  src="/themes/idg_assets/flash/bgglow_right.swf"  quality="high"  pluginspage="http://www.macromedia.com/go/getflashplayer&quot  wmode="transparent"  type="application/x-shockwave-flash" width="460"  height="578">;</embed>; </object>;</div>;’;
 }

set_dimensions looks like this. Comments again explain the code:

function set_dimensions(){
  //cross browser doc width. From ppk? I don’t remember where I got this.
                 docWidth  = (typeof( window.innerWidth ) == ‘number’) ? docWidth = window.innerWidth :  docWidth = document.documentElement.clientWidth;
  //cross browser doc height.
                 docHeight = (typeof(  window.innerHeight ) == ‘number’) ? docHeight = window.innerHeight : docHeight  = document.documentElement.clientHeight;
  //if you were going to repurpose this, you would want to
  //change the following 1000 to something like
  //document.getElementById("wrapper").style.width
  //or
  //document.getElementById("wrapper").offsetWidth;
  //I just knew that the wrapper div had a width of 1000 and  just worked 
  //with that knowledge.
  //anyway, I’m just making sure we don’t pass any nonsensical values  (in this case, a negative width) to the next part of the script
                if (docWidth>;1000){
  //again. We just want to make sure we pass a good value so  we parse an integer out of the diff
  //.5px doesn’t really make much sense.
                     diff=parseInt((docWidth-1000)/2)
                }
                else {
                      diff=0;
                }
  //then we just set some styles
                document.getElementById("left-bg").style.width=diff+"px";
                document.getElementById("right-bg").style.width=diff+"px";
                document.getElementById("left-bg").style.height=docHeight+"px";
                document.getElementById("right-bg").style.height=docHeight+"px";
  }

The CSS looks like this:

#left-bg,
#right-bg {
width:100px;
overflow:hidden;
position:absolute;
top:0;
z-index:0;
}
/*pin the left to the left edge*/
#left-bg {
left:0;
}
/*pin the right to the right edge*/
#right-bg {
right:0;
}
#left-bg div,
#right-bg div {
position:absolute;
top:0;
z-index:0;
}
/*pin the div containing the SWF to the right edge of the left div.
This ensures the div expands the same way a centered background image would
*/
#left-bg div{
right:0;
}
/*pin the div containing the SWF to the left edge of the right div.
This ensures the div expands the same way a centered background image would
*/
#right-bg div{
left:0;
}

And that’s that. It went really smoothly and it looks pretty cool across browsers (Safari, Firefox 2, IE6 an IE7). My biggest gripe about the way it looks is the way that Firefox waits until the resize event is completely over to redraw the screen. Because of that, things can look less than optimal in firefox with a dramatic browser resize. Other than that, I’m pretty happy with it (even if I’m kind of embarrassed to have written such a gratuitously useless script.)

*The site, since this article was written, has been rewritten. I’m no longer responsible for anything you see there in the way that I normally am. I tried my best to guide the site’s production, but we’re working with Drupal in a big way so the front end is simply out of my hands.

I like this Flash embed technique.

Assuming I don’t want to do any player detection*, don’t care about using the embed** tag, and just want to get the swf into the doc without IE hiccuping on it because of the Eolas patent dispute, I’m thinking this is my default Flash embed technique going forward.

This tiny bit of code gets around the “click to activate and use this control” IE issue and allows me to use traditional HTML methods to embed the SWF for browsers that didn’t lose a multimillion dollar lawsuit and can just present Flash the old school way. This also allows people with Flash installed and no JavaScript to see the Flash content (I wonder how many people that actually is.)

Assuming a div with the id of “flashcontent” on the page, we run this in an included script file onload (or equivalent).


/*@cc_on @*/
/*@if (@_win32)
the_swf=document.getElemebtById("flashcontent").innerHTML
document.getElemebtById("flashcontent").innerHTML = the_swf
/*@end @*/

We use some conditional compilation to hide the script from anything but IE and then we just do a pointless switcheroo, replacing the innerHTML of the div with itself. Amazingly, that’s all it takes to workaround the Eolas issue. And that’s that.

Personally, I’m sold.

*for fancy stuff see the excellent swfobject.

**on the same page you can see an “object only technique” to use if getting rid of the embed tag is important

“I hack, baby” or How I Made the SpingWidgets RSS Feed Work on Myspace

“I hack, baby”, sung to the tune of “I Get the Job Done,” by Big Daddy Kane.

I’m a Feedburner user. One of the tabs in their “publicize” section is a link to a Sping Widgets feed widget that you can use to put your feed on places like Myspace. I thought that seemed like a no brainer, so I did it up real quick and inserted it into my interests. It looked fine, I just couldn’t click any of the links*. Apparently, Myspace disables links in Flash objects, which kind of kills the point of having my feed posted over there. Not to be discouraged, I gave it a few minutes though and came up with a pretty simple hack to at least fake it enough to make the thing worthwhile.

What did I was wrap the whole thing in a DIV with height and width equal to the widget. Inside of that I added an empty anchor tag pointing back here. I figured If I couldn’t link to individual posts I might as well get some links back to the main blog page and people could figure it out for themselves. I styled that anchor thusly:


/*give it its own height and width*/
display:block;
width:230px;
height:280px;
/*set the position to absolute, so we can (a) stack it and (b) out it where it needs to go with pixel precision*/
position:absolute;
left:0px;
top:20px;
z-index:20;
/*give it a background color and then blow away the background color with opacity without this there's no "hook" for clicks. It's just an empty box I probably could have achieved the same effect with a transparent background image but this is bandwidth free.*/
background-color:#333;
opacity:.05;
filter: alpha(opacity=05)

You can see what the anchor looks like, in terms of positioning, with this example:

As you can see I left room for the scrollbar and the menu.

One thing that makes this work right out of the box is the fact that the Spring Widget code already sets wmode to transparent which allows HTML elements to sit on top of a Flash Movie.

Here’s some copy and paste code, if you’re into that sort of thing:

<div style="width:250px;height:300px;position:relative;"><a href="http://www.yourlink.com/" style="display:block;width:235px;height:285px;position:absolute;left:0px;top:15px;border:1px solid red;z-index:20;background-color:#333;opacity:.05;filter: alpha(opacity=05)"></a><!–YOUR WIDGET CODE GOES HERE!–>
</div>

*This was just copying and pasting the code as pure HTML I’m not sure if using the Spring Widgets “insert into myspace” button works any better as I couldn’t get it to actually insert the code into my profile.

Another weekend special.

This is actually from the 7th, but I never published it.

quickie.jpg

I have video of myself drawing this. I’ve got to get the whole Flash video thing worked out before publishing. Stay tuned.
Here it is. Flash Video is really easy.


PUMA HOLIDAY HEROES = Michelle Yeoh Flash Game

One of the greatest screen fighters of all time is now yours to control…

PUMA HOLIDAY HEROES

Back, Back, Back… GONE! Well… Reverse That…

I was in San Francisco for the How Conference this week.

The highlight of the conference itself was seeing two presentations by Hillman Curtis, one of the few “big name” web/new media designers that I really respect. His presentations were insightful, fun and inspiring. Very cool.

The highlight outside of the conference was seeing Barry Bonds hit homer number 33 of the season from great (and relatively inexpensive) seats at PacBell (a great ballpark, by the way.)

I’ve been waiting to see Bonds play live for close to 12 years and on the first pitch of the first at-bat I ever saw from the future hall of famer, he hit a homerun into McCovey cove. I was as happy as a little kid on Christmas. In all honesty I was choked up for about the next half inning.

The lowlight of the week was, without a doubt, being within about fifty yards of a broad daylight shooting. Hearing the sound of gunfire while on my way to lunch (at Tu Lan, a brilliant Vietnamese restaurant,) and then scampering across the street to avoid stray bullets isn’t the sort of thing that I want to repeat.