Working with text selection

Last week I started to implement a (still basic) low-level Text Selection API which especially the high-level form widgets like TextField and TextArea can make use of.

As some of you might already know working with the native Selection and Range / TextRange objects is not one of the things a developer dreams of :-)

However, looking at the basic implementation one thing is quite amazing. Besides a little tweak for Opera three (Gecko, Safari and Opera) of the four major browsers share the same implementation.
Sure there will be some more differences to encounter when the development of this low-level layer moves on, but the start looks quite promising.

Let there be color in the browser

I always wanted to play with the browser's canvas element but never really found the right toy project. Then I read Ariya Hidayat's blog post "Let there be color". He has implemented the HSL color pie using Qt's 2D drawing canvas. How hard would it be to put something like this into the browser? I decided to try the port of his code to JavaScript and render the pie using only canvas. If this worked out maybe I could embed it into nice little qooxdoo windows.

HSV Pie

Once I figured out how to realize "putPixel" and "getPixel" functions in canvas the port was merely a copy and paste with some minor changes. Right now I use the canvas methods "getImageData" and "putImageData" to obtain and render a pixel buffer. Unfortunately these methods are only available in Firefox. I'm still looking for an alternative for Opera and Safari. The last missing part was the conversion from HSV to RGB but luckily I could drop in a modified version of qooxdoo's hsbToRgb method.

Now the port could start. What really intrigued me was that the main algorithm was nearly the same as the C++ code. Just take this code fragment from the original code:

for (int i = 0; i < radius; i++) {
  qreal hue = 1 - init;
  qreal sat = 1 - qreal(i) / radius;
  for (int d = 0; d < depth; d++) {
    qreal value = 1 - qreal(d) / depth;
    QColor color = QColor::fromHsvF(hue, sat, value);
    img-&gt;setPixel(width / 2 - radius + i + 1, center + d, color.rgb());
  }
}

and compare it to the ported JavaScript:

for (var i = 0; i < radius; i++) {
  var hue = 1 - init;
  var sat = 1 - i / radius;
  for (var d = 0; d < depth; d++) {
    var value = 1 - d / depth;
    var color = hsbToRgb(hue, sat, value);
    setPixel(img, width / 2 - radius + i + 1, center + d, color);
  }
}

Basically only the variable declaration is different. The same is true for almost all of the relevant code. My first version was an all in one HTML file with the JavaScript code embedded. I used no framework, just plain JavaScript.

Of course I wanted to use some qooxdoo, so the next iteration was to put this into a qooxdoo application. Up to now qooxdoo had no support for embedding canvas elements into a qooxdoo widget. I used much of the new 0.8 widget infrastructure to create a canvas embedding widget. With this widget I could take the code from my first version and embed it into a qooxdoo window. You can see this application life or download the sources. This code is based on the latest qooxdoo 0.8 trunk.

Have fun!

Introducing HtmlArea

For quite a long time now qooxdoo-contrib includes a WYSIWYG html editing widget called HtmlArea. During the last few weeks Jonathan and I have been busy improving the existing widget, and have now released a new version.
Since there are many other open source projects around with a similar technical approach, why haven't we just picked one of those and ported them to (or just used them with) qooxdoo? Well, we think we have a slightly different focus and goal in mind than the other projects: We wanted to create a solid, clean cross-browser widget, focusing on a fundamental set of functionality rather than a full-blown WYSIWYG editor. HtmlArea intends to support all the four major browsers that include basic html editing capability in their most recent versions. Well, to be fair, that is a long-term goal, with IE and Firefox currently getting more love than Safari or Opera.

Today we released a new version HtmlArea 0.2 with the following features:

  • Text formatting
    • font family
    • font size
    • font weight
    • text decoration
    • font style
    • text color
    • background color
    • text indention
  • Complete Undo / Redo handling
  • Insertion of HTML elements
    • table
    • image
    • list
    • horizontal ruler
  • Easily expendable to insert custom HTML

