OdeToCode IC Logo

The Three Phases of OOP Matter

Wednesday, August 24, 2011 by K. Scott Allen

Gas

public static class Logger  {

    public static void Log(string message, LogTypeEnum type) {
        // ...
    }

}

 

Liquid

public class Logger  {

    public void LogError(Exception ex) {
        // ...
    }

}

 

Solid

public class Logger : ILog, IAudit  {

    public Logger(IExceptionFormatter exceptionFormatter,
                  IStackTraceFormatter stackTraceFormatter,
                  IClock clock,
                  ITextWriter writer) {
        // ...
    }

    public void LogError(Exception ex) {
        // ...
    }
}

A Magnifying Lens using Script and CSS

Tuesday, August 23, 2011 by K. Scott Allen

imageMagno is a something I put together because … well, just because. The idea is to provide a magnifying lens effect using a background image and background position animation. The lens tracks the position of the mouse, with a slight delay (debouncing, to be exact).

You can try it here: http://jsbin.com/adobuv (thanks to @austegard for putting up the jsbin).

The "magnifier" is an absolutely positioned div with borders curved to perfection.

function makeMagnifier() {
    var src = settings.src || img.attr("src");
    magnifier = makeEmptyDiv();
    magnifier.css({
        position: "absolute", 
        opacity: 0,
        width: settings.size, height: settings.size,
        left: img.offset().left, top: img.offset().right, 
        "-moz-border-radius": settings.size * .5 + "px", 
        "border-radius": settings.size * .5 + "px",       
        "background-image": "url(" + src + ")",
        "background-repeat": "no-repeat",
        "z-index": 998
    });
}

When the mouse pauses, the magnifier animates to the new location.

function onPosition(e) {
    var offset = img.offset();
    var backLeft = Math.round((e.pageX - offset.left) * 
                             (-1 / settings.scale));
    var backTop = Math.round((e.pageY - offset.top) * 
                             (-1 / settings.scale));
    backLeft += Math.round(settings.size / 2);
    backTop += Math.round(settings.size / 2);
    magnifier.animate({
        left: e.pageX - (settings.size/2),
        top: e.pageY - (settings.size/2),
        "backgroundPosition": backLeft + "px " + backTop + "px"
    });            
}

Animating the background position of an element is not something jQuery can do without help. I used a plugin from Alexander Farkas.

A Simple 2-Column Layout in Razor

Monday, August 22, 2011 by K. Scott Allen

2 column layouts are rather popular on the web, and there are 1,001 ways to make them work. The approach you choose really depends on the type of content you have, and how you want images and backgrounds to work. What I'll show is the Razor _Layout and CSS to achieve the following look:

image

The Razor _Layout file can rely on partial views to handle each of the primary sections: top, navigation, sidebar, and footer. RenderBody will produce the primary content area.

<!DOCTYPE html>
<html>
<head>    
    <title>@ViewBag.Title</title>    
    <link href="@Url.Content("~/Content/Site.css")" 
          rel="stylesheet" type="text/css" />
</head>

<body>
    @Html.Partial("_top")
    @Html.Partial("_navigation")
    @Html.Partial("_sidebar")                               
    <div id="body">
        @RenderBody()      
    </div>    
    @Html.Partial("_footer")   
</body>
</html>

A quick note on Html.Partial. If any sections, like the sidebar and navigation sections, require some logic or model information to build their piece of the UI, then use Html.Action instead of Html.Partial. Html.Action allows you to setup a little sub-request inside the current request and allow a controller action to build a model and select a view.

The CSS coming up assumes each partial view will render inside an element with an id matching it's purpose (so the _top view renders a div with an id of top).

<div id="top">
    This is the top content
</div>

Then finally, add some styles to the CSS file: 

#top {
    height: 20px;
    text-align: center;
    background-color: black;
    color: white;   
}

#navigation {
    height: 25px;
    margin: 5px;
    padding: 5px;
    color:crimson;
}

