Materiali realizzati durante le lezioni del 14/07 e 15/07

Abbiamo utilizzato la proprietà prototype per aggiungere due metodi alla classe predefinita Date. Abbiamo puoi preparato una pagina web per testare le funzionalità aggiunte.

estensioni.js

/*==========================================
        Array.forEach
  ==========================================*/
(function() {
  "use strict";
  if (typeof Array.prototype.forEach !== "function") {
    Array.prototype.forEach = function(func) {
      for (var i = 0; i < this.lenght; i++) {
        func(this[i], i, this);
      }
    }
  }
})()

/*==================================================================================
                                    Date.toDataItaliana
  ----------------------------------------------------------------------------------
  Estesione dell'oggetto Date che trasforma la parte data di un oggetto Date in una
  stringa localizzandola per la lingua italiana.
  Il metodo accetta il parametro formato che consente di personalizzare la stringa.
  
  SEPARATORE
  Per semplificare sono ammessi tre separatori per articolare il formato '/' (barra), 
  '-' (trattino), ' ' (spazio).
  SINTASSI DEGLI ELEMENTI
  'g' o 'gggg': Gorno della settimana per esteso in minuscolo (es.: lunedì)  
  'G' o 'Gggg': Gorno della settimana per esteso capitalizzato (es.: Lunedì)
  'GGG': Gorno della settimana in fomato breve maiuscolo (es.: LUN)
  
  'd': Giorno del mese (es.: 1)
  'dd': Giorno del mese di due cifre (es.: 01)
  
  'm': Mese in formato numerico (es.: 2) 
  'mm': Mese in formato numerico composto da 2 cifre (es.: 02) 
  'mmmm': mese per esteso in minuscolo (es.: febbraio)  
  'Mmmm': Mese per esteso capitalizzato (es.: Febbraio)
  'MMM': Mese in fomato breve maiuscolo (es.: LUN)
  
  'a', 'aaaa': Anno (quattro cifre)
  'aa': Anno (due cifre)
  
  LIMITI
  Nella stringa di formato i token devono essere saparati dallo stesso separatore
  
  ESEMPI
  data.toDataItaliana('dd/mm/aaaa') => 01/01/2017
  data.toDataItaliana('Gggg d Mmmm aaaa') -> Domenica 1 gennaio 2017
  ====================================================================================*/


Date.prototype.toDataItaliana = function(formato) {
  var mesi = ("Gennaio,Febbaraio,Marzo,Aprile,Maggio,Giugno,Luglio,Agosto,Settembre,Ottobre,Novembre,Dicembre").split(',');
  var giorni = ("Domenica,Lunedì,Martedì,Mercoledì,Giovedì,Venerdì,Sbato").split(',');
  var sep = ' ',
    formatArray, self = this;

  formato = formato || 'dd/mm/aaaa';

  if (formato.indexOf('/') > -1) {
    sep = '/';
  } else if (formato.indexOf('-') > -1) {
    sep = '-';
  };

  formatArray = formato.split(sep);

  formatArray.forEach(function(token, index, arr) {
    switch (token) {
      case 'g':
      case 'gggg':
        arr[index] = giorni[self.getDay()].toLowerCase();
        break;
      case 'G':
      case 'Gggg':
        arr[index] = giorni[self.getDay()];
        break;
      case 'GGG':
        arr[index] = giorni[self.getDay()].toUpperCase().substr(0, 3);
        break;
      case 'd':
        arr[index] = self.getDate();
        break;
      case 'dd':
        arr[index] = ('0' + self.getDate()).substr(-2);
        break;
      case 'm':
        arr[index] = self.getMonth() + 1;
        break;
      case 'mm':
        arr[index] = ('0' + (self.getMonth() + 1)).substr(-2);
        break;
      case 'mmmm':
        arr[index] = mesi[self.getMonth()].toLowerCase();
        break;
      case 'Mmmm':
        arr[index] = mesi[self.getMonth()];
        break;
      case 'MMM':
        arr[index] = mesi[self.getMonth()].toUpperCase().substr(0, 3);
        break;
      case 'a':
        arr[index] = self.getFullYear();
        break;
      case 'aaaa':
        arr[index] = ('000' + self.getFullYear()).substr(-4);
        break;
      case 'aa':
        arr[index] = ('0' + self.getFullYear()).substr(-2);
    }
  });
  return formatArray.join(sep);
}

