-
-
Notifications
You must be signed in to change notification settings - Fork 86
Example Umbrella JS and Picnic CSS
NOTE: Needs updating for uibuilder v2. If you use UmbrellaJS with uibuilder, please consider updating this article. Thanks.
Thanks to Dave CJ for this one. Using Umbrella.JS for the reactive front-end code and the lightweight CSS framework Picnic CSS for styling.
Umbrella JS is a lightweight alternative to JQuery.
Don't forget that you will need to manually put umbrella.min.js
and picnic.min.css
into your ~/.node-red/uibuilder/<node-url>/src
folder along with the files shown here. This example loads the 2 front-end libraries directly but you should really install them using npm
and reference them correctly if building a production system as this allows you to update them along with other dependencies.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
<!-- See https://goo.gl/OOhYW5 -->
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#3f51b5">
<!-- Used if adding to homescreen for Chrome on Android. Fallback for manifest.json -->
<meta name="mobile-web-app-capable" content="yes">
<meta name="application-name" content="Node-RED UI Builder">
<!-- Used if adding to homescreen for Safari on iOS -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Node-RED UI Builder">
<title>Node-RED UI Builder</title>
<meta name="description" content="Node-RED UI Builder">
<link rel="icon" href="images/node-blue.ico">
<link rel="stylesheet" href="picnic.min.css">
<link rel="stylesheet" href="index.css">
</head>
<body>
<!-- The "app" element is where the code for dynamic updates is attached -->
<div class="wrapper">
<div class="box header">
<h2>Welcome to UIbuilder for Node-RED</h2>
<p>This is the default web page. If you open the developer console, you will see some debug output.
You can also see some dynamic data updating below, thanks to Umbrella.js.
Please see the README for the
<a href="https://github.com/TotallyInformation/node-red-contrib-uibuilder">node-red-contrib-uibuilder</a>
node for details on how to use UIbuilder.
</p>
</div>
<div class="box sidebar">
<p><b>Dynamic Data (via Umbrella.js)</b></p>
<p><table><tr><td>Messages Received:</td><td><span id="msgsReceived"></span></td></tr></table></p>
<p>Control Messages Received: <span id="msgsControl"></span></p>
<p>Messages Sent: <span id="msgsSent"></span></p>
</div>
<div class="box content" id="app">
<p>UIBuilder Front-End Version: <span id="feVersion"></span></p>
<p>Websocket State: <span id="socketConnectedState" class="label"></span></p>
<p>Last Message Received: <code id="showMsg"></code></p>
<p>Last Control Message Received: <code id="showCtrlMsg"></code></p>
</div>
<div class="box footer">
<p>Send :
<select id="sandwich" style="width:20%">
<option>Cheese</option>
<option>Ham</option>
<option>Tomato</option>
</select>
<button id="button1">Click Me</button>
<button id="button2" class='success'>Success</button>
<button id="button3" class='warning'>Warning</button>
<button id="button4" class='error'>Error</button>
<button id="button5" disabled>Disabled</button>
<label>
<input id="toggle1" type="checkbox">
<span class="toggle button">Toggle</span>
</label>
</p>
<p>Sent : <code id="showMsgSent"></code></p>
</div>
</div>
<!-- These MUST be in the right order. Note no leading / -->
<!-- REQUIRED: Socket.IO is loaded only once for all instances
Without this, you don't get a websocket connection -->
<script src="/uibuilder/socket.io/socket.io.js"></script>
<!-- Note no leading / -->
<!-- OPTIONAL: Using Umbrella.js for this demo -->
<script src="umbrella.min.js"></script>
<!-- REQUIRED: Sets up Socket listeners and the msg object -->
<script src="uibuilderfe.min.js"></script>
<!-- OPTIONAL: You probably want this. Put your custom code here -->
<script src="index.js"></script>
</body>
</html>
/*global document,$,window,uibuilder */
// When JQuery is ready, update
//u( document ).ready(function() {
// Initial set
u('#msgsReceived').text( uibuilder.get('msgsReceived') )
u('#msgsControl').text( uibuilder.get('msgsCtrl') )
u('#msgsSent').text( uibuilder.get('msgsSent') )
u('#feVersion').text( uibuilder.get('version') )
u('button').on('click', function(e) { // send every button event on the page
uibuilder.send( { 'topic':e.target.id, 'payload':e.target.outerText } )
});
u('select').on('change keyup', function(e) { // send every select event on the page
uibuilder.send( { 'topic':e.target.id, 'payload':this.value } )
});
u('#toggle1').on('click', function(e) { // send toggle
uibuilder.send( { 'topic':e.target.id, 'payload':!e.srcElement.checked } )
});
// Turn on debugging (default is off)
//uibuilder.debug(true)
// If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO
// Note that you can also listen for 'msgsReceived' as they are updated at the same time
// but newVal relates to the attribute being listened to.
uibuilder.onChange('msg', function(newVal){
console.info('property msg changed!')
console.dir(newVal)
var foo = "";
Object.keys(newVal).forEach(function (key) {
foo += "<b>"+key+"</b> : "+JSON.stringify(newVal[key])+"<br/>";
});
u('#showMsg').html(foo)
})
// You can get attributes manually. Non-existent attributes return 'undefined'
//console.dir(uibuilder.get('msg'))
// You can also set things manually. See the list of attributes top of page.
// You can add arbitrary attributes to the object, you cannot overwrite internal attributes
// Try setting a restricted, internal attribute - see the warning in the browser console
uibuilder.set('msg', 'You tried but failed!')
// Remember that onChange functions don't trigger if you haven't set them
// up BEFORE an attribute change.
// uibuilder.onChange('msgCopy', function(newVal){
// console.info('msgCopy changed. New value: ', newVal)
// })
// Now try setting a new attribute - this will be an empty object because
// msg won't yet have been received
//uibuilder.set('msgCopy', uibuilder.msg)
// Hint: Try putting this set into the onChange for 'msg'
// As noted, we could get the msg here too
uibuilder.onChange('msgsReceived', function(newVal){
console.info('New msg sent to us from Node-RED over Socket.IO. Total Count: ', newVal)
u('#msgsReceived').text(newVal)
// uibuilder.msg is a shortcut for uibuilder.get('msg')
//$('#showMsg').text(JSON.stringify(uibuilder.msg))
})
// If Socket.IO connects/disconnects
uibuilder.onChange('ioConnected', function(newVal){
console.info('Socket.IO Connection Status Changed: ', newVal)
u('#socketConnectedState').text(newVal?"Connected":"Not Connected").toggleClass("success",newVal)
})
// If a message is sent back to Node-RED
uibuilder.onChange('msgsSent', function(newVal){
console.info('New msg sent to Node-RED over Socket.IO. Total Count: ', newVal)
u('#msgsSent').text(newVal)
u('#showMsgSent').text(JSON.stringify(uibuilder.get('sentMsg')))
})
// If we receive a control message from Node-RED
uibuilder.onChange('msgsCtrl', function(newVal){
console.info('New control msg sent to us from Node-RED over Socket.IO. Total Count: ', newVal)
u('#msgsControl').text(newVal)
u('#showCtrlMsg').text(JSON.stringify(uibuilder.get('ctrlMsg')))
})
// Automatically send a message back to Node-RED after 2 seconds
window.setTimeout(function(){
console.info('Sending a message back to Node-RED - after 1s delay')
uibuilder.send( { 'topic':'uibuilderfe', 'payload':'I am a message sent from the uibuilder front end' } )
}, 1000)
//})
body {
margin: 1em;
}
code {
word-break: break-all;
font-size: inherit;
padding: 0.45em .6em;
border-radius: .2em
}
select {
height: 2.2em;
}
button {
vertical-align: baseline;
}
:checked+.toggle, :checked+.toggle:hover {
box-shadow: inset 0 0 0 99em rgba(17,17,17,0.2);
color: #888;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
}
.footer {
grid-area: footer;
}
.wrapper {
display: grid;
grid-gap: 1em;
grid-template-areas:
"header"
"sidebar"
"content"
"footer"
}
@media only screen and (min-width: 500px) {
.wrapper {
grid-template-columns: 20% auto;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
}
.box {
background-color: #eee;
border-radius: 4px;
padding: 1em;
}
.header, .footer {
background-color: #ddd;
}
Please feel free to add comments to the page (clearly mark with your initials & please add a commit msg so we know what has changed). You can contact me in the Discourse forum, or raise an issue here in GitHub! I will make sure all comments & suggestions are represented here.
-
Walkthrough 🔗 Getting started
-
In Progress and To Do 🔗 What's coming up for uibuilder?
-
Awesome uibuilder Examples, tutorials, templates and references.
-
How To
- How to send data when a client connects or reloads the page
- Send messages to a specific client
- Cache & Replay Messages
- Cache without a helper node
- Use webpack to optimise front-end libraries and code
- How to contribute & coding standards
- How to use NGINX as a proxy for Node-RED
- How to manage packages manually
- How to upload a file from the browser to Node-RED
-
Vanilla HTML/JavaScript examples
-
VueJS general hints, tips and examples
- Load Vue (v2 or v3) components without a build step (modern browsers only)
- How to use webpack with VueJS (or other frameworks)
- Awesome VueJS - Tips, info & libraries for working with Vue
- Components that work
-
VueJS v3 hints, tips and examples
-
VueJS v2 hints, tips and examples
- Dynamically load .vue files without a build step (Vue v2)
- Really Simple Example (Quote of the Day)
- Example charts using Chartkick, Chart.js, Google
- Example Gauge using vue-svg-gauge
- Example charts using ApexCharts
- Example chart using Vue-ECharts
- Example: debug messages using uibuilder & Vue
- Example: knob/gauge widget for uibuilder & Vue
- Example: Embedded video player using VideoJS
- Simple Button Acknowledgement Example Thanks to ringmybell
- Using Vue-Router without a build step Thanks to AFelix
- Vue Canvas Knob Component Thanks to Klaus Zerbe
-
Examples for other frameworks (check version before trying)
- Basic jQuery example - Updated for uibuilder v6.1
- ReactJS with no build - updated for uibuilder v5/6
-
Examples for other frameworks (may not work, out-of-date)
-
Outdated Pages (Historic only)
- v1 Examples (these need updating to uibuilder v2/v3/v4/v5)