diff --git a/DailyXKCD.js b/DailyXKCD.js
index cd2fd33..aacd390 100644
--- a/DailyXKCD.js
+++ b/DailyXKCD.js
@@ -2,10 +2,17 @@ Module.register("DailyXKCD", {
// Default module config.
defaults: {
- dailyJsonUrl: "http://xkcd.com/info.0.json",
- updateInterval: 10000 * 60 * 60, // 10 hours
- invertColors: false
-
+ dailyJsonUrl : "http://xkcd.com/info.0.json",
+ updateInterval : 10000 * 60 * 60, // 10 hours
+ invertColors : false,
+ titleFont : "bright large light",
+ altTextFont : "xsmall dimmed",
+ limitComicHeight : 450,
+ scrollInterval : 8000, // 8 seconds,
+ scrollRatio : 0.8, // scroll by 80% of visible height,
+ randomComic : false,
+ showAltText : false,
+ showTitle : true
},
start: function() {
@@ -16,7 +23,28 @@ Module.register("DailyXKCD", {
this.dailyComicTitle = "";
this.dailyComicAlt = "";
+ this.autoIntervals = [];
+
this.getComic();
+
+ if (this.config.scrollInterval < 3000) {
+ // animation takes 3 seconds
+ this.config.scrollInterval = 3000;
+ }
+
+ // value should be between 0.0 and 1.0
+ this.config.scrollRatio = Math.max(this.config.scrollRatio, 0.0);
+ this.config.scrollRatio = Math.min(this.config.scrollRatio, 1.0);
+
+ if (this.config.limitComicHeight > 0)
+ {
+ var self = this;
+ // scroll comic up and down
+ this.addAutoSuspendingInterval(function() {
+ self.scrollComic();
+ }, this.config.scrollInterval);
+ this.scrollProgress = 0;
+ }
},
// Define required scripts.
@@ -24,6 +52,11 @@ Module.register("DailyXKCD", {
return ["moment.js"];
},
+ // Define required styles.
+ getStyles: function() {
+ return ["xkcd.css"];
+ },
+
getComic: function() {
Log.info("XKCD: Getting comic.");
@@ -33,7 +66,6 @@ Module.register("DailyXKCD", {
},
socketNotificationReceived: function(notification, payload) {
-
if (notification === "COMIC") {
Log.info(payload.img);
this.dailyComic = payload.img;
@@ -41,7 +73,10 @@ Module.register("DailyXKCD", {
this.dailyComicAlt = payload.alt;
this.scheduleUpdate();
}
+ },
+ notificationReceived: function(notification, payload, sender) {
+ this.checkUserPresence(notification, payload, sender);
},
// Override dom generator.
@@ -49,33 +84,134 @@ Module.register("DailyXKCD", {
var wrapper = document.createElement("div");
var title = document.createElement("div");
- title.className = "bright large light";
+ title.className = this.config.titleFont;
title.innerHTML = this.dailyComicTitle;
+ if (this.config.showTitle) {
+ wrapper.appendChild(title);
+ }
+ var comicWrapper = document.createElement("div");
+ comicWrapper.className = "xkcdcontainer";
+ if (this.config.limitComicHeight > 0)
+ {
+ comicWrapper.style.maxHeight = this.config.limitComicHeight + "px";
+ }
var xkcd = document.createElement("img");
+ xkcd.id = "xkcdcontent";
xkcd.src = this.dailyComic;
- if (this.config.invertColors) {
+ if(this.config.invertColors){
xkcd.setAttribute("style", "-webkit-filter: invert(100%);")
}
+ comicWrapper.appendChild(xkcd);
+ wrapper.appendChild(comicWrapper);
- if (this.config.title) wrapper.appendChild(title);
-
- wrapper.appendChild(xkcd);
-
- if (this.config.altText) {
+ if (this.config.showAltText) {
var alt = document.createElement("div");
- alt.className = "bright medium light";
+ alt.className = this.config.altTextFont;
alt.innerHTML = this.dailyComicAlt;
wrapper.appendChild(alt);
}
-
return wrapper;
},
+ /* suspend()
+ * This method is called when a module is hidden.
+ */
+ suspend: function() {
+ this.scrollProgress = 0;
+
+ // reset to beginning if module is suspended, so we start at the top
+ var scrollable = document.getElementById("xkcdcontent");
+ scrollable.style.top = "0px";
+
+ for (var i = 0; i < this.autoIntervals.length; i++)
+ {
+ var current = this.autoIntervals[i];
+
+ if (current.interval)
+ {
+ clearInterval(current.interval);
+
+ current.interval = null;
+ }
+ }
+ },
+
+ /* resume()
+ * This method is called when a module is shown.
+ */
+ resume: function() {
+ for (var i = 0; i < this.autoIntervals.length; i++)
+ {
+ var current = this.autoIntervals[i];
+
+ if (!current.interval)
+ {
+ current.callback();
+
+ current.interval = setInterval(current.callback, current.time);
+ }
+ }
+ },
+
+ /* scrollComic
+ * Scrolls the comic down if needed
+ */
+ scrollComic: function() {
+ var scrollable = document.getElementById("xkcdcontent");
+
+ var height = scrollable.naturalHeight;
+
+ var top = 0;
+ if (this.config.limitComicHeight > 0 && height > this.config.limitComicHeight)
+ {
+ var currentHeight = this.scrollProgress * -this.config.limitComicHeight * this.config.scrollRatio;
+ var maxHeight = this.config.limitComicHeight - height;
+ top = Math.max(currentHeight, maxHeight);
+ }
+ scrollable.style.top = top + "px";
+ scrollable.style.height = height + "px";
+ if (top == this.config.limitComicHeight - height)
+ {
+ this.scrollProgress = -1;
+ }
+
+ this.scrollProgress += 1;
+ },
+
+ /* checkUserPresence(notification, payload, sender)
+ * Use this method to conveniently suspend your module when no user is present.
+ */
+ checkUserPresence: function(notification, payload, sender) {
+ if (sender && notification === "USER_PRESENCE") {
+ if (payload === true)
+ {
+ this.resume();
+ }
+ else
+ {
+ this.suspend();
+ }
+ }
+ },
+
+ /* addAutoSuspendingInterval(callback, time)
+ * Use instead of setInterval for automatic pause when on suspend.
+ * The callback is executed immediately once after the user returns.
+ */
+ addAutoSuspendingInterval: function(callback, time) {
+ var newInterval = setInterval(callback, time);
+ this.autoIntervals.push({
+ callback: callback,
+ interval: newInterval,
+ time: time
+ });
+ },
+
scheduleUpdate: function() {
var self = this;
diff --git a/README.md b/README.md
index 24698e6..4545d1a 100644
--- a/README.md
+++ b/README.md
@@ -14,8 +14,8 @@ A module for MagicMirror2 that displays the daily XKCD web comic.
module: 'DailyXKCD',
position: 'top_left',
config: {
- invertColors: true
- title: true
+ invertColors: true,
+ title: true,
altText: false
}
},
@@ -25,5 +25,12 @@ A module for MagicMirror2 that displays the daily XKCD web comic.
| **Option** | **Description** |
| --- | --- |
| `invertColors` | Set to `true` to invert the colors of the comic to white on black for a darker feel. |
-| `title` | Set to `true` to display the title of the comic. |
-| `altText` | Set to `true` to display the alternate text of the comic. |
+| `updateInterval` | Set to desired update interval (in ms), default is `3600000` (10 hours). |
+| `showTitle` | Set to `true` to display the title of the comic. |
+| `titleFont` | Set a custom font format, default is `large light bright`. To set the size use one of `xsmall small medium large xlarge`, for boldness one of `thin light regular bold`, and to adjust brightness one of `dimmed normal bright`. |
+| `showAltText` | Set to `true` to show the alt text (tooltip on the original comic). |
+| `altTextFont` | See `titleFont`, except for this is the formatting of the alt text. |
+| `randomComic` | Set to `true`, if you want to see a random comic on days, when there is no new comic. |
+| `limitComicHeight` | Set to limit the height of the comic (in px), default is `450`. The comic will scroll downwards every few seconds, if it is heigher. |
+| `scrollInterval` | How often to scroll long comics (in ms), default is `8000` (every 8 seconds). |
+| `scrollRatio` | Set how much of the visible height is being scrolled every time. The value should be between `0.0` and `1.0`, default is `0.8` so it scrolls down by 80%. |
diff --git a/node_helper.js b/node_helper.js
index 042b38c..d72bf58 100644
--- a/node_helper.js
+++ b/node_helper.js
@@ -12,20 +12,37 @@ module.exports = NodeHelper.create({
var self = this;
console.log("Notification: " + notification + " Payload: " + payload);
- if(notification === "GET_COMIC"){
+ if(notification === "GET_COMIC") {
var comicJsonUri = payload.config.dailyJsonUrl;
+
+ var date = new Date();
+ var dayOfWeek = date.getDay();
request(comicJsonUri, function (error, response, body) {
if (!error && response.statusCode == 200) {
- console.log(body);
- self.sendSocketNotification("COMIC", JSON.parse(body));
- console.log(JSON.parse(body).img);
-
+ if (!payload.config.randomComic) {
+ // if we are not replacing "old" comics with random ones
+ self.sendSocketNotification("COMIC", JSON.parse(body));
+ return;
+ }
+
+ // otherwise select a random comic based on day of week
+ if (dayOfWeek == 1 || dayOfWeek == 3 || dayOfWeek == 5) {
+ self.sendSocketNotification("COMIC", JSON.parse(body));
+ } else {
+ var comic = JSON.parse(body);
+ var randomNumber = Math.floor((Math.random() * comic.num) + 1);
+ // use "randomNumber = 1732;" to test with long comic
+ var randomUrl = "http://xkcd.com/" + randomNumber + "/info.0.json";
+ request(randomUrl, function (error, response, body) {
+ if (!error && response.statusCode == 200) {
+ self.sendSocketNotification("COMIC", JSON.parse(body));
+ }
+ });
+ }
}
});
-
}
-
},
});
diff --git a/xkcd.css b/xkcd.css
new file mode 100644
index 0000000..33ed2f4
--- /dev/null
+++ b/xkcd.css
@@ -0,0 +1,22 @@
+/* The basic container */
+.xkcdcontainer {
+ overflow: hidden;
+
+ /* To make the height of the container exact. */
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+#xkcdcontent {
+ white-space: nowrap;
+ position: relative;
+ overflow: hidden; /* Required to make ellipsis work */
+ text-overflow: clip;
+
+ top: 0%;
+
+ -webkit-transition: top 3s, height 3s;
+ -moz-transition: top 3s, height 3s;
+ transition: top 3s, height 3s;
+}