#sidebar {
    margin: 5px;
    padding: 5px;
    position: absolute;
    top: 50px;
    left: 314px;
}

#body {
    width: 300px;
    padding: 5px;
    margin: 5px;
    background-color: #999999;
    border-radius: 5px;
    border: 2px black solid;
}

#footer {
    padding: 5px;
    text-align: center;
    background-color: black;
    color: white;
}

The trick is to use absolute positioning on the sidebar content, which is possible because we know the exact amount of space taken by the 2 sections at the top of the page, and we know the exact width of the content area (it is set explicitly in the CSS). You'll probably want to give the body more space than the 300px given in the sample above (which was constrained so the screenshot would fit on this page).

A Tale of Backgrounds, Absolutes, mouseleave, and mouseenter

Thursday, August 18, 2011 by K. Scott Allen

mouseleave is simple to understand:

Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element.

How hard could it be? http://jsfiddle.net/JP6aV/

$(function () {
    var output = $("#output");
    $("#content")
      .mouseenter(function (e) {
          output.text("I'm in!");
    }).mouseout(function (e) {
          output.text("I'm out!");
    });
});

Like many simple things there are some traps under different circumstances. For example, when you put absolutely positioned elements into a page, you might think mouseenter and mouseleave are misbehaving. Watch what happens on http://jsfiddle.net/uUsEM/1/ when the mouse goes into the grey box.

If you've worked with nearly any UI framework before, you'll realize this isn't a misbehavior, but a feature.  But, what if your goal is to use mouseleave and mouseenter to know when the mouse is over the content area, regardless of what might be positioned on top? One solution is to create an element whose sole purpose is to provide mouseenter and mouseleave events for the content area. If the element overlays the content area exactly, has a higher z-index than any other element, and is invisible, then you just might have something that works (see http://jsfiddle.net/5psgc/1/).

$(function() {
    var output = $("#output");
    var content = $("#content");
    var eventSource = $("<div></div>");
    $("body").append(eventSource);

    eventSource.css({
        position: "absolute",
        left: content.offset().left,
        top: content.offset().top,
        width: content.width(),
        height: content.height(),
        opacity: 0,
        "z-index": 999
    }).mouseenter(function(e){
        output.text("I'm in!");
    }).mouseout(function(e) {
        output.text("I'm out!"); 
    });
});

If you try http://jsfiddle.net/5psgc/1/ in Chrome, you'll see the "in" and "out" messages only appear when the mouse is going into, or out of, the content area – no matter where the grey div appears. In IE9 the "in" and "out" messages appear at the wrong places. It's as if Internet Explorer has no empathy for an empty, faceless, soulless div.

The solution?

Set the background-color on the event source. Even though the color doesn't appear, because the opacity is at 0, the events start working as expected.

eventSource.css({
    position: "absolute",
    left: content.offset().left,
    top: content.offset().top,
    width: content.width(),
    height: content.height(),
    opacity: 0,
    "background-color": "#000", // <-- crazy
    "z-index": 999
})

See: http://jsfiddle.net/5psgc/2/

Underscore.js

Wednesday, August 17, 2011 by K. Scott Allen

Liam told me about Underscore.js some time ago. From the home page:

Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects. It's the tie to go along with jQuery's tux.

The functional programming support from Underscore includes, but is not limited to, the standard map, filter, reduce functionality.

var data = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var result =
     _.filter(data, function (n) { return n % 2 == 0; })
      .map(function (n) { return n * n; })
      .reduce(function (sum, n) { return sum += n; });

Notice the gateway to all the Underscore features is the  _ (underscore) object.

What I've found useful recently are the throttle and debounce methods. Throttle ensures a method is only called once every n milliseconds, while debounce will ensure a method is only called after someone stops calling the method for n milliseconds. I'm fond of debounce because I spent many hours years ago writing debounce logic for mechanical switches, but also because it demonstrates the power of composing behavior with higher order functions. Both throttle and debounce use an internal function called limit to implement their behavior (the source code from Underscore shown below, sans comments).

