[Be el o ge]

I ♥ The Web

[Be el o ge]

Thinking about buying an iMac

August 29th, 2010 · 1 Comment

I like to believe that I’m 95% decided to buy an iMac. The remaining final question is: which one?

Out of the relatively big choice one currently has (new version released a couple of weeks ago, old version still available) I narrowed it down to these:

  • Old version of iMac 27″: i3 3.06GHz, 4GB RAM, 1TB hard disk, ATI 4670 256MB: 1439.00 EUR
  • Old version of iMac 21.5″: i3 3.06GHz, 4GB RAM, 1TB hard disk, ATI 4670 256MB: 1295.00 EUR
  • New version of iMac 21.5″: i3 3.2GHz, 4GB RAM, 1TB hard dis, ATI 5670 512MB: 1429.00 EUR

After all the difference between the old and recently released new version of the iMac is not really significant. At least if you’re not going for one of the high end versions with i5 / i7 quad core processors and high end ATI graphics. Since I’m not playing on the Mac, I’m not doing any video editing, etc, I probably can narrow the choice further down by eliminating #3 in the list: new version of 21.5″ iMac.

So old version with 27″ or 21.5″. Is the ATI 4670 powerful enough for the huge screen with its enormous resolution? I guess tomorrow I’ll decide : – )

  • Delicious
  • Twitter
  • Facebook
  • LinkedIn
  • Reddit
  • Slashdot
  • Technorati Favorites
  • Digg
  • Share/Bookmark

→ 1 CommentTags: in eigener Sache

Inside the Tornado – Geoffrey A. Moore

August 17th, 2010 · No Comments

Inside the Tornado is subtitled with “Strategies for Developing, Leveraging, and Surviving Hypergrowth Markets“.

Though I’m not working in Marketing, or maybe just because of that, I really enjoyed reading “Inside the Tornado”. There is a lot of valuable information in this book; unfortunately much more then I can keep in mind longterm. Therefore here some key concepts I thought are worth remembering even if you are, like me, not working in the Marketing or Sales department of your company.

The foundation of the whole book is the Technology Adoption Life Cycle.

Technology Adoption Lifecycle

This is pretty much the life cycle every tech product goes through during its lifetime. Each phase has it’s own dynamics and groups which are important to address and communicate with. Each phase needs its own strategies. As main customers of each phase, Moore defines below groups:

  • Innovators = Technology enthusiasts.
  • Early Adopters = Visionaries.
  • Early Majority = Pragmatists.
  • Late Majority = Conservatives.
  • Laggards = Skeptics.

The Chasm

The chasm is the phase of the technology adoption life cycle which needs to be crossed by the product in order to enter the mainstream market. Refining above diagram, we are getting this:

The Chasm

Add this point I’d like to quote from the book two paragraphs which, in my opinion, contain the central message ragarding “crossing the chasm”:

The fundamental strategy for making a successful “crossing” is based on a single observation: the main difference between the visionaries of the early market and the pragmatists in the mainstream is that the former are willing to bet “on the come” whereas the latter want to see solutions “in producion” before they buy. That is, when a visionary sees that you have 80 percent of the solution to her problem, she says, “Great, let’s get started right away on building the other 20 percent together.” A pragmatist, on the other hand, says, “Wait a minuate – aren’t you supposed to be the one improving my productivity? I’ll buy this thing when it’s done not before.” Specifically, what pragmatists want, more than anything else, is a 100 percent solution to their problem – what we came to call the whole product.
[...]
the key to a winning strategy is to identify a single beachhead of pragmatist customers in a mainstream market segment and to accelerate the formation of 100 percent of their whole product. The goal is to win a nice foothold in the mainstream as quickly as possible – that is what is meant by crossing the chasm.

In order to come to the main topic of the book we need one more refinement of the life cycle and introduce the Bowling Alley and, finally, the tornado.

Bowling Alley and Tornado

And more quotes directly from the book:

  • The Bowling Alley: A period of niche-based adoption in advance of the general marketplace, driven by compelling customer needs and the willingness of vendors to craft niche-specific whole products.
  • The Tornado: A period of mass-market adoption, when the general marketplace switches over to the new infrastructure paradigm.

Bowling Alley Market Development

Bowling Alley Market Development

So what this diagram wants to say is that from the one niche market you already dominate you have to spread out to other niche markets, ideally such markets which are close to the initial market. Thus you can use knowledge and and possible connections you gained by building and selling a whole product for the first market segment you entered. A lot more interesting stuff about market development during the Bowling Alley phase you will find on page 39 of “Inside the Tornado”.

Moore advices, that the Tornado is the market phase in which you need to become the “gorilla”. What that means in terms of market share and profit show these diagrams:

Marketshare by Profits and Revenue

This is the time when it’s more important than anything else to just ship your product. The profits of the gorilla are so high, even compared to its market share by revenue, because the gorilla in the market is the one who sets the price bar. All competitors must discount below that price in order to successfully compete! There are quite a few advantages of being the gorilla and the tornado is the only phase of the market to gain these.

Main Street

Unlike during crossing the chasm and in the Bowling Alley where you try to create whole products for each market niche, on Main Street, you extent your product in order to serve niche markets which could use your product if only you added very little functionality to it.

Niche Market Extensions

So….

This is just a very rough summary of approximately the first half of the book. There are plenty of details which are interesting and I totally recommend reading “Inside the Tornado”! I believe that having at least some background in marketing (like e.g. the stuff I talk about above) helps to understand certain dynamics which are observable in every tech company. And understanding something is the first step to make you even better in your job ;-)

Buy Inside the Tornado at Amazon:

  • Delicious
  • Twitter
  • Facebook
  • LinkedIn
  • Reddit
  • Slashdot
  • Technorati Favorites
  • Digg
  • Share/Bookmark

→ No CommentsTags: Marketing

Improving Javascript Minification by Using Closure

August 14th, 2010 · No Comments

Like jQuery, I’m using the Google Closure Compiler to minify the code of my Image Color Picker plugin.

When I looked over the minified code, I noticed that quite a few function names don’t get minified.
Let’s take a closer look at the v0.1 version of ImageColorPicker.js (github):

$.widget("ui.ImageColorPicker", {
 options: {},
  _create: function() {
  },
 
  destroy: function() {
  },
 
  selectedColor: function() {
  },
 
  _d2h: function(d) {
  },
 
  _h2d: function(h) {
  },
 
  _createImageColorPicker: function() {
  }
});

option, _create, destroy, selectedColor and all the other function names don’t get minified. Everything within these function gets minified pretty well. The reason for this is that the Closure Compiler regards all these functions and objects as public. Since they are public the compiler does not know whether another, external library uses one or more of the functions. In order not to break external libraries or, more generally, code that depends on our code, the Closure compiler does not touch the names.

In case you have quite a few “private” functions and / or use them heavily, it can become pretty space wasting to not minify them. So how to fix this?

The solution is: Use a Javascript Closure. By using closures you can make functions truly private, compared to marking them private by using the underscore convention. This is ImageColorPicker.js after the refactoring (github):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var uiImageColorPicker = function(){
 
	var _d2h = function(d) {
	};
 
	var _h2d = function(h) {
	};
 
	var _createImageColorPicker = function(widget) {
	};
 
 
 
	return {
		options: {},
 
		_create: function() {
		},
 
		destroy: function() {
		},
 
		selectedColor: function() {
		}
 
	};	
}();
$.widget("ui.ImageColorPicker", uiImageColorPicker);

In line 1 a function is assigned to uiImageColorPicker. But not really. Take a closer look at line 27. It’s directly executed. Therefore the value which is assigned to uiImageColorPicker is not a function, but the object which is returned by the function. This object is supposed to contain all public functions of your plugin and option, _create and destroy, since these are expected by the jQuery UI Widget implementation.
All private functions go to the function body, outside of the object. After the outer function ran, they won’t be accessible any more, but if you use them in functions of the returned object they are bound through a closure and thus can be used by the object’s functions even after the outer function finished execution.

