Twitter enabled web page slideshow
This flow is based almost entirely on https://flows.nodered.org/flow/8666510f94ad422e4765
It adds a Twitter user input (@archillect) extracts the https url of the posted media and feed said url to the websocket, so it can be displayed by the webpage available at 'http://{your-server-ip:1880/slideshow'
The image gets somewhat resized to the dimension of the browser window. It's not working 100% of the time i.e. with 16:10 aspect monitors the images get stretched too much, It's far from perfect, but it's a start. In the page template there's some javascript added so you can go fullscreen (but that gets resetted when the image changes) see: http://blogs.sitepointstatic.com/examples/tech/full-screen/index.html
It works quite well if you cast a tab of your browser to a chromecast, or if you have a spare tablet you can basically have a Twitter powered photo display.
[{"id":"affb0fda.9189c","type":"twitter in","z":"fb5b6e33.9bc11","twitter":"","tags":"@archillect","user":"user","name":"","topic":"tweets","x":170,"y":60,"wires":[["2ee36506.9e365a","e27ad042.65f95"]]},{"id":"e27ad042.65f95","type":"change","z":"fb5b6e33.9bc11","name":"get tweet object","rules":[{"t":"set","p":"payload","pt":"msg","to":"tweet","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":160,"y":140,"wires":[["62c28189.4ce19"]]},{"id":"62c28189.4ce19","type":"change","z":"fb5b6e33.9bc11","name":"get media https url","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.entities.media[0].media_url_https","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":140,"wires":[["b7450e85.a8207","fc94d254.85dd1"]]},{"id":"fc94d254.85dd1","type":"websocket out","z":"fb5b6e33.9bc11","name":"","server":"bc725200.1dc2d","client":"","x":550,"y":260,"wires":[]},{"id":"8905b6ac.848648","type":"http in","z":"fb5b6e33.9bc11","name":"","url":"/slideshow","method":"get","swaggerDoc":"","x":140,"y":200,"wires":[["6864b831.fe7818"]]},{"id":"6864b831.fe7818","type":"template","z":"fb5b6e33.9bc11","name":"HTML Slideshow","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<!DOCTYPE HTML>\n<html>\n <head>\n <style>\n*\n{\n\tpadding: 0;\n\tmargin: 0;\n}\n\nhtml, body\n{\n\tfont-family: \"Segoe UI\", arial, helvetica, freesans, sans-serif;\n\tcolor: #333;\n\tbackground-color: #000;\n\toverflow-y: auto;\n\toverflow-x: auto;\n}\n\nbody\n{\n\tmargin: 0 auto;\n\tmax-height: 100%;\n max-width: 100%;\n}\n\np\n{\n\tmargin: 0 0 1em 0;\n}\n\nsection\n{\n\tdisplay: block;\n\tfloat: center;\n\tpadding: 0;\n\tmargin: 0 auto;\n\tborder: 0 none;\n\tcursor: pointer;\n\tmax-height: 100%;\n max-width: 100%;\n}\n\n\nsection img\n{\n\twidth: 100%;\n\theight: 100%;\n}\n\n\nsection p\n{\n\tfont-weight: bold;\n\ttext-align: center;\n\tmargin: 0;\n}\n\nsection:-webkit-full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n\tbackground-color: #f00;\n}\n\nsection:-moz-full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n}\n\nsection:-ms-full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n}\n\nsection:-o-full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n}\n\nsection:full-screen\n{\n\tfloat: none;\n\twidth: 100%;\n\theight: 100%;\n\tpadding: 0;\n\tmargin: 0;\n\tborder: 0 none;\n}\n</style>\n <title>Simple Live Display</title>\n <script src=\"https://code.jquery.com/jquery-latest.js\"></script>\n <script type=\"text/javascript\">\n var ws;\n var wsUri = \"ws:\";\n var loc = window.location;\n console.log(loc);\n if (loc.protocol === \"https:\") { wsUri = \"wss:\"; }\n // This needs to point to the web socket in the Node-RED flow\n // ... in this case it's ws/simple\n wsUri += \"//\" + loc.host + loc.pathname.replace(\"slideshow\",\"ws/slideshow\");\n\n function wsConnect() {\n console.log(\"connect\",wsUri);\n ws = new WebSocket(wsUri);\n //var line = \"\"; // either uncomment this for a building list of messages\n ws.onmessage = function(msg) {\n var line = \"\"; // or uncomment this to overwrite the existing message\n // parse the incoming message as a JSON object\n var data = msg.data;\n //console.log(data);\n // build the output from the topic and payload parts of the object\n // line += \"<p>\"+data+\"</p>\";\n line += '<section id=\"fullscreen\" onclick=\"gofull();\"><img onload=\"fit_to_screen();\" src=\"' + data + '\"/></section>'\n // replace the messages div with the new \"line\"\n document.getElementById('messages').innerHTML = line;\n //ws.send(JSON.stringify({data:data}));\n set_body_height();\n }\n ws.onopen = function() {\n // update the status div with the connection status\n document.getElementById('status').innerHTML = \"connected\";\n //ws.send(\"Open for data\");\n console.log(\"connected\");\n }\n ws.onclose = function() {\n // update the status div with the connection status\n document.getElementById('status').innerHTML = \"not connected\";\n // in case of lost connection tries to reconnect every 3 secs\n setTimeout(wsConnect,3000);\n }\n }\n \n function set_body_height() { // set body height = window height\n $('body').height($(window).height());\n $('body').width($(window).width());\n fit_to_screen();\n }\n $(document).ready(function() {\n $(window).bind('resize', set_body_height);\n set_body_height();\n });\n \n function fit_to_screen() {\n img.removeAttribute(\"style\");\n // var winX = window.innerWidth + \"px\";\n var winX = $(window).width();\n // var winY = window.innerHeight + \"px\";\n var winY = $(window).height();\n var vbar = false;\n if (document.body.scrollHeight > document.body.clientHeight) // vertical scrollbar\n {\n img.style.height = winY;\n vbar = true;\n }\n if (document.body.scrollWidth > document.body.clientWidth) // horizontal scrollbar\n {\n if (vbar) // both scrollbars\n {\n if ((document.body.scrollHeight - document.body.clientHeight) > (document.body.scrollWidth - document.body.clientWidth)) // let's see which one is bigger\n {\n img.removeAttribute(\"style\");\n img.style.height = winY;\n }\n else\n {\n img.removeAttribute(\"style\");\n img.style.width = winX;\n }\n }\n else\n {\n img.removeAttribute(\"style\");\n img.style.width = winX;\n }\n }\n }\n \n function gofull() {\n \n var e = document.getElementById(\"fullscreen\");\n\n\t if (RunPrefixMethod(document, \"FullScreen\") || RunPrefixMethod(document, \"IsFullScreen\")) {\n\t\t RunPrefixMethod(document, \"CancelFullScreen\");\n\t }\n\t else {\n\t\t RunPrefixMethod(e, \"RequestFullScreen\");\n\t }\n\n }\n\n var pfx = [\"webkit\", \"moz\", \"ms\", \"o\", \"\"];\n function RunPrefixMethod(obj, method) {\n\t\n\t var p = 0, m, t;\n\t while (p < pfx.length && !obj[m]) {\n\t \tm = method;\n\t \tif (pfx[p] == \"\") {\n\t \t\tm = m.substr(0,1).toLowerCase() + m.substr(1);\n\t \t}\n \t\tm = pfx[p] + m;\n \t\tt = typeof obj[m];\n \t\tif (t != \"undefined\") {\n\t\t\t pfx = [pfx[p]];\n\t\t\t return (t == \"function\" ? obj[m]() : obj[m]);\n\t\t }\n\t\t p++;\n\t }\n\n }\n \n function doit(m) {\n if (ws) { ws.send(m); }\n }\n </script>\n </head>\n <body onload=\"wsConnect();\" onunload=\"ws.disconnect();\">\n <font face=\"Arial\">\n <div id=\"messages\"></div>\n <!-- <button type=\"button\" onclick='gofull();'>Full Screen</button> -->\n <!-- <button type=\"button\" onclick='fit_to_screen();'>Fit</button> -->\n <div id=\"status\">unknown</div>\n </font>\n </body>\n</html>\n","x":338,"y":200,"wires":[["b7cabbb.ce8e248"]]},{"id":"b7cabbb.ce8e248","type":"http response","z":"fb5b6e33.9bc11","name":"","x":550,"y":200,"wires":[]},{"id":"bc725200.1dc2d","type":"websocket-listener","z":"","path":"/ws/slideshow","wholemsg":"false"}]