Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
10008c8
Initial commit
choisohyun Feb 11, 2020
cbe9654
feat. html, css UI 틀 추가
choisohyun Feb 11, 2020
b481dd1
feat. html, css UI 틀 추가
choisohyun Feb 11, 2020
38aa4e7
feat. prev,next 버튼 클릭 시 슬라이드 이동 기능 추가
choisohyun Feb 12, 2020
6ba14ed
refactor. function -> class로 변경
choisohyun Feb 12, 2020
9c1d78d
feat. navigation 버튼 클릭 시 슬라이드 이동 기능 추가
choisohyun Feb 12, 2020
4a2b895
Merge remote-tracking branch 'javascript-amazon-anim/master' into cardui
choisohyun Feb 12, 2020
6046298
docs. Delete image files, duplicate files
choisohyun Feb 12, 2020
166cd89
feat. Add Mock Data & html 자동생성파일 완성
choisohyun Feb 14, 2020
b82e169
feat. Add dummy element for infinite slides
choisohyun Feb 16, 2020
cbe1e04
refactor. Rename & change class structure
choisohyun Feb 16, 2020
590f8ae
style. Edit arrow button position
choisohyun Feb 16, 2020
b708cf6
Merge branch 'choisohyun' into animation
choisohyun Feb 16, 2020
77f7ebe
feat. launch with express server, get json file fetch
choisohyun Feb 25, 2020
9738e81
refactor & fix. Remove duplicate code, fix some animation bugs
choisohyun Feb 25, 2020
69f14af
Merge branch 'fetch' into tmp
choisohyun Feb 25, 2020
e82d1ab
chore. Delete old work files added during merge
choisohyun Feb 26, 2020
3083758
fix & refactor. Change class structure
choisohyun Feb 26, 2020
e452111
refactor. Use template literal when forming html
choisohyun Feb 26, 2020
ccc1745
feat. Add Cache json file in localStorage
choisohyun Feb 26, 2020
276d08c
refactor. Rename function css => set
choisohyun Feb 26, 2020
6698e3a
fix. Rename function css => set
choisohyun Feb 26, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@

# Created by https://www.gitignore.io/api/node
# Edit at https://www.gitignore.io/?templates=node

### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# rollup.js default build output
dist/

# Uncomment the public line if your project uses Gatsby
# https://nextjs.org/blog/next-9-1#public-directory-support
# https://create-react-app.dev/docs/using-the-public-folder/#docsNav
# public

# Storybook build outputs
.out
.storybook-out

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# Temporary folders
tmp/
temp/

# End of https://www.gitignore.io/api/node
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file added client/images/button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 77 additions & 0 deletions client/js/carousel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { setTransform, setTransition } from "./util.js";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

es modules 브라우저의 지원범위에 대해서 조사해보세요.
호환성에 대해서 인지하고 개발하면 좋죠.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ES modules 지원 범위

image

  • MDN과 caniuse로 봤는데, IE뿐만 아니라 조금 마이너한 브라우저도 안되는데가 꽤 있는 것을 확인했습니다.
  • Nodejs에서도 8.5 이하 버전에서는 지원이 되지 않습니다.

추가적으로 블로그를 찾아봤는데, 지원범위 때문에 webpack같은 모듈 번들러를 사용한다는 것을 알게 되었습니다.


class Carousel {
constructor(config) {
this.config = config;
this.slideAll = config.slideAll;
this.width = config.MAX_PANEL_SIZE;
this.currentIndex = config.START_CAROUSEL_INDEX;
this.isMoveFinished = config.isMoveFinished;
this.nav = document.querySelectorAll(".slide-navigation > li");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네이밍 짓는게 쉽지 않죠. nav는 리스트라서 nav보다는 navList 정도도 괜찮을 듯.

this.init();
}

init() {
this.buttonHandler();
this.navigationHandler();
}

moveSlides(option) {
setTransform(this.slideAll, this.currentIndex, this.width);
setTransition(this.slideAll, option);
}

clickEvent(index) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clickEventHandler 나 Listener 라고 이름 짓곤해요.

if (this.isMoveFinished === false) return;
this.isMoveFinished = false;

const transitionOption = `transform 0.4s ease-in-out`;
let prevIndex = this.currentIndex - 1;
let nextIndex = this.currentIndex + 1;
this.currentIndex = index === 0 ? prevIndex : nextIndex;
this.moveSlides(transitionOption);
}

transitionendEvent() {
const transitionOption = "none";
const minIndex = this.config.START_CAROUSEL_INDEX;
const maxIndex = this.config.MAX_CAROUSEL_SIZE;

if (this.currentIndex === minIndex - 1) {
this.currentIndex = maxIndex - 1;
this.moveSlides(transitionOption);
} else if (this.currentIndex === maxIndex) {
this.currentIndex = minIndex;
this.moveSlides(transitionOption);
}
this.isMoveFinished = true;
}

buttonHandler() {
const buttons = this.config.buttons;
setTransform(this.slideAll, this.currentIndex, this.width);

buttons.forEach((element, index) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

델리게이션 고고

element.addEventListener("click", () => this.clickEvent(index));
});

this.slideAll.addEventListener("transitionend", () => this.transitionendEvent());
}