See a simple live demo.

In a future release we would like to include some kind of plug-in architecture which would allow for an easier development of extensions to HTMLArea. We also think about different feature sets (e.g. basic, simple and advanced) for different users' needs. Please also note that one of the next versions will target qooxdoo 0.8 and might not work with previous qooxdoo versions.

Let us know what you think about HtmlArea so far. The infrastructure of qooxdoo-contrib allows anyone to contribute to qooxdoo quite easily - either by collaborating on existing features or on starting and maintaining new ones.

qooxdoo 0.8: peek into next generator’s config

The generator, heart of qooxdoo's tool chain, has been overhauled extensively for 0.8, close to a complete rewrite. Main objectives for the new implementation include

  • support for parts
  • run multiple jobs "in one go"
  • replace "make" and other GNU/Unix tools as far as possible, to cut down on prerequisites
  • support a unified application/library structure throughout the project
  • pave the way for an enhanced GUI-based build tool

The first and maybe most visible change the new generator brings for the users is the changed configuration. The current tool chain relies heavily on GNU's make, deploying various related Makefiles. The primary means to configure the build process is through Makefile variables. The new generator replaces these make tools with config files that are based on JSON, a data format that blends well with both Javascript and Python.

The challenge here was to use JSON's basic declarative syntax elements like dictionaries (maps), arrays and simple data types, and build upon them a semantics that is both rich, to provide a sufficient level of power and abstraction, and generic, to cover all necessary use cases. (It almost feels like defining a new XML schema...).

The current state of the issue is that a config file contains a single big map that keeps a varying number of keys that represent jobs. A job can be anything from copying files around to generating the build version of an application or its API documentation. Consequently, jobs deploy certain keywords to trigger those actions, along with necessary configuration data like where to look for source classes, where to place outputs, where to find resources, and so forth. To foster re-use (and limit unnecessary typing), config files deploy three basic mechanisms: They can include other config files, and jobs can "extend" each other (This works a bit like inheritance between classes; the parent job's settings are merged into the current job, which can add new settings or override some of the parent's settings). The third tool are string macros that are expanded in other strings in the config.

For the curious who want to get their feet wet and their hands dirty, the generator2 config page provides a lot of further stuff to read and ponder. Feedback welcome.

qooxdoo 0.8 to support Netscape 4

In our constant quest for cross-platform compatibility we are especially proud to announce support for the legendary Netscape Navigator 4 browsers with qooxdoo 0.8. This browser, in its latest stable 4.08 release, has had a major impact on Internet usage and browser experience, and still maintains a small but die-hard community of users (Netscape's shares of the browser market total at about 0.68%).

This is another step forward to show qooxdoo's commitment to real world technologies and to help protect existing investments. We are particularly happy to present qooxdoo support for this platform in the 10th anniversary of its most recent release.

Netscape 4 - qooxdoo 0.8 Showcase

Happy Birthday, Netscape 4!

New Animation Layer

qooxdoo 0.8 - the next major release that includes an exciting rewrite of the GUI toolkit - will also offer a powerful animation layer with a wide range of effects. qooxdoo animation, as we call it, is to a large extent derived from the well-known effect library script.aculo.us.

To give you a small example, I will demonstrate how easy it is to build a typical One Second Spotlight in qooxdoo:
Imagine your website has an info box with the current number of your product's downloads:

Downloads today: <span id="dlAmount">10</span>.

Every time a user starts a download, a function should be called to update the box. Using the Highlight effect on the element containing the number of downloads, you can easily get the user's attention:

 
  var element = document.getElementById("dlAmount");
  var attention = new qx.fx.effect.core.Highlight(element);
 
  function update(amount)
  {
    element.innerHTML = parseInt(amount);
    attention.start();
  }

See the development version of the demobrowser for some early animation demos. Please note that the animation API might still change before the final 0.8 release. The current animation layer is a low-level DOM layer that will later also be used internally to animate the high-level qooxdoo widgets when they are available in 0.8.

Keyhandling for Safari 3.1 fixed

With the recent release of Safari 3.1 the WebKit team has completely reworked the handling of key events. John Resig has an interesting blog article with some details. Safari 3.1 now behaves pretty much like Internet Explorer and is in general much more sane than before. For instance, all those strange key codes larger than 64000 for special keys are gone and finally modifier keys like "shift" and "control" fire key events as well. Interestingly, Safari is now the first browser to support the key identifier property defined in the DOM level 3 event specification. In qooxdoo we already emulate this property in key events for quite some time now, and it really helps to simplify key handler code in our widgets.

Unfortunately, this change in Safari 3.1 broke the existing qooxdoo key event handler. But it is already fixed and available in our subversion repository for legacy_0_7_x branch and trunk. The fix was basically to detect the current WebKit version and use the existing Internet Explorer key handler code also for Safari 3.1 and above. Since all browser quirks are handled separately this was a pretty simple fix. Of course, it will be part of the next minor release 0.7.4 as well as the final 0.8. If you need Safari 3.1 support now, please checkout the latest version from the legacy_0_7_x branch.

Partial ordering of qooxdoo classes

This article is for the theoretically inclined among us :-).

