Forum customization
-
As an alternative to the above, if you want a slight delay before the tooltip appears, use the following:
/* Change FontAwesome "+" to FontAwesome expand/contract arrows */ .taskbar-composer .fa-plus:before {content: "\f065" !important;} .taskbar-composer.active .fa-plus:before {content: "\f066" !important;} /* Make a tooltip */ .taskbar-composer::after { position:absolute; text-align:center; top: -4ex; left: 0; background:cornsilk; box-shadow: .3em .3em .3em rgba(0,0,0,0.2); content: ""; opacity:0; transition:opacity 4s cubic-bezier(0.95, -0.25, 0.05, 1.25); } .taskbar-composer:hover::after { content: "Restore\A composer"; opacity:0.8; padding: 0.1em 0.4em; } .taskbar-composer.active:hover::after { content: "Hide\A composer"; }
-
@Isildur That's what I really like about Vivaldi and this community. When I ask for something, I often get something way better than what I asked for! That's perfect if you can just get it moved into wherever the production version is.
I don't know anything about CSS beyond what the initials stand for, so I probably won't apply the patch myself.
-
@josephj11 said in Forum customization:
@Isildur That's what I really like about Vivaldi and this community. When I ask for something, I often get something way better than what I asked for! That's perfect if you can just get it moved into wherever the production version is.
I don't know anything about CSS beyond what the initials stand for, so I probably won't apply the patch myself.
I don't have authority to move it into production, but maybe someone with authority will see the above stuff or your post in the suggestion thread.
CSS is the formatting language that applies styling to web pages. You can override a site's own styling for yourself by setting your own style rules to override any site's default styles. (It can always be disabled if it's not to your taste.) The easiest way is probably to use an extension like Stylus, as mentioned at the top of this thread.
(For years, the most frequently recommended extension for this sort of thing was the one named "Stylish", but there are concerns now about that extension collecting user data now in partnership with SimilarWeb, a "digital market intelligence platform" -- it could be that it's just harmless, properly anonymized data, but it understandably makes many uneasy, particularly because the new privacy policy was not clear on what data would be collected.).
In such extensions, you can select a new website you want styling to apply to, and paste in CSS code like the stuff I provided.
(Or you can follow the instructions I give at the beginning of this thread to make your own simple browser extension that applies to just one site. It's not as complicated as one might think.)
You don't need to know CSS to do any of the above, but if you're ever interested, CSS is generally just declaring what you want to effect, and then putting in curly brackets the effects.
Targeting an element type, like an image or paragraph
element-type { some-property: setting; some-property: setting; some-property: setting; }
Targeting a class name, with a period. Classes can be assigned in the HTML to any element, e.g. <img class="blah">
.element-class-name { some-property: setting; some-property: setting; some-property: setting; }
Whereas IDs are supposed to be unique to one element instance
#element-ID{ some-property: setting; some-property: setting; some-property: setting; }
Characteristics can be grouped, e.g.
img.x#y { some-property: setting; }
means apply that setting to that property for elements like the image element <img class="x" id="y">
And if you chain with spaces, it means your targeting things on the right that exist within things on the left. e.g.
p.x #y { some-property: setting; }
applies to a an element like the span in
<p class="x">text<span id="y">text</span>text</p>
There are more complicated aspects of CSS, but a lot of CSS is just stuff like
.class-X img{ some-property: setting; }
to target image elements that are inside elements with class "class-X".
One doesn't have to fully understand CSS to use copy it into an extension like Stylus. Unlike javascript, CSS is usually pretty harmless as it doesn't contain scripts, so it's not generally going to do anything worse than mess up your display of something if it's written wrong. (In which case you just disable it.) The only possible way that user css could be abused, that I could think of, is that if someone uses an off-site background image as a tracker, or if a browser's CSS parser or extension like Stylus has some security flaw discovered. So just look out for URLs in CSS or weird characters. If CSS looks like the stuff above, it's generally safe.
-
I gave this a go. Generally speaking I like the look of these forums, just opted to go for a little less contrast and tried to remove all distractions, such as tooltips and the data-leak notice. My theme was well underway when I found this thread, but boy was it helpful, especially the font-icon idea/solution.
The only really new thing added is a bit of javascript for hiding/showing the top menu on scroll, for better readability, because the Vivaldi forum can't be exactly called economical concerning vertical space. This is also why I packed it as chrome extension.
Try it if you like: Vivaldi Gray-Pink
-
Hey hey thanks Luetage! Looks great! I love the way the top menu hides on scroll
-
A little low-contrast for my taste, but I like the hiding the of the menu (similar to what the forum otherwise does only if initial page load happened in a window below 992px wide, and the window is viewed at 768px wide or greater.)
A CAUTION TO OTHERS:
The script in the extension .crx luetage posted is fine (and luetage has been a helpful Vivaldi Community member for a couple of years already, so I didn't expect anything malicious), but just as a general practice, people should check the files of non-Chrome-Web-Store extensions before installing them. One should check not just ".js" files but any file listed in the manifest.json line
"js": [ "FILNAME1", "FILENAME2"... ]
(Even extensions in the Chrome Web Store should be installed with some caution. Google apparently does some (automated?) analysis of extensions, but sometimes a bad one can slip through.)
Also, one cannot always rely on other people vouching for a particular file link, as files can be changed on the server. (Unless it's hosted at a place with version control like github.com, so people can vouch for a particular version.)
-
Yeah, that's a good practice, I'm using crx viewer myself since back from the new Opera days. Although I'm too lazy to check everything out for extensions from the store before installing them, can't be bothered.
-
Adding a time stamp to the bottom of edited posts:
There already is a little pencil icon after the post date of any post that has been modified, and if you hover it will give an approximate last-edit time, but if you want a more exact timestamp at the bottom of modified posts, we can take advantage of a hidden META tag that posts have. The raw data is a timestamp like "2017-06-08T16:55:58.648Z", so the following CSSS uses ::before and ::after psuedo elements and hidden overflows to isolate the date and time to make it more readable. If you want it at the top of the post, take out the "position:absolute; bottom:0;".
[component='topic'] [component='post'] meta[itemprop="dateModified"][content^="2"] { display: block; position:absolute; bottom:0; font-family:monospace; opacity:0.5; } [component='topic'] [component='post'] meta[itemprop="dateModified"][content^="2"]::before { display: inline-block; overflow:hidden; white-space:nowrap; width:31ch; content: 'Last Modified (UTC): ' attr(content); } [component='topic'] [component='post'] meta[itemprop="dateModified"][content^="2"]::after { display: inline-block; overflow:hidden; white-space:nowrap; width:8ch; text-indent:-11ch; margin-left:1ch; content: attr(content); }
Note: The time stamp shown may not be updated right after you edit a post yourself; you may have to refresh the page.
-
These are the javascript mods I'm using right now. The first one is for hiding the topmenu on scroll, the second one fixes the link (on profile) to the bookmarks page (currently named "favourites" and dysfunctional). I was surprised how useful bookmarks are once you have easy access to them.
var scp = 0; window.addEventListener('scroll', function(){ if (scp > window.scrollY) { document.getElementById("header-menu").style.top = "0px"; } else if (window.scrollY <= 51) { document.getElementById("header-menu").style.top = "0px"; } else if (window.scrollY > 51) { document.getElementById("header-menu").style.top = "-51px"; } scp = window.scrollY; }); document.addEventListener('click', bookmarked); function bookmarked(e) { var favourites = document.querySelector(".dropdown-menu.dropdown-menu-right li:nth-of-type(12) a"); favourites.innerHTML = "Bookmarked"; favourites.href = "/user/USERNAME/bookmarks"; };
-
@luetage said in Forum customization:
the second one fixes the link (on profile) to the bookmarks page (currently named "watched" and dysfunctional). I was surprised how useful bookmarks are once you have easy access to them.
@luetage I think you mean the dysfunctional one named "favorites", which is the one your code replaces. (The "Watched" one works.)
Huh, I hadn't even noticed the intended bookmark functionality for a long time. Good idea making the function get called on click, since that way the link is ready every time the user drops down the menu, even if they navigated to the profile page via AJAX smooth navigation.
For others:
Note that where luetage wrote USERNAME, you need to replace that with yours, but the username must be lowercased, and any periods in the username will need to replaces those with dashes. if you don't want to hardcode in the username, I've edited luetage's code slightly to fetche it from the page:
document.addEventListener('click', bookmarked); function bookmarked(e) { var favourites = document.querySelector(".dropdown-menu.dropdown-menu-right li:nth-of-type(12) a"); var username = document.querySelector('#user-control-list [component="header/username"]').innerHTML.toLowerCase().replace(/\./g, '-');; favourites.innerHTML = "Bookmarked"; favourites.href = "/user/" + username + "/bookmarks"; };
Click a post's bottom-right menu button, and click "Bookmark ".
Reach the Bookmarks page from your profile page's right-hand menu, using either the code that luetage posted (replacing USERNAME with your own username in all-lowercase and with any periods replaced with dashes) or my slightly edited version of it above. Or you can set a browser bookmark to it athttps://forum.vivaldi.net/user/[your lowercased and dashed username]/bookmarks
-
Yeah, it's replacing "favourites" not "watched" obviously, I fixed that in my post now, thanks.
And nice, good idea fetching the username, I didn't think about that, will use it in the extension. The AJAX navigation is giving me big headaches by the way, I wanted to do some other mods but it's sometimes simply too painful working around it. I tried to listen for a hashchange initially, but I didn't get it to work reliably.
-
@luetage said in Forum customization:
The AJAX navigation is giving me big headaches by the way, I wanted to do some other mods but it's sometimes simply too painful working around it. I tried to listen for a hashchange initially, but I didn't get it to work reliably.
Hmm, one possibility is you could define your own onpushstate function and set some delayed code to hopefully execute after the AJAX, something like
(function(history){ var pushState = history.pushState; history.pushState = function(state) { if (typeof history.onpushstate == "function") { history.onpushstate({state: state}); } return pushState.apply(history, arguments); } })(window.history); window.onpopstate = history.onpushstate = function(e) { alert('test (this alert box will pause the thread, just to showing that AJAX stuff is not loaded yet'); setTimeout(function(){ /* stuff to do after a delay for the AJAX stuff to be loaded */ }, 1000); };
(modified from https://stackoverflow.com/a/4585031/8067821 )
See also here and here for variations on registrering the pushState.
-
I see what this is trying to do, but I can't get it to work after all it seems. The problem is the code only triggers on going back or forth in history, it doesn't do anything when just the AJAX navigation is being used. Maybe I'm using it wrong though.
-
I made another javascript mod for the forum extension. Recently someone found out that every member can set a signature by visiting the hidden node.bb settings (https://forum.vivaldi.net/user/username/edit). User signatures can be informative and helpful, but they do also waste a lot of vertical space, and, if the member is a regular poster, you might unwillingly read the sig multiple times a day, and I wanted to do something about it.
window.onload = sig; document.addEventListener('click', sig); function sig() { setTimeout(sig, 500); var signatures = document.querySelectorAll(".post-signature"); var siblings = document.querySelectorAll(".post-signature + .pull-right"); var prevent = document.querySelector(".post-signature + .pull-right button"); for (var i=0; i < signatures.length; i++) { if (prevent == null) { signatures[i].style = "display: none"; var button = document.createElement('button'); button.innerHTML = 'Signature'; siblings[i].insertBefore(button, siblings[i].firstChild); } } var showsig = document.querySelectorAll(".post-signature + .pull-right button"); for (i=0; i < showsig.length; i++) { showsig[i].addEventListener('click', function(i) { signatures[i].style = "display: block"; showsig[i].style = "color: #fd3563; text-decoration: none; cursor: default"; }.bind(this, i)); } };
/* additional css for the button */ .post-signature + .pull-right button { background-color: transparent; color: #006bda; text-decoration: underline; border: none; outline: none; margin-right: 5px; } .post-signature + .pull-right button:hover { text-decoration: none; }
The mod finds and hides all existing signatures on a forum page, and replaces each with a button. When clicked, the button will display the signature of the according post. This way no vertical space is being wasted, you still get to know who runs a signature, and if curious, you can display it.
picture
-
A little tweak to show the user id when hovering a username in forums, just for fun (it's also informative sometimes ^^ )
.clearfix.post-header small.pull-left strong a:hover::after { content: " [UID:"attr(data-UID)"]"; font-size: smaller; }
-
@luetage said in Forum customization:
I see what this is trying to do, but I can't get it to work after all it seems. The problem is the code only triggers on going back or forth in history, it doesn't do anything when just the AJAX navigation is being used. Maybe I'm using it wrong though.
Ah, I have "Paginate topics and posts instead of using infinite scroll" turned on in my settings, so I didn't think of the replaceState situation. If the infinite scroll XHR is what you're referring to, that could similarly be treated with:
(function(history){ var replaceState = history.replaceState; history.replaceState = function(state) { if (typeof history.onreplacestate == "function") { history.onreplacestate({state: state}); } return replaceState.apply(history, arguments); } })(window.history); history.onreplacestate = function(e) { /* do stuff without delay */ setTimeout(function(){ /* stuff to do after a delay, if needed */ }, 500); };
-
@Isildur If you look at my mod above I already have it solved. Even history back and forth works with the code I'm using. I couldn't tell you why but it does
-
I'm thinking about making a general extension for Vivaldi forums. Completely modular, with different themes and all mods from this thread optional from a settings page. Anyone wanna help with this? Does this idea even make sense?
-
-
@sjudenim Looks really cool, just the dropdown menu seems to need a little help, the icons are barely visible.
Also I reported a profile alignment problem yesterday, the avatar isn't centered and the profile cover is partially hidden when visiting other user's profiles. You can fix it with this:
/* Profile alignment fix */ .account .cover .avatar-wrapper { margin-left: -68px !important; } .account .cover { margin-top: 50px; }