Как настроить Firefox, чтобы Javascript мог перехватить значение, вставленное из буфера обмена?
Мне нужно отфильтровать определенные символы, когда пользователь вставляет из буфера обмена. (Я действительно не хочу изменять, что в буфере обмена.) У меня уже есть эта работа в IE. Вздох...
tl; dr: capability.policy
элементы в user.js превращают его в prefs.js, но не вступают в силу.
FYI, я могу разумно установить всех пользователей user.js. Но ни у кого из нас нет доступа администратора к нашим машинам, так что обо всем, что я могу сделать относительно конфигурации.
Спасибо за любую помощь!
Примечание:
- Для целей этого вопроса я не хочу "обойти" доступ к буфере обмена -
Например, я не хочу работать с значением элемента DOM после того, как вставляется паста
- Я не хочу решение, требующее framework/library (например, jQuery, Dojo, Prototype, YUI,... )
Выполненные шаги
- Определенное местоположение моей профиля, перейдя по адресу URL about: support= > Каталог профилей = > Open Containing Folder
- Попробовал включить буфер обмена в Firefox, создав user.js со следующими строками:
user_pref("just.mike", "test to see if user.js works.");
user_pref("capability.policy.policynames", "allowclipboard");
user_pref("capability.policy.allowclipboard.sites", "https://my-site.com");
user_pref("capability.policy.allowclipboard.Clipboard.cutcopy", "allAccess");
user_pref("capability.policy.allowclipboard.Clipboard.paste", "allAccess");
Примечание: https://my-site.com - это не настоящий сайт.
- Как оказалось, элементы
capability.policy
не отображаются с помощью about: config - из-за Bugzilla Bug 284673 - about: config скрывает предпочтения "capability.policy" . Однако я думаю, что эти user.js элементы "работали" и что файл находится в правильной папке, потому что впоследствии:
- about: config показала запись
just.mike
- prefs.js содержит все новые строки, но в другом порядке - в алфавитном порядке:
user_pref("capability.policy.allowclipboard.Clipboard.cutcopy", "allAccess");
user_pref("capability.policy.allowclipboard.Clipboard.paste", "allAccess");
user_pref("capability.policy.allowclipboard.sites", "https://my-site.com");
user_pref("capability.policy.policynames", "allowclipboard");
...
user_pref("just.mike", "test to see if user.js works.");
(FYI, я также пробовал Zallowclipboard
всюду, так что строка policynames
появилась сначала из-за алфавита, но это тоже не сработало).
- Попытался прочитать буфер обмена в Firefox после события
onpaste
со следующим:
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"].getService(Components.interfaces.nsIClipboard);
if (!clipboard) {
throw new Error('internal error -- could not create clipboard object');
}
var transferable = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
if (!transferable) {
throw new Error('internal error -- could not create transferable object');
}
transferable.addDataFlavor("text/unicode");
clipboard.getData(transferable, clipboard.kGlobalClipboard);
var clipboard_data = new Object();
var clipboard_length = new Object();
transferable.getTransferData("text/unicode", clipboard_data, clipboard_length);
var clipboard_text = '';
if (!!clipboard_data) {
var clipboard_nsISupportsString = clipboard_data.value.QueryInterface(Components.interfaces.nsISupportsString);
clipboard_text = clipboard_nsISupportsString.data.substring(0, clipboard_length.value / 2);
}
return(clipboard_text);
- Сбой кода в первой строке, возвращая эту ошибку в консоли Firebug:
Permission denied for <https://my-site.com> to get property XPCComponents.classes
Примечание. Я фактически запускаю его на реальном URL-адресе, который отображается в сообщении об ошибке. Я просто изменил его на фиктивное имя.
- Я также видел несколько других примеров, в которых
createInstance
использовался в первой строке вместо getService
, но первая строка все равно генерирует один и тот же текст ошибки:
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"].createInstance(Components.interfaces.nsIClipboard);
// ...
Окружающая среда (это не входит в мой контроль)
- Нет доступа администратора к компьютеру
- Windows Vista
- Mozilla Firefox 10
Ссылки
Ответы
Ответ 1
Короче говоря, я не думаю, что можно делать то, что вы хотите сделать, как вы хотите это сделать. Mozilla (и большинство современных браузеров) ограничивает доступ к буфер обмена по соображениям безопасности. То, что вы, похоже, легко преодолели это ограничение в IE, не является утешительной мыслью.
При этом плагины имеют разные ограничения, чем веб-страницы, и вы можете обойти это ограничение, написав одну (или, возможно, даже флэш-память). Тем не менее, даже с плагином я подозреваю, что единственный способ заблокировать кого-то вставить что-то в веб-форму (или что-то еще) - это упреждающая очистка буфера обмена.
Если все, что вы хотите сделать, это запретить ввод определенных строк в текстовое поле, лучше всего следить за событиями в самом текстовом поле.
Если я правильно читаю вас, похоже, вы хотите заставить своих пользователей вводить (и только вводить) что-то в форму, и я не могу придумать тривиальный способ сделать это. Пара нетривиальных опций:
- Установите текстовое поле на
readonly
и всплывайте виртуальную клавиатуру, чтобы заставить пользователя "ввести" в
поле с помощью мыши. (Вам пришлось бы строить клавиатуру самостоятельно из HTML и
JavaScript или найти подходящее решение где-нибудь.)
- Отслеживать событие
oninput
; если текстовое поле меняется быстрее, чем то, что может
разумно ожидать ввода типа, отклонения изменений.
Ни один из них не является точным, но если вы хотите создавать решения с использованием открытых веб-технологий, тогда вы должны принять ограничения на систему, которую вы строите поверх нее, а также ее преимущества.
Ответ 2
Grubby, но метод crossbrowser - сравнить значение текущего ввода с предыдущим событием onchange.
Если длина увеличивается или значение слишком сильно отличается (не только уменьшено, но и много новых символов), возможно, что-то вставляется из буфера обмена.
Что-то вроде этого:
$('input, textarea').change(function(){
var prev = $(this).data('prev-val'),
current = $(this).val();
if (is_big_changes(prev,current)) {
$(this).val(my_filter_func(current));
}
if (!prev) {
$(this).data('prev-val', current);
}
})
(это только доказательство концепции, поэтому я использовал jQuery, чтобы избежать большого количества кодирования)
Где is_big_changes и my_filter_func - функции, которые вам нужно реализовать.
Предупреждение. Множество злых ошибок потенциально возможно при таком подходе, и я знаю, это выглядит крайне уродливо. Моя сделка - это предложение.
Ответ 3
Можем ли мы сказать, что вам альтернативно нужно обнаружить пачку буфера обмена? Поскольку, когда вы знаете, что было раньше, вы знаете, что было изменено.
Так почему бы просто не зацепить меня? Все символы, идентичные началу и концу содержимого, не вставлены. Если вы хотите отличить это от простых нажатий клавиш, прислушайтесь к keydown/keypress, тогда вы знаете, какие изменения происходят из "в другом месте".