Waypoints feature added to qx.Mobile

We enhanced the qx.Mobile pageEnd logic and added a scroll waypoint feature. It makes it possible to execute code whenever you scroll to a pre-defined offset. This is very useful if you want to trigger an animation/action when the user scrolls to specified vertical/horizontal point. This feature is also necessary if you want to implement infinite scrolling.

The waypoint feature can be used like this:

var scrollContainer = page._getScrollContainer();
scrollContainer.setWaypointsY(["0%","50%","100%",200,".waypoint"]);

You can add percentage-based waypoints by adding a string like "20%" or just add numbers for applying pixel-based offsets. Additionally you can determine waypoints through a CSS selector query.

Whenever a waypoint triggers, a qx.event.type.Data fires on the scroll container:

scrollContainer.addListener("waypoint", function(evt) {
  console.log("Waypoint reached:" + evt.getData());
}, this);

The payload of the waypoint event looks like this:

{
"offset": 0,
"input": "10%",
"index": 0,
"element" : 0
}
  • offset contains the scroll offset in pixel.
  • input is the waypoint condition you passed through the array and which triggered this event.
  • index identifies this waypoint relative to its position inside the waypoint array you have passed.
  • element contains the element index found through your selector. e.g. you have five elements with ‘.waypoint’ class inside your scroll container, and user scrolls to the fifth element with this identifier, then element would be 4. This value is only relevant for waypoint rules based upon a selector. For numbers and percentage-based rules it is always null.

Have a look at this feature at the qx.Mobile List demo or check out the demo source code.

Pointer Events

During recent weeks, pointer events have been the dominating topic in the framework team, as we already teasered in the weekly blog post some weeks ago. With this post, we want to give you a deeper insight into this topic.

The Challenge

qooxdoo features three GUI toolkits: desktop, mobile and website. Connected to these domains are the main input devices: mouse for desktop / website and touch for mobile. In detail, this means that desktop / website widgets register mouse event listeners and mobile widgets register touch event listeners. So using one type of app with another input device is at best not optimal. For that reason, we already added emulation layers for mouse on touch devices and touch on PCs. But transforming one event model to another is error prone and simply doesn’t feel natural. Another way to get the optimal user experience would be to listen to both types of event for each widget, but making that change takes a lot of effort without providing an ideal solution.

Pointer to the rescue

Luckily, some clever guys at Microsoft already recognized this issue and came up with a W3C spec named Pointer Events, which tackles this problem. The main idea of this spec is to offer a unified event, independent of the input device. In an ideal world, we would simply use these events and everyone would be happy. But every web developer knows that we don’t live in an ideal world and we have to support browsers that don’t implement the spec. In fact, it’s only IE10+ which already has support for native pointer events.

Pointer Spec in a nutshell

In a nutshell, the spec is based on mouse events and maps all input devices to pointer events. It extends the mouse event type with additional information like the id of the pointer for multi pointer devices. So as a developer familiar with mouse events, you will feel comfortable with pointer events as well because most of the events are equal at first sight, like pointerdown, pointermove or pointerover. For more details, take a look at the spec.

What we already did

Having pointer events in mind, the task was clear: offer pointer events for our GUI toolkits. That means adding event handlers for the website and desktop / mobile layer, bringing these events to the widgets and changing every widget so it listens to pointer events instead of mouse / touch events. After that, change every app we ship with the SDK to use pointer events as well. If we slow down a bit and take a step back, the most important things to consider here are the event layers which fire the pointer events. So here is a listing of the newly added pointer events:

  • pointerover
  • pointerout
  • pointermove
  • pointerdown
  • pointerup
  • pointercancel

If you have the spec in mind, you will see that this list does not contain all events it mentions. But these are the most important events we need for widgets so we kept the list as small as possible. This is one of the reasons we don’t like to call this implementation a polyfill, even if in most areas it’s well-aligned with the spec and is quite broad in scope.
All the events mentioned above have one thing in common: They are atomic. The click event for example is not atomic because it is generated by a sequence of other events. But click is also closely connected to the mouse so to achieve our goal, we needed something input device independent here as well.

