Полезная информация

Многие проблемы быстрее решаются поиском по форуму и чтением FAQ, чем созданием новой темы и томительным ожиданием ответа.

№1407617-01-2020 23:56:12

solombala
Участник
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 350
UA: Firefox 71.0

Re: Custom Buttons

func4ptch4
Это куда?

Отсутствует

 

№1407718-01-2020 03:22:21

func4ptch4
Участник
 
Группа: Members
Зарегистрирован: 03-05-2018
Сообщений: 198
UA: Firefox 72.0

Re: Custom Buttons

solombala, /*Initialization Code*/ забыл), мне (кажется) это лучше чем в каждой кнопке отдельно вписывать+можно все коды в одну кнопку и, назвать ну типа Hotkeys.


Dumby, все никак не могу привыкнуть, как без автопопапа люди пользуются кнопками...) ех, все-таки никак нельзя хотя бы в кнопках сделать автопопап? Ну просто смотрите навел на кнопку он раскрылся отвел закрылся, а без этого надо клик, клик по области чтобы закрылся(и это бесит). Ладно гамбургер меню, им наверно мало кто пользуеться, вроде в кнопки интегрировали e.preventDefault(); что если и это интегрировать? или это чисто мой привычки?)

Отредактировано func4ptch4 (18-01-2020 03:52:50)

Отсутствует

 

№1407818-01-2020 05:25:38

xrun1
Участник
 
Группа: Members
Зарегистрирован: 12-12-2013
Сообщений: 586
UA: Firefox 56.0

Re: Custom Buttons

func4ptch4
Если ты об этом автопопапе

скрытый текст
https://www.upload.ee/image/10994260/122.gif

, то работает.

Отсутствует

 

№1407918-01-2020 11:02:36

solombala
Участник
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 350
UA: Firefox 71.0

Re: Custom Buttons

Dumby
Что-то кн. скриншот не того (71- от правки биндинга избавился) Из контекста и иконки пропали и не работает...(текст в файл и вн. редактор)

скрытый текст

Выделить код

Код:

// Save, от 07.03.2017. .............

self.label = "Save";
self._handleClick =()=> menuPopup.openPopup(this, "after_start");
self.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABYklEQVR42q2Uv0vDQBSA7wy6qIh0cKztoOji5KaDm4Obf4Hg5CSCEKGbIFWETuKkoODi4CAOjg6u7jrYasEfgxaHgqLU+CWXg8sRiEnz4HuQe+++PC5HpMg5ZOSp6k2Sr+AV+mBTuPKkG2GZfG+suAi30wvVZAMwDsdGvQY7MByz14N+XngTJ/S6OLZZpNe2sE4uZRROILy1he1g/HThhfuLCJu28Jw8DV8wamx6gTsYEeqrf8AYDBo9JYQPUaEZ6jz125dpPrDqq0J9rB/oDQZw5WOSUMcKzftWvSL8+ylEB5z/TqhjjeaaVd8ibxgrqSZcpPnMqi+RD+E7OFdXRhxJwku4gKHwo3zCAswYPbvwBM/IT5OEaaKFsJCH8Bd6hP9TceVcnhM2ERbjhP4lfxfqkpt1J1yfhylj/QjeoIFwT4q0UfXWhfoD6SggaumHLEJ9sfXZlRE2sguV1EHSiSv9AY3RchX9yXjuAAAAAElFTkSuQmCC";



var folderpath="C:\\Users\\_________\\Desktop";         // папка для сохранения иконок для ярлыков и ярлыков сайтов


// Создать меню для кнопки .............
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=="},
   
   { 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="},
   { separator: ''},
   { label: "Сохранить всю страницу как HTML", func: "savePage()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAQCAYAAADJViUEAAAB5UlEQVQokY2Sz0tUURiGv1rUrkUb3UVBRbSq/oG20aqlTIsR0SSDiMh+CDK4mKhgTKgwaoYRx4awRU6EBTJDEKkz6pSOlSkzajCBWDg26HXuPedpce/VuaDS2Z33e5/3vOdwBGdZSmOa66AVoG1Rm85UAwrTXMNUykWQrSFQKaCNgq2sfsLKHEavJO29sYjemKPaL25KfHyWnpFxzMINANRiiEpCUPkO2z7fyovRUXozs1snuzVu9g8hFx8xPHwbZs5hlaexvvuwylPw4wJfMtcRfzdXYoMAmEohStsVfpXK7Gnpoi4yANlDbKRPon+/xhg7AxM1XOobQJo7WfhTsptpbde2lB3Q1DeIXA6Tn7wFHwQjuQ9SQjF3jb1Xo/giCar94qYA5IpLSEOIO69ewuda/iYFsge5m4gj9SHGFopU+zcfzBXOP+7nQGuMlekGSAprX33UtsU5G4p7fB7YrZKamUf8nTx5F4Wp/fQMPUP8D3mbm/P4PDCAG3oqGONYIAzL9zgdjHA8EGW75YHd1Fj6G9J4n7Y3I0jTA55+nHTmamfYLbRuWpzoiCL1QY60P2fVqHjm28LA5t/tSk0gdQGC79MefVdYOxcvlsocbQ+TXy559F3h6pDszyXP6/4/7ATsjMI/jSFZQARyBXYAAAAASUVORK5CYII="},
   { 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: "CB.Save.WebScreenShotOnImage"},
   { label: "Сохранить выделенный текст в файл, в контекстном меню", value: "CB.Save.SelectionToFile" },
   { label: "Открыть выделенный текст в внешнем редакторе, в контекстном меню", value: "CB.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();
  }
});
};


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);
 // стиль для изображение в сплывающей подсказке ....
      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);
   // подсказка
   var notific = 'Сохранил в: ' + folderpath;
   var image = gBrowser.selectedBrowser.mIconURL;
   Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(image, filename, notific);
};

// Кодировать изображение или текстовой файл в 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()
   });
}; 

// Сохранить иконку текущего сайта с диалогом сохранения .............
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] + " ";  
            };
      saveImageURL(gBrowser.selectedTab.image, getSiteName(), null, false, false, null, window.document);
};


// Скопировать иконку текущего сайта как base64 код .............
function copyFaviconData() {
   var img = new Image();
   img.src = gBrowser.selectedTab.image;
   WebScreenShotonImage(img);
};


// Сохранить выделенный текст или весь текст на странице как txt файл .............
function saveSelectionToTxt() {

let browserMM = gBrowser.selectedBrowser.messageManager;
        browserMM.addMessageListener('getSelection', function listener(message) {
        var sel = message.data;
       !sel && document.getElementById("cmd_selectAll").doCommand(); 
     
   // создать название файла из заголовка страницы и текущего времени и сохранить текст ....
   var fileTitle = getTabLabel() + '  ' + aDate().replace(/:/g, ".");
   saveURL("data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + ("\r\n\r\n" + sel)), 
                                fileTitle + ".txt", null, false, false, null, window.document);
   !sel && goDoCommand("cmd_selectNone"); 
 browserMM.removeMessageListener('getSelection', listener, true);
});
        browserMM.loadFrameScript('data:,sendAsyncMessage("getSelection", content.document.getSelection().toString())', false);
};

(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 = () => gBrowser.selectedBrowser.messageManager
            .loadFrameScript("data:;charset=utf-8," + encodeURIComponent(this.code()), false);

        this.handleEvent = () => menuitem.hidden = this.shouldHide;
    },
    get shouldHide() {
        return !gContextMenu.onImage || !cbu.getPrefs("CB.Save.WebScreenShotOnImage");
    },
    code: () => `(selectors => {

        var getImage = doc => {
            var elm = doc.querySelector(selectors.shift());
            if (selectors.length) elm = getImage(elm.contentDocument);
            return elm;
        }
        var image = getImage(content.document);

        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.targetSelectors)
    })`
}, 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", "menu-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 =()=> saveSelectionToFile();

   var editorItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el);
   editorItem.id = "content-editorItem";
   editorItem.setAttribute("label", "Открыть выделенный текст в внешнем редакторе");
   editorItem.setAttribute("class", "menu-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("CB.Save.SelectionToFile");
      editorItem.hidden = !sel || !cbu.getPrefs("CB.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 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
                ];
                wbp.saveURI.length == 9 && args.splice(2, 0, null);
                wbp.saveURI(...args);
            });
        }
        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() };


// Получить название домена с заглавным первым символом и без приставок( типа .ru и .com ) ..............
function getSiteName() {
   try { var domain = content.document.domain.split('.') } catch(e) { return "" };
   domain = (domain.length == 2) ? domain[0] : domain[1]
   return domain[0].toUpperCase() + domain.slice(1).split('.')[0] + " ";  
};


// Получить название вкладки без не сохраняемых символов и лишних пробелов ..............
function getTabLabel() { 
   var label = gBrowser.selectedTab.label;      
   var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " ");
   return label;
};

    
// Получить выделенный текст из страницы или 'false' ..............
function getSelect() {
   var el = document.commandDispatcher.focusedElement;
   try { return el.value.substring(el.selectionStart, el.selectionEnd) } catch(e) {};
   var sel = document.commandDispatcher.focusedWindow.getSelection();
   return (sel == '') ? false : sel.toString().replace(/^\s+|\s+$/g,"").replace(/\u000A/g, "\u000D\u000A").replace(/\u000D\u000D\u000A/g, "\u000D\u000A");
};

     

Отсутствует

 

№1408018-01-2020 17:09:15

sandro79
Участник
 
Группа: Members
Откуда: Гиперборея
Зарегистрирован: 15-11-2017
Сообщений: 805
UA: Firefox 68.0

Re: Custom Buttons

Dumby
В бытность 72 nightly, вы мне предложили скрипт для изменения сохранения закладок звездочкой в адресной строке в "Меню закладок", а через конт. меню на странице  в "Другие закладки" (штатное поведение).
Тогда в 72 nightly это работало, но теперь в релизной 72, да и в 68 версии проверил, через конт. меню страницы, сохранение идёт тоже в "Меню закладок".
Хотя в нынешней 74 nightly работает как надо. Подправьте пожалуйста, если не сложно под 68 ESR, скорее всего и в 72 сработает.
Хотелось бы на 68 перейти со стиля на скрипт. Спасибо.

Отсутствует

 

№1408118-01-2020 19:34:37

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 1072
UA: Firefox 52.0

Re: Custom Buttons

Andrey_Krropotkin пишет:

Можешь разъяснить по поводу Mozilla Thunderbird 68 и СВ

Чего ж тут разъяснять, в названии написано «-fx», это значит Firefox.
Если была бы поддержка Thunderbird, то было бы написано «-fx-tb».

скрытый текст
Я не пользователь Thunderbird совсем.
Хотя, вобще-то пробовал что-то сделать.
И задачу поставил весьма облегчённую — только Thunderbird
и только Thunderbird 68.

И нет, ничего хорошего не получилось.
Там развели целый вагон тулбоксов, это не для моих куриных мозгов.
Ну и было недоделано, нетестровано, брошено, полный отстой.

Но, кое-где, местами, вроде должно работать.
Если хочешь, можешь попробовать.

put.re что-то не алё, придётся от последнего paxmod'а собрать кодом.
После установки рестарт. Никакой конфиг не требуется.

Выделить код

Код:

// CB-{0.0.7.0.0.9-fx}-{68.0-tb}.js
(async () => {
    var gzip = "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";

    var sel = "Select";
    try {sel = Services.strings.createBundle("chrome://global/locale/commonDialogs.properties")
        .GetStringFromName(sel);} catch(ex) {}
    var picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
    var ln = "custom_buttons-0.0.7.0.0.9-fx-paxmod.xpi";
    picker.init(window, sel + " " + ln, picker.modeOpen);
    picker.appendFilter(null, ln);
    await new Promise(resolve => picker.open(resolve));
    var {file} = picker;
    if (!file) return;
    var {fileURL} = picker;

    var xpi = file.parent.clone();
    xpi.append(ln = "custom_buttons-68.0-tb.xpi");
    file.copyTo(file.parent, ln);

    var obs = {}, data;
    var td = new TextDecoder(), te = new TextEncoder();
    var scs = Cc["@mozilla.org/streamConverters;1"].getService(Ci.nsIStreamConverterService);
    var sis = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
    var sl =  Cc["@mozilla.org/network/stream-loader;1"].createInstance(Ci.nsIStreamLoader);

    sis.data = atob(gzip);
    obs.onStreamComplete = (a, b, c, d, result) => data = td.decode(new Uint8Array(result));
    sl.init(obs);
    var converter = scs.asyncConvertData("gzip", "uncompressed", sl, null);

    converter.onStartRequest(null, null);
    var args = [null, null, sis, 0, sis.data.length];
    if (converter.onDataAvailable.length == 4) args.shift();
    converter.onDataAvailable(...args);
    converter.onStopRequest(null, null, null);

    var zw = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter);
    var mt = Date.now() * 1000, cp = zw.COMPRESSION_DEFAULT;
    var prefix = "jar:" + fileURL.spec + "!/";
    var lr = /^¦(?:\d+)?$/, sep1 = "£", sep2 = "¥";

    zw.open(xpi, 0x04); // PR_RDWR
    for(var item of data.split(sep1)) {
        var [entry, val] = item.split(sep2);
        if (val == "+") {
            zw.addEntryDirectory(entry, mt, false); continue;
        }
        if (zw.hasEntry(entry)) {
            if (val.includes("¦")) {
                var lines = val.split("\n");
                var oldLines = (await (await fetch(prefix + entry)).text()).split("\n");

                lines.forEach((line, ind) => {
                    if (lr.test(line)) lines[ind] = oldLines[
                        line.length == 1 ? ind : +line.slice(1)
                    ];
                });
                val = lines.join("\n");
            }
            zw.removeEntry(entry, false);
            if (val == "-") continue;
        }
        var stream = Cc["@mozilla.org/io/string-input-stream;1"]
            .createInstance(Ci.nsISupportsCString);
        stream.data = String.fromCharCode(...new Uint8Array(te.encode(val)));
        zw.addEntryStream(entry, mt, cp, stream, false);
        stream.close();
    }
    zw.close(); xpi.reveal();
})();


