Thursday, October 1, 2020

Window Manager

The first “desktop experience” I created back in 2002, with a simulated web-based Windows desktop. Next attempt was two years later, this time a true “window manager” for QeX 4 and later for my personal website.

User was able to maximize, minimize or drag around the window. It either displayed an internal content, or external content in an iframe. Properties of each window, like position or state, was stored in a session and in user's profile.

Tiles in Win8 Start Menu is a great concept.

Monday, September 28, 2020

Which input type?

If the answer is YES, use checkbox. If the answer is A or B (or C, D or E), use radio. If there are more options, than five, use listbox. And if user can enter own custom value instead of offered choices, use combobox (textbox + listbox) or textbox with autocomplete.

☑ Do you want an ice cream?

Which ice cream do you want?🔘 Vanilla🔘 Chocolate

In Qedy, there are two kinds of textboxes with autocomplete. One based on "text" type, allowing to add any value, with autocompleted options only as a faster way of adding common values, and one based on "enum" type, where user is forced to pick one of the options from the menu.

In other words, text.autocomplete is more fancy text box and it's best used in situations where you want push users towards certain values (also dealing with letter capitalization or accents), while enum.autocompelete is text based select for situations, where listbox would have too many options.

Thursday, April 23, 2020

Subjects

With the team we finished a module for subjects (people and companies). We were hoping to get a shortcut, but the customer disagreed :-), so in the last months of many improvements and fixes I was forced to add a lot of technical debt to the codebase.

Another setback was the customer is still using IE11 and the original Edge, which added more complexity to the code, as various polyfills were required and also separate stylesheets, because there's no way to distinguish between the two using just media queries:

  1. IE11:
  2. @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) { ... }
  3. Edge:
  4. @supports (-ms-ime-align:auto) { ... }

This was our first deployment of QedyJS, where we gathered awful lot of experience, and also the module is only a temporary solution for the customer, because he contracted another company, that are unable to provide their solution at the moment for legal reasons.

So I took the opportunity and created basically a working “demo” of what the final version of QedyJS should be capable of, only without all the hacks, tweaks and crutches. It's always easier to think of what to do differently, than what to do. This demo became a foundation for the Mk. III announced back in January and was largely enhanced since – Mk. IIIb, if you will.

There were some approaches I didn't like, some of them didn't work, some of them were sub-optimal, some of them was proven and will be kept, some of them were introduced for the first time and some of them were put aside for the time being.

I gathered all of the above and started once again with a clean plate. This time not as my primary project, but rather as a side project to pamper and enjoy. I wanted to have the time to do it really properly, to be able to elaborate on ideas, to have an incubator for them.

Monday, February 10, 2020

Styling components

…Adding styles in QedyJS v3

.style(...)

(+) Snadné na implementaci, snadné použití

(-) Vždy budou kombinované selektory .comp.style a bude jich HODNĚ.

.style(...) => o... + i...

(+) Snadné na implementaci, snadné použití

(+) Jedna sada stylů

(-) Matoucí, v CSS nebude existovat styl, který zadám do .style(xxx); vždy bude prefixovaný

.styleInner(...) + .styleOuter(...)

(+) Jasné, málo kdy budou styly stejné

(-) Příliš mnoho psaní, rád bych měl jen .style(...), aby to korespondovalo se specifikací komponenty

(-) Dvě sady stylů v definici komponenty

.style(..., true)

(+) Ideální varianta

(-) Druhý parametr již je boolean na "force" (ala classList.toggle)

(-) Dvě sady stylů v definici komponenty

Tuesday, February 4, 2020

Lighthouse

After the blog conquered PageSpeed Insights, it's time to do the same with Lighthouse.

It's conveniently embedded with Chromium-based browsers and the new Edge is no different. Simply open DevTools and go to “Audits” page, which may be hidden under the “»”. There select desired categories, maybe some community plugins, and pick a target device (mobile or desktop). Then click the “Generate report” button and wait.

It will refresh the page couple of times and after a few seconds it shows scores between 0 (worst) and 100 (best) for Performance, Accessibility, Best Practices, SEO and where applicable, Progressive Web App (PWA).


...and some of them are even not faked or anything ;-)

In every section it will tell you what passed and what failed, with description how to improve it. Sometimes it's may be impossible to score 100 simply due to webhosting limitations, if you e.g. can't define headers for static files.

Tuesday, January 14, 2020

