Sunday, June 25, 2006

ExternalInterface Slower Than getURL

The test page speaks for itself. Basically, I wanted to see whether it was worth using ExternalInterface for Flash-to-JavaScript communication when the JavaScript function doesn't return anything.

It turns out getURL still has its advantages. My results from this test show the following:

10000 ExternalInterface calls: 1593ms.
10000 getURL calls: 83ms.

That's pretty significant. My theory for the difference in execution speed is that ExternalInterface is waiting for the JavaScript function to finish executing before it allows the next call to take place. With getURL, I believe it is leaving it to the browser to queue up those JS calls, and doesn't bother waiting for a return value.

In my test case, all the JavaScript function does is assign a variable, so it executes pretty quickly. However, in real life, a slow JavaScript function could have your ExternalInterface calls waiting for a return value that never comes.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Tuesday, June 20, 2006

Flash RIA Testing Effort

Yesterday, in my post "Why a Flash vs Ajax Debate?" I talked about how targeting an older version of the Flash player in the development of RIAs can yield a multiplication in testing effort as compared to their Ajax counterparts. See the original post for more detail, but basically this is because you have to test every minor Flash Player version back to the targeted version, on every browser, in order to make a cross-platform compatibility promise.

This prompted some great comments regarding QA methodologies for Flash, and I would like to hear more.

I'll start:

When developing solo, I test heavily on all major revisions of the Flash
player back to the targeted version. If I am targeting Player 6, I also
pay special attention to 6 r47. I spot-check a few minor revisions between
each major version.

My testing for browsers mirrors typical user
agent statistics: 85% IE PC, 10% Firefox, 5% everything else.
In other words, I test heavily on IE PC and spot-check virtually everything
else, with a little extra attention paid to Firefox.



This ends up being a manageable testing effort for solo development, and very few bugs have ever made it through. With JavaScript, the testing is usually similar, except that the Flash player is not a factor at all. I pay a little more attention to IE 5.x and Safari because of differences in their JavaScript implementation, but usually those differences are handled by a framework and don't present much of a problem.

Though my thoughts so far have been focused on the code behind the scenes, I would be remiss not to point out that one place where Flash can unquestionably reduce the QA effort is in the UI. Rendering differences between Flash player versions are almost nonexistent. In fact, this is one area in which I have come to take Flash for granted - you forget about the UI if it's not causing you problems. Getting complex components to work identically everywhere is not always a sure thing, but you can be guaranteed that they'll LOOK the same. Compare/contrast with HTML/CSS, and Flash clearly comes out the victor on that score.

So, what Flash player/browser combinations do you test in? What known issues do you specifically look out for? If you're an Ajax developer, what frameworks do you use, and which browsers do you test in? This promises to be a great discussion and one well worth having.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Monday, June 19, 2006

Why a Flash vs Ajax Debate?

I've been wondering for a while why Ajax has become so popular recently, when Flash has had the same capabilities and more for several years. I've been working with both JavaScript and Flash since 1999, and for me, there's never been a debate over which was the superior technology. I avoided JavaScript when possible, mostly because cross-platform compatibility was my prime directive, and because it was possible to do things in Flash that JavaScript was incapable of. For a long time, the Flash Player was more ubiquitous than the presence of advanced JavaScript capability.