kokoss пишет:

Что нужно изменить в коде этой кнопки, что бы работала в [firefox] 72 в многопроцес... режиме ?

В многопрцессном? Ничего.

А чтобы просто работала, заменить
все createElement на createXULElement и первую строку на
this._handleClick = () => menuPopup.openPopup(this, "after_start");

Ну и косметика, заменить некоторые иконки на актуальные или свои,
убрать ненужный LOG, убрать Search plugins и соответствующую проверку.

func4ptch4 пишет:

все-таки никак нельзя хотя бы в кнопках сделать автопопап? Ну просто смотрите навел на кнопку он раскрылся отвел закрылся, а без этого надо клик, клик по области чтобы закрылся(и это бесит).

Кнопки же могут быть сделаны совершенно как угодно,
так что, наверно, нет. Давай самую бесячую из несекретных,
а я попробую в неё какой-нибудь autopopup встроить.

solombala пишет:

Из контекста и иконки пропали и не работает

Иконок нет потому, что неверно указан class,
нужно "menuitem-iconic", а не "menu-iconic".

А не работает потому, что не определена функция convertFromUnicode()
Так что добавь определение, ну что-то типа

скрытый текст

Выделить код

Код:

function convertFromUnicode(...args) {
    var suc = Cc['@mozilla.org/intl/scriptableunicodeconverter']
        .createInstance(Ci.nsIScriptableUnicodeConverter);
    suc.charset = "UTF-8";
    return (convertFromUnicode =
        (a, text) => suc.ConvertFromUnicode(text) + suc.Finish()
    )(...args);
}


sandro79 пишет:

в 68 версии проверил, через конт. меню страницы, сохранение идёт тоже в "Меню закладок".

Как насчёт рискнуть переключить настройку javascript.options.asyncstack
Если неприемлимо, дай знать, подумаю как переделать.

Отсутствует

 

№1408218-01-2020 20:03:45

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 685
UA: Firefox 52.0

Re: Custom Buttons

Dumby пишет:

и соответствующую проверку

Можно поподробнее?
Add: проехали, и так работает! Благодарю :beer:

Отредактировано kokoss (18-01-2020 23:10:24)

Отсутствует

 

№1408318-01-2020 20:07:53

sandro79
Участник
 
Группа: Members
Откуда: Гиперборея
Зарегистрирован: 15-11-2017
Сообщений: 805
UA: Firefox 68.0

Re: Custom Buttons

Dumby пишет:

Как насчёт рискнуть переключить настройку javascript.options.asyncstack

Рискнул, работает. Негативных последствий вроде не заметил. Переделывать думаю не нужно. Спасибо за подсказку.

Отсутствует

 

№1408418-01-2020 20:18:18

solombala
Участник
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 350
UA: Firefox 71.0

Re: Custom Buttons

Dumby
Норм...Была еще одна шняга -  saveItem.onclick =()=> saveSelectionToTxt(); , а было ToFile
ЭТО Кн. Скриншот !

скрытый текст

Выделить код

Код:

// Save, от 07.03.2017. .............

self.label = "Save";
self._handleClick =()=> menuPopup.openPopup(this, "after_start");
self.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABYklEQVR42q2Uv0vDQBSA7wy6qIh0cKztoOji5KaDm4Obf4Hg5CSCEKGbIFWETuKkoODi4CAOjg6u7jrYasEfgxaHgqLU+CWXg8sRiEnz4HuQe+++PC5HpMg5ZOSp6k2Sr+AV+mBTuPKkG2GZfG+suAi30wvVZAMwDsdGvQY7MByz14N+XngTJ/S6OLZZpNe2sE4uZRROILy1he1g/HThhfuLCJu28Jw8DV8wamx6gTsYEeqrf8AYDBo9JYQPUaEZ6jz125dpPrDqq0J9rB/oDQZw5WOSUMcKzftWvSL8+ylEB5z/TqhjjeaaVd8ibxgrqSZcpPnMqi+RD+E7OFdXRhxJwku4gKHwo3zCAswYPbvwBM/IT5OEaaKFsJCH8Bd6hP9TceVcnhM2ERbjhP4lfxfqkpt1J1yfhylj/QjeoIFwT4q0UfXWhfoD6SggaumHLEJ9sfXZlRE2sguV1EHSiSv9AY3RchX9yXjuAAAAAElFTkSuQmCC";



var folderpath="C:\\Users\\_________\\Desktop";         // папка для сохранения иконок для ярлыков и ярлыков сайтов


// Создать меню для кнопки .............
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=="},
   
   { 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="},
   { separator: ''},
   { label: "Сохранить всю страницу как HTML", func: "savePage()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAQCAYAAADJViUEAAAB5UlEQVQokY2Sz0tUURiGv1rUrkUb3UVBRbSq/oG20aqlTIsR0SSDiMh+CDK4mKhgTKgwaoYRx4awRU6EBTJDEKkz6pSOlSkzajCBWDg26HXuPedpce/VuaDS2Z33e5/3vOdwBGdZSmOa66AVoG1Rm85UAwrTXMNUykWQrSFQKaCNgq2sfsLKHEavJO29sYjemKPaL25KfHyWnpFxzMINANRiiEpCUPkO2z7fyovRUXozs1snuzVu9g8hFx8xPHwbZs5hlaexvvuwylPw4wJfMtcRfzdXYoMAmEohStsVfpXK7Gnpoi4yANlDbKRPon+/xhg7AxM1XOobQJo7WfhTsptpbde2lB3Q1DeIXA6Tn7wFHwQjuQ9SQjF3jb1Xo/giCar94qYA5IpLSEOIO69ewuda/iYFsge5m4gj9SHGFopU+zcfzBXOP+7nQGuMlekGSAprX33UtsU5G4p7fB7YrZKamUf8nTx5F4Wp/fQMPUP8D3mbm/P4PDCAG3oqGONYIAzL9zgdjHA8EGW75YHd1Fj6G9J4n7Y3I0jTA55+nHTmamfYLbRuWpzoiCL1QY60P2fVqHjm28LA5t/tSk0gdQGC79MefVdYOxcvlsocbQ+TXy559F3h6pDszyXP6/4/7ATsjMI/jSFZQARyBXYAAAAASUVORK5CYII="},
   { 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: "CB.Save.WebScreenShotOnImage"},
   { label: "Сохранить выделенный текст в файл, в контекстном меню", value: "CB.Save.SelectionToFile" },
   { label: "Открыть выделенный текст в внешнем редакторе, в контекстном меню", value: "CB.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();
  }
});
};


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);
 // стиль для изображение в сплывающей подсказке ....
      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);
   // подсказка
   var notific = 'Сохранил в: ' + folderpath;
   var image = gBrowser.selectedBrowser.mIconURL;
   Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(image, filename, notific);
};

// Кодировать изображение или текстовой файл в 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()
   });
}; 

// Сохранить иконку текущего сайта с диалогом сохранения .............
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] + " ";  
            };
      saveImageURL(gBrowser.selectedTab.image, getSiteName(), null, false, false, null, window.document);
};


// Скопировать иконку текущего сайта как base64 код .............
function copyFaviconData() {
   var img = new Image();
   img.src = gBrowser.selectedTab.image;
   WebScreenShotonImage(img);
};


// Сохранить выделенный текст или весь текст на странице как txt файл .............
function saveSelectionToTxt() {

let browserMM = gBrowser.selectedBrowser.messageManager;
        browserMM.addMessageListener('getSelection', function listener(message) {
        var sel = message.data;
       !sel && document.getElementById("cmd_selectAll").doCommand(); 
     
   // создать название файла из заголовка страницы и текущего времени и сохранить текст ....
   var fileTitle = getTabLabel() + '  ' + aDate().replace(/:/g, ".");
   saveURL("data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + ("\r\n\r\n" + sel)), 
                                fileTitle + ".txt", null, false, false, null, window.document);
   !sel && goDoCommand("cmd_selectNone"); 
 browserMM.removeMessageListener('getSelection', listener, true);
});
        browserMM.loadFrameScript('data:,sendAsyncMessage("getSelection", content.document.getSelection().toString())', false);
};

(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 = () => gBrowser.selectedBrowser.messageManager
            .loadFrameScript("data:;charset=utf-8," + encodeURIComponent(this.code()), false);

        this.handleEvent = () => menuitem.hidden = this.shouldHide;
    },
    get shouldHide() {
        return !gContextMenu.onImage || !cbu.getPrefs("CB.Save.WebScreenShotOnImage");
    },
    code: () => `(selectors => {

        var getImage = doc => {
            var elm = doc.querySelector(selectors.shift());
            if (selectors.length) elm = getImage(elm.contentDocument);
            return elm;
        }
        var image = getImage(content.document);

        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.targetSelectors)
    })`
}, 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("CB.Save.SelectionToFile");
      editorItem.hidden = !sel || !cbu.getPrefs("CB.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) {
   // создать текст для записи
    function convertFromUnicode(...args) {
    var suc = Cc['@mozilla.org/intl/scriptableunicodeconverter']
        .createInstance(Ci.nsIScriptableUnicodeConverter);
    suc.charset = "UTF-8";
    return (convertFromUnicode =
        (a, text) => suc.ConvertFromUnicode(text) + suc.Finish()
    )(...args);
}

    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 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
                ];
                wbp.saveURI.length == 9 && args.splice(2, 0, null);
                wbp.saveURI(...args);
            });
        }
        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() };


// Получить название домена с заглавным первым символом и без приставок( типа .ru и .com ) ..............
function getSiteName() {
   try { var domain = content.document.domain.split('.') } catch(e) { return "" };
   domain = (domain.length == 2) ? domain[0] : domain[1]
   return domain[0].toUpperCase() + domain.slice(1).split('.')[0] + " ";  
};


// Получить название вкладки без не сохраняемых символов и лишних пробелов ..............
function getTabLabel() { 
   var label = gBrowser.selectedTab.label;      
   var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " ");
   return label;
};

    
// Получить выделенный текст из страницы или 'false' ..............
function getSelect() {
   var el = document.commandDispatcher.focusedElement;
   try { return el.value.substring(el.selectionStart, el.selectionEnd) } catch(e) {};
   var sel = document.commandDispatcher.focusedWindow.getSelection();
   return (sel == '') ? false : sel.toString().replace(/^\s+|\s+$/g,"").replace(/\u000A/g, "\u000D\u000A").replace(/\u000D\u000D\u000A/g, "\u000D\u000A");
};

     


Кстати, можно ли рихтануть по-взрослому 71 , (за 72 молчу) насчет SSl/TLS , а то прокси не берет от Frigate , только Socks могу, а там тормоза...

Отредактировано solombala (18-01-2020 20:31:32)

Отсутствует

 

№1408518-01-2020 21:16:31

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 392
UA: Firefox 68.0

Re: Custom Buttons

solombala
А как бы убрать лишнее вот такое окно при сохранении  "Сохранить всю страницу или выбранное как HTML"
В кнопке Save, от 07.03.2017
https://i111.fastpic.ru/big/2020/0118/c6/4baada21edf8e71cdd55757dd99733c6.png

Отсутствует

 

№1408618-01-2020 21:42:14

solombala
Участник
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 350
UA: Firefox 71.0

Re: Custom Buttons

rubel
Аддон поставь и "сохранить"
https://addons.mozilla.org/ru/firefox/a … src=search

Отсутствует

 

№1408718-01-2020 22:06:58

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 392
UA: Firefox 68.0

Re: Custom Buttons

solombala пишет:

rubel
Аддон поставь и "сохранить"

Поставил, ничего не изменилось. Вываливается тоже окошко. :/

Отсутствует

 

№1408818-01-2020 23:09:36

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 1072
UA: Firefox 52.0

Re: Custom Buttons

kokoss пишет:

Можно поподробнее?

Можно

скрытый текст
Вот смотри, три фрагмента кода.

В первом два объекта с данными для создания
пунктов меню Search plugins.

