Skip to content

Instantly share code, notes, and snippets.

@russiann
Last active August 29, 2015 14:23
Show Gist options
  • Save russiann/e40f525a03927e214a54 to your computer and use it in GitHub Desktop.
Save russiann/e40f525a03927e214a54 to your computer and use it in GitHub Desktop.
<!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