Vous êtes sur la page 1sur 123

appliness

TABLE OF CONTENTS

THE FIRST DIGITAL MAGAZINE FOR WEB APPLICATION DEVELOPERS


WELCOME TO APPLINESS. THE CONTRIBUTORS OF THIS FREE MAGAZINE ARE ALL PROFESSIONAL AND PASSIONATE DEVELOPERS. IF YOU WANT TO WRITE A TUTORIAL, SHOWCASE YOUR APPLICATION, CONTACT US ON OUR WEBSITE APPLINESS.COM. WE HOPE THAT YOU ENJOY READING THE 9TH ISSUE OF THIS MAGAZINE.

TUTORIALS

(
INTERVIEW TUTORIALS

JAVASCRIPT: FUNCTION INVOCATION PATTERNS


by Barry Steyn

WRITING FAST JAVASCRIPT


by Addy Osmani

WHY I CHOSE SASS


by Kianosh Pourian

COLLIE TUTORIALS
by Sangmin Shim

PLUGGING INTO SOCKET.IO: ADVANCED


by Joe Zimmerman

DYNAMICALLY LOADING A STYLE SHEET BASED ON WEATHER CONDITIONS


by Raymond Camden

JS ADOLESCENCE
by James Padosley

KEVIN LYNCH - CTO AT ADOBE


Exclusive interview by Maile Valentine & Michal Chaize

DESIGNING JAVASCRIPT APIS


by Brett van Zuiden

FUN WITH BUILT-IN CSS FILTERS


by CJ Gammon

GETTING STARTED WITH JAVASCRIPT MAPS


by Antanas Marcelionis

BUILDING YOUR FIRST BRACKETS EXTENSION


by David Deraedt

CLEARING FLOATS EVEN IN MODERN BROWSERS


by Louis Lazaris

MISSION IMPOSSIBLE: IPAD MINI DETECTION


by Maximiliano Firtman

EMBED PHONEGAP AS A SUBVIEW IN YOUR NATIVE IOS APPLICATION


by Holly Schinsky

RESPONSIVE MENU CONCEPTS


by Tim Pietrusky

JAVASCRIPT APIS YOUVE NEVER HEARD OF


by Nicholas C. Zakas

HELTER SKELTER NEWS

NEWS ABOUT HTML AND JAVASCRIPT


by Brian Rinaldi

NAVIGATION GUIDE READ

NAVIGATE
GO BACK TO THE LIBRARY MOVE TO THE PREVIOUS ARTICLE DISPLAY THE TABLE OF CONTENTS VISUALLY BROWSE ALL THE ARTICLES

MOVE TO THE NEXT ARTICLE BY A HORIZONTAL SWIPE

READ THROUGH THE ARTICLE BY A VERTICAL SWIPE

appliness

DONT WORRY, BE APPLI

JAVASCRIPT: FUNCTION INVOCATION PATTERNS

CHECK OUT THESE COOL TOOLS FOR CREATING INTERACTIVE MAPS USING SVG TO RENDER MAPS.

JavaScript has been described as a Functional Oriented Language (this as opposed to Object Oriented Language). The reason is because functions in JavaScript do more than just separate logic into execution units, functions are first class citizens that also provide scope and the ability to create objects. Having such a heavy reliance upon functions is both a blessing and a curse: Its a blessing because it makes the language light weight and fast (the main goal of its original development), but it is a curse because you can very easily shoot yourself in the foot if you dont know what you are doing. One concern with JavaScript functions is how different invocation patterns can produce vastly different results. This post explains the four patterns, how to use them and what to watch out for. The four invocation patterns are: 1. Method Invocation 2. Function Invocation 3. Constructor Invocation 4. Apply And Call Invocation

FUNCTION EXECUTION
JavaScript (like all languages these days) has the ability to modularise logic in functions which can be invoked at any point within the execution. Invoking a function suspends execution of the current function, passing controls

by Barry Steyn

and parameters to the invoked function. In addition, a parameter called this is also passed to the function. The invocation operator is a pair of round brackets (), that can contain zero or more expressions separated by a comma. Unfortunately, there is more than one pattern that can be used to invoke functions. These patterns are not nice-to-know: They are absolutely essential to know. This is because invoking a function with a different pattern can produce a vastly different result. I believe that this is a language design error in JavaScript, and had the language been designed with more thought (and less haste), this would not have been such a big issue.

THE FOUR INVOCATION PATTERNS


Even though there are is only one invocation operator (), there are four invocation patterns. Each pattern differs in how the this parameter is initialised. METHOD INVOCATION When a function is part of an object, it is called a method. Method invocation is the pattern of invoking a function that is part of an object. For example: var obj = { value: 0, increment: function() { this.value+=1; } }; obj.increment(); //Method invocation Method invocation is identified when a function is preceded by object., where object is the name of some object. JavaScript will set the this parameter to the object where the method was invoked on. In the example above, this would be set to obj. JavaScript binds this at execution (also known as late binding). FUNCTION INVOCATION Function invocation is performed by invoking a function using (): add(2,3); //5 When using the function invocation pattern, this is set to the global object. This was a mistake in the JavaScript language! Blindly binding this to the global object can destroy its current context. It is noticable when using an inner function within a method function. An example should explain things better: var value = 500; //Global variable var obj = { value: 0, increment: function() { this.value++; var innerFunction = function() { alert(this.value); } innerFunction(); //Function invocation pattern
2/5

} obj.increment(); //Method invocation pattern What do you think will be printed to screen? For those that answered 1, you are wrong (but dont be too hard on yourselves, this is because JavaScript does not do things very well). The real answer is 500. Note that innerFunction is called using the function invocation pattern, therefore this is set to the global object. The result is that innerFunction (again, it is important to note that it is invoked with function pattern) will not have this set to current object. Instead, it is set to the global object, where value is defined as 500. I stress that this is bad language design; the increment function was invoked with the method invocation pattern, and so it is natural to assume the this should always point to the current function when used inside it. There is an easy way to get round this problem, but it is in my opinion a hack. One gets around this problem by assigning a variable (by convention, it is named that) to this inside the function (aside: This works because functions in JavaScript are closures): var value = 500; //Global variable var obj = { value: 0, increment: function() { var that = this; that.value++; var innerFunction = function() { alert(that.value); } } innerFunction(); //Function invocation pattern

} obj.increment(); If this could be bound to the current object whose scope it is called in, function and method invocations would be identical.

CONSTRUCTOR INVOCATION
Warning: This is another JavaScript peculiarity! JavaScript is not a classical object oriented language. Instead, it is a prototypical object oriented language, but the creators of JavaScript felt that people with classical object orientation experience (the vast majority) may be unhappy with a purely prototype aproach. This resulted in JavaScript being unsure of its prototypical nature and the worst thing happened: It mixed classical object orientation syntax with its prototypical nature. The result: A mess! In classial object orientation, an object is an instantiation of a class. In C++ and Java, this instantiation is performed by using the new operator. This seems to be the inspiration behind the constructor invocation pattern... The constructor invocation pattern involves putting the new operator just before the function is invoked. For example:
3/5

