Colors for unvisted, visited and hovered/focused/active links
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I've created a userscript for Tampermonkey to style unvisited links with blue color, visited links with violet color, and red for hovered/active/focused links.
It was created primarily for my researches on Wikipedia.
Below are shown 3 implementations. The first one is very simple and shown just for demonstration purposes.
My actual question is about 2nd and 3rd implementations. I don't sure which one of them to choose from. Which is better?
1st and 2nd implementations
// ==UserScript==
// @name Test
// @match *://*/*
// ==/UserScript==
/* Preferences
=============================================== */
var links = 2;
// Set to "1" to style only simple links (example: a:link)
// Set to "2" to style also hidden links (example: a:link *)
/* Functions
=============================================== */
function AddGlobalStyle(css)
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
function Links(blue, violet, red)
AddGlobalStyle(
blue + '' +
'color: rgb(0, 138, 206) !important;' +
'text-decoration: none !important;' +
''
);
AddGlobalStyle(
violet + '' +
'color: rgb(180, 14, 180) !important;' +
''
);
AddGlobalStyle(
red + '' +
'color: rgb(204, 0, 0) !important;' +
''
);
/* Main part
=============================================== */
/* 1st way. Simple and works fine. Shown here just to show an idea
----------------- */
/*
if (links == 1)
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
if (links == 2)
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
Links('a:link *', 'a:visited *', 'a:hover *, a:focus *, a:active *');
*/
/* 2nd way
----------------- */
const plusX = s => s + ' *';
var args = ['a:link', 'a:visited', 'a:hover, a:focus, a:active'];
var modifiedArgs = args.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
The resulting rules in the head section will be as follows (6 style
elements):
<style>
a:link
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
</style>
<style>
a:visited
color: rgb(180, 14, 180) !important;
text-decoration: none !important;
</style>
<style>
a:hover, a:focus, a:active
color: rgb(204, 0, 0) !important;
text-decoration: none !important;
</style>
<style>
a:link *
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
</style>
<style>
a:visited *
color: rgb(180, 14, 180) !important;
text-decoration: none !important;
</style>
<style>
a:hover *, a:focus *, a:active *
color: rgb(204, 0, 0) !important;
text-decoration: none !important;
</style>
3rd implementation
// ==UserScript==
// @name Test
// @match *://*/*
// ==/UserScript==
/* Preferences
=============================================== */
var links = 2;
// Set to "1" to style only simple links (example: a:link)
// Set to "2" to style also hidden links (example: a:link *)
/* Functions
=============================================== */
// This function is the same
function AddGlobalStyle(css)
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
// But this one have changed
function Links(blue, violet, red)
if (links == 2)
blue = blue + ',' + blue + ' *';
violet = violet + ',' + violet + ' *';
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
AddGlobalStyle(
blue + '' +
'color: rgb(0, 138, 206) !important;' +
'text-decoration: none !important;' +
''
);
AddGlobalStyle(
violet + '' +
'color: rgb(180, 14, 180) !important;' +
''
);
AddGlobalStyle(
red + '' +
'color: rgb(204, 0, 0) !important;' +
''
);
/* Main part
=============================================== */
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
The resulting rules in the head section will be as follows (3 style
elements):
<style>
a:link, a:link *
color: rgb(0, 138, 206) !important;
text-decoration: none;
</style>
<style>
a:visited, a:visited *
color: rgb(180, 14, 180) !important;
text-decoration: none;
</style>
<style>
a:hover, a:focus, a:active, a:hover *, a:focus *, a:active *
color: rgb(204, 0, 0) !important;
text-decoration: none;
</style>
javascript beginner css comparative-review userscript
add a comment |Â
up vote
4
down vote
favorite
I've created a userscript for Tampermonkey to style unvisited links with blue color, visited links with violet color, and red for hovered/active/focused links.
It was created primarily for my researches on Wikipedia.
Below are shown 3 implementations. The first one is very simple and shown just for demonstration purposes.
My actual question is about 2nd and 3rd implementations. I don't sure which one of them to choose from. Which is better?
1st and 2nd implementations
// ==UserScript==
// @name Test
// @match *://*/*
// ==/UserScript==
/* Preferences
=============================================== */
var links = 2;
// Set to "1" to style only simple links (example: a:link)
// Set to "2" to style also hidden links (example: a:link *)
/* Functions
=============================================== */
function AddGlobalStyle(css)
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
function Links(blue, violet, red)
AddGlobalStyle(
blue + '' +
'color: rgb(0, 138, 206) !important;' +
'text-decoration: none !important;' +
''
);
AddGlobalStyle(
violet + '' +
'color: rgb(180, 14, 180) !important;' +
''
);
AddGlobalStyle(
red + '' +
'color: rgb(204, 0, 0) !important;' +
''
);
/* Main part
=============================================== */
/* 1st way. Simple and works fine. Shown here just to show an idea
----------------- */
/*
if (links == 1)
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
if (links == 2)
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
Links('a:link *', 'a:visited *', 'a:hover *, a:focus *, a:active *');
*/
/* 2nd way
----------------- */
const plusX = s => s + ' *';
var args = ['a:link', 'a:visited', 'a:hover, a:focus, a:active'];
var modifiedArgs = args.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
The resulting rules in the head section will be as follows (6 style
elements):
<style>
a:link
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
</style>
<style>
a:visited
color: rgb(180, 14, 180) !important;
text-decoration: none !important;
</style>
<style>
a:hover, a:focus, a:active
color: rgb(204, 0, 0) !important;
text-decoration: none !important;
</style>
<style>
a:link *
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
</style>
<style>
a:visited *
color: rgb(180, 14, 180) !important;
text-decoration: none !important;
</style>
<style>
a:hover *, a:focus *, a:active *
color: rgb(204, 0, 0) !important;
text-decoration: none !important;
</style>
3rd implementation
// ==UserScript==
// @name Test
// @match *://*/*
// ==/UserScript==
/* Preferences
=============================================== */
var links = 2;
// Set to "1" to style only simple links (example: a:link)
// Set to "2" to style also hidden links (example: a:link *)
/* Functions
=============================================== */
// This function is the same
function AddGlobalStyle(css)
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
// But this one have changed
function Links(blue, violet, red)
if (links == 2)
blue = blue + ',' + blue + ' *';
violet = violet + ',' + violet + ' *';
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
AddGlobalStyle(
blue + '' +
'color: rgb(0, 138, 206) !important;' +
'text-decoration: none !important;' +
''
);
AddGlobalStyle(
violet + '' +
'color: rgb(180, 14, 180) !important;' +
''
);
AddGlobalStyle(
red + '' +
'color: rgb(204, 0, 0) !important;' +
''
);
/* Main part
=============================================== */
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
The resulting rules in the head section will be as follows (3 style
elements):
<style>
a:link, a:link *
color: rgb(0, 138, 206) !important;
text-decoration: none;
</style>
<style>
a:visited, a:visited *
color: rgb(180, 14, 180) !important;
text-decoration: none;
</style>
<style>
a:hover, a:focus, a:active, a:hover *, a:focus *, a:active *
color: rgb(204, 0, 0) !important;
text-decoration: none;
</style>
javascript beginner css comparative-review userscript
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I've created a userscript for Tampermonkey to style unvisited links with blue color, visited links with violet color, and red for hovered/active/focused links.
It was created primarily for my researches on Wikipedia.
Below are shown 3 implementations. The first one is very simple and shown just for demonstration purposes.
My actual question is about 2nd and 3rd implementations. I don't sure which one of them to choose from. Which is better?
1st and 2nd implementations
// ==UserScript==
// @name Test
// @match *://*/*
// ==/UserScript==
/* Preferences
=============================================== */
var links = 2;
// Set to "1" to style only simple links (example: a:link)
// Set to "2" to style also hidden links (example: a:link *)
/* Functions
=============================================== */
function AddGlobalStyle(css)
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
function Links(blue, violet, red)
AddGlobalStyle(
blue + '' +
'color: rgb(0, 138, 206) !important;' +
'text-decoration: none !important;' +
''
);
AddGlobalStyle(
violet + '' +
'color: rgb(180, 14, 180) !important;' +
''
);
AddGlobalStyle(
red + '' +
'color: rgb(204, 0, 0) !important;' +
''
);
/* Main part
=============================================== */
/* 1st way. Simple and works fine. Shown here just to show an idea
----------------- */
/*
if (links == 1)
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
if (links == 2)
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
Links('a:link *', 'a:visited *', 'a:hover *, a:focus *, a:active *');
*/
/* 2nd way
----------------- */
const plusX = s => s + ' *';
var args = ['a:link', 'a:visited', 'a:hover, a:focus, a:active'];
var modifiedArgs = args.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
The resulting rules in the head section will be as follows (6 style
elements):
<style>
a:link
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
</style>
<style>
a:visited
color: rgb(180, 14, 180) !important;
text-decoration: none !important;
</style>
<style>
a:hover, a:focus, a:active
color: rgb(204, 0, 0) !important;
text-decoration: none !important;
</style>
<style>
a:link *
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
</style>
<style>
a:visited *
color: rgb(180, 14, 180) !important;
text-decoration: none !important;
</style>
<style>
a:hover *, a:focus *, a:active *
color: rgb(204, 0, 0) !important;
text-decoration: none !important;
</style>
3rd implementation
// ==UserScript==
// @name Test
// @match *://*/*
// ==/UserScript==
/* Preferences
=============================================== */
var links = 2;
// Set to "1" to style only simple links (example: a:link)
// Set to "2" to style also hidden links (example: a:link *)
/* Functions
=============================================== */
// This function is the same
function AddGlobalStyle(css)
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
// But this one have changed
function Links(blue, violet, red)
if (links == 2)
blue = blue + ',' + blue + ' *';
violet = violet + ',' + violet + ' *';
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
AddGlobalStyle(
blue + '' +
'color: rgb(0, 138, 206) !important;' +
'text-decoration: none !important;' +
''
);
AddGlobalStyle(
violet + '' +
'color: rgb(180, 14, 180) !important;' +
''
);
AddGlobalStyle(
red + '' +
'color: rgb(204, 0, 0) !important;' +
''
);
/* Main part
=============================================== */
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
The resulting rules in the head section will be as follows (3 style
elements):
<style>
a:link, a:link *
color: rgb(0, 138, 206) !important;
text-decoration: none;
</style>
<style>
a:visited, a:visited *
color: rgb(180, 14, 180) !important;
text-decoration: none;
</style>
<style>
a:hover, a:focus, a:active, a:hover *, a:focus *, a:active *
color: rgb(204, 0, 0) !important;
text-decoration: none;
</style>
javascript beginner css comparative-review userscript
I've created a userscript for Tampermonkey to style unvisited links with blue color, visited links with violet color, and red for hovered/active/focused links.
It was created primarily for my researches on Wikipedia.
Below are shown 3 implementations. The first one is very simple and shown just for demonstration purposes.
My actual question is about 2nd and 3rd implementations. I don't sure which one of them to choose from. Which is better?
1st and 2nd implementations
// ==UserScript==
// @name Test
// @match *://*/*
// ==/UserScript==
/* Preferences
=============================================== */
var links = 2;
// Set to "1" to style only simple links (example: a:link)
// Set to "2" to style also hidden links (example: a:link *)
/* Functions
=============================================== */
function AddGlobalStyle(css)
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
function Links(blue, violet, red)
AddGlobalStyle(
blue + '' +
'color: rgb(0, 138, 206) !important;' +
'text-decoration: none !important;' +
''
);
AddGlobalStyle(
violet + '' +
'color: rgb(180, 14, 180) !important;' +
''
);
AddGlobalStyle(
red + '' +
'color: rgb(204, 0, 0) !important;' +
''
);
/* Main part
=============================================== */
/* 1st way. Simple and works fine. Shown here just to show an idea
----------------- */
/*
if (links == 1)
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
if (links == 2)
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
Links('a:link *', 'a:visited *', 'a:hover *, a:focus *, a:active *');
*/
/* 2nd way
----------------- */
const plusX = s => s + ' *';
var args = ['a:link', 'a:visited', 'a:hover, a:focus, a:active'];
var modifiedArgs = args.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
The resulting rules in the head section will be as follows (6 style
elements):
<style>
a:link
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
</style>
<style>
a:visited
color: rgb(180, 14, 180) !important;
text-decoration: none !important;
</style>
<style>
a:hover, a:focus, a:active
color: rgb(204, 0, 0) !important;
text-decoration: none !important;
</style>
<style>
a:link *
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
</style>
<style>
a:visited *
color: rgb(180, 14, 180) !important;
text-decoration: none !important;
</style>
<style>
a:hover *, a:focus *, a:active *
color: rgb(204, 0, 0) !important;
text-decoration: none !important;
</style>
3rd implementation
// ==UserScript==
// @name Test
// @match *://*/*
// ==/UserScript==
/* Preferences
=============================================== */
var links = 2;
// Set to "1" to style only simple links (example: a:link)
// Set to "2" to style also hidden links (example: a:link *)
/* Functions
=============================================== */
// This function is the same
function AddGlobalStyle(css)
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) return;
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
// But this one have changed
function Links(blue, violet, red)
if (links == 2)
blue = blue + ',' + blue + ' *';
violet = violet + ',' + violet + ' *';
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
AddGlobalStyle(
blue + '' +
'color: rgb(0, 138, 206) !important;' +
'text-decoration: none !important;' +
''
);
AddGlobalStyle(
violet + '' +
'color: rgb(180, 14, 180) !important;' +
''
);
AddGlobalStyle(
red + '' +
'color: rgb(204, 0, 0) !important;' +
''
);
/* Main part
=============================================== */
Links('a:link', 'a:visited', 'a:hover, a:focus, a:active');
The resulting rules in the head section will be as follows (3 style
elements):
<style>
a:link, a:link *
color: rgb(0, 138, 206) !important;
text-decoration: none;
</style>
<style>
a:visited, a:visited *
color: rgb(180, 14, 180) !important;
text-decoration: none;
</style>
<style>
a:hover, a:focus, a:active, a:hover *, a:focus *, a:active *
color: rgb(204, 0, 0) !important;
text-decoration: none;
</style>
javascript beginner css comparative-review userscript
edited Jun 12 at 2:54
Grant Miller
2202416
2202416
asked Jan 28 at 15:16
john c. j.
268
268
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
5
down vote
accepted
Your question
My actual question is about 2nd and 3rd implementations. I don't sure which choose from them. Which is better?
That might lead to some opinionated answers, especially because better is subjective. The 2nd implementation calls .split()
, .map()
and .join()
on all three array elements while that is only really only mandatory for the third element. While there would be excess processing on the first two elements, the code is uniform and simpler to read. The 3rd implementation isn't necessarily less-readable but it does take a little longer for one to discern the difference in handling between the two types of strings. The 2nd implementation leads to 6 distinct rulesets while the 3rd leads to 3 - I would rather have as few as necessary and would thus pick the 3rd implementation (presuming the flaw mentioned in the first paragraph below is fixed). While CSS styleguides differ on how to format selectors, it should be agreed that the D.R.Y. principle applies and the output of the 3rd implementation adheres to it.
Review feedback
Flaw in 3rd implementation
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
That code calls .split()
and extra time (well, actually once extra for each string after separating the original string on commas), so that call can be removed inside the mapping. redNew
is an array (and implicitly converted to a string joined by commas via Array.toString()). Perhaps you intended to call .join()
on the array returned from .map()
:
redArray = red.split(',');
const plusX = s => s + ' *';
const redNew = redArray.map(plusX)
.join(',');
And as you suggested in your jsfiddle via comments you could just omit the call to .join()
. In a large web application one might want to explicitly use .join()
but it is probably fine to omit it in a small script like this that you are likely the only one who will maintain it.
Notice how I added const
. In your code, redArray
and redNew
are global variables because "Undeclared variables are always global."1, which could have unintentional consequences - for example, if the wikipedia JavaScript had a variable with the same name, then it would be overwritten.
One style tag for each ruleset?
Why not just add one style tag for the whole set of rulesets, instead of one style tag for each? To do this, just combine the three strings and call AddGlobalStyle()
once.
Template Literal
Going along with the advice in the previous section, you could use a template literal to add the styles. With expression interpolation, there is no need to terminate the string to add the arguments. That way there is no need to worry about appending strings together.
function Links(blue, violet, red)
AddGlobalStyle(`
$blue
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
$violet
color: rgb(180, 14, 180) !important;
$red
color: rgb(204, 0, 0) !important;
`);
Simplifying 2nd implementation
The 2nd implementation code could be simplified:
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
Since Links()
is always called with ...args
, that can be moved out of the if
blocks and then only have a check to see if Links()
should be called with the modified arguments (i.e. links == 2
).
Links(...args);
if (links == 2)
Links(...modifiedArgs);
And if you really want to make it shorter, use short-circuiting logical operators (though some may argue it is less readable or isn't as verbose):
Links(...args);
links == 2 && Links(...modifiedArgs);
1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#Description
1
First of all, thank you very much. Very interesting to read. I have some notes (N1, N2) about it.
â john c. j.
Jan 30 at 18:31
1
Okay - I realize there is a flaw in the third implementation... See the newly added first paragraph under the Review Feedback section
â Sam Onela
Jan 30 at 19:13
In that screenshot I see 2 style tags (i.e.<style>...</style>
), each with three declaration blocks so still 6 total declaration blocks (I admit I had to refresh my memory on the terminology today :) ) Actually, I guess we should call them rulesets
â Sam Onela
Jan 30 at 19:48
Big thanks for your edits, not the answer is much more clear. Could you elaborate is it a good idea to omit.join()
? Probably this omission have some drawbacks?
â john c. j.
Jan 31 at 17:59
Elaboration added
â Sam Onela
Jan 31 at 18:10
add a comment |Â
up vote
3
down vote
Better how?
In this case for me better is
- simple
- portable
I have not spent too much time with User Scripts but I write front end code all the time, so I will do my best.
Have you considered a User Stylesheet? Maybe you already have a bunch of tamper monkey code and want to continue using that.
Why spend so much time beating around the bush in Javascript? Maybe you want a more programmatic interface. But it seems like you aren't interested in varying from your requirements too much.
I know you wanted an answer on which is better, but I kind of had a hard time following it. I think it comes from where you are trying to optimize your code reuse. I think that is your biggest problem.
I would define your AddGlobalStyle
function, and then call it. Not much else.
AddGlobalStyle('a:link, a:link * '+
'color: rgb(0, 138, 206) !important;'+
'text-decoration: none;'+
''
Thanks for your post. ) Hardcoding botha:link
anda:link *
in the function will remove the ability to switch between them (as shown in myPreferences
section). Because, for some reasons (it will be a bit offtopic to describe it here), most of the time I prefer to use justa:link
and keepa:link *
in "off" state.
â john c. j.
Jan 30 at 16:57
Also, yes, I agree, the code is a bit overcomplicated, but that's because I tried to learn something new while writing it. The 1st implementation was very simple... Too simple to like it )
â john c. j.
Jan 30 at 17:04
Ok, so you do want to be able to customize beyond your default. That does invalidate some of my discussion.
â TMB
Jan 30 at 17:15
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
Your question
My actual question is about 2nd and 3rd implementations. I don't sure which choose from them. Which is better?
That might lead to some opinionated answers, especially because better is subjective. The 2nd implementation calls .split()
, .map()
and .join()
on all three array elements while that is only really only mandatory for the third element. While there would be excess processing on the first two elements, the code is uniform and simpler to read. The 3rd implementation isn't necessarily less-readable but it does take a little longer for one to discern the difference in handling between the two types of strings. The 2nd implementation leads to 6 distinct rulesets while the 3rd leads to 3 - I would rather have as few as necessary and would thus pick the 3rd implementation (presuming the flaw mentioned in the first paragraph below is fixed). While CSS styleguides differ on how to format selectors, it should be agreed that the D.R.Y. principle applies and the output of the 3rd implementation adheres to it.
Review feedback
Flaw in 3rd implementation
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
That code calls .split()
and extra time (well, actually once extra for each string after separating the original string on commas), so that call can be removed inside the mapping. redNew
is an array (and implicitly converted to a string joined by commas via Array.toString()). Perhaps you intended to call .join()
on the array returned from .map()
:
redArray = red.split(',');
const plusX = s => s + ' *';
const redNew = redArray.map(plusX)
.join(',');
And as you suggested in your jsfiddle via comments you could just omit the call to .join()
. In a large web application one might want to explicitly use .join()
but it is probably fine to omit it in a small script like this that you are likely the only one who will maintain it.
Notice how I added const
. In your code, redArray
and redNew
are global variables because "Undeclared variables are always global."1, which could have unintentional consequences - for example, if the wikipedia JavaScript had a variable with the same name, then it would be overwritten.
One style tag for each ruleset?
Why not just add one style tag for the whole set of rulesets, instead of one style tag for each? To do this, just combine the three strings and call AddGlobalStyle()
once.
Template Literal
Going along with the advice in the previous section, you could use a template literal to add the styles. With expression interpolation, there is no need to terminate the string to add the arguments. That way there is no need to worry about appending strings together.
function Links(blue, violet, red)
AddGlobalStyle(`
$blue
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
$violet
color: rgb(180, 14, 180) !important;
$red
color: rgb(204, 0, 0) !important;
`);
Simplifying 2nd implementation
The 2nd implementation code could be simplified:
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
Since Links()
is always called with ...args
, that can be moved out of the if
blocks and then only have a check to see if Links()
should be called with the modified arguments (i.e. links == 2
).
Links(...args);
if (links == 2)
Links(...modifiedArgs);
And if you really want to make it shorter, use short-circuiting logical operators (though some may argue it is less readable or isn't as verbose):
Links(...args);
links == 2 && Links(...modifiedArgs);
1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#Description
1
First of all, thank you very much. Very interesting to read. I have some notes (N1, N2) about it.
â john c. j.
Jan 30 at 18:31
1
Okay - I realize there is a flaw in the third implementation... See the newly added first paragraph under the Review Feedback section
â Sam Onela
Jan 30 at 19:13
In that screenshot I see 2 style tags (i.e.<style>...</style>
), each with three declaration blocks so still 6 total declaration blocks (I admit I had to refresh my memory on the terminology today :) ) Actually, I guess we should call them rulesets
â Sam Onela
Jan 30 at 19:48
Big thanks for your edits, not the answer is much more clear. Could you elaborate is it a good idea to omit.join()
? Probably this omission have some drawbacks?
â john c. j.
Jan 31 at 17:59
Elaboration added
â Sam Onela
Jan 31 at 18:10
add a comment |Â
up vote
5
down vote
accepted
Your question
My actual question is about 2nd and 3rd implementations. I don't sure which choose from them. Which is better?
That might lead to some opinionated answers, especially because better is subjective. The 2nd implementation calls .split()
, .map()
and .join()
on all three array elements while that is only really only mandatory for the third element. While there would be excess processing on the first two elements, the code is uniform and simpler to read. The 3rd implementation isn't necessarily less-readable but it does take a little longer for one to discern the difference in handling between the two types of strings. The 2nd implementation leads to 6 distinct rulesets while the 3rd leads to 3 - I would rather have as few as necessary and would thus pick the 3rd implementation (presuming the flaw mentioned in the first paragraph below is fixed). While CSS styleguides differ on how to format selectors, it should be agreed that the D.R.Y. principle applies and the output of the 3rd implementation adheres to it.
Review feedback
Flaw in 3rd implementation
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
That code calls .split()
and extra time (well, actually once extra for each string after separating the original string on commas), so that call can be removed inside the mapping. redNew
is an array (and implicitly converted to a string joined by commas via Array.toString()). Perhaps you intended to call .join()
on the array returned from .map()
:
redArray = red.split(',');
const plusX = s => s + ' *';
const redNew = redArray.map(plusX)
.join(',');
And as you suggested in your jsfiddle via comments you could just omit the call to .join()
. In a large web application one might want to explicitly use .join()
but it is probably fine to omit it in a small script like this that you are likely the only one who will maintain it.
Notice how I added const
. In your code, redArray
and redNew
are global variables because "Undeclared variables are always global."1, which could have unintentional consequences - for example, if the wikipedia JavaScript had a variable with the same name, then it would be overwritten.
One style tag for each ruleset?
Why not just add one style tag for the whole set of rulesets, instead of one style tag for each? To do this, just combine the three strings and call AddGlobalStyle()
once.
Template Literal
Going along with the advice in the previous section, you could use a template literal to add the styles. With expression interpolation, there is no need to terminate the string to add the arguments. That way there is no need to worry about appending strings together.
function Links(blue, violet, red)
AddGlobalStyle(`
$blue
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
$violet
color: rgb(180, 14, 180) !important;
$red
color: rgb(204, 0, 0) !important;
`);
Simplifying 2nd implementation
The 2nd implementation code could be simplified:
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
Since Links()
is always called with ...args
, that can be moved out of the if
blocks and then only have a check to see if Links()
should be called with the modified arguments (i.e. links == 2
).
Links(...args);
if (links == 2)
Links(...modifiedArgs);
And if you really want to make it shorter, use short-circuiting logical operators (though some may argue it is less readable or isn't as verbose):
Links(...args);
links == 2 && Links(...modifiedArgs);
1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#Description
1
First of all, thank you very much. Very interesting to read. I have some notes (N1, N2) about it.
â john c. j.
Jan 30 at 18:31
1
Okay - I realize there is a flaw in the third implementation... See the newly added first paragraph under the Review Feedback section
â Sam Onela
Jan 30 at 19:13
In that screenshot I see 2 style tags (i.e.<style>...</style>
), each with three declaration blocks so still 6 total declaration blocks (I admit I had to refresh my memory on the terminology today :) ) Actually, I guess we should call them rulesets
â Sam Onela
Jan 30 at 19:48
Big thanks for your edits, not the answer is much more clear. Could you elaborate is it a good idea to omit.join()
? Probably this omission have some drawbacks?
â john c. j.
Jan 31 at 17:59
Elaboration added
â Sam Onela
Jan 31 at 18:10
add a comment |Â
up vote
5
down vote
accepted
up vote
5
down vote
accepted
Your question
My actual question is about 2nd and 3rd implementations. I don't sure which choose from them. Which is better?
That might lead to some opinionated answers, especially because better is subjective. The 2nd implementation calls .split()
, .map()
and .join()
on all three array elements while that is only really only mandatory for the third element. While there would be excess processing on the first two elements, the code is uniform and simpler to read. The 3rd implementation isn't necessarily less-readable but it does take a little longer for one to discern the difference in handling between the two types of strings. The 2nd implementation leads to 6 distinct rulesets while the 3rd leads to 3 - I would rather have as few as necessary and would thus pick the 3rd implementation (presuming the flaw mentioned in the first paragraph below is fixed). While CSS styleguides differ on how to format selectors, it should be agreed that the D.R.Y. principle applies and the output of the 3rd implementation adheres to it.
Review feedback
Flaw in 3rd implementation
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
That code calls .split()
and extra time (well, actually once extra for each string after separating the original string on commas), so that call can be removed inside the mapping. redNew
is an array (and implicitly converted to a string joined by commas via Array.toString()). Perhaps you intended to call .join()
on the array returned from .map()
:
redArray = red.split(',');
const plusX = s => s + ' *';
const redNew = redArray.map(plusX)
.join(',');
And as you suggested in your jsfiddle via comments you could just omit the call to .join()
. In a large web application one might want to explicitly use .join()
but it is probably fine to omit it in a small script like this that you are likely the only one who will maintain it.
Notice how I added const
. In your code, redArray
and redNew
are global variables because "Undeclared variables are always global."1, which could have unintentional consequences - for example, if the wikipedia JavaScript had a variable with the same name, then it would be overwritten.
One style tag for each ruleset?
Why not just add one style tag for the whole set of rulesets, instead of one style tag for each? To do this, just combine the three strings and call AddGlobalStyle()
once.
Template Literal
Going along with the advice in the previous section, you could use a template literal to add the styles. With expression interpolation, there is no need to terminate the string to add the arguments. That way there is no need to worry about appending strings together.
function Links(blue, violet, red)
AddGlobalStyle(`
$blue
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
$violet
color: rgb(180, 14, 180) !important;
$red
color: rgb(204, 0, 0) !important;
`);
Simplifying 2nd implementation
The 2nd implementation code could be simplified:
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
Since Links()
is always called with ...args
, that can be moved out of the if
blocks and then only have a check to see if Links()
should be called with the modified arguments (i.e. links == 2
).
Links(...args);
if (links == 2)
Links(...modifiedArgs);
And if you really want to make it shorter, use short-circuiting logical operators (though some may argue it is less readable or isn't as verbose):
Links(...args);
links == 2 && Links(...modifiedArgs);
1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#Description
Your question
My actual question is about 2nd and 3rd implementations. I don't sure which choose from them. Which is better?
That might lead to some opinionated answers, especially because better is subjective. The 2nd implementation calls .split()
, .map()
and .join()
on all three array elements while that is only really only mandatory for the third element. While there would be excess processing on the first two elements, the code is uniform and simpler to read. The 3rd implementation isn't necessarily less-readable but it does take a little longer for one to discern the difference in handling between the two types of strings. The 2nd implementation leads to 6 distinct rulesets while the 3rd leads to 3 - I would rather have as few as necessary and would thus pick the 3rd implementation (presuming the flaw mentioned in the first paragraph below is fixed). While CSS styleguides differ on how to format selectors, it should be agreed that the D.R.Y. principle applies and the output of the 3rd implementation adheres to it.
Review feedback
Flaw in 3rd implementation
redArray = red.split(',')
const plusX = s => s + ' *';
redNew = redArray.map(
s => s
.split(',')
.map(plusX)
.join(',')
);
red = red + ',' + redNew;
That code calls .split()
and extra time (well, actually once extra for each string after separating the original string on commas), so that call can be removed inside the mapping. redNew
is an array (and implicitly converted to a string joined by commas via Array.toString()). Perhaps you intended to call .join()
on the array returned from .map()
:
redArray = red.split(',');
const plusX = s => s + ' *';
const redNew = redArray.map(plusX)
.join(',');
And as you suggested in your jsfiddle via comments you could just omit the call to .join()
. In a large web application one might want to explicitly use .join()
but it is probably fine to omit it in a small script like this that you are likely the only one who will maintain it.
Notice how I added const
. In your code, redArray
and redNew
are global variables because "Undeclared variables are always global."1, which could have unintentional consequences - for example, if the wikipedia JavaScript had a variable with the same name, then it would be overwritten.
One style tag for each ruleset?
Why not just add one style tag for the whole set of rulesets, instead of one style tag for each? To do this, just combine the three strings and call AddGlobalStyle()
once.
Template Literal
Going along with the advice in the previous section, you could use a template literal to add the styles. With expression interpolation, there is no need to terminate the string to add the arguments. That way there is no need to worry about appending strings together.
function Links(blue, violet, red)
AddGlobalStyle(`
$blue
color: rgb(0, 138, 206) !important;
text-decoration: none !important;
$violet
color: rgb(180, 14, 180) !important;
$red
color: rgb(204, 0, 0) !important;
`);
Simplifying 2nd implementation
The 2nd implementation code could be simplified:
if (links == 1)
Links(...args);
if (links == 2)
Links(...args);
Links(...modifiedArgs);
Since Links()
is always called with ...args
, that can be moved out of the if
blocks and then only have a check to see if Links()
should be called with the modified arguments (i.e. links == 2
).
Links(...args);
if (links == 2)
Links(...modifiedArgs);
And if you really want to make it shorter, use short-circuiting logical operators (though some may argue it is less readable or isn't as verbose):
Links(...args);
links == 2 && Links(...modifiedArgs);
1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#Description
edited Jan 31 at 18:10
answered Jan 30 at 17:30
Sam Onela
5,88461545
5,88461545
1
First of all, thank you very much. Very interesting to read. I have some notes (N1, N2) about it.
â john c. j.
Jan 30 at 18:31
1
Okay - I realize there is a flaw in the third implementation... See the newly added first paragraph under the Review Feedback section
â Sam Onela
Jan 30 at 19:13
In that screenshot I see 2 style tags (i.e.<style>...</style>
), each with three declaration blocks so still 6 total declaration blocks (I admit I had to refresh my memory on the terminology today :) ) Actually, I guess we should call them rulesets
â Sam Onela
Jan 30 at 19:48
Big thanks for your edits, not the answer is much more clear. Could you elaborate is it a good idea to omit.join()
? Probably this omission have some drawbacks?
â john c. j.
Jan 31 at 17:59
Elaboration added
â Sam Onela
Jan 31 at 18:10
add a comment |Â
1
First of all, thank you very much. Very interesting to read. I have some notes (N1, N2) about it.
â john c. j.
Jan 30 at 18:31
1
Okay - I realize there is a flaw in the third implementation... See the newly added first paragraph under the Review Feedback section
â Sam Onela
Jan 30 at 19:13
In that screenshot I see 2 style tags (i.e.<style>...</style>
), each with three declaration blocks so still 6 total declaration blocks (I admit I had to refresh my memory on the terminology today :) ) Actually, I guess we should call them rulesets
â Sam Onela
Jan 30 at 19:48
Big thanks for your edits, not the answer is much more clear. Could you elaborate is it a good idea to omit.join()
? Probably this omission have some drawbacks?
â john c. j.
Jan 31 at 17:59
Elaboration added
â Sam Onela
Jan 31 at 18:10
1
1
First of all, thank you very much. Very interesting to read. I have some notes (N1, N2) about it.
â john c. j.
Jan 30 at 18:31
First of all, thank you very much. Very interesting to read. I have some notes (N1, N2) about it.
â john c. j.
Jan 30 at 18:31
1
1
Okay - I realize there is a flaw in the third implementation... See the newly added first paragraph under the Review Feedback section
â Sam Onela
Jan 30 at 19:13
Okay - I realize there is a flaw in the third implementation... See the newly added first paragraph under the Review Feedback section
â Sam Onela
Jan 30 at 19:13
In that screenshot I see 2 style tags (i.e.
<style>...</style>
), each with three declaration blocks so still 6 total declaration blocks (I admit I had to refresh my memory on the terminology today :) ) Actually, I guess we should call them rulesetsâ Sam Onela
Jan 30 at 19:48
In that screenshot I see 2 style tags (i.e.
<style>...</style>
), each with three declaration blocks so still 6 total declaration blocks (I admit I had to refresh my memory on the terminology today :) ) Actually, I guess we should call them rulesetsâ Sam Onela
Jan 30 at 19:48
Big thanks for your edits, not the answer is much more clear. Could you elaborate is it a good idea to omit
.join()
? Probably this omission have some drawbacks?â john c. j.
Jan 31 at 17:59
Big thanks for your edits, not the answer is much more clear. Could you elaborate is it a good idea to omit
.join()
? Probably this omission have some drawbacks?â john c. j.
Jan 31 at 17:59
Elaboration added
â Sam Onela
Jan 31 at 18:10
Elaboration added
â Sam Onela
Jan 31 at 18:10
add a comment |Â
up vote
3
down vote
Better how?
In this case for me better is
- simple
- portable
I have not spent too much time with User Scripts but I write front end code all the time, so I will do my best.
Have you considered a User Stylesheet? Maybe you already have a bunch of tamper monkey code and want to continue using that.
Why spend so much time beating around the bush in Javascript? Maybe you want a more programmatic interface. But it seems like you aren't interested in varying from your requirements too much.
I know you wanted an answer on which is better, but I kind of had a hard time following it. I think it comes from where you are trying to optimize your code reuse. I think that is your biggest problem.
I would define your AddGlobalStyle
function, and then call it. Not much else.
AddGlobalStyle('a:link, a:link * '+
'color: rgb(0, 138, 206) !important;'+
'text-decoration: none;'+
''
Thanks for your post. ) Hardcoding botha:link
anda:link *
in the function will remove the ability to switch between them (as shown in myPreferences
section). Because, for some reasons (it will be a bit offtopic to describe it here), most of the time I prefer to use justa:link
and keepa:link *
in "off" state.
â john c. j.
Jan 30 at 16:57
Also, yes, I agree, the code is a bit overcomplicated, but that's because I tried to learn something new while writing it. The 1st implementation was very simple... Too simple to like it )
â john c. j.
Jan 30 at 17:04
Ok, so you do want to be able to customize beyond your default. That does invalidate some of my discussion.
â TMB
Jan 30 at 17:15
add a comment |Â
up vote
3
down vote
Better how?
In this case for me better is
- simple
- portable
I have not spent too much time with User Scripts but I write front end code all the time, so I will do my best.
Have you considered a User Stylesheet? Maybe you already have a bunch of tamper monkey code and want to continue using that.
Why spend so much time beating around the bush in Javascript? Maybe you want a more programmatic interface. But it seems like you aren't interested in varying from your requirements too much.
I know you wanted an answer on which is better, but I kind of had a hard time following it. I think it comes from where you are trying to optimize your code reuse. I think that is your biggest problem.
I would define your AddGlobalStyle
function, and then call it. Not much else.
AddGlobalStyle('a:link, a:link * '+
'color: rgb(0, 138, 206) !important;'+
'text-decoration: none;'+
''
Thanks for your post. ) Hardcoding botha:link
anda:link *
in the function will remove the ability to switch between them (as shown in myPreferences
section). Because, for some reasons (it will be a bit offtopic to describe it here), most of the time I prefer to use justa:link
and keepa:link *
in "off" state.
â john c. j.
Jan 30 at 16:57
Also, yes, I agree, the code is a bit overcomplicated, but that's because I tried to learn something new while writing it. The 1st implementation was very simple... Too simple to like it )
â john c. j.
Jan 30 at 17:04
Ok, so you do want to be able to customize beyond your default. That does invalidate some of my discussion.
â TMB
Jan 30 at 17:15
add a comment |Â
up vote
3
down vote
up vote
3
down vote
Better how?
In this case for me better is
- simple
- portable
I have not spent too much time with User Scripts but I write front end code all the time, so I will do my best.
Have you considered a User Stylesheet? Maybe you already have a bunch of tamper monkey code and want to continue using that.
Why spend so much time beating around the bush in Javascript? Maybe you want a more programmatic interface. But it seems like you aren't interested in varying from your requirements too much.
I know you wanted an answer on which is better, but I kind of had a hard time following it. I think it comes from where you are trying to optimize your code reuse. I think that is your biggest problem.
I would define your AddGlobalStyle
function, and then call it. Not much else.
AddGlobalStyle('a:link, a:link * '+
'color: rgb(0, 138, 206) !important;'+
'text-decoration: none;'+
''
Better how?
In this case for me better is
- simple
- portable
I have not spent too much time with User Scripts but I write front end code all the time, so I will do my best.
Have you considered a User Stylesheet? Maybe you already have a bunch of tamper monkey code and want to continue using that.
Why spend so much time beating around the bush in Javascript? Maybe you want a more programmatic interface. But it seems like you aren't interested in varying from your requirements too much.
I know you wanted an answer on which is better, but I kind of had a hard time following it. I think it comes from where you are trying to optimize your code reuse. I think that is your biggest problem.
I would define your AddGlobalStyle
function, and then call it. Not much else.
AddGlobalStyle('a:link, a:link * '+
'color: rgb(0, 138, 206) !important;'+
'text-decoration: none;'+
''
answered Jan 30 at 15:54
TMB
1796
1796
Thanks for your post. ) Hardcoding botha:link
anda:link *
in the function will remove the ability to switch between them (as shown in myPreferences
section). Because, for some reasons (it will be a bit offtopic to describe it here), most of the time I prefer to use justa:link
and keepa:link *
in "off" state.
â john c. j.
Jan 30 at 16:57
Also, yes, I agree, the code is a bit overcomplicated, but that's because I tried to learn something new while writing it. The 1st implementation was very simple... Too simple to like it )
â john c. j.
Jan 30 at 17:04
Ok, so you do want to be able to customize beyond your default. That does invalidate some of my discussion.
â TMB
Jan 30 at 17:15
add a comment |Â
Thanks for your post. ) Hardcoding botha:link
anda:link *
in the function will remove the ability to switch between them (as shown in myPreferences
section). Because, for some reasons (it will be a bit offtopic to describe it here), most of the time I prefer to use justa:link
and keepa:link *
in "off" state.
â john c. j.
Jan 30 at 16:57
Also, yes, I agree, the code is a bit overcomplicated, but that's because I tried to learn something new while writing it. The 1st implementation was very simple... Too simple to like it )
â john c. j.
Jan 30 at 17:04
Ok, so you do want to be able to customize beyond your default. That does invalidate some of my discussion.
â TMB
Jan 30 at 17:15
Thanks for your post. ) Hardcoding both
a:link
and a:link *
in the function will remove the ability to switch between them (as shown in my Preferences
section). Because, for some reasons (it will be a bit offtopic to describe it here), most of the time I prefer to use just a:link
and keep a:link *
in "off" state.â john c. j.
Jan 30 at 16:57
Thanks for your post. ) Hardcoding both
a:link
and a:link *
in the function will remove the ability to switch between them (as shown in my Preferences
section). Because, for some reasons (it will be a bit offtopic to describe it here), most of the time I prefer to use just a:link
and keep a:link *
in "off" state.â john c. j.
Jan 30 at 16:57
Also, yes, I agree, the code is a bit overcomplicated, but that's because I tried to learn something new while writing it. The 1st implementation was very simple... Too simple to like it )
â john c. j.
Jan 30 at 17:04
Also, yes, I agree, the code is a bit overcomplicated, but that's because I tried to learn something new while writing it. The 1st implementation was very simple... Too simple to like it )
â john c. j.
Jan 30 at 17:04
Ok, so you do want to be able to customize beyond your default. That does invalidate some of my discussion.
â TMB
Jan 30 at 17:15
Ok, so you do want to be able to customize beyond your default. That does invalidate some of my discussion.
â TMB
Jan 30 at 17:15
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186199%2fcolors-for-unvisted-visited-and-hovered-focused-active-links%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password