When putting together a JavaScript application order matters. Since the browser
evaluates JavaScript code in the order it arrives, every code that is referenced
by other code has to come beforehand, in order for that reference to succeed.
This for example affects calls to other functions within the body of a certain
function, since these references are resolved at load time by the interpreter.

The same holds true for the prototype reference used for a "derived" class
(constructor) object. The "ancestor" function has to be loaded before you can
use it as the prototype for another function.

In qooxdoo, classes are declared as maps which are passed to a
class-constructing method, qx.Class.define(). This method creates the basic constructor object, sets the prototype and other prototype properties, and so forth. It is only when qx.Class.define is actually executed that all referenced objects in the class definition have to be in place, the most prominent being the "extend" member of the class which names its parent class.

qooxdoo's generator goes to some length to assure that classes are constructed in the right order. This is reflected in the script/<application>.js file which contains a list to the appropriate class files (in the "source" version), or the actual class code (in the "build" version). Obviously, classes that serve as base classes for others have to come earlier. But this is not all there is to it. Classes not only inherit from other classes, they also use them, through creating instances of them in their own code or calling out to static functions. Whenever code that does that is evaluated those other classes have to be in place.

You probably already know where this is going to, there is a risk of circular dependencies. A simple example might illustrate that. Most classes in qooxdoo derive from qx.core.Object, e.g. the Logger class. But qx.core.Object itself might want to start logging early when it is created, that is "use" a Logger instance. Another typical example for complications of this kind is the 'tr' function that needs a qx.locale.LocalizedString, which might not be present at the time you call 'tr'. A point in the class declaration where this might crop up is the 'defer' section, which contains code that is actually run after the class has been constructed, but might include references to classes that are not readily present in the interpreter.

On a general level what we are looking for is a partial order on the set of qooxdoo classes, the relations in question being "require" (the other class is a parent class) and "use" (the other class is used in the code). The question is: Is there a partial order for the qooxdoo classes under the combined relation "require/use" where a class A "comes before" a class B exactly when A is required by B and/or A is used by B. Only if there is such an order can qooxdoo classes be sequenced consistently.

Rounded borders - and how to do it in IE

In qooxdoo 0.8 we will introduce the concept of widget decorators. This has already been described in an earlier blog article. Decorators allow a widget's background to be styled independent of the widget's content. To demonstrate the flexibility of the decorator concept I have written a decorator, which uses native CSS rounded borders in Firefox and Safari/Webkit and emulates the same behavior in Internet Explorer. The screenshot shows the same qooxdoo 0.8 application in Internet Explorer 7, Firefox 3 Beta 3, WebKit r30082 and Firefox 2.0.11.

