21
May
12

Maybe it’s not you. Maybe – just maybe – it IS your camera.

I read several photography blogs. One thing that several of these authors keep saying is, “The camera doesn’t matter.” Now I agree whole heartedly when they say something to the effect of “There’s no substitute for an artist’s eye”, but to say that the camera doesn’t matter is going too far.

There IS no substitute for a good eye. Remember that I said that.

Some of these guys just like to think that they are Ivan Lendl out there playing tennis with a wooden racket, still taking the younger players to school with their space-age rackets made with flubber-imbedded Kevlar.  They say things like, “Your equipment does not affect the quality of your image,” and they tell you stories about how this one guy made award winning photographs with nothing but a fifteen dollar Holga. Imagine someone telling Michael Jordan, “Why do you want a basketball? You know, to be a world-class athlete, all you really need is a wooden tennis racket.  Ivan Lendl did it!”

So you see, in my analogy, the photographer is not just like a tennis player picking his tools for returning serves and volleying. It’s bigger than tennis. It’s all sports. He’s an athlete picking a tool that will not only work on grass and clay, but on hardwood and ice … many different conditions. He’s not just getting tennis balls thrown at him. He’s getting tennis balls, basketballs, and boxing gloves thrown at him – and he has to use his broom to sweep the ice in front of the big round sliding stone… for some reason.

My point is, for some things, all you need is a Holga or a cell phone camera. Likewise, for some sports all you need is a racket. For others, you need a bat, a glove, and some metabolic steroids. Landscape photography has different needs than taking pictures at a dimly lit dance recital. Macro photography has different needs from taking long-exposure shots of fireworks.

What if you want to make an award winning photo, but all you have is a cell phone? Well you are limited to what kind of photos you can get. (Keep remembering that I said that there’s no substitute for a good eye.) You better want your award to be for a photo taken in the bright daylight. You want to control your depth of field? Sorry. You better want your award to be for a photo with a large depth-of-field because you can’t control that.

Want to make an award-winning photo using a Holga? You’d better (have the eye of an artist, and) want some wicked vignetting.

You’d better want to play tennis, because you have a tennis racket.

“Your equipment does not affect the quality of your image” is just simply a ludicrous thing to say, and quite frankly, diminishes all the rest of the authors’ arguments.  If you want people to believe you when you say, “there’s no substitute for an artist’s eye”, then don’t include that on a page where you also say that the equipment has absolutely no effect on the quality of the image.

You want to know another famous person who also said, “your equipment does not affect the quality of your image?” Adolf Hitler. See? All my arguments just fell flat because I went too far and said something that is (almost) certainly not true. These authors have a good message, but they spoil it with crazy proclamations and bad analogies about painters and piano players and their equipment.

An aside:

Speaking of bad analogies – back to Ivan Lendl for one more… These cameras-make-no-difference authors are also often the guys who dismiss techniques like HDR and other post-processing magic. It’s in-camera, or it’s cheating to these guys. When they look at photos from Trey Ratcliff, I can just imagine a look on their faces like the top-ranked Ivan Lendl had when seventeen-year-old Michael Change, suffering from cramps, served underhanded to win the point in the 1989 French Open. Lendl looked at the judges afterward with a look that seemed to say, “that had to break SOME rule, right?”

So don’t feel bad that you framed a shot beautifully, but you can’t get that tiny-depth-of-field effect that you want. It might not be you. It might be your camera. Don’t feel bad that you masterfully used the light to illuminate a beautiful portrait, but you can’t capture what’s in your mind’s eye with your 1990’s era webcam. It might not be you. It might be your camera.

Sorry Wayne Gretzky. Your tennis games sucks. But not just because you aren’t a tennis player. It’s also because hockey sticks make horrible tennis rackets.

15
Mar
12

Obvious Extension Methods: IEnumerable Cache

