[Ext] userChrome.js
-
- Posts: 0
- Joined: December 31st, 1969, 5:00 pm
[Ext] userChrome.js
<a href="http://www.haslo.ch/zeniko/software/userchrome.js.xpi">userChrome.js</a> allows to easily customize Firefox through JavaScript.
What userChrome.css is for CSS customization, userChrome.js is for JavaScript. Simply edit the file userChrome.js (in the same place as userChrome.css) and its content will be run whenever a new browser window is opened (onLoad).
If you want this to become a standard part of Firefox in the future, go and vote for bug 332529 and/or contribute to the discussion about how to fix this...
Download
<a href="http://www.haslo.ch/zeniko/software/userchrome.js.xpi">userChrome.js 0.7</a>
This release should work for Firefox and Thunderbird 1.0 and newer, Mozilla Suite, SeaMonkey, Netscape and Netscape Browser, Nvu, Sunbird and Flock - about just as long as extensions can be installed.
In case you're using Firefox or Thunderbird 2.0 or any newer Mozilla application and want to run code in other windows than the main ones (without the WindowHook hack from below), get userChrome.js 0.8 instead.
Code Samples
Basics (should work for all applications):
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Sub-Script%2FXUL%20Loader%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0A%2F%2F%20automatically%20includes%20all%20files%20ending%20in%20.uc.js%20and%20.uc.xul%20from%20the%20profile's%20chrome%20folder%0A%0A(function()%20%7B%0A%09var%20getURLSpecFromFile%20%3D%20Components.classes%5B%22%40mozilla.org%2Fnetwork%2Fio-service%3B1%22%5D.getService(Components.interfaces.nsIIOService).getProtocolHandler(%22file%22).QueryInterface(Components.interfaces.nsIFileProtocolHandler).getURLSpecFromFile%3B%0A%09var%20chromeDir%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Fdirectory_service%3B1%22%5D.getService(Components.interfaces.nsIProperties).get(%22UChrm%22%2C%20Components.interfaces.nsILocalFile)%3B%0A%09var%20files%20%3D%20chromeDir.directoryEntries.QueryInterface(Components.interfaces.nsISimpleEnumerator)%3B%0A%09var%20xul_files%20%3D%20%5B%5D%3B%0A%09%0A%09while%20(files.hasMoreElements())%0A%09%7B%0A%09%09var%20file%20%3D%20files.getNext().QueryInterface(Components.interfaces.nsIFile)%3B%0A%09%09if%20(%2F%5C.uc%5C.js%24%2Fi.test(file.leafName))%0A%09%09%7B%0A%09%09%09setTimeout(function(aFile)%20%7B%0A%09%09%09%09Components.classes%5B%22%40mozilla.org%2Fmoz%2Fjssubscript-loader%3B1%22%5D.getService(Components.interfaces.mozIJSSubScriptLoader).loadSubScript(getURLSpecFromFile(aFile))%3B%0A%09%09%09%7D%2C%200%2C%20file)%3B%0A%09%09%7D%0A%09%09else%20if%20(%2F(%5EuserChrome%7C%5C.uc)%5C.xul%24%2Fi.test(file.leafName))%0A%09%09%7B%0A%09%09%09xul_files.push(file)%3B%0A%09%09%7D%0A%09%7D%0A%09%0A%09setTimeout(function()%20%7B%0A%09%09if%20(xul_files.length%20%3E%200)%0A%09%09%7B%0A%09%09%09document.loadOverlay(getURLSpecFromFile(xul_files.shift())%2C%20null)%3B%0A%09%09%09setTimeout(arguments.callee%2C%200)%3B%0A%09%09%7D%0A%09%7D%2C%200)%3B%0A%7D)()%3B%0A%0A">Sub-Script/XUL Loader</a> (automatically includes all scripts ending in .uc.js and .uc.xul from the profile's chrome folder - this allows you to keep your code snippets somewhat ordered)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20WindowHook%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0Avar%20WindowHook%20%3D%20%7B%0A%09observe%3A%20function(aSubject%2C%20aTopic%2C%20aData)%0A%09%7B%0A%09%09if%20(!aSubject._WindowHook)%0A%09%09%7B%0A%09%09%09aSubject._WindowHook%20%3D%20this%3B%0A%09%09%09aSubject.addEventListener(%22load%22%2C%20this.onLoad_window%2C%20false)%3B%0A%09%09%7D%0A%09%7D%2C%0A%0A%09onLoad_window%3A%20function()%0A%09%7B%0A%09%09this.removeEventListener(%22load%22%2C%20this._WindowHook.onLoad_window%2C%20false)%3B%0A%09%09var%20funcs%20%3D%20this._WindowHook.mFuncs%5Bthis.document.location.href%5D%20%7C%7C%20null%3B%0A%09%09if%20(funcs)%0A%09%09%7B%0A%09%09%09funcs.forEach(function(aFunc)%20%7B%20aFunc(this)%3B%20%7D%2C%20this)%3B%0A%09%09%7D%0A%09%09delete%20this._WindowHook%3B%0A%09%7D%2C%0A%0A%09register%3A%20function(aURL%2C%20aFunc)%0A%09%7B%0A%09%09if%20(!this.mFuncs)%0A%09%09%7B%0A%09%09%09this.mFuncs%20%3D%20%7B%7D%3B%0A%09%09%09Components.classes%5B%22%40mozilla.org%2Fobserver-service%3B1%22%5D.getService(Components.interfaces.nsIObserverService).addObserver(this%2C%20%22domwindowopened%22%2C%20false)%3B%0A%09%09%7D%0A%09%09if%20(!this.mFuncs%5BaURL%5D)%0A%09%09%7B%0A%09%09%09this.mFuncs%5BaURL%5D%20%3D%20%5B%5D%3B%0A%09%09%7D%0A%09%09this.mFuncs%5BaURL%5D.push(aFunc)%3B%0A%09%7D%0A%7D%3B%0A">WindowHook</a> (allows to target all windows / not only the main window)
Extension replacements (for Firefox 1.5 and 2.0)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Tabs%20to%20the%20Right%20(cf.%20Tabs%20Open%20Relative)%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0A(function()%20%7B%0A%09getBrowser().__uc_addedTabs%20%3D%200%3B%0A%09eval(%22gBrowser.addTab%20%3D%20%22%20%2B%20gBrowser.addTab.toString().replace(%2F%5C%7B%2F%2C%20%22%24%26%20var%20__oldTabPos%20%3D%20this.mCurrentTab._tPos%3B%22).replace(%2Freturn%20%2F%2C%20%22if%20(!blank)%20this.moveTabTo(t%2C%20__oldTabPos%20%2B%201%20%2B%20this.__uc_addedTabs%2B%2B)%3B%20%24%26%22))%3B%0A%09eval(%22gBrowser.moveTabTo%20%3D%20%22%20%2B%20gBrowser.moveTabTo.toString().replace(%2F%7B%2F%2C%20%22%24%26%20if%20(aTab%20%3D%3D%20this.mCurrentTab)%20this.__uc_addedTabs%20%3D%200%3B%22))%3B%0A%09gBrowser.mTabContainer.addEventListener(%22select%22%2C%20function()%20%7B%20gBrowser.__uc_addedTabs%20%3D%200%3B%20%7D%2C%20false)%3B%0A%7D)()%3B%0A">Tabs to the Right</a> (Tabs Open Relative light)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Drag'n'go%20(cf.%20Super%20DragAndGo)%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0AcontentAreaDNDObserver.onDragOver%20%3D%20function(aEvent%2C%20aFlavour%2C%20aDragSession)%20%7B%0A%09aEvent.target.setAttribute(%22dragover%22%2C%20%22true%22)%3B%0A%09%0A%09return%20(aDragSession.canDrop%20%3D%20true)%3B%0A%7D%3B%0A%0AcontentAreaDNDObserver.__preDnG_onDrop%20%3D%20contentAreaDNDObserver.onDrop%20%7C%7C%20null%3B%0AcontentAreaDNDObserver.onDrop%20%3D%20function(aEvent%2C%20aXferData%2C%20aDragSession)%20%7B%0A%09var%20url%20%3D%20(%2F%5E%5Cs*(.*%3F)%5Cs*%24%2Fm.test(aXferData.data))%3FRegExp.%241%3Anull%3B%0A%09if%20(!url)%0A%09%7B%0A%09%09this.__preDnG_onDrop(aEvent%2C%20aXferData%2C%20aDragSession)%3B%0A%09%09return%3B%0A%09%7D%0A%09aEvent.preventDefault()%3B%0A%09%0A%09if%20(%2F%5Efile%3A%5C%2F%7B3%7D(%3F%3A.*%5C%2F)%3F(.%2B%5C.xpi)%24%2F.test(url))%20%2F%2F%20local%20XPI%20-%3E%20installation%0A%09%7B%0A%09%09var%20xpinstallObj%20%3D%20%7B%7D%3B%0A%09%09xpinstallObj%5BRegExp.%241%5D%20%3D%20url%3B%0A%09%09%0A%09%09for%20(var%20i%20%3D%201%3B%20i%20%3C%20aDragSession.numDropItems%3B%20i%2B%2B)%0A%09%09%7B%20%2F%2F%20allow%20to%20install%20several%20extensions%20at%20once%0A%09%09%09if%20((url%20%3D%20this.__DnG_getDroppedURL(aDragSession%2C%20i))%20%26%26%20%2F%5Efile%3A%5C%2F%7B3%7D(%3F%3A.*%5C%2F)%3F(.%2B%5C.xpi)%24%2F.test(url))%0A%09%09%09%7B%0A%09%09%09%09xpinstallObj%5BRegExp.%241%5D%20%3D%20url%3B%0A%09%09%09%7D%0A%09%09%7D%0A%09%09%0A%09%09InstallTrigger.install(xpinstallObj)%3B%0A%09%09return%3B%0A%09%7D%0A%09%0A%09if%20(aDragSession.numDropItems%20%3D%3D%201%20%26%26%20!%2F%5Efile%3A%5C%2F%7B3%7D%7C%5Edata%3A.%2B%7C%5E(%3F!javascript%3A)%5CS*%3F((%3F%3A%5B%5Cw-%5D%5C.)%2B%5Cw%7B2%2C7%7D%7Clocalhost(%5B%3A%5C%2F%5D%7C%24))%5CS*%24%2F.test(url))%20%2F%2F%20text%20string%20-%3E%20web%20search%0A%09%7B%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20searchURL%20%3D%20gPrefService.getComplexValue(%22browser.search.defaulturl%22%2C%20Components.interfaces.nsIPrefLocalizedString).data%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09searchURL%20%3D%20%22http%3A%2F%2Fwww.google.com%2Fsearch%3Fq%3D%22%3B%0A%09%09%7D%0A%09%09url%20%3D%20searchURL%20%2B%20encodeURIComponent(url)%3B%0A%09%7D%0A%09else%20if%20(%2F%5Ettps%3F%3A%2F.test(url))%0A%09%7B%0A%09%09url%20%3D%20%22h%22%20%2B%20url%3B%0A%09%7D%0A%09%0A%09gBrowser.dragDropSecurityCheck(aEvent%2C%20aDragSession%2C%20url)%3B%0A%09%0A%09if%20(gBrowser.currentURI.spec%20%3D%3D%20%22about%3Ablank%22)%0A%09%7B%0A%09%09loadURI(url%2C%20null%2C%20null)%3B%0A%09%7D%0A%09else%0A%09%7B%0A%09%09var%20newTab%20%3D%20gBrowser.addTab(url%2C%20gBrowser.currentURI)%3B%0A%09%09if%20(getBoolPref(%22browser.tabs.loadInBackground%22)%20!%3D%20!(aEvent%20%26%26%20aEvent.shiftKey))%0A%09%09%7B%0A%09%09%09gBrowser.selectedTab%20%3D%20newTab%3B%0A%09%09%7D%0A%09%7D%0A%09%0A%09for%20(i%20%3D%201%3B%20i%20%3C%20aDragSession.numDropItems%3B%20i%2B%2B)%0A%09%7B%0A%09%09if%20((url%20%3D%20this.__DnG_getDroppedURL(aDragSession%2C%20i)))%0A%09%09%7B%0A%09%09%09gBrowser.dragDropSecurityCheck(aEvent%2C%20aDragSession%2C%20url)%3B%0A%09%09%09gBrowser.addTab(url%2C%20gBrowser.currentURI)%3B%0A%09%09%7D%0A%09%7D%0A%7D%3B%0A%0AcontentAreaDNDObserver.__preDnG_onDragStart%20%3D%20contentAreaDNDObserver.onDragStart%20%7C%7C%20null%3B%0AcontentAreaDNDObserver.onDragStart%20%3D%20function(aEvent%2C%20aXferData%2C%20aDragAction)%20%7B%0A%09var%20target%20%3D%20aEvent.originalTarget%3B%0A%09if%20(!(target%20instanceof%20HTMLImageElement%20%26%26%20target.src))%0A%09%7B%0A%09%09contentAreaDNDObserver.__preDnG_onDragStart(aEvent%2C%20aXferData%2C%20aDragAction)%3B%0A%09%09return%3B%0A%09%7D%0A%09for%20(var%20obj%20%3D%20target.parentNode%3B%20obj%20%26%26%20!obj.href%3B%20obj%20%3D%20obj.parentNode)%3B%0A%09%0A%09var%20url%20%3D%20(obj)%3Fobj.href%3Atarget.src%3B%0A%09var%20caption%20%3D%20((obj)%3Fobj.title%3Anull)%20%7C%7C%20target.title%20%7C%7C%20target.alt%20%7C%7C%20url.replace(%2F%5E.*%5C%2F%2F%2C%20%22%22)%20%7C%7C%20url%3B%0A%09%0A%09aXferData.data%20%3D%20new%20TransferData()%3B%0A%09aXferData.data.addDataForFlavour(%22text%2Fx-moz-url%22%2C%20url%20%2B%20%22%5Cn%22%20%2B%20caption)%3B%0A%09aXferData.data.addDataForFlavour(%22text%2Funicode%22%2C%20url)%3B%0A%09aXferData.data.addDataForFlavour(%22text%2Fhtml%22%2C%20'%3Ca%20href%3D%22'%20%2B%20url%20%2B%20'%22%3E'%20%2B%20caption%20%2B%20'%3C%2Fa%3E')%3B%0A%09%0A%09const%20nsIDragService%20%3D%20Components.interfaces.nsIDragService%3B%0A%09aDragAction.action%20%3D%20nsIDragService.DRAGDROP_ACTION_COPY%20%7C%20nsIDragService.DRAGDROP_ACTION_MOVE%20%7C%20nsIDragService.DRAGDROP_ACTION_LINK%3B%0A%7D%3B%0A%0AcontentAreaDNDObserver.__DnG_getDroppedURL%20%3D%20function(aDragSession%2C%20aIx)%20%7B%0A%09try%0A%09%7B%0A%09%09var%20xfer%20%3D%20Components.classes%5B%22%40mozilla.org%2Fwidget%2Ftransferable%3B1%22%5D.createInstance(Components.interfaces.nsITransferable)%3B%0A%09%09xfer.addDataFlavor(%22application%2Fx-moz-file%22%2C%20%22nsIFile%22)%3B%0A%09%09xfer.addDataFlavor(%22text%2Fx-moz-url%22)%3B%0A%09%09xfer.addDataFlavor(%22text%2Funicode%22)%3B%0A%09%09aDragSession.getData(xfer%2C%20aIx)%3B%0A%09%09%0A%09%09var%20flavour%20%3D%20%7B%7D%2C%20data%20%3D%20%7B%7D%2C%20length%20%3D%20%7B%7D%3B%0A%09%09xfer.getAnyTransferData(flavour%2C%20data%2C%20length)%3B%0A%09%09var%20xferData%20%3D%20new%20FlavourData(data.value%2C%20length.value%2C%20this.getSupportedFlavours().flavourTable%5Bflavour.value%5D)%3B%0A%09%09%0A%09%09return%20transferUtils.retrieveURLFromData(xferData.data%2C%20xferData.flavour.contentType)%3B%0A%09%7D%0A%09catch%20(ex)%0A%09%7B%0A%09%09return%20null%3B%0A%09%7D%0A%7D%3B%0A%0Aeval(%22nsDragAndDrop.checkCanDrop%20%3D%20%22%20%2B%20nsDragAndDrop.checkCanDrop.toString().replace(%22aEvent.target%22%2C%20%22%24%26%20%7C%7C%20this.mDragSession.sourceNode%20instanceof%20HTMLImageElement%22))%3B%0A%0AgetBrowser().addEventListener(%22dragover%22%2C%20function(aEvent)%20%7B%0A%09nsDragAndDrop.dragOver(aEvent%2C%20contentAreaDNDObserver)%3B%0A%7D%2C%20false)%3B%0AgBrowser.addEventListener(%22drop%22%2C%20function(aEvent)%20%7B%0A%09nsDragAndDrop.dragOver(aEvent%2C%20contentAreaDNDObserver)%3B%0A%7D%2C%20false)%3B%0AgBrowser.addEventListener(%22draggesture%22%2C%20function(aEvent)%20%7B%0A%09nsDragAndDrop.startDrag(aEvent%2C%20contentAreaDNDObserver)%3B%0A%7D%2C%20true)%3B%0A">Drag'n'go</a> (Super DragAndGo without UI)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20LaunchIE%20(cf.%20IE%20View)%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0Avar%20LaunchIE%20%3D%20%7B%0A%09mSchemes%3A%20%5B%22file%22%2C%20%22ftp%22%2C%20%22http%22%2C%20%22https%22%5D%2C%0A%0A%09init%3A%20function()%0A%09%7B%0A%09%09this.mItem%20%3D%20document.createElement(%22menuitem%22)%3B%0A%09%09this.mItem.setAttribute(%22label%22%2C%20%22LaunchIE%22)%3B%0A%09%09this.mItem.setAttribute(%22accesskey%22%2C%20%22u%22)%3B%0A%09%09%0A%09%09document.getElementById(%22contentAreaContextMenu%22).addEventListener(%22popupshowing%22%2C%20function()%20%7B%20LaunchIE.onPopupShowing(this)%3B%20%7D%2C%20false)%3B%0A%09%7D%2C%0A%0A%09onPopupShowing%3A%20function(aPopup)%0A%09%7B%0A%09%09aPopup.insertBefore(this.mItem%2C%20document.getElementById(%22context-sep-%22%20%2B%20((gContextMenu.onLink)%3F%22open%22%3A%22stop%22)))%3B%0A%09%09this.mItem.setAttribute(%22oncommand%22%2C%20%22LaunchIE.launch(%22%20%2B%20((gContextMenu.onLink)%3F%22gContextMenu.linkURI%22%3A%22gBrowser.currentURI%22)%20%2B%20%22)%3B%22)%3B%0A%09%09this.mItem.hidden%20%3D%20!gContextMenu.onLink%20%26%26%20(gContextMenu.isTextSelected%20%7C%7C%20gContextMenu.onImage%20%7C%7C%20gContextMenu.onTextInput)%3B%0A%09%09this.mItem.setAttribute(%22disabled%22%2C%20this.mItem.hidden%20%7C%7C%20!this.isSupported((gContextMenu.onLink)%3FgContextMenu.linkURI%3AgBrowser.currentURI))%3B%0A%09%7D%2C%0A%0A%09launch%3A%20function(aURI%2C%20aApp)%0A%09%7B%0A%09%09if%20(!this.isSupported(aURI))%0A%09%09%7B%0A%09%09%09throw%20new%20Error(%22LaunchIE%3A%20unsupported%20URI%20scheme%20'%22%20%2B%20aURI.scheme%20%2B%20%22'!%22)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20iexplore%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Flocal%3B1%22%5D.createInstance(Components.interfaces.nsILocalFile)%3B%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20regkey%20%3D%20Components.classes%5B%22%40mozilla.org%2Fwindows-registry-key%3B1%22%5D.createInstance(Components.interfaces.nsIWindowsRegKey)%3B%0A%09%09%09regkey.open(Components.interfaces.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE%2C%20%22SOFTWARE%5C%5CMicrosoft%5C%5CWindows%5C%5CCurrentVersion%5C%5CApp%20Paths%5C%5C%22%20%2B%20(aApp%20%7C%7C%20%22IEXPLORE.EXE%22)%2C%20Components.interfaces.nsIWindowsRegKey.ACCESS_READ)%3B%0A%09%09%09iexplore.initWithPath(regkey.readStringValue(%22%22))%3B%0A%09%09%09regkey.close()%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09iexplore.initWithPath((Components.classes%5B%22%40mozilla.org%2Fprocess%2Fenvironment%3B1%22%5D.getService(Components.interfaces.nsIEnvironment).get(%22PROGRAMFILES%22)%20%7C%7C%20%22C%3A%5C%5CProgram%20Files%22)%20%2B%20%22%5C%5CInternet%20Explorer%5C%5Ciexplore.exe%22)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20process%20%3D%20Components.classes%5B%22%40mozilla.org%2Fprocess%2Futil%3B1%22%5D.createInstance(Components.interfaces.nsIProcess)%3B%0A%09%09process.init(iexplore)%3B%0A%09%09process.run(false%2C%20%5BaURI.spec%5D%2C%201)%3B%0A%09%7D%2C%0A%0A%09isSupported%3A%20function(aURI)%0A%09%7B%0A%09%09return%20this.mSchemes.indexOf(aURI.scheme)%20%3E%20-1%3B%0A%09%7D%0A%7D%3B%0A%0ALaunchIE.init()%3B%0A">LaunchIE</a> (IEView without UI)
User interface enhancements (for Firefox 2.0)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Fashion%20Tabs%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0A(%7B%0A%09init%3A%20function()%0A%09%7B%0A%09%09Array.forEach(getBrowser().mTabs%2C%20function(aTab)%20%7B%0A%09%09%09aTab.linkedBrowser.addProgressListener(this)%3B%0A%09%09%7D%2C%20this)%3B%0A%09%09%0A%09%09gBrowser.addEventListener(%22TabOpen%22%2C%20this%2C%20false)%3B%0A%09%09gBrowser.addEventListener(%22TabSelect%22%2C%20this%2C%20false)%3B%0A%09%09gBrowser.addEventListener(%22TabMove%22%2C%20this%2C%20false)%3B%0A%09%09gBrowser.addEventListener(%22TabClose%22%2C%20this%2C%20false)%3B%0A%09%7D%2C%0A%0A%09handleEvent%3A%20function(aEvent)%0A%09%7B%0A%09%09var%20tab%20%3D%20aEvent.originalTarget%3B%0A%09%09%0A%09%09switch%20(aEvent.type)%0A%09%09%7B%0A%09%09case%20%22TabOpen%22%3A%0A%09%09%09tab.linkedBrowser.addProgressListener(this)%3B%0A%09%09%09break%3B%0A%09%09case%20%22TabMove%22%3A%0A%09%09case%20%22TabSelect%22%3A%0A%09%09%09this.colorizeTab(tab)%3B%0A%09%09%09break%3B%0A%09%09case%20%22TabClose%22%3A%0A%09%09%09tab.linkedBrowser.removeProgressListener(this)%3B%0A%09%09%09break%3B%0A%09%09%7D%0A%09%7D%2C%0A%0A%09onLocationChange%3A%20function(aProgress%2C%20aRequest%2C%20aURI)%20%7B%0A%09%09var%20doc%20%3D%20aProgress.DOMWindow.document%3B%0A%09%09var%20tab%20%3D%20gBrowser.mTabs%5BgBrowser.getBrowserIndexForDocument(doc)%5D%3B%0A%09%09%0A%09%09this.colorizeTab(tab)%3B%0A%09%7D%2C%0A%0A%09onStateChange%3A%20function()%20%7B%20%7D%2C%0A%09onProgressChange%3A%20function()%20%7B%20%7D%2C%0A%09onStatusChange%3A%20function()%20%7B%20%7D%2C%0A%09onSecurityChange%3A%20function()%20%7B%20%7D%2C%0A%09onLinkIconAvailable%3A%20function()%20%7B%20%7D%2C%0A%0A%09colorizeTab%3A%20function(aTab)%0A%09%7B%0A%09%09function%20djb2hash(aString)%0A%09%09%7B%0A%09%09%09var%20hashvalue%20%3D%205381%3B%0A%09%09%09for%20(var%20i%20%3D%200%3B%20i%20%3C%20aString.length%3B%20i%2B%2B)%0A%09%09%09%7B%0A%09%09%09%09hashvalue%20%3D%20((hashvalue%20%3C%3C%205)%20%2B%20hashvalue)%20%2B%20aString.charCodeAt(i)%3B%0A%09%09%09%7D%0A%09%09%09return%20hashvalue%3B%0A%09%09%7D%0A%09%09%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20host%20%3D%20aTab.linkedBrowser.currentURI.host%3B%0A%09%09%7D%0A%09%09catch%20(ex)%20%7B%20%7D%0A%09%09%0A%09%09if%20(host%20%26%26%20host%20!%3D%20%22about%3Ablank%22)%0A%09%09%7B%0A%09%09%09var%20hue%20%3D%20djb2hash(host.replace(%2F%5Ewww%5C.(%3F%3D.%2B%5C..)%2F%2C%20%22%22))%20%25%20360%3B%0A%09%09%7D%0A%09%09var%20color%20%3D%20(hue)%3F%22hsl(%22%20%2B%20hue%20%2B%20%22%2C%2050%25%2C%2050%25)%22%3Anull%3B%0A%09%09%0A%09%09Array.forEach(aTab.ownerDocument.getAnonymousNodes(aTab)%2C%20function(aNode)%20%7B%0A%09%09%09aNode.style.backgroundColor%20%3D%20color%3B%0A%09%09%7D)%3B%0A%09%09%0A%09%09if%20(gBrowser.selectedTab%20%3D%3D%20aTab)%0A%09%09%7B%0A%09%09%09var%20node%20%3D%20aTab.ownerDocument.getAnonymousElementByAttribute(aTab.parentNode%2C%20%22class%22%2C%20%22tabs-bottom%22)%3B%0A%09%09%09if%20(color)%0A%09%09%09%09node.setAttribute(%22style%22%2C%20%22background-color%3A%20%22%20%2B%20color%20%2B%20%22%20!important%22)%3B%0A%09%09%09else%0A%09%09%09%09node.removeAttribute(%22style%22)%3B%0A%09%09%7D%0A%09%7D%2C%0A%0A%09QueryInterface%3A%20function(aIID)%20%7B%0A%09%09var%20Ci%20%3D%20Components.interfaces%3B%0A%09%09if%20(!%5BCi.nsIDOMEventListener%2C%20Ci.nsIWebProgressListener%2C%20Ci.nsISupportsWeakReference%2C%20Ci.nsISupports%5D.some(aIID.equals))%0A%09%09%7B%0A%09%09%09throw%20Components.results.NS_NOINTERFACE%3B%0A%09%09%7D%0A%09%09return%20this%3B%0A%09%7D%0A%7D).init()%3B%0A">Fashion Tabs</a> (Chromatabs lite; only tested with the default theme under Windows)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Undo%20Close%20Tab%20Menu%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0Avar%20UndoCloseTabMenu%20%3D%20%7B%0A%09mSavePref%3A%20%22extensions.userchrome_js.uctm_state%22%2C%0A%0A%09init%3A%20function()%0A%09%7B%0A%09%09this.mSS%20%3D%20Components.classes%5B%22%40mozilla.org%2Fbrowser%2Fsessionstore%3B1%22%5D.getService(Components.interfaces.nsISessionStore)%3B%0A%09%09%0A%09%09var%20dts%20%3D%20document.getElementById(%22devToolsSeparator%22)%3B%0A%09%09var%20menu%20%3D%20dts.parentNode.insertBefore(document.createElement(%22menu%22)%2C%20dts.parentNode.firstChild)%3B%0A%09%09%0A%09%09menu.setAttribute(%22label%22%2C%20%22Undo%20Close%20Tab%22)%3B%0A%09%09menu.setAttribute(%22accesskey%22%2C%20%22U%22)%3B%0A%09%09%0A%09%09this._popup%20%3D%20menu.appendChild(document.createElement(%22menupopup%22))%3B%0A%09%09this._popup.setAttribute(%22onpopupshowing%22%2C%20%22UndoCloseTabMenu.onPopupShowing()%3B%22)%3B%0A%09%7D%2C%0A%0A%09onPopupShowing%3A%20function()%0A%09%7B%0A%09%09while%20(this._popup.hasChildNodes())%0A%09%09%7B%0A%09%09%09this._popup.removeChild(this._popup.lastChild)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20undoItems%20%3D%20eval(%22(%22%20%2B%20this.mSS.getClosedTabData(window)%20%2B%20%22)%22)%3B%0A%09%09for%20(var%20i%20%3D%200%3B%20i%20%3C%20undoItems.length%3B%20i%2B%2B)%0A%09%09%7B%0A%09%09%09var%20key%20%3D%20(i%20%3C%209)%3Fi%20%2B%201%3A(i%20%3D%3D%209)%3F%220%22%3A%22%22%3B%0A%09%09%09var%20menuitem%20%3D%20this._popup.appendChild(document.createElement(%22menuitem%22))%3B%0A%09%09%09menuitem.setAttribute(%22label%22%2C%20((key)%3Fkey%20%2B%20%22)%20%22%3A%22%22)%20%2B%20undoItems%5Bi%5D.title)%3B%0A%09%09%09menuitem.setAttribute(%22accesskey%22%2C%20key)%3B%0A%09%09%09menuitem.setAttribute(%22oncommand%22%2C%20%22undoCloseTab(%22%20%2B%20i%20%2B%20%22)%3B%22)%3B%0A%09%09%7D%0A%09%09if%20(undoItems.length%20%3E%200)%0A%09%09%7B%0A%09%09%09this._popup.appendChild(document.createElement(%22menuseparator%22))%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20savedTabs%20%3D%20gPrefService.prefHasUserValue(this.mSavePref)%3B%0A%09%09menuitem%20%3D%20this._popup.appendChild(document.createElement(%22menuitem%22))%3B%0A%09%09menuitem.setAttribute(%22label%22%2C%20(savedTabs)%3F%22Restore%20Saved%20Window%22%3A%22Save%20Current%20Window%22)%3B%0A%09%09menuitem.setAttribute(%22accesskey%22%2C%20(savedTabs)%3F%22R%22%3A%22S%22)%3B%0A%09%09menuitem.setAttribute(%22oncommand%22%2C%20%22UndoCloseTabMenu.saveRestore(event)%3B%22)%3B%0A%09%09if%20(savedTabs)%0A%09%09%7B%0A%09%09%09menuitem.setAttribute(%22style%22%2C%20%22font-weight%3A%20bold%3B%22)%3B%0A%09%09%7D%0A%09%7D%2C%0A%0A%09saveRestore%3A%20function(aEvent)%0A%09%7B%0A%09%09if%20(gPrefService.prefHasUserValue(this.mSavePref))%0A%09%09%7B%0A%09%09%09var%20state%20%3D%20gPrefService.getCharPref(this.mSavePref)%3B%0A%09%09%09if%20(aEvent.ctrlKey)%0A%09%09%09%7B%0A%09%09%09%09var%20tabcount%20%3D%20gBrowser.mTabs.length%20%2B%20(eval(state).windows%5B0%5D.selected%20%7C%7C%201)%20-%201%3B%0A%09%09%09%7D%0A%09%09%09this.mSS.setWindowState(window%2C%20state%2C%20!aEvent.ctrlKey)%3B%0A%09%09%09if%20(aEvent.ctrlKey)%0A%09%09%09%7B%0A%09%09%09%09setTimeout(function(aTab)%20%7B%0A%09%09%09%09%09gBrowser.selectedTab%20%3D%20aTab%3B%0A%09%09%09%09%7D%2C%20100%2C%20gBrowser.mTabs%5Btabcount%5D)%3B%0A%09%09%09%7D%0A%09%09%09gPrefService.deleteBranch(this.mSavePref)%3B%0A%09%09%7D%0A%09%09else%0A%09%09%7B%0A%09%09%09gPrefService.setCharPref(this.mSavePref%2C%20%22(%22%20%2B%20this.mSS.getWindowState(window)%20%2B%20%22)%22)%3B%0A%09%09%7D%0A%09%7D%0A%7D%3B%0A%0Aif%20(Components.interfaces.nsISessionStore)%0A%7B%0A%09UndoCloseTabMenu.init()%3B%0A%09%0A%09getBrowser().undoRemoveTab%20%3D%20undoCloseTab%3B%0A%7D%0A">Undo Close Tab Menu</a> (moves the Recently Closed Tabs menu over to Tools for when you've hidden the History menu; and adds a one-shot session saving/restoring function)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Drag'n'Duplicate%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0AgBrowser.duplicateTab%20%3D%20function(aTab)%20%7B%0A%09var%20ss%20%3D%20Components.classes%5B%22%40mozilla.org%2Fbrowser%2Fsessionstore%3B1%22%5D.getService(Components.interfaces.nsISessionStore)%3B%0A%09var%20state%20%3D%20ss.getWindowState(aTab.ownerDocument.defaultView)%3B%0A%09state%20%3D%20eval(%22(%22%20%2B%20state%20%2B%20%22)%22)%3B%0A%09state.windows%5B0%5D.tabs%20%3D%20state.windows%5B0%5D.tabs.splice(aTab._tPos%2C%201)%3B%0A%09ss.setWindowState(window%2C%20state.toSource()%2C%20false)%3B%0A%09%0A%09return%20document.getAnonymousElementByAttribute(this%2C%20%22linkedpanel%22%2C%20this.mPanelContainer.lastChild.id)%3B%0A%7D%3B%0A%0AgBrowser.__preUC_onDrop%20%3D%20gBrowser.onDrop%3B%0AgBrowser.onDrop%20%3D%20function(aEvent%2C%20aXferData%2C%20aDragSession)%20%7B%0A%09if%20(aDragSession.sourceNode%20%26%26%20aDragSession.sourceNode.localName%20%3D%3D%20%22tab%22)%0A%09%7B%0A%09%09var%20oldTab%20%3D%20aDragSession.sourceNode%3B%0A%09%09if%20(aEvent.ctrlKey)%0A%09%09%7B%0A%09%09%09var%20tab%20%3D%20this.duplicateTab(oldTab)%3B%0A%09%09%09if%20(oldTab.parentNode%20!%3D%20this.mTabContainer)%0A%09%09%09%7B%0A%09%09%09%09this.selectedTab%20%3D%20tab%3B%0A%09%09%09%7D%0A%09%09%09this.moveTabTo(tab%2C%20this.getNewIndex(aEvent))%3B%0A%09%09%09return%3B%0A%09%09%7D%0A%09%09if%20(oldTab.parentNode%20!%3D%20this.mTabContainer)%0A%09%09%7B%0A%09%09%09this.selectedTab%20%3D%20this.duplicateTab(oldTab)%3B%0A%09%09%09this.moveTabTo(this.selectedTab%2C%20this.getNewIndex(aEvent))%3B%0A%09%09%09oldTab.ownerDocument.defaultView.gBrowser.removeTab(oldTab)%3B%0A%09%09%09window.focus()%3B%0A%09%09%09return%3B%0A%09%09%7D%0A%09%7D%0A%09gBrowser.__preUC_onDrop(aEvent%2C%20aXferData%2C%20aDragSession)%3B%0A%7D%3B%0A%0AgBrowser.__preUC_onDragOver%20%3D%20gBrowser.onDragOver%3B%0AgBrowser.onDragOver%20%3D%20function(aEvent%2C%20aFlavour%2C%20aDragSession)%20%7B%0A%09if%20(aDragSession.sourceNode%20%26%26%20aDragSession.sourceNode.localName%20%3D%3D%20%22tab%22%20%26%26%20aDragSession.sourceNode.parentNode%20!%3D%20this.mTabContainer)%0A%09%7B%0A%09%09aDragSession%20%3D%20%7B%20canDrop%3A%20aDragSession.canDrop%2C%20sourceNode%3A%20this.selectedTab%20%7D%3B%0A%09%7D%0A%09this.__preUC_onDragOver(aEvent%2C%20aFlavour%2C%20aDragSession)%3B%0A%7D%3B%0A">Drag'n'Duplicate</a> (allows to move tabs between windows and copy tabs through drag&drop; cf. Copy Dragged Tab)
Convenient access to userChrome.js (for Firefox, Thunderbird and possibly others)
<li><a href="data:text/javascript,var%20UserChromeJSEditor%20%3D%20%7B%0A%09init%3A%20function()%0A%09%7B%0A%09%09var%20menuitem%20%3D%20document.createElement(%22menuitem%22)%3B%0A%09%09menuitem.setAttribute(%22label%22%2C%20%22Edit%20userChrome.js%22)%3B%0A%09%09menuitem.setAttribute(%22accesskey%22%2C%20%22u%22)%3B%0A%09%09menuitem.setAttribute(%22oncommand%22%2C%20%22UserChromeJSEditor.open()%3B%22)%3B%0A%09%09%0A%09%09var%20optionsitem%20%3D%20document.getElementById(%22menu_preferences%22)%3B%0A%09%09optionsitem.parentNode.insertBefore(menuitem%2C%20optionsitem)%3B%0A%09%7D%2C%0A%0A%09open%3A%20function(aFileName%2C%20aAbsolutePath)%0A%09%7B%0A%09%09if%20(!aAbsolutePath)%0A%09%09%7B%0A%09%09%09var%20file%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Fdirectory_service%3B1%22%5D.getService(Components.interfaces.nsIProperties).get(%22UChrm%22%2C%20Components.interfaces.nsILocalFile)%3B%0A%09%09%09file.append(aFileName%20%7C%7C%20%22userChrome.js%22)%3B%0A%09%09%7D%0A%09%09else%0A%09%09%7B%0A%09%09%09file%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Flocal%3B1%22%5D.createInstance(Components.interfaces.nsILocalFile)%3B%0A%09%09%09file.initWithPath(aFilePath)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20info%20%3D%20Components.classes%5B%22%40mozilla.org%2Furiloader%2Fexternal-helper-app-service%3B1%22%5D.getService(Components.interfaces.nsIMIMEService).getFromTypeAndExtension(%22text%2Fplain%22%2C%20%22txt%22)%3B%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20editorPath%20%3D%20gPrefService.getCharPref(%22extensions.userchrome_js.editor%22)%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09var%20nsIFilePicker%20%3D%20Components.interfaces.nsIFilePicker%3B%0A%09%09%09var%20filePicker%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffilepicker%3B1%22%5D.createInstance(nsIFilePicker)%3B%0A%09%09%09%0A%09%09%09filePicker.init(window%2C%20%22Select%20userChrome.js%20editor%20path%22%2C%20nsIFilePicker.modeOpen)%3B%0A%09%09%09filePicker.appendFilters(nsIFilePicker.filterApps)%3B%0A%09%09%09%0A%09%09%09if%20(filePicker.show()%20!%3D%20nsIFilePicker.returnOK)%0A%09%09%09%7B%0A%09%09%09%09return%3B%0A%09%09%09%7D%0A%09%09%09%0A%09%09%09editorPath%20%3D%20filePicker.file.path%3B%0A%09%09%09gPrefService.setCharPref(%22extensions.userchrome_js.editor%22%2C%20editorPath)%3B%0A%09%09%7D%0A%09%09%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20editor%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Flocal%3B1%22%5D.createInstance(Components.interfaces.nsILocalFile)%3B%0A%09%09%09editor.initWithPath(editorPath)%3B%0A%09%09%09%0A%09%09%09info.preferredAction%20%3D%20info.useHelperApp%3B%0A%09%09%09info.preferredApplicationHandler%20%3D%20editor%3B%0A%09%09%09info.launchWithFile(file)%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09info.preferredAction%20%3D%20info.useSystemDefault%3B%0A%09%09%09info.launchWithFile(file)%3B%0A%09%09%7D%0A%09%7D%0A%7D%3B%0A%0AUserChromeJSEditor.init()%3B%0A">Tools menu entry to edit userChrome.js</a>
<li><a href="data:text/javascript,(function()%20%7B%0A%09var%20menuitem%20%3D%20document.createElement(%22menuitem%22)%3B%0A%09menuitem.setAttribute(%22label%22%2C%20%22Open%20'chrome'%20Folder%22)%3B%0A%09menuitem.setAttribute(%22accesskey%22%2C%20%22h%22)%3B%0A%09menuitem.setAttribute(%22oncommand%22%2C%20'Components.classes%5B%22%40mozilla.org%2Ffile%2Fdirectory_service%3B1%22%5D.getService(Components.interfaces.nsIProperties).get(%22UChrm%22%2C%20Components.interfaces.nsILocalFile).launch()%3B')%3B%0A%09%0A%09var%20optionsitem%20%3D%20document.getElementById(%22menu_preferences%22)%3B%0A%09optionsitem.parentNode.insertBefore(menuitem%2C%20optionsitem)%3B%0A%7D)()%3B%0A">Tools menu entry to open the chrome folder</a>
Snippets requiring other extensions (for Firefox 1.5)
<li>Undo Close Tab tab context menu item (requires Crash Recovery)
<li>Tab History for the context menu (requires Unified Back-/Forward Button)
<li>Customize address completion for [Shift]+[Enter]
Snippet collections by other authors
<li>A growing collection of snippets by the author of the ScrapBook extension
<li>Snippet collection from the MozillaZine Knowledge Base
<li>Snippets collected from this thread by Pirlouy
Revisions
~~ 0.8 (more info) ~~~~
<li>userChrome.js is now run for every chrome window, not just the main one
<li>Suggested for inclusion into one of the next Firefox versions (see bug 332529)
~~ 0.7 ~~~~
<li> Added support for most current Gecko applications
~~ 0.6 ~~~~
<li> The file userChrome.js is automatically created
~~ 0.5 ~~~~
<li> Initial release (2006-01-24)
What userChrome.css is for CSS customization, userChrome.js is for JavaScript. Simply edit the file userChrome.js (in the same place as userChrome.css) and its content will be run whenever a new browser window is opened (onLoad).
If you want this to become a standard part of Firefox in the future, go and vote for bug 332529 and/or contribute to the discussion about how to fix this...
Download
<a href="http://www.haslo.ch/zeniko/software/userchrome.js.xpi">userChrome.js 0.7</a>
This release should work for Firefox and Thunderbird 1.0 and newer, Mozilla Suite, SeaMonkey, Netscape and Netscape Browser, Nvu, Sunbird and Flock - about just as long as extensions can be installed.
In case you're using Firefox or Thunderbird 2.0 or any newer Mozilla application and want to run code in other windows than the main ones (without the WindowHook hack from below), get userChrome.js 0.8 instead.
Code Samples
Basics (should work for all applications):
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Sub-Script%2FXUL%20Loader%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0A%2F%2F%20automatically%20includes%20all%20files%20ending%20in%20.uc.js%20and%20.uc.xul%20from%20the%20profile's%20chrome%20folder%0A%0A(function()%20%7B%0A%09var%20getURLSpecFromFile%20%3D%20Components.classes%5B%22%40mozilla.org%2Fnetwork%2Fio-service%3B1%22%5D.getService(Components.interfaces.nsIIOService).getProtocolHandler(%22file%22).QueryInterface(Components.interfaces.nsIFileProtocolHandler).getURLSpecFromFile%3B%0A%09var%20chromeDir%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Fdirectory_service%3B1%22%5D.getService(Components.interfaces.nsIProperties).get(%22UChrm%22%2C%20Components.interfaces.nsILocalFile)%3B%0A%09var%20files%20%3D%20chromeDir.directoryEntries.QueryInterface(Components.interfaces.nsISimpleEnumerator)%3B%0A%09var%20xul_files%20%3D%20%5B%5D%3B%0A%09%0A%09while%20(files.hasMoreElements())%0A%09%7B%0A%09%09var%20file%20%3D%20files.getNext().QueryInterface(Components.interfaces.nsIFile)%3B%0A%09%09if%20(%2F%5C.uc%5C.js%24%2Fi.test(file.leafName))%0A%09%09%7B%0A%09%09%09setTimeout(function(aFile)%20%7B%0A%09%09%09%09Components.classes%5B%22%40mozilla.org%2Fmoz%2Fjssubscript-loader%3B1%22%5D.getService(Components.interfaces.mozIJSSubScriptLoader).loadSubScript(getURLSpecFromFile(aFile))%3B%0A%09%09%09%7D%2C%200%2C%20file)%3B%0A%09%09%7D%0A%09%09else%20if%20(%2F(%5EuserChrome%7C%5C.uc)%5C.xul%24%2Fi.test(file.leafName))%0A%09%09%7B%0A%09%09%09xul_files.push(file)%3B%0A%09%09%7D%0A%09%7D%0A%09%0A%09setTimeout(function()%20%7B%0A%09%09if%20(xul_files.length%20%3E%200)%0A%09%09%7B%0A%09%09%09document.loadOverlay(getURLSpecFromFile(xul_files.shift())%2C%20null)%3B%0A%09%09%09setTimeout(arguments.callee%2C%200)%3B%0A%09%09%7D%0A%09%7D%2C%200)%3B%0A%7D)()%3B%0A%0A">Sub-Script/XUL Loader</a> (automatically includes all scripts ending in .uc.js and .uc.xul from the profile's chrome folder - this allows you to keep your code snippets somewhat ordered)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20WindowHook%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0Avar%20WindowHook%20%3D%20%7B%0A%09observe%3A%20function(aSubject%2C%20aTopic%2C%20aData)%0A%09%7B%0A%09%09if%20(!aSubject._WindowHook)%0A%09%09%7B%0A%09%09%09aSubject._WindowHook%20%3D%20this%3B%0A%09%09%09aSubject.addEventListener(%22load%22%2C%20this.onLoad_window%2C%20false)%3B%0A%09%09%7D%0A%09%7D%2C%0A%0A%09onLoad_window%3A%20function()%0A%09%7B%0A%09%09this.removeEventListener(%22load%22%2C%20this._WindowHook.onLoad_window%2C%20false)%3B%0A%09%09var%20funcs%20%3D%20this._WindowHook.mFuncs%5Bthis.document.location.href%5D%20%7C%7C%20null%3B%0A%09%09if%20(funcs)%0A%09%09%7B%0A%09%09%09funcs.forEach(function(aFunc)%20%7B%20aFunc(this)%3B%20%7D%2C%20this)%3B%0A%09%09%7D%0A%09%09delete%20this._WindowHook%3B%0A%09%7D%2C%0A%0A%09register%3A%20function(aURL%2C%20aFunc)%0A%09%7B%0A%09%09if%20(!this.mFuncs)%0A%09%09%7B%0A%09%09%09this.mFuncs%20%3D%20%7B%7D%3B%0A%09%09%09Components.classes%5B%22%40mozilla.org%2Fobserver-service%3B1%22%5D.getService(Components.interfaces.nsIObserverService).addObserver(this%2C%20%22domwindowopened%22%2C%20false)%3B%0A%09%09%7D%0A%09%09if%20(!this.mFuncs%5BaURL%5D)%0A%09%09%7B%0A%09%09%09this.mFuncs%5BaURL%5D%20%3D%20%5B%5D%3B%0A%09%09%7D%0A%09%09this.mFuncs%5BaURL%5D.push(aFunc)%3B%0A%09%7D%0A%7D%3B%0A">WindowHook</a> (allows to target all windows / not only the main window)
Extension replacements (for Firefox 1.5 and 2.0)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Tabs%20to%20the%20Right%20(cf.%20Tabs%20Open%20Relative)%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0A(function()%20%7B%0A%09getBrowser().__uc_addedTabs%20%3D%200%3B%0A%09eval(%22gBrowser.addTab%20%3D%20%22%20%2B%20gBrowser.addTab.toString().replace(%2F%5C%7B%2F%2C%20%22%24%26%20var%20__oldTabPos%20%3D%20this.mCurrentTab._tPos%3B%22).replace(%2Freturn%20%2F%2C%20%22if%20(!blank)%20this.moveTabTo(t%2C%20__oldTabPos%20%2B%201%20%2B%20this.__uc_addedTabs%2B%2B)%3B%20%24%26%22))%3B%0A%09eval(%22gBrowser.moveTabTo%20%3D%20%22%20%2B%20gBrowser.moveTabTo.toString().replace(%2F%7B%2F%2C%20%22%24%26%20if%20(aTab%20%3D%3D%20this.mCurrentTab)%20this.__uc_addedTabs%20%3D%200%3B%22))%3B%0A%09gBrowser.mTabContainer.addEventListener(%22select%22%2C%20function()%20%7B%20gBrowser.__uc_addedTabs%20%3D%200%3B%20%7D%2C%20false)%3B%0A%7D)()%3B%0A">Tabs to the Right</a> (Tabs Open Relative light)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Drag'n'go%20(cf.%20Super%20DragAndGo)%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0AcontentAreaDNDObserver.onDragOver%20%3D%20function(aEvent%2C%20aFlavour%2C%20aDragSession)%20%7B%0A%09aEvent.target.setAttribute(%22dragover%22%2C%20%22true%22)%3B%0A%09%0A%09return%20(aDragSession.canDrop%20%3D%20true)%3B%0A%7D%3B%0A%0AcontentAreaDNDObserver.__preDnG_onDrop%20%3D%20contentAreaDNDObserver.onDrop%20%7C%7C%20null%3B%0AcontentAreaDNDObserver.onDrop%20%3D%20function(aEvent%2C%20aXferData%2C%20aDragSession)%20%7B%0A%09var%20url%20%3D%20(%2F%5E%5Cs*(.*%3F)%5Cs*%24%2Fm.test(aXferData.data))%3FRegExp.%241%3Anull%3B%0A%09if%20(!url)%0A%09%7B%0A%09%09this.__preDnG_onDrop(aEvent%2C%20aXferData%2C%20aDragSession)%3B%0A%09%09return%3B%0A%09%7D%0A%09aEvent.preventDefault()%3B%0A%09%0A%09if%20(%2F%5Efile%3A%5C%2F%7B3%7D(%3F%3A.*%5C%2F)%3F(.%2B%5C.xpi)%24%2F.test(url))%20%2F%2F%20local%20XPI%20-%3E%20installation%0A%09%7B%0A%09%09var%20xpinstallObj%20%3D%20%7B%7D%3B%0A%09%09xpinstallObj%5BRegExp.%241%5D%20%3D%20url%3B%0A%09%09%0A%09%09for%20(var%20i%20%3D%201%3B%20i%20%3C%20aDragSession.numDropItems%3B%20i%2B%2B)%0A%09%09%7B%20%2F%2F%20allow%20to%20install%20several%20extensions%20at%20once%0A%09%09%09if%20((url%20%3D%20this.__DnG_getDroppedURL(aDragSession%2C%20i))%20%26%26%20%2F%5Efile%3A%5C%2F%7B3%7D(%3F%3A.*%5C%2F)%3F(.%2B%5C.xpi)%24%2F.test(url))%0A%09%09%09%7B%0A%09%09%09%09xpinstallObj%5BRegExp.%241%5D%20%3D%20url%3B%0A%09%09%09%7D%0A%09%09%7D%0A%09%09%0A%09%09InstallTrigger.install(xpinstallObj)%3B%0A%09%09return%3B%0A%09%7D%0A%09%0A%09if%20(aDragSession.numDropItems%20%3D%3D%201%20%26%26%20!%2F%5Efile%3A%5C%2F%7B3%7D%7C%5Edata%3A.%2B%7C%5E(%3F!javascript%3A)%5CS*%3F((%3F%3A%5B%5Cw-%5D%5C.)%2B%5Cw%7B2%2C7%7D%7Clocalhost(%5B%3A%5C%2F%5D%7C%24))%5CS*%24%2F.test(url))%20%2F%2F%20text%20string%20-%3E%20web%20search%0A%09%7B%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20searchURL%20%3D%20gPrefService.getComplexValue(%22browser.search.defaulturl%22%2C%20Components.interfaces.nsIPrefLocalizedString).data%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09searchURL%20%3D%20%22http%3A%2F%2Fwww.google.com%2Fsearch%3Fq%3D%22%3B%0A%09%09%7D%0A%09%09url%20%3D%20searchURL%20%2B%20encodeURIComponent(url)%3B%0A%09%7D%0A%09else%20if%20(%2F%5Ettps%3F%3A%2F.test(url))%0A%09%7B%0A%09%09url%20%3D%20%22h%22%20%2B%20url%3B%0A%09%7D%0A%09%0A%09gBrowser.dragDropSecurityCheck(aEvent%2C%20aDragSession%2C%20url)%3B%0A%09%0A%09if%20(gBrowser.currentURI.spec%20%3D%3D%20%22about%3Ablank%22)%0A%09%7B%0A%09%09loadURI(url%2C%20null%2C%20null)%3B%0A%09%7D%0A%09else%0A%09%7B%0A%09%09var%20newTab%20%3D%20gBrowser.addTab(url%2C%20gBrowser.currentURI)%3B%0A%09%09if%20(getBoolPref(%22browser.tabs.loadInBackground%22)%20!%3D%20!(aEvent%20%26%26%20aEvent.shiftKey))%0A%09%09%7B%0A%09%09%09gBrowser.selectedTab%20%3D%20newTab%3B%0A%09%09%7D%0A%09%7D%0A%09%0A%09for%20(i%20%3D%201%3B%20i%20%3C%20aDragSession.numDropItems%3B%20i%2B%2B)%0A%09%7B%0A%09%09if%20((url%20%3D%20this.__DnG_getDroppedURL(aDragSession%2C%20i)))%0A%09%09%7B%0A%09%09%09gBrowser.dragDropSecurityCheck(aEvent%2C%20aDragSession%2C%20url)%3B%0A%09%09%09gBrowser.addTab(url%2C%20gBrowser.currentURI)%3B%0A%09%09%7D%0A%09%7D%0A%7D%3B%0A%0AcontentAreaDNDObserver.__preDnG_onDragStart%20%3D%20contentAreaDNDObserver.onDragStart%20%7C%7C%20null%3B%0AcontentAreaDNDObserver.onDragStart%20%3D%20function(aEvent%2C%20aXferData%2C%20aDragAction)%20%7B%0A%09var%20target%20%3D%20aEvent.originalTarget%3B%0A%09if%20(!(target%20instanceof%20HTMLImageElement%20%26%26%20target.src))%0A%09%7B%0A%09%09contentAreaDNDObserver.__preDnG_onDragStart(aEvent%2C%20aXferData%2C%20aDragAction)%3B%0A%09%09return%3B%0A%09%7D%0A%09for%20(var%20obj%20%3D%20target.parentNode%3B%20obj%20%26%26%20!obj.href%3B%20obj%20%3D%20obj.parentNode)%3B%0A%09%0A%09var%20url%20%3D%20(obj)%3Fobj.href%3Atarget.src%3B%0A%09var%20caption%20%3D%20((obj)%3Fobj.title%3Anull)%20%7C%7C%20target.title%20%7C%7C%20target.alt%20%7C%7C%20url.replace(%2F%5E.*%5C%2F%2F%2C%20%22%22)%20%7C%7C%20url%3B%0A%09%0A%09aXferData.data%20%3D%20new%20TransferData()%3B%0A%09aXferData.data.addDataForFlavour(%22text%2Fx-moz-url%22%2C%20url%20%2B%20%22%5Cn%22%20%2B%20caption)%3B%0A%09aXferData.data.addDataForFlavour(%22text%2Funicode%22%2C%20url)%3B%0A%09aXferData.data.addDataForFlavour(%22text%2Fhtml%22%2C%20'%3Ca%20href%3D%22'%20%2B%20url%20%2B%20'%22%3E'%20%2B%20caption%20%2B%20'%3C%2Fa%3E')%3B%0A%09%0A%09const%20nsIDragService%20%3D%20Components.interfaces.nsIDragService%3B%0A%09aDragAction.action%20%3D%20nsIDragService.DRAGDROP_ACTION_COPY%20%7C%20nsIDragService.DRAGDROP_ACTION_MOVE%20%7C%20nsIDragService.DRAGDROP_ACTION_LINK%3B%0A%7D%3B%0A%0AcontentAreaDNDObserver.__DnG_getDroppedURL%20%3D%20function(aDragSession%2C%20aIx)%20%7B%0A%09try%0A%09%7B%0A%09%09var%20xfer%20%3D%20Components.classes%5B%22%40mozilla.org%2Fwidget%2Ftransferable%3B1%22%5D.createInstance(Components.interfaces.nsITransferable)%3B%0A%09%09xfer.addDataFlavor(%22application%2Fx-moz-file%22%2C%20%22nsIFile%22)%3B%0A%09%09xfer.addDataFlavor(%22text%2Fx-moz-url%22)%3B%0A%09%09xfer.addDataFlavor(%22text%2Funicode%22)%3B%0A%09%09aDragSession.getData(xfer%2C%20aIx)%3B%0A%09%09%0A%09%09var%20flavour%20%3D%20%7B%7D%2C%20data%20%3D%20%7B%7D%2C%20length%20%3D%20%7B%7D%3B%0A%09%09xfer.getAnyTransferData(flavour%2C%20data%2C%20length)%3B%0A%09%09var%20xferData%20%3D%20new%20FlavourData(data.value%2C%20length.value%2C%20this.getSupportedFlavours().flavourTable%5Bflavour.value%5D)%3B%0A%09%09%0A%09%09return%20transferUtils.retrieveURLFromData(xferData.data%2C%20xferData.flavour.contentType)%3B%0A%09%7D%0A%09catch%20(ex)%0A%09%7B%0A%09%09return%20null%3B%0A%09%7D%0A%7D%3B%0A%0Aeval(%22nsDragAndDrop.checkCanDrop%20%3D%20%22%20%2B%20nsDragAndDrop.checkCanDrop.toString().replace(%22aEvent.target%22%2C%20%22%24%26%20%7C%7C%20this.mDragSession.sourceNode%20instanceof%20HTMLImageElement%22))%3B%0A%0AgetBrowser().addEventListener(%22dragover%22%2C%20function(aEvent)%20%7B%0A%09nsDragAndDrop.dragOver(aEvent%2C%20contentAreaDNDObserver)%3B%0A%7D%2C%20false)%3B%0AgBrowser.addEventListener(%22drop%22%2C%20function(aEvent)%20%7B%0A%09nsDragAndDrop.dragOver(aEvent%2C%20contentAreaDNDObserver)%3B%0A%7D%2C%20false)%3B%0AgBrowser.addEventListener(%22draggesture%22%2C%20function(aEvent)%20%7B%0A%09nsDragAndDrop.startDrag(aEvent%2C%20contentAreaDNDObserver)%3B%0A%7D%2C%20true)%3B%0A">Drag'n'go</a> (Super DragAndGo without UI)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20LaunchIE%20(cf.%20IE%20View)%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0Avar%20LaunchIE%20%3D%20%7B%0A%09mSchemes%3A%20%5B%22file%22%2C%20%22ftp%22%2C%20%22http%22%2C%20%22https%22%5D%2C%0A%0A%09init%3A%20function()%0A%09%7B%0A%09%09this.mItem%20%3D%20document.createElement(%22menuitem%22)%3B%0A%09%09this.mItem.setAttribute(%22label%22%2C%20%22LaunchIE%22)%3B%0A%09%09this.mItem.setAttribute(%22accesskey%22%2C%20%22u%22)%3B%0A%09%09%0A%09%09document.getElementById(%22contentAreaContextMenu%22).addEventListener(%22popupshowing%22%2C%20function()%20%7B%20LaunchIE.onPopupShowing(this)%3B%20%7D%2C%20false)%3B%0A%09%7D%2C%0A%0A%09onPopupShowing%3A%20function(aPopup)%0A%09%7B%0A%09%09aPopup.insertBefore(this.mItem%2C%20document.getElementById(%22context-sep-%22%20%2B%20((gContextMenu.onLink)%3F%22open%22%3A%22stop%22)))%3B%0A%09%09this.mItem.setAttribute(%22oncommand%22%2C%20%22LaunchIE.launch(%22%20%2B%20((gContextMenu.onLink)%3F%22gContextMenu.linkURI%22%3A%22gBrowser.currentURI%22)%20%2B%20%22)%3B%22)%3B%0A%09%09this.mItem.hidden%20%3D%20!gContextMenu.onLink%20%26%26%20(gContextMenu.isTextSelected%20%7C%7C%20gContextMenu.onImage%20%7C%7C%20gContextMenu.onTextInput)%3B%0A%09%09this.mItem.setAttribute(%22disabled%22%2C%20this.mItem.hidden%20%7C%7C%20!this.isSupported((gContextMenu.onLink)%3FgContextMenu.linkURI%3AgBrowser.currentURI))%3B%0A%09%7D%2C%0A%0A%09launch%3A%20function(aURI%2C%20aApp)%0A%09%7B%0A%09%09if%20(!this.isSupported(aURI))%0A%09%09%7B%0A%09%09%09throw%20new%20Error(%22LaunchIE%3A%20unsupported%20URI%20scheme%20'%22%20%2B%20aURI.scheme%20%2B%20%22'!%22)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20iexplore%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Flocal%3B1%22%5D.createInstance(Components.interfaces.nsILocalFile)%3B%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20regkey%20%3D%20Components.classes%5B%22%40mozilla.org%2Fwindows-registry-key%3B1%22%5D.createInstance(Components.interfaces.nsIWindowsRegKey)%3B%0A%09%09%09regkey.open(Components.interfaces.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE%2C%20%22SOFTWARE%5C%5CMicrosoft%5C%5CWindows%5C%5CCurrentVersion%5C%5CApp%20Paths%5C%5C%22%20%2B%20(aApp%20%7C%7C%20%22IEXPLORE.EXE%22)%2C%20Components.interfaces.nsIWindowsRegKey.ACCESS_READ)%3B%0A%09%09%09iexplore.initWithPath(regkey.readStringValue(%22%22))%3B%0A%09%09%09regkey.close()%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09iexplore.initWithPath((Components.classes%5B%22%40mozilla.org%2Fprocess%2Fenvironment%3B1%22%5D.getService(Components.interfaces.nsIEnvironment).get(%22PROGRAMFILES%22)%20%7C%7C%20%22C%3A%5C%5CProgram%20Files%22)%20%2B%20%22%5C%5CInternet%20Explorer%5C%5Ciexplore.exe%22)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20process%20%3D%20Components.classes%5B%22%40mozilla.org%2Fprocess%2Futil%3B1%22%5D.createInstance(Components.interfaces.nsIProcess)%3B%0A%09%09process.init(iexplore)%3B%0A%09%09process.run(false%2C%20%5BaURI.spec%5D%2C%201)%3B%0A%09%7D%2C%0A%0A%09isSupported%3A%20function(aURI)%0A%09%7B%0A%09%09return%20this.mSchemes.indexOf(aURI.scheme)%20%3E%20-1%3B%0A%09%7D%0A%7D%3B%0A%0ALaunchIE.init()%3B%0A">LaunchIE</a> (IEView without UI)
User interface enhancements (for Firefox 2.0)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Fashion%20Tabs%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0A(%7B%0A%09init%3A%20function()%0A%09%7B%0A%09%09Array.forEach(getBrowser().mTabs%2C%20function(aTab)%20%7B%0A%09%09%09aTab.linkedBrowser.addProgressListener(this)%3B%0A%09%09%7D%2C%20this)%3B%0A%09%09%0A%09%09gBrowser.addEventListener(%22TabOpen%22%2C%20this%2C%20false)%3B%0A%09%09gBrowser.addEventListener(%22TabSelect%22%2C%20this%2C%20false)%3B%0A%09%09gBrowser.addEventListener(%22TabMove%22%2C%20this%2C%20false)%3B%0A%09%09gBrowser.addEventListener(%22TabClose%22%2C%20this%2C%20false)%3B%0A%09%7D%2C%0A%0A%09handleEvent%3A%20function(aEvent)%0A%09%7B%0A%09%09var%20tab%20%3D%20aEvent.originalTarget%3B%0A%09%09%0A%09%09switch%20(aEvent.type)%0A%09%09%7B%0A%09%09case%20%22TabOpen%22%3A%0A%09%09%09tab.linkedBrowser.addProgressListener(this)%3B%0A%09%09%09break%3B%0A%09%09case%20%22TabMove%22%3A%0A%09%09case%20%22TabSelect%22%3A%0A%09%09%09this.colorizeTab(tab)%3B%0A%09%09%09break%3B%0A%09%09case%20%22TabClose%22%3A%0A%09%09%09tab.linkedBrowser.removeProgressListener(this)%3B%0A%09%09%09break%3B%0A%09%09%7D%0A%09%7D%2C%0A%0A%09onLocationChange%3A%20function(aProgress%2C%20aRequest%2C%20aURI)%20%7B%0A%09%09var%20doc%20%3D%20aProgress.DOMWindow.document%3B%0A%09%09var%20tab%20%3D%20gBrowser.mTabs%5BgBrowser.getBrowserIndexForDocument(doc)%5D%3B%0A%09%09%0A%09%09this.colorizeTab(tab)%3B%0A%09%7D%2C%0A%0A%09onStateChange%3A%20function()%20%7B%20%7D%2C%0A%09onProgressChange%3A%20function()%20%7B%20%7D%2C%0A%09onStatusChange%3A%20function()%20%7B%20%7D%2C%0A%09onSecurityChange%3A%20function()%20%7B%20%7D%2C%0A%09onLinkIconAvailable%3A%20function()%20%7B%20%7D%2C%0A%0A%09colorizeTab%3A%20function(aTab)%0A%09%7B%0A%09%09function%20djb2hash(aString)%0A%09%09%7B%0A%09%09%09var%20hashvalue%20%3D%205381%3B%0A%09%09%09for%20(var%20i%20%3D%200%3B%20i%20%3C%20aString.length%3B%20i%2B%2B)%0A%09%09%09%7B%0A%09%09%09%09hashvalue%20%3D%20((hashvalue%20%3C%3C%205)%20%2B%20hashvalue)%20%2B%20aString.charCodeAt(i)%3B%0A%09%09%09%7D%0A%09%09%09return%20hashvalue%3B%0A%09%09%7D%0A%09%09%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20host%20%3D%20aTab.linkedBrowser.currentURI.host%3B%0A%09%09%7D%0A%09%09catch%20(ex)%20%7B%20%7D%0A%09%09%0A%09%09if%20(host%20%26%26%20host%20!%3D%20%22about%3Ablank%22)%0A%09%09%7B%0A%09%09%09var%20hue%20%3D%20djb2hash(host.replace(%2F%5Ewww%5C.(%3F%3D.%2B%5C..)%2F%2C%20%22%22))%20%25%20360%3B%0A%09%09%7D%0A%09%09var%20color%20%3D%20(hue)%3F%22hsl(%22%20%2B%20hue%20%2B%20%22%2C%2050%25%2C%2050%25)%22%3Anull%3B%0A%09%09%0A%09%09Array.forEach(aTab.ownerDocument.getAnonymousNodes(aTab)%2C%20function(aNode)%20%7B%0A%09%09%09aNode.style.backgroundColor%20%3D%20color%3B%0A%09%09%7D)%3B%0A%09%09%0A%09%09if%20(gBrowser.selectedTab%20%3D%3D%20aTab)%0A%09%09%7B%0A%09%09%09var%20node%20%3D%20aTab.ownerDocument.getAnonymousElementByAttribute(aTab.parentNode%2C%20%22class%22%2C%20%22tabs-bottom%22)%3B%0A%09%09%09if%20(color)%0A%09%09%09%09node.setAttribute(%22style%22%2C%20%22background-color%3A%20%22%20%2B%20color%20%2B%20%22%20!important%22)%3B%0A%09%09%09else%0A%09%09%09%09node.removeAttribute(%22style%22)%3B%0A%09%09%7D%0A%09%7D%2C%0A%0A%09QueryInterface%3A%20function(aIID)%20%7B%0A%09%09var%20Ci%20%3D%20Components.interfaces%3B%0A%09%09if%20(!%5BCi.nsIDOMEventListener%2C%20Ci.nsIWebProgressListener%2C%20Ci.nsISupportsWeakReference%2C%20Ci.nsISupports%5D.some(aIID.equals))%0A%09%09%7B%0A%09%09%09throw%20Components.results.NS_NOINTERFACE%3B%0A%09%09%7D%0A%09%09return%20this%3B%0A%09%7D%0A%7D).init()%3B%0A">Fashion Tabs</a> (Chromatabs lite; only tested with the default theme under Windows)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Undo%20Close%20Tab%20Menu%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0Avar%20UndoCloseTabMenu%20%3D%20%7B%0A%09mSavePref%3A%20%22extensions.userchrome_js.uctm_state%22%2C%0A%0A%09init%3A%20function()%0A%09%7B%0A%09%09this.mSS%20%3D%20Components.classes%5B%22%40mozilla.org%2Fbrowser%2Fsessionstore%3B1%22%5D.getService(Components.interfaces.nsISessionStore)%3B%0A%09%09%0A%09%09var%20dts%20%3D%20document.getElementById(%22devToolsSeparator%22)%3B%0A%09%09var%20menu%20%3D%20dts.parentNode.insertBefore(document.createElement(%22menu%22)%2C%20dts.parentNode.firstChild)%3B%0A%09%09%0A%09%09menu.setAttribute(%22label%22%2C%20%22Undo%20Close%20Tab%22)%3B%0A%09%09menu.setAttribute(%22accesskey%22%2C%20%22U%22)%3B%0A%09%09%0A%09%09this._popup%20%3D%20menu.appendChild(document.createElement(%22menupopup%22))%3B%0A%09%09this._popup.setAttribute(%22onpopupshowing%22%2C%20%22UndoCloseTabMenu.onPopupShowing()%3B%22)%3B%0A%09%7D%2C%0A%0A%09onPopupShowing%3A%20function()%0A%09%7B%0A%09%09while%20(this._popup.hasChildNodes())%0A%09%09%7B%0A%09%09%09this._popup.removeChild(this._popup.lastChild)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20undoItems%20%3D%20eval(%22(%22%20%2B%20this.mSS.getClosedTabData(window)%20%2B%20%22)%22)%3B%0A%09%09for%20(var%20i%20%3D%200%3B%20i%20%3C%20undoItems.length%3B%20i%2B%2B)%0A%09%09%7B%0A%09%09%09var%20key%20%3D%20(i%20%3C%209)%3Fi%20%2B%201%3A(i%20%3D%3D%209)%3F%220%22%3A%22%22%3B%0A%09%09%09var%20menuitem%20%3D%20this._popup.appendChild(document.createElement(%22menuitem%22))%3B%0A%09%09%09menuitem.setAttribute(%22label%22%2C%20((key)%3Fkey%20%2B%20%22)%20%22%3A%22%22)%20%2B%20undoItems%5Bi%5D.title)%3B%0A%09%09%09menuitem.setAttribute(%22accesskey%22%2C%20key)%3B%0A%09%09%09menuitem.setAttribute(%22oncommand%22%2C%20%22undoCloseTab(%22%20%2B%20i%20%2B%20%22)%3B%22)%3B%0A%09%09%7D%0A%09%09if%20(undoItems.length%20%3E%200)%0A%09%09%7B%0A%09%09%09this._popup.appendChild(document.createElement(%22menuseparator%22))%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20savedTabs%20%3D%20gPrefService.prefHasUserValue(this.mSavePref)%3B%0A%09%09menuitem%20%3D%20this._popup.appendChild(document.createElement(%22menuitem%22))%3B%0A%09%09menuitem.setAttribute(%22label%22%2C%20(savedTabs)%3F%22Restore%20Saved%20Window%22%3A%22Save%20Current%20Window%22)%3B%0A%09%09menuitem.setAttribute(%22accesskey%22%2C%20(savedTabs)%3F%22R%22%3A%22S%22)%3B%0A%09%09menuitem.setAttribute(%22oncommand%22%2C%20%22UndoCloseTabMenu.saveRestore(event)%3B%22)%3B%0A%09%09if%20(savedTabs)%0A%09%09%7B%0A%09%09%09menuitem.setAttribute(%22style%22%2C%20%22font-weight%3A%20bold%3B%22)%3B%0A%09%09%7D%0A%09%7D%2C%0A%0A%09saveRestore%3A%20function(aEvent)%0A%09%7B%0A%09%09if%20(gPrefService.prefHasUserValue(this.mSavePref))%0A%09%09%7B%0A%09%09%09var%20state%20%3D%20gPrefService.getCharPref(this.mSavePref)%3B%0A%09%09%09if%20(aEvent.ctrlKey)%0A%09%09%09%7B%0A%09%09%09%09var%20tabcount%20%3D%20gBrowser.mTabs.length%20%2B%20(eval(state).windows%5B0%5D.selected%20%7C%7C%201)%20-%201%3B%0A%09%09%09%7D%0A%09%09%09this.mSS.setWindowState(window%2C%20state%2C%20!aEvent.ctrlKey)%3B%0A%09%09%09if%20(aEvent.ctrlKey)%0A%09%09%09%7B%0A%09%09%09%09setTimeout(function(aTab)%20%7B%0A%09%09%09%09%09gBrowser.selectedTab%20%3D%20aTab%3B%0A%09%09%09%09%7D%2C%20100%2C%20gBrowser.mTabs%5Btabcount%5D)%3B%0A%09%09%09%7D%0A%09%09%09gPrefService.deleteBranch(this.mSavePref)%3B%0A%09%09%7D%0A%09%09else%0A%09%09%7B%0A%09%09%09gPrefService.setCharPref(this.mSavePref%2C%20%22(%22%20%2B%20this.mSS.getWindowState(window)%20%2B%20%22)%22)%3B%0A%09%09%7D%0A%09%7D%0A%7D%3B%0A%0Aif%20(Components.interfaces.nsISessionStore)%0A%7B%0A%09UndoCloseTabMenu.init()%3B%0A%09%0A%09getBrowser().undoRemoveTab%20%3D%20undoCloseTab%3B%0A%7D%0A">Undo Close Tab Menu</a> (moves the Recently Closed Tabs menu over to Tools for when you've hidden the History menu; and adds a one-shot session saving/restoring function)
<li><a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20Drag'n'Duplicate%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0AgBrowser.duplicateTab%20%3D%20function(aTab)%20%7B%0A%09var%20ss%20%3D%20Components.classes%5B%22%40mozilla.org%2Fbrowser%2Fsessionstore%3B1%22%5D.getService(Components.interfaces.nsISessionStore)%3B%0A%09var%20state%20%3D%20ss.getWindowState(aTab.ownerDocument.defaultView)%3B%0A%09state%20%3D%20eval(%22(%22%20%2B%20state%20%2B%20%22)%22)%3B%0A%09state.windows%5B0%5D.tabs%20%3D%20state.windows%5B0%5D.tabs.splice(aTab._tPos%2C%201)%3B%0A%09ss.setWindowState(window%2C%20state.toSource()%2C%20false)%3B%0A%09%0A%09return%20document.getAnonymousElementByAttribute(this%2C%20%22linkedpanel%22%2C%20this.mPanelContainer.lastChild.id)%3B%0A%7D%3B%0A%0AgBrowser.__preUC_onDrop%20%3D%20gBrowser.onDrop%3B%0AgBrowser.onDrop%20%3D%20function(aEvent%2C%20aXferData%2C%20aDragSession)%20%7B%0A%09if%20(aDragSession.sourceNode%20%26%26%20aDragSession.sourceNode.localName%20%3D%3D%20%22tab%22)%0A%09%7B%0A%09%09var%20oldTab%20%3D%20aDragSession.sourceNode%3B%0A%09%09if%20(aEvent.ctrlKey)%0A%09%09%7B%0A%09%09%09var%20tab%20%3D%20this.duplicateTab(oldTab)%3B%0A%09%09%09if%20(oldTab.parentNode%20!%3D%20this.mTabContainer)%0A%09%09%09%7B%0A%09%09%09%09this.selectedTab%20%3D%20tab%3B%0A%09%09%09%7D%0A%09%09%09this.moveTabTo(tab%2C%20this.getNewIndex(aEvent))%3B%0A%09%09%09return%3B%0A%09%09%7D%0A%09%09if%20(oldTab.parentNode%20!%3D%20this.mTabContainer)%0A%09%09%7B%0A%09%09%09this.selectedTab%20%3D%20this.duplicateTab(oldTab)%3B%0A%09%09%09this.moveTabTo(this.selectedTab%2C%20this.getNewIndex(aEvent))%3B%0A%09%09%09oldTab.ownerDocument.defaultView.gBrowser.removeTab(oldTab)%3B%0A%09%09%09window.focus()%3B%0A%09%09%09return%3B%0A%09%09%7D%0A%09%7D%0A%09gBrowser.__preUC_onDrop(aEvent%2C%20aXferData%2C%20aDragSession)%3B%0A%7D%3B%0A%0AgBrowser.__preUC_onDragOver%20%3D%20gBrowser.onDragOver%3B%0AgBrowser.onDragOver%20%3D%20function(aEvent%2C%20aFlavour%2C%20aDragSession)%20%7B%0A%09if%20(aDragSession.sourceNode%20%26%26%20aDragSession.sourceNode.localName%20%3D%3D%20%22tab%22%20%26%26%20aDragSession.sourceNode.parentNode%20!%3D%20this.mTabContainer)%0A%09%7B%0A%09%09aDragSession%20%3D%20%7B%20canDrop%3A%20aDragSession.canDrop%2C%20sourceNode%3A%20this.selectedTab%20%7D%3B%0A%09%7D%0A%09this.__preUC_onDragOver(aEvent%2C%20aFlavour%2C%20aDragSession)%3B%0A%7D%3B%0A">Drag'n'Duplicate</a> (allows to move tabs between windows and copy tabs through drag&drop; cf. Copy Dragged Tab)
Convenient access to userChrome.js (for Firefox, Thunderbird and possibly others)
<li><a href="data:text/javascript,var%20UserChromeJSEditor%20%3D%20%7B%0A%09init%3A%20function()%0A%09%7B%0A%09%09var%20menuitem%20%3D%20document.createElement(%22menuitem%22)%3B%0A%09%09menuitem.setAttribute(%22label%22%2C%20%22Edit%20userChrome.js%22)%3B%0A%09%09menuitem.setAttribute(%22accesskey%22%2C%20%22u%22)%3B%0A%09%09menuitem.setAttribute(%22oncommand%22%2C%20%22UserChromeJSEditor.open()%3B%22)%3B%0A%09%09%0A%09%09var%20optionsitem%20%3D%20document.getElementById(%22menu_preferences%22)%3B%0A%09%09optionsitem.parentNode.insertBefore(menuitem%2C%20optionsitem)%3B%0A%09%7D%2C%0A%0A%09open%3A%20function(aFileName%2C%20aAbsolutePath)%0A%09%7B%0A%09%09if%20(!aAbsolutePath)%0A%09%09%7B%0A%09%09%09var%20file%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Fdirectory_service%3B1%22%5D.getService(Components.interfaces.nsIProperties).get(%22UChrm%22%2C%20Components.interfaces.nsILocalFile)%3B%0A%09%09%09file.append(aFileName%20%7C%7C%20%22userChrome.js%22)%3B%0A%09%09%7D%0A%09%09else%0A%09%09%7B%0A%09%09%09file%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Flocal%3B1%22%5D.createInstance(Components.interfaces.nsILocalFile)%3B%0A%09%09%09file.initWithPath(aFilePath)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20info%20%3D%20Components.classes%5B%22%40mozilla.org%2Furiloader%2Fexternal-helper-app-service%3B1%22%5D.getService(Components.interfaces.nsIMIMEService).getFromTypeAndExtension(%22text%2Fplain%22%2C%20%22txt%22)%3B%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20editorPath%20%3D%20gPrefService.getCharPref(%22extensions.userchrome_js.editor%22)%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09var%20nsIFilePicker%20%3D%20Components.interfaces.nsIFilePicker%3B%0A%09%09%09var%20filePicker%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffilepicker%3B1%22%5D.createInstance(nsIFilePicker)%3B%0A%09%09%09%0A%09%09%09filePicker.init(window%2C%20%22Select%20userChrome.js%20editor%20path%22%2C%20nsIFilePicker.modeOpen)%3B%0A%09%09%09filePicker.appendFilters(nsIFilePicker.filterApps)%3B%0A%09%09%09%0A%09%09%09if%20(filePicker.show()%20!%3D%20nsIFilePicker.returnOK)%0A%09%09%09%7B%0A%09%09%09%09return%3B%0A%09%09%09%7D%0A%09%09%09%0A%09%09%09editorPath%20%3D%20filePicker.file.path%3B%0A%09%09%09gPrefService.setCharPref(%22extensions.userchrome_js.editor%22%2C%20editorPath)%3B%0A%09%09%7D%0A%09%09%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20editor%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Flocal%3B1%22%5D.createInstance(Components.interfaces.nsILocalFile)%3B%0A%09%09%09editor.initWithPath(editorPath)%3B%0A%09%09%09%0A%09%09%09info.preferredAction%20%3D%20info.useHelperApp%3B%0A%09%09%09info.preferredApplicationHandler%20%3D%20editor%3B%0A%09%09%09info.launchWithFile(file)%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09info.preferredAction%20%3D%20info.useSystemDefault%3B%0A%09%09%09info.launchWithFile(file)%3B%0A%09%09%7D%0A%09%7D%0A%7D%3B%0A%0AUserChromeJSEditor.init()%3B%0A">Tools menu entry to edit userChrome.js</a>
<li><a href="data:text/javascript,(function()%20%7B%0A%09var%20menuitem%20%3D%20document.createElement(%22menuitem%22)%3B%0A%09menuitem.setAttribute(%22label%22%2C%20%22Open%20'chrome'%20Folder%22)%3B%0A%09menuitem.setAttribute(%22accesskey%22%2C%20%22h%22)%3B%0A%09menuitem.setAttribute(%22oncommand%22%2C%20'Components.classes%5B%22%40mozilla.org%2Ffile%2Fdirectory_service%3B1%22%5D.getService(Components.interfaces.nsIProperties).get(%22UChrm%22%2C%20Components.interfaces.nsILocalFile).launch()%3B')%3B%0A%09%0A%09var%20optionsitem%20%3D%20document.getElementById(%22menu_preferences%22)%3B%0A%09optionsitem.parentNode.insertBefore(menuitem%2C%20optionsitem)%3B%0A%7D)()%3B%0A">Tools menu entry to open the chrome folder</a>
Snippets requiring other extensions (for Firefox 1.5)
<li>Undo Close Tab tab context menu item (requires Crash Recovery)
<li>Tab History for the context menu (requires Unified Back-/Forward Button)
<li>Customize address completion for [Shift]+[Enter]
Snippet collections by other authors
<li>A growing collection of snippets by the author of the ScrapBook extension
<li>Snippet collection from the MozillaZine Knowledge Base
<li>Snippets collected from this thread by Pirlouy
Revisions
~~ 0.8 (more info) ~~~~
<li>userChrome.js is now run for every chrome window, not just the main one
<li>Suggested for inclusion into one of the next Firefox versions (see bug 332529)
~~ 0.7 ~~~~
<li> Added support for most current Gecko applications
~~ 0.6 ~~~~
<li> The file userChrome.js is automatically created
~~ 0.5 ~~~~
<li> Initial release (2006-01-24)
Last edited by old zeniko on September 7th, 2007, 9:16 am, edited 38 times in total.
-
- Posts: 2031
- Joined: February 6th, 2004, 11:59 am
- dougeeebear
- Posts: 548
- Joined: September 15th, 2005, 4:17 pm
-
- Posts: 103
- Joined: August 15th, 2005, 12:55 am
- Location: Finland
Works with Bon Echo also, at least Drag'n'go. Thanks.
(quick hack into Super DrangAndGo 2.4d1 didn't work.)
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20060325 Firefox/2.0a1 - Build ID: 2006032506
(quick hack into Super DrangAndGo 2.4d1 didn't work.)
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8) Gecko/20060325 Firefox/2.0a1 - Build ID: 2006032506
-
- Posts: 0
- Joined: December 31st, 1969, 5:00 pm
dougeeebear wrote:Out of curiosity, what's the difference between this and user.js?
user.js just describes what preferences should be overwritten at start. It (and also prefs.js) may look like JavaScript files (and once were), but are plain configuration files now. In contrast, userChrome.js is mainly aimed at UI modifications (see the Code Samples section in the first post).
cyberrus wrote:but is it somehow better then GreaseMonkey?
GreaseMonkey targets website content, while userChrome.js targets the browser chrome (i.e. GreaseMonkey is what userContent.js could have been). Have a look at the Code Samples section in the first post for an idea what this extension might be for.
- dougeeebear
- Posts: 548
- Joined: September 15th, 2005, 4:17 pm
-
- Posts: 0
- Joined: December 31st, 1969, 5:00 pm
-
- Posts: 2031
- Joined: February 6th, 2004, 11:59 am
if this http://forums.mozillazine.org/viewtopic.php?t=350714 the story will get even better
-
- Posts: 2031
- Joined: February 6th, 2004, 11:59 am
Re: userChrome.js
zeniko wrote:<li> <a href="data:text/javascript,%2F*%20%3A%3A%3A%3A%3A%3A%3A%3A%20LaunchIE%20(cf.%20IE%20View)%20%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%3A%20*%2F%0A%0Avar%20LaunchIE%20%3D%20%7B%0A%09mSchemes%3A%20%5B%22file%22%2C%20%22ftp%22%2C%20%22http%22%2C%20%22https%22%5D%2C%0A%0A%09init%3A%20function()%0A%09%7B%0A%09%09this.mItem%20%3D%20document.createElement(%22menuitem%22)%3B%0A%09%09this.mItem.setAttribute(%22label%22%2C%20%22LaunchIE%22)%3B%0A%09%09this.mItem.setAttribute(%22accesskey%22%2C%20%22u%22)%3B%0A%09%09%0A%09%09document.getElementById(%22contentAreaContextMenu%22).addEventListener(%22popupshowing%22%2C%20function()%20%7B%20LaunchIE.onPopupShowing(this)%3B%20%7D%2C%20false)%3B%0A%09%7D%2C%0A%0A%09onPopupShowing%3A%20function(aPopup)%0A%09%7B%0A%09%09aPopup.insertBefore(this.mItem%2C%20document.getElementById(%22context-sep-%22%20%2B%20((gContextMenu.onLink)%3F%22open%22%3A%22stop%22)))%3B%0A%09%09this.mItem.setAttribute(%22oncommand%22%2C%20%22LaunchIE.launch(%22%20%2B%20((gContextMenu.onLink)%3F%22gContextMenu.linkURI%22%3A%22gBrowser.currentURI%22)%20%2B%20%22)%3B%22)%3B%0A%09%09this.mItem.hidden%20%3D%20!gContextMenu.onLink%20%26%26%20(gContextMenu.isTextSelected%20%7C%7C%20gContextMenu.onImage%20%7C%7C%20gContextMenu.onTextInput)%3B%0A%09%09this.mItem.setAttribute(%22disabled%22%2C%20this.mItem.hidden%20%7C%7C%20!this.isSupported((gContextMenu.onLink)%3FgContextMenu.linkURI%3AgBrowser.currentURI))%3B%0A%09%7D%2C%0A%0A%09launch%3A%20function(aURI%2C%20aApp)%0A%09%7B%0A%09%09if%20(!this.isSupported(aURI))%0A%09%09%7B%0A%09%09%09throw%20new%20Error(%22LauchIE%3A%20unsupported%20URI%20scheme%20'%22%20%2B%20aURI.scheme%20%2B%20%22'!%22)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20iexplore%20%3D%20Components.classes%5B%22%40mozilla.org%2Ffile%2Flocal%3B1%22%5D.createInstance(Components.interfaces.nsILocalFile)%3B%0A%09%09try%0A%09%09%7B%0A%09%09%09var%20regkey%20%3D%20Components.classes%5B%22%40mozilla.org%2Fwindows-registry-key%3B1%22%5D.createInstance(Components.interfaces.nsIWindowsRegKey)%3B%0A%09%09%09regkey.open(Components.interfaces.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE%2C%20%22SOFTWARE%5C%5CMicrosoft%5C%5CWindows%5C%5CCurrentVersion%5C%5CApp%20Paths%5C%5C%22%20%2B%20(aApp%20%7C%7C%20%22IEXPLORE.EXE%22)%2C%20Components.interfaces.nsIWindowsRegKey.ACCESS_READ)%3B%0A%09%09%09iexplore.initWithPath(regkey.readStringValue(%22%22))%3B%0A%09%09%09regkey.close()%3B%0A%09%09%7D%0A%09%09catch%20(ex)%0A%09%09%7B%0A%09%09%09iexplore.initWithPath((Components.classes%5B%22%40mozilla.org%2Fprocess%2Fenvironment%3B1%22%5D.getService(Components.interfaces.nsIEnvironment).get(%22PROGRAMFILES%22)%20%7C%7C%20%22C%3A%5C%5CProgram%20Files%22)%20%2B%20%22%5C%5CInternet%20Explorer%5C%5Ciexplore.exe%22)%3B%0A%09%09%7D%0A%09%09%0A%09%09var%20process%20%3D%20Components.classes%5B%22%40mozilla.org%2Fprocess%2Futil%3B1%22%5D.createInstance(Components.interfaces.nsIProcess)%3B%0A%09%09process.init(iexplore)%3B%0A%09%09process.run(false%2C%20%5BaURI.spec%5D%2C%201)%3B%0A%09%7D%2C%0A%0A%09isSupported%3A%20function(aURI)%0A%09%7B%0A%09%09return%20this.mSchemes.indexOf(aURI.scheme)%20%3E%20-1%3B%0A%09%7D%0A%7D%3B%0A%0ALaunchIE.init()%3B%0A">LaunchIE</a> (IEView without UI)
for anyone who wants to differentiate between opening the target OR current tab/window
~line 20
this.mItem.setAttribute("oncommand", "LaunchIE.launch(" + ((gContextMenu.onLink)?"gContextMenu.linkURI":"gBrowser.currentURI") + ");");
ieLabel = (gContextMenu.onLink) ? "LaunchIE for Target" : "LaunchIE for Tab";
this.mItem.setAttribute("label", ieLabel);
-
- Posts: 2225
- Joined: November 9th, 2004, 6:45 pm
- Location: Jakarta, Indonesia (UTC+7)
- Contact:
I gotta love this extension.
Usually I use Contextmenu Extensions to execute custom scripts automatically at browser startup, but sometimes it doesn't work.
Good work

- dougeeebear
- Posts: 548
- Joined: September 15th, 2005, 4:17 pm
- dougeeebear
- Posts: 548
- Joined: September 15th, 2005, 4:17 pm
userChrome.css allows you to call other .css files using @import url.
Will userChrome.js allow calling other .js files in some manner?
Also I'm thinking I might be able to make use of some of the scripts at http://userscripts.org/
Will userChrome.js allow calling other .js files in some manner?
Also I'm thinking I might be able to make use of some of the scripts at http://userscripts.org/
Last edited by dougeeebear on March 26th, 2006, 12:23 pm, edited 1 time in total.
-
- Posts: 2225
- Joined: November 9th, 2004, 6:45 pm
- Location: Jakarta, Indonesia (UTC+7)
- Contact: