07. May 2015

JavaScript ES6 for-of vs for-in

Looping in javascript is the best thing ever and I do it all day everyday. I just stumpled upon some of the new ES6 iterators and one stuck out to me a lot. It's called the for-of loop and it much like to a for-in but with one major improvement.

The syntax for both are the same, as shown below:

//ES5
var myArray = ['cheddar','provolone','swiss','parmesan'];
for (var value of myArray) {
  console.log(value);
}

//ES6
let myArray = ['cheddar','provolone','swiss','parmesan'];
for (var value in myArray) {
  console.log(value);
}

Okay, easy enough so what is the difference right? The difference is in the output.

var myArray = ['cheddar','provolone','swiss','parmesan'];
for (var value of myArray) {
  console.log(value);
  // outputs 1,2,3,4
}

let myArray = ['cheddar','provolone','swiss','parmesan'];
for (var value in myArray) {
  console.log(value);
  // outputs 'cheddar','provolone','swiss','parmesan'
}

Do you get the difference? I've always been writing console.log(myArray[value]) to output what for-in outputs out of the box. It's not so life changing change, but it sure is welcomed by me and I appreciate the couple keystrokes this will save me.

Edit May 19, 2015: I did find one thing that might be bad/weird about the for-in loop. It's just a reference to the value and cannot be used to modify the original array.

24. April 2015

Initial Thoughts on PostCSS

Lets just use JavaScript for EVERYTHING!

Earlier today I found out about PostCSS, now my life is forever changed?

Very frequently do I complain about just how slow ruby Sass is (sometimes taking a whole 1s to compile a website's CSS... our definition of slow is just silly these days), but libsass is always behind and missing the cool kid features. This is where PostCSS comes in.

It's not meant to be a Javascript version of Sass like how libsass is a C++ version of ruby Sass, it's a completely different thing. At it's core it's just a CSS parser written in Javascript which people have written plugins for that give it Sass like features. This is the line that got me,

PostCSS can do the same work as preprocessors like Sass, Less, and Stylus. But PostCSS is modular, 4-40 times faster, and much more powerful.

4-40 Times faster... wow!

I immediately started reading the docs and playing with it. I even went so far as to making an example/tutorial and threw it up on github.

I used grunt to compile out my CSS, I tried straight from the command line and it didn't work after 2 tries so I switched to grunt as that's how I'd do it for real anyways.

Here's a snippet of my gruntfile.js

postcss: {
  options: {
    map: false,
    processors: [
      require('postcss-import')(),
      require('postcss-simple-vars')(),
      require('postcss-simple-extend')(),
      require('postcss-nested')(),
      require('postcss-media-minmax')(),
      require('postcss-merge-rules')(),
      require('postcss-discard-comments')({removeAll: true}),
      require('autoprefixer-core')({browsers: 'last 2 version'}).postcss,
      // require('csswring').postcss,
    ]
  },
  dist: {
    files: {
      'dist/styles.css': 'src/all.css'
    }
  }
}

You just add in all the plugins you want to run. Worth noting, order is important as that's the order they'll run in. One plugin said it needed to run before postcss-nested as running it after caused some issues. So far simple enough I think. I've left csswring commented out as it's a minifier and I think that isn't best practice when giving examples of what it does to the CSS when it's basically unreadable as minified.

After that you write CSS just like you would write Sass and it just sort of works. A couple things that were different were:

  • on @import you must include an _ if your filename starts with one.
  • cannot use file extension of .scss which caused some highlighting issues
  • @extend didn't work the way I thought it would (I rarely use extends in real life though)
  • comments must be in /* comment goes here */ format, // here is my comment won't get removed properly.
  • postcss-merge-rules sort of worked. I think it's an issue with nesting. It worked on my h1 tags, but not on one that had nesting on it.

I'm sure I've missed a ton of things, and if you know of cool things worth trying out or you see why things didn't work right for me let me know. I'm excited to keep playing with PostCSS!

23. April 2015

Sticky Bar With CSS Popup Animation

I was tasked with making a Google Adwords landing page for our company. Our designer Alex Benson decided he wanted a contact form to stick to the bottom of the page and popup when you click it.

 

See the Pen Sticky contact bar with popup animation by Josh Fabean (@fabean) on CodePen.

 

You can poke around the code yourself but I'll break down the main thing I did to accomplish this.

First there is the easy part, I did a couple CSS animations.

.fadeout {
  opacity: 0;
  transition: opacity 1s ease;
}
.fadein {
  opacity: 1;
  transition: opacity 1s ease;
}
.contact {
  position: fixed;
  bottom: 0;
  margin-bottom: 0;
  padding: 10px 0;
  width: 100%;
  height: auto;
  transition: all 400ms cubic-bezier(0, 0, 0.32, 1.50);
}

I was able to do that crazy transition simply by playing with the new Chrome Dev tools easy popup thingy.

alt text

After getting the CSS out of the way all that was left was to adjust the height of that bar based on the content we need to show and the CSS animation should do the rest.

Here's the js, cut up to only show the important part

// get all our elements we're going to be playing with.
var contact = document.getElementById('sticky-contact');
var formEl = document.getElementsByClassName('with-form')[0];
var getStarted = document.getElementById('get-started');

// when you click the first button do this thing!
getStarted.addEventListener('click', function(){
  var initHeight = contact.scrollHeight; // quick grab the current height
  contact.style.height = initHeight + 'px'; // set that height on the element
  formEl.classList.remove('hide'); // show the next step
  var withForm = formEl.scrollHeight; // find what new height would be
  contact.style.height = (withForm + 20) + 'px'; // set that height on the element
  document.getElementsByClassName('initial')[0].classList.add('hide'); // hide the first section of the bar
}, false);

If reading that code isn't enough here is the written out version.

When you click the 'Get Started' button we first grab the current height of the sticky bar. We take that height and set that as the height of the element instead of just height: auto;. Take the part that will show next and remove the class of hide so now it's visible. Grab the height of that element, now reset the height of the sticky bar to the height of the next step. Finally we take the first step that we just clicked and hide that.

Doing that allows for the CSS animation to take over and animate the height giving us the cool effect.

Overall nothing crazy complicated here just a bunch of simple things put together to make a good end result.

05. April 2015

The Selectinator 3000

On Friday Blake and I were asked how to take a list of people and in a fun way choose a random winner.

For fun, here's the finalized pen.

 

See the Pen The Selectinator 3000 by Josh Fabean (@fabean) on CodePen.

 

There you can see all the code but I'll break some of the cooler parts for you. Worth noting I wrote all the code in ES6 and used Traceur on CodePen to compile it to ES5 and work for people.


Below is a nice helper function I created the other day trying to make something useful but under 140bytes of data. It takes an element query array and turns it into an actual usable array. Not sure if you've ran into that issue before but you cannot simply say document.getElementsByClass('my-class') then loop through them, it needs to be made into an actual array for it to be usable.

// helper functions
function makeArray(r){return[].slice.call(r,0)};

To get the lightup effect I probably could have made a sass mixin based on class but doing it with javascript seemed cooler. So I grab everything with a class of light, use math to grab a random one, then each 300 milliseconds run the function lightUp. Then we're simply just toggling a class and the CSS animation is doing the rest.

let lights = makeArray(document.getElementsByClassName('light'));
/* figure out what block we're going to light up next */
(function nextLight() {
  let index = [Math.floor(Math.random() * lights.length)]; // math to grab a random element
  let light = lights[index];
  lightUp(light);
  setTimeout(nextLight,300);
})();

// take the el passed in an toggle a class
function lightUp(light) {
  light.classList.add('on');
  setTimeout(function(){
    light.classList.remove('on');
  },1000);
}

Finally is my favorite, the function where you pass it in a string and it types it out slowly to get the cool typing effect. All I'm doing for that is you pass in the string, and time in milliseconds between each letter and it appends it to the end of the element we're typing in.

// get passed in a string, delay, and current iterator
// based on that output text to the screen
// in future we should pass in element we are rendering to, that would make this more reusable
// also you can remove the first if, that's pretty specific to this situation
function typeText(text, time, i = 0) {
  if (terminal.style.bottom === '') {
    // if bottom isn't defined see if we need to start the scrolling effect
    screenScroll();
  }
  setTimeout(function(){
    // on first iteration of the string I'm making a new line
    // else we add to the line
    if (i === 0 && terminal.innerHTML != '' && text != ' you lose') {
      terminal.innerHTML += `<br /> ${text.charAt(i)}`;
    } else {
      terminal.innerHTML += text.charAt(i);
    }
    i++;
    if (text.length >= i) {
      typeText(text, time, i);
    }
  }, time);
}

 


This was my favorite pen I've made so far I really hope you enjoyed it.