Layout reflow

In Dev Console I sometimes got a warning, that page reflow took so much ms. And because I'm curious, I looked up what it means.

Reflow is basically recalculation of dimensions and positions for some or all layout elements on the page. Just from this description you may understand it's pretty expensive (performance-wise) task.

Reflow can be triggered by manipulating DOM, changing visuals (computed styles and classes), resizing browser's window and more. Different browser engines have slightly different triggers and time required for the particular reflow type, but the general idea remains.

You can speed up the reflow process by reducing DOM depth, CSS rules and complex selectors; or moving complex rendering (e.g. animations) out of the flow using absolute or fixed position for the element.

Friday, July 5, 2019

Saving

There are basically three major approaches:

  • save everything at once using a manual trigger (button),
  • save after every change using an event trigger,
  • save after a time period using a timer.

My approach is a combination of all of the above, with incremental saves prevalence. But, as usual, things aren't as simple as they may seem. In forms you can save data only after all required fields are filled. In editing long text there are no partial changes, so there's no cue when to save.

Therefore I have two ways of auto-save in a text. I define a 5 secs timer, that saves the text after it's not changed, which means e.g. arrow keys do not stop this from firing. The other way is I save after Enter key is pressed.

Before each change of text I create a “backup”, to have an undo option in case I or the editor mess it up. After the text is verified, those backups are deleted.

I also try to show saving in some unobtrusive way, like dimming header color or change it's background.

Saturday, June 1, 2019

Scoping

I started with a single “master” scope for all components and data elements. It went well, until it didn't :-) I needed to separate elems in lists (table columns), because they also got filled by the .data method.

The obvious choice was to create a per-component scope, but problems were single data elements can appear in multiple components and at the same time a single form can be composed of multiple other components.

So I tried keep all elems in the global scope and separate all elems in lists. It worked well and it solved the issue I had.

But I still had one issue, I wasn't able to declare a custom temporary form or a form-in-form. So the ultimate decision (and hopefully the last major rewrite of the whole thing) was to have somewhat hybrid scenario with per-major-component scopes – besides separate scope for lists, all nested forms will inherit scope from the initial parent form.

This way the nested parent form will have separate scope and a custom form, e.g. in a modal window, will also have it's own scope.

And to make it even more complex, I had to add a scope-groups, because I allow to load multiple modules at once (module-in-module) and I know what scopes to remove with closing the nested module. The former way didn't look right anyway :-)

Wednesday, October 17, 2018

Client-Server Web App

I'm often oldschool and even I keep an eye on contemporary approaches, I don't really pay much attention to them. I'm probably worried it's just a short term fashion or an upcoming dead end, but sometimes I miss a lot for a long time - like this time.

I prefer server side HTML rendering, because it's a single solution for both users and robots. I perceive Node.js as yet another Java, so server side JavaScript for the single solution is not appealing to me.

Years ago I participated on project, where client side was created using GWT in JavaScript, while servlet only provided data via API in a form of JSON messages. I liked the idea, but I didn't see myself doing such thing.

Few years after that I participated on a project with the same approach once again and still didn't see what it's all about, but this time I finally wanted to try it. My opportunity came in less than a year.

The project for it was perfect – transforming old intranet app, created in Microsoft Access, into a modern web app. Because of the Microsoft ecosystem, my proposal to use ASP.NET Core looked like an obvious choice.

I was little worried the Core platform may lack some features, but version 2.x was mature enough to provide everything I needed and I had QetriX up and running in just a few days.

For the client side I created standalone HTML templates, that defined a layout and components. Because nowadays the DOM is optimized enough, I opted out of virtual DOM, defined custom properties as “data” attributes and the rest as QetriX Modules.

It worked surprisingly well, but I also encountered some drawbacks. First of all, I worked with a lot of numbers, but values and data attributes are strings, so I had to convert data types all the time. Second of all...

Wednesday, April 18, 2018

Search box command line

The search box is asking for being abused as a command line, for several reasons: It's everywhere, it's easy to reach, it's simple and you can type anything into it. So I do, actually I've been guilty of that for ages - since QeX.

I usually prefix commands. I started by simply adding a space before the command, but sometimes there are spaces in the pasted text, so using a whitespace is not good idea.

So the next best thing is using two dashes before the command. The advantage of dashes is there are two keys for them on the keyboard, one of which is neatly in the corner of numpad, so it's very easy to find.