Во втором вычисляется номер версии Firefox.

В третьем, собственно, проверка. Если версия Firefox больше 40
и название пункта меню должно начинаться с «Search»,
то такой пункт не создаётся.

Таким образом, эти три фрагмента можно удалить,
ведь 72 больше чем 40, и намного.

А можно и не удалять, работать будет и так,
просто ненужная лишняя обработка.

Выделить код

Код:

     {
      label: "Search plugins(default)",
      style: "chrome://global/skin/icons/Search-glass.png",
      value: "CurProcD,searchplugins" 
     },
     {
      label: "Search plugins(user-defined)",
      style: "chrome://global/skin/icons/Search-glass.png",
      value: "UsrSrchPlugns"
     },
Выделить код

Код:

var version = parseInt(Services.appinfo.version);
Выделить код

Код:

   if ( version > 40 && m.label.startsWith("Search") ) return;

Отсутствует

 

№1408918-01-2020 23:24:37

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 685
UA: Firefox 52.0

Re: Custom Buttons

Dumby пишет:

Код:

var version = parseInt(Services.appinfo.version);


Код:

   if ( version > 40 && m.label.startsWith("Search") ) return;

Понятно!

Отсутствует

 

№1409019-01-2020 14:03:29

func4ptch4
Участник
 
Группа: Members
Зарегистрирован: 03-05-2018
Сообщений: 198
UA: Firefox 72.0

Re: Custom Buttons

xrun1, это tooltipText, autopopup когда меню раскрывается, как при клике(в общем экономит 2клика), ну и легко между несколькими кнопками не надо на каждый кликать... может на топбаре это и не удобно, но в вертикальной очень даже, если там еще закладками пользуетесь, на топбаре просто при любом наведений будет мешать там ведь юрлбар и т.д. + я там не держу CB-кнопки, удобно) там только аддоны uc.js скрипты, 1-2 возле вертикальной гамбургер-меню тамже..


Dumby, вроде это отвечает this._handleClick=()=>menuPopup.openPopup(this,"after_start"); за открытие? хотел еще пару кодов но тут ограничение в 64кб, в основном там с этой секцией, может пример а там я сам попробую изменить, или не только там надо править?
скрытый текст

Выделить код

Код:

//Quick toggle for about:config preferences [Fx]
// Быстрое переключение параметров about:config от 24.07.2016
this._handleClick=()=>menuPopup.openPopup(this,"after_start"); //(this,-1,-1,"popup","bottomleft","topleft");
var menuPopup=document.createXULElement("menupopup");self.prepend(menuPopup); //var menuPopup=self.appendChild(document.createXULElement("menupopup")); [old autopopup]
menuPopup.id='quick-aboutconfig-menupopup';

// Изменить иконку при несоответствие любого параметра пользовательскому предпочтению (см.ниже)||Иконка меняется только при изменеии параметров через меню кнопки, либо после его открытия.
  var s='CB.hasNotUserChoice';function toggleImage(){var val=custombuttons.getPrefs(s);self.image=val
//var s='CB.hasNotUserChoice';function toggleImage(){        custombuttons.getPrefs(s)?self.style.cssText='':self.style.cssText='filter:grayscale(100%)';};
? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB6klEQVQ4jZWTv2tUQRDHv8ntd28GLLQQfwS5VkuDSgRF/wlRiIiCQQQhhZ1VII1/wDUWkkLTBAsbC0FJYZGQ3NuZRcHYW6UQEQzoeXkW791xXh5CptodZr8z85kd4BBWRJwDgB5wyoCjh3mLbfK8C/ddW11XJlduNgYaeTFpvJWA0+P+BBx3Cf2sLEy5m4WrS8A0AGANaBUSrgKAKzdcY5k0PF4HJGm47NK6nSUMXOIXAEgSrrnG0oU/AGDKNb6qHe9c+Ms1lqbxqws/uoTfWVp3ksRll/DTJM6bcMWEn1KbDysBCW+zsnSNpWssTbg3PNf3uw7MuHDgym8uoW8aX496SxKXs7J0iTsFObcGRBfey8rShP1EXthSnDHhShJ0vM0H1uYiAKBSHWZqLYyDc+H7sSpeNlMX9l1jWWebEAgjgSxcbRRYB46YhCcVxH9bqDP3nbyUBB0XPk+Cjgnvj1qoqohvJqDtTUBdcGAmSzgIEQBM2R0fY/U41GPkwNpcTBKfmnDPNN4w4TOX+NnbfAQAWAKmXcMVAMgaNqrM1UfqkbMmrXkT/nGJO1XF4Xod8/0Ak4KcKzTe3AROjPs/AMdM2M8atk25a8IXAKYawTZZj5jNEvZN2TVldg3Ny/RfkYizALAFnByu819tzvCRWXKqTwAAAABJRU5ErkJggg=='
: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAACXBIWXMAAABnAAAAZwHVKNQmAAADGGlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjaY2BgnuDo4uTKJMDAUFBUUuQe5BgZERmlwH6egY2BmYGBgYGBITG5uMAxIMCHgYGBIS8/L5UBA3y7xsDIwMDAcFnX0cXJlYE0wJpcUFTCwMBwgIGBwSgltTiZgYHhCwMDQ3p5SUEJAwNjDAMDg0hSdkEJAwNjAQMDg0h2SJAzAwNjCwMDE09JakUJAwMDg3N+QWVRZnpGiYKhpaWlgmNKflKqQnBlcUlqbrGCZ15yflFBflFiSWoKAwMD1A4GBgYGXpf8EgX3xMw8BUMDVQYqg4jIKAX08EGIIUByaVEZhMXIwMDAoM2Qw7CDkY8xi/EskynTYmYR5i4WFpZGVibWNjYetmnsyuybOVw5bnIWcHFyLeV24n7E08KrwXuOr4xfnv+0QIWguuANoS5hO+EvIqtFU8TkxW6Jz5AIlxSXvCE1RzpBRk3mrexWuXp5LwUxhSeKm5SalENU1FR+qp5TW6JerRGsqaPFpvVIe5/ObN0qvSh9KwMZg3+Gj4yOG68xmWxaZZZs7mNhbqlkxWf12/qlzQ3bE3Y77Vc7zHWc6NTqXOVS4JruFuce7hHg6eXl6u3oY+dr7WfpbxFgEWgRZBlsHWIX6hTmFu4dERgZHhUfnR5TEFsZ1xzflzArcVnS5uSDKedT76W9S/+XKZClmG2S454bnZef31owq3Bj0YniByU/ygTLtStcKxOqaqpn1GytvVT3oYG/Ua/Jrzm/ZULrprYr7d87pbvsu5N7OnvX9V3t/zNRZZLP5JIp86aemPZphuxMz1mlsxfOOT/3z3ztBVELOxftXPxqqfQyn+V1KzaufLJaYo3P2sZ129a/2ai0KXLzxC0ntjFut9pRvHPtrhd7lPbG7Zu1/9pB4UOBh/uPnD3Gc9z7RPfJM6d5zvidnXDu0gXRixGX5lx+cFXlWtb19Te+3rK53Xzn1D2h+9EPljx8+9j8SePTM8/FXyS9XPfq9xuPt1PfPf5g+LHh0/kv8l/zv+3/IfAz6deWP2x/I/6t/v8fAATCIM0IpJTRAAAAIGNIUk0AAHolAACAgwAA+f8AAIDoAABSCAABFVgAADqXAAAXb9daH5AAAAEOSURBVHjabJGtS0MBFMXPJojBMMPwC1nV6FCZoGj/ZVGYiIJDBOEFm3XFP2DFIAu6ZrAYBM0OREEUnN20ICI40OfbsTzYB48b7oF74J4PWUnDjMU4GSv5PEubCo/UuwjMs8FEjLOEPNCkRloWAyxb3GEOGWKRTSLeLFYwXyLFBeaGH8w7z/yyRZlvilR5YV+kuMYY04r3NpNEfBByaYksZUyDAoPsYELmmKJKjj0CS0QYU4rl3WLMeceRCBMItW7CMEd9LxbIcUqOXQJLFld9Iks9Ii0qPTYjAo5pscYJrxzIIs1SV1B5ivzRsFjFfHaiLrDOaIxHCLmnyRmp5LLytKnw1FNWH2XaYoyM9T8AOvnw3YUOg90AAAAASUVORK5CYII=';};
    toggleImage();Services.prefs.addObserver(s,toggleImage,false);
addDestructor(()=>Services.prefs.removeObserver(s,toggleImage));

// nodeName: menuitem - для логических(boolean) параметров, menu - для целых(integer) и строковых(string). menuseparator - для разделителя.
// pref - параметр about:config.
// Параметры имеющие значения отличные от дефолтных - выделены жирным стилем текста.
// restart (задавать с пустым значением. т.е., restart: "") - добавляет возможность перезапуска браузера
// (с подтверждением в диалоговом окне) после изменения параметра.
// key - задает accesskey - клавиши для быстрой навигации по меню.
// userChoice - задает предпочитаемое значение и если текущее значение с ним не совпадает, пункт меню/название меню помечаются красным цветом.
// Также можно установить предупреждающую иконку для таких пунктов. См. стиль в посте ккнопки.
// А также меняется иконка самой кнопки (см. выше).
// strValues - значения и отображаемое в меню название значения. Задавать для целых(integer) и строковых(string) параметров.
// Задается в виде: значение,,,название,,,accesskey|||значение2,,,название2,,,accesskey2|||значение3,,,название3 и т.д. (accesskey - задается опционально)
// Полное значение отображается в подсказках, при наведении на название подменю/пункт подменю.
// Для логических(boolean) - отображается сразу после самого параметра (значение true - также ставит галочку для него).
// ЛКМ по пунктам меню - перключает значения для логических(boolean) параметров,
// любая кнопка по пунктам в субменю - задает это значение для целых(integer) и строковых(string) параметров.
// ПКМ по пунктам меню и названию субменю - сбрасывает значение параметра в дефолтное.
// Клавиатура: Enter - переключение параметра.
// Спецклавиша вызова контекстного меню / Shift+Enter - сброс в дефолтное значение.
// Alt + M - открыть меню кнопки. (Сочетание можно сменить на свое. См. в конце кода)
[ //{nodeName:"menuitem", name:"Откл. дискового кэша", pref:"browser.cache.disk.enable", userChoice:"false"},
  //{nodeName:"menuitem", name:"Откл. кэша в оперативной памяти", pref:"browser.cache.memory.enable", userChoice:"false"},
  //{nodeName:"menuseparator"},
  //{nodeName:"menuitem", name:"Откл. локального хранилища DB (Storage)", pref:"dom.indexedDB.enabled", key:'d'},
  //{nodeName:"menuitem", name:"Откл. локального хранилища", pref:"dom.storage.enabled", key:'s'},
  //{nodeName:"menuseparator"},
  //{nodeName:"menu", name:"Back-story-cash [Tessssttt]", pref:"browser.sessionhistory.max_total_viewers", strValues:"0,,,0"},
  //{nodeName:"menu", pref:"image.animation_mode", key:'i', userChoice:"none", strValues:"normal,,,Анимация картинок вкл.,,,|||none,,,Анимация картинок выкл.,,,"},
  //{nodeName:"menu", pref:"network.cookie.cookieBehavior", key:'k', userChoice:"1", strValues:"2,,,Не принимать куки с сайтов,,,|||0,,,Принимать куки со сторонних сайтов всегда,,,|||3,,,Принимать куки со сторонних посещённых сайтов,,,|||1,,,Принимать куки со сторонних сайтов никогда,,,"},
  //{nodeName:"menuseparator"},
  //{nodeName:"menu", pref:"general.useragent.locale", key:'l', restart:"", strValues:"en-US,,,English,,,e|||ru,,,Русский,,,r"},
  //{nodeName:"menu", name:"language", pref:"intl.accept_languages", strValues:"en-US, en;q=0.5,,,en-US, en;q=0.5,,,e|||en-US, en, ru-RU, ru,,,en-US, en, ru-RU, ru,,,r"},
  //{nodeName:"menu", pref:"browser.display.document_color_use", key:'c', userChoice:"0", strValues:"0,,,Automatic,,,0|||1,,,Always,,,1|||2,,,Never,,,2"},
  //{nodeName:"menu", pref:"CB.TEST", key:'t', userChoice:"C:\\Downloads\\TEST1", strValues:"C:\\Downloads\\TEST1,,,TEST1,,,1|||C:\\Downloads\\TEST2,,,TEST2,,,2"}
  //{nodeName:"menuseparator"},
  //{nodeName:"menuitem", name:"Откл. инфу начало/конец загрузки стр", pref:"dom.enable_performance", userChoice:"false"},
  //{nodeName:"menu", name:"Вкл/Выкл Referer", pref:"network.http.sendRefererHeader", strValues:"0,,,0"},
  //{nodeName:"menuitem", name:"В качестве реферера корень сайта", pref:"network.http.referer.spoofSource", userChoice:"true"},
  //{nodeName:"menu", name:"referer.trimmingPolicy", pref:"network.http.referer.trimmingPolicy", strValues:"2,,,2"},
  //{nodeName:"menuseparator"},
  //{nodeName:"menu", name:"On/Off Image", pref:"permissions.default.image", userChoice:1, strValues:"2,,,Off"},

  //{nodeName:"menuitem", name:"On/Off javascript", pref:"javascript.enabled", key:'j', userChoice:"true"},
  {nodeName:"menuitem", name:"On/Off useragentS", pref:"general.useragent.site_specific_overrides", userChoice:"true"},
  //{nodeName:"menuitem", pref:"dom.workers.enabled", key:'w', userChoice:"false"},
  //{nodeName:"menu", name:"Stopautoplay", pref:"media.autoplay.default", userChoice:0, strValues:"0,,,Stop,,,0|||1,,,Play,,,1"},
  //{nodeName:"menuitem", pref:"xpinstall.signatures.required"},                       //Check is compatibility
  //{nodeName:"menuitem", pref:"browser.bookmarks.autoExportHTML"},                    //BookmarksHtml [false=places.sqlite]
  //{nodeName:"menuitem", pref:"media.peerconnection.enabled"},                        //WebRTC false=off!

  {nodeName:"menuitem", name:"Drag&Drop(Safe) !Manual restart required!", pref:"browser.launcherProcess.enabled", userChoice:"true"},   //Drag&Drop(Safe) Manual restart required! - forum.mozilla-russia.org/viewtopic.php?pid=774980#p774980
  {nodeName:"menuitem", name:"On/Off media.play-stand-alone", pref:"media.play-stand-alone"},   //сразу скачивать медиафайлы, без перехода на новую страницу.
  {nodeName:"menuseparator"},
  {nodeName:"menu", name:"On/Off DoH", pref:"network.trr.mode", strValues:"3,,,3"},
  {nodeName:"menu", name:"Configure Proxies", pref:"network.proxy.type", userChoice:5, strValues:"1,,,httpP,,,1|||2,,,AutomaticP,,,2|||5,,,Use systemP,,,5"},
  {nodeName:"menu", name:"AutomaticP", pref:"network.proxy.autoconfig_url", strValues:"resource://FF/..pac,,,resource://FF/..pac,,,1|||https://antizapret.prostovpn.org/proxy.pac,,,https://antizapret.prostovpn.org/proxy.pac,,,2"},
  {nodeName:"menuseparator"}, 
  {nodeName:"menu", name:"User Agent", pref:"general.useragent.override", key:'u', strValues:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Firefox/60.0,,,Firefox 60/MacOSX 10.13|||Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36,,,Chrome 66/MacOSX 10.13.5|||Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36,,,Chrome 57/MacOSX|||Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30,,,Safari Generic/MacOSX|||Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36,,,Chrome57/W7|||Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12 Version/12.16,,,Opera12/W8|||Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Safari/537.36,,,Chrome61/W10|||Mozilla/5.0 (Linux; Android 7.0; PLUS Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36,,,Chrome61/Android7|||Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html),,,GoogleBot|||Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots),,,YandexBot|||Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp),,,YahooBot|||Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm),,,BingBot|||DuckDuck bot/1.0; (+http://duckduckgo.com/duckduckbot.html),,,DuckDuckBot|||Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html),,,BaiduspiderBot|||ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com),,,AlexaCrawlerBot|||Mozilla/5.0 (Linux; Android 5.1.1; SM-G928X Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36,,,Samsung Galaxy S6 Edge Plus|||Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586,,,Microsoft Lumia 950|||Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586,,,Xbox One|||Mozilla/5.0 (PlayStation 4 3.11) AppleWebKit/537.73 (KHTML, like Gecko),,,Playstation 4|||,,,Пустое значение"},
]

