Ignored By Dinosaurs 🦕

javascript

One of the first discoveries I ever made in web development was that CSS hex values that were all the same number would always give me some shade of grey. #444 was dark, almost black. #ccc was light, perfect for form borders. Not long after I discovered that Photoshop wouldn't accept these values and would make me type in all 6 characters – #444444, #cccccc.

Sometime after that I discovered how to tap into a shade somewhere between #eee and #fff, just a barely perceptible off-white with #f4f4f4. #f9f9f9 was lighter. #efefef was darker. The jobs at hand didn't really call for a deeper cognitive understanding. Just some off white colors.


It was only much more recently that somewhere in the corners of my mind I began to unravel the science, and just this morning walking down the stairs when it hit me in the way that I now have to write about.

parseInt()

There is a javascript function called parseInt(), and its job (in case it isn't clear) is to parse integers. There are two parameters – the first being the string/number you want to parse, but the second is often overlooked. The second is the “base number” in which you wish to parse, 10 (for decimal) is the default. I've read there is a bug whereby if you pass is a string beginning with the number 0, a base of 8 is assumed. This can lead to some weird bugs if that's not what you intend, so it's considered good style to always specify what you mean, usually 10.

If you want to play with this function, pass it some hexadecimal (base 16) and see what you get back. This will let you do something like this —

 parseInt('ef', 16); // -> 239
 
 parseInt('ff', 16); // -> 255
 
 parseInt('44', 16); // -> 68
 
 parseInt('45', 16); // -> 69

Hex and Rgb

Rgb color notation is pretty simple to get your head around. It means Red, Green, Blue. The same colors that your old tube TV used to put out in those tiny little dots if you got close enough. Mix those 3 colors together in the proper proportions anbd you can pull any shade of the rainbow out. Mix them together in equal portions and you get shades of grey, ie rgb(239, 239, 239) is a lovely shade of off-white.

16 x 16 = 256; Duh.

rgb(68, 68, 68) === #444444;

I haven't really been required to think much in base 16, and the average developer probably isn't called on to think in those terms very often, but once that clicked for me, I can somewhat compute the shades of colors that I want in my head based off of thinking about basic color mixing theory and then doing some base 16 calculations in my head. Staving off Alzheimers, hopefully.

#ui #javascript #css

I've recently finished up a project here at the job that gave me a blank check as far as writing the front end code was concerned. It was among the most blissful Drupal projects I've ever worked on, as my boss did all of the Drupal stuff, and I wrote all the code. It was heaven.

So, there were a lot of requests for some cool javascript features, and rather than reaching for the plugin drawer, I decided to write most of them from scratch. The main feature pages are mostly like this. The left hand “scrollspy” navigation was ripped off from Twitter's Bootstrap UI library, and (imho) warrants it's own write up, as it's some of the coolest code I've written yet.

Most of the moving features on the site, especially the left nav when activated and the contact tab flyout thingy were written initially using jQuery to animate positioning and display properties on the DOM elements themselves. “60 fps” is the battle cry of the UI engineer this month though, so I thought I'd try a few new tricks, namely swapping out those jQuery animations for CSS transitions. Turns out this is insanely easy, requires way less code than the previous alternative, and will outperform the JS implementation any day of the week.

var ABM = window.ABM || {};
ABM.contactFlyout = {};
 
ABM.contactFlyout = (function() {
 
var $ = window.jQuery;


var cloneContacts = function() {
// Clones the contacts div, which already exists on the page,
// attaches the copy to the page elsewhere where it can be 
// persistent, and slid out with a toggle.
};
 
var attachToggle = function() {
  $flyout = $('#flyout-wrapper');
  $('#toggle', $flyout).on('click autoFlyout', function() {
    var posY = ($flyout.hasClass('open')) ? -670 : 0;
    var winWidth = $(window).width();
    $flyout.animate({
    right: posY
    }, 350);
    $flyout.toggleClass('open');
    $(this).toggleClass('open');
  });
}

var flyoutFlash = function() {
// A thing Marketing wanted where the flyout would popout if you had never
// visited this page before, determined by a cookie.
}

// positions the contact flyout
var makeSticky = function() {
// SSIA
}
 
return {
  init: function() {
    if ($('.lt-ie9').length) return;
    cloneContacts();
    attachToggle();
    setInterval(makeSticky, 250);
    var cookieRE = /flyout/;
    if (!cookieRE.test(document.cookie)) {
      flyoutFlash();
      document.cookie = 'flyout=flown';
    }
  }
}
 
})();

The initial implementation.

So, obviously, the meat of the animation is in that attachToggle() method, which is totally poorly named and I'll refactor that right after I finish writing this. But, it just animates the positioning of that whole div, totally simple, right? So the only thing that's animating the is “right” property of that div, maybe we should try a CSS transform on that instead?

Turns out all that involves is removing that animation bit so it looks like this —

var attachToggle = function() {
  $flyout = $('#flyout-wrapper');
  $('#toggle', $flyout).on('click autoFlyout', function() {
    $flyout.toggleClass('open');
    $(this).toggleClass('open');
  });
}

And then the stylesheet for that div goes from this —

#flyout-wrapper
  position: fixed
  width: 700px
  right: -670px
  top: 20px
  z-index: 3

To this —

#flyout-wrapper
  position: fixed
  width: 700px
  right: -670px
  top: 20px
  z-index: 3
  transition: right .5s
  &.open
    right: 0

Yeah. Seriously. Instead of animating whole element, try just adding a class to it – the after state – and animate the in between with CSS. I did the same thing with the left nav dropdown bit. The whole page is a lot smoother now and I'm going to rework the main nav as soon as feasible.

Edit

If you're animating the position of something, say a #page-wrap element for an off-canvas menu, and it should present in a “normal” state when not activated, you still have to specify the default positioning (ie. left: 0), or the transition will not work. Just wasted too much time figuring out why my off canvas nav wasn't working like I wanted it to.

#ui #javascript #css

What's the difference between assigning an anonymous javascript function to a variable or just declaring a named function in the first place? Turns out “hoisting” of the function only works if you declare it as a named function in the first place. Assigning an anonymous function to a variable doesn't perform the hoist.

(function() {
	console.log(f()); // 'hello'
	function f(){
		return 'hello';
	};
})();

(function() {
	console.log(f()); // undefined
	var f = function() {
		return 'hello';
	};
})();

#javascript

It's simple really, but you have to know a few things about how a browser renders a page to get it. jQuery is a wonderful thing because it removes the need to know a LOT about a LOT to do with the DOM and still get amazingly cool things done – slideshows, form validation, etc. However, if you go and learn a bit more about how JavaScript works in a browser you can go beyond copying and pasting code snippets and really start getting creative. Or surgical. Or whatever you want.

So when code comes through the wire into your browser, your browser parses it from the top down. That's the fancy, mechanical way of saying it follows the instructions from the top of the page to the bottom. Any time it encounters a piece of JavaScript, be it either directly embedded in the page source or linked to another file (from your site or somewhere else), it will take a detour into that JavaScript and execute any instructions in that script before it moves on with parsing the rest of the page. If you put a humongous blob of JavaScript at the top of the page, your site will seem slower because everybody's browser is stopping to follow/execute the JS before it moves on down into the content of your page.

That means what? Well say you have a date field on a form in your page and you want to use the jQueryUI datepicker on it. All you then need to do is write $('#event-date').datepicker(); and you have a datepicker. But there's a catch. If you put that code at the top of your page (in the head), or in a file that's linked to in the head of your page (using script src), then the browser will execute that instruction as soon as it encounters it. The datepicker won't show up. You'll pull your hair out. The reason is that the browser goes and sets a datepicker() on an element that it doesn't know yet exists because it hasn't gotten down into the page to actually render that yet. It'd be like giving the steps for a recipe before giving the ingredient list. Only your computer is too stupid to look down the page and read the ingredients list. It'll just say "flour? There's no flour on my table. Moving on." and no datepicker.

There are two solutions.

One is to delay the execution of the datepicker() instruction until the page has been rendered/parsed/whatever you want to call it. You do this by putting all of your custom code inside a call to jQuery(document).ready() like this -

jQuery(document).ready(function($) {
 $('#event_date').datepicker();
}

// equivalent (and better) ->

jQuery(function($) {
 $('#event_date').datepicker();
}

That basically “hides” the instruction inside of a function that doesn't get called until the page is ready. When the page is “ready” (that happens once the browser has loaded the whole page and knows what's there) the function fires and your browser gets the instruction to add datepicker functionality to the field that it knows exists now. You can put as many things inside that function as you want, all your code if you like. And you should learn more about JS because it's a wonderfully cool language.

The other solution is to put all of your JS code at the bottom of the page. This was in vogue over the last couple years as a good way to increase the perceived performance of your website anyway, but I bet lots of people were still wrapping their jQuery code in document.ready() even though they didn't need to. I was anyway. Since your JS isn't encountered by the browser until after the rest of the page you don't need to wrap it in that call if you put it at the bottom.

#javascript

Hi, this post is wildly out of date. I tried to follow it to set up some test within the last year and none of this stuff actually worked. The concepts are likely still valid, but don't expect to be able to copy much.

jg – Oct 2015


I went down to Drupaldelphia (the name should be self-explanatory) a couple weeks ago mainly for a session called “Testing your site with CasperJS”. CasperJS is what's known as a “headless” Webkit testing framework. That means it's essentially a browser and can click around your site, fill out forms, test validation, etc. It's pretty much exactly what I've been looking for for one of my clients for a while now. I knew they were out there, but there's nothing like having something shown to you for an hour to really help you get your head around it.

So I came home and immediately went to work trying to figure out how to use it.

I have an assignment right now from a client to reorganize their website per instructions from their SEO vendor. It's about 10 or 12 little, tiny changes to about 50 pages. Most of the changes involve redoing their URLs, splitting content up, updating meta tags, page titles, and the like. The pattern for the updates is completely repetitive, but altogether we're talking about 500 or so changes to a Drupal site, which means it's going to be me sitting there typing all of this stuff into a web page edit form. I will screw up. I wont know it until somebody sends an email yelling at me. Enter Casper.

Casper is a Javascript tool. You can also use Coffeescript.

The tricky thing about Casper is that it basically has two scopes. One is the testing environment in which you write most of your code, and the other is the actual page environment, where the actual markup you might want to test is. Casper has a host of functions that all center around one called Casper.evaluate(). Code executed here in executed in the browser window context/scope.

I had a hell of a time trying to figure out how to test the meta tag for these pages. I knew I wanted to set up an array for the 25 different states =

A few utility functions to help out -

The base url = url = "http://example.com"

Create an instance of Casper. casper = require('casper').create()

I'll plop the code first and explain after.

The first line casper.start() obviously starts the test. each is a method which will look familiar if you work with any modern OO languages. It iterates over an array. The array in this case is states. self is the Casper instance, and state is the name of the current member of the array we're testing.

Most of this is pretty standard Casper 101. The more interesting stuff is about halfway down.

@evaluate drops us into the actual page context. There we can operate on what's in the DOM, as well as things that appear as a result of actions in the DOM. The contents of that function make a selection from one select box. The value of that select box determines what gets returned from a jQuery Ajax call. The return of that Ajax call populates another select box. Ajax 101, but we're testing, automatically, 25 pages here! You have to use legit javascript unless you can figure out how to get jQuery into this context. I haven't figured it out yet because actually learning core JS is something I need to do more of.

After that all happens we drop back into the DOM again to make sure that there are more than one option in the second select box.

Finally – Meta tags

Sorry. So I'm kinda new to JS and function scope gave me a time on this one. The main problem I was having was trying to get a piece of text that could only be found in the DOM scope back into Casper.each() scope so I could run some sort of assert() on it. Turns out it was really easy after several days of passive Googling.

So this drops back into the DOM and pulls out the contents of the Description meta tag and assigns it to the var descrip. Then all you have to do is a simple assertEquals()

Presto.

#testing #javascript