Dumby
Сори что так тупо обьяснил, идея в том чтобы открыть список вкладок из буфера в новом контейнере
Список вкладок я получаю дополнением(контекствое меню вкладки copy url)
Если выделить несколько вкладок то копируются адреса всех в буфер
Там получается список - каждый адрес с новой строки
Чет не додумался сразу сделать скрин, сори
фф 78, не могли бы помочь?
Отсутствует
Stkvsky
Хмм, странно. Завёл Firefox 78.9.0esr,
развернул ucf 2021-2-14, добавил код в custom_script.js
Поставил Copy Tab Links 0.0.3, открыл и выделил несколько вкладок,
ПКМ по вкладке — в пункте «Copy Tab Links», в субменю, выбрал «Copy URLs».
Теперь ПКМ на кнопке [+] (#tabs-newtab-button) — и вкладки открылись,
с теми адесами, которые были скопированы у выделенных вкладок.
И атрибут "usercontextid" есть, и у вкладок, и у связннных браузеров,
и цветная индикация присутствует, ну, то есть, открылись в контейнере.
Даже не знаю что и предложить. Разве что попробовать
закрыть браузер, и очистить startupCache вручную, вдруг заклинило.
Ну и, может, в консоль посмотреть на предмет подсказок.
Новый проверочный профиль можно собрать, но это, скорее, на интерес.
Отсутствует
Dumby
Блин, капец я туплю, точно работает, спасибо большое
Единственное, можете добавить пожалуйста чтобы при таком октрытии (с буфера при нажатии ПКМ на +) вкладки загружались
Отредактировано Stkvsky (16-04-2021 04:15:04)
Отсутствует
Спасибо, всем кто ниже на странице поделился используемой кнопкой "Save". Но к сожалению у меня в полном объёме ни одна не заработала. Поэтому пришлось из того, что у меня было в распоряжение и того, что вы тут предоставили, скомпоновать свой вариант, который у меня работает полностью. Из того что не увидел почему-то в других кнопках, сохраняет в HTML единым файлом. Если нет выделенного текста, то сохраняется в .txt вся страница целиком. Эту фишку по моей просьбе в своё время восстанавливал в кнопке Dumby, за что ему огромное спасибо и похоже она у меня только и сохранилась. Если кому интересно выкладываю то, что получилось
// Save, от 07.03.2017. ............. self.label = "Save"; self._handleClick =()=> menuPopup.openPopup(this, "after_start"); self.image = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAADAgBEDRIXnwxQjKQNWp6pDFWXqAxXm6gMV5moDFeaqAxXmqgMV5qoDFebqAxVlqgNW5+pCkyIogwSFqgDAgBHDQoFhyszOv8hheP+IJH7/x+L8v8fjfb/H433/x+N9v8fjfb/H432/x+N9/8fi/L/IJH7/yGF5P0kLTTvDAcDgwgICIQ8Ojf/0czA+Oji1fzh18r85NzO/OTbz/zj287849vO/OPbzvzk3M/84dfK++ji1f3Sy8D5NDIvywYGB3kKCgqFQ0A8/+XXw/v979f/9uTO//rp0f/66NH/+ujR//rn0f/66NH/+ujR//bkzv/979f/5tfD/UZBPv8KCwqEDQwMhUVDQP/f08X7+OrZ/+zf0P/v5NP/8OPT/+/j0//v4tP/8OPT/+/j0//s39D/+OrZ/+DTxfxEQj//DAwMhA8PD4VKR0T/4dXG+/rr2v/v4tH/9OXU//Ll1P/z5dT/8+XU//Pl1P/05NT/7+DR//rr2v/i1cX7SkhE/w8PD4USEhKFT0xI/+XXxfv97tr/9ePR//no1P/459T/+OfU//jn1P/459T/+OfU//Xk0f/97tr/5dfF+09MSf8SEhGFFRQUhVNQTv/j2cv7+u/g//Hm2P/169v/9Orb//Tq2//06tv/9erb//br3P/x5tf/+e/g/+PZzPtTUU7/FBQUhRgXF4VXU1D/2828+/Lk0f/q2sf/7d3K/+3dyv/t3cr/7N3K/+rayP/r28n/69vI//Ll0v/azbv7VlNP/xgXF4UfHh6FTktJ/1JOTPtZVFL/Uk5L/1FNSv9RTUr/UU1K/1JPTP9YVVD/VVJP/09NSv9WUk//UU1L+05LSf8fHh2FIR8fhVVTUP9FQkD7UlBM/6Wlj/+4uJ7/sLCX/7S0mv+xsJn/oKCQ/6+vmv+hoYv/TEtH/0NCQPtVUk//IR8fhSMhIIVcWVb/SEVF+19dVv/f3sP////e//X10v///93/2di8/1lYWP+eno//5+fG/19dV/9JRkb7W1hV/yMhIYUkJCOFXltZ/0tJSPtdW1f/0NC4/+/u1P/h4cj/8PDV/7++q/8vLC7/e3lw/9fWv/9eXVf/TElJ+15bWf8lJCKEJSQjhF9cWf9LSUf5XVtX/tbVwf/5+OL/6enV//j54v/GxrX/QD0+/42Kgv/d3cr/YF5a/k5LSvlhXlv/JSUjhCkoKIZpZWT/VVJR/WNhXP/V1cT//f3s/+3t3v/8/Or/zc2//01LSf+VlIz/4eDS/2hmYv9YVVT8aWVj/ycmJoIaGRlYSEVE1DYzM8NKSUfP0dHG9/X16P/n59v+7e3g/+jo3f/X2M3+6uve/9bWzPdOTUvNOjg3y0RBQLwPDw8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; var folderpath="f:\\Свой\\Путь"; // папка для сохранения иконок для ярлыков и ярлыков сайтов // Создать меню для кнопки ............. var array = [ { label: "Сохранить значок веб-сайта", func: "saveFavicon()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACPVBMVEX09ff////C3L+Uq8+Vq8+Uqs+Zr9CZrtCZr9Gfu+ear8+mt9JRf8ORxl3t8vfF06+Twojs8/d9otl8o9s+aquZrs/X9KLp8Pft8fZhisf//+DBzN2hveihv+pii8hti9pgicl6oNlojs1zncNsi836/P2duebx8/eYyWqBp+Gn0IKBvlKHsm9qmaVuk8zt7/FEbauEv1Tp7/JdhL9oi9Pl8e2LwlmdsdD7/P76+/3H7ofo8+peh8eHwFaSteZ0pkp2gl7q8/Ohy5OApt2by2eZuOqbuOWaezWuvtd7nN2HvWxul9Ty9feQxV5ljcqBp+JEcLCVtOOo0nR7odx5n9suX6Z1mtBzmtSXyGPv9PewzfOzx+O6zu/s8fd9o95Xfrthi8lYhMN5oNnw9ffw9Pjw9Pf8/f6ewO/m8O9zmdE6aapsjdyUwouPxWPDzd6XteOSs9B5nNVpnpqHt7h/s6F6n9d7ntSTttGHwVh4qp+Ev1HH7ox6qk5wj+Hm8e3t9fOm0IKAtqOBpNrx+P9ljcyhs9FpkM2hv+/u8/fF0eOLu4N+vFKgzX3p9OSFqN13qExekIl4n9j7/P3x9PhxmNDm8e9Vg8Zfkozr8veq0YTX9qL//92AtamOwnHFz96Fot1diMh+pd13ntmatu+YyW/3+/+Tqs5UgcShzJNbhsdTf8GHs7bo8PaXtuqMr+Ty8/SZt+SUqs7r7Ox3ndb9/f7t8feZyXGYyWWCpNbz9PRuiteNtNDn7/V4ntjx8fGo3JqNAAAAv3RSTlP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AEVuhDkAAAD+SURBVBhXY5jHzcUMAqxAICq9bx8D96adDFAgaGQOFOBaH7h7zoqZDTlFyptncAAFWBjyi52CXCI0unRLxcECPhsatbbzmlXMnS60hg0kkOxW0uNrq93tNaFpD1ggUm21QK532ZQdSm1hmXKdDCwdnOWVOi1RjNGMQCCrwMDMJ8NZ4LAynVGPkXFp8zpJBubYmn579wXtqhZb0iwn9a1iWLaViYmJ3891obOwYtLEvcYMGyWAAkwJdv6accEhi8LjGVr11SenpC5f61g3NcO0vjCAIc+DjZ2dnWexddWSbYa9nlkM+8BgWsxsK7FZ1VLzRaACNokmtdnyu1QMQgF7Rlh4zWWTAwAAAABJRU5ErkJggg=="}, { label: "Запомнить значок веб-сайта как base64", func: "copyFaviconData()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAI2bv/9RVpf/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAACIkvD/Jia6/ywpq/8AAAAAAAAAAAAAAAAAAAD/AAAA/wbwAf90qpv/Ymic/1RWqP9OUKr/W2Ch/2dumf9YYKT/Ly/B/xQP3/8MB9P/JCGb/wAAAAAAAAAAAAAAAAAAAP8G8AH/U5ea/ycr8f8VIP3/HiP4/ywo8v8sIvb/LCL2/ywi9v8KBOj/BQDe/wQAtv8tK4P/AAAAAAAAAAAAAAD/BvAB/3Sqm/9iaJz/Tim3/0UuuP9GPrT/R0ex/zk8uf8gIMz/FRDe/xEMzv8jIJz/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAP8AAAD/SqOR/yImvP8sLKj/AAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAD/AAAA/wAAAP8AAAD/BvAB/3Sqm/9KW5r/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAAAAAAAAAAAAAAAAAAABvAB/wbwAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/BvAB/wbwAf8G8AH/AAAAAAAAAAAAAAAAAAAAAAAAAAAG8AH/AAAAAAAAAP8G8AH/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/BvAB/wbwAf8AAAAAAAAA/wAAAP8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAAAG8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOesQQBjrEGAAaxBwACsQcABrEHDg6xBwAesQcAPrEHAD6xBw8+sQcPprEHD8axBwAGsQQABrEGAAaxB//+sQQ=="}, { separator: ''}, { label: "Сохранить ярлык страницы как…", func: "saveShortcuts()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADzqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/BP8k/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/BP8k/wT/JP8E/yT/BP8k/5XLDv/zqgD/86oA//I1///yNf//86oA//OqAP/zqgD/86oA//OqAP+Vyw7/lcsO/wT/JP8E/yT/BP8k/5XLDv+Vyw7/86oA//OqAP/yNf//8jX///OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA//02AP/9NgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP/9NgD//TYA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA/wA31v8AN9b/86oA//9If///SH//86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP8AN9b/ADfW//OqAP//SH///0h///OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/5XLDv+Vyw7/86oA//OqAP/zqgD/86oA/0CA//9AgP//86oA/07+9f9O/vX/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP9AgP//QID///OqAP9O/vX/Tv71//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/AACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQ=="}, { separator: ''}, { label: "Кодировать изображение(текст.файл) в base64", func: "copyFaviconbase()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AIAQ/wCAEf8AgA//AIAR/wCAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AgBX/AIAVAAAAAAAAAAD/AIAo/wCA//8AgP//AID//wCA//8AgP//AIAoAAAAAAAAAAAAAAAAAAAAAP8AgBL/AID//wCA//8AgA3/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgBAAAAAAAAAAAAAAAAD/AIAR/wCA//8AgP//AIAK/wCACv8AgP//AID//wCAIf8AgAX/AIAh/wCA//8AgP//AIAQAAAAAAAAAAAAAAAA/wCACv8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAUAAAAA/wCABf8AgP//AID//wCACgAAAAD/AIAQ/wCADP8AgCH/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCABf8AgCH/AID//wCA//8AgAv/AIAh/wCA//8AgP//AID//wCA//8AgP//AIAH/wCAB/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AIAg/wCA//8AgP//AID//wCA//8AgP//AID//wCAB/8AgAf/AID//wCA//8AgP//AID//wCA//8AgP//AIAh/wCAC/8AgP//AID//wCAHP8AgBz/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCACf8AgA7/AIAMAAAAAP8AgAj/AID//wCA//8AgAP/AIAD/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCABQAAAAAAAAAA/wCADf8AgAr/AIAL/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCAB/8AgAr/AID//wCA//8AgCH/AIAH/wCAJf8AgP//AID//wCAI/8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAf/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgCT/AID//wCA//8AgAr/AIAK/wCA//8AgP//AIAKAAAAAP8AgCj/AID//wCA//8AgP//AID//wCA//8AgCP/AIAM/wCA//8AgP//AIAN/wCADf8AgP//AID//wCADQAAAAAAAAAA/wCAEP8AgBH/AIAP/wCAEf8AgBAAAAAAAAAAAP8AgBT/AIAVAAAAAAAAAAD/AIAV/wCAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+sQcH5rEGA8KxBAHCsQQBwrEEIQKxBAACsQQAArEEAAKxBAQCsQQwArEEAAKxBAACsQYAArEHBmaxB//+sQQ=="}, { separator: ''}, { label: "Сохранить всю страницу как PDF", func: "savePageToPDF()", image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYUw4pJt3V/+Rb1D8lnFP/55zTf+VcVH/lXJS/5VyUv+VclL/lXJS/5VyUv+VclL/k3BR/J56Wv9cRzSkAAAAAJNvUKTto2L/4ppe/uehZf/Pmmr/noZv/9Scav/Wl17/1plh/9eZYf/XmWH/15lh/9eZYf/WmGD/2Jlg/suRXP9mRiuk8rWA/397dP1akKn/rqqi/3LF3f8Mntj/4dLJ///+9f/48u3/9e7n//bt5v/47+f/+O/n//jv5//rvZP/1ZJX/a9/VP9+lrD8AIvz/xOt+f8Douv/ALb6/wC28/9tmar/z8jJ//Lq5/////7//v////n9///6/P3//////+Ta0P/PjVP/pnpT/IWds/+aiXj/5efl/8Px//951/3/LMz//wCx8/8GltL/NIu3/4ycqf/l29L////+//n6+//8/v//3tXM/8+OVP+oe1P/6K57/86QWP/r6Ob////////++v/r9/z/oOb9/zDL//8Arf//AI/r/ydysv+hpqr//PTr///////d1Mz/0I5U/6h7U//osH//wo5g/+fm5P/7/f//9vf5//z7+////vv/9/r8/5Dc/P8Oqv7/AJf//wF02v9ffZ7/8Ojh/+Ha1P/NjFL/qHtT/+ewf//Ej1//7O3r///////+/v7//v7+//f5+v/6+vv////8/8Tq/f8hp/7/AJH//wB18/8/bqj/1MGu/9mXXv+leVH/569+/8iSYv+/tKn/wLew/8O5sf/P0M////////7+/v/3+fv////7/9Hv/v8hoP3/AIn//wB4/v84ZqL/w4NH/619VP/nsYD/x45c/9W5of/bv6j/0Jxt/6J/YP+spqD/2N3i//7////6+/3///76/8vr/v8Slv7/AIb+/wBz//83VH7/nW1B/+ewfv/Fjl7/7Ozr///////9+/r/9d7K/9Ghdv+jd1D/pJ6Y/+jt8f/9///////7/6fb/v8Ahv7/AYD//wRp6f95YlT/57B//8SOXv/n5uT//v7///r7/P/8/v////////XRsv/DhEv/loBu/9DX3P/9/v/////7/2O6/f8Afv//FnTU/5JtTf/nsH//xY9e/+jn5f/+/f//+fj5//n4+P/5+Pn/+/////Xbxf/Wj1D/nX1h/+Ll6P////7/3+/3/w+V//8tcbP/qHJB/+WuffzCjV7/5efn///////+/v7//////////////v7///////XRsP/TnW3/8fT3//////////z/ddD//0Nxl/+zdkH88LmH/9CRWP2+qJT/0M7N/8/Jxv/Pysf/z8rH/8/Kxv/Py8n/zsO6/7+pmP/PzMv/zsnG/9bNyP+nsK7/h4R3/b2BT/+Sb1Ck7qxw/9GSW/69hlb/wYhX/8CIV//AiFf/wIhX/8CIVv/BiVj/xI1d/8CIVv/BiFf/vYZW/9STW/7ppmv/bE80pAAAAACUd16k+sui/+7AmPzwwpr/8MKa//DCmv/wwpr/8MKa//DCmf/vwZj/8MKa//DCmv/uwJj8+cui/5N3XaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="}, { label: "Сохранить всю страницу или выбранное как HTML", func: "savePageToHTML()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACzElEQVQ4jV2STW8bZRDHf/Psrr11nZhgVKcKaSmUiArRKBRVIMgH4BKJ7xAp5MSFiA+Rc28ckBAoipC4koJQLyAaVFChIlQllDRWmjRev8Qvu14/+wwHx6ZlpNFcZn7zn79GVJW1tbXc6urqijHGqKoAPF3TgcVaq8owXJbphx99fOOnWzcHoqqsr68/t7y83BARVBXnHHraXo3a3HoUU8gFAHRTS2Bg/7C2Zx7vXPIBwjA0p3BU9Zns9i3vvVrhr6MWzlpee+EsRqAbHc3+/Pee7wPkcrkx4P+g0IMvb/5Iv5/iXEaWZQS+By578MaVy9YH8H3fE5FnANZajqMmgcAnH7yN73mICMYMd21sbLy7srKiPkA+n3/qBLhzv8p+EuOfTUjShPbODvOVWa5fnRsvKBaLAcAIMFbw+bc/EBVn8At7SPcQ60LSiVm++P0fGu0e7y++yalvHoABCILAiAj7hzU+vfcVT6zPVGmR3x4/xJoLSH6BVu4cN777nnQwQETI5XL/AYwxRkS4ff8BEk6Q2pBfq3dxUuHMmWt0kgFGStTDY/7YrTLybQwYPU2cpgzsCd1OgmSzWHeOR7VjWicxaT9lxn+HfjoYmWnGHgAiIsydf5HKnUXiThehQDG4Tr3e5KR7hN8XilnGKxfOoyrDgZECwIgIb125xIxxTGVdgjRG4pR2+zbG/sIkD7l2cYJyaYLMOZxzjBV4nueLCI1GnaWFab65t4OXt4gUuFqYJ8gGuPYBCxdLHNciys9PkaapjAHGGM8YQ7lcZv71OaYmC/xZPaJHTN4cUgpDXrr8MtOVaUqTRXzfY3t7u7O0tDR82a2trfkkSTSOY+31etrpdLTZbGoURRpFkdbrTY3qTW00mhrHse7u7t4tl8uhqg4VxHHcPDg4+ExVHeBU1YmIU1WnisucZtamLszn01ar9WRzc/PrWq2WAPwLJ7l2ULfXOAMAAAAASUVORK5CYII="}, { label: "Сохранить выделенный текст как txt файл", func: "saveSelectionToTxt()", image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAQE6AAAAZAAAAGgAAAJmAAACZgAAAGYAAABmAAAAZgAAAGYAAABmAAAAZgAAAGYAAABlAAAAaQABAmYAAQEjAAAAADlVkOdVcKHxVXKi8kdklPJLZpfyU3Cg8lJvn/JRbZ7yUW+g8lFun/JRbp/yUG6e8lVyofFVdKjzLkV45wAAAFABAQEAaIzF/3y34v9wsuL/cJe0/0lpgv9bjLP/dLLh/2+v3v9sq9v/cK3d/3Gv3v9sqtv/b7Df/4G77P9VcqT2AAAAVAMDAQBnir/+ZqfU/pDB4/7a3uD+j46N/kxYXv6To6/+1er4/tXp+P7J3/D+1ej4/svg8v6Gut/9aqzd/lhxnvAAAABSAwIBAGaIvv9pptX/ocfj//f4/P/P0tX/g4CA/1xZWf+Woqr/2uz8/9Hl+f/W5fT/2Of3/5fC4v5tq93/Vm+e8QAAAFIDAgEAaYm+/3mw2/+iyeX/9Pn8/+z0+//IzNL/d3h5/0tMTv+Mkpn/xdvs/9Hp/f/O4PL/msXk/nmz4/9XcJ/xAAAAUgMDAQBti7//k7/h/6fL5v/v9fn/4u73/9Dk9P+8wMT/YGpx/zJJWv94iJf/ztzo/9Pp/P+ZwuD+gLfk/1dwnvEAAABSAwMBAHOPwf+myub/sNHp//j7/P/6/P3/8fr///r39P+sxdP/IXWq/xJJcv+NjZD/0+Lu/6TN7f6Ft+L/WXGf8QAAAFIDAwEAd5LD/7PR6/+ZxOP/0ePx/97r9f/Y5/L/3e32/8Tc7f9gseT/CHK3/zBYdv+HiY7/lL/f/pLE7/9bcJ3xAAAAUgMDAQB4k8P/xNvx/5/F5f+kyOX/qMrn/6TH5f+kyOX/sM/q/5e51P9Mm83/GHm3/xxIav9fdYf+pMvs/1x1pfIAAABTAwMBAHmSxf/O4/T/y9/y/8Hb9P/C3PX/wNv0/7vW7/+93ff/utDm/42fsf9Gjbn/EXS2/ytSbv6Fj5r/WnGc8gAAAFICAwEBepPE/tHk9f/S5PX/vMjV/7fCzP+3w8//uMPP/7XBzP+6ytf/qa+4/3h/hv9Ghaz/JoO+/jNXdP82PVnyAAAAVgACAgCBmcb/2+r3/dHh8fyPkpX/kI6N/5yam/+dnJ3/paWk/6enpf+sr6//mpSR/3Bubf9SjbD8H4C+/QsrSvcCAAB/AAAAA3yVx//j8///3u/7/52gpf6pqKf+uLm5/rq7u/7Ly8v+ycnI/paWlf6LjY/+np2f/Xh+g/5gnL7/MX+y/xcgJ80BAgNNN1OUs6W84fDA1O73mJyj/ainpv+2trb/t7e4/8fHyP/Fxsb/kZGQ/4eGhP+vucT/j6G+/W53k/NlkbnwNoOv/AgiNb8CCBsQDRo/YwsaO3B0d33arKyp9q2trfWvr6/2u7u79ru7vPawr7H1sbCt9nJ2gOQIGD6bFCFEYB0qPE1Bf6SpEz9cggAAAAMCAQEBAQAAADIyMmlDQ0ONQUFBhUFBQYVCQkGFQkJBhUhISIRNTU2OKysrZAEAAAUBAQAAAgEAAAkEAAEDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="}, { separator: ''}, { label: "Запомнить изображение как base64, в контекстном меню", value: "Save.WebScreenShotOnImage"}, { label: "Сохранить выделенный текст в файл, в контекстном меню", value: "Save.SelectionToFile" }, { label: "Открыть выделенный текст в внешнем редакторе, в контекстном меню", value: "Save.TextToEditor"}, ]; var menuPopup = self.appendChild(document.createXULElement("menupopup")); array.forEach((m,i)=> { if ("separator" in m) { menuPopup.appendChild(document.createXULElement("menuseparator")); return }; var mItem = menuPopup.appendChild(document.createXULElement("menuitem")); mItem.setAttribute("label", m.label); mItem.setAttribute("class", "menuitem-iconic"); if ("image" in m) mItem.setAttribute("image", m.image || array[i-1].image); if ("value" in m) { mItem.setAttribute('type', 'checkbox'); mItem.setAttribute('checked', cbu.getPrefs(m.value) ); mItem.onclick =()=> cbu.setPrefs(m.value, !cbu.getPrefs(m.value)); } if ("func" in m) mItem.addEventListener("command", ()=> eval(m.func.toString())); }); menuPopup.setAttribute("onclick", "event.stopPropagation()"); function aDate() { var t=new Date(); var y=1900+t.getYear(); var min=t.getMinutes(); if (min<10){min="0"+min}; var h=t.getHours(); var m=t.getMonth();switch(m){case 0: m="января";break;case 1: m="февраля";break;case 2: m="марта";break;case 3: m="апреля";break;case 4: m="мая";break;case 5: m="июня";break;case 6: m="июля";break;case 7: m="августа";break;case 8: m="сентября";break;case 9: m="октября";break;case 10: m="ноября";break;default: m="декабря";} var d=t.getDate(); var curdate=d+" "+m+" "+y+" "+"г"; var myfilename=curdate; return myfilename; } function WebScreenShotonImage(image) { var canvas = document.createElementNS(xhtmlns, 'canvas'); canvas.width = image.naturalWidth; canvas.height = image.naturalHeight; var ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0); var base64 = canvas.toDataURL(); gClipboard.write(base64); // стиль для изображение в сплывающей подсказке .... var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }')); sss.loadAndRegisterSheet(uri, 0); // alertsService.showAlertNotification(base64, self.label, "Запомнил изображение как base64", false, "", (s, t)=> { Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(base64, self.label, "Запомнил изображение как base64", false, "", (s, t)=> { if (t == 'alertfinished') sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается }, ""); }; 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(); setTimeout(async lp => { var d = await Downloads.createDownload({ source: "about:blank", target: fp.file }); (await lp).add(d); d.refresh(d.succeeded = true); }, 777, Downloads.getList(Downloads.ALL)); } }); }; function savePageToHTML() { var vert=`javascript:(function(){var getSelWin=function(w){if(w.getSelection().toString())return w;for(var i=0,f,r;f=w.frames[i];i++){try{if(r=getSelWin(f))return r}catch(e){}}};var selWin=getSelWin(window),win=selWin||window,doc=win.document,loc=win.location;var qualifyURL=function(url,base){if(!url||/^([a-z]+:|%23)/.test(url))return url;var a=doc.createElement('a');if(base){a.href=base;a.href=a.protocol+(url.charAt(0)=='/'%3F(url.charAt(1)=='/'%3F'':'//'+a.host):'//'+a.host+a.pathname.slice(0,(url.charAt(0)!='%3F'&&a.pathname.lastIndexOf('/')+1)||a.pathname.length))+url}else{a.href=url};return a.href};var encodeImg=function(src,obj){var canvas,img,ret=src;if(/^https%3F:%5C/%5C//.test(src)){canvas=doc.createElement('canvas');if(!obj||obj.nodeName.toLowerCase()!='img'){img=doc.createElement('img');img.src=src}else{img=obj};if(img.complete)try{canvas.width=img.width;canvas.height=img.height;canvas.getContext('2d').drawImage(img,0,0);ret=canvas.toDataURL((/%5C.jpe%3Fg/i.test(src)%3F'image/jpeg':'image/png'))}catch(e){};if(img!=obj)img.src='about:blank'};return ret};var toSrc=function(obj){var strToSrc=function(str){var chr,ret='',i=0,meta={'%5Cb':'%5C%5Cb','%5Ct':'%5C%5Ct','%5Cn':'%5C%5Cn','%5Cf':'%5C%5Cf','%5Cr':'%5C%5Cr','%5Cx22':'%5C%5C%5Cx22','%5C%5C':'%5C%5C%5C%5C'};while(chr=str.charAt(i++)){ret+=meta[chr]||chr};return'%5Cx22'+ret+'%5Cx22'},arrToSrc=function(arr){var ret=[];for(var i=0;i<arr.length;i++){ret[i]=toSrc(arr[i])||'null'};return'['+ret.join(',')+']'},objToSrc=function(obj){var val,ret=[];for(var prop in obj){if(Object.prototype.hasOwnProperty.call(obj,prop)&&(val=toSrc(obj[prop])))ret.push(strToSrc(prop)+': '+val)};return'{'+ret.join(',')+'}'};switch(Object.prototype.toString.call(obj).slice(8,-1)){case'Array':return arrToSrc(obj);case'Boolean':case'Function':case'RegExp':return obj.toString();case'Date':return'new Date('+obj.getTime()+')';case'Math':return'Math';case'Number':return isFinite(obj)%3FString(obj):'null';case'Object':return objToSrc(obj);case'String':return strToSrc(obj);default:return obj%3F(obj.nodeType==1&&obj.id%3F'document.getElementById('+strToSrc(obj.id)+')':'{}'):'null'}};var ele,pEle,clone,reUrl=/(url%5C(%5Cx22%3F)(.+%3F)(%5Cx22%3F%5C))/g;if(selWin){var rng=win.getSelection().getRangeAt(0);pEle=rng.commonAncestorContainer;ele=rng.cloneContents()}else{pEle=doc.documentElement;ele=(doc.body||doc.getElementsByTagName('body')[0]).cloneNode(true)};while(pEle){if(pEle.nodeType==1){clone=pEle.cloneNode(false);clone.appendChild(ele);ele=clone};pEle=pEle.parentNode};var sel=doc.createElement('div');sel.appendChild(ele);for(var el,all=sel.getElementsByTagName('*'),i=all.length;i--;){el=all[i];if(el.style&&el.style.backgroundImage)el.style.backgroundImage=el.style.backgroundImage.replace(reUrl,function(a,b,c,d){return b+encodeImg(qualifyURL(c))+d});switch(el.nodeName.toLowerCase()){case'link':case'style':case'script':el.parentNode.removeChild(el);break;case'a':case'area':if(el.hasAttribute('href')&&el.getAttribute('href').charAt(0)!='%23')el.href=el.href;break;case'img':case'input':if(el.hasAttribute('src'))el.src=encodeImg(el.src,el);break;case'audio':case'video':case'embed':case'frame':case'iframe':if(el.hasAttribute('src'))el.src=el.src;break;case'object':if(el.hasAttribute('data'))el.data=el.data;break;case'form':if(el.hasAttribute('action'))el.action=el.action;break}};var head=ele.insertBefore(doc.createElement('head'),ele.firstChild);var meta=doc.createElement('meta');meta.httpEquiv='content-type';meta.content='text/html; charset=utf-8';head.appendChild(meta);var title=doc.getElementsByTagName('title')[0];if(title)head.appendChild(title.cloneNode(true));head.copyScript=function(){if('$'in win)return;var f=doc.createElement('iframe');f.src='about:blank';f.setAttribute('style','position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;');doc.documentElement.appendChild(f);var str,script=doc.createElement('script');script.type='text/javascript';for(var name in win){if(name in f.contentWindow||!/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name))continue;try{str=toSrc(win[name]);if(!/%5C{%5Cs*%5C[native code%5C]%5Cs*%5C}/.test(str)){script.appendChild(doc.createTextNode('var '+name+' = '+str.replace(/<%5C/(script>)/ig,'<%5C%5C/$1')+';%5Cn'))}}catch(e){}};f.parentNode.removeChild(f);if(script.childNodes.length)this.nextSibling.appendChild(script)};head.copyScript();head.copyStyle=function(s){if(!s)return;var style=doc.createElement('style');style.type='text/css';if(s.media&&s.media.mediaText)style.media=s.media.mediaText;try{for(var i=0,rule;rule=s.cssRules[i];i++){if(rule.type!=3){if((!rule.selectorText||rule.selectorText.indexOf(':')!=-1)||(!sel.querySelector||sel.querySelector(rule.selectorText))){style.appendChild(doc.createTextNode(rule.cssText.replace(reUrl,function(a,b,c,d){var url=qualifyURL(c,s.href);if(rule.type==1&&rule.style&&rule.style.backgroundImage)url=encodeImg(url);return b+url+d})+'%5Cn'))}}else{this.copyStyle(rule.styleSheet)}}}catch(e){if(s.ownerNode)style=s.ownerNode.cloneNode(false)};this.appendChild(style)};var sheets=doc.styleSheets;for(var j=0;j<sheets.length;j++)head.copyStyle(sheets[j]);head.appendChild(doc.createTextNode('%5Cn'));var doctype='',dt=doc.doctype;if(dt&&dt.name){doctype+='<!DOCTYPE '+dt.name;if(dt.publicId)doctype+=' PUBLIC %5Cx22'+dt.publicId+'%5Cx22';if(dt.systemId)doctype+=' %5Cx22'+dt.systemId+'%5Cx22';doctype+='>%5Cn'};var href = 'data:text/html;charset=utf-8,' + encodeURIComponent(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->');var a = document.documentElement.appendChild(document.createElement("a"));a.setAttribute("href", href);var name = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());name=name.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');name += (function () {var d = new Date(), z=function(n){return '_' + (n < 10 ? '0' : '') + n};return z(d.getHours()) + z(d.getMinutes()) + z(d.getSeconds());})();a.setAttribute("download", name + ".html");a.click();a.remove();})();`; gBrowser. loadURI(vert, {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()}); }; function savePage() { saveBrowser(gBrowser.selectedBrowser); }; function saveShortcuts() { var file = Components.classes["@mozilla.org/file/local;1"]. createInstance(Components.interfaces.nsIFile); file.initWithPath(folderpath); if( !file.exists() || !file.isDirectory() ) { file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0x1B6);} var savetodir=folderpath+"\\"; var urllink=gBrowser.currentURI.spec; var out=getTabLabel(); var filename=savetodir+out+'.url'; var data="[InternetShortcut]\r\nURL="+urllink+"\r\n"; saveToFile(data, filename); }; // Кодировать изображение или текстовой файл в base64 ............. function copyFaviconbase(){ var fp = window.makeFilePicker(); fp.init(window, "Открыть файл", fp.modeOpen); fp.appendFilter("Text and images", "*.txt; *.text; *.css; *.js; *.ini; *.rdf; *.xml; *.html; *.htm; *.shtml; *.xhtml; *.jpe; *.jpg; *.jpeg;\ *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw"); fp.open(re=> { if ( re != fp.returnOK ) return; var file = fp.file; var inputStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); inputStream.init(file, 0x01, 0600, 0); var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream); stream.setInputStream(inputStream); var encoded = btoa(stream.readBytes(stream.available())); var contentType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService).getTypeFromFile(file); var dataURI = "data:" + contentType + ";charset=utf-8;base64," + encoded; gClipboard.write(dataURI); //Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Скопировал файл как base64"); // стиль для изображение в сплывающей подсказке .... var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }')); sss.loadAndRegisterSheet(uri, 0); // alertsService.showAlertNotification(base64, self.label, "Запомнил изображение как base64", false, "", (s, t)=> { Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Запомнил изображение как base64", false, "", (s, t)=> { if (t == 'alertfinished') sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается }, ""); }); }; // Сохранить страницу как PDF файл через сервис 'pdfmyurl.com' ............. function savePageToPDF() { var loc = gBrowser.currentURI.spec; var vert = "http://pdfmyurl.com?url=" + loc; gBrowser. loadURI(vert, { triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal() }); }; // Сохранить иконку текущего сайта с диалогом сохранения ............. if (typeof window.saveImageURL != "function") var saveImageURL = internalSave.length == 15 ? (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) => internalSave(url, null, name, a9, type, a4, a3, null, a6, null, a7, a5, null, priv, prin) : (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) => internalSave(url, null, name, a9, type, a4, a3, null, a6, a7, a5, null, priv, prin); function saveFavicon() { var uri = gBrowser.currentURI; function getSiteName() { try { var domain = uri.host.split('.') } catch(e) { return "" }; domain = (domain.length == 2) ? domain[0] : domain[1] return domain.charAt(0).toUpperCase() + domain.slice(1).split('.')[0] + " "; }; var url = gBrowser.selectedTab.image; url && saveImageURL( url, getSiteName(), null, false, false, null, null, /^data:(image\/[^;,]+)/i.test(url) ? RegExp.$1.toLowerCase() : Cc["@mozilla.org/mime;1"] .getService(Ci.nsIMIMEService).getTypeFromURI(Services.io.newURI(url)), null, PrivateBrowsingUtils.isContentWindowPrivate(content || window), document.nodePrincipal ); }; // Скопировать иконку текущего сайта как base64 код ............. function copyFaviconData() { var img = new Image(); img.src = gBrowser.selectedTab.image; WebScreenShotonImage(img); }; // Сохранить выделенный текст или весь текст на странице как txt файл ............. function saveSelectionToTxt() { var splice = saveURL.length == 10; var msgName = _id + ":Save:GetSelection"; var receiver = msg => { var args = [ "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\r\n\r\n" + msg.data), getTabLabel() + ' ' + aDate().replace(/:/g, ".") + ".txt", null, false, false, null, window.document ]; splice && args.splice(5, 0, null); saveURL(...args); } messageManager.addMessageListener(msgName, receiver); addDestructor(() => messageManager.removeMessageListener(msgName, receiver)); var func = fm => { var res, fed, win = {}; var fe = fm.getFocusedElementForWindow(content, true, win); var sel = (win = win.value).getSelection(); if (sel.isCollapsed) { var ed = fe && fe.editor; if (ed && ed instanceof Ci.nsIEditor) sel = ed.selection, fed = fe; } if (sel.isCollapsed) fed && fed.blur(), docShell.doCommand("cmd_selectAll"), res = win.getSelection().toString(), docShell.doCommand("cmd_selectNone"), fed && fed.focus(); res = res || sel.toString(); /\S/.test(res) && sendAsyncMessage("NAME", res); } var url = "data:charset=utf-8," + encodeURIComponent(`(${func})`.replace("NAME", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } function saveSelectionToTxt() { var splice = saveURL.length == 10; var msgName = _id + ":Save:GetSelection"; var receiver = msg => { var args = [ "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\r\n\r\n" + msg.data), getTabLabel() + ' ' + aDate().replace(/:/g, ".") + ".txt", null, false, false, null, window.document ]; splice && args.splice(5, 0, null); saveURL(...args); } messageManager.addMessageListener(msgName, receiver); addDestructor(() => messageManager.removeMessageListener(msgName, receiver)); var func = fm => { var res, fed, win = {}; var fe = fm.getFocusedElementForWindow(content, true, win); var sel = (win = win.value).getSelection(); if (sel.isCollapsed) { var ed = fe && fe.editor; if (ed && ed instanceof Ci.nsIEditor) sel = ed.selection, fed = fe; } if (sel.isCollapsed) fed && fed.blur(), docShell.doCommand("cmd_selectAll"), res = win.getSelection().toString(), docShell.doCommand("cmd_selectNone"), fed && fed.focus(); res = res || sel.toString(); /\S/.test(res) && sendAsyncMessage("NAME", res); } var url = "data:charset=utf-8," + encodeURIComponent(`(${func})`.replace("NAME", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } //Добавить в контекстное меню страницы пункт "Запомнить изображение как base64".......................................................................................... (popup => addEventListener("popupshowing", { handleEvent(e) { if (this.shouldHide) return; var menuitem = document.createXULElement("menuitem"); menuitem.id = "content-baseItem"; menuitem.className = "menuitem-iconic"; menuitem.setAttribute("oncommand", "copyImageAsBase64()"); menuitem.setAttribute("label", "Запомнить изображение как base64"); menuitem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AIAQ/wCAEf8AgA//AIAR/wCAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AgBX/AIAVAAAAAAAAAAD/AIAo/wCA//8AgP//AID//wCA//8AgP//AIAoAAAAAAAAAAAAAAAAAAAAAP8AgBL/AID//wCA//8AgA3/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgBAAAAAAAAAAAAAAAAD/AIAR/wCA//8AgP//AIAK/wCACv8AgP//AID//wCAIf8AgAX/AIAh/wCA//8AgP//AIAQAAAAAAAAAAAAAAAA/wCACv8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAUAAAAA/wCABf8AgP//AID//wCACgAAAAD/AIAQ/wCADP8AgCH/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCABf8AgCH/AID//wCA//8AgAv/AIAh/wCA//8AgP//AID//wCA//8AgP//AIAH/wCAB/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AIAg/wCA//8AgP//AID//wCA//8AgP//AID//wCAB/8AgAf/AID//wCA//8AgP//AID//wCA//8AgP//AIAh/wCAC/8AgP//AID//wCAHP8AgBz/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCACf8AgA7/AIAMAAAAAP8AgAj/AID//wCA//8AgAP/AIAD/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCABQAAAAAAAAAA/wCADf8AgAr/AIAL/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCAB/8AgAr/AID//wCA//8AgCH/AIAH/wCAJf8AgP//AID//wCAI/8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAf/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgCT/AID//wCA//8AgAr/AIAK/wCA//8AgP//AIAKAAAAAP8AgCj/AID//wCA//8AgP//AID//wCA//8AgCP/AIAM/wCA//8AgP//AIAN/wCADf8AgP//AID//wCADQAAAAAAAAAA/wCAEP8AgBH/AIAP/wCAEf8AgBAAAAAAAAAAAP8AgBT/AIAVAAAAAAAAAAD/AIAV/wCAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+sQcH5rEGA8KxBAHCsQQBwrEEIQKxBAACsQQAArEEAAKxBAQCsQQwArEEAAKxBAACsQYAArEHBmaxB//+sQQ=="); popup.append(menuitem); addDestructor(() => menuitem.remove()); menuitem.copyImageAsBase64 = () => { var {osPid} = gContextMenu.actor.manager.browsingContext.currentWindowGlobal; if (osPid == -1) osPid = Services.appinfo.processID; for(var ind = 0, len = Services.ppmm.childCount; ind < len; ind++) { var pmm = Services.ppmm.getChildAt(ind); if (pmm.osPid == osPid) break; } pmm.loadProcessScript("data:;charset=utf-8," + encodeURIComponent(this.code()), false); } this.handleEvent = () => menuitem.hidden = this.shouldHide; }, get shouldHide() { return !gContextMenu.onImage; }, code: () => `(targetIdentifier => { var image = ChromeUtils.import("resource://gre/modules/ContentDOMReference.jsm") .ContentDOMReference.resolve(targetIdentifier); var canvas = image.ownerDocument.createElementNS("${xhtmlns}", "canvas"); canvas.width = image.naturalWidth; canvas.height = image.naturalHeight; var ctx = canvas.getContext("2d"); ctx.drawImage(image, 0, 0); var base64 = canvas.toDataURL(); Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper) .copyStringToClipboard(base64, Ci.nsIClipboard.kGlobalClipboard); Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) .showAlertNotification(base64, "${self.label}", "Запомнил изображение как base64"); })(${ JSON.stringify(gContextMenu.targetIdentifier) })` }, false, popup || 1))(document.getElementById("contentAreaContextMenu")); // Добавляем в контекстного меню страницы новые пункты ............. ((contextMenu, el)=> { // в контекстного меню выделенного текста .... var saveItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el); saveItem.id = "content-saveItem"; saveItem.setAttribute("label", "Сохранить выделенный текст в файл"); saveItem.setAttribute("class", "menuitem-iconic"); saveItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAADAgBEDRIXnwxQjKQNWp6pDFWXqAxXm6gMV5moDFeaqAxXmqgMV5qoDFebqAxVlqgNW5+pCkyIogwSFqgDAgBHDQoFhyszOv8hheP+IJH7/x+L8v8fjfb/H433/x+N9v8fjfb/H432/x+N9/8fi/L/IJH7/yGF5P0kLTTvDAcDgwgICIQ8Ojf/0czA+Oji1fzh18r85NzO/OTbz/zj287849vO/OPbzvzk3M/84dfK++ji1f3Sy8D5NDIvywYGB3kKCgqFQ0A8/+XXw/v979f/9uTO//rp0f/66NH/+ujR//rn0f/66NH/+ujR//bkzv/979f/5tfD/UZBPv8KCwqEDQwMhUVDQP/f08X7+OrZ/+zf0P/v5NP/8OPT/+/j0//v4tP/8OPT/+/j0//s39D/+OrZ/+DTxfxEQj//DAwMhA8PD4VKR0T/4dXG+/rr2v/v4tH/9OXU//Ll1P/z5dT/8+XU//Pl1P/05NT/7+DR//rr2v/i1cX7SkhE/w8PD4USEhKFT0xI/+XXxfv97tr/9ePR//no1P/459T/+OfU//jn1P/459T/+OfU//Xk0f/97tr/5dfF+09MSf8SEhGFFRQUhVNQTv/j2cv7+u/g//Hm2P/169v/9Orb//Tq2//06tv/9erb//br3P/x5tf/+e/g/+PZzPtTUU7/FBQUhRgXF4VXU1D/2828+/Lk0f/q2sf/7d3K/+3dyv/t3cr/7N3K/+rayP/r28n/69vI//Ll0v/azbv7VlNP/xgXF4UfHh6FTktJ/1JOTPtZVFL/Uk5L/1FNSv9RTUr/UU1K/1JPTP9YVVD/VVJP/09NSv9WUk//UU1L+05LSf8fHh2FIR8fhVVTUP9FQkD7UlBM/6Wlj/+4uJ7/sLCX/7S0mv+xsJn/oKCQ/6+vmv+hoYv/TEtH/0NCQPtVUk//IR8fhSMhIIVcWVb/SEVF+19dVv/f3sP////e//X10v///93/2di8/1lYWP+eno//5+fG/19dV/9JRkb7W1hV/yMhIYUkJCOFXltZ/0tJSPtdW1f/0NC4/+/u1P/h4cj/8PDV/7++q/8vLC7/e3lw/9fWv/9eXVf/TElJ+15bWf8lJCKEJSQjhF9cWf9LSUf5XVtX/tbVwf/5+OL/6enV//j54v/GxrX/QD0+/42Kgv/d3cr/YF5a/k5LSvlhXlv/JSUjhCkoKIZpZWT/VVJR/WNhXP/V1cT//f3s/+3t3v/8/Or/zc2//01LSf+VlIz/4eDS/2hmYv9YVVT8aWVj/ycmJoIaGRlYSEVE1DYzM8NKSUfP0dHG9/X16P/n59v+7e3g/+jo3f/X2M3+6uve/9bWzPdOTUvNOjg3y0RBQLwPDw8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="); saveItem.onclick =()=> saveSelectionToTxt(); var editorItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el); editorItem.id = "content-editorItem"; editorItem.setAttribute("label", "Открыть выделенный текст в внешнем редакторе"); editorItem.setAttribute("class", "menuitem-iconic"); editorItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAA////AIiafwC85K4AS1ZGANLsyABKU0UAy+m+AL/lsQC14aQAn9WMAJ/QjQCsrKwAqNyXAOPz3ADe8dcA2e/QANPtyQDM68EAxei4AL7lrwC14aUArt6dAJfOhACdz4sAgICAALThpQDg8doA3vHVANjuzgDR7MYAyum+AMLmtQC7460AsuCjAK3dmgCUy4AArdedANDsxQDL6sAAz+PIAMviwwDH4L4Awd62ALvbrwC02KcArdafAKbTlgCEu3EAtNWoANPqywDa8NIA1u7NANHtxwDK6cAAw+e3ALzkrwC14aYAr9+dAKXbkQCJwnMA1+3QAKncmADd8dQAyuLBAMbgvAC6264AttmoAK/XoACn1JYAotKPAJbNgwB9tWgA4+zfANju0ADT7coAz+vFAMPntgC95K8Art6eAKndlQCa1IYAi8R3AP3+/QDD37kAvt2yALjarACz2KYArdaeAKHRjwCXzoUAj8V6AI6/ewDu8e4Awea2AMrqwQDG6LoAweazALnjqwCz4KQAr9+cAKbbkwCd2IkAlc1/AKbTlQC73K8At9qqALDXowCp1ZsApdOVAKDRjQCYzoUAksx7AIi+cwCu0aEAp9yUAMXougDC5rYAveSuALfipwCw4J8AqdyXAKLajwCd2IcAlNR9AI3FdwDU6ssAqdWZAKPSkgCe0YsAmc6GAJDLfQB/tmoA3enZAJfWhACc2IkApNuRAKTbkACj2pAAodqOAKHZjgCl25IAotmOAIzHdgAPAAAA2JIKAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOzARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcrkUA9CUMAAAAAAAAAAAAAAAAAAAAAAAAAA8AAQAAAAEAAAAAAAAAVCIMAAAAAAABAAAAuwP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAACZDSMAAQAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAABAEAABHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGRkZGRkZGRkZAAAAAAAZAQEBAQEBAQEBARkAAIeHiImKi4yNjY5+AQEZAD4mJlZXRH+AgYKDhIVdGQBzJnR1dnd4eXp7fH1+ARkAGiYnaWprbG1ub3Bxcl0ZACdeJl9gYWJjZGVmZ2gBGQAAAyZUVVZXWEVZWltcXRkAAA1KS0wfTU45T1BRUlMZAAA+P0BBK0JDREVGR0hJGQAAAzIzNDU2Nzg5Ojs8PRkAACYnKCkqKywtLi8YMDEZAAAAGhscHR4fICEiIyQlGQAAAA0ODxAREhMUFRYXGBkAAAADBAUGBwYIBgkGChkAAAAAAAACAAIAAgACAAIAAPgBAADwAAAAwAAAAIAAAACAAAAAgAAAAIAAAADAAAAAwAAAAMAAAADAAAAAwAAAAOAAAADgAAAA4AEAAPqrAAA="); editorItem.onclick =()=> textToEditor(); // устанавливаем где и при каких настройках показывать новые пункты .... addEventListener('popupshowing', e=> { if (e.target != e.currentTarget) return; var sel = gContextMenu.isTextSelected; saveItem.hidden = !sel || !cbu.getPrefs("Save.SelectionToFile"); editorItem.hidden = !sel || !cbu.getPrefs("Save.TextToEditor"); }, false, contextMenu); // удалять новые пункти при изминениях .... addDestructor(()=> { saveItem.remove(); editorItem.remove(); }); })(document.getElementById("contentAreaContextMenu"), document.getElementById("context-sep-open")); // Сохранить выделенный текст в файл на рабочем столе ............. function saveSelectionToFile() { let browserMM = gBrowser.selectedBrowser.messageManager; browserMM.addMessageListener('getSelect', function listener(message) { // создать текст для записи var url = gBrowser.currentURI.spec; if (/\.рф/.test(url.host)) url = convertFromUnicode("UTF-8", url); var time = convertFromUnicode("UTF-8", aDate().replace(/:/g, ".")); var text = convertFromUnicode("UTF-8", message.data); var title = convertFromUnicode("UTF-8", getTabLabel()); var text = "..............................................................\n" + title + " - " + time + "\n" + url + "\n\n" + text + "\n\n\n"; var text = text.replace(/\u000A/g, "\u000D\u000A").replace(/\u000D\u000D\u000A/g, "\u000D\u000A"); // путь к файлу и название файла var file = Services.dirsvc.get("Desk", Ci.nsIFile); file.append("Save - " + (aDate().replace(/:/g, ".")) + ".txt"); // создать файл с текстом или добавлять текст в файл var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); file.exists() ? foStream.init(file, 0x02 | 0x10, 0664, 0) : foStream.init(file, 0x02|0x08|0x20, 0666, 0); foStream.write(text, text.length); foStream.close(); // всплывающая подсказка дает возможность открыть файл если кликнуть на подсказке var notificat = 'Сохранил выделенный текст в файл на рабочий стол'; var image = gBrowser.selectedTab.image || self.image; Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) .showAlertNotification(image, notificat, "Кликни чтобы открыть файл", true, "", (s, t)=> { if (t == 'alertclickcallback') file.launch(); }, ""); browserMM.removeMessageListener('getSelect', listener, true); }); browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false); }; // Создать текстовой файл с выделенным текстом в папке профиля и открыть в редакторе ............. function textToEditor() { let browserMM = gBrowser.selectedBrowser.messageManager; browserMM.addMessageListener('getSelect', function listener(message) { // создать текст для записи var text = convertFromUnicode("UTF-8", message.data); var file = Services.dirsvc.get('ProfD', Ci.nsIFile); file.append("TextToEditor.txt"); custombuttonsUtils.writeFile(file.path, text); file.launch(); browserMM.removeMessageListener('getSelect', listener, true); }); browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false); }; // Конвертировать текст в юникод ............. function convertFromUnicode(charset, str) { var converter = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter); converter.charset = charset; str = converter.ConvertFromUnicode(str); return str + converter.Finish(); }; // Получить название вкладки без не сохраняемых символов и лишних пробелов .............. function getTabLabel() { var label = gBrowser.selectedTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); }; ((main, parts) => this.onmousedown = e => { if (e.button) return; this.onmousedown = null; var df = MozXULElement.parseXULToFragment(` <menugroup orient="vertical"> <menuseparator/> <menuitem class="menuitem-iconic" image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAiAcFBa4KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwsJCaECAQE/BQMDAAAAAJUgICD4V1ZW/2FhYf5hYWH/YmFh/2BgYP9fX1//X19f/19fX/9gYGD/YmFh/2FhYf9gYGD+ZmVl/1RSUuIVFBQtCgkJy1paWv+Li4v9h4eH/oiIiP6FhYX+i4uL/pKSkv6Sk5P+kpKS/ouLi/6FhYX+iIiI/oiIiP6Hh4f7lZaW/25tbYQNDQ3OcHBw/5KSkv6Li4v/i4uL/5mZmf+EhIT/ZGRk/1tbWv9kZGT/hISE/5mZmf+Li4v/jY2N/4yMjPyWl5f/iomJjQ4NDc13d3f/m5ub/pWVlf+goKD/XFxc/ygoKP8fHyD/GBsb/yAhIv8pKSn/W1tb/6CgoP+Wlpb/lpaW/J6env+Jh4eMDg4OzX1+fv+ioqL+qqqq/1hYWP8ZGRn/Ghwb/x4dHP8mIh//FhQR/xUWF/8aGhr/WFhY/6urq/+cnJz8pKSk/4qJiYwPDg7Ng4OD/7W1tf6MjIz/Ghoa/xYYGP8uKCb/ZEAo/5xyOP++saL/RD45/xISE/8bGxv/jY2N/6+vr/ypqan/ioiIjA8PD82IiIj/xMTE/l1cXP8LDAz/JiId/1o3LP9ADgD/mGog//Dt6P/VysX/Ih4Z/wsMDf9eXl7/v7+//K6urv+KiYmMEA8PzY+Pj//Kysr+SEhH/wEDBv9MPi7/hlES/3dCAP+VZAn/tJVO/7eVXf9OQTL/AAIE/0pJSf/FxcX8tLS0/4qJiYwQEBDNm5ub/9/e3/5SUlL/AAAA/0M7Mf/aya7/ybiO/5RmEf9aIAD/cjkX/z80KP8AAAD/U1JS/9nZ2fzAwMD/i4qKjBEREc2oqKn/8O/w/oeGhv8AAAD/DAsK/6qkof/17uj/nW8l/14eCf9hPTr/ExUU/wAAAP+Hh4f/6urq/MzMzf+Mi4uMERERzbCwsv/r6uz+3Nzd/yoqKv8AAAD/ExEP/2heU/9yWjv/UD0u/xcXFv8AAAD/Kioq/93d3v/l5eb81NTV/4yLi4wSERHNuLm5/+/v8P7z8/P/xsbG/yAgIP8AAAD/AQEB/wAAAP8BAQH/AAAA/yAgIP/Gxsb/9PT0/+np6vzb29v/jIuLjBIREc2+vb7/+Pj5/uvr7P/7+/v/4ODg/3Nyc/8uLi7/Hh4d/y0sLP9zc3P/4ODg//v7+//s7O3/8/P0/OHg4f+Mi4uLFBMTyMPDw//////7+Pj4/ff29v38/Pz9/////fr6+v3u7u79+vr6/f////38/Pz99/b2/fn5+f37+/v53t7e/5KSko4GBgZ7m5yc//j4+P/w8fH/8fLy//Dw8P/u7u7/8vLy//X19f/y8vL/7u7u//Dw8P/x8vL/8vLy/uXl5f/BwcH+k5GRUAAAAAQeHR1yb25uxn59fcZ9fHzGfXx8xn18fMZ9e3vGfHt7xn17e8Z9fHzGfXx8xn18fMZ9fHzGgH9/xYmIiGVaV1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" label="Сохранить всю страницу как PNG" value="all"/> <menuitem class="menuitem-iconic" image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAiAcFBa4KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwsJCaECAQE/BQMDAAAAAJUgICD4V1ZW/2FhYf5hYWH/YmFh/2BgYP9fX1//X19f/19fX/9gYGD/YmFh/2FhYf9gYGD+ZmVl/1RSUuIVFBQtCgkJy1paWv+Li4v9h4eH/oiIiP6FhYX+i4uL/pKSkv6Sk5P+kpKS/ouLi/6FhYX+iIiI/oiIiP6Hh4f7lZaW/25tbYQNDQ3OcHBw/5KSkv6Li4v/i4uL/5mZmf+EhIT/ZGRk/1tbWv9kZGT/hISE/5mZmf+Li4v/jY2N/4yMjPyWl5f/iomJjQ4NDc13d3f/m5ub/pWVlf+goKD/XFxc/ygoKP8fHyD/GBsb/yAhIv8pKSn/W1tb/6CgoP+Wlpb/lpaW/J6env+Jh4eMDg4OzX1+fv+ioqL+qqqq/1hYWP8ZGRn/Ghwb/x4dHP8mIh//FhQR/xUWF/8aGhr/WFhY/6urq/+cnJz8pKSk/4qJiYwPDg7Ng4OD/7W1tf6MjIz/Ghoa/xYYGP8uKCb/ZEAo/5xyOP++saL/RD45/xISE/8bGxv/jY2N/6+vr/ypqan/ioiIjA8PD82IiIj/xMTE/l1cXP8LDAz/JiId/1o3LP9ADgD/mGog//Dt6P/VysX/Ih4Z/wsMDf9eXl7/v7+//K6urv+KiYmMEA8PzY+Pj//Kysr+SEhH/wEDBv9MPi7/hlES/3dCAP+VZAn/tJVO/7eVXf9OQTL/AAIE/0pJSf/FxcX8tLS0/4qJiYwQEBDNm5ub/9/e3/5SUlL/AAAA/0M7Mf/aya7/ybiO/5RmEf9aIAD/cjkX/z80KP8AAAD/U1JS/9nZ2fzAwMD/i4qKjBEREc2oqKn/8O/w/oeGhv8AAAD/DAsK/6qkof/17uj/nW8l/14eCf9hPTr/ExUU/wAAAP+Hh4f/6urq/MzMzf+Mi4uMERERzbCwsv/r6uz+3Nzd/yoqKv8AAAD/ExEP/2heU/9yWjv/UD0u/xcXFv8AAAD/Kioq/93d3v/l5eb81NTV/4yLi4wSERHNuLm5/+/v8P7z8/P/xsbG/yAgIP8AAAD/AQEB/wAAAP8BAQH/AAAA/yAgIP/Gxsb/9PT0/+np6vzb29v/jIuLjBIREc2+vb7/+Pj5/uvr7P/7+/v/4ODg/3Nyc/8uLi7/Hh4d/y0sLP9zc3P/4ODg//v7+//s7O3/8/P0/OHg4f+Mi4uLFBMTyMPDw//////7+Pj4/ff29v38/Pz9/////fr6+v3u7u79+vr6/f////38/Pz99/b2/fn5+f37+/v53t7e/5KSko4GBgZ7m5yc//j4+P/w8fH/8fLy//Dw8P/u7u7/8vLy//X19f/y8vL/7u7u//Dw8P/x8vL/8vLy/uXl5f/BwcH+k5GRUAAAAAQeHR1yb25uxn59fcZ9fHzGfXx8xn18fMZ9e3vGfHt7xn17e8Z9fHzGfXx8xn18fMZ9fHzGgH9/xYmIiGVaV1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" label="Сохранить видимую часть страницы как PNG" value="page"/> <menuitem class="menuitem-iconic" image="data:image/x-icon;base64,AAABAAEAIBkAAAEAIAAMDQAAFgAAACgAAAAgAAAAMgAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29fT/2tra/8jIyP/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8jIyP/a2tr/9vX0/+zs7P/ak0b/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/9qTRv/s7Oz/7Ozs/+J9Dv/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+/6SdmP/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r/+vn4//z7+v/6+fj/4n0O/+zs7P/s7Oz/4n0O//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r/aFtT//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//j39v/ifQ7/7Ozs/+zs7P/ifQ7/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P9oW1P/7+zq/+/s6v/v7Or/8O3r//Dt6//w7ev/8O3r//Dt6//w7ev/8O3r/+/s6v/w7ev/9fTy/+J9Dv/s7Oz/7Ozs/+J9Dv/49/b/+Pf2//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4/2hbU//q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/y8O//4n0O/+zs7P/s7Oz/4n0O//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/aFtT/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe//Dt6//ifQ7/7Ozs/+zs7P/ifQ7/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P9oW1P/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/7uro/+J9Dv/s7Oz/7Ozs/+J9Dv/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx/2hbU//x7+3/8vDv//Hv7f/x7+3/8e/t//Lw7//x7+3/8e/t//Lw7//x7+3/8vDv//Hv7f/29fT/4n0O/+zs7P/s7Oz/4n0O//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//aFtT/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/8vGwf/ifQ7/7Ozs/+zs7P/ifQ7/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f9nWlL/aFtT/2hbU/9nWlL/Z1pS/2hbU/9oW1P/Z1pS/2daUv9oW1P/aFtT/2hbU/9nWlL/pJyX/+J9Dv/s7Oz/7Ozs/+J9Dv/w7ev/8O3r//Dt6//w7ev/8O3r//Dt6//x7+3/8O3r//Dt6//w7ev/8e/t//Dt6//w7ev/8O3r//Hv7f/w7ev/8O3r//Dt6//x7+3/8O3r//Dt6//w7ev/8e/t//Dt6//w7ev/8O3r//Dt6//w7ev/4n0O/+zs7P/s7Oz/4n0O/+/s6v/v7Or/7uro/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/u6uj/7+zq/+/s6v/ifQ7/7Ozs/+zs7P/ifQ7/7uro/+7q6P/u6uj/7uro/+zo5v/u6uj/7uro/+7q6P/s6Ob/7uro/+7q6P/u6uj/7Ojm/+7q6P/u6uj/7uro/+zo5v/u6uj/7uro/+7q6P/s6Ob/7uro/+7q6P/u6uj/7Ojm/+7q6P/u6uj/7Ojm/+J9Dv/s7Oz/7Ozs/+J9Dv/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/4n0O/+zs7P/s7Oz/4n0O/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/ifQ7/7Ozs/+zs7P/ifQ7/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+J9Dv/s7Oz/7Ozs/+J9Dv/m4d7/5uHe/+bh3v/p5eL/5uHe/+bh3v/m4d7/6eXi/+bh3v/m4d7/5uHe/+nl4v/m4d7/5uHe/+bh3v/p5eL/5uHe/+bh3v/m4d7/6eXi/+bh3v/m4d7/5uHe/+nl4v/m4d7/5uHe/+bh3v/p5eL/4n0O/+zs7P/s7Oz/4n0O/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/ifQ7/7Ozs/+zs7P/ifQ7/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+J9Dv/s7Oz/7Ozs/+J9Dv/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/k39z/4n0O/+zs7P/s7Oz/4n0O/+Lc2f/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/ifQ7/7Ozs/+zs7P/ifQ7/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+J9Dv/s7Oz/9fTy/+J9Dv/8+/r/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/4n0O//X08v/8+/r/6KFU/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ooVT//Pv6/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" label="Сохранить выбранный элемент страницы как PNG" value="click"/> <menuitem class="menuitem-iconic" image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAADDn2Hfz5pE/8eVQP7IlkH/yJZB/8iWQf/IlUH/yJVA/8iVQP/IlED/yJQ//8iUP//IlD//yJM+/8iTPv/Hkj3/nI1w//bDbP//8OH//+zW///s1///69b//+rV///p1P//59L//+XQ///izf//38n//9vG///ZxP//1b///dG////Prf/KlkX/88N4/v37///99Pj//fT6//vy9v/68fT/+u/y//rt8P/66u3/+ufq//rl6P/64eT/+93h//3a3//71d7//9LK/86XR//0xHb//vv////18///9fT///f5///4////9f7///P8///v+f//7Pb//+nz///m8f//4eb//9vZ//3Y2v//1Mb/zphH//TGd//+/////Pj1///7///Q58r/m9aV/6TZnv+i15r/otWY/6LTlv+j0pb/mc6M/9DXuf//3+P//Nnc///Wyf/OmUf/9MZ3//7////8+/j//////53WnP+Y5pn/rvGv/6PvpP+e7p//me6b/5nvm/95533/mM+L///j7f/629z//9jL/86ZR//0xnf//v////z9+v//////qtup/8Xzxf/a/tn/z/vO/8n7yf/D+sL/xPvD/6Hzo/+j05b//+Tu//re3///2cz/zplI//XGeP/+/////P36//////+n26f/uvC6/9T71P/K+Mr/xvjG/8D3wP+/+L//nfCf/6LTlf//5u//+t/g///cz//OmUj/9MZ3//7////8/fr//////6rcqv/G9MX/3//f/9n92f/V/NX/0PzQ/9H+0P+s9a7/pdSY///o8f/64OL//9zP/86aSP/0xnf//v////z9+f//////ndid/5TjlP+v7q//qeyp/6jsqf+k7KX/p+6n/4Tlh/+Z0Y7//+r0//rh4v//3tH/zppI//TGd//+/////v77///////Y8Nj/p9+n/6/jr/+t4a3/rd2p/67bpv+u2ab/p9Wc/9jgx///6Oz//OPl///e0f/Omkj/9MV1//7//////fr///78///+/f///////////////////P////j////0+///8fn//+vu///m4v/94+P//97P/86ZSP/zx3v//v/////+/f///////f////v////7////+/////v+///7+///+/f///vz/P/98Pr//+33//3p9///5OL/zppL//a1Sv/0xoL/9cR7//XEfP/1xHz/9cR8//XEfP/1xH3/9cR8//XCev/1wXr/9b94//W9d//1u3X/87l0//y6bP/Llj7/+pMA/vWBAP/1gwD/9YMA//WDAP/1gwD/9YMA//WDAP/1gwD/9YQA//WEAP/1hAD/9YQA//WEAP/zhAH//okA/8qLIv3xpzP/4ptV/+OdU//jnVP/451T/+OdU//jnVP/451T/+OdU//jnVL/451S/+OdUv/jnVL/451S/+GdVf/qnUf/2aRJ/9q0c9/8yn7/98V5/vjGev/4xnr/+MZ6//jGev/4xnr/+MZ6//jGev/4xnr/+MZ6//jGev/4xnr/+MZ6/vrIe/+jj2y4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" label="Сохранить выбранную область страницы как PNG" value="clipping"/> </menugroup> `); var menugroup = df.firstChild; menugroup.setAttribute("context", ""); menugroup.setAttribute("oncommand", "handleCommand(event);"); menugroup.handleCommand = e => { var name = _id + ":DataURLReady"; main = main.replace("%MESSAGE_NAME%", name); var urls = {}, configurable = true, enumerable = true; Object.entries(parts).forEach(([key, part]) => Object.defineProperty(urls, key, { configurable, enumerable, get() { var value = `data:;charset=utf-8,({${ encodeURIComponent(main + part) }%0A}).init("${key}")`; Object.defineProperty(urls, key, {configurable, enumerable, value}); return value; }})); var getTabLabel = () => { var label = gBrowser.selectedTab.label; var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " "); return label.substring(0, 50); } var listener = msg => { var fp = makeFilePicker(); fp.init(window, "Сохранить как…", fp.modeSave); fp.appendFilter("", "*.png"); fp.defaultString = getTabLabel() + ".png"; fp.open(res => { if (res == fp.returnCancel || !fp.file) return; var wbp = makeWebBrowserPersist(), args = [ Services.io.newURI(msg.data), document.nodePrincipal, null, null, null, null, fp.file, null ]; var {length} = wbp.saveURI; length >= 9 && splice(args); length == 10 && args.splice(3, 0, null); wbp.saveURI(...args); setTimeout(async lp => { var d = await Downloads.createDownload({ source: "about:blank", target: fp.file }); (await lp).add(d); d.refresh(d.succeeded = true); }, 777, Downloads.getList(Downloads.ALL)); }); } var splice = arr => { var fox74 = parseInt(Services.appinfo.platformVersion) >= 74; var args = [fox74 ? 7 : 2, 0, fox74 ? Ci.nsIContentPolicy.TYPE_IMAGE : null]; (splice = arr => arr.splice(...args))(arr); } messageManager.addMessageListener(name, listener); addDestructor(() => messageManager.removeMessageListener(name, listener)); (menugroup.handleCommand = e => gBrowser.selectedBrowser.messageManager .loadFrameScript(urls[e.target.value], false) )(e); } menuPopup.querySelector('menuitem[label*="ярлык"]').after(df); })(` init(cmd) { cmd.startsWith("c") ? this[cmd].init(this[cmd].parent = this) : this[cmd](); }, capture(win, x, y, width, height) { var canvas = win.document.createElementNS("${xhtmlns}", "canvas"); canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); var tryDraw = ind => { try {ctx.drawWindow(win, x, y, canvas.width, canvas.height, "white")} catch(ex) {canvas.height = ind * canvas.width; tryDraw(--ind);} } tryDraw(17); sendAsyncMessage("%MESSAGE_NAME%", canvas.toDataURL("image/png")); }, `, { all: `all() { var win = content; this.capture(win, 0, 0, win.innerWidth + win.scrollMaxX, win.innerHeight + win.scrollMaxY); }`, page: `page() { var win = content, doc = win.document, body = doc.body, html = doc.documentElement; var scrX = (body.scrollLeft || html.scrollLeft) - html.clientLeft; var scrY = (body.scrollTop || html.scrollTop) - html.clientTop; this.capture(win, scrX, scrY, win.innerWidth, win.innerHeight); }`, clipping: `clipping: { handleEvent(e) { if (e.button) return false; e.preventDefault(); e.stopPropagation(); switch(e.type) { case "mousedown": this.downX = e.pageX; this.downY = e.pageY; this.bs.left = this.downX + "px"; this.bs.top = this.downY + "px"; this.body.appendChild(this.box); this.flag = true; break; case "mousemove": if (!this.flag) return; this.moveX = e.pageX; this.moveY = e.pageY; if (this.downX > this.moveX) this.bs.left = this.moveX + "px"; if (this.downY > this.moveY) this.bs.top = this.moveY + "px"; this.bs.width = Math.abs(this.moveX - this.downX) + "px"; this.bs.height = Math.abs(this.moveY - this.downY) + "px"; break; case "mouseup": this.uninit(); break; } }, init() { var win = {}; Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager) .getFocusedElementForWindow(content, true, win); this.win = win.value; this.doc = this.win.document; this.body = this.doc.body; if (!HTMLBodyElement.isInstance(this.body)) { Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService) .showAlertNotification("${self.image}", ${JSON.stringify(self.label)}, "Не удается захватить!"); return false; } this.flag = null; this.box = this.doc.createElement("div"); this.bs = this.box.style; this.bs.border = "#0f0 dashed 2px"; this.bs.position = "absolute"; this.bs.zIndex = "2147483647"; this.defaultCursor = this.win.getComputedStyle(this.body, "").cursor; this.body.style.cursor = "crosshair"; ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { var pos = [this.win, parseInt(this.bs.left), parseInt(this.bs.top), parseInt(this.bs.width), parseInt(this.bs.height)]; this.body.style.cursor = this.defaultCursor; this.body.removeChild(this.box); this.parent.capture.apply(this, pos); ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }`, click: `click: { getPosition() { var html = this.doc.documentElement; var body = this.doc.body; var rect = this.target.getBoundingClientRect(); return [ this.win, Math.round(rect.left) + (body.scrollLeft || html.scrollLeft) - html.clientLeft, Math.round(rect.top) + (body.scrollTop || html.scrollTop) - html.clientTop, parseInt(rect.width), parseInt(rect.height) ]; }, highlight() { this.orgStyle = this.target.hasAttribute("style") ? this.target.style.cssText : false; this.target.style.cssText += "outline: red 2px solid; outline-offset: 2px; -moz-outline-radius: 2px;"; }, lowlight() { if (this.orgStyle) this.target.style.cssText = this.orgStyle; else this.target.removeAttribute("style"); }, handleEvent(e) { switch(e.type){ case "click": if (e.button) return; e.preventDefault(); e.stopPropagation(); this.lowlight(); this.parent.capture.apply(this, this.getPosition()); this.uninit(); break; case "mouseover": if (this.target) this.lowlight(); this.target = e.target; this.highlight(); break; } }, init() { this.win = content; this.doc = content.document; ["click", "mouseover"].forEach(type=> this.doc.addEventListener(type, this, true)); }, uninit() { this.target = false; ["click", "mouseover"].forEach(type=> this.doc.removeEventListener(type, this, true)); } }` }); this.oncontextmenu =e=> { e.button && !e.ctrlKey && e.preventDefault() };
Отсутствует
Dumby и Vitaliy V. - Спасибо, ваша помощь невероятно полезна!
А как получить путь к папке Загрузки, если параметр "browser.download.lastDir" не существует?
Downloads.getSystemDownloadsDirectory() возвращает не строку, а что-то другое - [Object Promise]……
Dumby - подключил код saveSelectionToTxt(), но текстовый файл не сохраняется:
Uncaught ReferenceError: _id is not defined
Uncaught ReferenceError: addDestructor is not defined
Отредактировано Dobrov (16-04-2021 17:58:30)
Отсутствует
чтобы при таком октрытии (с буфера при нажатии ПКМ на +) вкладки загружались
(async (sel, self) => ({ icon: "circle", colors: [ "mediumseagreen", "silver", "crimson", "blue", "peru", ], initColors() { var colorName = "ucf-gen"; var css = "@-moz-document url(about:preferences#containers)," + " url-prefix(chrome://browser/content/browser.x) {\n"; this.colors.forEach((color, ind) => { var [ic, tc] = color.split(/\s*\|\s*/); css += `\t.identity-color-${colorName}${ind} {\n` + `\t\t--identity-tab-color: ${tc || ic};\n` + `\t\t--identity-icon-color: ${ic};\n\t}\n` }); var url = "data:text/css;charset=utf-8," + encodeURIComponent(css + "}"); var sss = Cc["@mozilla.org/content/style-sheet-service;1"] .getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI(url), sss.USER_SHEET); var len = this.colors.length; var pref = "ucf.openInGeneratedContainer.lastColor"; var ind = Math.min(Services.prefs.getIntPref(pref, -1), len - 1); this.nextColor = () => { var next = ind + 1; Services.prefs.setIntPref(pref, ind = next == len ? 0 : next); return colorName + ind; } }, init(topic) { Services.obs.addObserver(self = this, topic); Services.obs.addObserver(function quit(s, t) { Services.obs.removeObserver(self, topic); Services.obs.removeObserver(quit, t); }, "quit-application-granted"); this.initColors(); }, observe(doc) { var list = doc.querySelectorAll(sel); if (!list.length) return; var menuitem = doc.createXULElement("menuitem"); for(var args of Object.entries({ selectiontype: "single", oncommand: "cmd(window)", nodetype: "folder|query", selection: "folder|query", label: "Открыть всё в контейнере", id: "placesContext_openContainer:tabs:newUsercontext" })) menuitem.setAttribute(...args); menuitem.cmd = this.cmd; menuitem.rnd = menuitem.constructor.prototype.render; menuitem.render = this.render; var [m1, m2] = menuitem.list = Array.from(list); (m2 || m1).after(menuitem); if (doc.documentElement.getAttribute("windowtype") == "navigator:browser") for(var btn of [ doc.getElementById("tabs-newtab-button"), doc.getElementById("new-tab-button") || doc.ownerGlobal.gNavToolbox.palette.querySelector("#new-tab-button") ]) if (btn) btn.checkForMiddleClick = this.click; }, click(btn, e) { if (!(e.button != 2 || e.ctrlKey || e.shiftKey)) { var txt = e.view.readFromClipboard(); if (txt) { var urls = txt.split("\n").map(self.map).filter(Boolean); if (urls.length) return e.preventDefault(), self.openFromClipboard(e.view, urls); } } e.view.checkForMiddleClick(btn, e); }, eo: Object.create(null), map(str) { str = str.trim(); try { var scheme = Services.io.extractScheme(str); var ph = Services.io.getProtocolHandler(scheme); if (ph.scheme == scheme) return Services.io.newURI(str) && {uri: str}; } catch {} }, openFromClipboard(win, urls) { if (win.OpenInTabsUtils.confirmOpenInTabs(urls.length, win)) urls.load = true, this.open(win, this.eo, urls); }, async render() { this.rnd(); await new Promise(this.ownerGlobal.requestAnimationFrame); this.hidden || (this.hidden = this.list.every(self.every)); }, every: node => node.disabled || node.hidden, cmd(win) { var view = this.parentNode._view; var node = win.document.popupNode; node = node._placesView && node._placesView.result.root; self.open(win, node || view.selectedNode || view.result.root); }, open(win, node, list) { var gbw = Cu.import("resource:///modules/PlacesUIUtils.jsm", {}).getBrowserWindow; var w = gbw(win); this.pu = w.PlacesUIUtils; this.fs = w.PlacesUtils.favicons; this.cis = w.ContextualIdentityService; this.sysp = w.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL; (this.open = (win, node, list) => { this.openURLs(gbw(win), list || win.PlacesUtils.getURLsForContainerNode(node)); node.bookmarkGuid && this.pu.doCommand(win, "placesCmd_delete"); })(win, node, list); }, async openURLs(win, urls) { var {userContextId} = this.cis.create( `[ ${this.cis._lastUserContextId + 1} ]`, this.icon, this.nextColor() ); var mark = !win.PrivateBrowsingUtils.isWindowPrivate(win); var {load} = urls, gb = win.gBrowser, pos = gb.selectedTab._tPos; for(var {uri, title, isBookmark} of urls) try { if (mark) isBookmark ? this.pu.markPageAsFollowedBookmark(uri) : this.pu.markPageAsTyped(uri); if (load) { gb.addTrustedTab(uri, {index: ++pos, userContextId}); continue; } var state = {userContextId, entries: [{ url: uri, title: title || uri, triggeringPrincipal_base64: this.sysp }]}; var [,, data, mime] = await new Promise( resolve => this.fs.getFaviconDataForPage( Services.io.newURI(uri), (...args) => resolve(args), 16 ) ); if (data.length) state.image = `data:${ mime || "image/x-icon" };base64,${ btoa(String.fromCharCode(...data)) }`; var tab = gb.addTrustedTab(null, {index: ++pos, userContextId}); win.SessionStore.setTabState(tab, state); } catch {}; } }).init("chrome-document-loaded"))( "#placesContext_openBookmarkContainer\\:tabs,#placesContext_openContainer\\:tabs" );
Downloads.getSystemDownloadsDirectory() возвращает не строку, а что-то другое - [Object Promise]……
Верное наблюдение.
А как получить путь к папке Загрузки, если параметр "browser.download.lastDir" не существует?
Без понятия о чём речь. Может с консоли позапускай (оно или нет)
await Downloads.getPreferredDownloadsDirectory();
подключил код saveSelectionToTxt()
Это подключил что.
Теперь, подключил как, и подключил куда (к чему).
как привязать
Вроде как на то он и Shadow DOM, чтоб нельзя было привязать.
У себя вижу, что работает, если, например, добавить в
%Fox%\omni.ja\chrome\toolkit\skin\classic\global\global.css
:host(#BMB_bookmarksPopup) > vbox.panel-arrowcontainer { outline: 8px solid deeppink !important; outline-offset: -4px !important; }
Отредактировано Dumby (17-04-2021 01:36:43)
Отсутствует
Это подключил что? Теперь, подключил как, и подключил куда (к чему)?
Ошибка в 20 строке - нет _id. Подключил saveSelectionToTxt в 120 строку, как предыдущий пример с кодом save().
Доработал SaveHTML так: в конце сохранённого HTML будет ссылка на оригинал (вместо скрытого комментария).
Файл сохраняется в путь: Загрузки\_Web\домен\файл.html
(async (name, id, func) => { // дополнительные клики на downloads-button для custom_script_win.js if (name == "Object") return CustomizableUI.createWidget(func()); var win = name == "Window", g = Components.utils.import("resource://gre/modules/Services.jsm", {}); if (g[id]) {if (win) return;} else g[id] = func(); if (win) return CustomizableUI.createWidget(g[id]); addDestructor(r => r[5] == "e" && delete g[id]); g[id].onCreated(this); })(this.constructor.name, "ucf_hookClicks", () => { // BEGIN (async (id, func) => { await window.delayedStartupPromise; var btn = document.getElementById("downloads-button"); if (!btn) return; btn.setAttribute("context", "event.stopPropagation()"); // откл контекстное меню btn.tooltipText = GetDynamicShortcutTooltipText(btn.id) + '\nКолёсико: папка Загрузки\nПравый клик: Сохранить страницу'; var saveSelectionToTxt = () => { // сохранить страницу или выделенный текст как файл .txt var splice = saveURL.length == 10; var msgName = _id + ":Save:GetSelection"; var receiver = msg => { var args = [ "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\r\n\r\n" + msg.data), getTabLabel() + ' ' + aDate().replace(/:/g, ".") + ".txt", null, false, false, null, window.document ]; splice && args.splice(5, 0, null); saveURL(...args); } messageManager.addMessageListener(msgName, receiver); addDestructor(() => messageManager.removeMessageListener(msgName, receiver)); var func = fm => { var res, fed, win = {}; var fe = fm.getFocusedElementForWindow(content, true, win); var sel = (win = win.value).getSelection(); if (sel.isCollapsed) { var ed = fe && fe.editor; if (ed && ed instanceof Ci.nsIEditor) sel = ed.selection, fed = fe; } if (sel.isCollapsed) fed && fed.blur(), docShell.doCommand("cmd_selectAll"), res = win.getSelection().toString(), docShell.doCommand("cmd_selectNone"), fed && fed.focus(); res = res || sel.toString(); /\S/.test(res) && sendAsyncMessage("NAME", res); } var url = "data:charset=utf-8," + encodeURIComponent(`(${func})`.replace("NAME", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // end var save = () => { var {wm} = Services, find = w => !w.closed && w.toolbar.visible; var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); var obs = class { constructor(path, alertName) { this.fp = path; this.an = alertName; } noop() {} win = Cu.getWeakReference(window).get; observe(s, topic) {switch(topic) { case "alertshow": (this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer)) .initWithCallback(this, 5e3, Ci.nsITimer.TYPE_ONE_SHOT_LOW_PRIORITY); break; case "alertclickcallback": var win = this.win(); if (!win || win.closed) win = Array.from(wm.getEnumerator("navigator:browser")).find(find); if (win) { win.gBrowser.selectedTab = win.gBrowser.addTrustedTab(win.PathUtils.toFileURI(this.fp)); win.windowState == win.STATE_MINIMIZED && win.restore(); } case "alertfinished": this.observe = this.noop; this.timer.cancel(); }} notify() {as.closeAlert(this.an);} }; var msgName = "ucfDwnldsBtnSaveSnapshotToHTML"; var write = IOUtils.writeUTF8 ? "writeUTF8" : "writeAtomicUTF8"; var Title = function (type) { // заголовок (без обрезки, если type не указан), домен (type <0) var title = (document.title || gBrowser.mCurrentTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.replace(/[:\\\/<>?*|"]+/g,' ').replace(/\s+/g,' ').replace(/ /g,' ').substr(0, type).trim(); // ограничить длину имени var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=/,'').replace(/^https?:\/\//,'').replace(/\/.*/,''); return host.replace(/^www\./,'').replace(/^ru\./,'').replace(/^m\./,'').replace(/^forum\./,'').replace(/^club\.dns/,'dns'); }; var msgListener = async msg => { var [fileContent, fileName] = msg.data; var savedir = PathUtils.join(await Downloads.getPreferredDownloadsDirectory(), "_Web", Title(-1)); // каталог Загрузки + домен var path = PathUtils.join(savedir, fileName); await IOUtils[write](path, fileContent); var name = msgName + Cu.now(); as.showAlertNotification( null, "Страница сохранена в:", savedir, true, null, new obs(path, name), name ); } messageManager.addMessageListener(msgName, msgListener); ucf[id].destructor = () => { btn.removeEventListener("click", listener); messageManager.removeMessageListener(msgName, msgListener); } var svc = 'globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services'; var url = "data:;charset=utf8," + encodeURIComponent(`(${func})(${svc});`.replace("%MSG_NAME%", msgName)); (save = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // end save var listener = e => { // Clicks if (e.button == 1) { Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(), Cu.reportError); // Обзор папки «Загрузки» } else if (e.button == 2) { if (e.shiftKey) saveSelectionToTxt() // сохранить .txt else // ПКМ Click save(); // Single HTML } } btn.addEventListener("click", listener); var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; ucf[id] = {destructor: () => btn.removeEventListener("click", listener)}; ucf.unloadlisteners.push(id); })("downloads-button-click-listener", ({io, focus}) => { var resolveURL = function (url, base) { try { return io.newURI(url, null, io.newURI(base)).spec; } catch {} }; var getSelWin = function (w) { if (w.getSelection().toString()) return w; for (var i = 0, f, r; f = w.frames[i]; i++) { try { if (r = getSelWin(f)) return r; } catch(e) {} } }; var encodeImg = function (src, obj) { var canvas, img, ret = src; if (/^https?:\/\//.test(src)) { canvas = doc.createElement('canvas'); if (!obj || obj.nodeName.toLowerCase() != 'img') { img = doc.createElement('img'); img.src = src; } else { img = obj; }; if (img.complete) try{ canvas.width = img.width; canvas.height = img.height; canvas.getContext('2d').drawImage(img, 0, 0); ret = canvas.toDataURL((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png')); } catch (e) {}; if (img != obj) img.src = 'about:blank'; }; return ret; }; var toSrc = function (obj) { var strToSrc = function (str) { var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'}; while (chr = str.charAt(i++)) { ret += meta[chr] || chr; }; return '\x22' + ret + '\x22'; }, arrToSrc = function (arr) { var ret = []; for (var i = 0; i < arr.length; i++) { ret[i] = toSrc(arr[i]) || 'null'; }; return '[' + ret.join(',') + ']'; }, objToSrc = function (obj) { var val, ret = []; for (var prop in obj) { if (obj.hasOwnProperty(prop) && (val = toSrc(obj[prop]))) ret.push(strToSrc(prop) + ': ' + val); }; return '{' + ret.join(',') + '}'; }; switch (Object.prototype.toString.call(obj).slice(8, -1)) { case 'Array': return arrToSrc(obj); case 'Boolean': case 'Function': case 'RegExp': return obj.toString(); case 'Date': return 'new Date(' + obj.getTime() + ')'; case 'Math': return 'Math'; case 'Number': return isFinite(obj) ? String(obj) : 'null'; case 'Object': return objToSrc(obj); case 'String': return strToSrc(obj); default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null'; } }; var mainWin = {}; focus.getFocusedElementForWindow(content, true, mainWin); mainWin = mainWin.value; var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location; var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/g; if (selWin) { var rng = win.getSelection().getRangeAt(0); pEle = rng.commonAncestorContainer; ele = rng.cloneContents(); } else { pEle = doc.documentElement; ele = (doc.body || doc.getElementsByTagName('body')[0]).cloneNode(true); }; while (pEle) { if (pEle.nodeType == 1) { clone = pEle.cloneNode(false); clone.appendChild(ele); ele = clone; }; pEle = pEle.parentNode }; var sel = doc.createElement('div'); sel.appendChild(ele); for (var el, all = sel.getElementsByTagName('*'), i = all.length; i--;) { el = all[i]; if (el.style && el.style.backgroundImage) el.style.backgroundImage = el.style.backgroundImage.replace(reUrl, function (a, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href); return prev + encodeImg(url) + next; }); switch (el.nodeName.toLowerCase()) { case 'link': case 'style': case 'script': el.parentNode.removeChild(el); break; case 'a': case 'area': if (el.hasAttribute('href') && el.getAttribute('href').charAt(0) != '#') el.href = el.href; break; case 'img': case 'input': if (el.hasAttribute('src')) el.src = encodeImg(el.src, el); break; case 'audio': case 'video': case 'embed': case 'frame': case 'iframe': if (el.hasAttribute('src')) el.src = el.src; break; case 'object': if (el.hasAttribute('data')) el.data = el.data; break; case 'form': if (el.hasAttribute('action')) el.action = el.action; break; } }; var head = ele.insertBefore(doc.createElement('head'), ele.firstChild); var meta = doc.createElement('meta'); meta.httpEquiv = 'content-type'; meta.content = 'text/html; charset=utf-8'; head.appendChild(meta); var title = doc.getElementsByTagName('title')[0]; if (title) head.appendChild(title.cloneNode(true)); head.copyScript = function (unsafeWin) { if ('$' in unsafeWin) return; var f = doc.createElement('iframe'); f.src = 'about:blank'; f.setAttribute('style', 'position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;'); doc.documentElement.appendChild(f); var str, script = doc.createElement('script'); script.type = 'text/javascript'; for (var name in unsafeWin) { if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue; try { str = toSrc(unsafeWin[name]); if (!/\{\s*\[native code\]\s*\}/.test(str)) { script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n')); } } catch (e) {}; }; f.parentNode.removeChild(f); if (script.childNodes.length) this.nextSibling.appendChild(script); }; head.copyScript(win.wrappedJSObject || win); head.copyStyle = function (s) { if (!s) return; var style = doc.createElement('style'); style.type = 'text/css'; if (s.media && s.media.mediaText) style.media = s.media.mediaText; try { for (var i = 0, rule; rule = s.cssRules[i]; i++) { if (rule.type != 3) { if((!rule.selectorText || rule.selectorText.indexOf(':') != -1) || (!sel.querySelector || sel.querySelector(rule.selectorText))) { var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href); if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url); return prev + url + next; }); style.appendChild(doc.createTextNode(css + '\n')); } } else { this.copyStyle(rule.styleSheet); } } } catch(e) { if (s.ownerNode) style = s.ownerNode.cloneNode(false); }; this.appendChild(style); }; var sheets = doc.styleSheets; for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]); head.appendChild(doc.createTextNode('\n')); var doctype = '', dt = doc.doctype; if (dt && dt.name) { doctype += '<!DOCTYPE ' + dt.name; if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22'; if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22'; doctype += '>\n'; }; var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop()); fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).trim(); fileName += "_" + new Date().toLocaleString("ru").replace(", ","-").replace(/:/g, "։"); if (!/\.html?$/.test(fileName)) fileName += '.html'; sendAsyncMessage("%MSG_NAME%", [doctype + sel.innerHTML +'\n<a href='+ (loc.protocol != 'data:' ? loc.href : 'data:uri') +'><small><blockquote>источник: '+ new Date().toLocaleString("ru") +'</blockquote></small></a>', fileName]); }); }); // END hookClicks
Dumby - твой код SaveHTML не сохраняет графику некоторых сайтов. (проверил на чистом профиле FF 84)
Также не сохраняет графику сайта meteo7.ru код от Vitaliy V.
Сохраняем прогноз с meteo7.ru - открываем - картинок облаков, ветра и прочего нет!
Сохраняем страницу с habr.com - открываем - всё с картинками.
Проблема 2 - нет сохранённых файлов страниц, если нажимаем: "Показать все загрузки"
Хотелка - назначить сочетание клавиш (напр. Ctrl+Shift+S) на сохранение страницы - запуск save()
Возможно доработать SaveHTML, который ты мне делал для кода: «Перехват кликов Download Button» ?
или есть другой, более универсальный код ?
Dumby ещё проверь мой код получения заголовка или домена, может я где-то накосячил:
var Title = function (type) { // получить заголовок (без обрезки, если type не указан) или домен (type <0) var title = (document.title || gBrowser.mCurrentTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.replace(/[:\\\/<>?*|"]+/g,' ').replace(/\s+/g,' ').replace(/ /g,' ').substr(0, type).trim(); // ограничить длину имени var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=/,'').replace(/^https?:\/\//,'').replace(/\/.*/,''); return host.replace(/^www\./,'').replace(/^ru\./,'').replace(/^m\./,'').replace(/^forum\./,'').replace(/^club\.dns/,'dns'); };
Отредактировано Dobrov (17-04-2021 09:13:59)
Отсутствует
Dumby
С прошлыми проблемами понятно. А, что скажите на это ? В 87 dom.ipc.processCount - 1 и такая шняга при очистке профиля.( "startupCache.4.little")... dom.ipc.processCoun > больше 1-все норм.
https://forum.mozilla-russia.org/viewto … 88#p789988
Отсутствует
нет _id
Подойдёт и просто id (без «_»).
Подключил saveSelectionToTxt в 120 строку
Нужно определить addDestructor(), типа
... var addDestructor = nextDestructor => { var {destructor} = ucf[id]; ucf[id].destructor = () => { try {destructor();} catch(ex) {Cu.reportError(ex);} nextDestructor(); } }
/* ucf[id].destructor = () => { btn.removeEventListener("click", listener); messageManager.removeMessageListener(msgName, msgListener); } */ addDestructor(() => messageManager.removeMessageListener(msgName, msgListener));
И, третий(!) раз будет сказано — удалить всё от начала и до «// BEGIN»,
и, соответственно, последнюю строку.
твой код SaveHTML не сохраняет графику некоторых сайтов
Это что ещё за формулировка? Код не мой, а Лекса.
Да, с meteo картинки не сохраняет. Было бы хорошо, если бы Лекс нарисовался, и подправил,
чтобы там вообще svg-адреса кодировались в data-адреса без никакого canvas'а, но, увы...
Хотелка - назначить сочетание клавиш (напр. Ctrl+Shift+S) на сохранение страницы - запуск save()
Какие-то проблемы зарегистрировать листенер на событие "keydown"?
проверь мой код получения заголовка или домена, может я где-то накосячил
gBrowser.mCurrentTab давно уже неактуален, следует использовать gBrowser.selectedTab
А, что скажите на это ?
Ничего не скажу. Сходу — не воспроизводится. Ждать «иногда» — можно не дождаться.
Отсутствует
Да, с meteo картинки не сохраняет. Было бы хорошо, если бы Лекс нарисовался, и подправил,
чтобы там вообще svg-адреса кодировались в data-адреса без никакого canvas'а, но, увы...
SaveHTML использую, чтобы сохранить страницу из режима чтения. Почему-то SingleFile из Read View не сохраняет!
А есть способ сохранять страницу из about:reader как единый HTML этим или другим подобным расширением?
Спасибо!, поправил saveSelectionToTxt. Добавил некоторые фишки (подробности в подсказке кнопки), Сочетание клавиш Ctrl+Alt+S имитирует клик по кнопке SingleSave, а если нет расширения, то выполняет save()…
Есть вопросы: Дважды почти одинаковый код формирует имя с датой. Как сделать глобальную функцию filename = name_date() ?
function name_date (title) { // имя+дата: упрощённый пример без получения имени вкладки. title = title.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 99).trim(); return title +"_"+ new Date().toLocaleString("ru").replace(", ","-").replace(/:/g, "։"); };
Вторая просьба: переделать в глобальную функцию показ Уведомлений из кода save(), чтобы при сохранении текстового файла его тоже можно было открыть по клику на Notification.
А возможно эти (и другие общие) функции вписать сразу в custom_script.js или custom_script_win.js, чтобы их можно было вызвать из любого скрипта, подключенного как loadscript(…) ?
(async (id, func) => { // дополнительные клики на downloads-button для custom_script_win.js await window.delayedStartupPromise; var btn = document.getElementById("downloads-button"); if (!btn) return; btn.setAttribute("context", "event.stopPropagation()"); // откл контекстное меню btn.tooltipText = GetDynamicShortcutTooltipText(btn.id) +` Ролик: Обзор папки «Загрузки» …Shift Сайт: графика Вкл/Выкл ПКМ: Сохранить как файл .txt всё | выделенный текст …Shift Сохранить единый .html Alt⇧S нажать SingleSave`; // если такой кнопки нет, то выполнить save() var saveSelectionToTxt = () => { // сохранить страницу или выделенный текст как файл .txt var splice = saveURL.length == 10; var msgName = id + ":Save:GetSelection"; var title = (document.title || gBrowser.selectedTab.label); var receiver = msg => { var args = [ "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\n\n" + msg.data), title.replace(/[:\\\/<>?*|"]+/g,'_').replace(/\s+/g,' ').slice(0, 100).trim() + '_' + new Date().toLocaleString('ru').replace(', ','-').replace(/:/g, '։') + '.txt', null, false, true, null, window.document ]; splice && args.splice(5, 0, null); saveURL(...args); } messageManager.addMessageListener(msgName, receiver); var addDestructor = nextDestructor => { var {destructor} = ucf[id]; ucf[id].destructor = () => { try {destructor();} catch(ex) {Cu.reportError(ex);} nextDestructor(); } } var func = fm => { var res, fed, win = {}; var fe = fm.getFocusedElementForWindow(content, true, win); var sel = (win = win.value).getSelection(); if (sel.isCollapsed) { var ed = fe && fe.editor; if (ed && ed instanceof Ci.nsIEditor) sel = ed.selection, fed = fe; } if (sel.isCollapsed) fed && fed.blur(), docShell.doCommand("cmd_selectAll"), res = win.getSelection().toString(), docShell.doCommand("cmd_selectNone"), fed && fed.focus(); res = res || sel.toString(); /\S/.test(res) && sendAsyncMessage("saveSelectionToTxt", res); } var url = "data:charset=utf-8," + encodeURIComponent(`(${func})`.replace("saveSelectionToTxt", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // end var save = () => { // автор: Лекс, правка: Dumby, Dobrov var {wm} = Services, find = w => !w.closed && w.toolbar.visible; var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); var obs = class { constructor(path, alertName) { this.fp = path; this.an = alertName; } noop() {} win = Cu.getWeakReference(window).get; observe(s, topic) {switch(topic) { case "alertshow": (this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer)) .initWithCallback(this, 5e3, Ci.nsITimer.TYPE_ONE_SHOT_LOW_PRIORITY); break; case "alertclickcallback": var win = this.win(); if (!win || win.closed) win = Array.from(wm.getEnumerator("navigator:browser")).find(find); if (win) { win.gBrowser.selectedTab = win.gBrowser.addTrustedTab(win.PathUtils.toFileURI(this.fp)); win.windowState == win.STATE_MINIMIZED && win.restore(); } case "alertfinished": this.observe = this.noop; this.timer.cancel(); }} notify() {as.closeAlert(this.an);} }; var msgName = id + "ucfDwnldsBtnSaveSnapshotToHTML"; var write = IOUtils.writeUTF8 ? "writeUTF8" : "writeAtomicUTF8"; var Title = function (type) { // получить заголовок (без обрезки, если type не указан) или домен (type <0) var title = (document.title || gBrowser.selectedTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.replace(/[:\\\/<>?*|"]+/g,' ').replace(/\s+/g,' ').replace(/ /g,' ').substr(0, type).trim(); // ограничить длину имени var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=/,'').replace(/^https?:\/\//,'').replace(/\/.*/,''); return host.replace(/^www\./,'').replace(/^ru\./,'').replace(/^m\./,'').replace(/^forum\./,'').replace(/^club\.dns/,'dns'); }; var msgListener = async msg => { var [fileContent, fileName] = msg.data; var savedir = PathUtils.join(await Downloads.getPreferredDownloadsDirectory(), "_Web", Title(-1)); // каталог Загрузки + домен var path = PathUtils.join(savedir, fileName); await IOUtils[write](path, fileContent); var name = msgName + Cu.now(); as.showAlertNotification( null, "Страница сохранена в:", savedir, true, null, new obs(path, name), name ); } messageManager.addMessageListener(msgName, msgListener); ucf[id] = {destructor: () => btn.removeEventListener(msgName, listener)}; var svc = 'globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services'; var url = "data:;charset=utf8," + encodeURIComponent(`(${func})(${svc});`.replace("%MSG_NAME%", msgName)); (save = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // end save var listener = e => { // Clicks var trg = e.target, {prefs} = Services; if (e.button == 1) { if (e.shiftKey) { // СКМ + Shift if ( prefs.getIntPref("permissions.default.image", 1) == 1) prefs.setIntPref("permissions.default.image", 2), trg.style.filter = "hue-rotate(180deg) brightness(95%)" else prefs.setIntPref("permissions.default.image", 1), trg.style.filter = ""; BrowserReload(); } else // СКМ Click Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(), Cu.reportError); // Обзор папки «Загрузки» } else if (e.button == 2) { if (e.shiftKey) save() // Single HTML else // ПКМ Click saveSelectionToTxt(); // сохранить .txt } } var keydown_win = e => { if (!(e.keyCode == 83 && e.shiftKey && e.altKey)) return; var singlesave = document.getElementById("_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action"); // SingleSave singlesave ? singlesave.click() : save(); // имитировать клик по кнопке, используя её ID } var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; btn.addEventListener("click", listener); ucf[id] = {destructor: () => btn.removeEventListener("click", listener)}; window.addEventListener("keydown", keydown_win); ucf[id] = {destructor: () => window.removeEventListener("keydown", keydown_win)}; ucf.unloadlisteners.push(id); })("downloads-button-click-listener", ({io, focus}) => { var resolveURL = function (url, base) { try { return io.newURI(url, null, io.newURI(base)).spec; } catch {} }; var getSelWin = function (w) { if (w.getSelection().toString()) return w; for (var i = 0, f, r; f = w.frames[i]; i++) { try { if (r = getSelWin(f)) return r; } catch(e) {} } }; var encodeImg = function (src, obj) { var canvas, img, ret = src; if (/^https?:\/\//.test(src)) { canvas = doc.createElement('canvas'); if (!obj || obj.nodeName.toLowerCase() != 'img') { img = doc.createElement('img'); img.src = src; } else { img = obj; }; if (img.complete) try{ canvas.width = img.width; canvas.height = img.height; canvas.getContext('2d').drawImage(img, 0, 0); ret = canvas.toDataURL((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png')); } catch (e) {}; if (img != obj) img.src = 'about:blank'; }; return ret; }; var toSrc = function (obj) { var strToSrc = function (str) { var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'}; while (chr = str.charAt(i++)) { ret += meta[chr] || chr; }; return '\x22' + ret + '\x22'; }, arrToSrc = function (arr) { var ret = []; for (var i = 0; i < arr.length; i++) { ret[i] = toSrc(arr[i]) || 'null'; }; return '[' + ret.join(',') + ']'; }, objToSrc = function (obj) { var val, ret = []; for (var prop in obj) { if (obj.hasOwnProperty(prop) && (val = toSrc(obj[prop]))) ret.push(strToSrc(prop) + ': ' + val); }; return '{' + ret.join(',') + '}'; }; switch (Object.prototype.toString.call(obj).slice(8, -1)) { case 'Array': return arrToSrc(obj); case 'Boolean': case 'Function': case 'RegExp': return obj.toString(); case 'Date': return 'new Date(' + obj.getTime() + ')'; case 'Math': return 'Math'; case 'Number': return isFinite(obj) ? String(obj) : 'null'; case 'Object': return objToSrc(obj); case 'String': return strToSrc(obj); default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null'; } }; var mainWin = {}; focus.getFocusedElementForWindow(content, true, mainWin); mainWin = mainWin.value; var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location; var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/g; if (selWin) { var rng = win.getSelection().getRangeAt(0); pEle = rng.commonAncestorContainer; ele = rng.cloneContents(); } else { pEle = doc.documentElement; ele = (doc.body || doc.getElementsByTagName('body')[0]).cloneNode(true); }; while (pEle) { if (pEle.nodeType == 1) { clone = pEle.cloneNode(false); clone.appendChild(ele); ele = clone; }; pEle = pEle.parentNode }; var sel = doc.createElement('div'); sel.appendChild(ele); for (var el, all = sel.getElementsByTagName('*'), i = all.length; i--;) { el = all[i]; if (el.style && el.style.backgroundImage) el.style.backgroundImage = el.style.backgroundImage.replace(reUrl, function (a, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href); return prev + encodeImg(url) + next; }); switch (el.nodeName.toLowerCase()) { case 'link': case 'style': case 'script': el.parentNode.removeChild(el); break; case 'a': case 'area': if (el.hasAttribute('href') && el.getAttribute('href').charAt(0) != '#') el.href = el.href; break; case 'img': case 'input': if (el.hasAttribute('src')) el.src = encodeImg(el.src, el); break; case 'audio': case 'video': case 'embed': case 'frame': case 'iframe': if (el.hasAttribute('src')) el.src = el.src; break; case 'object': if (el.hasAttribute('data')) el.data = el.data; break; case 'form': if (el.hasAttribute('action')) el.action = el.action; break; } }; var head = ele.insertBefore(doc.createElement('head'), ele.firstChild); var meta = doc.createElement('meta'); meta.httpEquiv = 'content-type'; meta.content = 'text/html; charset=utf-8'; head.appendChild(meta); var title = doc.getElementsByTagName('title')[0]; if (title) head.appendChild(title.cloneNode(true)); head.copyScript = function (unsafeWin) { if ('$' in unsafeWin) return; var f = doc.createElement('iframe'); f.src = 'about:blank'; f.setAttribute('style', 'position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;'); doc.documentElement.appendChild(f); var str, script = doc.createElement('script'); script.type = 'text/javascript'; for (var name in unsafeWin) { if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue; try { str = toSrc(unsafeWin[name]); if (!/\{\s*\[native code\]\s*\}/.test(str)) { script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n')); } } catch (e) {}; }; f.parentNode.removeChild(f); if (script.childNodes.length) this.nextSibling.appendChild(script); }; head.copyScript(win.wrappedJSObject || win); head.copyStyle = function (s) { if (!s) return; var style = doc.createElement('style'); style.type = 'text/css'; if (s.media && s.media.mediaText) style.media = s.media.mediaText; try { for (var i = 0, rule; rule = s.cssRules[i]; i++) { if (rule.type != 3) { if((!rule.selectorText || rule.selectorText.indexOf(':') != -1) || (!sel.querySelector || sel.querySelector(rule.selectorText))) { var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href); if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url); return prev + url + next; }); style.appendChild(doc.createTextNode(css + '\n')); } } else { this.copyStyle(rule.styleSheet); } } } catch(e) { if (s.ownerNode) style = s.ownerNode.cloneNode(false); }; this.appendChild(style); }; var sheets = doc.styleSheets; for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]); head.appendChild(doc.createTextNode('\n')); var doctype = '', dt = doc.doctype; if (dt && dt.name) { doctype += '<!DOCTYPE ' + dt.name; if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22'; if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22'; doctype += '>\n'; }; var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop()); fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).trim(); fileName += "_" + new Date().toLocaleString("ru").replace(", ","-").replace(/:/g, "։"); if (!/\.html?$/.test(fileName)) fileName += '.html'; sendAsyncMessage("%MSG_NAME%", [doctype + sel.innerHTML +'\n<a href='+ (loc.protocol != 'data:' ? loc.href : 'data:uri') +'><small><blockquote>источник: '+ new Date().toLocaleString("ru") +'</blockquote></small></a>', fileName]); }); // END hookClicks
Отредактировано Dobrov (18-04-2021 15:55:53)
Отсутствует
Dumby
Вы бы не могли еще помочь пожалуйста, если можно сделать чтобы со строки поиска, результат поиска открывался тоже в новом контейнере?
Отредактировано Stkvsky (18-04-2021 17:04:13)
Отсутствует
Почему-то SingleFile из Read View не сохраняет!
Без комментариев.
поправил
addDestructor() сказано было определить не для того,
чтобы он торчал в saveSelectionToTxt() и ничего не делал,
а на на уровень выше, и чтобы пользоваться.
Дважды почти одинаковый код формирует имя с датой. Как сделать глобальную функцию filename = name_date() ?
Никак. Второй код для frame script'а.
Он в функции, которая используется не как функция, а как носитель кода (текста),
то есть, там можно только ещё один слот под replace сделать, если очень надо.
чтобы при сохранении текстового файла его тоже можно было открыть по клику на Notification
Ну и откуда возьмётся путь? Разве что загрузки отслеживать.
... var addDestructor = nextDestructor => { var {destructor} = ucf[id]; ucf[id].destructor = () => { try {destructor();} catch(ex) {Cu.reportError(ex);} nextDestructor(); } } var notify = (msg, path) => { var {wm} = Services, find = w => !w.closed && w.toolbar.visible; var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); var obs = class { constructor(path, name) { this.fp = path; this.an = name; } noop() {} win = Cu.getWeakReference(window).get; observe(s, topic) {switch(topic) { case "alertshow": (this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer)) .initWithCallback(this, 5e3, Ci.nsITimer.TYPE_ONE_SHOT_LOW_PRIORITY); break; case "alertclickcallback": var win = this.win(); if (!win || win.closed) win = Array.from(wm.getEnumerator("navigator:browser")).find(find); if (win) { win.gBrowser.selectedTab = win.gBrowser.addTrustedTab(win.PathUtils.toFileURI(this.fp)); win.windowState == win.STATE_MINIMIZED && win.restore(); } case "alertfinished": this.observe = this.noop; this.timer.cancel(); }} notify() {as.closeAlert(this.an);} }; (notify = (msg, path) => { var name = id + Cu.now(); as.showAlertNotification(null, msg, PathUtils.parent(path), true, null, new obs(path, name), name); })(msg, path); } var saveSelectionToTxt = async () => { // сохранить страницу или выделенный текст как файл .txt var splice = saveURL.length == 10; var msgName = id + ":Save:GetSelection"; var view = {onDownloadChanged(d) { d.succeeded && d.source.url.startsWith(this.id) && notify("Текст сохранён в:", d.target.path); }}; var list = await Downloads.getList(Downloads.ALL); await list.addView(view); var receiver = msg => { var prfx = view.id = `data:text/plain;${Date.now()};`; var title = document.title || gBrowser.selectedTab.label; var args = [ prfx + "charset=utf-8," + encodeURIComponent(/*"\ufeff" + */gBrowser.currentURI.spec + "\n\n" + msg.data), title.replace(/[:\\\/<>?*|"]+/g,'_').replace(/\s+/g,' ').slice(0, 100).trim() + '_' + new Date().toLocaleString('ru').replace(', ','-').replace(/:/g, '։') + '.txt', null, false, true, null, window.document ]; splice && args.splice(5, 0, null); saveURL(...args); } messageManager.addMessageListener(msgName, receiver); addDestructor(() => { list.removeView(view); messageManager.removeMessageListener(msgName, receiver); }); var func = fm => { var res, fed, win = {}; var fe = fm.getFocusedElementForWindow(content, true, win); var sel = (win = win.value).getSelection(); if (sel.isCollapsed) { var ed = fe && fe.editor; if (ed && ed instanceof Ci.nsIEditor) sel = ed.selection, fed = fe; } if (sel.isCollapsed) fed && fed.blur(), docShell.doCommand("cmd_selectAll"), res = win.getSelection().toString(), docShell.doCommand("cmd_selectNone"), fed && fed.focus(); res = res || sel.toString(); /\S/.test(res) && sendAsyncMessage("saveSelectionToTxt", res); } var url = "data:;charset=utf-8," + encodeURIComponent(`(${func})`.replace("saveSelectionToTxt", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // end var save = () => { // автор: Лекс, правка: Dumby, Dobrov var msgName = id + "ucfDwnldsBtnSaveSnapshotToHTML"; var write = IOUtils.writeUTF8 ? "writeUTF8" : "writeAtomicUTF8"; var Title = function (type) { // получить заголовок (без обрезки, если type не указан) или домен (type <0) var title = (document.title || gBrowser.selectedTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.replace(/[:\\\/<>?*|"]+/g,' ').replace(/\s+/g,' ').replace(/ /g,' ').substr(0, type).trim(); // ограничить длину имени var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=/,'').replace(/^https?:\/\//,'').replace(/\/.*/,''); return host.replace(/^www\./,'').replace(/^ru\./,'').replace(/^m\./,'').replace(/^forum\./,'').replace(/^club\.dns/,'dns'); }; var msgListener = async msg => { var [fileContent, fileName] = msg.data; var savedir = PathUtils.join(await Downloads.getPreferredDownloadsDirectory(), "_Web", Title(-1)); // каталог Загрузки + домен var path = PathUtils.join(savedir, fileName); await IOUtils[write](path, fileContent); notify("Страница сохранена в:", path); } messageManager.addMessageListener(msgName, msgListener); addDestructor(() => messageManager.removeMessageListener(msgName, msgListener)); var svc = 'globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services'; var url = "data:;charset=utf8," + encodeURIComponent(`(${func})(${svc});`.replace("%MSG_NAME%", msgName)); (save = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // end save var listener = e => { // Clicks var trg = e.target, {prefs} = Services; if (e.button == 1) { if (e.shiftKey) { // СКМ + Shift if ( prefs.getIntPref("permissions.default.image", 1) == 1) prefs.setIntPref("permissions.default.image", 2), trg.style.filter = "hue-rotate(180deg) brightness(95%)"; else prefs.setIntPref("permissions.default.image", 1), trg.style.filter = ""; BrowserReload(); } else // СКМ Click Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(), Cu.reportError); // Обзор папки «Загрузки» } else if (e.button == 2) { if (e.shiftKey) save() // Single HTML else // ПКМ Click saveSelectionToTxt(); // сохранить .txt } } btn.addEventListener("click", listener); var keydown_win = e => { if (!(e.keyCode == 83 && e.shiftKey && e.altKey)) return; var singlesave = document.getElementById("_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action"); // SingleSave singlesave ? singlesave.click() : save(); // имитировать клик по кнопке, используя её ID } window.addEventListener("keydown", keydown_win); var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; ucf[id] = {destructor() { btn.removeEventListener("click", listener); window.removeEventListener("keydown", keydown_win); }}; ucf.unloadlisteners.push(id);
А возможно эти (и другие общие) функции вписать сразу в custom_script.js или custom_script_win.js, чтобы их можно было вызвать из любого скрипта, подключенного как loadscript(…) ?
А почему нет? Обычно наоборот, стараются, без необходимости, не засорять
глобальную область видимости, но, если считаешь какие-то достойными, то добавляй,
как отдельные, или как методы одного объекта (типа gDobrovUtils).
Вот в custom_script_win.js, например, определена глобальная переменная ucf_custom_script_win
можно сделать чтобы со строки поиска, результат поиска открывался тоже в новом контейнере?
Если поиск пойдёт не в текущей вкладке, то можно, наверно
(async (sel, self) => ({ icon: "circle", colors: [ "mediumseagreen", "silver", "crimson", "blue", "peru", ], initColors() { var colorName = "ucf-gen"; var css = "@-moz-document url(about:preferences#containers)," + " url-prefix(chrome://browser/content/browser.x) {\n"; this.colors.forEach((color, ind) => { var [ic, tc] = color.split(/\s*\|\s*/); css += `\t.identity-color-${colorName}${ind} {\n` + `\t\t--identity-tab-color: ${tc || ic};\n` + `\t\t--identity-icon-color: ${ic};\n\t}\n` }); var url = "data:text/css;charset=utf-8," + encodeURIComponent(css + "}"); var sss = Cc["@mozilla.org/content/style-sheet-service;1"] .getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI(url), sss.USER_SHEET); var len = this.colors.length; var pref = "ucf.openInGeneratedContainer.lastColor"; var ind = Math.min(Services.prefs.getIntPref(pref, -1), len - 1); this.nextColor = () => { var next = ind + 1; Services.prefs.setIntPref(pref, ind = next == len ? 0 : next); return colorName + ind; } }, init(topic) { Services.obs.addObserver(self = this, topic); Services.obs.addObserver(function quit(s, t) { Services.obs.removeObserver(self, topic); Services.obs.removeObserver(quit, t); }, "quit-application-granted"); this.initColors(); this.newUsercontext = () => this.cis.create( `[ ${this.cis._lastUserContextId + 1} ]`, this.icon, this.nextColor() ).userContextId; }, observe(doc) { var list = doc.querySelectorAll(sel); if (!list.length) return; var menuitem = doc.createXULElement("menuitem"); for(var args of Object.entries({ selectiontype: "single", oncommand: "cmd(window)", nodetype: "folder|query", selection: "folder|query", label: "Открыть всё в контейнере", id: "placesContext_openContainer:tabs:newUsercontext" })) menuitem.setAttribute(...args); menuitem.cmd = this.cmd; menuitem.rnd = menuitem.constructor.prototype.render; menuitem.render = this.render; var [m1, m2] = menuitem.list = Array.from(list); (m2 || m1).after(menuitem); if (doc.documentElement.getAttribute("windowtype") != "navigator:browser") return; for(var btn of [ doc.getElementById("tabs-newtab-button"), doc.getElementById("new-tab-button") || doc.ownerGlobal.gNavToolbox.palette.querySelector("#new-tab-button") ]) if (btn) btn.checkForMiddleClick = this.click; var win = doc.ownerGlobal; this.redefDoSearch(win, win.customElements.get("searchbar").prototype); }, redefDoSearch(win, proto) { this.cis = win.ContextualIdentityService; var code = `(openTrustedLinkIn => [ {${proto.doSearch}}, openTrustedLinkIn ])( function otl(url, where, params) { if (where != "current") params.userContextId = otl.newUsercontext(); openTrustedLinkIn(url, where, params); } );`; (this.redefDoSearch = (win, proto) => { var [obj, func] = win.eval(code); Object.assign(proto, obj); func.newUsercontext = this.newUsercontext; })(win, proto); }, click(btn, e) { if (!(e.button != 2 || e.ctrlKey || e.shiftKey)) { var txt = e.view.readFromClipboard(); if (txt) { var urls = txt.split("\n").map(self.map).filter(Boolean); if (urls.length) return e.preventDefault(), self.openFromClipboard(e.view, urls); } } e.view.checkForMiddleClick(btn, e); }, eo: Object.create(null), map(str) { str = str.trim(); try { var scheme = Services.io.extractScheme(str); var ph = Services.io.getProtocolHandler(scheme); if (ph.scheme == scheme) return Services.io.newURI(str) && {uri: str}; } catch {} }, openFromClipboard(win, urls) { if (win.OpenInTabsUtils.confirmOpenInTabs(urls.length, win)) urls.load = true, this.open(win, this.eo, urls); }, async render() { this.rnd(); await new Promise(this.ownerGlobal.requestAnimationFrame); this.hidden || (this.hidden = this.list.every(self.every)); }, every: node => node.disabled || node.hidden, cmd(win) { var view = this.parentNode._view; var node = win.document.popupNode; node = node._placesView && node._placesView.result.root; self.open(win, node || view.selectedNode || view.result.root); }, open(win, node, list) { var gbw = Cu.import("resource:///modules/PlacesUIUtils.jsm", {}).getBrowserWindow; var w = gbw(win); this.pu = w.PlacesUIUtils; this.fs = w.PlacesUtils.favicons; this.cis = w.ContextualIdentityService; this.sysp = w.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL; (this.open = (win, node, list) => { this.openURLs(gbw(win), list || win.PlacesUtils.getURLsForContainerNode(node)); node.bookmarkGuid && this.pu.doCommand(win, "placesCmd_delete"); })(win, node, list); }, async openURLs(win, urls) { var userContextId = this.newUsercontext(); var mark = !win.PrivateBrowsingUtils.isWindowPrivate(win); var {load} = urls, gb = win.gBrowser, pos = gb.selectedTab._tPos; for(var {uri, title, isBookmark} of urls) try { if (mark) isBookmark ? this.pu.markPageAsFollowedBookmark(uri) : this.pu.markPageAsTyped(uri); if (load) { gb.addTrustedTab(uri, {index: ++pos, userContextId}); continue; } var state = {userContextId, entries: [{ url: uri, title: title || uri, triggeringPrincipal_base64: this.sysp }]}; var [,, data, mime] = await new Promise( resolve => this.fs.getFaviconDataForPage( Services.io.newURI(uri), (...args) => resolve(args), 16 ) ); if (data.length) state.image = `data:${ mime || "image/x-icon" };base64,${ btoa(String.fromCharCode(...data)) }`; var tab = gb.addTrustedTab(null, {index: ++pos, userContextId}); win.SessionStore.setTabState(tab, state); } catch {}; } }).init("chrome-document-loaded"))( "#placesContext_openBookmarkContainer\\:tabs,#placesContext_openContainer\\:tabs" );
Отсутствует
Ну и откуда возьмётся путь? Разве что загрузки отслеживать.
Понятно. Для .txt это лишнее, их загрузки и так отслеживаются и показываются браузером.
Недостаток SaveHTML в том, что сохранённые .html файлы не появляются в "Показать все загрузки".
Это можно исправить или хотя бы после сохранения .html помигать кнопкой Загрузки, как после скачивания файла?…
Ещё нужен код, чтобы показать свой текст в строке статуса. Я пробовал, но ничего не показывается:
XULBrowserWindow.statusTextField.label = text;
setTimeout(()=> XULBrowserWindow.statusTextField.label = '',3000);
Третье: Dumby, может сделаешь пример, скрывающий панель вкладок, если вкладка одна и показывающий для нескольких?
4) не получается поменять подсказку кнопки в зависимости от того, есть кнопка SingleSave или нет.
btn.tooltipText = GetDynamicShortcutTooltipText(btn.id) +`……`; var singlesave = document.getElementById("_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action"); // SingleSave доступен singlesave ? btn.tooltipText += "\nAlt⇧S нажать SingleSave" : btn.tooltipText += "\nAlt⇧S Сохранить единый .html" ;
(async (id, func) => { // дополнительные клики на downloads-button для custom_script_win.js await window.delayedStartupPromise; var btn = document.getElementById("downloads-button"); if (!btn) return; btn.setAttribute("context", "event.stopPropagation()"); // откл контекстное меню btn.tooltipText = GetDynamicShortcutTooltipText(btn.id) +` Ролик: Обзор папки «Загрузки» …Shift Сайт: графика Вкл/Выкл ПКМ: Сохранить как файл .txt всё | выделенный текст …Shift Сохранить единый .html Alt⇧S нажать SingleSave`; // если такой кнопки нет, то выполнить save() var addDestructor = nextDestructor => { var {destructor} = ucf[id]; ucf[id].destructor = () => { try {destructor();} catch(ex) {Cu.reportError(ex);} nextDestructor(); } } var notify = (msg, path) => { // по клику открытие файла ${path} var {wm} = Services, find = w => !w.closed && w.toolbar.visible; var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService); var obs = class { // клик на уведомлении constructor(path, name) { this.fp = path; this.an = name; } noop() {} win = Cu.getWeakReference(window).get; observe(s, topic) {switch(topic) { case "alertshow": (this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer)) .initWithCallback(this, 5e3, Ci.nsITimer.TYPE_ONE_SHOT_LOW_PRIORITY); break; case "alertclickcallback": var win = this.win(); if (!win || win.closed) win = Array.from(wm.getEnumerator("navigator:browser")).find(find); if (win) { win.gBrowser.selectedTab = win.gBrowser.addTrustedTab(win.PathUtils.toFileURI(this.fp)); win.windowState == win.STATE_MINIMIZED && win.restore(); } case "alertfinished": this.observe = this.noop; this.timer.cancel(); }} notify() {as.closeAlert(this.an);} }; (notify = (msg, path) => { var name = id + Cu.now(); as.showAlertNotification(null, msg, path, true, null, new obs(path, name), name); })(msg, path); } var saveSelectionToTxt = async () => { // сохранить страницу или выделенный текст как файл .txt var splice = saveURL.length == 10; var msgName = id + ":Save:GetSelection"; var receiver = msg => { var title = document.title || gBrowser.selectedTab.label; var args = [ "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\n\n" + msg.data), title.replace(/[:\\\/<>?*|"]+/g,'_').replace(/\s+/g,' ').slice(0, 100).trim() + '_' + new Date().toLocaleString('ru').replace(', ','-').replace(/:/g, '։') + '.txt', null, false, true, null, window.document ]; splice && args.splice(5, 0, null); saveURL(...args); } messageManager.addMessageListener(msgName, receiver); addDestructor(() => messageManager.removeMessageListener(msgName, receiver)); var func = fm => { var res, fed, win = {}; var fe = fm.getFocusedElementForWindow(content, true, win); var sel = (win = win.value).getSelection(); if (sel.isCollapsed) { var ed = fe && fe.editor; if (ed && ed instanceof Ci.nsIEditor) sel = ed.selection, fed = fe; } if (sel.isCollapsed) fed && fed.blur(), docShell.doCommand("cmd_selectAll"), res = win.getSelection().toString(), docShell.doCommand("cmd_selectNone"), fed && fed.focus(); res = res || sel.toString(); /\S/.test(res) && sendAsyncMessage("saveSelectionToTxt", res); } var url = "data:;charset=utf-8," + encodeURIComponent(`(${func})`.replace("saveSelectionToTxt", msgName)) + '(Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager));'; (saveSelectionToTxt = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // end var save = async () => { // автор: Лекс, правка: Dumby, Dobrov var msgName = id + "ucfDwnldsBtnSaveSnapshotToHTML"; var write = IOUtils.writeUTF8 ? "writeUTF8" : "writeAtomicUTF8"; var Title = function (type) { // получить заголовок (без обрезки, если type не указан) или домен (type <0) var title = (document.title || gBrowser.selectedTab.label); if ( !type ) return title; // заголовок if ( type > 0 ) return title.replace(/[:\\\/<>?*|"]+/g,' ').replace(/\s+/g,' ').replace(/ /g,' ').substr(0, type).trim(); // ограничить длину имени var host = (/^file:\/\//.test(gURLBar.value)) ? '' : gURLBar.value.replace(/^.*url=/,'').replace(/^https?:\/\//,'').replace(/\/.*/,''); return host.replace(/^www\./,'').replace(/^ru\./,'').replace(/^m\./,'').replace(/^forum\./,'').replace(/^club\.dns/,'dns'); }; var msgListener = async msg => { var [fileContent, fileName] = msg.data; var savedir = PathUtils.join(await Downloads.getPreferredDownloadsDirectory(), "_Web", Title(-1)); // каталог Загрузки + домен var path = PathUtils.join(savedir, fileName); await IOUtils[write](path, fileContent); notify("Страница сохранена в:", path); } messageManager.addMessageListener(msgName, msgListener); addDestructor(() => messageManager.removeMessageListener(msgName, msgListener)); var svc = 'globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services'; var url = "data:;charset=utf8," + encodeURIComponent(`(${func})(${svc});`.replace("%MSG_NAME%", msgName)); (save = () => gBrowser.selectedBrowser.messageManager.loadFrameScript(url, false))(); } // end save var listener = e => { // Clicks var trg = e.target, {prefs} = Services; if (e.button == 1) { if (e.shiftKey) { // СКМ + Shift if ( prefs.getIntPref("permissions.default.image", 1) == 1) prefs.setIntPref("permissions.default.image", 2), trg.style.filter = "hue-rotate(180deg) brightness(95%)" else prefs.setIntPref("permissions.default.image", 1), trg.style.filter = ""; BrowserReload(); } else // СКМ Click Downloads.getSystemDownloadsDirectory().then(path => FileUtils.File(path).launch(), Cu.reportError); // Обзор папки «Загрузки» } else if (e.button == 2) { if (e.shiftKey) save() // Single HTML else // ПКМ Click saveSelectionToTxt(); // сохранить .txt } } var keydown_win = e => { // нажатие клавиш if (!(e.keyCode == 83 && e.shiftKey && e.altKey)) return; var singlesave = document.getElementById("_531906d3-e22f-4a6c-a102-8057b88a1a63_-browser-action"); // SingleSave singlesave ? singlesave.click() : save(); // имитировать клик по кнопке, используя её ID } btn.addEventListener("click", listener); window.addEventListener("keydown", keydown_win); var ucf = window.ucf_custom_script_win || window.ucf_custom_script_all_win; ucf[id] = {destructor() { btn.removeEventListener("click", listener); window.removeEventListener("keydown", keydown_win); }}; ucf.unloadlisteners.push(id); })("downloads-button-click-listener", ({io, focus}) => { var resolveURL = function (url, base) { try { return io.newURI(url, null, io.newURI(base)).spec; } catch {} }; var getSelWin = function (w) { if (w.getSelection().toString()) return w; for (var i = 0, f, r; f = w.frames[i]; i++) { try { if (r = getSelWin(f)) return r; } catch(e) {} } }; var encodeImg = function (src, obj) { var canvas, img, ret = src; if (/^https?:\/\//.test(src)) { canvas = doc.createElement('canvas'); if (!obj || obj.nodeName.toLowerCase() != 'img') { img = doc.createElement('img'); img.src = src; } else { img = obj; }; if (img.complete) try{ canvas.width = img.width; canvas.height = img.height; canvas.getContext('2d').drawImage(img, 0, 0); ret = canvas.toDataURL((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png')); } catch (e) {}; if (img != obj) img.src = 'about:blank'; }; return ret; }; var toSrc = function (obj) { var strToSrc = function (str) { var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'}; while (chr = str.charAt(i++)) { ret += meta[chr] || chr; }; return '\x22' + ret + '\x22'; }, arrToSrc = function (arr) { var ret = []; for (var i = 0; i < arr.length; i++) { ret[i] = toSrc(arr[i]) || 'null'; }; return '[' + ret.join(',') + ']'; }, objToSrc = function (obj) { var val, ret = []; for (var prop in obj) { if (obj.hasOwnProperty(prop) && (val = toSrc(obj[prop]))) ret.push(strToSrc(prop) + ': ' + val); }; return '{' + ret.join(',') + '}'; }; switch (Object.prototype.toString.call(obj).slice(8, -1)) { case 'Array': return arrToSrc(obj); case 'Boolean': case 'Function': case 'RegExp': return obj.toString(); case 'Date': return 'new Date(' + obj.getTime() + ')'; case 'Math': return 'Math'; case 'Number': return isFinite(obj) ? String(obj) : 'null'; case 'Object': return objToSrc(obj); case 'String': return strToSrc(obj); default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null'; } }; var mainWin = {}; focus.getFocusedElementForWindow(content, true, mainWin); mainWin = mainWin.value; var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location; var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/g; if (selWin) { var rng = win.getSelection().getRangeAt(0); pEle = rng.commonAncestorContainer; ele = rng.cloneContents(); } else { pEle = doc.documentElement; ele = (doc.body || doc.getElementsByTagName('body')[0]).cloneNode(true); }; while (pEle) { if (pEle.nodeType == 1) { clone = pEle.cloneNode(false); clone.appendChild(ele); ele = clone; }; pEle = pEle.parentNode }; var sel = doc.createElement('div'); sel.appendChild(ele); for (var el, all = sel.getElementsByTagName('*'), i = all.length; i--;) { el = all[i]; if (el.style && el.style.backgroundImage) el.style.backgroundImage = el.style.backgroundImage.replace(reUrl, function (a, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href); return prev + encodeImg(url) + next; }); switch (el.nodeName.toLowerCase()) { case 'link': case 'style': case 'script': el.parentNode.removeChild(el); break; case 'a': case 'area': if (el.hasAttribute('href') && el.getAttribute('href').charAt(0) != '#') el.href = el.href; break; case 'img': case 'input': if (el.hasAttribute('src')) el.src = encodeImg(el.src, el); break; case 'audio': case 'video': case 'embed': case 'frame': case 'iframe': if (el.hasAttribute('src')) el.src = el.src; break; case 'object': if (el.hasAttribute('data')) el.data = el.data; break; case 'form': if (el.hasAttribute('action')) el.action = el.action; break; } }; var head = ele.insertBefore(doc.createElement('head'), ele.firstChild); var meta = doc.createElement('meta'); meta.httpEquiv = 'content-type'; meta.content = 'text/html; charset=utf-8'; head.appendChild(meta); var title = doc.getElementsByTagName('title')[0]; if (title) head.appendChild(title.cloneNode(true)); head.copyScript = function (unsafeWin) { if ('$' in unsafeWin) return; var f = doc.createElement('iframe'); f.src = 'about:blank'; f.setAttribute('style', 'position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;'); doc.documentElement.appendChild(f); var str, script = doc.createElement('script'); script.type = 'text/javascript'; for (var name in unsafeWin) { if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue; try { str = toSrc(unsafeWin[name]); if (!/\{\s*\[native code\]\s*\}/.test(str)) { script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n')); } } catch (e) {}; }; f.parentNode.removeChild(f); if (script.childNodes.length) this.nextSibling.appendChild(script); }; head.copyScript(win.wrappedJSObject || win); head.copyStyle = function (s) { if (!s) return; var style = doc.createElement('style'); style.type = 'text/css'; if (s.media && s.media.mediaText) style.media = s.media.mediaText; try { for (var i = 0, rule; rule = s.cssRules[i]; i++) { if (rule.type != 3) { if((!rule.selectorText || rule.selectorText.indexOf(':') != -1) || (!sel.querySelector || sel.querySelector(rule.selectorText))) { var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) { if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href); if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url); return prev + url + next; }); style.appendChild(doc.createTextNode(css + '\n')); } } else { this.copyStyle(rule.styleSheet); } } } catch(e) { if (s.ownerNode) style = s.ownerNode.cloneNode(false); }; this.appendChild(style); }; var sheets = doc.styleSheets; for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]); head.appendChild(doc.createTextNode('\n')); var doctype = '', dt = doc.doctype; if (dt && dt.name) { doctype += '<!DOCTYPE ' + dt.name; if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22'; if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22'; doctype += '>\n'; }; var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop()); fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).trim(); fileName += "_" + new Date().toLocaleString("ru").replace(", ","-").replace(/:/g, "։"); if (!/\.html?$/.test(fileName)) fileName += '.html'; sendAsyncMessage("%MSG_NAME%", [doctype + sel.innerHTML +'\n<a href='+ (loc.protocol != 'data:' ? loc.href : 'data:uri') +'><small><blockquote>источник: '+ new Date().toLocaleString("ru") +'</blockquote></small></a>', fileName]); }); // END hookClicks
Отредактировано Dobrov (19-04-2021 08:03:30)
Отсутствует
Подскажите, забыл, какая ф-ция в CB для окна выбора действий: "один" "два" "выход" ? Там alertbox или как-то так...
Замена\аналог консольному choice:
echo ^ ------------------------------------------------------------ echo ^ ^| ^| echo ^ ^| ¤¤¤ TOR - (t), или UltraSurf (u) ? (q) - Выход ¤¤¤ ^| echo ^ ^| ^| echo ^ ------------------------------------------------------------ choice /c tuq /T 15 /d q if %ERRORLEVEL% == 1 goto :tor if %ERRORLEVEL% == 2 goto :usurf if %ERRORLEVEL% == 3 goto :EOF
...программисты словно войну какую-то ведут за свои обновления. Блин, почему сейчас повсюду мания ухудшать интерфейсы и делать их максимально неудобными?! Radiation
Отсутствует
Если поиск пойдёт не в текущей вкладке, то можно, наверно
Класс, спасибо, да поиск открывается в новой вкладке
А можно ли добавить чтобы название для контейнера было такое же как и введенный текст в строке поиска?
Например если в строке поиска искать "солнечные панели" то и новый контейнер открывался с таким же названием
Отсутствует
Dumby
Как бы в Суммарном жоре памяти уменьшить размер шрифта? А то она иконки от дополнений растягивает.
Отсутствует
Недостаток SaveHTML в том, что сохранённые .html файлы не появляются в "Показать все загрузки".
Это можно исправить или хотя бы после сохранения .html помигать кнопкой Загрузки, как после скачивания файла?…
Недостаток?, как невхождение чего-либо в сам замысел?
Тут, как-то, на нечто подобное для кнопки Save,
предлагал фейковый download, и оно, вроде как, мигает кнопкой.
... notify("Страница сохранена в:", path); var d = await Downloads.createDownload({ source: "about:blank", target: FileUtils.File(path) }); (await Downloads.getList(Downloads.ALL)).add(d); d.refresh(d.succeeded = true);
Ещё нужен код, чтобы показать свой текст в строке статуса. Я пробовал, но ничего не показывается
У меня, с консоли, так работает
StatusPanel._label = "свой текст в строке статуса"; setTimeout(() => StatusPanel.update(), 2000);
может сделаешь пример, скрывающий панель вкладок, если вкладка одна и показывающий для нескольких?
Для CB
(url => { var num = gBrowser.tabs.length; var bar = document.getElementById("TabsToolbar"); if (num == 1) bar.collapsed = true; addEventListener("TabOpen", () => { if (++num == 2) bar.collapsed = false; }, false, gBrowser.tabContainer); addEventListener("TabClose", () => { if (--num == 1) bar.collapsed = true; }, false, gBrowser.tabContainer); var type = windowUtils.USER_SHEET; windowUtils.loadSheetUsingURIString(url, type); addDestructor(() => { windowUtils.removeSheetUsingURIString(url, type); if (num == 1) bar.collapsed = false; }); })("data:text/css;charset=utf-8,%23TabsToolbar[collapsed]:not([customizing]){visibility:collapse!important;}");
не получается поменять подсказку кнопки в зависимости от того, есть кнопка SingleSave или нет
Может, на момент исполнения кода, «кнопки SingleSave» ещё пока нет?
Просто запуск WebExtensions сильно тормозят (в угоду дражайшему стартап-перформансу).
Попробуй с таймаутом.
Подскажите, забыл, какая ф-ция в CB для окна выбора действий: "один" "два" "выход" ? Там alertbox или как-то так...
Оно чтоле?
var result = custombuttons.confirmBox3( "Header", "Message", "TOR", "Выход", "UltraSurf" ); var results = { 0: "TOR", 1: "Выход", 2: "UltraSurf" }; alert(results[result]);
А можно ли добавить чтобы название для контейнера было такое же как и введенный текст в строке поиска?
Например если в строке поиска искать "солнечные панели" то и новый контейнер открывался с таким же названием
(async (sel, self) => ({ icon: "circle", colors: [ "mediumseagreen", "silver", "crimson", "blue", "peru", ], initColors() { var colorName = "ucf-gen"; var css = "@-moz-document url(about:preferences#containers)," + " url-prefix(chrome://browser/content/browser.x) {\n"; this.colors.forEach((color, ind) => { var [ic, tc] = color.split(/\s*\|\s*/); css += `\t.identity-color-${colorName}${ind} {\n` + `\t\t--identity-tab-color: ${tc || ic};\n` + `\t\t--identity-icon-color: ${ic};\n\t}\n` }); var url = "data:text/css;charset=utf-8," + encodeURIComponent(css + "}"); var sss = Cc["@mozilla.org/content/style-sheet-service;1"] .getService(Ci.nsIStyleSheetService); sss.loadAndRegisterSheet(Services.io.newURI(url), sss.USER_SHEET); var len = this.colors.length; var pref = "ucf.openInGeneratedContainer.lastColor"; var ind = Math.min(Services.prefs.getIntPref(pref, -1), len - 1); this.nextColor = () => { var next = ind + 1; Services.prefs.setIntPref(pref, ind = next == len ? 0 : next); return colorName + ind; } }, init(topic) { Services.obs.addObserver(self = this, topic); Services.obs.addObserver(function quit(s, t) { Services.obs.removeObserver(self, topic); Services.obs.removeObserver(quit, t); }, "quit-application-granted"); this.initColors(); this.newUsercontext = name => this.cis.create( name || `[ ${this.cis._lastUserContextId + 1} ]`, this.icon, this.nextColor() ).userContextId; }, observe(doc) { var list = doc.querySelectorAll(sel); if (!list.length) return; var menuitem = doc.createXULElement("menuitem"); for(var args of Object.entries({ selectiontype: "single", oncommand: "cmd(window)", nodetype: "folder|query", selection: "folder|query", label: "Открыть всё в контейнере", id: "placesContext_openContainer:tabs:newUsercontext" })) menuitem.setAttribute(...args); menuitem.cmd = this.cmd; menuitem.rnd = menuitem.constructor.prototype.render; menuitem.render = this.render; var [m1, m2] = menuitem.list = Array.from(list); (m2 || m1).after(menuitem); if (doc.documentElement.getAttribute("windowtype") != "navigator:browser") return; for(var btn of [ doc.getElementById("tabs-newtab-button"), doc.getElementById("new-tab-button") || doc.ownerGlobal.gNavToolbox.palette.querySelector("#new-tab-button") ]) if (btn) btn.checkForMiddleClick = this.click; var win = doc.ownerGlobal; this.redefDoSearch(win, win.customElements.get("searchbar").prototype); }, redefDoSearch(win, proto) { this.cis = win.ContextualIdentityService; var code = `(openTrustedLinkIn => [ {${proto.doSearch}}, openTrustedLinkIn ])( function otl(url, where, params) { if (where != "current") params.userContextId = otl.newUsercontext( document.getElementById("searchbar").value ); openTrustedLinkIn(url, where, params); } );`; (this.redefDoSearch = (win, proto) => { var [obj, func] = win.eval(code); Object.assign(proto, obj); func.newUsercontext = this.newUsercontext; })(win, proto); }, click(btn, e) { if (!(e.button != 2 || e.ctrlKey || e.shiftKey)) { var txt = e.view.readFromClipboard(); if (txt) { var urls = txt.split("\n").map(self.map).filter(Boolean); if (urls.length) return e.preventDefault(), self.openFromClipboard(e.view, urls); } } e.view.checkForMiddleClick(btn, e); }, eo: Object.create(null), map(str) { str = str.trim(); try { var scheme = Services.io.extractScheme(str); var ph = Services.io.getProtocolHandler(scheme); if (ph.scheme == scheme) return Services.io.newURI(str) && {uri: str}; } catch {} }, openFromClipboard(win, urls) { if (win.OpenInTabsUtils.confirmOpenInTabs(urls.length, win)) urls.load = true, this.open(win, this.eo, urls); }, async render() { this.rnd(); await new Promise(this.ownerGlobal.requestAnimationFrame); this.hidden || (this.hidden = this.list.every(self.every)); }, every: node => node.disabled || node.hidden, cmd(win) { var view = this.parentNode._view; var node = win.document.popupNode; node = node._placesView && node._placesView.result.root; self.open(win, node || view.selectedNode || view.result.root); }, open(win, node, list) { var gbw = Cu.import("resource:///modules/PlacesUIUtils.jsm", {}).getBrowserWindow; var w = gbw(win); this.pu = w.PlacesUIUtils; this.fs = w.PlacesUtils.favicons; this.cis = w.ContextualIdentityService; this.sysp = w.E10SUtils.SERIALIZED_SYSTEMPRINCIPAL; (this.open = (win, node, list) => { this.openURLs(gbw(win), list || win.PlacesUtils.getURLsForContainerNode(node)); node.bookmarkGuid && this.pu.doCommand(win, "placesCmd_delete"); })(win, node, list); }, async openURLs(win, urls) { var userContextId = this.newUsercontext(); var mark = !win.PrivateBrowsingUtils.isWindowPrivate(win); var {load} = urls, gb = win.gBrowser, pos = gb.selectedTab._tPos; for(var {uri, title, isBookmark} of urls) try { if (mark) isBookmark ? this.pu.markPageAsFollowedBookmark(uri) : this.pu.markPageAsTyped(uri); if (load) { gb.addTrustedTab(uri, {index: ++pos, userContextId}); continue; } var state = {userContextId, entries: [{ url: uri, title: title || uri, triggeringPrincipal_base64: this.sysp }]}; var [,, data, mime] = await new Promise( resolve => this.fs.getFaviconDataForPage( Services.io.newURI(uri), (...args) => resolve(args), 16 ) ); if (data.length) state.image = `data:${ mime || "image/x-icon" };base64,${ btoa(String.fromCharCode(...data)) }`; var tab = gb.addTrustedTab(null, {index: ++pos, userContextId}); win.SessionStore.setTabState(tab, state); } catch {}; } }).init("chrome-document-loaded"))( "#placesContext_openBookmarkContainer\\:tabs,#placesContext_openContainer\\:tabs" );
размер шрифта
иконки от дополнений
???
Отсутствует
Оно чтоле?
Оно! Половина кнопок на батниках завязаны, вот решил перевести кой-чего в CB, а забыл название. Пасиб.
В итоге получилось так:
const prof = Services.dirsvc.get('ProfD', Ci.nsIFile), tor = prof.path + "\\SOFT_PM\\tor\\Tor\\tor.exe", usurf = prof.path + "\\SOFT_PM\\UltraSurf_Proxi\\u1902.exe"; let choice = custombuttons.confirmBox3( "Proxy utils", "Запустить что ", "TOR", "Выход", "UltraSurf" ), result = { 0: tor, 1: "Выход", 2: usurf }; //console.log("result of choise " + result[choice]); if(result[choice] == "Выход") return; else startProcess(result[choice], []); // ф-ция где проверяется аргументы и путь... ну и запускает прогу.
...программисты словно войну какую-то ведут за свои обновления. Блин, почему сейчас повсюду мания ухудшать интерфейсы и делать их максимально неудобными?! Radiation
Отсутствует
Не скачиваются, можно выложить еще раз?
Отсутствует
Dumby
Ну вот например открывается в контенере несколько вкладок
Потом все вкладки закрываются а контейнер созданный остается существовать
Можно ли сделать чтобы после закрытия последней вкладки контейнера он удалялся?
Отредактировано Stkvsky (22-04-2021 16:50:11)
Отсутствует