So you don’t want to do a ToList(), but you don’t want to enumerate your IEnumerable<T> more than once? How about an extension method called “Cache” that Caches the output as you go.

  1. public static class Extensions
  2. {
  3.     public static CachedEnumerable<T> Cache<T>(this IEnumerable<T> enumerable)
  4.     {
  5.         return new CachedEnumerable<T>(enumerable);
  6.     }
  7. }
  8. public class CachedEnumerable<T> : IEnumerable<T>
  9. {
  10.     IEnumerator<T> _originalEnumerator;
  11.     readonly IEnumerable<T> _originalEnumerable;
  12.     readonly List<T> _cache = new List<T>();
  13.     public CachedEnumerable(IEnumerable<T> enumerable)
  14.     {
  15.         _originalEnumerable = enumerable;
  16.     }
  17.     public IEnumerator<T> GetEnumerator()
  18.     {
  19.         foreach (var t in _cache)
  20.         {
  21.             yield return t;
  22.         }
  23.         if (_originalEnumerator == null)
  24.         {
  25.             _originalEnumerator = _originalEnumerable.GetEnumerator();
  26.         }
  27.         while (_originalEnumerator.MoveNext())
  28.         {
  29.             _cache.Add(_originalEnumerator.Current);
  30.             yield return _originalEnumerator.Current;
  31.         }
  32.     }
  33.     IEnumerator IEnumerable.GetEnumerator()
  34.     {
  35.         return GetEnumerator();
  36.     }
  37. }

That’s it. If you want to see it in action, open LINQPad, select Language: “C# Program”, delete everything, paste in the above, then finally, paste in the below:

void Main()
{
  var x = GetNumbers().Cache();

  "TAKE 2.".Dump();
  x.Take(2).Dump("TWO:");

  "Get them all.".Dump();
  x.Dump("ALL:");

  "Get them all again.".Dump();
  x.Dump("ALL:");
}

public IEnumerable<T> GetNumbers()
{
  yield return 1.Dump("Numbers is hard");
  Thread.Sleep(500);
  yield return 2.Dump("Numbers is hard");
  Thread.Sleep(500);
  yield return 3.Dump("Numbers is hard");
  Thread.Sleep(500);
  yield return 4.Dump("Numbers is hard");
  Thread.Sleep(500);
  yield return 5.Dump("Numbers is hard");
  Thread.Sleep(500);
  yield return 6.Dump("Numbers is hard");
}

There.

23
Feb
12

Dell Chat Log

Dell’s website won’t let you sort their products by things like screen resolution, but luckily, they offer a handy “chat” feature. So I started the chat, and the rest speaks for itself. Below is the “Dell Chat Session Log” (I might have edited some of my spelling mistakes)

 

Session Started with Agent (Tabassum M)
Agent (Tabassum M): “Hi Philip”
Agent (Tabassum M): “Welcome to Dell US Chat! My name is Tabassum Meraj and I will be your Dell.com Sales Chat Expert.
I can be reached at tabassum_meraj@dell.com or via phone at 1-800-289-3355 ext. 4163264. How can I help you today?”
Philip: “What’s the cheapest laptop dell has with around 1000 lines of resolution on the monitor?”
Agent (Tabassum M): “I would be Glad to assist you with that question”
Agent (Tabassum M): “how many inches of monitor are you looking at ?”
Philip: “It doesn’t matter.”
Philip: “I just want more than 720 lines of resolution.”
Agent (Tabassum M): “give me 2 minutes while I check that for you”
Philip: “ok”
Agent (Tabassum M): “thank you for waiting Philip”
Agent (Tabassum M): “we have Dell IN2030M 20-Inch Flat Panel Monitor with LED that comes with 1600X900 resolution for $159.99″
Philip: “I understand…”
Philip: “But…”
Philip: “My question was…”
Philip: “What’s the cheapest laptop dell has with around 1000 lines of resolution on the monitor?”
Philip: “laptop”
Agent (Tabassum M): “Philip you want the laptop screen with 1000 resolution”
Philip: “Yes. A laptop with a screen that has more than 720 lines of resolution.”
Agent (Tabassum M): “we have XPS 15 with 1080p resolution for $949.99 which is the least expensive one we have”
Philip: “Ah. Ok. thank you.”
Agent (Tabassum M): “How soon are you planning to purchase?”
Philip: “Unsure.”
Agent (Tabassum M): “we have very good deals running I can suggest one as per your needs”
Philip: “good deals on XPS 15 ?”
Agent (Tabassum M): “yes Philip”
Philip: “So they are $949.99 ? or are they actually less than $949.99 ?”
Agent (Tabassum M): “the price is $949.99 I can create quote and see what best deal I can offer you from my side however it will be valid only for today”
Philip: “Because I don’t really want or need the included camera and software. I have all of that already.”
Agent (Tabassum M): “all our laptops come with inbuilt webcam”
Philip: “That’s fine. i’m talking about this: “Includes Canon digital camera and Adobe Photoshop & Premier Elements.”"
Philip: “That’s the one that is $999.99 on your website.”
Agent (Tabassum M): “that is on promotion which camera with camera included in the deal we cannot remove it”
Agent (Tabassum M): “would you like to check the deal on the one without camera which is for $949.99″
Philip: “Sure”
Agent (Tabassum M): “can you help me with your phone number to pull your information”
Philip: “Actually, none of MY information will help you determine the price of your products.”
Philip: “Let me know the price.”
Agent (Tabassum M): “Philip I need to create quote to help you with the best deal”
Agent (Tabassum M): “Quote is not a commitment to purchase. But it Is the list of all the specs & also the price so that you can be absolutely clear of what you are getting & paying.”
Philip: “you’re losing the sale… you have my email address.”+B62
Philip: “You do not need my phone number.”
Philip: “you either have a price or you don’t.”
Philip: “If you do. I’m still listening.”
Philip: “If you don’t, then you’re wasting my time.”
Agent (Tabassum M): “the best deal that I can help you with is for $849.99″
Philip: “Is there a link for the computer that is that price?”
Philip: “the list of all the specs?”
Agent (Tabassum M): “Philip the price for the system on website is $949.99 and I need to create quote which will be emailed to you for $849.99 as it is not available online”
Philip: “You emailed it to me? Ok. Great! Thank you!”
Agent (Tabassum M): “Philip to create quote I need your information which will be emailed to you”
Philip: “I don’t need you to email me my information. I already have it. I need you to email me your product information. This is not difficult.”
Philip: “I understand you are following your rules, so I’m iritated at your rules, not you, personally.”
Philip: “I don’t need you to email me my phone number.”
Philip: “I need you to email me the price plus the specs. that’s it.”
Philip: “Can you do that or not.”
Philip: “?”
Agent (Tabassum M): “I understand Philip however this is the procedure to follow for a quote and I can help you with the link where you can check the specs however for the price that I offered it can only be done by quote”
Philip: “fine. SEND ME THE QUOTE!”
Agent (Tabassum M): “Can you help me with your billing and shipping address full name and contact number to create quote for you”
Philip: “Ha ha.”
Philip: “your procedures just lost you the sale.”
Session Ended



28
Jan
12

Knockout + jQueryUI draggable/droppable – the end

In earlier posts, I went through the simple and a slightly more than simple implementations of using jQueryUI’s dragon drop with knockout. Now I’m going to round it out with my final post on the topic. This time, I’ll add binding capability to other properties of the draggables and droppables. I’m only going to demonstrate binding the ‘disabled’ option of both the draggable and the droppable, but you can use the same process for binding any of the options.

Example

The contrived example this time is a teacher’s seating chart. Go ahead and check out the example. The “Locked” checkbox is bound to the draggables ‘disabled’ option. The droppables get disabled when the seat already has a student in it.

The Code

(function ($, ko) {

  var _dragged, _hasBeenDropped, _draggedIndex;

  ko.bindingHandlers.drag = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dragElement = $(element);

      var dragOptions = {

        helper: function () {

          return dragElement.clone().addClass(“ui-dragon”);

        },

        revert: true,

        revertDuration: 0,

        start: function () {

          _hasBeenDropped = false;

          _dragged = ko.utils.unwrapObservable(valueAccessor().value);

          if ($.isFunction(valueAccessor().value)) {

            valueAccessor().value(undefined);

            dragElement.draggable(“option”, “revertDuration”, 500);

          } else if (valueAccessor().array) {

            _draggedIndex = valueAccessor().array.indexOf(_dragged);

            valueAccessor().array.splice(_draggedIndex, 1);

          }

        },

        stop: function (e, ui) {

          if (!_hasBeenDropped) {

            if ($.isFunction(valueAccessor().value)) {

              valueAccessor().value(_dragged);

            } else if (valueAccessor().array) {

              valueAccessor().array.splice(_draggedIndex, 0, _dragged);

            }

          }

        },

        cursor: ‘default’

      };

      dragElement.draggable(dragOptions).disableSelection();

    },

    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dragElement = $(element);

      var disabled = !!ko.utils.unwrapObservable(valueAccessor().disabled);

      dragElement.draggable(“option”, “disabled”, disabled);

    }

  };

  ko.bindingHandlers.drop = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dropElement = $(element);

      var dropOptions = {

        tolerance: ‘pointer’,

        drop: function (event, ui) {

          _hasBeenDropped = true;

          valueAccessor().value(_dragged);

          ui.draggable.draggable(“option”, “revertDuration”, 0);

        }

      };

      dropElement.droppable(dropOptions);

    },

    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dropElement = $(element);

      var disabled = !!ko.utils.unwrapObservable(valueAccessor().disabled);

      //dropElement.droppable(“option”, “disabled”, disabled); didn’t work. jQueryUI bug?

      dropElement.droppable(“option”, “accept”, disabled ? “.nothing” : “*”);

    }

  };

})(jQuery, ko);

The thing that’s different from last time is the implementation of the ‘update’ methods in the binding handlers. The update method gets called when the value of any of the ko.observables change, so I just get the observable from the valueAccessor() and call ko.utils.unwrapObservable() with that sucka, and you have the value to update the options with.

Usage

The usage is very similar to the last example, with the addition of the disabled binding, as in the excerpt from the HTML in the jsfiddle example:

<span data-bind=“drag: {value: student, disabled: $root.isLocked}”>

…shows how I bind the value of the isLocked viewModel property to the ‘disabled’ option of the drag (The checkbox is also bound to the isLocked viewModel property), and…

<td data-bind=“drop: {value: student, disabled: !!student()}”>

…shows how I bind the ‘disabled’ option of the drop to the existence of a student in the seat.

Future

I might update this page sometime in the future to add other options bindings, or to add new functionality. For example, there’s a spot already for a hook to add a ‘revert‘ event to the draggable inside the if (!_hasBeenDropped)  block.

25
Jan
12

Obvious Methods: Distinct with equality selector

You have an IEnumerable<SomeType> on which you want to do a .Distinct(). ”SomeType” is not equatable – at least not in the way you want. Your only choice is to write an IEqualityComparer… Until today!!!

Here’s what you WANT to write:

myEnumerable.Distinct(item => item.Id);

…assuming that the Id’s make them unique. And here’s the extension method override of Distinct that lets you do this:

public static class Extensions

{

  public static IEnumerable<T> Distinct<T, TCompare>(this IEnumerable<T> items, Func<T, TCompare> predicate)

  {

    var distinctKeys = new HashSet<TCompare>();

    foreach (var item in items)

    {

      var key = predicate(item);

      if (distinctKeys.Contains(key)) continue;

      distinctKeys.Add(key);

      yield return item;

    }

  }

}

