behavior:htmlarea (WYSIWYG editor) in h-smile core.

My initial idea was to implement behavior:htmlarea (WYSIWYG editor) as editing behavior that manipulates elements in existing DOM tree. This approach is not working for many reasons.

Main reason is following:

In presence of CSS the same rendering result (pixels in the view) can be achieved in many ways – by using various CSS attributes. (Think about spacing between paragraphs – they can be done as margins or as paddings or as trivial <br>s.)

WYSIWYG editing behavior is aimed to solve task that is somehow opposite to rendering : to change DOM structure by using current view (what user sees).

So current CSS and DOM that are good for rendering prevent good WYSIWYG implementation. I have never seen any editor based on contenteditable=”true” in browsers that I can consider as a good WYSIWYG editor. It is just impossible because of such same-DOM/multiple-ways-of-rendering-by-CSS.

Perfect WYSIWYG assumes that you can change DOM structure by using solely toolbar and keyboard – without any knowledge about underlying CSS. But current state of CSS makes perfect WYSIWYG almost impossible. Some CSS attributes and abstractions are extremely hard to present to non-css-educated user.

Solution that I am working on now:

behavior:htmlarea will be based on my blocknote editing engine.
Blocknote editing engine is using so called “flat DOM” – linear sequence of paragraphs and tables. I am just adding there limited support for CSS so htmlarea will use separate CSS file for content representation:

<htmlarea content-markup=html|wiki content-style="editing.css" />

That editing.css is a linear set of style rules that use simple tags and class selectors:

  strong { font-weight: bold; }
  strong.very { font-weight: bold; color:red; }

No other type of selectors will be allowed. Reason is simple: “predictable WYSIWYG”.
Think about following selector:

  div.some > p { margin-top:40px; } 

and user editing text with it. ENTER will cause the paragraph to be split into two:

<div.some>
      <p>first</p>
      <p></p>
  </div>

That will create margin-top:40px; spacing between them. ENTER in other paragraphs (not in div.some) will create produce different spacing. There is no way for the user to explain why here it is 40px and there it is 10px or so.

That is why HTML WYSIWYG content editing widget, I think, shall use not-exactly-html DOM and CSS.

Implementation of Behaviors in Internet Explorer

Implementation below is a generalization of Ben Nolan’ idea of behaviors. Behaviors were implemented natively in Sciter and HTMLayout and here is their emulation for the Internet Explorer.

Basic principle is simple, CSS declaration like this:

li.myclass 
    { 
      prototype: MyBehavior; /* see var MyBehavior below */
    }

binds class of DOM elements with the “prototype behavior object” – collection of event handlers defined in script nearby:

var MyBehavior = 
    {
      attached:    function() { ... },
      onclick:     function() { ... },
    }

Thus after loading HTML that contains something like this:

<ul>
  <li class="myclass">Element with MyBehavior</li>
  <li>Element without behavior</li>
</ul>

first element will behave as MyBehavior.

Here is an implementation of the Behaviors Framework – HTML document that demonstrates basic principle. Implementation is based on the fact that Internet Explorer allows you to define custom attributes in CSS declarations. I will appreciate if someone will tell me how to define something like this but for other UAs (browsers).

This may be interesting too:
“Designing Reusable UI Components in Sciter: Part I, Part II and Part III“.


Here is Dave Herman’ version of original behavior.js of Ben Nolan.

Here is another sample for IE: Simple collapsible tree.

HTML5, broken hopes.

I am tracking HTML and CSS design efforts on W3C last three years.

My main area of interests is in CSS development as I think that in HTML/CSS/Script triade CSS as a technology is the weakest area. Next is the Script. And HTML appears as the most stable thing among these three.

Since CSS1 we did not get anything changed in styling in principle. In particular CSS, as a technology, still failed to provide layout mechanisms needed by modern web applications. < table > markup is unbeatable yet – there are simply no equivalents for rowspan/colspan and flex length units used in tables ( remember that width=”60″ may serve role of pixels *or weight* in table layout). So advices like “tables are only for tabular data” are at least non-professional in current circumstances.

It appeared initially that WHATWG would focus on “needs of real-world authors” but for some reasons group started from fixing HTML. That is what I really do not understand. What conceptually is so wrong with HTML 4.01 that we need to fix it now forgetting about two other components? (The only thing to add is < video > element that I think really makes sense in shed of lights of the Tube and others.)

I believe that main problem of semantically bad markup on the Web now is not in HTML per se but, again, in CSS (and in scripting at the less extent). Lack of layout facilities in CSS forces us (real-world web designers and developers) to use markup for layout purposes more than it is really needed. Web authors, people who write content of the web are happy with the current HTML but professional web designers *are* the people who are “breaking the semantic web” now. Simply because CSS as a standard failed to provide layout features needed for modern web applications. I thought that was clear for everyone who is doing practical web design…

To be short I disappointed by direction where W3C decided to move development focus these days. And yet, here are HTML5 and HTML4 differences. Could anyone tell me what all this will change in principle except of breaking of what works already?

So far all corner stone Web technologies were production of concrete personalities and companies – not committees. As an example: HTTPXMLRequest ( one of features AJAX is based on) was born as a result of guerrilla’s action taken by team doing web access for Microsoft Exchange. And now the whole yahoo and google set of technologies is built on it. So is the question that worries me somehow: how Web technologies should be designed/evolve? What is the best procedure:
design-by-precedent, design-by-committee, design-by-public-bazaar or just wild competition among browser vendors? But this is, I guess, an idea of separate topic.

Browser wars.

Somewhere in this month discovered in logs of this site that total number of visitiors who use Gecko (FireFox and Mozilla) and Opera browers became first time larger than number of Internet Explorer users. Of course this site has specific auditorium but nevertheless…

CSS extensions in h-smile engine. Part II. Flex units.

Flex length units are "weights" used in distribution of free space along some direction.

Example of the document with flex units:

<html>
<head>
  <style>
  div.outer
  {
    border:red 2px dashed;
    width:400px;
    height:250px;
  }
  div.inner 
  { 
    margin-left:30%%; width:50%; margin-right:70%%; 
    height:100%%;
    background:gold; border:brown 4px solid; 
  }
  </style>  
<head>
<body>

  <div class="outer">
    <div class="inner"></div>
  </div>
  
</body>
</html>

This document will be rendered in h-smile engine as:



As you see left and right margins of div.inner are distributed as 30:70 and they span whole free space left from width:50% and borders of the div.inner.


Key point here is distribution of free space. Computation of flex units happens as a last phase of layout algorithm – when container’s dimensions are known and all non-flex lengths were computed. Space left from fixed lengths will be distributed among elements and parts given in flexes.


Here is another example that demonstrates weighted distribution of heights:

<html>
<head>
  <style>
  div.outer
  {
    border:red 2px dashed;
    width:400px;
    height:250px;
  }
  div.inner1 
  { 
    height:1*;
    margin:4px;
    background:gold; border:brown 4px solid; 
  }
  div.inner2 
  { 
    height:2*;
    margin:4px;
    background:lightblue; border:navy 4px solid; 
  }
  </style>  
<head>
<body>
  <div class="outer">
    <div class="inner1"></div>
    Some text in between.
    <div class="inner2"></div>
  </div>
</body>
</html>

And its rendering:



As we see here heights of div.inner1 and div.inner2 are distributed using given 1:2 ratio (1* and 2*).


Notation of flex units


There are two equivalent forms of flex length notation: N%% and N*. These two forms are different by multiplier: 1* is exactly 100%%.


Computation details


If sum of flexes in the space that needs to be distributed is less than 100%% then some free space (remainder) will be left undistributed. If sum is equal or more than 100%% then all flex values are used as weights in distribution so all free space will be “covered by flexes”.


Nothing new under the sun


Idea of flex units for CSS was taken from HTML 4.0 relative length units . Flex units in N* notation are used there as values of cells dimensions. ( I do not know any html rendering engine that has this part of standard implemented though ).


XUL specification has also concept of flexes. Flexibility of widths (?) or heights(?) of elements in container is defined by the flex attribute.


Why flex’es are so good?



  1. Flex units allows to position elements with respect of other content on the page. For example if user will change base font size of the document then dimensions given in flexes will be recalculated accordingly. In principle design based on flex units will produce layout that is more stable to changes of platform dependent things – font sizes and types, screen sizes. etc.

  2. Flex units allows to position elements staying in static layout mode – without need of position:relative, absolute.

  3. Flex units significantly reduce need of use of tables or JavaScript code for layout purposes.

CSS extensions in h-smile engine. Part I. Style sets.

