首页 > 代码库 > firefox按钮菜单自动弹出uc脚本,修正Omnibar上的图标按钮有些不能弹出的问题

firefox按钮菜单自动弹出uc脚本,修正Omnibar上的图标按钮有些不能弹出的问题

// ==UserScript==
// @name           AutoPopup.uc.js
// @description    Auto popup menulist/menupopup
// @compatibility  Firefox 24.0+
// @author         GOLF-AT, modify by gsf
// @version        2015.1.29
// ==UserScript==

(function () {
	var nDelay = 300;
	var overElt = null;
	var PopElt = null;
	var PopTimer = null;
	var HideTimer = null;
	var searchBar = null;
	var AlwaysPop = false;

	//by gsf, 请用CSS,支持Fx的CSS所有语法。#表示id,.表示class,也能用[id='demo']
	var BlackIDs = [];

	//by gsf, 白名单,及触发动作
	var whiteIDs = [{
		id: 'omnibar-defaultEngine',
		popMemu: 'omnibar-engine-menu',
		run: function(overElem){
			document.getElementById('omnibar-in-urlbar').click(0);
		}
	},
	{
		id: 'readLater',
		popMemu: 'readLater-popup',
		run: null
		//function(overElem){ PopElt.popup();}
	},
	{
		id: 'foxyproxy-toolbar-icon',
		popMemu: 'foxyproxy-toolbarbutton-popup',
		run: null
	}];
	var whitesInx = -1;

	var popupPos = ['after_start', 'end_before', 'before_start', 'start_before'];

	var menuPanelID = 'PanelUI-popup';
	var downPanelID = 'downloadsPanel';
	var widgetPanelID = 'customizationui-widget-panel';

	function IsWidgetBtn(elt) {
		try {
			return elt.hasAttribute('widget-id')
				&& elt.getAttribute('widget-type') == 'view';
		} catch (e) {
			return false;
		}
	}

	function IsSearchBtn(elt) {
		try {
			return elt.getAttribute("anonid") == 'searchbar-search-button'
			|| whitesInx === 0;
		} catch (e) {
			return false;
		}
	}

	function IsNewMenuBtn(elt) {
		try {
			return elt.id == 'PanelUI-menu-button';
		} catch (e) {
			return false;
		}
	}

	function IsDownloadBtn(elt) {
		try {
			return elt.localName == 'toolbarbutton'
			&& elt.id == 'downloads-button';
		} catch (e) {
			return false;
		}
	}

	function IsAutoComplete(elt) {
		try {
			return elt.getAttribute('type').substr(0, 12) == 'autocomplete';
		} catch (e) {
			return false;
		}
	}

	function getPopupMenu(elt) {
		if (whitesInx > -1 && PopElt)
			return PopElt;
		var nodes = elt ? elt.ownerDocument.getAnonymousNodes(elt) : null;
		for (let [i, k] in Iterator(nodes)) {
			if (k.localName == 'menupopup')
				return k;
		}

		var s = elt.getAttribute('popup');
		return s ? document.getElementById(s) : null;
	}

	function isBlackNode(elt) {
		//var attr, val, nPos;
		for (let [i, css] in Iterator(BlackIDs)) {
/*			if (str.length == 0)
				continue;
 			if (str.charAt(0) == '#') {
				val = str.substr(1);
				attr = 'id';
			} else if (str.charAt(0) == '.') {
				val = str.substr(1);
				attr = 'class';
			} else {
				nPos = str.indexOf('=');
				if (nPos > 0) {
					val = str.substr(nPos + 1);
					attr = str.substr(0, nPos);
				} else {
					val = str;
					attr = 'id';
				}
			}  by gsf */
			try {
				//if (elt.getAttribute(attr) == val)
				if (css.length > 0 && document.querySelector(css))
					return true;
			} catch (e) {}
		}
		return false;
	}

	function getPopupPos(elt) {
		var x, y, pos, box;

		for (pos = 0, x = elt.boxObject.screenX, y = elt
			.boxObject.screenY; elt != null; elt = elt.parentNode)
		{
			if (elt.localName == 'window' || !elt.parentNode)
				break;
			else if ('toolbar' != elt.localName &&
				'hbox' != elt.localName && 'vbox' != elt.localName);
			else if (elt.boxObject.height >= 3 * elt.boxObject.width) {
				if (elt.boxObject.height >= 45) {
					pos = 9;
					break;
				}
			} else if (elt.boxObject.width >= 3 * elt.boxObject.height) {
				if (elt.boxObject.width >= 45) {
					pos = 8;
					break;
				}
			}
		}
		try {
			box = elt.boxObject;
			x = (pos & 1) ? (x <= box.width / 2 + box.screenX ? 1 : 3) :
							(y <= box.height / 2 + box.screenY ? 0 : 2);
		} catch (e) {
			x = 0;
		}
		return popupPos[x];		
	}

	function getPopupNode(node) {
		if (whitesInx > -1 && PopElt)
			return PopElt;
		var elt, isPop, s;

		for (; node != null; node = node.parentNode) {
			if (node == PopElt)
				return node;

			isPop = false; //Node isn't Popup node
			s = node.localName;
			if (s == 'menupopup' || s == 'popup' || s == 'menulist'
			   || IsAutoComplete(node) || IsMenuButton(node))
				isPop = true;
			else if (s == 'dropmarker') {
				if (node.getAttribute('type') == 'menu') {
					elt = node.parentNode;
					if (elt.firstChild.localName == 'menupopup')
						isPop = true;
				} else if (node.className == 'autocomplete-history-dropmarker')
					isPop = true;
				else {
					try {
						isPop = node.parentNode.id == 'urlbar';
					} catch (ex) {}
				}
			} else if (s == 'menu')
				isPop = 'menubar' == node.parentNode.localName;
			else if (IsButton(node)) {
				for (elt = node; (elt = elt.nextSibling) != null;) {
					if (elt.localName == 'dropmarker' &&
						elt.boxObject.width > 0 &&
						elt.boxObject.height > 0)
						break;
				}
				if (elt) break;
			}
			if (isPop) break;
		}
		if (PopElt && node) {
			//Whether node is child of PopElt
			for (elt = node.parentNode; elt != null; elt = elt.parentNode) {
				if (elt == PopElt)
					return PopElt;
			}
		}
		return isPop ? node : null;
	}

	function AutoPopup() {
		PopTimer = null;
		if (!overElt) return;
		
		if (whitesInx > -1 && PopElt && whiteIDs[whitesInx].run) {
			whiteIDs[whitesInx].run(overElt);
			return;
		}
		!PopElt && (PopElt = overElt);

		if (overElt.localName == 'dropmarker')
			PopElt.showPopup();
		else if (overElt.localName == 'menulist')
			overElt.open = true;
		else if (IsNewMenuBtn(overElt)) {
			PanelUI.show();
			PopElt = document.getElementById(menuPanelID);
		} else if (IsWidgetBtn(overElt)) {
			var cmdEvent = document.createEvent('xulcommandevent');
			cmdEvent.initCommandEvent("command", true, true, window, 0, false,
				false, false, false, null);
			overElt.dispatchEvent(cmdEvent);
			PopElt = document.getElementById(widgetPanelID);
		} else if (IsDownloadBtn(overElt)) {
			PopElt = document.getElementById(downPanelID);
			DownloadsPanel.showPanel();
		} else if (IsSearchBtn(overElt)) {
			searchBar.openSuggestionsPanel();
			//console.log('search click!');
		} else {
			PopElt = getPopupMenu(overElt);
			try {
				var Pos = getPopupPos(overElt);
				PopElt.openPopup(overElt, Pos, 0, 0, false, false, null);
			} catch (e) {
				PopElt = null;
			}
		}
	}

	function HidePopup() {
		try {
			if (overElt.localName == 'dropmarker')
				PopElt.parentNode.closePopup();
			else if (overElt.localName == 'menulist')
				PopElt.open = false;
			else if (IsDownloadBtn(overElt))
				DownloadsPanel.hidePanel();
			//else if (IsNewMenuBtn(overElt) || IsWidgetBtn(overElt))
			else if (PopElt && PopElt.hidePopup)
				PopElt.hidePopup();
			else if (PopElt.popupBoxObject)
				PopElt.popupBoxObject.hidePopup();
			 else if (IsSearchBtn(overElt))
				 searchBar.textbox.closePopup();			
		} catch (e) {}

		HideTimer = null;
		overElt = PopElt = null;
	}

	function MouseOver(e) {
		if (!AlwaysPop && !document.hasFocus())
			return;
		var popNode, n = e.originalTarget;

		whitesInx = -1;
		if (n.hasAttribute('id')) {
			for (let [i, k] in Iterator(whiteIDs)) {
				if (k.id == n.id) {
					overElt = n;
					whitesInx = i;
					PopElt = document.getElementById(k.popMemu);
					PopTimer = setTimeout(AutoPopup, nDelay);
					return;
				}
			}
		}
		popNode = getPopupNode(e.originalTarget);
		if (!popNode || (popNode && popNode.disabled) || isBlackNode(popNode)) {
			MouseOut();
			return;
		}

		if (HideTimer) {
			window.clearTimeout(HideTimer);
			HideTimer = null;
		}
		try {
			if (IsAutoComplete(popNode)) return;

			for (var elt = popNode; elt != null; elt = elt.parentNode) {
				if (elt.localName == 'menupopup' ||
				    elt.localName == 'popup')
					return;
			}
		}
		catch (ex) {}

		if (PopElt && popNode == PopElt && PopElt != overElt)
			return;
		if (overElt && popNode != overElt)
			HidePopup();
		overElt = popNode;
		PopElt = null;
		PopTimer = setTimeout(AutoPopup, nDelay);
	}

	function MouseOut(e) {
		if (PopTimer) {
			window.clearTimeout(PopTimer);
			PopTimer = null;
		}
		if (!HideTimer && PopElt)
			HideTimer = window.setTimeout(HidePopup, 500);
	}

	function IsButton(elt) {
		try {
			return elt.localName == 'button' ||
			elt.localName == 'toolbarbutton';
		} catch (e) {
			return false;
		}
	}

	function IsMenuButton(elt) {
		return IsNewMenuBtn(elt) || IsDownloadBtn(elt) || IsWidgetBtn(elt)
			|| (IsButton(elt) && getPopupMenu(elt));
	}

	searchBar = BrowserSearch.searchBar;
	window.addEventListener('mouseover', MouseOver, false);
})();

firefox按钮菜单自动弹出uc脚本,修正Omnibar上的图标按钮有些不能弹出的问题