// ==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); })();
时间: 2024-10-08 10:25:07