var Cheese = function(type) { var cheeseType = type;

return cheeseType;

cheddar = new Cheese(cheddar); //new object returned, not the type. Even though Cheese is a function object (and intuitively, one thinks of functions as running modularised pieces of code), we have created a new object by invoking the function with new in front of it. The this parameter will be set to the newly created object and the return operator of the function will have its behaviour altered. Regarding the behaviour of the return operator in constructor invocation, there are two cases: 1. If the function returns a simple type (number, string, boolean, null or undefined), the return will be ignored and instead this will be returned (which is set to the new object). 2. If the function returns an instance of Object (anything other than a simple type), then that object will be returned instead of returning this. This pattern is not used that often, but it can be very useful when combined with closures (see here for a great example). For example: var obj = { data : Hello World } var Func1 = function() { return obj; } var Func2 = function() { return I am a simple type; } var f1 = new Func1(); //f1 is set to obj var f2 = new Func2(); //f2 is set to a new object We might ignore this, and just use object literals to make objects, except that the makers of JavaScript have enabled a key feature of their language by using this pattern: Object creation with an arbitrary prototype link (see previous post for more details). This pattern is unintuitive and also potentially problematic. There is a remedy which was championed by Douglas Crockford: Augment Object with a create method that accomplishes what the constructor invocation pattern tries to do. I am happy to note that as of JavaScript 1.8.5, Object.create is a reality and can be used. Due to legacy, the constructor invocation is still used often, and for backward compatability, will crop up quite frequently.

APPLY AND CALL INVOCATION


The apply pattern is not as badly thought out as the preceding patterns. The apply method allows manual invocation of a function with a means to pass the function an array of parameters and explicitly set the this parameter. Because functions are first class citizens, they are also objects and hence can have methods (functions) run on it. In fact, every function is linked to Function.prototype (see here for more details), and so methods can very easily be augmented to any function. The apply method is just an augmentation to every function as - I presume - it is defined on Function.prototype.
4/5

Apply takes two parameters: the first parameter is an object to bind the this parameter to, the second is an array which is mapped to the parameters: var add = function(num1, num2) { return num1+num2; } array = [3,4]; add.apply(null,array); //7 In the example above, this is bound to null (the function is not an object, so it is not needed) and array is bound to num1 and num2. More interesting things can be done with the first parameter: var obj = { data:Hello World } var displayData = function() { alert(this.data); } displayData(); //undefined displayData.apply(obj); //Hello World The example above uses apply to bind this to obj. This results in being able to produce a value for this.data. Being able to expicitly assign a value to this is where the real value of apply comes about. Without this feature, we might as well use () to invoke functions. JavaScript also has another invoker called call, that is identical to apply except that instead of taking an array of parameters, it takes an argument list. If JavaScript would implement function overriding, I think that call would be an overridden variant of apply. Therefore one talks about apply and call in the same vein.

CONCLUSION
For better or worse, JavaScript is about to take over the world. It is therefore very important that the peculiarities of the language be known and avoided. Learning how the four function invocation methods differ and how to avoid their pitfalls is fundamental to anyone who wants to use JavaScript. I hope this post has helped people when it comes to invoking functions.

ABOUT THIS ARTICLE


Barry Steyn is an entrepreneur in the tech space. His formal education is in Math and Computer Science, but all he has ever wanted to do since he can remember is build things. Not anything mind you, but things that matter, that positively affect people. Thats why he is so attracted to computer science: he loves building programs. He also loves the building process that is inherent with entrepreneurism.

ONLINE RESOURCES JavaScript: Why Understanding Scope and Closures Matter http://doctrina.org/JavaScript:Why-Understanding-Scope-And-Closures-Matter.html JavaScript: Object Prototypes http://doctrina.org/Javascript-Objects-Prototypes.html JavaScript: Why Understanding Scope and Closures Matter
http://doctrina.org/JavaScript:Why-Understanding-Scope-And-Closures-Matter. html

http://doctrina.org/
@barrysteyn

appliness

DONT WORRY, BE APPLI

WRITING FAST, MEMORY-EFFICIENT JAVASCRIPT - PART 1

JAVASCRIPT ENGINES SUCH AS GOOGLES V8 (CHROME, NODE) ARE SPECIFICALLY DESIGNED FOR THE FAST EXECUTION OF LARGE JAVASCRIPT APPLICATIONS. AS YOU DEVELOP, IF YOU CARE ABOUT MEMORY USAGE AND PERFORMANCE, YOU SHOULD BE AWARE OF SOME OF WHATS GOING ON IN YOUR USERS BROWSERS JAVASCRIPT ENGINE BEHIND THE SCENES.

PERFORM
Whether its V8, SpiderMonkey (Firefox), Carakan (Opera), Chakra (IE) or something else, doing so can help you better optimize your applications. Thats not to say one should optimize for a single browser or engine. Never do that. You should, however, ask yourself questions such as: - Is there anything I could be doing more efficiently in my code? - What (common) optimizations do popular JavaScript engines make? - What is the engine unable to optimize for, and is the garbage collector able to clean up what Im expecting it to? There are many common pitfalls when it comes to writing memory-efficient and fast code, and in this article were going to explore some test-proven approaches for writing code that performs better.

by Addy Osmani

SO, HOW DOES JAVASCRIPT WORK IN V8?


While its possible to develop large-scale applications without a thorough understanding of JavaScript engines, any car owner will tell you theyve looked under the hood at least once. As Chrome is my browser of choice, Im going to talk a little about its JavaScript engine. V8 is made up of a few core pieces. - A base compiler, which parses your JavaScript and generates native machine code before it is executed, rather than executing bytecode or simply interpreting it. This code is initially not highly optimized. - V8 represents your objects in an object model. Objects are represented as associative arrays in JavaScript, but in V8 they are represented with hidden classes, which are an internal type system for optimized lookups. - The runtime profiler monitors the system being run and identifies hot functions (i.e., code that ends up spending a long time running). - An optimizing compiler recompiles and optimizes the hot code identified by the runtime profiler, and performs optimizations such as inlining (i.e., replacing a function call site with the body of the callee). - V8 supports deoptimization, meaning the optimizing compiler can bail out of code generated if it discovers that some of the assumptions it made about the optimized code were too optimistic. - It has a garbage collector. Understanding how it works can be just as important as the optimized JavaScript.

GARBAGE COLLECTION
Garbage collection is a form of memory management. Its where we have the notion of a collector which attempts to reclaim memory occupied by objects that are no longer being used. In a garbage-collected language such as JavaScript, objects that are still referenced by your application are not cleaned up. Manually de-referencing objects is not necessary in most cases. By simply putting the variables where they need to be (ideally, as local as possible, i.e., inside the function where they are used versus an outer scope), things should just work. Its not possible to force garbage collection in JavaScript. You wouldnt want to do this, because the garbage collection process is controlled by the runtime, and it generally knows best when things should be cleaned up. DE-REFERENCING MISCONCEPTIONS In quite a few discussions online about reclaiming memory in JavaScript, the delete keyword is brought up, as although it was supposed to be used for just removing keys from a map, some developers think you can force de-referencing using it. Avoid using delete if you can. In the below example, delete o.x does a lot more harm than good behind the scenes, as it changes os hidden class and makes it a generic slow object. var o = { x: 1 }; delete o.x; // true o.x; // undefined That said, you are almost certain to find references to delete in many popular JavaScript libraries it does have a purpose in the language. The main takeaway here is to avoid modifying the structure of hot objects at runtime. JavaScript engines can detect such hot objects and attempt to optimize them. This is easier

2/13

if the objects structure doesnt heavily change over its lifetime and delete can trigger such changes. There are also misconceptions about how null works. Setting an object reference to null doesnt null the object. It sets the object reference to null. Using o.x = null is better than using delete, but its probably not even necessary. var o = { x: 1 }; o = null; o; // null o.x // TypeError If this reference was the last reference to the object, the object is then eligible for garbage collection. If the reference was not the last reference to the object, the object is reachable and will not be garbage collected. Another important note to be aware of is that global variables are not cleaned up by the garbage collector during the life of your page. Regardless of how long the page is open, variables scoped to the JavaScript runtime global object will stick around. var myGlobalNamespace = {}; Globals are cleaned up when you refresh the page, navigate to a different page, close tabs or exit your browser. Function-scoped variables get cleaned up when a variable falls out of scope. When functions have exited and there arent any more references to it, the variable gets cleaned up. RULES OF THUMB To give the garbage collector a chance to collect as many objects as possible as early as possible, dont hold on to objects you no longer need. This mostly happens automatically; here are a few things to keep in mind. - As mentioned earlier, a better alternative to manual de-referencing is to use variables with an appropriate scope. I.e., instead of a global variable thats nulled out, just use a function-local variable that goes out of scope when its no longer needed. This means cleaner code with less to worry about. - Ensure that youre unbinding event listeners where they are no longer required, especially when the DOM objects theyre bound to are about to be removed. - If youre using a data cache locally, make sure to clean that cache or use an aging mechanism to avoid large chunks of data being stored that youre unlikely to reuse. FUNCTIONS Next, lets look at functions. As weve already said, garbage collection works by reclaiming blocks of memory (objects) which are no longer reachable. To better illustrate this, here are some examples. function foo() { var bar = new LargeObject(); bar.someCall(); } When foo returns, the object which bar points to is automatically available for garbage collection, because there is nothing left that has a reference to it. Compare this to:
3/13

function foo() { var bar = new LargeObject(); bar.someCall(); return bar; } // somewhere else var b = foo(); We now have a reference to the object which survives the call and persists until the caller assigns something else to b (or b goes out of scope). CLOSURES When you see a function that returns an inner function, that inner function will have access to the outer scope even after the outer function is executed. This is basically a closure an expression which can work with variables set within a specific context. For example: function sum (x) { function sumIt(y) { return x + y; }; return sumIt; } // Usage var sumA = sum(4); var sumB = sumA(3); console.log(sumB); // Returns 7 The function object created within the execution context of the call to sum cant be garbage collected, as its referenced by a global variable and is still very much accessible. It can still be executed via sumA(n). Lets look at another example. Here, can we access largeStr? var a = function () { var largeStr = new Array(1000000).join(x); return function () { return largeStr; }; }(); Yes, we can, via a(), so its not collected. How about this one? var a = function () { var smallStr = x; var largeStr = new Array(1000000).join(x); return function (n) { return smallStr; }; }(); We cant access it anymore and its a candidate for garbage collection.
4/13

TIMERS One of the worst places to leak is in a loop, or in setTimeout()/setInterval(), but this is quite common. Consider the following example. var myObj = { callMeMaybe: function () { var myRef = this; var val = setTimeout(function () { console.log(Time is running out!); myRef.callMeMaybe(); }, 1000); } }; If we then run: myObj.callMeMaybe(); to begin the timer, we can see every second Time is running out! If we then run: myObj = null; The timer will still fire. myObj wont be garbage collected as the closure passed to setTimeout has to be kept alive in order to be executed. In turn, it holds references to myObj as it captures myRef. This would be the same if wed passed the closure to any other function, keeping references to it. It is also worth keeping in mind that references inside a setTimeout/setInterval call, such as functions, will need to execute and complete before they can be garbage collected.

BE AWARE OF PERFORMANCE TRAPS


Its important never to optimize code until you actually need to. This cant be stressed enough. Its easy to see a number of micro-benchmarks showing that N is more optimal than M in V8, but test it in a real module of code or in an actual application, and the true impact of those optimizations may be much more minimal than you were expecting. Lets say we want to create a module which: - Takes a local source of data containing items with a numeric ID, - Draws a table containing this data, - Adds event handlers for toggling a class when a user clicks on any cell. There are a few different factors to this problem, even though its quite straightforward to solve. How do we store the data? How do we efficiently draw the table and append it to the DOM? How do we handle events on this table optimally? A first (naive) take on this problem might be to store each piece of available data in an object which we group into an array. One might use jQuery to iterate through the data and draw the table, then append it to the DOM. Finally, one might use event binding for adding the click behavior we desire.
5/13

NOTE: THIS IS NOT WHAT YOU SHOULD BE DOING var moduleA = function () { return { data: dataArrayObject, init: function () { this.addTable(); this.addEvents(); }, addTable: function () { for (var i = 0; i < rows; i++) { $tr = $(<tr></tr>); for (var j = 0; j < this.data.length; j++) { $tr.append(<td> + this.data[j][id] + </td>); } $tr.appendTo($tbody); } }, addEvents: function () { $(table td).on(click, function () { $(this).toggleClass(active); }); } }(); };

Simple, but it gets the job done. In this case however, the only data were iterating are IDs, a numeric property which could be more simply represented in a standard array. Interestingly, directly using DocumentFragment and native DOM methods are more optimal than using jQuery (in this manner) for our table generation, and of course, event delegation is typically more performant than binding each td individually. Note that jQuery does use DocumentFragment internally behind the scenes, but in our example, the code is calling append() within a loop and each of these calls has little knowledge of the other so it may not be able to optimize for this example. This should hopefully not be a pain point, but be sure to benchmark your own code to be sure. In our case, adding in these changes results in some good (expected) performance gains. Event delegation provides decent improvement over simply binding, and opting for documentFragment was a real booster. var moduleD = function () { return {
6/13

data: dataArray,

init: function () { this.addTable(); this.addEvents(); }, addTable: function () { var td, tr; var frag = document.createDocumentFragment(); var frag2 = document.createDocumentFragment(); for (var i = 0; i < rows; i++) { tr = document.createElement(tr); for (var j = 0; j < this.data.length; j++) { td = document.createElement(td); td.appendChild(document.createTextNode(this.data[j])); } tr.appendChild(frag2); frag.appendChild(tr); frag2.appendChild(td);

}, addEvents: function () { $(table).on(click, td, function () { $(this).toggleClass(active); }); } }; }(); We might then look to other ways of improving performance. You may have read somewhere that using the prototypal pattern is more optimal than the module pattern (we confirmed it wasnt earlier), or heard that using JavaScript templating frameworks are highly optimized. Sometimes they are, but use them because they make for readable code. Also, precompile! Lets test and find out how true this hold in practice. moduleG = function () {}; moduleG.prototype.data = dataArray; moduleG.prototype.init = function () { this.addTable(); this.addEvents(); }; moduleG.prototype.addTable = function () { var template = _.template($(#template).text()); var html = template({data : this.data}); $tbody.append(html); }; moduleG.prototype.addEvents = function () { $(table).on(click, td, function () { $(this).toggleClass(active); }); };

} tbody.appendChild(frag);

7/13

var modG = new moduleG(); As it turns out, in this case the performance benefits are negligible. Opting for templating and prototypes didnt really offer anything more than what we had before. That said, performance isnt really the reason modern developers use either of these things its the readability, inheritance model and maintainability they bring to your codebase. More complex problems include efficiently drawing images using canvas and manipulating pixel data with or without typed arrays Always give micro-benchmarks a close lookover before exploring their use in your application. Some of you may recall the JavaScript templating shoot-off and the extended shoot-off that followed. You want to make sure that tests arent being impacted by constraints youre unlikely to see in real world applications test optimizations together in actual code.

V8 OPTIMIZATION TIPS
Whilst detailing every V8 optimization is outside the scope of this article, there are certainly many tips worth noting. Keep these in mind and youll reduce your chances of writing unperformant code. Certain patterns will cause V8 to bail out of optimizations. A try-catch, for example, will cause such a bailout. For more information on what functions can and cant be optimized, you can use --trace-opt file. js with the d8 shell utility that comes with V8. If you care about speed, try very hard to keep your functions monomorphic, i.e., make sure that variables (including properties, arrays and function parameters) only ever contain objects with the same hidden class. For example, dont do this: function add(x, y) { return x+y; } add(1, 2); add(a,b); add(my_custom_object, undefined); Dont load from uninitialized or deleted elements. This wont make a difference in output, but it will make things slower. Dont write enormous functions, as they are more difficult to optimize For more tips, watch Daniel Cliffords Google I/O talk Breaking the JavaScript Speed Limit with V8 as it covers these topics well. Optimizing For V8 A Series is also worth a read.

OBJECTS VS. ARRAYS: WHICH SHOULD I USE?


- If you want to store a bunch of numbers, or a list of objects of the same type, use an array. - If what you semantically need is an object with a bunch of properties (of varying types), use an object with properties. Thats pretty efficient in terms of memory, and its also pretty fast.
8/13

- Integer-indexed elements, regardless of whether theyre stored in an array or an object, are much faster to iterate over than object properties. - Properties on objects are quite complex: they can be created with setters, and with differing enumerability and writability. Items in arrays arent able to be customized as heavily they either exist or they dont. At an engine level, this allows for more optimization in terms of organizing the memory representing the structure. This is particularly beneficial when the array contains numbers. For example, when you need vectors, dont define a class with properties x, y, z; use an array instead. Theres really only one major difference between objects and arrays in JavaScript, and thats the arrays magic length property. If youre keeping track of this property yourself, objects in V8 should be just as fast as arrays.

TIPS WHEN USING OBJECTS


Create objects using a constructor function. This ensures that all objects created with it have the same hidden class and helps avoid changing these classes. As an added benefit, its also slightly faster than Object.create(). There are no restrictions on the number of different object types you can use in your application or on their complexity (within reason: long prototype chains tend to hurt, and objects with only a handful of properties get a special representation thats a bit faster than bigger objects). For hot objects, try to keep the prototype chains short and the field count low. OBJECT CLONING Object cloning is a common problem for app developers. While its possible to benchmark how well various implementations work with this type of problem in V8, be very careful when copying anything. Copying big things is generally slow dont do it. for..in loops in JavaScript are particularly bad for this, as they have a devilish specification and will likely never be fast in any engine for arbitrary objects. When you absolutely do need to copy objects in a performance-critical code path (and you cant get out of this situation), use an array or a custom copy constructor function which copies each property explicitly. This is probably the fastest way to do it: function clone(original) { this.foo = original.foo; this.bar = original.bar; } var copy = new clone(original); CACHED FUNCTIONS IN THE MODULE PATTERN Caching your functions when using the module pattern can lead to performance improvements. See below for an example where the variation youre probably used to seeing is slower as it forces new copies of the member functions to be created all the time. Also note that using this approach can be significantly more optimal than just relying on the prototypal pattern (as confirmed by the jsPerf test).

9/13

Here is a test of prototype versus module pattern performance // Prototypal pattern Klass1 = function () {} Klass1.prototype.foo = function () { log(foo); } Klass1.prototype.bar = function () { log(bar); } // Module pattern Klass2 = function () { var foo = function () { log(foo); }, bar = function () { log(bar); }; return { foo: foo, bar: bar }

10/13

// Module pattern with cached functions var FooFunction = function () { log(foo); }; var BarFunction = function () { log(bar); };

Klass3 = function () { return { foo: FooFunction, bar: BarFunction } } // Iteration tests // Prototypal var i = 1000, objs = []; while (i--) { var o = new Klass1() objs.push(new Klass1()); o.bar; o.foo; } // Module pattern var i = 1000, objs = []; while (i--) { var o = Klass2() objs.push(Klass2()); o.bar; o.foo; } // Module pattern with cached functions var i = 1000, objs = []; while (i--) { var o = Klass3() objs.push(Klass3()); o.bar; o.foo; } // See the test for full details

TIPS WHEN USING ARRAYS


Next lets look at a few tips for arrays. In general, dont delete array elements. It would make the array transition to a slower internal representation. When the key set becomes sparse, V8 will eventually switch elements to dictionary mode, which is even slower. ARRAY LITERALS Array literals are useful because they give a hint to the VM about the size and type of the array. Theyre typically good for small to medium sized arrays.
11/13

// Here V8 can see that you want a 4-element array containing numbers: var a = [1, 2, 3, 4]; // Dont do this: a = []; // Here V8 knows nothing about the array for(var i = 1; i <= 4; i++) { a.push(i); } STORAGE OF SINGLE TYPES VS. MIXED TYPES Its never a good idea to mix values of different types (e.g., numbers, strings, undefined or true/false) in the same array (i.e., var arr = [1, 1, undefined, true, true]) Test of type inference performance As we can see from the results, the array of ints is the fastest. SPARSE ARRAYS VS. FULL ARRAYS When you use sparse arrays, be aware that accessing elements in them is much slower than in full arrays. Thats because V8 doesnt allocate a flat backing store for the elements if only a few of them are used. Instead, it manages them in a dictionary, which saves space, but costs time on access. Test of sparse arrays versus full arrays. The full array sum and sum of all elements on an array without zeros were actually the fastest. Whether the full array contains zeroes or not should not make a difference. PACKED VS. HOLEY ARRAYS Avoid holes in an array (created by deleting elements or a[x] = foo with x > a.length). Even if only a single element is deleted from an otherwise full array, things will be much slower. Test of packed versus holey arrays. PRE-ALLOCATING ARRAYS VS. GROWING AS YOU GO Dont pre-allocate large arrays (i.e., greater than 64K elements) to their maximum size, instead grow as you go. Before we get to the performance tests for this tip, keep in mind that this is specific to only some JavaScript engines.

12/13

Nitro (Safari) actually treats pre-allocated arrays more favorably. However, in other engines (V8, SpiderMonkey), not pre-allocating is more efficient.

Test of pre-allocated arrays. // Empty array var arr = []; for (var i = 0; i < 1000000; i++) { arr[i] = i; } // Pre-allocated array var arr = new Array(1000000); for (var i = 0; i < 1000000; i++) { arr[i] = i; }

ABOUT THIS ARTICLE


Addy Osmani is a Developer Programs Engineer on the Chrome team at Google. A passionate JavaScript developer, he has written open-source books like Learning JavaScript Design Patterns and Developing Backbone Applications, having also contributed to open-source projects like Modernizr and jQuery. He is currently working on Yeoman - an opinionated workflow for building beautiful applications.

MORE ARTICLES FROM...

http://addyosmani.com/blog/

http://www.smashingmagazine.com/

@addyosmani

appliness

DONT WORRY, BE APPLI

WRITING FAST, MEMORY-EFFICIENT JAVASCRIPT - PART 2

JAVASCRIPT ENGINES SUCH AS GOOGLES V8 (CHROME, NODE) ARE SPECIFICALLY DESIGNED FOR THE FAST EXECUTION OF LARGE JAVASCRIPT APPLICATIONS. AS YOU DEVELOP, IF YOU CARE ABOUT MEMORY USAGE AND PERFORMANCE, YOU SHOULD BE AWARE OF SOME OF WHATS GOING ON IN YOUR USERS BROWSERS JAVASCRIPT ENGINE BEHIND THE SCENES.

OPTIMIZING YOUR APPLICATION


In the world of Web applications, speed is everything. No user wants a spreadsheet application to take seconds to sum up an entire column or a summary of their messages to take a minute before its ready. This is why squeezing every drop of extra performance you can out of code can sometimes be critical. While understanding and improving your application performance is useful, it can also be difficult. We recommend the following steps to fix performance pain points: - Measure it: Find the slow spots in your application (~45%) - Understand it: Find out what the actual problem is (~45%) - Fix it! (~10%) Some of the tools and techniques recommended below can assist with this process. BENCHMARKING There are many ways to run benchmarks on JavaScript snippets to test their performance the general assumption being that benchmarking is simply comparing two timestamps. One such pattern was pointed out by the jsPerf

by Addy Osmani

team, and happens to be used in SunSpiders and Krakens benchmark suites: var totalTime, start = new Date, iterations = 1000; while (iterations--) { // Code snippet goes here } // totalTime the number of milliseconds taken // to execute the code snippet 1000 times totalTime = new Date - start; Here, the code to be tested is placed within a loop and run a set number of times (e.g., six). After this, the start date is subtracted from the end date to find the time taken to perform the operations in the loop. However, this oversimplifies how benchmarking should be done, especially if you want to run the benchmarks in multiple browsers and environments. Garbage collection itself can have an impact on your results. Even if youre using a solution like window.performance, you still have to account for these pitfalls. Regardless of whether you are simply running benchmarks against parts of your code, writing a test suite or coding a benchmarking library, theres a lot more to JavaScript benchmarking than you might think. For a more detailed guide to benchmarking, I highly recommend reading JavaScript Benchmarking by Mathias Bynens and John-David Dalton. PROFILING The Chrome Developer Tools have good support for JavaScript profiling. You can use this feature to detect what functions are eating up the most of your time so that you can then go optimize them. This is important, as even small changes to your codebase can have serious impacts on your overall performance.

Profiling starts with obtaining a baseline for your codes current performance, which can be discovered using the Timeline. This will tell us how long our code took to run. The Profiles tab then gives us a better view into whats happening in our application. The JavaScript CPU profile shows us how much CPU time is being used by our code, the CSS selector profile shows us how much time is spent processing selectors and Heap snapshots show how much memory is being used by our objects. Using these tools, we can isolate, tweak and reprofile to gauge whether changes were making to specific functions or operations are improving performance.

2/7

For a good introduction to profiling, read JavaScript Profiling With The Chrome Developer Tools, by Zack Grossbart. Tip: Ideally, you want to ensure that your profiling isnt being affected by extensions or applications youve installed, so run Chrome using the --user-data-dir <empty_directory> flag. Most of the time, this approach to optimization testing should be enough, but there are times when you need more. This is where V8 flags can be of help. AVOIDING MEMORY LEAKS THREE SNAPSHOT TECHNIQUES FOR DISCOVERY Internally at Google, the Chrome Developer Tools are heavily used by teams such as Gmail to help us discover and squash memory leaks.

Some of the memory statistics that our teams care about include private memory usage, JavaScript heap size, DOM node counts, storage clearing, event listener counts and whats going on with garbage collection. For those familiar with event-driven architectures, you might be interested to know that one of the most common issues we used to have were listen()s without unlisten()s (Closure) and missing dispose()s for objects that create event listeners. Luckily the DevTools can help locate some of these issues, and Loreena Lee has a fantastic presentation available documenting the 3 snapshot technique for finding leaks within the DevTools that I cant recommend reading through enough. The gist of the technique is that you record a number of actions in your application, force a garbage collection, check if the number of DOM nodes doesnt return to your expected baseline and then analyze three heap snapshots to determine if you have a leak. MEMORY MANAGEMENT IN SINGLE-PAGE APPLICATIONS Memory management is quite important when writing modern single-page applications (e.g., AngularJS, Backbone, Ember) as they almost never get refreshed. This means that memory leaks can become apparent quite quickly. This is a huge trap on mobile single-page applications, because of limited memory, and on long-running applications like email clients or social networking applications. With great power comes great responsibility. There are various ways to prevent this. In Backbone, ensure you always dispose old views and references
3/7

using dispose() (currently available in Backbone (edge)). This function was recently added, and removes any handlers added in the views events object, as well as any collection or model listeners where the view is passed as the third argument (callback context). dispose() is also called by the views remove(), taking care of the majority of basic memory cleanup needs when the element is cleared from the screen. Other libraries like Ember clean up observers when they detect that elements have been removed from view to avoid memory leaks. Some sage advice from Derick Bailey:

Other than being aware of how events work in terms of references, just follow the standard rules for manage memory in JavaScript and youll be fine. If you are loading data in to a Backbone collection full of User objects you want that collection to be cleaned up so its not using anymore memory, you must remove all references to the collection and the individual objects in it. Once you remove all references, things will be cleaned up. This is just the standard JavaScript garbage collection rule. In his article, Derick covers many of the common memory pitfalls when working with Backbone.js and how to fix them. There is also a helpful tutorial available for debugging memory leaks in Node by Felix Geisendrfer worth reading, especially if it forms a part of your broader SPA stack.
MINIMIZING REFLOWS When a browser has to recalculate the positions and geometrics of elements in a document for the purpose of re-rendering it, we call this reflow. Reflow is a user-blocking operation in the browser, so its helpful to understand how to improve reflow time.

You should batch methods that trigger reflow or that repaint, and use them sparingly. Its important to process off DOM where possible. This is possible using DocumentFragment, a lightweight document object. Think of it as a way to extract a portion of a documents tree, or create a new fragment of a document. Rather than constantly adding to the DOM using nodes, we can use document fragments to build up all we need and only perform a single insert into the DOM to avoid excessive reflow. For example, lets write a function that adds 20 divs to an element. Simply appending each new div directly to the element could trigger 20 reflows. function addDivs(element) { var div; for (var i = 0; i < 20; i ++) { div = document.createElement(div); div.innerHTML = Heya!; element.appendChild(div); } }

4/7

To work around this issue, we can use DocumentFragment, and instead, append each of our new divs to this. When appending to the DocumentFragment with a method like appendChild, all of the fragments children are appended to the element triggering only one reflow. function addDivs(element) { var div; // Creates a new empty DocumentFragment. var fragment = document.createDocumentFragment(); for (var i = 0; i < 20; i ++) { div = document.createElement(a); div.innerHTML = Heya!; fragment.appendChild(div); } element.appendChild(fragment); } You can read more about this topic at Make the Web Faster, JavaScript Memory Optimization and Finding Memory Leaks. JAVASCRIPT MEMORY LEAK DETECTOR To help discover JavaScript memory leaks, two of my fellow Googlers (Marja Hltt and Jochen Eisinger) developed a tool that works with the Chrome Developer Tools (specifically, the remote inspection protocol), and retrieves heap snapshots and detects what objects are causing leaks.

Theres a whole post on how to use the tool, and I encourage you to check it out or view the Leak Finder project page. Some more information: In case youre wondering why a tool like this isnt already integrated with our Developer Tools, the reason is twofold. It was originally developed to help us catch some specific memory scenarios in the Closure Library, and it makes more sense as an external tool (or maybe even an extension if we get a heap profiling extension API in place). V8 FLAGS FOR DEBUGGING OPTIMIZATIONS & GARBAGE COLLECTION Chrome supports passing a number of flags directly to V8 via the js-flags flag to get more detailed output about what the engine is optimizing. For example, this traces V8 optimizations: /Applications/Google Chrome/Google Chrome --js-flags=--trace-opt --trace-deopt Windows users will want to run chrome.exe --js-flags=--trace-opt --trace-deopt
5/7

When developing your application, the following V8 flags can be used.

- trace-opt log names of optimized functions and show where the optimizer is skipping code because it cant figure something out. - trace-deopt log a list of code it had to deoptimize while running. - trace-gc logs a tracing line on each garbage collection. V8s tick-processing scripts mark optimized functions with an * (asterisk) and non-optimized functions with ~ (tilde). If youre interested in learning more about V8s flags and how V8s internals work in general, I strongly recommend looking through Vyacheslav Egorovs excellent post on V8 internals, which summarizes the best resources available on this at the moment. HIGH-RESOLUTION TIME AND NAVIGATION TIMING API High Resolution Time (HRT) is a JavaScript interface providing the current time in sub-millisecond resolution that isnt subject to system clock skews or user adjustments. Think of it as a way to measure more precisely than weve previously had with new Date and Date.now(). This is helpful when were writing performance benchmarks.

HRT is currently available in Chrome (stable) as window.performance.webkitNow(), but the prefix is dropped in Chrome Canary, making it available via window.performance.now(). Paul Irish has written more about HRT in a post on HTML5Rocks. So, we now know the current time, but what if we wanted an API for accurately measuring performance on the web? Well, one is now also available in the Navigation Timing API. This API provides a simple way to get accurate and detailed time measurements that are recorded while a webpage is loaded and presented to the user. Timing information is exposed via window.performance.timing, which you can simply use in the console:

Looking at the data above, we can extract some very useful information. For example, network latency is responseEnd-fetchStart, the time taken for a page load once its been received from the server is loadEventEnd-responseEnd and the time taken to process between navigation and page load is loadEventEnd-navigationStart. As you can see above, a perfomance.memory property is also available that gives access to JavaScript memory usage data such as the total heap size.
6/7

For more details on the Navigation Timing API, read Sam Duttons great article Measuring Page Load Speed With Navigation Timing.

ABOUT:MEMORY AND ABOUT:TRACING about:tracing in Chrome offers an intimate view of the browsers performance, recording all of Chromes activities across every thread, tab and process.

Whats really useful about this tool is that it allows you to capture profiling data about what Chrome is doing under the hood, so you can properly adjust your JavaScript execution, or optimize your asset loading. Lilli Thompson has an excellent write-up for games developers on using about:tracing to profile WebGL games. The write-up is also useful for general JavaScripters. Navigating to about:memory in Chrome is also useful as it shows the exact amount of memory being used by each tab, which is helpful for tracking down potential leaks.

CONCLUSION
As weve seen, there are many hidden performance gotchas in the world of JavaScript engines, and no silver bullet available to improve performance. Its only when you combine a number of optimizations in a (real-world) testing environment that you can realize the largest performance gains. But even then, understanding how engines interpret and optimize your code can give you insights to help tweak your applications. Measure It. Understand it. Fix it. Rinse and repeat. Remember to care about optimization, but stop short of opting for micro-optimization at the cost of convenience. For example, some developers opt for .forEach and Object.keys over for and for in loops, even though theyre slower, for the convenience of being able to scope. Do make sanity calls on what optimizations your application absolutely needs and which ones it could live without. Also, be aware that although JavaScript engines continue to get faster, the next real bottleneck is the DOM. Reflows and repaints are just as important to minimize, so remember to only touch the DOM if its absolutely required. And do care about networking. HTTP requests are precious, especially on mobile, and you should be using HTTP caching to reduce the size of assets. Keeping all of these in mind will ensure that you get the most out of the information from this post. I hope you found it helpful!

ABOUT THIS ARTICLE


Addy Osmani is a Developer Programs Engineer on the Chrome team at Google. A passionate JavaScript developer, he has written open-source books like Learning JavaScript Design Patterns and Developing Backbone Applications, having also contributed to open-source projects like Modernizr and jQuery. He is currently working on Yeoman - an opinionated workflow for building beautiful applications.

MORE ARTICLES FROM...

http://addyosmani.com/blog/

http://www.smashingmagazine.com/

@addyosmani

appliness

DONT WORRY, BE APPLI

WHY I CHOSE SASS

KIANOSH DESCRIBES HIS HISTORY WITH SASS AND DIVES IN TO SASS TO SHOW WHY HE PREFERS SASS AS A CSS PRE-PROCESSOR.

Learning to appreciate the advantages of using pre-processors like Sass CSS in my work flow was not very hard for me. At times the challenge has been convincing others of the advantages of Sass and at times it can be divisive. A pre-processor is a simple tool that will provide some of the following advantages: Smooth some of the harsh edges and create code frameworks i.e. consistent code patterns Extends the current process further by adding needed and missing features A pre-processor like Sass does both. My introduction to Sass was in 2009 during an interview for a job. During this interview, the interviewer asked me if I knew of Sass. I did not. However after the interview, I googled it and was introduced to the world of sass-lang.com. After the 5 minutes that it took to install it on my Mac (Sorry PC users, it might take 10 minutes for you), I was up and running. I played around with all its features and before I knew it, I was hooked. In future projects, I was introduced to other CSS specific pre-processors like LESS, Stylus, and Closure Stylesheets. There has been certain feature sets that have made me gravitate back to Sass. Here are some of those features (I have used some code example from a real project) :

THE BASICS
All CSS pre-processors are built on the DRY (Dont Repeat Yourself) principle. On that basis they all have the following features: Variables

by Kianosh Pourian

Import Mixins Functions Selector Inheritance Variables, Import, and Mixins are basic features that were my first foray into Sass and all by themselves have added quite a punch in this application. CSS is a great language allowing designers and developers to improve the presentation layer. But until the introduction of pre-processors like Sass it has been a static language that uses its cascading feature to dynamically override styles and apply them to the presentation. With the introduction of Sass, DRY principles were added to CSS and therefore extending its features. So lets dive into some code and learn about Sass. The following is an example of a simple CSS. On one of the projects that I have been working on, I needed to create a header for sections of the site. This header will have a linear gradient background and white colored text. /*This is a variable for the primary color of the side*/ $primary: #00096E; /*primary grey color to be used throughout the site*/ $greyColor: #E0E0E0; /*This is an example of a mixin that will create a linear gradient. The ad vantages of using this is that we do not have to write the multiple vendor prefixed CSS repeatedly. And code maintenance is easier.*/ //this mixin will create a linear-gradient. The parameters passed here are: //$pos: position of the gradient which defaults to top but can take bottom, left, or right //$G1-G10: these allow for 10 color stops values, color and length/percentage //$fallback: this is the fallback color that will be used for older browsers, if this parameter //is not provided then the first color stop is used. @mixin linear-gradient($pos, $G1, $G2: false, $G3: false, $G4: false, $G5: false, $G6: false, $G7: false, $G8: false, $G9: false, $G10: false, $fallback: false) { // Detect what type of value exists in $pos $pos-type: type-of(nth($pos, 1)); // If $pos is missing from mixin, reassign vars and add default position @if ($pos-type == color) or (nth($pos, 1) == transparent) { $G10: $G9; $G9: $G8; $G8: $G7; $G7: $G6; $G6: $G5; $G5: $G4; $G4: $G3; $G3: $G2; $G2: $G1; $G1: $pos; $pos: top; // Default position }
2/7

$pos: unquote($pos); $full: $G1; @each $g in $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10 { @if $g != false { $full: $full + , + $g; } } $full: unquote($full); //If using COMPASS uncomment the line below and remove line 82 - 89 //$full: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10); // Set $G1 as the default fallback color $fallback-color: nth($G1, 1); // If $fallback is a color use that color as the fallback color @if type-of($fallback) == color { $fallback-color: $fallback; } background: $fallback-color; background: webkit-gradient(linear, $full); background: -webkit-linear-gradient($pos, $full); background: -moz-linear-gradient($pos, $full); background: -ms-linear-gradient($pos, $full); background: -o-linear-gradient($full); background: unquote(linear-gradient(#{$full})); }; The above mixin is courtesy of Thoughbots Bourbon mix which has quite an extensive collection of Sass mixins and functions.

FUNCTIONS
Sass comes with several built in functions. These are functions that are commonly used and they fall in the following categories: RGB functions HSL function Opacity functions Other Color functions String functions Number functions List functions Introspection functions Miscellaneous functions
3/7

Aside from the built-in functions, custom functions can also be created. .main-header { @include linear-gradient(top, $primary, lighten($primary, 20%)); color: white; display: inline-block; font-size: rfs(36); margin-left: 20px; } In this example, we are taking advantage of built-in color functions by passing the primary color and a 20% percent lighten primary color to our linear gradient mixin. We also are using a custom function that we have created to calculate the pixel font size in em, for a more responsive approach. Here is the detail of that function: // ==|===Responsive Font Size calculator==================== // Function that will calculate the responsive font size // return the em value to be used. // =========================================================*/ @function responsiveFontSize($fontSize: $defaultBrowserSize, $isIE: false) { @if $isIE { @return (($fontSize/$defaultBrowserSize) - 0.02) + em; } @else { @return ($fontSize/$defaultBrowserSize) + em; } } @function rfs($fontSize: $defaultBrowserSize, $isIE: false) { @return responsiveFontSize($fontSize, $isIE); } For more information on functions, refer to the Sass documentation.

SELECTOR INHERITANCE
This feature is one of the best features of Sass and one of the least used. This feature allows the user to think of the CSS and its features holistically and ensure the proper relationship among all the presentation elements. For example there are times that one class will encompass most of the styles needed however there will an addition of other classes that will include not the styles of the more general class but also some of its own. For example, in our code above we have a main-header class. Now we want to create sub headers: .main-header { @include linear-gradient(top, $primary, lighten($primary, 20%)); color: white; display: inline-block; font-size: rfs(36); margin-left: 20px; }
4/7

.sub-header { @extend .main-header; @include linear-gradient(top, $secondary, lighten($secondary, 15%)); font-size: rfs(24); } In this example, we inherited all the styles from main-header and over-wrote the linear gradient with a different color and reduced the size of our font. And the output will look something like this: .main-header, .sub-header { background: #00096e; background: webkit-gradient(linear, #00096e,#0011d4); background: -webkit-linear-gradient(top, #00096e,#0011d4); background: -moz-linear-gradient(top, #00096e,#0011d4); background: -ms-linear-gradient(top, #00096e,#0011d4); background: -o-linear-gradient(#00096e,#0011d4); background: linear-gradient(#00096e,#0011d4); color: white; display: inline-block; font-size: 2.25em; margin-left: 20px; } .sub-header { background: #cfc35d; background: webkit-gradient(linear, #cfc35d,#e0d998); background: -webkit-linear-gradient(top, #cfc35d,#e0d998); background: -moz-linear-gradient(top, #cfc35d,#e0d998); background: -ms-linear-gradient(top, #cfc35d,#e0d998); background: -o-linear-gradient(#cfc35d,#e0d998); background: linear-gradient(#cfc35d,#e0d998); font-size: 1.5em; } For a more comprehensive example of selector inheritance read this article by Thomas Reynolds.

PLACEHOLDER SELECTORS
Placeholder selectors follow the guideline of selector inheritance with one major improvement, they are silent until needed. A placeholder selector is a series of styles that are created for when there is situation where it is needed. If it is not extended, it will not be compiled to the final css output. If it is extended then the resulted styles will be in the output but the placeholder selector will not be in the compiled css. If we follow the example above, then the code will look like this: %header-setup{ color: white; display: inline-block; margin-left: 20px; }
5/7

.main-header { @extend %header-setup; @include linear-gradient(top, $primary, lighten($primary, 20%)); font-size: rfs(36); } .sub-header { @extend %header-setup; @include linear-gradient(top, $secondary, lighten($secondary, 15%)); font-size: rfs(24); } We placed the portion of the styles common to both classes in a placeholder selector and named it header-setup. The output of the code looks like this: .main-header, .sub-header { color: white; display: inline-block; margin-left: 20px; } .main-header { background: #00096e; background: webkit-gradient(linear, #00096e,#0011d4); background: -webkit-linear-gradient(top, #00096e,#0011d4); background: -moz-linear-gradient(top, #00096e,#0011d4); background: -ms-linear-gradient(top, #00096e,#0011d4); background: -o-linear-gradient(#00096e,#0011d4); background: linear-gradient(#00096e,#0011d4); font-size: 2.25em; } .sub-header { background: #cfc35d; background: webkit-gradient(linear, #cfc35d,#e0d998); background: -webkit-linear-gradient(top, #cfc35d,#e0d998); background: -moz-linear-gradient(top, #cfc35d,#e0d998); background: -ms-linear-gradient(top, #cfc35d,#e0d998); background: -o-linear-gradient(#cfc35d,#e0d998); background: linear-gradient(#cfc35d,#e0d998); font-size: 1.5em; }

6/7

OBJECT ORIENTED CSS (OOCSS)


Sass allows for a better framework for the implementation of OOCSS. If you are unfamiliar with OOCSS, Nicole Sullivans answer to writing a well structured, efficient and performant CSS; here are a few resources: How to write a well structured CSS http://oocss.org/ https://github.com/stubbornella/oocss/wiki http://coding.smashingmagazine.com/2011/12/12/an-introduction-to-object-oriented-css-oocss/ Combining Sass and OOCSS principles make for a great way to write CSS. Here are some great articles in this regard: http://ianstormtaylor.com/oocss-plus-sass-is-the-best-way-to-css/ http://takazudo.github.com/presentation-oocss-sass/#/ http://memerocket.com/2009/03/28/oocss-sass-fewer-classes-on-your-elements/

CONCLUSION
Sass is a great that will enhance and improve upon CSS. If you have any reservations about using Sass, just experiment with it especially with the SCSS extension which allows you to use regular CSS in their along side with all the features of Sass. Cheers.

ABOUT THIS ARTICLE


I am a native born Iranian and reside in Boston Massachusetts. Husband to a lovely New Englander and father to two lovely girls. In my spare time, I am an enthusiast in all things involving UI development and am lucky enough to be working in that field for clients like VMWare, MIT, and Novartis.

ONLINE RESOURCES SASS http://sass-lang.com/


SASS Documentation http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html DRY Principle http://en.wikipedia.org/wiki/Dont_repeat_yourself

http://innovatorylife.com/

@kianoshp

appliness

DONT WORRY, BE APPLI

COLLIE TUTORIALS

CHECKOUT THIS GREAT TUTORIAL ON THE COLLIE JAVASCRIPT LIBRARY TO LEARN MORE ABOUT MAKING ANIMATION AND GAMES OPTIMIZED FOR THE MOBILE PLATFORM.

#1 INTRODUCTION
Web in the old days was invented for the purpose of delivering information on static pages. However with the advent of HTML5 and improved JavaScript performance, various attempts have been made on web browser. Animation and games are no exceptions. Efforts to create animations and games using HTML5 canvas and CSS3 have been made numerously, along with many libraries being introduced for supporting such trial. In response to vitalizing mobile market, many attempts have been made on desk tops. On the mobile platform, however, it is difficult to create optimum animations and games via generally known method, since the lineup of mobile device is too massive, not to mention the fragmentation issue of OS. This guide is for getting to know JavaScript Library Collie which facilitates animation and games creation optimized for mobile platform. Guided by this tutorial, lets create codes for creating simple animations.

by Sangmin, Shim

#2 INTRODUCING COLLIE
The control flow bindings introduced in Knockout 2.0 are really just simple wrappers to the template Collie is a JavaScript library for making animation and games optimized for mobile platform. LGPL v2.1 which is an open source license has been adopted and it is downloadable on http://jindo.dev.naver.com/ collie/ Living up to its reputation as the most optimized JS library for mobile, Collie was introduced to the world through passing various tests on more than 18 mobile devices and many operating systems. Collie operates differently on each device by selecting respective rendering method based on its test result. The testing result is open for all on below website.

Figure 2-1 Performance Test Page per Mobile Device and OS Collie uses HTML5 Canvas or CSS3 based on the situation for its rendering. The interface is identical in spite of different operating method. Thus, it enables the users to use only one interface without contemplating on which rendering to operate since it automatically results in outputs optimized for various devices. Although there are some restrictions and bugs detected per device and OS, Collie lets you to engage in development without having to worry about those matters. On top of that Collie is ever more evolving to promise a quality performance on mobile platform by applying various options and algorithms. With its superb usability, learning to utilize a simple API will ensure you to create animations and games with ease. First, let us get the glimpse of what Collie is by creating a simple demo.

2/14

#3

CREATING A SIMPLE SAMPLE

Let us complete simple exercise of displaying Collie logo in the middle of the screen to familiarize ourselves with basic structure before actually working on the demo. If you make a code following below description, you will be able to see Collie log rotating constantly in the center of the screen CREATING MARK-UP First, load Collie script to a page as described below. <!doctype html> <html> <head> <meta charset=utf-8 /> <meta name=viewport content=width=device-width, initial-scale=1.0, maxi mum-scale=1.0, minimum-scale=1.0, user-scalable=no /> </head> <body> <div id=container></div> <script type=text/javascript src=http://jindo.dev.naver.com/collie/deploy/ collie.min.js></script> <script type=text/javascript> // Create code here. </script> </body> </html> There is no need to use other Scripts for writing Collie script. The size wouldnt be too much of a burden since it is around 20kb when g-zipped. It should be inserted within head tag or before using Collie. Although Collie script is provided on Deploy folder within official Collie website, for a more stable service, I would like to recommend you to download it from official website. <meta name=viewport content=width=device-width, initial-scale=1.0, maxi mum-scale=1.0, minimum-scale=1.0, user-scalable=no /> Above meta tag is required information for viewing pages as it is, on Mobile platform. Please refer to (http://developer.apple.com/library/ios/#documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html) for further details on how to set viewport. CREATING LAYER Before creating logo object, layer for holding display object should be created. Layer is capable of holding various display objects and a single canvas belongs to a single layer. The layer will be created as follows. var layer = new collie.Layer({ width: 320, height: 480 }); Option is entered in the first factor of the creator in layer as an object. Above option is for creating layer corresponding to a mobile display with 320 width and 480 height. Please refer to an API document (http://jindo.dev.naver.com/collie/doc/collie.Layer.html) for further information.

3/14

LOADING IMAGE USING IMAGEMANAGER Generally images used in animation or games are loaded asynchronously since the volume and number is considerable. Thus, Collie asynchronously manages its image resources as well using ImageManager. You may load images using add method in ImageManager as described below. collie.ImageManager.add({ logo: http://jindo.dev.naver.com/collie/img/small/logo.png }); // Create display object. Although image has yet to be loaded, you may use the logo. Although ImageManager loads images asynchronously, users can create display objects using the images without checking the loading result. Once display object is created and image loading gets completed, ImageManager allocates loaded image to display object. However, if you dont wish empty display object to be in display, you can create object after all images are loaded. collie.ImageManager.add({ logo: http://jindo.dev.naver.com/collie/img/small/logo.png }, function () { // Create display object after all images are loaded }); Please refer to API document (http://jindo.dev.naver.com/collie/doc/collie.ImageManager.html) for further information. CREATING DISPLAY OBJECT In order to display loaded image to the screen, display object needs to be created. There are various kinds of display objects including Circle for marking circle from DisplayObject and Text for indicating Text. Create display object using MovableObject capable of using veolocity attribute since the logo needs to be constantly rotating. var logo = new collie.MovableObject({ x: center, y: center, backgroundImage: logo, velocityRotate: 50 }).addTo(layer); While creating display object, you can add corresponding object to layer using addTo method. Display object will only be displayed on the screen when it is added to layer or parent display object. Display object, likewise, will be entered with option as the first factor. You may also type character strings for x and y same as the center and coordinate in the unit of pixel can be entered in. Input image resource key loaded in ImageManager beforehand into the backgroundImage. Display object will be set befitting the background image size unless width and height value is specified. VelocityRotate is an exclusive option for MovableObject which refers to the rotation angle per second. For instance, set as 50, the object will rotate 50 degrees for every second. Moving velocity can also be designated using velocityX and velocityY. Please refer to API document (http://jindo.dev.naver.com/collie/doc/collie.MovableObject.html) for further information.

4/14

PREPARING RENDERER Display object has been created and added to layer. Add the prepared layer to Renderer and execute Renderer to view the object on actual screen. collie.Renderer.addLayer(layer); collie.Renderer.load(document.getElementById(container)); collie.Renderer.start(); First of all, add the prepared layer onto Renderer using addLayer method. And use load method to initialize Collie on DOM object. DOM object with its ID of a container, has been added as described below during mark-up creation phase. <div id=container></div> Lastly, run Renderer using start method. As the first factor, Start method supports time frame in the unit of millisecond that is displayed on the screen. You may also add fps at the end for inputting in the unit of FPS through adding fps at the end. The default value is 60fps. In normal mobile setting it is the most effective to run with 30fps. collie.Renderer.start(30fps);

#3 SUMMARY
The following is the code created so far. <!doctype html> <html> <head> <meta charset=utf-8> <meta name=viewport content=width=device-width, initial-scale=1.0, maxi mum-scale=1.0, minimum-scale=1.0, user-scalable=no /> </head> <body> <div id=container></div> <script type=text/javascript src=http://jindo.dev.naver.com/collie/deploy/ collie.min.js></script> <script type=text/javascript> var layer = new collie.Layer({ width: 320, height: 480 }); collie.ImageManager.add({ logo: http://jindo.dev.naver.com/collie/img/small/logo.png }); var logo = new collie.MovableObject({ x: center, y: center, velocityRotate: 50, backgroundImage: logo

5/14

}).addTo(layer); collie.Renderer.addLayer(layer); collie.Renderer.load(document.getElementById(container)); collie.Renderer.start(); </script> </body> </html> Use above coding to create an object displaying constantly rotating image on the screen. You may also find above coding in http://jsbin.com/iwakuj/2/

Figure 3-1: Constantly rotating logo image Additionally, the idea of automatically processing each binding independently is being explored for a future version of Knockout.

#4 CREATING MOTIONS USING SPRITE


So far, we have looked into how to use Collie by making simple demonstrations. Now moving on from a rather boring static logo, lets create a moving rabbit with Sprite. PREPARING IMAGE AND OBJECT Sprite expresses continuous scene into a single cut image as shown below.

Image 4-1: Sprite image of walking rabbit

6/14

When creating display object with Sprite, the size of a single screen shall be based on width and height option. collie.ImageManager.add({ rabbit: http://jindo.dev.naver.com/collie/img/small/yame_walk.png }); var rabbit = new collie.DisplayObject({ x: center, y: center, width: 129.4, height: 165, backgroundImage: rabbit }).addTo(layer);

Image 4-2: Display object which only shows the first frame of Sprite image ANIMATION Followed by above stage, execute Renderer to find an immovable rabbit on the screen. To infuse a life into this rabbit, lets define animation. Collie supports various animations such as delay, repeat and transition. Here, cycle animation is used for Sprite. collie.Timer.cycle(rabbit, 18fps, { from: 0, to: 8, loop: 0 }); Animation can be created using collie.Timer. Input related display object or callback function in the first factor and time (millisecond unit) in the second. For more convenience, add fps at the end for Cycle animation. When set as 18fps for instance, at a speed of 18 movements per second, the frame changes 9 times from 0 to 8. The third factor is for inputting animation option. Please refer to API document (http://jindo.dev.naver. com/collie/doc/collie.AnimationCycle.html) for further information. The following is the organized coding. <!doctype html> <html> <head> <meta charset=utf-8> <meta name=viewport content=width=device-width, initial-scale=1.0, maxi mum-scale=1.0, minimum-scale=1.0, user-scalable=no /> </head>

7/14

<body> <div id=container></div> <script type=text/javascript src=http://jindo.dev.naver.com/collie/deploy/ collie.min.js></script> <script type=text/javascript> var layer = new collie.Layer({ width: 320, height: 480 }); collie.ImageManager.add ({ rabbit: http://jindo.dev.naver.com/collie/img/small/yame_walk.png }); var rabbit = new collie.DisplayObject({ x: center, y: center, width: 129.4, height: 165, backgroundImage: rabbit }).addTo(layer); collie.Timer.cycle(rabbit, 18fps, { from: 0, to: 8, loop: 0 }); collie.Renderer.addLayer(layer); collie.Renderer.load(document.getElementById(container)); collie.Renderer.start(); </script> </body> </html> Enter above code to find a walking rabbit. You will also find above code in http://jsbin.com/usaqih/1/

8/14

#5

CREATING CONTINUOUSLY MOVING BACKGROUND

It might be very boring, if the rabbit were to be the only movable object. Now, lets make a movable ground that proceeds according to rabbits walk. PREPARING IMAGE AND OBJECT To make a constantly moving ground, you need to prepare image that is more than double the size of what is displayed on the screen. Without having to prepare a repeating image separately, create required object using backgroundRepeat attribute of display object as shown below. collie.ImageManager.add({ ground: http://jindo.dev.naver.com/collie/img/large/ground.png }); var ground = new collie.MovableObject({ x: 0, width: 320 * 2, height: 88, velocityX: -50, backgroundImage: ground, backgroundRepeat: repeat-x }).bottom(0).addTo(layer); Since the ground needs to be proceeding towards the opposite direction of rabbit, you need to use MovableObject and input velocity value using. To make the object seem as if it is moving continuously, the ground needs to return to the original position every time each screen passes by. Therefore, rangeX and positionRepeat option need to be added to the following display object. var ground = new collie.MovableObject({ x: 0, width: 320 * 2, height: 88, velocityX: -50, backgroundImage: ground, backgroundRepeat: repeat-x, rangeX: [-320, 0], positionRepeat: true }).bottom(0).addTo(layer); RangeX refer to the scope of x-coordinate allowed for object to move and positionRepeat is for deciding whether to move to the opposite end when object reached one end.

9/14

#6

USING EVENT

To give a more vivid touch, you would want to make the rabbit jump up by clicking mouse or touching the screen. Such function can be materialized by using object events. ADDING EVENT TO OBJECT Event can be added by using attach method on rabbit object. Using click event, the object will respond to both touch and click since Collie supports mobile and desktop events at the same time. rabbit.attach({ click: function (e) { // Perform specific motion } }); DEFINING ANIMATION Define a parabolic motion to make the object seem like jumping. Use transition animation and animation queue as detailed below for parabolic motion. var currentY = rabbit.get(y); rabbit.attach({ click: function (e) { collie.Timer.queue(). transition(rabbit, 400, { to: currentY - 100, effect: collie.Effect.easeOut, set: y }). transition(rabbit, 400, { to: currentY, effect: collie.Effect.easeIn, set: y }); } }); Transition animation defines continuous motions by using various animation effects and animation queue is for combining multiple animations into a single one. Please refer to API document (http://jindo.dev. naver.com/collie/doc/collie.Effect.html) for more details on various animation effects that Collie supports.

#7

HIGH-RESOLUTION DISPLAY

10/14

You need to prepare a higher resolution image for devices supporting high-resolution display such as iPhone 4. Although there are various methods for meeting the high-resolution capacity, Collie enables you to support high-resolution display with ease. Now, lets see how to support high-resolution display using Collie.

DELETING DEBUGGING CODE Modify the following line when making a simple sample. collie.Renderer.RETINA_DISPLAY = auto; Default value for collie.Renderer.RETINA_DISPLAY is false. If you set this value as true or false, you will be able to create a high-resolution environment regardless of the type of device. CONFIRMATION DURING IMAGE LOADING When you opt for general resolution image during ordinary times and load high resolution image when it comes to catering to high-resolution display, Collie automatically calculates the value and displays accordingly on the screen. It is not easy to apply such condition to all objects; however on Collie, all you need to do is to use isRetinaDisplay method of Renderer and load images suitable for each resolution for Retina display. var folder = collie.Renderer.isRetinaDisplay() ? large : small; collie.ImageManager.add({ rabbit: http://jindo.dev.naver.com/collie/img/ + folder + /yame_walk. png, ground: http://jindo.dev.naver.com/collie/img/ + folder + /ground.png });

Image 7-1: High-resolution image (left) specially made for Retina Display and ordinary image (right) when viewed on Retina Display

#8 DEBUGGING
So far, we have looked into methods for operating Retina Display support mode using collie.Renderer. RETINA_DISPLAY value. Now, we are going to look into additional functions that are also beneficial. RENDERING MODE Desktop provides a more convenient developing environment than mobile. Collie provides multiple variables for selecting rendering mode (HTML5 canvas and Dom rendering) to better cater to each development circumstance. collie.Renderer.DEBUG_RENDERING_MODE = dom; Above code shall be defined before using Collie. Default value for collie.Renderer.DEBUG_RENDERING_ MODE is auto and you may view specific mode by setting canvas or dom. FPS CONSOLE
11/14

FPS represents the performance of animation and game. Collie provides FPSConsole for checking FPS on screen on demand.

var fpsConsole = new collie.FPSConsole(); fpsConsole.load(); Tool script is required for using FPSConsole as specified above. Tool script can be called for use as specified below. <script type=text/javascript src=http://jindo.dev.naver.com/collie/deploy/ collie.tool.min.js></script>

#9 SUMMARY
Below is the code created so far. Correctly following below code will lead to a walking rabbit and a jumping one at a click (touch) of the rabbit on the screen. <!doctype html> <html> <head> <meta charset=utf-8> <meta name=viewport content=width=device-width, initial-scale=1.0, maxi mum-scale=1.0, minimum-scale=1.0, user-scalable=no /> </head> <body> <div id=container></div> <script type=text/javascript src=http://jindo.dev.naver.com/collie/deploy/ collie.min.js></script> <script type=text/javascript> collie.Renderer.RETINA_DISPLAY = auto; var folder = collie.Renderer.isRetinaDisplay() ? large : small; collie.ImageManager.add({ rabbit: http://jindo.dev.naver.com/collie/img/ + folder + /yame_walk. png, ground: http://jindo.dev.naver.com/collie/img/ + folder + /ground.png }); var layer = new collie.Layer({ width: 320, height: 480 }); var rabbit = new collie.DisplayObject({ x: center, width: 129.4, height: 165, zIndex: 2, backgroundImage: rabbit }).bottom(50).addTo(layer); var currentY = rabbit.get(y); rabbit.attach({ click: function (e) { collie.Timer.queue(). transition(rabbit, 400, { to: currentY - 100,

12/14

}); collie.Timer.cycle(rabbit, 18fps, { from: 0, to: 8, loop: 0 }); var ground = new collie.MovableObject({ x: 0, width: 320 * 2, height: 88, velocityX: -200, backgroundImage: ground, backgroundRepeat: repeat-x, rangeX: [-320, 0], positionRepeat: true }).bottom(0).addTo(layer); collie.Renderer.addLayer(layer); collie.Renderer.load(document.getElementById(container)); collie.Renderer.start(); </script> </body> </html> You will find above code in http://jsbin.com/oyopeq/2/

}). transition(rabbit, 400, { to: currentY, effect: collie.Effect.easeIn, set: y });

effect: collie.Effect.easeOut, set: y

13/14

#10

SUMMARY

Collie has not only focused on optimization for mobile platform but also on development convenience as well as the productivity. If you developing accordingly, you will be able to create the most optimal animation which can tap into both DOM and Canvas depending on the circumstances, while supporting Retina display. The ultimate goal of developing animation and game with Collie is to free the users from thinking about functional matters and ensure them to focus only on coding. In short, the user will be able to exert his/ her energy in creation. With Collie, you will be able to make animation/game of your own with ease!

ABOUT THIS ARTICLE


He is a Senior JavaScript developer working at NHN and the creator of the JavaScript animation library Collie. He is very interested in making JavaScript apps run faster and more smoothly. He has authored a book titled What You Need to Know about JavaScripts Performance and also writes mobile games using Collie.

ONLINE RESOURCES Collie Home http://jindo.dev.naver.com/collie/


Collie Download http://jindo.dev.naver.com/collie/index.html#download Collie Documentation http://jindo.dev.naver.com/collie/index.html#documentation

http://jindo.dev.naver.com/collie/

@davidshimjs

appliness

DONT WORRY, BE APPLI

PLUGGING INTO SOCKET.IO: ADVANCED

RECENTLY, WE LOOKED AT THE BASICS OF USING SOCKET.IO. AS WE WENT THROUGH THAT, WE DISCOVERED THAT SOCKET.IO AFFORDS US A VERY SIMPLE API BASED ENTIRELY OFF OF SENDING AND RECEIVING MESSAGES AND BEING NOTIFIED OF THOSE MESSAGES THROUGH EVENTS. WELL, THERES MORE TO SOCKET.IO THAN THAT. IT HAS SEVERAL ADVANCED FEATURES THAT CAN COME IN VERY HANDY IN CERTAIN SITUATIONS.

BUILT-IN EVENTS
This isnt exactly an advanced feature. I just didnt have the time to include it in the previous post. Anyway, you saw that both the client and server side had a means of doing something once the connection was made: // Server Side io.listen(80); io.sockets.on(connection, function(socket){ . . . }); // Client Side socket = io.connect(http://localhost/); socket.on(connect, function() { . . . });

by Joe Zimmerman

On the back end, it is required that you react to this, otherwise you wont be able to do anything with the connection. On the front end, though, this isnt required, but it is usually helpful. In addition, both sides can also react to a disconnection. The code below applies to both front and back end. socket.on(disconnect, function() { // Let the users know something bad happened or log the disconnect }); Dont bother trying to reconnect in there, at least not right away. Socket.IO will try to reconnect on its own a certain number of times and it spaces out each reconnection attempt a little wider each time. But, it does give up after a while, so you might want to throw some setTimeouts in there to continue trying to reconnect later if you want. Oh, and by the way, you can disconnect on purpose, which doesnt cause the client to try connecting again, but should still fire the disconnect event: // Client Side socket.disconnect(); There is also a message event, which is used to make Socket.IO conform more closely to the WebSocket semantics. This way, all messages are received and dealt with within this single callback and you dont need to make up names for the messages. When using this, you also use send rather than emit to send messages. // Server Side io.listen(80); io.sockets.on(connection, function (socket) { socket.on(message, function (message) { console.log(message); socket.send(message was received); }); }); // Client Side socket = io.connect(http://localhost/); socket.on(connect, function() { . . . }); socket.on(message, function (message) { console.log(message); socket.send(message was received); });

ACKNOWLEDGEMENT
Sometimes, you want to have the system set up to have a response from the server any time the server receives your messages. You can do this by sending functions to the server, which the server will then call directly and pass some data in to it. // Server Side socket.on(getMessage, function(func) { func(The Message); }); // Client Side socket.emit(getMessage, function(message) {
2/6

});

console.log(message);

When this is run, The Message will be posted in the clients console. This might seem a bit like magic, but really its just a clever use of a proxy. The function itself isnt actually being called. Rather a different function is being called in its place, which sends the data back to the client and has the actual function called there with the data that was sent. Its a very nice system to ensure you receive acknowledgement of when the server receives your request. You could, of course, just rewrite the code like this and achieve the exact same effect, though. // Server Side socket.on(getMessage, function(func) { socket.emit(theMessage, The Message); }); // Client Side socket.emit(getMessage); socket.on(theMessage, function(message) { console.log(message); }); Its a little more code and it isnt entirely clear from the clients perspective that theMessage will be sent back immediately when getMessage is received, but it still works just as well.

STORING CLIENT DATA


Essentially Socket.IO has a special type of session storage that you can use to store information about each connected socket client. Its also really simple to use, just like pretty everything else about this library. // Server Side socket.on(set nickname, function (name) { socket.set(nickname, name, function () { socket.emit(ready); }); }); socket.on(msg, function () { socket.get(nickname, function (err, name) { console.log(Chat message by , name); }); }); // Client Side socket.emit(set nickname, user.nickname); socket.on(ready, function () { console.log(Connected !); socket.emit(msg, message); });
3/6

As you can see, it works well for storing a users nickname so that everyone in a chat can know who is sending the messages. Simply use socket.set and socket.get. Make sure you notice that they are asynchronous, so they require a callback if you want to do anything immediately after the value is saved or retrieved.

BROADCASTING
So you want to be on television? Sorry, wrong kind of broadcasting. By broadcasting, I mean sending a message to everyone who is connected to the server. We already talked about this in the previous post, where I said that on the server side you could use io.sockets.emit rather than socket.emit to send a message to every client that is connected. socket.on(chat message, function(msg) { io.sockets.emit(message, msg); }); There is potentially a problem with this setup, though: it sends the message to the original client too. The client who sent chat message probably doesnt need to receive it back. To get around this, there is a mechanism that allows you to send a message to everyone except the original client. Just use socket. broadcast.emit. The above code can now be written like this: socket.on(chat message, function(msg) { socket.broadcast.emit(message, msg); });

SEGMENTING USERS: ROOMS AND NAMESPACES


Sometimes you dont want all of the users lumped up together in the same pool. You might want to send messages to some clients and not others. For this we have two different ways of segmenting users: Rooms and Namespaces. ROOMS Users can be assigned to different rooms and then can be contacted when broadcasts are made to that room. First off, lets learn how clients can be assigned to and removed from rooms. All of this is done on the server side. The client has no real power in controlling which rooms it is assigned to, except to send messages normally that the server responds to by changing whether you are in a room or not. // Server Side socket.on(addToRoom, function(roomName) { socket.join(roomName); }); socket.on(removeFromRoom, function(roomName) { socket.leave(roomName); }); Simply use socket.join and socket.leave to join and leave rooms, respectively. Im pretty sure (though I havent tried it. You should try it if youre interested) that a socket can join multiple rooms at once. Now that youre assigned to a room, whenever someone broadcasts to the entire room, you will be notified. Heres how you broadcast to rooms:

4/6

// Broadcast to everyone in a room, except you socket.broadcast.to(room name).emit(your message); // Broadcast to everyone in a room, including you io.sockets.in(room name).emit(your message); And thats pretty much all there is to rooms! NAMESPACES Namespaces arent technically intended for segmenting your users. Rather, they are used to allow you to have multiple connections to multiple Socket.IO servers, but only require the use of a single Socket.IO server. In other words, a single server acts like multiple servers that you can connect to separately. While the intention is different, it does work to segregate users. Lets set up the server side to allow multiple connections: var io = require(socket.io).listen(80); var chat = io .of(/chat) .on(connection, function (socket) { // Send message to client like usual socket.emit(a message, { that: only, socket: will get }); // Broadcast message to everyone in this namespace chat.emit(a message, { everyone: in, /chat: will get }); }); var news = io .of(/news); .on(connection, function (socket) { socket.emit(item, { news: item }); }); As you can see, all you do is replace sockets with of(/namespace) when you start the on(connection, function(){}) call. This creates a segment of connections that you can keep separate from other connections. As you can see, this setup allows you to broadcast to everyone in this namespace too. Now we need the clients to connect to them separately. Simply just create separate connections to each of the namespaces and youre all set. var chat = io.connect(http://localhost/chat), news = io.connect(http://localhost/news); chat.on(connect, function () { chat.emit(connectedToChat); }); news.on(news, function () { news.emit( connectedToNews); }); Just add the namespace to the end of the normal URL and youll connect to the Socket.IO server with that namespace. You can treat chat or news exactly the same way you used to treat socket in the single-connection scenarios.

5/6

CONFIGURATION
Socket.IO has many configurable options, so they implemented a way to configure it. Heres a quick look at how to do it. io.configure(production, function(){ io.enable(browser client etag); io.set(log level, 1); }); io.set(transports, [websocket, flashsocket, xhr-polling]);

First, call io.configure sending in the environment you want the configuration to be set up for and a function. Inside the function, you can use io.enable (which just sets the options value to true), io.disable (which sets the value to false), and io.set (which sets the value to whatever the second argument is) to change all of the options available to Socket.IO. If you want more information on changing the environments and which options are available, I recommend you take a look at the wiki page about configuring Socket.IO.

CONCLUSION
Socket.IO has proven itself to be a great replacement for straight WebSockets. It allows amazing customizability and a wonderfully simple API for enabling real-time 2-way communication between a server and client. Its definitely worth taking a look at. God bless and happy coding!

ABOUT THIS ARTICLE


Joe Zimmerman has been doing web development for 12 years, which may make him sound old, but since he started in middle school, hes still pretty young. HTML and CSS were the coolest inventions ever. In college he was introduced to real JavaScript, starting his full addiction. Now his addiction pushes him to continuously learn more and spread the knowledge to the internet.

ONLINE RESOURCES His blog http://www.joezimjs.com/


Adobe Developer portal http://www.adobe.com/devnet.html Learning JS patterns by Addy Osmani http://addyosmani.com/resources/essentialjsdesignpatterns/book/

http://www.joezimjs.com/

@joezimjs

appliness

DONT WORRY, BE APPLI

DYNAMICALLY LOADING A STYLE SHEET BASED ON WEATHER CONDITIONS

SEE HOW RAY HAS FIGURED OUT HOW TO LOAD WEATHER DATA INTO DYNAMIC WEBSITE DESIGN.

I know what youre thinking - thank God Ray is blogging about this topic. I cant tell you the number of times clients have asked for a dynamic web site design based on the users current weather conditions. Well, todays your lucky day! (Ok, all snark aside - I saw this asked on StackOverflow and thought it would be fun to build.) In general, the process is relatively simple: Get the users location (simple!) Get the weather (mostly simple, depending on the API) Load a dynamic style sheet (simple!) Of course, actually designing a style sheet that adequately conveys a particular weather condition is way beyond my stylistic chops. So if you pretend for a moment that I could actually design worth a damn, then hopefully the rest of the technical bits will be interesting. Ok, lets do it. Following the order of operations above, I began with a simple geolocation check/call. document.addEventListener(DOMContentLoaded, init, false); function init() { console.log(init); } //First, grab the users location if(geolocationSupported()) getLocation();

function geolocationSupported() {

by Raymond Camden

return navigator.geolocation;

function getLocation() { console.log(Requesting location); //Notice - no error handler. Since this is just rainbows and unicorns, we can fail silently navigator.geolocation.getCurrentPosition(positionLoad); } Hopefully none of this is too new to my readers. Due to the nature of this feature, I dont have to worry about fallback of any sort. Users without geolocation support wont get an error nor will the site break, they just wont get the super fancy cool color scheme that matches their weather. The second part involves getting the weather. I decided to use Weather Undergrounds API for this. Yahoo has a nice API as well, but doesnt support longitute/latitude weather lookups. (They do have a service to do this lookup for you, but I wanted a simpler API.) Weather Underground doesnt support CORS, but does support JSON/P. Im not using jQuery for this, but the code to do a JSON/P call is incredibly trivial. function positionLoad(pos) { var long = pos.coords.longitude; var lat = pos.coords.latitude; //Now that weve gotten our position, lets get the weather //quick and dirty jsonp call var script = document.createElement(script); script.src = http://api.wunderground.com/api/80955450a9ddb7f6/conditions/ q/+lat+,+long+.json?callback=gotWeather; document.getElementsByTagName(head)[0].appendChild(script); } Ok, now for the fun part. The Weather Underground API returns a lot of data. All I care about is a key called weather that contains a general description. Examples: Mostly Cloudy, Partly Cloudy, Overcast. Unfortunately, they dont bother to actually freaking document the unique values here. I decided to take a tour around the world to find various examples and apparently the entire world now is covered in cloud, much like in Star Trek 4. (Yes, the one with the whales.)

2/5

So for now, I took a few simple values, a few guesses, and just rolled with it. I figured it would make sense to condense some conditions into each other so I built it up as a simple Switch block. function gotWeather(w) { //if we dont have current_observation, we had an error, and again, we can ignore if(!w.current_observation) return; var weatherType;

switch (w.current_observation.weather) { case Mostly Cloudy: case Partly Cloudy: case Overcast: weatherType = cloudy; break; case Rain: weatherType = rain; break; default: break; } } The final part was rather simple. To load a dynamic style sheet into the browser you follow much the same pattern for doing JSON/P - simply create a new DOM item and inject it. function loadStyleSheet(type) { var style = document.createElement(link); style.setAttribute(rel, stylesheet); style.type = text/css; style.href = ./css/+type+.css; document.getElementsByTagName(head)[0].appendChild(style); } Notice how each type of weather will match to a something.css in my css folder. To keep things simple, I added styles to the H1 and P tags. Heres cloudy.css:
h1, p { color: gray; } h1:after { font-style: italic; font-size: 0.6em; margin-left: 10px; content: Cloudy; }

console.log(w.current_observation.weather,weathertype is +weatherType); //Based on the general weather, load a style sheet if(weatherType) loadStyleSheet(weatherType);

3/5

Note the use of the after pseudo-class. I use this to inject the actual weather description (or a similar one) after the h1 tag. Heres an example based on my current location:

And since I have separate function, I was able to go into console and force it to the rainy version.

All in all, pretty simple. You can view the complete demo here: http://www.raymondcamden.com/demos/2012/nov/12/ I liked that - but - something nagged at me. Every time you load the page the code checks your location and gets the weather. Surely we could cache that, right? I built up a second version that makes use of sessionStorage. I update the setup code first: function init() { console.log(init); //First, grab the users location if(goodBrowser()) { if(window.sessionStorage.weatherType) loadStyleSheet(window.sessionStor age.weatherType); else getLocation(); } }

4/5

function goodBrowser() { return navigator.geolocation && window.sessionStorage; } view rawgistfile1.jsThis Gist brought to you by GitHub. And then stored the weatherType variable in the users session: if(weatherType) { loadStyleSheet(weatherType); //cache in session window.sessionStorage.weatherType = weatherType; } You can view this version here: http://www.raymondcamden.com/demos/2012/nov/12/index2.html

appliness

DONT WORRY, BE APPLI

JS ADOLESCENCE

SEE SOME OF THE LESSONS JAMES HAS LEARNED ABOUT HOW TO DO (OR NOT TO DO, THAT IS) JAVASCRIPT PROGRAMMING OVER THE YEARS.

For me there was a time that can only be described as adolescence in the field of programming and more specifically JavaScript. This period was characterised by a certain laziness and hubris. I thought I was right. I thought others were wrong. I could see no path but the very strict one that I had boxed myself into through a process in which I longed for certainty and the expulsion of realistic doubt. Today I present a short list of JavaScript practices that once seemed right but I now deem foolish (in most situations): Using logical operators as statements Always declaring variables at the top of their scope Repeatedly used inline object literals Complex inline regular expressions Using single letter variable names Strict equality everywhere Assuming truthiness equals presence Commenting nothing or commenting every little thing Thinking I can write something reliable without unit tests Using long names and being overly specific Strict coherence to a standard

by James Padosley

USING LOGICAL OPERATORS AS STATEMENTS


a() || b.foo.bar(); m && c() ? d() : l || m.foo[bee](3); There is no real advantage in forgoing convention for the sake of cleverness.

ALWAYS DECLARING VARIABLES AT THE TOP OF THEIR SCOPE

function calculate() { var a, m, t, y, This, is, really, understandable = false; // Actual logic goes here } Instead I declare a variable where it makes sense. Much of the time this is at the top of the scope, but there are enough exceptions to make me shake my head in dissapproval at the thought of a style guide imposing religious top-of-scope declarations.

REPEATEDLY USED INLINE OBJECT LITERALS


function prepareRequest(mode, updateId, value) { var req = { mode: mode, updateId: updateId, value: value, uid: genUID() }; // etc. } Its better for clarity and performance (potentially) to define separate classes for cases where you repeatedly make object literals of the same structure. For example the above could be refactored into a Request class.

COMPLEX INLINE REGULAR EXPRESSIONS


if (/r[ -~]?(?:m\d+|\d+[0-3]{2,})_m?$/.test(thing)) { // ... wat } It makes sense to cache these things. Plus naming it means someone might have a chance of understanding WTF the code does.
2/4

USING SINGLE LETTER VARIABLE NAMES


They make no sense unless used in the various idiomatic loops.

STRICT EQUALITY EVERYWHERE


if (typeof x === string && x === mode:45) { // ... } Sometimes its overkill. Regular equality can be used in both of the above cases.

ASSUMING TRUTHINESS EQUALS PRESENCE


if (!cachedReturnValues[key]) { cachedReturnValues[key] = value; } Its potentially dangerous. E.g., Its better to use the in operator to discover presence, or even hasOwnProperty.

COMMENTING NOTHING OR COMMENTING EVERY LITTLE THING


// This is a loop for (var i = 0; i < arr.length; i++) { // This is me adding one to the item in the array at the index // specified by the variable `i` declared slightly above this comment: arr[i] += 1; } // this is the end of the loop Commenting everything demonstrates either a lacking clarity in your code or a lacking clarity in your mind as to the intention of comments. Commenting nothing shows hubris and laziness.

THINKING I CAN WRITE SOMETHING RELIABLE WITHOUT UNIT TESTS


Unit tests give me the confidence to be sure that my code does what I intend it to do.

3/4

USING LONG NAMES AND BEING OVERLY SPECIFIC


A long name suggests bad API design. Re-think where youre defining the variable/method. Think of a circumstance in which the variable name could be shorter a context that makes sense for that variable. Then create that context. Youll probably end up with a cleaner internal API. E.g. // Version 1: var responseCache = {}; function generateNextIDForANewResponseCacheItem() {...} function deleteResponseCacheItemsThatDoNotEqual(value) {...} // Version 2: function ResponseCache() { this.data = {}; } ResponseCache.prototype = { genNextID: function() {...}, remove: function(optionalFnCheck) {...} };

STRICT COHERENCE TO A STANDARD


This never works and never solves what you think it will. Its better to dynamically sway and constantly rethink your idea of what is right and wrong given each situation as it arises. This is why I try to steer clear of over-zealous coding style dogma, or all dogma for that matter.

ABOUT THIS ARTICLE


James is a JS Developer with extensive experience in front-end web development. He enjoys challenges, breaking boundaries and doing helpful and inspiring work. He works in London for Lab49 as a UI Developer. He enjoys writing about his latest discoveries, opinions and adventures. Head over to posts to see what hes been distracting himself with lately.

ONLINE RESOURCES James on Github https://github.com/padolsey/


Jamess links on Delicious http://delicious.com/padolsey Lab49 http://www.lab49.com/

http://james.padolsey.com/

@padolsey

PHOTO BY: Elle Osmani

ADDY
OSMANI
THE MODERN YEOMAN

KEVIN
LY N C H
THE CREATIVE LEADER
PHOTOS BY: Elle Osmani

HI KEVIN, THANK YOU SO MUCH FOR YOUR TIME, IT IS A GREAT HONOR TO HAVE YOU FEATURED IN APPLINESS. Thanks for having me! Its an honor to be featured in Appliness. The team has done a great job with the publication. I am currently CTO at Adobe, and joined through the 2005 acquisition of Macromedia. At Macromedia we really helped imagine and push the boundaries of what the Web can be and developed some really great tools for the early Web. Prior to Macromedia, I was with three startups, two of which went public. One of those startups was Frame Technology, which was also acquired by Adobe. Ive been making software since I was twelve, and was lucky to find what I loved to do early in life. At Adobe today Im responsible for shaping our long-term technology vision and focusing innovation across the company amidst an exciting and transformative time. Its not only an exciting time for Adobe but for the entire industry. YOUR CAREER SHOWS A VAST HISTORY OF BLENDING THE CREATIVE WITH THE TECHNICAL. HOW MUCH OF WHAT YOU GET TO DO IS CREATIVE AND HOW MUCH IS TECHNICAL? Great question. To me, creative expression is technical, and at the same time technology opens new doors to creativity. I learned this early on as I worked for a time as a member of the Electronic Visualization Laboratory (http://www.evl.uic.edu) in college. I was an engineer sitting at a workbench right next to artists using the software we developed. They could literally ask for a feature, we would make it, and they would use it in their electronic art project right then. We would also make up new things, like controlling lasers to appear to draw with persistence of vision, and that would drive a whole new round of creations. It was incredibly intertwined. The most successful creative endeavors in technology have this element of interdependency within the work, and the close connection of the engineers and the artists. The intersection is where the magic happens. Adobe is heavily rooted in this blend of creativity and technology, and is what really keeps me so very engaged here. The challenge is finding the balance that enables us to fuel technology innovation with creative thinking and vice versa. We learn from those in our community who are on the leading edge and then work to mainstream those creative approaches in our software. Finding this balance is the heart of what Adobe is all about.

tal number of people connected to the Web, and the technologies and businesses blooming around it. Weve made amazing progress in building a healthy foundation for the Web and advancing technologies to ensure there is a strong future of content creation and app development online. Adobe is investing in making the Web and HTML5 even more expressive. Particularly right now, we are seeing a revolution online into a really modern (or perhaps post-modern) web platform. We are living in an ecosystem of multiple browsers and vast distribution across operating systems, as well as the cross-over from desktop to mobile devices. There is an explosion in design onlinewith richer functionality and embracing motion graphics and responsive layout in the work. This explosion of growth really requires an entire retooling that is focused on the new reality of web development and design. One in which were accounting for multiple screens of different sizes, varying experiences, dynamic content and hardware-accelerated graphics. FOR MANY YEARS, IT FELT LIKE INNOVATION IN WEB STANDARDS WAS STAGNANT, BUT IN THE PAST FEW YEARS, IT HAS BEEN INNOVATING AT A FAST AND ACCELERATING PACE. HOW HAS THIS IMPACTED ADOBE? Yes it has been terrific to see innovation come back on in the web both in standards and in the browsers. Having the browsers back on a rapid release cycle has really helped make the standards real and drives of course the practical reality of what people can express on the Web. For Adobe, the tools that we make continue to help people express themselves creatively on the Weband the more creative experiences that are possible, the more opportunity and need for creative tooling and technologies. The advancement of expression on the Web is a good thing for Adobe and our community. IS ADOBE HELPING TO PUSH WEB STANDARDS TO NEW HEIGHTS?

VISION
WHAT INSPIRES YOU? The rate at which technology is accelerating right now, across many industries, is incredibly inspiring. We are in the midst of several groundbreaking technology transformations across multiscreen, cloud computing, and social computing. These transformations are moving at an incredibly rapid pace and represent more change than Ive seen in the industry ever. Its creating many very exciting opportunities for Adobe and our community. ARE THERE ANY PERSONAL PROJECTS THAT YOU ARE WORKING ON, OR WOULD LIKE TO IF YOU HAD THE TIME?

Yes, absolutely. Adobe is continuing to contribute to the core infrastructure of the web through open source contributions Im very passionate about the new projects Im involved with to WebKit, for example, which is used within the Apple Safari alongside others at Adobe and take these very personally! We browser and Google Chrome. Engineers across Adobe are parare constantly looking to identify and pursue new research or ticipating in working groups and helping the standards develop, technology projectsespecially in the areas of mobile, touch, and were continuing to contribute code to help drive these in cloud, and social computing. browsers. However, something Im particularly excited about right now is the launch of a new site that gives insight into the transformation at Adobe, called Peek (http://peek.adobe.com). Peek is a celebration of the amazing work happening at and around Adobe, and highlights amazing digital content, industry thought leaders, and the artists and creators themselves. New content will be featured every month on Peek as well as blogs and other thoughts from mecheck it out! WE SEE PATTERNS OF ADOBE EXPERTISE AND INNOVATION IN WEB STANDARDS. WILL WE SEE MORE OF ADOBE BRINGING ITS EXPERTISE TO WEB STANDARDS?

Definitely. We are active contributors to moving the web forward, especially in areas where it will enable even greater expressiveness and creativity. The new browser capabilities were seeing lead to new experiences and greater expectations for those experiences. Right now for example, were working with THE WEB HAS BEEN AROUND FOR A WHILE NOW AND HAS W3C to add advanced cinematic features to the web through UNDERGONE RAPID AND DRASTIC CHANGE SINCE ITS EXISCSS Custom Filters, which now includes support for developerTENCE, YET DO YOU THINK WE ARE EXPERIENCING A TIME created custom filters. Our hope is that these will be broadly IN WHICH THERE IS POTENTIAL FOR EXPLOSIVE GROWTH adopted across browsers, and then supported with Adobe tools IN THE WEB? like Edge Animate. Were also focusing on advancing responsive magazine style layouts with CSS Exclusions and CSS Regions, Absolutely, the growth continues to be explosive both in the toPHOTO BY: Umesh Nair

and advancing graphical effects through CSS Blending and CSS Compositing tools. In October, we released a new tool called CSS FilterLab, which allows web designers to quickly learn the syntax of the new CSS Filters specification by using the tools drag-and-drop interface. The built-in filters are already being supported in Safari 6 and Chrome browsers, which means developers can copy/paste the generated CSS code into their pages today. Its very exciting for us that CSS FilterLab is open-source and written in web technologies itselfits posted on GitHub right now if youre interested in checking it out. ONLY A FEW YEARS AGO, WEB DESIGNERS ONLY HAD TO WORRY ABOUT FAIRLY LARGE, LANDSCAPE ORIENTED SCREENS, BUT NOW, THEY HAVE TO WORRY ABOUT SCREENS OF VARYING ASPECT RATIOS AT WIDTHS OF 320 PIXELS ALL THE WAY UP TO 2880 PIXELS. DO YOU SEE THIS CHALLENGE AS AN OPPORTUNITY FOR ADOBE? Yes this is an exciting opportunity, and one we had anticipated and are taking advantage of. There are also varying resolutions in addition to sizes, particularly with newer HiDPI displays. There is indeed an explosion of target screens now for our customers - its no longer one size fits all - so there is a need for responsive design, which is design that responds to the environment its being displayed in. We are working on this across our software and you can see this already appearing in tools such as InDesign, which now supports responsive layout of page designs including the ability to tie together element positioning and indicate where items should move or resize. We also support multiple layout design in Dreamweaver for websites, and in our new generation of tools such as Edge Reflow which is built from the ground up with responsive design as its essence. In some ways, a smaller screen enables a necessary degree of simplification that really helps improve the overall designwhen real estate is premium, more thinking goes into the UI and overall experience as you have to make more choices and prioritize the really key items.

ADOBE IS HEaVILY ROOTED IN THIS BLEND OF CREaTIVITY aND TECHNOLOGY, aND IS WHaT REaLLY KEEPS ME SO VERY ENGaGED HERE.
PHOTO BY: Umesh Nair

CLOUD
HOW IMPORTANT WAS IT FOR ADOBE TO OFFER HOSTED WHAT ROLE DOES CREATIVE CLOUD PLAY IN ADOBES FUSERVICES? TURE AND SUSTAINABLE SUCCESS? Its vitalit is not an overstatement to say Adobe will not survive without reinventing ourselves for the cloud. This is also for touch interfaces. The revolution is afoot and we are changing with it to create the next generation of Adobe. This is actually the fourth reinvention of Adobe since its founding, and we are fortunate our culture embraces change. Creative Cloud is playing a central role in the future of Adobe. It is a reimagining of how we build and deliver our creative software, and is expanding to include a wide variety of hosted services in addition to the classic creative tooling that is familiar to everyone. It also will become a place to be, not just a place to get and use tools, as we establish in Creative Cloud the foundation for the creative community around the world to connect and be inspired by one another. Software in boxes is a technology phase that is in the process of going away. Its already increasingly odd to go to a physical store and buy a box of software. This is much like how other digital The benefits of cloud computing also greatly come into play in media has transitioned from the physical world to the virtual. Creative Cloud, such as online services for file sharing, collaboraEmbracing this change is just one part of our move to the cloud. tion, publishing, automatic feature updates, greater enterprise control, and a more attractive pricing model for customers. We are working on two major cloud efforts, across our creative business and digital marketing business. Creative Cloud is enabling our teams to deliver new capabilities much faster than we could with the major release model of Weve been focusing on transitioning our creative business to shrink-wrapped software. Moving to a membership model is also Creative Cloud, and weve seen huge success alreadymuch enabling access to a number of new customers, and building more than originally anticipated. We have more than 1 million a more predictable recurring revenue business for Adobe. We Creative Cloud customers, a third of which are payingthis is are already seeing great success with the adoption of Creative incredible movement in just the short time since Creative Cloud Cloud. The fact that we were not only able to embrace such a has been available. dramatic change in an approximate $3 billion businessbut that we are already seeing strong adoptionis a good indicator of For marketing we are introducing Marketing Cloud, which en- our success with Creative Cloud. We are embracing the new ables people to get insight on the effectiveness of their creative, world. the relationship to their business, and take action to optimize it. We are also now working to connect these two clouds for our customers to enable even better collaboration across creative and marketing teams. There is no other company making a connection like this today and it will be a great competitive advantage for our customers. PHOTO BY: Umesh Nair

NEXT
WHAT ARE YOUR HOPES FOR 2013? 2013 will be a big year for Adobe, and one in which well see at a much larger scale the success of our business transformation. Strategically, Im continuing to look at technology trends across multiscreen (including touch and mobile), cloud, and social computing and working with our teams to take advantage of these more fully. Well be connecting Creative Cloud and Marketing Cloud to support collaboration across teams, which will be very exciting to deliver. Within Creative Cloud, well also build further on our servicespossibly even looking at new ways in which we could stream our creative applications, for example, through Creative Cloud. And in addition to creative services for professionals, youll be seeing more new software and cloud services from Adobe to enable everyday creativity for everyone. Finally, research and engineering teams at Adobe are continuing to work on some really breakout work for both creativity and in working with big data in marketing. Im looking forward to unveiling some of the things that we have in the works when the time is rightI think everyone will be pleasantly surprised.

THE
WEB.

TOOLS THaT WE MaKE CONTINUE TO HELP

PEOPLE EXPRESS THEMSELVES CREaTIVELY ON THE

PHOTO BY: Umesh Nair

appliness

DONT WORRY, BE APPLI

DESIGNING JAVASCRIPT APIS

WE AT FILEPICKER.IO SPEND A LOT OF TIME THINKING ABOUT APIS. WITH THE RELEASE OF OUR VERSION 1.0 JAVASCRIPT API, WE THOUGHT ABOUT BEST PRACTICES FOR JAVASCRIPT API DESIGN, AND WANTED TO SHARE THEM SO THAT WHEN WE USE YOUR API, ITLL BE JUST AS AWESOME AS WHEN YOU USE OURS. CLICK HERE TO SEE THE ORIGINAL BLOG POST.

RULE 0: NEVER MAKE BREAKING CHANGES TO YOUR API. UNLESS YOU MUST.
An API is a contract between you and the developers who use your product. Dont violate it. Unless its a terrible contract and you would both be better off moving to a better place. The developers building on your API have invested time and energy into learning how to use your product and integrating it into theirs. However as your knowledge about how people are using your product and API grows, the original API will become stale and a refresh will be in order. Wait until the cruft is unbearable, then in one giant leap move as far forward and future-proof as you can. Do it all at once in one clean break. If you can, provide a shim that maps the old API calls to the new one, so that someone can include the new API and a shim and not break any of their old calls. Over the course of our early customer development during YC, the product and feature set was changing so fast it essentially meant we just piled more and more on to the API. It worked, but in dealing with our API, there were all sorts of inconsistencies, rough edges, almost-theres, gotchas, etc. So we made the tough call of redesigning our API from the ground up as a V1, and our developers seem pleased with the result.

by Brett van Zuiden

RULE 1: PROVIDE WOOD AND NAILS, AND A COMPLETE HOUSE FOR YOUR API
Provide high-level functionality that completes a whole workflow in one line of code, and also raw primitives that allow a developer to build up entirely custom functionality. Things in the middle are just frustrating and confusing. If someone comes to you asking for help building a house, there are two useful things you can do for them: give them a house, or give them the tools, instruction, and raw materials they need to build it themselves. If you give them three pieces of wood nailed together, its just frustrating: theyll either find ways to rip it apart into the pieces they need, or theyll have to wedge it into their application in an awkward way. In the case of our API, we used to provide getFile, which would pick a file from Facebook, Google Drive, etc., optionally perform some conversions, and then store the result for you. Because of all the different things it did, configuring it was a mess. The developer had no way of getting progress, using individual components without the rest. Now, we have, amongst others, filepicker.pick, filepicker.store, and filepicker.convert, primitives that you can interweave and cascade as you see fit. We also have the HTML widgets which do the most common case in one line of code, perfect for people who just want basic uploading.

RULE 2: HAVE NOUNS, VERBS, AND A COMPLETE BIPARTITE GRAPH


Spec out what objects you pass around and what operations you can perform. You know you found a good candidate for a complete API when you can perform every action on every object. It helps to think of your API in terms of nouns and verbs which developers can use to form sentences. Draw a grid, with the models/nouns/objects on the one axis and the verbs/actions on the other. Fill in a square if you can perform the given action on the given object. Any blank square will require a special warning in the documentation that explains why you cant perform the action you wanted. It will require the developer to go back to their API docs every time he wants to do this one action you dont allow, and will result in support tickets. If you can fill in every square, consider that a complete block, a good candidate for an API design. In our case, our v0 would sometimes return urls, other time JSON blobs, certain ones could be cascaded into other actions but other ones couldnt. In the new version, everything turns into an FPFile (a JSON format we use as our standard), which can then be used directly in filepicker.store, filepicker.read, filepicker. write, filepicker.convert, and filepicker.export.

RULE 3: WHEN DEALING WITH APIS FAIL FAST, OR BETTER, NOT AT ALL
When dealing with APIs programming errors should throw exceptions immediately. User errors or unexpected situations should pass back errors in a consistent fashion. Be willing to do extra work in the library to follow the principle of least surprise. Your API will thank you. Come up with a consistent way of treating errors, but heres a scheme that we found particularly nice for javascript: Developers should never have to use a try-catch. Exceptions are thrown in situations where the developer made an error (or you made the error of not documenting well enough) and should be alerted as soon as possible. When unexpected things happen or the user does things that are error-like (closing the dialog without choosing something, uploading content that cant be read, etc.), pass back a consistent error type in a consistent way. For us, we have an onError(FPError){} callback on each function. By default the error contains a lookup code, but we also have a filepicker-debug.js library that will automatically inject helpful er-

2/3

ror messages into the FPError.toString() method. This way we keep our library lightweight for production while still helping developers in development mode. When interfacing with the API, see if there are things that your library can do which may take a little bit of extra work on your code, but will catch common mistakes. For instance, if you want to limit the user to only selecting images, you can set {mimetype: image/*}, or {mimetypes: image/*}, or {mimetypes: [image/*]}. The filepicker.read() call accepts FPFiles, URLs, DOM File objects, and DOM input types. If you try to read a file in IE8, rather than fail, the library will jump through hoops to perform the action (see post), but to you the developer, its magic - things just work so you dont have to futz with exceptions and error cases.

RULE 4: IF THE API IS HARD TO USE, ITS NOT GOOD ENOUGH


Use your API as youre building it. Try writing to the API before you even build it, and get some of your lead customers/friends to do the same. The first thing we did in specifying the API was convert all our demos to the new design. If something felt awkward, we redesigned it. The API required too much boilerplate to do simple things, we simplified it. We ran through the same exercise with our customers, writing up a quick guide and having them look at migrating their implementation. It was only after we loved using our API internally and our customers loved it that we built it. This was now fun, because once we had played with what the V1 of our API would be like, we couldnt wait to see it go live. If you want to try it out yourself, check out our documentation page, now with run-able, editable API code samples: https://developers.filepicker.io/docs/web/ In summary: Never make breaking changes to your API. Unless you must. Provide high-level functionality in one line of code, and also the raw primitives. Have nouns, verbs, and a complete bipartite graph. User errors with your API or unexpected situations should pass back errors in a consistent fashion. If your API is hard to use, its not good enough (meaning you have to use it first) Try out the newest version of our javascript API. If youre interested in API design, theres a burgeoning field of Developer Experience that might interest you. John Resig on javascript API design (some is a bit outdated, but good principles): http://www.youtube. com/watch?v=0LKDImgRfrg Pamela Fox on API design at Google, etc. http://vimeo.com/27216846 General information on developer experience for APIs: http://developerexperience.org/

ABOUT THIS ARTICLE


Brett van Zuiden is CEO and Founder of Filepicker.io, a product for developers that helps their web and mobile applications better work with user content, providing an SDK that performs accelerated uploading, image conversion, and integration with cloud sources like Facebook Photos, Dropbox, and Google Drive.

ONLINE RESOURCES JavaScript API on Filepicker.io https://github.com/padolsey/


Demos on Filepicker.io https://www.filepicker.io/demos/ Docs on Filrepicker.io https://developers.filepicker.io/docs/

https://www.filepicker.io/

@FilePicker

appliness

DONT WORRY, BE APPLI

FUN WITH BUILT-IN CSS FILTERS


CSS FILTERS ON IOS6

MAKE SURE YOU HAVE INSTALLED IOS6 ON YOUR IOS DEVICE AND ENJOY THE NEW CSS FILTERS.

With all the buzz around CSS Custom Filters, youre hopefully aware of all the cool effects you can play around with in Chrome Canary using our CSS FilterLab. While we have to wait for CSS Custom Filters to hit mainstream browsers, you can use CSS Filter Lab to play with built-in CSS filters already available in most WebKit browsers today, including Chrome, Safari, and even Mobile Safari on iOS6. These come to us from the world of SVG, where built-in filter shortcuts could be applied to SVG elements, but we will focus on the CSS specification here. Built-in filters are easy to use by simply applying the filter property and using a filter function, which accepts a value as a parameter. This is very similar to how CSS Transforms work. You can even apply multiple filters in the same filter property, the same way you can apply multiple transforms. In these examples, I will be using the un-prefixed filter property, but current release versions of Chrome and Safari use the -webkitexperimental prefix.

by CJ Gammon

PHOTO FILTER DEMO


It is possible to combine these filter functions in interesting ways to simulate complex photo filter effects. You can extend the visuals even further by layering the same element at varying opacity with different filters applied. We used a combination of filter functions to create a Photo Filter demo that we showcased at The Create The Web event in SF. This demo is now available on GitHub. Here is what we used to create an Old-Style photo effect: filter: sepia(0.8) saturate(3) brightness(0.25) contrast(2);

>

You can use many other built-in filter effects in tandem. The available built-in filters are: grayscale sepia saturate brightness contrast opacity invert hue-rotate blur drop-shadow Take a look at our code to find many ways these functions can be used to create complex photo filters. You can also read more about the built-in filters and their values in the specification. As built-in CSS Filters are already available in Chrome, Safari, & Mobile Safari on iOS, you can start playing with them today and see how they can be used to enhance your web application. The CSS FilterLab is a great resource to play with filters and instantly see the results. Now lets try a live demo on your device:
2/3

THE LIVE DEMO


Make sure you are using iOS 6 and play with this live sample:
Filters:

B&W -webkit-filter: grayscale(1); Sepia -webkit-filter: sepia(1); Saturate -webkit-filter: sepia(0.2) saturate(3) contrast(1.2); Old Style -webkit-filter: sepia(0.8) saturate(3) brightness(0.25) contrast(2); Vincent -webkit-filter: hue-rotate(40deg) contrast(3); Arno -webkit-filter: huerotate(200deg) contrast(1.2) saturate(2); Ethan -webkit-filter: huerotate(260deg) contrast(1.2); Soft Blur -webkit-filter: blur(10px) grayscale(0.8);

appliness

DONT WORRY, BE APPLI

GETTING STARTED WITH JAVASCRIPT MAPS


INTRODUCTION TO JAVASCRIPT MAPS

CHECK OUT THESE COOL TOOLS FOR CREATING INTERACTIVE MAPS USING SVG TO RENDER MAPS.

JavaScript amMap is a piece of software for creating interactive maps for your web sites and applications. Its quite different from mapping products like Google Maps, and so is its purpose. We do not provide deep-level maps like Google Maps does. We offer world map, continents map and a lot of country maps with district borders. We do not offer city maps or satellite images, our maps consist of pure country/district areas. Here are some examples of our mapping tool in use: United States Heat Map Interactive Flight Route Map Drill-down map Grouped countries map World capitals map Zooming to countries map Our tool uses SVG to render maps. We do not offer VML which would be needed to support Internet Explorer browses version 8 and older. VML is simply too slow to handle this amount of vector data. Sorry legacy browser lovers ;)

by Antanas Marcelionis

CREATING YOUR FIRST MAP


Download amMap package, unzip it to some folder and copy ammap folder to your working directory. Now open your HTML file (I will assume that it is in the same level where you copied ammap folder). First, you should include ammap.js into header of your HTML: <script src=ammap/ammap.js type=text/javascript></script> In case you are using our amcharts js file in the same page, you can insert ammap_amcharts_extension.js instead of ammap.js this will save you ~50 kilobytes. Remember, you have to insert ammap_amcharts_ extension.js after amcharts.js (or amstock.js) file! Next, you have to insert map file too. Actually there are two ways of using maps you can load SVG files at runtime or insert maps as .js files. We recommend inserting maps as .js files as it is much more reliable - some servers do not like SVG format. Also you will not be able to test maps without web server if you load them as SVG. To insert map file as .js file simply add this line to your HTML (after the line where you inserted ammap.js file!): <script src=ammap/maps/js/world_low.js type=text/javascript></script> You can use any other map just go to the ammap/maps/js folder and check the available maps (we are adding new maps constantly). Side note: we include two versions of each map high detail and low detail. Normally you should always use maps with _low suffix as they are faster and less resource-intensive. If your particular purpose calls for for greater detail and youre willing to potentially sacrifice some performance for it, go with the _ high version. In case you wish to load maps as SVG files read on, well cover this a bit later. Next, you should create a div which will hold your map. Add this to your HTML body: <div id=mapdiv style=width: 600px; height: 400px;></div> Now well do some JavaScripting. Below is a script with comments which should produce a simple World map: // add all your code to this method, as this will ensure that page is loaded AmCharts.ready(function() { // create AmMap object var map = new AmCharts.AmMap(); // set path to images map.pathToImages = ammap/images/; /* create data provider object mapVar tells the map name of the variable of the map data. You have to view source of the map file you included in order to find the name of the variable - its the very first line after commented lines. getAreasFromMap indicates that amMap should read all the areas available in the map data and treat them as they are included in your data provider. in case you dont set it to true, all the areas except listed in dataprovider will be treated as unlisted. */

2/8

var dataProvider = { mapVar: AmCharts.maps.worldLow, getAreasFromMap:true }; // pass data provider to the map object map.dataProvider = dataProvider; /* create areas settings * autoZoom set to true means that the map will zoom-in when clicked on the area * selectedColor indicates color of the clicked area. */ map.areasSettings = { autoZoom: true, selectedColor: #CC0000 }; // lets say we want a small map to be displayed, so lets create it map.smallMap = new AmCharts.SmallMap(); // write the map to container div map.write(mapdiv); }); Now, if you open your HTML file in a browser, you should see this:

Try to click on any country the map will zoom-in on it. You can also drag, pan the map or click on a small map to move the big one to the desired position. In case you dont see the map, check error console most likely it will show some errors. Its a first to-do if something is not working.

3/8

LOADING SVG MAPS


In case you wish to load SVG maps instead of including them as .js file, all you need to do is to change mapVar of your data provider to mapURL and specify path to the SVG map, for example: mapURL: ammap/maps/svg/world_low.svg, However, as we mentioned, its not as reliable as including maps as .js files.

MANIPULATING AREAS (COUNTRIES)


Lets say we want to change color of some of the countries. This should be done by adding these countries to data provider and specifying color of your choice. Map data provider is an instance of MapData object, check our docs to find more of what it is capable of. Each country/area has an id. For world map we use ISO country codes like US, UK, DE for ids. For countries administrative areas we use ids like AU_WA where AU is ISO code of the country (Australia in this case) and WA is id of the administrative area. All the available areas are listed in each maps .js and .svg files, in JavaScript array which you can copy/paste directly to data provider. I left only some of the countries, as I dont need them all: var dataProvider = { mapVar: AmCharts.maps.worldLow, areas:[{id:AU},{id:US},{id:FR}] }; Note, I deleted getAreasFromMap:true from data provider, as now I want all the areas except those three to be inactive. The result is this:

4/8

All the areas except listed are now grey. This color is set via AreasSettings unlistedAreasColor property. You can also control opacity, outline color and opacity of unlisted areas. The three areas we included are colored with color set via color property of AreasSettings. Check all the available properties to get impression of what else you can change. As you have correctly guessed, the settings you set for AreasSettings are applied for all listed areas, but only if you dont set some property of the area explicitly. Each country/area object listed in your data provider is an instance of MapArea. Check docs to see list of available properties. Lets say we want each of the three countries to be filled with a different color. The property responsible for this is color (surprise!). So we modify data provider by adding color with some HEX color code to each country: var dataProvider = { mapVar: AmCharts.maps.worldLow, areas:[{id:AU, color:#CC0000},{id:US, color:#00CC00},{id:FR, co lor:#0000CC}] }; And the result is now:

You can modify color, opacity, title (titles are hardcoded in a map, but you can simply change them using title property), add description which will popup if user clicks on a country and do a lot more.

ADDING AN IMAGE TO A MAP


Lets say I want to add some icon on the map in the place where New York City is. This will also be done via data provider, images property. Images are instances of MapImage object. Images can be placed in two ways by setting its position using left/top/right/bottom properties or by setting latitude and longitude. If you set latitude and longitude, the image will be bound to the map position it will move to-

5/8

gether with it. Otherwise the image will stay in the same place. As I want to mark New York City, I need to set latitude and longitude. So I went to Wikipedia and found that latitude is 40.3951 and longitude is -73.5619. MapImage has type property which can be set to one of the three values: circle, rectangle and bubble. I choose bubble this time and set its color to velvet: var dataProvider = { mapVar: AmCharts.maps.worldLow, images:[{latitude:40.3951, longitude:-73.5619, type:circle, color:#6c0 0ff}] }; Note, I deleted areas so that they wouldnt steal your attention. And here is the result:

As you can see, there is a red circle in the place where New York City is! Most of the maps we provide are calibrated, so real world latitudes and longitudes can be used. Only some of the maps for some technical reasons can not be calibrated (for example map of US where Alaska an Hawaii are shifted so that they would be close to mainland). You can still find longitudes/latitudes (and also a lot more information required to build maps) both for calibrated and non-calibrated maps using developer mode. Check developerMode.html example in samples folder to see it in action. Now I want to change the red circle to some more interesting picture. You can load gif, png, jpg or svg files by setting imageURL for your image with path to the image. However loaded images have limitations you can not change colors, set outline and some more. The recommended way of adding singlecolor images to the map would be creating variable of SVG path and setting it via svgPath property of MapImage. I recommend visiting Raphaels icons set page to get SVG paths for a lot of nice icons. Simply choose the icon you like and copy the path. Then you can create variable (so you could use it more than once) and set this variable as svgPath of your image:

6/8

var icon= M21.25,8.375V28h6.5V8.375H21.25zM12.25,28h6.5V4.125h6.5V28zM3.25,28h6.5V12.625h-6.5V28z; var dataProvider = { mapVar: AmCharts.maps.worldLow, images:[{latitude:40.3951, longitude:-73.5619, svgPath:icon, color:#CC0000, scale:0.5, label:New York, labelShiftY:2}] }; Note, I deleted type (we dont need it anymore) and set scale to 0.5 so that the icon wouldnt be too big, I also added label property with value New York and adjusted labels vertical position by 2 pixels so that it would fit better. And the result (after I manually zoomed in) is:

ADDING SOME INTERACTIVITY


Now I want to make the New York icon clickable and I want the map to zoom-in and display some more information when user clicks on it. MapImage has all the properties you need to do that: value set as description will be displayed in a popup window, zoomLevel will tell how much do you want to zoom-in:
var icon= M21.25,8.375V28h6.5V8.375H21.25zM12.25,28h6.5V4.125h6.5V28zM3.25,28h6.5V12.625h-6.5V28z; var dataProvider = { mapVar: AmCharts.maps.worldLow, images:[{latitude:40.3951, longitude:-73.5619, svgPath:icon, color:#CC0000, scale:0.5, label:New York, labelShiftY:2, zoomLevel:5, title:New York, description:New York is the most populous city in the United States and the center of the New York Metropolitan Area, one of the most populous metropolitan areas in the world.}] };

7/8

Now, after you click on New York icon, the map will zoom in and display description:

Thats it for this tutorial. You can do a lot more drill-down maps, heat maps. Not only you can display images but also draw lines on top of the map. You can use amMap together with amCharts and create stunning data visualizations. Good luck!

ABOUT THIS ARTICLE


Antanas Marcelionis failed as a blogger and has decided he likes coding more. His company, amCharts, based in Vilnius, Lithuania had its beginnings in 2004 when Antanas created the first version of amMap. In 2006, Antanas left his job as a manager at a web development company & the rest is history. http://www.amcharts.com/
@marcelionis

ONLINE RESOURCES amCharts official website http://www.amcharts.com/ amCharts blog http://blog.amcharts.com/ SVG official website http://www.w3.org/Graphics/SVG/

appliness

DONT WORRY, BE APPLI

BUILDING YOUR FIRST BRACKETS EXTENSION

BRACKETS IS AN OPEN SOURCE CODE EDITOR FOR THE WEB, WRITTEN IN JAVASCRIPT, HTML AND CSS. DAVID EXPLAINS IN THIS ARTICLE HOW TO WRITE CUSTOM EXTENSIONS FOR THIS IDE USING WEB STANDARDS.

BRACKETS, THE OPEN SOURCE IDE FOR THE WEB


Brackets, the new open source code editor for the web, takes extensibility very seriously. In fact, some of its core features are implemented as extensions, such as Quick Open, Quick Edit, and HTML Code Hinting.

Brackets has a highly modular architecture that enforces separation of concerns by keeping the Brackets main code as focused as possible, while it is still deeply customizablean absolute requirement to fit modern web developers needs.

You may notice, however, that while Brackets comes with some default extensions, out-of-box it still might seem a bit limited. For that reason, the first thing new users can do is to install extra extensions, as described in my blog post: Brackets/Edge Code extensions you should install right now. By doing so, you will have access to extensions, such as string manipulation or code snippets.

That said, as a user, youll probably quickly find yourself thinking if only Brackets could X... how hard can it be? Well, since Brackets is built using web standards, as described in the article, Brackets: The Open Source Code

by David Deraedt

Editor for the Web, by Adam Lehman, customizing it by yourself is far easier than you might imagine. Its also a very rewarding experienceone you can quickly get hooked on.

In this article, well take a look at how Brackets extensions work, how you can build one using a template or starting from scratch, and how to best set up your development environment.

Note: While Edge Code is a Brackets distribution that you can use to potentially build extensions too, it does not come with a Debug menu, making it less convenient than Brackets for the job of writing extensions. You can, however, use any extension you create with Brackets within Edge Code. This article was written using Brackets Sprint 16..

EXTENSIONS LOCATION
Technically speaking, an extension is nothing more than a folder containing a JavaScript file named main. js, which is executed by Brackets at startup.

When it finished loading and executing the rest of its code, the application will look for those extensions in the following folders: - The default extensions folder (src/extensions/default). This folder contains default extensions that the Brackets team has chosen. Users should not put anything in this folder. - The user extensions folder (/Users/<user>/Library/Application Support/Brackets/extensions/ user on OSX or C:\Users\<user>\AppData\Roaming\Brackets\extensions\user on Windows 7). Brackets users put downloaded third-party extensions from Github within this folder. For convenience, Brackets automatically opens this folder when you select Help > Show Extensions Folder. - The extension development folder (src/extensions/dev). As an extension developer, you place your own extensions within this folder. This is a more convenient place for them than the user extension folder, which ties into the user system. Note that Brackets provides a place for disabled extensions, at src/extensions/disabled, which makes it easy to temporarily disable extensions without having to delete them altogether.

2/8

SETTING UP BRACKETS FOR DEVELOPMENT


To debug an extension within Brackets, use the following steps. 1. Within Brackets, select Debug > Show Developer Tools to open the Chrome developer tools. Note that, in the current version (sprint 16), Brackets opens the Chrome developer tools in a Chrome browser window (or opens Chrome if it was closed). On Macintosh, if you use Spaces, ensure that you have a Chrome window open alongside Brackets.

2. I strongly recommend that you disable the cache in the developer tools tab opened from Brackets, otherwise you wont be able to test your changes, even after reloading the application. You can do that from the developer tools option panel.

3. Youll quickly realize, however, that writing code and testing the result within the same editor window is just not the way to go. This is exactly why it is preferable that you open a New Brackets Window under the Debug menu, but selecting Debug > New Brackets Window (Figure 4).

I also strongly recommend testing from this second window. To do so correctly, you must set up the developer tools from this window, as explained in step 1. My typical setup looks like the following:

WORKING FROM A BRACKETS REPOSITORY CLONE


Another good practice is to develop your code from a separate copy of the Brackets source. The advantage is that you can work with the latest version of the application code, ensuring your extension is upto-date. You also avoid having to edit the original application source, which could have some undesirable effects. A simple way to work from a Brackets repository clone would be to just fork or clone the Brackets repository from GitHub as described in the following steps. 1. Go to the Brackets repository from GitHub. 2. If you have the GitHub client for Mac or GitHub client for Windows, simply click the Clone in Mac or Clone in Windows button (depending on your platform) from this repo homepage, and choose and a local destination on your disk.

3. Specify that Brackets should run this code instead of the default application contents by pressing shift while you launch the app. To better understand what I mean by this, it is important to understand that the Brackets application is actually made up of two parts: - On the one hand, you have the Brackets shell built with the Chromium Embedded Framework, which executes local web content within a native desktop application shell.

- On the other hand, you have local web content such as HTML, CSS, and JavaScript files, which are the Brackets editor source code. By default, the Brackets shell executes the web files stored within the application content folder, which was created when the application was installed. It is not recommended that you edit code directly from this folder, however. As a result, the native application has the capacity of running from within a different source folder by pressing and holding the Shift key while launching the app. Alternatively, you can use the setup_for_hacking script included under the tools folder of the application source code. You can get this script in from the article, How to Hack on Brackets, on GitHub.

USING AN EXTENSION TEMPLATE


While you can of course write an extension from scratch, its preferable to start with a template. Several options are available for you to choose. A typical way to begin with extension development is to copy and paste an existing extension relatively close to what you want to achieve. This is a valid way to get started, but keep in mind that not all extensions are up to date, and that not all necessarily showcase the latest best practices. Also, some extensions can be really hard to read, especially if youre new to extension development. Alternatively, you can use the Brackets Extension Toolkit, which provides you with a dedicated template, which you can just drag and drop to the src/extensions/dev folder. The toolkit also comes with heavily commented code to guide you through your first development experience of extensions, and the toolkit also provides related helper tools. Whatever option you choose, once youre relatively comfortable, I recommend storing your own custom template in the src/extensions/disabled folder to access it quickly later. Simply copy it to the user extensions folder.

INTRODUCTION TO THE BRACKETS EXTENSION API


If you look at an existing extension for the first time, chances are that youll feel a bit lost. Brackets extensions are JavaScript modules as specified by RequireJS Simplified CommonJS Wrapper. Understanding JavaScript modules is outside the scope of this tutorial, however, for more information, see Modern Modular JavaScript Design Patterns, by Addy Osmani. For demonstration purposes, lets assume that in its simplest form, an extension would look like the following: define(function (require, exports, module) { use strict; // Extension code goes here console.log(Extension initialized); }); All the code within the body of the anonymous function inside the define call executes at application startup. Of course, most of the time, what you want to build is an extension that makes it possible to execute some code when another part of the application invokes the extension. For example, when a user selects a menu item, this causes your application to execute an action.

You can code this kind of mechanism through commands. You register a command ID with a function so that when the app invokes the ID, a function executes. This is the job of the CommandManager. As with pretty much everything in Brackets, the CommandManager itself is a module. To access other modules from an extension, simply call the dedicated brackets.getModule() method, passing to the method the path to the module relative to the src folder. Notice how the code below does not specify the JS file extension. var CommandManager = brackets.getModule(command/CommandManager); To specify to the CommandManager which function to execute, and when, specify the register(name, command_id, function) method. The parameters within this method are as follows: The name parameter is a readable user-friendly name, which is also used as a menu label in the user interface. The command_id parameter is a string to uniquely identify this command. Format it as follows: [author]. [my_extension].[menu_name].[my_command_name]. The last parameter, function, is the function the method calls when a user selects a menu item in the UI. When a user selects a menu item in the UI, the app automatically calls execute(command_id) method with the corresponding ID, as shown in the following code example. var COMMAND_ID = dderaedt.tutorialExt.logHelloWorld.logHelloWorld; var COMMAND_NAME = Log Hello World; function sayHello() { console.log(Hello World); } CommandManager.register(COMMAND_NAME, COMMAND_ID, sayHello); At this stage, the extension is functional but will never be called since something must invoke the command ID. To do so, we add a menu item through the Menus module to invoke the corresponding command ID, resulting in the execution of the function. To do so, well first access the Menus module, as follows: var Menus = brackets.getModule(command/Menus); Then, well get a handle to the menu we want to add our item to (the File menu, in this example). var fileMenu = Menus.getMenu(Menus.AppMenuBar.FILE_MENU); Finally, we simply add an item corresponding to the command that we wish to trigger, as follows: fileMenu.addMenuItem(COMMAND_ID); The resulting code for this Hello World extension is as follows: define(function (require, exports, module) { use strict; var CommandManager = brackets.getModule(command/CommandManager); var Menus = brackets.getModule(command/Menus); var COMMAND_ID = dderaedt.tutorialExt.LogHelloWorld;

var COMMAND_NAME = Log Hello World; function sayHello() { console.log(Hello World); } CommandManager.register(COMMAND_NAME, COMMAND_ID, sayHello); var fileMenu = Menus.getMenu(Menus.AppMenuBar.FILE_MENU); fileMenu.addMenuItem(COMMAND_ID);

});

EDITING THE CURRENT DOCUMENT


Now, to do something slightly more useful, lets pretend we want our extension to generate some code inside the current document.

In Brackets, files opened in the tool are represented as instances of the Document class. To get a reference to the current document (in other words, the file the user currently has open and editing), we need to use the DocumentManager module. First, we must get a reference to this module, which is inside the document folder. var DocumentManager = brackets.getModule(document/DocumentManager); Now, starting from the code in the previous section, rename the sayHello() function to addSomeText(). The first thing well need to do inside this function is get a reference to the current document. var currentDoc = DocumentManager.getCurrentDocument(); Now you can use the Document API, which can help you work with the text content. Here are some of the available methods: - getText() returns the whole text content - setText() set the whole text content - getRange(start, end) returns part of the text content - replaceRange(text, start, end) replaces text in a given position Note that the position in the text (such as the start and end parameters above) are expressed through a position object, which contains two properties: line, the line number, and ch (the character number). In the following scenario, pretend that we want to generate a one-line comment at the location of the current cursor position. Since the Editor object manages code editing, you must get access to the current editor instance as returned by the EditorManager.getCurrentFullEditor() method. So after you make sure to import the corresponding module, as follows: var EditorManager = brackets.getModule(editor/EditorManager);

You can access the editor for the current document, as follows: var editor = EditorManager.getCurrentFullEditor(); Finally, you can then use the editor to do all sorts of operations related to text selection, such as: - getSelectedText() - setSelection(start, end) - selectWordAt(position) - getCursorPos() Now that you have access to all you need, you can rewrite the addSomeText() function, as follows: function addSomeText() { var currentDoc = DocumentManager.getCurrentDocument(); var editor = EditorManager.getCurrentFullEditor(); var pos = editor.getCursorPos(); } currentDoc.replaceRange(//Black magic. Do not modify EVER, pos);

WHERE TO GO FROM HERE


Of course, such simple examples will only get you so far. Youll quickly need to learn more about the APIs exposed by other modules. The following are some useful resources to learn more about it: Brackets source code itself is, of course, the ultimate and only 100% reliable source of information. If you installed the Brackets extension toolkit, simply select Help > Open Brackets src. Start by taking a look at Document, Editor, EditorManager, FileUtils and of course all the default extensions. The Brackets wiki is full of useful information. In particular, the How to write extensions page covers the basics you should know about. The Brackets extension toolkit includes a shortcut to this wiki under the Help menu. If you intend to make an extension that edits the code for the current document, its a good idea to get familiar with CodeMirror, the project responsible for the underlying code editing logic. To understand how Brackets works at a higher level, learn more about the Brackets general architecture in the article, An overview of Brackets code architecture. Finally, if you plan to include some UI in your extension, be sure to check the Extension UI Guidelines draft on the Brackets wiki.

appliness

DONT WORRY, BE APPLI

CLEARING FLOATS: WHY IS IT NECESSARY EVEN IN MODERN BROWSERS?


READ HOW TO GET YOUR PHONEGAP APPLICATION APPROVED BY APPLE.

The other day, someone asked me the following question:

If youre new to CSS, then it would seem that the answer to this question should be yes, of course modern browsers dont have these types of bugs! But the necessity to clear floats is not a browser bug; its actually, well, more of a CSS feature. And its still needed in so-called modern browsers (assuming youre using floats for layout). This doesnt mean, though, that clearing floats will always be necessary. The eventual goal of CSS layouts is to never need to use floats for layout. Instead, we want to be able to use a better method. But clearing floats are a fact of developer lives today, and so I thought Id explain why clearing them is still necessary, even in modern browsers.

WHAT DOES A FLOAT DO?


Here is, in part, how the W3C spec explains what floats do:

f I understand it right clear float is automatic in most modern browsers right?

ontent flows down the right side of a left-floated box and down the left side of a right-floated box Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float didnt exist.

by Louis Lazaris

You can see this behaviour demonstrated in the JS Bin below:

Change my CSS!

Or, visit the live sample on the web: http://jsbin.com/azuwul/1/edit. Notice that the green box is acting as if the red box is not even there, rather than flowing around it like the text does. This is what floats do: They cause other floated elements and inline content to flow around the float, but other block boxes ignore the float. The only problem I have with the W3C definition is that it sounds like its talking about absolutely positioned elements. So it seems that floats should have a different wording ascribed to them. I prefer to say that floats are taken out of the normal flow in relation to sibling block elements. Regardless of the explanation, you should be able to see that no matter how far browsers advance, they will never clear floats automatically (as the original question seemed to assume) because the behaviour of floats is not a bug; its a feature. As Scott points out in the comments, it looks like there will indeed be an easy way to clear floats, using the contain-floats value for the min-height property. Interesting stuff. I believe this specification is only a month or two old, so I dont expect browsers to have support for this any time soon. But good to know.

FLOAT CLEARING METHODS


To round this post out, lets cover the most popular methods for clearing floats. clear: both/left/right The primary way to prevent an element from flowing alongside a floated sibling is to use the clear property. Any value other than none will clear the element that you want to follow the float (rather than bump up against it).

2/3

overflow: hidden/auto The main problem with floats is what you might refer to as the collapsing container, which causes background elements to disappear. In this case, you dont have a trailing element that you can clear to fix this. But instead, you want the parent element to fully contain all the floated children. In this case, at the very least youll need to use the overflow property. Using a value of hidden or auto, the parent will expand to contain all floated children. Although this is probably the easiest way to clear floats, its really not recommended, because of the problem of scrollbars appearing or child elements being cut off due to positioning, margins, or CSS3 transforms. I think the only time I would consider using this one is for a small widget-like box in the page that has floated children (like a tab switcher or something like that), where I know that positioned elements and margins are not going to be a problem. clearfix The best method to use to clear floats is the clearfix method. I cant remember who originally came up with this, but the most updated and optimized syntax that works in all browsers is the one proposed by Nicolas Gallagher and used in HTML5 Boilerplate. Heres the code: view plain? .clearfix:before, .clearfix:after { content: ; display: table; } .clearfix:after { clear: both; } /* For IE 6/7 only */ .clearfix { *zoom: 1; } With that in your CSS, all you have to do is add a class of clearfix to any element that is collapsed due to floated child elements. Again, you could use the overflow method instead, but its not universally ideal. Ive found it causes too many problems in complex layouts.

TO SUM UP
Yes, float clearing is still necessary in modern browsers, and the best method is the clearfix method. But eventually, we want all in-use browsers to support an alternative, more intuitive method for doing CSS layouts, so we dont have to worry about hacks and workarounds to fix these types of problems. Post excerpt photo credit: Root beer float from Bigstock.

ABOUT THIS ARTICLE


Louis Lazaris is a freelance web developer based in Toronto, Canada. He blogs about front-end code on Impressive Webs. Most recently, he has co-authored a book on front-end development published by SitePoint, called HTML5 & CSS3 for the Real World.

ONLINE RESOURCES Using Absolute Positioning in CSS http://www.impressivewebs.com/absolute-position-css/


The Difference Between Block and Inline http://www.impressivewebs.com/difference-block-inline-css/ How Do Browsers Render the Different CSS Border Style Properties? http://www.impressivewebs.com/comparison-css-border-style/

http://www.impressivewebs.com/

@ImpressiveWebs

appliness

DONT WORRY, BE APPLI

MISSION: IMPOSSIBLE IPAD MINI DETECTION FOR HTML5

AS YOU MAY KNOW, THE IPAD MINI IS A NEW 7.9 VARIANT OF THE IPAD TABLET AND ONE OF THE BIGGEST QUESTIONS OUT THERE TODAY IS HOW TO DETECT IT USING SERVER-SIDE OR CLIENT-SIDE TECHNIQUES.

MISSION IMPOSSIBLE?
I have bad news for you: it seems impossible. Two days ago, Ive tweeted about the first detected problem: It is confirmed that the iPad mini User Agent is the same as the iPad 2. Ive received literally hundreds of answers saying that user agent sniffing is a bad practice, that we should detect features not devices, etc, etc. Well yes guys, you are right, but it has no direct relationship with the problem. And I need to add the second bad news: there is no client-side technique to make feature detection either.

WHY DO WE NEED TO DETECT THE IPAD MINI IN FIRST PLACE


The iPad mini has no Retina display - the name that Apple gives to high resolution devices - and its an iPad 2 clone in terms of resolution: 7681024 pixels. The biggest difference is that while iPad 2 is 9.7; the iPad mini is 7.9.

by Maximiliano Firtman

While its true that the difference between iPad 2 and iPad mini (1.8 or 4.57cm diagonally) is not so big compared to other series (Nexus 7 and Nexus 10 difference is 3), we need to understand that everything looks 19% smaller on the iPad mini, including text and touch areas. (Update: real demo of this difference) Ok, you are right; we dont really need to care about iPad mini vs. iPad 2 in terms of the device itself, but we do need to care about the dpi difference. Designers should want to make some things larger so they can be read properly, or to make touchable areas larger to avoid usability problems. Second reason is analytics: some companies want to store information about users devices to make some decisions and in this case tablet size and factor, or device release date may be something useful. I know this is not a big problem, but it still sounds like an issue for some website and app owners.

HOW TO DETECT A FEATURE OR A DEVICE


There are several mechanisms to make feature and device detection and its a long story. I have a full chapter on this topic in the second edition of my book Programming the Mobile Web (available today as a prerelease draft version). We should always prefer feature detection against device detection; but on some specific situations device detection is the only way to go. When talking about server-side detection, the User Agent and/or device libraries, such as ScientiaMobiles WURFL is the way to go. The User Agent thing is a mess and there is no simple rule to follow and, when a company like Apple decides to use the same User Agent for all devices, there is no server-side only solution that can help us. In this particular case, all the iPads out there, from the first to fourth generation and the iPad mini uses the same User Agent. The only difference is the iOS version that they have. I know many of you are thinking: I dont care about server-side detection, a good practice following RWD - Responsive Web Design - principles is to use media queries or at least JavaScript to detect features. Well, the big bad news appears: there is no way to detect iPad mini unique features (dpi, screen size in inches/cm). Lets see why. USING RESOLUTION MEDIA QUERIES CSS3 Media queries includes a resolution attribute that we can query on. The iPad Mini has a 163 dpi resolution screen while iPad 2 has 132 dpi. Great! We have the solution well, the resolution attribute is not available con WebKit-based browsers, such as Safari on iOS. No way to use it. USING DEVICE PIXEL RATIO After that, we think on a non-standard media query extension: the device pixel ratio. High-resolution iPads expose a 2 value from both media queries and JavaScript for the device pixel ratio. Well, iPad mini and also iPad 2 both expose a value of 1; so we cant rely on this property neither. USING INCHES OR CENTIMETERS UNITS The other solution about dimensions in in (inches) or cm (centimeters). Well, trying to draw a 10 inch element on the screen, such as in width: 10in; Ive got same results on both devices (that is, on the iPad mini the div is 19% smaller). UPDATE: In the CSS3 spec, inches or centimeters units might not match the physical size if the anchor unit is the pixel. Therefore they are useless on these devices.
2/3

Both iPad 2 and iPad mini exposes same device-width and device-height in inches and centimeters (its matching the pixel values) while we know that is completely false. The following media query is true for all the iPads: only screen and (min-device-width: 8in) And the iPad mini has a device width smaller than 5.3 inches, so the query should be false in a first quick thought. And with font size and font adjustment, the results are also exactly the same. There is no special text adjustment for the iPad mini and its using the same values. If you want to try the media queries values yourself visit mediaqueriestest.com or m.ad.ag from your mobile device.

APPLE WHY?
I know some of you will find some obscure reasons, but the official reason is to reduce iOS fragmentation. From a developer and designer perspective we have only two devices: iPhones (including iPod touch) and iPads. Thats all you need to know from an Apple perspective to design and develop a website or an app. While is not a bad idea in a first thought, the iPad mini has a different screen size and that should be honor by the media queries at least. To make a final conclusion, the problem is not that we cant detect iPad mini; the problem is that we cant detect its unique features, such as density and real dimensions that are important for delivering the best possible experience one ach device using responsive web design techniques.

SOLUTIONS?
People were asking by Twitter how to deal with this. Well, I can only think on some suggestions: 1. Dont disable zoom ability in the viewport metatag, such as in user-scalable=no. 2. If you have text, offer the user the ability to increase and decrease font size and store the settings in Local Storage or a cookie for next visit. It can be easily implemented using JavaScript and you can change font-size or -webkit-text-size-adjust. PS: Dont get me wrong Ive tried the iPad mini and I like it; it feels good and the screen is much more useful than other 7 similar tablets.

ABOUT THIS ARTICLE


Max Firtman is a mobile+web developer, trainer, speaker and writer. He is Nokia Developer Champion, Adobe Community Champion and founder of ITMaster Professional Training. He wrote many books, including Programming the Mobile Web published by OReilly Media and jQuery Mobile: Up and Running.

http://www.mobilexweb.com/

@firt

appliness

DONT WORRY, BE APPLI

TUTORIAL: EMBED PHONEGAP AS A SUBVIEW IN YOUR NATIVE IOS APPLICATION


READ HOW TO SET PHONEGAP AS A WEB SUBVIEW OF A NATIVE APPLICATION.

Something cool that many mobile developers (and particularly native developers) might not be aware of at this point, is the option to use PhoneGap (aka Cordova) as a component within your mobile application, as a web subview of a whole native application where you want to render HTML/JS content and/ or interact with the PhoneGap APIs. In this webview component (sometimes also referred to as Cleaver), you can do anything a traditional PhoneGap application would do, such as access native features like the camera or contacts etc too. This post will expand the steps here and show you a sample application you could download and try yourself. Note that I am not an Objective-C native programmer, but this is just a simple example to show off the capabilities and create awareness. Feel free to post your application or source if you have used this and would like to share with others.

STEPS TO EMBED CORDOVA WEBVIEW


Below are detailed steps on including PhoneGap/Cordova as a web subview in your native application. At the end of this section I show screenshots from a sample application I made available on my github account for you to try this out yourself or refer to things as needed. 1. Create your base native iOS application in XCode (version 4.5 recommended) unless you just plan to add to an existing native application. In my case I chose to create a new Single View Application in XCode such as the following:

by Holly Schinsky

2. Download and extract the Cordova source to a permanent folder location on your hard drive (for example: ~/Documents/Cordova). NOTE: Youll need this for copying Cordova resources into your native application.

3. Close any other Cordova projects and exit XCode (XCode can be quirky, a restart often clears up potential or possible errors). 4. Navigate to the directory where you put the downloaded Cordova source above and copy the Cordova.plist file into your native application folder on the file system (at same level as the AppDelegate files etc, see picture below). Note: you could also use a Cordova.plist from a newly created Cordova application.

2/11

NOTE: This file contains specific Cordova property settings and plugins required for your application to use Cordova. 5. Drag and drop the Cordova.plist file into the Project Navigator of Xcode. 6. Choose the radio-button Create groups for any added folders, select the Finish button. 7. Go to the downloaded source from the previous step above and locate the CordovaLib.xcodeproj in the CordovaLib sub-folder. Drag and drop the CordovaLib.xcodeproj file into the Project Navigator of XCode (at the same level as the .plist file copied in above again choosing Create groups for any added folders). 8. Select CordovaLib.xcodeproj in the Project Navigator. 9. Open the File Inspector with Option-Command-1 or by going to View | Utilities | Show File Inspector. 10. Ensure that it says Relative to Group in the File Inspector for the Location drop-down menu similar to below:

11. Select the project icon in the Project Navigator, select your application under TARGETS (should have an A next to it), then select the Build Settings tab as shown below:

3/11

Locate the setting for Other Linker Flags (under the Linking section) and double-click the value text field to bring up the box to enter the flags -all_load and -Obj-C as shown here:

Select the project icon in the Project Navigator, select your target, then select the Build Phases tab. 12. Expand Link Binaries with Libraries. Select the + button, and add these frameworks (and optionally in the Project Navigator, move them under the Frameworks group): AddressBook.framework AddressBookUI.framework AudioToolbox.framework AVFoundation.framework CoreLocation.framework MediaPlayer.framework QuartzCore.framework SystemConfiguration.framework MobileCoreServices.framework CoreMedia.framework

4/11

Now expand Target Dependencies. Select the + button, and add the CordovaLib build product.

13. Expand Link Binaries with Libraries again and add libCordova.a. 14. Go to Xcode Preferences -> Locations -> Derived Data -> Advanced and ensure it is set to Unique. 15. Go back to Build Settings and locate the Header Search Paths and ensure the following properties are set (including the quotes): $(TARGET_BUILD_DIR)/usr/local/lib/include $(OBJROOT)/UninstalledProducts/include $(BUILT_PRODUCTS_DIR)

5/11

The result should look like the following:

CODE ADDITIONS
To actually use the subview, you need to add the following Objective-C code where you want to include it. IMPORT THE FOLLOWING HEADER #import <Cordova/CDVViewController.h> INSTANTIATE A NEW CDVVIEWCONTROLLER CDVViewController* viewController = [CDVViewController new]; SET UP THE VIEW FRAME viewController.view.frame = CGRectMake(0, 0, 320, 480); LASTLY, ADD TO YOUR VIEW AS A SUBVIEW [myView addSubview:viewController.view]; You could optionally set the www folder, start page or option to show the splash screen to something other than the default (default folder is www, start page is index.html and splash screen is no) on that CDVViewController as well with the following lines: viewController.wwwFolderName = @myfolder; viewController.startPage = @mystartpage.html; viewController.useSplashScreen = YES; Heres an example of actually implementing those lines above in my ViewController.m class that is created with a new native XCode Single View project like discussed above (the added code is in the viewDidLoad function):
6/11

#import ViewController.h #import <Cordova/CDVViewController.h> @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; CDVViewController* viewController = [CDVViewController new]; viewController.view.frame = CGRectMake(0, 40, 320, 450); [self.view addSubview:viewController.view]; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)inter faceOrientation { if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfa ceIdiomPhone) { return (interfaceOrientation != UIInterfaceOrientationPortraitUpsid eDown); } else { return YES; } } - (void)dealloc { [super dealloc]; } @end

7/11

NOTE: Since we added the above code to create a new CDVViewController into our main ViewController, we could reuse this class anywhere in our application and it will automatically include the Cordova subview. In the storyboard file in XCode (the UI environment), you can actually set the class of any given View Controller object to ViewController and you will get a new Cordova WebView subview component automatically due to this code. You can simply set the class to it if its not selected already in the Identity Inspector as shown here:

In my sample application you can see it when you press the Open a new Cordova WebView button. You could choose to add this code wherever you need it, this is just one example for simple illustration.

8/11

SAMPLE APPLICATION
In the first screenshot below, the header navigator and tab bar at the bottom (with badge), and the second view with all the text and controls are actually native iOS controls, whereas the middle embedded view with the button list is an embedded Cordova WebView containing HTML/JS to interact with the native Cordova/PhoneGap APIs to retrieve contacts, use the camera, etc.

If youre familiar with Storyboarding in XCode for iOS, the Storyboard shows an overview and flow of the application from the native perspective, so you can see the parts which are iOS Native controls versus the other buttons etc that were included from the HTML/JS as part of the Cordova WebView:

9/11

In the next screenshot you can see how we can interact with the Cordova/PhoneGap APIs for native functions like grabbing contacts right there inside our native application:

10/11

This next view is all native iOS controls (see storyboard), but includes a button to pop up a new view that uses the same ViewController class and will have the embbeded Cordova subview:

And lastly is our next view from the button pop-up that shows how another view will also have the embedded Cordova WebView:

Grab the sample application from my github account and give it a whirl. I will cover including a Cordova WebView in Android in my next post so stay tuned!

appliness

DONT WORRY, BE APPLI

RESPONSIVE MENU CONCEPTS


TIMS ARTICLE WAS ORIGINALLY PUBLISHED ON CSS-TRICKS.COM.

When it comes to responsive design we are faced with various techniques on how to best handle altering our navigation menus for small screens. The resources seem endless. Thats why Im going to show you four main concepts and discuss the advantages and disadvantages of all of them. Three of them are made with pure CSS and one uses a single line of JavaScript.

BEFORE WE START
In the code presented in this article, I dont use any vendor-prefixes to keep the CSS easier to see and understand. The more complex CSS examples use SCSS. Each example is hosted on CodePen where you can see the compiled CSS if you wish. All menu concepts in this article are based on this simple HTML structure which I call basic menu. The role attribute is used to specify the particular concept (full-horizontal, select, custom-dropdown and offcanvas). <nav role=> <ul> <li><a href=#>Stream</a></li> <li><a href=#>Lab</a></li> <li><a href=#>Projects</a></li> <li><a href=#>About</a></li> <li><a href=#>Contact</a></li> </ul> </nav>

by TIm Pietrusky

To address small screens I use the same media query on all concepts. @media screen and (max-width: 44em) { }

1. FULL HORIZONTAL
This is the most simple approach because you just need to make the list elements full width on small screens. HTML <nav role=full-horizontal> <ul> <li><a href=#>Stream</a></li> <li><a href=#>Lab</a></li> <li><a href=#>Projects</a></li> <li><a href=#>About</a></li> <li><a href=#>Contact</a></li> </ul> </nav> CSS @media screen and (max-width: 44em) { nav[role=full-horizontal] { ul > li { width: 100%; } } } This is what it looks like on a small screen with a custom style.

2/11

ADVANTAGES No JavaScript No extra HTML Simple CSS DISADVANTAGES Reserves too much screen-space DEMO On CodePen:

Tap the menu items

2. SELECT
This concept hides the basic menu on small screens and shows a select menu instead. To achieve this we need to extend our basic markup and add a select. To get the select working we also add some JavaScript which alters window.location.href when the onchange event on the select occurs. <nav role=select> <!-- basic menu goes here --> <select onchange=if (this.value) window.location.href = this.value;> <option value=#>Stream</option> <option value=#>Lab</option> <option value=#>Projects</option> <option value=#>About</option> <option value=#>Contact</option> </select> </nav>

3/11

We hide the select on big screens. nav[role=select] { > select { display:none; } } On small screens, we hide the basic menu and show the select. To help the user recognize that this is a menu were also adding a pseudo-element with the text Menu. @media screen and (max-width: 44em) { nav[role=select] { ul { display: none; } select { display: block; width: 100%; } &:after { position: absolute; content: Menu; right: 0; bottom: -1em; }

This is what it looks like on a small screen with a custom style.

ADVANTAGES Doesnt need much space Uses native controls DISADVANTAGES Needs JavaScript Duplicate content Select is not styleable in every browser
4/11

DEMO This demo is best viewed on CodePen.

3. CUSTOM DROPDOWN
This concept hides the basic menu on small screens and shows an input & label (to use the Checkbox Hack) instead. When the user clicks on the label, the basic menu is shown underneath. <nav role=custom-dropdown> <!-- Advanced Checkbox Hack (see description below) --> <!-- basic menu goes here --> </nav> PROBLEM WITH THE CHECKBOX HACK There are two problems with the default Checkbox Hack: 1. Doesnt work on mobile Safari (iOS < 6.0). Its not possible to click the label on iOS < 6.0 to toggle the input due to a bug. The only solution is to add an empty onclick to the label. 2. Doesnt work on the default Android browser (Android <= 4.1.2). Once upon a time there was a WebKit Adjacent/General Sibling & Pseudo Class Bug which prevented the use of pseudo-classes combined with adjacent (+) or general (~) sibling combinators. h1 ~ p { color: black; } h1:hover ~ p { color: red; } This has no effect because the checkbox hack uses the pseudo-class :checked combined with the general sibling. And since this was fixed in WebKit 535.1 (Chrome 13) and the actual WebKit on Android 4.1.2 is 534.30, the normal checkbox hack doesnt work on any Android device to date. The best solution is to add a WebKit-only fake animation on the body element. All stuff combined creates the Advanced Checkbox Hack: HTML <!-- Fix for iOS --> <input type=checkbox id=menu> <label for=menu onclick></label> CSS /* Fix for Android */ body { -webkit-animation: bugfix infinite 1s; } @-webkit-keyframes bugfix { from { padding: 0; } to { padding: 0; } } /* default checkbox */ input[type=checkbox] {
5/11

position: absolute; top: -9999px; left: -9999px;

label { cursor: pointer; user-select: none; } Reference: Advanced Checkbox Hack For large screens, we hide the label: CSS nav[role=custom-dropdown] { label { display: none; } } For small screens, we hide the basic menu and show the label. To help the user recognize that this is a menu were also adding a pseudo-element with the text (converted to \2261 to use it as content on the pseudo-element) to the label. When the user clicks on the input, the basic menu gets shown and the list elements are expanded to full width. @media screen and (max-width: 44em) { nav[role=custom-dropdown] { ul { display: none; height: 100%; } label { position: relative; display: block; width: 100%; } label:after { position: absolute; content: \2261; } input:checked ~ ul { display: block; > li { width: 100%; }

6/11

This is what the menu looks like on a small screen with a custom style. CLOSED

OPEN

ADVANTAGES Doesnt need much space when closed Custom styling No JavaScript DISADVANTAGES Bad semantics (input / label) Extra HTML

7/11

DEMO On CodePen:

Tap the submenu

4. OFF CANVAS
This concept hides the basic menu on small screens and shows a HTML input & label (to use the Advanced Checkbox Hack, see 3. Custom Dropdown for more infos) instead. When the user clicks on the label, the basic menu flies in from the left and the content moves to the right the screen gets divided: menu ~80 % and content ~20 % (depends on resolution and css units). HTML <input type=checkbox id=menu> <label for=menu onclick></label> <!-- basic menu goes here --> <div class=content> <!-- content goes here --> </div> On large screens, we hide the label. CSS label { position: absolute; left: 0; display: none; }
8/11

On small screens, we hide the basic menu outside the viewport and show the label / input. To hide the menu we specify a width ($menu_width) and add a negative position to it. To help the user recognize that this is a menu were also adding a pseudo-element with the text (converted to \2261 to use it as content on the pseudo-element) to the label. When the user clicks on the input, the basic menu flies in from the left and the content moves to the right. @media screen and (max-width: 44em) { $menu_width: 20em; body { overflow-x: hidden; } nav[role=off-canvas] { position: absolute; left: -$menu_width; width: $menu_width; ul > li { width: 100%; }

label { display: block; } label:after { position: absolute; content: \2261; } input:checked ~ nav[role=off-canvas] { left: 0; } input:checked ~ .content { margin-left: $menu_width + .5em; margin-right: -($menu_width + .5em); }

This is what the menu looks like on a small screen with a custom style. CLOSED

9/11

OPEN

ADVANTAGES Doesnt need much space when closed Custom styling No JavaScript Convention from Facebook / Google+ app DISADVANTAGES Bad semantics (input / label) Extra HTML Absolute position to the body = Feels like fixed position DEMO On CodePen:

Tap the submenu

10/11

DOES IT WORK ON IE?


All of the techniques used above have one goal: Create responsive menus for modern browsers! And because there is no IE 8 or lower on any mobile device we dont need to worry about it.

RELATED POSTS
Responsive Data Table Roundup Responsive Data Tables

ABOUT THIS ARTICLE


Im Tim Pietrusky, a 27 years old Web Craftsman from Frankfurt (Main), Germany. My time is divided into programming, writing and thinking about all kinds of web related stuff, because I freaking love what I do.

http://timpietrusky.com/

@TimPietrusky

appliness

DONT WORRY, BE APPLI

JAVASCRIPT APIS YOUVE NEVER HEARD OF (AND SOME YOU HAVE)


CLICK TO SEE NICHOLASS ORIGINAL BLOG POST.

The number of JavaScript APIs has exploded over the years, with a small subset of those APIs getting all the attention. While developers feverishly work on Web sockets and canvas, its easy to overlook some smaller and quite useful APIs. This talk uncovers the uncool JavaScript APIs that most people have never heard of and yet are widely supported by todays browsers. Youll learn tips and tricks for working with the DOM and other types of data that you can use today.
Nicholas C. Zakas is a front-end consultant, author and speaker. He worked at Yahoo! for almost five years, where he was front-end tech lead for the Yahoo! homepage and a contributor to the YUI library. He is the author of Maintainable JavaScript (OReilly, 2012), Professional JavaScript for Developers (Wrox, 2012), High Performance JavaScript (OReilly, 20120), and Professional Ajax (Wrox, 2007).
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, OReilly Publishing, or anyone else. I speak only for myself, not for them.

http://www.nczonline.net

@slicknet

by Nicholas C. Zakas

appliness

HELTER SKELTER NEWS

Fresh news about HTML and Javascript collected by Brian Rinaldi - remotesynthesis.com
How promises work via Kris Kowal Reducing HTTP Requests for Images using CSS Sprites via Peter Keating

Stairway Navigation (A jQuery Plugin?) via Chris Coyier

Variable declarations: three rules you can break via Dr. Axel Rauschmayer

Getting Started with Parse via Tilo Mitra

CSS Things That Dont Occupy Space via Louis Lazaris

Compiling to JavaScript: What, Why, and How? via Andre Rieussec

Defer ALL The Things via James Socol

Testing Globalization Support in PhoneGap 2.2 by Ray Camden

appliness

HELTER SKELTER NEWS

A Few New Things Coming To JavaScript via Addy Osmani The state of CSS 3D transforms via Keith Clark IE10 CSS Hacks via Louis Lazaris

Building A Relationship Between CSS & JavaScript via Tim Wright

Responsive CSS Timeline with 3D Effect via Mary Lou

Learning Principles for Improving Your CSS via Hugo Giraudel

Go Node Without Code via Brian Rinaldi Code smells in CSS via Harry Roberts

MORE NEWS ON REMOTESYNTHESIS.COM

appliness

THE TEAM
Contribute and join Appliness

Appliness is a free digital magazine edited by passionate web developers. We are looking for contributors. Contact us and join the adventure. Youll find on our website appliness.com a feedback form. You can also follow us on twitter, facebook and Google+.

MICHAEL
Michal Chaize is a Developer Evangelist at Adobe where he focuses on Rich Internet Application and Mobile applications. Based in Paris, he works with large accounts that need to understand the benefits of rich user interfaces, leverage the existing back-ends to add a rich presentation layer and measure the impact on the existing IT teams. He believes that intuitive user experiences in the Enterprise are key to successful developments of effective, efficient, engaging, easy to learn and error free applications. Before joining Adobe, Michael founded a software company and taught RIA languages such as Flex and PHP in IT engineering schools. Hes the editor in chief of Appliness.

CHAIZE

CHRISTOPHE
Christophe is a Developer Evangelist for Adobe where he focuses on Web Standards, Mobile, and Rich HTML Applications with a special focus on Enterprise Integration. In this role, Christophe has helped some of the largest financial services companies design, architect and implement some of their most mission critical applications. He was one of the initial members of the Flex Product Team in 2003. In his previous role at Macromedia, Christophe worked on JRun, the companys J2EE application server. Before joining Macromedia, Christophe was managing Java and Internet Applications Evangelism at Sybase and Powersoft. Christophe has been a regular speaker at conferences worldwide for the last 15 years.

COENRAETS

Piotr Walczyszyn is a technology geek living in Warsaw, Poland, where he was born. out of.me is his new blog in which he wants to express his current interests and share some of his work. Technologies change; new trends come and go. These days nobody talks about RIAs (Rich Internet Applications) anymore, and he thinks this phrase has become almost passe although its main concepts have not.

P I O T R WALCZYSZYN

PA U L

Paul has been working at Adobe Systems foundry since January 2009 helping to develop typefaces at every level of production from conceptualizing and drawing to OpenType programming, exporting and beta testing.

HUNT

B R I A N
Brian Rinaldi is as a Content and Community Manager for the Adobe Developer Center team, where he helps drive content strategy for HTML5 and JavaScript developer content. Brian blogs regularly at http://remotesynthesis.comand and is a unreformed twitter addict.

H O L L Y
Holly is a Developer Evangelist at Adobe Systems and has been doing software development since 1996 with experience working for various Fortune 500 companies to startup. Hollys experience is primarily in OO languages, but she thrives on constantly learning new things & is always up for a challenge.

RINALDI

SCHINSKY

A N D R E W D M I T R Y
BARANOVSKIY
Dmitry is a Sydney-based web developer interested in HTML, CSS, JavaScript, XSLT and SVG. Currently he is working at Adobe as a Senior Computer Scientist. Hes the creator of the JavaScript library Raphael. Andrew Trice is a Technical Evangelist with Adobe Systems. Andrew brings to the table more than a decade of experience designing, implementing, and delivering rich applications for the web, desktop, and mobile devices. He is an experienced architect, team leader, accomplished speaker, and published author, specializing in object oriented principles, mobile development, realtime data systems, GIS, and data visualization.

T R I C E

M A I L E

Maile is the assistant editor for Appliness magazine and has worked with Adobe both as an employee and consultant for 8 years now. Maile started with Adobe on the Technical Marketing team as a technical trainer for the Adobe LiveCycle Enterprise Suite (most recently Adobe Digital Enterprise Platform). She then went on to work with the Adobe Enterprise Evangelist team to support great Flex developer resources such as Tour de Flex and Flex.org. Maile is excited to jump into the world of digital publishing and dig deeper into leading edge HTML and related technologies.

VALENTINE

Greg is a Developer Evangelist at Adobe Systems focusing on the use of Adobe technologies in enterprise applications. Technologies include HTML, JavaScript and related technologies, Flex, AIR, data services, digital publishing, and anything mobile, tablet and desktop app development related. Prior to joining Adobe, Greg architected and developed many largescale applications at Verizon, Motorola, NASA/Boeing and others.

WILSON

Vous aimerez peut-être aussi