SyntaxScrewer's Blog

July 21, 2010

Firefox MouseWheel Problem with Flash Embedded Objects.

Filed under: Flash — geekymaira @ 10:19 am

Hey,

It’s been a while since I posted something new on the blog. I remember running into some problems a while back with custom flash scrollbars , the mouse wheel and firefox!

The problem was that my code worked great in flash player but started messing up when I tested it on Firefox after embedding the swf into an HTML. Internet Explorer didn’t have an issue with the scrolling (although I had to click the flash object once to activate it), but for Firefox it failed miserably. So I googled like crazy, found a few workarounds and after reading countless articles and a few code hacks, I discovered that it was a problem with firefox. In very simple words, firefox liked taking control of all the MouseWheel events that occurred on the page. So they never reached my flash object  like I wanted them too : ).  Moreover, I had 2 scrollbars on the stage and one MouseWheel event. So even when the MouseWheel event was passed to my flash object from the browser (if ever), it didn’t control the correct scrollbar. I’m not sure if only 1 worked or both did. It’s been a while.

Anyway, what was the solution ?

Let’s assume that you have an swf with 2 scroll bars, something like the image below.

In your code, you detect where the mouse is on the swf (on top of which display object) and accordingly activate that objects scrollbar
on a mousewheel event. When you publish this as an html and test it on firefox , it might not work as expected. This is due to the following reason. Your browser is taking control over the mousewheel event and is handling it the way it wants. This might mean, that even though you’re detecting the mouse to be over “content b”, when you scroll , the scroll bar for “content a” scrolls. This is one of the problems I was facing.

The solution :

0) Make a function called “handleExternalScroll(event:Object)” in the scrollbar class(es)

1) Use javascript to capture the MouseWheel event for the browser.

2) Pass the event object to flash using ExternalInterface callback.

3) In the flash callback function, detect which object is under the mouse.

4) Create a new MouseEvent using the event object sent from javascript (basically the event.delta)

5) Call the “handleExternalScroll” function for the scrollbar of the object which is under the mouse. Pass the event created in step 4 as the parameter.

6) In the body of handleExternalScroll(event:Object), just dispatch your new event on the relevant display object.

7) Done 🙂

THE HTML :

<html>
<head>
<script type="text/javascript">

	var mouseX,mouseY;
	var IE = document.all?true:false;

	alert("Is IE ? : " + IE);

	//Add an event listener to capture the scroll event [FOR Firefox]
	if (!IE)
	{
    	 if(!(document.attachEvent)) {
        	window.addEventListener("DOMMouseScroll", handleWheel, false);
	    }
	}

    function handleWheel(event) {
		//NOTE : To detect the actual content size in mozilla use event.pageX
		//NOTE : For IE this is different
		getMouseXY(event);

        var app = window.document["myswfid"];  //Pass in the ID of the swf component

		var offsetX=app.offsetLeft;
		var offsetY=app.offsetTop;

//		alert("Value of app is " + app.name);
        if (app) {
            var o = {x: mouseX-offsetX, y: mouseY-offsetY,
                delta: event.detail,
                ctrlKey: event.ctrlKey, altKey: event.altKey,
                shiftKey: event.shiftKey}
          //alert("Mouse_Moved!");
            app.handleWheel(o);
        }
    }

	//Returns the mouseX and mouseY of the browser CONTENT area (- the nonsense toolbar space)
	function getMouseXY(evt)
	{
		//alert("What is event ? : " + evt.pageX);
		//alert("IS IE ? : " + IE);
		if (IE)
		{
		// grab the x-y pos.s if browser is IE
		mouseX = evt.clientX + document.body.scrollLeft;
		mouseY = evt.clientY + document.body.scrollTop;
		}
		else
		{  // grab the x-y pos.s if browser is NS
		mouseX = evt.pageX;
		mouseY = evt.pageY;
	  }
	  // catch possible negative values in NS4
	  if (mouseX < 0)
	  {
		  mouseX = 0;
	  }
	  if (mouseY < 0)
	  {
		  mouseY = 0;
	  }

	}

	</script>
</head>
<body>
<object data="mySwf.swf" name="myswfname" id="myswfid" type="application/x-shockwave-flash" height="550" width="400">
  <param value="always" name="allowScriptAccess">
  <param name="quality" value="high">
  <!-- NOTE : wmode has a tendency to mess up things too. Use it wisely-->
  <param name="wmode" value="transparent">
  <param name="menu" value="false">
  <param name="movie" value="mySwf.swf">
  <embed src="mySwf.swf" quality="high" wmode="transparent" width="550" height="400" name="home" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
</body>
</html>

THE ACTIONSCRIPT :


//Declaring the external interface function
ExternalInterface.addCallback("handleWheel", handleWheel);

function handleWheel(event:Object): void
 {
 //Detect what component the mouse was over and accordingly call the handleExternalScroll function for that componenet
 var obj:InteractiveObject = null;
 var objects:Array = getObjectsUnderPoint(new Point(event.x , event.y));
 for (var i:int = objects.length - 1; i >= 0; i--)
 {
 if (objects[i] is InteractiveObject)
 {
 obj = objects[i] as InteractiveObject;
 //trace("Object under mouse point : " +obj.name);
 //trace("Object Parent Parent: " +obj.parent.parent.name);
 break;
 }
else
 {
 if (objects[i] is Shape && (objects[i] as Shape).parent)
 {
 obj = (objects[i] as Shape).parent;
 break;
 }
 }
 }
if (obj)
{
 var mEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_WHEEL, true, false,event.x, event.y, obj,event.ctrlKey, event.altKey, event.shiftKey,false, -Number(event.delta));
 //obj.dispatchEvent(mEvent);
 if (obj.name == "content1")
 {
 content1ScrollBar.handleExternalScroll(mEvent);
 }
 else if (obj.name == "content2")
 {
content2ScrollBar.handleExternalScroll(mEvent);
 }
 }
 }

//HandleExternalScroll function - NOTE : This is going to be inside your scrollbar class.
public function handleExternalScroll(event:Object):void
 {
 trace("Mouse Scrolled!");
 imageHolder.dispatchEvent(event);
 }

Hopefully, this should work 🙂

Advertisements

2 Comments »

  1. So whats the solution? I’ve had similar probs with ff?

    Comment by Nikos — July 21, 2010 @ 3:03 pm | Reply

    • Hi Nikos,

      I’m updating my post with the solution. It should be up soon 🙂

      Comment by geekymaira — July 28, 2010 @ 12:05 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: