esm.run croner demo

by hexag0n

HTML

<p>
  Pattern: <input id="pattern" value="* * * * * *"/>
</p>
<p>
  <button id="start">
  (re)start
  </button>
  <button id="pause">
  pause
  </button>
  <button id="resume">
  resume
  </button>
  <br>
  <div id="error" class="hide">
    <strong>Error:</strong>
    <div id="message"></div>
  </div>
</p>
<p>
  <strong>Next 5 runs:</strong>
  <div>
    <ul id="next">
    </ul>
  </div>
</p>
<p>
  <strong>Current run:</strong>
  <div><ul><li id="current"></li></ul>
</p>
<p>
  <strong>Previous run:</strong>
  <div><ul><li id="previous"></li></ul>
</p>
<p>
  <strong>ms to next:</strong>
  <div><ul><li id="mstonext"></li></ul>
</p>
<p><i>
If you change the config in the js-window, you have to press "Run" to apply the new config.</i>
</p>

CSS

* {
  font-family: monospace;
}
.show {
  display: block;
}
.hide {
  display: none;
}
#error {
  color: #FF5544;
}
ul {
  padding: 0;
  list-style-type: none;
}

JavaScript

// See https://www.npmjs.com/package/croner documentation.
import { Cron } from 'https://esm.run/croner@10.0.0-dev.3';

let scheduler, getPattern, updateInterface;

let config = {
	// maxRuns: 1,
  // timezone: 'Europe/Stockholm',
  // utcOffset: 0
  // paused: false,
  // startAt: "2021-12-01T00:00:00",
	// stopAt: "2021-12-02T00:00:00",
  // interval: 90,
  // domAndDow: false,
  // protect: false,
  // catch: false,
  // sloppyRanges: false
};

// - Fun stuff ----------------------------------
let restart = () => {

	if (scheduler) scheduler.stop();
  
  // This is where magic happen
  scheduler = new Cron(
  	getPattern(),
    config,
    () => {
      console.log('This will run on selected interval');

      // Update interface on each run
      updateInterface();
    }
  );
  
  // Update interface on restart
 	updateInterface();
};

// - Boring stuff ------------------------------
const 
	pause = () => scheduler && scheduler.pause(),
	resume = () => scheduler && scheduler.resume();
  
getPattern = () => {
	return document.getElementById('pattern').value;
};

updateInterface = () => {
	if (scheduler) {
		let next6 = scheduler.nextRuns(6),
    		nextHtml = '';
    next6.forEach(d=>{
    	nextHtml += '<li>'+d.toLocaleString()+'</li>';
    });
    if (next6.length === 0) {
    	nextHtml += '<li>'+d.toLocaleString()+'</li>';
    }
    document.getElementById('next').innerHTML = nextHtml;
		document.getElementById('previous').innerHTML = (scheduler.previousRun() ? scheduler.previousRun().toLocaleString() : '-');
    document.getElementById('current').innerHTML = (scheduler.currentRun() ? scheduler.currentRun().toLocaleString() : '-');
  }
};

// Sub second scheduling is best done with setInterval
setInterval(() => {
	let state = scheduler.options.paused ? '?' : scheduler.msToNext();
	document.getElementById('mstonext').innerHTML = state;
 ...