.forEach(function(m){var mItem=document.createElementNS(xulns,m.nodeName);var browserRestart='';
if("restart"in m)browserRestart='if(custombuttons.confirmBox(null,"Restart?","Yes","Cancel"))Services.startup.quit(Services.startup.eAttemptQuit|Services.startup.eRestart);';
if("name"in m) mItem.setAttribute('name',m.name);
if("pref"in m){mItem.setAttribute('closemenu','none');
mItem.setAttribute('oncontextmenu','event.preventDefault();custombuttons.clearPrefs("'+m.pref+'");'+browserRestart);}
if("key"in m)  mItem.setAttribute('accesskey',m.key);
if(m.nodeName==="menuitem"){mItem.setAttribute('type','checkbox');
mItem.setAttribute('oncommand','custombuttons.setPrefs("'+m.pref+'",!custombuttons.getPrefs("'+m.pref+'"));if(event.shiftKey&&event.keyCode==event.DOM_VK_RETURN){event.preventDefault();custombuttons.clearPrefs("'+m.pref+'")};'+browserRestart);}
if(m.nodeName==="menu"){mItem.setAttribute('class','menu-iconic');

var subMenu=mItem.appendChild(document.createXULElement("menupopup"));

for (var value of m.strValues.split('|||')){var submItem=document.createXULElement("menuitem");
var smVal=value.split(',,,')[0];
var smValConv=convertFromUnicode("UTF-8",smVal);
var smName=value.split(',,,')[1];
var key=value.split(',,,')[2];

key&&submItem.setAttribute('accesskey',key);submItem.setAttribute('type','radio');
submItem.setAttribute('label',smName);submItem.setAttribute('tooltiptext',smVal);
submItem.setAttribute('closemenu','none');
submItem.setAttribute('oncommand','try{custombuttons.setPrefs("'+m.pref+'","'+smValConv.replace(/\\/g,'\\\\')+'")}catch(e){Services.prefs.setIntPref("'+m.pref+'","'+smValConv+'")};'+browserRestart);
subMenu.appendChild(submItem);}}
menuPopup.appendChild(mItem);

  // Листенеры отслеживающие переключение параметров
  // и устанавливающие соответствующие названия и чекбоксы для пунктов меню при открытии меню и кликах
  for (var type of ['command','popupshowing','contextmenu']){addEventListener(type,(e)=>{setTimeout(()=>{if ("pref" in m){var val,def;
   def=Services.prefs.prefHasUserValue(m.pref);
   try {val=Services.prefs.getComplexValue(m.pref,Ci.nsISupportsString).data;} catch(e) {
   if (Services.prefs.getPrefType(m.pref)==64) val=custombuttons.getPrefs(m.pref).toString();else val=custombuttons.getPrefs(m.pref);}
   def ? mItem.style.setProperty('font-weight', 'bold', 'important') : mItem.style.removeProperty('font-weight');}

     if (m.nodeName==='menuitem'){mItem.setAttribute('checked',val);mItem.label=(mItem.hasAttribute('name') ? mItem.getAttribute('name') : m.pref)+' - "'+val+'"';
     if ("userChoice" in m){try {var usrChc=(val.toString()===m.userChoice)} catch(e) {usrChc=false};

     mItem.setAttribute('user-choice',usrChc);usrChc ? mItem.style.removeProperty('color') : mItem.style.setProperty('color','orangered','important');}}
     if (subMenu){for (var smitem of subMenu.getElementsByTagName('menuitem')) {var smval=smitem.getAttribute('tooltiptext');smitem.setAttribute('checked',(val===smval) ? true : false);}}
     if (m.nodeName==="menu") {var vname;
     try {vname=subMenu.getElementsByAttribute('checked','true')[0].getAttribute('label');} catch(e) {if (!Services.prefs.prefHasUserValue(m.pref)) vname='Default';else vname='Other';}

     mItem.setAttribute('label',(mItem.hasAttribute('name') ? mItem.getAttribute('name') : m.pref)+' - "'+vname+'"');
     mItem.setAttribute('tooltiptext',val || 'This preferences has null value or does not exist.');

     if ("userChoice" in m) {var smUsrChc=(val===m.userChoice.toString());mItem.setAttribute('user-choice',smUsrChc);
     smUsrChc ? mItem.style.removeProperty('color') : mItem.style.setProperty('color','orangered','important');}}

     if ("userChoice" in m) {var hasNotUserChoice=menuPopup.getElementsByAttribute('user-choice','false')[0];custombuttons.setPrefs(s,hasNotUserChoice ? true : false);}}, 0)},false,menuPopup)}});

// Листенер позволяющий сброс параметров с субменю по Shift+Enter||За код спасибо Dumby
addEventListener("popupshown",{handleEvent:function(e){this[e.type](e);},
  popupshown:function(e){if(e.target!=menuPopup)return;menuPopup.addEventListener   ("popuphidden",this,false);window.addEventListener   ("keydown",this,true);},
 popuphidden:function(e){if(e.target!=menuPopup)return;menuPopup.removeEventListener("popuphidden",this,false);window.removeEventListener("keydown",this,true);},
popupshowing:function(e){e.target.parentNode.removeEventListener("popupshowing",this,false);e.preventDefault();},get old(){delete this.old;
this.e=new MouseEvent("contextmenu",{});return this.old=parseInt(Services.appinfo.platformVersion)<25;},get prop(){delete this.prop;
if("key"in KeyboardEvent.prototype)this.prop="key",this.val="Enter";else this.prop="keyCode",this.val=KeyboardEvent.DOM_VK_RETURN;return this.prop;},
keydown:function(e){if(!e.shiftKey||e.ctrlKey||e.altKey||e[this.prop]!=this.val)return;var target=menuPopup.querySelector("menu[_moz-menuactive]:not([open])");
if(!target)return;this.old ? target.addEventListener("popupshowing",this,false) : e.stopPropagation();target.dispatchEvent(this.e);menuPopup.dispatchEvent(this.e);}},false,menuPopup);

// Открыть меню кнопки по сочетанию клавиш Alt + M (не зависит от текущей раскладки клавиатуры)
// Посмотреть коды клавиш можно здесь: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#Constants_for_keyCode_value
addEventListener('keyup',(e)=>{if(e.altKey&&!e.shiftKey&&!e.ctrlKey&&e.keyCode==77){e.preventDefault();e.stopPropagation();
menuPopup.showPopup(this,-1,-1,"popup","bottomleft","topleft");}},false,window);

// Конвертировать текст в юникод .............
function convertFromUnicode(charset,str){var converter=Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset=charset;str=converter.ConvertFromUnicode(str);return str+converter.Finish();};

все кнопки в вертикальном тулбаре, если можно реализовать как с этим кодом (this,-1,-1,"popup","bottomleft","topleft"); он открывает не как на навбаре


еще есть такой код, в uc.js, "//Define button, //Define menu" отвечают походу за открытие, но не знаю как реализовать.
QuickOpen.uc.js

Выделить код

Код:

//Define button
CustomizableUI.createWidget({id:'QuickOpen',defaultArea:CustomizableUI.AREA_NAVBAR,label:'Quick tools',/*tooltiptext:'Quickly open the specified options',*/onCreated:function(aNode){aNode.setAttribute('type','menu');    
 //Define menu
var myMenuJson=['xul:menupopup',{id:'QuickOpen_pop',position:'after_end'},
................................
................................
];aNode.appendChild(jsonToDOM(myMenuJson,aNode.ownerDocument,{}));aNode.setAttribute('menupopup','QuickOpen_pop');
}
});

весь код не вошел, поэтому только часть

Отредактировано func4ptch4 (19-01-2020 15:34:07)

Отсутствует

 

№1409119-01-2020 15:12:12

solombala
Участник
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 350
UA: Firefox 72.0

Re: Custom Buttons

Dumby
Больше не к кому...Такая поганка в 72 (нет там ничего нового после 70, тем более 71), но и морду попортили опять...
Megabar-Urlbar  - И при запуске расширяется и при клике на  самом и на панели вкладок...Это при дефолтной теме , никакие стили не помогают...Это скрипт где-то..
https://forum.mozilla-russia.org/viewto … 98#p776998
Там местные деляги  просто вянут, короче, есть мысль?
browser.urlbar.update1 = true , кажись это влияет

Отредактировано solombala (19-01-2020 15:52:52)

Отсутствует

 

№1409219-01-2020 18:03:47

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 685
UA: Firefox 52.0

Re: Custom Buttons

Dumby
Как убрать эти иконки:

скрытый текст
https://d.radikal.ru/d43/2001/47/17237f6eff56.png

а то всё равно другие не получается добавить ?

Отсутствует

 

№1409319-01-2020 20:14:26

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 1072
UA: Firefox 52.0

Re: Custom Buttons

func4ptch4
Здесь можно сделать так:

1. Переделываем кнопку под [type=menu].
Для этого, удаляем третью строку (начинающуюся с this._handleClick),
а в конец кода кладём this.type = "menu";

Если нужно, чтобы на вертикальном тулбаре
меню открывалось вбок, дописываем
this.matches("toolbar[orient=vertical] > :scope") && menuPopup.setAttribute("position", "end_before");

2. Идём к Infocatcher'у за сниппетом, открываем ссылку «Raw»,
копируем код от комментария // Autoopen/close feature и до конца,
и добавляем в код кнопки, тоже в конец.

Всё. Встроенный autopopup готов.