Now, you’re probably saying, couldn’t I just write?:

myEnumerable.GroupBy(item => item.Id).Select(g => g.First());

It gives you the same output, but, this new Distinct method is:

  1. faster… like an order of magnitude faster
  2. easier to read… like an order of magnitude easier to read.
  3. lazier. Consider the following contrived enumerable:

var list = new[]

            {

              new {x = 1, y = “one”},

              new {x = 1, y = “won”},

              new {x = 1, y = “juan”},

              new {x = 0, y = “zero”},

            };

…and this call to .Distinct:

list.Distinct(item => 1 / item.x).Take(1);

With the GroupBy approach, this would raise an Exception. But with the new Distinct, you get no exception because it is so dang lazy.

17
Jan
12

Knockout + jQueryUI Draggable/Droppable Follow-up

[Edit: The final edition in the Knockout + jQueryUI Draggable/Droppable series is in!]

This is the follow-up to my last post which described the simplest implementation possible of drag and drop with knockout.  In that example, the items in the list never moved, they were just cloned when dragged and dropped on the target. The goal accomplished was to drag data from one binding to another while allowing knockout to display the addition of data in the drop target.

Goals for This Iteration

  • I wanted to allow knockout to display the addition of the data in the drop target (as in the last post) and also display the removal of the data from the source when dragging begins.
  • I wanted the data item that is dragged to either be an element from an observable array OR a stand-alone observable – the former forcing the entire array’s UI to be redrawn without the element and the latter allowing just the space where the element was to be redrawn, allowing an empty space where the element was to remain, if you choose.

How it Works

The chain of events in this implementation is: 1) user clicks and begins a drag, then 2) JQueryUI clones the DOM element that will be used during the visual drag, then 3) the bound dragged data item is removed from the source. When the drop event happens on a droppable, 4a) the droppable’s bound data value is set to the dragged data item. If the drop event doesn’t happen, 4b) the dragged data item is added back to where it was removed in #3.

Code

(function ($, ko) {

  var _dragged, _hasBeenDropped, _draggedIndex;

  ko.bindingHandlers.drag = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dragElement = $(element);

      var dragOptions = {

        helper: ‘clone’,

        revert: true,

        revertDuration: 0,

        start: function () {

          _hasBeenDropped = false;

          _dragged = ko.utils.unwrapObservable(valueAccessor().value);

          if ($.isFunction(valueAccessor().value)) {

            valueAccessor().value(undefined);

            dragElement.draggable(“option”, “revertDuration”, 500);

          } else if (valueAccessor().array) {

            _draggedIndex = valueAccessor().array.indexOf(_dragged);

            valueAccessor().array.splice(_draggedIndex, 1);

          }

        },

        stop: function (e, ui) {

          if (!_hasBeenDropped) {

            if ($.isFunction(valueAccessor().value)) {

              valueAccessor().value(_dragged);

            } else if (valueAccessor().array) {

              valueAccessor().array.splice(_draggedIndex, 0, _dragged);

            }

          }

        },

        cursor: ‘default’

      };

      dragElement.draggable(dragOptions).disableSelection();

    }

  };

  ko.bindingHandlers.drop = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

      var dropElement = $(element);

      var dropOptions = {

        tolerance: ‘pointer’,

        drop: function (event, ui) {

          _hasBeenDropped = true;

          valueAccessor().value(_dragged);

          ui.draggable.draggable(“option”, “revertDuration”, 0);

        }

      };

      dropElement.droppable(dropOptions);

    }

  };

})(jQuery, ko);

How to use it

In the example, the user will be sorting items, and when I think sorting, I think laundry. Go ahead and try it out

The elements on which you put the data-bind=”drag: {value: whatever}” can be done in a couple of ways:

Using an observable:

In the viewModel:

myArray: [

  { item: ko.observable({ name: "Willis" }) },

  { item: ko.observable({ name: "Arnold" }) },

  { item: ko.observable({ name: "Mr. D" }) }

],

