<commit_before>/**
 * Tracks the currently focused node, and which widgets are currently "active".
 *
 * A widget is considered active if it or a descendant widget has focus,
 * or if a non-focusable node of this widget or a descendant was recently clicked.
 *
 * Call `focus.on("active-widget-stack", callback)` to track the currently focused stack of widgets.
 *
 * Call `focus.on("widget-blur", func)` or `focus.on("widget-focus", ...)` to monitor when
 * when widgets become active/inactive
 *
 * Finally, `focus.focus(node)` will focus a node, suppressing errors if the node doesn't exist.
 *
 * @module delite/focus
 * */
define([
	"dcl/advise",
	"dcl/dcl",
	"dojo/dom-class",
	"dojo/Evented",
	"dojo/on",
	"./a11y",	// a11y.isTabNavigable
	"requirejs-domready/domReady!"
], function (advise, dcl, domClass, Evented, on, a11y) {

	// Time of the last focusin event
	var lastFocusin;

	// Time of the last touch/mousedown or focusin event
	var lastTouchOrFocusin;

	var FocusManager = dcl(Evented, /** @lends module:delite/focus */ {

		/**
		 * List of currently active widgets (focused widget and its ancestors).
		 * @property {Element[]} activeStack
		 */
		activeStack: [],

		/**
		 * Registers listeners on the specified iframe so that any click
		 * or focus event on that iframe (or anything in it) is reported
		 * as a focus/click event on the `<iframe>` itself.
		 *
		 * In dijit this was only used by editor; perhaps it should be removed.
		 *
		 * @param {HTMLIframeElement} iframe
		 * @returns {Object} Handle with `remove()` method to deregister.
		 */
		registerIframe: function (iframe) {
			return this.registerWin(iframe.contentWindow, iframe);
		},

		/**
		 * Registers listeners on the specified window (either the main
		 * window or an iframe's window) to detect when the user has clicked somewhere
		 * or focused somewhere.
		 *
		 * Users should call registerIframe() instead of this method.
		 *
		 * @param {Window} [targetWindow] - If specified this is the window associated with the iframe,
		 *       i.e. iframe.contentWindow.
		 * @param {Element} [effectiveNode] - If specified, report any focus events inside targetWindow as
		 *       an event on effectiveNode, rather than on evt.target.
		 * @returns {Object} Handle with `remove()` method to deregister.
		 * @private
		 */
		registerWin: function (targetWindow, effectiveNode) {
			// Listen for blur and focus events on targetWindow's document.
			var _this = this,
				body = targetWindow.document && targetWindow.document.body;

			if (body) {
				// Listen for touches or mousedowns... could also use dpointer here.
				// TODO: change this to run on capture phase rather than bubbling phase.
				var event = "onpointerdown" in document ? "pointerdown" :
					"msMaxTouchPoints" in navigator ? "MSPointerDown" :
					"ontouchstart" in document ? "mousedown, touchstart" : "mousedown";
				var mdh = on(targetWindow.document, event, function (evt) {
					// workaround weird IE bug where the click is on an orphaned node
					// (first time clicking a Select/DropDownButton inside a TooltipDialog).
					// actually, strangely this is happening on latest chrome too.
					if (evt && evt.target && evt.target.parentNode == null) {
						return;
					}

					_this._onTouchNode(effectiveNode || evt.target, "mouse");
				});

				var fih = on(body, "focusin", function (evt) {
					// When you refocus the browser window, IE gives an event with an empty srcElement
					if (!evt.target.tagName) {
						return;
					}

					// IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
					// ignore those events
					var tag = evt.target.tagName.toLowerCase();
					if (tag === "#document" || tag === "body") {
						return;
					}

					if (a11y.isFocusable(evt.target)) {
						_this._onFocusNode(effectiveNode || evt.target);
					} else {
						// Previous code called _onTouchNode() for any activate event on a non-focusable node.   Can
						// probably just ignore such an event as it will be handled by onmousedown handler above, but
						// leaving the code for now.
						_this._onTouchNode(effectiveNode || evt.target);
					}
				});

				var foh = on(body, "focusout", function (evt) {
					_this._onBlurNode(effectiveNode || evt.target);
				});

				return {
					remove: function () {
						mdh.remove();
						fih.remove();
						foh.remove();
						mdh = fih = foh = null;
						body = null;	// prevent memory leak (apparent circular reference via closure)
					}
				};
			}
		},

		/**
		 * Called when focus leaves a node.
		 * Usually ignored, _unless_ it *isn't* followed by touching another node,
		 * which indicates that we tabbed off the last field on the page,
		 * in which case every widget is marked inactive.<commit_msg>Cleanup of focus.js:<commit_after>/**
 * Tracks the currently focused node, and which widgets are currently "active".
 *
 * A widget is considered active if it or a descendant widget has focus,
 * or if a non-focusable node of this widget or a descendant was recently clicked.
 *
 * Call `focus.on("active-widget-stack", callback)` to track the currently focused stack of widgets.
 *
 * Call `focus.on("widget-blur", func)` or `focus.on("widget-focus", ...)` to monitor when
 * when widgets become active/inactive
 *
 * Finally, `focus.focus(node)` will focus a node, suppressing errors if the node doesn't exist.
 *
 * @module delite/focus
 * */
define([
	"dcl/advise",
	"dcl/dcl",
	"dojo/dom-class",
	"dojo/Evented",
	"dpointer/events",		// so can just monitor for "pointerdown"
	"requirejs-domready/domReady!"
], function (advise, dcl, domClass, Evented) {

	// Time of the last focusin event
	var lastFocusin;

	// Time of the last touch/mousedown or focusin event
	var lastTouchOrFocusin;

	var FocusManager = dcl(Evented, /** @lends module:delite/focus */ {

		/**
		 * List of currently active widgets (focused widget and its ancestors).
		 * @property {Element[]} activeStack
		 */
		activeStack: [],

		/**
		 * Registers listeners on the specified iframe so that any click
		 * or focus event on that iframe (or anything in it) is reported
		 * as a focus/click event on the `<iframe>` itself.
		 *
		 * In dijit this was only used by editor; perhaps it should be removed.
		 *
		 * @param {HTMLIframeElement} iframe
		 * @returns {Object} Handle with `remove()` method to deregister.
		 */
		registerIframe: function (iframe) {
			return this.registerWin(iframe.contentWindow, iframe);
		},

		/**
		 * Registers listeners on the specified window (either the main
		 * window or an iframe's window) to detect when the user has clicked somewhere
		 * or focused somewhere.
		 *
		 * Users should call registerIframe() instead of this method.
		 *
		 * @param {Window} [targetWindow] - If specified this is the window associated with the iframe,
		 *       i.e. iframe.contentWindow.
		 * @param {Element} [effectiveNode] - If specified, report any focus events inside targetWindow as
		 *       an event on effectiveNode, rather than on evt.target.
		 * @returns {Object} Handle with `remove()` method to deregister.
		 * @private
		 */
		registerWin: function (targetWindow, effectiveNode) {
			// Listen for blur and focus events on targetWindow's document.
			var _this = this,
				doc = targetWindow.document,
				body = doc && doc.body;

			if (body) {
				// Listen for touches or mousedowns.
				function pointerDownHandler(evt) {
					// workaround weird IE bug where the click is on an orphaned node
					// (first time clicking a Select/DropDownButton inside a TooltipDialog).
					// actually, strangely this is happening on latest chrome too.
					if (evt && evt.target && evt.target.parentNode == null) {
						return;
					}

					_this._onTouchNode(effectiveNode || evt.target, "mouse");
				}
				doc.addEventListener("pointerdown", pointerDownHandler, true);

				function focusHandler(evt) {
					// When you refocus the browser window, IE gives an event with an empty srcElement
					if (!evt.target.tagName) {
						return;
					}

					// IE reports that nodes like <body> have gotten focus, even though they don't have a
					// tabindex setting.  Ignore those events.
					var tag = evt.target.tagName.toLowerCase();
					if (tag === "#document" || tag === "body") {
						return;
					}

					_this._onFocusNode(effectiveNode || evt.target);
				}
				body.addEventListener("focus", focusHandler, true);	// need true since focus doesn't bubble

				function blurHandler(evt) {
					_this._onBlurNode(effectiveNode || evt.target);
				}
				body.addEventListener("blur", blurHandler, true);	// need true since blur doesn't bubble

				return {
					remove: function () {
						doc.removeEventListener("pointerdown", pointerDownHandler, true);
						body.removeEventListener("focus", focusHandler, true);
						body.removeEventListener("blur", blurHandler, true);
					}
				};
			}
		},

		/**
		 * Called when focus leaves a node.
		 * Usually ignored, _unless_ it *isn't* followed by touching another node,
		 * which indicates that we tabbed off the last field on the page,
		 * in which case every widget is marked inactive.
{'fraction_non_alphanumeric': 0.10770913067249863, 'fraction_numerical': 0.0009841443411700383, 'mean_word_length': 3.0940017905102954, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6040581', 'n_tokens_mistral': 3160, 'n_tokens_neox': 2596, 'n_words': 985}