Rounded borders screen shot

The widget shown in the screen shots is generated by the following snippet of qooxdoo code:

 
doc = new qx.ui.root.Application(document);
 
var border = new qx.ui.decoration.RoundedBorder().set({
  radius: [10, 20, 30, 40],
  width: [3, 10, 20, 5],
  color: ["red", "green", "yellow", "blue"],
  backgroundColor: "gray"
});
 
doc.add(new qx.ui.basic.Label().set({
  html: qx.bom.client.Engine.NAME,
  decorator : border,
  width: 140,
  height: 100,
  padding: 20
}), 10, 10);

I think the most interesting question is about the IE implementation. Since IE has no native CSS rounded border support, the borders must be rendered using a different technique. A common approach is to render the borders using pixel-sized DIV elements like e.g. RUZEE.Borders does. We have used a different and in my opinion much more powerful approach.

We use VML to render the background including the border. The VML code is dynamically created and inserted into the decoration DIV using plain innerHTML. Since the decorator is informed about size changes by the qooxdoo layout engine, it can update its borders accordingly. The rendering quality is amazing and looks pretty much like the best native browser implementation of Firefox 3. This is the code automatically generated and applied by qooxdoo:

 
<style>v\: * { behavior:url(#default#VML);display:inline-block }</style>
 
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
<div style="left: 10px; width: 140px; position: absolute; top: 10px; height: 100px">
<div style="z-index: 10; left: 25px; width: 85px; position: relative; top: 23px; height: 37px" usehtml="true">mshtml</div>
<div style="z-index: 5; left: 0px; position: absolute; top: 0px">
    <v:group style="left: 0px; width: 140px; position: absolute; top: 0px; height: 100px; antialias: true" coordsize = "140,100">
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "gray" path = " m10,1 ns l120,1 qx139,20 l139,70 qy110,99 l40,99 qx1,60 l1,10 qy10,1 x e"></v:shape>
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "red" path = " m10,3 ns at5,3,15,13,10,3,5,3 wa0,0,20,20,0,0,10,0 wa100,0,140,40,120,0,140,0 at110,3,130,23,130,3,120,3 x e"></v:shape>
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "green" path = " m130,13 ns at110,3,130,23,130,13,130,3 wa100,0,140,40,140,0,140,20 wa80,40,140,100,140,70,140,100 at110,60,130,80,130,80,130,70 x e"></v:shape>
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "yellow" path = " m120,80 ns at110,60,130,80,120,80,130,80 wa80,40,140,100,140,100,110,100 wa0,20,80,100,40,100,0,100 at5,40,45,80,5,80,25,80 x e"></v:shape>
    <v:shape style="width: 140px; height: 100px" coordsize = "140,100" fillcolor = "blue" path = " m5,60 ns at5,40,45,80,5,60,5,80 wa0,20,80,100,0,100,0,60 wa0,0,20,20,0,10,0,0 at5,3,15,13,5,3,5,8 x e"></v:shape>
    </v:group>
  </div>
</div>
 

Generated HTML for Internet Explorer

The first two lines are required to enable VML support and are only added once into a page. Note that only one of the DIV elements contains VML code. The rest is typical HTML code generated by the qooxdoo GUI toolkit, which does all the layouting itself, just using JavaScript. It consists of a couple of nested, absolutely positioned DIV elements with the appropriate CSS styles applied.

The code for Firefox is much simpler and just sets the browser-specific CSS styles:

 
<div style="position: absolute; z-index: 0; left: 10px; top: 10px; width: 140px; height: 100px;">
<div style="position: relative; z-index: 10; left: 25px; top: 23px; width: 85px; height: 37px;">gecko</div>
<div style="border-style: solid; border-color: red green yellow blue; border-width: 3px 10px 20px 5px; z-index: 5; position: absolute; left: 0pt; top: 0pt; -moz-box-sizing: border-box; width: 100%; height: 100%; background-color: gray; -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 20px; -moz-border-radius-bottomright: 30px; -moz-border-radius-bottomleft: 40px;"></div>
</div>
 

Generated HTML for Firefox

Native browser support

The quality of rounded border implementations differ a lot between browsers. The CSS3 draft defines the property border-radius and a property for each corner like border-top-left-radius. These properties take two values, one for the horizontal radius and one for the vertical radius. That way it is possible to define (quarter-)elliptical borders. If only a single value is given, the border is (quarter-)circular.

Current browser implementations

  • Firefox 2: Firefox supports only circular borders. Border definitions always take a single parameter - the radius. The CSS property is called -moz-border-radius and -moz-border-radius-topleft, respectively. -moz-border-radius supports the CSS shorthand mode. If only one parameter is given, the radius of all four border is identical. If four parameters are defined, the radius for all four corners is set individually. The rendering quality is very poor since Firefox 2 does not use anti-aliasing to render the border (cf. screen shot).
  • Firefox 3: The same as Firefox 2 but borders are rendered using anti-aliasing, which looks much better (thanks to the Cairo 2D graphics library).
  • Safari/WebKit: The CSS property names differ from the W3C spec (-webkit-border-radius and -webkit-border-top-left-radius). Besides that, WebKit implements pretty much the CSS3 standard. Rendering looks fine as long as all border widths are equal. If they differ, the rendering looks quite ugly (cf. screen shot). This has already been reported in the WebKit Bugzilla and hopefully is going to be fixed soon.
  • Opera: Opera also does not support CSS rounded borders but there is a description online on how to emulate them using SVG backgrounds.
  • Internet Explorer: No native support either. I suppose the VML approach presented here works only well in the controlled environment of the qooxdoo widget toolkit, but I may be proved wrong.

Parsing Atom Feeds

The Feedreader is one of the standard applications that ship with qooxdoo. Behind a rather unostentatious surface it features quite an interesting showcase of networked OO programming. Feeds are retrieved from a server, processed and displayed in a three-pane layout. The feed retrieval works through a small proxy (to overcome same-origin issues) that delivers the data in a JSONP format which contains feed meta information and a list of individual feed entries. When you look at an individual feed entry in Feedreader you might notice the "read more..." link at its bottom. The idea behind this item is to link to the original feed entry and open it in a new window when clicked. To populate this link for an RSS entry is straight-forward, and the current Feedreader offers a couple of them.

But two of the feeds are atom feeds, and here the story is different. The RFC defining this protocol, 4287, lists a whole bunch of elements a feed entry can have, but it seems none of them is the definitive place for a URI that could hold the link to the entry's source. There are things like "atom:content@src" or "atom:id", but their semantics are often vague or their values are restricted to IRI's, "International Resource Identifiers", which are - roughly speaking - arbitrary strings as long as they are world-wide unique. Often the processor is explicitely required not to assume they are dereferencable (e.g. with atom:id).

This leaves it up to the feed provider if and where they are providing a source URI with every feed entry. One of the Feedreader's sample atom feeds, daringfireball.net, embeds them in the atom:content element of the feed entry. That means they are somewhere in a string (CDATA) section with a 'href=' prefix, where you might be lucky enough to pick them up reliably. Another atom feed, from blog.whatwg.org, uses the optional "xml:base" attribute of the content element (with full URIs in contrast to daringfireball.net, which only provides a true base URI in this attribute), but also uses the "atom:link" feature to provide links to the entry's source, but it does so specifying atom:link twice for every entry - where the one with the "alternate" rel attribute is what you are interested in. (And, in case you wondered, the RFC in general "assigns no meaning to the content (if any) of this element"[*]). daringfireball.net, on the other hand, uses atom:link too, but only to link to articles the blog entry is about, not the entry itself. Go figure!

Next Page »
 

Control

 

Categories:

Archives:

 
SourceForge.net Logo

Bad Behavior has blocked 635 access attempts in the last 7 days.