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.

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.

Mysterious security zone issue in IE7

It seems that Microsoft's brand new operating system, Windows Vista, introduced at least one interesting, not to say mysterious, phenomenon. It only arises when the user is trying to open a local HTML file with so-called "active content".

After some investigation we found out that it is problematic to open local HTML pages which reference non-existing JavaScript files. During development of qooxdoo applications this could be caused by renaming or moving a class without a re-execute of "make" to re-index the available classes (to regenerate the includer script).

Annoyingly, the displayed error is not very helpful. It just says "Invalid character" in line "0". No hint about security at all. All files are stored on the local file system. No "src" attribute uses another protocol like "http://"or an address of an (external) server. Just simple, relative paths. There seems to be no reason to interpret them the way IE7 under Vista does. The files do not access remote resources. They are not stored in other security zones. We really do not know what Internet Explorer "thinks" in this case.

In all other browsers a non-existing JS file is just ignored. No warning at the error console etc. (Ok, this could be improved here, too).

Please also take a look at the corresponding bug report. Any idea if this is a real IE7/Vista bug?

Key Event Nightmare - Resolved

Since the 0.6.3 release, qooxdoo includes a complete rewrite of the key event handling layer. The old one was basically a wrapper for each browsers native key event handler. It fixed many cross-browser issues but nonetheless the differences between browsers were still visible to the application developer. The new key handler aims to unify key event handling across all supported browsers (Internet Explorer, Firefox, Opera, Safari) so that qooxdoo application developers always see the same behavior. This ambitious task turned out to be harder than expected...

Key events are one area of web browser functionality where standardization has not yet taken place. Although there is a W3C draft for keyboard events, it is more or less useless because no browser currently implements it. Even if it would be implemented, it would not solve all problems, because the standard is still incomplete. Pretty sad. For example, it has no concept of repeated key events which are fired repeatedly while the key is held down.

At first glance key event handling doesn't look so different across browsers. All major browsers support the three key events keydown, keypress, keyup and all key event objects have a keyCode property and properties for the modifier keys altKey, shiftKey, ctrlKey, metaKey. Unfortunately, under the hood all browsers behave quite different. Even the same browser can behave different on different platforms, e.g. Firefox under MS Windows and Mac OS X, respectively.

Key event handling is so challenging because of (at least) the following five shortcomings:

  1. Key code vs. Char code: Key events return codes for the actual key that is pressed (the key code) and the character that will be printed on screen (char code). Theses codes are represented as numbers and it is sometimes hard to figure out if a given code is to be understood as a key code or rather a char code. This is a severe problem because some numbers can be interpreted as either key code or char code. For example in key press events in Opera it cannot be decided whether the returned code is a key code or a char code.
  2. Keys that require shift on some keyboard layout: The key code of keys that require the shift key on some keyboard layouts are not reliable. The key code which is generated depends on the current language-specific keyboard layout of the user. The key “#” for example can be reached on a German keyboard layout without the shift key and generates the key code 35, while the same character composed with Shift+3 on an American layout produces a key code of 51.
  3. Repeated key events: If the user keeps pressing a key the browsers fires some events repeatedly. Normally, only the keypress event is expected to be repeated, but no other events. Under Windows however, both Internet Explorer and Firefox repeat the keydown event as well.
  4. Incomplete event sequences: Not every browser fires for every key the complete event sequence of keydown, keypress and keyup. Internet Explorer does not fire keypress events if the corresponding key is non-printable (i.e. function key F1). Firefox does not fire keypress events for modifier keys (i.e. Ctrl or Alt) and Safari does not fire any key events for modifier keys at all.
  5. Char code only reliable in keypress events: Only Safari sets the char code also in keyup and keydown events. The good news is that the character code in keypress events is reliable and always represents the Unicode number of the character that would be printed on the screen.

qooxdoo's new key handler solves most of above challenges by browser specific key handlers which differentiate between key and char codes and normalize the event sequence. This means for example that repeated keydown events in Internet Explorer are intercepted and passed on as keypress events and that the missing keypress events for special keys are synthesized if the corresponding keydown event is detected. To simplify the programming interface for qooxdoo developers we chose the W3C draft for orientation and implemented their keyIdentifier property. The keyIdentifier maps the key codes to a (human readable) key identifier strings. To prevent the developer from accidentally using keys which seem to be working in one browser but might not work in another, we introduced a white list of keys which can be detected reliably with the new key handler.

Unfortunately, a completely unified key handler is still not possible with today's browsers. Issues like the ambiguity of Opera's key code in keypress events or Safari not firing any key events for modifier keys can only be solved by the browser manufacturers/programmers. Nonetheless, we think that we came pretty close to the, to our knowledge, best possible solution and can offer one of the most advanced key event handlers out there.

For more detailed information you may consult the corresponding documentation of qooxdoo's new key handler and the following sources:

Only five days to IE7

Untitled document Following a report of Microsoft Higher Education - Mid-Atlantic it seems that IE7 will be released on the 18th this month. In just 5 days. The most changes are only interesting for typical web developers (e.g. CSS fixes) while the latest improvements to the JavaScript engine are also an interesting point for us and other big JavaScript frameworks. I hope we will see a market share of 50 percent after the first six months.

Dramatically improved IE7 JavaScript performance

Untitled document

Really good news. My vocabulary may to be too limited to tell you how great the latest changes in IE7 RC1 are. Microsoft announced that they have "recently made some great fixes to our engine to improve the garbage collection routine and to reduce unbounded memory growth." and that one "should see noticeable improvements on AJAX sites in the Release Candidate we shipped last week". Yes indeed, we do see tremendeous improvements. :-)

In fact many demos of qooxdoo run much faster now in IE7 compared to IE6. And they are even faster than in Firefox 1.5 in many cases. This is a huge jump in performance. Microsoft did not tell about their exact modifications, of course. Anyway, they have fixed the major problem of large JavaScript-based web applications. This problem, despite having a catchy name, was mentioned many times before like here, here and there: If you have many objects created, which are simply accessible in the current scope, all methods and features of JavaScript slow down dramatically. Yeah, right, the entire execution speed drops significantly. No other browser besides IE shows such a strange behavior. It is quite interesting that IE6 really gets slower the larger the total number of (accessible) objects. Sure, it is logical that more instanciated objects need more memory, but it is not logical that at the same time this will dramatically reduce the performance of any code (that is not even accessing this data).

With the release candidate RC1 of their new browser version IE7, it seems that they have finally fixed this issue. You can test it yourself in this test case, which has been available in qooxdoo for several months to analyze and measure the IE performance problems. Please look at status bar of your browser (maybe you need to enable the status bar in the IE7 security settings). It will display the execution time of each loop while a large number of objects exists. On my machine the IE6 needs ~1400ms, while IE7 needs ~30ms, which is roughly the time Firefox 1.5 needs. Definitely incredible! Bright future for modern web applications. :-)

Advanced box model test - part 2

This is a small continuation of our original box model test. We added some tests to explicitely check for overflow problems already noticed during development of qooxdoo 0.5. We simply wanted to be sure about the current state of browsers before starting the development our new layout engine.

Results

Good news first: Konqueror (version 3.5.3) renders equally perfect for both overflow:hidden and overflow:visible. The box-sizing is correct. In all examples! Again kudos to the developers!

Opera 9.0 shows the same errors for overflows as without overflows. Fine. We are already happy if we need not to handle another special situation...

Internet Explorer 6.0 renders 2 boxes smaller in Standard Mode and even completely fails to render 2 boxes using "overflow:hidden" in Quirks Mode. The boxes were already wrong layouted before. So luckily it is not getting worse.

Firefox 1.5 shows differences compared to Firefox 1.0. Now we noticed the first box model difference between Gecko 1.7 and Gecko 1.8. Firefox 1.5 renders two more boxes wrong than without the overflow statement, both using "box-sizing:border-box". All other boxes are identical.

Surprisingly, for Firefox 1.0 the "overflow:hidden" fixes all the bugs on the right columns, i.e. making "box-sizing:border-box" to work perfectly, but breaking many boxes on the left side. This means Firefox 1.0 is the only browser in this roundup which fails to render the W3C-default "content-box". In general it supports all other CSS standards used in the tests (compared to Internet Explorer for example).

Complete set of test scenarios

Updated Screenshots

Advanced box model test

In preparation of our new layout engine we did a roundup of all modern browsers' abilities to render under the two different box models. It definitely is one of the most compelling questions in advanced web development: "Which browser supports what layout features and how well?". Like most other javascript toolkits qooxdoo currently depends on a box-sizing of "border-box". While not being the default box model in current browsers, many people think that it is the most natural way to define web layouts, if not layouts in general. The W3C-favored "content-box" model on the other hand is often seen as a rather counter-intuitive solution. Our tests particularly reveal how well the common use cases work in "border-box" regime.

Tested browsers and Screenshots

Firefox 1.0 and Firefox 2.0 beta 1 behave identically to Firefox 1.5. Browsers based on Gecko 1.6 behave differently (screenshots may be provided soon).

Results

Konqueror is the only current browser which renders all test examples flawlessly. There seems to be no box model layout bug. Just perfect. Kudos to the developers! Internet Explorer 7.0 (only in Standards Mode), Firefox 1.5 and Opera 9.0 show perfect results as well, but only in the "content-box" tests. Unfortunately, each of these browsers exhibits individual problems in the "border-box" model.

Internet Explorer 6.0 and Internet Explorer 7.0 render equally (wrong) in Quirks Mode. Internet Explorer 7.0 comes with support for stretching (i.e. define left and right or top and bottom together) and min- and max-dimensions, but only in Standards Mode. At least one of the very few improvements due to the IE7 revamp. Both Internet Explorer versions do not support the handy "box-sizing" property at all. Choosing either standard compliant or quirks mode is achieved by an appropriate doctype declaration as usual. Keeping in mind IE's inability to work in a "border-box" regime, it is obvious that the second part of each test document (the two columns to the right) are always wrong. While Internet Explorer 7.0 renders flawlessly in Standards Mode, Internet Explorer 6.0, lacking many CSS features, only renders exactly one of all the squares correctly. Which one depends on the current render mode, of course. Quite dissappointing, but not unexpected results.

Mozilla Firefox as of version 1.5 shows an almost perfect rendering behavior. Surprisingly, it doesn't follow the "box-sizing" rule, if no width or height is explicitly defined. This means for example that it isn't possible to only define a min-width without setting a (bogus) width as well. Long distance calling cards. A work-around for such a bug in "border-box" mode could be to add an appropriate width or height to each min-width, min-height, max-width or max-height statement. As already mentioned the W3C default value "content-box" yields absolutely perfect results.

Opera 9.0 has many strange problems. Sometimes the box is too large, sometimes too small. It appears to be somewhat inconsistent as well: while the box widths are often ok, the box heights are plain wrong. Hard to make sense of such an asymmetric behavior. Opera 9.0 in the "content-box" model is perfectly well-behaved, though.

Please have a look at our tests documents online, either our standard compliant test or quirks mode test.

Any ideas or comments welcome!

IE 7.2 will support SVG

Microsoft publicly stated IE will have core engine support for SVG in IE7.x (most likely 7.2) (power point presentation); they are currently working with Firefox, and others to ensure version / profile rolling compatibility.

Borrowed from allforces.com.

Maybe this would also mean the end of slow SVG/Canvas emulations using VML. Hopefully this release will also be available for Windows XP.

 

Control

 

Categories:

Archives:

 
SourceForge.net Logo

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