Tuesday, December 1, 2020

Link preload × prefetch

rel="preload" loads a resource early for the current document before the body is parsed, potentially saving overall loading time.

As a hint with a lower priority, rel="prefetch" caches a resource for the next navigation after the current document has been loaded.

Lorem ipsum dolor sit amet.

  1. <link rel="prefetch" herf="URL">

vs

  1. <link rel="preload" href="URL" as="MIME_TYPE">

preload is a declarative fetch, allowing you to force the browser to make a request for a resource without blocking the document’s onload event.

Prefetch is a hint to the browser that a resource might be needed, but delegates deciding whether and when loading it is a good idea or not to the browser.

preload

<link rel="preload"> tells the browser to download and cache a resource (like a script or a stylesheet) as soon as possible. It’s helpful when you need that resource a few seconds after loading the page, and you want to speed it up.

The browser doesn’t do anything with the resource after downloading it. Scripts aren’t executed, stylesheets aren’t applied. It’s just cached – so that when something else needs it, it’s available immediately.

prefetch

<link rel="prefetch"> asks the browser to download and cache a resource (like, a script or a stylesheet) in the background. The download happens with a low priority, so it doesn’t interfere with more important resources. It’s helpful when you know you’ll need that resource on a subsequent page, and you want to cache it ahead of time.

The browser doesn’t do anything with the resource after downloading it. Scripts aren’t executed, stylesheets aren’t applied. It’s just cached – so that when something else needs it, it’s available immediately.

Sunday, November 1, 2020

Autumn cleanup

I noticed some concepts in Qedy ain't right. For instance, I always perceived Modal window as a separate entity, but in fact it's just bit more complicated QView. This also once again confirms, that my choice of just four component types (elem, form, list, view) is indeed sufficient.

Similar problem was with various frontend perks, like content prefetching or smooth scrolling. I added prefetch to an ordinary QList as f_prefetch feature and I created some extensions (“plugins”) for QView_Page.

Saturday, August 15, 2020

HTTP routing

http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html

https://github.com/nikic/FastRoute

https://benhoyt.com/writings/go-routing/

You have several options, how to route HTTP requests. My habit is to find the fastest way, but it's not needed here, because the router is called only once on URL change.

Table

Loop through pre-compiled regexes or patterns and pass matches using the request context

  1. router.addRoute(httpMethod, "a/(*.)/c", routeHandler),

Or use directly the HTTP method:

  1. router.get("a/(*.)/c", routeHandler);

Switch

A switch statement with cases that call a regex-based match() helper which scans path parameters into variables.

Similar to regex match, but using a simple pattern matching function instead of regexes. It's not that powerful, but you will mostly need “anything” wildcard for a path part anyway.

  1. case httpMethod == "GET" && routeRegexPattern.match("a/(*.)/c"):
  2. return routeHandler();

Split

Split the path on / and then switch on the contents of the path segments

  1. case httpMethod == "GET" && p[0] == "a" && p[1] == "b":
  2. return routeHandler();

Shift

Basically delegates the route matching to the module, according to the first path part. For a/b/c path the router will call an “a” module, pass him [b,c] and don't care any more.

 

Thursday, June 25, 2020

Web icons

You have several options when it comes to icons on a web. The oldest way is to use images (GIF, later PNG), but they may look blurry on today's high DPI displays. You can use SVG, which is great, scales great, but may become CPU heavy and are harder to recolor on hover events. And then you have font icons.

Typicons

Microns

Icomoon

Font Awesome 3

Font Awesome 4

Thursday, January 30, 2020

JavaScript Framework Mk. III

If I find reengineering favorable, I usually go for it. Therefore major versions with breaking changes appear fairly quickly in the beginning of a new software product, allowing me to stabilize the API as soon as possible.

On the other hand, most changes are in QedyJS, so unfortunately almost none of the current improvements will go open source.

Scopes. Multiple modules at once, scope is passed with the component, which is no problem in most cases. But it's a little annoying, since I decided to have no cirucular references, which means a component can't contain scope object and therefore I have to pass component and scope separately in two parameters. And for the rest you must specify the scope, which is also annoying, but also necessary.

Speaking of scopes, I reimagined JavaScript scopes as well. Now module methods have direct access to the scope via this and because I decided to “trust” converters, they have now direct access to components and therefore are able to modify them. It makes a lot of things much easier and more streamlined.

I waited with a release many months, to have full functionality right from the start. Nothing was postponed (like datastores in Mk. II), because that's what bit me in the butt in the past the most.