Кстати, у тебя там открытие меню кнопки по Alt+M висит непеределанным.
Так что, заодно, можно либо удалить, раз не пользуешься,
либо, к контексте данной переделки, записать так:

//menuPopup.showPopup(this,-1,-1,"popup","bottomleft","topleft");}},false,window);
self.open = true;}},false,window);

solombala пишет:

никакие стили не помогают

Вот специально скачал Firefox 72.0.1, собрал чистый портабл,
тема «Стандартная», ничего не трогал,
включил browser.urlbar.update1, включил userChrome.css,
скормил ему стиль проекта «AntiMegabar» от Vitaliy V., рестарт.

И мегабар ни при запуске, ни при каких кликах, никуда не расширяется.
Ни на один пиксель. Стоит как вкопанный. Так что...

kokoss пишет:

Как убрать эти иконки

Удалить этот фрагмент кода.
Ну и все свойства image и style из объектов массива array (не обязательно).

скрытый текст

Выделить код

Код:

   mItem.setAttribute("class", "menuitem-iconic");
   ("image" in m) && mItem.setAttribute("image", m.image);    
   ("style" in m) && mItem.setAttribute("style", "list-style-image: url('"+ m.style +"'); -moz-image-region: rect(0, 16px, 16px, 0)");

Отсутствует

 

№1409419-01-2020 21:24:20

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 685
UA: Firefox 52.0

Re: Custom Buttons

Dumby
Благодарю!

Отсутствует

 

№1409520-01-2020 14:25:36

egorsemenov06
Участник
 
Группа: Members
Зарегистрирован: 12-06-2018
Сообщений: 91
UA: Firefox 72.0

Re: Custom Buttons

Dumby
не гляните вот эту кнопку в ней не работает правый клик проверка обновлений доролнений

скрытый текст

Выделить код

Код:

