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

Список ответов на каверзные вопросы можно получить в FAQ-разделе форума.

№1487605-08-2020 08:58:53

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 476
UA: Firefox 56.0

Re: Custom Buttons

Dumby - привет! Доработал кнопку (возможно твоего авторства), но получаю ошибку при использовании многострочной подсказки в параметрах, подробно расписал в коде…
код приготовлен для быстрой проверки. При запуске кнопки сразу видны два варианта меню переключения.
в кнопке 2 удобных меню переключения опций Firefox. (проверял на Waterfox)

Хотел сделать многострочные подсказки, но не получилось. ОШИБКА видна в строке меню: «Прокси (многострочная подсказка)» —
основной пункт меню всегда «Other», хотя должен подставляться, исходя из параметра в strValues:localhost+"\n МНОГОСТРОЧНАЯ ПОДСКАЗКА,,,отключен…,,,0|||…

экспортированная кнопка

Отсутствует

 

№1487705-08-2020 10:11:38

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

Re: Custom Buttons

Dumby
Блокировки хороши, но со storage пришлось поработать..

Отсутствует

 

№1487805-08-2020 12:22:39

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

Re: Custom Buttons

Dobrov пишет

основной пункт меню всегда «Other», хотя должен подставляться

Ну так smval и smVal это не одно и то же.
И вообще, как-то многословно, на мой вкус.

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

Выделить код

Код:

`
		if (subMenu) {
			for (var smitem of subMenu.getElementsByTagName('menuitem')) {
				var smval = smitem.getAttribute('tooltiptext');
				smVal = smVal.replace(/\n.*/g,''); // оставить только первую строку
				smitem.setAttribute('checked', (val === smval) ? true : false);
			}
		}
`;
		if (subMenu) for(var smitem of subMenu.getElementsByTagName("menuitem"))
			smitem.setAttribute("checked", smitem.getAttribute("tooltiptext").replace(/\n.*/g, "") == val);


Вау, кнопка регистрирует в _handlers 103 (сто три!) листенера. Жесть.

Отсутствует

 

№1487905-08-2020 13:26:09

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 606
UA: Firefox 52.0

Re: Custom Buttons

Dumby пишет

Ну да, я же говорю — бесполезно :).

Ладно, бог с ним.
Просто мне попадалось пару-тройку скриптов для "обезьяны", которые подменяют все ссылки на странице с youtube на invidio налету.
Вот и подумал, что можно сделать нечто подобное, но только по клику.


Мне Vitaliy V. подогнал дополнение, в котором можно настроить почти любой редирект.
Но я не любитель большого количества дополнений, и по возможности сначала пытаюсь реализовать нужный мне функционал с помощью СВ или Tampermonkey.
Раз, в этом случае, не получается, то поставлю дополнение.


Спасибо за помощь!


«The Truth Is Out There»

Отсутствует

 

№1488005-08-2020 19:00:45

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

Re: Custom Buttons

Dumby
Вот теперь уже кое-что. Это после авторизации на ютуб...Storage - пуст...
twgiorun.jpg
А это сам storage - три папки , но они пусты(хотя аддонов, как грязи)....Класс !
62aeoofv.jpg

Отредактировано solombala (05-08-2020 19:01:35)

Отсутствует

 

№1488106-08-2020 09:16:14

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

Re: Custom Buttons

egorsemenov06 пишет

Можно Вас попросить пожалуйста сделать для user_chrome_files кнопку Proxy

Разве что отдельным файлом.
Инициализацию в Proxy.js, а в custom_script.js

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

Выделить код

Код:

try {CustomizableUI.createWidget({
	label: "Proxy",
	image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAQAAAAAIAAYOQAAWJ2kADh1fAAAEKAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgICAgICAgICAgMBAQEAAAEEJBE4ULQ+fZ38ea/H/muhuv8gW3ztAxclewAAAAsAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEBAAAAAAMLNlO7PH+n/3Sgu/281eP9zuHr/mWZuP4XXon/ABAeZwAAAAAAAAAAAQEBAQAAAAAZGBoTKScsLyYkKjErJSgnIC8/XgZQgP9BcZb8b5q3/oiux/+qx9r/a5Ow+zFtlv8PRWrGAAACAAEBAQMHBwcbAAAAD2BeYn769/3/4eDm/Onh5v+DnrX/A0t9/j1vlv+FqMH/lrfN/7rS4f9+pL3+M26X/xJYhu0DEiMdAAAAAAEBAQEAAAABBgUGEaSiprbPzNP239fb/4OcsP4aXYr/RHOZ/5Gwx//T5e//mrjO/3KYtv40apP/D0x77AUTIhwhHyMmeXV7mXt4fqJ3dHmce3d+n6eirODMx8r/o6q3/kN4nf92m7n/vtPj/9Hg7P/C1OL/eJq1+jtulv8bSnC7AAEGAF1aYH7//////f39/P//////////////////////////lbHC/3ilvf/K4Oz/2OXv/7nN3f6FqcP/VIiv/AseMT8AAAAAXFtef+LY5/+AT534fU2d+4VXovyKXaf+jGGp/5BlrP+GWKT/ZmGc/4Cduf+ivtD+k7HH/1t/neUTJjhFAAAAAAEBAQJfXmB/3tHl/14giPxcIYr/Zy+S/244mP9yPZv/cj6c/3M9nP9wNpf/YDSP/1k0ivu7tdP/YmNmiAAAAAAEBAQGAAAAAF9eYIDg1Ob/cDqV/HE9mv9/TaT/hler/4tdr/+NXrD/iFms/4JTqP9+SqP/cjqW+9zJ4/9ubW6JAAAAAAMDBAQAAAAAX15ggODU5v94RZz8e0mi/4pcrv+Vabf/nXO9/6J5wf+jfMH/oXq//513u/+NY6z718bh/2pqa4gAAAAABAMEBAAAAABfXWCA4NTm/4VWpfyPY7L/onvA/7GPzP+8ndT/waTY/8Cj1/+6nNL/tZfO/6F9uvvYx+L/ampriAAAAAAEAwQEAAAAAF9eYH/e0uX/n3u5/LKTzP/Bpdf/zrbh/9jC6f/bxuv/2cTp/9O+5P/Qu+H/uJ3L+9jI4f9qaWuHAAAAAAQDBAQAAAAAX15gf97S5P+gfbf5sZPH/LqdzfzCqNT8ybHZ/My12vzKs9n8xq/W/Mav1fywksL418fh/2tqbIkAAAAABAMEBAAAAABZVlt3+fX8/+DU5vzj1un/5tvt/+ne7//r4PH/6t7w/+fb7f/k2Ov/4dPn/9nM4Pv79v//ZGFnfwAAAAADAwQEAAAAABcVGRpZVlt6YF9hgWBgYoBhYWKAYmFigGJiY4BiYmOAYmFigGFhYoBgYGGAX15ggF1aX4AbGR0eAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
	id: "ucf-cbbtn-Proxy",
	localized: false,
	get initCode() {
		delete this.initCode;
		return this.initCode = Cu.readUTF8URI(Services.io.newURI(
			"chrome://user_chrome_files/content/custom_scripts/Proxy.js"
		));
	},
	cbu: {
		128: "Bool", boolean: "Bool",
		64: "Int", number: "Int",
		32: "String", string: "String",

		getPrefs(pref) {
			try {return Services.prefs[`get${
					this[Services.prefs.getPrefType(pref)]
			}Pref`](pref);}
			catch {return null;}
		},
		setPrefs(pref, val) {
			Services.prefs[`set${this[typeof val]}Pref`](pref, val);
		}
	},
	addDestructor(destructor, context) {
		this._destructors.push({destructor, context});
	},
	addEventListener(...args) {
		var trg = args[3];
		if (!trg) trg = args[3] = this.ownerGlobal;
		trg.addEventListener(...args);
		this._handlers.push(args);
	},
	async onCreated(btn) {
		var win = btn.ownerGlobal;
		btn._handlers = new win.Array();
		btn._destructors = new win.Array();
		win.addEventListener("unload", this, {once: true});
		await new Promise(resolve => win.requestAnimationFrame(resolve));
		btn.image = this.image;
		new win.Function(
			"self,addDestructor,cbu,addEventListener,xulns", this.initCode
		).call(
			btn, btn, this.addDestructor.bind(btn),
			this.cbu, this.addEventListener.bind(btn),
			"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
		);
	},
	handleEvent(e) {
		var btn = e.target.getElementById(this.id);
		for(var args of btn._handlers)
			args.pop().removeEventListener(...args);
		delete btn._handlers;
		for(var {destructor, context} of btn._destructors)
			try {destructor.call(context, "destructor");}
			catch(ex) {Cu.reportError(ex);}
		delete btn._destructors;
	}
});} catch(ex) {Cu.reportError(ex);}

Отсутствует

 

№1488207-08-2020 00:14:32

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 476
UA: Firefox 56.0

Re: Custom Buttons

Dumby пишет

Вау, кнопка регистрирует в _handlers 103 (сто три!) листенера. Жесть.

Dumby, в QuickSettings всего 26 пунктов меню и 9 горячих клавиш.
Откуда лишние листенеры? Можно как-то исключить создание ненужных?
То есть, сделать, чтобы в подменюшках подставлялись значения из about:config , но без лишних addEventListener ?

Отредактировано Dobrov (07-08-2020 13:08:16)

Отсутствует

 

№1488307-08-2020 03:05:34

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 606
UA: Firefox 52.0

Re: Custom Buttons

DEL

Отредактировано unter_officer (07-08-2020 04:06:30)


«The Truth Is Out There»

Отсутствует

 

№1488407-08-2020 13:53:13

Duche
Участник
 
Группа: Members
Зарегистрирован: 07-02-2016
Сообщений: 209
UA: unknown 0.0

Re: Custom Buttons

Добрый день. Посмотрите пожалуйста, может у кого ест в закромах кнопка  "Восстановить закрытую вкладку", сколько нажатий на кнопку  столько "восстановленный" , по порядку  закрытия , начиная с первой ,штук 8 вкладок. Заранее спасибо.

Отредактировано Duche (07-08-2020 13:54:31)

Отсутствует

 

№1488507-08-2020 14:01:10

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 606
UA: Firefox 52.0

Re: Custom Buttons

Duche.

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

Выделить код

Код:

/*Initialization Code*/

this.onclick = function(e) {
  if ( e.button == 0 ) {
    e.preventDefault();
    undoCloseTab();
  }
};


«The Truth Is Out There»

Отсутствует

 

№1488607-08-2020 14:06:19

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

Re: Custom Buttons

Dobrov пишет

Смотрю капс-V опечатка не исправлена.
Почему? Я что-то непонятное написал?

Откуда лишние листенеры?

Что значит откуда? Так сделано.
Да, 26 пунктов меню (плюс 7 сепараторов) каждый из которых
рождён функцией CreateMenu, которая регистрирует в _handlers
по три листенера на события command, popupshowing, contextmenu.
Уже 99, мало что ли?

Можно как-то исключить создание ненужных?
То есть, сделать, чтобы в подменюшках подставлялись значения из about:config , но без лишних addEventListener ?

Разумеется можно. Один обработчик на кнопку, регистрация
на эти три события, обработка событий в зависимости от target.
Но так перелопатить этот комбайн наверно непросто.


P.S. Заметил в кнопке интригующий комментарий:
«ЗАДАЧА 2: невозможно создать подменю с произвольными строками: меню > checkbox1, checkbox2, разделитель, radio1, radio2»
Никакая конечно не задача, а просто утверждение, однако
не отказался бы посмотреть какой-нибудь синтетический
отдельный демо-код, его доказывающий, а то, со стороны,
в таком виде, утверждение выглядит абсурдно.

Отсутствует

 

№1488707-08-2020 15:33:21

Duche
Участник
 
Группа: Members
Зарегистрирован: 07-02-2016
Сообщений: 209
UA: unknown 0.0

