Moon Phase
-
The moon phase mod shows a different icon for each moon phase in form of a command chain button and adds age, progress, and name of the moon phase to the button title (hover). Add it to any toolbar, the moon phase updates when first loaded and after each click on the button. This is a Javascript modification, basic installation instructions for Javascripts files available from here: official guide. Follow additional instructions below.
moon phase icon New Moon Waxing Crescent First Quarter Waxing Gibbous Full Moon Waning Gibbous Last Quarter Waning Crescent
Start by creating a command chain in
vivaldi://settings/qc
, name itMoon Phase
and add any command(s) you like. If you don’t know what to add yet, leave the default delay. Afterwards open the Toolbar Editor, select Command Chains from the dropdown and drag the button to the toolbar of your choice.Create an SVG file and paste the code below. This file has to be loaded in
vivaldi://settings/themes/
⇒ themes ⇒ editor ⇒ icons in your currently active icon theme as replacement for the default Command Chain icon for the Moon Phase button. Alternatively you can load the file directly from Github.moon-phase.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg viewBox="-14 -14 28 28" width="28" height="28" xmlns="http://www.w3.org/2000/svg" > <g opacity="1"> <defs> <clipPath id="vm-mp-cut"> <rect id="vm-mp-mod" x="-5" y="-5" width="10" height="0" transform="rotate(0)" /> </clipPath> </defs> <circle cx="0" cy="0" r="7" fill="none" stroke="currentColor" stroke-width="1.5" /> <circle cx="0" cy="0" r="5" clip-path="url(#vm-mp-cut)" /> </g> </svg>
Then add the Javascript file to the application as usual. The mod uses the command chain identifier to load the current moon phase, therefore you need to inspect the UI, copy the ID for your own button out of the HTML and replace it with the existing ID in the file. As a second step add your latitude, which will adjust the perspective of the moon icon.
Finally restart Vivaldi and the mod should work as expected
moon-phase.js
// Moon Phase // version 2024.11.0 // https://forum.vivaldi.net/post/461432 // Displays the current moon phase as command chain button. Download the // moon-phase.svg file and load it in theme settings. Moon phase calculation // adapted from https://minkukel.com/en/various/calculating-moon-phase/ (async function moonPhase() { "use strict"; // EDIT START // choose a digit from 0 to 4 approximating your latitude // north[0] northern[1] equator[2] southern[3] south[4] const approx = 0; // alternatively input your exact latitude in degrees (between 90 and -90) const latitude = 48.3; // command chain identifier (inspect UI and input your own) const command = "COMMAND_cln9yq818001n2v649xyaiird"; // EDIT END const lunation = 29.53058770576; const lunartime = lunation * 86400; const newmoon = 947182440; const moon = { phases: [ ["New Moon", 1], ["Waxing Crescent", 6.38264692644], ["First Quarter", 8.38264692644], ["Waxing Gibbous", 13.76529385288], ["Full Moon", 15.76529385288], ["Waning Gibbous", 21.14794077932], ["Last Quarter", 23.14794077932], ["Waning Crescent", 28.53058770576], ["", lunation], ], illum: [ [-5, 0], [-5, 3], [-5, 5], [-5, 7], [-5, 10], [-2, 7], [0, 5], [2, 3], ], lat: [90, 45, 0, -45, -90], phase: () => { const unixtime = Math.floor(Date.now() / 1000); const progress = ((unixtime - newmoon) % lunartime) / lunartime; const age = progress * lunation; for (let i = 0; i < moon.phases.length; i++) { if (age <= moon.phases[i][1]) { if (i === 8) i = 0; return { name: moon.phases[i][0], age: Math.trunc(age), progress: Math.trunc(progress * 100), coordinate: moon.illum[i][0], range: moon.illum[i][1], angle: typeof latitude === "number" ? latitude : moon.lat[approx], }; } } }, }; function moonwatch(btn) { const get = moon.phase(); const number = get.age === 1 ? "day" : "days"; btn.title = `${get.name}\n${get.age} ${number} \u{21ba} ${get.progress}%`; const mod = btn.querySelector("#vm-mp-mod"); if (mod) { mod.setAttribute("y", get.coordinate); mod.setAttribute("height", get.range); mod.setAttribute("transform", `rotate(${get.angle})`); btn.classList.add("vm-mp"); } } function conflate(el) { const btn = el.getElementsByTagName("BUTTON"); console.info(btn.length); for (let i = 0; i < btn.length; i++) { if (btn[i].name === command && !btn[i].classList.contains("vm-mp")) { const send = () => moonwatch(btn[i]); send(); btn[i].addEventListener("click", send); } } } const wait = () => { return new Promise((resolve) => { const check = document.getElementById("browser"); if (check) return resolve(check); else { const startup = new MutationObserver(() => { const el = document.getElementById("browser"); if (el) { startup.disconnect(); resolve(el); } }); startup.observe(document.body, { childList: true, subtree: true }); } }); }; const lazy = (el, observer) => { observer.observe(el, { childList: true, subtree: true }); }; await wait().then((browser) => { const lazy_obs = new MutationObserver(() => { lazy_obs.disconnect(); setTimeout(() => { conflate(browser); lazy(browser, lazy_obs); }, 666); }); conflate(browser); lazy(browser, lazy_obs); }); })();
History
- 2021-03-26 Release (full moon
)
- 2021-03-27 Clean up code and svg icons.
- 2021-03-28 Improved moon phase calculation.
- 2021-03-29 Switch to J2000 (waning gibbous moon
)
- 2021-05-04 Add display for southern hemisphere (last quarter moon
)
- 2021-10-09 New SVG icons, remove CSS file.
- 2022.4.0 Cleanup
- 2022.12.0 Rewrite for custom buttons feature
- 2023.2.0 Only one SVG file needed in new Vivaldi versions
- 2023.9.0 New version uses a native command chain button
- 2024.4.0 Simplify phase names
- 2024.6.0 Age (days) in the tooltip alongside with progress and name
- 2024.6.2 Latitude setting
- 2024.10.0 Handle error when icon loads slowly on first run
- 2024.11.0 Move to mutation observer
- 2021-03-26 Release (full moon
-
Replying to my own topic, sad times ^^ Anyway, I cleaned up the code, but especially the svgs have improved. They look and behave like Vivaldi’s native icons now. The second path is transparent and shows the panel background, which has adjustable opacity since the latest release. The moon phase icon also became a little smaller to better harmonize with the other buttons. What this means is we could potentially run a background with a tiny moon at the right place, which would then shine through our icon o.O
-
Another update. I found a better and more accurate way to calculate and display the moon phases. Additionally the progress of the current lunar cycle will be shown as a percentage.
New script adapted from this excellent article ☛ https://minkukel.com/en/various/calculating-moon-phase/. The reference point for our calculation is the first new moon in 2000. There was no need to make the mod work for any point in the past. Should you find an issue, please let me know.
-
Why do you need to know the moon phases?
Are you, or have you ever been, a member of the witch and/or warlock councils?
-
@luetage This is a nice project, I may go back to the clock though. I installed your mods, and I wanted to ask you why did you hide the minimize button?
-
-
@Pathduck This mod could be also useful in case of lycantrophy :3
-
/* window buttons */ .window-buttongroup button.window-maximize, .window-buttongroup button.window-minimize { display: none; } .linux #tabs-container:not(.none).top { padding-right: 40px; }
This is in the GitHub repo, uimods.css
-
@code3 Yeah, uimod.css and uimod.js are my backup files, use them at your own risk, sometimes there are breaking changes in there. The reason I remove maximize and minimize buttons is I’m on Gnome desktop environment and by default hide these buttons in all native windows too. I use keyboard shortcuts to minimize and maximize.
-
@luetage Ok, oops. I will take your backup files out. Thanks!
-
@Pathduck said in Project History Moon:
Why do you need to know the moon phases?
@luetage lives near the ocean coast and high and low tides are caused by the Moon.@luetage is surfer!
-
@code3 The code is fine most of the time, after all it’s a backup, not a working version. But it makes more sense to take the mods you want and build your own version. The javascript backup file can help you with that, since it shows how to combine mods which share the prototype appendchild approach.
-
@luetage Yes, it didn’t break anything. I discovered an excellent project from @lonm to help with combining the files and adding them to Vivaldi; it also supports custom colors and page actions. I have been building the config.Jason with various mods - history clock, themes import export, auto save sessions, and some css styles. Thank you for sharing your mods! I hope to share some soon, I am working on a floating tab bar right now, but I am still a beginner at this.
-
@Stardust said in Project History Moon:
@Pathduck said in Project History Moon:
Why do you need to know the moon phases?
@luetage lives near the ocean coast and high and low tides are caused by the Moon.@luetage is surfer!
Are you?
-
@code3 Does listening to Beach Boys count? Then yes, I am a surfer.
But seriously, I don’t like non‐functioning clock‐faces. The moon phase icon is an alternative, slower timekeeper and it complements the existing clock in the toolbar.
-
@code3 I am an internet surfer! You?
-
@luetage Alright, good job on your work with the moonphases, it looks like a lot of work. Personally, I prefer the History Clock Mod you made earlier because it seems like a better icon to represent "history." Maybe I will try putting the history moon in the status bar.
-
@luetage Here is my adaption: the moon is in the status bar, and replaces the normal icon for Break Mode. If anyone wants to use this, remember to use history-moon.css as well but delete the first part that hides the history button.
It seems to be working correctly, thanks to luetage's moon math!
@luetage Also, do you know if the history clock (not moon) is broken in snapshot?// Moon Status // https://forum.vivaldi.net/topic/58821/project-history-moon/ // Puts the moon in the status bar as the , with the correct phase. // Depends on the installation of additional CSS code (history-moon.css). Please remove the first rule of the history-moon.css file. It looks like this: /* #switch button.history svg:not(.history-moon) { display: none; } */ // Moon phase calculation adapted from https://minkukel.com/en/various/calculating-moon-phase/ // This is an adaption of the history clock mod from luetage. The adaption is from @code3, but nearly all of this code and all of the work is from @luetage. // document.querySelector('[title="Take a Break"]').classList.add(".warlock-clock") should be executed upon loading of the browser. function initMod(){ if(document.querySelector("#browser")){ // History moon document.querySelector('[title="Take a Break"]').classList.add("warlock-clock"); } else { setTimeout(initMod, 500); } } initMod(); { let moon = { phases: [['New', 0, 1], ['Waxing Crescent', 1, 6.38264692644], ['First Quarter', 6.38264692644, 8.38264692644], ['Waxing Gibbous', 8.38264692644, 13.76529385288], ['Full', 13.76529385288, 15.76529385288], ['Waning Gibbous', 15.76529385288, 21.14794077932], ['Last Quarter', 21.14794077932, 23.14794077932], ['Waning Crescent', 23.14794077932, 28.53058770576], ['end', 28.53058770576, 29.53058770576]], phase: () => { const lunarcycle = 29.53058770576; const lunartime = lunarcycle * 86400; const unixtime = Math.round(Date.now()/1000); const newmoon = 947182440; const diff = unixtime - newmoon; const mod = diff % lunartime; const frac = mod / lunartime; const age = frac * lunarcycle; for (let i = 0; i < 9; i++) { if (age >= moon.phases[i][1] && age <= moon.phases[i][2]) { if (i === 8) i = 0; return {phase: i, name: moon.phases[i][0], progress: Math.trunc(frac * 100)}; } } } } let historymoon = phase => { const hbtn = document.querySelector('[title="Take a Break"]') || document.querySelector(".warlock-clock"); hbtn.innerHTML = `<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 216.2 216.2" class="history-moon"><path class="history-moon-${phase}" d="" fill-rule="evenodd"></path></svg>`; } let moonwatch = (mutations, phase) => { mutations.forEach(mutation => { if (mutation.attributeName === 'class') historymoon(phase); }) } let appendChild = Element.prototype.appendChild; Element.prototype.appendChild = function () { if (this.tagName === 'BUTTON') { setTimeout(function() { if (this == document.querySelector('[title="Take a Break"]') || this == document.querySelector(".warlock-clock")) { const p = moon.phase(); historymoon(p.phase); this.title += "! Get Outside!" + '\n' + "Tonight's Moon is a " + p.name + " " + p.progress + '%'; const mw = (mutations) => moonwatch(mutations, p.phase); const resist = new MutationObserver(mw); resist.observe(this, {attributes: true}); } }.bind(this, arguments[0])); } return appendChild.apply(this, arguments); } }
-
@code3 Yes, it’s broken for two reasons: First of all the styles for the clock hands have been removed, which were an anchor point for the calculated angles. Secondly the redesign of the panel icons introduced the automatic replacement of the svg/s, whenever an icon is being selected or deselected.
-
@luetage said in Project History Moon:
First of all the styles for the clock hands have been removed, which were an anchor point for the calculated angles
Let me see if I can get the styles for the clock hands.
@luetage said in Project History Moon:
Secondly the redesign of the panel icons introduced the automatic replacement of the svg/s, whenever an icon is being selected or deselected.
Couldn’t this be solved by replacing the SVGs yourself on click?