Найти все теги с изображениями (правило background-image или тег img+src) и собрать их в массив

347
19 сентября 2017, 09:47

Господа, данный скрипт, определяет есть ли на странице теги с правилом css "background-image" и тег "img" с атрибутом "src" для определения их значения.

Смысл в том, что бы создать массив из всех картинок или фото на странице и использовать их потом или для слайдера или использовать это для чего-нибудь другого.

Вопрос, можно ли код упростить и сделать его более компактным и грамотно ли я подошел к вопросу?

весь код проверять не надо. А что надо описано в js в комментариях.

var div = document.createElement('div'); 
const allBlocks = document.body.querySelectorAll('*'); 
const img = document.getElementsByTagName('img'); 
const dataImages = document.getElementsByClassName('dataImages'); 
var arraydataImagesValue = []; 
for (let i = 0; i < allBlocks.length; i++) { 
  /*тут я определяю у каких узлов в css  прописано правило background-image */ 
  if ((getComputedStyle(allBlocks[i]).getPropertyValue('background-image') !== "none")) { 
    /*и присваиваю этому узлу атрибут data-images и значение background-image*/ 
    allBlocks[i].setAttribute('data-images', getComputedStyle(allBlocks[i])['background-image']); 
  } 
} 
for (let i = 0; i < img.length; i++) { 
 
  /*тут я определяю у каких узлов имеется атрибут src */ 
  if (img[i].hasAttribute('src')) { 
    /*и присваиваю этому узлу атрибут data-images и  значение src*/ 
    img[i].setAttribute('data-images', 'url(' + img[i].getAttribute('src') + ')'); 
  } 
} 
for (let i = 0; i < allBlocks.length; i++) { 
  /*тут я определяю у каких узлов имеется атрибут data-images */ 
  if (allBlocks[i].hasAttribute('data-images')) { 
    /*и присваиваю этому узлу class dataImages */ 
    allBlocks[i].classList.add('dataImages') 
  } 
} 
/* 
Больше всего меня интересует, правильно ли я подошел к самой идее и правильно  
ли я сделал используя три цикла или можно бвло бы обойтись меньшим  
количеством циклов. 
 
В общем, одним словом, какие у меня ошибки в логике в синтаксисе и в понимании программирования на js 
*/ 
 
/*код ниже в инспекции не нуждяется, это на скорую руку для  
визуального отображения результата моей идеи, 
но если есть замечания, буду рад узнать о своих ошибка, 
можно даже грубо, но объективно*/ 
for (let i = 0; i < dataImages.length; i++) { 
  arraydataImagesValue[i] = dataImages[i].getAttribute('data-images'); 
 
 
  //=========================================== 
  let moduleWrapper = div.cloneNode(true); 
  moduleWrapper.setAttribute('id', 'moduleWrapper'); 
  //=========================================== 
  let fotoModuleWrapper = div.cloneNode(true); 
  fotoModuleWrapper.setAttribute('id', 'fotoModuleWrapper'); 
  //=========================================== 
  let fotoModule = div.cloneNode(true); 
  fotoModule.setAttribute('id', 'fotoModule'); 
  //=========================================== 
  let closedBlock = div.cloneNode(true); 
  closedBlock.setAttribute('id', 'closedBlock'); 
  //=========================================== 
 
 
 
 
  dataImages[i].addEventListener('click', () => { 
 
 
    document.body.appendChild(moduleWrapper); 
    moduleWrapper.setAttribute('id', 'moduleWrapperActive'); 
    moduleWrapper.appendChild(fotoModuleWrapper); 
    fotoModuleWrapper.setAttribute('id', 'fotoModuleWrapperActive'); 
    fotoModuleWrapper.appendChild(fotoModule); 
    fotoModule.setAttribute('id', 'fotoModuleActive'); 
    fotoModule.style.backgroundImage = dataImages[i].getAttribute('data-images'); 
    fotoModuleWrapper.appendChild(closedBlock); 
 
  }) 
 
 
  closedBlock.addEventListener('click', () => { 
    fotoModuleWrapper.removeChild(closedBlock); 
    fotoModule.setAttribute('id', 'fotoModule'); 
    fotoModuleWrapper.removeChild(fotoModule); 
    fotoModuleWrapper.setAttribute('id', 'fotoModuleWrapper'); 
    moduleWrapper.removeChild(fotoModuleWrapper); 
    moduleWrapper.setAttribute('id', 'moduleWrapper'); 
    document.body.removeChild(moduleWrapper); 
  }) 
 
}
* { 
  margin: 0; 
  padding: 0; 
  transition: all .3s; 
} 
 
html, 
body { 
  width: 100%; 
  height: 100%; 
  background-color: #262626; 
} 
 
#wrapper { 
  width: 100%; 
  height: 100%; 
  display: flex; 
  background: #012727; 
  color: white; 
  flex-direction: row; 
  flex-wrap: wrap; 
  justify-content: space-evenly; 
  align-items: center; 
  align-content: baseline; 
} 
 
.images { 
  cursor: pointer; 
  width: 180px; 
  height: 120px; 
  display: flex; 
  background: #012727; 
  color: white; 
  background-size: cover; 
  margin: 25px; 
} 
 
.images#bg1 { 
  background-image: url(http://4.bp.blogspot.com/_5orOplFcJxA/S_bQVXtyrXI/AAAAAAAAB8k/an2ZU5-q21g/s1600/hayvan-resimleri-5.jpg); 
} 
 
.images#bg2 { 
  background-image: url(https://file.sadecehaber.com/fotograf/fotograf_7eeafa862dffd9e3faa719b04748217d11f3a38a.jpg); 
} 
 
.images#bg3 { 
  background-image: url(http://www.zwalls.ru/pic/201309/1920x1200/zwalls.ru-4399.jpg); 
} 
 
.images#bg4 { 
  background-image: url(https://wallperz.com/wp-content/uploads/2016/11/11/wallperz.com-20161111130034.jpg); 
} 
 
#moduleWrapper { 
  cursor: pointer; 
  z-index: 0; 
  position: absolute; 
  width: 1px; 
  height: 1px; 
  left: 50%; 
  top: 50%; 
  background: rgba(0, 0, 0, .3); 
} 
 
#moduleWrapperActive { 
  cursor: pointer; 
  z-index: 2; 
  opacity: 1; 
  position: absolute; 
  width: 100%; 
  height: 100%; 
  left: 0; 
  top: 0; 
  background: rgba(0, 0, 0, .7); 
} 
 
#closedBlock { 
  cursor: pointer; 
  z-index: 6; 
  position: absolute; 
  width: 30px; 
  height: 30px; 
  right: -30px; 
  top: -30px; 
  background-image: url(https://www.shareicon.net/download/2017/01/17/872777_close_512x512.png); 
  background-size: cover; 
} 
 
#fotoModuleWrapper { 
  position: absolute; 
  opacity: 0; 
  width: 0; 
  height: 0; 
  left: 50%; 
  top: 50%; 
  border: 1px solid gray; 
} 
 
#fotoModuleWrapperActive { 
  position: absolute; 
  opacity: 1; 
  width: 700px; 
  height: 540px; 
  left: calc(50% - 350px); 
  top: calc(50% - 270px); 
  border: 1px solid gray; 
} 
 
#fotoModule { 
  position: absolute; 
  opacity: 1; 
  width: 100%; 
  height: 100%; 
  left: 0; 
  top: 0; 
  opacity: 0; 
  background: transparent; 
  background-size: cover; 
} 
 
#fotoModuleActive { 
  position: absolute; 
  opacity: 1; 
  width: 100%; 
  height: 100%; 
  left: 0; 
  top: 0; 
  opacity: 1; 
  background: transparent; 
  background-size: cover; 
}
<div id="wrapper"> 
  <header> 
 
    <div> 
      <p></p> 
    </div> 
  </header> 
  <main> 
 
    <div class="images" id="bg1"></div> 
    <div class="images" id="bg2"></div> 
    <div class="images" id="bg3"></div> 
 
  </main> 
  <div class="images" id="bg4"></div> 
  <footer> 
 
    <img class="images" src="https://animalplanet4u.files.wordpress.com/2013/02/the-best-top-desktop-lion-wallpapers-hd-lion-wallpaper-1.jpeg" alt=""> 
    <img class="images" src="https://animalplanet4u.files.wordpress.com/2013/02/lion-wallpaper-8.jpg" alt=""> 
    <img class="images" src="https://get.wallhere.com/photo/animals-wildlife-big-cats-whiskers-leopard-Jaguar-jaguars-fauna-mammal-vertebrate-cat-like-mammal-168017.jpg" alt=""> 
    <img class="images" src="https://get.wallhere.com/photo/black-animals-dog-white-flowers-daisies-puppies-Labrador-Retriever-puppy-mammal-vertebrate-dog-like-mammal-dog-breed-stabyhoun-retriever-flat-coated-retriever-231937.jpg" alt=""> 
  </footer> 
</div>

Answer 1

.setAttribute('data-images'

Горяздо лучше созранять данные в скрипте, а не изменять страницу.

/*тут я определяю у каких узлов в css прописано правило background-image */

Псевдоэлементы не учитываются.

const img = document.getElementsByTagName('img');
const dataImages = document.getElementsByClassName('dataImages');

Эффективнее будет использовать querySelectorAll в нужном месте. Живые коллекции гораздо затратнее при обращении по имени.

if (img[i].hasAttribute('src')) {
  1. Возможно, это стоит поместить в селектор.
  2. Как насчёт srcset?
  3. Как насчёт picture?
  4. Обращение к src лучше писать через свойство: img[i].src.
let moduleWrapper = div.cloneNode(true);
moduleWrapper.setAttribute('id', 'moduleWrapper');

Тут в цикле создаётся куча элементов с одинаковыми id. Перечитал внимательнее - вроде в dom они одновременно не окажутся, но в таком случае тебе нужен только один, а не все.

moduleWrapper.setAttribute('id', 'moduleWrapper');

id тоже лучше устанавливать через свойство: moduleWrapper.id = ....

moduleWrapper.setAttribute('id', 'moduleWrapperActive');

Менять id странно.

dataImages[i].addEventListener('click', () => {

А то если элемент расположен так, что его нельзя кликнуть? Либо на нём уже есть обработчик, который отменит распространение события? И снова псевдоэлементы.

READ ALSO
Изменение массива JS

Изменение массива JS

Приходит массив в виде:

230
Vue.js динамический рендеринг

Vue.js динамический рендеринг

Есть ли возможность динамической отрисовки в Vuejs ? К примеру отрисовка по евенту ? Примерно так

247
jQuery this find не работает

jQuery this find не работает

Я пытаюсь использовать $(this)find('

255