CSS and Javascript in template-node

1,157 views
Skip to first unread message

Jochen Scheib

unread,
Jan 13, 2016, 4:01:14 PM1/13/16
to Node-RED UI
Hey everyone,

i am using owntracks and want to display current position on a map using leaflet. I tried to use the template node, but failed.

Simple example 



<div id="map" style=" height: 200px"></div>


<script>
var map = L.map('map').setView([51.505, -0.09], 13);
    
maxZoom: 18,
attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
'Imagery © <a href="http://mapbox.com">Mapbox</a>',
id: 'mapbox.streets'
}).addTo(map);

    
    L.marker([51.5, -0.09]).addTo(map);
</script>

It works when the page is open and i hit the deploy button. But as soon as i refresh the page its broken.
The css-link section should be in the head part of an html file as far as i know. Could this be the problem?

Do you have an tutorial how to create something like this?

PS: Browser is giving me the following error on the js console:
ReferenceError: L is not defined
    at eval (eval at <anonymous> (http://pi2:1880/ui/js/app.min.js:3:2538), <anonymous>:1:11)
    at eval (native)
    at Function.n.extend.globalEval (http://pi2:1880/ui/js/app.min.js:3:2538)
    at n.fn.extend.domManip (http://pi2:1880/ui/js/app.min.js:4:17225)
    at n.fn.extend.append (http://pi2:1880/ui/js/app.min.js:4:14908)
    at null.<anonymous> (http://pi2:1880/ui/js/app.min.js:4:16268)
    at n.fn.extend.html (http://pi2:1880/ui/js/app.min.js:4:15939)

Thanks.

Jochen Scheib

unread,
Jan 13, 2016, 4:13:38 PM1/13/16
to Node-RED UI
And how do i inject my input into the javascript?

thx.

Julian Knight

unread,
Jan 13, 2016, 5:55:40 PM1/13/16
to Node-RED UI
As I suspected, a quick test by putting:
console.dir(L);
into the browser console after the page has loaded shows that L is loaded then. This means that your code is being executed BEFORE the library has loaded.

Simply wrap your code in the JQuery wrapper so that it doesn't run until the document is fullly loaded and the DOM is ready.
<script>
    $(document).ready(function(){
    var map = L.map('map').setView([51.505, -0.09], 13);
        
    maxZoom: 18,
    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
    '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
    'Imagery © <a href="http://mapbox.com">Mapbox</a>',
    id: 'mapbox.streets'
    }).addTo(map);
    
        
        L.marker([51.5, -0.09]).addTo(map);    
    });
</script>



On Wednesday, 13 January 2016 21:01:14 UTC, Jochen Scheib wrote:
Hey everyone,

i am using owntracks and want to display current position on a map using leaflet. I tried to use the template node, but failed.

...
Message has been deleted

Andrei Tătar

unread,
Jan 14, 2016, 2:43:11 AM1/14/16
to Node-RED UI
JQuery is already loaded by the UI.
Also, the template nodes are loaded dynamically into the DOM, long after  $(document).ready is fired.
The problem is that if your template has script tags inside it, angular (via jQuery) loads them async and it doesn't wait for the files to be loaded before executing the inline scripts.
So leaflet.js is probably loaded after your script tag is executed.

Here is a quick hackish fix. It basically sets up a timer that periodically checks if leaflet (L) is loaded. When it's loaded, it stops the timer and does the init.

<div id="map" style=" height: 200px"></div>

<script>
(function() {
    var timer = setInterval(function() {
        if (!window.L) return;
        debugger;
        clearInterval(timer);
    var map = L.map('map').setView([51.505, -0.09], 13);
        
    maxZoom: 18,
    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
    '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
    'Imagery © <a href="http://mapbox.com">Mapbox</a>',
    id: 'mapbox.streets'
    }).addTo(map);
    
        
        L.marker([51.5, -0.09]).addTo(map);
    }, 100);
})();
</script>


Julian Knight

unread,
Jan 14, 2016, 3:19:53 AM1/14/16
to Node-RED UI
Not needed, simply use JQuery document ready wrapper. The code won't run until the DOM is "complete" which is sufficient time to let the code from the CDN load and run.

Andrei Tătar

unread,
Jan 14, 2016, 3:22:39 AM1/14/16
to Node-RED UI
As I said, document ready is fired well before that template is loaded.

Jochen Scheib

unread,
Jan 14, 2016, 5:44:46 AM1/14/16
to Node-RED UI
Thanks, I will check this when I come home.

How can i change the coordinates in javascript based on the "input"? I tried with the template e.g. {{msg.payload}} but this is not working inside a script tag. Workaround would be "hidding" the information in a html tag and access them from javascript. Do you have a better solution?

Thanks for the great ui-node.

Jochen

Andrei Tătar

unread,
Jan 14, 2016, 9:04:21 AM1/14/16
to Node-RED UI
Here is a sample flow with a button that, when clicked, sets back the view of the map to the coordinates from the function node:
[{"id":"465d5d16.b9a2a4","type":"ui_tab","z":"94f4b225.6b0b5","name":"Home","icon":"dashboard","order":"1"},{"id":"f1cf7324.0e309","type":"ui_template","z":"94f4b225.6b0b5","tab":"465d5d16.b9a2a4","name":"","group":"","order":1,"format":"<link rel=\"stylesheet\" href=\"http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css\" />\n<script src=\"http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js\"></script>\n<div id=\"map\" style=\" height: 200px\"></div>\n\n<script>\n(function(scope) {\n    var timer = setInterval(function() {\n        if (!window.L) return;\n        clearInterval(timer);\n        \n    \tvar map = L.map('map').setView([51.505, -0.09], 13);\n        \n        L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6IjZjNmRjNzk3ZmE2MTcwOTEwMGY0MzU3YjUzOWFmNWZhIn0.Y8bhBaUMqFiPrDRW9hieoQ', {\n    \t\tmaxZoom: 18,\n    \t\tattribution: 'Map data &copy; <a href=\"http://openstreetmap.org\">OpenStreetMap</a> contributors, ' +\n    \t\t\t'<a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, ' +\n    \t\t\t'Imagery © <a href=\"http://mapbox.com\">Mapbox</a>',\n    \t\tid: 'mapbox.streets'\n    \t}).addTo(map);\n    \n        L.marker([51.5, -0.09]).addTo(map);\n        \n        scope.$watch('msg.payload', function (payload) {\n            if (payload && payload.length === 2)\n                map.setView(payload);\n        });\n    }, 100);\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"x":437,"y":210,"wires":[[]]},{"id":"b56ebf0.f4a914","type":"function","z":"94f4b225.6b0b5","name":"","func":"msg.payload = [51.505, -0.09];\nreturn msg;","outputs":1,"noerr":0,"x":278,"y":210,"wires":[["f1cf7324.0e309"]]},{"id":"91430464.6ebcf8","type":"ui_button","z":"94f4b225.6b0b5","tab":"465d5d16.b9a2a4","name":"Go Home","payload":"","topic":"","group":"","order":"0","x":134,"y":210,"wires":[["b56ebf0.f4a914"]]}]


Julian Knight

unread,
Jan 14, 2016, 5:30:21 PM1/14/16
to Node-RED UI
Tested and worked fine on my Pi2 installation.

Andrei Tătar

unread,
Jan 15, 2016, 4:44:18 AM1/15/16
to Node-RED UI
Curious, could you please post a flow?

Walter Kraembring

unread,
Jan 15, 2016, 6:53:17 AM1/15/16
to Node-RED UI
This great, I "played" a bit as well

Thank you, best regards
Walter
[{"id":"4fb3f15e.b04c1","type":"ui_tab","z":"4cf02873.b30fd8","name":"Home","icon":"dashboard","order":"1"},{"id":"3c534815.c3acb8","type":"ui_template","z":"4cf02873.b30fd8","tab":"4fb3f15e.b04c1","name":"","group":"","order":1,"format":"<link rel=\"stylesheet\" href=\"http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css\" />\n<script src=\"http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js\"></script>\n<div id=\"map\" style=\"width: 600px; height: 600px\"></div>\n\n<script>\n(function(scope) {\n    var timer = setInterval(function() {\n        if (!window.L) return;\n        clearInterval(timer);\n        \n    \tvar map = L.map('map').setView([40.71, -74.00], 14);\n\n        L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6IjZjNmRjNzk3ZmE2MTcwOTEwMGY0MzU3YjUzOWFmNWZhIn0.Y8bhBaUMqFiPrDRW9hieoQ', {\n    \t\tmaxZoom: 50,\n    \t\tattribution: 'Map data &copy; <a href=\"http://openstreetmap.org\">OpenStreetMap</a> contributors, ' +\n    \t\t\t'<a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, ' +\n    \t\t\t'Imagery © <a href=\"http://mapbox.com\">Mapbox</a>',\n    \t\tid: 'mapbox.streets'\n    \t}).addTo(map);\n    \n        var marker = L.marker([55.0, 10.0]).addTo(map);\n        \n        scope.$watch('msg.payload', function (payload) {\n            if (payload && payload.length === 2)\n//                map.setView(payload, 13);\n                L.marker(payload).addTo(map);\n                L.circle(payload, 500, {\n                    color: 'red',\n                    fillColor: 'blue',\n                    fillOpacity: 0.1\n                }).addTo(map);\n                map.setView(payload, 15);\n        });\n    }, 100);\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"x":495,"y":1005,"wires":[[]]},{"id":"b397e8c5.4c6818","type":"function","z":"4cf02873.b30fd8","name":"","func":"msg.payload = [51.505, -0.09];\nreturn msg;","outputs":1,"noerr":0,"x":314,"y":981,"wires":[["3c534815.c3acb8"]]},{"id":"857a7176.7a859","type":"ui_button","z":"4cf02873.b30fd8","tab":"4fb3f15e.b04c1","name":"Go London","payload":"","topic":"","group":"","order":"0","x":170,"y":981,"wires":[["b397e8c5.4c6818"]]},{"id":"e7d46cb4.182b9","type":"function","z":"4cf02873.b30fd8","name":"","func":"msg.payload = [59.4287, 18.0052];\nreturn msg;","outputs":1,"noerr":0,"x":312,"y":1042,"wires":[["3c534815.c3acb8"]]},{"id":"b9d015d5.462fe8","type":"ui_button","z":"4cf02873.b30fd8","tab":"4fb3f15e.b04c1","name":"Go Home","payload":"","topic":"","group":"","order":"0","x":159,"y":1044,"wires":[["e7d46cb4.182b9"]]}]

Julian Knight

unread,
Jan 15, 2016, 7:26:37 PM1/15/16
to Node-RED UI
Just this single node added to the bunch of other stuff I output:

[{"id":"a6144c49.59ebb","type":"ui_tab","z":"68da610e.9725a","name":"Test","icon":"windows","order":"99"},{"id":"44015c71.bbfea4","type":"ui_template","z":"68da610e.9725a","tab":"a6144c49.59ebb","name":"Leaflet","group":"","order":1,"format":"<link rel=\"stylesheet\" href=\"http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css\" />\n\n<script src=\"http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js\"></script>\n\n<div id=\"map\" style=\" height: 200px\"></div>\n\n\n<script>\n    $(document).ready(function(){\n    \tvar map = L.map('map').setView([51.505, -0.09], 13);\n        \n        L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6IjZjNmRjNzk3ZmE2MTcwOTEwMGY0MzU3YjUzOWFmNWZhIn0.Y8bhBaUMqFiPrDRW9hieoQ', {\n    \t\tmaxZoom: 18,\n    \t\tattribution: 'Map data &copy; <a href=\"http://openstreetmap.org\">OpenStreetMap</a> contributors, ' +\n    \t\t\t'<a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, ' +\n    \t\t\t'Imagery © <a href=\"http://mapbox.com\">Mapbox</a>',\n    \t\tid: 'mapbox.streets'\n    \t}).addTo(map);\n    \n        \n        L.marker([51.5, -0.09]).addTo(map);    \n    });\n</script>","storeOutMessages":true,"fwdInMessages":true,"x":1011,"y":3000,"wires":[[]]}]

Jochen Scheib

unread,
Jan 17, 2016, 9:59:10 AM1/17/16
to Node-RED UI
Hi,

thanks for your help. Working now perfectly. Document ready did not work for me. Andreis solution worked.

This flow uses Android Owntracks to show position and accuracy on map.

[{"id":"e6244e7f.19dbb","type":"ui_tab","z":"bb48b2ee.44b75","name":"Home","icon":"dashboard","order":"1"},{"id":"790243ac.86fdbc","type":"mqtt-broker","broker":"localhost","port":"1883","clientid":""},{"id":"3268e0b7.cd972","type":"mqtt in","z":"bb48b2ee.44b75","name":"","topic":"cloud/owntracks/jochen/#","broker":"790243ac.86fdbc","x":346,"y":237,"wires":[["74f48a64.8b0b74"]]},{"id":"29218e23.d6de72","type":"geofence","z":"bb48b2ee.44b75","name":"London","mode":"circle","inside":"both","rad":660.2497625752529,"points":[],"centre":{"latitude":51.50750208213464,"longitude":-0.13080596923828125},"x":428,"y":341,"wires":[["634f452f.9cb0bc"]]},{"id":"865ff4f.f79a008","type":"function","z":"bb48b2ee.44b75","name":"Formatierung und Timestamp","func":"if (msg.payload._type === \"location\") {\n    msg.location = {};\n    msg.location.lat = msg.payload.lat;\n    msg.location.lon = msg.payload.lon;\n    msg.timestamp = new Date();\n    return msg;\n}\n","outputs":1,"noerr":0,"x":810,"y":226,"wires":[["29218e23.d6de72"]]},{"id":"74f48a64.8b0b74","type":"json","z":"bb48b2ee.44b75","name":"","x":565,"y":229,"wires":[["865ff4f.f79a008"]]},{"id":"634f452f.9cb0bc","type":"ui_template","z":"bb48b2ee.44b75","tab":"e6244e7f.19dbb","name":"Position","group":"Jochen","order":1,"format":"<link rel=\"stylesheet\" href=\"http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css\" />\n<script src=\"http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js\"></script>\n<div id=\"map\" style=\" height: 200px\"></div>\n\n<script>\n(function(scope) {\n    var timer = setInterval(function() {\n        if (!window.L) return;\n        clearInterval(timer);\n        \n    \tvar map = L.map('map').setView([0,0], 13);\n    \tvar marker = L.marker([0,0]).addTo(map);\n    \tvar circle = L.circle([0, 0], 0, {\n                    color: 'blue',\n                    fillColor: '#0FF',\n                    fillOpacity: 0.3,\n                    stroke: false,\n                }).addTo(map);\n        \n        L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6IjZjNmRjNzk3ZmE2MTcwOTEwMGY0MzU3YjUzOWFmNWZhIn0.Y8bhBaUMqFiPrDRW9hieoQ', {\n    \t\tmaxZoom: 18,\n    \t\tattribution: 'Map data &copy; <a href=\"http://openstreetmap.org\">OpenStreetMap</a> contributors, ' +\n    \t\t\t'<a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, ' +\n    \t\t\t'Imagery © <a href=\"http://mapbox.com\">Mapbox</a>',\n    \t\tid: 'mapbox.streets'\n    \t}).addTo(map);\n    \n\n        scope.$watch('msg.payload', function (payload) {\n            if (payload._type === \"location\") {\n                var position = [];\n                position.push(payload.lat);\n                position.push(payload.lon);\n                map.setView(position);\n                marker.setLatLng(position);\n                circle.setLatLng(position);\n                circle.setRadius(payload.acc);\n            }\n        });\n    }, 100);\n})(scope);\n</script>","storeOutMessages":true,"fwdInMessages":true,"x":684,"y":342,"wires":[[]]}]


Thanks.



Am Mittwoch, 13. Januar 2016 22:01:14 UTC+1 schrieb Jochen Scheib:
Reply all
Reply to author
Forward
0 new messages