JSFiddle - React, Tailwind, and code Playground
by levchenko_d
HTML
<label for="travel">Time Travel</label>
<input id="travel" type="range" min="0" max="1" step="1" list="ticks" style="position: absolute; opacity: 0;">
<datalist id="ticks">
<option value="0" label="0"/>
<option value="1" label="0"/>
</datalist>
<div id="travel-preview"></div>
<br>
<button id="back"><</button>
<button id="log">log</button>
<button id="bulk">bulk</button>
<button id="forward">></button>
<canvas id="can" width="400" height="400" style="position:absolute;top:130px;left:10px;border:2px solid;"></canvas>
CSS
#travel-preview {
padding: 5px;
white-space: nowrap;
text-overflow: ellipsis;
overflow-x: scroll;
}
#travel-preview > *:not(.active) {
opacity: 0.5;
box-shadow: 0 0 0 1px #f2f3f9;
}
#travel-preview > *.active {
box-shadow: 0 0 0 2px #00b0ef;
}
#travel-preview > *:hover {
opacity: 1;
}
JavaScript
var Store = function(options){
var t=this;
t.storage = {};
t.handlers = {};
t.storageHistory = [];
t.version = 0;
t.callbacks = {
onchange: options.onchange
};
t.defaults = {
storageItem: {
key: undefined,
value: undefined,
handler: undefined
}
};
return t;
};
Store.prototype.handleStartData = function(optionsList){
var t=this,
list = optionsList || [],
isInit = true;
list.map(function(options, index){
var isInitDone = index === list.length - 1;
t.set(options, isInit, isInitDone);
});
};
Store.prototype._clone = function(obj){
return JSON.parse(JSON.stringify(obj));
};
Store.prototype.keyExist = function(options){
var t=this;
return t.storage[options.key];
};
Store.prototype.prettyStorage = function(){
var t=this,
pretty = {};
for(var key in t.storage){
if (t.storage.hasOwnProperty(key)) {
pretty[key] = t.storage[key].value;
}
}
return t._clone(pretty);
};
Store.prototype.updateHistory = function(options, isInit, isInitDone){
var t=this;
if(!isInit){
t.storageHistory = t.storageHistory.slice(0, t.version+1);
t.version += 1;
}
if(isInitDone){
t.storageHistory = [];
t.version = 0;
}
t.storageHistory.push(t._clone(t.storage));
return t;
};
Store.prototype.fillKey = function(options){
var t=this;
['key', 'value'].map(function(slug){
t.storage[options.key][slug] = options[slug];
});
if(options.handler && typeof options.handler === 'function'){
t.handlers[options.key] = options.handler;
}
return t;
};
Store.prototype.handleKey = function(options){
var t=this;
if(!t.keyExist(options)){
t.storage[options.key] = t._clone(t.defaults.storageItem);
}
t.fillKey(options);
return t;
};
Store.prototype.set = function(options, isInit, isInitDone){
var t=this;
t.handleKey(options);
t.updateHistory(options, isInit, isInitDone);
t.onchange(options);
...