Re: Custom Buttons

unter_officer пишет

unter_officer

Спасибо большое , то, что надо.

Отсутствует

 

№1488808-08-2020 08:55:11

firepox
Участник
 
Группа: Members
Зарегистрирован: 17-11-2011
Сообщений: 358
UA: Firefox 56.0

Re: Custom Buttons

приветствую,
пожалуйста, помогите подправить код.
нужно, чтобы при нажатии не было запроса где сохранить, а сразу сохранялось на рабочий стол ( C:\\Users\\USER\\Desktop\\)
и появлялось сообщение в углу - Страница сохранена на Рабочем столе.
спасибо

код кнопки Save snapshot to html

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

Выделить код

Код:

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);
    if(fp.show() == fp.returnCancel) return;
    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();
};
var resolveURL = function (url, base) {
    try {
        var ioService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
        var baseURI = ioService.newURI(base, null, null);
        var absURI = ioService.newURI(url, null, baseURI);
        return absURI.spec;
    } catch (e) {}
};

var getSelWin = function (w) {
    if (w.getSelection().toString()) return w;
    for (var i = 0, f, r; f = w.frames[i]; i++) {
        try {
            if (r = getSelWin(f)) return r;
        } catch(e) {}
    }
};
var encodeImg = function (src, obj) {
    var canvas, img, ret = src;
    if (/^https?:\/\//.test(src)) {
        canvas = doc.createElement('canvas');
        if (!obj || obj.nodeName.toLowerCase() != 'img') {
            img = doc.createElement('img');
            img.src = src;
        } else {
            img = obj;
        };
        if (img.complete) try{
            canvas.width = img.width;
            canvas.height = img.height;
            canvas.getContext('2d').drawImage(img, 0, 0);
            ret = canvas.toDataURL((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png'));
        } catch (e) {};
        if (img != obj) img.src = 'about:blank';
    };
    return ret;
};
var toSrc = function (obj) {
    var strToSrc = function (str) {
        var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'};
        while (chr = str.charAt(i++)) {
            ret += meta[chr] || chr;
        };
        return '\x22' + ret + '\x22';
    },
    arrToSrc = function (arr) {
        var ret = [];
        for (var i = 0; i < arr.length; i++) {
            ret[i] = toSrc(arr[i]) || 'null';
        };
        return '[' + ret.join(',') + ']';
    },
    objToSrc = function (obj) {
        var val, ret = [];
        for (var prop in obj) {
            if (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) ? String(obj) : 'null';
        case 'Object': return objToSrc(obj);
        case 'String': return strToSrc(obj);
        default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null';
    }
};

var mainWin = document.commandDispatcher.focusedWindow.top == content ? document.commandDispatcher.focusedWindow : content;
var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location;
var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/g;

if (selWin) {
    var rng = win.getSelection().getRangeAt(0);
    pEle = rng.commonAncestorContainer;
    ele = rng.cloneContents();
} else {
    pEle = doc.documentElement;
    ele = (doc.body || doc.getElementsByTagName('body')[0]).cloneNode(true);
};
while (pEle) {
    if (pEle.nodeType == 1) {
        clone = pEle.cloneNode(false);
        clone.appendChild(ele);
        ele = clone;
    };
    pEle = pEle.parentNode
};
var sel = doc.createElement('div');
sel.appendChild(ele);

for (var el, all = sel.getElementsByTagName('*'), i = all.length; i--;) {
    el = all[i];
    if (el.style && el.style.backgroundImage) el.style.backgroundImage = el.style.backgroundImage.replace(reUrl, function (a, prev, url, next) {
        if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href);
        return prev + encodeImg(url) + next;
    });
    switch (el.nodeName.toLowerCase()) {
        case 'link':
        case 'style':
        case 'script': el.parentNode.removeChild(el); break;
        case 'a': 
        case 'area': if (el.hasAttribute('href') && el.getAttribute('href').charAt(0) != '#') el.href = el.href; break;
        case 'img':
        case 'input': if (el.hasAttribute('src')) el.src = encodeImg(el.src, el); break;
        case 'audio':
        case 'video':
        case 'embed':
        case 'frame':
        case 'iframe': if (el.hasAttribute('src')) el.src = el.src; break;
        case 'object': if (el.hasAttribute('data')) el.data = el.data; break;
        case 'form': if (el.hasAttribute('action')) el.action = el.action; break;
    }
};

var head = ele.insertBefore(doc.createElement('head'), ele.firstChild);
var meta = doc.createElement('meta');
meta.httpEquiv = 'content-type';
meta.content = 'text/html; charset=utf-8';
head.appendChild(meta);
var title = doc.getElementsByTagName('title')[0];
if (title) head.appendChild(title.cloneNode(true));

head.copyScript = function (unsafeWin) {
    if ('$' in unsafeWin) return;
    var f = doc.createElement('iframe');
    f.src = 'about:blank';
    f.setAttribute('style', 'position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;');
    doc.documentElement.appendChild(f);
    var str, script = doc.createElement('script');
    script.type = 'text/javascript';
    for (var name in unsafeWin) {
        if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue;
        try {
            str = toSrc(unsafeWin[name]);
            if (!/\{\s*\[native code\]\s*\}/.test(str)) {
                script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n'));
            }
        } catch (e) {};
    };
    f.parentNode.removeChild(f);
    if (script.childNodes.length) this.nextSibling.appendChild(script);
};
head.copyScript(win.wrappedJSObject || win);

head.copyStyle = function (s) {
    if (!s) return;
    var style = doc.createElement('style');
    style.type = 'text/css';
    if (s.media && s.media.mediaText) style.media = s.media.mediaText;
    try {
        for (var i = 0, rule; rule = s.cssRules[i]; i++) {
            if (rule.type != 3) {
                if((!rule.selectorText || rule.selectorText.indexOf(':') != -1) || (!sel.querySelector || sel.querySelector(rule.selectorText))) {
                    var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) {
                        if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href);
                        if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url);
                        return prev + url + next;
                    });
                    style.appendChild(doc.createTextNode(css + '\n'));
                }
            } else {
                this.copyStyle(rule.styleSheet);
            }
        }
    } catch(e) {
        if (s.ownerNode) style = s.ownerNode.cloneNode(false);
    };
    this.appendChild(style);
};
var sheets = doc.styleSheets;
for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]);
head.appendChild(doc.createTextNode('\n'));

var doctype = '', dt = doc.doctype;
if (dt && dt.name) {
    doctype += '<!DOCTYPE ' + dt.name;
    if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22';
    if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22';
    doctype += '>\n';
};
var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());
fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');
fileName += ("  " + new Date().toLocaleFormat("%d.%m.%Y. %H:%M:%S"));
if(!/\.html?$/.test(fileName))fileName += '.html';

saveToFile(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->', fileName);

Отсутствует

 

№1488908-08-2020 13:09:39

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 476
UA: Firefox 56.0

Re: Custom Buttons

Dumby вопрос по кнопке QuickSettings :
Как вам задача сделать аналог, но работающий и на CustomButtons и (или) на скриптах от Виталия (профиль/chrome/user_chrome_files/)
Преимущества такой кнопки, открывающей меню настроек:
1) наглядно видны множество важных режимов работы браузера (нажатием на кнопку)
2) очень легко можно переключать настройки, например, загрузку графики, серверы VPN, юзер-агенты…
3) можно создать несколько виртуальных пунктов меню, переключающих несколько настроек. Это будут «профили» настроек.
3) можно открывать разные меню: Левая кнопка: основные настройки, Правая: системные (колёсико: внешний вид ?)


Dumby пишет

Смотрю капс-V опечатка не исправлена. Почему?

У себя я исправил сразу, но не вижу смысла выкладывать такие незначительные изменения…

Отредактировано Dobrov (09-08-2020 00:26:02)

Отсутствует

 

№1489008-08-2020 17:40:37

Duche
Участник
 
Группа: Members
Зарегистрирован: 07-02-2016
Сообщений: 209
UA: unknown 0.0

Re: Custom Buttons

Добрый день. Посмотрите пожалуйста два кода для FF710"Удалить активную вкладку из папки закладок" и " Удалить куки текущего сайта в контекстном меню на странице" для контекстного меню.

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

Выделить код

Код:

//Удалить активную вкладку из папки........................................
   
 (()=> {  
   ((popup, menugroup, bs) => addEventListener("popupshowing", {
    handleEvent(e) {
        if (this.shouldHide()) return;
        var before = popup.children[1];
        //var before = popup.querySelector("#page-menu-separator + *");  Строка ниже..........................
        var menuitem = popup.insertBefore(document.createElement("menuitem"), before);
        addDestructor(() => menuitem.remove());
        var attrs = {
            label: "Удалить эту страницу из закладок",
            class: "menuitem-iconic",
            oncommand: "removeBookmarks();"
        };
        for(var attr in attrs) menuitem.setAttribute(attr, attrs[attr]);

        var crop = (str, limit = 100) => str.length <= limit ? str : str.slice(0, limit) + "…";
        var notify = (num, msg) => {
            var forms = gNavigatorBundle.getString("editBookmark.removeBookmarks.label").replace(/ть/g, "л");
            (notify = (num, msg) => openDialog(
                "chrome://global/content/alerts/alert.xul", "", "popup=yes", menuitem.image,
                PluralForm.get(num, forms).replace("#1", num), msg, false, null, 4
            ))(num, msg);
        }
        menuitem.removeBookmarks = () => {
            var msg = crop(gBrowser.currentURI.spec) + "\n\n\Из:\n", num = 0;
            for(var id of this.ids) {
                var folder = bs.getFolderIdForItem(id);
                if (bs.getFolderIdForItem(folder) == PlacesUtils.tagsFolderId) continue;
                bs.removeItem(id);
                num++; msg += "\n" + (bs.getItemTitle(folder) || "[Безымянная папка]");
            }
            gBrowser.removeCurrentTab();
            notify(num, msg);
        }
        (this.handleEvent = () => {
            if ((menuitem.hidden = this.shouldHide())) return;
            var icon = gBrowser.selectedBrowser.mIconURL;
            menuitem.image = icon ? "moz-anno:favicon:" + icon : PlacesUtils.favicons.defaultFavicon.spec;
        })();
    },
    shouldHide(e) {
        if (menugroup.hidden) return true;
        var ids = bs.getBookmarkIdsForURI(gBrowser.currentURI);
        if (!ids.length) return true;
        this.ids = ids;
    }
}, false, popup))(
    document.getElementById("contentAreaContextMenu"),
    document.getElementById("context-navigation"), PlacesUtils.bookmarks
);
})();


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

Выделить код

Код:

