André Gil's Blog

UX, Dev, Tech and so on…

Bugzilla and Attached Images

I hate Bugzilla… It’s ugly, hard to use and has one of the the worst UI and UX that I know of. But the thing that annoys me most is when you have some image attached, you cannot open it. When you click at the link, it will download the image and then, you’ll be able to open it.

I know that’s configurable, and it’s for a security reason, but this is the default behavior and most admins don’t change it! So I’ve made this simple bookmarklet to solve the problem. Just create a bookmark for the link bellow and, when you open some bug, just click the link:

1
javascript:(function(){var d;var c=0;while(d=document.getElementById("c"+c)){var b=d.getElementsByTagName("a");for(i=0;i<b.length;i++){var a=b[i].href;if(a.indexOf("attachment.cgi")>-1&&a.indexOf("action=edit")==-1){d.innerHTML+='<img src="'+a+'"/><br/>'}}c++}})();


And if you are interested in the simple unobfuscated code, here it is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(function(){
   
    var commentDiv;
    var commentId = 0;
   
    while( commentDiv = document.getElementById("c" + commentId) ) {
   
        var links = commentDiv.getElementsByTagName("a");
       
        for ( i=0; i < links.length; i++ ) {
           
            var href = links[i].href;
           
            if( href.indexOf("attachment.cgi") > -1 && href.indexOf("action=edit") == -1 ) {
               
                commentDiv.innerHTML += "<img src=\"" + href + "\"/><br/>";
            }
        }
       
        commentId++;
    }

})();

Enjoy! ;)

How many real Twitter followers do you have?

If you check the profile of all your new followers on Twitter, you’ll notice that many of your followers are just trying to get as many followers as possible by following a lot of people and expecting that they will be followed back.

So I was wondering here, how many real followers do I have? To answer this question, I’ve made this simple tool in 5 minutes to check that for me. This tool will only consider someone “real” when they follow less than 100 people or they follow twice as many followers as they have, at maximum.

So check it out and tell me what you think… ;)

Update: Some Twitter API responses has changed. Code fixed now!

DownFlickr – Flickr Downloader

I always loved photography, since I was young. And since Flickr is probably the best place on the internet to find great photos and inspiration, I always spent a lot of time there looking for great photos and photographers.

One thing that I never liked on Flickr, is how hard it is to download photos. You have to open the photo, click on the “All sizes” option, choose the best quality, right click it and save. Imagine that if you want to save a whole Set of photos? It’s a nightmare!

DownFlickr - Flickr Downloader

That’s why I’ve created DownFlickr! It’s a Google Chrome extension, that helps me to download single photos or full sets automatically. I’ve programmed it at one night, just because I wanted to download a Set with more than 100 photos and I never thought it would help so many people. It’s not even that good, it’s just really helpful. But now it has 2200+ users and it’s featured on first page when you search for “flickr” on Chrome Extensions page.

So I’ve decided to share the code with you guys on Github. You can download the extension or get the source code, fork it and help with bug fixes or new features. =]

UX At The Pharmacy

Just a quick post to talk about UX (User eXperience). Do you still think that UX is only software-related? Do you still think UX is only usability and/or design? UX is all about what the user feels when he is using some product or service.

Pharmacy UX

Click on the photo to read it! ;]

I took this photo at some drugstore, in New York. Think about what the user (or customer) would feel when he has some problem, and he needs some medication, but doesn’t want to think or remember complex medication names.

I know that, in this particular case, there may be some problems like allergies or just hiding the real problem, instead of solving it. But I still think it’s a great idea, great design and it probably has some advices at the back, informing the medicine name and precautions.

But the message here is: UX is Everywhere! [F]

Think about it.

Firefox and the Flash/Flex focus problem

I’m working in a Flex project and the client asked for some Keyboard Shortcuts. It works great on Google Chrome and IE but, for some reason, Firefox doesn’t handle embedded objects focus correctly sometimes.

To “fix” this problem, I found a really nice workaround. First, you have to open your application on some browser and look at the source code. Then, look for the <object> tag “id” attribute inside it. If you use the default Flex template, it will probably be your Application name. In my case, it’s “index”. So I wrote this JavaScript line to set the focus on your application again:

1
document.getElementById('index').focus();

Now, to use it on your code without rewriting your template, you can do this:

1
2
navigateToURL(new URLRequest("javascript:try{ document.getElementById('index').focus(); void(0); }catch(err){}"), "_self");
someComponent.setFocus();

It works better if you try to identify when your application is loosing the focus (always when I opened a popup, in this case) and put the code after that. I also used a try/catch to avoid problems, like if the user opened the SWF directly.

I hope it helps someone!
Bye o/

Version-safe Monkey Patch on Flex components

What? Why?

Sometimes we want to add some custom behavior to a Flex component and everything you need is private or you find some bug that you can’t fix only with inheritance. Or maybe you can, but if you do, you’ll have to change all instances to your component. And sometimes you even can’t change the instance, like when you are using some closed library.

Today I was trying to fix a bug at the ComboBox component, using the Flex SDK 3.5. This bug was already fixed on the version 3.6, but I can’t update if they don’t release it as a stable version. This bug is very stupid and a simple method override with 3 lines of code would solve my problem. But, like I said, I can’t just change all the ComboBox instances in my application. And, even if I did, maybe some other developer could use the original ComboBox, instead of my FixedComboBox.

So I decided to temporarily Monkey Patch the ComboBox class. To do that, I just had to copy the original ComboBox class and all the includes, fix what I wanted and put it at the same package, but inside my project “src” folder. The compiler will use my patched version and ignore the original class.

The problem:

Okay, but what if we forget to remove the patched version when we update the SDK? Everything is Flex 4 now, so maybe they will only release the SDK 3.6 version in some months. And maybe in some months I will be working in a different project, don’t know…

The solution!

So I was thinking… How can I check if the SDK version was updated?

Every Flex component includes a file called “Version.as”, that have only one constant with the SDK version. Most people just copy this file when they are “Monkey Patching”, but if we do that, it will replace the SDK “Version.as” file and we will never know the correct version.

The trick is: don’t copy this “Version.as” file to your project. Then replace the include with the constant inside the file. Find this line:

1
include "../core/Version.as";

and replace with:

1
2
3
4
5
/**
 *  @private
 *  Version string for this class.
 */

mx_internal static const VERSION:String = "3.5.0.12683";

Now we don’t need to copy the file and we can have different versions for the SDK and the patched components. And you can add this code inside your constructor to check if the version changed:

1
2
3
4
5
6
if( FlexSprite.mx_internal::VERSION != mx_internal::VERSION )
{
    setTimeout(function():void{
        throw new Error("The SDK version was updated. Please update or remove the Monkey Patched ComboBox from this project.");
    }, 1);
}

That’s it!

FAQ:

Why FlexSprite?
I was thinking about using UIComponent, but maybe you’ll Monkey Patch it too. So I think you don’t need to change anything inside FlexSprite.

Why throwing an error?
You can change it to a trace(), but will you read the console all the time? And don’t worry, only people with the debugger Flash Player can read this error anyway.

Why the setTimeout()?
If you throw an error inside your constructor, it will break your application. I tried callLater(), but other things in Flex use the callLater() queue and, if you throw an error there, it will break the queue. So I think the setTimeout() is a safe place to put it.

Conclusion:

Monkey Patch is not the best solution. Actually, it’s not even a good solution! But it’s necessary sometimes and, if you really need it, I think the version check code is a good thing to help you.

Do you have some alternative solution? I would love to read it at the comments!

Cheers!

How to develop and debug Flex on Google Chrome

Developing and debugging Flex applications on Google Chrome sometimes can be a little tricky, but I will show you here how to solve this common problems.

Configuring Eclipse

First, you have to configure Eclipse. Open Preferences > General > Web Browser and select “Use external Web Browser”. Then, click on “New” and add “Google Chrome” using the following Location:

1
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome


Your configuration should look like this:

If you are using Windows, you should click “Browse…” and find your Google Chrome application .EXE file.

Debug Flash Player

Google Chrome have it’s own Flash Player, so even if you download the debugger version, you may have problems to debug. So first, if you don’t have the debugger version, download it.

If you already downloaded and restarted Google Chrome, open this URL:

1
about:plugins


You may notice that you have two versions installed and one version “Location” is inside Google Chrome’s directories. So, you have to Disable this version and keep the other I’ve just installed. It should look like this:

Update: If you can’t disable plugins, download the Google Chrome development version here.

After that, right click any flash content and look for the option “Show Redraw Regions”. If you have this option, you’re using the debugger version.

Cache Problems

If you keep refreshing your application all the time, you may have some problems with caching. And, since I don’t think Chrome have some quick setting to disable cache, I’ve created a simple application that will launch Google Chrome with some command line parameters that temporarily disable cache.

To use it, download the application, unzip it and move the app to the Applications folder. Then drag the icon to the Dock, if you want quick access:

Notice that, since Google Chrome will keep only one initial instance, you have to launch it using my app at the first time if you want no cache. If Chrome is already running, it will still keep caching files. If you want your cache back, just quit and open Chrome using the regular app icon.

For windows users, I think you can copy your regular Google Chrome shortcut, right click the copy, select Properties, and add this command line parameters:

1
--disk-cache-size=1 --media-cache-size=1

This beautiful black Chrome icon was created by GreasyBacon. Don’t forget to check his other works.

Conclusion

That’s it! The only problem that I’m still trying to solve, is when you use the option “Find in Language Reference”. It will not open! If I find some solution, I will update this post. Do you know how to solve it? Leave a comment!

Cheers.

Popout Flash Content (Videos, Games, etc) using this Bookmarklet

Sometimes, when I’m reading blogs, I want to watch some embedded video while I keep surfing on the older posts. Some websites give you the option to open the video in a new window, but this option is not always available. That’s why I created this Bookmarklet!

Just right click on this links below and add, or drag them, to your bookmarks. So when you want to pop out some video, or other embedded content, just click on this links on your bookmarks. Always try the first one and, if it doesn’t work, try the second one.

[Popout Flash] [Popout Flash (Alt)]

I hope you like it.. See ya!!

How to get BitmapData and ByteArray from Embed in Flex?

When you want to manipulate images and other file types in Flex, most of the time you need the BitmapData or the ByteArray from that file. Most people know how to get it when they are using the Loader, but it’s harder to find information about how to get it using Embedded files. It’s really easy to do that, let me show you how!

If you want to Embed some image (JPEG, GIF or PNG) in Flex, you have to Embed it into a Class. What most people doesn’t know is that the type of this Class will by the BitmapAsset and that BitmapAsset is a subclass of the Bitmap class. So you can do this:

1
2
3
4
5
6
7
8
[Embed(source="image.png")]
public var MyEmbed:Class;

private function getBitmapData():BitmapData
{
    var bitmapAsset:BitmapAsset = new MyEmbed();
    return bitmapAsset.bitmapData;
}

Now, to get the ByteArray, you need a little trick! You have to add the parameter mimeType="application/octet-stream" to the Embed metadata. With this parameter, the Class type will be ByteArrayAsset and that’s a subclass of ByteArray. So you can do this:

1
2
3
4
5
6
7
8
[Embed(source="image.png",mimeType="application/octet-stream")]
public var MyEmbed:Class;

private function getByteArray():ByteArrayAsset
{
    var byteArrayAsset:ByteArrayAsset = new MyEmbed();
    return byteArrayAsset;
}

This way, you can even Embed some TXT or XML file in your application and read it very easily! The ByteArray can be converted to a String:

1
2
3
4
5
6
7
8
[Embed(source="myTextFile.txt",mimeType="application/octet-stream")]
public var MyEmbed:Class;

private function readEmbeddedTxt():String
{
    var byteArrayAsset:ByteArrayAsset = new MyEmbed();
    return byteArrayAsset.toString();
}

Easy, huh?

Gif2TileSet: Extract GIF frames into a Tile Set

Some weeks ago I started studying some animation techniques in Flash games and I started making some Blitting experiments. I will post something about it soon, but the point is that to make an animation you first need the graphics and, as your probably don’t know, I suck at drawing! So the first step was ripping some sprites and I remembered about some really nice animated GIFs I’ve seen some months ago.

So I got the GIFs and tried to find some tool to extract all the frames and I didn’t find anything good for it. I know I can use the Adobe Fireworks to do that, but then I will have to copy frame by frame at the perfect position to do the blitting… So I’ve decided to make my own tool to do the job!

Gif2TileSet

Using the as3gif project I wrote a very simple and experimental tool to do the job and I decided to publish as Open Source to, maybe, help somebody else that is studying those techniques. You can even get the code and see some blitting there too! ;)

On this example I used the character “Infierno Púrpura” from this really beautiful final project game called “Ay, Caramba!” (thank you Jujuqui!):

Infierno Púrpura

And I’ve got this result:

Sample Tile Set

So that’s it! Check out the Gif2TileSet demo and, if you really like it, fork the code on GitHub and make your own improvements.

How to remove Event Listeners with parameters / closure?

On my last post, shaokai asked me how to remove those event handlers added dynamically with parameters and I think it’s a really good question, so I’m posting the solution here too.

Actually, I never tried to remove the listener, but you can’t do this the same way you add the listener. So I found two different solutions to this problem. First, but maybe not the best solution, you can keep a reference to your handler, like this:

1
2
3
4
5
6
7
8
// Keep the reference
var myHandler:Function = buttonHandler(0x0000FF);

// Add the listener
myComponent.addEventListener(MouseEvent.CLICK, myHandler);

// Remove the listener
myComponent.removeEventListener(MouseEvent.CLICK, myHandler);

This solution is valid when you can keep references to your handlers, but when you have many handlers with different parameters, it’s hard to keep all the references. So I found a generic solution to remove event listeners, so you can do this, inside your handler function:

1
2
3
4
5
6
7
8
9
10
private function buttonHandler(color:uint):Function
{
    return function(event:MouseEvent):void
    {
        box.setStyle("backgroundColor", color);
       
        // Remove the handler
        event.currentTarget.removeEventListener(event.type, arguments.callee);
    }
}

Passing parameters to Event handlers

One year ago I asked Beck Novaes how to pass parameters to Event Handlers added dynamically, because when you add a Event Listener using myComp.addEventListener(...), the handler must wait only one event parameter. So Beck came up with a solution, but he stated that this is just one “alternative” solution, not the better one.

Some days ago I was working with simultaneous requests to the server and I wanted to keep the data I sent on the request but I didn’t want to return it from Java, so I came up another solution. Assuming that your Event Handler is waiting a Function that have only one Event parameter, I created another Function that returns a Function waiting the Event parameter. But the trick is that the Function Closure scope allows you to access parameters passed to the first and the second Function, so you can do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" height="100%" width="100%"
    initialize="initApp()">

    <mx:Script>
        <![CDATA[
            private function initApp():void
            {
                buttonA.addEventListener(MouseEvent.CLICK, buttonHandler(0x0000FF));
                buttonB.addEventListener(MouseEvent.CLICK, buttonHandler(0xFF0000));
            }

            private function buttonHandler(color:uint):Function
            {
                return function(event:MouseEvent):void
                {
                    box.setStyle("backgroundColor", color);
                }
            }
        ]]>
    </mx:Script>

    <mx:HBox>
        <mx:Button id="buttonA" label="Blue"/>
        <mx:Button id="buttonB" label="Red"/>
    </mx:HBox>

    <mx:Box id="box" height="80" width="200" backgroundColor="#FFFFFF"/>

</mx:Application>


And now, what if you want to use this Event Handler directly in MXML? Well, you can’t do this:

1
<mx:Button label="Green" click="buttonHandler(0x00FF00)"/>


This will not work because the Function that returns from the first one is waiting the Event parameter. So you can do this:

1
<mx:Button label="Green" click="buttonHandler(0x00FF00)(event)"/>


Weird, huh? Maybe another FreaktionScript pattern?

Hello world!

Hello and welcome to my new blog!!

I’m a Brazilian developer and I’ve been working with Adobe Flex and Java since 2006. I also know something about Web Development (PHP, CSS, JavaScript, Ajax, etc) and a little bit of .NET. Recently I’ve been studying about GameDev, not that I want to make games, but I want to learn more about Flash drawing, performance optimization and physics in programming. So here I want to share some of my knowledge with you guys. I hope you all enjoy reading as much I enjoy writing. See you later!!

——————-

Olá, bem-vindos ao meu novo blog!!

Bem, antes de tudo gostaria de avisar que pretendo postar apenas em inglês por aqui, para assim poder atingir um número maior de pessoas. Também porque quero melhorar a minha escrita em inglês, pois como vocês podem ver, ainda cometo vários errinhos básicos as vezes. Caso não consiga ler nada de inglês, você poderá encontrar alguns de meus artigos em português no Blog da DClick ou utilizar o Widget de tradução na barra ao lado.

Sou programador e tenho trabalhado com Adobe Flex e Java desde 2006. Conheço também um pouco de Web (PHP, CSS, JavaScript, Ajax, etc) e já trabalhei com .NET. Atualmento estou estudando um pouco de desenvolvimento de jogos, não que eu queira desenvolver um jogo, mas pretendo aprender um pouco mais sobre a API de gráficos do Flash, otimizar performance e sobre física em programação. Quero aqui compartilhar um pouco do meu conhecimento e espero que gostem de ler tanto quanto gostei de escrever aqui. Até logo!!

André Gil