Last active
July 18, 2017 00:06
-
-
Save sokcuri/a8720228aa4347ba5cc883a885b5dd79 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html, body { | |
height: 100%; | |
} | |
body { | |
font-family: "Spoqa Han Sans"; | |
} | |
body, header, nav, section, div, footer, ul, dd { | |
margin: 0; | |
padding: 0; | |
} | |
li { | |
list-style: none; | |
} | |
dt { | |
font-weight: bold; | |
font-size: 1.2em; | |
margin-bottom: 5px; | |
} | |
.tab * { | |
pointer-events: none; | |
} | |
dl { | |
float: left; | |
width : 75%; | |
} | |
dd { | |
font-size: 0.9em; | |
} | |
#wrapper { | |
min-height: 100%; | |
position: relative; | |
} | |
.infoArea { | |
position: absolute; | |
top: 10px; | |
left: 10px; | |
width: 160px; | |
height: 130px; | |
background: rgba(255, 255, 255, 0.6); | |
border-radius: 3%; | |
background: url(https://raw.githubusercontent.com/sokcuri/StoreBox/master/woowahan_techcamp.png); | |
background-size: contain; | |
background-repeat: no-repeat; | |
} | |
.headerArea { | |
height:200px; | |
text-align: center; | |
padding-top: 20px; | |
line-height: 1.4em; | |
background: url(https://i.ytimg.com/vi/nRLsWw1-v94/maxresdefault.jpg); | |
background-size: cover; | |
} | |
.profilePic { | |
display: inline-block; | |
width: 100px; | |
height: 100px; | |
border: 3px solid white; | |
border-radius: 100%; | |
background: url(https://avatars1.githubusercontent.com/u/1456761?v=3&s=140); | |
background-size: contain; | |
} | |
.userId { | |
font-size: 1.2em; | |
font-weight: bold; | |
line-height: 2rem; | |
} | |
.userId > span { | |
border-bottom: 1px dashed #ddd; | |
text-shadow: 1px 1px #dedede; | |
line-height: 10px; | |
} | |
.userMessage, .userSNSInfo { | |
font-size: 0.9em; | |
color: seashell; | |
text-shadow: -1px -1px 0 #333, | |
1px -1px 0 #000, | |
-1px 1px 0 #555, | |
1px 1px 0 black; | |
} | |
.userSNSInfo { | |
display: inline-block; | |
overflow: auto; | |
margin: 0px auto; | |
} | |
.userSNSInfo > li { | |
float: left; | |
margin-right: 5px; | |
} | |
.userSNSInfo span.count { | |
color : chartreuse; | |
} | |
.mainView { | |
margin: 0 auto; | |
min-height: 600px; | |
} | |
.mainView > nav { | |
height:42px; | |
font-family: "Lucida Grande", "Lucida Sans Unicode", Tahoma, Sans-Serif; | |
padding-left: 8%; | |
padding-right: 8%; | |
background: #3d3d3e; | |
} | |
.tabArea ul { | |
padding: 0; | |
} | |
/* Tab 선택시에만 badge를 볼 수 있게 */ | |
.tabArea .badge { | |
display: none; | |
} | |
.tabArea .selectedTab .badge { | |
display: block; | |
width: 24px; | |
height: 24px; | |
position: absolute; | |
background: #9e9e9e; | |
color: white; | |
font-weight: bold; | |
border-radius: 100px; | |
/* border: 2px solid #5a5a5a; */ | |
z-index: 1; | |
top: -10px; | |
right: 8px; | |
font-size: 0.6rem; | |
line-height: 23px; | |
} | |
.tabArea ::selection { | |
background: transpaent; | |
color: inherit; | |
text-shadow: none; | |
} | |
.tabArea section { | |
position: relative; | |
float: left; | |
text-align: center; | |
list-style: none; | |
color: white; | |
padding: 8px; | |
height: 100%; | |
box-sizing: border-box; | |
cursor: pointer; | |
} | |
.tabArea section:hover { | |
background-color: #888; | |
} | |
.tabArea section.selectedTab { | |
background-color: #ccc; | |
color: black; | |
} | |
.tabArea span { | |
overflow: hidden; | |
display: block; | |
text-overflow: ellipsis; | |
white-space: nowrap; | |
font-size: 0.95rem; | |
} | |
.tabArea .selectedTab span:after { | |
content: ""; | |
position: absolute; | |
top: 100%; | |
left: 50%; | |
border-top: 16px solid #ccc; | |
border-left: 16px solid transparent; | |
border-right: 16px solid transparent; | |
margin-left: -16px; | |
} | |
/* Can CSS detect the number of children an element has? */ | |
/* https://stackoverflow.com/questions/8720931/can-css-detect-the-number-of-children-an-element-has */ | |
/* one item */ | |
.tabArea section:first-child:nth-last-child(1) { | |
width: 100%; | |
} | |
/* two items */ | |
.tabArea section:first-child:nth-last-child(2), | |
.tabArea section:first-child:nth-last-child(2) ~ section { | |
width: 50%; | |
} | |
/* three items */ | |
.tabArea section:first-child:nth-last-child(3), | |
.tabArea section:first-child:nth-last-child(3) ~ section { | |
width: 33.3333%; | |
} | |
/* four items */ | |
.tabArea section:first-child:nth-last-child(4), | |
.tabArea section:first-child:nth-last-child(4) ~ section { | |
width: 25%; | |
} | |
/* five items */ | |
.tabArea section:first-child:nth-last-child(5), | |
.tabArea section:first-child:nth-last-child(5) ~ section { | |
width: 20%; | |
} | |
/* six items */ | |
.tabArea section:first-child:nth-last-child(6), | |
.tabArea section:first-child:nth-last-child(6) ~ section { | |
width: 16.6667%; | |
} | |
/* seven items */ | |
.tabArea section:first-child:nth-last-child(7), | |
.tabArea section:first-child:nth-last-child(7) ~ section { | |
width: 14.2857%; | |
} | |
/* eight items */ | |
.tabArea section:first-child:nth-last-child(8), | |
.tabArea section:first-child:nth-last-child(8) ~ section { | |
width: 12.5%; | |
} | |
.tab:last-child { | |
border-right: 0px; | |
} | |
.sectionArea > div { | |
display:none; | |
padding:8%; | |
line-height: 1.5em; | |
} | |
.sectionArea > div.eleDisplayShow { | |
display: block; | |
padding: 30px 8%; | |
line-height: 1.5em; | |
} | |
.myName { | |
font-size: 1.2em; | |
font-weight: bold; | |
} | |
.myDesc { | |
font-size: 0.8em; | |
} | |
.eleDisplayShow li { | |
margin-bottom: 8%; | |
} | |
.sectionArea .pageHeader { | |
padding-bottom: 9px; | |
margin: 40px 0 20px; | |
border-bottom: 1px solid #ddd; | |
} | |
.sectionArea h1:after, .sectionArea h2:after, .sectionArea h3:after { | |
background-color: #1f5c99; | |
bottom: 0; | |
content: ""; | |
margin-top: 10px; | |
margin-bottom: -1px; | |
display: block; | |
width: 50px; | |
height: 3px; | |
} | |
.sectionArea h1, .sectionArea h2, .sectionArea h3 { | |
font-family: "Open Sans", Helvetica, Arial, sans-serif; | |
margin-bottom: -10px; | |
color: #555555; | |
} | |
.sectionArea h3 { | |
font-weight: 400; | |
} | |
.sectionArea ::selection { | |
background: #269ccb; | |
color: #fff; | |
} | |
.footerView { | |
position: absolute; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
background: #3d3d3e; | |
color: white; | |
text-align: right; | |
font-size: 0.7rem; | |
z-index: 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, user-scalable=no"> | |
<title>nigayo -- WoowaTechCamp</title> | |
<link rel="stylesheet" href="http://spoqa.github.io/spoqa-han-sans/css/SpoqaHanSans-kr.css"> | |
<link rel="stylesheet" href="https://spoqa.github.io/spoqa-han-sans/css/SpoqaHanSans-kr.css"> | |
<link rel="stylesheet" href="./tabUI.css"> | |
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js"></script> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js"></script> | |
<script src=./tabUI.js></script> | |
</head> | |
<body> | |
<div id="wrapper"> | |
<div class="infoView"> | |
<div class="infoArea"> | |
</div> | |
</div> | |
<div class="mainView"> | |
<header class="headerArea"> | |
<div class="profilePic"></div> | |
<div class="userId"> | |
<span>nigayo</span> | |
</div> | |
<div class="userMessage"><span>안녕하세요 nigayo입니다.</span> | |
</div> | |
<ul class="userSNSInfo"> | |
<li><span>review : </span><span class="count">10</span><span> | </span> | |
</li> | |
<li><span>follower : </span><span class="count"><span >12</span><span> </span></span><span > | </span> | |
</li> | |
<li><span>following : </span><span class="count"><span >30</span><span> </span></span><span > </span> | |
</li> | |
</ul> | |
</header> | |
<nav class="tabArea"></nav> | |
<main class="sectionArea"></main> | |
</div> | |
<footer class="footerView">original by nigayo, modified by sokcuri. </footer> | |
</div> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Template = { | |
NavigateTab: `<div class="badge">{{clickCount}}</div><div class="content" id="{{id}}"><span>{{text}}</span></div>`, | |
Section: `<div class="pageHeader"><h3>{{title}}</h3></div><p>{{content}}</p>` | |
} | |
const TabInfo = [ | |
{ | |
id: 'position', | |
text: 'About me' | |
}, | |
{ | |
id: 'news', | |
text: 'News' | |
}, | |
{ | |
id: 'following', | |
text: 'Following' | |
}, | |
{ | |
id: 'follower', | |
text: 'Follower' | |
}, | |
{ | |
id: 'comment', | |
text: 'Comment' | |
}, | |
{ | |
id: 'woowa', | |
text: 'Woowa' | |
}, | |
{ | |
id: 'dinner', | |
text: 'Dinner' | |
} | |
] | |
class TabList extends Array { | |
constructor() { | |
super([]); | |
} | |
init(TabInfo) { | |
let num = 0; | |
TabInfo.forEach(tab => this.push(new Tab(tab.id, tab.text, num++ === 0))); | |
} | |
push(tabObject) { | |
document.querySelector('.tabArea').appendChild(tabObject.makeNode()); | |
super.push(tabObject); | |
} | |
} | |
class Tab { | |
constructor(id, text, firstTab) { | |
this.data = this.initData.apply(this, arguments); | |
this.createSection(firstTab); | |
this.registerEvents(); | |
} | |
initData(id, text, clickCount) { | |
return { | |
id: id, | |
text: text, | |
clickCount: 0 | |
} | |
} | |
createSection(selected) { | |
this.node = document.createElement('section'); | |
this.node.classList.add('tab'); | |
if (selected) { | |
this.data.clickCount++; | |
this.node.classList.add('selectedTab'); | |
} | |
} | |
registerEvents() { | |
this.node.addEventListener('click', this.clickCountHandler.bind(this)); | |
} | |
clickCountHandler() { | |
this.data.clickCount++; | |
this.makeNode(); | |
} | |
getData() { | |
return this.data; | |
} | |
makeNode() { | |
this.node.innerHTML = Handlebars.compile(Template.NavigateTab)(this.getData()); | |
return this.node; | |
} | |
} | |
class Navigator { | |
constructor() { } | |
init() { | |
this.registerEvents(); | |
this.clickTabDelegate({target: document.querySelector('nav > section')}); | |
} | |
registerEvents() { | |
document.querySelector('nav').addEventListener('click', this.clickTabDelegate.bind(this)); | |
} | |
switchElement(element, name) { | |
let prev_el = document.querySelector(`.${name}`); | |
if (prev_el) | |
prev_el.classList.remove(name); | |
element.classList.add(name); | |
} | |
clickTabDelegate(evt) { | |
let tabElement = evt.target; | |
let id = evt.target.querySelector('.content').id; | |
let sectionElement = document.querySelector(`.sectionArea .${id}`) || this.createTabSection(id); | |
this.switchElement(tabElement, 'selectedTab'); | |
this.switchElement(sectionElement, 'eleDisplayShow'); | |
if (!sectionElement.dataset.receivedData) { | |
sectionElement.dataset.receivedData = true; | |
let reqURL = (document.location.href.indexOf('file:') === 0) ? 'http:' : ''; | |
reqURL += '//jsonplaceholder.typicode.com/posts/' + this.getTabNumber(tabElement); | |
let updateSection = this.updateSection; | |
xhr.get(reqURL, function() { | |
updateSection(sectionElement, JSON.parse(this.responseText)); | |
}); | |
} | |
} | |
createTabSection(id) { | |
let sectionArea = document.querySelector('.sectionArea'); | |
let sectionElement = document.createElement('div'); | |
sectionElement.classList.add(id); | |
sectionArea.appendChild(sectionElement); | |
return sectionElement; | |
} | |
getTabNumber(element) { | |
let navTabs = Array.from(document.querySelectorAll('nav > .tab')); | |
for (let i = 0; i < navTabs.length; i++) { | |
if (navTabs[i] == element) | |
return i + 1; | |
} | |
} | |
updateSection(sectionElement, obj) { | |
let result = Handlebars.compile(Template.Section)({title: obj.title, content: obj.body}); | |
sectionElement.innerHTML = result; | |
} | |
} | |
class Xhr { | |
constructor() { | |
this.xhr = new XMLHttpRequest(); | |
} | |
send(url, methods, callback) { | |
this.xhr.addEventListener('load', callback); | |
this.xhr.open(methods, url); | |
this.xhr.send(); | |
} | |
get(url, callback) { | |
this.send(url, 'get', callback); | |
} | |
post(url, callback) { | |
this.send(url, 'post', callback); | |
} | |
} | |
const xhr = new Xhr(); | |
const tabList = new TabList(); | |
const nav = new Navigator(); | |
document.addEventListener('DOMContentLoaded', function () { | |
tabList.init(TabInfo); | |
nav.init(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment