Tuesday, June 4, 2019

Liferay polymer integration

This is a guideline for Polymer 3 PWA integration as microapplication into Liferay Portlet. The npm module code is a part of portlet and deployed within its JAR. Sample has been build with Vaadin template.

Methods described in this article is applicable to any framework from Angular to Ionic. I am focusing on Polymer 3 as most compatible and smallest base. Other frameworks need extra level of compatibility coding in order to be Liferay (or any CMS) friendly.


Modern JS frameworks in Liferay 7.1 CMS are the pain to deal with.

The internal CDN publishing of NPM modules have promised to be an great helper. The build tool uses the package.json and node_modules content to publish module and dependencies version into Liferay URL. This way same package version could be shared among applications.

This brilliant idea had not been implemented sufficiently to be suitable for high-level frameworks like PolymerJS(native web components) or Quasar( VueJs ). Such libraries use dependencies in es6 source format which meant to be compiled and bundled depend of target platform into es5 or es6 bundles. Liferay JS toolkit unfortunately treats all dependencies as pre-build to es5 AMD format. Kicking off most of modern JS libs which use ES6 'import' capabilities. Bug.


Is to use selected platform bundled build capabilities. I would suggest to use legacy (es5/AMD) and modern(ES6) browsers build profiles, both as bundles with dynamic code load. This way in majority of browsers only minimal set of  JS will be used during page load still keeping page responsive to user actions when on-demand code is loaded.

The reference implementation also gives extra perks like

  • debug mode support to use unbundled JS sources on page load
  • build profile enforcing via URL parameter
  • JS project integrated and deployed withing portlet JAR.

Design notes

  • Portlet have to be published in fixed osgi path.
    I.e. for CSS /o/my-custom-portlet/my-custom.css deployment path defined by bnd.bnd is:
        Web-ContextPath: /my-custom-portlet
  • Legacy and es6 builds have to set own root path in index.html by build.sh
  • Browser compatibility recognition done on server side by BrowserSnifferUtil and uses the build profile matching browser.
    esm-bundled, es5-bundled profiles are made for modern and legacy browsers respectively.
  • Server-side inclusion of build/${profile}/index.html is done by jsp:include
  • the top-level component included by view.jsp after as tag with data passed as html element parameters. In sample the URL for ajax call is passed from jsp to portlet.
  • <script type="module"... > during navigation into page with PolymerPortlet is ignored by Liferay SPA implementation. view.jsp has a workaround by re-injecting script tag into page. Processed script tags are marked by `injected` property.
  • es5-unbundled generates document.write("<!--") which clears the page. Fix is removing code from generated index.html

Sample Code

Happy coding!

Monday, May 13, 2019

@xmlaspect/reactive-xml - reasons of creation

For ApiFusion the import documentation from sources into MediaWiki pages become a sequence for processing various data from different sources, mostly data and html web services. This mix when implemented with classic asynchronous patterns like callbacks, Promise call chain, or `async` JS keyword become a spaghetti code mess hard to code and maintain.

An another use case inspired reacive-xml creation is a web crawling for data mining. In my case finding who will share the floor on various dance competitions.

More on apifusion.com/@xmlaspect/reactive-xml 
Open source work in progress, meanwhile xml4jQuery gives similar solution.

Sunday, August 12, 2018

EPA-Translation as Community-Driven Localisation for Web Apps

Just redefined description for epa-translation:

the community driven translations of web application will extend the application audience beyond the initially targeted countries and lingual dialects.

Why I have started a new project? Ideas are cheap, "every day a dozen" appear and are back logged forever. But this time it became another project to worry about. Worthy of the effort, ApiFusion.com and EPA-WG are actively in progress. 

First, a bit of history. When a new more or less valuable idea appears, it is usually written out and sometimes shared with friends who could have potential interest. Usually that is where its life ends. But this time, Hogne Titlestad from FriendUp invited me to discuss it in their IM group. Apparently the work on translation is in progress there. 

To make it visual for discussion, I thought 3 hours would be sufficient for proof of concept. That is when the project started. And as usual the appetite came during the meal, making me feed-frenzy towards the unusual challenges.

The challenge factor is crucial for hobby style projects. Otherwise, why bother, right?  However, it is not just the challenge swung me to work on proj. The EPA-WG needs a few clear microapplication samples, better in web 3.0 context( cross- service vendors UI and integration ). So far epa-translation seems to be complex enough in functionality and simple enough to understand. 

There is final reason to get it done: epa-translation fits into concept of community-driven content and knowledge/culture evolution which drives modern civilization to progress, where only collective intelligence could counter-balance AI. ( I do recognize other options such as AI and human fusion, but that is a bit in the future. Rather, community initiatives are acting now.)

epa-translation is a part of EPA-WG (Embeddable Progressive Application Working Group) initiative. #OpenSource hosted on GitHub.

PS. This project's challenges came from various sides:
* how to make the translation process seamless?
* how to embed microapplication into host app context?
* How to split several flows ( view, edit, sync to cloud) into independent microapplications?
* What radically new pattern microapplication gives and does it give significant advantages?
Some in HTML5 
* How to identify the text chunks in page, select and substitute?
* What local storage to use - localStorage vs IndexedDB? There is large matrix of pros and cons on each side.

