Jump to content

User:Awesome Aasim/linkinfo.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
if (!userAndAPageInfoLoaded) {
	var userAndAPageInfoLoaded = true;
	(function() {
		$(document).ready(async function() {
			function isIP(text) {
				return mw.util.isIPv6Address(text) || mw.util.isIPv4Address(text);
			}
			var user, page, link;
			var queries = {};
			mw.loader.load("https://en.wikipedia.org/wiki/User:Awesome_Aasim/linkinfo.css?action=raw&ctype=text/css", "text/css");
			mw.loader.using(['oojs-ui-core', 'oojs-ui-widgets', 'oojs-ui.styles.icons-content', 'oojs-ui.styles.icons-alerts', 'oojs-ui.styles.icons-interactions', 'oojs-ui.styles.icons-moderation', 'oojs-ui.styles.icons-editing-core', 'oojs-ui.styles.icons-editing-list', 'oojs-ui.styles.icons-editing-functions', 'oojs-ui.styles.icons-editing-advanced', 'oojs-ui.styles.icons-user', 'oojs-ui.styles.icons-layout', 'oojs-ui.styles.icons-accessibility'], async function() {
				const OptWidget = OO.ui.MenuOptionWidget;
				const SectOptWidget = OO.ui.MenuSectionOptionWidget;
				// below adapted partly from Microsoft Copilot
				// Create a placeholder div where the custom context menu will attach
				const $container = $('<div class="linkinfo">').wrapAll().css({"position": "fixed", zIndex: 10000}).appendTo( document.body );
				$container.css({
					'user-select': 'none',
					'-webkit-user-select': 'none',
					'-moz-user-select': 'none',
					'-ms-user-select': 'none'
				});
				// Define menu items
				var select = new OO.ui.MenuSelectWidget();
				// var menu = new OO.ui.MenuLayout({
				// 	menuPanel: new OO.ui.PanelLayout({padded: true, scrollable: true, expanded: true})   
				// });
				// menu.$menu.append(select.$element);
				// Create popup widget to wrap the menu
				var popup = select;

				async function fetch(dataQuery, that) {
					let data;
					try {
						data = await $.get(mw.config.get('wgScriptPath') + '/api.php', dataQuery);
					} catch (e) {
						return;
					}
					let deletedrevs = [];
					if (data.query) {
						if (!data.query.pages[0].actions.undelete.length) {
							deletedrevs = await $.get(mw.config.get("wgScriptPath") + "/api.php", {
								action: "query",
								format: "json",
								list: "deletedrevs",
								title: data.query.pages[0].title,
								"formatversion": 2
							});
							deletedrevs = deletedrevs.query.deletedrevisions || [];
						}
					}
					queries[JSON.stringify(dataQuery)] = [data, deletedrevs];
					$(that).data("result", data);
					$(that).data("deletedrevs", deletedrevs);
				}
				function makeQuery(that) {
					if ($(that).data("nolinkinfo")) {
						return;
					}
					if (!$(that).attr("href")) return;
					let url = new URL($(that).attr("href"), location.origin);
					if (url.origin != location.origin || $(that).hasClass("external") || $(that).hasClass("extiw")) {
						return {};
					}
					let pageName;
					if (url.pathname.search(mw.config.get("wgArticlePath").replace("$1", "")) != 0) {
						pageName = url.searchParams.get("title");
					} else {
						pageName = url.pathname.substring(mw.config.get("wgArticlePath").replace("$1", "").length, url.pathname.length);
					}
					if (!pageName) {
						return {};
					}
					let title = new mw.Title(decodeURIComponent(pageName));
					if (title.getNamespaceId() < 0) {
						return {};
					}
					var showUserLinks = title.getNamespaceId() == 2 || title.getNamespaceId() == 3;
					
					let dataQuery = {
						"action": "query",
						"format": "json",
						"meta": "userinfo",
						"uiprop": "rights",
						"prop": "info",
						"inprop": "displaytitle|protection|subjectid|talkid|associatedpage",
						"intestactions": "edit|move|delete|undelete|protect|upload",
						"intestactionsdetail": "quick",
						"titles": title.getPrefixedText(),
						"formatversion": 2
					};
					if (showUserLinks) {
						let user;
						if (!isIP(title.getMainText()) || title.getNamespaceId() == 3) {
							user = title.getMainText().split("/")[0];
						} else {
							user = title.getMainText();
						}
						
						dataQuery = Object.assign(dataQuery, {
							"list": "users",
							"ususers": user,
							"usprop": "blockinfo|emailable|groups|implicitgroups|cancreate|groupmemberships"
						});
					}
					$(that).data("query", dataQuery);
					return dataQuery;
				}
				async function loadDataBeforeRightClick(e) {
					if ($(this).data("result")) return;
					let dataQuery = makeQuery(this);
					if (dataQuery) {
						let data = queries[JSON.stringify(dataQuery)] ? queries[JSON.stringify(dataQuery)][0] : null;
						if (data == null) {
							await fetch(dataQuery, this);
						} else {
							$(this).data("result", data);
						}
					}
				}
				$(document).on("mouseover", "a", loadDataBeforeRightClick);
				$(document).on("touchstart", "a", loadDataBeforeRightClick);
				var contextMenuEvent, contextMenuObject;
				$(document).on("contextmenu", "a", async function(e) {
					contextMenuEvent = e;
					contextMenuObject = this;
					function show() {
						//popup.setSize(null, null, false);
						popup.toggle(true);
						popup.toggleClipping(false);
						let puRect = popup.$element[0].getBoundingClientRect();
						let width = Math.min(window.innerWidth, document.documentElement.clientWidth);
						let height = Math.min(window.innerHeight, document.documentElement.clientHeight);
						if (puRect.width >= width / 2) {
							select.addItems([
								new OptWidget({ data: "close", label: "Close menu", icon: "close" })
							], 0);
						}
						puRect = popup.$element[0].getBoundingClientRect();
						if (puRect.bottom > height) {
							$container.css({ top: puRect.top - puRect.height > 3 ? puRect.top - puRect.height : 3 });
						}
						puRect = popup.$element[0].getBoundingClientRect();
						if (puRect.top < 3) {
							$container.css({ top: 3 });
						}
						puRect = popup.$element[0].getBoundingClientRect();
						if (puRect.right > width) {
							$container.css({ left: contextMenuEvent.clientX - puRect.width - 1 });
						}
						puRect = popup.$element[0].getBoundingClientRect();
						if (puRect.left < 3) {
							$container.css({ left: 3 });
						}
						popup.toggleClipping(true);
						popup.toggle(false);
						popup.toggle(true);
						// if (rightEdgeOS >= window.innerWidth || leftEdgeOS <= 0 || bottomEdgeOS >= window.innerHeight || topEdgeOS <= 0) {
						// 	$container.css({ top: $(window).scrollTop() + 'px', left: window.innerWidth / 2 + $(window).scrollLeft() + 'px' });
						// 	//popup.toggle(false);
						// 	//popup.computePosition();
						// 	//popup.setSize(null, null, false);
						// 	//popup.toggle(true);
						// }
					}
					function makeMenu(data, deletedrevs, $newA) {
						$container.css({ top: contextMenuEvent.clientY + 1 + 'px', left: contextMenuEvent.clientX + 1 + 'px' });
						popup.toggle(false);
						select.clearItems();
						select.addItems([
							new OptWidget({ data: "newtab", label: "Open in new tab", icon:  "newWindow" })
						]);
	
						select.addItems([
							new OptWidget({ data: "copylink", label: "Copy link", icon: "link" })
						]);
	
						if (window.getSelection().toString()) {
							select.addItems([
								new OptWidget({ data: "copy", label: "Copy", icon: "copy" })
							]);
						}
						function addPrimaryPageLinks() {
							select.addItems([
								new OptWidget({ data: "pageview", label: "View", flags: "progressive", icon: "eye" })
							]);
							select.addItems([
								new OptWidget({ data: "pagelink", label: "Copy as wikilink", icon: "wikiText" })
							]);
							if (page.ns % 2 == 0) {
								select.addItems([
									new OptWidget({ data: "pageassoc", label: "Discuss", icon: "speechBubbles" })
								]);
							} else {
								select.addItems([
									new OptWidget({ data: "pageassoc", label: "View primary", icon: "article" })
								]);
							}
							select.addItems([
								new OptWidget({ data: "pagelogs", label: "Page logs", icon: "viewDetails" })
							]);
						}
						if (data && data.query) {
							page = data.query.pages[0];
							if (data.query.users) {
								user = data.query.users[0];
								if (!user.missing && (!user.invalid || isIP(user.name))) {
									select.addItems([
										new SectOptWidget({ label: "User options: " + user.name })	
									]);
									if (user.name.split("/").length == 1) {
										if (!isIP(user.name)) {
											select.addItems([
												new OptWidget({ data: "userpage", label: "Profile", flags: "progressive", icon: "userAvatar" }),
												new OptWidget({ data: "userlink", label: "Copy mention", icon: "wikiText" }),
												new OptWidget({ data: "usertalk", label: "Message", icon: "userTalk" })
											]);
										} else {
											select.addItems([
												new OptWidget({ data: "usertalk", label: "Message", flags: "progressive", icon: "userTalk" })
											]);
										}
									}
									select.addItems([
										new OptWidget({ data: "usercontribs", label: "Contributions", icon: "userContributions" })
									]);
									if (data.query.userinfo.rights.includes("deletedhistory")) {
										select.addItems([
											new OptWidget({ data: "userdeletedcontribs", label: "Deleted contributions", icon: "eyeClosed" })
										]);
									}
									select.addItems([
										new OptWidget({ data: "userperformlogs", label: "User logs", icon: "listBullet" }),
										new OptWidget({ data: "usertargetlogs", label: "Target logs", icon: "viewDetails" })
									]);
									if (user.emailable && data.query.userinfo.rights.includes("sendemail")) {
										select.addItems([
											new OptWidget({ data: "useremail", label: "Email", icon: "message" })
										]);
									}
									if (data.query.userinfo.rights.includes("block")) {
										if (user.blockid) {
											select.addItems([
												new OptWidget({ data: "userblock", label: "Change block", flags: "destructive", icon: "block" }),
												new OptWidget({ data: "userunblock", label: "Unblock", flags: "destructive", icon: "unBlock" })
											]);
										} else {
											select.addItems([
												new OptWidget({ data: "userblock", label: "Block", flags: "destructive", icon: "block" })
											]);
										}
									}
									if (!isIP(user.name)) {
										select.addItems([
											new OptWidget({ data: "userroles", label: "User roles", icon: "userRights" }),
											new OptWidget({ data: "userid", label: "Copy user ID", icon: "markup" })
										]);
									}
								} else {
									select.addItems([
										new SectOptWidget({ label: "User not found: " + user.name })
									]);
								}
								select.addItems([
									new SectOptWidget({ label: "Page options: " + page.title })	
								]);
								if (page.title.split("/").length != 1 || user.missing) {
									addPrimaryPageLinks();
								} else if (page.ns % 2 == 1) {
									select.addItems([
										new OptWidget({ data: "pagelink", label: "Copy as wikilink", icon: "wikiText" }),
										new OptWidget({ data: "pagelogs", label: "Page logs", icon: "viewDetails" })
									]);
								}
							}
		
							if (!data.query.users) {
								select.addItems([
									new SectOptWidget({ label: "Page options: " + page.title })	
								]);
								addPrimaryPageLinks();
							}
							
							if (page.redirect) {
								select.addItems([
									new OptWidget({ data: "pageviewredir", label: "View redirect", icon: "articleRedirect" })
								]);
							}
							
							select.addItems([
								new OptWidget({ data: "pageinfo", label: "Page information", icon: "info" })
							]);
		
							if (!page.actions.edit.length) {
								if (page.missing) {
									select.addItems([
										new OptWidget({ data: "pageedit", label: "Create", icon: "articleAdd" })
									]);
								} else {
									select.addItems([
										new OptWidget({ data: "pageedit", label: "Edit", icon: "edit" })
									]);
								}
							} else {
								if (!page.missing) {
									select.addItems([
										new OptWidget({ data: "pageedit", label: "View source", icon: "editLock" })
									]);
								}
							}
							if (!page.missing) {
								select.addItems([
									new OptWidget({ data: "pagehist", label: "History", icon: "history" })
								]);
								if (!page.actions.move.length) {
									select.addItems([
										new OptWidget({ data: "pagemove", label: "Move", icon: "literal" })
									]);
								}
								if (!page.actions.upload.length && page.ns == 6) {
									select.addItems([
										new OptWidget({ data: "fileupload", label: "Replace file", icon: "upload" })
									]);
								}
								if (!page.actions.delete.length) {
									select.addItems([
										new OptWidget({ data: "pagedel", label: "Delete", "flags": "destructive", icon: "trash" })
									]);
								}
							} else {
								if (!page.actions.upload.length && page.ns == 6) {
									select.addItems([
										new OptWidget({ data: "fileupload", label: "Upload file", icon: "upload" })
									]);
								}
								if (!page.actions.undelete.length && deletedrevs.length) {
									select.addItems([
										new OptWidget({ data: "pageundel", label: "Restore", "flags": "destructive", icon: "restore" })
									]);
								}
							}
							if (!page.actions.protect.length) {
								if (page.protection.length > 0) {
									select.addItems([
										new OptWidget({ data: "pageprot", label: "Change or Remove Protection", icon: "unLock" })
									]);
								} else {
									select.addItems([
										new OptWidget({ data: "pageprot", label: "Protect", icon: "lock" })
									]);
								}
							}
							if (!page.missing) {
								select.addItems([
									new OptWidget({ data: "pageid", label: "Copy page ID", icon: "markup" })
								]);
							}
						}
						$newA.data("nolinkinfo", true);
						$newA.find("a").data("nolinkinfo", true);
						$newA.wrapAll("<span/>");
						select.addItems([
							new SectOptWidget({ label: $newA.parent().prepend("Original link: ") })
						]);
						show();
					}
					let dataQuery = $(this).data("query") || makeQuery(this);
					if (!dataQuery) return;

					e.preventDefault();
					e.stopPropagation();
					select.off( 'choose' );
					select.clearItems();
					$container.html( '' );
					select = new OO.ui.MenuSelectWidget();
					// menu = new OO.ui.MenuLayout({
					// 	menuPanel: new OO.ui.PanelLayout({padded: true, scrollable: true, expanded: true})   
					// });
					// menu.$menu.append(select.$element);
					// Create popup widget to wrap the menu
					popup = select;
					$container.append( popup.$element );
				    select.on( 'choose', async function (item) {
						let data = item.getData();
						switch (data) {
							case "close":
								popup.toggle( false );
								break;
							case "newtab":
								popup.toggle( false );
								window.open(link);
								break;
							case "copylink":
								popup.toggle( false );
								await navigator.clipboard.writeText(link.toString());
								break;
							case "copy":
								popup.toggle( false );
								await document.execCommand("copy");
								break;
	
							case "userpage":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `User:${user.name}`);
								break;
							case "userlink":
								popup.toggle( false );
								await navigator.clipboard.writeText(`@[[${mw.config.get("wgFormattedNamespaces")[2]}:${user.name}|${user.name}]]`);
								break;
							case "usertalk":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `User_talk:${user.name}`);
								break;
							case "usercontribs":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:Contributions/${user.name}`);
								break;
							case "userdeletedcontribs":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:DeletedContributions/${user.name}`);
								break;
							case "userperformlogs":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:Log/${user.name}`);
								break;
							case "usertargetlogs":
								popup.toggle( false );
								location.href = (function() {
									var url = new URL(location.origin);
									url.pathname = mw.config.get("wgScriptPath") + "/index.php";
									url.searchParams.set("title", "Special:Log");
									url.searchParams.set("page", `User:${user.name}`);
									return url;
								})();
								break;
							case "useremail":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:Email/${user.name}`);
								break;
							case "userblock":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:Block/${user.name}`);
								break;
							case "userunblock":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:Unblock/${user.name}`);
								break;
							case "userroles":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:UserRights/${user.name}`);
								break;
							case "userid":
								popup.toggle( false );
								await navigator.clipboard.writeText(user.userid);
								break;
	
							case "pageview":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", page.title);
								break;
							case "pageassoc":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", page.associatedpage);
								break;
							case "pagelink":
								popup.toggle( false );
								await navigator.clipboard.writeText(`[[${page.title}]]`);
								break;
							case "pagelogs":
								popup.toggle( false );
								location.href = (function() {
									var url = new URL(location.origin);
									url.pathname = mw.config.get("wgScriptPath") + "/index.php";
									url.searchParams.set("title", "Special:Log");
									url.searchParams.set("page", page.title);
									return url;
								})();
								break;
							case "pageinfo":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:PageInfo/${page.title}`);
								break;
							case "pageviewredir":
								popup.toggle( false );
								location.href = (function() {
									var url = new URL(location.origin);
									url.pathname = mw.config.get("wgScriptPath") + "/index.php";
									url.searchParams.set("title", page.title);
									url.searchParams.set("redirect", "no");
									return url;
								})();
								break;
							case "pageedit":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:EditPage/${page.title}`);
								break;
							case "pagehist":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:History/${page.title}`);
								break;
							case "pagemove":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:MovePage/${page.title}`);
								break;
							case "pagedel":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:DeletePage/${page.title}`);
								break;
							case "pageundel":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:Undelete/${page.title}`);
								break;
							case "pageprot":
								popup.toggle( false );
								location.href = mw.config.get("wgArticlePath").replace("$1", `Special:ProtectPage/${page.title}`);
								break;
							case "pageid":
								popup.toggle( false );
								await navigator.clipboard.writeText(page.pageid);
								break;
								
							case "fileupload":
								popup.toggle( false );
								location.href = (function() {
									var url = new URL(location.origin);
									url.pathname = mw.config.get("wgScriptPath") + "/index.php";
									url.searchParams.set("title", "Special:Upload");
									url.searchParams.set("wpDestFile", page.title.substring(mw.config.get("wgFormattedNamespaces")[6].length + 1, page.title.length));
									if (!page.missing) {
										url.searchParams.set("wpForReUpload", 1);
									}
									return url;
								})();
								break;
						}
				    });
					url = new URL($(contextMenuObject).attr("href"), location.origin);
					link = url;
					let data = queries[JSON.stringify(dataQuery)] ? queries[JSON.stringify(dataQuery)][0] : null;
					let deletedrevs = queries[JSON.stringify(dataQuery)] ? queries[JSON.stringify(dataQuery)][1] : null;
					if (link == url) makeMenu($(contextMenuObject).data("result") || data, deletedrevs, $(contextMenuObject).clone());
					await fetch(dataQuery, this);
					if (link == url) makeMenu($(contextMenuObject).data("result") || data, deletedrevs, $(contextMenuObject).clone());
				});
				$(document).on("scroll", function() {
					popup.toggle( false );
				});

			});
		});
	})();
}