├── .github
├── ModuleBar-01.png
├── ModuleBar-02.png
├── ModuleBar-03.png
├── ModuleBar-04.png
├── ModuleBar-05.png
└── ModuleBar-06.png
├── .gitignore
├── LICENSE
├── MMM-Modulebar.css
├── MMM-Modulebar.js
├── README.md
└── js
└── jquery.js
/.github/ModuleBar-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Snille/MMM-Modulebar/891d9a3de0b2d403ac2e7a1b5273c5857522fe30/.github/ModuleBar-01.png
--------------------------------------------------------------------------------
/.github/ModuleBar-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Snille/MMM-Modulebar/891d9a3de0b2d403ac2e7a1b5273c5857522fe30/.github/ModuleBar-02.png
--------------------------------------------------------------------------------
/.github/ModuleBar-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Snille/MMM-Modulebar/891d9a3de0b2d403ac2e7a1b5273c5857522fe30/.github/ModuleBar-03.png
--------------------------------------------------------------------------------
/.github/ModuleBar-04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Snille/MMM-Modulebar/891d9a3de0b2d403ac2e7a1b5273c5857522fe30/.github/ModuleBar-04.png
--------------------------------------------------------------------------------
/.github/ModuleBar-05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Snille/MMM-Modulebar/891d9a3de0b2d403ac2e7a1b5273c5857522fe30/.github/ModuleBar-05.png
--------------------------------------------------------------------------------
/.github/ModuleBar-06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Snille/MMM-Modulebar/891d9a3de0b2d403ac2e7a1b5273c5857522fe30/.github/ModuleBar-06.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 | *.VC.VC.opendb
85 |
86 | # Visual Studio profiler
87 | *.psess
88 | *.vsp
89 | *.vspx
90 | *.sap
91 |
92 | # TFS 2012 Local Workspace
93 | $tf/
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 | *.DotSettings.user
102 |
103 | # JustCode is a .NET coding add-in
104 | .JustCode
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | _NCrunch_*
114 | .*crunch*.local.xml
115 | nCrunchTemp_*
116 |
117 | # MightyMoose
118 | *.mm.*
119 | AutoTest.Net/
120 |
121 | # Web workbench (sass)
122 | .sass-cache/
123 |
124 | # Installshield output folder
125 | [Ee]xpress/
126 |
127 | # DocProject is a documentation generator add-in
128 | DocProject/buildhelp/
129 | DocProject/Help/*.HxT
130 | DocProject/Help/*.HxC
131 | DocProject/Help/*.hhc
132 | DocProject/Help/*.hhk
133 | DocProject/Help/*.hhp
134 | DocProject/Help/Html2
135 | DocProject/Help/html
136 |
137 | # Click-Once directory
138 | publish/
139 |
140 | # Publish Web Output
141 | *.[Pp]ublish.xml
142 | *.azurePubxml
143 | # TODO: Comment the next line if you want to checkin your web deploy settings
144 | # but database connection strings (with potential passwords) will be unencrypted
145 | *.pubxml
146 | *.publishproj
147 |
148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
149 | # checkin your Azure Web App publish settings, but sensitive information contained
150 | # in these scripts will be unencrypted
151 | PublishScripts/
152 |
153 | # NuGet Packages
154 | *.nupkg
155 | # The packages folder can be ignored because of Package Restore
156 | **/packages/*
157 | # except build/, which is used as an MSBuild target.
158 | !**/packages/build/
159 | # Uncomment if necessary however generally it will be regenerated when needed
160 | #!**/packages/repositories.config
161 | # NuGet v3's project.json files produces more ignoreable files
162 | *.nuget.props
163 | *.nuget.targets
164 |
165 | # Microsoft Azure Build Output
166 | csx/
167 | *.build.csdef
168 |
169 | # Microsoft Azure Emulator
170 | ecf/
171 | rcf/
172 |
173 | # Windows Store app package directories and files
174 | AppPackages/
175 | BundleArtifacts/
176 | Package.StoreAssociation.xml
177 | _pkginfo.txt
178 |
179 | # Visual Studio cache files
180 | # files ending in .cache can be ignored
181 | *.[Cc]ache
182 | # but keep track of directories ending in .cache
183 | !*.[Cc]ache/
184 |
185 | # Others
186 | ClientBin/
187 | ~$*
188 | *~
189 | *.dbmdl
190 | *.dbproj.schemaview
191 | *.pfx
192 | *.publishsettings
193 | node_modules/
194 | orleans.codegen.cs
195 |
196 | # Since there are multiple workflows, uncomment next line to ignore bower_components
197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
198 | #bower_components/
199 |
200 | # RIA/Silverlight projects
201 | Generated_Code/
202 |
203 | # Backup & report files from converting an old project file
204 | # to a newer Visual Studio version. Backup files are not needed,
205 | # because we have git ;-)
206 | _UpgradeReport_Files/
207 | Backup*/
208 | UpgradeLog*.XML
209 | UpgradeLog*.htm
210 |
211 | # SQL Server files
212 | *.mdf
213 | *.ldf
214 |
215 | # Business Intelligence projects
216 | *.rdl.data
217 | *.bim.layout
218 | *.bim_*.settings
219 |
220 | # Microsoft Fakes
221 | FakesAssemblies/
222 |
223 | # GhostDoc plugin setting file
224 | *.GhostDoc.xml
225 |
226 | # Node.js Tools for Visual Studio
227 | .ntvs_analysis.dat
228 |
229 | # Visual Studio 6 build log
230 | *.plg
231 |
232 | # Visual Studio 6 workspace options file
233 | *.opt
234 |
235 | # Visual Studio LightSwitch build output
236 | **/*.HTMLClient/GeneratedArtifacts
237 | **/*.DesktopClient/GeneratedArtifacts
238 | **/*.DesktopClient/ModelManifest.xml
239 | **/*.Server/GeneratedArtifacts
240 | **/*.Server/ModelManifest.xml
241 | _Pvt_Extensions
242 |
243 | # Paket dependency manager
244 | .paket/paket.exe
245 | paket-files/
246 |
247 | # FAKE - F# Make
248 | .fake/
249 |
250 | # JetBrains Rider
251 | .idea/
252 | *.sln.iml
253 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Erik Pettersson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MMM-Modulebar.css:
--------------------------------------------------------------------------------
1 | /*****************************************************
2 | * Magic Mirror 2 *
3 | * Custom CSS for MMM-modulebar *
4 | * *
5 | * By Erik Pettersson *
6 | * Based on the TouchNavigation CSS by Brian Janssen *
7 | * MIT Licensed. *
8 | * *
9 | *****************************************************/
10 | .modulebar-menu {
11 | display: flex;
12 | align-items: stretch;
13 | }
14 |
15 | .modulebar-button {
16 | z-index: 1;
17 | /* Border */
18 | border-style: solid;
19 | border-width: 2px;
20 | border-color: #aaa;
21 | border-radius: 15px;
22 |
23 | /* as container */
24 | display: flex;
25 | justify-content: center;
26 | align-items: center;
27 |
28 | margin: 2px;
29 | padding: 6px 6px;
30 | }
31 |
32 | .modulebar-picture {
33 | margin: 1px 1px;
34 | /* width: 60px;*/
35 | /* height: 60px;*/
36 | }
37 |
38 | .modulebar-text {
39 | margin: -5px 0;
40 | }
41 |
42 | .paint-it-black {
43 | position: fixed;
44 | top: 0px;
45 | right: 0px;
46 | bottom: 0px;
47 | left: 0px;
48 | display: none;
49 | width: 100%;
50 | height: 100%;
51 | background-color: #000;
52 | z-index: 999;
53 | }
54 |
--------------------------------------------------------------------------------
/MMM-Modulebar.js:
--------------------------------------------------------------------------------
1 | /* global Module */
2 |
3 | /* Magic Mirror 2
4 | * Module: MMM-Modulebar
5 | *
6 | * By Erik Pettersson
7 | * Based on the TouchNavigation Module by Brian Janssen
8 | *
9 | * MIT Licensed.
10 | */
11 |
12 | //var request = require('request');
13 |
14 | Module.register("MMM-Modulebar",{
15 |
16 | requiresVersion: "2.1.0",
17 |
18 | defaults: {
19 | // Allow the module to force modules to be shown (if hidden and locked by another module ex. profile-switcher).
20 | allowForce: false,
21 | // Determines if the border around the buttons should be shown.
22 | showBorder: true,
23 | // The minimum width for all the buttons.
24 | minWidth: "0px",
25 | // The minimum height for all the buttons.
26 | minHeight: "0px",
27 | // The location of the symbol relative to the text. Options: left, right, top or bottom
28 | picturePlacement: "left",
29 | // The direction of the bar. Options: row, column, row-reverse or column-reverse
30 | direction: "row",
31 | // The speed of the hide and show animation.
32 | animationSpeed: 1000,
33 | // Z-Index value for the hide all plane.
34 | zindex: 1000,
35 | // Visibility of the "unhide all button" when all is hidden (0.0 - 1.0).
36 | visability: 0.5,
37 | // The default button 1. Add your buttons in the config.
38 | buttons: {
39 | "1": {
40 | // Hides and show everything (Same as MMM-HideALL).
41 | module: "all",
42 | // When everything is shown - Toggle-on symbol from font-awesome.
43 | symbol: "toggle-on",
44 | // When everything is hidden - Toggle-off symbol from font-awesome.
45 | symbol2: "toggle-off",
46 | },
47 | "2": {
48 | // The modules exact name to be affected (clock in this case).
49 | module: "clock",
50 | // When module is shown - Bell symbol from font-awesome.
51 | symbol: "bell",
52 | // When module is hidden - Bell-Slash symbol from font-awesome.
53 | symbol2: "bell-slash",
54 | }
55 | }
56 | },
57 | // Loads the jquery library (if not loaded already).
58 | getScripts: function() {
59 | // Tried to fix a check if JQuery had already been loaded by something else. If not, then loaded it.
60 | // Did not work... I'll try again later. :)
61 | // if (typeof jQuery == "undefined") {
62 | return ["modules/MMM-Modulebar/js/jquery.js"];
63 | // } else {
64 | // return;
65 | // }
66 | },
67 |
68 | // Define required styles.
69 | getStyles: function(){
70 | return ["font-awesome.css", "MMM-Modulebar.css"];
71 | },
72 |
73 | // Override dom generator.
74 | getDom: function() {
75 | var overlay = document.createElement("div");
76 | overlay.className = "paint-it-black";
77 | var menu = document.createElement("span");
78 | menu.className = "modulebar-menu";
79 | menu.id = this.identifier + "_menu";
80 | menu.style.flexDirection = this.config.direction;
81 | // Sends each button to the "createButton" function be created.
82 | for (var num in this.config.buttons) {
83 | menu.appendChild(this.createButton(this, num, this.config.buttons[num], this.config.picturePlacement, overlay));
84 | }
85 | menu.appendChild(overlay);
86 | return menu;
87 | },
88 |
89 | // Creates the buttons.
90 | createButton: function (self, num, data, placement, overlay) {
91 | var hidden = true;
92 | // Creates the span element to contain all the buttons.
93 | var item = document.createElement("span");
94 | // Builds a unique identity / button.
95 | item.id = self.identifier + "_button_" + num;
96 | // Sets a class to all buttons.
97 | item.className = "modulebar-button";
98 |
99 | // Check for fas, far or fab in symbol.
100 | if (typeof data.symbol !== 'undefined') {
101 | var isfasthere = data.symbol.includes("fas ");
102 | var isfabthere = data.symbol.includes("fab ");
103 | var isfarthere = data.symbol.includes("far ");
104 | }
105 | if (typeof data.symbol2 !== 'undefined') {
106 | var isfasthere2 = data.symbol2.includes("fas ");
107 | var isfabthere2 = data.symbol2.includes("fab ");
108 | var isfarthere2 = data.symbol2.includes("far ");
109 | }
110 | // If fas, fab or far is defined in the symbol, nothing will be added (assume user had the full symbol name).
111 | if (isfasthere === true || isfasthere2 === true || isfabthere === true || isfabthere2 === true || isfarthere === true || isfarthere2 === true) {
112 | var faclassName = "modulebar-picture ";
113 | // If you just typed the symbol name, fas and fa- will be added (I'll keep this for compatibility).
114 | } else {
115 | var faclassName = "modulebar-picture fas fa-";
116 | }
117 | // Makes sure the width and height is at least the defined minimum.
118 | item.style.minWidth = self.config.minWidth;
119 | item.style.minHeight = self.config.minHeight;
120 | // Collects all modules loaded in MagicMirror.
121 | var modules = MM.getModules();
122 | // When a button is clicked, the module either gets hidden or shown depending on current module status.
123 | item.addEventListener("click", function () {
124 | // If "all" is defined in a button, the hide all is triggered.
125 | if (typeof data.gotoUrl !== 'undefined') {
126 | if (data.gotoUrl === "back") {
127 | window.history.back();
128 | } else {
129 | window.location.assign(data.gotoUrl);
130 | }
131 | }
132 | if (data.module === "all") {
133 | // Hiding all modules.
134 | if (hidden) {
135 | // Adding the black overlay.
136 | $(overlay).fadeIn(self.config.animationSpeed);
137 | // Set black overlay on this specific Z-Index.
138 | $(item).css("z-index",self.config.zindex);
139 | // Visability of the "unhide-button".
140 | $(item).fadeTo(self.config.animationSpeed,self.config.visability);
141 | // Sets the defined symbol for all hidden.
142 | if (typeof data.symbol2 !== 'undefined') {
143 | symbol.className = faclassName + data.symbol2;
144 | // Set the size if it's set.
145 | if (data.size) {
146 | symbol.className += " fa-" + data.size;
147 | symbol.className += data.size == 1 ? "g" : "x";
148 | }
149 | // Sets the defined image for all hidden.
150 | } else if (typeof data.img2 !== 'undefined') {
151 | image.className = "modulebar-picture";
152 | image.src = data.img2;
153 | }
154 | // Sets the defined text for all hidden.
155 | if (typeof data.text2 !== 'undefined') {
156 | text.innerHTML = data.text2;
157 | }
158 | // Prints console.
159 | console.log("Hiding all!");
160 | // Sets the "flip flop".
161 | hidden = false;
162 | // Showing all modules.
163 | } else {
164 | // Removing the black overlay.
165 | $(overlay).fadeOut(self.config.animationSpeed);
166 | // Show the button fully again.
167 | $(item).fadeTo(self.config.animationSpeed, 1);
168 | // Sets the defined symbol for all shown.
169 | if (typeof data.symbol !== 'undefined') {
170 | symbol.className = faclassName + data.symbol;
171 | // Set the size if it's set.
172 | if (data.size) {
173 | symbol.className += " fa-" + data.size;
174 | symbol.className += data.size == 1 ? "g" : "x";
175 | }
176 | // Sets the defined image for all shown.
177 | } else if (typeof data.img !== 'undefined') {
178 | image.className = "modulebar-picture";
179 | image.src = data.img;
180 | }
181 | // Sets the defined text for all shown.
182 | if (typeof data.text !== 'undefined') {
183 | text.innerHTML = data.text;
184 | }
185 | // Prints console.
186 | console.log("Showing all!");
187 | // Sets the "flip flop".
188 | hidden = true;
189 | }
190 | } else {
191 | // Lists through all modules for testing.
192 | for (var i = 0; i < modules.length; i++) {
193 | // Check if the current module is the one.
194 | if (modules[i].name === data.module) {
195 | // Splits out the module number of the module with the same name.
196 | var idnr = modules[i].data.identifier.split("_");
197 | // Check if the idnum is an array or not
198 | if (Array.isArray(data.idnum)) {
199 | // If it's an array, check what numbers are in it.
200 | var idnumber = data.idnum.find(function(element) {
201 | // Number of the module is found in the array.
202 | return element == idnr[1];
203 | });
204 | // If idnum is not an array.
205 | } else {
206 | // Set the module id to hide.
207 | var idnumber = data.idnum;
208 | }
209 | // Checks if idnum is set in config.js. If it is, it only hides that modules with those numbers and name, if not hides all modules with the same name.
210 | if (idnr[1] == idnumber || data.idnum == null) {
211 | // Check if the module is hidden.
212 | if (modules[i].hidden) {
213 | // Check if there is a "showURL" defined.
214 | if (data.showUrl != null) {
215 | // Visiting the show URL.
216 | fetch(data.showUrl);
217 | // Prints the visited hideURL.
218 | console.log("Visiting show URL: "+data.showUrl);
219 | }
220 | // Shows the module.
221 | modules[i].show(self.config.animationSpeed, 0, {force: self.config.allowForce});
222 | // Sets the defined symbol for shown module.
223 | if (typeof data.symbol !== 'undefined') {
224 | symbol.className = faclassName + data.symbol;
225 | // Set the size if it's set.
226 | if (data.size) {
227 | symbol.className += " fa-" + data.size;
228 | symbol.className += data.size == 1 ? "g" : "x";
229 | }
230 | // Sets the defined image for shown module.
231 | } else if (typeof data.img !== 'undefined') {
232 | image.className = "modulebar-picture";
233 | image.src = data.img;
234 | }
235 | // Sets the defined text for shown module.
236 | if (typeof data.text !== 'undefined') {
237 | text.innerHTML = data.text;
238 | }
239 | // Prints in the console what just happened (adding the ID).
240 | console.log("Showing "+modules[i].name+" ID: "+idnr[1]);
241 | } else {
242 | // Hides the module.
243 | modules[i].hide(self.config.animationSpeed, 0, {force: self.config.allowForce});
244 | // Sets the defined symbol for hidden module.
245 | if (typeof data.symbol2 !== 'undefined') {
246 | symbol.className = faclassName + data.symbol2;
247 | // Set the size if it's set.
248 | if (data.size) {
249 | symbol.className += " fa-" + data.size;
250 | symbol.className += data.size == 1 ? "g" : "x";
251 | }
252 | // Sets the defined image for hidden module.
253 | } else if (typeof data.img2 !== 'undefined') {
254 | image.className = "modulebar-picture";
255 | image.src = data.img2;
256 | }
257 | // Sets the defined text for hidden module.
258 | if (typeof data.text2 !== 'undefined') {
259 | text.innerHTML = data.text2;
260 | }
261 | // Prints in the console what just happened (adding the ID).
262 | console.log("Hiding "+modules[i].name+" ID: "+idnr[1]);
263 | // Check if there is a "hideURL" defined.
264 | if (data.hideUrl != null) {
265 | // Visiting the the URL.
266 | fetch(data.hideUrl);
267 | // Prints the visited hideURL.
268 | console.log("Visiting hide URL: "+data.hideUrl);
269 | }
270 | }
271 | }
272 | }
273 | }
274 | }
275 | });
276 | // Fixes the aligning.
277 | item.style.flexDirection = {
278 | "right" : "row-reverse",
279 | "left" : "row",
280 | "top" : "column",
281 | "bottom" : "column-reverse"
282 | }[placement];
283 | // Sets the border around the symbol/picture/text to black.
284 | if (!self.config.showBorder) {
285 | item.style.borderColor = "black";
286 | }
287 | // Adds the Font-Awesome symbol if specified.
288 | if (data.symbol) {
289 | var symbol = document.createElement("span");
290 | symbol.className = faclassName + data.symbol;
291 | // Sets the size on the symbol if specified.
292 | if (data.size) {
293 | symbol.className += " fa-" + data.size;
294 | symbol.className += data.size == 1 ? "g" : "x";
295 | }
296 | // Align the symbol with a margin.
297 | if (data.text && placement === "left") {
298 | symbol.style.marginRight = "4px";
299 | }
300 | // Adds the symbol to the item.
301 | item.appendChild(symbol);
302 | // Adds a picture if specified.
303 | } else if (data.img) {
304 | var image = document.createElement("img");
305 | image.className = "modulebar-picture";
306 | image.src = data.img;
307 | // Sets the size of the picture if specified.
308 | if (data.width) image.width = data.width;
309 | if (data.height) image.height = data.height;
310 | // Align the picture with a margin.
311 | if (data.text && placement === "left") {
312 | image.style.marginRight = "4px";
313 | }
314 | // Adds the picture to the item.
315 | item.appendChild(image);
316 | }
317 | // Adds the text if specified.
318 | if (data.text) {
319 | var text = document.createElement("span");
320 | text.className = "modulebar-text";
321 | text.innerHTML = data.text;
322 | // Align the text with a margin.
323 | if ((data.symbol || data.img) && placement === "right") {
324 | text.style.marginRight = "4px";
325 | }
326 | // Adds the text to the item.
327 | item.appendChild(text);
328 | }
329 | // All done. :)
330 | return item;
331 | }
332 | });
333 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MMM-Modulebar
2 |
3 | This an extension for the [MagicMirror²](https://magicmirror.builders/).
4 |
5 | This Module adds a touch menu to hide / show the defined (in config.js) modules.
6 |
7 | ### Screen shots
8 |
9 | Module with symbols only in row mode:
10 |
11 | 
12 |
13 | Module with symbols only in column mode:
14 |
15 | 
16 |
17 | Module with symbols and text in column mode:
18 |
19 | 
20 |
21 | Module with symbols and text in row mode:
22 |
23 | 
24 |
25 | This is my own mirrors view (Bottom Bar) using some addition in the custom.css [see below](#custom-css)
26 |
27 | 
28 |
29 | ### Installation
30 |
31 | In your terminal, go to your MagicMirror's Module folder:
32 | ````
33 | cd ~/MagicMirror/modules
34 | ````
35 |
36 | Clone this repository:
37 | ````
38 | git clone https://github.com/Snille/MMM-Modulebar.git
39 | ````
40 |
41 | ### Using the module
42 |
43 | To use this module, add it to the modules array in the `config/config.js` file:
44 | ````javascript
45 | modules: [
46 | {
47 | module: "MMM-Modulebar",
48 | position: "bottom_bar", // This can be any of the regions.
49 | header: "Modules", // Optional
50 | classes: "default everyone", // Optional
51 | config: {
52 | // See 'Configuration options' for more information.
53 | }
54 | }
55 | ]
56 | ````
57 |
58 | ### Configuration options
59 |
60 | The following properties can be configured:
61 |
62 | | Option | Default | Description
63 | | ------------------ | ------- | -----------
64 | | `allowForce` | `false` | Allow the module to force modules to be shown (if hidden and locked by ex. profile-switcher).
**Possible values:** `true` or `false`
65 | | `showBorder` | `true` | Determines if the border around the buttons should be shown.
**Possible values:** `true` or `false`
66 | | `minWidth` | `0px` | The minimum width for all the buttons.
**Possible values:** `css length`
67 | | `minHeight` | `0px` | The minimum height for all the buttons.
**Possible values:** `css length`
68 | | `picturePlacement` | `left` | The location of the symbol or image relative to the text.
**Possible values:** `left`, `right`, `top` or `bottom`
69 | | `direction` | `row` | The direction of the menu.
**Possible values:** `row`, `column`, `row-reverse` or `column-reverse`
70 | | `animationSpeed` | `1000` | The speed of the hide and show animation (lower is faster) **Possible values:** 0-10000.
71 | | `zindex` | `1000` | Z-Index value for the hide all plane (this is preferably a high value for the black plane to show above everything else. **Possible values:** 0-10000.
72 | | `visability` | `0.4` | Visibility of the "unhide all button" (if defined) when all is hidden **Possible values:** 0.0 - 1.0.
73 | | `buttons` | Clock example button | All the different buttons in the menu.
**Possible values:** a button configuration, see [Configuring Buttons](#configuring-buttons)
74 |
75 | ### Configuring Buttons
76 |
77 | Buttons have to be placed in `buttons` in the `config`. A button contains a unique number as a key and a set of options in the object (`{}`).
78 |
79 | Each button starts with it's own unique number (ex. "1"), then add the options needed.
80 |
81 | | Option | Description
82 | | -------- | -----------
83 | | `module` | A module name. **Note:** if set to `all` , all of the modules will be hidden or shown. **Possible values:** `all`,`clock`,`currentweather`,`MMM-xxx`
84 | | `text` | A string to display in the button.
**Note:** if no value is set no text will be displayed. **Possible values:** `string`
85 | | `text2` | A string to display in the button when module is hidden.
**Note:** if no value is set no text will be displayed. **Possible values:** `string`
86 | | `symbol` | A symbol to display in the button.
**Note:** if no value is set no symbol will be displayed. **Possible values:** See [Font Awesome](http://fontawesome.io/icons) website
87 | | `symbol2`| A secondary symbol to display in the button when module is hidden.
**Note:** if no value is set no symbol will be displayed. **Possible values:** See [Font Awesome](http://fontawesome.io/icons) website
88 | | `img` | An image to display in the button.
**Note:** it will only be displayed if no symbol is set. **Possible values:** A path to an image (an url or local path)
89 | | `img2` | A secondary image to display in the button when module is hidden.
**Note:** it will only be displayed if no symbol is set. **Possible values:** A path to an image (an url or local path)
90 | | `size` | The size of the symbol.
**Note:** will only have effect on a symbol. **Default value:** `1` **Possible values:** `1`, `2`, `3`, `4` or `5`
91 | | `width` | The width of the image.
**Note:** will only have effect on an image. **Possible values:** `number`
92 | | `height` | The height of the image.
**Note:** will only have effect on an image. **Possible values:** `number`
93 | | `idnum` | The unique module number if you have more then one of the same module (and want to manipulate only one of the modules), you can find the module numbers if you inspect the code and then check the "console" (in a normal web browser) when showing and hiding the module(s) (without setting this number) with the button.
**Possible values:** `number`
Or if you use multiple instances of the same module many times and you don't want to hide all or just one with one button, you can specify the numbers of the modules (of the same type) you want to hide in an array.
**Number Array** `[3,6,2,7]`
94 | | `showUrl`| If you have something you want to "do" via visiting a link before showing the module, this is where to put the link, it will be visited (ignoring the result) before showing the module..
**Possible values:** `url`
95 | | `hideUrl`| If you have something you want to "do" via visiting a link after hiding the module, this is where to put the link, it will be visited (ignoring the result) after hiding the module..
**Possible values:** `url`
96 | | `gotoUrl`| Use this if want to navigate away to another page. The special value "back" will reload a previous page. This option should be used with a browser and want to exit MM.
**Possible values:** `url` or `back`
97 |
98 | An example:
99 |
100 | ````javascript
101 | buttons: {
102 | // A number (unique for each button) lowest number will be displayed first...
103 | "1": {
104 | // This button hides everything and uses two symbols.
105 | module: "all",
106 | symbol: "toggle-on",
107 | symbol2: "toggle-off",
108 | },
109 | "2": {
110 | // This is a button with text that changes and a symbol that changes.
111 | // The EXACT module name (case sensitive)
112 | module: "currentweather",
113 | text: "Current Weather on",
114 | text2: "Current Weather off",
115 | symbol: "fas fa-sun",
116 | symbol2: "far fa-sun",
117 | },
118 | "4": {
119 | // A button with only a symbol and an idnum to target a specific weatherforecast module.
120 | module: "weatherforecast",
121 | symbol: "sun-o",
122 | // The ID-number of the "weatherforecast" module (when you have more then one).
123 | idnum: 8,
124 | },
125 | "6": {
126 | // A button with only a symbol and an idnum to target another specific weatherforecast module.
127 | module: "weatherforecast",
128 | symbol: "star-o",
129 | // The ID-number of the other "weatherforecast" module (when you have more then one).
130 | idnum: 6,
131 | },
132 | "8": {
133 | // A button with text and a changing symbol.
134 | module: "clock",
135 | text: "Clock",
136 | symbol: "bell",
137 | symbol2: "bell-slash",
138 | },
139 | "10": {
140 | // A button to show and hide for example a [MMM-MotionEye](https://github.com/CatoAntonsen/MMM-MotionEye) module.
141 | module: "MMM-MotionEye",
142 | idnum: 7,
143 | text: "CAM1",
144 | showUrl: "http://MagicMirrorIP:8080/motioneye/1",
145 | hideUrl: "http://MagicMirrorIP:8080/motioneye/hide/1"
146 | },
147 | }
148 | ````
149 |
150 | ### Custom-CSS
151 |
152 | Here is my CSS settings for the module that I have added to my custom.css to give it the extra special look. :)
153 |
154 | ```
155 | /* MMM-Modulebar ------------------------------------*/
156 | .modulebar-button {
157 | margin: 1px;
158 | padding: 1px 1px;
159 | border: 2px solid #fff;
160 | background-color: #fff;
161 | color: #000;
162 | border-radius: 0px;
163 | border-radius: 50%;
164 | width: 60px;
165 | height: 60px;
166 | }
167 | .modulebar-picture {
168 | margin: 0px 0px;
169 | border-radius: 50%;
170 | }
171 | .modulebar-menu {
172 | align-items: flex-start;
173 | }
174 | /*****************************************************/
175 | ```
176 |
177 |
178 | ### Notes
179 | * **Important:** unfortunately positioning this module as full screen will result in the menu floating top left. I currently do not know how to fix this but will look into it. If you know how don't hesitate to either write me or send me a pull request!
180 | * If the image is an local path and it does not show. Try different ways to write the local path. If this still does not work then try putting the image in a folder in your MagicMirror folder and use as local path `folder name/image name`.
181 | * If only height or width is set for an image the other size will scale to maintain it the image it's original aspect ratio.
182 | * Module name is case sensitive.
183 | * If both the `text` and `symbol` aren't set for a button then the button won't contain anything, but still show the border.
184 | * The symbols are all form the [Font Awesome](http://fontawesome.io/icons) website.
185 | * The text may contain HTML tags and will be displayed as HTML.
186 |
187 |
188 | ### The MIT License (MIT)
189 |
190 | Copyright (c) 2017 Erik Pettersson
191 |
192 | Permission is hereby granted, free of charge, to any person obtaining a copy
193 | of this software and associated documentation files (the "Software"), to deal
194 | in the Software without restriction, including without limitation the rights
195 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
196 | copies of the Software, and to permit persons to whom the Software is
197 | furnished to do so, subject to the following conditions:
198 |
199 | The above copyright notice and this permission notice shall be included in all
200 | copies or substantial portions of the Software.
201 |
202 | **THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
203 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
204 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
205 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
206 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
207 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
208 | SOFTWARE.**
209 |
210 |
--------------------------------------------------------------------------------
/js/jquery.js:
--------------------------------------------------------------------------------
1 | /*! jQuery v2.1.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
2 | !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m=a.document,n="2.1.0",o=function(a,b){return new o.fn.init(a,b)},p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};o.fn=o.prototype={jquery:n,constructor:o,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=o.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return o.each(this,a,b)},map:function(a){return this.pushStack(o.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},o.extend=o.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||o.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(o.isPlainObject(d)||(e=o.isArray(d)))?(e?(e=!1,f=c&&o.isArray(c)?c:[]):f=c&&o.isPlainObject(c)?c:{},g[b]=o.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},o.extend({expando:"jQuery"+(n+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===o.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isPlainObject:function(a){if("object"!==o.type(a)||a.nodeType||o.isWindow(a))return!1;try{if(a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}return!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=o.trim(a),a&&(1===a.indexOf("use strict")?(b=m.createElement("script"),b.text=a,m.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":k.call(a)},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?o.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),o.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||o.guid++,f):void 0},now:Date.now,support:l}),o.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=o.type(a);return"function"===c||o.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="