index-tv.html 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. <html>
  2. <head>
  3. <script>
  4. function importRssFeed (feedUrl) {
  5. var rssRequest = new XMLHttpRequest();
  6. rssRequest.onreadystatechange = function (e) {
  7. var r = rssRequest;
  8. if (r.readyState == XMLHttpRequest.DONE) {
  9. if (r.status >= 200 && r.status < 300) {
  10. console.log("Got RSS (" + r.status + "): ");
  11. var items = importRSSDoc(r.responseXML);
  12. populateItems( items );
  13. createPlot( items );
  14. importTvFeed( "https://harlanji.com/tv.xml" );
  15. }
  16. }
  17. };
  18. rssRequest.open("GET", feedUrl);
  19. rssRequest.send();
  20. }
  21. function importRSSDoc( rssDoc ) {
  22. console.log("importRSSDoc:");
  23. console.log( rssDoc );
  24. //var author = rssDoc.querySelector("generator").textContent.trim();
  25. var items = Array.from( rssDoc.querySelectorAll("item") );
  26. items = items.map(function (i) {
  27. var item = {
  28. title: i.querySelector("title").textContent.trim(),
  29. date: new Date( i.querySelector("pubDate").textContent.trim() ),
  30. description: i.querySelector("description").textContent.trim()
  31. };
  32. var occurenceParts = splitString( item.description, ":", 2);
  33. item.occurence = parseInt( occurenceParts[0] ) || 1;
  34. item.occurenceNote = occurenceParts[1].trim();
  35. if (item.occurenceNote == "") {
  36. item.occurenceNote = "Morning routine";
  37. }
  38. return item;
  39. });
  40. items = items.sort(function (a, b) {
  41. return b.date - a.date;
  42. });
  43. console.log("items:");
  44. console.log(items);
  45. return items;
  46. }
  47. function populateItems( items ) {
  48. console.log("populateItems");
  49. console.log( items );
  50. var rows = items.map(function (item) {
  51. var row = document.createElement( "tr" );
  52. var date = document.createElement( "td" );
  53. var occurence = document.createElement( "td" );
  54. var note = document.createElement( "td" );
  55. date.textContent = dateString( item.date );
  56. occurence.textContent = item.occurence;
  57. note.textContent = item.occurenceNote;
  58. row.appendChild( date );
  59. row.appendChild( occurence );
  60. row.appendChild( note );
  61. return row;
  62. });
  63. var tableBody = document.querySelector("#bed-makings tbody");
  64. console.log("populate: ");
  65. console.log(tableBody);
  66. console.log(rows);
  67. while (tableBody.lastChild) {
  68. tableBody.removeChild(tableBody.lastChild);
  69. }
  70. rows.forEach(function (row) {
  71. tableBody.appendChild(row);
  72. });
  73. }
  74. function importTvFeed (feedUrl) {
  75. var chart = {};
  76. var rssRequest = new XMLHttpRequest();
  77. rssRequest.onreadystatechange = function (e) {
  78. var r = rssRequest;
  79. if (r.readyState == XMLHttpRequest.DONE) {
  80. if (r.status >= 200 && r.status < 300) {
  81. console.log("Got TV RSS (" + r.status + "): ");
  82. var items = importTvDoc(r.responseXML);
  83. addTvToPlot( items );
  84. }
  85. }
  86. };
  87. rssRequest.open("GET", feedUrl);
  88. rssRequest.send();
  89. }
  90. function importTvDoc( rssDoc ) {
  91. console.log("importTvDoc:");
  92. console.log( rssDoc );
  93. var items = Array.from( rssDoc.querySelectorAll("item") );
  94. items = items.map(function (i) {
  95. var title = i.querySelector("title").textContent.trim();
  96. var state = title.indexOf("on") > -1;
  97. var item = {
  98. title: title,
  99. state: state,
  100. date: new Date( i.querySelector("pubDate").textContent.trim() ),
  101. description: i.querySelector("description").textContent.trim()
  102. };
  103. return item;
  104. });
  105. items = items.sort(function (a, b) {
  106. return b.date - a.date;
  107. });
  108. console.log("tv items:");
  109. console.log(items);
  110. return items;
  111. }
  112. function dateString (date) {
  113. // return "d: " + date;
  114. var str = (date.getYear() + 1900) + "-"
  115. + new String(date.getMonth() + 1).padStart(2, "0") + "-"
  116. + new String(date.getDate()).padStart(2, "0") + " "
  117. + new String(date.getHours()).padStart(2, "0") + ":"
  118. + new String(date.getMinutes()).padStart(2, "0") + ":"
  119. + new String(date.getSeconds()).padStart(2, "0") + " ";
  120. var tzOffset = date.getTimezoneOffset() / 60;
  121. if (tzOffset >= 0) {
  122. str += "+";
  123. }
  124. str += new String(tzOffset * 100).padStart(4, "0");
  125. return str;
  126. }
  127. function splitString(string, delimiter, n) {
  128. var parts = string.split(delimiter);
  129. return parts.slice(0, n - 1).concat([parts.slice(n - 1).join(delimiter)]);
  130. }
  131. </script>
  132. <!--
  133. <script defer data-domain="cityapper.com" src="https://pa.cityapper.com/js/plausible.js"></script>
  134. -->
  135. <script src="vis-timeline-graph2d.min.js"></script>
  136. <link href="vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" />
  137. <script src="suncalc.js"></script>
  138. </head>
  139. <body>
  140. <script>
  141. function importAuthorSubmitted( form ) {
  142. console.log("submitted:");
  143. console.log(form);
  144. }
  145. var authors = {
  146. "HarlanJI": "https://harlanji.com/bed.xml",
  147. "Marty": "https://harlanji.com/bed-marty.xml",
  148. "Dev": "bed-dev.xml"
  149. }
  150. function populateAuthors () {
  151. var authorsElem = document.querySelector("#author");
  152. while(authorsElem.lastChild) {
  153. authorsElem.removeChild(authorsElem.lastChild);
  154. }
  155. Object.entries(authors).forEach(function (e, i) {
  156. var option = document.createElement("option");
  157. option.value = e[1];
  158. option.textContent = e[0];
  159. if ( e[0] == "Dev" ) {
  160. option.selected = "selected";
  161. }
  162. authorsElem.appendChild(option);
  163. console.log(e);
  164. });
  165. authorsElem.dispatchEvent(new Event('change'));
  166. }
  167. function startOfDay (date) {
  168. var startDate = new Date(date);
  169. startDate.setHours(0);
  170. startDate.setMinutes(0);
  171. startDate.setSeconds(0);
  172. startDate.setMilliseconds(0);
  173. return startDate;
  174. }
  175. var dataset;
  176. function createPlot ( feedItems ) {
  177. console.log("createPlot");
  178. var container = document.getElementById('visualization');
  179. while( container.lastChild ) {
  180. container.removeChild( container.lastChild );
  181. }
  182. var items = feedItems.map(function (item) {
  183. var startDate = startOfDay(item.date);
  184. return {
  185. x: startDate,
  186. y: (item.date - startDate) / (1000 * 60),
  187. group: 0
  188. };
  189. });
  190. // feed items are in descending order
  191. var firstDate = startOfDay( feedItems[ feedItems.length - 1 ].date );
  192. var lastDate = startOfDay( feedItems[ 0 ].date );
  193. var firstTimes = SunCalc.getTimes(firstDate, 44.986656, -93.258133)
  194. var lastTimes = SunCalc.getTimes(lastDate, 44.986656, -93.258133)
  195. items.push({x: firstDate,
  196. y: (firstTimes.sunrise - firstDate) / (1000 * 60),
  197. group: 1});
  198. items.push({x: lastDate,
  199. y: (lastTimes.sunrise - lastDate) / (1000 * 60),
  200. group: 1});
  201. items.push({x: firstDate,
  202. y: (firstTimes.goldenHourEnd - firstDate) / (1000 * 60),
  203. group: 2});
  204. items.push({x: lastDate,
  205. y: (lastTimes.goldenHourEnd - lastDate) / (1000 * 60),
  206. group: 2});
  207. dataset = new vis.DataSet(items);
  208. var options = {
  209. sort: false,
  210. sampling:false,
  211. style:'points',
  212. dataAxis: {
  213. left: {
  214. range: {
  215. min: 0, max: (60 * 24)
  216. }
  217. }
  218. },
  219. drawPoints: {
  220. enabled: true,
  221. size: 6,
  222. style: 'circle' // square, circle
  223. },
  224. defaultGroup: 'Scatterplot',
  225. height: '400px',
  226. width: '90%'
  227. };
  228. var graph2d = new vis.Graph2d(container, dataset, options);
  229. }
  230. function addTvToPlot ( feedItems ) {
  231. console.log("addTvToPlot");
  232. // create two lists
  233. var offItems = [], onItems = [];
  234. feedItems.forEach(function (item) {
  235. var items = item.state ? onItems : offItems;
  236. var startDate = startOfDay(item.date);
  237. var group = item.state ? 4 : 3;
  238. items.push({
  239. x: startDate,
  240. y: (item.date - startDate) / (1000 * 60),
  241. group: group
  242. });
  243. });
  244. dataset.add( onItems );
  245. dataset.add( offItems );
  246. }
  247. </script>
  248. <h1>Author Made Bed</h1>
  249. <form id="import-author" action="#" onsubmit="console.log('s')">
  250. <p>
  251. Author:
  252. <select id="author" onchange="importRssFeed(this.options[this.selectedIndex].value)">
  253. </select>
  254. </p>
  255. </form>
  256. <div id="visualization"></div>
  257. <table id="bed-makings">
  258. <thead>
  259. <tr>
  260. <th>Date Time</th>
  261. <th>#</th>
  262. <th>Note</th>
  263. </tr>
  264. </thead>
  265. <tbody>
  266. </tbody>
  267. </table>
  268. <script>
  269. //importRssFeed( document.querySelector("#author").value );
  270. populateAuthors();
  271. </script>
  272. </body>
  273. </html>