Node.textContent ведёт себя как Node.innerHTML в протоколе javascript или генерация пароля в закладке браузера

от автора

Кроссбразуреная, кросплатформенная особенность задания (set) Node.textContent:

<a href="javascript:document.body.textContent = '<div>text</div>';">click</a> 

Вставит строчку как html код:

<div>text</div> 

Вступление

Для создания пароля можно использовать любые ASCII символы в диапазоне 32-126. Один из этих символов — знак меньше ("<"). Для удобства генерации пароля создал закладку (bookmark) в бразуре, в которой в url вместо ссылки на страницу используется протокол javascript.

JS генерирует пароль длиной n из набора доступных ASCII символов и вставляет в документ получившуюся строку с помощью document.body.textContent.

Url закладки

javascript:for(var a=[],i=0;i<95;i++)a.push(String.fromCharCode(32 + i));for(var b="",i=0;i<16;i++)b+=a[Math.floor(Math.random()*95)];document.body.textContent = b;

Более понятный js

document.body.textContent = createPassword();  function createPassword() {     var PASSWORD_LENGTH = 16;      var random = Math.random;     var allowedChars = getAllowedCharsArr();      for (var password = "", i = 0; i < PASSWORD_LENGTH; i++) {         var randomIndex = Math.floor(random() * allowedChars.length);         password += allowedChars[randomIndex]     }      return password; }  function getAllowedCharsArr() {     var FIRST_ALLOWED_ASCII_CHAR_INDEX = 32;     var ALLOWED_CHARS_COUNT = 95;      for (var allowedChars = [], i = 0; i < ALLOWED_CHARS_COUNT; i++) {         var asciiCode = FIRST_ALLOWED_ASCII_CHAR_INDEX + i;         var char = String.fromCharCode(asciiCode);         allowedChars.push(char)     }      return allowedChars; } 

Обнаружение

После некоторого использования закладки заметил, что иногда пароль отображается не полностью, т.е. первые k символов из всех, заранее заданых n.

Изучение

После некоторого изучения получил следующий код:

document.body.textContent = '<div>text</div>'; 

Если его запустить в консоли браузера, или в script теге html, javascript отработает как надо, т.е. вставит строку вместе с символами "<" и ">".

<div>text</div>

Особенность

Но если этот же код выполнить в протоколе javascript в документе окажется html элемент:

<a href="javascript:document.body.textContent = '<div>text</div>';">click</a> 

<div>text</div> 

Эфимерность

Причём если сохранить ссылку на переменную:

<a href="javascript:var str='<div>text</div>';document.body.textContent = str;window.test=function(){str}">click</a> 

Текст вставиться как надо:

<div>text</div>

Применение

На сайтах, где пользовательский текст вставляется через протокол javascript с использованием Node.textContent или Node.innerText для исполнения своих скриптов через тег script.

Решение

Для себя более удобным стало не вставлять текст в DOM а сразу копировать пароль в буффер обмена.

Закладка

javascript:for(var a=[],i=0;i<95;i++)a.push(String.fromCharCode(32 + i));for(var b="",i=0;i<16;i++)b+=a[Math.floor(Math.random()*95)];var c=document.createElement('input');c.style.opacity=0;document.body.appendChild(c); c.value=b;c.style.position='fixed';c.style.zIndex=1000000;c.focus();c.select(); document.execCommand('Copy');c.remove();

source

copyToClipBoard(createPassword());  function copyToClipBoard(str) {     var input = document.createElement('textarea');     document.body.appendChild(input);     input.value = str;     input.style.position = 'fixed';     input.style.zIndex = 1000000;     input.style.opacity = 0;     input.focus();     input.select();     document.execCommand('Copy');     input.remove(); }  function createPassword() {     var PASSWORD_LENGTH = 16;      var random = Math.random;     var allowedChars = getAllowedCharsArr();      for (var password = "", i = 0; i < PASSWORD_LENGTH; i++) {         var randomIndex = Math.floor(random() * allowedChars.length);         password += allowedChars[randomIndex]     }      return password; }  function getAllowedCharsArr() {     var FIRST_ALLOWED_ASCII_CHAR_INDEX = 32;     var ALLOWED_CHARS_COUNT = 95;      for (var allowedChars = [], i = 0; i < ALLOWED_CHARS_COUNT; i++) {         var asciiCode = FIRST_ALLOWED_ASCII_CHAR_INDEX + i;         var char = String.fromCharCode(asciiCode);         allowedChars.push(char)     }      return allowedChars; } 

P.S.: Вместо циклов можно использовать Array.map. Кто-то считает, что так элегантнее, кто-то замечает, что это медленнее — это уже дело вкуса.

Альтернатива

javascript:var a = Array.apply(null, Array(127)).map(String.fromCharCode, String).slice(32);var b = Array.apply(null, Array(16)).map(() => a[Math.floor(Math.random() * 95)]).join("");var c = document.createElement('input');document.body.appendChild(c);c.value = b;c.style.position = 'fixed';c.style.zIndex = 1000000;c.style.opacity = 0;c.focus();c.select();document.execCommand('Copy');c.remove();

P.P.S.: Вместо закладки можно использовать extenshion: например, chrome — это также дело вкуса.

ссылка на оригинал статьи http://habrahabr.ru/post/272189/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *