UNPKG

node-red-contrib-polymer

Version:
630 lines (514 loc) 20.4 kB
var isInited; var isFirstUpdate = true; var currentSiteName; var currentPageName; var sites; var pages; var groups; var elements; var sitePaths = {}; var pagePaths = {}; var tree = {}; var toasts = []; var socket; console.log(store.getAll()); if (!store.get('clientId')) { store.set('clientId', ('00000000' + (Math.ceil(Math.random() * Math.pow(2, 32))).toString(16)).slice(-8)) store.set('created', new Date()); } store.set('connectionDate', new Date()); if (!store.get('connectionCount')) { store.set('connectionCount', 1); } else { store.set('connectionCount', store.get('connectionCount') + 1); } window.addEventListener('WebComponentsReady', function (e) { function hashChange() { var hash = location.hash.substr(2); //console.log('hashChange', hash); var path = hash.split('/'); navigate(path[0], path[1]); // site, page } window.addEventListener('hashchange', hashChange); socket = io({path: location.pathname + 'socket.io'}); socket.on('connect', function () { //console.log(socket); document.getElementById('disconnect').removeAttribute('opened'); }); socket.on('disconnect', function () { document.getElementById('disconnect').setAttribute('opened', ''); }); socket.on('update', function (data) { if (!isFirstUpdate) { location.reload(); return; } else { isFirstUpdate = false; } sites = data.sites; pages = data.pages; groups = data.groups; elements = data.elements; Object.keys(sites).forEach(function (key) { var site = sites[key]; sitePaths[site.name] = site.id; tree[site.id] = {}; }); Object.keys(pages).forEach(function (key) { var page = pages[key]; if (!page.parent) { console.log('Error: page', key, 'has no parent. skipping', page); return; } var site = sites[page.parent]; pagePaths[site.name + '/' + page.name] = page.id; if (!tree[site.id]) tree[page.parent] = {}; if (!tree[site.id][page.id]) tree[site.id][page.id] = {}; }); Object.keys(groups).forEach(function (key) { var group = groups[key]; if (!group.parent) { console.log('Error: group', key, 'has no parent. skipping', group); return; } var page = pages[group.parent]; var site = sites[page.parent]; if (!tree[site.id][page.id]) tree[site.id][page.id] = {}; tree[site.id][page.id][group.id] = []; }); Object.keys(elements).forEach(function (key) { var element = elements[key]; if (element.element !== 'paper-toast') { if (!element.parent) { console.log('Error: element', key, 'has no parent. skipping', element); return; } var group = groups[element.parent]; var page = pages[group.parent]; var site = sites[page.parent]; if (!tree[site.id][page.id][group.id]) tree[site.id][page.id][group.id] = []; tree[site.id][page.id][group.id].push(element.id); } else { toasts.push(element); } }); if (!isInited) { var hash = location.hash.substr(2); //console.log('hash', hash); var path = hash.split('/'); navigate(path[0], path[1]); // site, page } }); socket.on('input', updateElem); }); function navigate(siteName, pageName) { if (!sitePaths[siteName]) { siteName = Object.keys(sitePaths)[0]; if (!sitePaths[siteName] || !sites[sitePaths[siteName]]) { console.error(siteName); return; } var pageId = sites[sitePaths[siteName]].pageOrder[0] || Object.keys(tree[sitePaths[siteName]])[0]; pageName = pages[pageId].name; window.location.hash = '#/' + siteName + '/' + pageName; return; } if (!pagePaths[siteName + '/' + pageName]) { var pageId = sites[sitePaths[siteName]].pageOrder[0] || Object.keys(tree[sitePaths[siteName]])[0]; pageName = pages[pageId].name; window.location.hash = '#/' + siteName + '/' + pageName; return; } if (currentSiteName === siteName && currentPageName === pageName) { // No Change return; } else if (isInited && currentSiteName !== siteName) { // Site Change location.reload(); } else if (isInited && currentPageName !== pageName) { // Page Change pageChange(pageName); } else if (!isInited) { initSite(siteName, pageName); } } function initSite(siteName, pageName) { isInited = true; currentSiteName = siteName; currentPageName = pageName; var siteId = sitePaths[siteName]; var pageId = pagePaths[siteName + '/' + pageName]; //var container = document.createElement('node-red-polymer'); //document.querySelector('body').appendChild(container); document.querySelector('title').innerHTML = sites[siteId].title; if (sites[siteId].theme) { document.querySelector('body').className = 'theme-' + sites[siteId].theme; Polymer.updateStyles(); } if (sites[siteId].css) { var style = document.createElement('style'); style.innerText = sites[siteId].css; document.querySelector('head').append(style); } document.querySelector('div.loader').style.display = 'none'; var container = document.querySelector('node-red-polymer'); container.setAttribute('title', pages[pageId].title); if (sites[siteId].forceNarrow) { container.setAttribute('force-narrow', ''); } if (sites[siteId].fixed) { container.setAttribute('fixed', ''); } if (sites[siteId].reveals) { container.setAttribute('reveals', ''); } var menu = []; sites[siteId].pageOrder.forEach(function (pageId) { if (tree[siteId][pageId]) { Polymer.dom(container).appendChild(createPage(pageId, siteId)); var icon = 'menu-icon'; if (pages[pageId].icon) icon = icon + ' fa fa-' + pages[pageId].icon; menu.push({title: pages[pageId].title, icon: icon, path: siteName + '/' + pages[pageId].name}); } }); Object.keys(tree[siteId]).forEach(function (pageId) { if (sites[siteId].pageOrder.indexOf(pageId) === -1) { Polymer.dom(container).appendChild(createPage(pageId, siteId)); var icon = 'menu-icon'; if (pages[pageId].icon) icon = icon + ' fa fa-' + pages[pageId].icon; menu.push({title: pages[pageId].title, icon: icon, path: siteName + '/' + pages[pageId].name}); } }); container.menu = menu; setTimeout(createToasts, 0); if (sites[siteId].saveScroll) saveScroll(); siteOutput(siteId, pageId); } function saveScroll() { var scrollTimer; window.addEventListener('scroll', function () { clearTimeout(scrollTimer); scrollTimer = setTimeout(function () { var scrollObj = {}; scrollObj[currentSiteName + '/' + currentPageName] = window.scrollY; store.set('scrollY', scrollObj); }, 250); }); var scrollY = store.get('scrollY'); if (scrollY && scrollY[currentSiteName + '/' + currentPageName]) { setTimeout(function () { window.scrollTo(0, scrollY[currentSiteName + '/' + currentPageName]); }, 300); } } function siteOutput(siteId, pageId) { var msg = {id: siteId, payload: { clientId: store.get('clientId'), pageId: pageId }}; if (socket) socket.emit('output', msg); } function createToasts() { toasts.forEach(function (toast) { if (pages[toast.parent]) { var page = document.getElementById(elementId(toast.parent)); if (page) { createElement(toast, page); } } else if ((sites[toast.parent] && (currentSiteName === sites[toast.parent].name)) || (!toast.parent)) { createElement(toast, document.querySelector('body')); } }); } function pageChange(pageName) { currentPageName = pageName; var siteId = sitePaths[currentSiteName]; var pageId = pagePaths[currentSiteName + '/' + pageName]; var container = document.querySelector('node-red-polymer'); container.setAttribute('title', pages[pageId].title); document.querySelector('node-red-polymer').select(); siteOutput(siteId, pageId); } function createPage(pageId, siteId) { var page = pages[pageId]; var pageElem = document.createElement('div'); pageElem.setAttribute('id', elementId(pageId)); if (!page.groupOrder) page.groupOrder = []; page.groupOrder.forEach(function (groupId) { if (tree[siteId][pageId][groupId]) { var groupElem = createGroup(groupId, pageId, siteId); createElements(groupElem, groupId, pageId, siteId); pageElem.appendChild(groupElem); } }); Object.keys(tree[siteId][pageId]).forEach(function (groupId) { if (page.groupOrder.indexOf(groupId) === -1) { var groupElem = createGroup(groupId, pageId, siteId); createElements(groupElem, groupId, pageId, siteId); pageElem.appendChild(groupElem); } }); pageElem.className = 'page'; return pageElem; } function createGroup(groupId, pageId, siteId) { var group = groups[groupId]; switch (group.type) { case 'polymer_nav_group': var groupElem = document.createElement('paper-card'); groupElem.setAttribute('id', elementId(groupId)); var contentElem = document.createElement('div'); contentElem.className = 'card-content'; if (group.title) groupElem.setAttribute('heading', group.title); groupElem.appendChild(contentElem); break; case 'polymer_nav_group_collapsible': var groupElem = document.createElement('node-red-collapse'); groupElem.setAttribute('id', elementId(groupId)); if (group.title) groupElem.setAttribute('heading', group.title); if (group.saveOpened && store.get(groupId) && store.get(groupId).opened) groupElem.setAttribute('opened', true); if (group.saveOpened) { groupElem.addEventListener('change', function (event) { var groupStore = store.get(groupId) || {} groupStore.opened = event.detail; store.set(groupId, groupStore); if (socket) socket.emit('output', { id: groupId, payload: event.detail }); }); } break; } if (group.lastMsg) { setTimeout(function () { updateElem(group.lastMsg); }, 0); } return groupElem; } function createElements(groupElem, groupId, pageId, siteId) { var container = groupElem.querySelector('div.card-content'); var elemOrder = groups[groupId].elementOrder; var cmdQueue = []; if (!elemOrder) elemOrder = []; elemOrder.forEach(function (elemId) { if (tree[siteId][pageId][groupId].indexOf(elemId) !== -1) { cmdQueue.push(function (callback) { createElemWrap(elements[elemId], container, callback); }); } }); tree[siteId][pageId][groupId].forEach(function (elemId) { if (elemOrder.indexOf(elemId) === -1) { cmdQueue.push(function (callback) { createElemWrap(elements[elemId], container, callback); }); } }); async.series(cmdQueue); function createElemWrap(elem, container, cb) { if (elem.element === 'node-red-template') { /* todo try again to get this working and remove this workaround! var tplElement = document.createElement('dom-module'); tplElement.setAttribute('id', 'node-red-template-' + elemId); var tplTemplate = document.createElement('template'); tplTemplate.setAttribute('is', 'dom-bind'); tplTemplate.innerHTML = elem.html; tplElement.appendChild(tplTemplate); var tplScript = document.createElement('script'); var tplScriptText = document.createTextNode('Polymer({is:"node-red-template-' + elemId + '"})'); tplScript.appendChild(tplScriptText); tplElement.appendChild(tplScript); document.body.appendChild(tplElement); elem.element = 'node-red-template-' + elemId; createElement(); */ Polymer.Base.importHref(['elements/custom_template.html?node=' + elem.id], function () { elem.element = 'node-red-template-' + elem.id; createElement(elem, container); if (typeof cb === 'function') cb(); }); } else { createElement(elem, container); if (typeof cb === 'function') cb(); } } } function createElement(elem, container) { var elemId = elem.id; var customElement = document.createElement(elem.element); customElement.classList.add('node-red-widget'); customElement.setAttribute('id', elementId(elemId)); if (elem.width) customElement.style.width = elem.width; if (elem.height) customElement.style.height = elem.height; if (elem.class) { elem.class.split(' ').forEach(function (c) { customElement.classList.add(c); }); } if (elem.html && elem.element.indexOf('node-red-template-') === -1) { var newContent = document.createTextNode(elem.html); customElement.appendChild(newContent); } if (elem.attrs && elem.attrs.forEach) { elem.attrs.forEach(function (attr) { var value = elem[attr]; if (attr === 'attrType') attr = 'type'; if (value === null || (typeof value === 'undefined')) { customElement.removeAttribute(attr); } else if (typeof value === 'object') { value = JSON.stringify(value); customElement.setAttribute(attr, value); } else { customElement.setAttribute(attr, value); } }); } if (elem.event) { var tmp = elem.event.split(':'); customElement.addEventListener(tmp[0], function (data) { var payload; if (typeof tmp[1] !== 'undefined') { payload = customElement[tmp[1]]; if (typeof payload === 'undefined') return; } else { switch (elem.payloadType) { case 'bool': if (typeof elem.payload !== 'boolean') payload = elem.payload === 'true'; break; case 'num': if (typeof elem.payload === 'string') payload = parseFloat(elem.payload); break; case 'json': if (typeof elem.payload === 'string') payload = JSON.parse(elem.payload); break; default: payload = elem.payload; } } if (payload === true && (typeof elem.payloadTrue !== 'undefined')) { switch (elem.payloadTrueType) { case 'bool': payload = elem.payloadTrue === 'true'; break; case 'num': payload = parseFloat(elem.payloadTrue); break; default: payload = elem.payloadTrue; } } else if (payload === false && (typeof elem.payloadFalse !== 'undefined')) { switch (elem.payloadFalseType) { case 'bool': payload = elem.payloadFalse === 'true'; break; case 'num': payload = parseFloat(elem.payloadFalse); break; default: payload = elem.payloadFalse; } } var msg = {id: elemId, payload: payload}; if (elem.topic) msg.topic = elem.topic; socket.emit('output', msg); }); } container.appendChild(customElement); if (elem.lastMsg) { setTimeout(function () { updateElem(elem.lastMsg); }, 0); } } function elementId(id) { return 'node-' + id.replace('.', '_'); } function updateElem(msg) { console.log('updateElem', msg) var elem = document.getElementById(elementId(msg.id)); if (!elem) return; var replacement; var replaced; var subject; if (elements[msg.id]) subject = elements[msg.id]; if (groups[msg.id]) subject = groups[msg.id]; if (pages[msg.id]) subject = pages[msg.id]; if (sites[msg.id]) subject = sites[msg.id]; console.log('subject', subject); if (typeof subject.payloadFalse !== 'undefined') { switch (subject.payloadFalseType) { case 'bool': replacement = subject.payloadFalse === 'true'; break; case 'num': replacement = parseFloat(subject.payloadFalse); break; default: replacement = subject.payloadFalse; } if (msg.payload === replacement) { msg.payload = false; replaced = true; } if (!replaced && typeof subject.payloadTrue !== 'undefined') { switch (subject.payloadTrueType) { case 'bool': replacement = subject.payloadTrue === 'true'; break; case 'num': replacement = parseFloat(subject.payloadTrue); break; default: replacement = subject.payloadTrue; } if (msg.payload === replacement) msg.payload = true; } } if (subject.valueFalseNull && msg.payload === false) msg.payload = null; if (msg.payload === null || (typeof msg.payload === 'undefined')) { elem.removeAttribute(subject.valueAttribute); } else if (typeof msg.payload !== 'object') { elem.setAttribute(subject.valueAttribute, msg.payload); } else { Object.keys(msg.payload).forEach(function (attr) { var val = msg.payload[attr]; if (attr === 'style' && typeof val === 'object') { // TODO some elements need workaround: // when they are rendered with display:none on start they render wrong size when // display:none is removed later Object.keys(val).forEach(function (style) { elem.style[style] = val[style]; }); } else if (attr === 'addClass') { if (typeof val === 'string') { val = val.split(' '); } if (typeof val === 'object' && val.forEach) { val.forEach(function (c) { elem.classList.add(c); }); } } else if (attr === 'removeClass') { if (typeof val === 'string') { val = val.split(' '); } if (typeof val === 'object' && val.forEach) { val.forEach(function (c) { elem.classList.remove(c); }); } } else { if (attr === 'attrType') { attr = 'type'; } if (val !== null) { elem.setAttribute(attr, val); } else { elem.removeAttribute(attr); } } }); } }