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.
Development
Firefox
safari
internet
qooxdoo
Technical
explorer
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.
Development
Firefox
safari
internet
qooxdoo
Technical
explorer
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.
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->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!
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.
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->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!
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.
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>
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
-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).-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.
Development
Firefox
safari
internet
qooxdoo
Technical
issues
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.
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>
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
-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).-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.
Development
Firefox
safari
internet
qooxdoo
Technical
issues
Firefox: del.icio.us/tag/firefox
Firefox
Technical
imported
mozillafirebird&mozillainformation
Firefox: del.icio.us/tag/firefox
Firefox
Technical
imported
mozillafirebird&mozillainformation
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:
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:
Development
Firefox
safari
internet
qooxdoo
Technical
explorer
Firefox: del.icio.us/tag/firefox
Software
Firefox
mozilla
del.icio.us
Technical
delicious
extension
extensions