SpoilerTags

SpoilerTags allows editors to mark and hide text containing spoilers. It differs from other spoiler scripts/styles in that the content must be clicked to show/hide it, as opposed to hovered. Although it is designed mainly for words, sentences, and small paragraphs of text, it can work with blocks of text and images too. 
It is loosely based off the appearance and behaviour of Reddit's spoiler text, and Discord's spoiler tags.
Because it uses click events, it requires JavaScript in addition to CSS, and does not work on mobile. If you want your spoilers to be shown on hover, or if you prefer JavaScript-less spoilers, you'll want to use Heimu or SpoilerBlur instead.
Found an issue? Want to request a feature? Please feel free to post it on the talk page.
== ==
The stylesheet must be installed manually, the script does not automatically import it (this is to reduce flicker and potential spoilers from late-loading scripts).
== ==
===Inline spoilers===
Text may be marked as a spoiler by wrapping it in .... All spoilers are inline, and as such only may be used.
Example 	Results in
This is a spoiler 	This is a spoiler
This is a [[SpoilerTags|spoiler tag]]! [[File:Wiki.png|20px|link=Main Page]] 	This is a spoiler tag!
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.	Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
===Nested spoilers===
Spoilers may be nested easily by simply adding another ... within the last. In order to spoil inner spoilers, the outer spoilers must first be spoiled. When a spoiler is "unspoiled", all spoilers within will be unspoiled too.
When using nested spoilers, you may wish to to use opaque "hover" and "show" colors, rather than the transparent defaults, as they will be layered on top of one another (see below).
Example 	Results in
This an example of nesting spoilers: [[Special:MyPage|Me, myself, and I]]. 	This an example of nesting spoilers: Me, myself, and I.
This an example of nesting spoilers: [[Special:MyPage|Me, myself, and I]]. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.	This an example of nesting spoilers: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
===Multiline spoilers===
Multiline spoilers may be accomplished by wrapping text in a ... (note use of div instead of span). This will be converted into a spoiler-group, and all text within will be wrapped in a series of ...s, one for each block of adjacent inline text, belonging to the spoiler-group.
Example	Results in
The spans below are treated as a single spoiler, even though they are split across multiple lines.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.	
The spans below are treated as a single spoiler, even though they are split across multiple lines.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
===Grouped spoilers===
Spoilers may only ever be single inline spans of text. You can group spoilers together so they act as one contiguous spoiler by creating an overarching element with the "spoiler-group" class, and adding nested ...s at any level. Clicking any of the nested spoilers will show all spoilers in that group.
This is an alternate way of doing multiline spoilers, but allows for better control in cases where you might have more complex layouts.
Example 	Results in
[[Special:MyPage|My]] favourite food is [[wikipedia:Ice cream|ice cream]], but only on a hot day.	My favourite food is ice cream, but only on a hot day
You can also group completely separate spoilers with the attribute data-group, without the need for an encapsulating "spoiler-group". Clicking on a spoiler with this attribute will show all other spoilers or spoiler-groups whose data-group matches the one that was clicked.
Example 	Results in
The quick brown fox jumped over the lazy dog.	The quick brown fox jumped over the lazy dog.
Spoilers may have more than one group (delimited by , in the data-group attribute). When the spoiler is toggled, all spoilers in all of the groups it belongs to are also toggled, but not the groups that those spoilers belong to and so on and soforth. The following is an example of a collection of spoilers with multiple groups.
Example	Results in
__1__ __2__ __3__ __4__
__A__ __B__ __C__ __D__
foo bar baz qux	
__1__ __2__ __3__ __4__
__A__ __B__ __C__ __D__
foo bar baz qux
You may also nest spoilers within a spoiler that is part of a group. When the group is spoiled, the nested spoiler will not be spoiled.
Example 	Results in
Example of grouped spoilers that also have nested spoilers within them	Example of grouped spoilers that also have nested spoilers within them
=== Block-level spoilers ===
Block-level elements may be made into spoilers by using the class "spoiler-block", e.g. ....
Example 	Results in
[[File:Example.jpg|150px]]A pretty flower	A pretty flower
=== Image spoilers ===
Images can be marked as a spoiler by wrapping the image in an element with the class "spoiler-image". This is similar to a spoiler block, but instead blurs the image and shows the text "Spoiler" over the image. The element tag may be either or .
Using an image class (via [[File:Example.jpg|class=spoiler-image]]) is NOT supported.
Image spoilers are not unspoiled when an image, a button, or a link within them is clicked. When a spoiler contains a link, (clickable) image, or button, any clicks on those elements are ignored when unspoiling.
You can also use this style of spoiler with any block level container, not only images. The class "spoiler-blur" is an analogue to "spoiler-image" if you prefer this naming.
Example 	Results in
[[File:Example.png|150px]] 	
[[File:Example.jpg|150px]]A pretty flower	A pretty flower
=== Gallery spoilers ===
All images within a gallery can be marked as a spoiler by wrapping the gallery in an element with the class spoiler-gallery This gives each image within the gallery the spoiler-image class.
Example.png | An example image
Example.jpg | Another example image
== Toggle all spoilers ==
SpoilerTags adds a button to the side-tools (the area with the floating buttons to the top left of the page) which can be clicked to toggle all the spoilers that are currently on the page. When toggling, all conditions that might prevent a spoiler from being shown or hidden are ignored. The button only appears if the config option spoilAllButton is true, and there are spoilers on the page.
The icon in the button represents the current "spoiled" state of spoilers on the page:
* If any spoilers are unspoiled (hidden), an crossed eye appears, indicating that there is hidden content.
* If any spoilers are spoiled (visible), an eye appears, indicating that all content is visible.
When hovering over the button, the icon switches to the opposite, representing the desired state:
* When hovered, if any spoilers are unspoiled (hidden), an eye appears, indicating that clicking the button will show spoilers.
* When hovered, if any spoilers are spoiled (visible), an crossed eye appears, indicating that clicking the button will hide spoilers.
The button automatically updates as items on the page are toggled:
* If any spoilers are unspoiled, clicking it will spoil all.
* If all spoilers are spoiled, clicking it will unspoil all.
* If all spoilers are spoiler and all cannot be unspoiled, the button will be disabled.
== Configuration ==
=== User-set config ===
For users, the spoiler settings menu is the most accessible mode of configuration. It provides a basic level of configuration, focusing on usability options rather than behaviour and appearance. It can be accessed via the "My Tools" menu in the toolbar, or via the gear icon shown while hovering over the "Show all spoilers" button in the side tools. Options set here will override any options set via community or personal JavaScript for the wiki.
For anonymous users, these settings are saved to the cookie fandom_spoilertags, which persists on the browser+device and applies for the user across all wikis with SpoilerTags installed. Cookies are used instead of localStorage (Web Storage API), as localStorage is limited to only the original host address and not to other subdomains (wikis). This cookie expires 30 days after it is last accessed. To reduce the amount of additional data that has to be transmitted, the user config is stored as a bitmask.
For logged-in users, these settings are saved to the user option userjs-spoilertags via the Options API, which will persist for the specific user across all devices and all wikis while they are logged in
The options available are:
Option 	JS equivalent 	Notes
Enable spoilers 	disable 	(negation)
Always show spoilers 	spoilAll 	
Hide "show all spoilers" button	spoilAllButton	(negation)
Hide settings from toolbar 	toolbarButton 	(negation)
Disable hovering 	hover 	(negation)
Allow text selection 	selection 	
=== JavaScript options ===
You can use the JavaScript object window.spoilerTags to configure the default behaviour of spoilers across the wiki. This can be done in either community JS or personal JS.
For example, in MediaWiki:Common.js:
window.spoilerTags = {
 unspoil: true,
 selection: true,
 tooltip: true,
 tooltipText: "Click to reveal"
};
Unless you have a reason to, using the CSS variables below over their JavaScript counterparts is recommended. This is due to the delay between loading the CSS, and this script loading and applying the configuration. Additionally, CSS doesn't require a script review and can be changed at any time.
Option 	Data type	Default 	Description
disable 	Boolean 	false 	Used to disable spoilers entirely (typically set in personal JS). When this occurs, the CSS and JS is still loaded, but all spoiler classes are stripped from the page when it loaded and the script is not run otherwise.
spoilAll 	Boolean 	false 	Used to initially show all spoilers on pages (typically set in personal JS), additionally locking them in the spoiled state. This may also be set by clicking the "lock" button that appears while hovering over the spoil all button (you must have shown all spoilers first).
spoilAllButton 	Boolean 	true 	When true, the "spoil all" button is shown in the page side tools, which allows users to quickly toggle all spoilers on the page. When false, it is disabled.
toolbarButton 	Boolean 	true 	When true, a menu item is added to "My Tools" in the toolbar, which allows users to set some spoiler settings that will apply only to themselves. When false, this shortcut is not created.
unspoil 	Boolean 	true 	When true, spoilers may be re-hidden after they are shown. When false, spoilers may only be shown, but never hidden again.
This can also be set per-spoiler via data-unspoil, which overrides this setting.
hover 	Boolean 	true 	When false, spoilers don't respond to hover or focus (tab) events (they will not display a tooltip, be highlighted, or change visually in any way as a result).
Sets the class "spoiler-hover-disabled" on the <body> element.
selection 	Boolean 	false 	When true, the spoiler text may be text selected and copied when it is unspoiled.
Sets the class "spoiler-selection-disabled" on the <body> element.
tooltip 	Boolean 	true 	Used to enable or disable the tooltip above the spoiler, indicating to the user that they need to click to reveal the spoiler.
Sets the class "spoiler-tooltips-disabled" on the <body> element
tooltipText 	String 	"Click to reveal"	Used to set the default text shown in the tooltip. If unset, an i18n message will be used instead, which changes depending on the language of the wiki.
Sets the CSS variable "--spoiler-tooltip-text" to this value when present.
imageButtonText	String 	"SPOILER" 	Used to set the text shown in the image spoiler button. If unset, an i18n message will be used instead, which changes depending on the language of the wiki.
Sets the CSS variable "--spoiler-image-button-text" to this value when present.
===HTML attributes===
Data attributes may be used to modify the behaviour per-spoiler. Attributes default to the value of their respective JavaScript config option when unset, and override this option when set. They may be modified at runtime, but can also be overridden by CSS variables.
Nested spoilers do not inherit attribute values from their ancestor elements, but grouped spoilers do.
Attribute 	Data type 	Description 	
data-unspoil 	Boolean 	This spoiler can be unspoiled	This spoiler can be unspoiled
This spoiler cannot be unspoiled	This spoiler cannot be unspoiled	 	
===CSS variables===
The following CSS variables are used to influence the styles of spoilers. Overrides may be applied in your CSS (on the :root psuedo-element or any selector that would target spoilers), or inline with style="--spoiler-tooltip-text: 'Test'", for example.
An example of style overrides, set in your wiki CSS:
:root {
	--spoiler-hide-color: red;
	--spoiler-hover-color: yellow;
	--spoiler-show-color: green;
 --spoiler-tooltip-text: "There be spoilers ahead cap'n!";
 --spoiler-image-button-text: "ARRR";
}
If preferred, you can also copy the stylesheet locally (from MediaWiki:SpoilerTags.css on Dev, to the same page on your own wiki), make whatever changes you want, and add a local import in Common.css or Fandomdesktop.css.
The JavaScript options listed above have some counterparts in the CSS variables below, which are used to determine their default value. These are overridden by your own CSS. So if you've set a tooltipText in the config but also have --spoiler-tooltip-text: "xyz"; in your CSS, the CSS will take precedence.
Variable 	Default 	Description
--spoiler-hide-color 	rgba(0, 0, 0, 0.75) 	The colour of the spoiler background in its hidden state.
--spoiler-hover-color 	rgba(var(--theme-body-text-color--rgb), 0.1) 	The color of the spoiler background when the user hovers over it. Using a non-transparent color here is preferable, if possible.
--spoiler-show-color 	rgba(var(--theme-body-text-color--rgb), 0.1) 	The color of the spoiler background in its revealed state.
--spoiler-tooltip-color 	var(--theme-page-background-color--secondary)	The color of the tooltip background.
--spoiler-tooltip-text-color 	var(--theme-page-text-color) 	The color of the text shown in the tooltip.
--spoiler-tooltip-text 	"Click to reveal" 	The text shown in the tooltip when the spoiler is hovered over while it is hidden. The default value is filled in by i18n.
--spoiler-image-button-color 	rgba(0, 0, 0, 0.75) 	The background color of the image spoiler button.
--spoiler-image-button-text-color	#ebebeb 	The color of the text in the image spoiler button.
--spoiler-image-button-text 	"SPOILER" 	The text shown in the image spoiler button. The default value is filled in by i18n.
--spoiler-image-blur 	20px 	For image spoilers, this is the blur radius passed to the blur() function in CSS, which determines how much the image is blurred. 20px is enough to where most content becomes unrecognizable, but still retains the general shape and color of the image.
--spoiler-tags-loaded 	1 	Internal use only, to identify the SpoilerTags stylesheet on which to apply defaults from JS. If copying the stylesheet locally instead of importing it from dev, ensure this variable is preserved.
=== URL parameters ===
The following URL parameters may be passed to any page on a wiki with SpoilerTags installed:
* stsafemode - Ignore all configurations and use the defaults instead.
* stspoilall - Show all spoilers on the page.
* stdisable - Overrides the "disabled" value in the config. May be set to 0 (enabled) or 1 (disabled)
== Notes ==
* Interactions between text selection events (like double or triple clicking on text) and spoilers may be annoying to users. You may wish to disable selection if your spoiler is expected to be copied or selected. To help mitigate this, the script will not toggle a spoiler on or off if any part of it is included within the selected/highlighted text.
* Spoiler tooltips use a modified version of CSS3Tooltip, and are applied in the form of psuedo-elements, which will cause conflicts with existing styles that make use of psuedo-elements when used on the same container.
* Deeply nesting inline elements within a spoiler is not recommended, generally you should keep your spoilers as flat as possible to reduce the liklihood of conflicting styles. If you do happen to find a styling issue when using elements within a spoiler, feel free to mention it on the talk page.
* This script exports a collection of its properties to window.dev.spoilerTags, and uses the hook "dev.spoilerTags" (passing it this collection), which fires after all spoilers have been initialized and are ready. You can listen for this event with:
: 
mw.hook("dev.spoilerTags").add(function(spoilerTags) {
 // Do something with spoilerTags here
});
== Known issues ==
* Tooltips near the top of the page are hidden due to overflow. As a workaround, you can override it with .page-content { overflow-x: initial; }, or add enough space so that the tooltip doesn't go beyond the bounds of the page content. A script solution might be to create tooltips on a JS-created container instead.
* Script imported on mobile does not function correctly. Fixing this will involve creating a mobile-specific stylesheet and modifying some of the script to account for input differences on mobile.
== Breaking changes ==
* July 3, 2024: Modified how multiline spoilers work to be more intuitive and less clumsy. Previously, you had to encapsulate text in the in spans e.g. TextMore text. Now you can omit the spans. This may break styles for some users, and may yield different spoiler text depending on the formatting of the multiline spoiler.
== Dependencies ==
;Scripts
* i18n-js
* WDSIcons
;Modules
* oojs-ui-core
* oojs-ui-windows
* mediawiki.widgets
* mediawiki.user
== See also ==
* Heimu
* SpoilerBlur
* SpoilerAlert
* MediaWiki's built-in collapsible elements