/** * 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: , * async: , (default true) * data: , * cache: (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' } })); });