Bahaipedia
Bahaipedia
Menu
About Bahaipedia
Ask a question
General help
Random page
Recent changes
In other projects
Tools
What links here
Related changes
User contributions
Logs
View user groups
Upload file
Special pages
Printable version
Permanent link
Page information
User page
Discussion
View source
View history
Talk
Contributions
Create account
Log in
Navigation
About Bahaipedia
Ask a question
General help
Random page
Recent changes
In other projects
Learn more
Core topics
Bahá’í Faith
Central Figures
Teachings
Practices
Tools
What links here
Related changes
User contributions
Logs
View user groups
Upload file
Special pages
Printable version
Permanent link
Page information
Translations

User:Brettz9/common.js

From Bahaipedia
< User:Brettz9
Jump to:navigation, search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/*

CONTENTS
1. Collapsible headings (taken from https://bahai9.com/index.php?title=MediaWiki:Common.js&action=edit )
2. Collapsible list (taken from https://bahai9.com/index.php?title=MediaWiki:Common.js&action=edit )
*/

// Collapsible headings
var a = $('<a href="javascript:void(0);">collapse</a>').click(function () {
	var currentHeading = parseInt($(this).parent().parent()[0].nodeName.match(/\d$/));
	var sameOrHigherHeading = 'h' + Array.from({length: 6}, function (x, i) {return i+1;}).slice(0, currentHeading).join(',h');
	var method = this.textContent === 'collapse' ? 'hide' : 'show';
	$(this).parent().parent().nextUntil(sameOrHigherHeading)[method]();
	this.textContent = this.textContent === 'collapse' ? 'show' : 'collapse';
});
$('h1,h2,h3,h4,h5,h6').children('.mw-editsection').append(' [', a, ']');

// add collapsible list if an empty span is present indicating to do so
if ($('.enable_collapsibleList').length || $('.enable_collapsibleList_collapsed').length) {
	$('ul,ol').each(function () {
		$(this).addClass('collapsibleList');
		var li = $(this).find('li:has(ul,ol)').addClass('collapsibleListOpen');
		if (!li.find('span').length) {
			li.prepend('<span style="user-select: none;">&nbsp; &nbsp; &nbsp;</span>');
		}
	});
}

// User:Brettz9 added with some JSLint/XHTML/JSDoc clean-up, optimization/convenience changes, OL support, and beginning of work to allow pre-expansion of lists
/*
MEDIAWIKI LIST NOTES

Nested DL hierarchies do not work properly with Mediawiki (see bug at http://www.mediawiki.org/wiki/Thread:Project:Support_desk/How_to_create_nested_definition_lists%3F )

Resources:
1. http://www.mediawiki.org/wiki/Help:Formatting
2. http://en.wikipedia.org/wiki/Help:List
*/
/*
CollapsibleLists.js

An object allowing lists to dynamically expand and collapse

Original version created by Stephen Morley - http://code.stephenmorley.org/javascript/collapsible-lists/ -
and released under the terms of the CC0 1.0 Universal legal code:

http://creativecommons.org/publicdomain/zero/1.0/legalcode

Ideas
1. Remember expanded states
2. Make DL collapsible via its DD
3. Support collapsing of DL component children (DD and DT)

Todo summary: (see "todo"'s below)
1. Optimize iteration algorithms
2. When #1 is completed, check top-most class of list (or its parent) for `doNotRecurse` and pre-expansion options
*/

// eslint-disable-next-line no-unused-vars -- Might expand
var CollapsibleLists;
(function () {
	// Create the CollapsibleLists object
	var collapsibleLists,
		autoApplyWithNoGlobal = true; // Configure as to whether to auto-apply to lists on the page (without creating a global) or whether to allow manual control via a global

	/**
	* Opens or closes the list elements of the given type
	*   within the specified node.
	* @private
	* @static
	* @param {Element} node The node containing the list elements
	* @param {'ul'|'ol'} [listType] Type of list; defaults to "ul"
	* @returns {int}
	*/
	function toggle (node, listType) {
		listType = listType || 'ul,ol';
		// Determine whether to open or close the lists
		var index, li,
			open = node.className.match(/(^| )collapsibleListClosed( |$)/),
			// Loop over the list elements with the node
			lists = node.querySelectorAll(listType),
			listsLength = lists.length;

		for (index = 0; index < listsLength; index++) {

			// Find the ancestor list item of this list
			li = lists[index];
			while (li.nodeName.toLowerCase() !== 'li') {
				li = li.parentNode;
			}

			// Style the list if it is within this node
			if (li === node) {
				lists[index].style.display = (open ? 'block' : 'none');
			}
		}

		if (listsLength) {
			// Remove the current class from the node
			node.className = node.className.replace(
				/(^| )collapsibleList(Open|Closed)( |$)/, ''
			);

			// If the node contains lists, set its class
			if (listsLength > 0) {
				node.className += ' collapsibleList' + (open ? 'Open' : 'Closed');
			}
		}
		return listsLength;
	}

 /**
  * @callback ClickHandler
  * @private
  * @static
  * @param {Event} e The click event
  * @returns {void}
  */

	/**
	* Returns a function that toggles the display status of any
	*   list elements within the specified node. The parameter is...
	* @private
	* @static
	* @param {Element} node The node containing the list elements
	* @returns {ClickHandler}
	*/
	function createClickListener (node) {

		// Return the function
		/**
     * @type {ClickHandler}
     */
		return function (e) {

			// Ensure the event object is defined
			e = e || window.event;

			// Find the list item containing the target of the event
			var li = e.target || e.srcElement;
			while (li.nodeName.toLowerCase() !== 'li') {
				li = li.parentNode;
			}

			// Toggle the state of the node if it was the target of the event
			if (li === node) {
				toggle(node);
			}
		};
	}

	/**
	* @private
	* @static
	* @param {Event} e The event to prevent
	* @returns {void}
	*/
	function preventDefault (e) {
		e.preventDefault();
	}

	/**
	* @private
	* @static
	* @returns {void}
	*/
	function preventDefaultIE () {
		// eslint-disable-next-line no-restricted-globals -- IE
		event.returnValue = false;
	}

	/**
	 * @param {boolean} leaveExpanded
 	 * @private
 	 * @static
     * @returns {void}
	 */
	function applyLists (leaveExpanded) {
		collapsibleLists.apply(false, leaveExpanded);
	}

	/**
	* Makes sublists of a given list type collapsible.
	* @private
	* @static
	* @param {Element} list The list element
	* @param {'ul'|'ol'} [listType] The list type under which sublists should be made collapsible
  * @returns {void}
	*/
	function applySubListsForListType (list, listType) {
		listType = listType || 'ul,ol';
		// Todo: This is unnecessarily redundant and thus expensive for deeply nested lists;
		//			 should instead check direct children recursively
		var subIndex,
			subLists = list.getElementsByTagName(listType),
			subListsLength = subLists.length;
		for (subIndex = 0; subIndex < subListsLength; subIndex++) {
			// Tempory fix to at least avoid multiple classes
			if (!(/(^| )collapsibleList( |$)/).test(subLists[subIndex].className)) {
				subLists[subIndex].className += ' collapsibleList';
			}
		}
	}

	collapsibleLists = {
		/**
		* Makes all lists with the class 'collapsibleList' collapsible.
		* @param {boolean} [doNotRecurse] True if sub-lists should not be made collapsible
		* @param {boolean} [leaveExpanded] True if list and its sublists should be left pre-expanded
    * @returns {void}
		*/
		apply: function (doNotRecurse, leaveExpanded) {
			this.applyForListType(doNotRecurse, leaveExpanded);
		},
		/**
		* Makes lists of the given type with the class 'collapsibleList' collapsible.
		* @param {boolean} [doNotRecurse] True if sub-lists should not be made collapsible
		* @param {boolean} [leaveExpanded] True if list and its sublists should be left pre-expanded
		* @param {'ul'|'ol'} [listType] Type of list; defaults to "ul"
		*/
		applyForListType: function (doNotRecurse, leaveExpanded, listType) {
			listType = listType || 'ul,ol';
			// Loop over the lists
			var index, list,
				// Todo: This is unnecessarily redundant and thus inefficient; should instead
				//			 iterate over direct children
				lists = document.querySelectorAll(listType),
				listsLength = lists.length,
				listPattern = /(^| )collapsibleList( |$)/;
			for (index = 0; index < listsLength; index++) {
				list = lists[index];
				// Check whether this list should be made collapsible
				if (listPattern.test(list.className) ||
					listPattern.test(list.parentNode.className) // For convenience when used with Mediawiki simple syntax lists (which cannot specify classes on the list)
				) {

					// Make this list collapsible
					this.applyTo(list, true, leaveExpanded);

					// Check whether sub-lists should also be made collapsible
					// Todo: When iteration algorithm is fixed, check class at top of list (or parent of list) to allow doNotRecurse specification
					if (!doNotRecurse) {
						// Add the collapsibleList class to the sub-lists
						applySubListsForListType(list);
					}
				}
			}
		},

		/**
		* Makes the specified list collapsible.
		* @param {Element} node The list element
		* @param {boolean} [doNotRecurse] True if sub-lists should not be made collapsible
		* @param {boolean} [leaveExpanded] True if list and its sublists should be left pre-expanded
		*/
		applyTo: function (node, doNotRecurse, leaveExpanded) {

			// Loop over the list items within this node
			var index,
				lis = node.querySelectorAll('li'),
				lisLength = lis.length;
			for (index = 0; index < lisLength; index++) {

				// Todo: When iteration algorithm is fixed, check class at top of list (or parent of list) to allow doNotRecurse specification
				// Check whether this list item should be collapsible
				if (!doNotRecurse || node === lis[index].parentNode) {

                    var attachNode = lis[index].querySelector('span');
                    if (!attachNode) {
                    	continue;
                    }

					// Prevent text from being selected unintentionally
					if (attachNode.addEventListener) {
						attachNode.addEventListener('mousedown', preventDefault, false);
					} else {
						attachNode.attachEvent('onselectstart', preventDefaultIE);
					}

					// Add the click listener
					if (attachNode.addEventListener) {
						attachNode.addEventListener('click', createClickListener(lis[index]), false);
					} else {
						attachNode.attachEvent('onclick', createClickListener(lis[index]));
					}

					// Close the lists within this list item
					// Todo: When iteration algorithm is fixed, check class at top of list (or parent of list) to allow expansion via class
					if (!leaveExpanded) {
						toggle(lis[index]);
					}
				}
			}
		}
	};
	if (autoApplyWithNoGlobal) {
		/*
		if (window.addEventListener) {
			window.addEventListener('DOMContentLoaded', applyLists, false);
		}
		else {
			window.attachEvent('onload', applyLists);
		}
		*/
		applyLists(!$('.enable_collapsibleList_collapsed').length);
	} else {
		CollapsibleLists = collapsibleLists;
	}
}());
Retrieved from "https://bahaipedia.org/index.php?title=User:Brettz9/common.js&oldid=105097"
This page was last edited on 28 March 2022, at 03:00.
Text is available under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License.
Privacy policy
About Bahaipedia
Disclaimers
Powered by MediaWiki