Friday, November 10, 2017

Coffee, and more Coffee

So last week in the Front End Web Dev class I am TA'in, we launched The Big Kahuna Concept: we started the JS portion of the course.

While Tom stood at the front leading everyone through basic concepts and syntax, I put together a simple web page that would have a JS-driven clock and time-appropriate, coffee-themed greeting.

You can see the code here: https://github.com/mgienow/Coffee_Clock


I am humbled by how long it took me to get this going.

The initial page came together in less than 20 minutes.  Which is maybe 10 more than it ought to be, since it;s basically three divs in the markup, plus basic CSS styling and a background image.

But my grasp of tying JS in to HTML has always been shaky, mainly because I've barely ever done it.

Today was the day.

The first time, I had to work from an example in my Duckett text.

That gave the structure for the "It's Coffee O'Clock" greeting:
const java = document.getElementById('java');
let msg= `It's Coffee O'Clock!`
java.textContent = msg;

From there, I could start to figure out how to get the other parts I needed. Which also required either brushing up on, or learning from new, some JS concepts like the Date() object and Math.random(). 

The clock was pretty easy...
const hourNow = today.getHours();
const minNow = today.getMinutes();
const clock = document.getElementById('clock');
clock.innerHTML = `${hourNow}:${minutes}`;

...until I realized that the built-in getMinutes() function returns literally only the minute number. So at 3:10 you're cool, it returns '10' -- but if it's 3:01, you only get '1'.  So my clock would say "15:1" instead of "15:01".  So I had to puzzle out a function to put that zero in whenever the minute value was <10:
let minutes = minsAddZero(minNow);  
function minsAddZero(i){
  if(i<10){i='0' + i};
  return i;
}
which got things looking right.

Finally, the biggest challenge. Or smallest, since in a way I was totally ready for this based on all the code challenges I've done. Conceptually, I had it right away:
function sendSalutations() {  let coffeeBreak  if (hourNow>16){    coffeeBreak = `Good evening!<br>                    Like some decaf?`  } else if (hourNow>11){  coffeeBreak = `Good afternoon.<br>                How about an energizing<br>                espresso?`  }else if (hourNow>5){    coffeeBreak = `Good morning!<br>                    Ahhh, nothing like that first cup...`  } else {    coffeeBreak = `How do you take YOURS?`  }  const salutations = document.getElementById('salutations')  salutations.innerHTML = coffeeBreak}sendSalutations();

Take a look at the hour, and use for/else to pass in the proper humorous greeting for that time of day.

Anyway, it's all there, abundantly commented on GH.  The big thing for me was that I did it two more times, refining it each time. The first re-do, I needed to peek a couple times at my original code. The second one I did blindfolded. Figuratively speaking.

IMportant lesson learned: one of the things I was puzzled about was how the new ES6 template literal for strings is supposed to take away the need to use newline escaped characters (\n) to indicate line breaks. But it wasn't showing up that way in my HTML.  They were right in console, but not on the page. It took what is an embarrassingly long time for me to realize that HTML doesn't speak ES6...so I had to switch from .textContent (which only passes the straight string) to .innerHTML (which allows HTML tags for styling).

 

Monday, November 6, 2017

Workin' My Way Back to RegEx...

Ok, so in the past week, my coding activities have included the following:

  1. Working on "Intro to JS" materials to help co-teach the Front End Web Development course my JavaScript mentor Tom teaches at Betamore Academy;
  2. As a direct outcome of item 1, realizing that even 15 months in to learning JS, there are serious potholes in the roadway of my self-taught JS journey;
  3. Working through pothole-filling material in my favorite JS book, "JavaScript and jQuery: Interactive Front-End Development," by Jon Duckett;
  4. Getting my ass kicked -- repeatedly -- on a level 7 Codewars Kata (see item 2 about holes, above).

Today, let's talk about the kata.  It is the "compare strings by sum of chars" challenge, wherein you are given two strings and asked to determine whether or not they are equal by dint of their ASCII values. If the arg strings are null, empty or contain anything other than a letter (i.e., numbers or punctuation or, say, the turd emoji) the string's value is zero.

I decided to approach the challenge in pure JS, no regex. I then wrote out the code logic in plain words. I will skip boring you with this because it is in the final code, in the form of comments.

Where I got stuck: 
  • First, on null string test cases. Because, for what I now realize was an embarrassingly long time, my code proceeded upon the assumption that null had length of zero -- when of course you can't determine length of something that does not exist. It finally occurred to me to look at MDN  to see why my code kept returning an error -- that told me, in plain English, "TypeError: Cannot read property 'length' of null". I was extremely sure that I was right and JS simply wrong. Sigh. This is actually weird for me, because I typically assume the opposite -- last week I had some freaky browser thing going on where console.log(whatever) was not displaying, and I was sure it was me. As in, I had somehow messed up in applying one of the most fundamental JS tools in the box.  Turns out there is a toggle in console that I had accidentally flipped, turning off display of anything NOT an error. Gosh, thanks, Chrome!
  • Next, I was also SUPER sure of another thing that also turned to be ahem wrong wrong wrong. My test case for whether string elements were alpha only characters involved converting .toUpperCase() -- the instructions specified treating all letters as capitals even if passed as lower case -- and then checking if the ASCII value was greater than or equal to 65 (the value of capital "A") and less than or equal to 90 (the value of cap "Z").  Unfortunately, I was confident that you could do this:
                  if(65 <= str1Val <=90){do some stuff}


         When it turns out, no you can't.  it's got to be:

                         if(str1Val>=65 && str1Val<=90){do that stuff}

    Dude, I was just trying to make my code a little sleeker. Though I guess i               could drop two equal signs and achieve the same thing with 

                         if(str1Val>64 && str1Val<91){do that stuff}

My thought with using 65 and 90 with the greater/lesser equals operators was to make my code more readable -- i.e., make it plain that these numbers represented A and Z. Like, more readable  for all the ASCII savants who will ever stumble across my Codewars solution and instantly convert this in their heads and be impressed.

 function compare(s1, s2) {  
 //establish counter variables to hold the ASCII code values of the strings  
 let s1Sum=0;  
 let s2Sum=0;  
 //if s1 is null OR empty (has a length of zero) return s1Sum=0:  
 if(s1 == null || s1.length==0) {  
  s1Sum=0;  
 } else {  
 //else, convert s1 to upper case and loop over each character in the string,   
 //assigning the ASCII value (obtained with `charCodeAt()` for each position)  
 //to a newly inititalized variablie, s1Val:  
 s1=s1.toUpperCase();  
 for(var i=0; i<s1.length; i++){  
  let s1Val = s1.charCodeAt(i);  
  //IF the value is between 65 and 90 (the capital alphabet ASCII values),  
  //add s1Val to s1Sum:  
   if(s1Val>=65 && s1Val <= 90){  
    s1Sum += s1Val;  
   }   
  //if it's not between 65 and 90, then it is a number or other symbol, so return   
  //s1Sum = 0:  
   else {  
    s1Sum=0;  
    }  
   }  
  }  
  //Now repeat same logic for the second passed arg, s2:  
  if(s2==null || s2.length==0) {  
  s2Sum = 0;  
  }else {  
   s2=s2.toUpperCase();  
   for(var i=0; i<s2.length; i++) {  
   var s2Val = s2.charCodeAt(i);  
   if(s2Val>=65 && s2Val <= 90){  
   s2Sum += s2Val;  
   } else {  
    s2Sum=0;  
    }  
   }  
  }  
  //Finally, compare the two counter variables, s1Sum and s2Sum, returning   
  //true if equal and false if not equal  
 if(s1Sum === s2Sum) {  
   return true;  
  } else {  
   return false;  
  }  
 }

So!  That got things working. Notice, however, that a few lets aside, I am still thinking in ES5. Tomorrow's challenge: refactor into more modern JS, if that is possible. And then a side quest: repeat the challenge, this time using regex.