Comparing sensitive data, confidential files or internal emails?

Most legal and privacy policies prohibit uploading sensitive data online. Diffchecker Desktop ensures your confidential information never leaves your computer. Work offline and compare documents securely.

Untitled diff

Created Diff never expires
21 removals
873 lines
17 additions
869 lines
// See [[mw:Reference Tooltips]]
// See [[mw:Reference Tooltips]]
// Source https://en.wikipedia.org/wiki/MediaWiki:Gadget-ReferenceTooltips.js
// Source https://en.wikipedia.org/wiki/MediaWiki:Gadget-ReferenceTooltips.js


( function () {
( function () {


// enwiki settings
// enwiki settings
var REF_LINK_SELECTOR = '.reference, a[href^="#CITEREF"]',
var REF_LINK_SELECTOR = '.reference, a[href^="#CITEREF"]',
COMMENTED_TEXT_CLASS = '',
COMMENTED_TEXT_CLASS = '',
COMMENTED_TEXT_SELECTOR = ( COMMENTED_TEXT_CLASS ? '.' + COMMENTED_TEXT_CLASS + ', ' : '') +
COMMENTED_TEXT_SELECTOR = ( COMMENTED_TEXT_CLASS ? '.' + COMMENTED_TEXT_CLASS + ', ' : '') +
'abbr[title]';
'abbr[title]';


mw.messages.set( {
mw.messages.set( {
'rt-settings': 'Reference Tooltips settings',
'rt-settings': 'Подешавања тултипова за референце',
'rt-enable-footer': 'Enable Reference Tooltips',
'rt-enable-footer': 'Омогући тултипове за референце',
'rt-settings-title': 'Reference Tooltips',
'rt-settings-title': 'Тултипови за референце',
'rt-save': 'Save',
'rt-save': 'Сачувај',
'rt-cancel': 'Cancel',
'rt-cancel': 'Откажи',
'rt-enable': 'Enable',
'rt-enable': 'Омогући',
'rt-disable': 'Disable',
'rt-disable': 'Онемогући',
'rt-activationMethod': 'Tooltip appears when',
'rt-activationMethod': 'Начин активирања тултипа',
'rt-hovering': 'hovering',
'rt-hovering': 'ховеровање',
'rt-clicking': 'clicking',
'rt-clicking': 'кликање',
'rt-delay': 'Delay before the tooltip appears (in milliseconds)',
'rt-delay': 'Одлагање пре него што се тултип појави (у милисекундама)',
'rt-tooltipsForComments': 'Show tooltips over <span title="Tooltip example" class="' + ( COMMENTED_TEXT_CLASS || 'rt-commentedText' ) + '" style="border-bottom: 1px dotted; cursor: help;">text with a dotted underline</span> in Reference Tooltips style (allows to see such tooltips on devices with no mouse support)',
'rt-tooltipsForComments': 'Прикажи тултипове изнад <span title="Пример тултипа" class="' + ( COMMENTED_TEXT_CLASS || 'rt-commentedText' ) + '" style="border-bottom: 1px dotted; cursor: help;">текст подвучен испрекиданом линијом</span> у стилу тултипова за референце (дозвољава да видите тултипове на уређајима који немају могућност миша)',
'rt-disabledNote': 'You can re-enable Reference Tooltips using a link in the footer of the page.',
'rt-disabledNote': 'Можете поново омогућити тултипове за референце користећи везу у заглављу странице.',
'rt-done': 'Done',
'rt-done': 'Урађено',
'rt-enabled': 'Reference Tooltips are enabled'
'rt-enabled': 'Тултипови за референце су омогућени'
} );
} );


// "Global" variables
// "Global" variables
var SECONDS_IN_A_DAY = 60 * 60 * 24,
var SECONDS_IN_A_DAY = 60 * 60 * 24,
CLASSES = {
CLASSES = {
FADE_IN_DOWN: 'rt-fade-in-down',
FADE_IN_DOWN: 'rt-fade-in-down',
FADE_IN_UP: 'rt-fade-in-up',
FADE_IN_UP: 'rt-fade-in-up',
FADE_OUT_DOWN: 'rt-fade-out-down',
FADE_OUT_DOWN: 'rt-fade-out-down',
FADE_OUT_UP: 'rt-fade-out-up'
FADE_OUT_UP: 'rt-fade-out-up'
},
},
IS_TOUCHSCREEN = 'ontouchstart' in document.documentElement,
IS_TOUCHSCREEN = 'ontouchstart' in document.documentElement,
// Quite a rough check for mobile browsers, a mix of what is advised at
// Quite a rough check for mobile browsers, a mix of what is advised at
// https://stackoverflow.com/a/24600597 (sends to
// https://stackoverflow.com/a/24600597 (sends to
// https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent)
// https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent)
// and https://stackoverflow.com/a/14301832
// and https://stackoverflow.com/a/14301832
IS_MOBILE = /Mobi|Android/i.test( navigator.userAgent ) ||
IS_MOBILE = /Mobi|Android/i.test( navigator.userAgent ) ||
typeof window.orientation !== 'undefined',
typeof window.orientation !== 'undefined',
CLIENT_NAME = $.client.profile().name,
CLIENT_NAME = $.client.profile().name,
settingsString, settings, enabled, delay, activatedByClick, tooltipsForComments, cursorWaitCss,
settingsString, settings, enabled, delay, activatedByClick, tooltipsForComments, cursorWaitCss,
windowManager,
windowManager,
$body = $( document.body ),
$body = $( document.body ),
$window = $( window );
$window = $( window );


function rt( $content ) {
function rt( $content ) {
// Popups gadget
// Popups gadget
if ( window.pg ) {
if ( window.pg ) {
return;
return;
}
}


var teSelector,
var teSelector,
settingsDialogOpening = false;
settingsDialogOpening = false;


function setSettingsCookie() {
function setSettingsCookie() {
mw.cookie.set(
mw.cookie.set(
'RTsettings',
'RTsettings',
Number( enabled ) + '|' + delay + '|' + Number( activatedByClick ) + '|' +
Number( enabled ) + '|' + delay + '|' + Number( activatedByClick ) + '|' +
Number( tooltipsForComments ),
Number( tooltipsForComments ),
{ path: '/', expires: 90 * SECONDS_IN_A_DAY, prefix: '' }
{ path: '/', expires: 90 * SECONDS_IN_A_DAY, prefix: '' }
);
);
}
}


function enableRt() {
function enableRt() {
enabled = true;
enabled = true;
setSettingsCookie();
setSettingsCookie();
$( '.rt-enableItem' ).remove();
$( '.rt-enableItem' ).remove();
rt( $content );
rt( $content );
mw.notify( mw.msg( 'rt-enabled' ) );
mw.notify( mw.msg( 'rt-enabled' ) );
}
}


function disableRt() {
function disableRt() {
$content.find( teSelector ).removeClass( 'rt-commentedText' ).off( '.rt' );
$content.find( teSelector ).removeClass( 'rt-commentedText' ).off( '.rt' );
$body.off( '.rt' );
$body.off( '.rt' );
$window.off( '.rt' );
$window.off( '.rt' );
}
}


function addEnableLink() {
function addEnableLink() {
// #footer-places – Vector
// #footer-places – Vector
// #f-list – Timeless, Monobook, Modern
// #f-list – Timeless, Monobook, Modern
// parent of #footer li – Cologne Blue
// parent of #footer li – Cologne Blue
var $footer = $( '#footer-places, #f-list' );
var $footer = $( '#footer-places, #f-list' );
if ( !$footer.length ) {
if ( !$footer.length ) {
$footer = $( '#footer li' ).parent();
$footer = $( '#footer li' ).parent();
}
}
$footer.append(
$footer.append(
$( '<li>' )
$( '<li>' )
.addClass( 'rt-enableItem' )
.addClass( 'rt-enableItem' )
.append(
.append(
$( '<a>' )
$( '<a>' )
.text( mw.msg( 'rt-enable-footer' ) )
.text( mw.msg( 'rt-enable-footer' ) )
.attr( 'href', 'javascript:' )
.attr( 'href', 'javascript:' )
.click( function ( e ) {
.click( function ( e ) {
e.preventDefault();
e.preventDefault();
enableRt();
enableRt();
} )
} )
)
)
);
);
}
}


function TooltippedElement( $element ) {
function TooltippedElement( $element ) {
var tooltip,
var tooltip,
events,
events,
te = this;
te = this;


function onStartEvent( e ) {
function onStartEvent( e ) {
var showRefArgs;
var showRefArgs;


if ( activatedByClick && te.type !== 'commentedText' && e.type !== 'contextmenu' ) {
if ( activatedByClick && te.type !== 'commentedText' && e.type !== 'contextmenu' ) {
e.preventDefault();
e.preventDefault();
}
}
if ( !te.noRef ) {
if ( !te.noRef ) {
showRefArgs = [ $( this ) ];
showRefArgs = [ $( this ) ];
if ( te.type !== 'supRef' ) {
if ( te.type !== 'supRef' ) {
showRefArgs.push( e.pageX, e.pageY );
showRefArgs.push( e.pageX, e.pageY );
}
}
te.showRef.apply( te, showRefArgs );
te.showRef.apply( te, showRefArgs );
}
}
}
}


function onEndEvent() {
function onEndEvent() {
if ( !te.noRef ) {
if ( !te.noRef ) {
te.hideRef();
te.hideRef();
}
}
}
}


if ( !$element ) {
if ( !$element ) {
return;
return;
}
}


// TooltippedElement.$element and TooltippedElement.$originalElement will be different when
// TooltippedElement.$element and TooltippedElement.$originalElement will be different when
// the first is changed after its cloned version is hovered in a tooltip
// the first is changed after its cloned version is hovered in a tooltip
this.$element = $element;
this.$element = $element;
this.$originalElement = $element;
this.$originalElement = $element;
if ( this.$element.is( REF_LINK_SELECTOR ) ) {
if ( this.$element.is( REF_LINK_SELECTOR ) ) {
if ( this.$element.prop( 'tagName' ) === 'SUP' ) {
if ( this.$element.prop( 'tagName' ) === 'SUP' ) {
this.type = 'supRef';
this.type = 'supRef';
} else {
} else {
this.type = 'harvardRef';
this.type = 'harvardRef';
}
}
} else {
} else {
this.type = 'commentedText';
this.type = 'commentedText';
this.comment = this.$element.attr( 'title' );
this.comment = this.$element.attr( 'title' );
if ( !this.comment ) {
if ( !this.comment ) {
return;
return;
}
}
this.$element.addClass('rt-commentedText');
this.$element.addClass('rt-commentedText');
}
}
if ( activatedByClick ) {
if ( activatedByClick ) {
events = {
events = {
'click.rt': onStartEvent
'click.rt': onStartEvent
};
};
// Adds an ability to see tooltips for links
// Adds an ability to see tooltips for links
if ( this.type === 'commentedText' &&
if ( this.type === 'commentedText' &&
( this.$element.closest( 'a' ).length ||
( this.$element.closest( 'a' ).length ||
this.$element.has( 'a' ).length
this.$element.has( 'a' ).length
)
)
) {
) {
events[ 'contextmenu.rt' ] = onStartEvent;
events[ 'contextmenu.rt' ] = onStartEvent;
}
}
} else {
} else {
events = {
events = {
'mouseenter.rt': onStartEvent,
'mouseenter.rt': onStartEvent,
'mouseleave.rt': onEndEvent
'mouseleave.rt': onEndEvent
};
};
}
}


this.$element.on( events );
this.$element.on( events );


this.hideRef = function ( immediately ) {
this.hideRef = function ( immediately ) {
clearTimeout( te.showTimer );
clearTimeout( te.showTimer );


if ( this.type === 'commentedText' ) {
if ( this.type === 'commentedText' ) {
this.$element.attr( 'title', this.comment );
this.$element.attr( 'title', this.comment );
}
}


if ( this.tooltip && this.tooltip.isPresent ) {
if ( this.tooltip && this.tooltip.isPresent ) {
if ( activatedByClick || immediately ) {
if ( activatedByClick || immediately ) {
this.tooltip.hide();
this.tooltip.hide();
} else {
} else {
this.hideTimer = setTimeout( function () {
this.hideTimer = setTimeout( function () {
te.tooltip.hide();
te.tooltip.hide();
}, 200 );
}, 200 );
}
}
} else if ( this.$ref && this.$ref.hasClass( 'rt-target' ) ) {
} else if ( this.$ref && this.$ref.hasClass( 'rt-target' ) ) {
this.$ref.removeClass( 'rt-target' );
this.$ref.removeClass( 'rt-target' );
if ( activatedByClick ) {
if ( activatedByClick ) {
$body.off( 'click.rt touchstart.rt', this.onBodyClick );
$body.off( 'click.rt touchstart.rt', this.onBodyClick );
}
}
}
}
};
};


this.showRef = function ( $element, ePageX, ePageY ) {
this.showRef = function ( $element, ePageX, ePageY ) {
// Popups gadget
// Popups gadget
if ( window.pg ) {
if ( window.pg ) {
disableRt();
disableRt();
return;
return;
}
}
if ( this.tooltip && !this.tooltip.$content.length ) {
if ( this.tooltip && !this.tooltip.$content.length ) {
return;
return;
}
}


var tooltipInitiallyPresent = this.tooltip && this.tooltip.isPresent;
var tooltipInitiallyPresent = this.tooltip && this.tooltip.isPresent;


function reallyShow() {
function reallyShow() {
var viewportTop, refOffsetTop, teHref;
var viewportTop, refOffsetTop, teHref;


if ( !te.$ref && !te.comment ) {
if ( !te.$ref && !te.comment ) {
teHref = te.type === 'supRef' ?
teHref = te.type === 'supRef' ?
te.$element.find( 'a' ).attr( 'href' ) :
te.$element.find( 'a' ).attr( 'href' ) :
te.$element.attr( 'href' ); // harvardRef
te.$element.attr( 'href' ); // harvardRef
te.$ref = teHref &&
te.$ref = teHref &&
$( '#' + $.escapeSelector( teHref.slice( 1 ) ) );
$( '#' + $.escapeSelector( teHref.slice( 1 ) ) );
if ( !te.$ref || !te.$ref.length || !te.$ref.text() ) {
if ( !te.$ref || !te.$ref.length || !te.$ref.text() ) {
te.noRef = true;
te.noRef = true;
return;
return;
}
}
}
}


if ( !tooltipInitiallyPresent && !te.comment ) {
if ( !tooltipInitiallyPresent && !te.comment ) {
viewportTop = $window.scrollTop();
viewportTop = $window.scrollTop();
refOffsetTop = te.$ref.offset().top;
refOffsetTop = te.$ref.offset().top;
if ( !activatedByClick &&
if ( !activatedByClick &&
viewportTop < refOffsetTop &&
viewportTop < refOffsetTop &&
viewportTop + $window.height() > refOffsetTop + te.$ref.height() &&
viewportTop + $window.height() > refOffsetTop + te.$ref.height() &&
// There can be gadgets/scripts that make references horizontally scrollable.
// There can be gadgets/scripts that make references horizontally scrollable.
$window.width() > te.$ref.offset().left + te.$ref.width()
$window.width() > te.$ref.offset().left + te.$ref.width()
) {
) {
// Highlight the reference itself
// Highlight the reference itself
te.$ref.addClass( 'rt-target' );
te.$ref.addClass( 'rt-target' );
return;
return;
}
}
}
}


if ( !te.tooltip ) {
if ( !te.tooltip ) {
te.tooltip = new Tooltip( te );
te.tooltip = new Tooltip( te );
if ( !te.tooltip.$content.length ) {
if ( !te.tooltip.$content.length ) {
return;
return;
}
}
}
}


// If this tooltip is called from inside another tooltip. We can't define it
// 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;
// in the constructor since a ref can be cloned but have the same Tooltip object;
// so, Tooltip.parent is a floating value.
// so, Tooltip.parent is a floating value.
te.tooltip.parent = te.$element.closest( '.rt-tooltip' ).data( 'tooltip' );
te.tooltip.parent = te.$element.closest( '.rt-tooltip' ).data( 'tooltip' );
if ( te.tooltip.parent && te.tooltip.parent.disappearing ) {
if ( te.tooltip.parent && te.tooltip.parent.disappearing ) {
return;
return;
}
}


te.tooltip.show();
te.tooltip.show();


if ( tooltipInitiallyPresent ) {
if ( tooltipInitiallyPresent ) {
if ( te.tooltip.$element.hasClass( 'rt-tooltip-above' ) ) {
if ( te.tooltip.$element.hasClass( 'rt-tooltip-above' ) ) {
te.tooltip.$element.addClass( CLASSES.FADE_IN_DOWN );
te.tooltip.$element.addClass( CLASSES.FADE_IN_DOWN );
} else {
} else {
te.tooltip.$element.addClass( CLASSES.FADE_IN_UP );
te.tooltip.$element.addClass( CLASSES.FADE_IN_UP );
}
}
return;
return;
}
}


te.tooltip.calculatePosition( ePageX, ePageY );
te.tooltip.calculatePosition( ePageX, ePageY );


$window.on( 'resize.rt', te.onWindowResize );
$window.on( 'resize.rt', te.onWindowResize );
}
}


// We redefine this.$element here because e.target can be a reference link inside
// 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
// a reference tooltip, not a link that was initially assigned to this.$element
this.$element = $element;
this.$element = $element;


if ( this.type === 'commentedText' ) {
if ( this.type === 'commentedText' ) {
this.$element.attr( 'title', '' );
this.$element.attr( 'title', '' );
}
}


if ( activatedByClick ) {
if ( activatedByClick ) {
if ( tooltipInitiallyPresent ||
if ( tooltipInitiallyPresent ||
( this.$ref && this.$ref.hasClass( 'rt-target' ) )
( this.$ref && this.$ref.hasClass( 'rt-target' ) )
) {
) {
return;
return;
} else {
} else {
setTimeout( function () {
setTimeout( function () {
$body.on( 'click.rt touchstart.rt', te.onBodyClick );
$body.on( 'click.rt touchstart.rt', te.onBodyClick );
}, 0 );
}, 0 );
}
}
}
}


if ( activatedByClick || tooltipInitiallyPresent ) {
if ( activatedByClick || tooltipInitiallyPresent ) {
reallyShow();
reallyShow();
} else {
} else {
this.showTimer = setTimeout( reallyShow, delay );
this.showTimer = setTimeout( reallyShow, delay );
}
}
};
};


this.onBodyClick = function ( e ) {
this.onBodyClick = function ( e ) {
if ( !te.tooltip && !te.$ref.hasClass( 'rt-target' ) ) {
if ( !te.tooltip && !te.$ref.hasClass( 'rt-target' ) ) {
return;
return;
}
}


var $current = $( e.target );
var $current = $( e.target );


function contextMatchesParameter( parameter ) {
function contextMatchesParameter( parameter ) {
return this === parameter;
return this === parameter;
}
}


// The last condition is used to determine cases when a clicked tooltip is the current
// The last condition is used to determine cases when a clicked tooltip is the current
// element's tooltip or one of its descendants
// element's tooltip or one of its descendants
while ( $current.length &&
while ( $current.length &&
( !$current.hasClass( 'rt-tooltip' ) ||
( !$current.hasClass( 'rt-tooltip' ) ||
!$current.data( 'tooltip' ) ||
!$current.data( 'tooltip' ) ||
!$current.data( 'tooltip' ).upToTopParent(
!$current.data( 'tooltip' ).upToTopParent(
contextMatchesParameter, [ te.tooltip ],
contextMatchesParameter, [ te.tooltip ],
true
true
)
)
)
)
) {
) {
$current = $current.parent();
$current = $current.parent();
}
}
if ( !$current.length ) {
if ( !$current.length ) {
te.hideRef();
te.hideRef();
}
}
};
};


this.onWindowResize = function () {
this.onWindowResize = function () {
te.tooltip.calculatePosition();
te.tooltip.calculatePosition();
};
};
}
}


function Tooltip( te ) {
function Tooltip( te ) {
function openSettingsDialog() {
function openSettingsDialog() {
var settingsDialog, settingsWindow;
var settingsDialog, settingsWindow;


if ( cursorWaitCss ) {
if ( cursorWaitCss ) {
cursorWaitCss.disabled = true;
cursorWaitCss.disabled = true;
}
}


function SettingsDialog() {
function SettingsDialog() {
SettingsDialog.parent.call( this );
SettingsDialog.parent.call( this );
}
}
OO.inheritClass( SettingsDialog, OO.ui.ProcessDialog );
OO.inheritClass( SettingsDialog, OO.ui.ProcessDialog );


SettingsDialog.static.name = 'settingsDialog';
SettingsDialog.static.name = 'settingsDialog';
SettingsDialog.static.title = mw.msg( 'rt-settings-title' );
SettingsDialog.static.title = mw.msg( 'rt-settings-title' );
SettingsDialog.static.actions = [
SettingsDialog.static.actions = [
{
{
modes: 'basic',
modes: 'basic',
action: 'save',
action: 'save',
label: mw.msg( 'rt-save' ),
label: mw.msg( 'rt-save' ),
flags: [ 'primary', 'progressive' ]
flags: [ 'primary', 'progressive' ]
},
},
{
{
modes: 'basic',
modes: 'basic',
label: mw.msg( 'rt-cancel' ),
label: mw.msg( 'rt-cancel' ),
flags: 'safe'
flags: 'safe'
},
},
{
{
modes: 'disabled',
modes: 'disabled',
action: 'deactivated',
action: 'deactivated',
label: mw.msg( 'rt-done' ),
label: mw.msg( 'rt-done' ),
flags: [ 'primary', 'progressive' ]
flags: [ 'primary', 'progressive' ]
}
}
];
];


SettingsDialog.prototype.initialize = function () {
SettingsDialog.prototype.initialize = function () {
var dialog = this;
var dialog = this;


SettingsDialog.parent.prototype.initialize.apply( this, arguments );
SettingsDialog.parent.prototype.initialize.apply( this, arguments );


this.enableOption = new OO.ui.RadioOptionWidget( {
this.enableOption = new OO.ui.RadioOptionWidget( {
label: mw.msg( 'rt-enable' )
label: mw.msg( 'rt-enable' )
} );
} );
this.disableOption = new OO.ui.RadioOptionWidget( {
this.disableOption = new OO.ui.RadioOptionWidget( {
label: mw.msg( 'rt-disable' )
label: mw.msg( 'rt-disable' )
} );
} );
this.enableSelect = new OO.ui.RadioSelectWidget( {
this.enableSelect = new OO.ui.RadioSelectWidget( {
items: [ this.enableOption, this.disableOption ],
items: [ this.enableOption, this.disableOption ],
classes: [ 'rt-enableSelect' ]
classes: [ 'rt-enableSelect' ]
} );
} );
this.enableSelect.selectItem( this.enableOption );
this.enableSelect.selectItem( this.enableOption );
this.enableSelect.on( 'choose', function ( item ) {
this.enableSelect.on( 'choose', function ( item ) {
if ( item === dialog.disableOption ) {
if ( item === dialog.disableOption ) {
dialog.activationMethodSelect.setDisabled( true );
dialog.activationMethodSelect.setDisabled( true );
dialog.delayInput.setDisabled( true );
dialog.delayInput.setDisabled( true );
dialog.tooltipsForCommentsCheckbox.setDisabled( true );
dialog.tooltipsForCommentsCheckbox.setDisabled( true );
} else {
} else {
dialog.activationMethodSelect.setDisabled( false );
dialog.activationMethodSelect.setDisabled( false );
dialog.delayInput.setDisabled( dialog.clickOption.isSelected() );
dialog.delayInput.setDisabled( dialog.clickOption.isSelected() );
dialog.tooltipsForCommentsCheckbox.setDisabled( false );
dialog.tooltipsForCommentsCheckbox.setDisabled( false );
}
}
} );
} );


this.hoverOption = new OO.ui.RadioOptionWidget( {
this.hoverOption = new OO.ui.RadioOptionWidget( {
label: mw.msg( 'rt-hovering' )
label: mw.msg( 'rt-hovering' )
} );
} );
this.clickOption = new OO.ui.RadioOptionWidget( {
this.clickOption = new OO.ui.RadioOptionWidget( {
label: mw.msg( 'rt-clicking' )
label: mw.msg( 'rt-clicking' )
} );
} );
this.activationMethodSelect = new OO.ui.RadioSelectWidget( {
this.activationMethodSelect = new OO.ui.RadioSelectWidget( {
items: [ this.hoverOption, this.clickOption ]
items: [ this.hoverOption, this.clickOption ]
} );
} );
this.activationMethodSelect.selectItem( activatedByClick ?
this.activationMethodSelect.selectItem( activatedByClick ?
this.clickOption :
this.clickOption :
this.hoverOption
this.hoverOption
);
);
this.activationMethodSelect.on( 'choose', function ( item ) {
this.activationMethodSelect.on( 'choose', function ( item ) {
if ( item === dialog.clickOption ) {
if ( item === dialog.clickOption ) {
dialog.delayInput.setDisabled( true );
dialog.delayInput.setDisabled( true );
} else {
} else {
dialog.delayInput.setDisabled( dialog.clickOption.isSelected() );
dialog.delayInput.setDisabled( dialog.clickOption.isSelected() );
}
}
} );
} );
this.activationMethodField = new OO.ui.FieldLayout( this.activationMethodSelect, {
this.activationMethodField = new OO.ui.FieldLayout( this.activationMethodSelect, {
label: mw.msg( 'rt-activationMethod' ),
label: mw.msg( 'rt-activationMethod' ),
align: 'top'
align: 'top'
} );
} );


this.delayInput = new OO.ui.NumberInputWidget( {
this.delayInput = new OO.ui.NumberInputWidget( {
input: { value: delay },
input: { value: delay },
step: 50,
step: 50,
min: 0,
min: 0,
max: 5000,
max: 5000,
disabled: activatedByClick,
disabled: activatedByClick,
classes: [ 'rt-numberInput' ]
classes: [ 'rt-numberInput' ]
} );
} );
this.delayField = new OO.ui.FieldLayout( this.delayInput, {
this.delayField = new OO.ui.FieldLayout( this.delayInput, {
label: mw.msg( 'rt-delay' ),
label: mw.msg( 'rt-delay' ),
align: 'top'
align: 'top'
} );
} );


this.tooltipsForCommentsCheckbox = new OO.ui.CheckboxInputWidget( {
this.tooltipsForCommentsCheckbox = new OO.ui.CheckboxInputWidget( {
selected: tooltipsForComments
selected: tooltipsForComments
} );
} );
this.tooltipsForCommentsField = new OO.ui.FieldLayout(
this.tooltipsForCommentsField = new OO.ui.FieldLayout(
this.tooltipsForCommentsCheckbox,
this.tooltipsForCommentsCheckbox,
{
{
label: new OO.ui.HtmlSnippet( mw.msg( 'rt-tooltipsForComments' ) ),
label: new OO.ui.HtmlSnippet( mw.msg( 'rt-tooltipsForComments' ) ),
align: 'inline',
align: 'inline',
classes: [ 'rt-tooltipsForCommentsField' ]
classes: [ 'rt-tooltipsForCommentsField' ]
}
}
);
);
new TooltippedElement(
new TooltippedElement(
this.tooltipsForCommentsField.$element.find(
this.tooltipsForCommentsField.$element.find(
'.' + ( COMMENTED_TEXT_CLASS || 'rt-commentedText' )
'.' + ( COMMENTED_TEXT_CLASS || 'rt-commentedText' )
)
)
);
);


this.fieldset = new OO.ui.FieldsetLayout();
this.fieldset = new OO.ui.FieldsetLayout();
this.fieldset.addItems( [
this.fieldset.addItems( [
this.activationMethodField,
this.activationMethodField,
this.delayField,
this.delayField,
this.tooltipsForCommentsField
this.tooltipsForCommentsField
] );
] );


this.panelSettings = new OO.ui.PanelLayout( {
this.panelSettings = new OO.ui.PanelLayout( {
padded: true,
padded: true,
expanded: false
expanded: false
} );
} );
this.panelSettings.$element.append(
this.panelSettings.$element.append(
this.enableSelect.$element,
this.enableSelect.$element,
$( '<hr>' ).addClass( 'rt-settingsFormSeparator' ),
$( '<hr>' ).addClass( 'rt-settingsFormSeparator' ),
this.fieldset.$element
this.fieldset.$element
);
);


this.panelDisabled = new OO.ui.PanelLayout( {
this.panelDisabled = new OO.ui.PanelLayout( {
padded: true,
padded: true,
expanded: false
expanded: false
} );
} );
this.panelDisabled.$element.append(
this.panelDisabled.$element.append(
$( '<table>' )
$( '<table>' )
.addClass( 'rt-disabledHelp' )
.addClass( 'rt-disabledHelp' )
.append(
.append(
$( '<tr>' ).append(
$( '<tr>' ).append(
$( '<td>' ).append(
$( '<td>' ).append(
$( '<img>' ).attr( 'src', 'https://en.wikipedia.org/w/load.php?modules=ext.popups.images&image=footer&format=rasterized&lang=ru&skin=vector&version=0uotisb' )
$( '<img>' ).attr( 'src', 'https://en.wikipedia.org/w/load.php?modules=ext.popups.images&image=footer&format=rasterized&lang=ru&skin=vector&version=0uotisb' )
),
),
$( '<td>' )
$( '<td>' )
.addClass( 'rt-disabledNote' )
.addClass( 'rt-disabledNote' )
.text( mw.msg( 'rt-disabledNote' ) )
.text( mw.msg( 'rt-disabledNote' ) )
)
)
)
)
);
);


this.stackLayout = new OO.ui.StackLayout( {
this.stackLayout = new OO.ui.StackLayout( {
items: [ this.panelSettings, this.panelDisabled ]
items: [ this.panelSettings, this.panelDisabled ]
} );
} );


this.$body.append( this.stackLayout.$element );
this.$body.append( this.stackLayout.$element );
};
};


SettingsDialog.prototype.getSetupProcess = function ( data ) {
SettingsDialog.prototype.getSetupProcess = function ( data ) {
return SettingsDialog.parent.prototype.getSetupProcess.call( this, data )
return SettingsDialog.parent.prototype.getSetupProcess.call( this, data )
.next( function () {
.next( function () {
this.stackLayout.setItem( this.panelSettings );
this.stackLayout.setItem( this.panelSettings );
this.actions.setMode( 'basic' );
this.actions.setMode( 'basic' );
}, this );
}, this );
};
};


SettingsDialog.prototype.getActionProcess = function ( action ) {
SettingsDialog.prototype.getActionProcess = function ( action ) {
var dialog = this;
var dialog = this;


if ( action === 'save' ) {
if ( action === 'save' ) {
return new OO.ui.Process( function () {
return new OO.ui.Process( function () {
var newDelay = Number( dialog.delayInput.getValue() );
var newDelay = Number( dialog.delayInput.getValue() );


enabled = dialog.enableOption.isSelected();
enabled = dialog.enableOption.isSelected();
if ( newDelay >= 0 && newDelay <= 5000 ) {
if ( newDelay >= 0 && newDelay <= 5000 ) {
delay = newDelay;
delay = newDelay;
}
}
activatedByClick = dialog.clickOption.isSelected();
activatedByClick = dialog.clickOption.isSelected();
tooltipsForComments = dialog.tooltipsForCommentsCheckbox.isSelected();
tooltipsForComments = dialog.tooltipsForCommentsCheckbox.isSelected();


setSettingsCookie();
setSettingsCookie();


if ( enabled ) {
if ( enabled ) {
dialog.close();
dialog.close();
disableRt();
disableRt();
rt( $content );
rt( $content );
} else {
} else {
dialog.actions.setMode( 'disabled' );
dialog.actions.setMode( 'disabled' );
dialog.stackLayout.setItem( dialog.panelDisabled );
dialog.stackLayout.setItem( dialog.panelDisabled );
disableRt();
disableRt();
addEnableLink();
addEnableLink();
}
}
} );
} );
} else if ( action === 'deactivated' ) {
} else if ( action === 'deactivated' ) {
dialog.close();
dialog.close();
}
}
return SettingsDialog.parent.prototype.getActionProcess.call( this, action );
return SettingsDialog.parent.prototype.getActionProcess.call( this, action );
};
};


SettingsDialog.prototype.getBodyHeight = function () {
SettingsDialog.prototype.getBodyHeight = function () {
return this.stackLayout.getCurrentItem().$element.outerHeight( true );
return this.stackLayout.getCurrentItem().$element.outerHeight( true );
};
};


tooltip.upToTopParent( function adjustRightAndHide() {
tooltip.upToTopParent( function adjustRightAndHide() {
if ( this.isPresent ) {
if ( this.isPresent ) {
if ( this.$element[ 0 ].style.right ) {
if ( this.$element[ 0 ].style.right ) {
this.$element.css(
this.$element.css(
'right',
'right',
'+=' + ( window.innerWidth - $window.width() )
'+=' + ( window.innerWidth - $window.width() )
);
);
}
}
this.te.hideRef( true );
this.te.hideRef( true );
}
}
} );
} );


if ( !windowManager ) {
if ( !windowManager ) {
windowManager = new OO.ui.WindowManager();
windowManager = new OO.ui.WindowManager();
$body.append( windowManager.$element );
$body.append( windowManager.$element );
}
}


settingsDialog = new SettingsDialog();
settingsDialog = new SettingsDialog();
windowManager.addWindows( [ settingsDialog ] );
windowManager.addWindows( [ settingsDialog ] );
settingsWindow = windowManager.openWindow( settingsDialog );
settingsWindow = windowManager.openWindow( settingsDialog );
settingsWindow.opened.then( function () {
settingsWindow.opened.then( function () {
settingsDialogOpening = false;
settingsDialogOpening = false;
} );
} );
settingsWindow.closed.then( function () {
settingsWindow.closed.then( function () {
windowManager.clearWindows();
windowManager.clearWindows();
} );
} );
}
}


var tooltip = this;
var tooltip = this;


// This variable can change: one tooltip can be called from a harvard-style reference link
// This variable can change: one tooltip can be called from a harvard-style reference link
// that is put into different tooltips
// that is put into different tooltips
this.te = te;
this.te = te;


switch ( this.te.type ) {
switch ( this.te.type ) {
case 'supRef':
case 'supRef':
this.id = 'rt-' + this.te.$originalElement.attr( 'id' );
this.id = 'rt-' + this.te.$originalElement.attr( 'id' );
this.$content = this.te.$ref
this.$content = this.te.$ref
.contents()
.contents()
.filter( function ( i ) {
.filter( function ( i ) {
var $this = $( this );
var $this = $( this );
return this.nodeType === Node.TEXT_NODE ||
return this.nodeType === Node.TEXT_NODE ||
!( $this.is( '.mw-cite-backlink' ) ||
!( $this.is( '.mw-cite-backlink' ) ||
( i === 0 &&
( i === 0 &&
// Template:Cnote, Template:Note
// Template:Cnote, Template:Note
( $this.is( 'b' ) ||
( $this.is( 'b' ) ||
// Template:Note_label
// Template:Note_label
$this.is( 'a' ) &&
$this.is( 'a' ) &&
$this.attr( 'href' ).indexOf( '#ref' ) === 0
$this.attr( 'href' ).indexOf( '#ref' ) === 0
)
)
)
)
);
);
} )
} )
.clone( true );
.clone( true );
break;
break;
case 'harvardRef':
case 'harvardRef':
this.id = 'rt-' + this.te.$originalElement.closest( 'li' ).attr( 'id' );
this.id = 'rt-' + this.te.$originalElement.closest( 'li' ).attr( 'id' );
this.$content = this.te.$ref
this.$content = this.te.$ref
.clone( true )
.clone( true )
.removeAttr( 'id' );
.removeAttr( 'id' );
break;
break;
case 'commentedText':
case 'commentedText':
this.id = 'rt-' + String( Math.random() ).slice( 2 );
this.id = 'rt-' + String( Math.random() ).slice( 2 );
this.$content = $( document.createTextNode( this.te.comment ) );
this.$content = $( document.createTextNode( this.te.comment ) );
break;
break;
}
}
if ( !this.$content.length ) {
if ( !this.$content.length ) {
return;
return;
}
}


this.insideWindow = Boolean( this.te.$element.closest( '.oo-ui-window' ).length );
this.insideWindow = Boolean( this.te.$element.closest( '.oo-ui-window' ).length );


this.$element = $( '<div>' )
this.$element = $( '<div>' )
.addClass( 'rt-tooltip' )
.addClass( 'rt-tooltip' )
.attr( 'id', this.id )
.attr( 'id', this.id )
.attr( 'role', 'tooltip' )
.attr( 'role', 'tooltip' )
.data( 'tooltip', this );
.data( 'tooltip', this );
if ( this.insideWindow ) {
if ( this.insideWindow ) {
this.$element.addClass( 'rt-tooltip-insideWindow' );
this.$element.addClass( 'rt-tooltip-insideWindow' );
}
}


// We need the $content interlayer here in order for the settings icon to have correct
// We need the $content interlayer here in order for the settings icon to have correct
// margins
// margins
this.$content = this.$content
this.$content = this.$content
.wrapAll( '<div>' )
.wrapAll( '<div>' )
.parent()
.parent()
.addClass( 'rt-tooltipContent' )
.addClass( 'rt-tooltipContent' )
.addClass( 'mw-parser-output' )
.addClass( 'mw-parser-output' )
.appendTo( this.$element );
.appendTo( this.$element );


if ( !activatedByClick ) {
if ( !activatedByClick ) {
this.$element
this.$element
.mouseenter( function () {
.mouseenter( function () {
if ( !tooltip.disappearing ) {
if ( !tooltip.disappearing ) {
tooltip.upToTopParent( function () {
tooltip.upToTopParent( function () {
this.show();
this.show();
} );
} );
}
}
} )
} )
.mouseleave( function ( e ) {
.mouseleave( function ( e ) {
// https://stackoverflow.com/q/47649442 workaround. Relying on relatedTarget
// https://stackoverflow.com/q/47649442 workaround. Relying on relatedTarget
// alone has pitfalls: when alt-tabbing, relatedTarget is empty too
// alone has pitfalls: when alt-tabbing, relatedTarget is empty too
if ( CLIENT_NAME !== 'chrome' ||
if ( CLIENT_NAME !== 'chrome' ||
( !e.originalEvent ||
( !e.originalEvent ||
e.originalEvent.relatedTarget !== null ||
e.originalEvent.relatedTarget !== null ||
!tooltip.clickedTime ||
!tooltip.clickedTime ||
$.now() - tooltip.clickedTime > 50
$.now() - tooltip.clickedTime > 50
)
)
) {
) {
tooltip.upToTopParent( function () {
tooltip.upToTopParent( function () {
this.te.hideRef();
this.te.hideRef();
} );
} );
}
}
} )
} )
.click( function () {
.click( function () {
tooltip.clickedTime = $.now();
tooltip.clickedTime = $.now();
} );
} );
}
}


if ( !this.insideWindow ) {
if ( !this.insideWindow ) {
$( '<div>' )
$( '<div>' )
.addClass( 'rt-settingsLink' )
.addClass( 'rt-settingsLink' )
.attr( 'title', mw.msg( 'rt-settings' ) )
.attr( 'title', mw.msg( 'rt-settings' ) )
.click( function () {
.click( function () {
if ( settingsDialogOpening ) {
if ( settingsDialogOpening ) {
return;
return;
}
}
settingsDialogOpening = true;
settingsDialogOpening = true;


if ( mw.loader.getState( 'oojs-ui' ) !== 'ready' ) {
if ( mw.loader.getState( 'oojs-ui' ) !== 'ready' ) {
if ( cursorWaitCss ) {
if ( cursorWaitCss ) {
cursorWaitCss.disabled = false;
cursorWaitCss.disabled = false;
} else {
} else {
cursorWaitCss = mw.util.addCSS( 'body { cursor: wait; }' );
cursorWaitCss = mw.util.addCSS( 'body { cursor: wait; }' );
}
}
}
}
mw.loader.using( [ 'oojs', 'oojs-ui' ], openSettingsDialog );
mw.loader.using( [ 'oojs', 'oojs-ui' ], openSettingsDialog );
} )
} )
.prependTo( this.$content );
.prependTo( this.$content );
}
}


// Tooltip tail element is inside tooltip content element in order for the tooltip
// Tooltip tail element is inside tooltip content element in order for the tooltip
// not to disappear when the mouse is above the tail
// not to disappear when the mouse is above the tail
this.$tail = $( '<div>' )
this.$tail = $( '<div>' )
.addClass( 'rt-tooltipTail' )
.addClass( 'rt-tooltipTail' )
.prependTo( this.$element );
.prependTo( this.$element );


this.disappearing = false;
this.disappearing = false;


this.show = function () {
this.show = function () {
this.disappearing = false;
this.disappearing = false;
clearTimeout( this.te.hideTimer );
clearTimeout( this.te.hideTimer );
clearTimeout( this.te.removeTimer );
clearTimeout( this.te.removeTimer );


this.$element
this.$element
.removeClass( CLASSES.FADE_OUT_DOWN )
.removeClass( CLASSES.FADE_OUT_DOWN )
.removeClass( CLASSES.FADE_OUT_UP );
.removeClass( CLASSES.FADE_OUT_UP );


if ( !this.isPresent ) {
if ( !this.isPresent ) {
$body.append( this.$element );
$body.append( this.$element );
}
}


this.isPresent = true;
this.isPresent = true;
};
};


this.hide = function () {
this.hide = function () {
var tooltip = this;
var tooltip = this;


tooltip.disappearing = true;
tooltip.disappearing = true;


if ( tooltip.$element.hasClass( 'rt-tooltip-above' ) ) {
if ( tooltip.$element.hasClass( 'rt-tooltip-above' ) ) {
tooltip.$element
tooltip.$element
.removeClass( CLASSES.FADE_IN_DOWN )
.removeClass( CLASSES.FADE_IN_DOWN )
.addClass( CLASSES.FADE_OUT_UP );
.addClass( CLASSES.FADE_OUT_UP );
} else {
} else {
tooltip.$element
tooltip.$element
.removeClass( CLASSES.FADE_IN_UP )
.removeClass( CLASSES.FADE_IN_UP )
.addClass( CLASSES.FADE_OUT_DOWN );
.addClass( CLASSES.FADE_OUT_DOWN );
}
}


tooltip.te.removeTimer = setTimeout( function () {
tooltip.te.removeTimer = setTimeout( function () {
if ( tooltip.isPresent ) {
if ( tooltip.isPresent ) {
tooltip.$element.detach();
tooltip.$element.detach();
tooltip.$tail.css( 'left', '' );
tooltip.$tail.css( 'left', '' );


if ( activatedByClick ) {
if ( activatedByClick ) {
$body.off( 'click.rt touchstart.rt', tooltip.te.onBodyClick );
$body.off( 'click.rt touchstart.rt', tooltip.te.onBodyClick );
}
}
$window.off( 'resize.rt', tooltip.te.onWindowResize );
$window.off( 'resize.rt', tooltip.te.onWindowResize );


tooltip.isPresent = false;
tooltip.isPresent = false;
}
}
}, 200 );
}, 200 );
};
};


this.calculatePosition = function ( ePageX, ePageY ) {
this.calculatePosition = function ( ePageX, ePageY ) {
var teElement, teOffsets, teOffset, tooltipTailOffsetX, tooltipTailLeft,
var teElement, teOffsets, teOffset, tooltipTailOffsetX, tooltipTailLeft,
offsetYCorrection = 0;
offsetYCorrection = 0;


this.$tail.css( 'left', '' );
this.$tail.css( 'left', '' );


teElement = this.te.$element.get( 0 );
teElement = this.te.$element.get( 0 );
if ( ePageX !== undefined ) {
if ( ePageX !== undefined ) {
tooltipTailOffsetX = ePageX;
tooltipTailOffsetX = ePageX;
teOffsets = teElement.getClientRects &&
teOffsets = teElement.getClientRects &&
teElement.getClientRects() ||
teElement.getClientRects() ||
teElement.getBoundingClientRect();
teElement.getBoundingClientRect();
if ( teOffsets.length > 1 ) {
if ( teOffsets.length > 1 ) {
for (var i = teOffsets.length - 1; i >= 0; i--) {
for (var i = teOffsets.length - 1; i >= 0; i--) {
if ( ePageY >= Math.round( $window.scrollTop() + teOffsets[i].top ) &&
if ( ePageY >= Math.round( $window.scrollTop() + teOffsets[i].top ) &&
ePageY <= Math.round(
ePageY <= Math.round(
$window.scrollTop() + teOffsets[i].top + teOffsets[i].height
$window.scrollTop() + teOffsets[i].top + teOffsets[i].height
)
)
) {
) {
teOffset = teOffsets[i];
teOffset = teOffsets[i];
}
}
}
}
}
}
}
}


if ( !teOffset ) {
if ( !teOffset ) {
teOffset = teElement.getClientRects &&
teOffset = teElement.getClientRects &&
teElement.getClientRects()[0] ||
teElement.getClientRects()[0] ||
teElement.getBoundingClientRect();
teElement.getBoundingClientRect();
}
}
teOffset = {
teOffset = {
top: $window.scrollTop() + teOffset.top,
top: $window.scrollTop() + teOffset.top,
left: $window.scrollLeft() + teOffset.left,
left: $window.scrollLeft() + teOffset.left,
width: teOffset.width,
width: teOffset.width,
height: teOffset.height
height: teOffset.height
};
};
if ( !tooltipTailOffsetX ) {
if ( !tooltipTailOffsetX ) {
tooltipTailOffsetX = ( teOffset.left * 2 + teOffset.width ) / 2;
tooltipTailOffsetX = ( teOffset.left * 2 + teOffset.width ) / 2;
}
}
if ( CLIENT_NAME === 'msie' && this.te.type === 'supRef' ) {
if ( CLIENT_NAME === 'msie' && this.te.type === 'supRef' ) {
offsetYCorrection = -Number(
offsetYCorrection = -Number(
this.te.$element.parent().css( 'font-size' ).replace( 'px', '' )
this.te.$element.parent().css( 'font-size' ).replace( 'px', '' )
) / 2;
) / 2;
}
}
this.$element.css( {
this.$element.css( {
top: teOffset.top - this.$element.outerHeight() - 7 + offsetYCorrection,
top: teOffset.top - this.$element.outerHeight() - 7 + offsetYCorrection,
left: tooltipTailOffsetX - 20,
left: tooltipTailOffsetX - 20,
right: ''
right: ''
} );
} );


// Is it squished against the right side of the page?
// Is it squished against the right side of the page?
if ( this.$element.offset().left + this.$element.outerWidth() > $window.width() - 1 ) {
if ( this.$element.offset().left + this.$element.outerWidth() > $window.width() - 1 ) {
this.$element.css( {
this.$element.css( {
left: '',
left: '',
right: 0
right: 0
} );
} );
tooltipTailLeft = tooltipTailOffsetX - this.$element.offset().left - 5;
tooltipTailLeft = tooltipTailOffsetX - this.$element.offset().left - 5;
}
}


// Is a part of it above the top of the screen?
// Is a part of it above the top of the screen?
if ( teOffset.top < this.$element.outerHeight() + $window.scrollTop() + 6 ) {
if ( teOffset.top < this.$element.outerHeight() + $window.scrollTop() + 6 ) {
this.$element
this.$element
.removeClass( 'rt-tooltip-above' )
.removeClass( 'rt-tooltip-above' )
.addClass( 'rt-tooltip-below' )
.addClass( 'rt-tooltip-below' )
.addClass( CLASSES.FADE_IN_UP )
.addClass( CLASSES.FADE_IN_UP )
.css( {
.css( {
top: teOffset.top + teOffset.height + 9 + offsetYCorrection
top: teOffset.top + teOffset.height + 9 + offsetYCorrection
} );
} );
if ( tooltipTailLeft ) {
if ( tooltipTailLeft ) {
this.$tail.css( 'left', ( tooltipTailLeft + 12 ) + 'px' );
this.$tail.css( 'left', ( tooltipTailLeft + 12 ) + 'px' );
}
}
} else {
} else {
this.$element
this.$element
.removeClass( 'rt-tooltip-below' )
.removeClass( 'rt-tooltip-below' )
.addClass( 'rt-tooltip-above' )
.addClass( 'rt-tooltip-above' )
.addClass( CLASSES.FADE_IN_DOWN )
.addClass( CLASSES.FADE_IN_DOWN )
// A fix for cases when a tooltip shown once is then wrongly positioned when it
// 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.
// is shown again after a window resize. We just repeat what is above.
.css( {
.css( {
top: teOffset.top - this.$element.outerHeight() - 7 + offsetYCorrection
top: teOffset.top - this.$element.outerHeight() - 7 + offsetYCorrection
} );
} );
if ( tooltipTailLeft ) {
if ( tooltipTailLeft ) {
// 12 is the tail element width/height
// 12 is the tail element width/height
this.$tail.css( 'left', tooltipTailLeft + 'px' );
this.$tail.css( 'left', tooltipTailLeft + 'px' );
}
}
}
}
};
};


// Run some function for all the tooltips up to the top one in a tree. Its context will be
// 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
// 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,
// 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,
// the execution stops when the function in question returns true for the first time,
// and ToolTip.upToTopParent returns true as well.
// and ToolTip.upToTopParent returns true as well.
this.upToTopParent = function ( func, parameters, stopAtTrue ) {
this.upToTopParent = function ( func, parameters, stopAtTrue ) {
var returnValue,
var returnValue,
currentTooltip = this;
currentTooltip = this;


do {
do {
returnValue = func.apply( currentTooltip, parameters );
returnValue = func.apply( currentTooltip, parameters );
if ( stopAtTrue && returnValue ) {
if ( stopAtTrue && returnValue ) {
break;
break;
}
}
} while ( currentTooltip = currentTooltip.parent );
} while ( currentTooltip = currentTooltip.parent );


if ( stopAtTrue ) {
if ( stopAtTrue ) {
return returnValue;
return returnValue;
}
}
};
};
}
}


if ( !enabled ) {
if ( !enabled ) {
addEnableLink();
addEnableLink();
return;
return;
}
}


teSelector = REF_LINK_SELECTOR;
teSelector = REF_LINK_SELECTOR;
if ( tooltipsForComments ) {
if ( tooltipsForComments ) {
teSelector += ', ' + COMMENTED_TEXT_SELECTOR;
teSelector += ', ' + COMMENTED_TEXT_SELECTOR;
}
}
$content.find( teSelector ).each( function () {
$content.find( teSelector ).each( function () {
new TooltippedElement( $( this ) );
new TooltippedElement( $( this ) );
} );
} );
}
}


settingsString = mw.cookie.get( 'RTsettings', '' );
settingsString = mw.cookie.get( 'RTsettings', '' );
if ( settingsString ) {
if ( settingsString ) {
settings = settingsString.split( '|' );
settings = settingsString.split( '|' );
enabled = Boolean( Number( settings[ 0 ] ) );
enabled = Boolean( Number( settings[ 0 ] ) );
delay = Number( settings[ 1 ] );
delay = Number( settings[ 1 ] );
activatedByClick = Boolean( Number( settings[ 2 ] ) );
activatedByClick = Boolean( Number( settings[ 2 ] ) );
// The forth value was added later, so we provide for a default value. See comments below
// The forth value was added later, so we provide for a default value. See comments below
// for why we use "IS_TOUCHSCREEN && IS_MOBILE".
// for why we use "IS_TOUCHSCREEN && IS_MOBILE".
tooltipsForComments = settings[ 3 ] === undefined ?
tooltipsForComments = settings[ 3 ] === undefined ?
IS_TOUCHSCREEN && IS_MOBILE :
IS_TOUCHSCREEN && IS_MOBIL
Boolean( Number( settings[ 3 ] ) );
} else {
enabled = true;