In the html:

<ul data-bind=“foreach: myArray”>

  <li>

    <div data-bind=“drag: {value: item}”>

      <!– ko if:item –>

        <div data-bind=“text: name”></div>

      <!– /ko –>

    </div>

  </li>

</ul>

In this example, myArray doesn’t need to be an observable array unless items will be added to the list. The observables don’t even have to be in a list at all. This is the preferred way and allows for the most flexibility. If you want the space that the element occupied to remain after the element is ripped out (or you want control over that), use this method.  The jsfiddle example using this method will provide more details.

Using an obserableArray:

In the viewModel:

myArray: ko.observableArray([

  { name: "Willis" },

  { name: "Arnold" },

  { name: "Mr. D" }

]),

In the html:

<div data-bind=“foreach: myArray”>

    <div data-bind=“drag: {value: $data, array: $root.myArray}”>

        <div data-bind=“text: name”></div>

    </div>

</div>

If you use it in this way, the element that has the data-bind=”drag: …” needs to be the child of the element with the data-bind=”foreach: …”. If it is not, strange things happen when knockout re-renders the list. I have a laundry sorting jsfiddle example using this method, too, but still prefer using observables over observableArrays. You have to tell it what array the items are in (see the array: $root.myArray in the sample code above.). Sorry.

Conclusion

In my next post, I’ll put a bow on it and add a few more features, like data binding for other draggable and droppable properties. Maybe that’ll be cool.

07
Jan
12

Knockout + jQueryUI Draggable/Droppable

[Edit: The follow-up to this is in, as well as the final edition in the Knockout + jQueryUI Draggable/Droppable series is in!]

I recently wanted to create a simple game with my son that was very drag-n-drop-centric. I knew I’d use JqueryUI for the drag/drop, so I coded it up, took a step back, and realized that my code was seriously ugly. There was way too much DOM interaction in my code. What it needed was some Knockoutjs!

So this blog post will be the first in a series building up a drag-n-drop knockout custom binding. I’ll start out simple in this post, and build it up to be more feature-rich in later posts. In this post, we’ll learn about:

  • data binding using knockout
  • Jquery draggables and droppables
…as well as some slightly more advanced Knockout features such as…

The contrived task… a pizza builder. Take a list of toppings for a pizza that are in json, and drag the toppings onto the pizza, resulting in toppings data in my pizza json.

Knockout is all about binding data to the UI, so my drag-n-drop implementation will drag and drop DATA, and the UI will just represent that… you’ll see what I mean – especially if you look at the jsfiddle of it.

Here’s the html:

    1 <ul id=“toppings” data-bind=“foreach: toppings”>

    2   <li data-bind=“text: $data, drag: {value: $data}”></li>

    3 </ul>

    4 <br>

    5 <!– ko with: pizza –>

    6 <div id=“pizza” data-bind=“drop: {value: latestTopping}”>

    7   <div data-bind=“visible:(!!latestTopping())”>

    8     <p>

    9       Thanks for adding <span data-bind=“text:latestTopping”></span>!</p>

   10     <span>So far, you’ve added:</span>

   11     <ul data-bind=“foreach: toppingStack”>

   12       <li data-bind=“text: $data”></li>

   13     </ul>

   14   </div>

   15 </div>

   16 <!– /ko –>

Notice the drag: {value: ___} and drop: {value: ___}. That just says that I’m dragging one of the values from the toppings (see the foreach on line 1) and when it’s dropped, it’ll update the the latestTopping property (line 6) on the pizza (line 5). Small note: I could have simply used drag:$data instead of drag: {value:$data}, but I know I’ll have more options to add later.

The viewModel that I’m calling ko.applyBindings on looks like this:

var pizzaria = {

  toppings: ["Pepperoni", "Olives", "Sausage", "Bacon", "Canadian Bacon", "Chilean Bacon"],

  pizza: new Pizza()

};

