Outlook 2011 and OS X Notification Center Integration

Microsoft Outlook 2011 was released before Mac OS X introduced the Notification Center, but you can still implement consistent OS notifications with the help of some AppleScript.

Simply save the following code as an AppleScript (.scpt) file and then create a rule in Outlook to run it when new mail arrives. Once you have confirmed it’s working, you can disable the built-in Outlook notifications.

-- Get a list of all "current messages" in Outlook.
tell application "Microsoft Outlook"
  set currentMessages to the current messages
end tell

-- Loop through the messages.
repeat with eachMessage in currentMessages
  tell application "Microsoft Outlook"
    -- Only notify about unread messages.
    if is read of eachMessage is false then
      set displayNotification to true
      set messageSubject to get the subject of eachMessage
      set messageSender to sender of eachMessage
      set messageContent to plain text content of eachMessage
      -- Get an appropriate representation of the sender; preferably name, but fall back on email.
      try
        if name of messageSender is "" then
          set messageSender to address of messageSender
        else
          set messageSender to name of messageSender
        end if
      on error errorMessage number errorNumber
        try
          set messageSender to address of messageSender
        on error errorMessage number errorNumber
          -- Couldn’t get name or email; we’ll just say the sender is unknown.
          set messageSender to "Unknown sender"
        end try
      end try
    else
      -- The message was already read, so we won’t bother notifying about it.
      set displayNotification to false
    end if
  end tell
  
  -- Display notification
  if displayNotification is true then
    display notification messageContent with title messageSender subtitle messageSubject
    -- Allow time for the notification to trigger.
    delay 1
  end if
end repeat

Note: This script is based on a Growl notification script for Outlook by Matt Gemmell, which was based on an Entourage script he found on the internet.

Auto-generated Line Numbers

I’ve been using the Google Code Prettify plugin for my code samples, which is nice for syntax highlighting, but still lacks something I think every code sample should have: line numbers.

I didn’t want to have to add them manually to every code sample I put up, so I came up with a quick solution to auto-generate line numbers with JavaScript. Because I wanted a quick solution, this code uses jQuery for all the heavy lifting.

Here it is, complete with line numbers:

$(document).ready(
  function() {
    $("pre.prettyprint").each(
      function() {
        var code = $(this).html();
        code = escape(code);
        // %0A is a line feed, %0D is a carriage return
        if (code.indexOf("%0D%0A") > -1) {
          linecount = code.match(/%0D%0A/g).length;
        }
        else if (code.indexOf("%0A") > -1) {
          linecount = code.match(/%0A/g).length;
        }
        else if (code.indexOf("%0D") > -1) {
          linecount = code.match(/%0D/g).length;
        }
        code = unescape(code);
        var linenumbers = 1;
        for (i = 1; i < linecount; i++) {
          linenumbers += "<br />" + (i + 1);
        }
        $(this).before("<pre class=\"linenumbers\">" + linenumbers + "</pre>")
      }
    );
  }
);

And then this little bit of CSS so it matches the prettify.css that comes with the Google Code Prettify plugin:

pre.linenumbers {
  width: auto;
  background-color: #EEE;
  border-width: 1px 0 1px 1px;
  border-style: solid;
  border-color: #888;
  float: left;
  margin: 0;
  padding: 2px 4px;
  color: #888;
  text-align: right;
}

I purposefully keep the numbers in a separate element from the code, so they don’t interfere when you try to copy the code samples to your clipboard.

And there you have it. Now I can easily reference specific line numbers in my code.

Perfect Pagination with PHP

Okay, so this may not be “perfect” but it does exactly what I want it to do, so I thought I would share.

The following code takes a set of items and breaks them into pages. 10 pages are shown in the list at any given time and the current page is displayed in the middle of the list. Sample HTML code is shown below so you can see what it does.

