mirror of
https://github.com/0x1d/esp8266-laser.git
synced 2025-12-14 18:15:22 +01:00
252 lines
8.3 KiB
JavaScript
252 lines
8.3 KiB
JavaScript
/**
|
|
* Poor Man's JQuery
|
|
* Lightweight DOM manipulation utility
|
|
*/
|
|
var $ = function(selector){
|
|
|
|
var that = this;
|
|
var element = selector.nodeType === 1 ? selector : {};
|
|
|
|
// utility functions
|
|
this.util = {
|
|
// build a fragment from a given html string
|
|
buildFragment: function(html){
|
|
// set the html to a temporary element
|
|
var nodeHolder = document.createElement('div');
|
|
nodeHolder.innerHTML = html;
|
|
// create a document fragment and append all input nodes
|
|
var fragment = document.createDocumentFragment();
|
|
while(nodeHolder.firstChild){
|
|
fragment.appendChild(nodeHolder.firstChild);
|
|
}
|
|
return fragment;
|
|
}
|
|
};
|
|
// check if the input selector is already an element or a css selector
|
|
if(selector.nodeType === 1){ // is element
|
|
if(selector.is$ ? selector.is$() : false){ // check if the element is already extended
|
|
return selector;
|
|
}
|
|
element = selector; // set the element to be extended
|
|
} else { // the element is in fact a css selector
|
|
element = document.querySelector(selector); // search for the element
|
|
}
|
|
|
|
// overload the innerHTML attribute
|
|
element.html = function(val){
|
|
this.innerHTML = val;
|
|
return this;
|
|
};
|
|
|
|
// overload the value attribute
|
|
element.val = function(val){
|
|
this.value = val;
|
|
return this;
|
|
};
|
|
|
|
// append the given string as child fragment
|
|
element.append = function(html){
|
|
var fragment = that.util.buildFragment(html);
|
|
this.appendChild(fragment);
|
|
return this;
|
|
};
|
|
|
|
// prepend the given string as child fragment
|
|
element.prepend = function(html){
|
|
var fragment = that.util.buildFragment(html);
|
|
this.insertBefore(fragment,this.firstChild);
|
|
return this;
|
|
};
|
|
|
|
// search for an element inside of an element
|
|
element.find = function(what){
|
|
var found = $(what);
|
|
if(found){
|
|
return $(found);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// get parent of the current element
|
|
element.parent = function(){
|
|
if(this.parentElement){
|
|
return $(this.parentElement);
|
|
}
|
|
}
|
|
|
|
// indicates that this element is a $ function
|
|
element.is$ = function(){
|
|
return true;
|
|
}
|
|
|
|
element.on = function(event, func, useCapture) {
|
|
this.addEventListener(event, func, useCapture);
|
|
return this;
|
|
}
|
|
|
|
return element;
|
|
};var Sui = {
|
|
ready: (callback) => {
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
callback();
|
|
}, false);
|
|
},
|
|
select: (selector) => {
|
|
return document.querySelectorAll(selector);
|
|
},
|
|
link: (node) => {
|
|
return (actuator) => {
|
|
let update = actuator.handler || function(actuator) {
|
|
Sui.http.ajax({
|
|
method: actuator.method,
|
|
endpoint: actuator.api,
|
|
data: actuator.data ?
|
|
actuator.data.call(this) : [this.value],
|
|
cache: false
|
|
}, actuator.onResponse || null);
|
|
};
|
|
Sui.select(actuator.selector).forEach( (domEl) =>{
|
|
let handle = function(event) {
|
|
update.call(this, actuator);
|
|
}
|
|
domEl.addEventListener(actuator.event, handle)
|
|
});
|
|
};
|
|
},
|
|
util: {
|
|
|
|
/**
|
|
* serialize a flat json object
|
|
*/
|
|
serialize: (obj) => {
|
|
var str = [];
|
|
for(var p in obj){
|
|
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
|
}
|
|
return str.join("&");
|
|
}
|
|
},
|
|
http: {
|
|
|
|
/**
|
|
* ajax request
|
|
* {
|
|
* method: <'GET', 'POST', whatever >,
|
|
* endpoint: <URL to the service endpoint>,
|
|
* async: <true or false>, (default true)
|
|
* data: <json object with data to transmit>,
|
|
* cache: <true or false> (default false)
|
|
* }
|
|
*/
|
|
ajax: (config, callback) => {
|
|
var cache = config.cache || false;
|
|
var data = config.data || {};
|
|
if(!cache) {
|
|
data['_'] = new Date().getTime();
|
|
}
|
|
var serializedData = data; //Sui.util.serialize(data);
|
|
var endPointUrl = (config.method === 'GET' || config.method === 'DELETE') && data ? config.endpoint+'?'+serializedData : config.endpoint;
|
|
var postData = config.method === 'POST' || config.method === 'PUT' ? serializedData : null;
|
|
|
|
var request = new XMLHttpRequest();
|
|
request.open(config.method, endPointUrl, config.async || true);
|
|
request.onreadystatechange = function () {
|
|
// TODO handle response properly
|
|
callback ? callback(request.responseText, request.status) : undefined;
|
|
};
|
|
request.send(postData);
|
|
}
|
|
}
|
|
};
|
|
let click = element => element.click();
|
|
let check = element => element.setAttribute('checked','checked');
|
|
let uncheck = element => element.removeAttribute('checked');
|
|
|
|
let switchElementState = element => {
|
|
let state = element.getAttribute('data-state') == 'false';
|
|
element.setAttribute('data-state', state);
|
|
return state;
|
|
};
|
|
let bindData = (element, attribute, data) => {
|
|
element.setAttribute('data-' + attribute, data);
|
|
};
|
|
Sui.ready(() => {
|
|
let debugResponse = (data) => {
|
|
document.querySelector('#response').innerHTML = data;
|
|
};
|
|
|
|
// init collapsible containers
|
|
Sui.select('.collapsible').forEach((container) => {
|
|
container.querySelector('.heading').addEventListener('click', (item) => {
|
|
container.classList.toggle('open');
|
|
});
|
|
});
|
|
|
|
// init actuators
|
|
[{
|
|
api: '/wificonfig',
|
|
method: 'POST',
|
|
selector: '.switch.ap-mode .slider',
|
|
event: 'click',
|
|
onResponse: debugResponse,
|
|
handler: function() {
|
|
let nextState = switchElementState(this);
|
|
/*let bindingName = this.getAttribute('data-bind');
|
|
Sui.select('.switch.ap-mode [name="'+ bindingName+'"]')
|
|
.forEach(check);*/
|
|
console.log(nextState);
|
|
}
|
|
},{
|
|
api: '/presetMode',
|
|
method: 'POST',
|
|
selector: '.switch.preset-mode .slider',
|
|
event: 'click',
|
|
onResponse: debugResponse,
|
|
data: function() {
|
|
let state = switchElementState(this);
|
|
console.log(state);
|
|
return Sui.util.serialize({
|
|
mode: state ? 1 : 0
|
|
});
|
|
}
|
|
},{
|
|
api: '/spirograph',
|
|
method: 'POST',
|
|
selector: '.slider.motor',
|
|
event: 'change',
|
|
onResponse: debugResponse,
|
|
data: function() {
|
|
let payload = {},
|
|
motorValue = this.value,
|
|
motorNr = this.getAttribute('data-motor-nr'),
|
|
actuatorId = 'motor' + motorNr;
|
|
// update actuator value label
|
|
Sui.select('[data-actuator-id=\"'+ actuatorId + '\"]')
|
|
.forEach( element => element.innerHTML = motorValue);
|
|
// add actuator to payload
|
|
payload[actuatorId] = motorValue;
|
|
return Sui.util.serialize(payload);
|
|
}
|
|
}, {
|
|
api: '/spirograph',
|
|
method: 'POST',
|
|
selector: '.slider.laser',
|
|
event: 'change',
|
|
onResponse: debugResponse,
|
|
data: function() {
|
|
// update actuator value label
|
|
Sui.select('[data-actuator-id="laser"]')
|
|
.forEach( element => element.innerHTML = this.value );
|
|
// return payload
|
|
return Sui.util.serialize({
|
|
laser: this.value
|
|
});
|
|
}
|
|
}].forEach(Sui.link({
|
|
api: {
|
|
MOTOR: '/spirograph', // {motorNr}/{value}
|
|
LASER: '/spirograph', // {value}
|
|
PRESET: '/presetMode'
|
|
}
|
|
}));
|
|
}); |