Tracing output with line numbers
Problem:
When coding AS3, the trace() function comes in very handy for debugging.
In some cases however, it can be quite annoying as well. Sometimes you don’t remember where you put the trace() action,
or you get an output, from which you don’t know exactly where it comes from. Also, when adding trace() actions,
it can take you some seconds to find where this trace() -code is written, especially in bigger classes or functions.
A few seconds might not seem much, but at the end of the project, it’ll be a lot of seconds lost, and a lot of frustration comes along with it.
Solution:
I’ve written a class called DebugTracer, which will output your message, and add a prefix to it, which indicates the ClassName and line number of the trace action.
How it works:
It’s a bit of a trick. Line numbers are not directly accessible in AS3.
However, when an error occurs, the error information output contains the ClassName and line number of the code that generates the error.
In AS3, we refer to this info as the stackTrace. So the trick is to create an error object, and get this information out of the errors stackTrace.
Example:
Let’s output a classic “Hello world”.
Using the basic built-in trace() action:
trace ("Hello world");
// output: Hello world
And now the same thing with the DebugTracer class:
DebugTracer.getInstance().report ("Hello world");
// output: DebugExample (Line 21): Hello world
Additional Info:
Because the DebugTracer class works with errors, it needs a debugger version of flash player to make this work.
Also, in order to get the line number, you need to check “Permit debugging” option in the Publish Settings>Flash.
If not, only the ClassName will be added to the prefix.
Files:
You can download the DebugTracer Class here:
DebugTracer.zip
Admin section won’t load properly
Problem
A problem that a lot of people seem to encounter when working with Drupal and especially after a new installation, is the fact that the admin section loads very slow or sometimes not at all. This is due to the fact that Drupal by default is configured to automatically check for updates. Often this is blocked however causing Drupal to keep trying.
Solution
You could solve this by disabling the Update module in the Modules section but sometimes it’s impossible to get to that page due to the problem.
A second option is to disable it manually by going to the ’system’ table in your Drupal MySQL database, explore the table and look for the ”modules/update/update.module’ entry.
Once you have found it, edit the status field of the module to 0 (should have been 1). Your problem is most likely fixed now.
Some pointers:
- Drupal needs at least 16MB to run properly - if you feel your local configuration is running very slow, verify your apache settings and change the memory limit to a higher number (like 64M)
- Importing sql.zips can sometimes fail, in this case you could try adjusting the maximum allowed packet size in your mysql settings.
==> the best solution however is to export all your tables except the ‘watchdog’ table and every table with ‘cache’ in it’s tablename as these are the ones to take up most of the volume.
PHP closing tags
A little something I found out recently :
when you’re writing a PHP script, you don’t need to end your file with closing tags. In fact, this is better because it removes the chances of having troubles with invisible spaces or line endings.
so, not this:
<?php
echo “Very nice!”;
//closing tag
?>
But rather just this
<?php
echo “this is even better!”;
//no closing tag
AnalyticsManager with multi-tracker support
Problem:
I was working on an international website for Le Pain Quotidien.
Depending on which country is chosen on the homepage, an other Google Analytics Tracker had to be used.
Solution:
I wrote a class which allows to create trackers at Runtime, and send tracking information to a specific tracker.
How it works:
The system consists of 2 classes:
- An AnalyticsManager class, which allows to add or remove trackers at runtime.
- An AnalyticsTracker class, which uses ExternalInterface to send the tracking-information to it’s associated tracker.
Code in AS3:
var analytics:AnalyticsManager = new AnalyticsManager ();
analytics.addTracker ("pageTracker1");
analytics.addTracker ("pageTracker2");
analytics.getTracker ("pageTracker1").track ( "tag_for_tracker_1" );
analytics.getTracker ("pageTracker2").track ( "tag_for_tracker_2" );
Code in HTML:
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker1 = _gat._getTracker("UA-xxxxxxx-1");
var pageTracker2 = _gat._getTracker("UA-xxxxxxx-2");
pageTracker1 ._trackPageview("/home");
</script>
Files:
You can download the files here:
AnalyticsManager.zip
The class uses a HashMap to save the trackers.
The HashMap classes are included in the zip-file.
AIR Updater
I’ve written a class to make the updating process of AIR-projectors easier.
The class uses the great AIRRemoteUpdater classes, written by Claus Wahlers (http://codeazur.com.br/lab/airremoteupdater/).
How it works:
You create an AIRUpdater object, configure the wanted listeners, and ask it to check for an update.
Code in AS3:
var updater:AIRUpdater = new AIRUpdater ("path_to_air_file", true, true);
updater.addEventListener(AIRUpdaterEvent.COMPLETE, updateCompleteHandler);
updater.addEventListener(AIRUpdaterEvent.CONFIRM, updateConfirmHandler);
updater.addEventListener(AIRUpdaterEvent.WARNING, updateWarningHandler);
updater.addEventListener(AIRUpdaterEvent.CONNECTION_ERROR, updateErrorHandler);
updater.update();
function updateCompleteHandler(event:AIRUpdaterEvent):void
{
// Starting application.
}
function updateConfirmHandler(event:AIRUpdaterEvent):void
{
// Update confirmation requested.
// Current version: updater.localVersion
// Remote version: updater.remoteVersion
// on confirm: updater.update (false);
}
function updateWarningHandler(event:AIRUpdaterEvent):void
{
// Update warning message.
updater.install ();
}
function updateErrorHandler(event:AIRUpdaterEvent):void
{
// Update file not found.
}
The constructor of the class requires the path to the air file, and gives you the choice to stop the updating process for a confirmation and/or a warning.
Files:
You can download the zip-file here:
AIRUpdater.zip
I’ve included the original AIRRemoteUpdater classes in the zip file.
Note that these classes are not written by me, so more recent versions might be available.
full screen swf flash background
The problem:
For a project we were trying to make a Drupal based site a bit more attractive, by adding a full screen flash background.
The SWF had to scale with the browserwindow - and stay fixed in the window during scolling.
The solution:
HTML:
Make sure the flash div comes first - otherwise it won’t work.
since this solution doesn’t work in IE6 (go figure) - we only embed the swf when your browser is greater than IE6
<!--[if gt IE 6]><!--> <div id="flash"> place your swf here </div> <!--><![endif]--> <div id="wrapper"> your sites content </div>
Â
CSS:
We position the flash div fixed to the upper left corner of the . This way the flash stays on the same place while scrolling.
The Z-indexes make sure the Flash div is positioned behind the website content.
#flash {
background-color: #000000;
height: 100%;
position: fixed;
top: 0;
width: 100%;
z-index: 0;
}
#wrapper {
position: relative;
z-index: 1;
}
Further issues:
- doesn’t work in IE6
- no mouse pointer in Safari when hovering over links (even when added in CSS)
Finding videos or other files by directory listing
I just found this google command to search videos or other files in directories with a specific name
-inurl:htm -inurl:html -inurl:asp intitle:�index of� + (flv|avi)
Easy for finding some quick examples in a specific format.
Font embedding solution for AS3
The problem:
When embedding fonts in Flash or Flex the size of the swf becomes too big to be useful. If we embed simplified Chinese (13746 glyphs) the size of an empty swf with only a text-field is a whopping 3.9MB. Using flash with dynamic text together with embedded fonts is a real pain in the *ss. It seems there is no way to just use the glyphs you need and embed them at run-time.
Our solution:
When you load a swf in another swf the fonts embedded in the first swf become available in the second. So what if we compile an swf on the server with the letters we need and embed this swf as a “fontlibrary” in your main project. Because the flex SDK is now opensource (link) we can use flex without any extra cost to compile our fontlibrary in realtime on the server.
Example:
Here some code snippets to explain how we do it. It is not the full solution but just ask and i will complete the code some more
First we create an *.as file to compile on the server:
package {
import flash.display.Sprite;
import flash.text.*;
public class ArialFontLib extends Sprite {
[Embed(source='ARIALUNI.TTF', fontName='_Arial', mimeType="application/x-font-truetype", unicodeRange = '@1@')]
public static var _Arial:Class;
public function ArialFontLib()
{
super();
Font.registerFont(_Arial);
}
}
}
We replace the @1@ tag with the unicode letters. Here an example of the [Embed] line after php reads the file and replaced the @1@ tag with the letters it got from the cms (drupal in this case)
[Embed(source='ARIALUNI.TTF', fontName='_Arial', mimeType="application/x-font-truetype", unicodeRange = 'U+6B61-U+6B61,U+8FCE-U+8FCE,U+9032-U+9032,U+5165-U+5165,U+5BCC-U+5BCC,U+901A-U+901A,U+8CC7-U+8CC7,U+7522-U+7522')]
Because the unicodeRange parameter needs a range we just repeat each code and thus create a 1 glyph range. As a font we use the Arial Unicode font.
Then we compile the as file with the following command in php:
exec("c:\flex\bin\mxmlc c:\fontdemo\ArialFontLib.as -managers flash.fonts.AFEFontManager -output fontlibrary.swf");
Note the -managers flash.fonts.AFEFontManager, this extra fontmanager is necessary to make it work and it is only available when you install the full flex 3 sdk (so not the light ones).
When this is done we just load the fontlibrary.swf we just created in our Flash project where we need the font.
The new font is available with the name “_Arial”.
Extras
Now we can create a service which generates a fontlibrary file when needed, we can use the function hasGlyphs to check if a textField can display the glyphs otherwise use the external fontlibrary. Here a little snippet to give you some idea how this should work.
public static function giveFormat(str:String, size:Number):TextFormat {
var myFormat:TextFormat = new TextFormat();
for each (var f:Font in Font.enumerateFonts()) {
//trace(f.fontName);
if (f.fontName == banner.externalFontName) {
var t:Font = f;
}
}
if (f.hasGlyphs(str)) {
myFormat.font = banner.externalFontName;
}else{
myFormat.font = banner.defaultFontName;
}
myFormat.size = size;
return myFormat;
}
But more about this automated class solution later.
Recent Comments