Last active
June 28, 2017 20:34
-
-
Save tjunussov/8313e800d79724c7fbadce3a24397250 to your computer and use it in GitHub Desktop.
Calendar multicolumn scrollable vue
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
<style id="jsbin-css"> | |
html,body { | |
height:300px; | |
width:756px; | |
font-family:monospace; | |
} | |
/********* reseting ************/ | |
ul,li { | |
padding: 0; | |
margin: 0; | |
list-style: none; | |
box-sizing:border-box; | |
} | |
td { | |
padding:0; | |
} | |
/*********************/ | |
.scroll { | |
width: 100%; height: 100%; overflow-x: scroll; position:relative; | |
} | |
.scroll_container { | |
position:absolute; | |
left:0; | |
right:0; | |
top: 0; | |
bottom: 0; | |
} | |
/*********CALENDAR************/ | |
.table { | |
display:table; | |
border-spacing:0; | |
border-collapse:collapse; | |
padding:0; | |
margin:0; | |
box-sizing:border-box; | |
} | |
.labels ul, .items .decor ul:not(:last-child) { | |
border-right:1px solid rgba(0,0,0,0.05); | |
} | |
.items ul { | |
display: table-cell; | |
/*overflow:hidden;*/ | |
position:relative; | |
} | |
ul > label { | |
display:list-item; | |
background-color:rgba(0,0,0,0.15); | |
} | |
.items .decor li, | |
.labels li, | |
ul > label | |
{ | |
border-bottom:1px solid rgba(0,0,0,0.15); | |
height:var(--reservation-height); | |
} | |
.items ul { | |
min-width:200px; | |
overflow:hidden; | |
} | |
/*****************************/ | |
.sm-calendar { | |
--reservation-height: 25px; | |
--duration : 30; /* defaul minimal duration is 30*/ | |
--start : 1; /* minutes, start 10:00 */ | |
--precision : 30; /*[30min] 1800 sec in 30min*/ | |
} | |
.sm-calendar { | |
border:1px solid #ccc; | |
} | |
.sm-calendar td { | |
vertical-align:top; | |
} | |
/******************/ | |
.decor, .books { | |
position:absolute; | |
height: 100%; | |
} | |
.books ul, .books li { | |
} | |
/********* FX *********/ | |
.items li:hover { | |
background:rgba(255,0,0,0.5); | |
} | |
book:hover { | |
background:rgba(0,0,255,0.5); | |
} | |
/******************/ | |
book { | |
display:inline-block; | |
box-sizing:border-box; | |
overflow: hidden; | |
/*max-width: 200px;*/ | |
width: 100%; | |
background:#ccc; | |
top:calc(var(--reservation-height) * var(--start)/var(--precision)); | |
min-height:calc(var(--reservation-height) * var(--duration)/var(--precision)); /* actual height, для плавного отрытия */ | |
max-height:calc(var(--reservation-height) * var(--duration)/var(--precision));/* actual height */ | |
z-index: 16; | |
position: absolute; /* why not ? */ | |
opacity:0.8; | |
cursor:pointer; | |
} | |
/******************/ | |
book.canceled { | |
opacity:0.5; | |
z-index:-2; | |
} | |
</style> | |
<html> | |
<body> | |
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script> | |
<table id="sm-calendar" border="0" class="sm-calendar table" style="table-layout:fixed; width:100%;height:100%;"> | |
<tr> | |
<td class="labels" style="width:50px;"> | |
<ul> | |
<label>#</label> | |
<li v-for="t in timeRange">{{t+10}}:00</li> | |
</ul> | |
</td> | |
<td class="items "> | |
<div class="scroll"> | |
<div class="scroll_container"> | |
<div class="books table" style="width:100%;"> | |
<ul v-for="r in resources"> | |
<book v-for="b in books[r.name]" key="r.name" | |
:style="{ '--start':b.start, '--duration':b.end-b.start}" | |
:class="{ 'canceled':b.canceled }" | |
>{{b.title}} | |
</book> | |
</ul> | |
</div> | |
<div class="decor table" style="width:100%;"> | |
<ul v-for="r in resources"> | |
<label>{{r.name}}</label> | |
<li v-for="t in timeRange"></li> | |
</ul> | |
</div> | |
</div> | |
</div> | |
</td> | |
</tr> | |
</table> | |
<script id="jsbin-javascript"> | |
Vue.config.ignoredElements = ['book']; | |
new Vue({ | |
el: '#sm-calendar', | |
data: { | |
resources: [ | |
{ | |
"name": "Room1", | |
"status": "active" | |
}, { | |
"name": "Room2", | |
"status": "active" | |
}, { | |
"name": "Room3", | |
"status": "active" | |
}, { | |
"name": "Room4", | |
"status": "active" | |
} | |
], | |
books: { | |
"Room1": [{ | |
"start": 60, | |
"end": 120, | |
"title": "Тайская изюминка" | |
}], | |
"Room2": [{ | |
"start": 120, | |
"end": 240, | |
"title": "Тайская изюминка", | |
"canceled": true | |
}] | |
}, | |
start: 10, | |
end: 20, | |
timeRange: 10 | |
} | |
/*methods: { | |
add: !-> | |
this.items.push {text: this.todoText} | |
this.todoText = '' | |
delete: (ev) !-> | |
this.items.remove ev.targetVM.$data | |
deleteAll: !-> | |
#e = this.items | |
#pop = e.pop.bind e | |
#[0 to e.length].forEach pop | |
this.items = [] | |
}*/ | |
}); | |
</script> | |
<script id="jsbin-source-html" type="text/html"><html> | |
<body> | |
<script src="https://unpkg.com/vue@latest/dist/vue.js"><\/script> | |
<table id="sm-calendar" border="0" class="sm-calendar table" style="table-layout:fixed; width:100%;height:100%;"> | |
<tr> | |
<td class="labels" style="width:50px;"> | |
<ul> | |
<label>#</label> | |
<li v-for="t in timeRange">{{t+10}}:00</li> | |
</ul> | |
</td> | |
<td class="items "> | |
<div class="scroll"> | |
<div class="scroll_container"> | |
<div class="books table" style="width:100%;"> | |
<ul v-for="r in resources"> | |
<book v-for="b in books[r.name]" key="r.name" | |
:style="{ '--start':b.start, '--duration':b.end-b.start}" | |
:class="{ 'canceled':b.canceled }" | |
>{{b.title}} | |
</book> | |
</ul> | |
</div> | |
<div class="decor table" style="width:100%;"> | |
<ul v-for="r in resources"> | |
<label>{{r.name}}</label> | |
<li v-for="t in timeRange"></li> | |
</ul> | |
</div> | |
</div> | |
</div> | |
</td> | |
</tr> | |
</table> | |
</body> | |
</html> | |
</script> | |
<script id="jsbin-source-css" type="text/css">html,body { | |
height:300px; | |
width:756px; | |
font-family:monospace; | |
} | |
/********* reseting ************/ | |
ul,li { | |
padding: 0; | |
margin: 0; | |
list-style: none; | |
box-sizing:border-box; | |
} | |
td { | |
padding:0; | |
} | |
/*********************/ | |
.scroll { | |
width: 100%; height: 100%; overflow-x: scroll; position:relative; | |
} | |
.scroll_container { | |
position:absolute; | |
left:0; | |
right:0; | |
top: 0; | |
bottom: 0; | |
} | |
/*********CALENDAR************/ | |
.table { | |
display:table; | |
border-spacing:0; | |
border-collapse:collapse; | |
padding:0; | |
margin:0; | |
box-sizing:border-box; | |
} | |
.labels ul, .items .decor ul:not(:last-child) { | |
border-right:1px solid rgba(0,0,0,0.05); | |
} | |
.items ul { | |
display: table-cell; | |
/*overflow:hidden;*/ | |
position:relative; | |
} | |
ul > label { | |
display:list-item; | |
background-color:rgba(0,0,0,0.15); | |
} | |
.items .decor li, | |
.labels li, | |
ul > label | |
{ | |
border-bottom:1px solid rgba(0,0,0,0.15); | |
height:var(--reservation-height); | |
} | |
.items ul { | |
min-width:200px; | |
overflow:hidden; | |
} | |
/*****************************/ | |
.sm-calendar { | |
--reservation-height: 25px; | |
--duration : 30; /* defaul minimal duration is 30*/ | |
--start : 1; /* minutes, start 10:00 */ | |
--precision : 30; /*[30min] 1800 sec in 30min*/ | |
} | |
.sm-calendar { | |
border:1px solid #ccc; | |
} | |
.sm-calendar td { | |
vertical-align:top; | |
} | |
/******************/ | |
.decor, .books { | |
position:absolute; | |
height: 100%; | |
} | |
.books ul, .books li { | |
} | |
/********* FX *********/ | |
.items li:hover { | |
background:rgba(255,0,0,0.5); | |
} | |
book:hover { | |
background:rgba(0,0,255,0.5); | |
} | |
/******************/ | |
book { | |
display:inline-block; | |
box-sizing:border-box; | |
overflow: hidden; | |
/*max-width: 200px;*/ | |
width: 100%; | |
background:#ccc; | |
top:calc(var(--reservation-height) * var(--start)/var(--precision)); | |
min-height:calc(var(--reservation-height) * var(--duration)/var(--precision)); /* actual height, для плавного отрытия */ | |
max-height:calc(var(--reservation-height) * var(--duration)/var(--precision));/* actual height */ | |
z-index: 16; | |
position: absolute; /* why not ? */ | |
opacity:0.8; | |
cursor:pointer; | |
} | |
/******************/ | |
book.canceled { | |
opacity:0.5; | |
z-index:-2; | |
}</script> | |
<script id="jsbin-source-javascript" type="text/javascript">Vue.config.ignoredElements = ['book']; | |
new Vue { | |
el: '#sm-calendar', | |
data: { | |
resources: [ | |
{"name":"Room1", "status":"active"}, | |
{"name":"Room2", "status":"active"}, | |
{"name":"Room3", "status":"active"}, | |
{"name":"Room4", "status":"active"} | |
], | |
books : { | |
"Room1" : [{"start":60, "end":120, "title": "Тайская изюминка"}], | |
"Room2" : [{"start":120, "end":240, "title": "Тайская изюминка", "canceled":true }] | |
}, | |
start:10, | |
end:20, | |
timeRange : 10 | |
}, | |
/*methods: { | |
add: !-> | |
this.items.push {text: this.todoText} | |
this.todoText = '' | |
delete: (ev) !-> | |
this.items.remove ev.targetVM.$data | |
deleteAll: !-> | |
#e = this.items | |
#pop = e.pop.bind e | |
#[0 to e.length].forEach pop | |
this.items = [] | |
}*/ | |
} | |
</script></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
html,body { | |
height:300px; | |
width:756px; | |
font-family:monospace; | |
} | |
/********* reseting ************/ | |
ul,li { | |
padding: 0; | |
margin: 0; | |
list-style: none; | |
box-sizing:border-box; | |
} | |
td { | |
padding:0; | |
} | |
/*********************/ | |
.scroll { | |
width: 100%; height: 100%; overflow-x: scroll; position:relative; | |
} | |
.scroll_container { | |
position:absolute; | |
left:0; | |
right:0; | |
top: 0; | |
bottom: 0; | |
} | |
/*********CALENDAR************/ | |
.table { | |
display:table; | |
border-spacing:0; | |
border-collapse:collapse; | |
padding:0; | |
margin:0; | |
box-sizing:border-box; | |
} | |
.labels ul, .items .decor ul:not(:last-child) { | |
border-right:1px solid rgba(0,0,0,0.05); | |
} | |
.items ul { | |
display: table-cell; | |
/*overflow:hidden;*/ | |
position:relative; | |
} | |
ul > label { | |
display:list-item; | |
background-color:rgba(0,0,0,0.15); | |
} | |
.items .decor li, | |
.labels li, | |
ul > label | |
{ | |
border-bottom:1px solid rgba(0,0,0,0.15); | |
height:var(--reservation-height); | |
} | |
.items ul { | |
min-width:200px; | |
overflow:hidden; | |
} | |
/*****************************/ | |
.sm-calendar { | |
--reservation-height: 25px; | |
--duration : 30; /* defaul minimal duration is 30*/ | |
--start : 1; /* minutes, start 10:00 */ | |
--precision : 30; /*[30min] 1800 sec in 30min*/ | |
} | |
.sm-calendar { | |
border:1px solid #ccc; | |
} | |
.sm-calendar td { | |
vertical-align:top; | |
} | |
/******************/ | |
.decor, .books { | |
position:absolute; | |
height: 100%; | |
} | |
.books ul, .books li { | |
} | |
/********* FX *********/ | |
.items li:hover { | |
background:rgba(255,0,0,0.5); | |
} | |
book:hover { | |
background:rgba(0,0,255,0.5); | |
} | |
/******************/ | |
book { | |
display:inline-block; | |
box-sizing:border-box; | |
overflow: hidden; | |
/*max-width: 200px;*/ | |
width: 100%; | |
background:#ccc; | |
top:calc(var(--reservation-height) * var(--start)/var(--precision)); | |
min-height:calc(var(--reservation-height) * var(--duration)/var(--precision)); /* actual height, для плавного отрытия */ | |
max-height:calc(var(--reservation-height) * var(--duration)/var(--precision));/* actual height */ | |
z-index: 16; | |
position: absolute; /* why not ? */ | |
opacity:0.8; | |
cursor:pointer; | |
} | |
/******************/ | |
book.canceled { | |
opacity:0.5; | |
z-index:-2; | |
} |
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
Vue.config.ignoredElements = ['book']; | |
new Vue({ | |
el: '#sm-calendar', | |
data: { | |
resources: [ | |
{ | |
"name": "Room1", | |
"status": "active" | |
}, { | |
"name": "Room2", | |
"status": "active" | |
}, { | |
"name": "Room3", | |
"status": "active" | |
}, { | |
"name": "Room4", | |
"status": "active" | |
} | |
], | |
books: { | |
"Room1": [{ | |
"start": 60, | |
"end": 120, | |
"title": "Тайская изюминка" | |
}], | |
"Room2": [{ | |
"start": 120, | |
"end": 240, | |
"title": "Тайская изюминка", | |
"canceled": true | |
}] | |
}, | |
start: 10, | |
end: 20, | |
timeRange: 10 | |
} | |
/*methods: { | |
add: !-> | |
this.items.push {text: this.todoText} | |
this.todoText = '' | |
delete: (ev) !-> | |
this.items.remove ev.targetVM.$data | |
deleteAll: !-> | |
#e = this.items | |
#pop = e.pop.bind e | |
#[0 to e.length].forEach pop | |
this.items = [] | |
}*/ | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment