Difference between revisions of "MediaWiki:Common.js"
From AppleGamingWiki, the wiki about gaming on M1 Apple silicon Macs
m (latest PCGW copy) |
m (remove windows and linux release dates, moved some templates over to more AGW appropriate) |
||
| Line 1,003: | Line 1,003: | ||
type: 'encapsulate', | type: 'encapsulate', | ||
options: { | options: { | ||
| − | pre: "===[[Glossary:Save game cloud syncing|Save game cloud syncing]]===\n{{Save game cloud syncing | + | pre: "===[[Glossary:Save game cloud syncing|Save game cloud syncing]]===\n{{Save game cloud syncing\n|epic games launcher = \n|epic games launcher notes = \n|gog galaxy = \n|gog galaxy notes = \n|origin = \n|origin notes = \n|steam cloud = \n|steam cloud notes = \n}}\n", |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
ownline: true | ownline: true | ||
} | } | ||
| Line 1,021: | Line 1,009: | ||
}, | }, | ||
'apitable': { | 'apitable': { | ||
| − | label: ' | + | label: 'macOS Compatibility', |
type: 'button', | type: 'button', | ||
icon: '//images.pcgamingwiki.com/c/cb/Editor_Icon_-_API.svg', | icon: '//images.pcgamingwiki.com/c/cb/Editor_Icon_-_API.svg', | ||
| Line 1,027: | Line 1,015: | ||
type: 'encapsulate', | type: 'encapsulate', | ||
options: { | options: { | ||
| − | pre: " | + | pre: "{{Compatibility/macOS\n|native = na\n|native notes = \n|rosetta 2 = na\n|rosetta 2 notes = \n|ios-ipados app = na\n|ios-ipados app notes = \n|crossover = na\n|crossover notes = \n|wine = na\n|wine notes = \n|parallels = na\n|parallels notes = \n|windows 10 arm = na\n|windows 10 arm notes = \n|linux arm = na\n|linux arm notes = \n}}", |
ownline: true | ownline: true | ||
} | } | ||
| Line 1,101: | Line 1,089: | ||
options: { | options: { | ||
pre: "{{Infobox game/row/engine|", | pre: "{{Infobox game/row/engine|", | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
post: "}}", | post: "}}", | ||
ownline: true | ownline: true | ||
| Line 1,124: | Line 1,100: | ||
options: { | options: { | ||
pre: "{{Infobox game/row/date|OS X|", | pre: "{{Infobox game/row/date|OS X|", | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
peri: "Month dd, yyyy", | peri: "Month dd, yyyy", | ||
post: "}}", | post: "}}", | ||
Revision as of 19:29, 29 September 2022
//<nowiki>
/* ===== FIX: Suppress link click on user menu on tablet devices =========================================================================================================================
*
* Fixes the user menu being inaccessible on tablets due to touch events going through to to the user page link.
*
* @source https://stackoverflow.com/a/15558423
*
*/
function fixTabletLinks() {
if(document.createEvent("TouchEvent")) { // using document.createEvent is more reliable than navigator (Modernizr uses this practice)
$("div#personal-bar-flyout > div > a").each(function() { // have to use an `each` here - either a jQuery `each` or a `for(...)` loop
var onClick; // this will be a function
var firstClick = function() {
$("a").trigger("JWUnhover"); // triggering hoverfix reset if any link gets touched
onClick = secondClick;
return false;
};
secondClick = function() {
onClick = firstClick;
return true;
};
onClick = firstClick;
$(this).click(function() {
if (Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) > 800)
{
return onClick();
} else {
return true;
}
});
$(this).bind('JWUnhover', function(){ onClick = firstClick; });
});
}
}
try {
fixTabletLinks();
} catch (e) {
// Suppress console error if device does not support touch events.
}
/* ===== FUNCTIONALITY : Style pages based on categories =========================================================================================================================
*
* Adds CSS classes to the body tag based on the categories this page belongs to
*
* @source https://www.mediawiki.org/wiki/Snippets/Style_pages_based_on_categories
* @revision 2016-01-18
*
*/
(function($, mw) {
var fn = function() {
var cats = mw.config.get('wgCategories'), newClasses;
if (cats) {
newClasses = $.map(cats, function(el) {
return 'cat-' + encodeURIComponent(el.replace(/[ .]/g, '_')).replace(/%/g, '_');
}).join(' ');
$(document.body).addClass(newClasses);
}
};
if (document.body) {
fn();
} else {
$(fn);
}
})(jQuery, mw);
/* ===== FUNCTIONALITY : System Requirements Tabs =========================================================================================================================
*
*/
function sysreqTabs() {
// run tab code only if tabNav exists
if ($('#tabNav')[0]) {
// store the number of sysreq tables
var sysreqcount = $('.sysreq').length
// run tab code only if there are at least two sysreq tables
if (sysreqcount > 1) {
// Make tab nav visible
$('#tabNav').css('display', 'inline-block');
// hide sysreq table headings
$('.sysreq_heading').css('display', 'none');
// remove tabs for missing tables (if not already removed by the template)
$('.sysreq_PC_booter')[0] || $('#sysreq_PC_booter').remove();
$('.sysreq_DOS')[0] || $('#sysreq_DOS').remove();
$('.sysreq_Windows_3x')[0] || $('#sysreq_Windows_3x').remove();
$('.sysreq_Windows')[0] || $('#sysreq_Windows').remove();
$('.sysreq_Mac_OS')[0] || $('#sysreq_Mac_OS').remove();
$('.sysreq_OS_X')[0] || $('#sysreq_OS_X').remove();
$('.sysreq_Linux')[0] || $('#sysreq_Linux').remove();
// find first tab and apply style
var firstTab = document.querySelector('.sysreqTab:first-child');
$(firstTab).addClass('selectedTab');
// ensure table matching first tab is visible (in case page order does not match OS order expected by tab template)
$('.sysreq').css('display', 'none');
$('.' + $(firstTab).attr('id')).css('display', 'block');
// apply table visibility and tab style changes when tabs are clicked
$('.sysreqTab').click(function() {
$('.sysreqTab').removeClass('selectedTab');
$(this).addClass('selectedTab');
$('.sysreq').css('display', 'none');
$('.' + $(this).attr('id')).css('display', 'block');
})
// remove tabs table if there are fewer than two sysreq tables
} else {
$('#tabNav').remove();
}
}
}
$(sysreqTabs);
/* ===== FUNCTIONALITY : Extend the WYSIWYG wiki editor with new functions =========================================================================================================================
*
*/
// Retrieves todays date according to UTC and slices out the YYYY-MM-DD part of it.
var TodaysDateUTC = new Date().toJSON().slice(0,10);
var customizeToolbar = function() {
// Add a hook handler.
mw.hook('wikiEditor.toolbarReady').add(function($textarea) {
// Removes the 'file' tool (the Image-icon) as this makes use of [[File:]] and not the preferred {{Image|}} template.
$textarea.wikiEditor('removeFromToolbar', {
'section': 'main',
'group': 'insert',
'tool': 'file'
});
// Removes the 'reference' tool as using the templates are the preferred way of referencing stuff
$textarea.wikiEditor('removeFromToolbar', {
'section': 'main',
'group': 'insert',
'tool': 'reference'
});
// Removes the 'redirect' tool as it have been moved to the search group
$textarea.wikiEditor('removeFromToolbar', {
'section': 'advanced',
'group': 'insert',
'tool': 'redirect'
});
// Adds a custom Image icon to the insert group
$textarea.wikiEditor('addToToolbar', {
'section': 'main',
'group': 'insert',
'tools': {
'smile': {
label: 'Image',
type: 'button',
icon: '/w/load.php?modules=oojs-ui.styles.icons-media&image=image&format=rasterized&lang=en&skin=overclocked',
action: {
type: 'encapsulate',
options: {
pre: "{{Image|",
peri: "File.png|Caption",
post: "}}",
ownline: true
}
}
}
}
});
// Adds a custom Redirect icon to the search group
$textarea.wikiEditor('addToToolbar', {
'section': 'advanced',
'group': 'search',
'tools': {
'redirect': {
label: 'Redirect',
type: 'button',
icon: '/w/load.php?modules=oojs-ui.styles.icons-content&image=articleRedirect&format=rasterized&lang=en&skin=overclocked',
action: {
type: 'encapsulate',
options: {
pre: "#REDIRECT [[",
peri: "Target page name",
post: "]]",
ownline: true
}
}
}
}
});
// Adds custom byttons to the advanced > insert group
$textarea.wikiEditor('addToToolbar', {
'section': 'advanced',
'group': 'insert',
'tools': {
'fixbox': {
label: 'Fixbox',
type: 'button',
icon: '//images.pcgamingwiki.com/d/d8/Editor_Icon_-_Fixbox.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{Fixbox|description=",
peri: "Name",
post: "|ref=<ref>Reference</ref>|fix=\n}}",
ownline: true
}
}
}
}
});
// Adds custom templates in a new group to the right of the advanced > insert group
$textarea.wikiEditor('addToToolbar', {
'section': 'advanced',
'groups': {
'insert-sections': {
'label': '',
'tools': {
'availabilityrow': {
label: 'Availability row',
type: 'button',
icon: '//images.pcgamingwiki.com/6/67/Editor_Icon_-_Availability_Table_Row.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{Availability/row| ",
peri: "store",
post: " | id | DRM | notes | Key | OS }}",
ownline: true
}
}
},
'dlcrow': {
label: 'DLC row',
type: 'button',
icon: '//images.pcgamingwiki.com/9/9f/Editor_Icon_-_DLCrow.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{DLC/row| ",
peri: "Name",
post: " | notes | OS }}",
ownline: true
}
}
},
'gamedataconfigrow': {
label: 'Game data row - config',
type: 'button',
icon: '//images.pcgamingwiki.com/0/0c/Editor_Icon_-_Game_Data_Row.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{Game data/config|",
peri: "System",
post: "|Path}}",
ownline: true
}
}
},
'gamedatasavesrow': {
label: 'Game data row - saves',
type: 'button',
icon: '//images.pcgamingwiki.com/0/0c/Editor_Icon_-_Game_Data_Row.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{Game data/saves|",
peri: "System",
post: "|Path}}",
ownline: true
}
}
},
'langrow': {
label: 'Language row',
type: 'button',
icon: '//images.pcgamingwiki.com/2/22/Editor_Icon_-_Localizations.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{L10n/switch \n |language = ",
post: "\n |interface = true\n |audio = \n |subtitles = \n |notes = \n |fan = \n |ref = \n}}",
ownline: true
}
}
}
}
}
}
});
// Adds custom templates in a new group to the right of the advanced > insert-sections group
$textarea.wikiEditor('addToToolbar', {
'section': 'advanced',
'groups': {
'main-templates': {
'label': '',
'tools': {
'reftemplates': {
label: 'Reference',
type: 'select',
list: {
'refuser': {
label: 'Checked by user',
action: {
type: 'encapsulate',
options: {
pre: "<ref>{{Refcheck|user=" + (mw.config.get('wgUserName') !== null ? mw.config.get('wgUserName') : "User") + "|date=" + TodaysDateUTC + "|comment=Comment (optional)}}</ref>"
}
}
},
'refurl': {
label: 'URL',
action: {
type: 'encapsulate',
options: {
pre: "<ref>{{Refurl|url=|title=|date=" + TodaysDateUTC + "}}</ref>"
}
}
},
'refsnippet': {
label: 'Snippet from URL',
action: {
type: 'encapsulate',
options: {
pre: "<ref>{{Refurl|url=|title=|date=" + TodaysDateUTC + "|snippet=}}</ref>"
}
}
},
'cn': {
label: 'Citation needed',
action: {
type: 'encapsulate',
options: {
pre: "{{cn|date=" + TodaysDateUTC + "|reason=}}"
}
}
},
'dubious': {
label: 'Dubious',
action: {
type: 'encapsulate',
options: {
pre: "{{dubious|date=" + TodaysDateUTC + "|reason=}}"
}
}
},
'note': {
label: 'Note',
action: {
type: 'encapsulate',
options: {
pre: "{{note|",
peri: "The content of the note here.",
post: "}}"
}
}
}
}
},
'termsection': {
label: 'Term',
type: 'select',
list: {
'categorygeneral': {
label: 'General:',
},
'drm': {
label: '· DRM',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|DRM}}"
}
}
},
'fmv': {
label: '· FMV (full motion video)',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|FMV}}"
}
}
},
'categoryvr': {
label: 'VR:',
},
'hmd': {
label: '· HMD (head-mounted display)',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|HMD}}"
}
}
},
'categorygraphics': {
label: 'Graphics:',
},
'sdr': {
label: '· SDR',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|SDR}}"
}
}
},
'hdr': {
label: '· HDR (modern HDR)',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|HDR}}"
}
}
},
'hdrr': {
label: '· HDR Rendering ("old-school HDR")',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|HDR Rendering}}"
}
}
},
'categoryscaling': {
label: 'Scaling:',
},
'horplus': {
label: '· Hor+',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Hor+}}"
}
}
},
'vertminus': {
label: '· Vert-',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Vert-}}"
}
}
},
'letterbox': {
label: '· Letterbox',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Letterbox}}"
}
}
},
'pillarbox': {
label: '· Pillarbox',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Pillarbox}}"
}
}
},
'anamorphic': {
label: '· Anamorphic',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Anamorphic}}"
}
}
},
'pixelbased': {
label: '· Pixel-based',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Pixel-based}}"
}
}
},
'pixelperfect': {
label: '· Pixel-perfect / integer scaling',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Pixel-perfect}}"
}
}
},
'stretch': {
label: '· Stretch',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Stretch}}"
}
}
},
'noscaling': {
label: '· No scaling',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|No scaling}}"
}
}
},
'nearestneighbor': {
label: '· Nearest-neighbor (algorithm)',
action: {
type: 'encapsulate',
options: {
pre: "{{Term|Nearest-neighbor}}"
}
}
}
}
},
'filepath': {
label: 'Path',
type: 'select',
list: {
'categorygeneral': {
label: 'General:',
},
'pathgame': {
label: '· Path to game',
action: {
type: 'encapsulate',
options: {
pre: "{{P|game}}"
}
}
},
'pathlocalized': {
label: '· Localized folder or file name',
action: {
type: 'encapsulate',
options: {
pre: "{{LocalizedPath|",
peri: "Folder or file name",
post: "}}"
}
}
},
'pathuid': {
label: '· User ID',
action: {
type: 'encapsulate',
options: {
pre: "{{P|uid}}"
}
}
},
'pathsteam': {
label: '· Steam install folder',
action: {
type: 'encapsulate',
options: {
pre: "{{P|steam}}"
}
}
},
'pathubisoftconnect': {
label: '· Ubisoft Connect install folder',
action: {
type: 'encapsulate',
options: {
pre: "{{P|ubisoftconnect}}"
}
}
},
'categorywindowsdisk': {
label: 'Windows (disk):',
},
'pathuserprofile': {
label: '· %USERPROFILE%',
action: {
type: 'encapsulate',
options: {
pre: "{{P|userprofile}}"
}
}
},
'pathuserprofiledocuments': {
label: '· %USERPROFILE%\\Documents',
action: {
type: 'encapsulate',
options: {
pre: "{{P|userprofile\\Documents}}"
}
}
},
'pathappdata': {
label: '· AppData\\Roaming (%APPDATA%)',
action: {
type: 'encapsulate',
options: {
pre: "{{P|appdata}}"
}
}
},
'pathlocalappdata': {
label: '· AppData\\Local (%LOCALAPPDATA%)',
action: {
type: 'encapsulate',
options: {
pre: "{{P|localappdata}}"
}
}
},
'pathlocallowappdata': {
label: '· AppData\\LocalLow',
action: {
type: 'encapsulate',
options: {
pre: "{{P|userprofile\\appdata\\locallow}}"
}
}
},
'pathpublic': {
label: '· %PUBLIC%',
action: {
type: 'encapsulate',
options: {
pre: "{{P|public}}"
}
}
},
'pathprogramdata': {
label: '· %PROGRAMDATA%',
action: {
type: 'encapsulate',
options: {
pre: "{{P|programdata}}"
}
}
},
'pathwindir': {
label: '· %WINDIR%',
action: {
type: 'encapsulate',
options: {
pre: "{{P|windir}}"
}
}
},
'categorywindowsregistry': {
label: 'Windows (registry):',
},
'pathhkcu': {
label: '· HKEY_CURRENT_USER',
action: {
type: 'encapsulate',
options: {
pre: "{{P|hkcu}}"
}
}
},
'pathhklm': {
label: '· HKEY_LOCAL_MACHINE',
action: {
type: 'encapsulate',
options: {
pre: "{{P|hklm}}"
}
}
},
'pathwow64': {
label: '· Wow6432Node',
action: {
type: 'encapsulate',
options: {
pre: "{{P|wow64}}"
}
}
},
'categoryosx': {
label: 'OS X:',
},
'pathosxhome': {
label: '· Home folder (osx)',
action: {
type: 'encapsulate',
options: {
pre: "{{P|osxhome}}"
}
}
},
'categorylinux': {
label: 'Linux:',
},
'pathlinuxhome': {
label: '· Home folder (linux)',
action: {
type: 'encapsulate',
options: {
pre: "{{P|linuxhome}}"
}
}
},
'pathlinuxxdgdatahome': {
label: '· XDG data home',
action: {
type: 'encapsulate',
options: {
pre: "{{P|xdgdatahome}}"
}
}
},
'pathxdgconfighome': {
label: '· XDG config home',
action: {
type: 'encapsulate',
options: {
pre: "{{P|xdgconfighome}}"
}
}
}
}
},
'seesection': {
label: 'See...',
type: 'select',
list: {
'categoryvideo': {
label: 'Video:',
},
'widescreen': {
label: '· Widescreen resolution',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Widescreen resolution|Widescreen resolution]]."
}
}
},
'multimonitor': {
label: '· Multi-monitor',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Multi-monitor|Multi-monitor]]."
}
}
},
'ultrawidescreen': {
label: '· Ultra-widescreen',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Ultra-widescreen|Ultra-widescreen]]."
}
}
},
'4kultrahd': {
label: '· 4K Ultra HD',
action: {
type: 'encapsulate',
options: {
pre: "See [[#4K Ultra HD|4K Ultra HD]]."
}
}
},
'fieldofview': {
label: '· Field of view (FOV)',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Field of view (FOV)|Field of view (FOV)]]."
}
}
},
'windowed': {
label: '· Windowed',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Windowed|Windowed]]."
}
}
},
'borderless': {
label: '· Borderless fullscreen windowed',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Borderless fullscreen windowed|Borderless fullscreen windowed]]."
}
}
},
'anisotropic': {
label: '· Anisotropic filtering (AF)',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Anisotropic filtering (AF)|Anisotropic filtering (AF)]]."
}
}
},
'antialiasing': {
label: '· Anti-aliasing (AA)',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Anti-aliasing (AA)|Anti-aliasing (AA)]]."
}
}
},
'vsync': {
label: '· Vertical sync (Vsync)',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Vertical sync (Vsync)|Vertical sync (Vsync)]]."
}
}
},
'highframe': {
label: '· High frame rate',
action: {
type: 'encapsulate',
options: {
pre: "See [[#High frame rate|High frame rate]]."
}
}
},
'hdr': {
label: '· High dynamic range display (HDR)',
action: {
type: 'encapsulate',
options: {
pre: "See [[#High dynamic range display (HDR)|High dynamic range display (HDR)]]."
}
}
},
'raytracing': {
label: '· Ray tracing',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Ray tracing|Ray tracing]]."
}
}
},
'colorblind': {
label: '· Color blind mode',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Color blind mode|Color blind mode]]."
}
}
},
'categoryinput': {
label: 'Input:',
},
'remapping': {
label: '· Remapping',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Remapping|Remapping]]."
}
}
},
'mouseaccel': {
label: '· Mouse acceleration',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Mouse acceleration|Mouse acceleration]]."
}
}
},
'controllersupport': {
label: '· Controller support',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Controller support|Controller support]]."
}
}
},
'controllerremap': {
label: '· Controller remapping',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Controller remapping|Controller remapping]]."
}
}
},
'touchscreen': {
label: '· Touchscreen optimised',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Touchscreen|Touchscreen]]."
}
}
},
'categoryvr': {
label: 'VR:',
},
'oculus': {
label: '· Oculus Rift',
action: {
type: 'encapsulate',
options: {
pre: "See [[#Oculus Rift|Oculus Rift]]."
}
}
}
}
}
}
}
}
});
// Adds custom controls to the toolbar
$textarea.wikiEditor('addToToolbar', {
sections: {
'section-templates': {
type: 'toolbar',
label: 'Sections',
groups: {
templates: {
'label': '',
'tools': {
'introduction': {
label: 'Introduction',
type: 'button',
icon: '//images.pcgamingwiki.com/4/40/Editor_Icon_-_Introduction.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{Introduction\n|introduction = ",
post: "\n\n|release history = \n\n|current state = \n}}",
ownline: true
}
}
},
'dlc': {
label: 'DLC',
type: 'button',
icon: '//images.pcgamingwiki.com/3/38/Editor_Icon_-_DLCtable.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{DLC|\n",
peri: "{{DLC/row| Name | notes | OS }}",
post: "\n}}",
ownline: true
}
}
},
'cloud': {
label: 'Cloud syncing',
type: 'button',
icon: '//images.pcgamingwiki.com/b/bc/Editor_Icon_-_Cloud_Sync.svg',
action: {
type: 'encapsulate',
options: {
pre: "===[[Glossary:Save game cloud syncing|Save game cloud syncing]]===\n{{Save game cloud syncing\n|epic games launcher = \n|epic games launcher notes = \n|gog galaxy = \n|gog galaxy notes = \n|origin = \n|origin notes = \n|steam cloud = \n|steam cloud notes = \n}}\n",
ownline: true
}
}
},
'apitable': {
label: 'macOS Compatibility',
type: 'button',
icon: '//images.pcgamingwiki.com/c/cb/Editor_Icon_-_API.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{Compatibility/macOS\n|native = na\n|native notes = \n|rosetta 2 = na\n|rosetta 2 notes = \n|ios-ipados app = na\n|ios-ipados app notes = \n|crossover = na\n|crossover notes = \n|wine = na\n|wine notes = \n|parallels = na\n|parallels notes = \n|windows 10 arm = na\n|windows 10 arm notes = \n|linux arm = na\n|linux arm notes = \n}}",
ownline: true
}
}
},
'middlewaretable': {
label: 'Middleware',
type: 'button',
icon: '//images.pcgamingwiki.com/c/c2/Editor_Icon_-_Middleware.svg',
action: {
type: 'encapsulate',
options: {
pre: "===Middleware===\n{{Middleware\n|physics = \n|physics notes = \n|audio = \n|audio notes = \n|interface = \n|interface notes = \n|input = \n|input notes = \n|cutscenes = \n|cutscenes notes = \n|multiplayer = \n|multiplayer notes= \n|anticheat = \n|anticheat notes = \n}}",
ownline: true
}
}
},
'sysreq': {
label: 'System requirements',
type: 'button',
icon: '//images.pcgamingwiki.com/4/4b/Editor_Icon_-_System_Requirements.svg',
action: {
type: 'encapsulate',
options: {
pre: "{{System requirements\n|OSfamily = ",
peri: "System",
post: "\n|minOS = \n|minCPU = \n|minRAM = \n|minHD = \n|minGPU = \n\n|recOS = \n|recCPU = \n|recRAM = \n|recHD = \n|recGPU = \n}}",
ownline: true
}
}
},
'infoboxdrop': {
label: 'Infobox row',
type: 'select',
list: {
'infoboxdeveloper': {
label: 'Developer',
action: {
type: 'encapsulate',
options: {
pre: "{{Infobox game/row/developer|",
post: "}}",
ownline: true
}
}
},
'infoboxporter': {
label: 'Porter',
action: {
type: 'encapsulate',
options: {
pre: "{{Infobox game/row/porter|",
post: "|OS}}",
ownline: true
}
}
},
'infoboxpublisher': {
label: 'Publisher',
action: {
type: 'encapsulate',
options: {
pre: "{{Infobox game/row/publisher|",
post: "}}",
ownline: true
}
}
},
'infoboxengine': {
label: 'Engine',
action: {
type: 'encapsulate',
options: {
pre: "{{Infobox game/row/engine|",
post: "}}",
ownline: true
}
}
},
'infoboxdateosx': {
label: 'OS X release date',
action: {
type: 'encapsulate',
options: {
pre: "{{Infobox game/row/date|OS X|",
peri: "Month dd, yyyy",
post: "}}",
ownline: true
}
}
},
'infoboxreception': {
label: 'Reception rows',
action: {
type: 'encapsulate',
options: {
post: "|reception = \n{{Infobox game/row/reception|Metacritic|link|rating}}\n{{Infobox game/row/reception|OpenCritic|link|rating}}\n{{Infobox game/row/reception|IGDB|link|rating}}",
ownline: true
}
}
},
'infobox taxonomy': {
label: 'Taxonomy rows',
action: {
type: 'encapsulate',
options: {
post: "|taxonomy = \n{{Infobox game/row/taxonomy/monetization | }}\n{{Infobox game/row/taxonomy/microtransactions | }}\n{{Infobox game/row/taxonomy/modes | }}\n{{Infobox game/row/taxonomy/pacing | }}\n{{Infobox game/row/taxonomy/perspectives | }}\n{{Infobox game/row/taxonomy/controls | }}\n{{Infobox game/row/taxonomy/genres | }}\n{{Infobox game/row/taxonomy/sports | }}\n{{Infobox game/row/taxonomy/vehicles | }}\n{{Infobox game/row/taxonomy/art styles | }}\n{{Infobox game/row/taxonomy/themes | }}\n{{Infobox game/row/taxonomy/series | }}",
ownline: true
}
}
}
}
}
}
}
}
}
}
});
/* Adds fade out on mouse out for the dropdown menus */
/* disabled 2022-09-17 due to seeminlgy causing issues with menus in certain scenarios
$('div.tool-select > div.menu > div').mouseleave(function() {
$(this).fadeOut();
});
*/
});
};
// Check if we're editing a page, and if so customize the toolbar
if (['edit', 'submit'].indexOf(mw.config.get('wgAction')) !== -1) {
$.when(
mw.loader.using( 'ext.wikiEditor' ),
$.ready
).then( customizeToolbar );
}
// Add achors in headers
function addAnchorInHeaders() {
$('span.mw-headline', '#mw-content-text').each(function() {
var $this = $(this);
if ($this.attr('id') !== undefined) {
$('<span class="mw-linkhere"></span>').text(' • ').append(
$('<a></a>').text('Link').attr({title: 'Link', href: '#'+$this.attr('id')})
).appendTo(this);
}
});
}
$(addAnchorInHeaders);
/* ===== FUNCTIONALITY : Collapsible TOC levels =========================================================================================================================
*
* Adds collapsible TOC levels copied directly over from the French Wiktionary.
*
* Source Code:
* - Javascript : https://fr.wiktionary.org/wiki/MediaWiki:Gadget-SommaireDeveloppable.js
*
* 2019-07-21 - Added expand/collapse all options + storing the setting in a cookie.
* 2019-07-20 - Localization, updated to automatically expand Essential Improvements, various changes.
* 2019-07-19 - Initial commit, with a minor change to CollapsibleTOC_LabelNeither.
*
*/
/* -----------------------------------------------------------------------------------------------------
Table of contents which shows by default only level 1 headers (so as not to clutter the screen)
but whose higher depth levels are viewable (or expandable) by clicking a [+] button (or [-]),
in a way similar to what classic file browsers do.
--------------------------------------------------------------------------------------------------------
Authors:
* Eiku April 25, 2012 for most of the code.
* ArséniureDeGallium for details and various additions.
* Inspired by WikiTravel (http://files.wikitravel.org/mw/skins/common/wikibits.js?0.1), but made differently
--------------------------------------------------------------------------------------------------------*/
/*----------------- config variables ------------------------------------------*/
// Which pages should we expand the first level 1 section automatically on?
var CollapsibleTOC_PreDevelop = (mw.config.get('wgNamespaceNumber') === 0); // only for the main namespace
// Should we number the sections in the TOC?
var CollapsibleTOC_NumberHeadings = mw.user.options.get('numberheadings'); // use the user's preferences, aka is "auto-number headings" enabled or not?
// What characters to use to indicate expanded/collapsed status?
var CollapsibleTOC_LabelExpand = '[+]';
var CollapsibleTOC_LabelCollapse = '[-]';
var CollapsibleTOC_LabelNeither = ' ';
// Help tooltips
var CollapsibleTOC_TooltipExpand = 'This section has subsections, click to expand them';
var CollapsibleTOC_TooltipCollapse = 'Click to collapse the subsections';
var CollapsibleTOC_TooltipNeither = 'This section has no subsections';
/*------------------- hooks the function ----------------------------------------------*/
// This is where the possible presence of the {{CollapsibleTOC}} template is managed in the page
// * CollapsibleTOC_NO has priority
// * CollapsibleTOC_YES afterwards
// * for the rest of the majority of pages it's the namespace that decides
var NoCollapsibleTOC = document.getElementById('CollapsibleTOC_NO');
var YesCollapsibleTOC = document.getElementById('CollapsibleTOC_YES') || (mw.config.get('wgNamespaceNumber') === 0);
if ((!NoCollapsibleTOC) && (YesCollapsibleTOC)) {
$(CollapsibleTOC_Main);
$(CollapsibleTOC_Toggle);
}
/*----------------- support function ------------------------------------------*/
jQuery.fn.cleanWhitespace = function() {
this.contents().filter(
function() { return (this.nodeType == 3 && !/\S/.test(this.nodeValue)); })
.remove();
return this;
};
/*----------------- main function ------------------------------------------*/
function CollapsibleTOC_Main() {
alwaysExpand = $.cookie( 'pcgw_alwaysexpand' ) === '1';
// for each reasonable level of depth of table of contents
for (var level = 1; level < 7; level++) {
// get the list of <li> class elements "toclevel-n"
var lis = $('.toclevel-' + level);
if (lis.length === 0) break; // no need to continue, there is no deeper level
// for each
for (var _i = 0; _i < lis.length; _i++) {
var li = lis[_i];
// check that it is a <li>
if (li.tagName.toLowerCase() != 'li') continue;
var plus;
if (li.children.length >= 2) {
var ul = li.children[1];
// check that the 2nd child is a <ul>
if (ul.tagName.toLowerCase() != 'ul') continue;
// add (later) a clickable element
plus = document.createElement('a');
// add the 'collapsibletoc-section-toggle' CSS class to it
plus.className = "collapsibletoc-section-toggle";
// if we click on it and that ul is visible, it hides it, and vice versa
plus.onclick = (function(ul, plus) {
return function() {
if (ul.style.display == 'none') {
ul.style.display = 'block';
plus.title = CollapsibleTOC_TooltipCollapse;
plus.innerHTML = CollapsibleTOC_LabelCollapse;
} else {
ul.style.display = 'none';
plus.title = CollapsibleTOC_TooltipExpand;
plus.innerHTML = CollapsibleTOC_LabelExpand;
}
};
})(ul, plus);
if (alwaysExpand) {
ul.style.display = 'block';
plus.title = CollapsibleTOC_TooltipCollapse;
plus.innerHTML = CollapsibleTOC_LabelCollapse;
} else {
// hide by default, except for the first one section (to advertise)
if ((level == 1) && (li.children[0].innerText == "Essential improvements") && CollapsibleTOC_PreDevelop) {
ul.style.display = 'block';
plus.title = CollapsibleTOC_TooltipCollapse;
plus.innerHTML = CollapsibleTOC_LabelCollapse;
} else {
ul.style.display = 'none';
plus.title = CollapsibleTOC_TooltipExpand;
plus.innerHTML = CollapsibleTOC_LabelExpand;
}
}
plus.style.cursor = 'pointer'; // cursor to indicate its a link
} else {
// add a visual element that takes as many spaces for same width as + and - for elements without child headers
plus = document.createElement('span');
//plus.title = CollapsibleTOC_TooltipNeither;
plus.innerHTML = CollapsibleTOC_LabelNeither;
plus.style.cursor = 'default'; // force default pointer to hide the fact that users are currently hovering over a bunch of non-breaking spaces ( )
// add the 'collapsibletoc-section-neither' CSS class to it
plus.className = "collapsibletoc-section-neither";
}
// use a monospaced font for the expand/collapse links so that they have the same width regardless of character
plus.style.fontFamily = 'courier, monospace, mono';
plus.style.color = '#000';
plus.style.fontWeight = 'bold';
plus.style.textDecoration = 'none';
// insert the link as the 1st node of the current <li>
$(li).children().first().before(plus);
}
}
//---- visibility of auto-number headings ----
var spans = $('.tocnumber');
if (CollapsibleTOC_NumberHeadings) {
for (var _i = 0; _i < spans.length; _i++) {
spans[_i].style.display = "inline";
}
} /* else {
for (var _i = 0; _i < spans.length; _i++) {
spans[_i].style.display = "none";
}
// in Chrome, if you leave the display: table-cell by default,
// a line break inserts between the added [+] and the <a> that follows.
$('.toctext').css('display', 'inline');
} */ // Unnecessary
$('.toclevel-1 a').cleanWhitespace();
}
function CollapsibleTOC_ToggleAll(s) {
for (var level = 1; level < 7; level++) {
// get the list of <li> class elements "toclevel-n"
var lis = $('.toclevel-' + level);
if (lis.length === 0) break; // no need to continue, there is no deeper level
// for each
for (var _i = 0; _i < lis.length; _i++) {
var li = lis[_i];
// check that it is a <li>
if (li.tagName.toLowerCase() != 'li') continue;
if (li.children.length >= 3) {
var toggle = li.children[0];
var ul = li.children[2];
// check that the 3rd child is a <ul>
if (ul.tagName.toLowerCase() != 'ul') continue;
if (s == 'block') {
ul.style.display = 'block';
toggle.title = CollapsibleTOC_TooltipCollapse;
toggle.innerHTML = CollapsibleTOC_LabelCollapse;
} else {
ul.style.display = 'none';
toggle.title = CollapsibleTOC_TooltipExpand;
toggle.innerHTML = CollapsibleTOC_LabelExpand;
}
}
}
}
}
function CollapsibleTOC_Toggle() {
// Table of contents toggle
var $content = $('#mw-content-text');
var $toc, $tocTitle, $tocToggleLink, $tocList, alwaysExpand;
$toc = $content.find( '#toc' );
$tocTitle = $content.find( '.toctitle' );
$tocToggleLink = $content.find( '#alwaysToggle' );
$tocList = $toc.find( 'ul' ).eq( 0 );
// Hide/show the table of contents element
function toggleSections() {
if ( $.cookie( 'pcgw_alwaysexpand' ) === '1' ) {
CollapsibleTOC_ToggleAll('none');
$tocToggleLink.html( '<span class="tocExpandAll">e</span>' );
$.cookie( 'pcgw_alwaysexpand', null, {
expires: 365,
path: '/'
} );
} else {
CollapsibleTOC_ToggleAll('block');
$tocToggleLink.html( '<span class="tocCollapseAll">c</span>' );
$.cookie( 'pcgw_alwaysexpand', '1', {
expires: 365,
path: '/'
} );
}
}
// Only add it if there is a complete TOC and it doesn't
// have a toggle added already
if ( $toc.length && $tocTitle.length && $tocList.length && !$tocToggleLink.length ) {
alwaysExpand = $.cookie( 'pcgw_alwaysexpand' ) === '1';
$tocToggleLink = $( '<a href="#" id="togglelink"></a>' )
.html( alwaysExpand ? '<span class="tocCollapseAll">c</span>' : '<span class="tocExpandAll">e</span>' )
.click( function ( e ) {
e.preventDefault();
toggleSections();
} );
$tocTitle.append(
$tocToggleLink
.wrap( '<span class="toctoggle collapsibletoc-toggle"></span>' )
.parent()
.prepend( ' [' )
.append( '] ' )
);
if ( alwaysExpand ) {
CollapsibleTOC_ToggleAll('block');
}
}
}
/* ===== FUNCTIONALITY : Adds ReferenceTooltips =========================================================================================================================
*
* Adds ReferenceTooltips copied directly over from the Russian Wikipedia.
*
* Information: https://www.mediawiki.org/w/index.php?title=Topic:Ueqlcc482l9yw8gv&topic_showPostId=ueqlcc6fkvg15qzj#flow-post-ueqlcc6fkvg15qzj
*
* Source Code:
* - Javascript : https://ru.wikipedia.org/wiki/MediaWiki:Gadget-referenceTooltips.js
* - CSS : https://ru.wikipedia.org/wiki/MediaWiki:Gadget-referenceTooltips.css
*
* 2019-02-22 - Merged with latest version from https://ru.wikipedia.org/wiki/MediaWiki:Gadget-referenceTooltips.js
* 2018-09-17 - Updated + added english text (Google Translated)
*
*/
// See [[mw:Reference Tooltips]]
var referenceTooltips = function () {
// ruwiki settings
var REF_LINK_SELECTOR = '.reference, a[href^="#CITEREF"]',
COMMENTED_TEXT_CLASS = 'ts-comment-commentedText',
COMMENTED_TEXT_SELECTOR = '.' + COMMENTED_TEXT_CLASS + ', abbr[title]';
mw.messages.set( {
'rt-settings': 'Tooltip settings', // hover alt text on the cog wheel shown on the tooltips.
'rt-settings-title': 'Reference Tooltips settings',
'rt-save': 'Save settings',
'rt-cancel': 'Cancel',
'rt-enable': 'Enable Reference Tooltips',
'rt-disable': 'Disable Reference Tooltips',
'rt-activationMethod': 'Tooltip is activated by:',
'rt-hovering': 'hovering',
'rt-clicking': 'clicking',
'rt-delay': 'Delay before the tooltip appears (in milliseconds):',
'rt-tooltipsForComments': 'Show tooltips over <span title="Tooltip example" class="'+ COMMENTED_TEXT_CLASS +'" style="border-bottom: 1px dotted; cursor: help;">underlined text</span> in the style of Reference Tooltips (allows you to see tooltips on devices without mouse support).',
'rt-disabledNote': 'Once disabled, Reference Tooltips can be re-enabled using a link in the footer of the page.',
'rt-ready': 'Done',
'rt-enable-footer': 'Enable Reference Tooltips', // Text as shown in the footer among the category links
'rt-enabled': 'Reference Tooltips have been enabled.' // Shown on the popup in the top right corner when re-enabling Reference Tooltips from the footer.
} );
// "Global" variables
var SECONDS_IN_A_DAY = 60 * 60 * 24,
CLASSES = {
FADE_IN_DOWN: 'rt-fade-in-down',
FADE_IN_UP: 'rt-fade-in-up',
FADE_OUT_DOWN: 'rt-fade-out-down',
FADE_OUT_UP: 'rt-fade-out-up'
},
IS_TOUCHSCREEN = 'ontouchstart' in document.documentElement,
// Quite a rough check for mobile browsers, a mix of what is advised at
// https://stackoverflow.com/a/24600597 (sends to
// https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent)
// and https://stackoverflow.com/a/14301832
IS_MOBILE = /Mobi|Android/i.test( navigator.userAgent ) ||
typeof window.orientation !== 'undefined',
CLIENT_NAME = $.client.profile().name,
settingsString, settings, enabled, delay, activatedByClick, tooltipsForComments, cursorWaitCss,
windowManager,
$body = $( document.body ),
$window = $( window );
function rt( $content ) {
// Popups gadget
if ( window.pg ) {
return;
}
var teSelector,
settingsDialogOpening = false;
function setSettingsCookie() {
mw.cookie.set(
'RTsettings',
Number( enabled ) + '|' + delay + '|' + Number( activatedByClick ) + '|' +
Number( tooltipsForComments ),
{ path: '/', expires: 90 * SECONDS_IN_A_DAY }
);
}
function enableRt() {
enabled = true;
setSettingsCookie();
$( '.rt-enableItem' ).remove();
rt( $content );
mw.notify( mw.msg( 'rt-enabled' ) );
}
function disableRt() {
$content.find( teSelector ).removeClass( 'rt-commentedText' ).off( '.rt' );
$body.off( '.rt' );
$window.off( '.rt' );
}
function addEnableLink() {
// #footer-places – Vector
// #f-list – Timeless, Monobook, Modern
// parent of #footer li – Cologne Blue
// var $footer = $( '#footer-places, #f-list' );
var $footer = $( '#mw-normal-catlinks ul' );
if ( !$footer.length ) {
$footer = $( '#footer li' ).parent();
}
$footer.append(
$( '<li>' )
.addClass( 'rt-enableItem' )
.append(
$( '<a>' )
.text( mw.msg( 'rt-enable-footer' ) )
.attr( 'href', 'javascript:' )
.click( function ( e ) {
e.preventDefault();
enableRt();
} )
)
);
}
function TooltippedElement( $element ) {
var tooltip,
te = this;
function onStartEvent( e ) {
var showRefArgs;
if ( activatedByClick ) {
e.preventDefault();
}
if ( !te.noRef ) {
showRefArgs = [ $( this ) ];
if ( te.type !== 'supRef' ) {
showRefArgs.push( e.pageX, e.pageY );
}
te.showRef.apply( te, showRefArgs );
}
}
function onEndEvent() {
if ( !te.noRef ) {
te.hideRef();
}
}
if ( !$element ) {
return;
}
// TooltippedElement.$element and TooltippedElement.$originalElement will be different when
// the first is changed after its cloned version is hovered in a tooltip
this.$element = $element;
this.$originalElement = $element;
if ( this.$element.is( REF_LINK_SELECTOR ) ) {
if ( this.$element.prop( 'tagName' ) === 'SUP' ) {
this.type = 'supRef';
} else {
this.type = 'harvardRef';
}
} else {
this.type = 'commentedText';
this.comment = this.$element.attr( 'title' );
if ( !this.comment ) {
return;
}
this.$element.addClass('rt-commentedText');
}
this.$element.on( activatedByClick ?
{ 'click.rt': onStartEvent } :
{ 'mouseenter.rt': onStartEvent, 'mouseleave.rt': onEndEvent }
);
this.hideRef = function ( immediately ) {
clearTimeout( te.showTimer );
if ( this.type === 'commentedText' ) {
this.$element.attr( 'title', this.comment );
}
if ( this.tooltip && this.tooltip.isPresent ) {
if ( activatedByClick || immediately ) {
this.tooltip.hide();
} else {
this.hideTimer = setTimeout( function () {
te.tooltip.hide();
}, 200 );
}
} else if ( this.$ref && this.$ref.hasClass( 'rt-target' ) ) {
this.$ref.removeClass( 'rt-target' );
if ( activatedByClick ) {
$body.off( 'click.rt touchstart.rt', this.onBodyClick );
}
}
};
this.showRef = function ( $element, ePageX, ePageY ) {
// Popups gadget
if ( window.pg ) {
disableRt();
return;
}
var tooltipInitiallyPresent = this.tooltip && this.tooltip.isPresent;
function reallyShow() {
var viewportTop, refOffsetTop, teHref;
if ( !te.$ref && !te.comment ) {
teHref = te.type === 'supRef' ?
te.$element.find( 'a' ).attr( 'href' ) :
te.$element.attr( 'href' ); // harvardRef
te.$ref = teHref &&
$( '#' + $.escapeSelector( teHref.slice( 1 ) ) );
if ( !te.$ref || !te.$ref.length || !te.$ref.text() ) {
te.noRef = true;
return;
}
}
if ( !tooltipInitiallyPresent && !te.comment ) {
viewportTop = $window.scrollTop();
refOffsetTop = te.$ref.offset().top;
if ( !activatedByClick &&
viewportTop < refOffsetTop &&
viewportTop + $window.height() > refOffsetTop + te.$ref.height() &&
// There can be gadgets/scripts that make references horizontally scrollable.
$window.width() > te.$ref.offset().left + te.$ref.width()
) {
// Highlight the reference itself
te.$ref.addClass( 'rt-target' );
return;
}
}
if ( !te.tooltip ) {
te.tooltip = new Tooltip( te );
if ( !te.tooltip.$content.length ) {
return;
}
}
// If this tooltip is called from inside another tooltip. We can't define it
// in the constructor since a ref can be cloned but have the same Tooltip object;
// so, Tooltip.parent is a floating value.
te.tooltip.parent = te.$element.closest( '.rt-tooltip' ).data( 'tooltip' );
if ( te.tooltip.parent && te.tooltip.parent.disappearing ) {
return;
}
te.tooltip.show();
if ( tooltipInitiallyPresent ) {
if ( te.tooltip.$element.hasClass( 'rt-tooltip-above' ) ) {
te.tooltip.$element.addClass( CLASSES.FADE_IN_DOWN );
} else {
te.tooltip.$element.addClass( CLASSES.FADE_IN_UP );
}
return;
}
te.tooltip.calculatePosition( ePageX, ePageY );
$window.on( 'resize.rt', te.onWindowResize );
}
// We redefine this.$element here because e.target can be a reference link inside
// a reference tooltip, not a link that was initially assigned to this.$element
this.$element = $element;
if ( this.type === 'commentedText' ) {
this.$element.attr( 'title', '' );
}
if ( activatedByClick ) {
if ( tooltipInitiallyPresent ||
( this.$ref && this.$ref.hasClass( 'rt-target' ) )
) {
return;
} else {
setTimeout( function () {
$body.on( 'click.rt touchstart.rt', te.onBodyClick );
}, 0 );
}
}
if ( activatedByClick || tooltipInitiallyPresent ) {
reallyShow();
} else {
this.showTimer = setTimeout( reallyShow, delay );
}
};
this.onBodyClick = function ( e ) {
if ( !te.tooltip && !te.$ref.hasClass( 'rt-target' ) ) {
return;
}
var $current = $( e.target );
function contextMatchesParameter( parameter ) {
return this === parameter;
}
// The last condition is used to determine cases when a clicked tooltip is the current
// element's tooltip or one of its descendants
while ( $current.length &&
( !$current.hasClass( 'rt-tooltip' ) ||
!$current.data( 'tooltip' ) ||
!$current.data( 'tooltip' ).upToTopParent(
contextMatchesParameter, [ te.tooltip ],
true
)
)
) {
$current = $current.parent();
}
if ( !$current.length ) {
te.hideRef();
}
};
this.onWindowResize = function () {
te.tooltip.calculatePosition();
};
}
function Tooltip( te ) {
function openSettingsDialog() {
var settingsDialog, settingsWindow;
if ( cursorWaitCss ) {
cursorWaitCss.disabled = true;
}
function SettingsDialog() {
SettingsDialog.parent.call( this );
}
OO.inheritClass( SettingsDialog, OO.ui.ProcessDialog );
SettingsDialog.static.name = 'settingsDialog';
//SettingsDialog.static.size = 'large';
SettingsDialog.static.title = mw.msg( 'rt-settings-title' );
SettingsDialog.static.actions = [
{
modes: 'basic',
action: 'save',
label: mw.msg( 'rt-save' ),
flags: [ 'primary', 'progressive' ]
},
{
modes: 'basic',
label: mw.msg( 'rt-cancel' ),
flags: 'safe'
},
{
modes: 'disabled',
action: 'deactivated',
label: mw.msg( 'rt-ready' ),
flags: [ 'primary', 'progressive' ]
}
];
SettingsDialog.prototype.initialize = function () {
var dialog = this;
SettingsDialog.parent.prototype.initialize.apply( this, arguments );
this.enableOption = new OO.ui.RadioOptionWidget( {
label: mw.msg( 'rt-enable' )
} );
this.disableOption = new OO.ui.RadioOptionWidget( {
label: mw.msg( 'rt-disable' )
} );
this.enableSelect = new OO.ui.RadioSelectWidget( {
items: [ this.enableOption, this.disableOption ],
classes: [ 'rt-enableSelect' ]
} );
this.enableSelect.selectItem( this.enableOption );
this.enableSelect.on( 'choose', function ( item ) {
if ( item === dialog.disableOption ) {
dialog.activationMethodSelect.setDisabled( true );
dialog.delayInput.setDisabled( true );
dialog.tooltipsForCommentsCheckbox.setDisabled( true );
} else {
dialog.activationMethodSelect.setDisabled( false );
dialog.delayInput.setDisabled( dialog.clickOption.isSelected() );
dialog.tooltipsForCommentsCheckbox.setDisabled( false );
}
} );
this.hoverOption = new OO.ui.RadioOptionWidget( {
label: mw.msg( 'rt-hovering' )
} );
this.clickOption = new OO.ui.RadioOptionWidget( {
label: mw.msg( 'rt-clicking' )
} );
this.activationMethodSelect = new OO.ui.RadioSelectWidget( {
items: [ this.hoverOption, this.clickOption ]
} );
this.activationMethodSelect.selectItem( activatedByClick ?
this.clickOption :
this.hoverOption
);
this.activationMethodSelect.on( 'choose', function ( item ) {
if ( item === dialog.clickOption ) {
dialog.delayInput.setDisabled( true );
} else {
dialog.delayInput.setDisabled( dialog.clickOption.isSelected() );
}
} );
this.activationMethodField = new OO.ui.FieldLayout( this.activationMethodSelect, {
label: mw.msg( 'rt-activationMethod' ),
align: 'top'
} );
this.delayInput = new OO.ui.NumberInputWidget( {
input: { value: delay },
step: 50,
min: 0,
max: 5000,
disabled: activatedByClick,
classes: [ 'rt-numberInput' ]
} );
this.delayField = new OO.ui.FieldLayout( this.delayInput, {
label: mw.msg( 'rt-delay' ),
align: 'top'
} );
this.tooltipsForCommentsCheckbox = new OO.ui.CheckboxInputWidget( {
selected: tooltipsForComments
} );
this.tooltipsForCommentsField = new OO.ui.FieldLayout(
this.tooltipsForCommentsCheckbox,
{
label: new OO.ui.HtmlSnippet( mw.msg( 'rt-tooltipsForComments' ) ),
align: 'inline',
classes: [ 'rt-tooltipsForCommentsField' ]
}
);
new TooltippedElement(
this.tooltipsForCommentsField.$element.find( '.' + COMMENTED_TEXT_CLASS )
);
this.fieldset = new OO.ui.FieldsetLayout();
this.fieldset.addItems( [
this.activationMethodField,
this.delayField,
this.tooltipsForCommentsField
] );
this.panelSettings = new OO.ui.PanelLayout( {
padded: true,
expanded: false
} );
this.panelSettings.$element.append(
this.enableSelect.$element,
$( '<hr>' ).addClass( 'rt-settingsFormSeparator' ),
this.fieldset.$element
);
this.panelDisabled = new OO.ui.PanelLayout( {
padded: true,
expanded: false
} );
this.panelDisabled.$element.append(
$( '<table>' )
.addClass( 'rt-disabledHelp' )
.append(
$( '<tr>' ).append(
$( '<td>' ).append(
$( '<img>' ).attr( 'src', '/images/b/b3/Reference_Tooltips_footer.png' )
),
$( '<td>' )
.addClass( 'rt-disabledNote' )
.text( mw.msg( 'rt-disabledNote' ) )
)
)
);
this.stackLayout = new OO.ui.StackLayout( {
items: [ this.panelSettings, this.panelDisabled ]
} );
this.$body.append( this.stackLayout.$element );
};
SettingsDialog.prototype.getSetupProcess = function ( data ) {
return SettingsDialog.parent.prototype.getSetupProcess.call( this, data )
.next( function () {
this.stackLayout.setItem( this.panelSettings );
this.actions.setMode( 'basic' );
}, this );
};
SettingsDialog.prototype.getActionProcess = function ( action ) {
var dialog = this;
if ( action === 'save' ) {
return new OO.ui.Process( function () {
var newDelay = Number( dialog.delayInput.getValue() );
enabled = dialog.enableOption.isSelected();
if ( newDelay >= 0 && newDelay <= 5000 ) {
delay = newDelay;
}
activatedByClick = dialog.clickOption.isSelected();
tooltipsForComments = dialog.tooltipsForCommentsCheckbox.isSelected();
setSettingsCookie();
if ( enabled ) {
dialog.close();
disableRt();
rt( $content );
} else {
dialog.actions.setMode( 'disabled' );
dialog.stackLayout.setItem( dialog.panelDisabled );
disableRt();
addEnableLink();
}
} );
} else if ( action === 'deactivated' ) {
dialog.close();
}
return SettingsDialog.parent.prototype.getActionProcess.call( this, action );
};
SettingsDialog.prototype.getBodyHeight = function () {
return this.stackLayout.getCurrentItem().$element.outerHeight( true );
//return 400; // sets height of the dialog to ~430px
};
tooltip.upToTopParent( function adjustRightAndHide() {
if ( this.isPresent ) {
if ( this.$element[ 0 ].style.right ) {
this.$element.css(
'right',
'+=' + ( window.innerWidth - $window.width() )
);
}
this.te.hideRef( true );
}
} );
if ( !windowManager ) {
windowManager = new OO.ui.WindowManager();
$body.append( windowManager.$element );
}
settingsDialog = new SettingsDialog();
windowManager.addWindows( [ settingsDialog ] );
settingsWindow = windowManager.openWindow( settingsDialog );
settingsWindow.opened.then( function () {
settingsDialogOpening = false;
} );
settingsWindow.closed.then( function () {
windowManager.clearWindows();
} );
}
var tooltip = this;
// This variable can change: one tooltip can be called from a harvard-style reference link
// that is put into different tooltips
this.te = te;
switch ( this.te.type ) {
case 'supRef':
this.id = 'rt-' + this.te.$originalElement.attr( 'id' );
this.$content = this.te.$ref
.children()
.not( '.mw-cite-backlink' )
.clone( true );
break;
case 'harvardRef':
this.id = 'rt-' + this.te.$originalElement.closest( 'li' ).attr( 'id' );
this.$content = this.te.$ref
.clone( true )
.removeAttr( 'id' );
break;
case 'commentedText':
this.id = 'rt-' + String( Math.random() ).slice( 2 );
this.$content = $( document.createTextNode( this.te.comment ) );
break;
}
if ( !this.$content.length ) {
return;
}
this.insideWindow = Boolean( this.te.$element.closest( '.oo-ui-window' ).length );
this.$element = $( '<div>' )
.addClass( 'rt-tooltip' )
.attr( 'id', this.id )
.attr( 'role', 'tooltip' )
.data( 'tooltip', this );
if ( this.insideWindow ) {
this.$element.addClass( 'rt-tooltip-insideWindow' );
}
// We need the $content interlayer here in order for the settings icon to have the correct
// margins
this.$content = this.$content
.wrapAll( '<div>' )
.parent()
.addClass( 'rt-tooltipContent' )
.appendTo( this.$element );
if ( !activatedByClick ) {
this.$element
.mouseenter( function () {
if ( !tooltip.disappearing ) {
tooltip.upToTopParent( function () {
this.show();
} );
}
} )
.mouseleave( function ( e ) {
// https://stackoverflow.com/q/47649442 workaround. Relying on relatedTarget
// alone has pitfalls: when alt-tabbing, relatedTarget is empty too
if ( CLIENT_NAME !== 'chrome' ||
( !e.originalEvent ||
e.originalEvent.relatedTarget !== null ||
!tooltip.clickedTime ||
$.now() - tooltip.clickedTime > 50
)
) {
tooltip.upToTopParent( function () {
this.te.hideRef();
} );
}
} )
.click( function () {
tooltip.clickedTime = $.now();
} );
}
if ( !this.insideWindow ) {
$( '<div>' )
.addClass( 'rt-settingsLink' )
.attr( 'title', mw.msg( 'rt-settings' ) )
.click( function () {
if ( settingsDialogOpening ) {
return;
}
settingsDialogOpening = true;
if ( mw.loader.getState( 'oojs-ui' ) !== 'ready' ) {
if ( cursorWaitCss ) {
cursorWaitCss.disabled = false;
} else {
cursorWaitCss = mw.util.addCSS( 'body { cursor: wait; }' );
}
}
mw.loader.using( [ 'oojs', 'oojs-ui' ], openSettingsDialog );
} )
.prependTo( this.$content );
}
// Tooltip tail element is inside tooltip content element in order for the tooltip
// not to disappear when the mouse is above the tail
$( '<div>' )
.addClass( 'rt-tooltipTail' )
.prependTo( this.$element );
this.disappearing = false;
this.show = function () {
this.disappearing = false;
clearTimeout( this.te.hideTimer );
clearTimeout( this.te.removeTimer );
this.$element
.removeClass( CLASSES.FADE_OUT_DOWN )
.removeClass( CLASSES.FADE_OUT_UP );
if ( !this.isPresent ) {
$body.append( this.$element );
}
this.isPresent = true;
};
this.hide = function () {
var tooltip = this;
tooltip.disappearing = true;
if ( tooltip.$element.hasClass( 'rt-tooltip-above' ) ) {
tooltip.$element
.removeClass( CLASSES.FADE_IN_DOWN )
.addClass( CLASSES.FADE_OUT_UP );
} else {
tooltip.$element
.removeClass( CLASSES.FADE_IN_UP )
.addClass( CLASSES.FADE_OUT_DOWN );
}
tooltip.te.removeTimer = setTimeout( function () {
if ( tooltip.isPresent ) {
tooltip.$element.detach();
if ( tooltip.tailCss ) {
tooltip.tailCss.disabled = true;
}
if ( activatedByClick ) {
$body.off( 'click.rt touchstart.rt', tooltip.te.onBodyClick );
}
$window.off( 'resize.rt', tooltip.te.onWindowResize );
tooltip.isPresent = false;
}
}, 200 );
};
this.calculatePosition = function ( ePageX, ePageY ) {
var teElement, teOffsets, teOffset, tooltipTailOffsetX, tooltipTailLeft,
offsetYCorrection = 0;
if ( this.tailCss ) {
this.tailCss.disabled = true;
}
teElement = this.te.$element.get( 0 );
if ( ePageX !== undefined ) {
tooltipTailOffsetX = ePageX;
teOffsets = teElement.getClientRects &&
teElement.getClientRects() ||
teElement.getBoundingClientRect();
if ( teOffsets.length > 1 ) {
for (var i = teOffsets.length - 1; i >= 0; i--) {
if ( ePageY >= Math.round( $window.scrollTop() + teOffsets[i].top ) &&
ePageY <= Math.round(
$window.scrollTop() + teOffsets[i].top + teOffsets[i].height
)
) {
teOffset = teOffsets[i];
}
}
}
}
if ( !teOffset ) {
teOffset = teElement.getClientRects &&
teElement.getClientRects()[0] ||
teElement.getBoundingClientRect();
}
teOffset = {
top: $window.scrollTop() + teOffset.top,
left: $window.scrollLeft() + teOffset.left,
width: teOffset.width,
height: teOffset.height
};
if ( !tooltipTailOffsetX ) {
tooltipTailOffsetX = ( teOffset.left * 2 + teOffset.width ) / 2;
}
if ( CLIENT_NAME === 'msie' && this.te.type === 'supRef' ) {
offsetYCorrection = -Number(
this.te.$element.parent().css( 'font-size' ).replace( 'px', '' )
) / 2;
}
this.$element.css( {
top: teOffset.top - this.$element.outerHeight() - 7 + offsetYCorrection,
left: tooltipTailOffsetX - 20,
right: ''
} );
// Is it squished against the right side of the page?
if ( this.$element.offset().left + this.$element.outerWidth() > $window.width() - 1 ) {
this.$element.css( {
left: '',
right: 0
} );
tooltipTailLeft = tooltipTailOffsetX - this.$element.offset().left - 5;
}
// Is a part of it above the top of the screen?
if ( teOffset.top < this.$element.outerHeight() + $window.scrollTop() + 6 ) {
this.$element
.removeClass( 'rt-tooltip-above' )
.addClass( 'rt-tooltip-below' )
.addClass( CLASSES.FADE_IN_UP )
.css( {
top: teOffset.top + teOffset.height + 9 + offsetYCorrection
} );
if ( tooltipTailLeft ) {
this.tailCss = mw.util.addCSS(
'#' + $.escapeSelector( tooltip.id ) + ' .rt-tooltipTail { left: ' +
( tooltipTailLeft + 12 ) + 'px; }'
);
}
} else {
this.$element
.removeClass( 'rt-tooltip-below' )
.addClass( 'rt-tooltip-above' )
.addClass( CLASSES.FADE_IN_DOWN )
// A fix for cases when a tooltip shown once is then wrongly positioned when it
// is shown again after a window resize. We just repeat what is above.
.css( {
top: teOffset.top - this.$element.outerHeight() - 7 + offsetYCorrection
} );
if ( tooltipTailLeft ) {
// 12 is the tail element width/height
this.tailCss = mw.util.addCSS(
'#' + $.escapeSelector( tooltip.id ) + ' .rt-tooltipTail { left: ' +
tooltipTailLeft + 'px; }'
);
}
}
};
// Run some function for all the tooltips up to the top one in a tree. Its context will be
// the tooltip, while its parameters may be passed to Tooltip.upToTopParent as an array
// in the second parameter. If the third parameter passed to ToolTip.upToTopParent is true,
// the execution stops when the function in question returns true for the first time,
// and ToolTip.upToTopParent returns true as well.
this.upToTopParent = function ( func, parameters, stopAtTrue ) {
var returnValue,
currentTooltip = this;
do {
returnValue = func.apply( currentTooltip, parameters );
if ( stopAtTrue && returnValue ) {
break;
}
} while ( currentTooltip = currentTooltip.parent );
if ( stopAtTrue ) {
return returnValue;
}
};
}
if ( !enabled ) {
addEnableLink();
return;
}
teSelector = REF_LINK_SELECTOR;
if ( tooltipsForComments ) {
teSelector += ', ' + COMMENTED_TEXT_SELECTOR;
}
$content.find( teSelector ).each( function () {
new TooltippedElement( $( this ) );
} );
}
try {
settingsString = mw.cookie.get( 'RTsettings' );
} catch (e) {
}
if ( settingsString ) {
settings = settingsString.split( '|' );
enabled = Boolean( Number( settings[ 0 ] ) );
delay = Number( settings[ 1 ] );
activatedByClick = Boolean( Number( settings[ 2 ] ) );
// The forth value was added later, so we provide for a default value. See comments below
// for why we use "IS_TOUCHSCREEN && IS_MOBILE".
tooltipsForComments = settings[ 3 ] === undefined ?
IS_TOUCHSCREEN && IS_MOBILE :
Boolean( Number( settings[ 3 ] ) );
} else {
enabled = true;
delay = 200;
// Since the mobile browser check is error-prone, adding IS_MOBILE condition here would probably
// leave cases where a user interacting with the browser using touches doesn't know how to call
// a tooltip in order to switch to activation by click. Some touch-supporting laptop users
// interacting by touch (though probably not the most popular use case) would not be happy too.
activatedByClick = IS_TOUCHSCREEN;
// Arguably we shouldn't convert native tooltips into gadget tooltips for devices that have
// mouse support, even if they have touchscreens (there are laptops with touchscreens).
// IS_TOUCHSCREEN check here is for reliability, since the mobile check is prone to false
// positives.
tooltipsForComments = IS_TOUCHSCREEN && IS_MOBILE;
}
mw.hook( 'wikipage.content' ).add( rt ); /* Default: Fired when wiki content is being added to the DOM */
/* mw.hook( 'wikipage.categories' ).add( rt ); */ /* Custom: Fired when categories are being added to the DOM */
};
$(referenceTooltips);
/* Run stuff after page have finished loading */
jQuery( document ).ready( function ( $ ) {
/* Stupid Firefox DOM related bug: Forces a refresh of the elements to fix rendering bugs */
$(".article-image").hide().show(0);
/* Hides Cargo's refresh option */
// $("#ca-cargo-purge").remove(); // Disabled 2022-09-05 following infrastructure upgrade and SMW's disabling to restore Cargo's refresh option
/* Move Gamesplanet row to the top (but not above Retail row) */
var rowGamesplanet = $('.table-availability-body-row').find('[data-sort-value="Gamesplanet"]').parent();
var rowRetail = $('.table-availability-body-row').find('[data-sort-value="aaa- Retail"]').last().parent();
if (rowRetail.length > 0)
{
rowGamesplanet.insertAfter ( rowRetail );
} else {
rowGamesplanet.insertAfter ( rowGamesplanet.parent().find('tr:first-child') );
}
} );
//</nowiki>