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

В мире Mozilla происходит много интересных событий. Но вам не нужно постоянно посещать новостные сайты, чтобы быть в курсе всех изменений. Зайдите на ленту новостей Mozilla Россия.

№1407617-01-2020 23:56:12

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

Re: Custom Buttons

func4ptch4
Это куда?

Отсутствует

 

№1407718-01-2020 03:22:21

func4ptch4
Участник
 
Группа: Members
Зарегистрирован: 03-05-2018
Сообщений: 220
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
Сообщений: 1160
UA: Firefox 56.0

Re: Custom Buttons

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

скрытый текст
122.gif

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

Отсутствует

 

№1407918-01-2020 11:02:36

solombala
Забанен
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 652
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
Сообщений: 1750
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
Сообщений: 2129
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
Сообщений: 1728
UA: Firefox 52.0

Re: Custom Buttons

Dumby пишет

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

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

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


Win7

Отсутствует

 

№1408318-01-2020 20:07:53

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

Re: Custom Buttons

Dumby пишет

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

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

Отсутствует

 

№1408418-01-2020 20:18:18

solombala
Забанен
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 652
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
Сообщений: 559
UA: Firefox 68.0

Re: Custom Buttons

solombala
А как бы убрать лишнее вот такое окно при сохранении  "Сохранить всю страницу или выбранное как HTML"
В кнопке Save, от 07.03.2017
4baada21edf8e71cdd55757dd99733c6.png

Отсутствует

 

№1408618-01-2020 21:42:14

solombala
Забанен
 
Группа: Members
Зарегистрирован: 20-07-2019
Сообщений: 652
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
Сообщений: 559
UA: Firefox 68.0

Re: Custom Buttons

solombala пишет

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

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

Отсутствует

 

№1408818-01-2020 23:09:36

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
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
Сообщений: 1728
UA: Firefox 52.0

Re: Custom Buttons

Dumby пишет

Код:

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


Код:

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

Понятно!


Win7

Отсутствует

 

№1409019-01-2020 14:03:29

func4ptch4
Участник
 
Группа: Members
Зарегистрирован: 03-05-2018
Сообщений: 220
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
Сообщений: 652
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
Сообщений: 1728
UA: Firefox 52.0

Re: Custom Buttons

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

скрытый текст
17237f6eff56.png

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


Win7

Отсутствует

 

№1409319-01-2020 20:14:26

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
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
Сообщений: 1728
UA: Firefox 52.0

Re: Custom Buttons

Dumby
Благодарю!


Win7

Отсутствует

 

№1409520-01-2020 14:25:36

egorsemenov06
Участник
 
Группа: Members
Зарегистрирован: 12-06-2018
Сообщений: 378
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
Сообщений: 652
UA: Firefox 70.0

Re: Custom Buttons

Отсутствует

 

№1409721-01-2020 07:43:17

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
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
Сообщений: 652
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
Сообщений: 378
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
Сообщений: 557
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–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]