Found even more great articles and talks about JS performance and did tremendous amount of micro optimizations in the code, especially in loops, where it makes sense the most. Some (if not most) of them are probably unnecessary, but I'm a performance freak, so it feels good to have 'em all :-)

Got rid of domLinks, now links are bundled with the component. The same applies for items and data-realted logic (e.g. sorting and filtering) were moved from components to datastores.

Some of original designs are great and in fact some of them even goes back to Mk. I. And don't let me start with the whole concept of QetriX, I must admin it makes me proud the core basics I established over a decade ago still works perfectly.

Friday, September 13, 2019

Navigator

Browsers and especially Chromium based ones offers a lot of information about the device it's running on in various APIs. They are great if you want to tailor the experience for your users.

Some of such APIs are in Navigator interface, accessible as read-only object from window.navigator property.

navigator.connection: .effectiveType (how fast), .saveData (data saver preference)

navigator.deviceMemory: reducing memory consumption

navigator.hardwareConcurrency: limit CPU intensive logic and effects

Those APIs also could be abused. There's a rumor one Booking site used now deprecated Battery Status API to crank up prices when your Android phone was running low on juice and therefore you probably didn't have much time to think and compare.

Friday, June 14, 2019

CORS and CSP

In recent years browser manufacturers added an additional security checks for third party content, in a form of headers or META tags.

CORS (Cross-Origin Resource Sharing) is telling the browser it can read data even if it's in different origin. You can get around it using a CORS Proxy.

CSP (Content Security Policy) battles XSS (cross site scripting) and packet sniffing attacks, and exists in three versions. The first requires to specify a white-list of allowed sources in Content-Security-Policy header, which often led to enabling all of them for convenience. The second introduced a nonce, and the third is the best, but not yet widely supported.

Monday, May 6, 2019

xx

I had a little more time, so instead doing just incremental changes I was able to go knee-deep into some of those excremental ones :-)

Wednesday, January 16, 2019

QuacFeeds

RSS, RDF, Atom easily, not inventing wheel. It's similar to each other, so I used XDocument for that with ease.

Every feed item holds a “feed” object, containing basic info about the feed, because in one timeline there are multiple feeds.

As a storage I used serialization, until it became unbearable and I'll do it properly using SQLite database.

Wednesday, January 30, 2019

QuacTweetsRead

Register as Dev on Twitter website.

For starters I used a nice tutorial by Danny Tuppeny for simple Twitter posting and it really worked right away. But I abandoned his solution for one based on TinyTwitter, which I still had to modify heavily.

For example, it's quite old and therefore doesn't support 280 char tweets. I had to add tweet_mode=extended to API call and then in JSON response use full_text instead of text.

Speaking of JSON, for Qip I used heavily modified custom JSON library, even there's the popular Json.NET from Newtonsoft. It's based on per-character loop and I don't think there's much faster approach how to parse it.

I customized it to accept comments and commas after the last element or property (in a JSON5 manner). For viewing I used open source JSON Viewer by Eyal Post.

Problem datetime created_at thanks to solution:

```

DateTime createdAt = DateTime.ParseExact(tweet["created_at"], 

"ddd MMM dd HH:mm:ss +ffff yyyy", new System.Globalization.CultureInfo("en-US"));

```

asdf

Wednesday, January 23, 2019

QuacIcons

…asdf IconsDownload

RSS or favicon

Bitmap as PNG or ICO to PNG

Quac icon as dynamic bitmap.

Custom Quac icons, that gives users a freedom to use whatever icon they please.

Tuesday, August 28, 2018

SVG, Sometimes Verbose Gibberish

For icons and glyphs I've always preferred webfonts, because they're easier to work with and has much lower impact on CPU. But they're not easy to create, fortunately there are services like Fontello, that allows to pick only what I need.

Inline SVG in CSS

  1. background-image: url('data:image/svg+xml;utf8,<svg height="16" version="1.1" viewBox="0 0 48 48" width="16" height="16">...</svg>');

Mismatched markup, unnecessary namespaces, ballast metadata from editors, empty <g> elements etc.

Editing by hand, simple HTML editor

Thursday, June 21, 2018

xxx

xxx

Sunday, June 17, 2018

Inverse square root

xx

https://pastebin.com/4Afm45AH

https://en.wikipedia.org/wiki/Fast_inverse_square_root

www.beyond3d.com/content/articles/8/ www.beyond3d.com/content/articles/8/www.beyond3d.com/content/articles/15/ www.beyond3d.com/content/articles/15/www.lomont.org/Math/Papers/2003/InvSqrt.pdf www.lomont.org/Math/Papers/2003/InvSqrt.pdfbetterexplained.com/articles/understanding-quakes-fast-inverse-square-root/betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/

