Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Изменение html элемента с помощью JS (https://javascript.ru/forum/misc/78119-izmenenie-html-ehlementa-s-pomoshhyu-js.html)

crabkilla 29.07.2019 15:07

Изменение html элемента с помощью JS
 
Всё тот же код из задания про удаление элемента, но теперь требуется заменить элемент с плохой картинкой спаном, в котором будет текст Now here is a ‘span’ element. внутри этого самого спана.
<!DOCTYPE html>
  <head>
    
  </head>
  <body>
    <p style="color: navy"> There's only picture here...
     <br>
     <img src="http://ipic.su/img/img7/fs/burger.1537205489.jpg" width="100px" height="100px" />
    </p>
    <br>
    <p> This one cannot be displayed. We have to replace it. 
     <img alt="bad picture">
    </p>
    
    <script type="text/javascript">
    var pElement=document.getElementsByTagName('p')[1];
    var imgElement=document.getElementsByTagName('img')[1];
    var sElement = document.createElement('span'); 
    var txt = "Now here is a ‘span’ element.";
    sElement.innerHTML = txt;
    pElement.replaceChild(sElement,imgElement);
    </script>
  </body>
</html>

Вот что получилось, в HTML текст отображается, но значение спана все ещё не соответствует тексту, даже не знаю как это поправить

ksa 29.07.2019 15:19

Цитата:

Сообщение от crabkilla
даже не знаю как это поправить

Его нужно добавить на страницу в нужное место... ;)

<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=windows-1251' />
<!--
<script src='https://code.jquery.com/jquery-latest.js'></script>
<script src="https://code.angularjs.org/1.3.9/angular.min.js"></script>
<script src="https://code.angularjs.org/1.3.9/angular-route.js"></script>
-->
<style type='text/css'>
</style>
<script type='text/javascript'>
</script>
</head>
<body>
<p style="color: navy"> There's only picture here...
	<br>
	<img src="http://ipic.su/img/img7/fs/burger.1537205489.jpg" width="100px" height="100px" />
</p>
<br>
<p> This one cannot be displayed. We have to replace it. 
	<img alt="bad picture">
</p>
<script type="text/javascript">
var imgElement=document.getElementsByTagName('img')[1];
var pElement=imgElement.parentNode;
var sElement = document.createElement('span'); 
sElement.innerHTML = "Now here is a ‘span’ element.";
pElement.removeChild(sElement,imgElement);
pElement.appendChild(sElement);
</script>
</body>
</html>

ksa 29.07.2019 15:25

Цитата:

Сообщение от crabkilla
даже не знаю как это поправить

Или так...
pElement.appendChild(sElement);
pElement.replaceChild(sElement,imgElement);

Т.е. на момент выполнения replaceChild() оба дитя должны существовать в родителе... ;)

Malleys 29.07.2019 15:56

ksa, 🌚

crabkilla, вот правильное решение...
Вариант №1 Одноразовое замещение ломанных картинок после загрузки...
<!DOCTYPE html>

<head></head>

<body>
	<p style="color: navy"> There's only picture here...
		<br>
		<img src="http://ipic.su/img/img7/fs/burger.1537205489.jpg" width="100px" height="100px" />
	</p>
	<br>
	<p id="pic"> This one cannot be displayed. We have to delete it.
		<img alt="bad picture">
	</p>

	<script>
		addEventListener("load", function() {
			for(const image of document.images) {
				if(image.naturalWidth === 0) {
					const node = document.createElement("span");
					node.textContent = "Now here is a ❄️.";
					image.replaceWith(node);
				}
			}
		});
	</script>
</body>

</html>


Вариант №2 Живое замещение ломанных картинок ...
<!DOCTYPE html>

<head></head>

<body>
	<script>
		const observer = new MutationObserver(mutationRecords => {
			for(const mutationRecord of mutationRecords) {
				if(mutationRecord.type === "childList") {
					for(const node of mutationRecord.addedNodes) {
						if(node instanceof HTMLImageElement) {
							if(!node.hasAttribute("src"))
								replaceBrokenImage(node);
							else
								node.addEventListener("error", ()=> replaceBrokenImage(node));
						}
					}
				}
			}
		});
		observer.observe(document.body, { childList: true, subtree: true });
		function replaceBrokenImage(image) {
			const node = document.createElement("span");
			node.textContent = "Now here is a ❄️.";
			image.replaceWith(node);
		}
	</script>
	<p style="color: navy"> There's only picture here...
		<br>
		<img src="http://ipic.su/img/img7/fs/burger.1537205489.jpg" width="100px" height="100px" />
	</p>
	<br>
	<p id="pic"> This one cannot be displayed. We have to delete it.
		<img alt="bad picture">
	</p>
</body>

</html>

Vlasenko Fedor 29.07.2019 16:20

Malleys,
создание элементов в цикле дорогая операция
для этого есть клонирование, фрагмент, insertAdjacentHTML ...
кроме того сам подход замены битых картинок средствами js напоминает (........)
вы правильно прочитали
для этого достаточно пару строк в nginx или htaсcess, обработать сервером

Malleys 29.07.2019 16:35

Цитата:

Сообщение от Poznakomlus
для этого достаточно пару строк в nginx или htaсcess, обработать сервером

Для этого есть Service Worker.

Цитата:

Сообщение от Poznakomlus
кроме того сам подход замены битых картинок средствами js напоминает (........)