<?php
  // sample MySQL database connection and query to get a dataset
  $dbConnection = mysql_connect("localhost", "usename", "password");
  mysql_select_db("foo", $dbConnection);
  $dbQuery = "SELECT t.table_id, t.data FROM table AS t ORDER BY t.table_id ASC";

  // set how many items to show per page
  $limit = 50;
  
  // count the total number of items that the query returns
  $dbCount = mysql_query($dbQuery, $dbConnection);
  $totalRows  = mysql_num_rows($dbCount);     

  // divide the total rows by the limit to get the page count
  $numOfPages = ceil($totalRows / $limit);
  
  // get the current page number
  $currentPage = $_GET['page'];
  
  // if $currentPage is undefined, not a number, or out of range, then we're on page one
  if (empty($currentPage) || !is_numeric($currentPage) || ($currentPage > $numOfPages)) {
    $page = 1;
  }
  else {
    $page = $currentPage;
  }
  
  // figure out where to start on each page
  $limitValue = ($page * $limit) - $limit;

  // apply limits to the query
  $dbQuery = $dbQuery . " LIMIT $limit_value, $limit";
  
  $dbResult = mysql_query($dbQuery, $dbConnection);

  // display pagination only if needed
  if ($totalRows > $limit) {
    print("<div class=\"pagination\">\n");

    if ($_SERVER["QUERY_STRING"]) {
      $existing_query = preg_replace("/[&]*page=[^&]+/i", "" , $_SERVER["QUERY_STRING"]);
      if ($existing_query != "") $existing_query = preg_replace("/^&/i", "" , $existing_query) . "&";
    }
    else {
      $existingQuery = "";
    }

    // display previous link if there is a previous page to go to
    if ($page != 1) {  
      $pagePrev = "   <div class=\"gotopage\"><a href=\"" . $_SERVER["PHP_SELF"] . "?" . $existingQuery . "page=" . ($page - 1) . "\">Previous</a></div>\n";
    }

    // display next link if there is a next page to go to
    if (($totalRows - ($limit * $page)) > 0) { 
      $pageNext = "   <div class=\"gotopage\"><a href=\"" . $_SERVER["PHP_SELF"] . "?" . $existingQuery . "page=" . ($page + 1) . "\">Next</a></div>\n";
    }

    // divide the total rows by the limit to get the page count
    $numOfPages = ceil($totalRows / $limit);

    if ($numOfPages > 10) {
      // make the current page in the "center" of the list when possible
      if ($page > 5) {
        if (($page - 5) > ($numOfPages - 9)) {
          $startNum = ($page - 5) - (($page - 5) - ($numOfPages - 9));
        }
        else {
          $startNum = $page - 5;
        }
        if ($startNum > 1) {
          $pageFirst = "    <div class=\"gotopage\"><a href=\"" . $_SERVER["PHP_SELF"] . "?" . $existingQuery . "page=" . 1 . "\">First</a></div>\n";
        }
      }
      else {
        $startNum = 1;
      }
      if ($page < ($numOfPages - 4)) {
        if (($page + 4) < 10)
          $endNum = ($page + 4) + (10 - ($page + 4));
        else {
          $endNum = $page + 4;
        }
        $pageLast = "   <div class=\"gotopage\"><a href=\"" . $_SERVER["PHP_SELF"] . "?" . $existingQuery . "page=" . $numOfPages . "\">Last</a></div>\n";
      }
      else {
        $endNum = $numOfPages;
      }
    }
    else {
      $startNum = 1;
      $endNum = $numOfPages;
    }

    // first page link
    print(" <div class=\"pagefirst\">\n");
    if ($pageFirst) print($pageFirst);
    print(" </div>\n");

    // previous page link
    print(" <div class=\"pageprev\">\n");
    if ($pagePrev) print($pagePrev);
    print(" </div>\n");

    // individual page links
    print(" <div class=\"pages\">\n");
    for ($i = $startNum; $i <= $endNum; $i++) { 
      if ($i == $page) { 
        print("   <div class=\"currentpage\">" . $i . "</div>\n");
      }
      else { 
        print("   <div class=\"gotopage\"><a href=\"" . $_SERVER["PHP_SELF"] . "?" . $existingQuery . "page=" . $i . "\">" . $i . "</a></div>\n");
      } 
    } 
    print(" </div>\n");

    // next page link
    print(" <div class=\"pagenext\">\n");
    if ($pageNext) print($pageNext);
    print(" </div>\n");

    // last page link
    print(" <div class=\"pagelast\">\n");
    if ($pageLast) print($pageLast);
    print(" </div>\n");

    print("</div> <!-- .pagination -->\n");
  }
?>

So what does all that do? Well, let’s assume we were on page 10 of our result set. This is the HTML that would be generated:

<div class="pagination">
  <div class="pagefirst">
    <div class="gotopage"><a href="index.php?page=1">First</a></div>
  </div>
  <div class="pageprev">
    <div class="gotopage"><a href="index.php?page=9">Previous</a></div>
  </div>
  <div class="pages">
    <div class="gotopage"><a href="index.php?page=5">5</a></div>
    <div class="gotopage"><a href="index.php?page=6">6</a></div>
    <div class="gotopage"><a href="index.php?page=7">7</a></div>
    <div class="gotopage"><a href="index.php?page=8">8</a></div>
    <div class="gotopage"><a href="index.php?page=9">9</a></div>
    <div class="currentpage">10</div>
    <div class="gotopage"><a href="index.php?page=11">11</a></div>
    <div class="gotopage"><a href="index.php?page=12">12</a></div>
    <div class="gotopage"><a href="index.php?page=13">13</a></div>
    <div class="gotopage"><a href="index.php?page=14">14</a></div>
  </div>
  <div class="pagenext">
    <div class="gotopage"><a href="index.php?page=11">Next</a></div>
  </div>
  <div class="pagelast">
    <div class="gotopage"><a href="index.php?page=38">Last</a></div>
  </div>