…and the Pizza function just defines a latestTopping property that is a knockout observable.

I wanted to know all the toppings ever added to the pizza, so the latestTopping property makes use of ko.computed so that the write adds the value to an array and the read just reads the most recently added topping. So here’s the Pizza:

    1 function Pizza() {

    2   this.toppingStack = ko.observableArray();

    3   this.latestTopping = ko.computed({

    4     read: function () {

    5       return this.toppingStack().length ? this.toppingStack()[0] : “”;

    6     },

    7     write: function (value) {

    8       if (value) {

    9         this.toppingStack.unshift(value);

   10       } else {

   11         this.toppingStack.shift();

   12       }

   13     },

   14     owner: this

   15   });

   16 }

   17

Then of course, there’s this important magical line of javascript:

ko.applyBindings(pizzaria);

So here it is… my simplest-thing-that-could-work dragon drop knockout custom binding with jqueryui draggable and droppable:

    1 (function () {

    2   var _dragged, _noOp = function () { };

    3   ko.bindingHandlers.drag = {

    4     init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

    5       var dragElement = $(element);

    6       var dragOptions = {

    7         helper: ‘clone’,

    8         revert: true,

    9         revertDuration: 0,

   10         start: function () {

   11           _dragged = ko.utils.unwrapObservable(valueAccessor().value);

   12         },

   13         cursor: ‘default’

   14       };

   15       dragElement.draggable(dragOptions).disableSelection();

   16     }

   17   };

   18

   19   ko.bindingHandlers.drop = {

   20     init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

   21       var dropElement = $(element);

   22       var dropOptions = {

   23         drop: function (event, ui) {

   24           valueAccessor().value(_dragged);

   25         }

   26       };

   27       dropElement.droppable(dropOptions);

   28     }

   29   };

   30 })();

First thing to note is that it is inside a self-executing function (note the “()” on the last line). The reason that is done is so that the variables declared at the top are hidden from the global scope.

A couple of notes about the variable “_dragged”:

  1. I named it with an underscore just so it would stand out to me as a closure from a scope outside where it is written and read. No big deal.
  2. I didn’t have to use a variable for that. I could have stuck it in the data of the html element being dragged (that is: $(element).data(“key”, “value”)), but I made the assumption that only one thing could be dragged at a time and I figured with a single variable to hold it, I wouldn’t leave data lying around tied to DOM elements or have to worry about cleaning them up.

For a custom bindingHandler, you have to implement one or both of the methods init and update. For now, I only need the init. Inside the drag’s init method and the drop’s init method, everything looks pretty typical for the jqueryui draggable and droppable, except for just a few things.

Notable items from the drag’s init function:

  • I used the option “helper: ‘clone’” and “revert: true” because I wanted to only effectively drag around DATA, and not actually move DOM elements around. I let the bindings do their magic and leave the DOM elements where they originate. Don’t worry, in a later post, I’ll discuss how to make it appear that the elements are actually moving, but in this example, the pizza toppings stay in the toppings list forever. They do appear to be ‘added’ to the pizza, but that is just plain-old data binding at work.  Besides, you probably want to be able to add bacon to the pizza multiple times.
  • Line 11 is where the _dragged variable is set from the observable you declared to be draggable in the data-bind=”drag:{value: ___}”

Notable items from the drop’s init function:

  • line 24 is where the observable you declared to be droppable in the data-bind=”drop: {value: ___}” gets set from the _dragged variable.

That’s pretty much it for the simple example.

Please check out the jsfiddle for this example to see it in action. More to come on this later.

30
Dec
11

Snizzlator (Lite) for ALL

You loved the original Snizzlator and the Snizzlator for Chrome, but you’ve moved on from Greasemonkey and Tampermonkey?