Date.prototype.toTimeFormatted = function(formato) {
  var formatArray, self = this;
  formato = formato || "hh:mm:ss:cc";
  
  formatArray = formato.split(':');
  
  formatArray.forEach(function(token,index, arr){
    switch (token) {
      case 'h':
        arr[index] = self.getHours();
        break;
      case 'hh':
        arr[index] = ('0' + self.getHours()).substr(-2);
        break;
      case 'm':
        arr[index] = self.getMinutes();
        break;
      case 'mm':
        arr[index] = ('0' + self.getMinutes()).substr(-2);
        break;
      case 's':
        arr[index] = self.getSeconds();
        break;
      case 'ss':
        arr[index] = ('0' + self.getSeconds()).substr(-2);
        break;
      case 'c':
        arr[index] = Math.round(self.getMilliseconds() / 10);
        break;
      case 'cc':
        arr[index] = ('0' + Math.round(self.getMilliseconds() / 10)).substr(-2);
        break;
    }
  });
  
  return formatArray.join(':');
}

 

test-estensioni.html

<!doctype html>

<html>

<head>
  <title>Page Title</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="initial-scale=1.0">
  <link href="css/bootstrap.min.css" rel="stylesheet">
  <link href="css/miostile.css" rel="stylesheet">
</head>

<body>
  <div class="jumbotron bg-sfumato">
    <div class="container">
      <h1>Test estensioni</h1>
    </div>
  </div>
  <div class="container">
    <div class="row">
      <div class="form-group col-sm-5">
        <label>Formato Data</label>
        <input type="text" class="form-control input-lg" id="input-formatodata">
      </div>
      <div class="form-group col-sm-4">
        <label>Formato Ora</label>
        <input type="text" class="form-control input-lg" id="input-formatoora">
      </div>
      <div class="form-group col-sm-3">
         <label>&nbsp;</label>
        <button class="btn btn-lg btn-success btn-block" id="btn-test">Test</button>
      </div>
    </div>
    <h1 id="test-out"></h1>
  </div>
  <script src="js/estensioni.js"></script>
  <script>
    document.getElementById('btn-test').addEventListener('click', function () {
      var adesso = new Date();
      var formato_data = document.getElementById('input-formatodata').value;
      var formato_ora = document.getElementById('input-formatoora').value;
      document.getElementById('test-out').innerHTML = adesso.toDataItaliana(formato_data) + " " +
        adesso.toTimeFormatted(formato_ora);
    });
  </script>
</body>

</html>

Abbiamo poi realizzato la Classe personalizzata MyTimer che gestisce le funzionalità di un cronometro elettronico con puslate start-stop, memorizzazione dei tempi parziali e histori dei tempi rilevati.

MyTimer.js

;
(function(win, doc) {
  "use strict";
  // Se requestAnimationFrame non è disponibile viene simulato
  if (!win.requestAnimationFrame) {
    win.requestAnimationFrame = (function() {
      return (
        win.webkitRequestAnimationFrame ||
        win.mozRequestAnimationFrame ||
        win.oRequestAnimationFrame ||
        win.msRequestAnimationFrame ||
        function(
          /* function FrameRequestCallback */
          callback,
          /* DOMElement Element */
          element
        ) {
          win.setTimeout(callback, 1000 / 60);
        }
      );
    })();
  }

  // Costructor
  function MyTimer(selettore) {
    try {
      var el = doc.querySelector(selettore);
      if (typeof Date.prototype.toTimeFormatted !== "function") {
        throw ('L\'oggetto dipende da estensioni.js. Caricalo.');
      }
      if (!el) {
        throw ("Il selettore " + selettore + " non identifica alcun elemento.");
      }
      this.elemento = el;
      this.elemento.innerHTML = "00:00:00:00";
      this.load();
    } catch (err) {
      alert(err);
      throw (err);

    }
  }

  //Valori di partenza delle proprietà
  MyTimer.prototype.startTime = 0;
  MyTimer.prototype.endTime = 0;
  MyTimer.prototype.on = false;
  MyTimer.prototype.history = [];
  MyTimer.prototype.isPartial = false;

  // Rinnova lo schermo ogni sessantesimo di secondo
  MyTimer.prototype.draw = function() {
    var self = this;
    var now = Date.now();
    if (self.startTime == 0)
      self.startTime = Date.now();

    self.elemento.innerHTML = new Date(now - self.startTime - 3600000).toTimeFormatted();
    self.endTime = now;

    if (self.on) {
      win.requestAnimationFrame(function() {
        self.draw();
      })
    } else if (!self.isPartial) {
      self.startTime = 0;
    }
  }

  // Start e stop
  MyTimer.prototype.start = function() {
    this.on = true;
    this.draw();
  }

  MyTimer.prototype.stop = function() {
    this.on = false;
    this.isPartial = false;
    this.aggiornaHistory('tt');
  }

  // Registra un tempo parziale
  MyTimer.prototype.parziale = function() {
    var self = this;
    if (!self.on) return;
    this.isPartial = true;
    this.on = false;
    this.aggiornaHistory('tp');
    setTimeout(function() {
      self.start();
    }, 1200);
  }
  
  // Gestione history
  MyTimer.prototype.aggiornaHistory = function(tipo) {
    var tempo = {
      tipo: tipo,
      data: Date.now(),
      tempo: this.endTime - this.startTime
    };
    this.history.push(tempo);
    this.save();
  }

  // History in formato elemento html (tbody)
  MyTimer.prototype.getHistory = function() {
    var tbody = doc.createElement('tbody');
    for (var i = 0; i < this.history.length; i++) {
      var tr = doc.createElement('tr');
      var date = new Date(this.history[i].data);
      var timeStop = new Date(this.history[i].tempo - 3600000);
      if (this.history[i].tipo == "tp") {
        tr.innerHTML = '<td>' + date.toDataItaliana('dd/mm') + ' ' + date.toTimeFormatted('hh:mm:ss') + '</td><td>' + timeStop.toTimeFormatted() + '</td>';
      } else {
        tr.innerHTML = '<th>' + date.toDataItaliana('dd/mm') + ' ' + date.toTimeFormatted('hh:mm:ss') + '</th><th>' + timeStop.toTimeFormatted() + '</th>';
      }
      tbody.appendChild(tr);
    }
    return tbody;
  }


  // Caricamento e salvataggio history
  MyTimer.prototype.save = function() {
    if (win.localStorage) {
      localStorage.setItem("MyTimerHistory", JSON.stringify(this.history));
    }
  }

  MyTimer.prototype.load = function() {
    if (win.localStorage) {
      var h = localStorage.getItem('MyTimerHistory');
      if (h) {
        this.history = JSON.parse(h);
      }
    }
  }

  MyTimer.historyReset = function() {
    this.history = [];
    this.save();
  }


  win.MyTimer = MyTimer;

})(window, document);

Pagina html che utilizza MyTimer per visualizzare un cronometro elettronico. Visualizza la pagina.

newtimer.html

<!doctype html>

<html>

<head>
  <title>Page Title</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="initial-scale=1.0, width=device-width">
  <link href="css/bootstrap.min.css" rel="stylesheet">
  <link href="css/miostile.css" rel="stylesheet">
</head>

