Last active
August 29, 2015 14:23
-
-
Save russiann/e40f525a03927e214a54 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
<!DOCTYPE html> | |
<html ng-app="calendar"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Document</title> | |
</head> | |
<style> | |
/* | |
Some stylesheets for this pen, ignore.. | |
*/ | |
body { | |
font-family: 'helvetica neue'; | |
background-color: #A25200; | |
width: 100vw; | |
height: 100vh; | |
margin:0; | |
} | |
flex-calendar { | |
order: 0; | |
flex: 0 1 auto; | |
align-self: auto; | |
box-shadow:0px 0px 7px 0px rgba(0,0,0,0.3); | |
} | |
/* | |
Calendar :D | |
*/ | |
flex-calendar { | |
width: 100%; | |
min-height: 50px; | |
color: #FFFFFF; | |
font-weight: 200; | |
} | |
flex-calendar .month { | |
position:relative; | |
display: flex; | |
flex-direction: row; | |
flex-wrap: nowrap; | |
justify-content: space-between; | |
align-content: flex-start; | |
align-items: flex-start; | |
background-color: #ffb835; | |
} | |
flex-calendar .month .arrow, | |
flex-calendar .month .label{ | |
height: 60px; | |
order: 0; | |
flex: 0 1 auto; | |
align-self: auto; | |
line-height: 60px; | |
font-size:20px; | |
} | |
flex-calendar .month .arrow { | |
width: 50px; | |
box-sizing: border-box; | |
background: url( data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAABqUlEQVR4Xt3b0U3EMBCE4XEFUAolHB0clUFHUAJ0cldBkKUgnRDh7PWsd9Z5Tpz8nyxFspOCJMe2bU8AXgG8lFIurMcurIE8x9nj3wE8AvgE8MxCkAf4Ff/jTEOQBjiIpyLIAtyJpyFIAjTGUxDkADrjhxGkAIzxQwgyAIPxZgQJAFJ8RbgCOJVS6muy6QgHiIyvQqEA0fGhAArxYQAq8SEASvHTAdTipwIoxk8DUI2fAqAc7w6gHu8KkCHeDSBLvAtApng6QLZ4KkDGeBpA1ngKQOb4YYDs8UMAK8SbAVaJNwGsFN8NsFq8FeADwEPTmvPxSXV/v25xNy9fD97v8PLuVeF9FiyD0A1QKVdCMAGshGAGWAVhCGAFhGGA7AgUgMwINICsCFSAjAh0gGwILgCZENwAsiC4AmRAcAdQR5gCoIwwDUAVYSqAIsJ0ADWEEAAlhDAAFYRQAAWEcIBoBAkAIsLX/rV48291MgAEhO747o0Rr82J23GNS+6meEkAw0wwx8sCdCAMxUsDNCAMx8sD/INAiU8B8AcCLT4NwA3CG4Az68/xOu43keZ+UGLOkN4AAAAASUVORK5CYII=) no-repeat; | |
background-size: contain; | |
background-origin: content-box; | |
padding:15px 5px; | |
} | |
flex-calendar .month .arrow:last-child { | |
transform: rotate(180deg); | |
} | |
flex-calendar .week, | |
flex-calendar .days { | |
line-height: 25px; | |
font-size: 16px; | |
display: flex; | |
flex-wrap: wrap; | |
} | |
flex-calendar .week { | |
background-color: #faac1c; | |
} | |
flex-calendar .week .day, | |
flex-calendar .days .day{ | |
flex-grow: 0; | |
min-width: 14.285714286%; | |
text-align: center; | |
} | |
flex-calendar .days .day{ | |
min-height: 60px; | |
box-sizing: border-box; | |
position: relative; | |
line-height: 60px; | |
border-top:1px solid #FCFCFC; | |
background-color: #fff; | |
color: #c0c0c0; | |
transition: all 0.3s ease; | |
} | |
flex-calendar .days .day.out { | |
background-color: #fCFCFC; | |
} | |
flex-calendar .days .day.today, | |
flex-calendar .days .day.disabled.today{ | |
color: #FFB835; | |
border: 1px solid; | |
} | |
flex-calendar .days .day.selected { | |
display: flex; | |
flex-direction: row; | |
flex-wrap: nowrap; | |
justify-content: center; | |
align-content: center; | |
align-items: center; | |
} | |
flex-calendar .days .day.selected .number { | |
width: 40px; | |
height: 40px; | |
background-color: #FFB835; | |
border-radius: 100%; | |
line-height: 40px; | |
color: #FFFFFF; | |
} | |
flex-calendar .days .day:not(.disabled):not(.out){ | |
cursor: pointer; | |
} | |
flex-calendar .days .day.disabled { | |
border: none; | |
} | |
/* FFDC9A */ | |
flex-calendar .days .day.disabled .number { | |
background-color: #EFEFEF; | |
background-image: url('data:image/gif;base64,R0lGODlhBQAFAOMAAP/14////93uHt3uHt3uHt3uHv///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAFAAUAAAQL0ACAzpG0YnonNxEAOw=='); | |
} | |
flex-calendar .days .day.event:before { | |
content: ""; | |
width: 6px; | |
height: 6px; | |
border-radius:100%; | |
background-color: #faac1c; | |
position:absolute; | |
bottom:10px; | |
margin-left:-3px; | |
} | |
</style> | |
<body ng-controller="MainController"> | |
<flex-calendar options="options"></flex-calendar> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.min.js"></script> | |
<script> | |
angular | |
.module('calendar', ['russian60.flexcalendar']) | |
.controller('MainController', MainController); | |
MainController.$inject = ['$scope']; | |
function MainController($scope) { | |
$scope.options = { | |
maxDate: new Date([2020, 12, 31]), | |
dayNamesLength: 1, // How to display weekdays (1 for "M", 2 for "Mo", 3 for "Mon"; 9 will show full day names; default is 1) | |
eventClick: function eventClick (event){ | |
/* body... */ | |
}, | |
dateClick: function dateClick (event){ | |
/* body... */ | |
}, | |
changeMonth: function changeMonth (event){ | |
/* body... */ | |
}, | |
}; | |
} | |
</script> | |
<script> | |
(function(){ | |
angular | |
.module('russian60.flexcalendar', []) | |
.directive('flexCalendar', flexCalendar); | |
function flexCalendar() { | |
var template = | |
'<div class="flex-calendar">'+ | |
'<div class="month">'+ | |
'<div class="arrow" ng-click="prevMonth()"></div>'+ | |
'<div class="label">{{selectedMonth}} {{selectedYear}}</div>'+ | |
'<div class="arrow" ng-click="nextMonth()"></div>'+ | |
'</div>'+ | |
'<div class="week">'+ | |
'<div class="day" ng-repeat="day in weekDays(options.dayNamesLength) track by $index">{{day}}</div>'+ | |
'</div>'+ | |
'<div class="days">'+ | |
'<div class="day"'+ | |
'ng-repeat="day in days track by $index"'+ | |
'ng-class="{selected: isDefaultDate(day), event: day.event, disabled: day.disabled, out: !day}"'+ | |
'ng-click="onClick(day, $index)"'+ | |
'>'+ | |
'<div class="number">{{day.day}}</div>'+ | |
'</div>'+ | |
'</div>'+ | |
'</div>'; | |
var directive = { | |
restrict: 'E', | |
scope: { | |
options: '=?', | |
events: '=?' | |
}, | |
template: template, | |
controller: Controller | |
}; | |
return directive; | |
} | |
Controller.$inject = ['$scope']; | |
function Controller($scope) { | |
var MONTHS = ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro']; | |
var WEEKDAYS = ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado']; | |
var calculateSelectedDate, calculateWeeks, allowedDate, bindEvent; | |
$scope.days = []; | |
$scope.options = $scope.options || {}; | |
$scope.options.dayNamesLength = $scope.options.dayNamesLength || 1; | |
$scope.onClick = function (date, index) { | |
if (!date || date.disabled) { return; } | |
$scope.options.defaultDate = date.date; | |
if (date.event) { | |
$scope.options.eventClick(date); | |
} else { | |
$scope.options.dateClick(date); | |
} | |
}; | |
if ($scope.options.minDate) { | |
$scope.options.minDate = new Date($scope.options.minDate); | |
} | |
if ($scope.options.maxDate) { | |
$scope.options.maxDate = new Date($scope.options.maxDate); | |
} | |
bindEvent = function (date) { | |
if (!date || !$scope.events) { return; } | |
$scope.events.forEach(function(event) { | |
event.date = new Date(event.date); | |
if (date.year === event.date.getFullYear() && date.month === event.date.getMonth() && date.day === event.date.getDate()) { | |
date.event = event; | |
} | |
}); | |
}; | |
allowedDate = function (date) { | |
if (!$scope.options.minDate && !$scope.options.maxDate) { | |
return true; | |
} | |
var currDate = new Date([date.year, date.month + 1, date.day]); | |
if ($scope.options.minDate && (currDate < $scope.options.minDate)) { return false; } | |
if ($scope.options.maxDate && (currDate > $scope.options.maxDate)) { return false; } | |
return true; | |
}; | |
$scope.allowedPrevMonth = function () { | |
var prevYear = null; | |
var prevMonth = null; | |
if (!$scope.options.minDate) { return true; } | |
var currMonth = MONTHS.indexOf($scope.selectedMonth); | |
if (currMonth === 0) { | |
prevYear = ($scope.selectedYear - 1); | |
} else { | |
prevYear = $scope.selectedYear; | |
} | |
if (currMonth === 0) { | |
prevMonth = 11; | |
} else { | |
prevMonth = (currMonth - 1); | |
} | |
if (prevYear < $scope.options.minDate.getFullYear()) { return false; } | |
if (prevYear === $scope.options.minDate.getFullYear()) { | |
if (prevMonth < $scope.options.minDate.getMonth()) { return false; } | |
} | |
return true; | |
}; | |
$scope.allowedNextMonth = function () { | |
var nextYear = null; | |
var nextMonth = null; | |
if (!$scope.options.maxDate) { return true; } | |
var currMonth = MONTHS.indexOf($scope.selectedMonth); | |
if (currMonth === 11) { | |
nextYear = ($scope.selectedYear + 1); | |
} else { | |
nextYear = $scope.selectedYear; | |
} | |
if (currMonth === 11) { | |
nextMonth = 0; | |
} else { | |
nextMonth = (currMonth + 1); | |
} | |
if (nextYear > $scope.options.maxDate.getFullYear()) { return false; } | |
if (nextYear === $scope.options.maxDate.getFullYear()) { | |
if (nextMonth > $scope.options.maxDate.getMonth()) { return false; } | |
} | |
return true; | |
}; | |
flattenWeek = function(){ | |
$scope.days = $scope.weeks.reduce(function(a, b) { | |
return a.concat(b); | |
}); | |
}; | |
calculateWeeks = function () { | |
$scope.weeks = []; | |
var week = null; | |
var daysInCurrentMonth = new Date($scope.selectedYear, MONTHS.indexOf($scope.selectedMonth) + 1, 0).getDate(); | |
for (var day = 1; day < daysInCurrentMonth + 1; day += 1) { | |
var date = new Date($scope.selectedYear, MONTHS.indexOf($scope.selectedMonth), day); | |
var dayNumber = new Date($scope.selectedYear, MONTHS.indexOf($scope.selectedMonth), day).getDay(); | |
week = week || [null, null, null, null, null, null, null]; | |
week[dayNumber] = { | |
year: $scope.selectedYear, | |
month: MONTHS.indexOf($scope.selectedMonth), | |
day: day, | |
date: date, | |
_month : date.getMonth() + 1, | |
}; | |
if (allowedDate(week[dayNumber])) { | |
if ($scope.events) { bindEvent(week[dayNumber]); } | |
} else { | |
week[dayNumber].disabled = true; | |
} | |
if (dayNumber === 6 || day === daysInCurrentMonth) { | |
$scope.weeks.push(week); | |
week = undefined; | |
} | |
} | |
flattenWeek(); | |
}; | |
calculateSelectedDate = function () { | |
if ($scope.options.defaultDate) { | |
$scope.options._defaultDate = new Date($scope.options.defaultDate); | |
} else { | |
$scope.options._defaultDate = new Date(); | |
} | |
$scope.selectedYear = $scope.options._defaultDate.getFullYear(); | |
$scope.selectedMonth = MONTHS[$scope.options._defaultDate.getMonth()]; | |
$scope.selectedDay = $scope.options._defaultDate.getDate(); | |
calculateWeeks(); | |
}; | |
$scope.weekDays = function (size) { | |
return WEEKDAYS.map(function(name) { return name.slice(0, size) }); | |
}; | |
$scope.isDefaultDate = function (date) { | |
if (!date) { return; } | |
var result = date.year === $scope.options._defaultDate.getFullYear() && | |
date.month === $scope.options._defaultDate.getMonth() && | |
date.day === $scope.options._defaultDate.getDate(); | |
return result; | |
}; | |
$scope.prevMonth = function () { | |
if (!$scope.allowedPrevMonth()) { return; } | |
var currIndex = MONTHS.indexOf($scope.selectedMonth); | |
if (currIndex === 0) { | |
$scope.selectedYear -= 1; | |
$scope.selectedMonth = MONTHS[11]; | |
} else { | |
$scope.selectedMonth = MONTHS[currIndex - 1]; | |
} | |
var month = {name: $scope.selectedMonth, index: currIndex - 1, _index: currIndex+2 } | |
$scope.options.changeMonth(month); | |
calculateWeeks(); | |
}; | |
$scope.nextMonth = function () { | |
if (!$scope.allowedNextMonth()) { return; } | |
var currIndex = MONTHS.indexOf($scope.selectedMonth); | |
if (currIndex === 11) { | |
$scope.selectedYear += 1; | |
$scope.selectedMonth = MONTHS[0]; | |
} else { | |
$scope.selectedMonth = MONTHS[currIndex + 1]; | |
} | |
var month = {name: $scope.selectedMonth, index: currIndex + 1, _index: currIndex+2 } | |
$scope.options.changeMonth(month); | |
calculateWeeks(); | |
}; | |
$scope.$watch('options.defaultDate', function() { | |
calculateSelectedDate(); | |
}); | |
$scope.$watch('events', function() { | |
calculateWeeks(); | |
}); | |
} | |
})(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment