OS X Mouse Wheel Support for Flex 2 Applications
In my current job I have been programming user interfaces for applications that display networks of data (as in nodes, links etc.) with the Adobe Flex framework, and the UI paradigm I have been utilizing is a kind of a Zoomable User Interface (ZUI). The idea there is to enable the user to view and manipulate objects on a two-dimensional plane, and navigate around that plane by zooming and panning.
Now, the easiest way (at least for me) to control the zooming is to use the mouse wheel. Mouse wheel support for Flex is implemented by registering an event listener of type MouseEvent.MOUSE_WHEEL with the DisplayObject that would dispatch the event. Sadly, mouse wheel support is not available in the Mac OS X version of Flash Player. This prompted me to create a custom solution, as my main computer is a MacBook and I would like to be able to test the mouse wheel navigation with my development machine.
Update: The javascript now works with more browsers than just Firefox 2 and Safari 2. I Tested it, in addition to those two, with Opera 9, Camino 1.5 and Omniweb 5.5, and it seems to work in all of them now.
Update #2: Changed the javascript code to also work with Safari 3 beta. When using it, small movements with the wheel do not invoke any action, so you'll have to roll it a bit further to make the app respond.
Update #3: Added statement about licensing the code under the MIT License as per request of Philip Flip Kromer
Update #4 (feb 8, 08): If you're looking for AS3 (not Flex) OS X mouse wheel support, check out PixelBreaker.com.
Update #5 (feb 12, 08): Fljot sent me a version of this that works also in non-Flex AS3 projects. He also fixed some issues in the code related to the automatic registration of listening objects. You can find him here.
The solution has been tested with Firefox 2 and Safari 2 Firefox 2, Safari 2, Opera 9, Camino 1.5 and Omniweb 5.5, and it is based on two main elements:
- JavaScript code that catches mouse events and sends their details through a function call to the Flash app using the ExternalInterface
- An ActionScript 3 singleton class ExternalMouseWheelSupport that registers an ExternalInterface callback for the function call and makes objects that are under the mouse cursor dispatch MouseEvents of type MouseEvent.MOUSE_WHEEL
JavaScript:
Just include the osxmousewheel.js file in your HTML and specify the ids/names of your flash object element and the div element that contains the flash object:
<script type="text/javascript">
var mw_flashMovieId = "flashMovie"; // the id/name of your flash app's HTML DOM element
var mw_flashContainerId = "flashContainerDiv"; // the id/name of the flash element's surrounding div element
</script>
<script src="./osxmousewheel.js" type="text/javascript"></script>
ActionScript:
The singleton has to be created first, and that can be done by getting a reference to the instance property in at least one place:
import org.hasseg.externalMouseWheel.*;
private var _mwSupport:ExternalMouseWheelSupport = ExternalMouseWheelSupport.instance;
Then, all objects that you want to have the OS X mouse wheel support enabled for have to be registered with the ExternalMouseWheelSupport class. This can be done in two ways:
- Manually: This is the more foolproof way. First make sure that the registerAutomatically property is set to false (it is true by default):
- Automatically: This is the easier, but more bug-prone way. Simply make sure that the registerAutomatically property is set to true (it is true by default, so you actually don't even need to do this):
ExternalMouseWheelSupport.registerAutomatically = false;
Then just register the objects one by one:
_mwSupport.registerObject(myBox);
or several at a time:
_mwSupport.registerObjects([myBox, myButton, mySlider]);
ExternalMouseWheelSupport.registerAutomatically = true;
After that, all InteractiveObjects on the stage should dispatch mouse events, so you can normally attach event listeners to them and do whatever you want in them:
myBox.addEventListener(MouseEvent.MOUSE_WHEEL, function(event:MouseEvent):void {
t.text = ("Mouse wheel delta: "+event.delta);
});
The code could probably use some debugging and optimization, but it seems to work well if you're not doing anything too fancy. If you take it and make any fixes, please let me know! ;)
A working example.
The source code for the example.
The AsDoc-generated API Documentation for the support library
This code is distributed under the MIT License.
44 Comments
[…] OS X Mouse wheel support for Flex 2 applicationsIn my current job I have been programming user interfaces for applications that display networks of data (as in nodes, links etc.) with the Adobe Flex framework, and the UI paradigm I have been utilizing is a kind of a Zoomable User Interface (ZUI) …. […]
Hey mate. Great solution, works well in Safari. However, I couldn’t get it to work in Camino. As far as I know, Camino uses the same engine than Firefox?… Could you have a look and let me/us know?
thanks in advance.
Hey Nicolas.
I modified the javascript to work with other OS X browsers, too. See the post for more details. :)
Nice work. I was going to use SWFMacMouseWheel, only to find that it was AS2. I just searched through it and found your post. Again, nice work.
Nice stuff, I have the same trap: dev on macBook fo’ win users.. :) but guys.. I just can’t make it work It’s like:
The error console sais:
1120: Access of undefined property _mwSupport.
Why It doesen’t recognise it?
thx
akay.. you can check it out here.. http://www.figurart.hu/test.mxml
Hi Geza,
Well, you seem to be declaring the variable _mwSupport properly, so that shouldn’t be a problem. In the code you posted, I don’t really see anything wrong. I would just make sure that you actually have an object with the id redArea in there.
Hi, This is great stuff – thanks for figuring this out.
Would you please clarify the license attached to this code? In the US and many other countries, if no copyright is specified then all rights are reserved – so I can’t include your excellent work in other projects.
If you’d like to let anyone do whatever they want with the code, the MIT license is probably easiest: http://www.opensource.org/licenses/mit-license.php
Cheers, flip
In my dev environment using “file://” your code works fine, but it doesn’t as soon as I use “http://”. It doesn’t even brings up an error message.
I have no clue why. Do you have any hints for me??
Regards, Bernhard
Bernhard: Your problem probably has to do with Flash Player’s security sandbox features and the ExternalInterface. Make sure that the javascript file is in the same host and port as the .swf and the page that embeds the .swf and you should be fine.
Nice Site!
Hi there! Nice work, Just a dumb question though (I’m not use to Flex, not sure to know what it is): does this mean that we can add the mouse wheel support (for scrollPanes or whatever) on flash websites (no Flex) ? Tks for your answer
Hi David.
This code is ActionScript 3 and it relies on the use of some Flex classes, but it can be adapted for non-Flex AS3 – I just haven’t done it. If you do, please send me the code or the link to the code and I’ll post it here for others as well. If you use AS2, check out the following link:
http://blog.pixelbreaker.com/2006/11/08/flash/swfmacmousewheel/
thank you
Hasseg, you are a genius.
Unfortunely the example is not working with Opera version 9.23
Thanks for this project Hasseg, however; your example does not work on Win XP SP2 - IE … Any thoughts?
Mike:
I Tried to fix it for the new Opera version but couldn’t find a quick fix and I haven’t had time to go into it more deeply. It has something to do with JavaScript not being able to listen for mouse events inside the div that contains the Flash app, or more likely that Opera just uses some other method for doing it that I couldn’t figure out when I tried to fix it.
Bram:
It seems to work fine on WinXP SP2 when using Firefox. I Don’t have the proper access rights to update the ActiveX Flash player on my work computer (the only Windows box I have available), and it currently has Flash player 8 on it so I can’t test it :( Sorry..
Hasse:
FF & Opera 9.24 work just fine on Windows for me, Internet Explorer is an issue, as I can not see the example. The page is completely empty, as in total blank :).
In case of Vista + IE7?
Win XP SP2
I tried implementing your mouse scroll wheel support using Flex 3 and it worked great locally, but when I put the site up on our web server, it did not work. I had the “allowScriptAccess” set to “sameDomain”, but no go. Do you know if your code should work correctly with Flex 3? Thanks!
Hey Anthony,
I haven’t tried Flex 3 at all so I can’t say if this’ll work with it. For what it’s worth, I believe it should work and your problem is probably based somewhere else, but I can’t say for sure. I Apologize for not having more useful advice but I unfortunately haven’t had time to work on this stuff lately. :(
Very good job!
Bravo!
Bram, I could avoid the bug in IE by wrapping the JS code in the html page in a conditional tag :
var mw_flashMovieId = "flashMovie"; // the id/name of your flash app's HTML DOM element
var mw_flashContainerId = "flashContainerDiv"; // the id/name of the flash element's surrounding div element
guuhhh all tags were stripped in my previous message :(
here’s the code : http://toolateatnight.be/macmousewheel/
Thanks Melvyn, It works on my projects, but not on the example pages provided on this site :)
all right ;)
I used your solution for getting MouseWheel support on Macs and it is fabulous! A while later I discovered that setting wmode=opaque breaks Flash’s MouseWheel in Firefox 2 on Windows. A google search shows it has been a major problem for a lot of Flex developers. So what I did was fall back to your solution. I just commented out the following conditional statement in osxmousewheel.js
//if (navigator.userAgent.indexOf(‘Mac’) != -1)
Now I can have wmode=opaque AND MouseWheel in IE, Firefox, and Safari on both Windows and Mac.
If anyone has any information on making this work in Flex 3 that would be most helpful. I really can’t figure out why it isn’t working, but it works on my local box and not on my server. Also I moved my files to get the error to popup in the local environment and I got this:
TypeError: Error #1009: Cannot access a property or method of a null object reference. at mx.managers::PopUpManagerImpl/addPopUp()[E:\dev\flex_3_beta3\sdk\frameworks\projects\framework\src\mx\managers\PopUpManagerImpl.as:229] at mx.managers::PopUpManager$/addPopUp()[E:\dev\flex_3_beta3\sdk\frameworks\projects\framework\src\mx\managers\PopUpManager.as:167] at mx.controls::Alert$/show()[E:\dev\flex_3_beta3\sdk\frameworks\projects\framework\src\mx\controls\Alert.as:505] at org.hasseg.externalMouseWheel::ExternalMouseWheelSupport/initialize()[/Users/jonathan/Documents/Flex Builder 3/dflex/src/org/hasseg/externalMouseWheel/ExternalMouseWheelSupport.as:64] at org.hasseg.externalMouseWheel::ExternalMouseWheelSupport()[/Users/jonathan/Documents/Flex Builder 3/dflex/src/org/hasseg/externalMouseWheel/ExternalMouseWheelSupport.as:43] at org.hasseg.externalMouseWheel::ExternalMouseWheelSupport$/get instance()[/Users/jonathan/Documents/Flex Builder 3/dflex/src/org/hasseg/externalMouseWheel/ExternalMouseWheelSupport.as:51] at dflex()[/Users/jonathan/Documents/Flex Builder 3/dflex/src/com/dflex/controllers/application.as:18] at _dflex_mx_managers_SystemManager/create() at mx.managers::SystemManager/initializeTopLevelWindow()[E:\dev\flex_3_beta3\sdk\frameworks\projects\framework\src\mx\managers\SystemManager.as:2436] at mx.managers::SystemManager/docFrameHandler()[E:\dev\flex_3_beta3\sdk\frameworks\projects\framework\src\mx\managers\SystemManager.as:2328]
Jonathan
Exact same behaviour on my machines. Can you produce a solution for Flex 3?
Hi guys, I don’t have Flex 3 installed nor have I time to start debugging this with it, but from the error message it seems that it’s failing in the initialize() method:
private function initialize():void {
try {
ExternalInterface.addCallback("dispatchExternalMouseWheelEvent", externalMouseWheelEventHandler);
ExternalInterface.call("mw_initialize");
}catch(e:Error){
Alert.show("Error initializing ExternalMouseWheelSupport: "+e.toString());
}
}
It’s clear that the ExternalInterface method calls are causing a problem there, so I think the way to start debugging is to check if any security features are blocking it.
stab in the dark… allowScriptAccess=“samedomain” ?
Anyone close to converting this for AS3 use in Flash, rather than Flex?
http://toolateatnight.be/macmousewheel/
Sources : http://toolateatnight.be/macmousewheel/mac_mousewheel_AS3.zip
I modified the class in a new one “ExternalMouseWheelSupportFlash.as” with the Flex-specific stuff stripped out.
Yay!! This made my day. Thanks thanks thanks.
I made it work with Flash AS3.
PixelBreaker has updated his mac mousewheel support for AS3 : http://blog.pixelbreaker.com/flash/as30-mousewheel-on-mac-os-x/
Thanks for the info, Melvyn. I Put a link to the top of the page for that to guide people looking for an AS3-only solution there.
Just a note. The PixelBreaker solution will work with all Flex applications, not just AS3 projects. Just change the line in the PixelBreaker example:
MacMouseWheel.setup(stage);
to:
MacMouseWheel.setup(Application.application.stage);
I put this line in my applicationComplete event handler, although it may work elsewhere.
[…] the mouse wheel work in Flash on OS X (it doesn’t by default) by using Ali Rantakari’s excellent ExternalMouseWheelSupport package. The The GAE SWF Project version 1.34 article by Aral Balkan, unless otherwise expressly […]
Hey everyone, just posting this into the comments here in case someone has subscribed and would thus like to be informed of this.
I’ve just made a post about the new version (2) of this solution – check it out:
://hasseg.org/blog/post/138/os-x-mouse-wheel-support-for-actionscript-3-flash-applications-v2/
[…] You can find the full explenation on this blog post. […]
[…] I’ve finally updated the solution I’ve made earlier for enabling Mac OS X mouse wheel support in Flex applications to a second version. I didn’t want to continue adding stuff into the original post, so I decided […]
Awesome. Thanks!!