Sunday, April 5, 2020

JSM CDN use in stackoverflow sample

Newer thought to have JSM CDN useful in stackoverflow. If you check my answer, it is capable of running the sample inline from CDN.

   https://stackoverflow.com/questions/50404970/web-components-pass-data-to-and-from

Data from HTML attribute - Declarative Programming with Web Components

How to pass JSON string from HTML as object for data binding of Polymer Web Component?

The answer resides in embedding of data into URL of iron-ajax.
vaadin-elements-demo.html
<iron-ajax url='data:text/json;charset=utf-8, 
                [{"label": "Hydrogen", "value": "H"} 
                ,{"label": "Oxygen"  , "value": "O"} 
                ,{"label": "Carbon"  , "value": "C"} 
                ]'
           last-response="{{lifeElements}}" auto handle-as="json"></iron-ajax>
<vaadin-combo-box id="cbDemo"
        label="Label, value:[[cbDemoValue]]"
        placeholder="Placeholder"
        items="[[lifeElements]]"
        value="{{ cbDemoValue }}"
>
    <template>
        [[index]]: [[item.label]] <b>[[item.value]]</b>
    </template>
</vaadin-combo-box>
<vaadin-combo-box label="Disabled" disabled value="H" items="[[lifeElements]]"></vaadin-combo-box>
<vaadin-combo-box label="Read-only" readonly value="O" items="[[lifeElements]]"></vaadin-combo-box>

Sunday, March 15, 2020

Polymer 3 dom-bind event handling

Original intent

is to update the text when component.selection is changed
index-0.html
<textarea style="width: 100%;height: 9em" id="configtext"></textarea>
<button onclick=" navigator.clipboard.writeText(configtext.value) ">&boxbox; Copy</button>

<webcomponents-element visible="true" id="webcomponentsElement" ></webcomponents-element>
<script>
    window.addEventListener("load",()=>{
        webcomponentsElement.addEventListener("selection-changed",(ev)=>{
            configtext.value=webcomponentsElement.selection.replace( /,/g , ",\n");
        });
    });
</script>

using dom-bind

The change handler is still initialized in SCRIPT code:
index-1.html
<dom-bind id="configurator">
    <template>

        <textarea style="width: 100%;height: 9em" id="configtext"></textarea>
        <button onclick=" navigator.clipboard.writeText(configtext.value) ">&boxbox; Copy</button>

        <webcomponents-element visible="true" id="webcomponentsElement"
                               on-selection-changed="onSelectionChanged"
        ></webcomponents-element>
    </template>
</dom-bind>
<script>
    configurator.onSelectionChanged = function (e) {
        configtext.value = webcomponentsElement.selection.replace(/,/g, ",\n");
    };
</script>

Final version - The power of declarative programming!

No JavaScript, binding only via sel variable scoped in binding context of dom-bind.
index.html
<dom-bind>
    <template>
        <textarea style="width: 100%;height: 9em" id="configtext" value="{{sel::change}}"></textarea>
        <button onclick=" navigator.clipboard.writeText(configtext.value) ">&boxbox; Copy</button>

        <webcomponents-element visible="true" id="webcomponentsElement" selection="{{sel}}"></webcomponents-element>
    </template>
</dom-bind>

Sunday, March 8, 2020

Java Lambda vs method performance is 2x slower

Going over algorithms exercises I found that inline functions with access to outer scope variables make code way cleaner.  In Java 8+ I know two ways of doing so:

  1. wrap an outer scope variables in object and define a method
  2. use Lambda functions
Surprisingly 1st method became almost 2x more performant:
member
    final public class
