Jump to content

User:LinguistAtLarge/AfDNav.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.
// ###################################################################
// add some keyboard shortcuts on AfD pages
if (wgPageName.indexOf('Wikipedia:Articles_for_deletion/Log/20') != -1 || wgPageName.indexOf('User:LinguistAtLarge/Today\'s_AfD') != -1)
{
	addOnloadHook(function()
	{
		var debug = false;

		if (debug) { alert('Start: adding AfD keyboard shortcuts'); }

		// see if an afd is closed by passing the a name for it
		var is_afd_closed = function(afd_anchor)
		{
			var el = document.getElementById(afd_anchor);

			var parent_class = '';
			if (el && el.parentNode)
			{
				parent_class = el.parentNode.getAttribute('class');
			}
			if (parent_class && parent_class.indexOf('xfd-closed') != -1)
			{
				return true;
			}
			return false;
		};

		if (debug) { alert('After is_afd_closed definition'); }

		// see if an afd article has been deleted or not
		var is_afd_article_redlink = function(afd_anchor)
		{
			if (debug) { alert('In is_afd_article_redlink() : Start : afd_anchor : ' + afd_anchor); }

			// get the anchor
			var el = document.getElementById(afd_anchor);
			if (!el)
			{
				return false;
			}

			if (debug) { alert('In is_afd_article_redlink() : el : ' + el); }
			if (debug) { alert('In is_afd_article_redlink() : el.nodeType : ' + el.nodeType); }

			// get the <h3> element following it
			var the_heading = el.nextSibling;

			if (debug) { alert('In is_afd_article_redlink() : the_heading (1) : ' + the_heading); }

			if (!the_heading)
			{
				the_heading = el.parentNode.nextSibling;
			}
			if (!the_heading)
			{
				return false;
			}

			if (debug) { alert('In is_afd_article_redlink() : the_heading (2) : ' + the_heading); }

			while (the_heading.nodeType != 1)
			{
				the_heading = the_heading.nextSibling;
			}

			if (debug) { alert('In is_afd_article_redlink() : the_heading (3)(after while) : ' + the_heading); }

			if (!the_heading)
			{
				return false;
			}

			// get the <a> elements inside the <h3>, and specifically the link to the article
			var search_elements = the_heading.getElementsByTagName('a');

			if (debug) { alert('In is_afd_article_redlink() : search_elements : ' + search_elements); }

			// replace this now, for searching within the HREF value
			afd_anchor = afd_anchor.replace(/\./g, '%');

			var i;
			for (i = 0; i < search_elements.length; ++i)
			{
				if (search_elements[i] && search_elements[i].href && search_elements[i].href.indexOf &&  search_elements[i].href.indexOf('title=' + afd_anchor) != -1 && search_elements[i].href.indexOf('redlink=1') != -1)
				{
					return true;
				}
			}
			return false;
		};

		if (debug) { alert('After is_afd_article_redlink definition'); }

		// has this user participated in this afd?
		var afd_participation_cache = {};
		var afd_closed_cache = {};
		var have_participated_in_afd = function(afd_anchor)
		{
			//afd_anchor = afd_anchor.replace(/\./g, '%');

			if (typeof(afd_participation_cache[afd_anchor]) == 'undefined')
			{
				// cache participation in all afds
				var anchors = document.getElementsByTagName('a');
				var i = 0;
				var curr_afd_anchor = '';
				var in_top_section_of_closed_afd = false;
				var next_afd_closed_flag = false;

				for (i = 0; i < anchors.length; ++i)
				{
					if (anchors[i].href &&
						anchors[i].href.indexOf('http://en.wikipedia.org/wiki/Wikipedia:Articles_for_deletion/Log/20') != -1 &&
						anchors[i].parentNode &&
						anchors[i].parentNode.className == 'printfooter')
					{
						// at the end of page, so stop
						//alert('at end of page');
						i = anchors.length; // break
					}
					else if (anchors[i].parentNode &&
						anchors[i].parentNode.nodeName.toUpperCase() == 'SPAN' &&
						anchors[i].parentNode.className == 'mw-headline' &&
						anchors[i].href)
					{
						// change the current afd we are on
						var matches = anchors[i].href.match(/\/wiki\/(.+)$/);
						if (!matches)
						{
							matches = anchors[i].href.match(/\/w\/index\.php\?title=(.+?)&action=edit/);
						}
						if (matches && matches[1])
						{
							curr_afd_anchor = matches[1];
							curr_afd_anchor = curr_afd_anchor.replace(/%/g, '.');
							//curr_afd_anchor = curr_afd_anchor.replace(/'/g, '.27'); // this should be taken care of above.
							curr_afd_anchor = curr_afd_anchor.replace(/\(/g, '.28');
							curr_afd_anchor = curr_afd_anchor.replace(/\)/g, '.29');
							curr_afd_anchor = curr_afd_anchor.replace(/,/g, '.2C');

							// default to false
							afd_participation_cache[curr_afd_anchor] = false;
							afd_closed_cache[curr_afd_anchor] = false;

							if (next_afd_closed_flag)
							{
								// we are now at the next afd, so mark it as closed by us
								next_afd_closed_flag = false;
								afd_closed_cache[curr_afd_anchor] = true;
							}

							// no longer in top section
							in_top_section_of_closed_afd = false; 
						}
						else
						{
							if (debug) { alert('PROBLEM: ' + anchors[i].href); }
						}
					}
					else if (anchors[i].href &&
							anchors[i].href.indexOf('/wiki/Wikipedia:Deletion_review') != -1 &&
							anchors[i].parentNode &&
							anchors[i].parentNode.nodeName.toUpperCase() == 'I')
					{
						// we are in a new afd, but it is closed, so we do not have the afd_anchor yet
						in_top_section_of_closed_afd = true;
					}
					else if (curr_afd_anchor &&
							anchors[i].href &&
							anchors[i].href.indexOf('User:LinguistAtLarge') != -1 &&
							anchors[i].parentNode &&
							anchors[i].parentNode.nodeName.toUpperCase() != 'SMALL' &&
							anchors[i].parentNode.parentNode &&
							anchors[i].parentNode.parentNode.nodeName.toUpperCase() != 'SMALL')
					{
						// see if we have participated in this afd
						if (in_top_section_of_closed_afd)
						{
							// we closed the following afd
							next_afd_closed_flag = true;
						}
						else
						{
							// we participated in the afd
							afd_participation_cache[curr_afd_anchor] = true;
						}
					}
				}
			}

			return afd_participation_cache[afd_anchor];
		};

		if (debug) { alert('After have_participated_in_afd definition'); }

		// see if this user has closed the given afd
		var have_closed_afd = function(afd_anchor)
		{
			// make sure data is cached
			have_participated_in_afd(afd_anchor);

			return afd_closed_cache[afd_anchor];
		};

		if (debug) { alert('After have_closed_afd definition'); }

		// get an anchor for each afd
		var afd_anchors = (function()
		{
			if (debug) { alert('In afd_anchors() : Start'); }

			var base_element = window.document.getElementById('toc');
			var search_elements = base_element.getElementsByTagName('a');
			var len = search_elements.length;
			var afd_ids = [];
			var href = '';
			var pos = -1;
			var the_anchor = '';
			var add_text = '';
			var open_afd_count = 0;
			var open_deleted_afd_count = 0;
			var this_afd_open = false;
			var total_afd_count = 0;
			for(var i = 0; i < len; ++i)
			{
				href = search_elements[i].href;
				pos = href.indexOf('#');
				if (pos != -1)
				{
					the_anchor = href.substr(pos + 1);
					add_text = '';

					if (debug) { alert('In afd_anchors() : In loop. Anchor: ' + the_anchor); }

					afd_ids.push(the_anchor);
					if (is_afd_closed(the_anchor))
					{
						add_text += ' <em style="color: black ! important;">[closed]</em>';
						this_afd_open = false;
					}
					else
					{
						add_text += ' <em style="color: green ! important; font-weight: bold ! important;">[open]</em>';
						this_afd_open = true;
						++open_afd_count;
					}
					if (is_afd_article_redlink(the_anchor))
					{
						add_text += ' <em style="color: red ! important;">[redlink]</em>';
						if (this_afd_open)
						{
							++open_deleted_afd_count;
							add_text += ' <em style="color: red ! important;">**********</em>';
						}
					}
					if (have_participated_in_afd(the_anchor))
					{
						add_text += ' <em style="color: orange ! important;">[participated]</em>';
					}
					if (have_closed_afd(the_anchor))
					{
						add_text += ' <em style="color: orange ! important;">[closed]</em>';
					}

					if (debug) { alert('In afd_anchors() : In loop. Add text: ' + add_text); }

					search_elements[i].innerHTML = search_elements[i].innerHTML + add_text;

					++total_afd_count;
				}
			}

			// show open/closed/redlink counts at top of toc
			var tocel = document.getElementById('toctitle');
			var newtocel = document.createElement('div');
			newtocel.innerHTML = 'Open: <b>' + open_afd_count + '</b> &mdash; Open but deleted: <b>' + open_deleted_afd_count + '</b> &mdash; Total: <b>' + total_afd_count + '</b>';
			tocel.appendChild(newtocel);

			if (debug) { alert('In afd_anchors() : End'); }
			return afd_ids;
		})();

		if (debug) { alert('AfD shortcut anchors: ' + afd_anchors); }

		// jump to an afd anchor
		var jumptoanchor = function(anchor)
		{	
			var el = document.getElementById(anchor);

			// if the afd is closed, scroll to the top of the div, instead of the a name (only applies to scrollIntoView)
			if (is_afd_closed(anchor))
			{
				el = el.parentNode;
			}

			if (el && el.scrollIntoView)
			{
				el.scrollIntoView();
			}
			else
			{
				window.location.hash = '#' + anchor;
			}
		};

		// handle keydown events
		var onkeydown_handler = function(e)
		{
			var e = e || window.event;
			var key = e.which || e.keyCode || e.charCode || null;
			var target = (e.srcElement || e.target || null);
			var shifted = (e.shiftKey || (e.modifiers && (e.modifiers & 4)));
			var ctrled = (e.ctrlKey || (e.modifiers && (e.modifiers & 2)));
			var tag_name = target.tagName.toLowerCase();
			var inputting = (tag_name == 'textarea' || tag_name == 'input' || tag_name == 'select') ? true : false;

			if (shifted || ctrled || inputting)
			{
				return;
			}

			if (typeof this.curr_afd_anchor_index == 'undefined')
			{
				this.last_afd_anchor_index = afd_anchors.length - 1;

				// set this to the fragment if it exists on page load
				this.curr_afd_anchor_index = -1;
				var curr_afd_anchor = '';
				if (window.location.hash)
				{
					curr_afd_anchor = window.location.hash.substring(1);
				}

				var len = afd_anchors.length;
				for (var i = 0; i < len; ++i)
				{
					if (afd_anchors[i] == curr_afd_anchor)
					{
						this.curr_afd_anchor_index = i;
						break;
					}
				}
			}

			switch (key)
			{
				// first afd f
				case 70:
				{
					if (this.curr_afd_anchor_index != 0)
					{
						this.curr_afd_anchor_index = 0;
						jumptoanchor(afd_anchors[0]);
					}
					break;
				}
				// last afd l
				case 76:
				{
					if (this.curr_afd_anchor_index != this.last_afd_anchor_index)
					{
						this.curr_afd_anchor_index = this.last_afd_anchor_index;
						jumptoanchor(afd_anchors[this.last_afd_anchor_index]);
					}
					break;
				}
				// next afd n
				case 78:
				{
					if (this.curr_afd_anchor_index < this.last_afd_anchor_index)
					{
						++this.curr_afd_anchor_index;
						jumptoanchor(afd_anchors[this.curr_afd_anchor_index]);
					}
					break;
				}
				// previous afd p
				case 80:
				{
					if (this.curr_afd_anchor_index > 0)
					{
						--this.curr_afd_anchor_index;
						jumptoanchor(afd_anchors[this.curr_afd_anchor_index]);
					}
					break;
				}
			}
			return true;
		};

		// set up the keydown handler
		if (debug) { alert('Adding keydown handler'); }
		addHandler(document, 'keydown', onkeydown_handler);

		// add shortcut keys reminder at the bottom of the page
		if (debug) { alert('Adding shortcut keys reminder at bottom of page'); }
		var newel = document.createElement('div');
		newel.innerHTML = 'Shortcut keys: <b>f</b> - first afd, <b>n</b> - next afd, <b>p</b> - previous afd, <b>l</b> - last afd';
		newel.setAttribute('class', 'catlinks');
		document.getElementById('bodyContent').appendChild(newel);

		if (debug) { alert('End: adding AfD keyboard shortcuts'); }
	});
}