Gestures on top

But click is not the only combined event we know. Think of tap, swipe, or rotate in the mobile world. So we introduced another set of new events which can be grouped as gestures:

  • tap
  • longtap
  • swipe
  • rotate
  • pinch
  • track

All these events should work with either mouse or touch. Of course, for rotate and pinch, you need more than one pointer, which is not possible using a mouse.

What’s still missing

There are still some challenges left for us to tackle. One obvious thing is scrolling as there is no mouse wheel or scroll bar on mobile devices. Most of the algorithms relying on hover events are to be refactored e.g. Drag & Drop, quick selection for lists and tooltips. Last but not least, we need to add some manual pages explaining why, how and when to use use these events.

Give it a try

While we continue to complete this event layer, we would like to invite you to take a look at the changes so far. Check out our demo apps we built based on the pointer branch and let us know what you think.

Introducing qx.Website Widgets

Since its initial release with qooxdoo 2.0, the qx.Website component has steadily grown and matured into a fully-featured DOM library, allowing developers to enrich websites with dynamic features. One frequent request we’ve heard from projects using qx.Website is the need for “low-level widgets”, meaning prefab UI components that are easy to integrate with just a few lines of code but also fully customizable so they can be adapted to any site design.

That’s why the upcoming qooxdoo release will ship with a new qx.Website module: q-ui.js, a.k.a. “qx.Website Widgets”, a library of UI elements including components such as Calendar, Slider and Accordion.

Key features of the qx.Website Widgets library include:

  • Uses the same well-known programming paradigms as qx.Website and other DOM manipulation libraries:  Widgets are wrapped in Array-like collections (inheriting from qxWeb so all qx.Website Core methods are supported). Widget methods generally return the collection to support call chaining.
  • Easy customization using CSS and mustache.js templates
  • Widgets can be created either entirely in JavaScript or be configured using HTML data attributes, e.g. for HTML generated on the server.

Demos

The new Website Widget Browser application contains demos for all currently available widgets, while the recently made-over qx.Website API Viewer provides all the information you need to integrate them into your website projects.

Give them a try, and let us know what you think via the usual channels – blog comment, mailing list, Facebook or Twitter. Just keep in mind this new feature is still considered experimental – the API can and probably will change, possibly taking into account your input.

Next steps

In the weeks and months following the December release, we plan to stabilize the qx.Website Widgets API, add new widgets and improve support for legacy browsers. From a framework perspective, our goal will be to leverage qx.Website as a foundation for the higher-level UI toolkits (qx.Desktop and qx.Mobile), consolidating and unifying the technology stack where appropriate. This will make it even easier for you to create universal apps for any or all domains of Website, Mobile and Desktop.

 

Compiler Hints in qooxdoo 3

tl;dr

When migrating compiler hints from their “#” form to the new “@” form, make sure to start the surrounding comment with “/**“.

The Details

qooxdoo 3 introduced the new compiler hints which are integrated with JSDoc comments. Basically, this is a straight-forward migration, but many people struggle when they do it. They find that after rewriting their hints they stop working, as if not there. This has to do with the structure of JSDoc comments in general.

When changing the compiler hints many start by replacing a compiler hint like #asset(custom/*) with @asset(custom/*). But you have to make sure that it is actually embedded in a valid JSDoc comment. So for the old hints

/* ****************************
#asset(custom/*)
**************************** */

was a suitable block comment, but just replacing “#” with “@”

/* ****************************
@asset(custom/*)  // doesn't work!
**************************** */

for the new hints it is NOT!

That’s because JSDoc comments absolutely positively have to start with “/**” (that is  slash-star-star). Otherwise, the comment will not be recognized as a JSDoc comment, intentionally to allow hiding comments from the JSDoc system.

So a correct form of the above compiler hint would be

/** ***************************
@asset(custom/*)  // works!
**************************** */

(mind the start of the comment!), and a more standards-conform formatting of the same comment would be

/**
 * @asset(custom/*)  // works too
 */

Please keep an eye on that when migrating the compiler hints in your code.