Today it seems to me that the Flash Player and advanced JavaScript capability are almost on an even footing in terms of ubiquity (I say this based on user agent stats I've seen from a few different market segments). When you consider that MSIE 6 can make up 90% of the traffic to a consumer-oriented site, that's a pretty good chunk of it. Then, you've got the IE 5.x's, the Firefox's and the occasional Safari. Really, the browser that can't do Ajax is increasingly rare.

I still believe Flash is superior, in many ways. But ironically, the things that used to be its main strengths are becoming liabilities.

I used to rely on Flash because it reduced my testing effort. With Flash, I could be basically assured that what worked on PC IE would work on Mac IE (no small feat, by JavaScript standards). Unfortunately, over the last several versions of the Flash Player, many obscure bugs have come and gone, bugs that existed for perhaps only one minor version of the Player on one browser. I recall one particularly egregious bug in Player 6-dot-something for Mac IE, where you could not cancel a loadMovie request once it was made (hogging up bandwidth to an unusable degree, in my case).

Fortunately, Macromedia was great about fixing those bugs. Unfortunately, the public was not so great about updating their players. These days, if you want to reach that 97% audience that Adobe advertises, you have to target Player 6. I recently came across a scenario where the company-wide IT policy was Player 6, no hope of upgrade (in some companies, shockwave is just completely blocked at the firewall level).

[As a long-time Flash devotee, I cringe while writing the following]

The upshot of all this is that Flash represents a multiplication in testing effort for every back-version you target. Even some of the simplest tasks, such as Local Shared Object read and write, can not in my experience be relied upon to work identically across all minor player versions back to 6.0. If you want to make a compatibility promise, the only way to do so is to test every feature of your application in every version of every targeted browser, in every minor version of the Flash player going back to the targeted version.

To put that in perspective, there are 6 releases in the Player 6 archive, and Player 7 had 7. Let's ignore Player 8 for now. Let's suppose we want to target MSIE 5 and greater, Firefox 1 and greater, and Safari 2 and greater. That's at least 3 versions of IE, at least 3 of Firefox, and probably 2 of Safari (I'm speaking loosely here, I'm sure there are more). That makes 8 browsers to test on, and 13 versions of the player - a total of 104 test configurations.

Yikes.

No development team in their right mind would take on such a testing effort, even for a mildly involved project. (Now, I'm not suggesting that you have to - you can definitely achieve high quality products in Flash without all that. But to be precise, you can't make a cross-platform compatibility promise without actually testing on all targeted configurations.) Compare this to JavaScript, where you have only the browsers themselves to concern yourself with.

Now, I have never tested a complex application in every minor version of the Player, and more often than not, the cross-platform compatibility promise of Flash does hold true. But I have also had situations where bugs didn't present themselves until the product was launched and customers complained. Those situations have made me very cautious, and even though I don't test all the minor versions, I do end up with longer QA cycles on my Flash projects than the JavaScript ones.

Not that testing JavaScript-based apps is easier: there tend to be more unanticipated bugs than in Flash, so I probably end up with more QA cycles.

Ultimately, Flash can still do way more than JavaScript, and I firmly believe it remains a better solution for RIA. But I don't think Adobe can rightfully trumpet cross-platform compatibility and player ubiquity in the same breath. If you want all the considerable advantages that the Flash Player has to offer, you have to sacrifice some market penetration. If you want 97% reach, you have to author for Player 6 and test like mad.

One thing Adobe could do to help the situation would be to publicize the bug databases from old releases of the player. That would at least allow us to know what we're dealing with when developing for older player versions. A lot of the bugs that have given me the most grief in the past were only documented in the Flashcoders archives, and only in the ad hoc format of a discussion thread.

I have had a hard time understanding why so many developers were so keen to jump on the Ajax bandwagon when Flash has been around so much longer. Maybe this testing effort thing has something to do with it. Am I onto something here?

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Flash Bug - Contents of TextField w/autoSize = true Scroll When Selected

This one's for Mark Wubben of SIFR fame -

When you create a multiline TextField and set its autoSize = true, the TextField should expand to accomodate its contents, and the contents should not scroll when selected by clicking and dragging within the text field. However, sometimes when you select the text, it scrolls and the top gets chopped off. This seems to happen most frequently when the mouse exits the TextField at the bottom edge, rather than the right edge.

The best solution I have found for this is not to use the autoSize property at all, but rather to simulate it, and add a little extra height:

myTextField._height = myTextField.textHeight + 7;

7 seems to be the magic number. This is just enough extra padding to prevent the scrolling, and is only a pixel or two taller than the autoSize = true version. 7 seems pretty aribitrary, and the difference between the autoSized TextField and the non-autoSized TextField varys with font face and font size. So, I use 10px to be on the safe side. I've tested this with a lot of different font faces and sizes, and it hasn't failed me yet. To maintain an accurate visual representation, I subtract 10px from the height of the containing object (in the case of SWF Headings, its the ActiveX object or plugin, but it could also be a masked movieclip).

Here's a test case, and the source as well.

[Edit: in the test case, the TextField on the left is autoSize = true, the one on the right has the workaround applied ]

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Wednesday, June 14, 2006

More About Failing Eolas Patent Workarounds

I happen to be one of those lucky people for whom the Eolas workarounds do not always work. The issue for me is that if I clear IE's cache and then visit an Eolas-remediated site, the workarounds fail. If I restart the browser after clearing the cache, the workarounds are fine. Not all of my PCs exhibit this behavior.

I found the following article which says essentially that the problem may be due to a faulty installation of the Eolas patch:

http://blog.metawrap.com/blog/MicrosoftsEolasActiveXPatchForIESometimesBreaksJavaScriptWorkaround.aspx

Awesome article. Too bad I can't uninstall the patch to prove the theory. Windows gives me Access Denied errors, and won't even let me do System Restore to a date prior to the Eolas patch. I feel a rant coming on...

But I'll spare you my feelings on Mac v. Windows. I think I'll instead keep an eye out for a JavaScript tweak to fix the issue, although at the moment I'm feeling very doubtful that such a critter exists.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

A Sad Day on Flashcoders - Update

As of about 6 PM yesterday, Flashcoders is offline. Maybe it began loathing what it had become and decided to end it all? Start casting your votes - if Flashcoders was standing on a ledge, would you

a) Talk it down - it has so much to live for

or

b) Give it a nudge?

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Tuesday, June 13, 2006

A Sad Day on Flashcoders

Today was a dark day in Flashcoders history. I counted no fewer than 45 posts on the topic of "Flash coders content degrading" today, and this was a carry over from yesterday. Many of these posts were multi-paragraph rants regarding noobs, RTFM & Googable questions, the place of newbies in the mailing list ecosystem, elitists, etc. The tone of the posts ranged from irate to juvenile to jovial to concerned. The vitriol spilled into other threads as well, with accusations being hurled as to who did and did not Google or read the Help manual before posting. Scorn was heaped, soap-boxes were stood upon, and real questions went unanswered.

I resisted the temptation to voice my own opinion, except to defend one hapless soul who happened across Micael Stuhr's inbox at the wrong time. But my hackles are up, and this blog is the correct forum to voice my opinion, and so here it is:

The only people degrading the content on Flashcoders are the ones who post messages about people degrading the content on Flashcoders, and the occasional "joke of the day". What about the noobs and all their silly questions, you say? I believe there is no such thing as a stupid question, as long as it is sincere. I have learned more from answering "newbie" questions, and from reading answers to "newbie" questions than I have learned from almost any other source. Anybody who thinks they're above "newbie" questions simply doesn't see the benefit they can gain from a review of the basics.

Like many others, I love Flashcoders for its potential to provide answers to really difficult questions. But I recognize that some of the very people who today are asking "simple" questions are the same ones who will be answering hard questions in the future. Over the years, I have watched some great minds at work on Flashcoders, many of whom no longer post to the list. Today, those guys are legends in the Flash world, and probably busier than hell.

Who has taken their place? From today's conversation, it looks like their places are empty.

So, what can be done? Stacey Mulcahey issued a call to save Flashcoders, but then promptly disappeared from the scene. (I don't mean that as a personal attack on Stacey... it's just that 1) I love her blog and have been looking for an excuse to link to it, and 2) I was right there with her and a little disappointed not to see her on Flashcoders anymore). She's not the only one who complained and then dropped out of site. But if you want to save Flashcoders, you can't abandon it.

Here's what can be done: do not respond to off-topic messages. There are those who will... Ignore them. With regard to newbies and RTFM questions: either answer the question, or do not answer the question. It seriously does not take long to determine if a question is of interest to you.

The key thing to remember is this: it is not your civic duty to reprimand anyone for OT, RTFM, or anything else. You are not the OT Police. Dave Watts is pretty much the only person who can be attributed that title, and he seems disinterested in the job.

