home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Adblock for Mozilla. * * The Initial Developer of the Original Code is * Henrik Aasted Sorensen. * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Henrik Aasted Sorensen * Stefan Kinitz * Wladimir Palant * rue * ***** END LICENSE BLOCK ***** */ var sortFlag = 0; // global flag to discern if the user has already been told to "reload settings to activate sort" var popupBeingShownN = new Array(); // global node for button-menus popupBeingShownN[0] = false; // boolean: are we showing a button-menu -- "now" popupBeingShownN[1] = null; // the id of the button-menu showing now -- "currentItem" var restoreindexTimer; // calls restoreListIndex after a short delay when the list is created / updated var menuTimer; // deactivates the button-menu's after 15 seconds var buttonMenusLoaded = false; // global flag to discern if the button-menus have been called -- filter context-menu needs this // Loads preferences into the UI. function loadPrefWindow() { try { var prefObj = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); var Branch = prefObj.getBranch("adblock."); var Enabled = !Branch.prefHasUserValue("enabled") || Branch.getBoolPref("enabled"); // default:true var LinkCheck = Branch.prefHasUserValue("linkcheck") && Branch.getBoolPref("linkcheck"); // default:false var PageBlock = Branch.prefHasUserValue("pageblock") && Branch.getBoolPref("pageblock"); // default:false var Hide = Branch.prefHasUserValue("hide") && Branch.getBoolPref("hide"); // default:false; var FastCollapse = Branch.prefHasUserValue("fastcollapse") && Branch.getBoolPref("fastcollapse"); // default:false var Patterns = Branch.prefHasUserValue("patterns") ? Branch.getCharPref("patterns").split(" ") : null; var ListSort = Branch.prefHasUserValue("listsort") && Branch.getBoolPref("listsort"); // default:false var FrameObjects = !Branch.prefHasUserValue("frameobjects") || Branch.getBoolPref("frameobjects"); // default:true } catch(e) {} // load patterns into list var overwriteCurrentList = true; // always overwrite the current list if (Patterns != null && Patterns != "") fillList(Patterns, overwriteCurrentList, ListSort); //else document.getElementById("newfilter").focus(); // UNNEEDED: reSelectListItem does this -- empty-list returns focus to the textbox var enablebox = document.getElementById("enabled"); enablebox.checked = Enabled; var radiohide = document.getElementById("radio-hide"); var radioremove = document.getElementById("radio-remove"); radiohide.disabled = !enablebox.checked; radioremove.disabled = !enablebox.checked; if (Hide) radiohide.setAttribute("selected", true); else radioremove.setAttribute("selected", true); /* var collapsebox = document.getElementById("fastcollapse"); collapsebox.checked = FastCollapse; (document.getElementById('radio-remove').selected) ? document.getElementById('fastcollapse').setAttribute('style', 'visibility: visible') : document.getElementById('fastcollapse').setAttribute('style', 'visibility: hidden'); */ var listsortmenu = document.getElementById("listsort"); listsortmenu.setAttribute("checked", ListSort); var frameobjectsmenu = document.getElementById("frameobjects"); frameobjectsmenu.setAttribute("checked", FrameObjects); var slowcollapsemenu = document.getElementById("slowcollapse"); slowcollapsemenu.setAttribute("checked", !FastCollapse); // reverse-pref: fast -> slow var linkcheckmenu = document.getElementById("linkcheck"); linkcheckmenu.setAttribute("checked", LinkCheck); var pageblockmenu = document.getElementById("pageblock"); pageblockmenu.setAttribute("checked", PageBlock); window.setTimeout("restoreListIndex()", 0); // sets the list to the last-selected item, or the input-line if none //restoreListIndex(); } // Add a filter to the list -- now constructed for inline-editing :) function addFilter() { var newItem; var list = document.getElementById("list"); var textbox = document.getElementById("newfilter"); // if there's an actual entry if (textbox.value != "") { // if it's not a regular expression, or it is, BUT we've said 'ok' to the warning if (!adblockIsRegExp(textbox.value) || (adblockIsRegExp(textbox.value) && adblockWarnRegExp())) { var filter = makePattern(textbox.value); // must be made into pattern textbox.value = ""; var newItem = createListItem(filter); var newItemindex = list.getIndexOfItem(newItem); list.selectedIndex = newItemindex; // sets the list's selection to the new item list.currentItem = newItem; list.ensureIndexIsVisible(newItemindex); // scrolls the list to show the new item enableRevert(); } } //if (!textbox.focused) //textbox.focus(); // always return focus to the textbox } function fillList(Patterns, overwriteCurrentList, listSortChecked) { var list = document.getElementById("list"); if (overwriteCurrentList && list.getRowCount() != 0) { // use instead for the disabled code -> && list.hasChildNodes()) { clearList(true); // clear the list, sans dialog } // Sort the patterns -- would *much* rather do this with a col-header [rue] if (listSortChecked) Patterns.sort(); // fill the list with patterns for (var i = 0 ; i < Patterns.length; i++) if (!/^[\s]*$/.test(Patterns[i])) createListItem(Patterns[i]); // only non-empty patterns! restoreindexTimer = setInterval('clearInterval(restoreindexTimer); restoreListIndex();',10); } // Asks the user if he really wants to clear the list. function clearList(dontConfirm) { if (!dontConfirm) if (!confirm("Do you really want to clear the list?")) return; var list = document.getElementById("list"); list.parentNode.replaceChild(list.cloneNode(false), list); // clear the list enableRevert(); } // Imports filters from web. function importListFromWeb() { var URI = Components.classes["@mozilla.org/network/simple-uri;1"].createInstance(Components.interfaces.nsIURI); try { URI.spec = 'http://www.eschew.org:80/filters.txt'; } catch(e) { console.logStringMessage(e.toString()); alert("oops"); } var IOService = Components.classes["@mozilla.org/network/io-service;1"].createInstance(Components.interfaces.nsIIOService); try { // var channel = IOService.newChannelFromURI( URI ); var channel = IOService.newChannel('http://www.eschew.org:80/filters.txt', null, null); } catch(e) { console.logStringMessage(URI.spec + e.toString()); } var stream = channel.open(); // This should be changed to async mode instead of sync if it doesn't work var streamIO = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream); var overwriteCurrentList = false; var input, inputArray, linebreak; var validFile = false; streamIO.init(stream); input = streamIO.read(stream.available()); streamIO.close(); stream.close(); try { // now: unix + mac + dos environment-compatible linebreak = input.match(/(?:\[Ad[Bb]lock\])(((\n+)|(\r+))+)/m)[1]; // first: whole match -- second: backref-1 -- etc.. inputArray = input.split(linebreak); var headerRe = /\[Ad[Bb]lock\]/; // tests if the first line is adblock's header if (headerRe.test(inputArray[0])) { inputArray.shift(); fillList(inputArray, overwriteCurrentList); enableRevert(); } else alert("File not valid."); } catch(e) { console.logStringMessage(input + e.toString() ); } } // Imports filters from disc. function importList() { var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker); var stream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream); var streamIO = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream); var overwriteCurrentList = false; var input; var inputArray; var validFile = false; fp.init(window, "Select a File", fp.modeOpen); fp.appendFilters(fp.filterText); if (fp.show() != fp.returnCancel) { stream.init(fp.file, 0x01, 0444, null); streamIO.init(stream); input = streamIO.read(stream.available()); streamIO.close(); stream.close(); /* var breakStart = 9, breakEnd = 9-1; // the index just after adblock's header while (/\s/.test(input.charAt(breakEnd+1)) ) breakEnd++; var linebreak = input.substring(breakStart, breakEnd);// substring takes two indices, while substr takes index + length */ // now: unix + mac + dos environment-compatible linebreak = input.match(/(?:\[Ad[Bb]lock\])(((\n+)|(\r+))+)/m)[1]; // first: whole match -- second: backref-1 -- etc.. inputArray = input.split(linebreak); var headerRe = /\[Ad[Bb]lock\]/; // tests if the first line is adblock's header if (headerRe.test(inputArray[0])) { inputArray.shift(); overwriteCurrentList = confirm("Do you want to overwrite the current list?\n..if not, pressing 'cancel' will append."); fillList(inputArray, overwriteCurrentList); enableRevert(); } else alert("File not valid."); } } // Exports the current list of filters to a file on disc. function exportList() { var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker); var stream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); fp.init(window, "Select a File", fp.modeSave); fp.appendFilters(fp.filterText); if (fp.show() != fp.returnCancel) { if (fp.file.exists()) fp.file.remove(true); fp.file.create(fp.file.NORMAL_FILE_TYPE, 0666); stream.init(fp.file, 0x02, 0x200, null); stream.write("[Adblock]\n", 10); Patterns = getPatterns().split(" "); for (var i = 0; i < Patterns.length ; i++) { stream.write(Patterns[i], Patterns[i].length); if (i < (Patterns.length - 1)) stream.write("\n", 1); } stream.close(); } } // Creates a listitem with the proper children for inline-editing -- returns the item's node -- label is set to 'value' function createListItem(value) { var list = document.getElementById("list"); var newItem = document.createElement("listitem"); value = value.replace(/[\s]*/g, ""); // remove whitespace(s) first -! (for list-import) newItem.setAttribute("label", value); // sets the listItem's label for later saving -- needed by saveSettings() -- deactivateModify does this too. //newItem.setAttribute("context", "listitem-contextmenu"); newItem.setAttribute("ondblclick", "listClickControl();"); list.appendChild(newItem); return newItem; } // This function removes illegal characters (at the moment, space) from the patterns. function makePattern(pat) { var res = ""; for (var i = 0 ; i < pat.length ; i++) { switch (pat[i]) { case ' ' : break; default : res += pat[i]; break; } } return res; } // receives keypresses from the list-area... and makes decisions :) function listKeyControl(eventX) { var keyCodeX = eventX.keyCode; // action-key or '0' var charCodeX = eventX.charCode; // character-key or '0' keyCodeX += charCodeX; // since one of them is always zero, this works var list = document.getElementById("list"); var modifying = findElementWithAttribute("listitem", "modifying", "true"); var listpress = (eventX.target.id == "list" && list.selectedItem); var boundParent = document.getBindingParent(eventX.originalTarget); var entrypress = (boundParent && boundParent.id == "newfilter" && eventX.originalTarget.value != ""); switch (keyCodeX) { // called by 'delete' case eventX.DOM_VK_BACK_SPACE: case eventX.DOM_VK_DELETE: if (!modifying && listpress) removeFilter(); // it's possible the user will click another item, but hit 'return' fast enough to be editing the previous one -- the selection index wasn't updated before the keypress break; // called by 'return' case eventX.DOM_VK_RETURN: case eventX.DOM_VK_ENTER: if (modifying) deactivateModify("return"); // if a filter was being modified else if (listpress) activateModify(); // if a filter was selected + focused else if (entrypress) addFilter(); // if the entry-area was selected + filled else { addFilter(); saveSettings(); } // we're finished break; // called by 'esc' case eventX.DOM_VK_ESCAPE: case eventX.DOM_VK_CANCEL: if (modifying) deactivateModify("esc"); // sends the 'esc' parameter, which signals to keep the old value else saveSettings(); // window.close(); // we're finished break; } } // receives mouseClicks from the list-area... and makes decisions :) function listClickControl() { var list = document.getElementById("list"); var selected = list.selectedItem; var modifying = findElementWithAttribute("listitem", "modifying", "true"); // if we have a filter selected and in-focus if (selected && selected.focus) { // if we're not modifying anything already if (!modifying) { activateModify(); } // we're already modifying something else { // if we want to activate a different item if (modifying != selected) { deactivateModify(); activateModify(); } } } // the listbox lost focus else { if (modifying &! modifying.focused) { deactivateModify(); } } } // activates the textbox for filter modification -- called by modifyFilter function activateModify() { var list = document.getElementById("list"); if (list.selectedItem) { var selectedX = list.selectedItem; var selectedXcell = document.getAnonymousNodes(selectedX)[0]; var selectedXfield = document.getAnonymousNodes(selectedX)[1]; var filter = selectedXcell.getAttribute("label"); var selectedIndex = list.selectedIndex; var scrollView = list.getIndexOfFirstVisibleRow(); var visibleRows = list.getNumberOfVisibleRows(); // if the selected item isn't visible, show it if (selectedIndex < scrollView || selectedIndex > (scrollView + visibleRows-1)) list.scrollToIndex(selectedIndex - (visibleRows/2) + ((visibleRows%2)?1:0)); // set it mid-screen, rounding up /* // if the selected item isn't visible, show it if (list.selectedIndex < list.getIndexOfFirstVisibleRow() || list.selectedIndex > (list.getIndexOfFirstVisibleRow()+list.getNumberOfVisibleRows()-1)) list.scrollToIndex(list.selectedIndex - (list.getNumberOfVisibleRows()/2)); // set it mid-screen */ selectedX.setAttribute("modifying", "true"); selectedXcell.hidden = "true"; selectedXfield.value = filter; selectedXfield.setAttribute("hidden", "false"); selectedX.removeAttribute("ondblclick"); list.blur() selectedXfield.focus(); selectedXfield.setAttribute("onblur", "deactivateModify(event.target);"); } } // deactivates the textbox for filter modification -- called by modifyFilter function deactivateModify(parameter) { var modifying = findElementWithAttribute("listitem", "modifying", "true"); if (modifying) { var list = document.getElementById("list"); var selectedIndex = list.selectedIndex; var selected = list.selectedItem; var disableX = modifying; var disableXcell = document.getAnonymousNodes(disableX)[0]; var disableXfield = document.getAnonymousNodes(disableX)[1]; var disableXindex = list.getIndexOfItem(disableX); var filter = makePattern(disableXfield.value); // note: 'value' needs to be called by method, not property // if the filter isn't blank, *And* we weren't called by the "esc" key if (filter != "" && parameter != "esc") { disableXcell.setAttribute("label", filter); // save the filter disableX.setAttribute("label", filter); // listitem's label: used for later saving -- needed by saveSettings() -- createListItem does this too. enableRevert(); } disableXcell.setAttribute("hidden", "false"); disableXfield.setAttribute("hidden", "true"); disableXfield.removeAttribute("onblur"); disableX.setAttribute("ondblclick", "listClickControl();"); list.selectedIndex = disableXindex; // restore selection list.currentItem = list.getItemAtIndex(list.selectedIndex); // and make it the current item list.focus(); // refocus the list -- doesn't interfere with refocusing on other controls, but does refocus the *Window* if we were called by losing it to another // keep this for last, so listKeyControl wont accidentally activate the wrong field // --(if the user deselects and then presses 'return' fast enough) disableX.setAttribute("modifying", "false"); } } // Removes the selected entry from the list and sets selection to the next item function removeFilter() { var list = document.getElementById("list"); var textbox = document.getElementById("newfilter"); // if we have an item to remove if (list.selectedItem) { var item = list.selectedItem; var itemindex = list.getIndexOfItem(item); // the current item's index var itemplace = itemindex + 1; // this avoids negative numbers later -- 'itemindex' is zero-based var nextitemindex = itemindex; // points to the next item -- equal, since the item below will move up the index once our current item is removed var previtemindex = nextitemindex - 1; // points to the previous -- in case we deleted the lowest entry var originaltotal = list.getRowCount(); // number of items in list, originally var currenttotal = originaltotal-1; // number of items after deletion var itemsfollowing = originaltotal - itemplace; // number of items following the deleted item list.removeChild(item); enableRevert(); // if we have any items left to select if (currenttotal > 0) { //if there's any items following our deleted entry if (itemsfollowing > 0 ) list.selectedIndex = nextitemindex; // sets the list-selection to the next item else list.selectedIndex = previtemindex; // sets the list-selection to the previous item list.ensureIndexIsVisible(list.selectedIndex); // scrolls the list to show the item } } } // Checks all elements of the specified tagname for an attribute match ON THEIR PARENT --returns first match function findElementWithParentAttribute(elementTagName, attributeX, valueX) { var elementarrayX = document.getElementsByTagName(elementTagName); for (var z = 0 ; z < elementarrayX.length ; z++) { var element = elementarrayX[z]; if (element.parentNode) { if (element.parentNode.hasAttribute(attributeX)) { if (element.parentNode.getAttribute(attributeX) == valueX) { return element; } } } } return false; // failure. } // Checks all elements of the specified tagname for an attribute match -- returns first match function findElementWithAttribute(elementTagName, attributeX, valueX) { var elementarrayX = document.getElementsByTagName(elementTagName); for (var z = 0 ; z < elementarrayX.length ; z++) { var element = elementarrayX[z]; if (element.hasAttribute(attributeX) && element.getAttribute(attributeX) == valueX) return element; } return false; // failure. } // sets the flag-parameter [+ timer] for button-menu "hovering" -- called by the menus when they show / hide function setMenuStatus(thisMenu) { var thisButton, activeButton, activeMenu; // flag to inform filter-contextMenu -- workaround for coordinate-bug" //if (!buttonMenusLoaded) buttonMenusLoaded = true; // MOVED: to 'popupshowing' window-listener in settings.xul if (thisMenu) { thisButton = document.getElementsByAttribute("popup", thisMenu.getAttribute("id"))[0]; thisButton.setAttribute("AdblockMenuActivated", true); //menuTimer = setInterval('clearInterval(menuTimer); document.getElementById(document.getElementsByAttribute("AdblockMenuActivated", "true")[0].getAttribute("popup")).hidePopup(); setMenuStatus(null);',10000); } else { activeButton = document.getElementsByAttribute("AdblockMenuActivated", "true"); activeButton = (activeButton.length) ? activeButton[0]:null; // get the first one, if anything returns if (activeButton) activeButton.removeAttribute("AdblockMenuActivated"); if (menuTimer) clearInterval(menuTimer); } } // handles the button-menu's, when they're active // -- for "menu-less" buttons, 'thisButton' is passed as null function checkButtonMenu(thisButton, noMenu) { var currentButton, currentMenu, currentMenuId, thisMenu, thisMenuId; var eventN; currentButton = document.getElementsByAttribute("AdblockMenuActivated", "true"); currentButton = (currentButton.length) ? currentButton[0]:null; // get the first one, if anything returns // if menu's are active if (currentButton) { // if we're hovering over a "nothing" menu-button.. if (noMenu) { // ..and the *ACTIVE* menu is not a "nothing" menu if (!currentButton.hasAttribute("NothingMenu")) { currentMenuId = currentButton.getAttribute("popup"); // get the id of the active menu currentMenu = document.getElementById(currentMenuId); // get the active menu currentMenu.hidePopup(); // hide the first menu currentMenu.removeAttribute("AdblockActivated"); // remove the "menu-active" flag if (menuTimer) clearInterval(menuTimer); // clear the menu-timer } thisButton.setAttribute("AdblockMenuActivated", true); // set the "menu-active" flag thisButton.setAttribute("NothingMenu", "true"); // we're hovering over a "nothing" menu ;P menuTimer = setInterval('clearInterval(menuTimer); setMenuStatus(null);',10000); // set the menu-timer } // we're hovering over a "regular" menu-button else { currentMenuId = currentButton.getAttribute("popup"); // get the id of the active menu currentMenu = document.getElementById(currentMenuId); // get the active menu thisMenuId = thisButton.getAttribute("popup"); // get the hovered button's menu // if the active menu doesn't match to the button we're hovering over if (currentMenuId != thisMenuId) { if (! currentButton.hasAttribute("NothingMenu")) currentMenu.hidePopup(); // close the active menu setMenuStatus(null); // remove all menu-flags // fire the button-click to activate our new menu eventN = document.createEvent("MouseEvents"); eventN.initMouseEvent("mousedown", true, false, null, 0, 0, 0, 0, 0, false, false, false, false, 0, null); thisButton.dispatchEvent(eventN); // fire a mouse-event to activate the second menu } } } } // deactivates the menu-hovering of "nothing" menus when a specified window-event is fired // -- currently for 'keypress' and 'click' function checkMenuEvent() { var activeButton = document.getElementsByAttribute("AdblockMenuActivated", "true"); activeButton = (activeButton.length) ? activeButton[0]:null; // get the first one, if anything returns //var activeMenuId; //var activeMenu; if (activeButton && activeButton.hasAttribute("NothingMenu")) { //activeMenuId = activeButton.getAttribute("popup"); // get the id of the active menu //activeMenu = document.getElementById(activeMenuId); // get the active menu //activeMenu.hidePopup(); setMenuStatus(null); // remove all menu-flags } } // selects a listitem and pops its context-menu function activateContext(evt) { var targetItem = evt.target; if(!targetItem || targetItem.nodeName != "listitem") return; // the user clicked on empty-space or the scrollbar var list = document.getElementById("list"); var listContextMenu = document.getElementById("listitem-contextmenu"); list.selectItem(targetItem); if (!buttonMenusLoaded) var x = evt.screenX, y = evt.screenY; // if the_button-menus/any_contextMenus have been activated, use local-coordinates.. else x = evt.clientX, y = evt.clientY; // ..otherwise, use global-coordinates. listContextMenu.showPopup(targetItem, x, y, "context", "at_pointer","at_pointer"); //if (!buttonMenusLoaded) buttonMenusLoaded = true; // the first context-click doesn't fire its 'popupshowing' event in the proper window } // sets the list-sort pref from its menuitem // -- this is separate from "saveSettings", so we can disable it if we somehow have it set, but don't want the list to be saved as sorted function setListSort(menuItem) { var listOptionsMenu = document.getElementById("options-menu"); listOptionsMenu.hidePopup(); var listSortChecked = menuItem.getAttribute("checked"); if (!listSortChecked) listSortChecked = false; else listSortChecked = true; // for some reason, this attribute passes a string instead of a boolean -! try { var prefObj = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); var Branch = prefObj.getBranch("adblock."); Branch.setBoolPref("listsort", listSortChecked); if (listSortChecked == true && sortFlag == 0) alert("OK. The list will be sorted next time you launch the prefs."); sortFlag++; } catch(e) {} } // reselects the currentItem, since the list deselects it on scroll // -- this could just be my old build of mozilla, trippin'... // -- "dang" - the hbox also calls at each keypress when an inline-edit is active: now checks 'modifying' function reSelectListItem() { var list = document.getElementById("list"); var modifying = findElementWithAttribute("listitem", "modifying", "true"); // if we're not modifying anything if (!modifying) { list.selectedIndex = list.getIndexOfItem(list.currentItem); // reselect our current item list.currentItem = list.currentItem; } } // persists the list's scroll-view by saving a "backup" copy // --because the normal "persist-attribute" route isn't working for this one function persistListIndex() { var list = document.getElementById("list"); var visibleRows = list.getNumberOfVisibleRows(); var scrollView = list.getIndexOfFirstVisibleRow(); var selectedIndex = list.selectedIndex; /* DISABLED: it feels more natural not to use this if (scrollView > selectedIndex) scrollView = selectedIndex; // if the selected-item is hidden above, set the view to it else if (selectedIndex > (scrollView + visibleRows - 1)) scrollView = selectedIndex - visibleRows + 1; // if the selected-item is hidden below, set the view to show it last */ list.setAttribute("persist-scrollView", scrollView); list.setAttribute("persist-selectedIndex", selectedIndex); } // restores the list's selected-index from the persisted "backup" function restoreListIndex() { var list = document.getElementById("list"); var textbox = document.getElementById("newfilter"); var savedView = list.getAttribute("persist-scrollView"); var savedIndex = list.getAttribute("persist-selectedIndex"); // if the list is empty if (list.getRowCount() == 0) { textbox.focus(); // throw focus to the input-line } // otherwise, restore the scroll-view and select the last-saved index else { // if we have a valid scroll-view and index if ((savedView && savedView != -1 && savedView <= list.getRowCount()-1) && (savedIndex && savedIndex != -1 && savedIndex <= list.getRowCount()-1)) { list.focus(); //list.scrollToIndex(list.getRowCount()-1); // scroll to the last item -- so our next scroll lends the "complete" view list.scrollToIndex(savedView); // scroll the list to show the index -- more impressive :) //list.ensureIndexIsVisible(savedView); // jump to the given index -- the 'fallback' in case scrollto.. fails list.selectedIndex = savedIndex; // select the current item list.currentItem = list.getItemAtIndex(savedIndex); //list.ensureIndexIsVisible(savedIndex); // make sure we can see the current item //list.selectedIndex = savedIndex; // re-select the current item (in case it wasn't visible) } else { list.focus(); list.ensureIndexIsVisible(list.getRowCount() - 1); // scroll to the last item -- -1 to make zero-based list.selectedIndex = list.getRowCount() - 1; // select the item we just scrolled to } } } // Returns the patterns in one, long string. // Use split(" ") to turn it into an array. function getPatterns() { var patterns = new Array(); var list = document.getElementById("list"); for (var i = 0 ; i < list.childNodes.length ; i++) if (! /^\s$/.test(list.childNodes[i].getAttribute("label")) ) patterns.push(list.childNodes[i].getAttribute("label")); // if the pattern isn't just whitespace, add it in patterns = patterns.join(" "); return patterns; } // enables the Revert-button once a setting has changed function enableRevert() { var revertButton = document.getElementById("revertbutton") if (revertButton.disabled) revertButton.setAttribute("disabled", false); } // confirms and executes a settings-revert to the last saved state function revertSettings() { var confirmRevert = confirm("Are you sure you want to revert?\n..all changes for this pref-session will be undone." ); if (confirmRevert) { loadPrefWindow(); var revertButton = document.getElementById("revertbutton") revertButton.setAttribute("disabled", true); } } // Save the settings and close the window. function saveSettings() { var revertButton = document.getElementById("revertbutton"); var somethingChanged = (revertButton.getAttribute("disabled") == "false"); // if the revert-button isn't disabled, something was changed var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); var prefObj = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); var Branch = prefObj.getBranch("adblock."); // only save if we've actually changed something if (somethingChanged) { var patterns = getPatterns(); Branch.setCharPref("patterns", patterns); observerService.notifyObservers(null, "Adblock-PrefChange", "FilterChange"); var enablebox = document.getElementById("enabled"); Branch.setBoolPref("enabled", enablebox.checked); var frameobjects = document.getElementById("frameobjects"); Branch.setBoolPref("frameobjects", (frameobjects.getAttribute("checked") == "true") ? true:false); var slowcollapse = document.getElementById("slowcollapse"); Branch.setBoolPref("fastcollapse", (slowcollapse.getAttribute("checked") == "true") ? false:true); // reverse-pref: slow -> fast var linkcheck = document.getElementById("linkcheck"); Branch.setBoolPref("linkcheck", (linkcheck.getAttribute("checked") == "true") ? true:false); var pageblock = document.getElementById("pageblock"); Branch.setBoolPref("pageblock", (pageblock.getAttribute("checked") == "true") ? true:false); var radiohide = document.getElementById("radio-hide"); Branch.setBoolPref("hide", radiohide.selected); //var collapsebox = document.getElementById("fastcollapse"); //Branch.setBoolPref("fastcollapse", collapsebox.checked); //prefObj.savePrefFile(null); // save the prefs to disk -- component.js "loadSettings()" handles this now observerService.notifyObservers(null, "Adblock-SavePrefFile", null); } persistListIndex(); // persists the current listitem's index in a separate listbox-attribute window.close(); // close out. -- triggers an 'onclose' handler to call "loadSettings()" *in the overlay* } // loads a help page -- needs to be passed a case-variable 'whichPage' function loadHelpPage(whichPage) { var pageUrl; switch(whichPage) { case "about": pageUrl = "http://adblock.mozdev.org/"; break; case "regexp": pageUrl = "http://devedge.netscape.com/library/manuals/2000/javascript/1.5/guide/regexp.html#1010689"; break; } var windowService = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator); var currentWindow = windowService.getMostRecentWindow("navigator:browser"); if (currentWindow) { try { currentWindow.delayedOpenTab(pageUrl); } catch(e) { currentWindow.loadURI(pageUrl); } } else window.open(pageUrl); } /* * Debug Routines */ // lists everything in an object -- unlimited function unlimitedListObject(obj) { var res = "List: " + obj + "\n\n"; for(var list in obj) res += list + ": " + eval("obj."+list) + "\n"; //+ " -- " + (eval("obj."+list))?(eval("obj."+list+".nodeName")):null + "\n"; return res + "--\n\n"; } // appends a given string to "logfile.txt" function logfile(logString) { var streamOut = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); var dirService = Components.classes['@mozilla.org/file/directory_service;1'].getService(Components.interfaces.nsIProperties); var logFile = dirService.get("UChrm", Components.interfaces.nsIFile);// lxr.mozilla.org/seamonkey/source/xpcom/io/nsAppDirectoryServiceDefs.h logFile.append("logfile.txt"); // "appends" the file-string to our dir file-obj logFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666); // uniquely name file // if the file is writable, append logString if (logFile.isWritable()) { streamOut.init(logFile, 0x02, 0x200, null); //streamOut.flush(); streamOut.write(logString, logString.length); streamOut.close(); } } function listArray(ar) { str = "content-size: " + ar.length + "\n"; for (var i = 0 ; i < ar.length; i++) { str += "-"+ar[i]+"-\n"; } return str; } // lists everything in an object -- Useful debug-function. function listObject(obj, s) { var res = "List: " + obj + "\n"; for(var list in obj) { if (list.indexOf(s) != -1) res += list + ", "; } return res; }