123

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <div id="calendar-container">
  <div id="calendar-header">
    <div class="calendar-header-box calendar-button" onclick="calendarBack()"><i class="fa fa-angle-left"></i></div>
    <div id="calendar-year-title" class="calendar-header-box year">2017</div>
    <div class="calendar-header-box calendar-button" onclick="calendarNext()"><i class="fa fa-angle-right"></i></div>
  </div>
  <div id="calendar-wrapper">
  
  </div>
</div>
            
          
!
            
              
$color_dark: rgb(51,51,51)
$color_dark_saturated: rgb(72,107,111)
$color_complement: rgb(217,195,164)
$color_bright: rgb(63,171,171)
$color_light: rgb(252,241,247)

$color_booked: rgba($color_bright, 0.24)
$color_pending: rgba(200, 200, 200, 0.2)

html, body
  padding: 0px
  margin: 0px
  border: 0px

#calendar-container
  display: inline-block
  border-collapse: collapse
  text-align: center
  background-color: $color_dark
  font-family: 'Roboto Condensed', sans-serif
  padding-left: 0pt
  padding-right: 0pt
  //padding-bottom: 5pt
  padding-top: 10pt
  height: 270px
  width: 714px
  overflow: hidden

#calendar-wrapper
  width: 714px
  
.calendar-month-heading
  color: $color_bright
  position: absolute
  left: 0pt
  right: 0pt
  top: 0pt
  height: 30pt

#calendar-header
  color: $color_bright
  font-size: 14pt
  line-height: 14pt
  padding-top: 5pt
  padding-bottom: 6pt
  position: relative
  //text-shadow: 0px 0px 8px rgba($color_bright, 0.6)

.calendar-header-box
  float: left
  width: 35%
  background-color: $color_dark
  &.year
    width: 30%
    font-weight: 700
    font-size: 24pt
  
  &.calendar-button
    font-size: 30pt
    line-height: 30pt
    margin-top: -10pt
    transition: all 300ms ease-in-out
    &:hover
      color: $color_complement

table.calendar
  float: left
  text-align: center
  border: 0px solid
  padding-left: 5px
  padding-right: 5px
  padding-bottom: 10px
  padding-top: 12px
  
  &.calendar-table1
  
.calendar-dim
  opacity: 0.4

.calendar-table-break
  float: left
  text-align: center
  width: 2px
  border-collapse: collapse
  border: 0px solid
  margin: 0px
  padding: 0px
  
.calendar-table-break-child
  height: 200px
  border: 0px solid
  margin: 0px
  padding: 0px
  margin-bottom: -190px
  margin-top: 20px
  background-color: $color_dark_saturated

th.calendar,
td.calendar
  width: 28px
  height: 28px
  border: 0px solid
  margin: 0px
  padding: 0px
  z-index: -1


th.calendar
  color: $color_bright

td.calendar
  color: $color_light
  font-size: 10pt
  border: 1px solid transparent
  transition: all 500ms
  -webkit-transition: all 500ms
  position: relative
  
  &:hover
    border: 1px solid $color_dark_saturated
  
  &.calendar-daystyle-today
    border: 1px solid $color_bright
    
  &.calendar-daystyle-price-normal::after
    content: ''
    position: absolute
    bottom: -1px
    left: 0px
    right: 0px
    height: 2px
    margin: 0px
    border: 0px solid
    border-bottom: 0px solid rgba(pink, 0.3)
    
  &.calendar-daystyle-price-high::after
    content: ''
    position: absolute
    bottom: -1px
    left: 0px
    right: 0px
    height: 2px
    margin: 0px
    border: 0px solid
    border-bottom: 1px solid rgba(pink, 0.4)
    
  &.calendar-daystyle-price-peak::after
    content: ''
    position: absolute
    bottom: -1px
    left: 0px
    right: 0px
    height: 2px
    margin: 0px
    border: 0px solid
    border-bottom: 1px solid rgba(260, 100, 115, 0.6)

    
    
    
.calendar-daystyle-booking-middle::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background-color: $color_booked
  //rgba(200, 200, 200, 0.26)
  
.calendar-daystyle-booking-start::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background: linear-gradient(to bottom right, rgba(100,100,100,0) 0%, rgba(100,100,100,0) 49%, $color_booked 51%, $color_booked 100%)
  
.calendar-daystyle-booking-end::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background: linear-gradient(to top left, rgba(100,100,100,0) 0%, rgba(100,100,100,0) 49%, $color_booked 51%, $color_booked 100%)
  
.calendar-daystyle-booking-cross::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background: linear-gradient(to top left, $color_booked 0%, $color_booked 40%, rgba(100,100,100,0) 41%, rgba(100,100,100,0) 59%, $color_booked 60%, $color_booked 100%)
  
.calendar-daystyle-booking-cross-pending::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background: linear-gradient(to top left, $color_pending 0%, $color_pending 40%, rgba(100,100,100,0) 41%, rgba(100,100,100,0) 59%, $color_booked 60%, $color_booked 100%)

  
.calendar-daystyle-pending-middle::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background-color: $color_pending
  //rgba(200, 200, 200, 0.26)
  
.calendar-daystyle-pending-start::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background: linear-gradient(to bottom right, rgba(100,100,100,0) 0%, rgba(100,100,100,0) 49%, $color_pending 51%, $color_pending 100%)
  
.calendar-daystyle-pending-end::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background: linear-gradient(to top left, rgba(100,100,100,0) 0%, rgba(100,100,100,0) 49%, $color_pending 51%, $color_pending 100%)
  
.calendar-daystyle-pending-cross::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background: linear-gradient(to top left, $color_pending 0%, $color_pending 40%, rgba(100,100,100,0) 41%, rgba(100,100,100,0) 59%, $color_pending 60%, $color_pending 100%)
  
.calendar-daystyle-pending-cross-booking::before
  content: ''
  position: absolute
  bottom: 2px
  top: 2px
  left: 2px
  right: 2px
  margin: 0px
  border: 0px solid
  z-index: 1
  background: linear-gradient(to top left, $color_booked 0%, $color_booked 40%, rgba(100,100,100,0) 41%, rgba(100,100,100,0) 59%, $color_pending 60%, $color_pending 100%)
  
  
.calendar-animation-left
  transform-origin: left
  animation: calendarLeft 1400ms cubic-bezier(0.55, 0.01, 0.17, 1.01) 1 forwards
  
.calendar-animation-right
  transform-origin: right
  animation: calendarRight 1400ms cubic-bezier(0.55, 0.01, 0.17, 1.01) 1 forwards
  
.calendar-animation-leftFade
  transform-origin: left
  animation: calendarLeftFade 1200ms cubic-bezier(0.55, 0.01, 0.17, 1.01) 1 forwards
  
.calendar-animation-rightFade
  transform-origin: right
  animation: calendarRightFade 1200ms cubic-bezier(0.55, 0.01, 0.17, 1.01) 1 forwards
  
.calendar-animation-leftFadeOut
  transform-origin: right
  animation: calendarLeftFadeOut 1000ms cubic-bezier(0.55, 0.01, 0.17, 1.01) 1 forwards
  
.calendar-animation-rightFadeOut
  transform-origin: left
  animation: calendarRightFadeOut 1000ms cubic-bezier(0.55, 0.01, 0.17, 1.01) 1 forwards
  
@keyframes calendarLeft
  0%
    transform: translateX(238px)
    -webkit-transform: translateX(238px)
  100%
    transform: translateX(0px)
    -webkit-transform: translateX(0px)
  
@keyframes calendarRight
  0%
    transform: translateX(-238px)
    -webkit-transform: translateX(-238px)
  100%
    transform: translateX(0px)
    -webkit-transform: translateX(0px)
  
@keyframes calendarLeftFade
  0%
    transform: translateX(238px)
    -webkit-transform: translateX(238px)
    opacity: 0.4
    -webkit-opacity: 0.4
  100%
    transform: translateX(0px)
    -webkit-transform: translateX(0px)
    opacity: 1.0
    -webkit-opacity: 1.0
  
@keyframes calendarRightFade
  0%
    transform: translateX(-238px)
    -webkit-transform: translateX(-238px)
    opacity: 0.4
    -webkit-opacity: 0.4
  100%
    transform: translateX(0px)
    -webkit-transform: translateX(0px)
    opacity: 1.0
    -webkit-opacity: 1.0
  
@keyframes calendarLeftFadeOut
  0%
    transform: translateX(238px)
    -webkit-transform: translateX(238px)
    opacity: 1.0
    -webkit-opacity: 1.0
  100%
    transform: translateX(0px)
    -webkit-transform: translateX(0px)
    opacity: 0.4
    -webkit-opacity: 0.4
  
@keyframes calendarRightFadeOut
  0%
    transform: translateX(-238px)
    -webkit-transform: translateX(-238px)
    opacity: 1.0
    -webkit-opacity: 1.0
  100%
    transform: translateX(0px)
    -webkit-transform: translateX(0px)
    opacity: 0.4
    -webkit-opacity: 0.4
  
// Drop

.calendar-animation-drop
  animation: calendarDrop 300ms cubic-bezier(0.55, 0.01, 0.17, 1.01) 1 forwards
  
@keyframes calendarDrop
  0%
    transform: translateY(0pt)
    -webkit-transform: translateY(0pt)
    opacity: 0.4
    -webkit-opacity: 0.4
  100%
    transform: translateY(200pt)
    -webkit-transform: translateY(200pt)
    opacity: 0.0
    -webkit-opacity: 0.0
            
          
!
            
              Date.prototype.addDays = function(days) {
  var dat = new Date(this.valueOf())
  dat.setDate(dat.getDate() + days);
  return dat;
};

var focusDate = new Date();
var today = new Date();

window.onload = function(){
  var container = document.getElementById("calendar-wrapper");
  
  makeCalendar(true, focusDate);
};

function calendarBack() {
  var fadeOutTable = document.getElementsByClassName("calendar-table3")[0];
  fadeOutTable.classList.add("calendar-animation-drop");
  window.setTimeout(function() {
    var newYear = focusDate.getFullYear();
    var newMonth = focusDate.getMonth()-1;
    if(newMonth == 0){
      newMonth = 12;
      newYear--;
    }
    focusDate.setYear(newYear);
    focusDate.setMonth(newMonth);
    makeCalendar(true, focusDate, false);
  }, 300);
}

function calendarNext() {
  var fadeOutTable = document.getElementsByClassName("calendar-table1")[0];
  fadeOutTable.classList.add("calendar-animation-drop");
  window.setTimeout(function() {
    var newYear = focusDate.getFullYear();
    var newMonth = focusDate.getMonth()+1;
    if(newMonth == 12){
      newMonth = 0;
      newYear++;
    }
    focusDate.setYear(newYear);
    focusDate.setMonth(newMonth);
    makeCalendar(true, focusDate, true);
  }, 300);
}

function makeCalendar(isTriple, fDate, isNext){
  var elements = document.getElementsByClassName("calendar");
  while(elements.length > 0){
    elements[0].parentNode.removeChild(elements[0]);
  }
  
  document.getElementById("calendar-year-title").innerHTML = fDate.getFullYear();
  
  if(!isTriple){
    document.getElementById("calendar-wrapper").appendChild(getCalendarTable(focusDate.getFullYear(), focusDate.getMonth()+1));
  } else {
    var tableToEdit = getCalendarTable(focusDate.getFullYear(), focusDate.getMonth());
    tableToEdit.classList.add("calendar-dim");
    tableToEdit.classList.add("calendar-table1");
    if(isNext){
      tableToEdit.classList.add("calendar-animation-leftFadeOut");
    } else {
      tableToEdit.classList.add("calendar-animation-right");
    }
    document.getElementById("calendar-wrapper").appendChild(tableToEdit);
    addBreak();
    tableToEdit = getCalendarTable(focusDate.getFullYear(), focusDate.getMonth()+1);
    tableToEdit.classList.add("calendar-table2");
    if(isNext){
      tableToEdit.classList.add("calendar-animation-leftFade");
    } else {
      tableToEdit.classList.add("calendar-animation-rightFade");
    }
    document.getElementById("calendar-wrapper").appendChild(tableToEdit);
    addBreak();
    tableToEdit = getCalendarTable(focusDate.getFullYear(), focusDate.getMonth()+2);
    tableToEdit.classList.add("calendar-dim");
    tableToEdit.classList.add("calendar-table3");
    if(isNext){
      tableToEdit.classList.add("calendar-animation-left");
    } else {
      tableToEdit.classList.add("calendar-animation-rightFadeOut");
    }
    document.getElementById("calendar-wrapper").appendChild(tableToEdit);
  }
};

function addBreak() {
  var breakElement = document.createElement('div');
  breakElement.classList.add("calendar-table-break");
  breakElement.classList.add("calendar");
  var breakElementChild = document.createElement('div');
  breakElementChild.classList.add("calendar-table-break-child");
  breakElement.appendChild(breakElementChild);
  document.getElementById("calendar-wrapper").appendChild(breakElement);
};

function getCalendarTable(year, month){  
  if(month == 0){
    month = 12;
    year--;
  }
  
  if(month == 13){
    month = 1;
    year++;
  }
  
  // Safari fix
  if(month < 10){
    month = "0" + month;
  }
  
  var calendarDate = new Date(year + "-" + month + "-01");
  var firstDay = calendarDate.getDay();
  var numberOfDays = new Date(calendarDate.getFullYear(), calendarDate.getMonth() + 1, 0).getDate();
  
  var monthNameArray = ["January","February","March","April","May","June","July","August","September","October","November","December"];
  
  // Create HTML Table
  var table = document.createElement('table');
  table.classList.add("calendar");
  var heading = document.createElement('div');
  heading.classList.add("calendar-month-heading");
  heading.innerHTML = monthNameArray[month-1];
  table.appendChild(heading);
  var tr = document.createElement('tr');
  tr.classList.add("calendar");
  
  // Day Letters
  for(var i = 0; i < 7; i++){
    var th = document.createElement('th');
    th.classList.add("calendar");
    th.innerHTML = "SMTWTFS"[i];
    tr.appendChild(th);
  }
  table.appendChild(tr);
  
  // Week 1
  tr = document.createElement('tr');
  tr.classList.add("calendar");
  var i = 0;
  for(; i < 7; i++){
    if(i == firstDay){
      break;
    }
    var td = document.createElement('td');
    td.classList.add("calendar");
    td.innerHTML = "";
    tr.appendChild(td);
  }
  table.appendChild(tr);
  
  var dayNumber = 1;
  for(; i < 7; i++){
    var td = document.createElement('td');
    td.classList.add("calendar");
    processDay(td, calendarDate, dayNumber);
    td.innerHTML = dayNumber;
    dayNumber++;
    tr.appendChild(td);
  }
  table.appendChild(tr);
  
  // Other Weeks
  for(var r = 3; r <= 7; r++){
    tr = document.createElement('tr');
    tr.classList.add("calendar");
    for(var i = 0; i < 7; i++){
      if(dayNumber > numberOfDays){
        table.appendChild(tr);
        return table;
      }
      var td = document.createElement('td');
      td.classList.add("calendar");
      processDay(td, calendarDate, dayNumber);
      td.innerHTML = dayNumber;
      dayNumber++;
      tr.appendChild(td);
    }
    table.appendChild(tr);
  }
  return table;
};

var seasons = [ new DaysRange(new Date("2016-11-25"), new Date("2017-01-20"), "peak"),
                new DaysRange(new Date("2017-01-21"), new Date("2017-02-02"), "high")
              ];

var bookings = [ new DaysRange(new Date("2017-01-11"), new Date("2017-01-16"), "booked"),
                 new DaysRange(new Date("2017-01-16"), new Date("2017-01-28"), "pending"),
                 new DaysRange(new Date("2016-12-23"), new Date("2017-01-04"), "booked"),
                 new DaysRange(new Date("2017-02-04"), new Date("2017-02-22"), "pending"),
                 new DaysRange(new Date("2017-02-22"), new Date("2017-02-24"), "pending"),
                 new DaysRange(new Date("2017-02-24"), new Date("2017-03-04"), "booked")
              ];

function DaysRange(startDate, endDate, name){
  this.days = getDates(startDate, endDate);
  this.name = name;
};

function processDay(element, calendarDate, dayNumber){
  var dayDate = new Date(calendarDate.getTime());
  dayDate.setDate(dayNumber);
  
  // Highlight Today
  if(dayDate.toDateString() == today.toDateString()){
    element.classList.add("calendar-daystyle-today");
  }
  
  var bookingName = getDateBooking(dayDate.toDateString());
  //console.log(dayNumber + " : " + bookingName);
  if(bookingName.startsWith("booked")){
    if(bookingName.includes("_start") && bookingName.includes("_end")){
      if(bookingName.includes("pending")){
        element.classList.add("calendar-daystyle-booking-cross-pending");
      } else {
        element.classList.add("calendar-daystyle-booking-cross");
      }
    } else if(bookingName.includes("_start")){
      element.classList.add("calendar-daystyle-booking-start");
    } else if(bookingName.includes("_end")){
      element.classList.add("calendar-daystyle-booking-end");
    } else {
      element.classList.add("calendar-daystyle-booking-middle");
    }
  } else if(bookingName.startsWith("pending")) {
    if(bookingName.includes("_start") && bookingName.includes("_end")){
      if(bookingName.includes("booked")){
        element.classList.add("calendar-daystyle-pending-cross-booking");
      } else {
        element.classList.add("calendar-daystyle-pending-cross");
      }
    } else if(bookingName.includes("_start")){
      element.classList.add("calendar-daystyle-pending-start");
    } else if(bookingName.includes("_end")){
      element.classList.add("calendar-daystyle-pending-end");
    } else {
      element.classList.add("calendar-daystyle-pending-middle");
    }
  }
  
  var seasonName = getDateSeason(dayDate.toDateString());
  if(seasonName == "peak"){
    element.classList.add("calendar-daystyle-price-peak");
  } else if(seasonName == "high") {
    element.classList.add("calendar-daystyle-price-high");
  } else {
    element.classList.add("calendar-daystyle-price-normal");
  }
  
};

function getDateSeason(dayDateString){
  var seasonName = "";
  seasons.forEach(function (season) {
    season.days.forEach(function (day) {
      if (day == dayDateString) {
        seasonName = season.name;
        return seasonName;
      }
    });
  });
  return seasonName;
};

function getDateBooking(dayDateString){
  var bookingName = "";
  bookings.forEach(function (booking) {
    var dayNum = 1;
    booking.days.forEach(function (day) {
      if (day == dayDateString) {
        var extra = "";
        if(dayNum == 1){
          extra = "_start";
        } else if(dayNum == booking.days.length){
          extra = "_end";
        }
        bookingName += booking.name + extra;
      }
      dayNum++;
    });
  });
  return bookingName;
};

// Get days array between 2 dates
function getDates(startDate, stopDate) {
  var dateArray = new Array();
  var currentDate = startDate;
  while (currentDate <= stopDate) {
    var dateString = currentDate.toDateString();
    dateArray.push(dateString);
    currentDate = currentDate.addDays(1);
  }
  return dateArray;
};
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console