Javascript: Measure those “em”s for your layout

For many of us designing fluid layouts, which are generally based in “em”s (pronounced like the letter M) you end up not really knowing how many pixels an “em” is while you are deep in the DOM tree. This is especially confusing if you increase/decrease text size with your browser.

For this reason, I have created a simple Javascript function that you can use to poll any element on your test page and figure out what size an “em” is.

The Javascript code:

function getEmSize(el) {
  // If you pass in an element ID then get a reference to the element
  if (typeof el == "string") el = document.getElementById(el);

  if (el != null) {
    var tempDiv = document.createElement("DIV");
    tempDiv.style.height = 1 + "em";
    // Make a readable bar with the em measurement
    tempDiv.style.background = "#FF9";
    tempDiv.style.color = "#000";
    tempDiv.style.paddingBottom = 4 + "px"; // This makes the DIV text readable
    // Just in case the content of "el" takes up it's container's height :)
    tempDiv.style.marginTop = -1 + "em";

    el.appendChild(tempDiv);
    // Remember to take off the 4px we added earlier
    var emSize = (tempDiv.offsetHeight - 4) + "px";
    tempDiv.innerHTML = emSize;
  }
}

Explanation and Usage

This function will create a yellow bar below content within the element you pass in with the pixel value equivalent to 1 “em”. You can change it to print the value to the console by replacing lines 8-18 with:

    el.appendChild(tempDiv);
    console.log(tempDiv.offsetHeight + "px");
    el.removeChild(tempDiv);

You can easily use this function by calling:

    getEmSize("elementid");
    // OR
    getEmSize(elementReference);

from your navigation bar or Firebug console or of course within a loop traversing your entire DOM tree (watch out for those text nodes though!).

Caveats

You could improve this by implementing some CSS positioning to always be a the lower-right etc. of these elements. You could also use a loop as I said earlier and print out a nice DOM tree with pixel values. You could also have the function update a global variable while printing to console to prevent using document.createElement() so often (it’s costly).

I know that there are some improvements to be made here so I wanna see some in the comments! What other ways do you keep track of your “em”s in a fluid layout?

If you liked this post, please help me share it
  • Reddit
  • StumbleUpon
  • description
  • del.icio.us
  • Digg
  • co.mments
  • Google
  • Slashdot
  • Technorati
  • TwitThis
  • E-mail this story to a friend!
  • Furl

Staples of the Bookshelf: ppk on JavaScript

Peter-Paul Koch explains how to create beautiful JavaScript and shows you how to combine it with proper HTML and CSS for the best web experience in ppk on JavaScript. Here is my review.

The structure of this book

ppk begins with a brief history of JavaScript and explains the “fat and thin” JavaScript cycle. I would agree with him on that we are in a fattening state right now, but I think the tides will turn soon (my guess is before 2010).

Then ppk gives a basic overview of accessibility (which he adds to later) before introducing us to the 8 real world scripts used as examples in this book:

ppk on JavaScript

  • Textarea Maxlength
  • Usable Forms
  • Form Validation
  • Dropdown Menu
  • Edit Style Sheets
  • Sandwich Picker
  • XMLHTTP Speed Meter
  • Site Survey

We then see chapters on browsers, how to prepare your markup for good JavaScript and a series of chapters that use his examples heavily giving light on several very diverse topics of JavaScript.

Bits of ingenuity

Here I am going to sum of a few particularly useful snippets of this book.

A section on object detection vs. browser detection explains that object detection is the better way to go in general. ppk makes a good case for object detection: browsers will change, and by using object detection we can determine if an action is executed by directly tying the action to its dependencies. A lot of good JavaScript coders believe in this but it cannot be stressed enough.

Koch also knows that we need other fundamentals of how to setup our HTML and CSS for good JavaScript. He makes a very appropriate example for this is his Sandwich Picker script in Chapter 4: Preparation He summed up his advice well by saying:

Obviousness is the key to creating HTML structures that will help your script instead of hinder it

Since we want to separate content from behavior, we need to develop obvious element hooks to neatly tie our JavaScript to our HTML and CSS. We learn that the id attribute is the best known and most popular element hook. Another great idea that ppk presents here, though, is using custom attributes, such as a rel attribute.

One last bit I’d like to mention here is that ppk’s createXMLHTTPObject() function in Chapter 10: Data Retrieval is really quite elegant and I think you might check it out here. Your homework is to make this function rewrite itself upon successful completion so that it doesn’t have to try different methods of creation after the first call. ;)

Conclusion

There are several reasons I highly recommend this book, and Koch’s site: quirksmode.org.

First of all ppk gives us a really good foundation in Chapter 5: Core, one that I would recommend even experienced JavaScript-ers read. He also covers the BOM, JavaScript Events, and DOM in great detail also keeping accessibility fresh in your head as you pick up JavaScript’s quirks and issues with different browsers. That said, I would say that the amount of history covered by the book may have been excessive but may be more helpful to other readers.

ppk on JavaScript is a good reference book that I keep as one of only 10 books within arms reach at work (I obviously have others but I don’t feel the need to keep many so close by). I think that more than a few of you would also benefit from keeping this book handy as well as checking out quirksmode.org for other bits.

If you liked this post, please help me share it
  • Reddit
  • StumbleUpon
  • description
  • del.icio.us
  • Digg
  • co.mments
  • Google
  • Slashdot
  • Technorati
  • TwitThis
  • E-mail this story to a friend!
  • Furl

How to highlight search results with JavaScript and CSS