var limit = function (func, wait, debounce) {
    var timeout;
    return function () {
        var context = this, args = arguments;
        var throttler = function () {
            timeout = null;
            func.apply(context, args);
        };
        if (debounce) clearTimeout(timeout);
        if (debounce || !timeout) timeout = setTimeout(throttler, wait);
    };
};

_.throttle = function (func, wait) {
    return limit(func, wait, false);
};

_.debounce = function (func, wait) {
    return limit(func, wait, true);
};

There are so many interesting concepts in the limit function – I think you could build an 8 hour workshop from those 11 lines of code.

To see how throttle would work, you could use the following code to process and log mouse movement, but throttle the processing so you only see the console output once every 1,000 milliseconds.

$(window).mousemove(_.throttle(function (e) {
    console.log(e.pageX, e.pageY);
}, 1000));
Fantastico!

Clojure and the CLR

Tuesday, August 16, 2011 by K. Scott Allen

From the Clojure home page:

Clojure is a dialect of Lisp, and shares with Lisp the code-as-data philosophy and a powerful macro system. Clojure is predominantly a functional programming language, and features a rich set of immutable, persistent data structures. When mutable state is needed, Clojure offers a software transactional memory system and reactive Agent system that ensure clean, correct, multithreaded designs.

I’ve had an interest in Clojure ever since I saw Craig Andera do a talk on the topic in D.C. (Craig also has a set of Clojure videos @ Pluralsight). It was just an intellectual fascination until clojure-clr appeared and things took a turn towards the possibly practical.

Why Am I Interested in Clojure?

As a dialect of Lisp, Clojure embodies the spirit of the greatest single programming language ever designed, including the parentheses, prefix notation, and a simple, clutter-free syntax.

Clojure C#
; Comparing 5 and 3+2 returns 0
(println (compare 5 (+ 3 2)))
// Comparing 5 and 3+2 returns 0
Console.WriteLine(5.CompareTo(2 + 3));

Functions are first class citizens in Clojure, of course, so you can pass functions as parameters and return them as the result of other functions. There are closures, currying, and recursive looping. Fans of LINQ and functional programming with Func<> and Action<> on the CLR should know that you won’t be missing anything with Clojure, in fact, there is a whole new world to explore.

Clojure C#
(take 2 (reverse 
  (filter (fn [s] (= \L (first s))) 
    ["Minnesota", "Detroit", "London", "Las Vegas"] )))
var places = new string[] 
    { "Minnesota", "Detroit", 
       "London", "Las Vegas" }
    .Where(s => s.First() == 'L')
    .Reverse()
    .Take(2);

Also, like any LISP, the compiler offers extensibility through macros. Program code is data you can evaluate or manipulate. However, the hallmark of Clojure is the inherent support for safe and simple concurrency. I plan on using Clojure in some data analysis work, and we'll explore interop and threading in a future post.

What's Wrong With This Code? (#28)

Monday, August 15, 2011 by K. Scott Allen

Victor Brumble is writing code again, and this time he's writing a jQuery plugin. His plugin makes alert boxes easy, because Victor loves pointless, modal dialogs.

(function ($) {

    var settings = {
        text: 'Thank you for clicking!'
    };
    
    $.fn.alerter = function (options) {

        return this.each(function () {

            if (options) {
                $.extend(settings, options);
            }

            $(this).click(function () {
                alert(settings.text);
            });
        });
    };
})(jQuery);

As you can see, Victor has a default text message associated with his plugin, but he also learned how to use jQuery.extend to allow callers to override the default text. The plugin is working well for Victor, but another developer is complaining about the following code not working correctly.

<p id="p1">
    This is paragraph 1.
</p>
<p id="p2">
    This is paragraph 2.
</p>
<script type="text/javascript">
    $("#p1").alerter({ text: "Please don't click again!" });
    $("#p2").alerter({ text: "This is not the text you want!" });
</script>

What could possibly be wrong?