</div> <!-- .pagination -->

All of the additional DIV tags are so I have complete flexibility to style the page list any way I like.

And yes, this will support pages with other URL passed parameters, such as search results.

Regular Expression Back References

Looking to trim down your six digit hex codes down to three digits?   You can only trim six digit hex codes if first two, middle two, and last two digits are the same (e.g. #003300, #CCCC55, #FF88AA, #999999, etc.).   If all six digits are the same, you can find them all by using regular expressions and searching for #([a-fA-F0-9])\1{5}.  When they aren’t all the same, you can find the three groups of two by searching for #([a-fA-F0-9])\1([a-fA-F0-9])\2([a-fA-F0-9])\3.   The latter method would find all applicable hex codes, regardless if all six digits match or not.

Let’s break those down so you know how to use them in other applications.

# matches #.   Simple enough.

[a-fA-F0-9] matches any single occurrence of the following characters: a, b, c, d, e, f, A, B, C, D, E, F, 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9.

( ) saves the match as a matched item.

\1 is a back reference to a matched item.  The number represents the numerical count of matched items. \2 would equal the second matched item, \3 would equal the third matched item, etc.

{5} repeats the previous match 5 times. So in our case, this is the same as writing \1\1\1\1\1.

Example:
Let’s assume you have the following hex code: #3366FF

The first occurrence of [a-fA-F0-9] would match 3. ([a-fA-F0-9]) would return 3 as a matched item.
\1 would also match 3 since that is the first matched item. So ([a-fA-F0-9])\1 would match 33.  Then we just repeat the process for the second and third set of two digits.

Bonus Tip:
If you want to use search and replace so you don’t have to manually edit all occurances of your 6 digit hex codes, you can use that same matched item in your replacement string.   You may need to check the documentation of your favorite editor to find out how matched items are referenced in the replacement string.  In EditPlus for Windows, you would use \1\2\3, but in TextMate for Mac, you would use $1$2$3.

This is bit of a confusing topic, so please leave any questions in the comments and I’ll be happy to answer them and update this article to clear up any ambiguity.

PHP Auto-link Function

function auto_link($text) {
  $pattern = '/(((http[s]?:\/\/(.+(:.+)?@)?)|(www\.))[a-z0-9](([-a-z0-9]+\.)*\.[a-z]{2,})?\/?[a-z0-9.,_\/~#&=:;%+!?-]+)/is';
  $text = preg_replace($pattern, ' <a href="$1">$1</a>', $text);
  // fix URLs without protocols
  $text = preg_replace('/href="www/', 'href="http://www', $text);
  return $text;
}

Note: Code updated on February 7, 2014 to allow single letter domains and exclamation points in URLs and a few additional tweaks for better matching.

DOM Scripting External Links

Here’s the JavaScript:

function externalLinks() {
  var domainList = new Array("andycouch.com", "google.com");  // Your domain(s).
  // Links to anything on these domains are considered internal.
  // Enclose each domain in quotes, separated by a comma.  (e.g. "domain1", "domain2")
  // You do not need to list sub-domains.  This function already assumes all sub-domains
  // are internal.

  // Open external links in a new window?  true = yes, false = no
  var newWindow = true;

  // Add a special class to external links?  true = yes, false = no
  var addClass = true;
  // Class name for external links.
  var extClass = "external";

  // Add a warning dialog to external links?  true = yes, false = no
  var addWarning = true;
  // Text for warning dialog.
  var warning = "You are about to leave my site.";

  if (!document.getElementsByTagName) return false;
  var anchorList = document.getElementsByTagName("a");
  var protocolStart = "^http[s]?:\/\/";
  var protocol = new RegExp(protocolStart, "i");
  var domains = "";
  for (var i=0; i < domainList.length; i++) {
    domains += "(" + domainList[i] + ")";
    if (i < (domainList.length - 1)) {
      domains += "|";
    }
  }
  var mySites = new RegExp(protocolStart + "([a-z0-9-\.]*\.)?" + domains, "i");

  for (var i=0; i < anchorList.length; i++) {
    if (anchorList[i].href.match(protocol) && !anchorList[i].href.match(mySites)) {
      if (newWindow) anchorList[i].setAttribute("target", "_blank");
      if (addClass) anchorList[i].className=extClass;
      if (addWarning) anchorList[i].onclick=function() {
        var leave = window.confirm(warning);
        return leave;
      }
    }
  }
}
window.onload=externalLinks;

Here’s some extra CSS:

a.external {
  padding-right: 17px;
  background: url("/images/icon_globe.png") right center no-repeat;
}

I’ll add some more text to this entry eventually.

Code Repository and Tidbits from Andy Couch