I know this is an idealistic approach, and not likely to reduce the amount of OT. But it WILL cut the amount of OT about OT, and that actually seems to be more of a problem these days.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Monday, June 12, 2006

Shared Libraries - Branden Hall's Original Solution

I was researching shared fonts for my SWF Headings library, and I kept coming across references to a post on Branden Hall's blog where he found a slick way to allow dynamic creation of elements from shared libraries. Alas, the post no longer seems to exist anywhere on his blog.

Finally, I found this post on Flashcoders which contains a sizable excerpt:

http://chattyfig.figleaf.com/pipermail/flashcoders/2002-August/045588.html

Interesting technique. Not sure I'll be able to use it, but good to have in the arsenal just the same.

[Edit] Found a more complete writeup elsewhere on Flashcoders: http://chattyfig.figleaf.com/pipermail/flashcoders/2004-June/115662.html

[Edit] Naturally, the Wayback Machine is the first place I should have thought to look:
http://web.archive.org/web/20021206180401/http://www.waxpraxis.org/archives/000062.html

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Friday, June 09, 2006

Flash 8 ColorMatrix Explained

Here are a couple sources I found really useful in understanding the ColorMatrix class:

http://www.adobe.com/devnet/flash/articles/matrix_transformations_04.html

http://chattyfig.figleaf.com/pipermail/flashcoders/2005-September/150592.html

These were simple and straightforward, unlike many of the articles on ColorMatrix that assume you have prior knowledge of matrices in general. Also, much better than the help docs on this topic.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Thursday, June 08, 2006

JavaScript - Concatenating NodeLists

In JavaScript, you cannot concatenate two nodeLists using Array.concat(). This is because nodeLists are not true Arrays, they are more like Objects that happen to have a length property. Here's an example scenario:

var pElements = document.body.getElementsByTagName("p");
var divElements = document.body.getElementsByTagName("div");

// This results in a new array where the last element is the entire
divElements nodeList
var pAndDivElements = pElements.concat(divElements);

As a workaround, I wrote a quick method that will join two nodelists:

joinNodeLists: function(list1,list2){
var i = list2.length - 1;

do{ list1[list1.length] = list2[i];

}
while(i--);

return list1;
}


Note that I use list1[list1.length] = list2[i] instead of list1.push(list2[i]). This is for compatibility with IE 5.

To Do: Make a function that accepts an unlimited number of nodeLists and joins them all.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Tuesday, June 06, 2006

Great Info on Closures in JavaScript

If you ever want to know more than you ever wanted to know about closures in ECMA Script, here's the place to go:
http://jibbering.com/faq/faq_notes/closures.html

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Monday, June 05, 2006

SIFR Alternative - Update

I have posted the latest build of my heading replacement library at http://labs.tom-lee.com/HeadingReplacement/. This build includes numerous performance tweaks, a couple of bug fixes, and a major change to the element selection methodology.

First off, I fixed Ian's bug, where some headings scrolled when highlighted by dragging the mouse. Secondly, I have greatly refined the process by which you specify which heading elements will be replaced, and in the process provided support for multiple fonts. Here's how it works:

1) Specify the path to your fonts in a css font or font-family declaration. Paths must be in double or single quotes:

h1{
font-family:"Swf/FranklinGothicBook.swf", Helvetica, sans-serif;
}


Note that the font lists still work: if you don't include the JS library, the CSS selector behaves as you'd expect it to, and you'd get Helvetica. Also, inheritance works the way you'd expect it to, and you can override the declaration later in the style sheet or in an inline style.

I really like this approach because it allows me to specify fonts where style information should be specified (in STYLE sheets), and it does not require a lot of JavaScript overhead for the purpose of parsing CSS selectors. The swf path is merely passed along in the computed style of the element. Sadly, there is no way I know of to make this approach work in Opera, as it does not support document.styleSheets and it does not pass along the swf path from the font declaration. So, I'm making a decision at this point that I will not make any further efforts to be compatible with Opera. I think it's a safe bet that the few people who do use Opera will not miss the smooth fonts, since the pages will gracefully degrade to normal web text anyway.

My next steps will include tweaking the swf path stuff. Presently, you specify FontName.swf and the parser changes that to FontNameV6.swf and FontNameV8.swf, both of which must be on your server. I'd like to come up with something cleaner, more of a single font package that would work for both version 6 and 8. Also, I have some performance tuning to do in terms of decreasing the number of function calls that are made between the swf files and the JavaScript. I may try to create some kind of automatic switching between a high-performance and low-performance mode.

As always, let me know what you think of the demo!

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Sunday, June 04, 2006

Flash 8 ExternalInterface Crash Bug

This is one of those things that you can stay up until 1 AM trying unsuccessfully to debug, and then the next morning you spot the trouble immediately.

If a swf uses ExternalInterface to call a JavaScript function that removes the swf from the document, the browser will crash. PC Firefox gives the dubiously helpful error "The plugin performed an illegal operation. You are strongly advised to restart Firefox."

Simply delay the removing call using setTimout, and all is well.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Friday, June 02, 2006

SIFR Alternative - Update

As suggested by Scott Moore of nonsponsored.com, I've got dynamic font resizing for Safari 2.0 working. Hey, nothing better to do on a Friday night! It may work in earlier versions of Safari as well, but I have not tested it. As before, the test page is at http://labs.tom-lee.com/HeadingReplacement/. I'll be addressing some other issues soon.

Thanks to everyone who has offered their comments so far. I plan to put some sort of bug-tracking system in place for this project in the near future. Hopefully it will be public so that everyone can be included in the process.

I'm also thinking about giving it an official name... I don't really like calling it "SIFR Alternative", although that does say exactly what it is. Any suggestions?

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Eolas Workaround Fails If Triggered From Deferred Script

As a workaround to the gruesome IE Eolas patch, you must write your SWFs into the DOM from an external JavaScript library or other external source. This can happen via a function call within the body of your document, or can be triggered by an onload event.

These two triggers have their downsides. It is often not desirable to put a JS function call within the body of your HTML document, as this makes your code more difficult to maintain. If you have a large site, you probably want a single library that you can snap in and out at will. A lot of function calls sprinkled throughout your site can make it difficult to remove the functionality if you need to.

As far as the onload event goes, it is better to do any DOM manipulation BEFORE document.body.onload, so that if you are replacing images and so forth, they don't need to be completely loaded before they are replaced. It's about bandwidth savings.

So, I thought I'd be clever and trigger my SWF injection script when the DOM is ready, but before the page load completes by using Dean Edwards IE onload solution. Basically, any script that you include with "defer" in the script tag will execute when the DOM has loaded, but before document.body.onload.

Unfortunately, though the swf is injected into the page properly, the Eolas patch is in full effect complete with the "Click to Activate And Use This Control" message. Check out this test page to see it for yourself.

I've tried a bunch of ways around this. It turns out that if the SWF file is already cached, the Eolas garbage goes away, so I could possibly work out some kind of prefetch scheme. If anyone else has come across this and has a solution, let me know!

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Protecting SWFs

This is by far the most informative article I've found to date on SWF obfuscation and protection techniques. http://www.gotoandplay.it/_articles/2004/04/swfProtection.php - I've been referencing this for years.

Posting it so I never lose it - it wasn't easy to find.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

Thursday, June 01, 2006

SIFR Alternative - Demo Page

As promised, I have been working to clean up my codebase and post a working demo of my SWF Headings library. This is really a proof of concept: it has a few known issues, and is not feature-complete. At the moment, it only supports one font for all heading elements, and the methods for specifying which headings get replaced are not done. But what it does have is dynamic font resizing and dynamic text reflow.

The demo is a liquid layout, so by resizing your browser window, you should see it in action! Also, be sure to do View > Text Size and play with that a bit.

Let me know if you have any problems, and I'll be working in the meantime to iron out the remaining issues.

Without further adieu, the demo.

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.