Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MMM-pages.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. Module.register('MMM-pages', {
  2. // We require the older style of function declaration for compatibility
  3. // reasons.
  4. /**
  5. * By default, we have don't pseudo-paginate any modules. We also exclude
  6. * the page indicator by default, in case people actually want to use the
  7. * sister module. We also don't rotate out modules by default.
  8. */
  9. defaults: {
  10. modules: [],
  11. excludes: [], // Keep for compatibility
  12. fixed: ['MMM-page-indicator'],
  13. hiddenPages: {},
  14. animationTime: 1000,
  15. rotationTime: 0,
  16. rotationFirstPage: 0, // Keep for compatibility
  17. rotationHomePage: 0,
  18. rotationDelay: 10000,
  19. homePage: 0,
  20. useLockString: true,
  21. },
  22. /**
  23. * Apply any styles, if we have any.
  24. */
  25. getStyles: function () {
  26. return ['pages.css'];
  27. },
  28. /**
  29. * Modulo that also works with negative numbers.
  30. *
  31. * @param {number} x The dividend
  32. * @param {number} n The divisor
  33. */
  34. mod: function (x, n) {
  35. return ((x % n) + n) % n;
  36. },
  37. /**
  38. * Pseudo-constructor for our module. Makes sure that values aren't negative,
  39. * and sets the default current page to 0.
  40. */
  41. start: function () {
  42. // Clamp homePage value to [0, num pages).
  43. if (this.config.homePage >= this.config.modules.length || this.config.homePage < 0) {
  44. this.config.homePage = 0;
  45. }
  46. this.curPage = this.config.homePage;
  47. this.rotationPaused = false;
  48. // Compatibility
  49. if (this.config.excludes.length) {
  50. Log.warn('[Pages]: The config option "excludes" is deprecated. Please use "fixed" instead.');
  51. this.config.fixed = this.config.excludes;
  52. }
  53. if (this.config.rotationFirstPage) {
  54. Log.warn('[Pages]: The config option "rotationFirstPage" is deprecated. Please used "rotationHomePage" instead.');
  55. this.config.rotationHomePage = this.config.rotationFirstPage;
  56. }
  57. // Disable rotation if an invalid input is given
  58. this.config.rotationTime = Math.max(this.config.rotationTime, 0);
  59. this.config.rotationDelay = Math.max(this.config.rotationDelay, 0);
  60. this.config.rotationHomePage = Math.max(this.config.rotationHomePage, 0);
  61. if (!this.config.useLockString) {
  62. Log.log('[Pages]: User opted to not use lock strings!');
  63. }
  64. },
  65. /**
  66. * Handles incoming notifications. Responds to the following:
  67. * 'PAGE_CHANGED' - Set the page to the specified payload page.
  68. * 'PAGE_INCREMENT' - Move to the next page.
  69. * 'PAGE_DECREMENT' - Move to the previous page.
  70. * 'DOM_OBJECTS_CREATED' - Starts the module.
  71. * 'QUERY_PAGE_NUMBER' - Requests the current page number
  72. * 'PAUSE_ROTATION' - Stops rotation
  73. * 'RESUME_ROTATION' - Resumes rotation
  74. * 'HOME_PAGE' - Calls PAGED_CHANGED with the default home page.
  75. * 'SHOW_HIDDEN_PAGE' - Shows the (in the payload) specified hidden
  76. * page by name
  77. * 'LEAVE_HIDDEN_PAGE' - Hides the currently showing hidden page and
  78. * resumes showing the last page
  79. *
  80. * @param {string} notification the notification ID
  81. * @param {number|string} payload the page to change to/by
  82. */
  83. notificationReceived: function (notification, payload) {
  84. switch (notification) {
  85. case 'PAGE_CHANGED':
  86. Log.log('[Pages]: received a notification '
  87. + `to change to page ${payload} of type ${typeof payload}`);
  88. this.curPage = payload;
  89. this.updatePages();
  90. break;
  91. case 'PAGE_INCREMENT':
  92. Log.log('[Pages]: received a notification to increment pages!');
  93. this.changePageBy(payload, 1);
  94. this.updatePages();
  95. break;
  96. case 'PAGE_DECREMENT':
  97. Log.log('[Pages]: received a notification to decrement pages!');
  98. // We can't just pass in -payload for situations where payload is null
  99. // JS will coerce -payload to -0.
  100. this.changePageBy(payload ? -payload : payload, -1);
  101. this.updatePages();
  102. break;
  103. case 'DOM_OBJECTS_CREATED':
  104. Log.log('[Pages]: received that all objects are created;'
  105. + ' will now hide things!');
  106. this.sendNotification('MAX_PAGES_CHANGED', this.config.modules.length);
  107. this.sendNotification('NEW_PAGE', this.curPage);
  108. this.animatePageChange();
  109. this.resetTimerWithDelay(0);
  110. break;
  111. case 'QUERY_PAGE_NUMBER':
  112. this.sendNotification('PAGE_NUMBER_IS', this.curPage);
  113. break;
  114. case 'PAUSE_ROTATION':
  115. this.setRotation(false);
  116. break;
  117. case 'RESUME_ROTATION':
  118. this.setRotation(true);
  119. break;
  120. case 'HOME_PAGE':
  121. this.notificationReceived('PAGE_CHANGED', this.config.homePage);
  122. break;
  123. case 'SHOW_HIDDEN_PAGE':
  124. Log.log(`[Pages]: received a notification to change to the hidden page "${payload}" of type "${typeof payload}"`);
  125. this.setRotation(false);
  126. this.showHiddenPage(payload);
  127. break;
  128. case 'LEAVE_HIDDEN_PAGE':
  129. Log.log("[Pages]: received a notification to leave the current hidden page ");
  130. this.animatePageChange();
  131. this.setRotation(true);
  132. break;
  133. default: // Do nothing
  134. }
  135. },
  136. /**
  137. * Changes the internal page number by the specified amount. If the provided
  138. * amount is invalid, use the fallback amount. If the fallback amount is
  139. * missing or invalid, do nothing.
  140. *
  141. * @param {number} amt the amount of pages to move forward by. Accepts
  142. * negative numbers.
  143. * @param {number} fallback the fallback value to use. Accepts negative
  144. * numbers.
  145. */
  146. changePageBy: function (amt, fallback) {
  147. if (typeof amt !== 'number' && typeof fallback === 'undefined') {
  148. Log.warn(`[Pages]: ${amt} is not a number!`);
  149. }
  150. if (typeof amt === 'number' && !Number.isNaN(amt)) {
  151. this.curPage = this.mod(
  152. this.curPage + amt,
  153. this.config.modules.length
  154. );
  155. } else if (typeof fallback === 'number') {
  156. this.curPage = this.mod(
  157. this.curPage + fallback,
  158. this.config.modules.length
  159. );
  160. }
  161. },
  162. /**
  163. * Handles hiding the current page's elements and showing the next page's
  164. * elements.
  165. */
  166. updatePages: function () {
  167. // Update iff there's at least one page.
  168. if (this.config.modules.length !== 0) {
  169. this.animatePageChange();
  170. if (!this.rotationPaused) {
  171. this.resetTimerWithDelay(this.config.rotationDelay);
  172. }
  173. this.sendNotification('NEW_PAGE', this.curPage);
  174. } else { Log.error("[Pages]: Pages aren't properly defined!"); }
  175. },
  176. /**
  177. * Animates the page change from the previous page to the current one. This
  178. * assumes that there is a discrepancy between the page currently being shown
  179. * and the page that is meant to be shown.
  180. *
  181. * @param {string} [targetPageName] the name of the hiddenPage we want to show.
  182. * Optional and only used when we want to switch to a hidden page
  183. */
  184. animatePageChange: function (targetPageName) {
  185. let lockStringObj = { lockString: this.identifier };
  186. if (!this.config.useLockString) {
  187. // Passing in an undefined object is equivalent to not passing it in at
  188. // all, effectively providing only one arg to the hide and show calls
  189. lockStringObj = undefined;
  190. }
  191. // Hides all modules not on the current page. This hides any module not
  192. // meant to be shown.
  193. const self = this;
  194. let modulesToShow;
  195. if (typeof targetPageName !== 'undefined') {
  196. modulesToShow = this.config.hiddenPages[targetPageName];
  197. } else {
  198. modulesToShow = this.config.fixed.concat(this.config.modules[this.curPage]);
  199. }
  200. const animationTime = self.config.animationTime / 2;
  201. MM.getModules()
  202. .exceptWithClass(modulesToShow)
  203. .enumerate(module => module.hide(animationTime, lockStringObj));
  204. // Shows all modules meant to be on the current page, after a small delay.
  205. setTimeout(() => {
  206. MM.getModules()
  207. .withClass(modulesToShow)
  208. .enumerate(module => module.show(animationTime, lockStringObj));
  209. }, animationTime);
  210. },
  211. /**
  212. * Resets the page changing timer with a delay.
  213. *
  214. * @param {number} delay the delay, in milliseconds.
  215. */
  216. resetTimerWithDelay: function (delay) {
  217. if (this.config.rotationTime > 0) {
  218. // This timer is the auto rotate function.
  219. clearInterval(this.timer);
  220. // This is delay timer after manually updating.
  221. clearInterval(this.delayTimer);
  222. const self = this;
  223. this.delayTimer = setTimeout(() => {
  224. self.timer = setInterval(() => {
  225. // Inform other modules and page change.
  226. // MagicMirror automatically excludes the sender from receiving the
  227. // message, so we need to trigger it for ourselves.
  228. self.sendNotification('PAGE_INCREMENT');
  229. self.notificationReceived('PAGE_INCREMENT');
  230. }, self.config.rotationTime);
  231. }, delay);
  232. } else if (this.config.rotationHomePage > 0) {
  233. // This timer is the auto rotate function.
  234. clearInterval(this.timer);
  235. // This is delay timer after manually updating.
  236. clearInterval(this.delayTimer);
  237. const self = this;
  238. this.delayTimer = setTimeout(() => {
  239. self.timer = setInterval(() => {
  240. // Inform other modules and page change.
  241. // MagicMirror automatically excludes the sender from receiving the
  242. // message, so we need to trigger it for ourselves.
  243. self.sendNotification('PAGE_CHANGED', 0);
  244. self.notificationReceived('PAGE_CHANGED', self.config.homePage);
  245. }, self.config.rotationHomePage);
  246. }, delay);
  247. }
  248. },
  249. /**
  250. * Pause or resume the page rotation. If the provided isRotating value is
  251. * set to true, it will resume the rotation. If the requested
  252. * state (f.e. isRotating === true) equals the current state, print a warning
  253. * and do nothing.
  254. *
  255. * @param {boolean} isRotating the parameter, if you want to pause or resume.
  256. */
  257. setRotation: function (isRotating) {
  258. const stateBaseString = (isRotating) ? "resum" : "paus";
  259. if (isRotating === this.rotationPaused) {
  260. Log.warn(`[Pages]: Was asked to ${stateBaseString}e but rotation is already ${stateBaseString}ed!`);
  261. } else {
  262. Log.log(`[Pages]: ${stateBaseString}ing rotation`);
  263. if (!isRotating) {
  264. clearInterval(this.timer);
  265. clearInterval(this.delayTimer);
  266. } else {
  267. this.resetTimerWithDelay(this.rotationDelay);
  268. }
  269. this.rotationPaused = isRotating;
  270. }
  271. },
  272. /**
  273. * Handles hidden pages.
  274. *
  275. * @param {string} name the name of the hiddenPage we want to show
  276. */
  277. showHiddenPage: function (name) {
  278. // Only proceed if the named hidden page actually exists
  279. if (name in this.config.hiddenPages) {
  280. this.animatePageChange(name);
  281. } else {
  282. Log.error(`Hidden page "${name}" does not exist!`);
  283. }
  284. },
  285. });