728x90
1. 코드
HTML
(1) main page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
첫페이지
<a href="/shop">상점으로</a>
</body>
<script>
const socket = io();
</script>
</html>
(2) shop page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<link
rel="stylesheet"
href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css"
/>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<body>
상점 페이지
<div class="content">
<ul
id="listview"
data-role="listview"
data-inset="true"
data-filter="true"
>
<li data-role="list-divider">products</li>
<% products.forEach(function(item, index){ %>
<li class="product" data-index="<%= item.index %>">
<a href="#">
<img src="src/1.jpg" alt="" />
<h3><%= item.name %></h3>
<h3><%= item.price %>원</h3>
<span class="ui-li-count"><%= item.count %></span>
</a>
<a href="#" data-icon="heart" data-index="<%= item.index %>"></a>
</li>
<% }); %>
</ul>
</div>
</body>
<script>
//document가 로드가 되었을때
$(document).ready(function () {
//아이콘 변경할 함수
function changeIcon(target, from, to) {
// alert("체크");
//클래스의 이름은 매개변수로 전달
$(target).removeClass(from).addClass(to);
}
//갯수를 변경해주는 함수
function changeCount(index, count) {
//li[data-index=" + index + "] 이게 부모태그
// 부모태그중 ui-li-count 자식 선택
// html = innerHTML 과 같음
// $("li[data-index=" + index + "] .ui-li-count").html(count);
//eq : 인덱스
$(".product").eq(index).find(".ui-li-count").html(count);
}
//소켓 연결 생성
const socket = io();
// 소켓 이벤트 연결
// 클라이언트가 알고있는 이벤트
socket.on("count", function (data) {
changeCount(data.index, data.count);
});
// 태그 이벤트연결
$(".product > a[data-icon]").click(function () {
//클릭했을때 attr추가
let $this = $(this);
let index = $this.attr("data-index");
if ($this.attr("toggle") != "off") {
socket.emit("cart", parseInt(index));
changeIcon(this, "ui-icon-heart", "ui-icon-check");
$this.attr("toggle", "off");
} else {
if (confirm("물건을 구매 하시나요?")) {
socket.emit("buy", parseInt(index));
// $this요소의 부모태그 선택해서 제거
$this.parent().remove();
// 해당 태그가 listview 속성인 태그에
// listview() 함수를 사용해서 실행할 속성을 매개변수로 전달
//해보기
// let $btnindex = $(".product > [data-index]");
// let $productindex = $(".product");
// $btnindex.each(function (index, el) {
// $btnindex.eq(index).attr("data-index", index);
// $productindex.eq(index).attr("data-index", index);
// });
$(listview).listview("refresh");
} else {
socket.emit("return", parseInt(index));
changeIcon(this, "ui-icon-check", "ui-icon-heart");
$this.attr("toggle", "on");
}
}
// $this.attr("toggle", "on");
});
});
</script>
</html>
JS
const express = require("express");
const app = express();
const socketio = require("socket.io");
const ejs = require("ejs");
const fs = require("fs");
const PORT = 3000;
const server = app.listen(PORT, () => {
console.log("server start");
});
const io = socketio(server);
//상품의 기본 틀 객체
//상품의 번호를 정해줄 변수
let counter = 0;
// 생성자 함수(객체를 만들기 위해 함수 만듬)
function Product(name, image, price, count) {
//번호가 증가 할수 있도록 증감 연산자 사용
this.index = counter++;
this.name = name;
this.image = image;
this.price = price;
this.count = count;
}
//동적 할당으로 new를 붙여서 생성자 함수 사용
// console.log(new Product("사과", "/", 2000, 20));
//상품을 가지고 있을 박스
//상품들 전부 가지고 있다.
const products = [
new Product("사과", "/", 2000, 20),
new Product("수박", "/", 2000, 20),
new Product("초코바", "/", 2000, 20),
new Product("비타민", "/", 2000, 20),
new Product("커피", "/", 2000, 20),
];
//사진 링크 설정
// ues함수 사용해서 설정 추가
//함수를 전달했고 server의 설정에 파일의 경로를 설정해준다.
// __dirname : 현재 경로
// __filename : 파일경로
app.use("/src", express.static(__dirname + "/images"));
// "src" 이 부분은 자신이 설정한 경로의 이름을 정의해줄수 있다.
// (__dirname + "/images") 이경로가 /src 로 이름을 부여한 것이다.
// css도 마찬가지로 불러오면 된다.
console.log(__dirname + "/images");
console.log(express.static(__dirname + "/images"));
console.log(products);
app.get("/", (req, res) => {
fs.readFile("index.html", "utf-8", (err, data) => {
res.send(data);
});
});
app.get("/shop", (req, res) => {
//파일 읽어온것
const page = fs.readFileSync("shop.html", "utf-8");
// page 는 html 파일을 읽어서 utf-8인코딩 하고 반환해준다.
res.send(
ejs.render(page, {
products: products,
})
);
});
//소켓 이벤트 연결
let cart = [];
io.on("connect", (socket) => {
//상품 구매 취소했을때 돌리는 함수
function onReturn(index) {
//물건의 갯수를 다시 돌린다. 더해준다.
products[index].count++;
// 물건을 제거
// 배열 안의 값 제거 delete 배열[인덱스]
delete cart[index];
let count = products[index].count;
io.emit("count", {
index,
count,
});
}
//이벤트 연결
socket.on("cart", (index) => {
//물건의 갯수를 감소
products[index].count--;
// 빈객체를 하나 만들어서 해당 배열의 인덱스를 넣어준다.
cart[index] = {};
cart[index].index = index;
let count = products[index].count;
io.emit("count", {
index,
count,
});
});
//구매했을때 이벤트 연결
socket.on("buy", (index) => {
// 카트의 해당 상품 인덱스 제거
delete cart[index];
let count = products[index].count;
io.emit("count", {
index,
count,
});
});
//상품 구매를 취소했을때
socket.on("return", (index) => {
onReturn(index);
});
});
728x90