/*== User Info Popup ==Adds an "i" (info) icon at the top of user-related pages(e.g. user pages, user talk pages, "Contributions" pages, etc.)The color of the "i" icon represents the amount of time passed since the user last edited:* Green – user last edited less than 20 minutes ago* Orange – user last edited more than 20 minutes ago, but less than 3 months ago* Red – user last edited more than 3 months agoHover over the "i" icon to quickly view useful information about the relevant user:* Registration date* Number of edits* Time elapsed since last edit* User groups (rights), incl. global ones* Latest block time (incl. range and global blocks, when applicable)* Gender (if disclosed)See full documentation at:[[User:Guycn2/UserInfoPopup]]See also:* [[User:Guycn2/UserInfoPopup.css]] – for the corresponding style sheetSkins supported:Vector (both 2022 and 2010), Monobook, Timeless, and Minerva.Also fully supported on the mobile interface.Dependencies:* mediawiki.api* mediawiki.language.months* mediawiki.user* mediawiki.util* user.options* oojs-ui-coreWritten by: [[User:Guycn2]]*/( async () => {'use strict';const username = mw.config.get( 'wgRelevantUserName' );if ( !username || mw.config.get( 'userInfoPopupLoaded' ) ) {return;}mw.config.set( 'userInfoPopupLoaded', true );await mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] );const isAnon = mw.util.isIPAddress( username );const api = new mw.Api();async function checkIfUserExists() {if ( isAnon ) {return true;}const data = await api.get( { list: 'users', ususers: username } );if ( data.query.users[ 0 ].userid ) {return true;}return false;}if ( !( await checkIfUserExists() ) ) {return;}mw.loader.load('https:https://www.search.com.vn/wiki/index.php?lang=en&q=User:Guycn2/UserInfoPopup.css&action=raw&ctype=text/css','text/css');const scriptData = {lang: mw.config.get( 'wgUserLanguage' ),skin: mw.config.get( 'skin' ),secsFromLastEdit: await calcSecsFromLastEdit()};createInfoIcon();await $.when( mw.loader.using( 'oojs-ui-core' ), $.ready );addInfoIconToPage();attachEventListeners();function i18n( key ) {const messages = {en: {infoIconAlt: 'Info icon',femaleSymbolAlt: 'Female',maleSymbolAlt: 'Male',fetchingData: 'Fetching data…',regUnknown: 'Unknown',joined: 'Joined:',editCount: 'Edits:',lastEdited: 'Last edited:',lastEditedNever: 'Never',lastEditedUnknown: 'Unknown',groups: 'Groups:',noGroups: 'None',lastBlocked: 'Last blocked:',neverBlocked: 'Never',partiallyBlocked: 'Currently blocked (partially)',fullyBlocked: 'Currently blocked',rangeBlockedPartially: 'Currently range-blocked (partially)',rangeBlockedFully: 'Currently range-blocked',globallyBlocked: 'Currently blocked globally',globallyLocked: 'Currently locked globally',ago: '$1 ago',seconds: [ '1 second', '$1 seconds' ],minutes: [ '1 minute', '$1 minutes' ],hours: [ '1 hour', '$1 hours' ],days: [ '1 day', '$1 days' ],weeks: [ '1 week', '$1 weeks' ],months: [ '1 month', '$1 months' ],years: [ '1 year', '$1 years' ]},he: {infoIconAlt: 'צלמית מידע',femaleSymbolAlt: 'נקבה',maleSymbolAlt: 'זכר',fetchingData: 'המידע בטעינה…',regUnknown: 'לא ידוע',joined: 'הרשמה:',editCount: 'עריכות:',lastEdited: 'עריכה אחרונה:',lastEditedNever: 'אין',lastEditedUnknown: 'לא ידוע',groups: 'קבוצות:',noGroups: 'ללא',lastBlocked: 'חסימה אחרונה:',neverBlocked: 'אין',partiallyBlocked: 'חסימה פעילה כעת (חלקית)',fullyBlocked: 'חסימה פעילה כעת',rangeBlockedPartially: 'חסימת טווח פעילה כעת (חלקית)',rangeBlockedFully: 'חסימת טווח פעילה כעת',globallyBlocked: 'חסימה גלובלית פעילה כעת',globallyLocked: 'נעילה גלובלית פעילה כעת',ago: 'לפני $1',seconds: [ 'שנייה', '$1 שניות' ],minutes: [ 'דקה', '$1 דקות' ],hours: [ 'שעה', 'שעתיים', '$1 שעות' ],days: [ 'יום', 'יומיים', '$1 ימים' ],weeks: [ 'שבוע', 'שבועיים', '$1 שבועות' ],months: [ 'חודש', 'חודשיים', '$1 חודשים' ],years: [ 'שנה', 'שנתיים', '$1 שנים' ]}};if (messages[ scriptData.lang ] &&messages[ scriptData.lang ][ key ]) {return messages[ scriptData.lang ][ key ];} else {return messages.en[ key ];}}async function calcSecsFromLastEdit() {const params = {list: 'usercontribs',ucuser: username,ucprop: 'timestamp',uclimit: 1};const data = await api.get( params );if ( data.query.usercontribs.length === 0 ) {return null;}const lastEditTime =new Date( data.query.usercontribs[ 0 ].timestamp ).getTime();return ( mw.now() - lastEditTime ) / 1000;}function createInfoIcon() {const $img = $( '<img>' ).addClass( 'user-info-popup-icon' ).attr( {alt: i18n( 'infoIconAlt' ),width: '20.3',height: '20.3'} );if ( scriptData.secsFromLastEdit === null ) {$img.addClass( 'user-info-popup-grey-icon' ).attr( 'src', 'https://upload.wikimedia.org/wikipedia/commons/d/df/Information_grey.svg' );} else if ( scriptData.secsFromLastEdit < 60 * 20 ) {$img.addClass( 'user-info-popup-green-icon' ).attr( 'src', 'https://upload.wikimedia.org/wikipedia/commons/7/7d/Information_green.svg' );} else if ( scriptData.secsFromLastEdit < 60 * 60 * 24 * 30 * 3 ) {$img.addClass( 'user-info-popup-orange-icon' ).attr( 'src', 'https://upload.wikimedia.org/wikipedia/commons/f/f0/Information_orange.svg' );} else {$img.addClass( 'user-info-popup-red-icon' ).attr( 'src', 'https://upload.wikimedia.org/wikipedia/commons/5/55/Information_red.svg' );}scriptData.$indicator = $( '<div>' ).addClass( 'mw-indicator' ).attr( { id: 'mw-indicator-user-info-popup-indicator', tabindex: '0' } ).append( $img );}function addInfoIconToPage() {const $throbberImg = $( '<img>' ).attr( {alt: i18n( 'fetchingData' ),id: 'user-info-popup-throbber',src: 'https://upload.wikimedia.org/wikipedia/commons/f/f8/Ajax-loader(2).gif'} );const $placeholderText = $( '<p>' ).attr( 'id', 'user-info-popup-placeholder-text' ).text( i18n( 'fetchingData' ) );scriptData.$popupPlaceholder = $( '<div>' ).attr( 'id', 'user-info-popup-placeholder' ).append( $throbberImg, $placeholderText );scriptData.popup = new OO.ui.PopupWidget( {$content: scriptData.$popupPlaceholder,align: 'backwards',autoFlip: false,id: 'user-info-popup-popup',hideWhenOutOfView: false,padded: true,position: 'below',width: 225} );scriptData.$indicator.append( scriptData.popup.$element );if (scriptData.skin === 'vector-2022' &&$( '.vector-page-toolbar-container:has( #ca-nstab-user )' ).length) {scriptData.$indicator.insertBefore( '.vector-page-tools-landmark:has( #vector-page-tools-dropdown )' );} else {const $indicatorsContainer = $( '.mw-indicators' );if (!window.matchMedia( '( orientation: portrait )' ).matches ||scriptData.skin === 'vector-2022' ||scriptData.skin === 'vector' ||( scriptData.skin === 'monobook' && !$( '#sidebar-toggle:visible' ).length )) {scriptData.popup.setAlignment( 'forwards' );scriptData.popup.setPosition( 'before' );if ( $indicatorsContainer.children( '.mw-indicator' ).length >= 6 ) {scriptData.popup.setAutoFlip( true );}}if ( scriptData.skin === 'minerva' ) {scriptData.$indicator.css( 'float', $( 'body.rtl' ).length ? 'left' : 'right' ).appendTo( '.header-container' );} else {$indicatorsContainer.prepend( scriptData.$indicator );}}}function attachEventListeners() {scriptData.popup.on( 'ready', () => {// Prevent mobile browsers from occasionally jumping// to the top of the page when tapping the "i" icon.window.scrollTo( scriptData.posX, scriptData.posY );if (document.documentElement.clientWidth < 600 &&scriptData.skin === 'vector-2022' &&scriptData.popup.$element.hasClass( 'oo-ui-popupWidget-anchored-top' )) {adaptPopupPosition();}scriptData.popup.$element.hide().fadeIn();} );scriptData.$indicator.on( 'mouseenter focusin keydown', e => {if ( e.type === 'keydown' ) {if ( ![ 'Enter', ' ' ].includes( e.key ) ) {return;}if ( e.key === ' ' ) {e.preventDefault();}}clearTimeout( scriptData.mouseLeaveTimeout );scriptData.mouseEnterTimeout = setTimeout( openPopup, 200 );} );scriptData.$indicator.on( 'mouseleave focusout', () => {if (document.activeElement.id === 'mw-indicator-user-info-popup-indicator' ||document.activeElement.parentElement.classList.contains('user-info-popup-value')) {return;}clearTimeout( scriptData.mouseEnterTimeout );scriptData.mouseLeaveTimeout = setTimeout( closePopup, 2500 );} );$( document ).on( 'keydown', e => {if ( e.key === 'Escape' ) {closePopup();}} );$( document ).on( 'click', closePopup );$( '.oo-ui-fieldsetLayout-header, .ext-discussiontools-init-section-bar' ).on( 'click', closePopup );scriptData.$indicator.on( 'click', e => e.stopPropagation() );}function adaptPopupPosition() {const innerBody = document.querySelector( '.mw-page-container' );const innerBodyRect = innerBody.getBoundingClientRect();const indicator = scriptData.$indicator[ 0 ];const indicatorRect = indicator.getBoundingClientRect();const dir = $( 'body.rtl' ).length ? 'left' : 'right';const pos =Math.abs( indicatorRect[ dir ] - innerBodyRect[ dir ] ) -indicator.offsetWidth / 2;scriptData.popupCss = mw.util.addCSS(`#user-info-popup-popup { ${ dir }: ${ pos }px !important; }`);}function openPopup() {if ( !scriptData.popup.isVisible() ) {// posX and posY are used to prevent mobile browsers from // occasionally jumping to the top of the page when tapping// the "i" icon. See the popup's "ready" event listener above.scriptData.posX = window.scrollX;scriptData.posY = window.scrollY;scriptData.popup.toggle( true );if ( !scriptData.dataFetched ) {getUserData().then( fillPopupContent );scriptData.dataFetched = true;}}}function closePopup() {clearTimeout( scriptData.mouseLeaveTimeout );if ( scriptData.popup.isVisible() ) {scriptData.popup.$element.fadeOut( () => {scriptData.popup.toggle( false );scriptData.popup.$element.show();if ( scriptData.popupCss ) {scriptData.popupCss.disabled = true;}} );}}async function getUserData() {let params;if ( isAnon ) {params = {list: 'blocks|globalblocks|logevents|usercontribs',bkip: username,bkprop: 'flags|user',bklimit: 2,bgip: username,bgprop: 'address',bglimit: 1,leaction: 'block/block',letitle: `User:${ username }`,leprop: 'timestamp',lelimit: 1,ucuser: username,ucprop: '',uclimit: 'max'};} else {params = {list: 'blocks|logevents|usercontribs|users',meta: 'globaluserinfo',bkusers: username,bkprop: 'flags',bklimit: 1,leaction: 'block/block',letitle: `User:${ username }`,leprop: 'timestamp',lelimit: 1,ucuser: username,ucdir: 'newer',ucprop: 'timestamp',uclimit: 1,ususers: username,usprop: 'editcount|gender|groupmemberships|registration',guiuser: username,guiprop: 'groups'};}const data = await api.get( params );if ( isAnon ) {const editCount = data.query.usercontribs.length;scriptData.editCount = await renderAnonEditCount( editCount );scriptData.isGloballyBlocked = data.query.globalblocks.length;if ( scriptData.isGloballyBlocked ) {scriptData.globalBlockTarget = data.query.globalblocks[ 0 ].address;}} else {scriptData.gender = data.query.users[ 0 ].gender;if ( data.query.users[ 0 ].registration ) {scriptData.regDate =await formatDate( data.query.users[ 0 ].registration, true );} else if ( data.query.usercontribs[ 0 ] ) {scriptData.regDate =await formatDate( data.query.usercontribs[ 0 ].timestamp, true );} else {scriptData.regDate = i18n( 'regUnknown' );}scriptData.editCount = data.query.users[ 0 ].editcount.toLocaleString();const localGroups =data.query.users[ 0 ].groupmemberships.map( item => item.group );scriptData.localGroups = await renderGroups( localGroups );if ( data.query.globaluserinfo.groups ) {const globalGroups = data.query.globaluserinfo.groups.filter(item => !localGroups.includes( item ));scriptData.globalGroups = await renderGroups( globalGroups );scriptData.isLocked = data.query.globaluserinfo.locked === '';}}const blocks = data.query.blocks;scriptData.isBlocked = blocks.length;if ( scriptData.isBlocked ) {if ( isAnon && blocks[ 0 ].user !== username && blocks[ 1 ] ) {blocks.shift();}scriptData.isPartiallyBlocked = blocks[ 0 ].partial === '';scriptData.isRangeBlocked = isAnon && blocks[ 0 ].user !== username;if ( scriptData.isRangeBlocked ) {scriptData.rangeBlockTarget = blocks[ 0 ].user;}} else if ( data.query.logevents.length ) {scriptData.lastBlockDate =await formatDate( data.query.logevents[ 0 ].timestamp, false );}}async function renderAnonEditCount( editCount ) {if ( editCount < 500 ) {return editCount.toLocaleString();}await mw.loader.using( 'mediawiki.user' );const rights = await mw.user.getRights();const maxAnonEditCount = rights.includes( 'apihighlimits' ) ? 5000 : 500;if ( editCount === maxAnonEditCount ) {return `${ editCount.toLocaleString() }+`;} else {return editCount.toLocaleString();}}async function renderGroups( groups ) {if ( groups.length === 0 ) {return '';}let sysMsgGroups = '';groups.forEach( ( group, index ) => {sysMsgGroups += `{${ '{' }int:group-${ group }}}`;if ( index < groups.length - 1 ) {sysMsgGroups += ', ';}} );const params = {action: 'parse',uselang: scriptData.lang,text: sysMsgGroups,prop: 'text',contentmodel: 'wikitext',disablelimitreport: true};const data = await api.get( params );return $( data.parse.text[ '*' ] ).find( 'p' ).text().trim();}async function formatDate( timestamp, includeDay ) {await mw.loader.using( 'mediawiki.language.months' );const date = new Date( timestamp );const monthName = mw.language.months.names[ date.getMonth() ];const monthNameGen = mw.language.months.genitive[ date.getMonth() ];const year = date.getFullYear();if ( includeDay ) {const day = date.getDate();await mw.loader.using( 'user.options' );if ( mw.user.options.get( 'date' ) === 'mdy' ) {return `${ monthName } ${ day }, ${ year }`;} else {return `${ day } ${ monthNameGen } ${ year }`;}} else {return `${ monthName } ${ year }`;}}function fillPopupContent() {const $container = $( '<aside>' ).attr( 'id', 'user-info-popup-content' );const $header = $( '<header>' ).attr( 'id', 'user-info-popup-header' );$header.append($( '<bdi>' ).attr( 'id', 'user-info-popup-username' ).text( mw.util.prettifyIP( username ) ));const $ul = $( '<ul>' ).attr( 'id', 'user-info-popup-list' );$container.append( $header, $ul );if ( !isAnon ) {addListItem( $ul, i18n( 'joined' ), scriptData.regDate );}const editCounterUrl =`https://xtools.wmcloud.org/ec/${ mw.config.get( 'wgServerName' ) }/${ encodeURIComponent( username ) }`;addListItem($ul,i18n( 'editCount' ),`<a target="_blank" href="${ editCounterUrl }">${ scriptData.editCount }</a>`);const contribsUrl = mw.util.getUrl( `Special:Contributions/${ username }` );let lastEditedText;if ( scriptData.editCount === ( 0 ).toLocaleString() ) {lastEditedText = i18n( 'lastEditedNever' );} else if ( scriptData.secsFromLastEdit === null ) {lastEditedText = i18n( 'lastEditedUnknown' );} else {lastEditedText = i18n( 'ago' ).replace( '$1', calcTimeFromLastEdit() );}addListItem($ul,i18n( 'lastEdited' ),`<a href="${ contribsUrl }">${ lastEditedText }</a>`);if ( !isAnon ) {const localGroupsUrl = mw.util.getUrl( `Special:UserRights/${ username }` );const globalGroupsUrl =mw.util.getUrl( `m:Special:GlobalUserRights/${ username }` );let groupsHtml;if ( !scriptData.localGroups && !scriptData.globalGroups ) {groupsHtml =`<a href="${ localGroupsUrl }">${ i18n( 'noGroups' ) }</a>`;}if ( scriptData.localGroups && !scriptData.globalGroups ) {groupsHtml =`<a href="${ localGroupsUrl }">${ scriptData.localGroups }</a>`;}if ( !scriptData.localGroups && scriptData.globalGroups ) {groupsHtml =`<a href="${ globalGroupsUrl }">${ scriptData.globalGroups }</a>`;}if ( scriptData.localGroups && scriptData.globalGroups ) {groupsHtml =`<a href="${ localGroupsUrl }">${ scriptData.localGroups }</a>,<a href="${ globalGroupsUrl }">${ scriptData.globalGroups }</a>`;}addListItem( $ul, i18n( 'groups' ), groupsHtml );}let lastBlockText;let blockLogUrl = mw.util.getUrl( 'Special:Log', {type: 'block',page: `User:${ username }`} );if ( scriptData.isGloballyBlocked ) {lastBlockText = i18n( 'globallyBlocked' );blockLogUrl = mw.util.getUrl( 'm:Special:Log', {type: 'gblblock',page: `User:${ scriptData.globalBlockTarget }`} );} else if ( scriptData.isLocked ) {lastBlockText = i18n( 'globallyLocked' );blockLogUrl = mw.util.getUrl( 'm:Special:Log', {type: 'globalauth',page: `User:${ username }@global`} );} else if ( scriptData.isBlocked ) {if ( scriptData.isRangeBlocked ) {if ( scriptData.isPartiallyBlocked ) {lastBlockText = i18n( 'rangeBlockedPartially' );} else {lastBlockText = i18n( 'rangeBlockedFully' );}blockLogUrl = mw.util.getUrl( 'Special:Log', {type: 'block',page: `User:${ scriptData.rangeBlockTarget }`} );} else {if ( scriptData.isPartiallyBlocked ) {lastBlockText = i18n( 'partiallyBlocked' );} else {lastBlockText = i18n( 'fullyBlocked' );}}} else {lastBlockText = scriptData.lastBlockDate || i18n( 'neverBlocked' );}addListItem($ul,i18n( 'lastBlocked' ),`<a href="${ blockLogUrl }">${ lastBlockText }</a>`);if ( !isAnon && scriptData.gender !== 'unknown' ) {const images = {female: {alt: i18n( 'femaleSymbolAlt' ),path: 'https://upload.wikimedia.org/wikipedia/commons/8/8a/Light_pink_Venus_symbol.svg'},male: {alt: i18n( 'maleSymbolAlt' ),path: 'https://upload.wikimedia.org/wikipedia/commons/2/29/Light_blue_Mars_symbol.svg'}};$( '<img>' ).attr( {alt: images[ scriptData.gender ].alt,id: 'user-info-popup-gender-symbol',src: images[ scriptData.gender ].path,width: '16.6',height: '16.6'} ).appendTo( $header );}scriptData.$popupPlaceholder.replaceWith( $container );}function addListItem( $ul, property, value ) {const $li = $( '<li>' );const $property = $( '<span>' ).addClass( 'user-info-popup-property' ).text( property );const $value = $( '<span>' ).addClass( 'user-info-popup-value' ).html( value );$li.append( $property, ' ', $value ).appendTo( $ul );}function calcTimeFromLastEdit() {const secs = scriptData.secsFromLastEdit;const days = secs / 60 / 60 / 24;if ( secs < 60 ) {let fullSecs = Math.floor( secs );if ( fullSecs < 1 ) {fullSecs = 1;}const secsArrLength = i18n( 'seconds' ).length;if ( fullSecs < secsArrLength ) {return i18n( 'seconds' )[ fullSecs - 1 ];} else {return i18n( 'seconds' )[ secsArrLength - 1 ].replace( '$1', fullSecs );}} else if ( secs < 60 * 60 ) {const fullMins = Math.floor( secs / 60 );const minsArrLength = i18n( 'minutes' ).length;if ( fullMins < minsArrLength ) {return i18n( 'minutes' )[ fullMins - 1 ];} else {return i18n( 'minutes' )[ minsArrLength - 1 ].replace( '$1', fullMins );}} else if ( secs < 60 * 60 * 24 ) {const fullHours = Math.floor( secs / 60 / 60 );const hoursArrLength = i18n( 'hours' ).length;if ( fullHours < hoursArrLength ) {return i18n( 'hours' )[ fullHours - 1 ];} else {return i18n( 'hours' )[ hoursArrLength - 1 ].replace( '$1', fullHours );}} else if ( days < 7 ) {const fullDays = Math.floor( days );const daysArrLength = i18n( 'days' ).length;if ( fullDays < daysArrLength ) {return i18n( 'days' )[ fullDays - 1 ];} else {return i18n( 'days' )[ daysArrLength - 1 ].replace( '$1', fullDays );}} else if ( days < 30 ) {const fullWeeks = Math.floor( days / 7 );const weeksArrLength = i18n( 'weeks' ).length;if ( fullWeeks < weeksArrLength ) {return i18n( 'weeks' )[ fullWeeks - 1 ];} else {return i18n( 'weeks' )[ weeksArrLength - 1 ].replace( '$1', fullWeeks );}} else if ( days < 365 ) {let fullMonths = Math.floor( days / 30 );if ( fullMonths === 12 ) {fullMonths = 11;}const monthsArrLength = i18n( 'months' ).length;if ( fullMonths < monthsArrLength ) {return i18n( 'months' )[ fullMonths - 1 ];} else {return i18n( 'months' )[ monthsArrLength - 1 ].replace( '$1', fullMonths );}} else {const fullYears = Math.floor( days / 365 );const yearsArrLength = i18n( 'years' ).length;if ( fullYears < yearsArrLength ) {return i18n( 'years' )[ fullYears - 1 ];} else {return i18n( 'years' )[ yearsArrLength - 1 ].replace( '$1', fullYears );}}}} )();
🔥 Top keywords: Main PageSpecial:SearchIndian Premier LeagueWikipedia:Featured picturesPornhubUEFA Champions League2024 Indian Premier LeagueFallout (American TV series)Jontay PorterXXXTentacionAmar Singh ChamkilaFallout (series)Cloud seedingReal Madrid CFCleopatraRama NavamiRichard GaddDeaths in 2024Civil War (film)Shōgun (2024 miniseries)2024 Indian general electionJennifer PanO. J. SimpsonElla PurnellBaby ReindeerCaitlin ClarkLaverne CoxXXX (film series)Facebook2023–24 UEFA Champions LeagueYouTubeCandidates Tournament 2024InstagramList of European Cup and UEFA Champions League finalsJude BellinghamMichael Porter Jr.Andriy LuninCarlo AncelottiBade Miyan Chote Miyan (2024 film)