<div id="carouselExampleIndicators<%= i %>" class="carousel slide">
<div class="carousel-indicators">
<button type="button" data-bs-target="#carouselExampleIndicators<%= i %>" data-bs-slide-to="0"
class="active" aria-current="true" aria-label="Slide 1"></button>
<% if (포토[i].img[1] != undefined) { %>
<% for (j = 1; j < 포토[i].img.length; j++) { %>
<button type="button" data-bs-target="#carouselExampleIndicators<%= i %>"
data-bs-slide-to="<%= j %>" aria-label="Slide <%= j + 1 %>"></button>
<% } %>
<% } %>
</div>
<div class="carousel-inner">
<% if (포토[i].img[1] === undefined) { %>
<div class="carousel-item active">
<img class="carousel-img d-block" src="<%= 포토[i].img[0].location %>" alt="...">
</div>
<% } else { %>
<div class="carousel-item active">
<img class="carousel-img d-block" src="<%= 포토[i].img[0].location %>" alt="...">
</div>
<% for (k = 1; k < 포토[i].img.length; k++) { %>
<div class="carousel-item">
<img class="carousel-img d-block" src="<%= 포토[i].img[k].location %>" alt="...">
</div>
<% } %>
<% } %>
</div>
<% if (포토[i].img[1] != undefined) { %>
<button class="carousel-control-prev" type="button"
data-bs-target="#carouselExampleIndicators<%= i %>" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button"
data-bs-target="#carouselExampleIndicators<%= i %>" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
<% } %>
</div>
사진탭의 코드이다.
정말 애를 많이 쓴 코드인데 일단 부트스트랩에서 Carousel 기능을 통해 슬라이드 기능을 구현했다.
부트스트랩 코드를 내 코드에 입히는 과정에서 게시물마다 각 각 슬라이드 기능을 구현해야했기 때문에 나는
<div id="carouselExampleIndicators<%= i %>"
위처럼 기존의 carouselExampleIndicators id 값 뒤에 동적으로 변수를 지정해야했다.
그런데 뒤에 변수를 지정을 하니까. 모바일에서 스와이핑이 기능을 안 했다.
chatGPT 의 힘을 빌렸는데,
document.addEventListener('DOMContentLoaded', function () {
// 모든 캐러셀 요소를 가져와서 반복
var carousels = document.querySelectorAll('.carousel');
carousels.forEach(function (carousel) {
// 부트스트랩 캐러셀 초기화
new bootstrap.Carousel(carousel, {
interval: false // 자동 슬라이드를 비활성화하려면 이 부분을 추가합니다.
});
});
});
위의 코드를 script 태그 안에 넣어주니 해결되었다.
부트스트랩의 캐러셀은 JavaScript에 의존적인 컴포넌트입니다. 캐러셀을 사용하려면 해당 컴포넌트의 JavaScript 파일이 로드되어야 하며, 또한 캐러셀이 초기화되고 설정되어야 합니다. 부트스트랩은 자동으로 이러한 초기화를 수행하지 않기 때문에 사용자가 직접 초기화 코드를 작성해야 합니다.
따라서 부트스트랩 캐러셀을 사용하고자 할 때, 해당 컴포넌트의 JavaScript 코드를 포함하고, 이를 초기화하는 스크립트를 실행해야 합니다. 여기서는 사용자의 편의를 위해 캐러셀을 초기화하는 스크립트를 제공한 것입니다.
만약 해당 스크립트를 포함하지 않으면, 캐러셀이 올바르게 초기화되지 않아 슬라이딩과 같은 기능이 작동하지 않을 것입니다. 사용자가 슬라이드를 수동으로 전환하거나 화면을 작게 확대할 수 없게 되므로 부트스트랩 캐러셀이 정상적으로 작동하지 않습니다.
캐러셀을 사용하려면 부트스트랩의 JavaScript 라이브러리가 필요하며, 초기화 코드를 통해 캐러셀을 사용자 상호 작용에 대해 준비시켜야 합니다.
부트스트랩에서 JavaScript 를 이용하는 경우 위의 코드를 통해 연결을 시켰어야 했다는 것이다.
드디어 해결을 하니 기분이 좋았다. 7일 걸렸다.
댓글을 달 때 input 태그를 클릭하면 확대되어서 게시 버튼이 안보이는 현상이 있었다.
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
위와 같이 meta 태그를 넣어주니까 해결되었다.
사진탭 수정 기능을 추가했는데, 글 수정과는 조금 다른 점이 있었다.
<body>
<%- include('nav.ejs') %>
<div class="management-title"></div>
<div class="flex-col white-main">
<form class="form-box" action="/photo-edit?_method=PUT" method="POST">
<h4>글 수정</h4>
<input name="id" value="<%= 포토._id%>" style="display: none;">
<!-- <input type="file" name="img1" accept="image/*" multiple> -->
<div style="margin-left: 1px;">
<textarea class="textarea-notice" name="content"><%=포토.content%></textarea>
</div>
<div style="text-align: center;">
<button type="submit">수정</button>
</div>
</form>
</div>
</body>
일단 html 코드는 위와 같이 구현했다,
function EditPhoto(event) {
event.preventDefault();
var editId = event.target.getAttribute('data-photo-id');
window.location.href = '/photo-edit/' + edittId;
}
<a href="#" data-photo-id="<%= 포토[i]._id%>" onclick="EditPhoto(event)" style="margin-right: 5px; cursor: pointer;">수정</a>
a 태그 안에 onclick 함수를 넣었다,
event,preventDefault(); 는 form 태그의 동작을 우선 막는다.
이건 Delete 기능을 구현할 때 확인을 먼저 하기 위해서 사용되었는데, 삭제해도 되겠다.
event.target.getAttribute() 를 이용해서 event 가 발생한 곳의 data-photo-id 값을 가져와서 editId 안에 넣었고,
이를 param 값에 넣어서 서버로 전달시켰다.
app.get('/photo-edit/:id', async (req, res) => {
let photoID = await db.collection('photo').findOne({ _id: new ObjectId(req.params.id) })
res.render('photo-edit.ejs', { 포토: photoID })
})
app.put('/photo-edit', async (req, res) => {
let result = await db.collection('photo').updateOne({ _id: new ObjectId(req.body.id) },
{
$set: {
content: req.body.content
}
})
res.redirect('/photo')
})
서버에서는 위와 같이 처리했다.
댓글을 입력하지 않았을 시에 alert 를 이용해 댓글을 입력하라는 팝업을 띄우고 싶었다.
<form action="/photo-comment" method="POST">
<input name="parentId" value="<%= 포토[i]._id%>" style="display: none;">
<div id="story-photo-add-comment-input-area0<%= i %>" style="display: none;">
<div id="story-photo-add-comment-input-area" class="story-photo-add-comment-input-area">
<input id="story-photo-add-comment-input" name="content" class="story-photo-add-comment-input" type="text"
autocomplete="off">
<button type="submit" class="story-photo-add-comment-inputBt" onclick="PostPhotoComment(event)">게시</button>
</div>
</div>
</form>
form 태그 안에서 전송 event 를 갖고 있는 button 에 PostPhotoComment(event) 함수를 추가시켜줬다.
function PostPhotoComment(event) {
event.preventDefault();
var commentId = document.getElementById('story-photo-add-comment-input').value;
if (commentId ==''){
alert('댓글을 입력하세요')
} else {
return;
}
}
우선 form 태그 event를 중지시키고 input 태그 id 값을 가져와서 그 안에 value 값을 commentId 안에 넣어준다.
만약 commentId 값이 빈 칸이면 댓글을 입력하세요 라는 문구를 띄우게 했다.
그러고 예외 경우에 return; 을 통해 함수를 빠져나가게 했는데, 문제가 발생했다.
함수를 빠져나가도 정상적으로 form 태그를 작동시키지 않았다.
함수를 빠져나갔을 때 event 를 정상적으로 작동시키기 위해 방법을 찾아봤다.
function PostPhotoComment(event) {
event.preventDefault();
var commentInput = document.getElementById('story-photo-add-comment-input');
var commentId = commentInput.value;
if (commentId == '') {
alert('댓글을 입력하세요')
} else {
var form = commentInput.closest('form');
form.submit();
}
}
위와 같이 수정해줬다.
return; 을 이용해서 함수를 빠져나가서는 다시 form 태그를 작동시킬 수 없었다.
직접적으로 함수 안에서 form 태그를 작동시켜야했다.
var form = commentInput.closest('form');
위 코드는 Element 에서 가장 가까운 form 태그를 찾는 코드이다.
그러고 뒤에 submit 를 붙여서 작동시켰다.
정상적으로 작동되었다. 이를 이제 공지사항 탭에서도 작동시킬 예정이고, 로그인 페이지, 회원가입 페이지 등에서 작동시킬 것이다. 굿!