저번 시간, 미니 프로젝트의 JS를 짜던 중 클릭 이벤트를 받아 id값을 추적해 div 태그의 class를 추가하는 코드를 짰습니다.
그 과정에서 여러개의 div 태그에 동시 적용이 되어야 하는데 맨 처음 div태그에만 적용되는 이상한 현상이 일어났습니다.
그래서 왜일까? 일단 열심히 찾아봤습니다.
Try1. 태그에 붙은 id 및 class값 확인
확인해본 결과, id값을 통하여 받아오는 일련에 과정에 필요한 전제조건 id값은 고유하다.
라는 법칙부터 틀려 있었습니다. 굉장히 초보적인 실수였습니다.
일단 HTML을 생성하는 코드를 수정하였습니다.
let temp_html = `
<div class="" id='memberCard${idx}'>
<div class="" id='checknum${idx}'>
<img src="${image}" type="button" alt="${name}">
<p>${name} [${mbti}]</p>
<p><label><input type="text" name="eq1" value="${scontent}"></label></p>
<p>${blog}, ${github}</p>
<p>${bcontent}</p>
</div>
</div>`;
id값의 뒤에 ${idx}를 추가하여 HTML을 하나 생성할 때마다 idx++를 통하여 뒤 숫자를 통해 고유한 id값을 주는 방향입니다.
그렇다면 이걸 한 후에는 잘 되었나?
잘 됐으면 좋았겠지만!
고유한 id값은 잘 들어갔으나 여전히 작동이 맨 처음 태그에만 작동을 하였습니다.
Try2. 특정 id가 포함된 요소의 값을 잘 받았나?
여기서부터 제일 인상깊고 재미있던 과정이였습니다.
우선, id의 값이 고유하다고 하여 그 고유한 값으로 어느 한 태그의 주소만 가져와 클릭을 감지하고... 여튼 안되는 것입니다. 그리하여 튜터님께 도움을 청하고 얻은 힌트
로직 클릭 이벤트가 각각 들어가는지 보아라, 요소 선택을 확인해라, 요소를 배열로 관리하여 인덱스 값으로 구분
!
그래서... 뜯어 고쳤습니다. 왜? 동작을 감지하는 이벤트를 각 카드마다 심어주어야 하고, 카드가 생성될 때마다 이벤트를 심어주어야 하니... forEach문으로 심어주면 되겠구나
먼저 forEach문을 사용해 모든 카드에 대해 클릭 이벤트 처리를 추가해주어야 하고 클릭 이벤트 처리 할 특정 요소를 data-*을 통하여 지정 해주어야 합니다. 또, class에 먼저 값을 하나 추가해주어 카드 요소들을 모두 선택이 가능하도록 하여야 했습니다.
그래서 우선 HTML을 생성하는 코드 먼저 수정해준 후
let temp_html = `
<div class="card" id='memberCard${idx}' data-index='${idx}'>
<div class="" id='checknum${idx}' data-turn='${idx}'>
<img src="${image}" type="button" alt="${name}">
<p>${name} [${mbti}]</p>
<p><label><input type="text" name="eq1" value="${scontent}"></label></p>
<p>${blog}, ${github}</p>
<p><button id='ex'>확장</button></p>
<p>${bcontent}</p>
</div>
</div>`;
모든 카드 요소들을 선택하여주고
const cards = document.querySelectorAll('.card');
각 카드에 클릭 이벤트를 처리하고 클릭 시 상태를 변경합니다!
cards.forEach((card) => {
const cardId = card.getAttribute('data-index');
let cardState = localStorage.getItem(cardId);
const openCard = () => {
card.classList.add('opened');
localStorage.setItem(cardId, 'active');
};
const closeCard = () => {
card.classList.remove('opened');
localStorage.setItem(cardId, null); //
};
if (cardState === 'active') {
openCard();
}
card.addEventListener('click', () => {
cardState = localStorage.getItem(cardId);
cardState !== 'active' ? openCard() : closeCard();
});
});
이렇게 하여 작동하니 정상 작동이 완료되었습니다!
이 이후부터는 일사천리였습니다.
카드의 데이터 순서를 확인 후 홀짝을 구분하여 그에 따라 하위 div태그에 even혹은 odd를 class에 넣어주는 코드
const cn = document.getElementById(`checknum${idx}`);
const dataTurn = cn.getAttribute('data-turn');
if (dataTurn % 2 === 0) {
cn.classList.add('even');
} else {
cn.classList.add('odd');
}
조금의 구글링과 AI를 통하여 만들어 낸 Firebase에 데이터를 저장 할 때에 timestamp를 이용하여 저장 순서를 예상할 수 있게 만든 코드
let doc = { // firebase 데이터 값 저장
'image': image,
'name': name,
'blog': blog,
'github': github,
'scontent': scontent,
'bcontent': bcontent,
'mbti': mbti,
'timestamp': new Date() // 현재 시간 추가
};
const q = query(collection(db, "memcard"), orderBy("timestamp"));
newsapi.org 사이트를 통하여 전 세계 뉴스를 키워드를 사용하여 검색 후 항목 5개를 추출하는 코드
const urlTemplate = (keyword) => `https://newsapi.org/v2/everything?q=${keyword}&sortBy=popularity&pageSize=5&apiKey=${apiKey}`;
fetch(url)
.then(response => response.json())
.then(data => {
console.log(data);
const articles = data.articles;
if (articles.length === 0) {
alert('검색 결과가 없습니다. 다른 키워드를 시도해 보세요.');
}
const headlineElement = document.getElementById('headline');
headlineElement.textContent = `${keyword}에 대한 최신 뉴스`;
displayNews(articles);
})
.catch(error => {
alert('뉴스를 가져오는 데 실패했습니다');
});
});
간략하게 힘들었던 코드만 적어두어 복습으로 사용 할 예정입니다.