// http://infocatcher.ucoz.net/js/cb/toggleRestartlessAddons.js
    // https://forum.mozilla-russia.org/viewtopic.php?id=57948
    // https://github.com/Infocatcher/Custom_Buttons/tree/master/Toggle_Restartless_Add-ons
    
    // Toggle Restartless Add-ons button for Custom Buttons
    // (code for "initialization" section)
    // Also the code can be used from main window context (as Mouse Gestures code, for example)
    
    // Also you can check for add-ons updates using right-click:
    // copy all code from
    // https://github.com/Infocatcher/Custom_Buttons/blob/master/Check_for_Addons_Updates/checkForAddonsUpdates.js
    // after "//== Check for Addons Updates begin"
    
    // See "var style = " to modify styles for specific add-ons
    
    // (c) Infocatcher 2013-2017
    // version 0.1.3pre3 - 2017-10-23
      
    var options = {
        addonTypes: ["extension"],
        // Possible values: "extension", "plugin"
        // From extensions: "userstyle" (Stylish), "greasemonkey-user-script" (Greasemonkey), "userscript" (Scriptish)
        // (swap to reorder in the menu)
        showVersions: 1,
        // 0 - don't show versions
        // 1 - show after name: "Addon Name 1.2"
        // 2 - show as "acceltext" (in place for hotkey text)
        showHidden: 0,
        // 0  - don't show hidden add-ons
        // -1 - show only enabled hidden add-ons (e.g. to track new items)
        // 1  - show all hidden add-ons
        sort: {
            enabled:     0,
            clickToPlay: 0,
            disabled:    0
            // Sort order:
            // 0, 0, 0 - sort add-ons of each type alphabetically
            // 0, 0, 1 - show enabled add-ons (of each type) first
            // 0, 1, 2 - enabled add-ons, then click-to-play and then disabled
        },
        closeMenu: false, // Close menu after left-click
        closeMenuClickToPlay: false // Close menu after left-click, for click to play plugins
        // Use Shift+click to invert closeMenu* behavior
    };
    
    var mp = document.createXULElement("menupopup");
    mp.setAttribute("onpopupshowing", "this.updateMenu();");
    mp.setAttribute("oncommand", "this.handleEvent(event);");
    mp.setAttribute("onmousedown", "if(event.button == 0) this.handleEvent(event);");
    mp.setAttribute("onclick", "if(event.button > 0) this.handleEvent(event);");
    mp.setAttribute("oncontextmenu", "return false;");
    mp.setAttribute("onpopuphidden", "this.destroyMenu();");
    
    var tb = this.parentNode;
    if(tb && tb.getAttribute("orient") == "vertical") {
        // https://addons.mozilla.org/firefox/addon/vertical-toolbar/
        var isRight = tb.parentNode.getAttribute("placement") == "right";
        mp.setAttribute("position", isRight ? "start_before" : "end_before");
    }
    
    var cleanupTimer = 0;
    mp.updateMenu = function() {
        clearTimeout(cleanupTimer);
        addStyle();
        getRestartlessAddons(options.addonTypes, function(addons) {
            var df = document.createDocumentFragment();
            var prevType;
            function sortPosition(addon) {
                if("STATE_ASK_TO_ACTIVATE" in AddonManager && addon.userDisabled == AddonManager.STATE_ASK_TO_ACTIVATE)
                    return options.sort.clickToPlay;
                if(addon.isActive)
                    return options.sort.enabled;
                return options.sort.disabled;
            }
            function key(addon) {
                return options.addonTypes.indexOf(addon.type)
                    + "\n" + sortPosition(addon)
                    + "\n" + addon.name.toLowerCase();
            }
            addons.sort(function(a, b) {
                var ka = key(a);
                var kb = key(b);
                return ka == kb ? 0 : ka < kb ? -1 : 1;
            }).forEach(function(addon) {
                var type = addon.type;
                if(prevType && type != prevType)
                    df.appendChild(document.createXULElement("menuseparator"));
                prevType = type;
                var icon = addon.iconURL || addon.icon64URL;
                var mi = document.createXULElement("menuitem");
                mi.className = "menuitem-iconic";
                var label = addon.name;
                if(options.showVersions == 1)
                    label += " " + addon.version;
                else if(options.showVersions == 2)
                    mi.setAttribute("acceltext", addon.version);
                mi.setAttribute("label", label);
                mi.setAttribute("image", icon || mp.icons[type] || "");
                if(!icon && mp.icons.useSVG)
                    mi.style.fill = "#15c";
                var tip = addon.description || "";
                var delay = "delayedStartupAddons" in Services
                    && Services.delayedStartupAddons[addon.id] || null;
                var isDelayed = delay !== null;
                mi.classList.toggle("toggleRestartlessAddons-isDelayed", isDelayed);
                if(isDelayed)
                    tip = "[Delayed Startup: " + delay.toLocaleString() + "]" + (tip ? "\n" + tip : "");
                tip && mi.setAttribute("tooltiptext", tip);
                mi.classList.toggle("toggleRestartlessAddons-isHidden", addon.hidden || false);
                setDisabled(mi, addon.userDisabled);
                mi._cbAddon = addon;
                df.appendChild(mi);
            });
            mp.textContent = "";
            mp.appendChild(df);
        });
    };
    mp.handleEvent = function(e) {
        var mi = e.target;
        if(!("_cbAddon" in mi))
            return;
        var addon = mi._cbAddon;
        if(e.type == "mousedown") {
            var closeMenu = isAskToActivateAddon(addon)
                ? options.closeMenuClickToPlay
                : options.closeMenu;
            if(e.shiftKey)
                closeMenu = !closeMenu;
            mi.setAttribute("closemenu", closeMenu ? "auto" : "none");
            return;
        }
        var hasMdf = hasModifier(e);
        if(e.type == "command" && (!hasMdf || e.shiftKey)) {
            let newDis = setNewDisabled(addon);
            setDisabled(mi, newDis);
        }
        else if(e.type == "command" && hasMdf || e.type == "click" && e.button == 1) {
            openAddonPage(addon);
            closeMenus(mi);
        }
        else if(e.type == "click" && e.button == 2) {
            if(openAddonOptions(addon))
                closeMenus(mi);
        }
    };
    mp.destroyMenu = function() {
        removeStyle();
        clearTimeout(cleanupTimer);
        cleanupTimer = setTimeout(function() {
            mp.textContent = "";
        }, 5000);
    };
    mp.icons = {
        get useSVG() {
            delete this.useSVG;
            return this.useSVG = Services.appinfo.name == "Firefox"
                && parseFloat(Services.appinfo.version) >= 57;
        },
        get plugin() {
            delete this.plugin;
            return this.plugin = this.useSVG
                ? "chrome://mozapps/skin/plugins/pluginGeneric.svg"
                : "chrome://mozapps/skin/plugins/pluginGeneric-16.png";
        },
        get extension() {
            delete this.extension;
            return this.extension = this.useSVG
                ? "chrome://mozapps/skin/extensions/extensionGeneric-16.svg"
                : "chrome://mozapps/skin/extensions/extensionGeneric-16.png";
        }
    };
    function isAskToActivateAddon(addon) {
        return addon.type == "plugin"
            && "STATE_ASK_TO_ACTIVATE" in AddonManager
            && Services.prefs.getBoolPref("plugins.click_to_play");
    }
    function setNewDisabled(addon) {
        var newDis = getNewDisabled(addon);
        var oldDis = addon.userDisabled;
        try {
            addon.userDisabled = newDis;
        }
        catch(e) { // Error: Cannot disable hidden add-on firefox@getpocket.com
            _log("Can't set addon.userDisabled to " + newDis + ", error:\n" + e);
            if(addon.hidden)
                setNewDisabledRaw(addon, newDis);
        }
        var realDis = addon.userDisabled;
        if(realDis != newDis && addon.type == "extension") { // Firefox 62+? Weird things happens
            setNewDisabledRaw(addon, newDis);
            realDis = addon.userDisabled;
        }
        if(realDis != newDis) { // We can't enable vulnerable plugins
            let err = "Can't set addon.userDisabled to " + newDis + ", real value: " + realDis;
            if(newDis) {
                _log(err + "\nSTATE_ASK_TO_ACTIVATE not supported?");
                newDis = false;
            }
            else {
                _log(err + "\nVulnerable plugin?");
                if(oldDis == AddonManager.STATE_ASK_TO_ACTIVATE)
                    newDis = true;
                else
                    newDis = AddonManager.STATE_ASK_TO_ACTIVATE;
            }
            addon.userDisabled = newDis;
        }
        return addon.userDisabled;
    }
    function getNewDisabled(addon) {
        // disabled -> STATE_ASK_TO_ACTIVATE -> enabled -> ...
        var curDis = addon.userDisabled;
        var newDis;
        if("STATE_ASK_TO_ACTIVATE" in AddonManager && curDis == AddonManager.STATE_ASK_TO_ACTIVATE)
            newDis = false;
        else if(!curDis)
            newDis = true;
        else {
            if(isAskToActivateAddon(addon))
                newDis = AddonManager.STATE_ASK_TO_ACTIVATE;
            else
                newDis = false;
        }
        return newDis;
    }
    function setNewDisabledRaw(addon, newDis) {
        _log("Let's try set addon.userDisabled using raw hack");
        let g = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {});
        if("XPIDatabase" in g && "updateAddonDisabledState" in g.XPIDatabase) { // Firefox 61+
            let rawAddon = g.XPIDatabase.getAddons().find(function(rawAddon) {
                return rawAddon.id == addon.id;
            });
            g.XPIDatabase.updateAddonDisabledState(rawAddon, newDis);
        }
        else if("eval" in g) { // See "set userDisabled(val)"
            let addonFor = g.eval("addonFor");
            let rawAddon = addonFor(addon);
            //rawAddon.userDisabled = newDis;
            g.XPIProvider.updateAddonDisabledState(rawAddon, newDis);
        }
        else { // Firefox 57+? See https://forum.mozilla-russia.org/viewtopic.php?pid=745272#p745272
            updateAddonDisabledState(addon, newDis);
        }
    }
    function updateAddonDisabledState(addon, newDis) {
        var nsvo = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {});
        var key = "_cbToggleRestartlessAddonsData";
        var url = URL.createObjectURL(new Blob([
            "XPIProvider.updateAddonDisabledState(addonFor(this." + key + "[0]), this." + key + "[1]); delete this." + key + ";"
        ]));
        addDestructor(function() {
            URL.revokeObjectURL(url);
        });
        (updateAddonDisabledState = function(addon, newDis) {
            nsvo[key] = [addon, newDis];
            Services.scriptloader.loadSubScript(url, nsvo);
        })(addon, newDis);
    }
    function setDisabled(mi, disabled) {
        var askToActivate = "STATE_ASK_TO_ACTIVATE" in AddonManager && disabled == AddonManager.STATE_ASK_TO_ACTIVATE;
        var cl = mi.classList;
        cl.toggle("toggleRestartlessAddons-askToActivate", askToActivate);
        cl.toggle("toggleRestartlessAddons-disabled", disabled && !askToActivate);
    }
    
    if(
        this instanceof XULElement // Custom Buttons
        && typeof event == "object"
        && !("type" in event) && typeof _phase == "string" && _phase == "init" // Initialization
    ) {
        this.type = "menu";
        this.orient = "horizontal";
        this.appendChild(mp);
    
        this.onmouseover = function(e) {
            if(e.target != this)
                return;
            Array.prototype.some.call(
                this.parentNode.getElementsByTagName("*"),
                function(node) {
                    if(
                        node != this
                        && node.namespaceURI == xulns
                        && node.boxObject
                        // See https://github.com/Infocatcher/Custom_Buttons/issues/28
                        //&& node.boxObject instanceof Components.interfaces.nsIMenuBoxObject
                        && "open" in node
                        && node.open
                        && node.getElementsByTagName("menupopup").length
                    ) {
                        node.open = false;
                        this.open = true;
                        return true;
                    }
                    return false;
                },
                this
            );
        };
        this.onmousedown = function(e) {
            if(e.target == this && e.button == 0 && hasModifier(e))
                e.preventDefault();
        };
        this.oncontextmenu = function(e) {
            if(e.target == this && !hasModifier(e) && hasUpdater())
                e.preventDefault();
        };
        this.onclick = function(e) {
            if(e.target != this)
                return;
            if(e.button == 0 && hasModifier(e) || e.button == 1)
                openAddonsManager();
            else if(e.button == 2 && !hasModifier(e) && hasUpdater())
                checkForAddonsUpdates.call(this);
        };
    }
    else { // Mouse gestures or something other...
        let e;
        if(typeof event == "object" && event instanceof Event && "screenX" in event) // FireGestures
            e = event;
        else if(
            this instanceof Components.interfaces.nsIDOMChromeWindow
            && "mgGestureState" in window && "endEvent" in mgGestureState // Mouse Gestures Redox
        )
            e = mgGestureState.endEvent;
        else {
            let anchor = this instanceof XULElement && this
                || window.gBrowser && gBrowser.selectedBrowser
                || document.documentElement;
            if("boxObject" in anchor) {
                let bo = anchor.boxObject;
                e = {
                    screenX: bo.screenX,
                    screenY: bo.screenY
                };
                if(this instanceof XULElement)
                    e.screenY += bo.height;
            }
        }
        if(!e || !("screenX" in e))
            throw new Error("[Toggle Restartless Add-ons]: Can't get event object");
        document.documentElement.appendChild(mp);
        mp.addEventListener("popuphidden", function destroy(e) {
            mp.removeEventListener(e.type, destroy, false);
            setTimeout(function() {
                mp.destroyMenu();
                mp.parentNode.removeChild(mp);
            }, 0);
        }, false);
        mp.openPopupAtScreen(e.screenX, e.screenY);
    }
    
    function getRestartlessAddons(addonTypes, callback, context) {
        if(!("AddonManager" in window))
            Components.utils.import("resource://gre/modules/AddonManager.jsm");
        if(!("Services" in window))
            Components.utils.import("resource://gre/modules/Services.jsm");
        var then, promise = AddonManager.getAddonsByTypes(addonTypes, then = function(addons) {
            var restartless = addons.filter(function(addon) {
                var ops = addon.operationsRequiringRestart;
                return !addon.appDisabled
                    && !(ops & AddonManager.OP_NEEDS_RESTART_ENABLE || ops & AddonManager.OP_NEEDS_RESTART_DISABLE)
                    && (
                        !addon.hidden
                        || options.showHidden > 0
                        || options.showHidden == -1 && !addon.userDisabled
                    );
            });
            callback.call(context, restartless);
        });
        promise && typeof promise.then == "function" && promise.then(then, Components.utils.reportError); // Firefox 61+
    }
    function openAddonOptions(addon) {
        // Based on code from chrome://mozapps/content/extensions/extensions.js
        // Firefox 21.0a1 (2013-01-27)
        var optionsURL = addon.optionsURL;
        if(!addon.isActive || !optionsURL)
            return false;
        if(addon.type == "plugin") // No options for now!
            return false;
        if(
            addon.optionsType == AddonManager.OPTIONS_TYPE_INLINE
            || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_INFO || NaN)
            || addon.optionsType == (AddonManager.OPTIONS_TYPE_INLINE_BROWSER || NaN)
        )
            openAddonPage(addon, true);
        else if(addon.optionsType == AddonManager.OPTIONS_TYPE_TAB && "switchToTabHavingURI" in window)
            switchToTabHavingURI(optionsURL, true);
        else {
            let windows = Services.wm.getEnumerator(null);
            while(windows.hasMoreElements()) {
                let win = windows.getNext();
                if(win.document.documentURI == optionsURL) {
                    win.focus();
                    return true;
                }
            }
            // Note: original code checks browser.preferences.instantApply and may open modal windows
            window.openDialog(optionsURL, "", "chrome,titlebar,toolbar,centerscreen,dialog=no");
        }
        return true;
    }
    function openAddonsManager(view) {
        var openAddonsMgr = window.BrowserOpenAddonsMgr // Firefox
            || window.openAddonsMgr // Thunderbird
            || window.toEM; // SeaMonkey
        openAddonsMgr(view);
    }
    function openAddonPage(addon, scrollToPreferences) {
        var platformVersion = parseFloat(
            Services.appinfo.name == "Pale Moon"
                ? Services.appinfo.version
                : Services.appinfo.platformVersion
        );
        scrollToPreferences = scrollToPreferences && platformVersion >= 12
            ? "/preferences"
            : "";
        openAddonsManager("addons://detail/" + encodeURIComponent(addon.id) + scrollToPreferences);
    }
    
    function hasModifier(e) {
        return e.ctrlKey || e.shiftKey || e.altKey || e.metaKey;
    }
    
    function addStyle() {
        if(addStyle.hasOwnProperty("_style"))
            return;
        var style = '\
            .toggleRestartlessAddons-isDelayed > .menu-iconic-text {\n\
                opacity: 0.75;\n\
                color: #070;\n\
            }\n\
            .toggleRestartlessAddons-isHidden > .menu-iconic-text {\n\
                color: #609;\n\
            }\n\
            .toggleRestartlessAddons-disabled > .menu-iconic-left {\n\
                opacity: 0.4;\n\
            }\n\
            .toggleRestartlessAddons-disabled > .menu-iconic-text,\n\
            .toggleRestartlessAddons-disabled > .menu-accel-container {\n\
                opacity: 0.5;\n\
            }\n\
            .toggleRestartlessAddons-askToActivate {\n\
                color: -moz-nativehyperlinktext;\n\
            }';
        addStyle._style = document.insertBefore(
            document.createProcessingInstruction(
                "xml-stylesheet",
                'href="' + "data:text/css,"
                    + encodeURIComponent(style) + '" type="text/css"'
            ),
            document.documentElement
        );
    }
    function removeStyle() {
        if(!addStyle.hasOwnProperty("_style"))
            return;
        var s = addStyle._style;
        s.parentNode.removeChild(s);
        delete addStyle._style;
    }
    function closeMenus(node) {
        // Based on function closeMenus from chrome://browser/content/utilityOverlay.js
        for(; node && "tagName" in node; node = node.parentNode) {
            if(
                node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
                && (node.localName == "menupopup" || node.localName == "popup")
            )
                node.hidePopup();
        }
    }
    function _log(s) {
        if(typeof LOG == "function") // Custom Buttons
            LOG(s);
        else // Or something else
            Services.console.logStringMessage("Toggle Restartless Add-ons: " + s);
    }
    
    function hasUpdater() {
        var has = checkForAddonsUpdates.toString().indexOf("about:addons") != -1;
        hasUpdater = function() {
            return has;
        };
        return has;
    }
    
    
    
    
    
    
    
    
    
    function checkForAddonsUpdates() {
// http://infocatcher.ucoz.net/js/cb/checkForAddonsUpdates.js
// https://forum.mozilla-russia.org/viewtopic.php?id=57958
// https://github.com/Infocatcher/Custom_Buttons/tree/master/Check_for_Addons_Updates

// Check for Addons Updates button for Custom Buttons
// (code for "code" section)

// (c) Infocatcher 2012-2014
// version 0.1.5 - 2014-10-13

// Button just open hidden tab with about:addons and trigger built-in "Check for Updates" function.
// And show tab, if found updates.

(function() {
var btn = this instanceof XULElement
    ? this
    : { // Launched not from custom button
        image: "", // Base64-encoded icon (if empty, will be used "imgLoading")
        label: "Check for Addons Updates",
        tooltipText: ""
    };
if("_cb_disabled" in btn)
    return;
btn._cb_disabled = true;

if(!("Services" in window))
    Components.utils.import("resource://gre/modules/Services.jsm");
var app = Services.appinfo.name;

var ADDONS_URL = "about:addons";

var progressIcon = new ProgressIcon(btn);
var image = btn.image || progressIcon.imgLoading;
var tip = btn.tooltipText;
btn.tooltipText = "Open " + ADDONS_URL + "…";

var tab, browser, gBrowser;
var tbTabInfo, tbTab;

var trgWindow = Services.wm.getMostRecentWindow("navigator:browser")
    || app == "Thunderbird" && Services.wm.getMostRecentWindow("mail:3pane")
    || window;
var trgDocument = trgWindow.document;
var tabmail = trgDocument.getElementById("tabmail");

if(tabmail && app == "Thunderbird") { // Note: SeaMonkey doesn't support content tabs in mail window
    let addonsWin;
    let receivePong = function(subject, topic, data) {
        addonsWin = subject;
    };
    Services.obs.addObserver(receivePong, "EM-pong", false);
    Services.obs.notifyObservers(null, "EM-ping", "");
    Services.obs.removeObserver(receivePong, "EM-pong");
    if(addonsWin) {
        let rootWindow = addonsWin
            .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
            .getInterface(Components.interfaces.nsIWebNavigation)
            .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
            .rootTreeItem
            .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
            .getInterface(Components.interfaces.nsIDOMWindow);
        tabmail = rootWindow.document.getElementById("tabmail");
        tbTabInfo = tabmail.getBrowserForDocument(addonsWin);
        tbTab = tab = tbTabInfo.tabNode;
        processAddonsTab(addonsWin);
    }
    else {
        Services.obs.addObserver(function observer(subject, topic, data) {
            Services.obs.removeObserver(observer, topic);
            if(subject.document.readyState == "complete")
                processAddonsTab(subject);
            else {
                subject.addEventListener("load", function onLoad(e) {
                    subject.removeEventListener(e.type, onLoad, false);
                    processAddonsTab(subject);
                }, false);
            }
        }, "EM-loaded", false);
        // See openAddonsMgr() -> openContentTab()
        tbTabInfo = tabmail.openTab("contentTab", {
            contentPage: ADDONS_URL,
            clickHandler: "specialTabs.siteClickHandler(event, /addons\.mozilla\.org/);",
            background: true
        });
        tbTab = tab = tbTabInfo.tabNode;
        tbTab.collapsed = true;
        // Note: dontSelectHiddenTab() not implemented
    }
}
else if("gBrowser" in trgWindow && trgWindow.gBrowser.tabs) {
    let isPending = false;
    let ws = Services.wm.getEnumerator("navigator:browser");
    windowsLoop:
    while(ws.hasMoreElements()) {
        let w = ws.getNext();
        let tabs = w.gBrowser.tabs;
        for(let i = 0, l = tabs.length; i < l; ++i) {
            let t = tabs[i];
            if(
                !t.closing
                && t.linkedBrowser
                && t.linkedBrowser.currentURI.spec == ADDONS_URL
            ) {
                tab = t;
                break windowsLoop;
            }
        }
    }

    gBrowser = trgWindow.gBrowser;
    if(!tab) {
        tab = gBrowser.addTab(ADDONS_URL, {
            triggeringPrincipal: "Services" in window // Firefox 63+
                && Services.scriptSecurityManager
                && Services.scriptSecurityManager.getSystemPrincipal()
        });
        tab.collapsed = true;
        tab.closing = true; // See "visibleTabs" getter in chrome://browser/content/tabbrowser.xml
        trgWindow.addEventListener("TabSelect", dontSelectHiddenTab, false);
    }
    else if(
        tab.getAttribute("pending") == "true" // Gecko >= 9.0
        || tab.linkedBrowser.contentDocument.readyState == "uninitialized"
        // || tab.linkedBrowser.__SS_restoreState == 1
    )
        isPending = true;

    browser = tab.linkedBrowser;
    if(isPending || browser.webProgress.isLoadingDocument) {
        browser.addEventListener("load", processAddonsTab, true);
        if(isPending) {
            if(parseFloat(Services.appinfo.platformVersion) >= 41) {
                // Workaround to correctly restore pending tab
                // See https://github.com/Infocatcher/Custom_Buttons/issues/39
                let selTab = gBrowser.selectedTab;
                gBrowser.selectedTab = tab;
                gBrowser.selectedTab = selTab;
            }
            else {
                browser.reload();
            }
        }
    }
    else {
        processAddonsTab();
    }
}
else {
    progressIcon.restore();
    btn.tooltipText = tip;
    delete btn._cb_disabled;
    Services.prompt.alert(window, btn.label, "Error: Can't find supported window!");
    return;
}

function processAddonsTab(e) {
    var doc;
    if(e && e instanceof Components.interfaces.nsIDOMWindow) {
        doc = e.document;
    }
    else if(e) {
        doc = e.target;
        if(doc.location != ADDONS_URL)
            return;
        browser.removeEventListener(e.type, processAddonsTab, true);
    }
    else {
        doc = browser.contentDocument;
    }

    progressIcon.loading();
    var inProgress = $("updates-progress");
    btn.tooltipText = inProgress.getAttribute("value");

    var origIcon = tab.image;
    tab.image = image;

    var updEnabledPref = "extensions.update.enabled";
    var updEnabled = Services.prefs.getBoolPref(updEnabledPref);
    if(!updEnabled)
        Services.prefs.setBoolPref(updEnabledPref, true);

    var notFound = $("updates-noneFound");
    var updated = $("updates-installed");
    // Avoid getting false results from the past update check (may not be required for "noneFound")
    notFound.hidden = updated.hidden = true;

    $("cmd_findAllUpdates").doCommand();

    var waitTimer = setInterval(function() {
        if(!doc.defaultView || doc.defaultView.closed) {
            stopWait();
            notify("Tab with add-ons manager was closed!");
            return;
        }
        if(!inProgress.hidden)
             return;
        var autoUpdate = $("utils-autoUpdateDefault");
        var autoUpdateChecked = autoUpdate.getAttribute("checked") == "true";

        var found = $("updates-manualUpdatesFound-btn");
        if(
            autoUpdateChecked
                ? notFound.hidden && updated.hidden
                : notFound.hidden && found.hidden
        ) // Too early?
            return;

        stopWait();
        if(!tbTab)
            tab.closing = false;
        function removeTab() {
            if(!tab.collapsed)
                return;
            if(tbTab)
                tabmail.closeTab(tbTabInfo, true /*aNoUndo*/);
            else {
                gBrowser.removeTab(tab);
                (function forgetClosedTab(isSecondTry) {
                    var ss = "nsISessionStore" in Components.interfaces
                        ? (
                            Components.classes["@mozilla.org/browser/sessionstore;1"]
                            || Components.classes["@mozilla.org/suite/sessionstore;1"]
                        ).getService(Components.interfaces.nsISessionStore)
                        : SessionStore; // Firefox 61+ https://bugzilla.mozilla.org/show_bug.cgi?id=1450559
                    if(!("forgetClosedTab" in ss))
                        return;
                    var closedTabs = JSON.parse(ss.getClosedTabData(window));
                    for(let i = 0, l = closedTabs.length; i < l; ++i) {
                        let closedTab = closedTabs[i];
                        let state = closedTab.state;
                        if(state.entries[state.index - 1].url == ADDONS_URL) {
                            ss.forgetClosedTab(window, i);
                            return;
                        }
                    }
                    if(!isSecondTry) // May be needed in SeaMonkey
                        setTimeout(forgetClosedTab, 0, true);
                })();
            }
        }

        if(!updEnabled)
            Services.prefs.setBoolPref(updEnabledPref, false);

        if(!notFound.hidden) {
            removeTab();
            notify(notFound.getAttribute("value"));
            return;
        }
        if(autoUpdateChecked) {
            removeTab();
            notify(updated.getAttribute("value"));
            return;
        }

        tab.collapsed = false;
        $("categories").selectedItem = $("category-availableUpdates");
        var tabWin = tab.ownerDocument.defaultView;
        if(tbTab)
            tabmail.switchToTab(tbTabInfo);
        else
            tabWin.gBrowser.selectedTab = tab;
        setTimeout(function() {
            tabWin.focus();
            doc.defaultView.focus();
            $("addon-list").focus();
        }, 0);
    }, 50);
    function $(id) {
        return doc.getElementById(id);
    }
    function stopWait() {
        clearInterval(waitTimer);
        progressIcon.restore();
        btn.tooltipText = tip;
        if(tab.image == image)
            tab.image = origIcon;
        trgWindow.removeEventListener("TabSelect", dontSelectHiddenTab, false);
        setTimeout(function() {
            delete btn._cb_disabled;
        }, 500);
    }
    function notify(msg) {
        Components.classes["@mozilla.org/alerts-service;1"]
            .getService(Components.interfaces.nsIAlertsService)
            .showAlertNotification(
                Services.appinfo.name == "Firefox" && parseFloat(Services.appinfo.version) >= 57
                    ? "chrome://mozapps/skin/extensions/extensionGeneric.svg"
                    : "chrome://mozapps/skin/extensions/extensionGeneric.png",
                btn.label,
                msg, false, "", null
            );
    }
}
function dontSelectHiddenTab(e) {
    // <tab /><tab collapsed="true" />
    // Close first tab: collapsed tab becomes selected
    var trgTab = e.originalTarget || e.target;
    if(trgTab != tab)
        return;

    if(/\n(?:BrowserOpenAddonsMgr|toEM)@chrome:\/\//.test(new Error().stack)) {
        // User open Add-ons Manager, show tab
        trgWindow.removeEventListener("TabSelect", dontSelectHiddenTab, false);
        setTimeout(function() { // Hidden tab can't be selected, so select it manually...
            tab.collapsed = tab.closing = false;
            gBrowser.selectedTab = tab;
        }, 0);
    }

    function done(t) {
        if(!t.hidden && !t.closing) {
            e.preventDefault();
            e.stopPropagation();
            return gBrowser.selectedTab = t;
        }
        return false;
    }
    for(var t = tab.nextSibling; t; t = t.nextSibling)
        if(done(t))
            return;
    for(var t = tab.previousSibling; t; t = t.previousSibling)
        if(done(t))
            return;
}
function ProgressIcon(btn) {
    if(!(btn instanceof XULElement)) {
        this.loading = this.restore = function() {};
        return;
    }
    var app = Services.appinfo.name;
    var pv = parseFloat(Services.appinfo.platformVersion);
    if(app == "SeaMonkey")
        this.imgConnecting = this.imgLoading = "chrome://communicator/skin/icons/loading.gif";
    else if(app == "Thunderbird") {
        this.imgConnecting = "chrome://messenger/skin/icons/connecting.png";
        this.imgLoading = "chrome://messenger/skin/icons/loading.png";
    }
    else {
        this.imgConnecting = "chrome://browser/skin/tabbrowser/connecting.png";
        this.imgLoading = app == "Firefox" && pv >= 48
            ? "chrome://global/skin/icons/loading.png"
            : "chrome://browser/skin/tabbrowser/loading.png";
    }
    var useAnimation = app == "Firefox" && pv >= 32;
    var btnIcon = btn.ownerDocument.getAnonymousElementByAttribute(btn, "class", "toolbarbutton-icon")
                    || btn.getElementsByClassName("toolbarbutton-icon")[0];
    var origIcon = btnIcon.src;
    btnIcon.src = this.imgConnecting;
    if(useAnimation) {
        let cs = btnIcon.ownerDocument.defaultView.getComputedStyle(btnIcon, null);
        let s = btnIcon.style;
        s.margin = [cs.marginTop, cs.marginRight, cs.marginBottom, cs.marginLeft].join(" ");
        s.padding = [cs.paddingTop, cs.paddingRight, cs.paddingBottom, cs.paddingLeft].join(" ");
        s.width = cs.width;
        s.height = cs.height;
        s.boxShadow = "none";
        s.borderColor = s.background = "transparent";
        btnIcon.setAttribute("fadein", "true");
        btnIcon.setAttribute("busy", "true");
        btnIcon.classList.add("tab-throbber");
        btnIcon._restore = function() {
            delete btnIcon._restore;
            btnIcon.removeAttribute("busy");
            btnIcon.removeAttribute("progress");
            setTimeout(function() {
                btnIcon.classList.remove("tab-throbber");
                btnIcon.removeAttribute("style");
                btnIcon.removeAttribute("fadein");
            }, 0);
        };
    }
    this.loading = function() {
        btnIcon.src = this.imgLoading;
        if(useAnimation)
            btnIcon.setAttribute("progress", "true");
    };
    this.restore = function() {
        btnIcon.src = origIcon;
        if(useAnimation)
            btnIcon._restore();
    };
}
}).call(this);
//== Check for Addons Updates end
}