<body>
  <div class="jumbotron fullscreen bg-sfumato">
    <header class="page-header">
      <h1 class="text-center">Timer</h1>
    </header>
    <div id="timer-canvas" class="text-center h1"></div>
    <div class="text-center container">
      <div class="row">
        <div class="col-sm-2 col-sm-offset-4 col-xs-4 col-xs-offset-2 text-center">
          <button id="btn-start" class="interruttore"></button>
          <br>Start/stop
        </div>
        <div class="col-sm-2 col-xs-4 text-center">
          <button id="btn-parziale" class="interruttore pulsante"></button>
          <br>Parziale
        </div>
      </div>
      <a id="btn-history" href="#history-modal" data-toggle="modal" class="btn btn-lg btn-danger btn-history">History</a>
    </div>
  </div>
  <!-- Modal che contiene la history -->
  <div class="modal fade" id="history-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
          <h4 class="modal-title text-center" id="myModalLabel">Tempi rilevati</h4>
        </div>
        <div class="modal-body">
          <table class="table table-striped" >
            <thead>
              <th>Ora</th>
              <th>Tempo</th>
            </thead>
            <tbody id="tbody-history"></tbody>
          </table>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal">Chiudi</button>
          <button id="btn-resethistory" type="button" class="btn btn-primary">Reset</button>
        </div>
      </div>
    </div>
  </div>
  
  <script src="js/estensioni.js"></script>
  <script src="js/interruttore.js"></script>
  <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
  <script src="js/bootstrap.min.js"></script>
  <script src="js/MyTimer.js"></script>
  <script>
    var timer = new MyTimer('#timer-canvas');
    document.getElementById('btn-start').addEventListener('click', function() {
      if (this.classList.contains('on'))
        timer.start();
      else
        timer.stop();
    });
    document.getElementById('btn-parziale').addEventListener('click', function() {
      timer.parziale();
    })
    
    document.getElementById('btn-history').addEventListener('click', function() {
      var h = timer.getHistory();
      document.getElementById('tbody-history').innerHTML = h.innerHTML;
    })
  </script>
</body>

</html>

Infini il foglio di stile comune a tutte le pagine web.

miostile.css

.bg-darkblue {
  background-color: darkblue;
  color: white;
}

.bg-sfumato {
  background-image: -webkit-gradient(linear,left top, left bottom,from(#000033),to(#800));
  background-image: -webkit-linear-gradient(#000033,#800);
  background-image: linear-gradient(#000033,#800);
  color: white;
}

.fullscreen {
  min-height: 100vh;
  margin-bottom: 0;
}

.jumbotron .page-header {
  margin-top: 0;
  padding-bottom: 50px;
}

.off.dissolvenza {
  opacity: 0;
}

.dissolvenza {
  opacity: 1;
  -webkit-transition: all 0.7s;
  transition: all 0.7s;
}

.off.rotazione {
  opacity: 0;
  -webkit-transform: rotate(-180deg);
  -ms-transform: rotate(-180deg);
  transform: rotate(-180deg);
}
.rotazione {
  opacity: 1;
  -webkit-transform: rotate(0);
  -ms-transform: rotate(0);
  transform: rotate(0);
  -webkit-transition: all 0.5s;
  transition: all 0.5s;
}

.off.zoom {
  -webkit-transform: scale(0.1, 0.1);
  -ms-transform: scale(0.1, 0.1);
  transform: scale(0.1, 0.1);
  opacity: 0;
}
.zoom {
  -webkit-transform: scale(1, 1);
  -ms-transform: scale(1, 1);
  transform: scale(1, 1);
  opacity: 1;
  -webkit-transition: all 1s;
  transition: all 1s;
}

.off.slide {
  -webkit-transform: translateY(-20%);
  -ms-transform: translateY(-20%);
  transform: translateY(-20%);
  opacity: 0;
}
.slide {
  -webkit-transform: translateY(0);
  -ms-transform: translateY(0);
  transform: translateY(0);
  opacity: 1;
  -webkit-transition: all .7s;
  transition: all .7s;
}

/* Interruttore */

.interruttore {
  border:0;
  background-image: url(/img/on-off.png);
  background-position: top left;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  -webkit-box-shadow: #000 0 0 10px;
  box-shadow: #000 0 0 10px;
  margin: 10px;
}

.interruttore:focus {
  outline: 0;
}

.interruttore.on {
  background-position: top right;
  -webkit-box-shadow: #400 0 0 10px;
  box-shadow: #400 0 0 10px;
}

.btn-history {
  margin-top: 40px;
  border-radius: 20px;
}

 

Torna all'inizio