2

Ok so first I was having 2 issues with default wmode of "window". My web page navigation menus would go under my flex/flash app. The other issue was when scrolling in the flash app the whole page would scroll.

I changed wmode to "opaque" and this fixed the issue with the navigation menus and so now they show up above the flash app. Thats great but now I dont have scrolling at all in the flash app.

I realize this is a big issue out there but I can't seem to find any solutions for solving both(actually 2.5 issues) of these problems.

I would like to A) Have navigation links show up above the flash app so they aren't hidden; B) Allow scrolling within the flash application; and C) Prevent scrolling of the web page if the mouse is over the flash app.

If you guys have any ideas that would be fantastic. :) Thanks in advance.

MurderDev
  • 157
  • 1
  • 10
  • 1
    possible duplicate of [MouseWheel not working when published movie has wmode="transparent"?](http://stackoverflow.com/questions/313966/mousewheel-not-working-when-published-movie-has-wmode-transparent) – zzzzBov Mar 29 '11 at 18:52
  • 1
    wmode=transparent & wmode=opaque behave the same as far as mousewheel. – zzzzBov Mar 29 '11 at 18:53
  • I agree with zzzzBov. Are you sure that something on your HTML page in the JS code isn't gobbling up the mousewheel and stopping propagation before it can reach the swf? – scriptocalypse Mar 29 '11 at 19:13
  • wait, so you want your flash app to scroll when you use the browser's scrollbar? – J_A_X Mar 29 '11 at 19:18
  • Actually, it's not quite clear what you mean by "I don't have scrolling at all". Can you click anything in the swf at all? It's possible that an "invisible" div is overlaying the swf (in part or in full) and completely blocking input to the parts of the swf obscured by the div. Are you absolutely positive that nothing in the HTML page is "in the way?" – scriptocalypse Mar 29 '11 at 19:29
  • I can click and use the flash app fine in any mode. Mouse wheel scrolling (its a mapping app similar to google maps) does not work at all. If its in window mode it does. The problem is a common issue with wmode when not set to window will not pass on scrolling events to the flash app. zzzzBovs link may be what I need. – MurderDev Mar 29 '11 at 20:04
  • @scriptocalypse, it's not the HTML, it's [a bug with flash](http://cookbooks.adobe.com/index.cfm?event=showdetails&postId=13086). – zzzzBov Mar 29 '11 at 20:34
  • @zzzzBov Thank you for the link, that's good information to have. – scriptocalypse Mar 29 '11 at 20:36

3 Answers3

5

What I meant when I wrote:

wmode=transparent & wmode=opaque behave the same as far as mousewheel.

is that both modes do not capture the MOUSE_WHEEL event in flash in most browsers (I believe IE is the only browser to capture the MOUSE_WHEEL event properly).

The solution is to listen for the MOUSE_WHEEL event via JavaScript:

//ie handles wmode=transparent correctly
//every other browser uses addEventListener
if ( !document.attachEvent )
{
  //console.log('attached');
  window.addEventListener('DOMMouseScroll', scrollListener, false);
  window.addEventListener('mousewheel', scrollListener, false);
}

scrollListener( e )
{
  var delta
  if ( e.wheelDelta )
  {
    delta = e.wheelDelta / 40;
  }
  else if ( e.detail )
  {
    delta = -e.detail;
  }
  //do stuff with delta
}

You'll then need to use ExternalInterface.addCallback to set up a callback for JS to alert flash that a MOUSE_WHEEL event took place.

wmode=transparent & wmode=opaque have issues with other mouse events as well.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
1

Fix for no MouseWheel in a Flex app when wmode="opaque" (it actually works in IE, just not Firefox or Chrome, probably not Safari or Opera either). This also fixes the different MouseWheel scroller rates between Firefox and everything else.

Add this JavaScript to your wrapper: .

        if(window.addEventListener) {
            var eventType = (navigator.userAgent.indexOf('Firefox') !=-1) ? "DOMMouseScroll" : "mousewheel";            
            window.addEventListener(eventType, handleWheel, false);
        }

        function handleWheel(event) {
            var app = document.getElementById("YOUR_APPLICATION");
            var edelta = (navigator.userAgent.indexOf('Firefox') !=-1) ? -event.detail : event.wheelDelta/40;                                   
            var o = {x: event.screenX, y: event.screenY, 
                delta: edelta,
                ctrlKey: event.ctrlKey, altKey: event.altKey, 
                shiftKey: event.shiftKey}

            app.handleWheel(o);
        }

And drop this support class into your main MXML file (Declarations for Flex4): .

package {
import flash.display.InteractiveObject;
import flash.display.Shape;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.external.ExternalInterface;
import flash.geom.Point;

import mx.core.FlexGlobals;
import mx.core.UIComponent;
import mx.events.FlexEvent;

public class MouseWheelSupport {

    //--------------------------------------
    //   Constructor 
    //--------------------------------------

    public function MouseWheelSupport() {
        FlexGlobals.topLevelApplication.addEventListener(FlexEvent.APPLICATION_COMPLETE, attachMouseWheelHandler);
    }

    //------------------------------------------------------------------------------
    //
    //   Functions  
    //
    //------------------------------------------------------------------------------

    //--------------------------------------
    //   Private 
    //--------------------------------------

    private function attachMouseWheelHandler(event : FlexEvent) : void {
        ExternalInterface.addCallback("handleWheel", handleWheel);
    }

    private function handleWheel(event : Object) : void {
        var obj : InteractiveObject = null;
        var applicationStage : Stage = FlexGlobals.topLevelApplication.stage as Stage;

        var mousePoint : Point = new Point(applicationStage.mouseX, applicationStage.mouseY);
        var objects : Array = applicationStage.getObjectsUnderPoint(mousePoint);

        for (var i : int = objects.length - 1; i >= 0; i--) {
            if (objects[i] is InteractiveObject) {
                obj = objects[i] as InteractiveObject;
                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,
                                                     mousePoint.x, mousePoint.y, obj,
                                                     event.ctrlKey, event.altKey, event.shiftKey,
                                                     false, Number(event.delta));
            obj.dispatchEvent(mEvent);
        }
    }
}
}
Kevin Gallahan
  • 1,645
  • 10
  • 9
1

I was actually able to solve all three issues after that good link from zzzzBov. This lets me pass the mouse scrolling to the flash app while only doing this if the mouse is over the flash app. It also allows my flash app to stay in "opaque" mode so that it is not above the other HTML elements on the page.

An example of this is found here

Javascript

$(document).ready(function () {
        $('#MapSWFDiv').bind('mousewheel', function (event) {
            HandleMouseWheel(event);

            return false;
        });

        //Firefox
        $('#MapSWFDiv').bind('DOMMouseScroll', function (event) {
            HandleMouseWheel(event);

            return false;
        });
    });

    function HandleMouseWheel(event) {
        var app = GetMapSWF();
        if (app) {
            var delta = event.wheelDelta ? event.wheelDelta : event.detail;

            var o = { x: event.clientX, y: event.clientY,
                delta: delta,
                ctrlKey: event.ctrlKey, altKey: event.altKey,
                shiftKey: event.shiftKey
            }

            app.HandleMouseWheel(o);
        }
    }

Flex

protected function appComplete():void  {
    ExternalInterface.addCallback("HandleMouseWheel", HandleMouseWheel);
}

//This function passes the event to my map object. You could actually pass 
//it to any objects in the app that you would like. Also note that I am 
//getting the mouse coords from the flex app vs the actual browser. This keeps 
//everything local.
public function HandleMouseWheel(event:Object): void {
    var mEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_WHEEL, true, false,                     
        this.contentMouseX, this.contentMouseY, map, 
        event.ctrlKey, event.altKey, event.shiftKey, 
        false, -Number(event.delta));
    map.dispatchEvent(mEvent);
}
MurderDev
  • 157
  • 1
  • 10