navigationHandler() {
const transitionOption = `transform 0.4s ease-in-out`;
setTransform(this.slideAll, this.currentIndex, this.width);

this.nav.forEach((el, index) => {
let nextIndex = index + 1;

el.addEventListener("click", () => {
if (nextIndex === this.currentIndex) return;
this.currentIndex = nextIndex;
this.moveSlides(transitionOption);
});
});
}
}

export { Carousel };
29 changes: 29 additions & 0 deletions client/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Carousel } from "./carousel.js";
import { TemplateData } from "./templateData.js";

const jsonFileUrl = "http://localhost:8080/users";
const data = localStorage.getItem("mockData");

const carousel = { slideAll: document.querySelector(".slider") };
const arrowButtons = { buttons: document.querySelectorAll(".slide-btn > button") };
const width = { MAX_PANEL_SIZE: 760 };
let currentIndex = { START_CAROUSEL_INDEX: 1 };
let maxIndex = { MAX_CAROUSEL_SIZE: 5 };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기까지 선언된 default 값은 누구의 것일까요?
제 생각에는 Carousel 의 것인거 같습니다.
그래서 그 안으로 옮겨야 하는거 아닌가 싶네요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코멘트 보고 이해가 잘 안 갔었는데 오늘 강의 보고 이해했습니다. 제가 원했던 구조가 model, cardMenu와 casouselSlide였었어서 참고해서 적용해 다음 pr에 보내도록 하겠습니다!


const config = Object.assign(carousel, arrowButtons, width, currentIndex, maxIndex);

const run = () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run은 여기서만 호출되는 코드라면, 이름없이 익명즉시실행함수라는 걸 써도 되겠군요.

fetch(jsonFileUrl)
.then(response => response.json())
.then(mockData => {
localStorage.setItem("mockData", JSON.stringify(mockData));
})
.then(() => {
const templateData = new TemplateData(JSON.parse(data));
})
.then(() => {
const carousel = new Carousel(config);
});
};

run();
81 changes: 81 additions & 0 deletions client/js/templateData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
class TemplateData {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TemplateData가 클래스 형태이여야 하는 이유는 뭘까요?
클래스로 얻는 장점에 대해서 이야기해보세요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TemplateData 클래스 안의 메소드를 함수로 하나씩 쓰게 되면 함수를 하나씩 여러번 실행하거나 선언한 함수들을 객체로 따로 저장해 실행하는 방식을 취해야 합니다.
클래스를 사용하게 되면 data를 template한다는 의미를 가진 객체에 각각의 메소드가 생기는 것이므로 의미가 명확해 진다고 생각합니다.
또, Carousel 객체와의 형식이 동일하기 때문에 일관성을 가지고 있습니다.

constructor(mockData) {
this.cardList = mockData.cardList;
this.init();
}

init() {
this.addNavTitle();
this.addSlide();
this.addDummySlide();
}

addNavTitle() {
let navButtons = ``;

this.cardList.forEach(element => {
navButtons += `<li><button type="button">${element.title}</button></li>`;
});

const slideNav = document.querySelector(".slide-navigation");
slideNav.innerHTML = navButtons;
}

addSlide() {
let slides = ``;

this.cardList.forEach(element => {
const img = element.image;
const header = element.header;
const sentence = element.contents;

slides += `
<li>
${this.addImgWrap(img)}
${this.addContentsWrap(header, sentence)}
</li>`;
});

const sliderWrap = document.querySelector(".slider");
sliderWrap.innerHTML = slides;
}

addImgWrap(img) {
let imgWrap = `
<div class="img-wrap">
<img src="${img}">
</div>`;

return imgWrap;
}

addContentsWrap(header, sentences) {
let sentenceList = ``;
sentences.forEach(el => (sentenceList += `<li>${el}</li>`));

let contentsWrap = `
<div class="contents-wrap">
<h2>${header}</h2>
<ul>
${sentenceList}
</ul>
</div>`;

return contentsWrap;
}

addDummySlide() {
const sliderWrap = document.querySelector(".slider");

let firstChild = sliderWrap.firstElementChild;
let lastChild = sliderWrap.lastElementChild;

let clonedFirst = firstChild.cloneNode(true);
let clonedLast = lastChild.cloneNode(true);

sliderWrap.appendChild(clonedFirst);
sliderWrap.insertBefore(clonedLast, sliderWrap.firstElementChild);
}
}

export { TemplateData };
10 changes: 10 additions & 0 deletions client/js/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const setTransform = (target, width, currentIndex) => {
let transformOption = `translateX(${-width * currentIndex}px)`;
target.style.transform = transformOption;
};

const setTransition = (target, option) => {
target.style.transition = option;
};

export { setTransform, setTransition };
28 changes: 28 additions & 0 deletions client/views/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="../css/reset.css" />
<link rel="stylesheet" href="../css/style.css" />
<title>아마존</title>
</head>

<body>
<div class="wrap">
<div class="slide-container">
<ul class="slide-navigation clearfix">
<!-- addNavTitle -->
</ul>
<ul class="slider clearfix">
<!-- addSlideImg, addSlideHeader -->
</ul>
</div>
<div class="slide-btn">
<button type="button" class="prev-btn"></button>
<button type="button" class="next-btn"></button>
</div>
</div>
<script type="module" src="../js/main.js"></script>
</body>
</html>
Loading