почистит папку startupCache
Помогло. Спасибо.
Отсутствует
В 113.0.1 у меня поломалось что-то.НЕ показывает, т.е нет инфы с правой стороны:
Кнопку использую эту: №161 Memory Monitor+Minimize memory
custombutton://%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0D%0A%3Ccustombutton%20xmlns%3Acb%3D%22http%3A//xsms.nm.ru/custombuttons/%22%3E%0A%20%20%3Cname%3E%u041F%u0430%u043C%u044F%u0442%u044C%20%u0432%20%u0430%u0434%u0440%u0435%u0441%u043D%u043E%u0439%20%u0441%u0442%u0440%u043E%u043A%u0435%3C/name%3E%0A%20%20%3Cimage%3E%3C%21%5BCDATA%5Bdata%3Aimage/png%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADHklEQVQ4jYWTXUxTBxiG32hn62h1GLASoWoY+JNaZBtLmIMjyyKixLgEspEFkJZNHDHOAdmBU6RkUZzZsmK1+EOyOspAQ92QpjhbEEaUSmLXru4s4WLdxSgmrhCdEGSL7640ahb23L3J99w9H/AsiwBoHo9dOcu+fydvuQuAGoAKQBwWQvMiCps/TPo9WbvYBEDnatHOXTu7nnm5b1w/3NQUliRpHEDO895qnVYhAtiSrV9yfP7mBnY0Jz9am6z1W1v2/3Pj+jDn5h7yMXa7PaZUKnc9sVNWKmvv/5hBW03Cg7ffXHe343Q9f/BcYiTyG/+amefM7BxjsRgnJyc5MTHBWCxGq9X6QKlUFgAA9giaDu/pjfzmjJnBn3/h1PQsp6bvMRqdZCQS4fj4OGVZZjgcZjAYZCAQoCzLrK+vn1IoFNmo3K0ZFvfn0uH8jtFolLIsMxQKMRAIcGxsjKOjoxwZGeHQ0BB9Ph99Ph8HBgbo8XgoCEIIB4rUv3aek9jy+Rd0Op30+/0cHByk1+tlf38/3W43+/r66Ha76XL1sK2tjQ1SIz+pqWP+9u1/wlyx4u6pryT2X/GyurqaXV1d7O3tZU9PD10uF7u7u2m32ylJZlZVVbGy8gOWFO+guaGGpWVlf0DYovK+/kraja8d52mz2Wg0Gtne3s7W1laKokiTyUSj0cjSchMls4W1dSI9J1LZeXQjl7208ksAUAJQZ2VlDTscDoqiyMLCQpaX72Vp+T42NR+hubGR5ywZPLRXP5+UpGsr2Kq5PDW4mZkblhx9uoc1giCELRYLKyqMtDSZeeTQqywrKXik12++9e1nKXd+6kyfB/AyACF6xcCPihN8z0eVmpaWdnNb3luzBoM+PHBq7f1rZ1L/BrAzP1ttDXVtIoAMQ7qq4c5VA3XaFz7+z6IBpANQ5b0W1/7Qn8nlmkW1+4oSnOeb18wASDj4buKtk5/q7gFIWvA3SnbEO29f2EQA+ccPro4ceC9xCEDcqkTFMZUC2xaUAShsdSm3Lx5bNw1gVW5mnEcbv7jk/6SnWfp+fnwwJ1NtX+joXwJBlDIWFgabAAAAAElFTkSuQmCC%5D%5D%3E%3C/image%3E%0A%20%20%3Cmode%3E0%3C/mode%3E%0A%20%20%3Cinitcode%3E%3C%21%5BCDATA%5B%28function%20%28%29%20%7B%0A%20%20%20if%20%28%20document.getElementById%28%27memoryDisplay%27%29%20%29%20return%3B%0A%20%20%20%20%0A%20%20%20//%20%u0421%u043E%u0437%u0434%u0430%u0442%u044C%20%u0432%20%u0430%u0434%u0440%u0435%u0441%u043D%u043E%u0439%20%u0441%u0442%u0440%u043E%u043A%u0435%20%u0441%u0447%u0451%u0442%u0447%u0438%u043A%20%u043F%u0430%u043C%u044F%u0442%u0438%20....%0A%20%20%20var%20memoryDisplay%20%3D%20document.createElement%28%22statusbarpanel%22%29%3B%0A%20%20%20var%20urlbarIcons%20%3D%20document.getElementById%28%22urlbar-icons%22%29%3B%0A%20%20%20urlbarIcons.insertBefore%28%20memoryDisplay%2C%20urlbarIcons.lastChild%20%29%3B%20//%20%u043F%u0435%u0440%u0435%u0434%20%u043F%u0435%u0440%u0432%u043E%u0439%20%u0438%u043A%u043E%u043D%u043A%u043E%u0439%20%u0430%u0434%u0440%u0435%u0441%u043D%u043E%u0439%20%u0441%u0442%u0440%u043E%u043A%u0438%0A%20%20%20memoryDisplay.id%20%3D%20%22memoryDisplay%22%3B%0A%20%20%20memoryDisplay.label%20%3D%20getMemory%28%29%20+%20%27%20MB%27%3B%20%20%0A%20%20%20self.timer%20%3D%20setInterval%28function%28%29%20%7B%0A%20%20%20%20%20%20var%20mv%20%3D%20getMemory%28%29%3B%0A%20%20%20%20%20%20memoryDisplay.label%20%3D%20mv%20+%20%27%20MB%27%3B%0A%20%20%20%7D%2C%202000%20%29%3B%20%20//%20%u0442%u0430%u0439%u043C%u0435%u0440%20%u043E%u0431%u043D%u043E%u0432%u043B%u044F%u0435%u0442%20%u0441%u0447%u0451%u0442%u0447%u0438%u043A%20%u0440%u0430%u0437%20%u0432%202000%u043C%u0441%28%202%20%u0441%u0435%u043A%20%29%0A%20%20%0A%20%20%0A//%20%u0412%u0441%u043F%u043B%u044B%u0432%u0430%u044E%u0449%u0430%u044F%20%u043F%u043E%u0434%u0441%u043A%u0430%u0437%u043A%u0430%20%u0443%20%u0441%u0447%u0451%u0442%u0447%u0438%u043A%u0430%20%u043E%u0442%u043E%u0431%u0440%u0430%u0436%u0430%u0435%u0442%20%u0437%u0430%u043F%u043E%u043B%u043D%u0435%u043D%u0438%u0435%20%u0434%u0438%u0441%u043A%u043E%u0432%u043E%u0433%u043E%20%u043A%u0435%u0448%u0430%20....%0A%20%20%20var%20title%20%3D%20%22%u041B%3A%20%u041E%u0447%u0438%u0441%u0442%u0438%u0442%u044C%20%u043A%u044D%u0448%20%u0438%20%u0443%u0434%u0430%u043B%u0438%u0442%u044C%20Flash-%u043A%u0443%u043A%u0438%5Cn%u0421%3A%20%u041C%u0438%u043D%u0438%u043C%u0438%u0437%u0438%u0440%u043E%u0432%u0430%u0442%u044C%20%u0438%u0441%u043F%u043E%u043B%u044C%u0437%u043E%u0432%u0430%u043D%u0438%u0435%20%u043F%u0430%u043C%u044F%u0442%u0438%5Cn%5Cn%22%3B%0A%20%20%20var%20data%20%3D%20%7B%0A%20%20%20%20%20%20%20memory%3A%20%22Memory%20Cache%3A%20%20%22%2C%0A%20%20%20%20%20%20%20disk%3A%20%22Disk%20Cache%3A%20%20%22%2C%0A%20%20%20%20%20%20%20offline%3A%20%22Offline%20Cache%3A%20%20%22%0A%20%20%20%7D%3B%20%20%20%0A%20%20%20%20%20%20function%20getSize%28size%29%20%7B%0A%20%20%20%20%20%20if%20%28%21size%29%20return%20size%20%3D%3D%3D%200%20%3F%20%220%22%20%3A%20%22%3F%22%3B%0A%20%20%20%20%20%20for%28var%20count%20%3D%20-1%3B%20size%20%3E%3D%201024%3B%20size%20/%3D%201024%2C%20count++%29%3B%0A%20%20%20%20%20%20return%20size.toFixed%282%29.replace%28/0+%24/%2C%20%22%22%29.replace%28/%5C.%24/%2C%20%22%22%29%20+%20%22%20%22%20+%20%28%22KMGT%22%5Bcount%5D%20%7C%7C%20%22%22%29%20+%20%22B%22%3B%0A%20%20%20%7D%0A%20%20%20function%20setInf%28tot%2C%20max%2C%20type%2C%20i%29%20%7B%0A%20%20%20%20%20%20var%20inf%20%3D%20getSize%28tot%29%20+%20%22%20/%20%22%20+%20getSize%28max%29%3B%0A%20%20%20%20%20%20var%20key%20%3D%20%22browser.cache.%22%20+%20type%20+%20%22.enable%22%3B%0A%20%20%20%20%20%20if%20%28%21Services.prefs.getBoolPref%28key%29%29%20inf%20+%3D%20%22%20%28disabled%29%22%3B%0A%20%20%20%20%20%20memoryDisplay.tooltipText%20%3D%20memoryDisplay.tooltipText.replace%28zws%28i%29%2C%20inf%29%3B%0A%20%20%20%7D%0A%20%20%20function%20zws%28ind%29%20%22%5Cu200B%5Cu200B%5Cu200B%22.slice%280%2C%20++ind%29%3B%0A%0A%20%20%20var%20types%20%3D%20Object.keys%28data%29%3B%0A%20%20%20var%20ttt%20%3D%20title%20+%20types.map%28function%28key%2C%20i%29%20data%5Bkey%5D%20+%20zws%28i%29%29.join%28%22%5Cn%22%29%3B%0A%20%20%20%0A%20%20%20var%20context%20%3D%20Cu.import%28%22resource%3A//gre/modules/LoadContextInfo.jsm%22%2C%20%7B%7D%29.LoadContextInfo.default%3B%0A%20%20%20memoryDisplay.onmouseenter%20%3D%20function%28%29%20%7B%0A%20%20%20%20%20%20%20memoryDisplay.tooltipText%20%3D%20ttt%3B%0A%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20var%20entries%20%3D%20%7B%7D%3B%0A%20%20%20%20%20%20%20%20%20%20%20Services.cache.visitEntries%28%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20visitDevice%3A%20function%28device%2C%20info%29%20entries%5Bdevice%5D%20%3D%20info%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20visitEntry%3A%20function%28%29%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20types.forEach%28function%28type%2C%20i%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20info%20%3D%20entries%5Btype%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20setInf%28info%20%26%26%20info.totalSize%2C%20info%20%26%26%20info.maximumSize%2C%20type%2C%20i%29%0A%20%20%20%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%7D%20catch%28ex%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20Services.cache2%20%26%26%20types.forEach%28function%28type%2C%20i%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20func%20%3D%20function%28aEntryCount%2C%20aConsumption%2C%20aCapacity%2C%20aDiskDirectory%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setInf%28aConsumption%2C%20aCapacity%2C%20type%2C%20i%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20storage%20%3D%20Services.cache2%5B%28type%20%3D%3D%20%22offline%22%20%3F%20%22app%22%20%3A%20type%29%20+%20%22CacheStorage%22%5D%28context%2C%20null%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%20storage.asyncVisitStorage%28%7BonCacheStorageInfo%3A%20func%7D%2C%20false%29%20%7D%20catch%28ex%29%20%7B%7D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%29%3B%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%3B%0A%20%20%20%0A%20%20%20%0A%20%20%20//%20%u041F%u043E%u043B%u0443%u0447%u0438%u0442%u044C%20%u0432%u0441%u044E%20%u0437%u0430%u043D%u0438%u043C%u0430%u0435%u043C%u0443%u044E%20%u043E%u043F%u0435%u0440%u0430%u0442%u0438%u0432%u043D%u0443%u044E%20%u043F%u0430%u043C%u044F%u0442%u044C%20%u0432%20MB%20....%0A%20%20%20function%20getMemory%28%29%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20var%20reporterManager%20%3D%20Cc%5B%22@mozilla.org/memory-reporter-manager%3B1%22%5D.getService%28Ci.nsIMemoryReporterManager%29%3B%0A%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20e%20%3D%20reporterManager.enumerateReporters%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20while%20%28%20e.hasMoreElements%28%29%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20mr%20%3D%20e.getNext%28%29.QueryInterface%28Ci.nsIMemoryReporter%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self%5Bmr.path%5D%20%3D%20mr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20var%20memory%20%3D%20self%5B%22resident%22%5D.amount%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20catch%28e%29%20%7B%20var%20memory%20%3D%20reporterManager.resident%20%7D%3B%20//%20%u0434%u043B%u044F%20Nightly%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20return%20%28%20Math.round%28%20memory/1048576%20%29%20%29%3B%0A%20%20%20%7D%3B%20%20%20%20%20%20%0A%20%20%20%0A%20%0A%20//%20%u041D%u0430%u0441%u0442%u0440%u043E%u0439%u043A%u0430%20%u0444%u0443%u043D%u043A%u0446%u0438%u0439%20%u043A%u043B%u0438%u043A%u043E%u0432%20%u043C%u044B%u0448%u0438%20%u0434%u043B%u044F%20Memory%20Monitor%20.....%0A%20%20%20memoryDisplay.onclick%20%3D%20function%28e%29%20%7B%0A%20%20%20%20%20%20//%20%u043F%u043E%20%u041B%u041A%u041C%20%u043E%u0447%u0438%u0441%u0442%u0438%u0442%u044C%20%u043A%u044D%u0448%20%u0438%20%u0443%u0434%u0430%u043B%u0438%u0442%u044C%20Flash%20%u043A%u0443%u043A%u0438%u0441%u044B%0A%20%20%20%20%20%20if%20%28%20e.button%20%3D%3D%200%20%29%7B%0A%20%20%20%20%20%20%20%20%20%20%20try%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Services.cache.evictEntries%28Ci.nsICache.STORE_IN_MEMORY%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Services.cache.evictEntries%28Ci.nsICache.STORE_ON_DISK%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20catch%28e%29%20%7B%20Services.cache2.clear%28%29%20%7D%3B%0A%20%20%20%20%20%20%20%20%20%20%20var%20dir%20%3D%20Services.dirsvc.get%28%27Home%27%2C%20Ci.nsIFile%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20dir.append%28%22Application%20Data%22%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20dir.append%28%22Macromedia%22%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20dir.exists%28%29%20%26%26%20dir.remove%28true%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%21dir.exists%28%29%20%26%26%20dir.create%28Ci.nsIFile.DIRECTORY_TYPE%2C%200777%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20//%20%u0432%u0441%u043F%u043B%u044B%u0432%u0430%u044E%u0449%u0435%u0435%20%u0441%u043E%u043E%u0431%u0449%u0435%u043D%u0438%u0435%20....%0A%20%20%20%20%20%20%20%20%20%20%20Cc%5B%22@mozilla.org/alerts-service%3B1%22%5D.getService%28Ci.nsIAlertsService%29.%0A%20%20%20%20%20%20%20%20%20%20%20showAlertNotification%28self.image%2C%20self.label%2C%20%27%u041E%u0447%u0438%u0441%u0442%u0438%u043B%20%u043A%u0435%u0448%20%u0438%20%u0443%u0434%u0430%u043B%u0438%u043B%20Flash-%u043A%u0443%u043A%u0438%27%2C%20false%2C%20%22%22%2C%20null%2C%20%22%22%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20//%20%u043F%u043E%20%u0421%u041A%u041C%20%u043C%u0438%u043D%u0438%u043C%u0438%u0437%u0438%u0440%u043E%u0432%u0430%u0442%u044C%20%u0438%u0441%u043F%u043E%u043B%u044C%u0437%u043E%u0432%u0430%u043D%u0438%u0435%20%u043F%u0430%u043C%u044F%u0442%u0438%0A%20%20%20%20%20%20if%20%28%20e.button%20%3D%3D%201%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20memoryDisplay.style.color%20%3D%20%22red%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20if%20%28%20self.interval%20%29%20%7B%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearInterval%28%20self.interval%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20self.interval%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20self.interval%20%3D%20setInterval%28function%28%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20Cc%5B%22@mozilla.org/memory-reporter-manager%3B1%22%5D.getService%28Ci.nsIMemoryReporterManager%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.minimizeMemoryUsage%28null%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%2C%2040000%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%7D%3B%0A%20%20%20%0A%20%20%20%20%20%0A%20%20%20//%20Css%20%u0441%u0442%u0438%u043B%u044C%20%u0434%u043B%u044F%20%u0441%u0447%u0451%u0442%u0447%u0438%u043A%u0430%20....%0A%20%20%20var%20uri%20%3D%20makeURI%28%27data%3Atext/css%2C%27+%20encodeURIComponent%28%27%5C%0A%20%20%20%20%20%20%23memoryDisplay%20%7B%20-moz-appearance%3A%20none%20%21important%3B%20margin-left%3A%20-4px%20%21important%3B%20margin-right%3A%20-4px%20%21important%3B%20border%3A%200%20%21important%3B%20padding%3A%200%20%21important%3B%20text-align%3A%20right%3B%20%7D%5C%0A%20%20%20%20%20%20%23memoryDisplay%5BresetMemory%5D%20%7B%20color%3A%20red%20%21important%3B%20%7D%5C%0A%20%20%20%27%29%29%3B%0A%20%20%20const%20sss%20%3D%20Cc%5B%22@mozilla.org/content/style-sheet-service%3B1%22%5D.getService%28Ci.nsIStyleSheetService%29%3B%0A%20%20%20sss.loadAndRegisterSheet%28uri%2C%20sss.AGENT_SHEET%29%3B%20%0A%20%20%20%0A%20%20%20%0A%20%20%20//%20%u0423%u0434%u0430%u043B%u044F%u0442%u044C%20%u0441%u0447%u0451%u0442%u0447%u0438%u043A%20%u043F%u0430%u043C%u044F%u0442%u0438%20%u0438%20%u0434%u0440%u0443%u0433%u0438%u0435%20%u0438%u0437%u043C%u0435%u043D%u0435%u043D%u0438%u044F%20....%0A%20%20%20addDestructor%28function%28%29%20%7B%20%0A%20%20%20%20%20%20sss.unregisterSheet%28uri%2C%20sss.AGENT_SHEET%29%3B%0A%20%20%20%20%20%20urlbarIcons.removeChild%28%20memoryDisplay%20%29%0A%20%20%20%20%20%20try%20%7B%20window.clearTimeout%28%20self.timer%20%29%20%7D%20catch%28e%29%20%7B%7D%3B%0A%20%20%20%7D%29%3B%0A%20%20%20%0A%7D%29%28%29%3B%0A%0A%0A%0A%0A%0A%0A%0A%20%5D%5D%3E%3C/initcode%3E%0A%20%20%3Ccode%3E%3C%21%5BCDATA%5B/*CODE*/%5D%5D%3E%3C/code%3E%0A%20%20%3Caccelkey%3E%3C%21%5BCDATA%5B%5D%5D%3E%3C/accelkey%3E%0A%20%20%3Chelp%3E%3C%21%5BCDATA%5B%5D%5D%3E%3C/help%3E%0A%20%20%3Cattributes/%3E%0A%3C/custombutton%3E
Initialization Code
/*Initialization Code*/ // ==================================================================================== // Memory Monitor ................................ // https://forum.mozilla-russia.org/viewtopic.php?id=52237 // ==================================================================================== var idbut=this.id; var urlbar = document.getElementById("page-action-buttons"); var button = document.getElementById(idbut); urlbar.insertBefore(button, urlbar.lastChild); var style = custombutton.buttonGetHelp(self).replace(/id/g, _id); var uri = makeURI('data:text/css,'+ encodeURIComponent(style)); var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(uri, 0); // Подсказка кнопки ................................ this.tooltipText = "Л: Открыть about:memory\nП: Очистка Кеш и удаление Flash-кукисов"; // Настройка функций кликов мыши для кнопки ................................ this.onclick = function(e) { if ( e.button == 0 ) { var memoryTab = gBrowser.getBrowserForTab( gBrowser.selectedTab = gBrowser.addTab("about:memory") ); // oбработчик ждет пока откроется "about:memory", удаляет себя и нажимает кнопку на странице memoryTab.addEventListener("pageshow", function c(e) { this.removeEventListener( e.type, c ); setTimeout(function() { try { e.originalTarget.getElementById('measureButton').click() } catch(e) {} }, 0); }); } if ( e.button == 1 ) gShowPopup(this); if ( e.button == 2 && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey ) { e.preventDefault(); // очистить кэш .... try { Services.cache.evictEntries(Ci.nsICache.STORE_IN_MEMORY); Services.cache.evictEntries(Ci.nsICache.STORE_ON_DISK); } catch(e) { Services.cache2.clear() } // Удалить Flash кукиси .... var dir = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("Home", Ci.nsIFile); dir.append("Application Data"); dir.append("Macromedia"); if ( dir.exists() ) dir.remove(true); if ( !dir.exists() ) dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); // Всплывающее сообщение .... var alertService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); alertService.showAlertNotification('chrome://global/skin/icons/information-16.png', 'Показывать потребление памяти', 'Очистил кеш и удалил Flash кукиси'); setTimeout(function() { alertService.closeAlert() }, 2500); } }; // Показывать потребление памяти на текущей кнопке (function () { self.timer = setInterval(function() { var memory = getMemory(); self.label = getMemory() + ' mb' if ( memory < 300 ) return; var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); file.initWithPath('буква диска:\\путь\\до\\файла.расширение'); file.launch(); }, 2000 ); // Получить всю занимаемую оперативную память в MB .... function getMemory() { var reporterManager = Cc["@mozilla.org/memory-reporter-manager;1"].getService(Ci.nsIMemoryReporterManager); try { var e = reporterManager.enumerateReporters(); while ( e.hasMoreElements() ) { var mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter); self[mr.path] = mr; } var memory = self["resident"].amount; } catch(e) { var memory = reporterManager.resident; } // FF26 - Nightly return ( Math.round( memory/1048576 ) ); }; // Стиль добавляет текст на кнопку .... var uri = makeURI('data:text/css,'+ encodeURIComponent('\ %button% .toolbarbutton-icon {\ display: none !important;\ }\ %button% .toolbarbutton-text {\ display: -moz-box !important;\ }\ %button% {\ -moz-box-orient: horizontal !important;\ }\ '.replace(/%button%/g, "#" + _id) )); const sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET); // Удалять счётчик памяти и другие изменения .... addDestructor(function() { try { window.clearTimeout( self.timer ) } catch(e) {}; }); })();
1.Обновление , версии custom_buttons-0.0.7.0.0.30-fx-bootstrap: не помогло
2. почистить папку startupCache :не помогло
Есть возможность подправить код?
Отредактировано KOMMEHTATOP (16-05-2023 15:49:31)
Distance Subordinatio!
Отсутствует
1.Обновление , версии custom_buttons-0.0.7.0.0.30-fx-bootstrap: не помогло
Проверьте с актуальной версией -> https://forum.mozilla-russia.org/viewto … 67#p804467
Win7
Отсутствует
KOMMEHTATOP
// Стиль добавляет текст на кнопку ....
display: -moz-box !important;\ заменить на display: flex !important;\
-moz-box-orient: horizontal !important;\ заменить на flex-direction: row !important;\
На форуме
KOMMEHTATOP
// Стиль добавляет текст на кнопку ....
display: -moz-box !important;\ заменить на display: flex !important;\
-moz-box-orient: horizontal !important;\ заменить на flex-direction: row !important;\
Distance Subordinatio!
Отсутствует
Dumby
просьба доработать антиподписячий код – с ним браузер LibreWolf 110 не запускается, но LibreWolf 97 работает нормально.
JavaScript error: resource://gre/modules/AddonManager.jsm, line 20: InternalError: module record has unexpected status: Evaluating JavaScript error: resource://gre/modules/AsyncShutdown.sys.mjs, line 727: Error: Phase "profile-before-change" is finished, it is too late to register completion condition "OS.File: flush I/O queued before profileBeforeChange"
Отсутствует
браузер LibreWolf 110
Где я его возьму? По ссылке другая версия,
а гитлаб мне фигу показывает, а не «all versions and release notes».
Ладно, скачал 112.0.2-1
просьба доработать антиподписячий код
Антиподписячий код, по сути, меняет AppConstants.MOZ_REQUIRE_SIGNING
чтобы релиз или бета были как DE, ESR, Unbraindead.
Насколько я вижу, в LibreWolf 112.0.2-1, его значение уже выставлено в false
То есть, антиподписячий код просто не требуется, достаточно настроек
xpinstall.signatures.required
extensions.experiments.enabled
А дурацкие надписи на about:addons скрыл так: layout.css.has-selector.enabled
и в userContent.css
@-moz-document url(about:addons) { .addon-card-message:has([data-l10n-id=details-notification-unsigned]) { display: none !important; } }
Отредактировано Dumby (20-05-2023 09:39:51)
Отсутствует
Dumby дурацкие надписи не могу скрыть – до них не доходит!
LibreWolf версий 110-113 не запускаются под виндой и Маком с таким антиподписячим config.js
Просьба сделать так, чтобы ошибки выполнения в этом коде не мешали запускаться браузеру !
// try {(jsval => { // Firefox 78+, FIX 100+ https://forum.mozilla-russia.org/viewtopic.php?pid=802045#p802045 var dbg, gref, genv = func => { var sandbox = new Cu.Sandbox(g, {freshCompartment: true}); Cc["@mozilla.org/jsdebugger;1"].createInstance(Ci.IJSDebugger).addClass(sandbox); (dbg = new sandbox.Debugger()).addDebuggee(g); gref = dbg.makeGlobalObjectReference(g); return (genv = func => func && gref.makeDebuggeeValue(func).environment)(func); } var g = Cu.getGlobalForObject(jsval), o = g.Object, {freeze} = o, disleg; var lexp = () => lockPref("extensions.experiments.enabled", true); var MRS = "MOZ_REQUIRE_SIGNING", AC = "AppConstants", uac = `resource://gre/modules/${AC}.`; if (o.isFrozen(o)) { // Fx 102.0b7+ lexp(); disleg = true; genv(); dbg.onEnterFrame = frame => { var {script} = frame; try {if (!script.url.startsWith(uac)) return;} catch {return;} dbg.onEnterFrame = undefined; if (script.isModule) { // ESM, Fx 108+ var env = frame.environment; frame.onPop = () => env.setVariable(AC, gref.makeDebuggeeValue(freeze( o.assign(new o(), env.getVariable(AC).unsafeDereference(), {[MRS]: false}) ))); } else { // JSM var nsvo = frame.this.unsafeDereference(); nsvo.Object = {freeze(ac) { ac[MRS] = false; delete nsvo.Object; return freeze(ac); }}; } } } else o.freeze = obj => { if (!Components.stack.caller.filename.startsWith(uac)) return freeze(obj); obj[MRS] = false; if ((disleg = "MOZ_ALLOW_ADDON_SIDELOAD" in obj)) lexp(); else obj.MOZ_ALLOW_LEGACY_EXTENSIONS = true, lockPref("extensions.legacy.enabled", true); return (o.freeze = freeze)(obj); } lockPref("xpinstall.signatures.required", false); lockPref("extensions.langpacks.signatures.required", false); var useDbg = true, xpii = "resource://gre/modules/addons/XPIInstall."; if (Ci.nsINativeFileWatcherService) { // Fx < 100 jsval = Cu.import(xpii + "jsm", {}); var shouldVerify = jsval.shouldVerifySignedState; if (shouldVerify.length == 1) useDbg = false, jsval.shouldVerifySignedState = addon => !addon.id && shouldVerify(addon); } if (useDbg) { // Fx 99+ try {var exp = ChromeUtils.importESModule(xpii + "sys.mjs");} catch {exp = g.ChromeUtils.import(xpii + "jsm");} jsval = o.assign({}, exp); var env = genv(jsval.XPIInstall.installTemporaryAddon); var ref = name => {try {return env.find(name).getVariable(name).unsafeDereference();} catch {}} jsval.XPIDatabase = (ref("lazy") || {}).XPIDatabase || ref("XPIDatabase"); var proto = ref("Package").prototype; var verify = proto.verifySignedState; proto.verifySignedState = function(id) { return id ? {cert: null, signedState: undefined} : verify.apply(this, arguments); } dbg.removeAllDebuggees(); } if (disleg) jsval.XPIDatabase.isDisabledLegacy = () => false; })( "permitCPOWsInScope" in Cu ? Cu.import("resource://gre/modules/WebRequestCommon.jsm", {}) : Cu );} catch(ex) {Cu.reportError(ex);}
Отсутствует
Dobrov
Я что-то непонятное написал?
Есть непреодлимое желание устанавливать в false то,
что уже и так стоит в false?
Хорошо, есть у меня код, который делался под const,
а не под var, как сейчас.
Вроде устанавливает, и ошибок не вызывает.
Такая правка:
/* var env = frame.environment; frame.onPop = () => env.setVariable(AC, gref.makeDebuggeeValue(freeze( o.assign(new o(), env.getVariable(AC).unsafeDereference(), {[MRS]: false}) ))); */ var line = script.source.text .split("\n").findIndex(str => str.includes(MRS)) + 1; var max = script.getPossibleBreakpoints().at(-1).offset; for(var offset = 0; offset < max; offset++) try { if (script.getOffsetMetadata(offset).lineNumber > line) break; } catch {} var cls = {class: "Object"}; var find = o => o.getProperty(MRS).return !== undefined; frame.onStep = () => { var ac = frame.offset > offset && dbg.findObjects(cls).find(find); if (ac) frame.onStep = undefined, ac.unsafeDereference()[MRS] = false; }
Отсутствует
Dumby - спасибо!, код нужен был просто для тестирования.
Второй вопрос: в новых FF перестала мигать кнопка Загрузок, как исправить?
async function dflash(){ var d = await Downloads.createDownload({source: "about:blank", target: FileUtils.File("/")}); (await Downloads.getList(Downloads.ALL)).add(d); d.refresh(d.succeeded = true); } dflash();
Отсутствует
matchMedia("(prefers-reduced-motion)").matches;
выдаёт «true»
системную анимацию не хочу включать, при этом на FF97 кнопка Загрузки мигает.
Отредактировано Dobrov (21-05-2023 17:34:57)
Отсутствует
при этом на FF97 кнопка Загрузки мигает
Баг то хоть глазами пробежал?
Написано же: «Target Milestone: --- → 111 Branch».
системную анимацию не хочу включать
Системную? Ты, наверно, хотел написать «в браузере»?
Можно ведь создать числовую настройку ui.prefersReducedMotion
со значением ноль.
Если это не устраивает, то можно, например, переключать её в коде.
То есть, перед строкой с d.refresh — устанавливаем, а после — сбрасываем.
Только не забудь тогда в самой строке добавить await перед d.refresh
(можно её ещё и в try catch завернуть, чтобы гарантировать сброс).
Отсутствует
Системную? Ты, наверно, хотел написать «в браузере»?
насколько я понял, браузер учитывает анимацию системы:
In Windows 10 Settings, in Display, set "Show animations in Windows" to Off.
Or on macOS , in the Accessibility system preferences, under "Display" tick the "Reduce motion" checkbox.
Фиктивное завершение загрузки файла переделал так:
async function dflash(){ // фиктивное завершение загрузки var {prefs} = Services; var d = await Downloads.createDownload({source: "about:blank", target: FileUtils.File("/")}); (await Downloads.getList(Downloads.ALL)).add(d); if (matchMedia("(prefers-reduced-motion)").matches) prefs.setIntPref('ui.prefersReducedMotion', 0); await d.refresh(d.succeeded = true); prefs.clearUserPref('ui.prefersReducedMotion'); } dflash();
Отредактировано Dobrov (22-05-2023 05:44:12)
Отсутствует
переделал так
А зачем matchMedia("(prefers-reduced-motion)").matches проверяется?
Мы ведь уже выяснили, что у тебя там будет true.
И настройку предложил сбрасывать, поскольку не хочешь завести её на постоянно,
то есть под конкретный расклад.
А если проверка matches, подразумевается как бы под более общий случай,
тогда и пост-d.refresh() действие должно производиться только если matches был true.
И, в таком случае, настройку следует сбрасывать только если её не существовало,
иначе — вернуть какая была.
Отсутствует
А зачем matchMedia("(prefers-reduced-motion)").matches проверяется?
Мы ведь уже выяснили, что у тебя там будет true.
Вот 2 вариант. Не знаю, как не создавать настройку, если её не было. У меня в неё пишется значение по-умолчанию…
async function dflash(){ // фиктивное завершение загрузки var {prefs} = Services, p = 'ui.prefersReducedMotion', t = prefs.getIntPref(p, 0); var d = await Downloads.createDownload({source: "about:blank", target: FileUtils.File("/")}); (await Downloads.getList(Downloads.ALL)).add(d); prefs.setIntPref(p, 0); await d.refresh(d.succeeded = true); prefs.setIntPref(p, t); } dflash();
Ещё подскажите, как посмотреть объект Java-Script (например Свойства для кнопки) без расширения DOM-Inspector ?
Может, возможно доработать кнопку Attributes Inspector для просмотра Java-Script свойств ?
Отредактировано Dobrov (23-05-2023 09:47:15)
Отсутствует
если её не было
Обычно, существование настройки проверяется
вызовом метода Services.prefs.getPrefType()
Для несуществующей настройки
результатом вызова будет Services.prefs.PREF_INVALID
Однако, поскольку ui.prefersReducedMotion дефолтно не существует,
можно просто проверять Services.prefs.prefHasUserValue()
Вобщем, я типа о чём-то таком
//... var p = "ui.prefersReducedMotion"; var {matches} = matchMedia("(prefers-reduced-motion)"); if (matches) { var has = prefs.prefHasUserValue(p); if (has) var was = prefs.getIntPref(p); prefs.setIntPref(p, 0); } await d.refresh(d.succeeded = true); if (matches) has ? prefs.setIntPref(p, was) : prefs.clearUserPref(p);
как посмотреть объект Java-Script (например Свойства для кнопки) без расширения DOM-Inspector ?
Эээ, в консоли.
console.log(button);
Если с Инспектора, то ПКМ —> «Использовать в Консоли» —> Enter
И гораздо круче, в DOMi только лишь for-in-перечисляемые свойства,
а в консоли — вообще все.
Но, для функций не предусмотрено отображение как toString(),
что слегка снижает информативность.
Отсутствует
Dumby — спасибо за уроки!
Ещё проблема: «Инструменты браузера: Пипетка» при вызове из кода ничего не происходит.
Но если открыть «Консоль браузера», то потом Пипетка из кода открывается.
Как сделать, чтобы сразу из скрипта работало ?
document.getElementById("menu_eyedropper").click();
Отсутствует
«Инструменты браузера: Пипетка»
Хмм, у меня код для пипетки, неожиданно, даже сохранился.
Но это код для CB, надеюсь распорядишься правильно.
this._handleClick = () => { var sub = parseInt(Services.appinfo.platformVersion) >= 96 ? "loader/" : ""; var url = `resource://devtools/shared/${sub}Loader.`; try {var exp = ChromeUtils.importESModule(url + "sys.mjs");} catch {exp = ChromeUtils.import(url + "jsm");} var obj = exp.require("devtools/client/menus").menuitems .find(menuitem => menuitem.id == "menu_eyedropper"); (this._handleClick = obj.oncommand.bind(null, {target: this}))(); }
Отсутствует
Dumby - menu_eyedropper работает, Спасибо!
Вопрос по элементу "menupopup" на примере старой кнопки Quick Toggle меню (строка 458 в этом коде)
Как определить состояние меню: Открыто, Не открыто? Какой флаг это показывает ?
В моём профиле при наведении на кнопку есть подсказка в строке статуса. Если сделать правый клик, то откроется меню кнопки ToggleButton.
При наведении мыши по строкам меню опять показывается эта же подсказка, хотя id менюшки «ToggleButton-Popup», а в коде подсказка прописана для id «ToggleButton».
При открытом меню "ToggleButton-Popup" его id.state всегда "closed" и других флагов в DOM Inspector я не нашёл для этой менюшки.
Нужен код, чтобы получить состояние менюшки открыта или нет (чтобы не выводить лишние подсказки).
Отсутствует
Как сделать программно клик на пункте контекстного меню страницы?
Если в атрибуте oncommand этого пункта нет строки "gContextMenu", то все нормально.
Но если "gContextMenu" есть, то это не работает.
Я вызываю меню document.getElementById("contentAreaContextMenu").openPopup()
Меню открывается, но клика не происходит. В консоли ошибка this.ownerDoc is undefined а при закрывании меню появляется еще и gContextMenu is null
Отсутствует
Garalf эта?
/*Initialization Code*/ ///////////////////////////////////////////////////////////////////////////// /////////////////////////////// Создание меню /////////////////////////////// ///////////////////////////////////////////////////////////////////////////// function $(aId) { return document.getElementById(aId); }; function addMenuItem(aNewIDs, aNodeIDs, aLabel, aIcon, aCommand) { for (var i = 0; i < aNewIDs.length; i++) { if ($(aNewIDs[i])) $(aNewIDs[i]).parentNode.removeChild($(aNewIDs[i])); var mi = document.createXULElement("menuitem"); mi.setAttribute("id", aNewIDs[i]); mi.setAttribute("class", "menuitem-iconic"); mi.setAttribute("image", aIcon); mi.setAttribute("label", aLabel); mi.setAttribute("oncommand", aCommand); if (i == 0) mi.setAttribute("observes", "custombuttons-contextbroadcaster-primary"); if ($(aNodeIDs[i])) { if ($(aNodeIDs[i]).nextSibling) { $(aNodeIDs[i]).parentNode.insertBefore(mi, $(aNodeIDs[i]).nextSibling); } else { $(aNodeIDs[i]).parentNode.appendChild(mi); } } } }; var saveImg1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAnUlEQVQ4jc3RPQ4BURTF8Z+PgrAPtUJnIxZgBZagkolVqDWWIliARCFR6GSq0Twyw2SemcpJTnPzzv/edy//ohOymj7mARl6NRoOQ6YAiGmNFAm6TQBpePdAJwYYYIF+rpaE8CoGaGEbarsw7qfaVYCl4rY3mOOGaQwwU326O8Zhyi/AJPwxdv8rRmWAyw/hl89lgCZ+69AgvPcXegKfOWlGgoA/rgAAAABJRU5ErkJggg=="; var saveImg2 = "data:application/file;base64,AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAADbAAADpcAAA//AAANVwAAD/8AAAKsAAAD/AAAP//AAAP8AAAD/AAAD/8AAAwDAAAP/wAAA/wAAAP8AAA"; var saveImg3 = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAAAAAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+sQf//rEH4j6xB8IesQeHDrEHD4axBh/CsQYf4rEGH8KxBw+GsQeHDrEHwh6xB+I+sQf//rEH//6xB//+sQQ=="; var saveImg4 = "data:application/file;base64,AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAD/8AAA//AAAP/wAAA/wAAAP8AAA"; var saveImg5 = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU1FQr1FRT7BRUU+wUVFPsFFRT7BRUU+wUVFPsFFRT7BRUU+wUVFPsFFRT7BRUU+wU1FQrwAAAAAAAAAAAAAAAHd0cpz//////////////////////////////////////////////////////////3d0cpwAAAAAAAAAAAAAAAB4d3Sc/////+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg//////94d3ScAAAAAAAAAAAAAAAAenh3nP/////i4uL/4uLi/5yiz/9HYcT/PWrR/1qQ3P+nuNr/4uLi/+Li4v//////enh3nAAAAAAAAAAAAAAAAH18eJz/////5OTk/2FluP8IJ6r/D1TU/wli4v8FZeb/D3He/4y+5f/k5OT/+/v7/318eJwAAAAAAAAAAAAAAACBfXyc/////5Wc0v8JKq//E2Pd/yFTrv9EKTn/LjVZ/xaF2/8OdNP/zNnm//z8/P+BfXycAAAAAAAAAAAAAAAAhIGBnP////89Xc7/Dk7N/wpQ0/8zVp//TGCK/4U2Cf9DW2b/Eqj7/5C+5//8/Pz/hIGBnAAAAAAAAAAAAAAAAIaEgZz/////Kmnf/wlFzf8gPZ7/uXcl/8OAK/+UTBL/b1Az/zfG9f9srdX/+fn5/4aEgZwAAAAAAAAAAAAAAACJhoac/////0iN6P8HQtH/EVzd/2mCqf/dqkz/0pY6/6FnKv9Nvt7/kMfs//X19f+JhoacAAAAAAAAAAAAAAAAiomJnP////+Mr+r/FFnU/xVRyv+LorL/8Oqh//nXbP+5omH/Urvf/8bj7v/s7Oz/iomJnAAAAAAAAAAAAAAAAI6Kipz/////2+n3/5aSm/+hcEn/4uXC////2P/25KD/rqSD/7HR5//o6Oj/4eHh/46KipwAAAAAAAAAAAAAAACPjo6c//////j4+P/4+Pj/3s/F/9i/n//p27n/5NG0/+7r6f/r6+v/3t7e/9LS0v+Pjo6cAAAAAAAAAAAAAAAAk4+PnP/////6+vr/+vr6//r6+v/6+vr/+vr6//j4+P/19fX/r66t/62sq/ObmprrkI2NpgAAAAAAAAAAAAAAAJOTk5z//////Pz8//z8/P/8/Pz/+/v7//r6+v/4+Pj/9fX1/66trfHs7Ozrp6emp4aGhhMAAAAAAAAAAAAAAACWlpOc/////////////////v7+//39/f/6+vr/9/f3//Pz8/+bmprrp6enp3NzcxYAAAAAAAAAAAAAAAAAAAAAmJiWnJiYlpyYmJacmJiWnJeTk52SkZGemJiWnJeTk52SkZGej4+LpIaGhhMAAAAAAAAAAAAAAAAAAAAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACAAwAAgAMAAIADAACABwAAgA8AAA=="; var saveImg6 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABKklEQVR42mNkQAMNDAxCQMoTiB2BWAEq/ACI9wPxdqD8O2T1jGiao4HUEgb8IAaobimGAUDBGiDVzEAcqAWqb4EbQKTNWF3CCPXzW5ho/f//YDqHkZFhCpQNA7lAMV4gzY4QEmZEtx1mgCtQ8W4o2xLIPg5lJwDZUghDYkAGzAEyktENMAQqPA9l6wDZEkB6D6Yhc0EG7AGynfEZYAxkawHpxVC+A5CvC6RFGBj2Em2AIZCeg8Q3BtLSUAMIegGkwQBIz8U0YC7OQEQ2wAjIPoekGRQTUC/E4IxGkMKzaNEI8jso4chDbGdgA0UjekJ6A8S3gRikFWQyKOF/higGR50UFLPBEhLM9AZoUv4F1cAA1QTi/2SAJFkQnxdCoyZlJEPIz0xIhpCUnQFx83abgfUZOQAAAABJRU5ErkJggg=="; var saveImg7 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASUlEQVR42mNkoBAw0s6ABob/aHxGkg1I8zEGM2dtOTskDED3MxCgGIBpASOGATANhACyi6hrAGVeoDgQB6UB2PxMvAFEAooNAAC7izYR2pQ0nAAAAABJRU5ErkJggg=="; var saveImg8 = "data:application/file;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///8A////AESqAABHpgAASKAAAEukAQxMpQMYR6MAAEepAQ9MpgOLRKgACUenAABHpgAARKoAAP///wD///8A////AP///wBEqgAARaIAAFS2FVBj0jS3Y9AzyVG0EUROrwt8TKcDs0ikAANInwAAR6YAAESqAAD///8A////AP///wD///8ARKQAAVvJKJtj0jX/SaAJ/0abCv9UtSH/U7QX8lW5IMddwyfQW8Iii0mqBQ1DqQAA////AP///wD///8A////AEWlAAFYwB6YXsYc5F7GFt9bwA+vVbgWvU6rAKBRrgf0RZgA/02oDP9ezCzJR6UBA////wD///8A////AP///wBFrAAASKIAADiGNQAeYIIpF1iJHVa4GKEve0tFLHl1Pla7J51exRnUWL8VjEetAAP///8A////AP///wD///8AC0WuAAk/tAAANdpIAFD6/wA+7f8gd6jqBlPX+QBE9PIGS8uDLnZLADqNJwAzjDMA////AP///wD///8A////AAAw0QAALc0AAEPdegBI4f8AK8P/ADHX/wAwzf8AL8b/AEno/gAz2zYALtEQAC3VAP///wD///8A////AP///wAAMssAADjSMwBA2pIATen/ADG9/wBe1v8ATcz/ADHK/wBN5/4ASeH/AEvl6wA10DP///8A////AP///wD///8AADnTSQBO5/8ANc7/ADnR/xC+9/8C0f//AMj//wCP8P8ALcX/ACrC/wBE3f8ASeOf////AP///wD///8A////AABI4Z4ARN3/ACvG/wJAxP8Z5v//AMT//wDE//8Axv7/AETM/wA51P8AUervADjSPP///wD///8A////AP///wAAOdRiAFry+QBS6/QATOP/H+P8/xDe//8J1///E9H4/wFE2f8AReC6ADTOEwAyywD///8A////AP///wD///8AADDNAAAyzCcARN7WACvG/wVfzf8d0vf/HM30/whf0/8AI7n/ADzV+AA40kUAMswA////AP///wD///8A////AAAwywAAPNdTAEfg/wAsw/8AOdb/ADLP/wAswv8AReP/AC7H/wA40f8AR+GfADDKAP///wD///8A////AP///wAAMswAADfRQgBY8f8AT+j/AE7o7AA+1/8AK8T/AE7o/wBN5f8AVe7/AD/ZbAAwywD///8A////AP///wD///8AADPMAAAyywAANM4vADjSUQA0zikAU+z3AEff/wBJ4sMAN9EtADjROQAyywAAM8wA////AP///wD///8A////AAAzzAAAM8wAADHLAAAwywAAMcsAAD/YXQBK4pYAN9AxAC/KAAAwygAAM8wAADPMAP///wD///8A+R8AAPAfAADABwAAwAMAAPgDAADwHwAA8AcAAOADAADAAwAAwAMAAMAHAADgBwAA4AcAAOAHAADwDwAA/j8AAA=="; var saveImg9 = "data:application/file;base64,AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8BAAAAFwAAAGkAAABzAAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAAHUAAAB1AAAAdQAAADkAAAAP////AQAAAIdgZmj/YWlt/2FobP9haGz/YGhr/2Boa/9fZ2v/X2dr/15mav9dZWn/XGRo/0ZNUP8AAACdAAAAFf///wEAAACr2tzc/9ve4P/a3t//1dnZ/7S2tf+foJz/m5ya/6apqP/O0tP/09fZ/9DV1v+hqq//AAAAuQAAABX///8BAAAAq+3u7//e4eL/ub29/2hnXv9oVUX/U0As/zgxGf83Lx3/YWBX/7a5uv/S1tj/o6yx/wAAALkAAAAV////AQAAAKv29/f/19na/1dUQf9jXDv/dmtJ/4FoSP9VQiL/V0Ek/008Iv9HQTP/yc3P/6Wus/8AAAC5AAAAFf///wEAAACr+Pj4/5uamP9tY0L/g31b/6GLa/+McVH/eFY5/4xwUv9yXkD/RTki/4uMiv+nsLT/AAAAuQAAABX///8BAAAAq/n6+v+FfXL/waSM/8qznf/DrZP/ooFi/7WfhP+qh2//blk9/1A+Iv9aWlH/pK2x/wAAALkAAAAV////AQAAAKv6+/v/d3Rr/9zCsP/RxbH/z8Wu/9fJt//Qvab/qItv/5iOb/9tYUH/VVJK/6Wtsf8AAAC5AAAAFf///wEAAACr+/z8/4mHff+3pI//3NK//+HXxf/m3Mz/5trJ/9rMuf+bgWT/d14//2hnYP+osbX/AAAAuQAAABX///8BAAAAq/z9/f/FxL7/j4l+//Xw5f/29ez/8/Dl/+DMuv/VuaP/poZn/2dFKv+srav/oamt/wAAALkAAAAV////AQAAAKv+/v7/+/z8/5iZjf+5uqr/6+PW/+3i1P/kzL3/vZR+/4NhSf+Qh3z/z9HS/4qQkv8AAAC1AAAAFf///wEAAACr/v7+//7+/v/u7u3/tbiv/5WSgP+DfGj/e25Z/29gTv+sppz/vr6+/5aYmP90eHr/AAAApwAAABP///8BAAAAq/////////////////7+/v/9/f3//f39//v8/P/5+fn/1dXV/2pqav9TU1P/QUFB/wEBAYkAAAAJ////AQAAAKv7+/v//////////////////v7+//7+/v/+/v7/+vr6/9fY2P/V1tb/7Ozs/4KCgv8EBAQrAAAAA////wEAAACFlJSU/6ioqP+qqqr/qqqq/6qqqv+qqqr/qKio/6anp/2kpaX9o6Oj/4qKitUZGRk9////Af///wH///8BAAAAFQAAAFUAAABVAAAAVQAAAFUAAABVAAAAVQAAAFUAAABTBAQEUx8fH1dfX18z////Af///wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w=="; var loadImg = "data:image/x-icon;base64,AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8B////Af///wH///8B////AQAAAB+yg2l71ZRt+daTa//Wk2v/1pNr/9aTa//Wk2v/v4NlywYEAycAAAAX////Af///wH///8B////Af///wHdo4M53Zx3/+Sgef/innb/4p52/+Kedv/lo3r/5aR6/+mqgfvPj27N////Af///wH///8B////Af///wH///8B4KSD8+mmff/opH3/56N6/+Whef/no3r/66qB/8KBXf/Fg1//0Y5s78+Pbqn///8B////Af///wH///8B////AeGlg//trIX/7ayE/+6thP/urIX/9bWL/8eFYf/GhF//yYZh/9SPa/nkn3j/////Af///wH///8B////Af///wHkn3j/76+G/+6uh//vrob/76+G//W3jP/GhF//y4di/9ONZ//XkWr/5J94/////wH///8B////Af///wH///8B5J94/++wif/wsIj/8LGJ//CxiP/0toz/y4di/8+KZf/vroP/766D/+SfeP////8B////Af///wH///8B////AeSfeP/xs4v/8bOL//Cziv/ws4v/87WL/9CNa+3QjWvt3p96/96fev/en3r/////Af///wH///8B////Af///wHkn3j/8rWN//K2jf/ytY3/8rWN//O2jvfdo4Lj0I5sJdCObCXQjmwl0I5sJf///wH///8B////Af///wH///8B5J94//O3j//zuI//87iP//O4j//zuZDx3aOD7////wH///8B////Af///wHdo4M/5J94/+SfeP/kn3j/5J94/++2j//zupH/9LqR//O6kv/0upL/87qR/+SfeP/kn3j/5J94/+SfeP////8B////Af///wHkoXr/9cCY//W8k//0vJT/9L2T//S8lP/0vZT/9LyU//S8lP/1vJT/9cCY/+Shev////8B////Af///wH///8B9b+WC+SjfP/2yqP/9b+W//a/lf/2v5X/9b6V//W+lv/1vpX/9sqj/+SjfP////8B////Af///wH///8B////Af///wH2wZgX5aZ+//fTrP/2wJj/9sCY//bAmP/2wZj/99Os/+Smf/////8B////Af///wH///8B////Af///wH///8B////Af///wHkqYH/99ax//fCmv/3wpn/99aw/+Sogf////8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////AeWrhP/317L/99ey/+WrhP////8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B5a2F/+Wthf////8B////Af///wH///8B////Af///wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//w=="; var moveToMenu = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABKElEQVR42o3TMUvDQBQH8P+7tLlEwaW4ugl+iU6CCA4i0tbdqavgZ/ErCE79DsVBkYpKLR2kuApOatG297zLJWkqXnIPwrsk937cveQIJXHZBZt8cgFyzaEqYGuTvl7feM2FVAIHR8Bj341UAu1T4PPdjXgBJgzyPKDFy4SDIkJZo1yRASZ+FDB5Itzfct7YBGjuBBBh6oT6ed2OazGjsV3wQ2Cu64bXUKM7FgZJgPaufinTSVFhrDPFheVIe01nwLgfq9HNVCRAaw8Q6USWS4B05mgVIH2/qG+ABh+46im7heP9EELOLRDZpVqAQev8ZwUS/DBLivMtlDWxc7Ycs6yBhyov9vqMGcBBDB5/rxT7/Qfntjn/FXsDrmIvoHUonMVegMllx/kXlvSRMQ0GPE4AAAAASUVORK5CYII="; var removeFromToolbar = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACMElEQVR42p3Sz2/SUBwA8G9pgQJd6QYZQQkOjUFdXMCLMn9B4l3myRgXhydPZgcTY2KyLfGiF/wT9GTmhfIXjMQ4NP5YD5qZTGdVdEx+9FVKSwttrTV4QD3AN3mH9837fr7v+/Kww1e4ic2HiSYMRGxufcHjxs87nQ5GN0zodnXQNLVomvCAL6ZR/xxmAS9VsX1umz1pJ/dfKGeD4+58OERNYQQO7Y4BWs8E3XCAqvRAEkWkdpTcNptm+4DpMVUOtboZl4tY2reXWmTGvbDTVKFnALicTrvYsFqbpgEOBw6tpgiigOb4Yoa1gTMzY1B+XUexKM1gLid8a3QgQHtBklQQBJm3RuAxDBiPl0z4aMq+eu1rFYmiFLOBowd8QJEEiLIBlbpV7PdArdZCApJX3j9O3e/Pe/Di0zTpJgvB8CSjSG1o7O7mbCA04QIHjoGsGuAfI6FRk0D8ISe3VlPc4OPGL61nab+/QDE0VD9/+T1CKOCCtqoDQRBAe0n4yH/nZUVLVtjTCP4R8cvPN8LRSKL6qVKygUjIC0rXAAMw6+EI6GkmoGaDM0DP8KuzfyHx+WfLe6KRpdpOlbMB+E9oWof78OhEcjB/5OqLbHAyUEB1oYTBCDFz7VWaYZg11BTYkYBj17lFyu3Lo5aYGwk4fuNNHgd8QVHk2EjA7K3NDVM3iuV708tDA2dXtqb0rr5mrWT57jQaGjh1+13eKio+uXOo9Gs/NJC6+TZhdf7zQ38Ceg0HgF1MCP0AAAAASUVORK5CYII="; var iconADD = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAASCAMAAABl5a5YAAAAkFBMVEWsFBSfERGYExOPDw8jEBCwFBRJICDXICBCGRnELCwUDg5BDg6XDg7AFhbAGBjVKyvHHBzIKyuJGBiDGRm7FxeiOTmMMDASDg5PExM1Dg4TDg4xEBBaIyMvExMsExMbDw9GDg4AAAC5Dw/JDg7MDg7QDw++Dg60Dg7DDg6sDg61FRWNDg7YGRmwDg7WKyvEGhojAnMyAAAAInRSTlP7+/TzTfst/k/9J4T85N/16PFfWgljXR15BRU7HQ8MMIsAJl/uYAAAAINJREFUeF6Nz8cSgzAMBFDSGx1Cc4wdSy6Q9v9/F4Y2Hk7sTe+iXee5yFqokzhOqAWPr5QtsyFAOMxQ0voYIDokTcsestALTwjK8/2ih/tbSkQwSjd8BEDobjFB9hPCGNVuXHeAipBzpMR2z1g+vaWR1rvc7nFpPq+rXb3g/FatXrvIH9eGIuNzLuIwAAAAAElFTkSuQmCC"; var customBtn = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjVJREFUeNqcUkuIUmEUPl4fML6bBsFRacRF2EaCcRO48bFLEIJcBIJLxb2b2UWLkIEgQQjauVFaKmgYuclUTMUHKoaKE4GPxnxh5r3ezh0QHJFmmA/OPZfDfx7fdw7AfojQ7qGx4QawdgMymeyRyWR6IZVKucFg8N10Ov0Ot4VGozmNRCLx5XL5F/HHbrefYZh7m1yWWq0+TafTn2kEdqXr9TrtcDje3JR4xRHH1QYCgXOz2Wzs9/sQj8dBIpEATtGrVqu9yWSywmdLNGq3AAeNsFgsz202mxk7QzKZBK1WCzqdjtHjKUmSx41Go4L+slQqpYvF4keKoibXpnA6nWfY+VehUKBSqRTJ0Oh2u3Qul6MHgwE9Ho9pLMD4H16v95zD4RxuU6BbrdYlPh5g8tfFYvET9XiIiRylUsnQgPl8DtgVhsOheL1eS6LRaGy1Wg02FAA5VmKxWB1/yUQioWOxWHKXy2XEYsDQEggEgKJCJpOBcrnMbOliW4MNSOaDCbVKpVISCoVGHBnQQygUgnK1AkeH9z+Ew+HX2xoQezZDjUaj3ygDiMViaLfbV8kK+TGw2WysJzzafry3QK1W+9Lr9RpIDbLZLEhE4vedTsdvMBieuN3ulwRBPLh2B7uYzWYXzWZzjBoc5PP5MJ70K1xfEsVc4cpNeDcnuLFvzM3978gILpcrRy/w+XybGE+v1z/z+/2frFarG9d5AHeBSqUyeDyetwqF4jHcFXw+/4TH44n+CTAA3Ccog288LRAAAAAASUVORK5CYII="; var saveAll = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACOElEQVR42mNkwAJ+7xf7//3tKwZeIUELRqf3JxnwAEZkzrtlwnv/MzE6/WfkWCwS/iTu7RLO/wzMPAwc/z4Lc0f/eIfTgP/7BM0PXDY5ofB9N8M/EB8k+BcoyQw1mEWd4SurLIO97lkUFzX9b/oPNmBznc7/////MbAzfIdoBoI/P77Abfnzn4XhH9A0kOLA7icQV88HKn0EdcH6Ss3/yM76/f0jg2vTXYZ/f39j9fdUgQkMdTp1DNFXoiEGrCzFNMCj6SrD/79/MDQzsbAzCEfyMTBwADkbGBjBBiwrRDXgF9AAz6ZLWF1QIlHCsFRnKdj2pYxLIQYsytPAMMC75SLYBVMkpzDkPM+By0lFSTEwCDAwvJ79eouoqKgv2IB5WWgGfPvI4N95kUEyQQwcJVXbq8CGeEp6MlzUuQi2fcKbCQgDZqWhG/CJIaDrLIPMf0kGBjeggAoDw5YNWxh8rHwYGMQZGB5PfszAysq6RUJCAmLAtCR1DAMCu08zzJSZxtDm0cbA8AQoyAxJGyDbWx+2MrCwsGyRkZGBGDApDpsBx8FhME95HkObfhtYM4MqA8OdnjtgNSAXyMvLQwzoi8JmwGF4NGoc12Bg6IHYXnuzFm6AsrIyxIAJ+UHXfj27oomIhc9AA/ajpAOdPToMV1yuwPnMzMxbNDU14QaEAqnGH28fqYGywt/fP5i8q5czYUtIMABygY6ODsSAJUuWOKMrUFHT2PPvzy90YZhX/79//36dt7d3KACPfPJHOU7GxAAAAABJRU5ErkJggg=="; let cIDs = ["custombuttons-contextpopup-exportXML", "custombuttons-contextpopup-exportXML-sub"]; let bIDs = ["custombuttons-contextpopup-bookmarkButton", "custombuttons-contextpopup-bookmarkButton-sub"]; addMenuItem(cIDs, bIDs, "Сохранить код кнопки в XML файл", saveImg9, "document.getElementById('" + this.id + "').saveXML(('triggerNode' in this.parentNode) " + "? this.parentNode.triggerNode.URI " + ": document.popupNode.URI);", "X"); let xIDs = ["custombuttons-contextpopup-importnewbutton", "custombuttons-contextpopup-importnewbutton-sub"]; let aIDs = ["custombuttons-contextpopup-addnewbutton", "custombuttons-contextpopup-addnewbutton-sub"]; addMenuItem(xIDs, aIDs, "Добавить кнопку из XML файла\u2026", loadImg, "document.getElementById('" + this.id + "').loadXML();"); let fIDs = ["custombuttons-contextpopup-copyImageURI", "custombuttons-contextpopup-copyImageURI-sub"]; let b2IDs = ["custombuttons-contextpopup-copyURI", "custombuttons-contextpopup-copyURI-sub"]; addMenuItem(fIDs, b2IDs, "Копировать изображение кнопки в формате base64", saveImg1, "document.getElementById('" + this.id + "').copyImageURI();"); let f1IDs = ["custombuttons-contextpopup-saveButtonImage", "custombuttons-contextpopup-saveButtonImage-sub"]; addMenuItem(f1IDs, cIDs, "Сохранить изображение кнопки", saveImg8, "document.getElementById('" + this.id + "').saveImageURI();"); let f2IDs = ["custombuttons-contextpopup-copyButtonsCodeText", "custombuttons-contextpopup-copyButtonsCodeText-sub"]; addMenuItem(f2IDs, b2IDs, "Копировать код кнопки как текст", saveImg2, "document.getElementById('" + this.id + "').copyButtonsCodeText();"); let f3IDs = ["custombuttons-contextpopup-copyAsHTML", "custombuttons-contextpopup-copyAsHTML-sub"]; addMenuItem(f3IDs, b2IDs, "Копировать код кнопки как HTML ссылку", saveImg3, "document.getElementById('" + this.id + "').copyToHTMLCode();"); let f4Ds = ["custombuttons-contextpopup-copyToBBCode", "custombuttons-contextpopup-copyToBBCode-sub"]; addMenuItem(f4Ds, b2IDs, "Копировать код кнопки как BBcode сылку", saveImg4, "document.getElementById('" + this.id + "').copyToBBCode();"); let f5Ds = ["custombuttons-contextpopup-saveAsHTML", "custombuttons-contextpopup-saveAsHTML-sub"]; addMenuItem(f5Ds, bIDs, "Сохранить код кнопки в HTML файл", saveImg5, "document.getElementById('" + this.id + "').saveToHTMLCode();"); let f8Ds = ["custombuttons-contextpopup-saveAsHTMLAll", "custombuttons-contextpopup-AsHTMLAll-sub"]; addMenuItem(f8Ds, f5Ds, "Сохранить все кнопки в HTML файл", saveAll, "document.getElementById('" + this.id + "').saveToHTMLALLCode()"); let f6Ds = ["custombuttons-contextpopup-getButtonId", "custombuttons-contextpopup-getButtonId-sub"]; let b1IDs = ["custombuttons-contextpopup-remove", "custombuttons-contextpopup-remove-sub"]; addMenuItem(f6Ds, b1IDs, "Показать Id кнопки", saveImg6, "document.getElementById('" + this.id + "').idMIonclick(window.document);"); let f7Ds = ["custombuttons-contextpopup-addNextButton", "custombuttons-contextpopup-addNextButton-sub"]; var addMI = document.getElementById('custombuttons-contextpopup-addnewbutton'); addMI.setAttribute('image', iconADD); var addMI1 = document.getElementById('custombuttons-contextpopup-addnewbutton-sub'); addMI1.setAttribute('image', iconADD); var addMI2 = document.getElementById('custombuttons-contextpopup-move-moveToPanel'); addMI2.setAttribute('image', moveToMenu); var addMI3 = document.getElementById('custombuttons-contextpopup-move-removeFromToolbar'); addMI3.setAttribute('image', removeFromToolbar); var addMI4 = document.getElementById('custombuttons-contextpopup-customize'); addMI4.setAttribute('image', customBtn); //var addMI5 = document.getElementById('custombuttons-contextpopup-remove'); //addMI5.setAttribute('label', 'Удалить...'); ///////////////////////////////////////////////////////////////////////////// /////////////////////////////// Общие функци //////////////////////////////// ///////////////////////////////////////////////////////////////////////////// var options1 = {year: "numeric"}; var options2 = {day: "numeric", month: "long"}; var cDate = new Date().toLocaleDateString("ru-RU", options1); var dDate = new Date().toLocaleDateString("ru-RU", options2); var aDate = cDate + "г" + " " + dDate; var options3 = {weekday: "long", year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", hour12: false}; var bDate = new Date().toLocaleDateString("ru-RU", options3); var saveToFile = function (fileContent, fileName) { var uc = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); uc.charset = 'utf-8'; fileContent = uc.ConvertFromUnicode(fileContent); var nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker); fp.init(window, '', fp.modeSave); fp.defaultString = fileName; fp.appendFilters(fp.filterHTML); fp.appendFilters(fp.filterAll); fp.open(function (rv) { if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { var stream = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream); stream.init(fp.file, 0x02|0x20|0x08, 0666, 0); stream.write(fileContent, fileContent.length); stream.close(); } }); }; function mostRecentWindow(windowType) { return Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow(windowType); }; ///////////////////////////////////////////////////////////////////////////// ////////////////////////////Остальные функци //////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /////////////////////////////// Показать Id кнопки /////////////////////////////// this.idMIonclick = function idMIonclick() { var btn = custombuttons.popupNode.id; var box = custombuttons.confirmBox("Копировать в буфер", btn, "Да", "Нет"); if (box) { custombuttons.cbService.writeToClipboard(btn); custombuttons.alertSlide(btn, "Скопирована в буфер"); } } /////////////////////////////// Копировать изображение кнопки в формате base64 /////////////////////////////// this.copyImageURI = function copyImageURI() { var btn = custombuttons.popupNode; if (!btn) return; cbu.gClipboard.write(btn.image); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "Изображение кнопки скопировано в буфер", false, "", null); } /////////////////////////////// Копировать код кнопки как текст /////////////////////////////// this.copyButtonsCodeText = function copyButtonsCodeText() { var btn = custombuttons.popupNode; if (!btn) return; var code = ((btn.cbCommand == "") || (btn.Command == "/*CODE*/")) ? "" : ("\n/*CODE*/\n" + btn.cbCommand + "\n"); var init = ((btn.cbInitCode == "") || (btn.cbInitCode == "/*Initialization Code*/")) ? "" : ("\n/*Initialization Code*/\n" + btn.cbInitCode); cbu.gClipboard.write(code + init); //custombuttons.alertSlide(btn.name, "Код скопирван в буфер"); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "Код скопирван в буфер", false, "", null); } /////////////////////////////// Копировать код кнопки как HTML ссылку /////////////////////////////// this.copyToHTMLCode = function copyToHTMLCode() { var btn = custombuttons.popupNode; if (!btn) return; var code = "<p><div id=\"install\" style=\"background: transparent -moz-linear-gradient(center top , rgb(224, 102, 255) 30%, rgb(125, 38, 205) 55%); text-shadow: 0pt -1px 0pt rgb(122, 55, 139); border: 1px outset rgb(85, 26, 139); border-radius: 1em; padding: 0; width: 240px; text-align: center;\"><a href=\"" + btn.URI + "\" style=\"display: block; padding: 1em; color: #ffffff; text-decoration: none;\" title=\"Click here to install " + btn.name + "\" rel=\"nofollow\"><img src=\"" + btn.image + "\" alt=\"" + btn.name + "\" style=\"vertical-align: middle; float: left;\"/>" + btn.name + "</a></div></p>"; cbu.gClipboard.write(code); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "HTML кнопки скопирован в буфер", false, "", null); } /////////////////////////////// Копировать код кнопки как BBcode сылку /////////////////////////////// this.copyToBBCode = function copyToBBCode() { var btn = custombuttons.popupNode; if (!btn) return; var code = "[url=" + btn.URI + "][B]" + btn.name + "[/B][/url]"; cbu.gClipboard.write(code); //.toXMLString()); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "BBCode кнопки скопирован в буфер", false, "", null); } /////////////////////////////// Сохранить изображение кнопки custombutton /////////////////////////////// this.saveImageURI = function saveImageURI() { var gb = gBrowser; var remove = gb.removeCurrentTab.bind(gb); var promiseTargetFile = async (...args) => { var info = args[0].fileInfo; info.fileName = `${gb.selectedTab.label}.${info.fileExt}`; var res = await window.promiseTargetFile(...args); setTimeout(remove, 0); return res; } var internalSave = eval(`(${window.internalSave})`); var saveBrowser = eval(`(${window.saveBrowser})`); var save = (tab, name) => { (gb.selectedTab = tab).label = name; saveBrowser(tab.linkedBrowser); } (self.saveImageURI = () => { var btn = custombuttons.popupNode; if (!btn) return; if (btn.image == "") return custombuttons.alertBox("Эта кнопка не имеет изображения!"); var tab = gb.selectedTab = gb.addTrustedTab(btn.image); setTimeout(save, 2e3, tab, btn.name || "image"); })(); } /////////////////////////////// Сохранить кнопку в XML файл /////////////////////////////// this.saveXML = function saveXML(aStrURI) { var cbURI = (aStrURI != undefined) ? aStrURI : readFromClipboard(); if (!cbURI || !/^custombutton\:\/\//.test(cbURI)) { custombuttons.uChelpButton(this); return; } var topicURL = "http://forum.mozilla-russia.org/viewforum.php?id=34" var cbXML = cbURI.replace(/^custombutton\:\/\//, ""); var decodeXML = unescape(cbXML); var btnName = decodeXML.match(/\<name\/?.+/).toString(); var name = "untitled"; if (!/\<name\/\>/.test(btnName)) { name = btnName.replace(/\<\/?\w+\>/g, "").toString(); } var image = decodeXML.match(/\<image\/?.+/).toString(); var icon = ""; if (!/\<\image.*\[\].*\>$/.test(image)) { icon = image.match(/[^\[\]]+/g)[2].toString() .replace(/custombuttons\-stdicon\-\d/, "").toString(); } function htmlEntities(str) { return str.replace(/&/g, "&").replace(/</g, "<") .replace(/>/g, ">").replace(/"/g, """); } var xmlTemplate = "custombuttons/\"\n\ xmlns:html=\"http://www.w3.org/1999/xhtml\">\n\ <html:head>\n\ <html:title><![CDATA[" + name + "]]></html:title>\n\ <html:link rel=\"shortcut icon\" href=\"" + icon + "\"/>\n\ <html:style type=\"text/css\"><![CDATA[\n\ body { font-size: medium; margin: 0; }\n\ body, code:before, help:before, initcode:before {\n\ font-family: \"Verdana\", sans-serif;\n\ }\n\ #wrapper { position: fixed; top: 1em; right: 1em; text-align: center; }\n\ p { font-size: small; text-align: center; }\n\ #button {\n\ background-color: rgb(85, 168, 2);\n\ background-image: linear-gradient(to bottom, rgb(147, 200, 94),\ rgb(85, 168, 2));\n\ background-image: -moz-linear-gradient(top, rgb(147, 200, 94),\ rgb(85, 168, 2));\n\ background-image: -o-linear-gradient(top, rgb(147, 200, 94),\ rgb(85, 168, 2));\n\ background-image: -webkit-linear-gradient(top, rgb(147, 200, 94),\ rgb(85, 168, 2));\n\ border: 1px solid rgb(58, 116, 4);\n\ border-radius: .5em;\n\ -moz-border-radius: .5em;\n\ -webkit-border-radius: .5em;\n\ padding: 0;\n\ margin-bottom: 1em;\n\ box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\ -moz-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\ -o-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\ -webkit-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25);\n\ }\n\ #button a {\n\ color: #000;\n\ text-shadow: -1pt -1px 0pt rgba(255, 255, 255, .5);\n\ padding: 1em;\n\ text-decoration: none;\n\ }\n\ :-moz-any-link:focus {\n\ color: white;\n\ outline-color: transparent;\n\ text-decoration: none;\n\ }\n\ #button a, code, code:before, initcode, initcode:before, help, help:before {\ \n display: block;\n\ }\n\ #credits { position: fixed; bottom: 1em; right: 1em; font-size: small; }\n\ custombutton { background-color: rgb(171, 171, 171); margin: 1em; }\n\ date, image, mode, accelkey { display: none; }\n\ name { font-weight: bold; font-size: x-large; }\n\ code:before, help:before, initcode:before {\n\ font-weight: bold;\n\ font-size: large;\n\ margin: 0 0 1em;\n\ padding: .5em;\n\ }\n\ code:before { content: \"Код\"; }\n\ help:before { content: \"Справка\"; }\n\ initcode:before { content: \"Инициализация\"; }\n\ code, initcode, help {\n\ background-color: rgb(255, 255, 255);\n\ border: 1px inset rgb(170, 170, 170);\n\ font: medium monospace;\n\ margin: 1em 1em 2em 0;\n\ padding: 1em;\n\ text-align: left;\n\ width: 840px;\n\ white-space: pre-wrap;\n\ word-wrap: break-word;\n\ }\n\ .clear { clear: both; }\n\ ]]></html:style>\n\ </html:head>\n\ <html:body>\n\ <html:div id=\"wrapper\">\n\ <html:div id=\"button\">\n\ <html:a href=\"" + cbURI + "\" rel=\"nofollow\" title=\"Установить " + htmlEntities(name, "ENT_COMPAT") +"\">\n\ <![CDATA[Установить кнопку]]>\n\ </html:a>\n\ </html:div>\n\ <html:div id=\"credits\">\n\ <html:a href=\"" + topicURL +"\">\n\ <![CDATA[Другие кнопки]]><html:br/>\ <![CDATA[на форуме Mozilla Россия]]>\n\ </html:a>\n\ </html:div>\n\ </html:div>\n\ </html:body>"; decodeXML = decodeXML.replace(/custombuttons\/\"\>/, xmlTemplate); name += ".xml"; saveToFile(decodeXML, name); var btn = document.popupNode; var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "сохранена в XML файл", false, "", null); } var mrw = mostRecentWindow('navigator:browser'); var css = '@-moz-document url("chrome://browser/content/browser.xhtml"){' + this.Help + '}'; var uri = makeURI('data:text/css,' + encodeURIComponent(css)); var sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService); if (!sss.sheetRegistered(uri, sss.USER_SHEET)) sss.loadAndRegisterSheet(uri, sss.USER_SHEET); /////////////////////////////// Добавить кнопку из XML файл /////////////////////////////// this.loadXML = function loadXML() { var nsIFilePicker = Ci.nsIFilePicker; var fp = window.makeFilePicker(); fp.init(window, "Установить кнопку из XML файла", nsIFilePicker.modeOpen); fp.appendFilters(fp.filterXML); fp.appendFilter("Все файлы", "*.*"); fp.open(re=> { if ( re == fp.returnOK ) gBrowser.selectedTab = gBrowser.addTrustedTab(fp.file.path); }) } /////////////////////////////// Сохранить все кнопки в HTML файл /////////////////////////////// this.saveToHTMLALLCode = function saveToHTMLALLCode() { var visibleCBbuttons = [...document.querySelectorAll('[cb-mode]')]; var paletteCBbuttons = [...custombuttons.palette.querySelectorAll('[cb-mode]')]; var allCBbuttons = visibleCBbuttons.concat(paletteCBbuttons); var gn = btn => btn.getAttribute("label") || "Без названия"; allCBbuttons.sort((a, b) => gn(a).localeCompare(gn(b))); var array = []; allCBbuttons.forEach(but=> { var uri = but.URI ? but.URI : getPaleteButtonsURI(but); var name1 = but.getAttribute("label") || "Без названия"; var image = but.getAttribute("image") || "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACNFBMVEXDRgDweQDnbwC0NgDCRQC7PQDtpTu+QQD78q3PUwDCRAD//8vbYQDLTgDocAD0iQX1jQbGSgD7iAD4gwDVaw7vdwDyegD+igDweQDlawDyhAXveADmZwDzmBbtcwDwkhHveADmhBTkgxbweADkfRH+igD7hADXZQX0gADyjA/tfgvveQDiawDQVADRXgfnbwD1jAb9iQD9z0PVZAbxpinykRHtdgD5mRbERQDDRgDOYArCRAD9iQD3ewDxegD3dwDFRgDAQAD+hgD4fQDucgDtgQftfwTISQDCRQDvdgD5lxb1kRb2qh7wnynkagD766LDRQDDRwDDRQDspjbtpzbuqDbvqzv//8DUZAbCRQD//83pjhvveQbvggW+QQDfcxLlmUb//8veYADMTwDHSADVVwC8PgDwixb78q3oZgDUWADRVADCRQD9iQDERwDBQQDYVQC+PgC0NgDbYQDWWgDUWADSVQDFSAC+QAC7PAC0NgD+wRL+/kD+/zb+7i3+8Cv+/DX+wBL/+DD/rwz+qgz+rwz/tAz+sQzfbAT+3iP/+jD//Dz1jwP+nwf5iwf7pBz2tRr4lwb/ogfsdQT+2R7/9ET+2iT8yyLmgBL5iQL2egLokhP7zzT60zv1zUr0gAL1ewP50yn9+UL++EXooyngaAH41EPzowzyySj+xxzlhhHvvyruwjXxvTnUag3+zxrwigP+swz86U/ZXwD75lHqegD6xzb//kn+uhPTXAG3OAD/+UC2vFeJAAAAe3RSTlMAAAAAAAAAAAAAAAAAAAAAAAAAAACfnwAIaelpAAA2+wD7UQAAa3oArKzRzMysnwgAvPQA/gAAw3prw0oALr16vS4AACnF6bspAAAA/mIAADQAAAAAAI8AAEwA0vv7kd2yAuuvr+vKABL23U+8Sk/d9vUDIIAQAAAQgCAfvupHAAABB0lEQVR4Xi3IU3fDABgA0C+u26FdZ9u2bdu2vZSzbds2/tyac3IfLxjpGyA6MimqY6gHTNgiiNwkwRM1E7EhTrYyTfMzzsh0ZEPiH+D6+u5mV1jEhpe5haVCYW1T4suEvUOkk7PLpVJ5WFnl7hEUDN5LPvsHJ6cazdn13f3DYxu0B35+/Y2qVSr17NzGeUgohIVHLK/PMDa39qKieRATGxd/9cS4uU1MwnmQktqY/qGlaVr7/ZOVDTmQm5df8PwyNj4xOTVdjOM4kCRZOr+wWFa+srpWQVEU8PnV2zu7NbV19UfHDQRBAIfTdNHc0soVdnR2dfdgGAgEvW99/QNc4eDQ8O8Ihv0D77NPgbVLZ6kAAAAASUVORK5CYII="; array.push("<li>\n<img src=" + image + "> \<a href=" + uri + ">" + name1 +"</a><br>\n"); }); var before = "<html>\n<head>\n<title>Custom Buttons</title>\n<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>\n"; var before1 = "<style type='text/css'>\nbody {background: beige;} a:link {color: black; text-decoration: none;} img {border: 0; margin: 0px 10px;}\n</style>\n"; var before2 = "</head>\n<body>\nCustom Buttons\n<p>\n"; var info = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo); var before3 = info.vendor + " " + info.name + " " + info.version + " (build " + info.appBuildID + ")\n"; var after = "\n</ol>\n</body>\n</html>"; var text = before + before1 + before2 + before3 + "<p>\n" + bDate + "<p>\n" + "<ol>" + array.join("") + after; var name = "CB buttons " + aDate + ".html" saveToFile(text, name); var alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) alertsService.showAlertNotification(saveImg5, "Экспорт в HTML", "Экспортировал все CB кнопки как HTML"); setTimeout(()=> alertsService.closeAlert(), 4000); }; function getPaleteButtonsURI(but) { var uri = "chrome://custombuttons/content/nbftemplate.xml"; var stream = NetUtil.newChannel({uri, loadUsingSystemPrincipal: true}).open(); var doc = new DOMParser().parseFromStream(stream, null, stream.available(), "application/xml"); stream.close(); ["help,Help", "name,label", "image,image", "mode,cb-mode", "initcode,cb-init", "accelkey,cb-accelkey", "code,cb-oncommand"] .forEach(str=> { var arr = str.split(','); var value = but.getAttribute(arr[1]), name = arr[0]; custombutton.buttonSetText(doc, name, value, true); }); var ser = new XMLSerializer(); return "custombutton://" + escape(ser.serializeToString(doc)); }; /////////////////////////////// Сохранить кнопку в HTML файл /////////////////////////////// this.saveToHTMLCode = function saveToHTMLCode() { var btn = custombuttons.popupNode; var xml = '<html xmlns="' + xhtmlns + '">\n'; xml += '<head>\n'; xml += '<meta http-equiv = "Content-Type" content = "text/html; charset=utf-8"/>\n'; xml += '<title> ' + btn.name + ' для Custom Buttons </title>\n'; xml += '<link rel="icon" type="image/vnd.microsoft.icon" href = "'+ btn.image +'" />\n'; xml += '<style type="text/css">\n'; xml += '.button a{ \n'; xml += 'background-color: rgb(85, 168, 2); \n'; xml += 'background-image: linear-gradient(to bottom, rgb(147, 200, 94), rgb(85, 168, 2)); \n'; xml += 'background-image: -moz-linear-gradient(top, rgb(147, 200, 94), rgb(85, 168, 2)); \n'; xml += 'border: 1px solid rgb(58, 116, 4); \n'; xml += 'border-radius: .5em; \n'; xml += ' -webkit-border-radius: .5em; \n'; xml += 'padding: 0; \n'; xml += 'margin-bottom: 1em; \n'; xml += 'box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n'; xml += ' -o-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n'; xml += ' -webkit-box-shadow: 1px 2px 3px rgba(0, 0, 0, .25); \n'; xml += ' color: #000; \n'; xml += ' text-shadow: -1pt -1px 0pt rgba(255, 255, 255, .5); \n'; xml += ' padding: 0.5em; \n'; xml += ' text-decoration: none; \n'; xml += '} '; xml += 'pre { border: 1px inset rgb(170, 170, 170); \n'; xml += 'background-color: rgb(255, 255, 255);} \n'; xml += 'body { background-color: rgb(245, 245, 220);} \n'; xml += '</style> \n'; xml += '</head>\n'; xml += '<body>\n'; xml += '<section id="install"><h1> ' + btn.name + ' </h1> \n'; xml += '</section>\n'; xml += '<div class="button"><a href = "' + btn.URI + '">Установить кнопку</a></div> \n'; xml += '<section id="init"><h2>Инициализация</h2><pre>' + e4xConv_encodeHTML(btn.cbInitCode) + '</pre></section>\n'; xml += '<section id="code"><h2>Код</h2><pre>' + e4xConv_encodeHTML(btn.cbCommand) + '</pre></section> \n'; xml += '<section id="help"><h2>Справка</h2><pre>' + e4xConv_encodeHTML(btn.Help) + '</pre></section> \n'; xml += '</body> \n'; xml += '</html> '; var html = '<!DOCTYPE html>\n' + xml; var name = btn.name + ".HTML"; saveToFile(html, name); var as = Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService); as.showAlertNotification(btn.image, "Кнопка: " + btn.name, "сохранена в HTML файл", false, "", null); } function e4xConv_encodeHTML(s, isAttr) { s = String(s) .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """); if(isAttr) { s = s .replace(/\t/g, "	") .replace(/\n/g, "
") .replace(/\r/g, "
"); } return s; }; /////////////////////////////// Переместить кнопку /////////////////////////////// this.MoveToolbarButtons = MTB = { // Start editable preferences MoveButtonMICBContext: true, // Add "Move button" menu item to Custom Buttons context menu? MoveButtonMITBarContext: false, // Add "Move button" menu item to toolbars context menu? ShowMoveAlert: false, // Show the alert with instructions when moving buttons? MoveBtnImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAYklEQVQ4jWNgGJTgaAXHf2LEcGrGZQBBQ45WcPz/fZ0XpwG45FAUEDIAqzyyJLIiZIxNHqdmYvHRCo7/DLhsIEYziivQDcHnBawxgqyQUCzgjQlC6YCotEB2QkJWTIzY4AAAezv/caeCLKcAAAAASUVORK5CYII=", // End editable preferences _UID: "__cb_move_toolbar_buttons_" + custombuttons.getNumber(self.id), WindowIDs: ["main-window", "messengerWindow", "msgcomposeWindow"], ToolbarContexIDs: ["toolbar-context-menu", "aios-toolbar-contextmenu", "aios-sbhtoolbar-contextmenu"], Pref: "extensions.custombuttons.MoveToolbarButtons.Id" + custombuttons.getNumber(self.id) + ".MoveButtonID", SP: Services.prefs, Init: function() { if (!(MTB._UID in window)) { window[MTB._UID] = { Initialized: false }; } if (!window[MTB._UID]["Initialized"]) { window[MTB._UID]["Initialized"] = true; custombuttons.isPref(MTB.Pref, ""); if ("CustomizableUI" in window) { var originalFunction = custombuttons.persistCurrentSets.toString(); eval("custombuttons.persistCurrentSets=" + originalFunction .replace(", newButtonId)", ", newButtonId, aToRight)") .replace("pos + 1", "aToRight ? pos : pos + 1")); } if (MTB.MoveButtonMICBContext) { var contextPops = document.getElementsByTagName("menupopup"); let p = 0, pLen = contextPops.length; for (; p < pLen; p++) { var cPopID = contextPops[p].id; if (cPopID.substr(0, 26) === "custombuttons-contextpopup") { var cPopEl = document.getElementById(cPopID); var moveMIID = "custombuttons-contextpopup-moveButton" + cPopID.slice(26); var moveMIEl = document.getElementById(moveMIID); if (!moveMIEl) MTB.CreateMoveMI(moveMIID, cPopEl); } } } if (MTB.MoveButtonMITBarContext) { Array.prototype.slice.call(MTB.ToolbarContexIDs).forEach(function(aTBCtxID, aIndex) { let Ctx = document.getElementById(aTBCtxID); let tBarCtxMIID = MTB._UID + "moveButton" + aIndex; if (!document.getElementById(tBarCtxMIID)) { if (Ctx) { MTB.CreateMoveMI(tBarCtxMIID, Ctx); Ctx.addEventListener("popupshowing", function(aE) { document.getElementById(tBarCtxMIID).hidden = (document.popupNode.tagName !== "toolbarbutton"); }, false); } } }); } addDestructor(function(aReason) { if (aReason === "delete") { SP.resetUserPrefs(MTB.Pref); delete window[_UID]; } if (aReason === "delete" || aReason === "update") { window[MTB._UID]["Initialized"] = false; } }); } }, getPopupNode: function(aEl) { if (custombuttons.popupNode) return custombuttons.popupNode; var popupNode = aEl; while (popupNode.tagName.toLowerCase() !== "toolbarbutton") { popupNode = popupNode.parentNode; } return popupNode; }, CreateMoveMI: function(aMItemID, aPopupEl) { let moveMIEl = aPopupEl.appendChild(document.createElementNS(xulns, "menuitem")); moveMIEl.setAttribute("id", aMItemID); moveMIEl.setAttribute("label", "Переместить кнопку..."); moveMIEl.setAttribute("class", "menuitem-iconic"); moveMIEl.setAttribute("image", MTB.MoveBtnImage); moveMIEl.setAttribute("tooltip", MTB._UID + "moveButtonMI_tooltip"); moveMIEl.setAttribute("onclick", "document.getElementById(\"" + self.id + "\").MoveToolbarButtons.MoveOnClick(event);"); }, MoveOnClick: function(aE) { var popupNode = MTB.getPopupNode(aE.target); if (!popupNode) return; aE.stopPropagation(); aE.preventDefault(); if (aE.button === 0 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey) { MTB.SP.setCharPref(MTB.Pref, popupNode.id); window.addEventListener('click', MTB.MoveListener, true); window.addEventListener('mouseup', MTB.DefaultPrevention, true); window.addEventListener('mousedown', MTB.DefaultPrevention, true); window.addEventListener('contextmenu', MTB.DefaultPrevention, true); MTB.HidePopup(aE.target); MTB.ShowMoveAlert && Services.prompt.alert(null, self.name, "Now click ANY toolbarbutton element inside ANY toolbar.\n" + "Left click will position the button to the left of the target.\n" + "Right click will position the button to the right of the target.\n\n" + "To cancel the movement, just click ANY element inside the browser that IS NOT a toolbarbutton.\n"); } }, MoveListener: function(aE) { MTB.DefaultPrevention(aE); window.removeEventListener('click', MTB.MoveListener, true); window.removeEventListener('mouseup', MTB.DefaultPrevention, true); window.removeEventListener('mousedown', MTB.DefaultPrevention, true); window.removeEventListener('contextmenu', MTB.DefaultPrevention, true); var anchor = aE.target; if (anchor.tagName !== "toolbarbutton") return; var toolbar = anchor.parentNode; var BtnToMove = document.getElementById(MTB.SP.getCharPref(MTB.Pref)); if (aE.button === 0 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey) toolbar.insertBefore(BtnToMove, anchor); else if (aE.button === 2 && !aE.shiftKey && !aE.ctrlKey && !aE.altKey) toolbar.insertBefore(BtnToMove, anchor.nextSibling); if ("CustomizableUI" in window) custombuttons.persistCurrentSets(toolbar.id, anchor.id, BtnToMove.id || BtnToMove.getAttribute("id"), !(aE.button === 2)); else { toolbar.setAttribute("currentset", toolbar.currentSet); document.persist(toolbar.id, "currentset"); } MTB.SP.setCharPref(MTB.Pref, ""); }, DefaultPrevention: function(aE) { aE.preventDefault(); aE.stopImmediatePropagation && aE.stopImmediatePropagation(); aE.stopPropagation(); }, Tooltips: function(aRem) { var popSetID = MTB._UID + "popupset"; var popSetEl = document.getElementById(popSetID); if (popSetEl) popSetEl.parentNode.removeChild(popSetEl); if (aRem) return; if (!popSetEl) { popSetEl = document.createElementNS(xulns, "popupset"); popSetEl.setAttribute("id", popSetID); } popSetEl.appendChild(MTB.parseXML("<tooltip xmlns=\"" + xulns + "\" xmlns:html=\"" + xhtmlns + "\" id=\"" + MTB._UID + "moveButtonMI_tooltip" + "\">" + "<description><html:b>Instructions</html:b> : After clicking this menu item, you can " + "click ANY toolbarbutton element inside the application to place the currently " + "selected button to the left (with Left click) or to the right (with Right click) " + "of the targeted toolbarbutton.</description>" + "<separator/>" + "<description><html:b>Note</html:b> : It can be ANY toolbarbutton, not just " + "other Custom Buttons.</description>" + "</tooltip>")); setTimeout(function() { Array.prototype.slice.call(MTB.WindowIDs).forEach(function(aWinID) { let win = document.getElementById(aWinID); if (win) !document.getElementById(popSetID) && win.appendChild(popSetEl); }); }, 100); }, parseXML: function(aXML) { // Return parsed XML aXML = aXML.replace(/>\s+</g, "><"); // Linearize XML return (new DOMParser).parseFromString(aXML, "application/xml").documentElement; }, HidePopup: function(aEl) { try { aEl.hidePopup(); } catch (aError) { try { aEl.parentNode.hidePopup(); } catch (aError) { try { aEl.parentNode.parentNode.hidePopup(); } catch (aError) { try { aEl.parentNode.parentNode.parentNode.hidePopup(); } catch (aError) {} } } } } }; this.MoveToolbarButtons.Init();
На форуме
Да, работает на 114. Премного благодарен.
Добавлено 01-06-2023 15:22:42
Andrey_Krropotkin
Если можно, еще один вопрос.
Нужна рабочая версия [CB]Toggle Restartless Add-ons
Отредактировано Garalf (01-06-2023 15:24:22)
Отсутствует
Garalf у меня на 113 такая
// http://infocatcher.ucoz.net/js/cb/toggleRestartlessAddons.js // https://forum.mozilla-russia.org/viewtopic.php?id=57948 // https://github.com/Infocatcher/Custom_Buttons/tree/master/Toggle_Restartless_Add-ons // Toggle Restartless Add-ons button for Custom Buttons // (code for "initialization" section) // Also the code can be used from main window context (as Mouse Gestures code, for example) // Also you can check for add-ons updates using right-click: // copy all code from // https://github.com/Infocatcher/Custom_Buttons/blob/master/Check_for_Addons_Updates/checkForAddonsUpdates.js // after "//== Check for Addons Updates begin" // See "var style = " to modify styles for specific add-ons // (c) Infocatcher 2013-2019 // version 0.1.3pre4 - 2020-01-01 var options = { addonTypes: ["extension"], // Possible values: "extension", "plugin" // From extensions: "userstyle" (Stylish), "greasemonkey-user-script" (Greasemonkey), "userscript" (Scriptish) // (swap to reorder in the menu) showVersions: 1, // 0 - don't show versions // 1 - show after name: "Addon Name 1.2" // 2 - show as "acceltext" (in place for hotkey text) showHidden: 0, // 0 - don't show hidden add-ons // -1 - show only enabled hidden add-ons (e.g. to track new items) // 1 - show all hidden add-ons sort: { enabled: 0, clickToPlay: 0, disabled: 1 // Sort order: // 0, 0, 0 - sort add-ons of each type alphabetically // 0, 0, 1 - show enabled add-ons (of each type) first // 0, 1, 2 - enabled add-ons, then click-to-play and then disabled }, closeMenu: false, // Close menu after left-click closeMenuClickToPlay: false // Close menu after left-click, for click to play plugins // Use Shift+click to invert closeMenu* behavior }; var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var mp = document.createElementNS(xulns, "menupopup"); mp.setAttribute("onpopupshowing", "this.updateMenu();"); mp.setAttribute("oncommand", "this.handleEvent(event);"); mp.setAttribute("onmousedown", "if(event.button == 0) this.handleEvent(event);"); mp.setAttribute("onclick", "if(event.button > 0) this.handleEvent(event);"); mp.setAttribute("oncontextmenu", "return false;"); mp.setAttribute("onpopuphidden", "this.destroyMenu();"); var tb = this.parentNode; if(tb && tb.getAttribute("orient") == "vertical") { // https://addons.mozilla.org/firefox/addon/vertical-toolbar/ var isRight = tb.parentNode.getAttribute("placement") == "right"; mp.setAttribute("position", isRight ? "start_before" : "end_before"); } var cleanupTimer = 0; mp.updateMenu = function() { clearTimeout(cleanupTimer); addStyle(); getRestartlessAddons(options.addonTypes, function(addons) { var df = document.createDocumentFragment(); var prevType; function sortPosition(addon) { if("STATE_ASK_TO_ACTIVATE" in AddonManager && addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE) return options.sort.clickToPlay; if(addon.isActive) return options.sort.enabled; return options.sort.disabled; } function key(addon) { return options.addonTypes.indexOf(addon.type) + "\n" + sortPosition(addon) + "\n" + addon.name.toLowerCase(); } addons.sort(function(a, b) { var ka = key(a); var kb = key(b); return ka == kb ? 0 : ka < kb ? -1 : 1; }).forEach(function(addon) { var type = addon.type; if(prevType && type != prevType) df.appendChild(document.createElementNS(xulns, "menuseparator")); prevType = type; var icon = addon.iconURL || addon.icon64URL; var mi = document.createElementNS(xulns, "menuitem"); mi.className = "menuitem-iconic"; var label = addon.name; if(options.showVersions == 1) label += " " + addon.version; else if(options.showVersions == 2) mi.setAttribute("acceltext", addon.version); mi.setAttribute("label", label); mi.setAttribute("image", icon || mp.icons[type] || ""); if(!icon && mp.icons.useSVG) mi.style.fill = "#15c"; var tip = addon.description || ""; var delay = "delayedStartupAddons" in Services && Services.delayedStartupAddons[addon.id] || null; var isDelayed = delay !== null; mi.classList.toggle("toggleRestartlessAddons-isDelayed", isDelayed); if(isDelayed) tip = "[Delayed Startup: " + delay.toLocaleString() + "]" + (tip ? "\n" + tip : ""); tip && mi.setAttribute("tooltiptext", tip); mi.classList.toggle("toggleRestartlessAddons-isHidden", addon.hidden || false); setDisabled(mi, addon.userDisabled); mi._cbAddon = addon; df.appendChild(mi); }); mp.textContent = ""; mp.appendChild(df); }); }; mp.handleEvent = function(e) { var mi = e.target; if(!("_cbAddon" in mi)) return; var addon = mi._cbAddon; if(e.type == "mousedown") { var closeMenu = isAskToActivateAddon(addon) ? options.closeMenuClickToPlay : options.closeMenu; if(e.shiftKey) closeMenu = !closeMenu; mi.setAttribute("closemenu", closeMenu ? "auto" : "none"); return; } var hasMdf = hasModifier(e); if(e.type == "command" && (!hasMdf || e.shiftKey)) { let newDis = setNewDisabled(addon); setDisabled(mi, newDis); } else if(e.type == "command" && hasMdf || e.type == "click" && e.button == 1) { openAddonPage(addon); closeMenus(mi); } else if(e.type == "click" && e.button == 2) { if(openAddonOptions(addon)) closeMenus(mi); } }; mp.destroyMenu = function() { removeStyle(); clearTimeout(cleanupTimer); cleanupTimer = setTimeout(function() { mp.textContent = ""; }, 5000); }; mp.icons = { get platformVersion() { delete this.platformVersion; return this.platformVersion = parseFloat(Services.appinfo.platformVersion); }, get useSVG() { delete this.useSVG; return this.useSVG = Services.appinfo.name == "Firefox" && this.platformVersion >= 57; }, get plugin() { delete this.plugin; return this.plugin = this.useSVG ? this.platformVersion >= 65 ? "chrome://global/skin/plugins/pluginGeneric.svg" : "chrome://mozapps/skin/plugins/pluginGeneric.svg" : "chrome://mozapps/skin/plugins/pluginGeneric-16.png"; }, get extension() { delete this.extension; return this.extension = this.useSVG ? this.platformVersion >= 76 ? "chrome://mozapps/skin/extensions/extensionGeneric.svg" // Or chrome://mozapps/skin/extensions/extension.svg : "chrome://mozapps/skin/extensions/extensionGeneric-16.svg" : "chrome://mozapps/skin/extensions/extensionGeneric-16.png"; } }; function isAskToActivateAddon(addon) { return addon.type == "plugin" && "STATE_ASK_TO_ACTIVATE" in AddonManager && Services.prefs.getBoolPref("plugins.click_to_play", true); } function setNewDisabled(addon) { var newDis = getNewDisabled(addon); var oldDis = addon.userDisabled; try { addon.userDisabled = newDis; } catch(e) { // Error: Cannot disable hidden add-on firefox@getpocket.com _log("Can't set addon.userDisabled to " + newDis + ", error:\n" + e); if(addon.hidden) setNewDisabledRaw(addon, newDis); } var realDis = addon.userDisabled; if(realDis != newDis && addon.type == "extension") { // Firefox 62+? Weird things happens setNewDisabledRaw(addon, newDis); realDis = addon.userDisabled; } if(realDis != newDis) { // We can't enable vulnerable plugins let err = "Can't set addon.userDisabled to " + newDis + ", real value: " + realDis; if(newDis) { _log(err + "\nSTATE_ASK_TO_ACTIVATE not supported?"); newDis = false; } else { _log(err + "\nVulnerable plugin?"); if(oldDis == AddonManager.STATE_ASK_TO_ACTIVATE) newDis = true; else newDis = AddonManager.STATE_ASK_TO_ACTIVATE; } addon.userDisabled = newDis; } ensureSpecialDisabled(addon, newDis); return addon.userDisabled; } function getNewDisabled(addon) { // disabled -> STATE_ASK_TO_ACTIVATE -> enabled -> ... var curDis = addon.userDisabled; var newDis; if("STATE_ASK_TO_ACTIVATE" in AddonManager && curDis == AddonManager.STATE_ASK_TO_ACTIVATE) newDis = false; else if(!curDis) newDis = true; else { if(isAskToActivateAddon(addon)) newDis = AddonManager.STATE_ASK_TO_ACTIVATE; else newDis = false; } return newDis; } function setNewDisabledRaw(addon, newDis) { _log("Let's try set addon.userDisabled using raw hack"); let g = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {}); if("lazy" in g) g = g.lazy; if("XPIDatabase" in g && "updateAddonDisabledState" in g.XPIDatabase) { // Firefox 61+ let rawAddon = g.XPIDatabase.getAddons().find(function(rawAddon) { return rawAddon.id == addon.id; }); g.XPIDatabase.updateAddonDisabledState( rawAddon, g.XPIDatabase.updateAddonDisabledState.length == 1 // Firefox 74+ ? { userDisabled: newDis } : newDis ); } else if("eval" in g) { // See "set userDisabled(val)" let addonFor = g.eval("addonFor"); let rawAddon = addonFor(addon); //rawAddon.userDisabled = newDis; g.XPIProvider.updateAddonDisabledState(rawAddon, newDis); } else { // Firefox 57+? See https://forum.mozilla-russia.org/viewtopic.php?pid=745272#p745272 updateAddonDisabledState(addon, newDis); } } function updateAddonDisabledState(addon, newDis) { var nsvo = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {}); var key = "_cbToggleRestartlessAddonsData"; var url = URL.createObjectURL(new Blob([ "XPIProvider.updateAddonDisabledState(addonFor(this." + key + "[0]), this." + key + "[1]); delete this." + key + ";" ])); addDestructor(function() { URL.revokeObjectURL(url); }); (updateAddonDisabledState = function(addon, newDis) { nsvo[key] = [addon, newDis]; Services.scriptloader.loadSubScript(url, nsvo); })(addon, newDis); } function setDisabled(mi, disabled) { var askToActivate = "STATE_ASK_TO_ACTIVATE" in AddonManager && disabled == AddonManager.STATE_ASK_TO_ACTIVATE; var cl = mi.classList; cl.toggle("toggleRestartlessAddons-askToActivate", askToActivate); cl.toggle("toggleRestartlessAddons-disabled", disabled && !askToActivate); } function ensureSpecialDisabled(addon, newDis) { if(addon.id == "screenshots@mozilla.org") Services.prefs.setBoolPref("extensions.screenshots.disabled", newDis); } if( this instanceof XULElement // Custom Buttons && typeof event == "object" && !("type" in event) && typeof _phase == "string" && _phase == "init" // Initialization ) { this.type = "menu"; this.orient = "horizontal"; this.appendChild(mp); this.onmouseover = function(e) { if(e.target != this) return; Array.prototype.some.call( this.parentNode.getElementsByTagName("*"), function(node) { if( node != this && node.namespaceURI == xulns // See https://github.com/Infocatcher/Custom_Buttons/issues/28 //&& node.boxObject //&& node.boxObject instanceof Components.interfaces.nsIMenuBoxObject && "open" in node && node.open && node.getElementsByTagName("menupopup").length ) { node.open = false; this.open = true; return true; } return false; }, this ); }; this.onmousedown = function(e) { if(e.target == this && e.button == 0 && hasModifier(e)) e.preventDefault(); }; this.oncontextmenu = function(e) { if(e.target == this && !hasModifier(e) && hasUpdater()) e.preventDefault(); }; this.onclick = function(e) { if(e.target != this) return; if(e.button == 0 && hasModifier(e) || e.button == 1) openAddonsManager(); else if(e.button == 2 && !hasModifier(e) && hasUpdater()) checkForAddonsUpdates.call(this); }; } else { // Mouse gestures or something other... let e; if(typeof event == "object" && event instanceof Event && "screenX" in event) // FireGestures e = event; else if( this instanceof Components.interfaces.nsIDOMChromeWindow && "mgGestureState" in window && "endEvent" in mgGestureState // Mouse Gestures Redox ) e = mgGestureState.endEvent; else { let anchor = this instanceof XULElement && this || window.gBrowser && gBrowser.selectedBrowser || document.documentElement; if("boxObject" in anchor) { let bo = anchor.boxObject; e = { screenX: bo.screenX, screenY: bo.screenY }; if(this instanceof XULElement) e.screenY += bo.height; } } if(!e || !("screenX" in e)) throw new Error("[Toggle Restartless Add-ons]: Can't get event object"); document.documentElement.appendChild(mp); mp.addEventListener("popuphidden", function destroy(e) { mp.removeEventListener(e.type, destroy, false); setTimeout(function() { mp.destroyMenu(); mp.parentNode.removeChild(mp); }, 0); }, false); mp.openPopupAtScreen(e.screenX, e.screenY); } function getRestartlessAddons(addonTypes, callback, context) { if(!("AddonManager" in window)) Components.utils.import("resource://gre/modules/AddonManager.jsm"); if(!("Services" in window)) Components.utils.import("resource://gre/modules/Services.jsm"); var then, promise = AddonManager.getAddonsByTypes(addonTypes, then = function(addons) { callback.call(context, addons.filter(function(addon) { var ops = addon.operationsRequiringRestart; return !addon.appDisabled && !(ops & AddonManager.OP_NEEDS_RESTART_ENABLE || ops & AddonManager.OP_NEEDS_RESTART_DISABLE) && ( !addon.hidden || options.showHidden > 0 || options.showHidden == -1 && !addon.userDisabled ) && (addon.iconURL || "").substr(0, 29) != "resource://search-extensions/"; })); }); promise && typeof promise.then == "function" && promise.then(then, Components.utils.reportError); // Firefox 61+ } function openAddonOptions(addon) { // Based on code from chrome://mozapps/content/extensions/extensions.js // Firefox 21.0a1 (2013-01-27) var optionsURL = addon.optionsURL; if(!addon.isActive || !optionsURL) return false; if(addon.type == "plugin") // No options for now! return false; if( addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE || NaN) || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_INFO || NaN) || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_BROWSER || NaN) ) openAddonPage(addon, true); else if(addon.optionsType == AddonManager.OPTIONS_TYPE_TAB && "switchToTabHavingURI" in window) switchToTabHavingURI(optionsURL, true); else { let windows = Services.wm.getEnumerator(null); while(windows.hasMoreElements()) { let win = windows.getNext(); if(win.document.documentURI == optionsURL) { win.focus(); return true; } } // Note: original code checks browser.preferences.instantApply and may open modal windows window.openDialog(optionsURL, "", "chrome,titlebar,toolbar,centerscreen,dialog=no"); } return true; } function openAddonsManager(view) { var openAddonsMgr = window.BrowserOpenAddonsMgr // Firefox || window.openAddonsMgr // Thunderbird || window.toEM; // SeaMonkey openAddonsMgr(view); } function openAddonPage(addon, scrollToPreferences) { var platformVersion = parseFloat( Services.appinfo.name == "Pale Moon" ? Services.appinfo.version : Services.appinfo.platformVersion ); scrollToPreferences = scrollToPreferences && platformVersion >= 12 ? "/preferences" : ""; openAddonsManager("addons://detail/" + encodeURIComponent(addon.id) + scrollToPreferences); } function hasModifier(e) { return e.ctrlKey || e.shiftKey || e.altKey || e.metaKey; } function addStyle() { if(addStyle.hasOwnProperty("_style")) return; var style = '\ .toggleRestartlessAddons-isDelayed > .menu-iconic-text {\n\ opacity: 0.75;\n\ color: #070;\n\ }\n\ .toggleRestartlessAddons-isHidden > .menu-iconic-text {\n\ color: #609;\n\ }\n\ .toggleRestartlessAddons-disabled > .menu-iconic-left {\n\ opacity: 0.4;\n\ }\n\ .toggleRestartlessAddons-disabled > .menu-iconic-text,\n\ .toggleRestartlessAddons-disabled > .menu-accel-container {\n\ opacity: 0.5;\n\ }\n\ .toggleRestartlessAddons-askToActivate {\n\ color: -moz-nativehyperlinktext;\n\ }'; addStyle._style = document.insertBefore( document.createProcessingInstruction( "xml-stylesheet", 'href="' + "data:text/css," + encodeURIComponent(style) + '" type="text/css"' ), document.documentElement ); } function removeStyle() { if(!addStyle.hasOwnProperty("_style")) return; var s = addStyle._style; s.parentNode.removeChild(s); delete addStyle._style; } function closeMenus(node) { // Based on function closeMenus from chrome://browser/content/utilityOverlay.js for(; node && "tagName" in node; node = node.parentNode) { if( node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" && (node.localName == "menupopup" || node.localName == "popup") ) node.hidePopup(); } } function _log(s) { if(typeof LOG == "function") // Custom Buttons LOG(s); else // Or something else Services.console.logStringMessage("Toggle Restartless Add-ons: " + s); } function hasUpdater() { var has = checkForAddonsUpdates.toString().indexOf("about:addons") != -1; hasUpdater = function() { return has; }; return has; } function checkForAddonsUpdates() { // http://infocatcher.ucoz.net/js/cb/checkForAddonsUpdates.js // https://forum.mozilla-russia.org/viewtopic.php?id=57958 // https://github.com/Infocatcher/Custom_Buttons/tree/master/Check_for_Addons_Updates // Check for Addons Updates button for Custom Buttons // (code for "code" section) // (c) Infocatcher 2012-2021 // version 0.1.6pre4 - 2021-03-28 // Button just open hidden tab with about:addons and trigger built-in "Check for Updates" function. // And show tab, if found updates. (function() { var btn = this instanceof XULElement ? this : { // Launched not from custom button image: "", // Base64-encoded icon (if empty, will be used "imgLoading") label: "Check for Addons Updates", tooltipText: "" }; if("_cb_disabled" in btn) return; btn._cb_disabled = true; if(!("Services" in window)) Components.utils.import("resource://gre/modules/Services.jsm"); var app = Services.appinfo.name; var pv = parseFloat(Services.appinfo.platformVersion); var ADDONS_URL = "about:addons"; var progressIcon = new ProgressIcon(btn); var image = btn.image || progressIcon.imgLoading; var tip = btn.tooltipText; btn.tooltipText = "Open " + ADDONS_URL + "…"; var tab, browser, gBrowser; var tbTabInfo, tbTab; var trgWindow = Services.wm.getMostRecentWindow("navigator:browser") || app == "Thunderbird" && Services.wm.getMostRecentWindow("mail:3pane") || window; var trgDocument = trgWindow.document; var tabmail = trgDocument.getElementById("tabmail"); if(tabmail && app == "Thunderbird") { // Note: SeaMonkey doesn't support content tabs in mail window let addonsWin; let receivePong = function(subject, topic, data) { addonsWin = subject; }; Services.obs.addObserver(receivePong, "EM-pong", false); Services.obs.notifyObservers(null, "EM-ping", ""); Services.obs.removeObserver(receivePong, "EM-pong"); if(addonsWin) { let rootWindow = addonsWin .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebNavigation) .QueryInterface(Components.interfaces.nsIDocShellTreeItem) .rootTreeItem .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIDOMWindow); tabmail = rootWindow.document.getElementById("tabmail"); tbTabInfo = tabmail.getBrowserForDocument(addonsWin); tbTab = tab = tbTabInfo.tabNode; processAddonsTab(addonsWin); } else { Services.obs.addObserver(function observer(subject, topic, data) { Services.obs.removeObserver(observer, topic); if(subject.document.readyState == "complete") processAddonsTab(subject); else { subject.addEventListener("load", function onLoad(e) { subject.removeEventListener(e.type, onLoad, false); processAddonsTab(subject); }, false); } }, "EM-loaded", false); // See openAddonsMgr() -> openContentTab() tbTabInfo = tabmail.openTab("contentTab", { contentPage: ADDONS_URL, clickHandler: "specialTabs.siteClickHandler(event, /addons\.mozilla\.org/);", background: true }); tbTab = tab = tbTabInfo.tabNode; tbTab.collapsed = true; // Note: dontSelectHiddenTab() not implemented } } else if("gBrowser" in trgWindow && trgWindow.gBrowser.tabs) { let isPending = false; let ws = Services.wm.getEnumerator("navigator:browser"); windowsLoop: while(ws.hasMoreElements()) { let w = ws.getNext(); let tabs = w.gBrowser.tabs; for(let i = 0, l = tabs.length; i < l; ++i) { let t = tabs[i]; if( !t.closing && t.linkedBrowser && t.linkedBrowser.currentURI.spec == ADDONS_URL ) { tab = t; break windowsLoop; } } } gBrowser = trgWindow.gBrowser; if(!tab) { tab = gBrowser.addTab(ADDONS_URL, { triggeringPrincipal: "Services" in window // Firefox 63+ && Services.scriptSecurityManager && Services.scriptSecurityManager.getSystemPrincipal() }); tab.collapsed = true; tab.closing = true; // See "visibleTabs" getter in chrome://browser/content/tabbrowser.xml trgWindow.addEventListener("TabSelect", dontSelectHiddenTab, false); } else if( tab.getAttribute("pending") == "true" // Gecko >= 9.0 || tab.linkedBrowser.contentDocument.readyState == "uninitialized" // || tab.linkedBrowser.__SS_restoreState == 1 ) isPending = true; browser = tab.linkedBrowser; if( isPending || browser.webProgress.isLoadingDocument || browser.currentURI.spec == "about:blank" // Firefox 79+ ) { browser.addEventListener("load", processAddonsTab, true); if(isPending) { if(pv >= 41) { // Workaround to correctly restore pending tab // See https://github.com/Infocatcher/Custom_Buttons/issues/39 let selTab = gBrowser.selectedTab; gBrowser.selectedTab = tab; gBrowser.selectedTab = selTab; } else { browser.reload(); } } } else { processAddonsTab(); } } else { progressIcon.restore(); btn.tooltipText = tip; delete btn._cb_disabled; Services.prompt.alert(window, btn.label, "Error: Can't find supported window!"); return; } function processAddonsTab(e, again) { var doc; if(e && e instanceof Components.interfaces.nsIDOMWindow) { doc = e.document; } else if(e) { doc = e.target; if(doc.location != ADDONS_URL) return; browser.removeEventListener(e.type, processAddonsTab, true); } else { doc = browser.contentDocument; } btn.tooltipText = "Process " + ADDONS_URL + "…"; progressIcon.loading(); var origAttr = "_cb_checkForAddonsUpdates_origImage"; if(!tab.hasAttribute(origAttr)) { var link = doc.querySelector('link[rel="shortcut icon"]'); // Not loaded yet? tab.setAttribute(origAttr, link && link.href || tab.image); } tab.image = image; var fu = $("cmd_findAllUpdates"); if(!fu) { // Firefox 72+ var win = doc.defaultView; var vb = doc.getElementById("html-view-browser"); if(!vb) { if(!HTMLHtmlElement.isInstance(doc.documentElement)) { // Firefox 87+ win.setTimeout(processAddonsTab, 20, win); return; } vb = browser; } if(!again) { // Strange errors happens // chrome://mozapps/content/extensions/aboutaddons.js // getTelemetryViewName() -> el.closest(...) is null win.setTimeout(processAddonsTab, 20, win, true); return; } var vbDoc = vb.contentDocument; fu = vbDoc.querySelector('[action="check-for-updates"]'); var um = vbDoc.getElementById("updates-message"); } var notFound = $("updates-noneFound") || { get hidden() { return um.getAttribute("state") != "none-found"; } }; var updated = $("updates-installed") || { get hidden() { return um.getAttribute("state") != "installed"; } }; // Avoid getting false results from the past update check (may not be required for "noneFound") if(um) { // Firefox 72+ um.hidden = true; um.removeAttribute("state"); } else { notFound.hidden = updated.hidden = true; } //fu.doCommand(); fu.click(); function localize(node, key, callback) { if(um) { // Firefox 72+ doc.l10n.formatValue(key).then(function(s) { callback(s || key); }, Components.utils.reportError); return; } callback(node.getAttribute("value") || key); } var inProgress = $("updates-progress") || { get hidden() { return um.getAttribute("state") != "updating"; } }; localize(inProgress, "addon-updates-updating", function(s) { btn.tooltipText = s; }); var waitTimer = setInterval(function() { if(!doc.defaultView || doc.defaultView.closed) { stopWait(); notify("Tab with add-ons manager was closed!"); return; } if(!inProgress.hidden) return; var autoUpdate = $("utils-autoUpdateDefault") || vbDoc.querySelector('[action="set-update-automatically"]'); var autoUpdateChecked = autoUpdate.getAttribute("checked") == "true" || autoUpdate.checked; var found = $("updates-manualUpdatesFound-btn") || { get hidden() { return um.getAttribute("state") != "manual-updates-found"; } }; if( autoUpdateChecked ? notFound.hidden && updated.hidden : notFound.hidden && found.hidden ) // Too early? return; stopWait(); if(!tbTab) tab.closing = false; function removeTab() { if(!tab.collapsed) return; if(tbTab) { tabmail.closeTab(tbTabInfo, true /*aNoUndo*/); return; } gBrowser.removeTab(tab); (function forgetClosedTab(isSecondTry) { var ss = "nsISessionStore" in Components.interfaces ? ( Components.classes["@mozilla.org/browser/sessionstore;1"] || Components.classes["@mozilla.org/suite/sessionstore;1"] ).getService(Components.interfaces.nsISessionStore) : trgWindow.SessionStore; // Firefox 61+ https://bugzilla.mozilla.org/show_bug.cgi?id=1450559 if(!("forgetClosedTab" in ss)) return; var closedTabs = JSON.parse(ss.getClosedTabData(window)); for(let i = 0, l = closedTabs.length; i < l; ++i) { let closedTab = closedTabs[i]; let state = closedTab.state; if(state.entries[state.index - 1].url == ADDONS_URL) { ss.forgetClosedTab(window, i); return; } } if(!isSecondTry) // May be needed in SeaMonkey setTimeout(forgetClosedTab, 0, true); })(); } if(!notFound.hidden) { removeTab(); localize(notFound, "addon-updates-none-found", function(s) { notify(s); }); return; } if(autoUpdateChecked) { removeTab(); localize(updated, "addon-updates-installed", function(s) { notify(s); }); return; } tab.collapsed = false; var cats = $("categories"); var upds = $("category-availableUpdates"); if(cats && upds) { if(vb && cats.selectedItem == upds) // Only for Firefox 72+ cats.selectedItem = $("category-extension"); // Trick to force update cats.selectedItem = upds; } else { // Firefox 76+ ? vbDoc.querySelector('.category[name="available-updates"]').click(); } var tabWin = tab.ownerDocument.defaultView; if(tbTab) tabmail.switchToTab(tbTabInfo); else tabWin.gBrowser.selectedTab = tab; setTimeout(function() { tabWin.focus(); doc.defaultView.focus(); var al = $("addon-list") || vb; al.focus(); }, 0); }, 50); function $(id) { return doc.getElementById(id); } function stopWait() { clearInterval(waitTimer); progressIcon.restore(); btn.tooltipText = tip; if(tab.image == image) tab.image = tab.getAttribute(origAttr); tab.removeAttribute(origAttr); trgWindow.removeEventListener("TabSelect", dontSelectHiddenTab, false); setTimeout(function() { delete btn._cb_disabled; }, 500); } function notify(msg) { Components.classes["@mozilla.org/alerts-service;1"] .getService(Components.interfaces.nsIAlertsService) .showAlertNotification( app == "Firefox" && pv >= 57 ? "chrome://mozapps/skin/extensions/extensionGeneric.svg" : "chrome://mozapps/skin/extensions/extensionGeneric.png", btn.label, msg, false, "", null ); } } function dontSelectHiddenTab(e) { // <tab /><tab collapsed="true" /> // Close first tab: collapsed tab becomes selected var trgTab = e.originalTarget || e.target; if(trgTab != tab) return; if(/\n(?:BrowserOpenAddonsMgr|toEM)@chrome:\/\//.test(new Error().stack)) { // User open Add-ons Manager, show tab trgWindow.removeEventListener("TabSelect", dontSelectHiddenTab, false); setTimeout(function() { // Hidden tab can't be selected, so select it manually... tab.collapsed = tab.closing = false; gBrowser.selectedTab = tab; }, 0); } function done(t) { if(!t.hidden && !t.closing) { e.preventDefault(); e.stopPropagation(); return gBrowser.selectedTab = t; } return false; } for(var t = tab.nextSibling; t; t = t.nextSibling) if(done(t)) return; for(var t = tab.previousSibling; t; t = t.previousSibling) if(done(t)) return; } function ProgressIcon(btn) { var app = Services.appinfo.name; var pv = parseFloat(Services.appinfo.platformVersion); if(app == "SeaMonkey") this.imgConnecting = this.imgLoading = "chrome://communicator/skin/icons/loading.gif"; else if(app == "Thunderbird") { this.imgConnecting = "chrome://messenger/skin/icons/connecting.png"; this.imgLoading = "chrome://messenger/skin/icons/loading.png"; } else { this.imgConnecting = app == "Firefox" && pv >= 58 ? "chrome://browser/skin/tabbrowser/tab-connecting.png" : "chrome://browser/skin/tabbrowser/connecting.png"; this.imgLoading = app == "Firefox" && pv >= 48 ? "chrome://global/skin/icons/loading.png" : "chrome://browser/skin/tabbrowser/loading.png"; } if(!(btn instanceof XULElement)) { this.loading = this.restore = function() {}; return; } var useAnimation = app == "Firefox" && pv >= 32 && pv < 48; var btnIcon = btn.icon || btn.ownerDocument.getAnonymousElementByAttribute(btn, "class", "toolbarbutton-icon"); var origIcon = btnIcon.src; btnIcon.src = this.imgConnecting; if(useAnimation) { let cs = btnIcon.ownerDocument.defaultView.getComputedStyle(btnIcon, null); let s = btnIcon.style; s.margin = [cs.marginTop, cs.marginRight, cs.marginBottom, cs.marginLeft].join(" "); s.padding = [cs.paddingTop, cs.paddingRight, cs.paddingBottom, cs.paddingLeft].join(" "); s.width = cs.width; s.height = cs.height; s.boxShadow = "none"; s.borderColor = s.background = "transparent"; btnIcon.setAttribute("fadein", "true"); btnIcon.setAttribute("busy", "true"); btnIcon.classList.add("tab-throbber"); btnIcon._restore = function() { delete btnIcon._restore; btnIcon.removeAttribute("busy"); btnIcon.removeAttribute("progress"); setTimeout(function() { btnIcon.classList.remove("tab-throbber"); btnIcon.removeAttribute("style"); btnIcon.removeAttribute("fadein"); }, 0); }; } this.loading = function() { btnIcon.src = this.imgLoading; if(useAnimation) btnIcon.setAttribute("progress", "true"); }; this.restore = function() { btnIcon.src = origIcon; if(useAnimation) btnIcon._restore(); }; } }).call(this); //== Check for Addons Updates end } this.tooltipText = "Переключатель джетпаков" + "\n\nУправление:\nЛКМ – открыть меню" + "\nПКМ – проверить обновления" + "\nСКМ – открыть страницу дополнений" + "\nShift+ПКМ – меню кнопки" + "\n\nВ меню: \nЛКМ – включить/выключить дополнение" + "\nShift+ЛКМ – включить/выключить дополнение без закрытия меню" + "\nСКМ – открыть страницу дополнения в управлении дополнениями" + "\nПКМ – открыть настройки дополнения (если есть)";
На форуме