Cloud layer
* Should it be server-less based?
* Should the platform be open?
* Could distributed DB be used? BlockChain vs CDN.

I am pretty sure the list of challenges will grow.

Wednesday, January 24, 2018

Sunday, October 29, 2017

WebComponents via AMD - pragmatic view

What I need for apps is ability to use AMD dependencies for my and external web components:
  • use the external libs from their CDN on prod, and local on developer machine
  • own AMD-based JS loading web components via AMD (webpack, dojo, requirejs) dependencies
  • own HTML syntax web components which list dependencies in JS section via AMD
Why AMD API? It is running without any compilers/transpilers in browser and compatible with webpack in case of need the bundling.

Why AMD instead of ES6 imports?

While ES6 imports are giving ability to load module from relative path, that is not enough as libraries could be served from different locations including different domains. AMD provides runtime URL resolving based on configuration making a combination of local component development with CDN dependencies a breathe.

How to load WebComponents via AMD?

require([   "link-import!iron-demo-helpers/demo-pages-shared-styles.html|onload"
        ,   "link-import!iron-demo-helpers/demo-snippet.html"
        ,   "link-import!../test-element.html"
        ], (a,b,c)=> console.log(`${a}, ${b}, ${c} webComponents loaded`) );

Of course the AMD configuration should be set to define URL mappings and common script loaded

  var dojoConfig ={ async: true
                  , packages:
                      [ { name: "webcomponentsjs", location: webcomponent_root }
                      , { name: "polymer", location: polymer_root }
                  , aliases:  [ [ "link-import"  , isLocal ? "/components/link-import/link-import.js" : "../../link-import.js" ]
                              , [ /(vaadin-)(.*)/, (m,x,y)=>`${vaadin_root}/${x}${y}`   ]
                              , [ /(iron-)(.*)/  , (m,x,y)=>`${iron_root}/${x}${y}`     ]
                  , deps: [ "webcomponentsjs/webcomponents-lite" ] // common for all pages

Here the Polymer and Vaadin Elements are used as good example of WebComponent frameworks.

Your custom WebComponent could use Polymer 2.x syntax and defined as HTML. Just the script section will have a class declaration wrappd into define() and dependencies are listed as JS strings instead of link imports:

        const NAME = 'test-element'
        define( NAME
            ,   [   "link-import!polymer/polymer-element.html"
                ,   "link-import!iron-ajax/iron-ajax.html"
                ,   "link-import!vaadin-material-theme/vaadin-text-field.html" //,   "link-import!vaadin-valo-theme/vaadin-combo-box.html"
                ,   "link-import!vaadin-combo-box/vaadin-combo-box.html"
            , ()=>
                class TestElement extends Polymer.Element
                    static get is() { return 'test-element'; }

                    static get properties()
                        return  {   prop1: {
                                        type: String,
                                        value: 'test-element'

                window.customElements.define( TestElement.is, TestElement );

Where to find the working sample of loading and making WebComponent via AMD?


What library I need to use AMD loader in my WebComponent?

link-import on github or NPM

Want to go wild?

Help me with creation of module loader for JS and WebComponents as jQuery plugin. The async API for jQuery is already available via xml4jQuery, WebComponents integration is missing:
    .linkImport('vaadin-combo-box/vaadin-combo-box.html') // path resolved by config
    .asWebComponent('vaadin-combo-box') // path resolved by config, WC loaded, and injected
    .prop('items',['red','green','blue]) // property assigned once WC is ready

//  will be auto-populated  even if the code run way later:
$.defineWebComponent( 'my-component' )
    .$then( ()=>$.get('colors.json') )
    .$then( (combo, colors)=> combo.items = colors );
Happy coding!

Saturday, September 16, 2017

Moraga fiscal emergency solution

The sfchronicle post inspired me to look on infrastructure cost solutions across the globe and national scope. Seems the cities and larger entities already developed several ways of making sustainable and balanced budgeting models. 

The base principle came from this brief review: the cost should be placed on shoulders the entities which actually utilizing the infrastructure. From the owners of properties to utility companies. 

For utilities the shared infrastructure rental from municipal entity, for landscape owners - the amount of water and traffic they create, ...

There is a way to have the rental super-attractive by making it significantly cheaper than servicing by themselves. The way to achieve that: use the shared infrastructure for different services. The drain system with embedded fiberoptics(cable TV, internet, phone), power, sewage and water. The highly modularized, oriented on hot-swap non-destructive replacement  grid will cost a fraction of single service. And having many services will cut the cost on level of magnitude.

Monday, July 24, 2017

SVG use notes

Notes for myself.
Dimensions Embedded SVG within HTML page have several ways to define those:

  1. CSS via style="width:18px;height:18px" or class name like class="icon"
  2. attributes via width="18px" height="18px"
  3. viewport and viewBox attributes
While all of above could define the image sizes, there is a need for discipline in orchestrating all. The best way is to rely on CSS for sizing within HTML. Hence to use only #1. 
The reason is that in HTML CSS has higher priority than width/height attributes and if SVG tag has any default style, it would override those width/height inline attributes.

For cross-browser compatibility you still need the viewBox="0 0 1000 1000" attribute to define dimensions in SVG coordinates, usually it matches the image size. Only exception is a tile - when multiple images collected in SVG and you want to display only one a time. That is an advanced technique handy for collections like color icons. 
More on W3C site.