When doing such thing, there are two things I can think of which require a little extra attention:

  • Don’t store object specific data in the function body. That’s like storing data in an object prototype. All objects would either read the same data, or worse, overwrite data. Therefore, keep object related data in the object.
  • this refers to the object when used within the object and to the function when used outside of the object in the function body. If you need to use the object’s this reference in your private function, pass it in as a parameter. I’m doing this for example in the create function. Check out github for the code.

A bonus: In case you ever forget to remove a private function which you don’t use anymore it will be removed entirely by the Closure Compiler in the minified version of your plugin ;-)

Measuring the result

After refactoring the code, I ran the Closure Compiler again. Before the minified version of the plugin had 3729 bytes. After the refactoring it had 3475 bytes. That’s about 8% smaller. Hm, not quite a lot you’d say. But:

  • ImageColorPicker is a very small plugin anyway. If your plugin has a lot more private functions and / or uses them more frequently the savings will increase.
  • If you have thousands of hits per day, each percent you save in download size will save yourself or your company cash money.
  • Delicious
  • Twitter
  • Facebook
  • LinkedIn
  • Reddit
  • Slashdot
  • Technorati Favorites
  • Digg
  • Share/Bookmark

→ No CommentsTags: JavaScript · jQuery

Image Color Picker v0.1

August 8th, 2010 · No Comments

Today I’m releasing my first jQuery plugin :-)

Read more about it here: Image Color Picker or check out the demo.

You can find the code on Github.

  • Delicious
  • Twitter
  • Facebook
  • LinkedIn
  • Reddit
  • Slashdot
  • Technorati Favorites
  • Digg
  • Share/Bookmark

→ No CommentsTags: JavaScript · jQuery

HTML Canvas, getImageData and Browser Security

July 27th, 2010 · No Comments

Today I played a bit with Canvas and getImageData. What I tried to figure out was how to get the color of a certain pixel. The solution is easy to find via Google. The code looks somewhat like this:

var ctx = document.getElementById('canvas').getContext('2d');  
var img = new Image();  
img.onload = function(){  
  ctx.drawImage(img, 0, 0); 
  var objImageData = ctx.getImageData(0, 0, img.width, img.height)  
  alert("Pixel at (0,0): rgba("+objImageData.data[4]+", "+objImageData.data[5]+", "+objImageData.data[6]+","+objImageData.data[6]+")")
}  
img.src = 'test.jpg';

If you run this locally in Firefox. It will show the image, but it won’t show the popup. Instead, you’ll see this exception in the Firebug console:

Security error" code: "1000
var objImageData = ctx.getImageData(0, 0, img.width, img.height)

Here is why:

  • If the image is hosted on a different domain than the script, you can’t access image data without causing above security exception.
  • If you run this locally, you anyway will get this exception because, locally there’s no domain, so Firefox thinks for sure: different Domains >> Panic!
  • If you upload above code to some web server, image and HTML page with the Javascript code on the same domain, the code will work perfectly.
  • If you want to get the image data of an image which is not on the same domain, but e.g. on Amazon S3, you will end up with above security exception.

One way to handle the exception is to catch it, enable the appropriate browser permission and retry.

try {
  try { 
    var objImageData = ctx.getImageData(0, 0, img.width, img.height)  
  } catch (e) { 
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
    var objImageData = ctx.getImageData(0, 0, img.width, img.height) 
  } 						 
} catch (e) {
  throw new Error("unable to access image data: " + e)
} 
 
alert("Pixel an (0,0): rgba("+objImageData.data[4]+", "+objImageData.data[5]+", "+objImageData.data[6]+","+objImageData.data[6]+")");

Now, that works, at least in Firefox, but it is ugly, because the user will get a security warning and he has to decide whether to grant the script the requested additional permission.

The only “nice” way of getting the code to work, without browser specific try / catch statements and without security warnings is to host the images on the same domain as the script. Luckily Amazon S3 supports that through Virtual Hosting of Buckets.

If anyone knows about additional solutions for this, I’m happy to hear about it.

Most information I got from this article on Aaron’s blog.

  • Delicious
  • Twitter
  • Facebook
  • LinkedIn
  • Reddit
  • Slashdot
  • Technorati Favorites
  • Digg
  • Share/Bookmark

→ No CommentsTags: JavaScript