this.tooltipText = "Переключатель джетпаков" 
                   + "\n\nУправление:\nЛКМ – открыть меню" 
                   + "\nПКМ – проверить обновления"
                   + "\nСКМ – открыть страницу дополнений"
                   + "\nShift+ПКМ – меню кнопки"
                   + "\n\nВ меню: \nЛКМ – включить/выключить дополнение"
                   + "\nShift+ЛКМ – включить/выключить дополнение без закрытия меню"   
                   + "\nСКМ – открыть страницу дополнения в управлении дополнениями"                    
                   + "\nПКМ – открыть настройки дополнения (если есть)";    


и если не сложно как сделать autopopup на эту кнопку
скрытый текст

Выделить код

Код:

(async obj => {
    Services.search.isInitialized || await Services.search.init();
    obj.observe();  
    this._handleClick = () => obj.menupopup.openPopup(this);
    var topic = "browser-search-engine-modified";
    Services.obs.addObserver(obj, topic, false);
    addDestructor(() => Services.obs.removeObserver(obj, topic));
    if (!obj.excludeHiddenOneOffs) return;
    var obs = () => obj.upd = true;
    Services.prefs.addObserver(obj.pref, obs);
    addDestructor(() => Services.prefs.removeObserver(obj.pref, obs));
})({
    excludeHiddenOneOffs: false,

    get menupopup() {
        this.upd && this.rebuild();
        return this.popup;
    },
    get popup() {
        var popup = self.appendChild(document.createXULElement("menupopup"));
        popup.setAttribute("context", "");
        popup.setAttribute("position", "after_start");
        popup.setAttribute("oncommand", "Services.search.defaultEngine = event.target.engine");
        delete this.popup; return this.popup = popup;
    },
    async rebuild() {
        this.popup.textContent = "";
        var df = document.createDocumentFragment();
        var de = Services.search.defaultEngine.wrappedJSObject, jsde = this.json(de);
        if (this.excludeHiddenOneOffs)
            var ex = Services.prefs.getStringPref(this.pref, "").split(",");
        var check = true;
        for(var engine of await Services.search.getVisibleEngines()) {
            if (check && engine.name == de.name && this.json(engine) == jsde) {
                check = false; continue;
            }
            if (this.excludeHiddenOneOffs && ex.includes(engine.name)) continue;
            var menuitem = df.appendChild(document.createXULElement("menuitem"));
            menuitem.engine = engine;
            menuitem.label = engine.name;
            menuitem.image = this.img(engine);
            menuitem.className = "menuitem-iconic";
        }
        this.upd = this.popup.append(df);
    },
    observe() {
        var engine = Services.search.defaultEngine;
        (self.icon || document.getAnonymousElementByAttribute(
            self, "class", "toolbarbutton-icon"
        )).src = this.img(engine);
        self.tooltipText = engine.name;
        this.upd = true;
    },
    pref: "browser.search.hiddenOneOffs",
    json: e => JSON.stringify(e.toJSON()),
    img: e => e.iconURI ? e.iconURI.spec : "chrome://browser/skin/search-engine-placeholder.png"
});


[firefox] 72.0.1

Отредактировано egorsemenov06 (20-01-2020 15:27:26)

Отсутствует

 

№1409620-01-2020 22:13:35

solombala
Участник
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 350
UA: Firefox 70.0

Re: Custom Buttons

Отсутствует

 

№1409721-01-2020 07:43:17

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 1072
UA: Firefox 52.0

Re: Custom Buttons

egorsemenov06 пишет:

не гляните вот эту кнопку в ней не работает правый клик проверка обновлений доролнений

Не, не моя тема, совсем. Но можно приглядывать за страницей
Check_for_Addons_Updates, прогресс возможен, наверно.

egorsemenov06 пишет:

сделать autopopup на эту кнопку

Хорошо, попробую

скрытый текст

Выделить код

Код:

