Mouse wheel and Trackpad scroll for GWT Applications

The last post I did about mouse wheel scroll for Flash applications came in handy in a GWT application I was working recently. The solution is a embeddable viewer for Creately diagrams. The player lets you view large diagrams by letting you zoom and pan around. Panning naturally works by dragging but what makes it amazingly smooth and easy is the mouse/trackpad scroll (specially on a Mac). Give it a try here.

All I had to do is use JSNI on GWT to access Javascript scroll events and manage them accordingly within GWT. Here I have used the same JS that was used in the previous post with minor tweaks. Originally taken from FlexAmphetamine. Follow these steps to get it working on your GWT application.

1) Create the JS file that will capture the events for you.

Create the scrollsupport.js and place it under the build folder /war/{modulename}/. Note that when you build the GWT application this folder will be cleaned and you will lose the file. So make sure the keep a copy somewhere else in the source OR move it to the root and change the XML accordingly in the next step.

function setupScrolling( objectID ) {
  var containerObj = document.getElementById(objectID);
  if ( containerObj ) {
    var eventListenerObject = containerObj;
    var isWebkit = false;

    if (navigator && navigator.vendor) {
      isWebkit = navigator.vendor.match("Apple") || navigator.vendor.match("Google"); }

    // some events will need to point to the containing object tag
    if (isWebkit && containerObj.parentNode.tagName.toLowerCase() == "object") {
      eventListenerObject = containerObj.parentNode; }

    var scrollHandler = function(event) {
      var xDelta = 0;
      var yDelta = 0;

      if (!event) // IE special case
        event = window.event;

      if (event.wheelDelta) { // IE/Webkit/Opera
        if (event.wheelDeltaX) { // horizontal scrolling is supported in Webkit
          // Webkit can scroll two directions simultaneously
          xDelta = event.wheelDeltaX;
          yDelta = event.wheelDeltaY;
        } else { // fallback to standard scrolling interface
          yDelta = event.wheelDelta; }

        // you'll have to play with these,
        //browsers on Windows and OS X handle them differently
        xDelta /= 120;
        yDelta /= 120;

        if (window.opera) { // Opera special case
          yDelta = -yDelta; }// Opera doesn't support hscroll; vscroll is also buggy
      } else if (event.detail) { // Firefox (Mozilla)
        yDelta = -event.detail/1.5;

        if (event.axis) { // hscroll supported in FF3.1+
          if (event.axis == event.HORIZONTAL_AXIS) {
            // FF can only scroll one dirction at a time
            xDelta = yDelta;
            yDelta = 0; } }

      try {
        scrollEvent(xDelta, yDelta);
      } catch(e) {};

      if (event.preventDefault)
      event.returnValue = false;

    if (window.addEventListener && eventListenerObject) { // not IE
      eventListenerObject.addEventListener('mouseover', function(e) {
        if (isWebkit) {
          window.onmousewheel = scrollHandler;
        } else {
          window.addEventListener("DOMMouseScroll", scrollHandler, false); }
      }, false);
    } else { // IE
      containerObj.onmouseover = function(e) {
        document.onmousewheel = scrollHandler; };
  } else { /* No scroll */ }

2) Include the JS file in the module xml file to be loaded prior to anything else.

Include the following line in the {modulename}.gwt.xml file.

<script src="scrollsupport.js"></script>

3) Add code in the application EntryPoint class to handle the scroll events

public class MyGwtApp implements EntryPoint {
  private static String MAIN_CONTAINER = "appContainer";

   * This is the entry point method.
  public void onModuleLoad() {
    // Code for the application
    this.setScrollHandler( this, MAIN_CONTAINER );
    // Code for the application

/* ************************************************* *
 *  Mac scroll functionality
 * ************************************************* */  

  private void mouseScrollHandler ( double deltaX, double deltaY ) {
    // use the scroll delta values to do scroll actions.

  public native void setScrollHandler( MyGwtApp app, String objectID ) /*-{
    $wnd.scrollEvent = function (xDelta,yDelta) {
          ( Number(xDelta), Number(yDelta) );
    $wnd.setupScrolling( objectID );

See it work in Creately Diagram Viewer

You may notice that in this specific case I have inverted the scroll function to give the natural feeling of dragging on the canvas.

This is just a quick and dirty way to get the mouse wheel/trackpad scroll working on GWT Apps. I’m sure this can be done in a much nicer way which I havent had the time to explore. However I look forward to play around more with GWT to build more cooler HTML apps.

Image from: PtiBlog