index-4.html 7.9 KB

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