Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 15.12.2014, 09:25
Интересующийся
Отправить личное сообщение для нуб-нубом Посмотреть профиль Найти все сообщения от нуб-нубом
 
Регистрация: 15.12.2014
Сообщений: 13

замена текста на картинки
здравствуйте вам!
хочу сделать букмарклет для перевода китайского портала
перевод решено сделать картинками, т.к. иероглифы все стандартной длины, а наши слова очень разные, поэтому при замене текста очень ломается верстка.
пример:
<div id="replace_me">高於</div>

должно стать:
<div id="replace_me"><img src="myhost.ru/高於.jpeg"></div>

скорее всего, из иероглифа нужно вычислить хеш, чтобы мой сервер мог нормально отдать статичную картинку..
сделал так:
javascript:document.body.innerHTML = document.body.innerHTML.replace(/高於/g, '<img src="myhost.ru/高於.jpeg">');

но таким образом вся страница перерисовывается, причем без css. а еще не учел id.. возможно и не придется..
знания мои ниже базовых.. задача срочная.. по серверу впринципе, разберусь сам (если картинки нет, выдам заглушку).
что непонятно - уточню. прошу не пинать в сторону учебников, ибо некогда. форум перекопал.. если слеп, ткните носом.
основной затык - как сделать чтобы страничка перерисовывалась нормально или не вся страничка, а только заменяемый текст.
спасибо

Последний раз редактировалось нуб-нубом, 15.12.2014 в 09:27. Причина: уточнил
Ответить с цитированием
  #2 (permalink)  
Старый 15.12.2014, 10:10
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

Чтобы перерисовывался заменяемый текст, а не страница, надо заменять текст, а не страницу. Ваш капитан.

Вот функция обхода всех элементов, с заменой любого текста на картинки:
(function(){
    var elems = document.getElementsByTagName('*'), i = elems.length;
    while(i--) {
        var childs = elems[i].childNodes, j = childs.length;
        while(j--) if( childs[j].nodeType === 3 && /\S/.test( childs[j].data ) ){ //перебираем детей и если нода текстовая и не пустая
            var img = document.createElement('img'); //создаём картинку
            img.src = 'http://myhost.ru/' + childs[j].data + '.jpeg'; //добавляем в картинки адрес текст
            elems[i].replaceChild(img, childs[j]); //меняем текстовую ноду на картинку
        }        
    }
}())

Но разумнее заменять только тот текст, для которого есть перевод, заранее сделав список. А ещё разумнее(если кол-во перевода не велико) - обращаться напрямую к каждому элементу по id:
var el = document.getElementById('replace_me');
el.innerHTML = el.innerHTML.replace(/高於/g, '<img src="myhost.ru/高於.jpeg">')
__________________
29375, 35

Последний раз редактировалось Aetae, 15.12.2014 в 10:17.
Ответить с цитированием
  #3 (permalink)  
Старый 15.12.2014, 10:17
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

нуб-нубом,
собрать коллекцию textNode и appendChild часть текста или replaceChild весь текст ноды
Ответить с цитированием
  #4 (permalink)  
Старый 15.12.2014, 10:35
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

рони, что то я сейчас заморочился, универсальный вариант:
(function(){
    var locale = function(re, arr){ //сразу преобразуем массив в регулярное выражение
        var i = arr.length;
        while(i--)  arr[i] = arr[i].replace(re, '\\$&')
        return new RegExp(arr.join('|'), 'g')
    }(/[.*+?^${}()|\[\]\/\\]/g, [ //массив переведённых фраз
        '高於',
        'foo',
        'bar'
    ]);
    
    function replace(node){
        var frag = document.createDocumentFragment(), 
            div = document.createElement('div');
        div.appendChild(node.cloneNode());
        div.innerHTML = div.innerHTML.replace(locale, '<img src="http://myhost.ru/$&.jpeg">');
        while(div.hasChildNodes()) frag.appendChild(div.firstChild);            
        return frag       
    }
    
    var elems = document.getElementsByTagName('*'), i = elems.length;
    while(i--) {
        var childs = elems[i].childNodes, j = childs.length;
        while(j--) if( childs[j].nodeType === 3 && locale.test( childs[j].data ) ){ //перебираем детей и если нода текстовая и в ней есть переведённый текст 
            elems[i].replaceChild(replace(childs[j]), childs[j]); //меняем текстовую ноду на фрагмент докумета из текста и картинки
        }        
    }
}())
__________________
29375, 35
Ответить с цитированием
  #5 (permalink)  
Старый 15.12.2014, 11:11
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

Aetae,
Ответить с цитированием
  #6 (permalink)  
Старый 15.12.2014, 14:18
Интересующийся
Отправить личное сообщение для нуб-нубом Посмотреть профиль Найти все сообщения от нуб-нубом
 
Регистрация: 15.12.2014
Сообщений: 13

может, это слишком круто?
по моему нику ведь понятно, что мне ничего непонятно
на самом деле, понятно, что это универсальное решение, и оно сработает во многих случаях.. кроме моего
я хотел простенький букмарклет, а выходит, нужно писать нехилый скрипт.. нет времени это делать..
1. как упаковать функцию в букмарклет (нашел здесь-же на сайте)
2. не каждый элемент имеет id (каюсь)
соответственно, логика вырисовывается такая:
делаем список (массив?) id элементов внутри которых есть вложенные элементы без id, вот в этих вложенных элементах и будем менять текст.
<div id="rep1"><p>text1</p></div>
<div id="no_rep"><p>text2</p></div>
<div id="rep2"><p>text3</p></div>

список будет такой:
'rep1','rep2'

вот результат после работы букмарклета:
<div id="rep1"><p><img src="mysite.ru/text1.jpeg"></p></div>
<div id="no_rep"><p>text2</p></div>
<div id="rep2"><p><img src="mysite.ru/text3.jpeg"></p></div>

так я буду видеть на сервере на какие запросы я выдаю заглушку, соответственно эти слова мне надо доперевести.
и еще.. как все-таки сделать хеш, а не непонятные \x65\x22?
а еще.. *размечтался* воткнуть бы кусочек с моего сайта сразу после тега <body>..

Последний раз редактировалось нуб-нубом, 15.12.2014 в 14:53. Причина: очепятка
Ответить с цитированием
  #7 (permalink)  
Старый 15.12.2014, 16:11
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

нуб-нубом, используй первый вариант тогда, только замени
document.getElementsByTagName('*') 
на 
document.querySelectorAll('#rep1 *, #rep2 *, #repx *')

Чтоб текст был кодированным - замени
childs[j].data + '.jpeg'
на
encodeURIComponent(childs[j].data) + '.jpeg'
__________________
29375, 35
Ответить с цитированием
  #8 (permalink)  
Старый 15.12.2014, 17:03
Интересующийся
Отправить личное сообщение для нуб-нубом Посмотреть профиль Найти все сообщения от нуб-нубом
 
Регистрация: 15.12.2014
Сообщений: 13

крутяяк
только на сервер всеравно приходят кракозябры:
\xe9\xab\x98\xe6\x96\xbc что странно - в отладчике в хроме все кодируется, а на сервер летят такие странности.. тут дело явно не в скрипте
а еще цифры, символы, пробелы и \n
значит, нужно их отрезать? и не заменять строки, в которых есть что-то кроме иероглифов.. или в которых нет иероглифов.. капеец..

Последний раз редактировалось нуб-нубом, 15.12.2014 в 17:51. Причина: уточнил
Ответить с цитированием
  #9 (permalink)  
Старый 15.12.2014, 17:14
Интересующийся
Отправить личное сообщение для нуб-нубом Посмотреть профиль Найти все сообщения от нуб-нубом
 
Регистрация: 15.12.2014
Сообщений: 13

получается, что нужно удалить из строки всё специальное (цифры, символы, пробелы), и заменять ее только если она не пуста..
а еще строку нужно преобразовать в набор букво-цифр..

в итоге получилось так:
(function(){
    var elems = document.querySelectorAll('#rep1, #repx *'), i = elems.length;
    while(i--) {
        var childs = elems[i].childNodes, j = childs.length;
        while(j--) if( childs[j].nodeType === 3 && /\S/.test( childs[j].data ) ){
			var str = childs[j].data;
			var reg = /\s|\d|\.|%|\[|\]|\(|\)/gi;
			var res = str.replace( reg, '' );
			if( res.length ){
            	var img = document.createElement('img');
				img.src = 'http://mysite.ru/' + encodeURIComponent( res ) + '.jpeg';
				elems[i].replaceChild(img, childs[j]);
			}
        }        
    }
}())

и это работает.. но на самом деле, все неправильно

значит, надо так:
1. тянем с сервера массив переведенных иероглифов и линков на картинки выходит, каждый раз, когда я переведу очередную порцию, пользователь должен обновить скрипт? ааа.. так вот, что такое XSS.. блин..
2. с помощью querySelectorAll и childNodes выбираем что будем менять
3. меняем то, что есть на линки из массива..

Последний раз редактировалось нуб-нубом, 15.12.2014 в 22:23.
Ответить с цитированием
  #10 (permalink)  
Старый 17.12.2014, 01:22
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,577

Букмарклет:
javascript:(function(script,body,src){script.src=src;body.appendChild(script)}(document.createElement('script'),document.body,'http://site/script.js'));;

Скрипт который отдаёт сервер:
(function(){
  var dict = { //массив переведенных иероглифов и линков на картинки
    '高於' : 'http://site.ru/img1.jpg',
    'меняем' : 'http://site.ru/img2.jpg'
  }


  var locale = function(re, arr){ //сразу преобразуем список в регулярное выражение
    var i = arr.length;
    while(i--)  arr[i] = arr[i].replace(re, '\\$&')
    return new RegExp(Object.keys(dict).join('|'), 'g')
  }(/[.*+?^${}()|\[\]\/\\]/g, dict);

  function replace(node){
    var frag = document.createDocumentFragment(),
        div = document.createElement('div');
    div.appendChild(node.cloneNode());
    div.innerHTML = div.innerHTML.replace(locale, function(word) { return '<img src="' + dict[word] + '">' });
    while(div.hasChildNodes()) frag.appendChild(div.firstChild);           
    return frag      
  }

  var elems = document.getElementsByTagName('*'), i = elems.length;
  while(i--) {
    var childs = elems[i].childNodes, j = childs.length;
    while(j--) if( childs[j].nodeType === 3 && locale.test( childs[j].data ) ){ //перебираем детей и если нода текстовая и в ней есть переведённый текст
      elems[i].replaceChild(replace(childs[j]), childs[j]); //меняем текстовую ноду на фрагмент докумета из текста и картинки
    }       
  }
}())
__________________
29375, 35
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Замена текста при наведении Sirius-jack Общие вопросы Javascript 3 04.05.2013 05:16
[GreaseMonkey] Замена картинки на локальный ресурс VitAl2013 Firefox/Mozilla 6 13.04.2012 16:50
Замена частей текста Joshka Javascript под браузер 5 04.05.2011 05:10
Замена ссылок на картинки самими картинками shipitko Общие вопросы Javascript 3 23.07.2010 19:49
смайлы для чата, замена текста brain Общие вопросы Javascript 9 28.11.2008 21:35