0
\$\begingroup\$

I'm making a digital clock with ES5 ( no arrow stuff and so ). The location and temperature I'll do later. How can I improve/refactor the current code that I have with functional programming?

CodePen: https://codepen.io/Aurelian/pen/opaxqx?editors=1010

This is the HTML:

<div class="clock">
<div class="clock-ram">
<div class="clock-display">


  <div class="clock-location">United Kingdom, Manchester</div>

  <div class="clock-main">
    <div class="clock-time"></div>

    <div class="clock-widgets">
      <div class="clock-widget clock-date"></div>
      <div class="clock-widget clock-day"></div>
      <div class="clock-widget clock-temperature">NAN</div>
    </div> 
  </div><!-- /clock-main -->

  <ul class="clock-weekdays">

  </ul>


</div><!-- /display -->
</div><!-- /ram -->
</div> <!-- /clock -->

This is the JS:

// Get te location
// Make the : blink

//var location = document.querySelector('.clock-location');

function abbrev(a,b) {
  return a.substr(0,b);
}

 function checkTime(i) {
      if (i < 10) {
        i = "0" + i
      };
      return i;
  }


function displayTime() {

  var clockTime = document.querySelector('.clock-time');
  var clockDate = document.querySelector('.clock-date');
  var clockDay = document.querySelector('.clock-day');
  var clockWeekdays = document.querySelector('.clock-weekdays');
  while(clockWeekdays.firstChild) clockWeekdays.removeChild(clockWeekdays.firstChild);

  var date = new Date();

  var weekday = new Array(7);
  weekday[0] = "Sunday";
  weekday[1] = "Monday";
  weekday[2] = "Tuesday";
  weekday[3] = "Wednesday";
  weekday[4] = "Thursday";
  weekday[5] = "Friday";
  weekday[6] = "Saturday";

  var monthNames = ["January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December"
];


  var singleDay = [];

  for (var i = 0; i < weekday.length; i++) {
    var day = weekday[i];
    var li = document.createElement('li');
    li.textContent = abbrev(day,3);
    if (i === date.getDay()) {
        li.classList.add('active');
    }
    clockWeekdays.appendChild(li);
  }

  // Mechanics
  var todayDay = weekday[date.getDay()];
  var h = date.getHours();
  var m = checkTime(date.getMinutes());
  var s = checkTime(date.getSeconds());

  var year = date.getFullYear();
  var month = date.getMonth();

  // Display
  clockDay.textContent = abbrev(todayDay,3);
  clockTime.textContent = h + ":" + m + ":" + s;
  clockDate.textContent = monthNames[month] + " / " +  year;

}

window.setInterval(displayTime, 1000);


//displayTime();

// Get the time

//Loop Throw weekdays - show 3 letters

CodePen: https://codepen.io/Aurelian/pen/opaxqx?editors=1010

\$\endgroup\$
2
  • \$\begingroup\$ Minor point. Your clock shows a location in the UK but the time day and date on the display are local. You need to show the time relative to UTC \$\endgroup\$
    – Blindman67
    Commented Jan 17, 2018 at 17:18
  • \$\begingroup\$ Yeah, though I was wondering how can I improve the whole code apart from location and temperature for now. The location and temperature are static. I'm learning JS and don't want to be overwhelmed by the google API and stuff for now :) \$\endgroup\$ Commented Jan 17, 2018 at 19:12

1 Answer 1

1
\$\begingroup\$

You have almost everything in a single function, displayTime.

I'd start by refactoring the date-to-string manipulations into separate functions and leaving only DOM manipulation code in displayTime:

// qs :: String -> Element
// formatTime :: Date -> String
// formatYearMonth :: Date -> String
function displayTime() {
  let date = new Date();
  // handle weekdays here
  qs('.clock-time').textContent = formatTime(date);
  qs('.clock-date').textContent = formatYearMonth(date);
}

formatTime would be more readable IMO if we named your checkTime function zeroPad and used mm/ss for double-digit strings:

function formatTime(date) {
  let zeroPad = (i) => ((i < 10) ? "0" : "") + i; // I know you said no arrow functions, but I can't resist

  let h = date.getHours();
  let mm = zeroPad(date.getMinutes());
  let ss = zeroPad(date.getSeconds());
  return `${h}:${mm}:${ss}`;
}

The weekday indicators can be created once and only get updated as necessary. This makes it obvious what part is dynamic:

let weekdayLIs = Array.from(qs('.clock-weekdays').children);
// I'm no fond of using the index here, can be changed to inspect the <li>
function isCurrentWeekday(idx) { return idx === date.getDay(); }

weekdayLIs.forEach((li, idx) => {
  li.classList.toggle('active', isCurrentWeekday(idx));
});

I'm not sure what's the point of displaying the current weekday in two places, but if you insist:

qs('.clock-day').textContent = weekdayLIs.find((li,idx) => isCurrentWeekday(idx)).textContent;

As for creating the <li>s corresponding to the weekdays, you can simply list them in HTML; this has the benefit of having all the structure defined in one place:

  <ul class="clock-weekdays">
    <li>Sun</li><li>Mon</li><li>Tue</li><li>Wed</li><li>Thu</li><li>Fri</li><li>Sat</li>
  </ul>

https://codepen.io/anon/pen/zpyRjm?editors=1010

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Code Review! That's a really good first answer; I hope you stay around and contribute some more. \$\endgroup\$ Commented Jan 19, 2018 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.