Google highlight search textYou see it in Google search results and a lot of other sites that have good search functionality. When you perform a search, your words or phrases are highlighted in the search results making it easy for you to find the most relevant content.

Today I’m going to show you a simple way to add this to your website or blog so your users can find what they need in style. I think that this kind of thing should be implemented more often for how easy it is to implement.

Here we go!

Search Results JavaScript code:

function highlightOnLoad() {
  // Get search string
  if (/s\=/.test(window.location.search)) {
    var searchString = getSearchString();
    // Starting node, parent to all nodes you want to search
    var textContainerNode = document.getElementById("content");

    // Informational message for search
    var searchInfo = 'Search Results for: ';

    // Split search terms on '|' and iterate over resulting array
    var searchTerms = searchString.split('|');
    for (var i in searchTerms) 	{
      // The regex is the secret, it prevents text within tag declarations to be affected
      var regex = new RegExp(">([^<]*)?("+searchTerms[i]+")([^>]*)?<","ig");
      highlightTextNodes(textContainerNode, regex, i);
      // Add to info-string
      searchInfo += ' <span class="highlighted term'+i+'">'+searchTerms[i]+'</span> ';
    }

    // Create div describing the search
    var searchTermDiv = document.createElement("H2");
    searchTermDiv.className = 'searchterms';
    searchTermDiv.innerHTML = searchInfo;

    // Insert as very first child in searched node
    textContainerNode.insertBefore(searchTermDiv, textContainerNode.childNodes[0]);
  }
}

// Pull the search string out of the URL
function getSearchString() {
  // Return sanitized search string if it exists
  var rawSearchString = window.location.search.replace(/[a-zA-Z0-9\?\&\=\%\#]+s\=(\w+)(\&.*)?/,"$1");
  // Replace '+' with '|' for regex
  // Also replace '%20' if your cms/blog uses this instead (credit to erlando for adding this)
  return rawSearchString.replace(/\%20|\+/g,"\|");
}

function highlightTextNodes(element, regex, termid) {
  var tempinnerHTML = element.innerHTML;
  // Do regex replace
  // Inject span with class of 'highlighted termX' for google style highlighting
  element.innerHTML = tempinnerHTML.replace(regex,'>$1<span class="highlighted term'+termid+'">$2</span>$3<');
}

// Call this onload, I recommend using the function defined at: http://untruths.org/technology/javascript-windowonload/
addOnLoad(highlightOnLoad());

Now, the highlighting CSS:

span.highlighted {
  background-color: #161616;
  font-weight: bold;
}
span.term0 {
  background-color: #161633;
}
span.term1 {
  background-color: #331616;
}
span.term2 {
  background-color: #163316;
}

Code explanation

First, the highlightOnLoad function checks window.location.search to see if we need to be running any of this stuff, then calls getSearchString to get a sanitized search string so that nothing funky can happen if, say, the user searches for ‘<script>’. You should really be sanitizing all search inputs at least on the back-end anyway.

Then, the highlightTextNodes function uses a regex replace on our textContainerNode’s innerHTML. The regex verifies that the text is between a > and a < (and not the other way around). Actually nice and simple!

Caveats

This may end up being a bit slow if you are doing this on a LOT of text, but for my blog text, it seems quite snappy to me. Also, the CSS does not bold text inside links, but the background color is there to make it obvious.

What do you think? Try it out on the search box on the upper-right. I’m hoping for some optimizations in the comments.

Updates

Reader erlando has recommended some changes that allow for changing the styles of each search term individually and add an informational message showing what the user searched for here are the code updates:

This is added to the end of the highlightOnLoad() function:

  // Informational message for search
  var searchInfo = 'Search Results for: ';

  // Split search terms on '|' and iterate over resulting array
  var searchTerms = searchString.split('|');
  for (var i in searchTerms) 	{
    // The regex is the secret, it prevents text within tag declarations to be affected
    var regex = new RegExp(">([^<]*)?("+searchTerms[i]+")([^>]*)?<","ig");
    highlightTextNodes(textContainerNode, regex, i);
    // Add to info-string
    searchInfo += ' <span class="highlighted term'+i+'">'+searchTerms[i]+'</span> ';
  }

  // Create div describing the search
  var searchTermDiv = document.createElement("H2");
  searchTermDiv.className = 'searchterms';
  searchTermDiv.innerHTML = searchInfo;

  // Insert as very first child in searched node
  textContainerNode.insertBefore(searchTermDiv, textContainerNode.childNodes[0]);

The new highlightTextNodesFunction now takes and additional parameter and uses it to make each search term unique. Here it is:

  function highlightTextNodes(element, regex, termid) {
    var tempinnerHTML = element.innerHTML;
    // Do regex replace
    // Inject span with class of 'highlighted termX' for google style highlighting
    element.innerHTML = tempinnerHTML.replace(regex,'>$1<span class="highlighted term'+termid+'">$2</span>$3<');
  }

Finally we can add as many classes as we want for search terms. Here I am changing the colors slightly.

span.term0 {
  background-color: #161633;
}
span.term1 {
  background-color: #331616;
}
span.term2 {
  background-color: #163316;
}

Now you should try searching my site for: “firecookie extension for firefox” and check out the new improved search! Thanks erlando!!

If you liked this post, please help me share it
  • Reddit
  • StumbleUpon
  • description
  • del.icio.us
  • Digg
  • co.mments
  • Google
  • Slashdot
  • Technorati
  • TwitThis
  • E-mail this story to a friend!
  • Furl