Пока вы не придумали, что же оно означает... JavaScript является языком программирования общего назначения. Сеть является не единственным источником данных! Это может быть и файловая система и локальный кеш...

Цитата:

Сообщение от Poznakomlus
создание элементов в цикле дорогая операция

Однако программирование работает именно так! Циклы используют и при манипуляции узлов DOM и при разработке игр... А вы предлагаете unroll делать? (надеюсь не руками!)

Цитата:

Сообщение от Poznakomlus
пару строк в nginx или htaсces

и в итоге логика приложения будет размазана уже по 2-ум местам

Цитата:

Сообщение от Poznakomlus
создание элементов в цикле дорогая операция

Кто-то где-то это пукнул (я так понимаю в контексте JS) и вы повторяете как мантру! А если вы вычисляли какие-то тесты с 10 000 000 итерациями цикла с созданием элементов, то вот когда будет в приложении именно такое кол-во итерации, тогда вы и говорите, что это дорогая операция!

Vlasenko Fedor 29.07.2019 16:46

https://learn.javascript.ru/multi-insert
читаем учебник

Vlasenko Fedor 29.07.2019 16:55

img.onload = function() {
    // the image is ready
};
img.onerror = function() {
    // the image has failed
};

Это для
Цитата:

Сообщение от Malleys
Для этого есть Service Worker


Malleys 29.07.2019 17:31

Цитата:

Сообщение от Poznakomlus
https://learn.javascript.ru/multi-insert
читаем учебник

Читаю...

Однако, всё это так и так это знаю! И я обычно не использую innerHTML+=, insertAdjacentHTML поскольку это ломает объекты или является не ООП подходом!

Я так понимаю, вы хотели доказать какую-то, как вам кажется, мою ошибочность... однако статья, на которую вы дали ссылку, как раз таки подтверждает все мои взгляды!

Вот...
  • https://learn.javascript.ru/multi-in...rt-bench-tbody Бенчмарк
    Потыкал 8 раз на каждый тест, вот циферки, которые выскакивали в alert...
    • TBODY сразу DOM: 84 109 99 79 90 94 81 95
    • Отложенная вставка TBODY в DOM: 90 87 96 94 110 90 76 75
    Я считаю, что оба способа хороши!
  • https://learn.javascript.ru/multi-in...cumentfragment DocumentFragment

    Цитата:

    Важно для старых браузеров
    Оптимизация, о которой здесь идёт речь, важна в первую очередь для старых браузеров, включая IE9-. В современных браузерах эффект от нее, как правило, небольшой, а иногда может быть и отрицательным.
    Как видите, то что вы предлагаете, является сильно не популярным и крайним взглядам, характерным для микроскопически малого кол-ва пользователей IE9- 📉

    Цитата:

    Понять текущее положение вещей вы можете, запустив следующий небольшой бенчмарк.
    с фрагментом работает примерно в 0,9...1,5 раз медленней... В общем думаю оба варианта хороши! (Без фрагмента было 10 15 13, с фрагментом 14 22 12)

    И там делается вывод в конце
    Цитата:

    DocumentFragment позволяет минимизировать количество вставок в большой живой DOM. Эта оптимизация особо эффективна в старых браузерах, в новых эффект от неё меньше или наоборот отрицательный.
    Да, оно так и есть! 😜

Я прочитал статью и запустил тесты, не знаю, что именно вы хотели мне сказать...

Посмотрел с телефона (результаты такие же, т. е. вставка через фрагмент незначительно медленней)

Т. е. разумная точка зрения такая, что можно использовать оба варианта! 🎉

На компьютере был Chrome 75 и телефоне Chrome 74!

Цитата:

Сообщение от Poznakomlus
https://learn.javascript.ru/multi-insert
читаем учебник

А вы прочитали?

Цитата:

Сообщение от Poznakomlus (Сообщение 510876)
img.onload = function() {
    // the image is ready
};
img.onerror = function() {
    // the image has failed
};

Это для
Цитата:

Сообщение от Malleys
Для этого есть Service Worker


Вы воспринимаете всё как-то фанатично... Типо есть единственно истинный способ вставки, единственный истинный способ обработки ошибки загрузки картинки...

Это способ подходит только если вы работаете с конкретным изображением... А если вы вставляете HTML-код в DOM и в коде есть картинки, то правильней использовать именно Service Worker.

И Service Worker предоставляет централизованный способ обработки запрашиваемых ресурсов, будь то шрифты, картинки интерфейса, данные приложения, шаблоны, всё, что нужно для работы приложения. 😎

Vlasenko Fedor 29.07.2019 18:12

1. не стоит перекручивать задачи
2. в автономных приложениях битую картинку должен видеть разработчик и править
3. единственно где проверяют картинки это контент редактируемый пользователями на сервере. сервера настраивают всегда. Не стоит считать конфигурацию сервера вредом. Это наоборот полезно и нужно.
4. когда вы утверждаете в правильности вашего решения, вы думаете что можете ошибаться? Зачем эта замена (надо заменять сервером). И если уж так горит js то по событию image onerror заменять src на base64 одно пиксельной картинкой
onload и onerror для image здесь отлично работают
5. исходя из ваших убеждений разработчики языка написали много ненужных вещей clone, onerror ...
ох уж эти разработчики


Часовой пояс GMT +3, время: 17:04.