Contenu du fichier dvjhUtilities.js le 2016-02-14
        const
  kModel = Symbol( 'ObjModel' ),
  kGetType = function( Obj ){
    return Object.prototype.toString.call( Obj ).match( /\s([a-zA-Z]+)/ )[ 1 ].toLowerCase();
  },
  kSetModel = function( Obj ){
    if ( kGetType( Obj ) === "object" ){
      Obj[ kModel ] = Object.create( Object.prototype );
      Object.getOwnPropertyNames( Obj ).forEach( function( key ){
        if ( key != kModel ) {
          Object.defineProperty( Obj[ kModel ], key, {
            "value" : kGetType( Obj[ key ] ),
            "enumerable" : true
          });
        }
      });
      
      Object.getOwnPropertySymbols( Obj ).forEach( function( key ){
        if ( key != kModel ) {
          Object.defineProperty( Obj[ kModel ], key, {
            "value" : kGetType( Obj[ key ] ),
            "enumerable" : true
          });
        }
      });
    } else {
      throw `Erreur dans kSetModel(), ${Obj} n'est pas un objet`;
    }
  },
  kCreateDOMObject = function( domFragment, keys, boolChildren ){
    let
      Obj = Object.create( Object.prototype ),
      nodes = [],
      treeWalker = {},
      bool = boolChildren || false;
    if ( kGetType( domFragment ).slice( 0, 4 ) === "html" ) {
      treeWalker = document.createTreeWalker(
        domFragment,
        NodeFilter.SHOW_ELEMENT,
        {
          "acceptNode" : function( node ){
            if ( bool ) {
              return NodeFilter.FILTER_ACCEPT;
            } else if ( node.parentNode === domFragment ) {
              return NodeFilter.FILTER_ACCEPT;
            }
            
            return NodeFilter.FILTER_SKIP;
          }
        },
        false
      );
      while( treeWalker.nextNode() ){
        nodes.push( treeWalker.currentNode );
      }
      
      nodes.forEach( function( item, i ){
        let key = "dom_" + (  keys[ i ] ? keys[ i ] : i );
        
        Object.defineProperty( Obj, key, {
          "value" : item,
          "enumerable" : true
        });
      });
    } else {
      alert( `L'objet créé est vide, car le paramètre domFragment ne contient pas un fragment du DOM` );
    }
    return Obj;
  },
  kSortTable = function( table, ordre, bcp47String ){
    let
      bcpStr = bcp47String || "fr-BE",
      ctor = new Intl.Collator( bcpStr, { "numeric" : true } ),
      n = ( ordre === "desc" ) ? ( -1 ) : ( 1 );
      
    table.sort( function( a, b ){
        return n * ctor.compare( a, b );
    });
    
    return table;
  },
  kCloneObject = function( originalObject ){ // impossible si super()
      if ( ( typeof originalObject !== 'object' ) || originalObject === null ){ 
        throw new TypeError( "originalObject parameter must be an object which is not null" ); 
      } 
   
      function deepProto( originalObject ){
        let deepCopy = Object.create( Object.getPrototypeOf( originalObject ) );
        
        for ( let attribute in originalObject ){
          deepCopy[ attribute ] = originalObject[ attribute ];
          
          if ( typeof originalObject[ attribute ] === 'object' && originalObject[ attribute ] !== null ){ 
            deepCopy[ attribute ] = deepProto( originalObject[ attribute ] );
          }
        }
        
        return deepCopy;
      }
      
      return deepProto( originalObject ); 
  },
  kDvjhDate = class extends Date {
    constructor( p ){
      if ( p ) {
        super( p );
      } else {
        super();
      }
      
      this.auteur = 'Daniel Hagnoul';
    }
    toString(){ // format ISO long, dépend de moment.js
      return moment( this ).format( "YYYY-MM-DDTHH:mm:ss.SSSZZ" );
    }
    toInput(){
      return this.toString().split( "T" )[0];
    }
  },
  kLogVars = function( templateStrings, ...substitutions ){
    let result = templateStrings[ 0 ];
    
    for ( let [ i, obj ] of substitutions.entries() ){
      let propKeys = Object.keys( obj );
      
      for ( let [ j, propKey ] of propKeys.entries() ){
        if ( j > 0 ){
          result += ", ";
        }
        
        result += propKey + " = " + obj[ propKey ];
      }
      
      result += templateStrings[ i + 1 ];
    }
    
    return result;
  },
  kIntRandom = function( min, max ){
    // retourne X tel que : min <= X <= max
    return Math.floor( Math.random() * ( max - min + 1 ) + min );
  },
  kProcessStatus = function( r ){ // thenable, pour fetch()
    /*
     * status "0" to handle local files
     * fetching (e.g. Cordova/Phonegap etc.)
     */ 
    if ( r.status === 200 || r.status === 0 ){
      return Promise.resolve( r );
    } else {
      return Promise.reject( new Error( r.statusText ) );
    }
  },
  kDelay = function( ms ){ // thenable
    return new Promise( ( resolve, reject ) => {
      setTimeout( resolve, ms );
    });
  };