(async obj => {
    Services.search.isInitialized || await Services.search.init();
    obj.observe();
    this.type = "menu";
    obj.popup = this.appendChild(document.createXULElement("menupopup"));
    addEventListener("popupshowing", obj, false, obj.popup);

    // https://github.com/Infocatcher/Custom_Buttons/blob/master/code_snippets/autoOpenCloseMenu.js
    // Automatically open menu on mouse over (and hide it on mouse out)

    //=======[ Start Autoopen/close feature ]=======
    var openDelay = 200;
    var closeDelay = 350;

    var _openTimer = 0;
    var _closeTimer = 0;
    this.onmouseover = function(e) {
        clearTimeout(_closeTimer);
        if(e.target == this && closeOtherMenus()) {
            this.open = true;
            return;
        }
        _openTimer = setTimeout(function() {
            self.open = true;
        }, openDelay);
    };
    this.onmouseout = function(e) {
        clearTimeout(_openTimer);
        _closeTimer = setTimeout(function() {
            if(!isContextOpened())
                self.open = false;
        }, closeDelay);
    };
    function closeOtherMenus() {
        return Array.prototype.some.call(
            self.parentNode.getElementsByTagName("*"),
            function(node) {
                if(
                    node != self
                    && node.namespaceURI == xulns
                    // See https://github.com/Infocatcher/Custom_Buttons/issues/28
                    //&& node.boxObject
                    //&& node.boxObject instanceof Components.interfaces.nsIMenuBoxObject
                    && "open" in node
                    && node.open
                    && node.getElementsByTagName("menupopup").length
                ) {
                    node.open = false;
                    return true;
                }
                return false;
            }
        );
    }
    function isContextOpened() {
        return inBtn(document.popupNode);
    }
    function inBtn(node) {
        for(; node; node = node.parentNode)
            if(node == self)
                return true;
        return false;
    }
    //=======[ End Autoopen/close feature ]=======

    var topic = "browser-search-engine-modified";
    Services.obs.addObserver(obj, topic, false);
    addDestructor(() => Services.obs.removeObserver(obj, topic));
    if (!obj.excludeHiddenOneOffs) return;
    var obs = () => obj.upd = true;
    Services.prefs.addObserver(obj.pref, obs);
    addDestructor(() => Services.prefs.removeObserver(obj.pref, obs));
})({
    excludeHiddenOneOffs: false,

    handleEvent() {
        var {popup} = this;
        popup.setAttribute("context", "");
        popup.setAttribute("position", "after_start");
        popup.setAttribute("oncommand", "Services.search.defaultEngine = event.target.engine");
        (this.handleEvent = () => this.upd && this.rebuild())();
    },
    async rebuild() {
        this.popup.textContent = "";
        var df = document.createDocumentFragment();
        var de = Services.search.defaultEngine.wrappedJSObject, jsde = this.json(de);
        if (this.excludeHiddenOneOffs)
            var ex = Services.prefs.getStringPref(this.pref, "").split(",");
        var check = true;
        for(var engine of await Services.search.getVisibleEngines()) {
            if (check && engine.name == de.name && this.json(engine) == jsde) {
                check = false; continue;
            }
            if (this.excludeHiddenOneOffs && ex.includes(engine.name)) continue;
            var menuitem = df.appendChild(document.createXULElement("menuitem"));
            menuitem.engine = engine;
            menuitem.label = engine.name;
            menuitem.image = this.img(engine);
            menuitem.className = "menuitem-iconic";
        }
        this.upd = this.popup.append(df);
    },
    observe() {
        var engine = Services.search.defaultEngine;
        (self.icon || document.getAnonymousElementByAttribute(
            self, "class", "toolbarbutton-icon"
        )).src = this.img(engine);
        self.tooltipText = engine.name;
        this.upd = true;
    },
    pref: "browser.search.hiddenOneOffs",
    json: e => JSON.stringify(e.toJSON()),
    img: e => e.iconURI ? e.iconURI.spec : "chrome://browser/skin/search-engine-placeholder.png"
});


solombala пишет:

Может знаете...?

WFM

Отсутствует

 

№1409821-01-2020 09:19:15

solombala
Участник
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 350
UA: Firefox 72.0

Re: Custom Buttons

Dumby

Dumby пишет:

WFM

Это что ? Радио-УКВ ? Кстати, странно эта 72 ведет, после очистки профиля , кэша запуска и т.д. Зависает прилично...

Отредактировано solombala (21-01-2020 09:23:38)

Отсутствует

 

№1409921-01-2020 11:16:23

egorsemenov06
Участник
 
Группа: Members
Зарегистрирован: 12-06-2018
Сообщений: 91
UA: Firefox 72.0

Re: Custom Buttons

Dumby

СПАСИБО!
посмотрите пожалуйста еще кнопку в ней в консоли выдает ошибку   NS_ERROR_FILE_NOT_FOUND: Component returned failure code: 0x80520012 (NS_ERROR_FILE_NOT_FOUND) [nsIProcess.init]

скрытый текст

Выделить код

Код:

// Запустить QTranslate и жмакнуть(программно) дважды CTRL(код Dumby)
// - стандартн. комбин. для захвата текста из окна в QTranslate.
// интервал можно увеличить или уменьшить, зависит от железа  
 setTimeout(dblCtrlSend, 100);
 quickTranslate();

 // ----------------------------------- =  QuickTranslate  = ----------------------------------------------
   function quickTranslate() {
//  скопировать выделенный текст в буфер. 
//       gClipboard.write(document.commandDispatcher.focusedWindow.getSelection().toString());
     var profile = Services.dirsvc.get('ProfD', Ci.nsIFile);
     profile.initWithPath(profile.path + "\\_QTranslate\\QTranslate.exe");
      var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
      var arg = [];
   process.init(profile);
   process.run(false, [arg], 1);
//   setTimeout(function() window.content.focus(), 500);
   };


function dblCtrlSend() {

// See https://gist.github.com/Noitidart/0de3be2442a0295eb386
// vk codes: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx

// Double Ctrl [Ctrl-Down, Ctrl-Up, Ctrl-Down, Ctrl-Up]
var data = [[0x11, false], [0x11, true], [0x11, false], [0x11, true]];

// Ctrl+Q [Ctrl-Down, Q-Down, Q-Up, Ctrl-Up]
//var data = [[0x11, false], [0x51, false], [0x51, true], [0x11, true]];

var {ctypes} = Cu.import("resource://gre/modules/ctypes.jsm", {});
var KEYBDINPUT = ctypes.StructType("tagKEYBDINPUT", [
    {wVk: ctypes.unsigned_short},
    {wScan: ctypes.unsigned_short},
    {dwFlags: ctypes.unsigned_long},
    {time: ctypes.unsigned_long},
    {dwExtraInfo: ctypes.voidptr_t.size == 8 ? ctypes.uint64_t : ctypes.unsigned_long},
    {padding0: ctypes.uint8_t.array(8)}
]);
var INPUT = ctypes.StructType("tagINPUT", [{type: ctypes.unsigned_long}, {ki: KEYBDINPUT}]);
var pInputs = INPUT.array()(data.map(([vkCode, keyup]) => 
    INPUT(1, KEYBDINPUT(vkCode, 0, keyup ? 2 : 0, 0, 0, ctypes.uint8_t.array(8)()))
));
var user32 = ctypes.open("user32"); try {
    var SendInput = user32.declare("SendInput", ctypes.winapi_abi, ctypes.unsigned_int, ctypes.unsigned_int, INPUT.ptr, ctypes.int);
    SendInput(pInputs.length, pInputs, INPUT.size);
 } finally {
    user32.close();
 }
};


и в этой кнопке   TypeError: gURLBar.reset is not a function
инициализация
скрытый текст

Выделить код

Код:

// Настройка функций кликов мыши для кнопки ...........
this.onclick =e=> {
   if ( e.button == 0 ) gBrowser.selectedTab = gBrowser.addTrustedTab(notepad); // открыть блокнот    
     
   if ( e.button == 1 ) {  
        // запомнить текст из буфера обмена и скопировать текст на странице
        var clip = gClipboard.read();
        window.content.focus();
        goDoCommand("cmd_copy");            

        // открыть блокнот и вставить текст из буфера обмена
        var browser = gBrowser.getBrowserForTab(gBrowser.selectedTab = gBrowser.addTrustedTab(notepad)); 
        browser.addEventListener("pageshow", function c(e) {      
           this.removeEventListener(e.type, c);           

           setTimeout(()=> {              
              content.document.getElementsByTagName("textarea")[0].value = gClipboard.read();
              clip && gClipboard.write(clip); // вернуть текст в буфер обмена 
           }, 50);      
        });       
        };
};


// Обновить блокнот в текущей вкладке после обновления кнопки ...........
if ( gBrowser.currentURI.spec == notepad ) {
     var val = content.document.getElementsByTagName("textarea")[0].value;
     loadURI(notepad);
     setTimeout(()=> content.document.getElementsByTagName("textarea")[0].value = val, 500);     
     };

        
// Очистить адресную строку в кладке блокнота ...........
addEventListener("TabAttrModified", ()=> gBrowser.currentURI.spec == notepad && gURLBar.reset());


// Получаем адрес блокнота как base64 из вкладки Справка и добавляем иконку для вкладки блокнота ...........
var notepad = "data:text/html;base64," + window.btoa(self.getAttribute('Help').replace('selfImage', self.image));


// Подсказка у кнопки ...........
this.tooltipText = "Блокнот в вкладке \nЛ: Открыть блокнот \nС: Открыть блокнот с текстом( выделенным или из буфера ) \nП: CB меню";


Справка
скрытый текст

Выделить код

Код:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>Notepad</title>
<head>
 <link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAgAAAAApKSlRRkZGh0BAQHxBQUF+QUFBfkFBQX5BQUF+QEBAfEZGRogaGho1AAAAAAABAAECAgICAgICAgQEBAUAAAAAMTEwWeLi4f//////+vr6//r6+v/6+vr//Pz8//v7+//5+fn++/v7/7CwsPdNTU2hAQEBAgAAAAAAAAAAAwMDBAAAAABvbm+x8vHy/+Df4Pfi4+P76ubr++Lh4vvk5OT7/f39+/////v////77/Dv/aysrP8BEAElKngnxDCDLdEvgSzOLX8qy0GTPu1Zq1b/WatW/lasU/9op2f/xcPF/8PEw//i5+L/8vfx//H27//p6+n/qqqq/ESaQOS67a7/teip/rbpqv+36qv/suSm/6zfoP+s36D/teOo/4bNfP93s3b/39bf/9XY1f/5/Pj/+Pv2/+vs6/+qqar/T6RK8bvjsP6t2qT8sNym/LDcpvyx3af+st6o/7LeqP+w3ab/vuaz/1mqVP+2w7b/3dvd//D07//4+/f/6+zr/6qqqv8BNwFvndiU/8Djt/y34a//ueGw/7nhsP+54bD/ueGw/7jgr//B5Lj/mtSS/3q1ev/WzNb/4ufh//f79f/p6+n/qqqq/wAAAANHk0Pbzu/F/73gtP3A47f/wOO3/8Djt//A47f/wOO4/73itf/D5rn/Y7Je/7/MwP/k4eP/+f35/+vs6/+qqqr/AAAAAAAzAGap4KP/zebG+8Tkvv/G5b//xuS//8blv//F5b7/vuK2/8LkuP+U0Yv/ZaBl/97W3v/u9e3/6+3r/6qqqv8DAQMAAAAABE6XS+Db8dT/yuPD/czmxv/N5sf/zObG/8blv//A47j/t+Cu/7vjsP9nuWP/uMW5/+zr6//s7+z/qamq/wACAAQAAAAAATQBZrTir//a6dX70ufN/9Pozv/N5sf/xuS//8Djt/+44K//u+Ow/4zNgv9uqW7/6+Tr/+ru6v+qqar/AAAAAQMBAwAAAAAHVJhS2Or25v/W59L91OjP/8zmxv/G5b//wOO3/7rhsP+w3ab/tuSp/1isU/+vva//6+rq/6qqqv8AAAAAAQIBAwAAAAAENQRkv+S7/+Pr3vvR58z/zObG/8bkv/+/4rf/ueCw/7Hep/+z4Kf/h818/3Kucv/r4uv/qKqo/gAAAAAAAAABAwEDAAAAAApVl1TU7Pbo/9HlzP3P58j/xuS//8Ljuf+64bH/s9+p/6vcoP+t4KD/Wq5U/8bSx/23tLf9AAAAAAAAAAABAgEDAAAAAAk3CWaq36b/1unR+cLjvPzF5r78t+Cv/LXgrP2w36b8odmW/Kzgn/1yxGf7gLKA/52Sne0AAAAAAAAAAAAAAAECAQIAAAEADUOCQcdwt23/Zati82GrXvVjrWD4XKlY9FqpVvZaqlX3UqZN81OnTvxYbFndGxcbNAAAAAAAAAAAAAAAAAABAQEAAAAAFBAUHTAzMGcqKipRJSclUS8wL14nJyZNKCspVy4uLlsiJCJKNjU2aQQABAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="type="image/x-icon">
</head>

<TEXTAREA></TEXTAREA>
<style>

html {
  background-color: #696969;
  overflow: hidden;
}
textarea {
  background: white;
  overflow-y: auto;
  width: 100%;
  height: 100%;
  border-radius: 2px;
  border: 2px inset #170202;
  color: black;
}
</style>


[firefox] 72.0.2

Отредактировано egorsemenov06 (21-01-2020 21:46:45)

Отсутствует

 

№1410021-01-2020 12:01:07

sonyas75
Участник
 
Группа: Members
Откуда: Ставрополь
Зарегистрирован: 22-03-2011
Сообщений: 385
UA: Firefox 72.0

Re: Custom Buttons

ничего не понимаю, поэтому вопрос, вот такой код работает в принципе?

Выделить код

Код:

addEventListener("click", function(e) {
   if ( e.button == 0 && e.target.nodeName == "tab" ) BrowserReload();
}, true, gBrowser.mTabContainer );

у меня не фурычит, а хотелось бы :blush:

На форуме

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2011 Mozilla Russia
Язык отображения форума: [Русский] [English]