/* Find Search Words * nanto_vi (TOYAMA Nao), 2007-01-28 * * Search web pages for words in the search bar. * * Original Extension: SearchWP * * Copyright (C) 2004-2006 All Rights Reserved. * Author: Georges-Etienne Legendre (legege@legege.com) * * Original Icons: famfamfam.com: Silk Icons * */ var gFSWPrefs = { insertIn: "PersonalToolbar", insertBefore: null, insertAfter: "personal-bookmarks", findEnabledTooltip: "このページを検索: \"%s\"", findDisabledTooltip: "このページを検索", findShortcutKeyCode: "VK_F4", wrappedToTopMessage: "ページの最後まで検索しました。" + "ページの最初から検索を続けます。", wrappedToBottomMessage: "ページの最初まで検索しました。" + "ページの最後から検索を続けます。", notFoundMessage: "\"%s\" は見つかりませんでした。", messageDisplayTime: 3000, updateInterval: 500, style: .toolbarbutton-icon { -moz-margin-end: 4px !important; } .findsearchwords-button > .toolbarbutton-text { display: -moz-box !important; } .findsearchwords-button > .toolbarbutton-menu-dropmarker { -moz-margin-start: 3px !important; } .findsearchwords-empty > #findsearchwords-separator-1, #findsearchwords-separator-3 { display: none; } #findsearchwords-find-button { list-style-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAQCAYAAABQrvyxAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wEYAScNzpR0GAAABIBJREFUeNrNll1sVEUUx3/37t0uLbv9oOy21G13EWkh6jZggBCNMSZEATW+UDQkmmJMjCaS+OST8dH4BKE81JgGiS8QMWiiQU2MEomFVkWw0BKQ2k+2S/ej3b337t6ZOz5sWwrZbXkwqSc5uZlJfmfmP2fOnaNRtDDQAHhY2qaAEcC9b36leZ6wbTvtOI4UQqhSbtu26urqOgJEAf1/xrPdcRyZzWZVLpdb8Ewmo1KplIrH40oIoSYnJ9WxY8dKBVlRXgO2CyGUZVkqn88ry7KUZVlqdnZWpdNpNTU1pYQQyjRNlc1mVXd393yQFee1Od8mhLggpVw4Etd1UUohhCCfz1NXV3dPygzD2AH0zQ3/ez45Bdd+Q7tyETebwa1cjR7bifH4DvT60AJvLA6q6zqaphWPRdMYHR3Fsix8Ph/AwoZCoVDJCruX1/l1RDJr6dT7DB4h9eB8KoF95jM8NdX4HmtfqGw7PoJ58hK1r751l1kcYH5xpRTxeJyamhqampoQQjA6OophGAtiStldHq7EFc21OrEmL6aj0fuP+0C8St0h+8WnVLVuxJA2hfPfYzzbgf3zWbzCJtDWRvJEFwc2tzxEqWoGGB4eprKyklwuRyaToaqqimAwSH9/P16vl+Xs/LBD3SpFMieYyAiq/RU0h/ycvJBalpeXe/HUVCPHbiH/HkS5qnilhIt99Sr29Rvoq6vp2LDu+bICstlsMZiUCCGwLAuPx0MqlcIwjGUFJGfzaBoUhCIvFDOmxGN4uJ00l+ULf5xnVUMj4tZ1XKlQwl0Q4DoS5+YQ/uYw61YZe8oK8Pv9TExMoGkaQggCgQCDg4PMzMyQTqeXFdDoh8GxLPqciGDA4OLAJKGZfuz05JKsk0wUr6FwcYWLFMUMyIKLdIpzALrrBssKiEaj5PN5dF0nEAgwNDREMpmkvr6enp4eEonEkpvYtn41ll3A64FQjcHFq7fJTt/mmYZJ+o+/RzYxUl6Ar6r4tQSOKXBMh5meI8Xx3BzAbM5MlBWgaRrt7e0MDAxw7tw5xsbGyOVyhMNhWlpaOHz4MLFYLLJUMb6wtZ5f/hzn1A9DiInfebLwJfXNG1nb0saPRw+yZ8uaknzFlqfIjYxT0bqpmAHHpfrgIVzHRQqXirZNpG4MMzxjfltWwPwvbdeuXezbt4+Ojg4A+vr6iEQiRKNRYrHYJ0tlQdd13t69ng8PPErnK7sRGNzs/45QcxvrIq28vNVfkq/c9jRmfAqtIYIeacUVLsmjHyOli691M77ow5h3pjgzcufs/QJUqZPUNA3DMNi/fz+6rtPb20s4HEYIUXsfU5b3GBVs7fgAx1PFYP9ZQuENSFEoyXuDjYTeOETyr8s4Xi/Vz+3F19TImhdfwvFVkLhyici777tfjafGAaXPga6U0irV5S16Oens7MTr9arTp08zPT19fNHCy/K64WXnax8hKwLqp6+7GU+a5fm6IHWvv0MhuJZr35zi0okuLp/5HKuuluCbh1xZvcYE5HwrAdA8187qPJjJudZ2dKX5fwEPJ3wWzuanmQAAAABJRU5ErkJggg=="); -moz-image-region: rect(0px 32px 16px 16px); } #findsearchwords-find-button.findsearchwords-notfound { -moz-image-region: rect(0px 48px 16px 32px); } #findsearchwords-find-button[disabled] { -moz-image-region: rect(0px 16px 16px 0px); } ]]>.toString().replace(/\s+/g, " ") }; var gFindSearchWords = { init: function FSW_init() { var sspi = document.createProcessingInstruction( "xml-stylesheet", "type=\"text/css\" href=\"data:text/css," + encodeURI(gFSWPrefs.style) + "\"") document.insertBefore(sspi, document.documentElement); // XXX Workaround for Firefox 2 sspi.getAttribute = new Function("name", "return document.documentElement.getAttribute(name);"); var overlay = ; if (gFSWPrefs.insertBefore) overlay..kXULNS::toolbaritem.@insertbefore = gFSWPrefs.insertBefore; if (gFSWPrefs.insertAfter) overlay..kXULNS::toolbaritem.@insertafter = gFSWPrefs.insertAfter; var overlayURI = "data:application/vnd.mozilla.xul+xml;charset=utf-8," + encodeURI(overlay.toXMLString()); document.loadOverlay(overlayURI, null); var searchBar = document.getElementById("searchbar"); searchBar.addEventListener("input", gFSWToolbar, false); searchBar.addEventListener("input", gFSWFinder, false); addEventListener("resize", gFSWToolbar, false); }, handleEvent: function FSW_handleEvent(aEvent) { switch (aEvent.type) { case "input": gFSWToolbar.update(); break; case "resize": gFSWToolbar.refresh(); break; } } }; var gFSWToolbar = { _searchString: null, _timerId: 0, _needsUpdate: false, _prevWidth: 0, _prevHeight: 0, handleEvent: function FSWT_handleEvent(aEvent) { switch (aEvent.type) { case "input": this._searchString = aEvent.target.value; if (this._timerId) this._needsUpdate = true; else this.update(); break; case "resize": // XXX A resize event fires not only when window size changes // but also when toolbar size changes. So we have to check // window size to detect window size change. if (this._prevWidth == document.width && this._prevHeight == document.height) return; this._prevWidth = document.width; this._prevHeight = document.height; this._maybeUpdate(this, true); break; } }, get _container() { return document.getElementById("findsearchwords-container"); }, get _buttonBox() { return document.getElementById("findsearchwords-button-box"); }, get _chevron() { return document.getElementById("findsearchwords-chevron"); }, get _popup() { return document.getElementById("findsearchwords-popup"); }, _wordsList: [], _searchWordRE: new RegExp( "\\s*(([()+-]?)(?:(?:" + "allinanchor|allintext|allintitle|allinurl|author|bphonebook|cache|" + "define|ext|filetype|group|id|inanchor|info|insubject|intext|intitle|" + "inurl|link|location|movie|msgid|phonebook|related|rphonebook|" + "safesearch|site|source|stocks|store|weather" + "):)?(?:\"([^\"]*)\"|(\\S+)))", "g" ), update: function FSWT_update() { this._wordsList.length = 0; var match = null; var added = {}; while ((match = this._searchWordRE.exec(this._searchString))) { if (match[2] == "-" || match[1] == "OR" || match[1] == "AND") continue; var phrase = null; var words = []; if (match[4]) { phrase = match[4].replace(/[()]$/, ""); words.push(phrase); phrase = phrase.replace(/^-+/, "").replace(/-+$/, "") var terms = phrase.split(/-+/); if (terms.length >= 2) { words.push(terms.join(" "), terms.join("")); words.push.apply(words, terms); } } else { phrase = match[3]; words.push(phrase); } var lowerPhrase = phrase.toLowerCase(); if (!phrase || lowerPhrase in added) continue; added[lowerPhrase] = true; this._wordsList.push(words); } if (this._wordsList.length) { this._container.className = ""; } else { this._container.className = "findsearchwords-empty"; gFSWFinder.enable(false); } this.refresh(); }, _buttonCount: 0, refresh: function FSWT_refresh() { this._clear(); this._needsUpdate = false; this._timerId = setTimeout(this._maybeUpdate, gFSWPrefs.updateInterval, this, false); var wordsCount = this._wordsList.length; if (!wordsCount) return; var buttonBox = this._buttonBox; var buttons = buttonBox.childNodes; var preparedButtonCount = buttons.length; var parentBox = this._container.parentNode.boxObject; var parentWidth = parentBox.width; // XXX Hmmm... Sometimes the right edge of the rightmost box is // 1px larger than its parent's width. parentWidth += 2; var [leftmostBox, rightmostBox] = this._getEdgeBoxes(parentBox); for (var i = 0; i < wordsCount; i++) { var words = this._wordsList[i]; var button = null; if (i < preparedButtonCount) { button = buttons[i]; if (button.fswWords.join("\0") != words.join("\0")) this._updateButton(button, words); button.hidden = false; } else { button = this._createButton(words); buttonBox.appendChild(button); } this._buttonCount++; if (rightmostBox.x + rightmostBox.width > parentWidth || leftmostBox.x < 0) { this._chevron.hidden = false; do { button.hidden = true; button = button.previousSibling; this._buttonCount--; } while ((rightmostBox.x + rightmostBox.width > parentWidth || leftmostBox.x < 0) && button); break; } } }, _clear: function FSWT__clear() { var buttons = this._buttonBox.childNodes; for (var i = 0; i < this._buttonCount; i++) buttons[i].hidden = true; this._buttonCount = 0; var popup = this._popup var menu = null; while ((menu = popup.firstChild)) popup.removeChild(menu); this._chevron.hidden = true; }, _getEdgeBoxes: function FSWT__getEdgeBoxes(aParentBox) { var { firstChild: firstChild, lastChild: lastChild } = aParentBox; if (!firstChild) return [null, null]; var firstBox = firstChild.boxObject, lastBox = lastChild.boxObject; return (firstBox.x < lastBox.x) ? [firstBox, lastBox] : [lastBox, firstBox]; }, _updateButton: function FSWT__updateButton(aButton, aWords) { aButton.label = aWords[0]; aButton.fswWords = aWords; if (aWords.length == 1) { aButton.removeAttribute("type"); } else { aButton.type = "menu"; var popup = this._createSubPopup(aWords); if (aButton.hasChildNodes()) aButton.replaceChild(popup, aButton.firstChild); else aButton.appendChild(popup); } }, _createButton: function FSWT__createButton(aWords) { var button = document.createElementNS(kXULNS, "toolbarbutton"); button.className = "findsearchwords-button"; button.setAttribute("label", aWords[0]); button.setAttribute("oncommand", "gFSWToolbar.onCommand(event);"); if (aWords.length > 1) { button.setAttribute("type", "menu"); button.appendChild(this._createSubPopup(aWords)); } button.fswWords = aWords; return button; }, updatePopup: function FSWT_updatePopup(aPopup) { if (aPopup.hasChildNodes()) return; for (var i = this._buttonCount; i < this._wordsList.length; i++) { var words = this._wordsList[i]; var menu = null; if (words.length == 1) { menu = document.createElementNS(kXULNS, "menuitem"); menu.className = "menuitem-iconic findsearchwords-menu"; } else { menu = document.createElementNS(kXULNS, "menu"); menu.className = "menu-iconic findsearchwords-menu"; menu.appendChild(this._createSubPopup(words)); } menu.setAttribute("label", words[0]); aPopup.appendChild(menu); } }, _createSubPopup: function FSWT__createSubPopup(aWords) { var popup = document.createElementNS(kXULNS, "menupopup"); for (var i = 0; i < aWords.length; i++) { var menu = document.createElementNS(kXULNS, "menuitem"); menu.setAttribute("label", aWords[i]); popup.appendChild(menu); } return popup; }, _maybeUpdate: function FSWT__maybeUpdate(aThis, aForceRefresh) { if (aThis._timerId) { clearTimeout(aThis._timerId) aThis._timerId = 0; } if (aThis._needsUpdate) aThis.update(); else if (aForceRefresh) aThis.refresh(); }, onCommand: function FSWT_onCommand(aEvent) { gFSWFinder.find(aEvent.target.label, aEvent); } }; var gFSWFinder = { handleEvent: function FSWF_handleEvent(aEvent) { if (!aEvent.target.value) this.enable(false); }, get _command() { return document.getElementById("cmd_fsw_find"); }, _searchString: null, find: function FSWF_find(aSearchString, aEvent) { this._searchString = aSearchString; this.enable(true); this.findAgain(aEvent); }, findAgain: function FSWF_findAgain(aEvent) { var finder = gBrowser.webBrowserFind; finder.searchString = this._searchString; finder.matchCase = aEvent.ctrlKey; finder.findBackwards = aEvent.shiftKey; finder.wrapFind = true; var currentWin = document.commandDispatcher.focusedWindow; var selection = currentWin.getSelection(); var prevRange = null; if (selection.rangeCount) { prevRange = selection.getRangeAt(0); if (prevRange.toString().toLowerCase() != this._searchString.toLowerCase()) prevRange = null; } var succeed = finder.findNext(); var message = null; if (succeed) { this._command.className = ""; if (prevRange) { var currentRange = currentWin.getSelection().getRangeAt(0); var position = currentRange.compareBoundaryPoints(Range.START_TO_START, prevRange); if (finder.findBackwards) { if (position >= 0) message = gFSWPrefs.wrappedToBottomMessage; } else { if (position <= 0) message = gFSWPrefs.wrappedToTopMessage; } } } else { this._command.className = "findsearchwords-notfound"; message = gFSWPrefs.notFoundMessage.replace("%s", this._searchString); } if (this._timerId) { clearTimeout(this._timerId); if (!message) this._hideMessage(this, null); } if (message) this._showMessage(message); }, _timerId: 0, _showMessage: function FSWF__showMessage(aMessage) { XULBrowserWindow.setOverLink(aMessage); var sound = Cc["@mozilla.org/sound;1"].createInstance(Ci.nsISound); sound.beep(); this._timerId = setTimeout(this._hideMessage, gFSWPrefs.messageDisplayTime, this, aMessage); }, _hideMessage: function FSWF__hideMessage(aThis, aMessage) { aThis._timerId = 0; aThis._command.className = ""; if (!aMessage || XULBrowserWindow.overLink == aMessage) XULBrowserWindow.setOverLink(""); }, enable: function FSWF_enable(aEnable) { var command = this._command; command.className = ""; if (aEnable) { command.removeAttribute("disabled"); command.tooltipText = gFSWPrefs.findEnabledTooltip .replace("%s", this._searchString); } else { command.setAttribute("disabled", "true"); command.tooltipText = gFSWPrefs.findDisabledTooltip; } } }; gFindSearchWords.init();