Even I still adore Data Particles I “invented” almost 10 years ago, without proper tools (I struggle to create) it's quite hard to manage the data. I encounter it from time to time when I need to fix some order in our intranet app.

So for QB I decided to move from Data Particles to JSON structure I created for Qedy. It suits the purpose rather well and I can improve it to be mutually beneficial.

  1. float Q_rsqrt(float number)
  2. {
  3. long i;
  4. float x2, y;
  5. const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = *(long *) &y; // evil floating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // what the fuck? y = *(float *) &i; y = y * (threehalfs - (x2 * y * y)); // 1st iteration // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration
  6. return y;
  7. }

I created a simple parser, that runs for every ID, which is time consuming, but there's no rush.

Wednesday, February 28, 2018

Subjects

I thought more about tags and found out it's even more flexible, than I imagined. All in the sense of the original idea of simplification for QetriX, tags is a generic group of anything.

It works well for users. Now tag is not only a group of users, but it acts as a role as well. You can tag users as “employee”, “customer”, “vip”

Sunday, June 25, 2017

Coding standards

I know the industry standard is keep lines of code up to 80 characters. Also I know my FullHD computer screen has a pivot, so I can it to "portrait" mode to see much more lines.

But I don't.

PSR

tabs vs spaces

Idiomatic CSS and JS

Sunday, October 16, 2016

JSON

…I consider it a great data type

object's keys are unordered, usually ordered by name or by how properties were added.

array always preserves order of elements

Not for humans, so for better human writing emerged more forgiving formats, like JSON5 (ES5), HJSON and more.

There's a nice summary of all competing formats.

Saturday, October 8, 2016

Relations

ER diagram editor, multipurpose

Canvas or SVG

Monday, August 1, 2016

Qedy

Golfers have caddie, corporations have Qedy. Both do basically the same job – supports the star in every way possible. And there are really many ways for Qedy!

Qedy is a commercial extension of the Framework, which means most of the shared functionalities won't be open source. Qedy is purposed for rapid development of intranet and extranet information systems.

With Qedy, instead of coding, you simply create your apps in Builder, where you can see a mockup of GUI, define a data model, create label translations and more.


Qedy Logo: “ED” from rotated Q, styled as Möbius strip.

But Qedy isn't just for web apps, you can create websites with it as well! Using simple block approach you add content for the page quickly and easily. In fact, exhibit A is this blog, whose content editor uses exactly that.

With Qedy you can define component conditions, visualize them and test using defined values.

Thursday, June 11, 2015

Order by rating

Incorrect:

SELECT name, positive, negative, positive/total x FROM productz ORDER BY x DESC;

By the way, I'm not sure that the Wilson correction gives any better results than a one standard deviation lower bound for the positive score:

SELECT name, positive, negative, positive/total - sqrt(positive*negative/total)/total x FROM productz ORDER BY x DESC;

Score = Lower bound of Wilson score confidence interval for a Bernoulli parameter:

SELECT name, positive, negative, ((positive + 1.9208) / (positive + negative) - 

                   1.96 SQRT((positive negative) / (positive + negative) + 0.9604) / 

                          (positive + negative)) / (1 + 3.8416 / (positive + negative)) 

       AS ci_lower_bound

FROM productz

WHERE positive + negative > 0 

ORDER BY ci_lower_bound DESC;

Single 1 0 1

Good new 5 0 1

Excellent 23400 23 0.9988134107340426

Quite good 520 200 0.7055298549839887

Exc-ish 5 1 0.6811881781678829

Some shitty 1000 2000 0.3247267033417656

Quite bad 28 82 0.21301210856756564

Bad-ish 1 2 0.06116780616017409

Single bad 0 1 0

Single 1 0 1.0000

Good new 5 0 1.0000

Excellent 23400 23 0.9990

Exc-ish 5 1 0.8333

Quite good 520 200 0.7222

Some shitty 1000 2000 0.3333

Bad-ish 1 2 0.3333

Quite bad 28 82 0.2545

Single bad 0 1 0.0000

Excellent 23400 23 0.998

Quite good 520 200 0.688

Good new 5 0 0.565

Exc-ish 5 1 0.436

Some shitty 1000 2000 0.316

Single 1 0 0.206

Quite bad 28 82 0.182

Bad-ish 1 2 0.061

Single bad 0 1 4.586

rating = (((positive + 1.9208) / (positive + negative) - 1.96 Math.Sqrt(((positive negative) / (positive + negative)) + 0.9604) / (positive + negative)) / (1 + 3.8416 / (positive + negative)));