BinaryGap
{
    public BinaryGap( long value ){ val = value; }

        public final static int
    maxGapCount( final long value )
    {
        final BinaryGap vo = new BinaryGap(value);
        vo.skipBits(0 );

        for( int max0 = 0; vo.val !=0 ; )
        {
            vo.skipBits(1 );
            int z = vo.skipBits(0 );
            if( z == 0 )
                return max0;
            if( z > max0 )
                max0 = z;
        }
        return 0;
    }
    long val;

    final int skipBits( final int bit0 )
    {   int ret = 0;
        do
        {   if( val == 0 || (val&1) != bit0  )
                return ret;
            val = val >> 1;
            ret++;
        }while( val != 0 );
        return ret;
    }
}
Lambda
        public final static int
    maxGapCountLambda(  long value )
    {   class Wrap{ long v; }
        final Wrap w = new Wrap(); w.v = value;
        IntSupplier skip0 = ()->
        {   int count=0;
            long L = w.v;
            for( ; L!=0 && (L&1) == 0; count++ ) // skip 0
                L = L>>1;
            w.v = L;
            return count;
        };
        IntSupplier skip1 = ()->
        {   long L = w.v;
            while( L!=0 && (L&1) == 1 ) // skip 1
                L = L>>1;
            w.v = L;
            return 0;
        };

        skip0.getAsInt();
        int maxCount =0;
        while( w.v != 0 )
        {
            skip1.getAsInt();
            int count =skip0.getAsInt();
            if( count > maxCount )
                maxCount = count;
        }
        return maxCount;
    }

Tests

Test Duration Result
maxGapCount 0s passed
maxGapCountInlineLoad 0.126s
Of course inline is fastest, but not as much readable.
passed
maxGapCountLambdaLoad 0.226s passed
maxGapCountLoad 0.141s passed
skipBits 0s passed
Full sources
BinaryGap.java
package codily.lesson1;

import java.util.function.IntSupplier;
import java.util.function.LongPredicate;
import java.util.function.LongToIntFunction;

/**
 * https://app.codility.com/programmers/lessons/1-iterations/binary_gap/
 */
    final public class
BinaryGap
{
    long val;
    public BinaryGap( long value ){ val = value; }

        public final static int
    maxGapCount( final long value )
    {
        final BinaryGap vo = new BinaryGap(value);
        vo.skipBits(0 );

        for( int max0 = 0; vo.val !=0 ; )
        {
            vo.skipBits(1 );
            int z = vo.skipBits(0 );
            if( z == 0 )
                return max0;
            if( z > max0 )
                max0 = z;
        }
        return 0;
    }
        public final static int
    maxGapCountInline(  long value )
    {
        while( value!=0 && (value&1) == 0 ) // skip 0
            value = value>>1;
        int maxCount =0;

        while( value !=0 )
        {
            while( value!=0 && (value&1) == 1 ) // skip 1
                value = value>>1;

            int count =0;
            while( value!=0 && (value&1) == 0 ) // skip 0
            {   count ++;
                value = value >> 1;
            }
            if( count > maxCount )
                maxCount = count;
        }
        return maxCount;
    }
        public final static int
    maxGapCountLambda(  long value )
    {   class Wrap{ long v; }
        final Wrap w = new Wrap(); w.v = value;
        IntSupplier skip0 = ()->
        {   int count=0;
            long L = w.v;
            for( ; L!=0 && (L&1) == 0; count++ ) // skip 0
                L = L>>1;
            w.v = L;
            return count;
        };
        IntSupplier skip1 = ()->
        {   long L = w.v;
            while( L!=0 && (L&1) == 1 ) // skip 1
                L = L>>1;
            w.v = L;
            return 0;
        };

        skip0.getAsInt();
        int maxCount =0;
        while( w.v != 0 )
        {
            skip1.getAsInt();
            int count =skip0.getAsInt();
            if( count > maxCount )
                maxCount = count;
        }
        return maxCount;
    }


        final int
    skipBits( final int bit0 )
    {   int ret = 0;
        do
        {   if( val == 0 || (val&1) != bit0  )
                return ret;
            val = val >> 1;
            ret++;
        }while( val != 0 );
        return ret;
    }
}
BinaryGapTest.java
package codily.lesson1;

import org.junit.Test;
import static org.junit.Assert.*;

    public class
BinaryGapTest
{
    public final long [] exp =  { 00, 00, 00, 00, 00, 00, 01, 02, 03, 30 };
    public final long [] inp =  { 0b0000_0000_0000_0000_0000_0000_0000_0000L
                                , 0b1111_1111_1111_1111_1111_1111_1111_1111L
                                , 0b0000_0000_0000_0000_0000_0000_0000_0001L
                                , 0b0000_0000_0000_0000_0000_0000_0000_0011L
                                , 0b0000_0000_0000_0000_0000_0000_0000_0010L
                                , 0b0000_0000_0000_0000_0000_0000_0000_0100L
                                , 0b0000_0000_0000_0000_0000_0000_0000_0101L
                                , 0b0000_0000_0000_0000_0000_0000_0000_1001L
                                , 0b0000_0000_0000_0000_0000_0000_1000_1001L
                                , 0b1000_0000_0000_0000_0000_0000_0000_0001L
                                };
    long [] act= new long[inp.length];

        @Test public void
    maxGapCount()
    {
        assertEquals(00, BinaryGap.maxGapCount( 0b0000_0000_0000_0000_0000_0000_0000_0000L ) );
        assertEquals(00, BinaryGap.maxGapCount( 0b1111_1111_1111_1111_1111_1111_1111_1111L ) );
        assertEquals(00, BinaryGap.maxGapCount( 0b0000_0000_0000_0000_0000_0000_0000_0001L ) );
        assertEquals(00, BinaryGap.maxGapCount( 0b0000_0000_0000_0000_0000_0000_0000_0011L ) );
        assertEquals(00, BinaryGap.maxGapCount( 0b0000_0000_0000_0000_0000_0000_0000_0010L ) );
        assertEquals(00, BinaryGap.maxGapCount( 0b0000_0000_0000_0000_0000_0000_0000_0100L ) );

        assertEquals(01, BinaryGap.maxGapCount( 0b0000_0000_0000_0000_0000_0000_0000_0101L ) );
        assertEquals(02, BinaryGap.maxGapCount( 0b0000_0000_0000_0000_0000_0000_0000_1001L ) );
        assertEquals(03, BinaryGap.maxGapCount( 0b0000_0000_0000_0000_0000_0000_1000_1001L ) );
        assertEquals(30, BinaryGap.maxGapCount( 0b1000_0000_0000_0000_0000_0000_0000_0001L ) );
    }
    final int REPEAT_COUNT = 1000_000;

    @Test public void
    maxGapCountLoad()
    {
        for( int k=0; k < REPEAT_COUNT; k++ ) // timer count
            for( int i=0; i<exp.length; i++ )
                act[i] = BinaryGap.maxGapCount( inp[i] );
        assertArrayEquals( act, exp );
    }
        @Test public void
    maxGapCountInlineLoad()
    {
        for( int k=0; k < REPEAT_COUNT; k++ ) // timer count
            for( int i=0; i<exp.length; i++ )
                act[i] = BinaryGap.maxGapCountInline( inp[i] );
        assertArrayEquals( act, exp );
    }
        @Test public void
    maxGapCountLambdaLoad()
    {
        for( int k=0; k < REPEAT_COUNT; k++ ) // timer count
            for( int i=0; i<exp.length; i++ )
                act[i] = BinaryGap.maxGapCountLambda( inp[i] );
        assertArrayEquals( act, exp );
    }

        @Test public void
    skipBits()
    {
        BinaryGap bg = new BinaryGap( 0L );
        assertEquals( "zero", bg.skipBits(0), 0 );
        assertEquals( "zero", bg.skipBits(0), 0 );
        assertEquals( "zero", bg.skipBits(1), 0 );

        bg = new BinaryGap( 0b1111_1111_1111_1111_1111_1111_1111_1111L );
        assertEquals( "zero", bg.skipBits(0), 0 );
        assertEquals( "zero", bg.skipBits(1), 32 );
        assertEquals( "zero", bg.skipBits(1), 0 );
        assertEquals( "zero", bg.skipBits(0), 0 );
    }
}

Thursday, February 20, 2020

polymer bi-directional databind within dom-repeat

Two-way databinding in dom-repeat could be based on extending the item model with component-specific field ( where it is a good habit to use component-specific prefix).

In sample the fieldset is shown only upon checkbox selection.

<ul>
    <template is="dom-repeat" items="[[forms]]">
        <paper-checkbox label="Enable [[item.name]]" checked="{{item.fieldset_enabled}}"></paper-checkbox>
        <template is="dom-if" if="[[item.fieldset_enabled]]">
            <fieldset><legend> '[[item.name]]' section </legend>
                ...
            </fieldset>
        </template>
    </template>
</ul>