Style set is a named set of style declarations – it is a system of selectors and style definitions that are applied as the whole.


Style sets are declared by using @set at-rule:


@set my-table
{
td { color:blue }
td.highlighted { color:red }
}

Assignment of style set to elements is made by using style-set attribute:

table#my
{
style-set: "my-table";
}

After this declaration <table> element with id="my" will get system of styles defined by the set. In this particular case all cells ( <td>s ) will have blue color and all cells of class "highlighted" will have color red.


If somewhere later in your CSS you will have definition:


table#my {  style-set: none; }

then it will drop definitions from the set my-table all together. In other words style-set is a switch of style sets.


:root


Element that has style set applied serves role of the root for selectors defined in the set. :root pseudo class being used in style set definition matches the element this set is applied to.


Specificity of selectors in sets.


Specificity of selectors inside style set is calculated by using standard CSS algorithm.


In presence of style sets an element is getting its style in two stages:  



  1. by applying all style rules and attributes without style set – as usual.

  2. if element gets some value of the style-set attribute then the element gets all matching style from the style set.

So styles inside style set are of larger importance/weight than ordinary styles.


Motivation


Style sets mechanism solves two principal problems of CSS:



  1. They allow to define local and independent style systems for elements in the same DOM tree without need of using <frames>.


  2. Style sets allow to reduce computational complexity of style resolution. In classic CSS all style rules that used by the document are placed in the single ordered table. Task of finding list of matching selectors for the element has computational complexity near O(n), where n is a number of rules in the table. And style resolution of the whole DOM tree is O(n * m * d) task. Where m is a number of DOM elements and d is an average depth of the tree. Style sets allow to reduce significantly n multiplier in this formula.

Style sets are actively used in so called Master Style Sheet of the h-smile engine. Master Style Sheet defines default rendering and behaviors of intrinsic input elements and components. See link above for more details.

HTMPrintMeasure or basics of HTML/CSS printing

PrintEx API of htmlayout has HTMPrintMeasure function with the following signature:

HPRESULT HTMPrintMeasure(HTMPRINT hPrint, HDC hdc,
            int scaledWidth,
            int viewportWidth,
            int viewportHeight,
            int* pOutNumberOfPages);

I would like to explain here meanings of its parameters as I am getting questions about printing and scaling pretty frequently.


First fact that we need to know: pixels in HTML and CSS are logical units and have nothing common with device pixels our HTML/CSS is rendered on.


By accident 1px in HTML normally mapped to one physical pixel on screen (but not always, sic!) and one "HTML pixel" on printer can be mapped to some rectangular area that covers multiple printer "pixels". Strictly speaking printers have no pixels.


Showing that more device pixels (dots)
are needed to cover a 1px by 1px area on a high-resolution device than
on a low-res one   [D]
(illustration taken from W3C CSS specification)


According to the specification, HTML pixels are logical units that are just fractions of real length units:

   1px (html,css) = 1in / 96

Thus pixel in HTML is very close by its nature to "point" – 1pt is 1/72nd of an inch.


And this is it about theory, back to our business – HTMPrintMeasure function and its parameters:



  • int scaledWidth

    – is a number of "HTML pixels" between left and right border of the page.

  • int viewportWidth

    – is a number of "printer physical pixels" or dots between left and right border of the page (a.k.a. physical page width).

  • int viewportHeight

    – is a number of "printer physical pixels" or dots between top and bottom border of the page (a.k.a. physical page height).


At this point of our "printing saga" we can ask the question "what are the correct values for these parameters?"


Let’s assume that we have given:



  1. printer that has 600 dpi (dots per inch) resolution.

  2. paper of the format "legal" – 8.5 by 11 inches.

Calculation then is pretty straightforward:

viewportWidth = 600 dpi * 8.5in = 5100 dots (or printer pixels if you wish)
viewportHeight = 600 dpi * 11in = 6600 dots.
scaledWidth = 8.5in * 96 (html px per inch) = 816

Therefore we have 816 "HTML pixels" on printing page of the legal/portrait format in horizontal direction.
This means that if you have <table width=800> or <img width=800> then they shall fit on such page in full (if printing margins were set to zero).


In reality things are a bit more complex – you need to take in account printing margins in calculations to get precise results. But this I hope will not be so difficult for people who knows, let’s say, C# programming language .