// Удалить куки текущего сайта в контекстном меню на странице, от 06.03.2017. ................
  
 (()=> {
(contextMenu=> {
   var menu = contextMenu.appendChild(document.createElement("menu"));
   menu.id = "content-removeCookies."
   menu.setAttribute("label", "Удалить куки текущего сайта");
   menu.setAttribute("class", "menu-iconic");
   addEventListener("popupshowing", ()=> menu.setAttribute("image", gBrowser.mCurrentTab.image), false, contextMenu);
   addDestructor(()=> menu.remove() );
   
   var menuPopup = menu.appendChild(document.createElement("menupopup"));
   var menuitem = menuPopup.appendChild(document.createElement("menuitem"));               
   menuitem.setAttribute("label", "Удалить");
   menuitem.onclick =()=> {
      var host = Services.eTLD.getBaseDomain(gBrowser.currentURI);

      for ( var en = Services.cookies.enumerator; en.hasMoreElements(); ) {
            var cookie = en.getNext().QueryInterface(Ci.nsICookie);
            ~cookie.host.indexOf(host.trim()) && Services.cookies.remove(cookie.host, cookie.name, cookie.path, false); 
            }
   
      var reversedDomain = host.split("").reverse().join("") + ".";
      Cu.import("resource://gre/modules/FileUtils.jsm");
      var file = FileUtils.getFile("ProfD", ["webappsstore.sqlite"]);
      var dbConn = Services.storage.openDatabase(file);
      dbConn.executeSimpleSQL("DELETE FROM webappsstore2 WHERE scope LIKE \"%" + reversedDomain +"%\"");
      dbConn.close();
      
      var host = content.document.domain;
      for( var tab of gBrowser.tabs ) {  
           var tabHost = tab.linkedBrowser.contentDocument.location.host;
           if ( host == tabHost ) gBrowser.reloadTab(tab);
           }
          
      // очистить кэш ....
      try { 
          Services.cache.evictEntries(1);
          Services.cache.evictEntries(2);
          } 
      catch(e) { Services.cache2.clear() };
   
      // удалить все Flash куки
      var dir = Services.dirsvc.get('Home', Ci.nsIFile);
      dir.append("Application Data");
      dir.append("Macromedia");
      //dir.remove(true);
      //dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
      dir.exists() && dir.remove(true);                      // Удалить Flash кукисы222 ....
      !dir.exists() && dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
   
      // Всплывающее сообщение ....
      var win = openDialog("chrome://global/content/alerts/alert.xul", "", "popup=yes", (gBrowser.mCurrentTab.image || "chrome://global/skin/icons/Portrait.png"),
           "", "Очистил куки, кеш текущего сайта и удалил Flash куки", false, null, 4);
      setTimeout(()=> win && win.close(), 2500);          
  };
})(document.getElementById("contentAreaContextMenu"));
})();

Отредактировано Duche (08-08-2020 17:41:08)

Отсутствует

 

№1489110-08-2020 14:17:30

Duche
Участник
 
Группа: Members
Зарегистрирован: 07-02-2016
Сообщений: 209
UA: unknown 0.0

Re: Custom Buttons

Добрый день. Посмотрите пожалуйста. Часики работают , тут все нормально но, недавно заменил вот такое, описать нет слов , лучше посмотреть.

скрытый текст
e4a0db9572ca.jpg

Код часы.

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

Выделить код

Код:

// Аналоговые часы, от 08.02.2016. ............... 
(()=> {
   var dia = 30; // диаметр аналоговых часов
   
   var canvas = document.createElementNS(xhtmlns, 'canvas');
   canvas.setAttribute("width", dia+"px;");
   canvas.setAttribute("height", dia+"px;");
   //canvas.style.cssText = "position: fixed !important; top: 30px; right: 218px; min-width: diapx; min-height: diapx; max-width: diapx; max-height: diapx".replace(/dia/g, dia);
   canvas.style.cssText = "min-width: diapx; min-height: diapx; max-width: diapx; max-height: diapx".replace(/dia/g, dia);
   var ctx = canvas.getContext("2d");
   ctx.scale(dia/122, dia/122);
   self.parentNode.insertBefore(canvas, self);
   addDestructor(()=> canvas.remove() );
   
   self.hidden = true;
   canvas.onclick =()=> self.hidden = !self.hidden;
 

      var interval = setInterval(()=> {
      var ctx = canvas.getContext("2d");
      ctx.save();
      ctx.clearRect(0, 0, 150, 150);
      ctx.translate(61, 61);
      ctx.scale (0.4, 0.4);
      ctx.fillStyle = "white";
      ctx.arc(0, 0, 142, 0, Math. PI * 2, true);
      ctx.fill();
      ctx.rotate(-Math. PI / 2);
      ctx.strokeStyle = "black";
      ctx.fillStyle = "white";
      ctx.lineWidth = 12;
      ctx.lineCap = "round";
      ctx.save();
      ctx.beginPath();
      for ( var i = 0; i < 12; i++ ) {
            ctx.rotate(Math. PI / 6);
            ctx.moveTo(100, 0);
            ctx.lineTo(120, 0);
            }
      ctx.stroke();
      ctx.restore();
      ctx.save();
      ctx.lineWidth = 5;
      ctx.beginPath();
      for ( var i = 0; i < 60; i++ ) {
            if ( i % 5 != 0 ) {
                 ctx. moveTo (117, 0);
                 ctx. lineTo (120, 0);
                 }
            ctx.rotate(Math. PI / 30);
            }
      ctx.stroke();
      ctx.restore();
      var now = new Date();
      now.setHours(now.getHours() + 1);  /*на час вперёд*/
      var sec = now.getSeconds();
      var min = now.getMinutes();
      var hr = now.getHours();
      self.tooltipText = [hr, min > 9? min: "0" + min, sec > 9? sec: "0" + sec]. join (" : ");
      hr = hr >= 12? hr - 12: hr;
      ctx.fillStyle = "black";
      ctx.save();
      ctx.strokeStyle = "black";
      ctx.rotate(hr * (Math. PI / 6) + (Math. PI / 360) * min + (Math. PI / 21600) * sec)
      ctx.lineWidth = 14;
      ctx.beginPath();
      ctx.moveTo(-20, 0);
      ctx.lineTo(80, 0);
      ctx.stroke();
      ctx.restore();
      ctx.save();
      ctx.rotate((Math. PI / 30) * min + (Math. PI / 1800) * sec)
      ctx.lineWidth = 10;
      ctx.beginPath();
      ctx.moveTo(-28, 0);
      ctx.lineTo(112, 0);
      ctx.stroke();
      ctx.restore();
      ctx.save();
      ctx.rotate(sec * Math. PI / 30);
      ctx.strokeStyle = "#ee0000";
      ctx.fillStyle = "#ee0000";
      ctx.lineWidth = 6;
      ctx.beginPath();
      ctx.moveTo(-30, 0);
      ctx.lineTo(93, 0);
      ctx.stroke();
      ctx.fillStyle = "#555";
      ctx.arc(0, 0, 3, 0, Math. PI * 2, true);
      ctx.fill();
      ctx.restore();
      ctx.beginPath();
      ctx.lineWidth = 14;
      ctx.strokeStyle = '#1581e6';
      ctx.arc(0, 0, 142, 0, Math. PI * 2, true);
      ctx.stroke();
      ctx.restore();
   }, 1000);
   addDestructor(()=> clearInterval(interval) );
   
})();


Там ещё в секции код
/*CODE*/

this.leftclick(event);

Отредактировано Duche (10-08-2020 14:23:55)

Отсутствует

 

№1489210-08-2020 16:04:11

unter_officer
Участник
 
Группа: Members
Откуда: Санкт-Петербург
Зарегистрирован: 27-03-2011
Сообщений: 606
UA: Firefox 52.0

Re: Custom Buttons

Duche пишет

Добрый день. Посмотрите пожалуйста. Часики работают , тут все нормально но, недавно заменил вот такое, описать нет слов , лучше посмотреть.

Duche, не уверен, что поможет, но попробуйте перед вашим кодом часов (в инициализации) вставить это:

Выделить код

Код:

this.setAttribute("stop","true");

Отредактировано unter_officer (10-08-2020 16:25:14)


«The Truth Is Out There»

Отсутствует

 

№1489310-08-2020 16:30:58

Duche
Участник
 
Группа: Members
Зарегистрирован: 07-02-2016
Сообщений: 209
UA: unknown 0.0

Re: Custom Buttons

unter_officer пишет

не уверен, что поможет, но попробуйте

Не помогло, а жаль.

Отсутствует

 

№1489410-08-2020 18:52:35

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

Re: Custom Buttons

firepox пишет

пожалуйста, помогите подправить код.
нужно, чтобы при нажатии не было запроса где сохранить, а сразу сохранялось на рабочий стол ( C:\\Users\\USER\\Desktop\\)
и появлялось сообщение в углу - Страница сохранена на Рабочем столе.

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

Выделить код

Код:

var saveToFile = this.stf || (this.stf = (suc => {
	suc.charset = "utf-8";
	var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
	var alertName = "Save_snapshot_to_html_alert";
	var notify = as.showAlertNotification.bind(
		as, null, "Страница сохранена на Рабочем столе", null, false, null, null, alertName
	);
	var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
	var fos = Components.Constructor("@mozilla.org/network/file-output-stream;1", "nsIFileOutputStream", "init");
	return (html, name) => {
		var file = desk.clone()
		file.append(name);
		html = suc.ConvertFromUnicode(html);
		var stream = new fos(file, 0x02|0x20|0x08, 0o666, 0);
		stream.write(html, html.length);
		stream.close();
		notify();
		setTimeout(as.closeAlert, 2e3, alertName);
	}
})(Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter)));

Dobrov пишет

Как вам задача сделать аналог, но работающий и на CustomButtons и (или) на скриптах от Виталия

Ну вот, смотрю добавлено «(или)», получилась бессмыслица.
Задача «сделать аналог» энтузиазма не вызывает совсем.
А вот (когда было только) это «и» — заинтересовало, решил попробовать.
Типа тяп-ляп, только переключение настроек. Вроде работает, в «и»-смысле.


Что-то форум код не переваривает, пишет «Unable to create post».
Тогда base64 адрес, для открытия во вкладке.

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

Выделить код

Код:

