Почему-то русская ночная сборка под Win не обновлялась с 15-го.
Последняя крашится при закрытии вкладок. Наверное, виноват плагин с флешем, потому что при его отключении проблема пропадает (обновлял Shockwave Flash до беты 11.4.400.252, но это не помогало).
Может, кому пригодится (хотя, наверное, такое добро всё время постят :)
Кнопка создаёт в контекстном меню подменю с настраиваемыми пользователем вставками.
[spoiler][code]
'use strict';
/******************************************************************************/
// \x01 = selected text. \x02 = clipboard content.
var clips = {
"mail": "somebody@gmail.com",
"link": "<a href='\x02'>\x01</a>",
"image": "<img src='\x02'>",
"bold": "<span style='font-weight: bold'>\x01</span>",
"italic": "<span style='font-style: italic'>\x01</span>",
}
/******************************************************************************/
var transferService = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
transferService.addDataFlavor("text/unicode");
var clipboardService = Components.classes["@mozilla.org/widget/clipboard;1"].getService(Components.interfaces.nsIClipboard);
/*********************
hydrolizer
Спасибо.
Infocatcher
Мне спокойнее работать поближе к стандартам (поэтому не хочется ничего переопределять): так код можно использовать и в других случаях, не только с CustomButton. Да и в случае с addEventListener причина тоже не догматическая: хочется оставлять на будущее максимально доступное место для манёвров.
Infocatcher, bunda1
Да, любой из этих кодов работает:
-----------------------------------------------------------------
this.clickBtn = function(event) {
if (event.button == 0) {
event.preventDefault();
alert("cb click " + Date.now());
}
}
this.addEventListener("click", this.clickBtn, true);
this.onDestroy = function() {
this.removeEventListener("click", this.clickBtn, true);
}
-----------------------------------------------------------------------------
this.clickBtn = function(event) {
if (event.button == 0) {
event.preventDefault();
alert("cb click " + Date.now());
}
}
this.onclick = this.clickBtn;
---------------------------------------------
Жаль только, что оба не очень красивы (добавления свойств window и подавно хотелось бы избегать). Onclick обычно советуют заменять на addEventListener (гибкий и стандартизированный метод), а вся эта суматоха с onDestroy выглядит костылями.
Большое спасибо всем за помощь.
…Infocatcher
Ваш код двоится при пересохранении, потому что анонимная функция не может восприниматься как один и тот же обработчик, она всегда создаётся заново (см., например. этот раздел по поводу анонимный функций).
Попробую сейчас помудрить с onDestroy. Тут есть рецепт с window, но он меня немного пугает. Да и неправильное ведь всё равно поведение получается с этими обработчиками.
bunda1
Попробую и так, спасибо.
Может, они дублируются, только если функция анонимна или если она объявлена, но не привязана как свойство к кнопке?
okkamas_knife
Проверил на 13.0.1. Та же самая проблема, только при инициализации после закрытия палитры в консоли появляется сообщение об ошибке:
Ошибка: uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIObserverService.removeObserver]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: chrome://browser/content/search/search.xml :: :: line 90" data: no]
Однако оно относится не к расширению, а к панели поиска (если его удалить в палитру, при последующих закрытиях палитры этой ошибки не возникает, но обработчики событий всё равно наслаиваются). Так что у меня и на 13.0.1 та же проблема. А вы проверяли на 13.0?
okkamas_knife
Какой именно код некорректный и в чём?
Удаление не помогает, этот код ведёт себя точно так же:
this.clickBtn = function(event) {
if (event.button == 0) {
event.preventDefault();
alert("cb click " + Date.now());
}
}
this.removeEventListener("click", this.clickBtn, true);
this.addEventListener("click", this.clickBtn, true);
В упомянутой цитате сказано, что при добавлении такого же обработчика с теми же параметрами удалять не нужно, дубликаты отбрасываются. Можно предположить, что при переинициализации this.clickBtn — уже другая функция (даже если её код одинаков), поэтому происходит дублирование и поэтому удаление бесполезно. Но почему же при редактировании кнопки такого эффекта нет, хотя и тогда происходит повторная инициализация?
Скажите, пожалуйста, почему при переинициализации всех кнопок (она происходит каждый раз, когда закрывается палитра инструментов при настройке панелей инструментов) обработчики событий, заданные в коде инициализации, дублируются? Однако при редактировании кнопки такого не происходит.
Здесь, например, написано:
If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded. They do not cause the EventListener to be called twice, and since the duplicates are discarded, they do not need to be removed manually with the removeEventListener method.
Однако для такой тестовой кнопки:
this.clickBtn = function(event) {
if (event.button == 0) {
event.preventDefault();
alert("cb click " + Date.now());
}
}
this.addEventListener("click", this.clickBtn, true);
каждая переинициализация после закрытия
…Infocatcher
Спасибо за информацию, не знал. Привычная предосторожность в наследство от создания расширений. Сейчас подправлю.
hydrolizer
Спасибо.
Кстати, оказывается, не обязательно вызывать ошибку, чтобы проверить существование ключа. Поскольку из кнопки можно создать только пользовательскую настройку, существование можно проверять методом prefHasUserValue. На MDN говорится: In particular, when no default value exists for a preference, prefHasUserValue() indicates whether a preference exists.
В общем, код инициализации ключа может быть такой:
[code]
var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
var prefBranch = prefService.getBranch("cb_storage.");
var supportsString = Components.interfaces.nsISupportsString;
if (!prefBranch.prefHasUserValue("obj_1")) {
var uStr = Components.classes["@mozilla.org/supports-string;1"].createInstance(supportsString);
uStr.data = JSON.stringify({"ключ_1": "значение_1", "ключ_2": "значение_2"});
prefBr
Infocatcher
Спасибо. Насколько я понял из опытов, использовать getDefaultBranch вне расширения нет смысла, потому что созданные ключи не сохраняются в файл настроек и не восстанавливаются после перезапуска. Но система пользовательских настроек вроде бы работает.
Kamui
okkamas_knife
Большое спасибо. Не думал, что set...Pref не только изменяет значения, но и создаёт ключи при их отсутствии.
Кстати, удивился, что у nsIPrefService тоже есть методы set...Pref, на MDN они значатся только в nsIPrefBranch.
Скажите, пожалуйста, есть ли какой-то способ сохранять данные из кода кнопки между сессиями?
1. Использовать Preferences, как это делают расширения, не получится: из кода кнопки можно только получить или изменить значение, но не создать новый ключ (создавать можно или вручную из about:config, или в файлах настроек расширений, или через user.js, но всё это не подходит).
2. Использовать простой файл или базу данных слишком сложно.
3. Использовать Local storage тоже не получается, потому кнопка не связана со страницами браузера (с объектом content), она лишь посылает и получает XMLHttpRequest, а у документов этого типа нет объекта window (defaultView), к которому был бы привязан Local storage.
Есть ли ещё какие-то способы хранить и восстанавливать данные?
Новые данные: http://habrahabr.ru/post/145953/
Пытаюсь реализовать в своём расширении для rutracker.org новые возможности XHR.
Не могу понять, почему данный код в девяти случаях из десяти уходит в таймаут.
var xhr = new XMLHttpRequest(); xhr.open("GET", "http://rutracker.org/forum/index.php", true); xhr.mozBackgroundRequest = true; xhr.timeout = 10000; xhr.responseType = "document"; xhr.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE; xhr.overrideMimeType('text/html; charset=windows-1251'); xhr.onload = function() { alert(this.responseXML.title); } xhr.onerror = function() { alert("Error!"); } xhr.ontimeout = function() { alert("Timeout!"); } xhr.send(null);
Причём относительно других сайтов всё работает правильно (отслеживаю таким образом обновления на нескольких форумах). В те редкие случаи, когда таймаута не происходит, http заголовки как запроса, так и ответа идентичны проблемным случаям, причём во всех случаях отве
…hydrolizer
Спасибо, не знал.
hydrolizer
Да, пожалуй, это логичное объяснение. Тогда, выходит, сама полумера с responseType = "document" не очень логична.
Не мог бы кто-нибудь из знатоков ответить здесь или на хабре?
Лия
Странно. У меня эта настройка активна. Fx 4.0.1, ILO 0.6.21.
Vitafresh
Ну, видите, мои опасения были не напрасны. Я ведь сразу предупреждал, что возможны проблемы. Там какие-то очень хитрые механизмы авторского модуля XPCOM, в которых я не очень хорошо разбираюсь. Например, обнаружил, что в четвёрке постоянно почему-то сбрасывается список фильтров и его нужно для каждой страницы, а то и для каждой картинки создавать заново, а это очень тормозит браузер. Так что пользуйтесь на свой страх и риск и простите, что не смог сделать лучше.
Shaggoth
Попробуй отключать расширения попеременно, может, уточнишь причину.
Shaggoth
К сожалению, не знаю. Хорошо бы, потому что заплатки мои сомнительны, а некоторые, думаю, кушают ресурсы больше чем следовало бы. Надеюсь, автор к нему вернётся.