14 luglio 2019

javascript ES6 ES2015

const

const myVar = 'value';
myVar = 'value2'; // error


let

var myVar = 'value';
if( myVar ){
    let myVar = 'value2';
    console.log(myVar);  // 'value2'
}
console.log(myVar);  // 'value'


String Template

let myHtml = `<div>${myVar}</div>`; // ` -> back tick character
let myTemplate = `
    <div>
        <span>${var1}</span>
        <span>${var2}</span>
    </div>
`;


Default values

function myFunction(par='some value'){
     // code
}
var defaultValue = 'value';
function MyFunction2(par=defaultValue){
    // code
}


Arrow function

let add5 = par1 => par1+5;
let sum = (par1, par2) => par1 + par2;
let myFunc = (par1, par2) => {
    if(par1<=0){
        par1 = 1;
   }
   return par1*par2;
}
let myObj = {
    myMeth: function(){   
         // code
   }
   myMeth2: function(){
         setTimeout(function(){
              this.myMeth(); // ERROR! function not preserve scope
        }, 1000);
   }
   myMeth2: function(){
        setTimeout( ()=>{
            this.myMeth();  // scope is myObj
        },1000);
   }
}

Destructuring

let obj = {k1:v1, k2: v2};
let {k1, k2} = obj;
console.log(k1, k2);
let myFunc = ({k1}) => console.log(k1);
let arr = ['first', 'second', 'third'];
let [firstItem] = arr;
let [,, thirdItem] = arr;

Object Literal Ehancement

let var1 = value1;
let var2 = value2;//rest is array without first item
let obj = {var1, var2}; //obj= {var1:value1, var2:value2}
let myFunc = function(){  
     return this.var1;
};
let obj2 =  {var1, var2, myFunc};
let obj3 = {
    prop1,
    prop2,
    myMeth(){
        //code
   }
}

Spread Operator

let arr1 = [v1, v2, v3];
let arr2 = [v4, v5, v6];
let arr3 = [...arr1, ...arr2]; //arr3 = [v1, v2, v3, v4, v5, v6];
let [last] = arr.reverse(); //array altered
let [last] = [...arr].reverse(); 
let [first, ...rest] = arr; //rest is array without first item
let obj = {k1:v1, k2:v2};
let prop = value;
let obj2 = {...obj, prop};

Promise

const getUsers = count => new Promise(
    (resolves, rejects) => {
         const url = `http://myapi/user/?limit:${count}`;
         const req = new XMLHttpRequest/(;
         req.open('GET', url);
         req.onload = () =>  req,status == 200 ? 
                            resolves(JSON.parse(req.response)).results :
                            reject(Error(req.statusText));
         req.onerror = (err) => reject(err);
         req.send();
   }
);

getUsers(10).then(
         users=>console.log(users), 
         err => console.error(err)
     );
getUsers(10)
    .then(users=>console.log(users))
    .catch(err=>console.log(err));


Class


class MyClass {
    constructor(par1, par2){
        // code
    }
    myMeth(){
        // code
    }
}
class MyClass2 extends MyClass{
    constructor(par1, par2, par3){
        super(par1, par2);
        // code
    }
    myMeth2(){
        // code
    }

}


Module

Module -> file

file1.js
export const myFunc = (par1) => par1+5;
export const myFunc2 = (par2) => par2^2;

file2,js
export const default myVar = 5;

file3.js
import {myFunc, myFunct2} from "./file1";
import {myVar} from "./file2";

alias
import {myFunc as f1, myFunct2 as f2} from "./file1";
all
import * as f from "./file1"

NodeJS (Common js)

file1.js
module.exports = {myFunc, myFunct2};
file3.js
const {myFunc, MyFunc2} = require("./file1");

3 agosto 2018

React prefill input/form

In these example form components are react uncontrolled components.

It's best practice using controlled input (value+onChange. https://reactjs.org/docs/forms.html)


Example 1: implement componentDidUpdate method

class Form extends Component { submit = (e) => { e.preventDefault(); var user = Object.keys(this.refs).reduce( (obj, k) =>{ obj[k] = this.refs[k].value; this.refs[k].value = ''; return obj; }, {} ); this.props.onSubmit(user); } onChange = ({target:el}) => el.value = el.value.toUpperCase(); render() { return ( <form onSubmit={this.submit}> <div className="form-group"> <input type="text" ref="name" className="form-control" placeholder = "name"/> </div> <div className="form-group"> <input type="text" ref="surname" onChange={this.onChange} className="form-control" placeholder="surname" /> </div> <button type="submit" className="btn btn-primary">add</button> </form> ); } componentDidUpdate(){ const {user} = this.props; this.refs.name.value = user.name; this.refs.surname.value = user.surname; } }

Example 2: use defaultValue

class Content6 extends Component { state = { formCfg: {name:'', cities:[]}, submittedData: {} } dataList = [ {name:'Pippo', cities:['Milan', 'Rome', 'Palermo'], isMale:true, defaultCity:'Rome' }, {name:'Tina', cities:['Torino', 'Genova', 'Pavia'], isMale:false}, {name:'Pino', cities:['Venice', 'Padova', 'Firenze'], isMale:true} ] onClick = (formCfg) => this.setState({formCfg}); onSave = (submittedData) => this.setState({submittedData}); render() { const {formCfg, submittedData} = this.state; return ( <div> <p>click item to fill form:</p> {this.dataList.map( (cfg, i)=>( <div key={i} onClick={(ev)=>this.onClick(cfg)} style={{cursor:'pointer', backgroundColor:'#CCC', margin:2}}> {JSON.stringify(cfg)} </div>))} <div> <p>Submitted data: {JSON.stringify(submittedData)}</p> </div> <div><FormSL {...formCfg} save={this.onSave}/></div> </div> ); } } //stateless component class FormSL extends Component { onSubmit = ({name: {value:name}, city:{value:city},isMale:{checked:isMale}}) => this.props.save({name, city, isMale}); render() { const {name, cities,isMale, defaultCity} = this.props; return ( <form> <input ref='name' defaultValue={name} type="text" className="form-control" /><br/> <select ref='city' name="" id="" className="form-control" size={cities.length+1}> <option value=''>[select city]</option> {cities.map((city)=><option key={city} value={city.toUpperCase()} selected={defaultCity===city}> {city} </option> ) } </select><br/> <input ref="isMale" type="checkbox" defaultChecked={isMale} /> isMale<br/> <button type="button" onClick={() => this.onSubmit(this.refs)} >submit</button> </form> ); } }

3 febbraio 2015

PHP | JS: convert date format to sql timestamp


HTML
<input id="myinput" type="text" value="20/09/1973" /> <!-- format: dd/mm/yyyy -->


Javascript
var mydate = document.getElementById("myinput").value;
var t = mydate.replace(/^(\d{2})\/(\d{2})\/(\d{4})$/, "$3-$2-$1 00:00:00");

//t= "1973-09-20 00:00:00"



PHP
echo preg_replace("/^(\d{2})\/(\d{2})\/(\d{4})$/", "$3-$2-$1 00:00:00", "20/09/1973");

3 dicembre 2014

angular js: set input focus

var app = angular

.module("app")

.factory("mySetFocus", ["$timeout", function($timeout){
return {
focus : {},
set : function(name){
this.focus[name] = !!!this.focus[name];
}
};
}])

.directive('myFocus', ["$timeout", "mySetFocus", function($timeout, mySetFocus) {
return {
restrict: 'A',
link : function(scope, element, attrs) {
scope.setter = mySetFocus;
scope.$watch("setter.focus."+attrs.name, function(v){
if(v==undefined) return;
$timeout(function() {
element[0].focus();
});
});
}
};
}])

.controller("myCtrl", ["$scope", "mySetFocus", function($scope, mySetFocus){
mySetFocus.set("myfield");
}]);

17 maggio 2014

AngularJs: creare una tabella con riodinamenti crescenti e decrescenti via template


Nel template html seguente, viene creata una tabella tramite AngularJs in cui le colonne sono riordinabli con un click sull'header della colonna.
Questo viene fatto tramite una semplice condizione

ng-click = "colOrd= colOrd=='fieldname' && '-fieldame' || 'fieldname'"

che assegna al parametro "colOrd" utilizzato per il filtro "orderBy", il nome del campo preceduto dal segno meno (ordinamento decrescente) se gia è attivo l'ordinamento crescente su questa colonna.


<span>ordinamento attuale: {{colOrd}}</span>
<table border=1 cellpadding=5>
  <tr>
      <td ng-click="colOrd= colOrd=='id' && '-id' || 'id'">Id:</td>
      <td ng-click="colOrd= colOrd=='nome' && '-nome' || 'nome'">Nome:</td>
      <td ng-click="colOrd= colOrd=='cognome' && '-cognome' || 'cognome'">Cognome:</td>
      <td ng-click="colOrd= colOrd=='cell' && '-cell' || 'cell' ">Cellulare:</td>
  </tr>
  <tr ng-repeat="item in mylist | orderBy:colOrd">
      <td>{{item.id}}</td>
      <td>{{item.nome}}</td>
      <td>{{item.cognome}}</td>
      <td>{{item.cell}}</td>
  </tr>
</table>

9 novembre 2013

dojo autocomplete (suggest box)

CLIENT



(html)



<input id="mySuggestBox" />



(javascript dojo v.1.9):



require([
    "dojo/_base/declare",
    "dojox/data/QueryReadStore",
    "dijit/form/ComboBox",
    "dojo/domReady!",

], function(declare, QueryReadStore, ComboBox) {


var AutocompleteStore = declare(QueryReadStore, {

    fetch: function(request){
        request.serverQuery = {q:request.query.name};
        return this.inherited("fetch", arguments);
    },
    wrapItem: function(rawItem, callback){
        this._xhrFetchHandler({
                identifier:'id',
                items: [rawItem],
                label: 'label'
            },
            {},
            function(items){ 
                callback(items[0]); 
            }
        );

    }
});
var store new AutocompleteStore({url:'services/myservice.php'});
var cb = new ComboBox({

        store: store,
        searchAttr: "name",
        labelAttr: "label",
        autoComplete: true,
        onChange: function(){  if(!this.item)  this.set("displayedValue", "");  }
  }, "mySuggestBox");

  //set default value

  store.wrapItem({id:111, name:"lorem", label: "ipsum"}, function(item){ 
       cb.set("item", item);
  });

 });



SERVER


(myservice.php):

<?php
$q = $_GET["q"];
$sql = "SELECT field_id AS id, field_xxx AS name, CONCACT('<b>',field_xxx,'</b')" AS label FROM myTable WHERE field_xxx LIKE "%{$q}% ORDER BY field_xxx LIMIT 10";
//fetch query... :
/*
$fields = array(
    array (id=>1, name=>"lorem", label=> "<span>lorem</span>",
    array (id=>2, name=>"ipsum", label=>"<span>impsum</span>", 
   ....
);
*/
header("Content-Type", "text/json");
echo json_encode(array('numRows'=>count($fields), 'items'=>$fields, 'identity'=>'id'));

11 febbraio 2012

GWT: SplitLayoutPanel, double(or single) click to show/hide panel

La classe seguente consente di chiudere o mostrare i pannelli di uno SplitLayoutPanel tramite un doppio click sugli "splitters" (le barre per ridimensionare i pannelli). 
Il doppio click viene riconosciuto se l'intervallo tra un click e quello successivo non supera un secondo (primo valore evidenziato in giallo espresso in millisecondi). 
L'animazione che mostra o nasconde il pannello dura 500 millisecondi (secondo valore evidenziato in giallo).


public class SplitLayoutPanelExt extends SplitLayoutPanel {


  private class ClickSplitter {
  private Widget widget;
    private Widget splitter;
    private long t = 0;
    public ClickSplitter(Widget w, Widget splitter){
    this.widget = w;
     this.splitter = splitter;
   }
    public void onAttach(){
    DOM.setEventListener(splitter.getElement(), new EventListener() {
    @Override
     public void onBrowserEvent(Event event) {
     if(Event.ONMOUSEDOWN==event.getTypeInt()){
       long t2 = (new Date()).getTime();
         if(t2-t>1000) { t = t2; splitter.onBrowserEvent(event); return; }
         LayoutData layout = (LayoutData)widget.getLayoutData();
         if(layout.size>0){
            layout.oldSize = layout.size;
           layout.size = 0;
           }else {
          layout.size = layout.oldSize;
           layout.oldSize = 0;
           }
          t=0;
           animate(500);
          event.preventDefault();
          }else {
          splitter.onBrowserEvent(event);
          }
        }
      });
    }
  }


private List<ClickSplitter> clickSplitterList = new ArrayList< ClickSplitter >();

public void addWestClosable( Widget widget, double size) {
  super.addWest(widget, size);
  addClickSplitter(widget);
}


  public void addEastClosable( Widget widget, double size){
    super.addEast(widget, size);
    addClickSplitter(widget);
}

public void addNorthClosable(Widget widget, double size){
  super.addNorth(widget, size);
    addClickSplitter(widget);
}

public void addSouthClosable(Widget widget, double size){
  super.addSouth(widget, size);
  addClickSplitter(widget);
}


  private void  addClickSplitter(Widget widget){
    int idx = super.getWidgetIndex(widget);
   if(idx>-1 && idx < getWidgetCount()-1){
      Widget splitter = super.getWidget(idx+1);
     clickSplitterList.add(new ClickSplitter(widget, splitter));
    }
}


  @Override
  protected void onAttach() {
   super.onAttach();
    for(ClickSplitter clickSplitter: clickSplitterList){
      clickSplitter.onAttach();
    }
}
}


Example:

/**
* This is the entry point method.
*/
public void onModuleLoad() {

SplitLayoutPanelExt splitLayoutPanelExt = new SplitLayoutPanelExt();

splitLayoutPanelExt.addWestClosable(new Label("west panel"), 200);
splitLayoutPanelExt.addWestClosable(new Label("west2 panel"), 200);
splitLayoutPanelExt.addEastClosable(new Label("east panel"), 200);
splitLayoutPanelExt.addEastClosable(new Label("east2 panel"), 200);
splitLayoutPanelExt.addNorthClosable(new Label("north panel"), 100);
splitLayoutPanelExt.addSouthClosable(new Label("south panel"), 100);
splitLayoutPanelExt.add(new Label("center panel"));

RootLayoutPanel.get().add(splitLayoutPanelExt);

}

Variante single click
Per mostrare/nascondere i pannelli con un click singolo, sostituire il metodo "onBrowserEvent" con il seguente codice:

    @Override
     public void onBrowserEvent(Event event) {
     if(Event.ONMOUSEDOWN==event.getTypeInt()){
                   t = (new Date()).getTime();
               }else if(Event.ONMOUSEUP==event.getTypeInt()) {
                   long t2 = (new Date()).getTime();
         if(t2-t>200) { t = 0; splitter.onBrowserEvent(event); return; }
         LayoutData layout = (LayoutData)widget.getLayoutData();
         if(layout.size>0){
            layout.oldSize = layout.size;
           layout.size = 0;
           }else {
          layout.size = layout.oldSize;
           layout.oldSize = 0;
           }
          t=0;
           animate(500);
          }
          splitter.onBrowserEvent(event);
        }