The snizzlatorLite has all the funny, but without the preferences.

  1. Use Chrome.
  2. Install The SnizzlatorLite by clicking I’m not sure about this whole snizzlator thing.
  3. Go to your favorite site.
  4. Behold the power of random.

The results?

  1. Use Chrome.
  2. Install Tha Snizzlata’ by clickin’ I’m not sho’ abizzle dis whole snizzlata’ stuff.
  3. Go to yo’ favorite site.
  4. Behold tha powa’ of random.
30
Dec
11

Snizzlator for Chrome

You loved the original Snizzlator, but you’ve moved on from Firefox…?

  1. Use Chrome.
  2. Install Tampermonkey by clicking With a name like Tampermonkey…
  3. Install The Snizzlator by clicking I’m not sure about this whole snizzlator thing.
  4. Go to your favorite site.
  5. Behold the power of random.

This thing has preferences too.  Just click the tampermonkey logo:

The results?

  1. Use Chrome.
  2. Instiggity Tampermonkey by clickin’ Wit a name like Tampermonkey…
  3. Install Tha Snizzlata’ by clickin’ I’m not sho’ abizzle dis whole snizzlata’ stuff.
  4. Go to yo’ favorite site.
  5. Behold tha powa’ of random.

Dis stuff have prizzneferences too.  Jus’ click tha tampermonkey logo:

20
Dec
11

Obvious Methods: IDictionary Get – with defaults

Most of this blog is just obvious extension methods. Here’s another.

I was writing this code today:

var mappedValue = mapDictionary.ContainsKey(value) ? mapDictionary[value] : defaultMapValue;

I immediately knew I was going to find an existing method on IDictionary, or write an extension method for this. I couldn’t find an existing one, so I wrote one. Now my code looks like this:

var mappedValue = mapDictionary.Get(value, defaultMapValue);

It takes the key that I want the value for, and a value to return if the key is not found.

IEnumerable has an ElementAtOrDefault method that returns the default value for the type, so I wrote an overload for my method that returns the default value for the type, too. (It returns null for reference types, like strings, and return zero for ints, etc…)

I figured I needed another overload or two that take a Func to get the default value for use in the case where getting the default value is not trivial.

So here’s my suite of three IDictionary.Get methods:

  public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> getDefaultValue)

  {

    TValue value;

    return dictionary.TryGetValue(key, out value) ? value : getDefaultValue(key);

  }

  public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> getDefaultValue)

  {

    return dictionary.Get(key, k => getDefaultValue());

  }

  public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)

  {

    return dictionary.Get(key, k => defaultValue);

  }

  public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)

  {

    return dictionary.Get(key, k => default(TValue));

  }

How do you use it?  How about I provide a completely contrived example? Let’s say you have this list of state abbreviations and state names that begin with the letter ‘A’ in a Dictionary, but we don’t have the rest of the states:

var aStates = new Dictionary<string, string>{{"AL", "Alabama"}, {"AK", "Alaska"}, {"AZ", "Arizona"}, {"AR", "Arkansas"},};

Now lets say you have another list of state abbreviations, and you want to get the names for them.

new[]{"AL", "AR", "TN", "AZ"}.Select(s => aStates.Get(s, "Some non-A state"));

Run that, and you get an IEnumerable with the following:

Alabama
Arkansas
Some non-A state
Arizona

If you use the overload that doesn’t take a default…

new[]{"AL", "AR", "TN", "AZ"}.Select(s => aStates.Get(s));

…you’d see a NULL for the “TN” value.

Alabama
Arkansas
null
Arizona

You could use the overload that takes a Func to call some service that gets the state name for the abbreviation.

new[]{"AL", "AR", "TN", "AZ"}.Select(s => aStates.Get(s, StateService.GetByAbbreviation));

…and it only gets called when it’s needed.

Maybe it would be cool to write one that adds “TN” to the underlying dictionary after the service is called, so that it doesn’t have to call the service again for “TN”. (Caching!)




Follow

Get every new post delivered to your Inbox.