data:text/plain;charset=utf-8;base64,KGFzeW5jIChuYW1lLCBpZCwgZnVuYykgPT4gew0KCWlmIChuYW1lID09ICJPYmplY3QiKSByZXR1cm4gQ3VzdG9taXphYmxlVUkuY3JlYXRlV2lkZ2V0KGZ1bmMoKSk7DQoJdmFyIHdpbiA9IG5hbWUgPT0gIldpbmRvdyIsIGcgPSBDb21wb25lbnRzLnV0aWxzLmltcG9ydCgicmVzb3VyY2U6Ly9ncmUvbW9kdWxlcy9TZXJ2aWNlcy5qc20iLCB7fSk7DQoJaWYgKGdbaWRdKSB7aWYgKHdpbikgcmV0dXJuO30gZWxzZSBnW2lkXSA9IGZ1bmMoKTsNCglpZiAod2luKSByZXR1cm4gQ3VzdG9taXphYmxlVUkuY3JlYXRlV2lkZ2V0KGdbaWRdKTsNCglhZGREZXN0cnVjdG9yKHIgPT4gcls1XSA9PSAiZSIgJiYgZGVsZXRlIGdbaWRdKTsNCglnW2lkXS5vbkNyZWF0ZWQodGhpcyk7DQp9KSh0aGlzLmNvbnN0cnVjdG9yLm5hbWUsICJRdWlja1RvZ2dsZUFib3V0Q29uZmlnU2V0dGluZ3MiLCAoKSA9PiB7DQoNCgl2YXIge3ByZWZzfSA9IFNlcnZpY2VzLCBkYiA9IHByZWZzLmdldERlZmF1bHRCcmFuY2goIiIpOw0KCXZhciBwdiA9IHBhcnNlSW50KFNlcnZpY2VzLmFwcGluZm8ucGxhdGZvcm1WZXJzaW9uKTsNCgl2YXIgeHVsX25zID0gImh0dHA6Ly93d3cubW96aWxsYS5vcmcva2V5bWFzdGVyL2dhdGVrZWVwZXIvdGhlcmUuaXMub25seS54dWwiOw0KDQoJdmFyIGxvY2FsaG9zdCA9ICIxMjcuMC4wLjEiOw0KCXZhciBhbnRpY2Vuc29yaXR5ID0gImh0dHBzOi8vZ2l0LmlvL2FjLWFudGljZW5zb3JpdHktcGFjIjsNCgl2YXIgYW50aXphcHJldCA9ICJodHRwczovL2FudGl6YXByZXQucHJvc3RvdnBuLm9yZy9wcm94eS5wYWMiOw0KCXZhciBwYWNmaWxlID0gcHJlZnMuZ2V0U3RyaW5nUHJlZigidXNlci5wYWNmaWxlIiwgImZpbGU6Ly8vZXRjL3Byb3h5LnBhYyIpOw0KCXZhciB1c2VyYWdlbnQgPSAiTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBXT1c2NDsgcnY6NTYuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC81Ni4wIjsNCg0KLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KCS8vIHJlZnJlc2g6DQoJLy8JZmFsc2UgLSByZWxvYWQgY3VycmVudCB0YWINCgkvLwl0cnVlIC0gcmVsb2FkIGN1cnJlbnQgdGFiIHNraXAgY2FjaGUNCgkvLw0KCS8vIHJlc3RhcnQ6DQoJLy8JZmFsc2UgLSByZXN0YXJ0IGJyb3dzZXINCgkvLwl0cnVlIC0gcmVzdGFydCBicm93c2VyIHdpdGggY29uZmlybQ0KDQoJdmFyIHByaW1hcnkgPSBbew0KDQoJCQlwcmVmOiBbIm5ldHdvcmsucHJveHkuYXV0b2NvbmZpZ191cmwiLCAi0J/RgNC+0LrRgdC4IChWUE4pIl0sDQoJCQl1c2VyQ2hvaWNlOiBsb2NhbGhvc3QsIHJlZnJlc2g6IHRydWUsIGltYWdlOiAiY2hyb21lOi8vYnJvd3Nlci9za2luL3ByaXZhdGVicm93c2luZy9mYXZpY29uLnN2ZyIsDQoJCQl2YWx1ZXM6IFsNCgkJCQlbbG9jYWxob3N0LCAi0L7RgtC60LvRjtGH0LXQveKApiIsICIwIl0sDQoJCQkJW2FudGl6YXByZXQsICLQkNC90YLQuNCX0LDQv9GA0LXRgiIsICIxIl0sDQoJCQkJW3BhY2ZpbGUsICJ1c2VyIC5wYWMg0YTQsNC50LsiLCAiMiJdLA0KCQkJCVthbnRpY2Vuc29yaXR5LCAiYWMtYW50aWNlbnNvcml0eSIsICIzIl0sDQoJCQkJWyJsb2NhbGhvc3QiLCAiVG9yIEJyb3dzZXIiLCAiNCJdDQoJXX0sew0KCQkJcHJlZjogWyJuZXR3b3JrLnByb3h5LmF1dG9jb25maWdfdXJsIiwgItCf0YDQvtC60YHQuCAo0LzQvdC+0LPQvtGB0YLRgNC+0YfQvdCw0Y8g0L/QvtC00YHQutCw0LfQutCwKSJdLA0KCQkJdXNlckNob2ljZTogbG9jYWxob3N0LCByZWZyZXNoOiB0cnVlLCBpbWFnZTogImNocm9tZTovL2Jyb3dzZXIvc2tpbi9wcml2YXRlYnJvd3NpbmcvZmF2aWNvbi5zdmciLA0KCQkJdmFsdWVzOiBbDQoJCQkJW2xvY2FsaG9zdCwgItC+0YLQutC70Y7Rh9C10L3igKYiLCAiMCIsICLQv9C+LdGD0LzQvtC70YfQsNC90LjRjiJdLA0KCQkJCVthbnRpemFwcmV0LCAi0JDQvdGC0LjQl9Cw0L/RgNC10YIiLCAiMSIsICLQstGC0L7RgNCw0Y8g0YHRgtGA0L7QutCwIl0sDQoJCQkJW3BhY2ZpbGUsICJ1c2VyIC5wYWMg0YTQsNC50LsiLCAiMiIsICJhYm91dDpjb25maWcg4oCUIHVzZXIucGFjZmlsZSJdLA0KCQkJCVthbnRpY2Vuc29yaXR5LCAiYWMtYW50aWNlbnNvcml0eSIsICIzIiwgItCy0YLQvtGA0LDRjyDRgdGC0YDQvtC60LAiXSwNCgkJCQlbImxvY2FsaG9zdCIsICJUb3IgQnJvd3NlciIsICI0IiwgItC40YHQv9C+0LvRjNC30YPQtdGC0YHRjyDRgdC10YDQstC40YEgdG9yIl0NCgldfSx7DQoJCQlwcmVmOiBbIm5ldHdvcmsucHJveHkudHlwZSIsICJwcm94eSDQodC10YDQstC10YAiXSwNCgkJCXVzZXJDaG9pY2U6IDAsIHJlZnJlc2g6IHRydWUsDQoJCQl2YWx1ZXM6IFsNCgkJCQlbMiwgItCw0LLRgtC+0L3QsNGB0YLRgNC+0LnQutCwIiwgIjIiXSwgWzEsICLQv9C+0LvRjNC30L7QstCw0YLQtdC70YwiLCAiMSJdLA0KCQkJCVs1LCAi0YHQuNGB0YLQtdC80L3Ri9C5IiwgIjUiXSwgWzAsICLQvtGC0LrQu9GO0YfQtdC9IiwgIjAiXSwgWzQsICLigKbQtNC70Y8g0YLQtdC60YPRidC10Lkg0YHQtdGC0LgiLCAiNCJdDQoJXX0sew0KCQkJcHJlZjogWyJDQi5Qcm94eS5yZXNldCIsICLRgNC10LbQuNC8ICfQkdC10Lcg0L/RgNC+0LrRgdC4JyDQv9GA0Lgg0LLRi9GF0L7QtNC1Il0sIHVzZXJDaG9pY2U6IGZhbHNlDQoJfSwNCgkJCW51bGwsDQoJew0KCQkJcHJlZjogWyJwZXJtaXNzaW9ucy5kZWZhdWx0LmltYWdlIiwgItCX0LDQs9GA0YPQttCw0YLRjCDQs9GA0LDRhNC40LrRgyJdLA0KCQkJdXNlckNob2ljZTogMSwgcmVmcmVzaDogZmFsc2UsDQoJCQl2YWx1ZXM6IFtbMSwgItCU0LAiXSwgWzMsICJTaXRlIG9ubHkiXSwgWzIsICLQndC10YIiXV0NCgl9LHsNCgkJCXByZWY6IFsiYnJvd3Nlci5kaXNwbGF5LnVzZV9kb2N1bWVudF9mb250cyIsICLQl9Cw0LPRgNGD0LbQsNGC0Ywg0YjRgNC40YTRgtGLIFdlYiJdLA0KCQkJdmFsdWVzOiBbWzAsICLQktGL0LrQuyJdLCBbMSwgItCS0LrQuyJdXQ0KCX0sew0KCQkJcHJlZjogWyJqYXZhc2NyaXB0LmVuYWJsZWQiLCAi0JLRi9C/0L7Qu9C90Y/RgtGMINGB0LrRgNC40L/RgtGLIEphdmEiLCAiaiJdLCB1c2VyQ2hvaWNlOiB0cnVlDQoJfSx7DQoJCQlwcmVmOiBbIm1lZGlhLmF1dG9wbGF5LmVuYWJsZWQiLCAi0LDQstGC0L7Qv9GA0L7QuNCz0YDRi9Cy0LDQvdC40LUg0LzQtdC00LjQsCIsICJtIl0sIHVzZXJDaG9pY2U6IHRydWUNCgl9LHsNCgkJCXByZWY6IFsibmV0d29yay5jb29raWUuY29va2llQmVoYXZpb3IiLCAi0JrRg9C60LgiXSwgdXNlckNob2ljZTogMCwNCgkJCXZhbHVlczogWw0KCQkJCVswLCAi0KDQsNC30YDQtdGI0LjRgtGMINCy0YHQtSDRgdCw0LnRgtGLIl0sDQoJCQkJWzIsICLQl9Cw0L/RgNC10YLQuNGC0Ywg0LLRgdC1INGB0LDQudGC0YsiXSwNCgkJCQlbMywgItCh0YLQvtGA0L7QvdC90LjQtSDQv9C+0YHQtdGJ0ZHQvdC90YvQtSDRgdCw0LnRgtGLIl0sDQoJCQkJWzEsICLQndC1INC/0YDQuNC90LjQvNCw0YLRjCDRgdC+INGB0YLQvtGA0L7QvdC90LjRhSDRgdCw0LnRgtC+0LIiXQ0KCV19LHsNCgkJCXByZWY6IFsiQ0IuUm9vdE1vZGUiLCAi0K3QutGB0L/QtdGA0YLQvdGL0Lkg0YDQtdC20LjQvCDQutC90L7Qv9C+0LoiXQ0KCX0sDQoJCQludWxsLA0KCXsNCgkJCXByZWY6IFsiZ2VuZXJhbC51c2VyYWdlbnQub3ZlcnJpZGUiLCAiVXNlckFnZW50IiwgInUiXSwNCgkJCXVzZXJDaG9pY2U6IHVzZXJhZ2VudCwgcmVmcmVzaDogdHJ1ZSwgaW1hZ2U6ICJjaHJvbWU6Ly9icm93c2VyL3NraW4vcHJpdmF0ZWJyb3dzaW5nL2Zhdmljb24uc3ZnIiwNCgkJCXZhbHVlczogWw0KCQkJCVsiTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBXT1c2NDsgcnY6NTYuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC81Ni4wIiwgIkZpcmVmb3ggNTYiXSwNCgkJCQlbIk1vemlsbGEvNS4wIChYMTE7IExpbnV4IHg4Nl82NDsgcnY6NTYuMCkgR2Vja28vMjAxMDAxMDEgRmlyZWZveC81Ni4wIiwgIkZpcmVmb3ggNTYgTGludXgiXSwNCgkJCQlbIk1vemlsbGEvNS4wIChNYWNpbnRvc2g7IEludGVsIE1hYyBPUyBYIDEwLjEzOyBydjo2OC4wKSBHZWNrby8yMDEwMDEwMSBGaXJlZm94LzY4LjAiLCAiRmlyZWZveCA2OCBNYWNPU1giXSwNCgkJCQlbIk1vemlsbGEvNS4wIChXaW5kb3dzOyBVOyBNU0lFIDYuMDsgV2luZG93cyBOVCA1LjE7IFNWMTsgLk5FVCBDTFIgMi4wLjUwNzI3KSIsICJNU0lFIDYuMCBXaW5kb3dzIl0sDQoJCQkJWyJNb3ppbGxhLzUuMCAoTGludXg7IEFuZHJvaWQgNy4wOyBQTFVTIEJ1aWxkL05SRDkwTSkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzYxLjAuMzE2My45OCBNb2JpbGUgU2FmYXJpLzUzNy4zNiIsICJDaHJvbWU2MSBBbmRyb2lkNyJdLA0KCQkJCVsiTW96aWxsYS81LjAgKE1hY2ludG9zaDsgSW50ZWwgTWFjIE9TIFggMTBfMTJfNCkgQXBwbGVXZWJLaXQvNjAzLjEuMzAgKEtIVE1MLCBsaWtlIEdlY2tvKSBWZXJzaW9uLzEwLjEgU2FmYXJpLzYwMy4xLjMwIiwgIlNhZmFyaSA2IE1hY09TWCJdLA0KCQkJCVsiT3BlcmEvOS44MCAoV2luZG93cyBOVCA2LjI7IFdpbjY0OyB4NjQpIFByZXN0by8yLjEyIFZlcnNpb24vMTIuMTYiLCAiT3BlcmExMiBXOCJdLA0KCQkJCVsiTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgNi4xOyBXT1c2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzU3LjAuMjk4Ny4xMzMgU2FmYXJpLzUzNy4zNiIsICJDaHJvbWU1NyBXNyJdLA0KCQkJCVsiTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzYxLjAuMzE2My45OCBTYWZhcmkvNTM3LjM2IiwgIkNocm9tZTYxIFcxMCJdLA0KCQkJCVsiTW96aWxsYS81LjAgKExpbnV4OyBBbmRyb2lkIDUuMS4xOyBTTS1HOTI4WCBCdWlsZC9MTVk0N1gpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS80Ny4wLjI1MjYuODMgTW9iaWxlIFNhZmFyaS81MzcuMzYiLCAiU2Ftc3VuZyBHYWxheHkgUzYiXSwNCgkJCQlbIk1vemlsbGEvNS4wIChQbGF5U3RhdGlvbiA0IDMuMTEpIEFwcGxlV2ViS2l0LzUzNy43MyAoS0hUTUwsIGxpa2UgR2Vja28pIiwgIlBsYXlzdGF0aW9uIDQiXSwNCgkJCQlbIlhib3ggKFhib3g7IFhib3ggT25lKSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvNDYuMC4yNDg2LjAgTW9iaWxlIFNhZmFyaS81MzcuMzYgRWRnZS8xMy4xMDU4NiIsICJYYm94IE9uZSAobW9iaWxlKSJdLA0KCQkJCVsiTW96aWxsYS81LjAgKFdpbmRvd3MgUGhvbmUgMTAuMDsgQW5kcm9pZCA0LjIuMTsgTWljcm9zb2Z0OyBMdW1pYSA5NTApIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS80Ni4wLjI0ODYuMCBNb2JpbGUgU2FmYXJpLzUzNy4zNiBFZGdlLzEzLjEwNTg2IiwgIk1pY3Jvc29mdCBMdW1pYSA5NTAiXSwNCgkJCQlbIk1vemlsbGEvNS4wIChjb21wYXRpYmxlOyBNU0lFIDkuMDsgV2luZG93cyBQaG9uZSBPUyA3LjU7IFRyaWRlbnQvNS4wOyBJRU1vYmlsZS85LjA7IFNBTVNVTkc7IEdULUk4MzUwKSIsICJXaW5kb3dzIFBob25lIl0sDQoJCQkJWyJNb3ppbGxhLzUuMCAoY29tcGF0aWJsZTsgR29vZ2xlYm90LzIuMTsgK2h0dHA6Ly93d3cuZ29vZ2xlLmNvbS9ib3QuaHRtbCkiLCAiR29vZ2xlQm90Il0sDQoJCQkJWyIiLCAi0J/Rg9GB0YLQvtC1INC30L3QsNGH0LXQvdC40LUiXQ0KCV19XTsNCg0KLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KCXZhciBzZWNvbmRhcnkgPSBbew0KDQoJCQlwcmVmOiBbImltYWdlLmFuaW1hdGlvbl9tb2RlIiwgItCQ0L3QuNC80LDRhtC40Y8g0LjQt9C+0LHRgNCw0LbQtdC90LjQuSIsICJpIl0sDQoJCQl1c2VyQ2hvaWNlOiAibm9ybWFsIiwgcmVmcmVzaDogZmFsc2UsDQoJCQl2YWx1ZXM6IFtbIm5vcm1hbCIsICLQstC60LsuIl0sIFsibm9uZSIsICLQstGL0LrQuy4iXV0NCgl9LHsNCgkJCXByZWY6IFsiZG9tLndvcmtlcnMuZW5hYmxlZCIsICJPbkxpbmUg0LLQuNC00LXQviDwn46sICdkb20ud29ya2VycyciLCAidyJdLCB1c2VyQ2hvaWNlOiB0cnVlDQoJfSx7DQoJCQlwcmVmOiBbImRvbS5lbmFibGVfcGVyZm9ybWFuY2UiLCAi0KHQvtC+0LHRidC40YLRjCDQviDQt9Cw0LPRgNGD0LfQutC1INGB0YLRgNCw0L3QuNGG0YsiXSwgdXNlckNob2ljZTogZmFsc2UNCgl9LA0KCQkJbnVsbCwNCgl7DQoJCQlwcmVmOiBbImJyb3dzZXIuY2FjaGUuZGlzay5lbmFibGUiLCAi0J7RgtC60LsuINC00LjRgdC60L7QstC+0LPQviDQutGN0YjQsCJdLCB1c2VyQ2hvaWNlOiBmYWxzZQ0KCX0sew0KCQkJcHJlZjogWyJicm93c2VyLmNhY2hlLm1lbW9yeS5lbmFibGUiLCAi0J7RgtC60LsuINC60Y3RiNCwINCyINC+0L/QtdGA0LDRgtC40LLQvdC+0Lkg0L/QsNC80Y/RgtC4Il0sIHVzZXJDaG9pY2U6IGZhbHNlDQoJfSx7DQoJCQlwcmVmOiBbImRvbS5pbmRleGVkREIuZW5hYmxlZCIsICLQm9C+0LrQsNC70YzQvdC+0LUg0YXRgNCw0L3QuNC70LjRidC1IGluZGV4ZWREQiIsICJkIl0sIHVzZXJDaG9pY2U6IHRydWUNCgl9LHsNCgkJCXByZWY6IFsiZG9tLnN0b3JhZ2UuZW5hYmxlZCIsICLQntGC0LrQuy4g0LvQvtC60LDQu9GM0L3QvtCz0L4g0YXRgNCw0L3QuNC70LjRidCwIiwgInMiXQ0KCX0sDQoJCQludWxsLA0KCXsNCgkJCXByZWY6IFsiZ2VuZXJhbC51c2VyYWdlbnQubG9jYWxlIiwgInVzZXJhZ2VudC5sb2NhbGUiLCAibCJdLCByZXN0YXJ0OiB0cnVlLA0KCQkJdmFsdWVzOiBbDQoJCQkJWyJlbi1VUyIsICJFbmdsaXNoIiwgImUiXSwNCgkJCQlbInJ1LVJVIiwgItCg0YPRgSAocnUtUlUpIiwgInIiXSwNCgkJCQlbInJ1IiwgItGA0YPRgdGB0LrQuNC5IChydSkiXQ0KCV19LHsNCgkJCXByZWY6IFsiaW50bC5hY2NlcHRfbGFuZ3VhZ2VzIiwgImxhbmd1YWdlIl0sDQoJCQl2YWx1ZXM6IFtbImVuLVVTLCBlbjtxPTAuNSIsICJlbi1VUywgZW47cT0wLjUiLCAiZSJdLCBbImVuLVVTLCBlbiwgcnUtUlUsIHJ1IiwgImVuLVVTLCBlbiwgcnUtUlUsIHJ1IiwgInIiXV0NCgl9LHsNCgkJCXByZWY6IFsiYnJvd3Nlci5kaXNwbGF5LmRvY3VtZW50X2NvbG9yX3VzZSIsICJkb2N1bWVudF9jb2xvcl91c2UiLCAiYyJdLCB1c2VyQ2hvaWNlOiAwLA0KCQkJdmFsdWVzOiBbWzAsICJBdXRvIiwgIjAiXSwgWzEsICJBbHdheXMiLCAiMSJdLCBbMiwgIk5ldmVyIiwgIjIiXV0NCgl9LA0KCQkJbnVsbCwNCgl7DQoJCQlwcmVmOiBbIm5ldHdvcmsuaHR0cC5yZWZlcmVyLnNwb29mU291cmNlIiwgItCSINC60LDRh9C10YHRgtCy0LUg0YDQtdGE0LXRgNC10YDQsCDQutC+0YDQtdC90Ywg0YHQsNC50YLQsCJdLCB1c2VyQ2hvaWNlOiB0cnVlDQoJfSx7DQoJCQlwcmVmOiBbIm5ldHdvcmsuaHR0cC5zZW5kUmVmZXJlckhlYWRlciIsICLQktC60Lsv0JLRi9C60LsgUmVmZXJlciJdLCB1c2VyQ2hvaWNlOiAyLA0KCQkJdmFsdWVzOiBbWzAsICIwIl0sIFsyLCAiMiJdXQ0KCX0sew0KCQkJcHJlZjogWyJuZXR3b3JrLmh0dHAucmVmZXJlci50cmltbWluZ1BvbGljeSIsICJyZWZlcmVyLnRyaW1taW5nUG9saWN5Il0sDQoJCQl2YWx1ZXM6IFtbMCwgIjAiXSwgWzIsICIyIl1dDQoJfSwNCgkJCW51bGwsDQoJew0KCQkJcHJlZjogWyJtZWRpYS5tZWRpYXNvdXJjZS5lbmFibGVkIl0sIHVzZXJDaG9pY2U6IHRydWUNCgl9LHsNCgkJCXByZWY6IFsibWVkaWEucGVlcmNvbm5lY3Rpb24uZW5hYmxlZCJdDQoJfSx7DQoJCQlwcmVmOiBbImJyb3dzZXIudGFicy5yZW1vdGUuYXV0b3N0YXJ0IiwgItCc0L3QvtCz0L7Qv9C+0YLQvtGH0L3QvtGB0YLRjCDQstC60LvQsNC00L7QuiAoQ1BVKSJdLA0KCQkJdXNlckNob2ljZTogZmFsc2UsIHJlc3RhcnQ6IHRydWUNCgl9LA0KCQkJbnVsbA0KCV07DQoNCg0KCXJldHVybiB7DQoJCWxhYmVsOiAiUXVpY2sgdG9nZ2xlIiwNCgkJaWQ6ICJRdWlja1RvZ2dsZUFib3V0Q29uZmlnU2V0dGluZ3MiLA0KCQlsb2NhbGl6ZWQ6IGZhbHNlLA0KCQlpbWFnZTogImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBUUNBWUFBQUFmOC85aEFBQUI2a2xFUVZRNGpaV1R2MnRVUVJESHY4bnRkMjhHTExRUWZ3UzVWa3VEU2dSRi93bFJpSWlDUVFRaGhaMVZJSTEvd0RVV2trTFRCQXNiQzBGSllaR1EzTnVaUmNIWVc2VVFFUXpvZVhrVzc5MXhYaDVDcHRvZFpyOHo4NWtkNEJCV1JKd0RnQjV3eW9DamgzbUxiZks4Qy9kZFcxMVhKbGR1TmdZYWVURnB2SldBMCtQK0JCeDNDZjJzTEV5NW00V3JTOEEwQUdBTmFCVVNyZ0tBS3pkY1k1azBQRjRISkdtNDdOSzZuU1VNWE9JWEFFZ1Nycm5HMG9VL0FHREtOYjZxSGU5YytNczFscWJ4cXdzL3VvVGZXVnAza3NSbGwvRFRKTTZiY01XRW4xS2JEeXNCQ1crenNuU05wV3NzVGJnM1BOZjN1dzdNdUhEZ3ltOHVvVzhhWDQ5NlN4S1hzN0owaVRzRk9iY0dSQmZleThyU2hQMUVYdGhTbkRIaFNoSjB2TTBIMXVZaUFLQlNIV1pxTFl5RGMrSDdzU3BlTmxNWDlsMWpXV2ViRUFnamdTeGNiUlJZQjQ2WWhDY1Z4SDlicURQM25ieVVCQjBYUGsrQ2pnbnZqMXFvcW9odkpxRHRUVUJkY0dBbVN6Z0lFUUJNMlIwZlkvVTQxR1Brd05wY1RCS2ZtbkRQTk40dzRUT1grTm5iZkFRQVdBS21YY01WQU1nYU5xck0xVWZxa2JNbXJYa1QvbkdKTzFYRjRYb2Q4LzBBazRLY0t6VGUzQVJPalBzL0FNZE0yTThhdGsyNWE4SVhBS1lhd1RaWmo1ak5FdlpOMlRWbGRnM055L1Jma1lpekFMQUZuQnl1ODE5dHp2Q1JXWEtxVHdBQUFBQkpSVTVFcmtKZ2dnPT0iLA0KCQlvbkNyZWF0ZWQoYnRuKSB7DQoJCQlidG4uc2V0QXR0cmlidXRlKCJpbWFnZSIsIHRoaXMuaW1hZ2UpOw0KCQkJdmFyIGRvYyA9IGJ0bi5vd25lckRvY3VtZW50Ow0KDQoJCQlidG4uZG9tUGFyZW50ID0gbnVsbDsNCgkJCWJ0bi5wb3B1cHMgPSBuZXcgYnRuLm93bmVyR2xvYmFsLkFycmF5KCk7DQoJCQl0aGlzLmNyZWF0ZVBvcHVwKGRvYywgYnRuLCAicHJpbWFyeSIsIHByaW1hcnkpOw0KCQkJdGhpcy5jcmVhdGVQb3B1cChkb2MsIGJ0biwgInNlY29uZGFyeSIsIHNlY29uZGFyeSk7DQoNCgkJCWJ0bi5saW5rZWRPYmplY3QgPSB0aGlzOw0KCQkJZm9yKHZhciB0eXBlIG9mIFsiY29tbWFuZCIsICJjb250ZXh0bWVudSJdKQ0KCQkJCWJ0bi5zZXRBdHRyaWJ1dGUoIm9uIiArIHR5cGUsIGBsaW5rZWRPYmplY3QuJHt0eXBlfShldmVudClgKTsNCgkJfSwNCgkJY3JlYXRlUG9wdXAoZG9jLCBidG4sIG5hbWUsIGRhdGEpIHsNCgkJCXZhciBwb3B1cCA9IGRvYy5jcmVhdGVFbGVtZW50TlMoeHVsX25zLCAibWVudXBvcHVwIik7DQoJCQl2YXIgcHJvcCA9IG5hbWUgKyAiUG9wdXAiOw0KCQkJYnRuLnBvcHVwcy5wdXNoKGJ0bltwcm9wXSA9IHBvcHVwKTsNCgkJCXBvcHVwLmlkID0gdGhpcy5pZCArICItIiArIHByb3A7DQoJCQlwb3B1cC5zZXRBdHRyaWJ1dGUoIm9ucG9wdXBzaG93aW5nIiwgInBhcmVudE5vZGUubGlua2VkT2JqZWN0LnBvcHVwc2hvd2luZyhldmVudCkiKTsNCgkJCWZvcih2YXIgb2JqIG9mIGRhdGEpIHBvcHVwLmFwcGVuZCh0aGlzLmNyZWF0ZUVsZW1lbnQoZG9jLCBvYmopKTsNCgkJCWJ0bi5hcHBlbmQocG9wdXApOw0KCQl9LA0KCQljcmVhdGVFbGVtZW50KGRvYywgb2JqKSB7DQoJCQlpZiAoIW9iaikgcmV0dXJuIGRvYy5jcmVhdGVFbGVtZW50TlMoeHVsX25zLCAibWVudXNlcGFyYXRvciIpOw0KCQkJdmFyIHByZWYgPSBkb2Mub3duZXJHbG9iYWwuT2JqZWN0LmNyZWF0ZShudWxsKSwgbm9kZSwgaW1nOw0KCQkJZm9yKHZhciBba2V5LCB2YWxdIG9mIE9iamVjdC5lbnRyaWVzKG9iaikpIHsNCgkJCQlpZiAoa2V5ID09ICJwcmVmIikgew0KCQkJCQl2YXIgW2FwcmVmLCBsYWIsIGFrZXksIHR0dF0gPSB2YWw7DQoJCQkJCXByZWYucHJlZiA9IGFwcmVmOyBwcmVmLmxhYiA9IGxhYiB8fCBhcHJlZjsNCgkJCQkJaWYgKGFrZXkpIHByZWYua2V5ID0gYWtleTsNCgkJCQkJaWYgKHR0dCkgcHJlZi50dHQgPSB0dHQ7DQoJCQkJfQ0KCQkJCWVsc2UgaWYgKGtleSA9PSAiaW1hZ2UiKSBpbWcgPSB2YWw7DQoJCQkJZWxzZSBpZiAoa2V5ICE9ICJ2YWx1ZXMiKSBwcmVmW2tleV0gPSB2YWw7DQoJCQl9DQoJCQl2YXIgdHlwZSA9IHByZWZzLmdldFByZWZUeXBlKHByZWYucHJlZik7DQoJCQl2YXIgcGludCA9IHR5cGUgPT0gcHJlZnMuUFJFRl9JTlQsIGludiA9IHR5cGUgPT0gcHJlZnMuUFJFRl9JTlZBTElEOw0KCQkJaWYgKGludiAmJiBvYmoudmFsdWVzIHx8IHBpbnQgfHwgdHlwZSA9PSBwcmVmcy5QUkVGX1NUUklORykgew0KCQkJCW5vZGUgPSBkb2MuY3JlYXRlRWxlbWVudE5TKHh1bF9ucywgIm1lbnUiKTsNCgkJCQlpbWcgJiYgbm9kZS5zZXRBdHRyaWJ1dGUoImltYWdlIiwgaW1nKTsNCgkJCQlpZiAoaW1nIHx8ICFwcmVmLmtleSkgbm9kZS5jbGFzc05hbWUgPSAibWVudS1pY29uaWMiOyAvLyBDRSBidWc/DQoJCQkJbm9kZS5hcHBlbmQoZG9jLmNyZWF0ZUVsZW1lbnROUyh4dWxfbnMsICJtZW51cG9wdXAiKSk7DQoJCQkJcHJlZi5ib29sID0gZmFsc2U7DQoJCQkJdmFyIHN0ciA9IHBpbnQgfHwgKGludiAmJiB0eXBlb2Ygb2JqLnZhbHVlc1swXVswXSA9PSAibnVtYmVyIikgPyAiSW50IiA6ICJTdHJpbmciOw0KCQkJCXByZWYuZ2V0ID0gcHJlZnNbYGdldCR7c3RyfVByZWZgXTsNCgkJCQlwcmVmLnNldCA9IHByZWZzW2BzZXQke3N0cn1QcmVmYF07DQoJCQl9IGVsc2Ugew0KCQkJCW5vZGUgPSBkb2MuY3JlYXRlRWxlbWVudE5TKHh1bF9ucywgIm1lbnVpdGVtIik7DQoJCQkJbm9kZS5zZXRBdHRyaWJ1dGUoInR5cGUiLCAiY2hlY2tib3giKTsNCgkJCQlub2RlLnNldEF0dHJpYnV0ZSgiY2xvc2VtZW51IiwgIm5vbmUiKTsNCgkJCQlwcmVmLmJvb2wgPSB0cnVlOw0KCQkJCXByZWYuZ2V0ID0gcHJlZnMuZ2V0Qm9vbFByZWY7DQoJCQkJcHJlZi5zZXQgPSBwcmVmcy5zZXRCb29sUHJlZjsNCgkJCX0NCgkJCShub2RlLnByZWYgPSBwcmVmKS52YWxzID0gZG9jLm93bmVyR2xvYmFsLk9iamVjdC5jcmVhdGUobnVsbCk7DQoJCQlwcmVmLmtleSAmJiBub2RlLnNldEF0dHJpYnV0ZSgiYWNjZXNza2V5IiwgcHJlZi5rZXkpOw0KCQkJcHJlZi5ib29sIHx8IHRoaXMuY3JlYXRlUmFkaW9zKGRvYywgb2JqLnZhbHVlcywgbm9kZS5maXJzdENoaWxkKTsNCgkJCXJldHVybiBub2RlOw0KCQl9LA0KCQl1cGQobm9kZSkgew0KCQkJdmFyIHtwcmVmfSA9IG5vZGUsIGRlZiA9IGZhbHNlLCB1c2VyID0gZmFsc2UsIHZhbDsNCgkJCWlmIChwcmVmcy5nZXRQcmVmVHlwZShwcmVmLnByZWYpICE9IHByZWZzLlBSRUZfSU5WQUxJRCkgew0KCQkJCXZhciBwbiA9IHByZWYucHJlZjsNCgkJCQl0cnkge3ZhbCA9IGRiW3ByZWYuZ2V0Lm5hbWVdKHBuKTsgZGVmID0gdHJ1ZX0gY2F0Y2goZXgpIHtkZWYgPSBmYWxzZTt9DQoJCQkJdmFyIHVzZXIgPSBwcmVmcy5wcmVmSGFzVXNlclZhbHVlKHBuKTsNCgkJCQlpZiAodXNlcikgdHJ5IHt2YWwgPSBwcmVmLmdldChwbiwgdW5kZWZpbmVkKTt9IGNhdGNoKGV4KSB7fQ0KCQkJfQ0KCQkJaWYgKHZhbCA9PSBwcmVmLnZhbCAmJiBkZWYgPT0gcHJlZi5kZWYgJiYgdXNlciA9PSBwcmVmLnVzZXIpIHJldHVybjsNCgkJCXByZWYudmFsID0gdmFsOyBwcmVmLmRlZiA9IGRlZjsgcHJlZi51c2VyID0gdXNlcjsNCgkJCXZhciBleGlzdHMgPSBkZWYgfHwgdXNlcjsNCg0KCQkJdmFyIHR0dCA9IGV4aXN0cyA/IHZhbCA6ICJUaGlzIHByZWZlcmVuY2VzIGRvZXMgbm90IGV4aXN0IjsNCgkJCWlmICh0dHQgPT09ICIiKSB0dHQgPSAiWyBlbXB0eV9zdHJpbmcgXSI7DQoJCQlpZiAocHJlZi50dHQpIHR0dCArPSAiXG4iICsgcHJlZi50dHQ7DQoJCQlub2RlLnRvb2x0aXBUZXh0ID0gdHR0Ow0KDQoJCQlpZiAocHJlZi5ib29sKSB2YWwNCgkJCQk/IG5vZGUuc2V0QXR0cmlidXRlKCJjaGVja2VkIiwgdHJ1ZSkNCgkJCQk6IG5vZGUucmVtb3ZlQXR0cmlidXRlKCJjaGVja2VkIik7DQoNCgkJCWlmICgidXNlckNob2ljZSIgaW4gcHJlZikgdmFsID09IHByZWYudXNlckNob2ljZQ0KCQkJCT8gbm9kZS5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgiY29sb3IiKQ0KCQkJCTogbm9kZS5zdHlsZS5zZXRQcm9wZXJ0eSgiY29sb3IiLCAibWFyb29uIiwgImltcG9ydGFudCIpDQoJCQl1c2VyDQoJCQkJPyBub2RlLnN0eWxlLnNldFByb3BlcnR5KCJmb250LXdlaWdodCIsICJib2xkIiwgImltcG9ydGFudCIpDQoJCQkJOiBub2RlLnN0eWxlLnJlbW92ZVByb3BlcnR5KCJmb250LXdlaWdodCIpOw0KDQoJCQl2YXIge2xhYn0gPSBwcmVmOw0KCQkJaWYgKGV4aXN0cyAmJiAhcHJlZi5ib29sKSB7DQoJCQkJaWYgKHZhbCBpbiBwcmVmLnZhbHMpIHZhciBzZnggPSBwcmVmLnZhbHNbdmFsXSB8fCB2YWw7DQoJCQkJZWxzZSB2YXIgc2Z4ID0gdXNlciA/ICJPdGhlciIgOiAiRGVmYXVsdCI7DQoJCQkJbGFiICs9IGAg4oCUICIke3NmeH0iYDsNCgkJCX0NCgkJCW5vZGUuc2V0QXR0cmlidXRlKCJsYWJlbCIsIGxhYik7DQoJCX0sDQoJCWNyZWF0ZVJhZGlvcyhkb2MsIHZhbHMsIHBvcHVwKSB7DQoJCQlmb3IodmFyIGFyciBvZiB2YWxzKSB7DQoJCQkJaWYgKCFhcnIpIHsNCgkJCQkJcG9wdXAuYXBwZW5kKGRvYy5jcmVhdGVFbGVtZW50TlMoeHVsX25zLCAibWVudXNlcGFyYXRvciIpKTsNCgkJCQkJY29udGludWU7DQoJCQkJfQ0KCQkJCXZhciBbdmFsLCBsYWIsIGtleSwgdHR0XSA9IGFycjsNCgkJCQl2YXIgbWVudWl0ZW0gPSBkb2MuY3JlYXRlRWxlbWVudE5TKHh1bF9ucywgIm1lbnVpdGVtIik7DQoJCQkJbWVudWl0ZW0uc2V0QXR0cmlidXRlKCJ0eXBlIiwgInJhZGlvIik7DQoJCQkJbWVudWl0ZW0uc2V0QXR0cmlidXRlKCJjbG9zZW1lbnUiLCAibm9uZSIpOw0KCQkJCW1lbnVpdGVtLnNldEF0dHJpYnV0ZSgibGFiZWwiLCBwb3B1cC5wYXJlbnROb2RlLnByZWYudmFsc1t2YWxdID0gbGFiKTsNCgkJCQlrZXkgJiYgbWVudWl0ZW0uc2V0QXR0cmlidXRlKCJhY2Nlc3NrZXkiLCBrZXkpOw0KCQkJCXZhciB0aXAgPSBtZW51aXRlbS52YWwgPSB2YWw7DQoJCQkJaWYgKHR0dCkgdGlwICs9ICJcbiIgKyB0dHQ7DQoJCQkJbWVudWl0ZW0udG9vbHRpcFRleHQgPSB0aXA7DQoJCQkJcG9wdXAuYXBwZW5kKG1lbnVpdGVtKTsNCgkJCX0NCgkJfSwNCgkJb3BlblBvcHVwKHBvcHVwKSB7DQoJCQl2YXIgYnRuID0gcG9wdXAucGFyZW50Tm9kZTsNCgkJCWlmIChidG4uZG9tUGFyZW50ICE9IGJ0bi5wYXJlbnROb2RlKSB7DQoJCQkJYnRuLmRvbVBhcmVudCA9IGJ0bi5wYXJlbnROb2RlOw0KCQkJCXZhciBwb3M7DQoJCQkJaWYgKGJ0bi5tYXRjaGVzKCIud2lkZ2V0LW92ZXJmbG93LWxpc3QgPiA6c2NvcGUiKSkNCgkJCQkJcG9zID0gImFmdGVyX3N0YXJ0IjsNCgkJCQllbHNlIHZhciB3aW4gPSBidG4ub3duZXJHbG9iYWwsIHt3aWR0aCwgaGVpZ2h0LCB0b3AsIGJvdHRvbSwgbGVmdCwgcmlnaHR9ID0NCgkJCQkJYnRuLmNsb3Nlc3QoInRvb2xiYXIiKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSwgcG9zID0gd2lkdGggPiBoZWlnaHQNCgkJCQkJCT8gYCR7d2luLmlubmVySGVpZ2h0IC0gYm90dG9tID4gdG9wID8gImFmdGVyIiA6ICJiZWZvcmUifV9zdGFydGANCgkJCQkJCTogYCR7d2luLmlubmVyV2lkdGggLSByaWdodCA+IGxlZnQgPyAiZW5kIiA6ICJzdGFydCJ9X2JlZm9yZWA7DQoJCQkJZm9yKHZhciBwIG9mIGJ0bi5wb3B1cHMpIHAuc2V0QXR0cmlidXRlKCJwb3NpdGlvbiIsIHBvcyk7DQoJCQl9DQoJCQlwb3B1cC5vcGVuUG9wdXAoYnRuKTsNCgkJfSwNCgkJbWF5YmVSZXN0YXJ0KG5vZGUsIGNvbmYpIHsNCgkJCXZhciBtc2dSZXN0ID0gIlJlc2FydD8iLCBtc2dBYm9ydCA9ICJUaGUgcXVpdCByZXF1ZXN0IGhhcyBiZWVuIGNhbmNlbGVkLiI7DQoJCQlpZiAocHYgPj0gNzcpIHsNCgkJCQl2YXIgdGl0bGUgPSBub2RlLmNsb3Nlc3QoInRvb2xiYXJidXR0b24iKS5sYWJlbDsNCgkJCQl2YXIgcHAgPSBkb21XaW4gPT4gU2VydmljZXMucHJvbXB0LndyYXBwZWRKU09iamVjdC5waWNrUHJvbXB0ZXIoew0KCQkJCQlkb21XaW4sIG1vZGFsVHlwZTogQ2kubnNJUHJvbXB0Lk1PREFMX1RZUEVfV0lORE9XDQoJCQkJfSk7DQoJCQkJdmFyIGNvbmZpcm0gPSB3aW4gPT4gcHAod2luKS5jb25maXJtKHRpdGxlLCBtc2dSZXN0KTsNCgkJCQl2YXIgYWxlcnQgPSB3aW4gPT4gcHAod2luKS5hbGVydCh0aXRsZSwgbXNnQWJvcnQpOw0KCQkJfSBlbHNlIHsNCgkJCQl2YXIgY29uZmlybSA9IHdpbiA9PiB3aW4uY29uZmlybShtc2dSZXN0KTsNCgkJCQl2YXIgYWxlcnQgPSB3aW4gPT4gd2luLmFsZXJ0KG1zZ0Fib3J0KTsNCgkJCX0NCgkJCXJldHVybiAodGhpcy5tYXlCZVJlc3RhcnQgPSAobm9kZSwgY29uZikgPT4gew0KCQkJCXZhciB3aW4gPSBub2RlLm93bmVyR2xvYmFsOw0KCQkJCWlmIChjb25mICYmICFjb25maXJtKHdpbikpIHJldHVybjsNCgkJCQlpZiAod2luLkJyb3dzZXJVdGlscy5yZXN0YXJ0QXBwbGljYXRpb24oKSA9PT0gZmFsc2UpIGFsZXJ0KHdpbik7DQoJCQkJZWxzZSByZXR1cm4gdHJ1ZTsNCgkJCX0pKG5vZGUsIGNvbmYpOw0KCQl9LA0KCQlyZWdleHBSZWZyZXNoOiAvXig/OnZpZXctc291cmNlOik/KD86aHR0cHM/fGZ0cCkvLA0KCQltYXliZVJlKG5vZGUpIHsNCgkJCXZhciB7cHJlZn0gPSBub2RlOw0KCQkJaWYgKCJyZXN0YXJ0IiBpbiBwcmVmKSB7DQoJCQkJaWYgKHRoaXMubWF5YmVSZXN0YXJ0KG5vZGUsIHByZWYucmVzdGFydCkpIHJldHVybjsNCgkJCX0NCgkJCWVsc2UgdGhpcy5wb3B1cHNob3dpbmcobnVsbCwgbm9kZS5wYXJlbnROb2RlKTsNCgkJCWlmICgicmVmcmVzaCIgaW4gcHJlZikgew0KCQkJCXZhciB3aW4gPSBub2RlLm93bmVyR2xvYmFsOw0KCQkJCWlmICh0aGlzLnJlZ2V4cFJlZnJlc2gudGVzdCh3aW4uZ0Jyb3dzZXIuY3VycmVudFVSSS5zcGVjKSkgcHJlZi5yZWZyZXNoDQoJCQkJCT8gd2luLkJyb3dzZXJSZWxvYWRTa2lwQ2FjaGUoKSA6IHdpbi5Ccm93c2VyUmVsb2FkKCk7DQoJCQl9DQoJCX0sDQoJCWNvbW1hbmQoZSkgew0KCQkJdmFyIHRyZyA9IGUudGFyZ2V0Ow0KCQkJaWYgKHRyZy5ub2RlTmFtZS5zdGFydHNXaXRoKCJ0IikpDQoJCQkJcmV0dXJuIHRoaXMub3BlblBvcHVwKHRyZy5wcmltYXJ5UG9wdXApOw0KDQoJCQl2YXIgbm9kZSA9IHRyZy5jbG9zZXN0KCJtZW51IikgfHwgdHJnOw0KCQkJdmFyIG5ld1ZhbCA9ICJwcmVmIiBpbiB0cmcgPyAhdHJnLnByZWYudmFsIDogdHJnLnZhbDsNCgkJCWlmIChuZXdWYWwgPT0gbm9kZS5wcmVmLnZhbCkgcmV0dXJuOw0KCQkJbm9kZS5wcmVmLnNldChub2RlLnByZWYucHJlZiwgbmV3VmFsKTsNCgkJCXRoaXMubWF5YmVSZShub2RlKTsNCgkJfSwNCgkJcG9wdXBzaG93aW5nKGUsIHRyZyA9IGUudGFyZ2V0KSB7DQoJCQlpZiAodHJnLmlkKSB7DQoJCQkJZm9yKHZhciBub2RlIG9mIHRyZy5jaGlsZHJlbikgew0KCQkJCQlpZiAobm9kZS5ub2RlTmFtZS5lbmRzV2l0aCgiciIpKSBjb250aW51ZTsNCgkJCQkJdGhpcy51cGQobm9kZSk7DQoJCQkJCSFlICYmIG5vZGUub3BlbiAmJiB0aGlzLnBvcHVwc2hvd2luZyhudWxsLCBub2RlLnF1ZXJ5U2VsZWN0b3IoIm1lbnVwb3B1cCIpKTsNCgkJCQl9DQoJCQkJcmV0dXJuOw0KCQkJfQ0KCQkJdmFyIHt2YWx9ID0gdHJnLmNsb3Nlc3QoIm1lbnUiKS5wcmVmOw0KCQkJdmFyIGNoZWNrZWQgPSB0cmcucXVlcnlTZWxlY3RvcigiW2NoZWNrZWRdIik7DQoJCQlpZiAoY2hlY2tlZCkgew0KCQkJCWlmIChjaGVja2VkLnZhbCA9PSB2YWwpIHJldHVybjsNCgkJCQllbHNlIGNoZWNrZWQucmVtb3ZlQXR0cmlidXRlKCJjaGVja2VkIik7DQoJCQl9DQoJCQlmb3IodmFyIG5vZGUgb2YgdHJnLmNoaWxkcmVuKSBpZiAoInZhbCIgaW4gbm9kZSAmJiBub2RlLnZhbCA9PSB2YWwpIHsNCgkJCQlub2RlLnNldEF0dHJpYnV0ZSgiY2hlY2tlZCIsIHRydWUpOw0KCQkJCWJyZWFrOw0KCQkJfQ0KCQl9LA0KCQljb250ZXh0bWVudShlKSB7DQoJCQl2YXIgdHJnID0gZS50YXJnZXQ7DQoJCQlpZiAodHJnLm5vZGVOYW1lLnN0YXJ0c1dpdGgoInQiKSkgew0KCQkJCWlmIChlLmN0cmxLZXkgfHwgZS5zaGlmdEtleSkgcmV0dXJuOw0KCQkJCWlmIChlLmRldGFpbCA9PSAyKSByZXR1cm4gdHJnLnNlY29uZGFyeVBvcHVwLmhpZGVQb3B1cCgpOw0KCQkJCXRoaXMub3BlblBvcHVwKHRyZy5zZWNvbmRhcnlQb3B1cCk7DQoJCQl9DQoJCQllbHNlIGlmICgicHJlZiIgaW4gdHJnICYmIHRyZy5wcmVmLnVzZXIpDQoJCQkJcHJlZnMuY2xlYXJVc2VyUHJlZih0cmcucHJlZi5wcmVmKSwNCgkJCQl0aGlzLm1heWJlUmUodHJnKTsNCgkJCWUucHJldmVudERlZmF1bHQoKTsNCgkJfQ0KCX07DQp9KTs=

Duche пишет

для FF710"Удалить активную вкладку из папки закладок"

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

Выделить код

Код:

((popup, menugroup, bs) => addEventListener("popupshowing", {
	async handleEvent() {
		if (await this.shouldHide()) return;
		var before = popup.children[1];
		//var before = popup.querySelector("#page-menu-separator + *");  Строка ниже..........................
		var menuitem = document.createXULElement("menuitem");
		var attrs = {
			label: "Удалить эту страницу из закладок",
			class: "menuitem-iconic menuitem-with-favicon",
			oncommand: "removeBookmarks();"
		};
		for(var attr in attrs) menuitem.setAttribute(attr, attrs[attr]);
		popup.insertBefore(menuitem, before);
		addDestructor(() => menuitem.remove());

		var crop = (str, limit = 100) => str.length <= limit ? str : str.slice(0, limit) + "…";
		var url = "chrome://global/content/alerts/alert.x";
		try {await fetch(url + "html", {method: "head"}); url += "html";} catch {url += "ul";}
		var notify = (num, msg) => {
			var forms = gNavigatorBundle.getString("editBookmark.removeBookmarks.label").replace(/ть/g, "л");
			(notify = (num, msg) => setTimeout(win => win.close(), 3e3, openDialog(
				url, "", "popup=yes", menuitem.image,
				PluralForm.get(num, forms).replace("#1", num), msg, false, null, 4
			)))(num, msg);
		}
		menuitem.removeBookmarks = async () => {
			var msg = crop(this.bookmarks.spec) + "\n\n\Из:\n", num = 0;
			for(var bookmark of this.bookmarks) {
				try {
					var title = bs.getLocalizedTitle(await bs.fetch({guid: bookmark.parentGuid}));
					await bs.remove(bookmark);
				} catch {continue;}
				num++; msg += `\n${title || "[Безымянная папка]"}`;
			}
			gBrowser.removeCurrentTab();
			notify(num, msg);
		}
		this.collect = this.bookmarks.add.bind(this.bookmarks);
		var setIcon = () => menuitem.image = "page-icon:" + this.bookmarks.spec;
		this.handleEvent = async () => (menuitem.hidden = await this.shouldHide()) || setIcon();
		setIcon();
	},
	shouldHide() {
		var bms = this.bookmarks = new Set(), collect = bms.add.bind(bms);
		return (this.shouldHide = async () => menugroup.hidden || bms.clear() ||
			!(await bs.fetch({url: bms.spec = gBrowser.currentURI.spec}, collect, this)))();
	},
	concurrent: true
}, false, popup))(
	document.getElementById("contentAreaContextMenu"),
	document.getElementById("context-navigation"), PlacesUtils.bookmarks
);

Отсутствует

 

№1489510-08-2020 18:56:32

firepox
Участник
 
Группа: Members
Зарегистрирован: 17-11-2011
Сообщений: 358
UA: Firefox 56.0

Re: Custom Buttons

Dumby
огромное спасибо
а куда вставить код?

Отсутствует

 

№1489610-08-2020 19:03:01

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

Re: Custom Buttons

firepox
Эээ...


firepox пишет

помогите подправить код

Заменить функцию saveToFile, видимо.
Она там в самом начале определяется.

Отсутствует

 

№1489710-08-2020 19:08:17

firepox
Участник
 
Группа: Members
Зарегистрирован: 17-11-2011
Сообщений: 358
UA: Firefox 56.0

Re: Custom Buttons

ничего не происходит при нажатии
огромная просьба, можно весь код кнопки с исправлениями
спасибо

Отредактировано firepox (10-08-2020 19:08:41)

Отсутствует

 

№1489810-08-2020 19:24:06

Duche
Участник
 
Группа: Members
Зарегистрирован: 07-02-2016
Сообщений: 209
UA: unknown 0.0

Re: Custom Buttons

Dumby.  Спасибо большое за помощь.

Отсутствует

 

№1489910-08-2020 19:41:38

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

Re: Custom Buttons

firepox пишет

ничего не происходит при нажатии
огромная просьба, можно весь код кнопки с исправлениями

Вот шляпа, всё надо проверять.
Недоглядел, что fileName кривой передаётся. Хорошо, весь

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

Выделить код

Код:

var saveToFile = this.stf || (this.stf = (suc => {
    suc.charset = "utf-8";
    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
    var alertName = "Save_snapshot_to_html_alert";
    var notify = as.showAlertNotification.bind(
        as, null, "Страница сохранена на Рабочем столе", null, false, null, null, alertName
    );
    var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
    var fos = Components.Constructor("@mozilla.org/network/file-output-stream;1", "nsIFileOutputStream", "init");
    return (html, name) => {
        var file = desk.clone()
        file.append(name);
        html = suc.ConvertFromUnicode(html);
        var stream = new fos(file, 0x02|0x20|0x08, 0o666, 0);
        stream.write(html, html.length);
        stream.close();
        notify();
        setTimeout(as.closeAlert, 2e3, alertName);
    }
})(Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter)));

var resolveURL = function (url, base) {
    try {
        var ioService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
        var baseURI = ioService.newURI(base, null, null);
        var absURI = ioService.newURI(url, null, baseURI);
        return absURI.spec;
    } catch (e) {}
};

var getSelWin = function (w) {
    if (w.getSelection().toString()) return w;
    for (var i = 0, f, r; f = w.frames[i]; i++) {
        try {
            if (r = getSelWin(f)) return r;
        } catch(e) {}
    }
};
var encodeImg = function (src, obj) {
    var canvas, img, ret = src;
    if (/^https?:\/\//.test(src)) {
        canvas = doc.createElement('canvas');
        if (!obj || obj.nodeName.toLowerCase() != 'img') {
            img = doc.createElement('img');
            img.src = src;
        } else {
            img = obj;
        };
        if (img.complete) try{
            canvas.width = img.width;
            canvas.height = img.height;
            canvas.getContext('2d').drawImage(img, 0, 0);
            ret = canvas.toDataURL((/\.jpe?g/i.test(src) ? 'image/jpeg' : 'image/png'));
        } catch (e) {};
        if (img != obj) img.src = 'about:blank';
    };
    return ret;
};
var toSrc = function (obj) {
    var strToSrc = function (str) {
        var chr, ret = '', i = 0, meta = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\x22' : '\\\x22', '\\': '\\\\'};
        while (chr = str.charAt(i++)) {
            ret += meta[chr] || chr;
        };
        return '\x22' + ret + '\x22';
    },
    arrToSrc = function (arr) {
        var ret = [];
        for (var i = 0; i < arr.length; i++) {
            ret[i] = toSrc(arr[i]) || 'null';
        };
        return '[' + ret.join(',') + ']';
    },
    objToSrc = function (obj) {
        var val, ret = [];
        for (var prop in obj) {
            if (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) ? String(obj) : 'null';
        case 'Object': return objToSrc(obj);
        case 'String': return strToSrc(obj);
        default: return obj ? (obj.nodeType == 1 && obj.id ? 'document.getElementById(' + strToSrc(obj.id) + ')' : '{}') : 'null';
    }
};

var mainWin = document.commandDispatcher.focusedWindow.top == content ? document.commandDispatcher.focusedWindow : content;
var selWin = getSelWin(mainWin), win = selWin || mainWin, doc = win.document, loc = win.location;
var ele, pEle, clone, reUrl = /(url\(\x22)(.+?)(\x22\))/g;

if (selWin) {
    var rng = win.getSelection().getRangeAt(0);
    pEle = rng.commonAncestorContainer;
    ele = rng.cloneContents();
} else {
    pEle = doc.documentElement;
    ele = (doc.body || doc.getElementsByTagName('body')[0]).cloneNode(true);
};
while (pEle) {
    if (pEle.nodeType == 1) {
        clone = pEle.cloneNode(false);
        clone.appendChild(ele);
        ele = clone;
    };
    pEle = pEle.parentNode
};
var sel = doc.createElement('div');
sel.appendChild(ele);

for (var el, all = sel.getElementsByTagName('*'), i = all.length; i--;) {
    el = all[i];
    if (el.style && el.style.backgroundImage) el.style.backgroundImage = el.style.backgroundImage.replace(reUrl, function (a, prev, url, next) {
        if (!/^[a-z]+:/.test(url)) url = resolveURL(url, loc.href);
        return prev + encodeImg(url) + next;
    });
    switch (el.nodeName.toLowerCase()) {
        case 'link':
        case 'style':
        case 'script': el.parentNode.removeChild(el); break;
        case 'a': 
        case 'area': if (el.hasAttribute('href') && el.getAttribute('href').charAt(0) != '#') el.href = el.href; break;
        case 'img':
        case 'input': if (el.hasAttribute('src')) el.src = encodeImg(el.src, el); break;
        case 'audio':
        case 'video':
        case 'embed':
        case 'frame':
        case 'iframe': if (el.hasAttribute('src')) el.src = el.src; break;
        case 'object': if (el.hasAttribute('data')) el.data = el.data; break;
        case 'form': if (el.hasAttribute('action')) el.action = el.action; break;
    }
};

var head = ele.insertBefore(doc.createElement('head'), ele.firstChild);
var meta = doc.createElement('meta');
meta.httpEquiv = 'content-type';
meta.content = 'text/html; charset=utf-8';
head.appendChild(meta);
var title = doc.getElementsByTagName('title')[0];
if (title) head.appendChild(title.cloneNode(true));

head.copyScript = function (unsafeWin) {
    if ('$' in unsafeWin) return;
    var f = doc.createElement('iframe');
    f.src = 'about:blank';
    f.setAttribute('style', 'position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;');
    doc.documentElement.appendChild(f);
    var str, script = doc.createElement('script');
    script.type = 'text/javascript';
    for (var name in unsafeWin) {
        if (name in f.contentWindow || !/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) continue;
        try {
            str = toSrc(unsafeWin[name]);
            if (!/\{\s*\[native code\]\s*\}/.test(str)) {
                script.appendChild(doc.createTextNode('var ' + name + ' = ' + str.replace(/<\/(script>)/ig, '<\\/$1') + ';\n'));
            }
        } catch (e) {};
    };
    f.parentNode.removeChild(f);
    if (script.childNodes.length) this.nextSibling.appendChild(script);
};
head.copyScript(win.wrappedJSObject || win);

head.copyStyle = function (s) {
    if (!s) return;
    var style = doc.createElement('style');
    style.type = 'text/css';
    if (s.media && s.media.mediaText) style.media = s.media.mediaText;
    try {
        for (var i = 0, rule; rule = s.cssRules[i]; i++) {
            if (rule.type != 3) {
                if((!rule.selectorText || rule.selectorText.indexOf(':') != -1) || (!sel.querySelector || sel.querySelector(rule.selectorText))) {
                    var css = !rule.cssText ? '' : rule.cssText.replace(reUrl, function (a, prev, url, next) {
                        if (!/^[a-z]+:/.test(url)) url = resolveURL(url, s.href || loc.href);
                        if(rule.type == 1 && rule.style && rule.style.backgroundImage) url = encodeImg(url);
                        return prev + url + next;
                    });
                    style.appendChild(doc.createTextNode(css + '\n'));
                }
            } else {
                this.copyStyle(rule.styleSheet);
            }
        }
    } catch(e) {
        if (s.ownerNode) style = s.ownerNode.cloneNode(false);
    };
    this.appendChild(style);
};
var sheets = doc.styleSheets;
for (var j = 0; j < sheets.length; j++) head.copyStyle(sheets[j]);
head.appendChild(doc.createTextNode('\n'));

var doctype = '', dt = doc.doctype;
if (dt && dt.name) {
    doctype += '<!DOCTYPE ' + dt.name;
    if (dt.publicId) doctype += ' PUBLIC \x22' + dt.publicId + '\x22';
    if (dt.systemId) doctype += ' \x22' + dt.systemId + '\x22';
    doctype += '>\n';
};
var fileName = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());
fileName = fileName.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');
fileName += ("  " + new Date().toLocaleFormat("%d.%m.%Y. %H-%M-%S"));
if(!/\.html?$/.test(fileName))fileName += '.html';

saveToFile(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->', fileName);

Отсутствует

 

№1490010-08-2020 19:43:59

firepox
Участник
 
Группа: Members
Зарегистрирован: 17-11-2011
Сообщений: 358
UA: Firefox 56.0

Re: Custom Buttons

Dumby
огромное спасибо
работает :rock:

Отсутствует

 

Board footer

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