ng-model=”name” - RIAgora
October 30, 2017 | Author: Anonymous | Category: N/A
Short Description
url: “http://search.twitter.com/search.json”, I used Twitter Bootstrapin my MediaExplorer, but subsequently found ....
Description
(
appliness
TUTORIALS JAVASCRIPT
BOOKMARK / SHARE / TOC
Secrets of Awesome JavaScript API Design by Brandon Satrom
TUTORIALS AWESOME JAVASCRIPT API DESIGN
by Brandon Satrom
Article published by:
GETTING STARTED Design is a universal concept. As the act of “form[ing] a plan or scheme of [some thing]… for later execution,” (Oxford English Dictionary) design is the common thread that weaves together art, architecture, hardware and more. Software design, specifically the subcategory of API design, is no different. Yet API design is often given little attention in the world of software development, because the exercise of writing code for other developers often seems far less important than the design of application UI and end-user experiences. But API design—the public interfaces we provide in the libraries we create, with the express intent of exposing features and functionality to developers who call our code— is just as important as UI design. In fact, both are the primary mode of creating user experiences for a segment of an application’s audience. Where application UI is a large part of end-user UX, an application’s API is developer UX. As such, it should be designed with the same level of care and attention to detail that we provide to user interfaces. Just as we pay attention to the utility, simplicity and elegance of a UI, we should similarly evaluate the utility, simplicity and elegance of an API. API design, and in the context of this article JavaScript API design, presents a unique challenge for all developers, whether you’re building a public library or an internal one. The dynamic nature of JavaScript, the anonymity of library consumers and ambiguity in requirements presents a daunting set of challenges for the API designer. While there are no quick shortcuts to good API design, it is possible to distill a handful of design principles that hold up when applied to some of the popular JavaScript libraries of today. API DESIGN: A STRUGGLE OF GOOD VS. EVIL Poor design in JavaScript APIs is costly, both to the developers consuming your API and to you. In both cases, a poor design generates waste: wasted time for developers as they struggle to make sense of an interface, and wasted time for the API author as she deals with the increased load of support and rework brought about by developer confusion. Considering that nearly all APIs are created with the goal of abstracting common functionality for easy consumption and thus, saving time, a poor API leaves both you and your users wondering if this little library of yours was such a good idea 2 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
after all. Good API design, on the other hand, accomplishes the goal of abstraction, while being self-describing. When an API is well-designed, users can leverage your work quickly and intuitively, without the constant reference of a manual, documentation or frequent visits to support and Q&A sites. You’ve also saved another developer time by packaging up some feature that would have taken much longer to create on their own. And not only does good design save developers time, it makes them look smart and responsible. Helping your users look smart and capable makes them feel awesome, which makes you look pretty awesome, too. IN JAVASCRIPT, API DESIGN IS ESPECIALLY IMPORTANT While API design is important regardless of programming language or framework, the stakes of API design are much higher for JavaScript than for many other languages. To begin with, as a dynamic, late-bound programing language, JavaScript has no compiler to serve as a safety net or first unit test to point out mistakes in your code. Linting or verification frameworks like JSLint and JSHint help somewhat. These utilities are useful in pointing out common mistakes in JavaScript code, but they do nothing to catch the errors a developer might make when using your API. It’s up to you, then, to build an API with a design that helps users of your library fall into the proverbial “pit of success.” This means that your library feels comfortable and familiar to the developer, while also providing positive reinforcement and building the developer’s confidence as she interacts with your code. One of the best examples of “falling into the pit of success” is jQuery’s use of CSS selector syntax for fetching DOM elements. For example, if I want to select all article elements with the class blogPost, I can do the following in jQuery: $(“article.blogPost”).fadeIn();
It’s no coincidence that the selector article.blogPost uses the exact same syntax as the following: article.blogPost { border-radius: 10px; background-color: salmon; box-shadow: 0px 0px 10px 2px #ccc; 3 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
}
jQuery’s selector engine was designed to enable me, the developer, to map my existing understanding of CSS selectors onto basic interactions with its engine. As a result, I’m instantly and measurably more productive than if jQuery required me to use a new, purpose-built syntax. It’s possible to take inspiration from libraries like jQuery and others, and to apply these our own designs. However, inspiration by itself is a degree removed from copying, and anyone who’s ever designed an API based solely on the inspiration of another knows that he will inherit both good and bad. Instead, if we map examples of good JavaScript API design to proven principles found in other fields, we can build a framework of good API design that can be applied in any context.
SECRETS OF AWESOME JAVASCRIPT APIS While it’s true that software doesn’t have the same visual qualities as a painting or a building, we tend to use the same adjectives to describe software as we do for physical media. It’s not uncommon to hear someone refer to an API as “elegant” or “beautiful.” If it’s valid to describe APIs in terms we use for visual media, it’s equally valid to use the principles of those media to inform our software designs. In this section, I’m going to introduce four popular design principles from the art world and apply these to API design: Unity and Harmony Balance Proportionality Emphasis For each of these, I’ll point to one or more examples of the principle as leveraged in the API of a popular JavaScript library. PRINCIPLE 1: UNITY & HARMONY In art, unity is the concept behind a work, or how the composer brings everything together into a coherent whole. Harmony, on the other hand, is the placement of 4 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
similar elements throughout a work, which yields an uncomplicated and simple feel when considered in its entirety. For the API designer, these principles can be applied through the use of similar and/or unifying elements in a library. Take, for instance, Kendo UI, a JavaScript framework for building rich web applications. One of Kendo UI’s offerings is a set of UI controls and widgets, all of which can be initialized using a similar syntax. For example, if I wanted to create a TreeView control from an unordered list, I need only call the following: $(“ul.tree”).kendoTreeView({ /* Configuration goes here */ });
If, on the other hand, I wanted to create a PanelBar from a list, I’ll make a slightly different call. $(“ul.panel”).kendoPanelBar({ /* Configuration goes here */ });
5 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
Kendo UI promotes unity and harmony by using this consistent kendoX syntax for all of it’s widgets. What’s more, its dependency on jQuery objects for obtaining DOM elements adds an additional layer of harmony that any developer already familiar with jQuery will benefit from. By using a “local dialect” of JavaScript that millions of developers are familiar with, Kendo UI promotes harmony across libraries. Another example of harmony in action is Backbone’s [object].extend syntax to create objects that inherit and extend the functionality of Backbone Models, Views, Collections and Routers. To create a new Backbone model, I can do something like the following, and I’ll get a model object that’s fully-supported by Backbone, while being customized to my application’s needs: var Book = Backbone.Model.extend({ initialize: function() { ... }, author: function() { ... }, pubDate: function() { ... }, });
The goals of unity and harmony are to convey familiarity and comfort to developers new to your API. By leveraging identical or similar idioms for related but different actions, an API can convey familiarity and comfort which can greatly ease a developer’s adoption of a new tool. 6 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
PRINCIPLE 2: BALANCE The next principle is balance, an arrangement of elements to ensure that no one part of the work overpowers other parts or causes the work to feel unstable. In art, balance is about visual weight. Even when asymmetrical, a work can feel balanced because its asymmetry follows a pattern. In the context of API design, I interpret balance to mean both the visual weight of the code and its predictability. A balanced API is one whose component parts feel as though they belong together, because they behave the same or aid the consumer in accomplishing a complementary goal. By extension, these APIs also feel balanced because they allow the consumer to extrapolate usage from a small sample. Consider Modernizr’s property tests. These achieve balance by a) using property names that match HTML5 and CSS concepts and APIs; and b) by consistently returning a truthy or falsy value for every single test: // All of these properties will be ‘true’ or ‘false’ for a given browser Modernizr.geolocation Modernizr.localstorage Modernizr.webworkers Modernizr.canvas Modernizr.borderradius Modernizr.boxshadow Modernizr.flexbox
Accessing a single property tells the developer everything he or she needs to know in order to access every other property, a quality that’s powerful in its simplicity. It also ensures that the code I write to interact with Modernizr has the same visual weight each time I write or read it. How I use and access the API looks and feels the same, regardless of my usage. If, on the other hand, Modernizr were to add an API to polyfill Canvas, imbalance would take hold. Not only is the visual weight of the library affected by this new API, but the scope and purpose of Modernizr has grown greatly, and my ability to predict how to interact with the API is hampered. Another way to achieve balance through predictability is to rely on concepts already familiar to developers. A notable example is jQuery’s selector syntax, which maps CSS1–3 selectors into its own DOM selector engine: $(“#grid”) // Selects by ID $(“ul.nav > li”) // All LIs for the UL with class “nav” $(“ul li:nth-child(2)”) // Second item in each list 7 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
By using a familiar concept and mapping it to its own library, jQuery is able to avoid creating a new selector syntax, while also creating a mechanism that makes new users of the library instantly productive with a predictable API. PRINCIPLE 3: PROPORTION The next principle is proportion, which is a measurement of the size and quantity of elements within a work. Rather than stating that a good API is a small API, proportion is about size relative to purpose. A proportional API is one whose API surface matches its scope of capability. For instance, Moment.js, a popular date parsing and formatting library, can be considered proportional because it’s API surface is compact, which matches the straightforward purpose of the library. Moment.js is for working with dates and, as such, its API is filled with convenience functions designed to make the JavaScript Date object tolerable to work with: moment().format(‘dddd’); moment().startOf(‘hour’).fromNow();
For libraries with a targeted purpose, like Moment.js, keeping the API focused and small is important. For larger, more expansive libraries, the size of the API should reflect the capabilities of the library itself. Take Underscore. As a general-purpose utility library, Underscore provides a large number of convenience functions designed to help developers work with JavaScript collections, arrays, functions and objects. It has a larger API surface than a library like Moment.js, and yet Underscore is proportional because each function aids in the purpose of the library. Consider the following examples, the first two of which illustrate using Underscore to work with Arrays, and the last of which illustrates working with strings: _.each([“Todd”, “Burke”, “Derick”], function(name){ alert(name); }); _.map([1, 2, 3], function(num){ return num * 3;
8 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
_.isNumber(“ten”); // False
}); As a library grows, the challenge of maintaining proportion becomes even more critical. Care must be taken to ensure that every feature and function added to a library reinforces the library’s purpose. For a large offering like Kendo UI, an expansive purpose doesn’t mean we need to add every feature under the sun. For a library as large as Kendo, even utility objects and features should prove their worth to be included. Take for example, Kendo UI’s JavaScript based DataSource, which can be used to query and work with remote data: var dataSource = new kendo.data.DataSource({ transport: { read: { url: “http://search.twitter.com/search.json”, dataType: “jsonp”, data: { q: “API Design” } } }, schema: { data: “results” } });
At first glance, it might seem like a custom DataSource falls outside of the primary purpose of the library. However, many of today’s web widgets assume the existence of dynamic data, and the inclusion of a DataSource allows Kendo UI to use a consistent—and thus, comfortable—paradigm for working with remote data across the entire library. Allowing an API to turn into a veritable JavaScript junk drawer is a danger of library growth, but it is not the only danger. Of equal risk is falling in the trap not allowing your API to grow along with a library; constraining the surface area of your library for artificial reasons. A good example of how not to handle API growth, is jQuery’s jQuery or $ function. As much as I and millions of others love jQuery, the library’s gateway method is a bit of a mess, providing no less than eleven separate overloads for everything from DOM selection to the ability to wrap DOM elements in a jQuery object. For the most part, these are loosely related features that have been stuffed into one API. Taken on the whole, jQuery is a large library and can be considered reasonably 9 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
proportional. The jQuery method, on the other hand, represents what can happen when we attempt to force functionality into a single interface, without care for proportion. If you find yourself stuffing tangential features into existing methods, or rationalizing the addition of function overloads that don’t feel natural to the API, chances are you need to loosen the belt and let that library breathe. Your users will have an easier time adapting to a new function with a self-describing name than they will yet another overload on an existing method.
PRINCIPLE 4: EMPHASIS In art, emphasis is the use of contrast to cause an aspect of the work to stand out and serve as a focal point. In many APIs, the focal point might be a gateway or main method that anchors the library. Another example of emphasis could be a “chained” or fluent API, which adds emphasis to a central object used by the library. jQuery’s tendency to return a jQuery object from many of it’s functions demonstrates this type of emphasis: $(‘ul.first’).find(‘.overdue’) .css(‘background-color’,’red’) .end() .find(‘.due-soon’) .css(‘background-color’, ‘yellow’);
For many modern libraries, another excellent example of emphasis is extensibility: that part of the library where the creators embrace what’s missing from the library by giving you a vehicle to add functionality yourself. A classic example is jQuery’s fn (pronounced “effin”) namespace, the general extensibility point from which countless plugins and complementary libraries have been launched: (function($) { $.fn.kittehfy = function() { return this.each(function(idx, el) { var width = el.width, height = el.height; var src= “http://placekitten.com/”;
10 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
el.src= src + width + “/” + height; }); }; })(jQuery);
Another example of extensibility is Backbone’s “extend” function, which we’ve looked at already in this article: var DocumentRow = Backbone.View.extend({ tagName: “li”, className: “row”, events: { “click .icon”: “open”, “click .button.edit”: “openEditDialog” }, render: function() { ... } });
Adding extensibility exhibits emphasis because it calls attention to the fact that a given library wasn’t meant to be the end–all–be–all, while at the same time encouraging you to add to the capabilities of the library as you see fit. When libraries encourage extensibility, they unlock not only new specialized uses, but additional general uses that might benefit countless other developers. One great example is the Backbone.Marionette framework, a extension library for Backbone that aims to “…simplify the construction of large scale JavaScript applications.” Were it not for the extensibility of a library like Backbone, libraries like Marionette would be much more difficult, if not impossible, to deliver. API DESIGN: NOT JUST FOR LIBRARY AUTHORS If you’re not a JavaScript library author, but consider yourself a JavaScript app developer and library implementer, you might be tempted to think that the principles in this article don’t apply to you. After all, most of us often think of thirdparty libraries, like those I’ve used for the samples in this article, when we hear the term “API.” The truth is that an API, by definition, is nothing more than a segregated piece of functionality that provides an interface for others to leverage. I’m using general terms here to underscore an important point: modular JavaScript code is written to be consumed; the number of consumers is irrelevant. 11 of 12
TUTORIALS AWESOME JAVASCRIPT API DESIGN
Your own JavaScript code exposes interfaces for others, just as the libraries referenced in this article do. Even if the consumers of your code are a small, internal team—or even if you’re building a library for private use—you don’t have to be a public library author to think about API design and apply the principles covered in this article. The benefits of leveraging intentional API design pay off for an audience of one, just as they do for an audience of one million. Because API design represents UX for developers, it is just as important as UI design for end-users. Just as we can learn to develop a sense for UI design by studying principles and examples of good and bad interfaces, we can learn much about good API design by doing the same. Applying the four principles from this article, as well as others you discover on your own, can result in awesome APIs that delight your users and help them build amazing experiences for others.
Brandon Satrom
his blog
share
twitter
github
Developer extraordinaire
(
appliness
TUTORIALS JAVASCRIPT
BOOKMARK / SHARE / TOC
asm.js: closing the gap between JavaScript and native. by Dr. Axel Rauschmayer
TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE
by Dr. Axel Rauschmayer
“[asm.js] effectively describes a safe virtual machine for memory-unsafe languages like C or C++.”
GETTING STARTED asm.js defines a subset of JavaScript that can be compiled to fast executables. It has been created at Mozilla by David Herman, Luke Wagner and Alon Zakai. According to the specification, “[asm.js] effectively describes a safe virtual machine for memoryunsafe languages like C or C++.” This blog post describes how asm.js works, it is based on the specification. 1. THINGS THAT SLOW DOWN JAVASCRIPT Current JavaScript is already quite fast, but a few mechanisms in engines limit its speed: • Boxing: Floating point numbers (including integers stored as floating point numbers) are boxed, they have wrappers that allow them to co-exist with other values such as objects. • Just-in-time (JIT) compilation and runtime type checks: Most JavaScript engines compile code in two stages. Initially, a format is used that can be compiled to quickly, but that runs slowly (e.g. interpreted bytecode). The execution of that format is observed. If it runs more often, assumptions can be made about the types of its parameters etc. and it can be compiled to a format that runs faster. If one of the assumptions turns out to be wrong, the faster format can’t be used any more and the engine has to go back to the slower format. The faster format is always slowed down by checking whether the assumptions still hold. • Automated garbage collection: which can be slow. • Flexible memory layout: JavaScript’s data structures are very flexible, but they also make memory management slower. asm.js code can produce executables that exhibit none of these drawbacks. They can be compiled “ahead of time” (before execution) and are faster than JIT-compiled ones: “asm.js can be implemented massively faster than anything existing JavaScript engines can do, and it’s closing the gap to native more than ever.” – David Herman 2 of 9
TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE
The asm.js specification only describes what JavaScript code has to look like to be asm.js-compliant, the semantics follow from the ECMAScript language specification. That is, asm.js is a true subset of JavaScript. 2. HOW ASM.JS WORKS asm.js code is packaged in specially marked functions (“asm.js modules”) that have the following structure: function MyAsmModule(stdlib, foreign, heap) { “use asm”; // marks this function as an asm.js module // module body: function f1(...) { ... } function f2(...) { ... } ...
}
return { export1: f1, export2: f2, ... };
Two steps are performed before asm.js code can be used: • Ahead of time (AOT) compilation: a complete fast executable can be produced when the code is loaded (compare: JITs only produce a slow version at load time). • Linking: The asm.js module function is invoked and linked to its external dependencies stdlib and foreign (see below). All three parameters are optional (if any of them are missing, appropriate default values are created): • stdlib: a standard library object, providing access to (a subset of) the standard library. • foreign: a foreign function interface (FFI) providing access to arbitrary external JavaScript functions. • heap: a heap buffer, an instance of ArrayBuffer that acts as the asm.js heap. 3 of 9
TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE
The functions in the returned object can be invoked from non-asm.js code like all other JavaScript functions. Example. Let’s look at a concrete example: function DiagModule(stdlib) { “use asm”; var sqrt = stdlib.Math.sqrt; function square(x) { x = +x; return +(x*x); } function diag(x, y) { x = +x; y = +y; return +sqrt(square(x) + square(y)); } }
return { diag: diag };
The following code links and uses this asm.js module. // Browsers: this === window var fast = DiagModule(this); console.log(fast.diag(3, 4));
// link the module // 5
2.1 STANDARD LIBRARY asm.js has very limited access to JavaScript’s standard library. Only the following values can be accessed: • Global double values: Infinity, NaN • Double functions (arity 1): Math.acos, Math.asin, Math.atan, Math. cos, Math.sin, Math.tan, Math.ceil, Math.floor, Math.exp, Math.log, Math.sqrt • Double functions (arity 2): Math.atan2, Math.pow • Integer or double function (arity 1): Math.abs • Integer function (arity 2, proposed for ECMAScript 6): Math.imul (integer multiplication) • Double values: Math.E, Math.LN10, Math.LN2, Math.LOG2E, Math. LOG10E, Math.PI, Math.SQRT1_2, Math.SQRT2 4 of 9
TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE
2.2 STATIC TYPING asm.js code is statically typed. You statically specify the type of a variable declaration via its initializer. For example: var a = 0; var b = 0.0;
// a has type int // b has type double
You statically specify the types of parameters and return values via type annotations. For example: function foo(x, y) { var x = x|0; // x has type int var y = +y; // y has type double return +(x * y); // function returns a double }
The annotations tell the compiler what type to expect and also coerce arguments to the correct type. 2.3 SUPPORTED TYPES Value types. Roughly, asm.js supports 64 bit double-precision floating point numbers and 32 bit integers (ignoring several types that are needed so that all asm.js-supported JavaScript operations can be typed correctly). asm.js’s doubles are the same as JavaScript’s. You can’t work with integers directly in JavaScript, but 32 bit integers (similar to asm.js’s integers) are used internally [1]. References types. Reference types are only allowed for variable declarations at the top level of a module. All other variables and parameters must have value types. The following reference types are available: • ArrayBufferView types: Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array. These types are used for accessing the asm.js heap. • Functions • Function tables: an array of functions that all have the same type • References to foreign functions
5 of 9
TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE
2.4 CHECKING FOR ASM.JS CONFORMANCE Static checks (at compile time). The code of an asm.js is statically checked (when the JavaScript code is loaded): It must only use the declarations, statements and expressions that are part of asm.js (e.g. almost none of the OOP features of JavaScript are). And it must be well-typed, according to the static type system. If the checks fail, then asm.js code can’t be AOT-compiled and is executed as normal JavaScript code. Dynamic checks (at link time). When you invoke an asm.js module, the following dynamic checks are performed. If one of them fails, the AOT-compiled code can’t be linked and the engine must fall back to normal JavaScript. • No exception must be thrown until the return statement is reached. • The heap object (if provided) must be an instance of ArrayBuffer. Its byteLength must be a multiple of 8. • All view objects must be true instances of their respective typed array types. • All properties of the stdlib object must implement the semantics as specified by the ECMAScript standard. In practice, that means that they must have the same values as the properties of the global object that have the same names. 3. ADVANTAGES OF ASM.JS The approach taken by asm.js has the following benefits: • Relatively easy to implement on top of existing JavaScript engines. Quoting David Herman: [...] it’s significantly easier to implement in an existing JavaScript engine than from-scratch technologies like NaCl/PNaCl. Luke Wagner has implemented our optimizing asm.js engine entirely by himself in the matter of a few months. • Interacts well with JavaScript. It is a subset of JavaScript, after all. • Backward compatible with all existing JavaScript engines: if an engine isn’t aware of asm.js then the code simply runs as normal JavaScript.
6 of 9
TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE
3.1 EMSCRIPTEN To see what is possible with asm.js, you only have to look at Emscripten which is described as follows on its web site: Emscripten is an LLVM-to-JavaScript compiler. It takes LLVM bitcode (which can be generated from C/C++, using llvm-gcc or clang, or any other language that can be converted into LLVM) and compiles that into JavaScript, which can be run on the web – or anywhere else JavaScript can run. The list of projects that have been compiled via Emscripten is impressive: SQLite, Graphviz, LaTeX, Python, etc. Emscripten already produces surprisingly fast code. In fact, its way of code generation has been the inspiration for asm.js and its creator Alon Zakai is part of the asm.js team. A modified version of Emscripten now targets asm.js, which will result in considerable performance increases on engines with the necessary support. First performance numbers are already in: OdinMonkey
SpiderMonkey
V8
skinning
2.46
12.90
59.35
zlib
1.61
5.15
5.95
bullet
1.79
12.31
9.30
OdinMonkey is Firefox’s SpiderMonkey with asm.js support, V8 is Google’s JavaScript engine. Numbers denote how much slower the code is compared to code compiled via gcc -O2 (1.0 would mean “same speed”). 3.3 THE FUTURE Several features are on the horizon for JavaScript that will also benefit asm.js: • Modules: ECMAScript 6 will have modules, then asm.js code can be packaged more conveniently. • Type guards: Versions after ECMAScript 6 [2] might have type guards, obviating the need for the current, slightly hacky, type annotations. 7 of 9
TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE
• Better parallel programming: better support for data parallelism could come via either River Trail [3] or SIMD [2]. • More value objects are also planned for ECMAScript, with 64 bit integers having priority. Once JavaScript has them, they are also available to asm.js. Furthermore, asm.js might be expanded to be a more full-fledged virtual machine in the future, similar to the Java Virtual Machine or Microsoft’s Common Language Runtime. Quoting the asm.js FAQ: Right now, asm.js has no direct access to garbage-collected data; an asm.js program can only interact indirectly with external data via numeric handles. In future versions we intend to introduce garbage collection and structured data based on the ES6 structured binary data API, which will make asm.js an even better target for managed languages. 3.3 AVAILABILITY Quoting Herman: As the site says, the spec is a work in progress but it’s nearly done. Our prototype implementation in Firefox is almost done and will hopefully land in the coming few months. 4. CONCLUSION asm.js is impressive technology. There will probably always be people who would prefer a single standardized bytecode for the web, but asm.js proves that different approaches are possible and beneficial. It gives you the best of both worlds: • Low-level code: use asm.js for computationally intensive tasks and/or code that can be compiled to LLVM bitcode. • High-level code: use all of JavaScript for maximum flexibility. JavaScript source code becomes a format for delivering programs that abstracts over the different compilation strategies of JavaScript engines [4] and over the difference between asm.js and JavaScript. Delivering source code is not an approach that opposes a particular compilation strategy (bytecode etc.), you simply postpone deciding on one, giving engines the freedom to make their own choice. Additionally, this approach allows you to compile asm.js code in the browser: simply assemble a text string with the code and use eval() or Function() to compile it.
8 of 9
TUTORIALS ASM.JS: CLOSING THE GAP BETWEEN JAVASCRIPT AND NATIVE
JavaScript engines are optimized for higher-level code in a manner that can’t be replicated by less specialized engines. Thus, there will always be a schism between low-level and high-level engines; asm.js manages to make that schism as small as possible. 5. MORE MATERIAL • Website asmjs.org: • Specification • FAQ • Talk: “Big Web App? Compile It!” by Alon Zakai [video and slides] 6. REFERENCES 1. Integers and shift operators in JavaScript 2. A first look at what might be in ECMAScript 7 and 8 3. JavaScript: parallel programming via River Trail coming to Firefox 4. JavaScript myth: JavaScript needs a standard bytecode
Dr. Axel Rauschmayer
his blog
share
twitter
github
JavaScript Consultant
(
appliness
TUTORIALS JAVASCRIPT
BOOKMARK / SHARE / TOC
Functions Explained. by Mark Daggett
TUTORIALS FUNCTIONS EXPLAINED
by Mark Daggett
“Functions are the most rudimentary components of JavaScript.”
PHOTO BY: DERREN RASER Mark Daggett is an pioneering New Media artist, professional developer and CEO of Humansized Inc., a social innovations lab in Kansas City. He is a co-creator of Pledgie. com, the popular crowd-funding platform, and an adjunct professor at the Kansas City Art Institute. He has worked for over a decade within the fields of experience and user interaction design, concept development and strategy, through a variety of start-up ventures, consulting and advisory roles. He is a Rockefeller New Media Grant nominee, and has been profiled in The New York Times, Le Monde, WIRED Magazine and Surface Magazine, among others. A DEEP DIVE INTO JAVASCRIPT FUNCTIONS Based on my readership I have to assume most of you are familiar with JavaScript already. Therefore, it may seem odd to include a post on functions. After all, they are one of the most rudimentary components of JavaScript. My assertion is this, just as a person can speak a language without the ability to read or write it, so too can developers use functions in JavaScript and yet be blissfully unaware of their complexities. Typically developers only become aware of the specifics of functions when something they wrote explodes in their face. My goal in this section is to expose the intricacies of JavaScript functions to you, which will hopefully save you from having to pull syntactic shrapnel from your codebase. A word of caution before we begin; JavaScript is only as good as its interpreter. While the concepts we’ll consider are well-covered in the language spec, it does not mean that all runtime environments will work the same way. In other words your milage may vary. This section will discuss common misconceptions of JavaScript functions, and the silent bugs they introduce. However, debugging functions in detail is not covered. Fortunately, debugging has been documented by others in the JavaScript community especially in Juriy Zaytsev’s excellent article “Named Function Expressions Demystified” [1].
2 of 10
TUTORIALS FUNCTIONS EXPLAINED
BLOCKS IN JAVASCRIPT Before we can understand functions in JavaScript we have to understand blocks. JavaScript blocks are nothing more than statements grouped together. Blocks start with a left curly bracket “{“ and end with a right one “}”. Simply put, blocks allow statements inside the brackets to be executed together. Blocks form the most basic control structure in JavaScript. The following are a few examples of how blocks in JavaScript: // Block as an anonymous self-executing function ;!function () { var triumph = false, cake = false, satisfaction = 0, isLie, note; // Block used as part of function expression var isLie = function (val) { return val === false; } // Block used as part of a conditional statement if (isLie(cake)) { triumph = true; makeNote(‘huge success’); satisfaction += 10; } // Block used as part of a function declaration function makeNote(message) { note = message; } }();
As we saw above, functions are essentially named blocks, which the developer can invoke on demand. This is easy to demonstrate: // The inline conditional block statement is executed only once per cycle. if (isLie(cake)) { ... } function makeNote(message) { ... } 3 of 10
TUTORIALS FUNCTIONS EXPLAINED
// The function declaration is executed as many times as it is called. makeNote(“Moderate Success”); makeNote(“Huge Success”);
FUNCTION ARGUMENTS Functions like control flow statements (if, for, while etc.) can be initialized by passing arguments into the function body. In JavaScript variables are either a complex type (e.g. Object, Array) or a primitive type (e.g. String, Integer). When a complex object is supplied as an argument it is passed by reference to the function body. Instead of sending a copy of the variable, JavaScript sends a pointer to its location in memory. Conversely, when passing a primitive type to a function JavaScript passes by value. This difference can lead to subtle bugs because conceptually we often treat functions as a black box, and assume they can only effect the enclosing scope by returning a variable. With pass by reference, the argument object is modified even though it may not returned by the function. Pass by reference and pass by value are demonstrated below: var object = { ‘foo’: ‘bar’ }, num = 1; // Passed by reference ;!function(obj) { obj.foo = ‘baz’; }(object); // => Object {foo: “baz”} console.log(object); // Passed by value; ;!function(num) { num = 2; }(num); // => 1 console.log(num);
4 of 10
TUTORIALS FUNCTIONS EXPLAINED
FUNCTION TYPES Now that we have a better understanding of blocks, and arguments lets dive deeper into Function Declaration and Function Expression, the two types of functions used in JavaScript. To the casual reader the two appear very similar: // Function Declaration function isLie(cake){ return cake === true; } // Function Expression var isLie = function(cake){ return cake === true; }
The only real difference between the two, is when they are evaluated. A function declaration can be accessed by the interpreter as it is being parsed. The function expression on the other hand is part of an assignment expression, which prevents JavaScript from evaluating it until the program has completed the assignment. This difference may seem minor, but implications are huge; consider the following example: // => Hi, I’m a function declaration! declaration(); function declaration() { console.log(“Hi, I’m a function declaration!”); } // => Uncaught TypeError: undefined is not a function expression(); var expression = function () { console.log(“Hi, I’m a function expression!”); }
As you can see in the previous example the expression function threw an exception when it was invoked, but the declaration function executed just fine. This exception gets to the heart of the difference between declaration and expression functions. JavaScript knows about declaration function and can parse it before the program executes. Therefore, it doesn’t matter if the program invokes the function before it is defined. This is because behind the scenes JavaScript has hoisted the function to the top of the current scope. The function expression is not evaluated until it 5 of 10
TUTORIALS FUNCTIONS EXPLAINED
is assigned to a variable; therefore it is still undefined when invoked. This is why good code style is to define all variables at the top of the current scope. Had we done this then our script would visually match what JavaScript is doing during parsetime. The concept to take away is that during parsetime JavaScript moves all function declarations to the top of the current scope. This is why it doesn’t matter where declarative functions appear in the script body. To further explore the distinctions between declarations and expressions, consider the following: function sayHi() { console.log(“hi”); } var hi = function sayHi() { console.log(“hello”); } // => “hello” hi(); // => ‘hi’ sayHi();
Casually reading this code, one might assume that the declaration function would get clobbered because it function expression has an identical name. However, since the second function is part of an assignment expression it is given its own scope, and JavaScript treats them as seperate entities. To make things even more confusing look at this example: var sayHo // => function console.log(typeof (sayHey)) // => undefined console.log(typeof (sayHo)) if (true) { function sayHey() { console.log(“hey”); }
6 of 10
TUTORIALS FUNCTIONS EXPLAINED
sayHo = function sayHo() { console.log(“ho”); } } else { function sayHey() { console.log(“no”); } sayHo = function sayHo() { console.log(“no”); } } // => no sayHey(); // => ho sayHo();
In the previous example we saw that functions of the same name were considered different if one was an expression and the other was a declaration. In this example we are attempting to conditionally define the function based on how the program executes. Reading the script’s control flow you’d expect sayHey to return “hey” since the conditional statement evaluates true. Instead it returns “no”, meaning the second version of the sayHey function clobbered the first. Even more confusing is that the sayHo function behaves the opposite way! Again, the difference comes down to parsetime versus runtime. We already learned that when JavaScript parses the script it collects all of the function declarations and hoists them to the top of the current scope. When this happens it clobbers the first version of sayHey with the second because they exist in the same scope. This explains why it returns “no.” We also know that function expressions are ignored by the parser until the assignment process completes. Assignment happens during runtime, which is also when the conditional statement is evaluated. That explains why the sayHo function was able to be conditionally defined. The key to remember here is that function declarations can not be conditionally defined. If you need conditional definition use a function expression. Furthermore, function declarations should NEVER be made inside a control flow statement, due to the different ways interpreters handle it.
7 of 10
TUTORIALS FUNCTIONS EXPLAINED
FUNCTION SCOPES Unlike many other languages which are scoped to the block, JavaScript is scoped to the function. In Ruby (version 1.9.+) you can write this: x = 20 10.times do |x| # => 0..9 puts x end # => 20 puts x
What this demonstrates is that each block gets its own scope. Conversely, if we wrote similar code in JavaScript: var x = 20; // Functions have their own scope ;!function() { var x = “foo”; // => “foo” console.log(x); }(); // => 20 console.log(x); for (x = 0; x < 10; x++) {
}
// => 0..9 console.log(x);
// => 10 console.log(x);
In JavaScript x is available inside the for loop, because as a control statement it belongs to the enclosing scope. This is not intuitive to many developers used to block level scope. JavaScript handles the need of block level scope at least partially through the use of closures which we’ll discuss later.
8 of 10
TUTORIALS FUNCTIONS EXPLAINED
DEBUGGING FUNCTIONS Before we wrap this topic up, lets briefly touch on debugging functions. In JavaScript naming a function expression is completely optional; so why do it? The answer is to aid the debugging process. Named function expressions have access to their name within the newly defined scope, but not in the enclosing scope. Without a name their anonymous nature can make them feel a bit like ghosts in the machine when it comes to debugging. var namedFunction = function named() { // => function console.log(typeof(named));
} namedFunction();
// => undefined console.log(typeof(named));
9 of 10
TUTORIALS FUNCTIONS EXPLAINED
Nameless function expressions will be displayed in the stack trace as “(anonymous function)” or something similar. Naming your function expression gives you clarity when trying to unwind an exception whose call stack may feel miles long. /* * It is much harder to debug anonymous function expressions * Uncaught boom * - (anonymous function) * - window.onload */ ;!function(){ throw(“boom”); }(); /* * Naming your function expressions give you a place to start looking when debuggin. * Uncaught boom * - goBoom * - window.onload */ ;!function goBoom() { throw(“boom”) }();
Mark Daggett
his blog
share
twitter
github
Data Viz Tool Maker
(
appliness
TUTORIALS JAVASCRIPT
BOOKMARK / SHARE / TOC
Fun with AngularJS! by Holly Schinsky
TUTORIALS FUN WITH ANGULARJS!
by Holly Schinsky
“I may have been hooked initially because of my Adobe Flex background.”
GETTING STARTED Recently AngularJS, an MVC style JavaScript framework from Google, has been gaining more momentum. I’ve been curious about it for awhile and when I read this article recently, I decided it was finally time to give it a whirl. I was pleasantly surprised with what I found. I first watched these two videos by John Lindquist which I highly recommend as a starting point to get your feet wet. They are short and totally worth the time: 1. Simple ToDo’s App 2. Simple Twitter Search App Part of the reason I personally may have been hooked initially could be due to my Adobe Flex background. There’s a reminiscent feel with AngularJS to Flex in the twoway binding, HTML extension etc so I could see how a lot of Flex developers might feel at home with this framework. The framework is built on the idea that declarative programming should be used for building the UI and imperative programming for your business logic. With AngularJS you can do quite a bit with a small amount of code due to the built-in features that will be explained further in this post. It also relies on dependency injection throughout as well as the separation of the model/view/ controller. Here’s a nice illustration from the AngularJS site I found that helps explain more:
2 of 11
TUTORIALS FUN WITH ANGULARJS!
Disclaimer: My intention is not to incite a frameworks war here. I know there are a myriad of JavaScript frameworks available that people are passionate about. I’m simply sharing my thoughts and observations. After watching the videos above, I moved on to the tutorial, which was very easy to follow and I thought it was especially cool how they introduced testing your AngularJS app while building it using Jasmine and Testacular. I had previously only heard of those but got a much better idea of how to use them from the tutorial. It’s obvious they kept testing in mind while creating this framework. I then decided to build myself a web application with what I had learned. I’m a big music fan, always downloading from iTunes for my running playlists etc, so I thought I’d build a simple web app that interfaced with the iTunes Search API. The resulting application is here. You can grab the project from my github account here. This was my first newbie attempt so I’m open to critique and feedback on how I could make it better. I noticed there are often multiple ways to do the same thing using AngularJS, so I’m still in the learning process of when to use what. Overall though I was impressed by how fast I was able to make it all work and how much the framework provides for you. From my Media Explorer application you can enter a search term for anything media related (artist, song name or part, video etc). Once you get the results back, try out the sort and filter to see the returned results sort and filter accordingly. The filter field will filter results as you type into it. This is all built into the array filtering mechanism in AngularJS. Currently the max number of results returned defaults to 50.
3 of 11
TUTORIALS FUN WITH ANGULARJS!
Hitting the play button on the far left of any row will bring up an overlay to play the sample media as shown below:
I used Twitter Bootstrap in my MediaExplorer, but subsequently found AngularUI and Angular Bootstrap which you should also check out for help with your UI specific to Angular. In the next sections I’ll cover some of the main AngularJS concepts that seem important to understand.
4 of 11
TUTORIALS FUN WITH ANGULARJS!
DATA BINDING One of the first things I was most excited to see with AngularJS is that it has builtin support for two-way data binding similar to Flex (yay)! This is a big deal for datadriven applications in particular and can save you a TON of time coding. Below are two images from the AngularJS site that I think illustrate this point so well:
5 of 11
TUTORIALS FUN WITH ANGULARJS!
If you want to try a very basic example of the two-way data binding in action, I found this live sample here. If you look at the source code you’ll see how simple it is:
Binding the value in the text field to the model name. Hello {{name}}>
As you type into the input field it will show up next to the ‘Hello’ string since the name field is referenced there and is also the bound model object on the HTML input (with ng-model=”name”). MODEL The model is simply a plain old JavaScript object, does not use getter/setter methods or have any special framework-specific needs. Any changes are immediately reflected in the view via the two-way binding feature. There’s a concept of scope in the AngularJS framework, where all model objects stem from. I recommend seeing the AngularJS Scope documentation for more information on this topic. Typically your model objects are initialized in your controller code with syntax like: $scope.searchTerm = “Alicia Keys”;
But in the HTML template, that model variable would be referenced in curly braces such as: {{searchTerm}} without the $scope prefix.
6 of 11
TUTORIALS FUN WITH ANGULARJS!
VIEW The view is the rendered HTML that contains the transformed DOM resulting from a combination of the HTML template along with the AngularJS model and controller. The AngularJS View is aware of the controller and model, and accesses it through annotated HTML directives specific to AngularJS. For example, an ngclick AngularJS ‘directive’ can be applied to a button element to call a specific method in the controller when clicked. More on directives below… CONTROLLER The controller is used to provide the business logic behind the view and construct and value the model. The goal is to not manipulate the DOM at all in the controller, which is something to get used to if you’ve been using other frameworks. FILTERS AngularJS filters are used to modify data in some way, similar to formatters in Flex. For instance, a built-in filter called uppercase would look like this when applied to the name string from the model in order to uppercase it upon display. {{name|uppercase}}
You’re welcome to write your own filters as well. I included a custom one for fun in my application called capitalize that will simply capitalize the first letter of a string. mediaApp.filter(‘capitalize’, function() { return function(input, scope) { if (input!=null) return input.substring(0,1).toUpperCase()+input.substring(1); } });
7 of 11
TUTORIALS FUN WITH ANGULARJS!
You can see it applied here:
There’s also an array filtering feature which is really cool, and you can see an example of it in the Media Explorer app. When you specify a filter string on an array in the Angular ng-repeat directive it will automatically filter the matching results into a new array. For instance, here’s the code from the Media Explorer that specifies the filterTerm (the model object bound to the filter input HTML element) to your results list as you type (automatically applied do to the two-way data binding on the model data): Filter by ... {{(item.trackName != null) item.trackName || item.collectionName}} {{item.kind | capitalize}} {{item.artistName}} {{item.collectionName}} {{item.trackPrice}} {{item.collectionPrice}} ... 8 of 11
TUTORIALS FUN WITH ANGULARJS!
DIRECTIVES Directives are ways to transform the DOM through extended HTML. The add additional behavior. If you happen to have done Flex, it’s similar to adding a property like itemRenderer to an MXML component, or specifying click to call a function. In AngularJS there are a bunch of built-in ones you can use, most with a prefix of ‘ng’ (ng-click, ng-show, ng-change, ng-app etc). They’re actually defined with camelCase in the JavaScript, but applied with a dash to the HTML. You can also define your own directives and apply them in a similar fashion. In my Media Explorer application I wrote a couple of directives you could see for more examples. I used them to manipulate DOM elements since it’s not good practice to do so in the controller code. One called videoLoader is used to play and stop the video in the modal when the play button is clicked: mediaApp.directive(‘videoLoader’, function(){ return function (scope, element, attrs){ console.log(scope.url); scope.$watch(“url”, function(newValue, oldValue){ //watching the scope url value element[0].children[0].attributes[3].value=newValue; //set the URL on the src attribute element[0].load(); element[0].play(); }, true); scope.$watch(“showFlag”, function(newValue, oldValue){ if (!newValue) // if the showFlag is false, stop playing the video (modal was closed) element[0].pause(); }, true); } });
Then to apply this videoLoader directive to my video control, I add it as an attribute with a dash, such as: {{url}}
9 of 11
TUTORIALS FUN WITH ANGULARJS!
SERVICES Services are provided in AngularJS to help you do common task. For instance, there’s a built-in $http service that gives you access to make http or JSON requests etc, there’s also a $location service that gives you access to the browser location URL and helps you parse it etc. There are a bunch of others built-in and once again you can also write your own. You may write your own in the case where there’s something you know you’re going to use more than once in your application. In my application I did write a service just to try it out and use it to call the iTunes API with the $resource service, which allows you to interact with RESTful services and provides higher level behavior over the $http service (but is dependent on the $http service). My service looks like this: mediaApp.factory(‘MediaService’, function($resource){ return $resource(‘https://itunes.apple.com/:action’, {action: “search”, callback: ‘JSON_CALLBACK’}, {get: {method: ‘JSONP’} }); });
ROUTES You typically configure routes in your main or app.js file for an AngularJS app. For instance, mine is very basic since I’m not using multiple views and looks like this: mediaApp.config([‘$routeProvider’, function($routeProvider) { $routeProvider.when(‘/’, {templateUrl: ‘views/media-list.html’, controller: ‘MediaListCtrl’}); }]);
You can specify multiple paths for different URLs as well as a fallback. More on route configuration can be found here. QUICK START` You can use the AngularJS seed project, or if you’re familiar with Yeoman, there’s a whole option to generate an AngularJS-based project as well as additional commands that can be run to add new routes, views, controllers etc. It’s actually really cool and easy to use, check out this article for an awesome walkthrough of it. It will even generate your stubbed out tests for testing with Jasmine / Testacular. They 10 of 11
TUTORIALS FUN WITH ANGULARJS!
can’t make it much easier for us than that ! I didn’t discover this until after I created my application so my project structure doesn’t follow the Yeoman structure, but instead mirrors the AngularJS seed project structure. There are also seed projects available for using AngularJS on the front-end and Express+Node on the backend here, as well as AngularJS on the front-end, and Socket.io+Express+Node here if that fits your needs. I’ve only scratched the surface of what this framework is about. Below is a list of resources that can be used to follow-up with more in-depth information for those interested. The AngularJS documentation is good and the community support as well from my experience. Next I plan to turn my Media Explorer web application into a mobile application using PhoneGap and will post it here so check back soon! USEFUL RESOURCES • 5 Awesome AngularJS Features • @briantford on Building huuuuuuge Angular apps • AngularJS Batarang – Chrome Extension for Debugging • AngularJS Forum • AngularJS on Google+ • AngularJS Cheat Sheet • AngularJS Docs • AngularJS Blog • @briantford on Brian Ford on AngularJS with PhoneGap • @simpulton on The AngularJS Scope LifeCycle • AngularJS for jQuery Developers • @simpulton blog – lots of useful articles on AngularJS • Dean Sofer – AngularJS Tips and Tricks
Holly Schinsky
hER blog
share
twitter
github
Developer Evangelist
(
appliness
TUTORIALS JAVASCRIPT
BOOKMARK / SHARE / TOC
Building a Unit Test in Jasmine, Part 3. by David Posin
TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3
by David Posin
“This time we will expand the object to be more robust.”
We created a Jasmine unit test example in the first two parts of this series that started with a statement and then abstracted out to an object. This time we will expand the object to be more robust. Most importantly, we are not changing the tests currently in place. The JasmineTester is going to be updated to accept a random number of values. The first step is to create a unit test to describe this. The number of properties being added is upped to 4. The new test will check to make sure the new object constructor still returns an object by using the toBeDefined matcher. //Check for expanded options object it(‘Increase number of values to 4’, function() { var testObject = new JasmineTester({ a: 2, b: 2, c: 2, d: 2 }); expect(testObject).toBeDefined(); });
The test passes. testObject should now have 4 properties so let’s add a new expect to check the number of properties. expect(Object.keys(testObject).length).toEqual(4);
This test fails: Expected 2 to equal 4.
It’s time to update the constructor to use a random number of properties. for (o in opts) { if (opts[o]) { this[o] = opts[o]; } } 2 of 6
TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3
The constructor is changed to copy all properties from the passed object to itself. This is fairly simple and allows the JasmineTester to accept more than numbers. We run the tests and our new test pass. However, our old tests fail. The old tests should not be changed. It’s time to take a look at the total function. The total function is looking for number1 and number2. We can no longer guarantee that those properties will exist. The total function needs to be updated to use all number properties on the object regardless of name. The total is changed to a loop that adds all properties to a running total. for (num in this) { total += this[num]; }
Unfortunately, our tests still fail because properties from the prototype are also getting added in. We need to make sure the loop only uses this object’s own propertes, so the code is changed to: for (num in this) { if (this.hasOwnProperty(num)) { total += this[num]; } }
Now everything passes, so we can move on. Our new sets of tests are checking for existence and property length, but they are not using the total function yet. We add one more expect function to our new set of tests: expect(testObject.total()).toEqual(8);
The test passes, and everything is looking good.
3 of 6
TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3
A quick look at the code shows a new possibility we did not need to check for before. The JasmineTester can take any property type now, so what happens if any of the properties are not numbers? A new test is added to check if the same result is returned when a string is passed in as a property. //Make sure object doesn’t include strings in total it(‘Successful total with a string value’, function() { var testObject = new JasmineTester({ a: 2, b: ‘2’ }); });
expect(testObject.total()).toEqual(2);
This test fails. Expected 22 to equal 4.
The total function needs a little more work. The string ‘2’ is being concatenated to the running total instead of being added to it. Adding a typeof check will ensure that the property is a valid ‘number’ that can be used in a computation. Now the validation test passes. Even though the validation passes, it would be good to expand the check. Let’s ensure that the total function won’t break if other types are also sent in. The string unit test can be changed to be a generic validation check. The code can be modified to reuse one of the properties of the testObject multiple times and then send the object back for testing. //Make sure the total function doesn’t include/break with non-numbers it(‘Successful total with non-number values’, function() { var testObject = new JasmineTester({ a: 2, b: ‘2’ }); expect(testObject.total()).toEqual(2); testObject.b = function (){}; expect(testObject.total()).toEqual(2);
});
testObject.b = {b:2}; expect(testObject.total()).toEqual(2);
4 of 6
TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3
We run all of our tests in the suite and they all pass. Our new changes are complete.
The JasmineTester has now been expanded to be more robust and our total function is smarter than before. There are two critical points here: • The old tests still pass. Any code that would have been written previously is still working with our new changes. • Our process has also changed. Changes to our object started by being described in the unit test. The object was expanded after the test was written. Our development was being guided towards a demonstrable end point that showed success. 5 of 6
TUTORIALS BUILDING A UNIT TEST IN JASMINE, PART 3
The next post will finish this series by adding a second object to the mix. Other parts in the series: • Building a unit test in jasmine, Part 1 • Building a unit test in jasmine, Part 2
David Posin
his blog
share
Scrollmotion, Inc.
TWITTER
github
JavaScript Architect at
(
appliness
TUTORIALS HTML / CSS
BOOKMARK / SHARE / TOC
Using White Space for Readability in HTML and CSS. by Louis Lazaris
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
by Louis Lazaris
“Well-written, readable code doesn’t create mind games and labyrinths when other developers read it.”
This article was originally published in Smashing Magazine on February 19, 2013. You can read it here.
Right up front, I’ll offer some simple advice: In production, your code should be as performance-friendly as possible. This means, Gzip’ing, concatenating and minifying as many assets as possible, thus serving the smallest possible files and the least number of files. I don’t think anyone would argue that these suggestions aren’t best practices (even if we don’t implement them in every project).
Well-written, readable code doesn’t create mind games and labyrinths when other developers read it. (Image: Toca Boca) 2 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
Now that we’ve got that out of the way, how can we use white space in development code to ensure that our files are as readable and maintainable as possible? Well, we could consider a number of options, starting with some basics. (Smashing’s note: Subscribe to the Smashing eBook Library and get immediate unlimited access to all Smashing eBooks, released in the past and in the future, including digital versions of our printed books. At least 24 quality eBooks a year, 60 eBooks during the first year. Subscribe today!) BASIC HTML INDENTATION I think most if not all of us add basic indentation in our HTML: Section title Tagline Contact
Content goes here.
The principle here is that whenever something is nested, you indent, so that it’s clear where everything is in the markup’s hierarchy. With simple HTML nesting, the content in the section is often neglected, but keeping the nesting consistent here, too, is good practice.
3 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
For example, the following sample code is fairly readable, even with no nesting: Foo
However, with much more content in the section, nesting could make it easier to scan the contents: HTML5 Please - Use the new and shiny responsibly if (location.host == ‘h5bp.github.com’) location.href = ‘// html5please.us/’ 4 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
This last chunk of code is taken from the HTML5 Please website. As you can see, when the content in the section starts to get larger, indenting makes things a bit easier to digest at a glance. Notice that the and elements are indented, because they are both immediate children of the element. Of course, some developers might have a slightly different method of indenting in certain areas, but the idea is basically the same; the intention is to make the code easier to read in a development environment. BASIC CSS INDENTATION In addition to indenting HTML, many developers (me included) will do matching indentation in any corresponding CSS. The following code would match the HTML shown in the first example above: header { color: blue; } hgroup { color: green; } hgroup h1 { line-height: 1.5; } hgroup h2 { font-size: 15px; } nav { background: purple; } nav ul { float: left; } nav ul li { font-size: 20px; } nav ul li a, nav ul li a:visited { 5 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
}
text-decoration: none;
.main { border: solid 1px #ccc; }
To some, this seems a bit obsessive. But I prefer it because it helps me to scan the CSS and find matching hierarchies without having to read each selector. Of course, this type of hierarchy in your CSS should be used sparingly if you’re implementing modular CSS principles that encourage class-based modules and limited use of the descendant selector (for example, ul li). Certainly, some of the code above is kind of awful; I wouldn’t recommend tying your heading and list styles to a specific context like that. But for the purpose of understanding this concept of indenting CSS, look at it as a theoretical example. The point is that you have the option to indent CSS to match the HTML’s structure, thus making it easier to scan and easier to make sense of relative to the markup. Of course, as is the case with a few things mentioned in this post, some of this doesn’t apply when you’re using a CSS preprocessor. For example, the nested selectors option for Sass would make this last tip quite different in such an environment. READABLE CSS3 Let’s take our abuse of white space even further. Many new CSS3 features allow for either comma-separated or space-separated value sets. Two simple examples are multiple backgrounds and transforms. Let’s see how we can make these easier to read: .example { background: url(images/example.png) center center no-repeat, url(images/example-2.png) top left repeat, url(images/example-3.png) top right no-repeat; } .example-2 { transform: scale(.8) skew(20deg, 30deg) translateZ(0); }
Notice what we’ve done here? Instead of keeping the entire value on a single 6 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
line (which can get lengthy in some cases — especially when gradients and vendor prefixes are involved), we’ve put each value set on a new line, aligned with the one above it. Thus, each of the three backgrounds is on its own line, and each transform function is on its own line, left-aligned with the first of each example. Generally, this might go against the idea of having a single property per line (assuming, of course, that you’re not doing single-line rule sets). But when compared to the alternative of potentially really long lines, this is a good option, and it makes these rule sets very easy to read. DEALING WITH VENDOR PREFIXES As mentioned, if you’re preprocessing your CSS or using -prefix-free, then this advice doesn’t apply. But you could manipulate white space to make your vendor prefixes easier to read at a glance: .example { -webkit-transform: -moz-transform: -o-transform: transform: }
scale(.8); scale(.8); scale(.8); scale(.8);
Here we’ve lined up the colons so that the values align, making it easy to scan all values to ensure they’re the same. I can’t tell you how many times I’ve adjusted only the WebKit value in a rule set like this and forgotten to do the rest. Of course, this illustrates the importance of preprocessing, but if you’re not doing that yet, then this use of white space is a good option to consider. Additionally, many text editors offer a feature called “block edit” or multiline editing. This is available in Sublime Text, Vim, Coda and probably most others. Using this feature is that much easier when the values you’re changing are aligned vertically.
7 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
READABLE FILE REFERENCES The gist of this next suggestion comes from a tweet by Twitter Bootstrap cofounder Jacob Thornton. The idea here is that if a list of file references is contained in your document, you can make them easier to read by doing something like the following:
The example above is taken directly from Bootstrap. Here, all href attributes of the elements are aligned. This makes it easier to refer to or adjust a tag because the update will usually be to the value of the href attribute. Of course, this somewhat violates the rules of indenting HTML. So, alternatively, you could opt for this:
This latter example seems cleaner and has the bonus of aligning the other attributes, although that’s not as necessary in my opinion.
8 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
But wait. What if you don’t care that the href attribute is listed last (which seems to be the custom and is unnecessary for validation)? Then you could do this instead:
No white space tricks needed here, because the href attributes align just fine. But if you’re bothered by the lack of alignment of the other attributes, or if you just can’t stand the thought of the href attribute being listed first, then you’ll have to opt for one of the preceding solutions. READABLE CONDITIONAL CLASSES The concept behind the alignment of attributes is nothing new. HTML5 Boilerplate has been doing this sort of thing for some time now with its IE conditional classes. Here’s what that chunk of code looks like in the latest version:
class=”no-js”>
In this case, the class attribute on the opening tag in each conditional (and, incidentally, the tag itself) is being aligned, because this is the part of the code that’s most relevant to readability and maintenance, and the part of the code that would suffer most in readability if this alignment were not present.
9 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
READABLE COMMA-SEPARATED SELECTORS Sticking with Boilerplate, let’s go back to CSS. Here’s something used in that project’s main style sheet: html, button, input, select, textarea { color: #222; }
Here, instead of keeping all of the comma-separated selectors on a single line — which would be more difficult to scan — each selector is put on a new line. This can be helpful when the selectors are somewhat lengthy, as in this next example, also taken from Boilerplate: .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
Similar to the idea behind aligning HTML attributes discussed above, this vertical alignment makes the code a breeze to scan through when compared to scanning a single seemingly never-ending line of comma-separated selectors. CAN YOUR TEXT EDITOR HELP WITH ANY OF THIS? As a long-time developer who has grown accustomed to coding by hand, my knowledge of the features of different text editors is fairly limited. Some text editors or IDEs might do some of this automatically. Also, plugin developers can use some of these patterns to create plugins or extensions that do this sort of thing automatically or at the click of a button. If you have any suggestions of built-in tools or extensions to text editors that can assist with this, I’m sure Smashing Magazine’s readers would be glad to hear about them. 10 of 11
TUTORIALS USING WHITE SPACE FOR READABILITY IN HTML AND CSS
CONCLUSION We’re all encouraged to do whatever we can to make code in a development environment as easy to read and maintain as possible. I hope these suggestions will improve your code in this way. And knowing that this use of white space won’t bloat our files is comforting — after all, this is not for production code. So, do whatever you feel is necessary to make your HTML and CSS easier to deal with, and be sure to minify those assets when deploying to production. Finally, if you have any suggestions on using white space in HTML or CSS, we’d be glad to hear them.
Louis Lazaris
his blog
share
twitter
github
Web Developer
(
appliness
INTERVIEW CHRIS COYIER
BOOKMARK / SHARE / TOC
(
appliness
INTERVIEW CHRIS COYIER
BOOKMARK / SHARE / TOC
INTERVIEW
Chris Coyier
THE WEB CRAFTSMAN by Maile Valentine
ABOUT YOU
INTERVIEW CHRIS COYIER
APPLINESS: Hi Chris, thank you for your time, we’re excited to have you in this issue of Appliness! Can you tell us a bit about yourself? Chris Coyier: Thanks for having me! I’m a web worker. I write about the web at CSS-Tricks, talk about the web on ShopTalk, and design for the social coding site CodePen. How did you manage the transition into making css-tricks a full-time job? Can you tell us about some other projects you are actively working on or contributing to? It was a very slow process. I worked hard and continuously on CSS-Tricks while working full time for five years. Right about at the five year mark I was able to go off on my own, and even that was a bit risky. Luckily I was able to do a Kickstarter and ask people to help me and they did. My biggest project right now is CodePen, which I co-founded with Tim Sabat and Alex Vasquez. I’m excited every second I work on it. The things people build on CodePen are incredible. It is a place for inspiration, finding code to use on your own projects, learning new things, teaching, getting feedback, troubleshooting,
and more. CodePen is really what you make of it. We’re soon to be going through that same transition - going full time on it and building it into a strong business that can support us. Your design process sounds unique, can you describe it to our readers? How do you transition your design into development? I’m not sure my process is that unique. When designing from scratch I often use Photoshop a bit to get my bearings and stay as open minded as I can. But I get out of Photoshop as quickly as I can and into the browser. That’s where the things we build are used. That’s what matters. Fortunately, everywhere I’ve ever worked building websites, the teams were small enough that being crossdiscipline was a big advantage. I can work however I want to - I’m not waiting for designers to send me comps or designing things just to be passed off like more silo-oriented teams.
3 of 7
INTERVIEW CHRIS COYIER
CHRIS COYIER & WEB DESIGN What is the “white canvas funk”? How do you get out of this funk? When starting a project from scratch, any designer faces a empty white browser window or a blank white Photoshop document. This is the same kind of issue writers face when they start a new writing project, only
they have more established tricks for fighting against that moment of terror. For example, as a writer, you can just write out your grocery list. It’s not what you need to write, but it gets the blood flowing in your fingers and might get you started. As a designer, the equivalent might be just putting shapes and textures down on the page 4 of 7
INTERVIEW CHRIS COYIER
to get the creative juices flowing.
WEB DESIGN
What are your favorite tools to use for web design? Testing design / browser variances? I write code in Sublime Text and largely use Google Chrome as a browser to develop in. BrowserStack is pretty sweet for testing on a huge variety of other browsers without needing to have other computers or devices. Like many of us, IE testing is still a big thing, and I like to use a real Window 7 install running on my Mac through Parallels. It’s just nice and fast. I also own more than my fair share of devices. My most recent being a Nexus 7 so I have a real Android device for testing. How do you plan for performance as you develop? I mostly just think about the easy front end wins. Like using as few resources as I can. Compressing and concatenating all scripts and styles. Using a CDN. Making sure expires headers are set nice and long.
the final .css and .js files are created with cache busting random numbers in them so our changes are seen right away by users. Are you a fan of preprocessors? If so, what’s to like? Sass with Compass is fantastic. There is very little not to like. There is too many features to go into here, but getting into them isn’t something you’ll regret. It’s also very easy. See my screencast! You’ve had some big names on the very popular podcast ShopTalk, any guests (past or future) you are most excited about? I’m excited about every guest. For real. Everybody in this industry is so dang smart and has unique things to share. I think we give them a great venue on ShopTalk with our Q & A format. We don’t tell the questions ahead of time, so what you hear on the show is them reacting to unknown questions totally naturally. ShopTalk day is usually my favorite day of the week!
My biggest project right now, CodePen, is on Ruby on Rails and we use the Rails Asset Pipeline. It’s not all wonderful (our deployment is a bit slow at the moment) but I like what it does for us. It gives us Sass and Compass which concatenates and compresses our CSS (which we write in small modular bits). It also combines and concatenates JavaScript. Then when we do deploy, 5 of 7
INTERVIEW CHRIS COYIER
CHRIS COYIER & FUN Can you tell us what motivated you to write Digging into Wordpress and Wordpress 3: Creating and Editing Custom Themes? The book was a result of Jeff Starr and me essentially wanting to write a book together and choosing a topic we both had things to say about. I’ve used
WordPress a ton in my web career. It’s my go-to CMS for sure. Since I had to learn a lot about it to create all the sites with it that I have, writing about it was very easy and natural. We had both been writing about tech for a number of years. The Lynda.com course came a bit later 6 of 7
INTERVIEW CHRIS COYIER
and was a natural next step after the book. The book isn’t so much step-bystep theme building, and this course was.
Gosh I sure hope so. Thanks for having me!
FUN
I’m don’t have any book plans right now but I wouldn’t doubt I do another at some point in my life. I’m staying plenty busy between ShopTalk, CSSTricks, and CodePen. You play a mean ukulele and banjo any other instruments? I suck equally at the guitar and mandolin as well! Can you tell us about your history with music? Your roots in bluegrass? Do you play professionally? I was in an acoustic band for a bunch of years. Mid-college to a few years after college. It was bluegrass-ish but we didn’t have a scruggs-style banjo player which is kinda of a requirement for real bluegrass. I was in an acoustic Irish punk band called The Groggers after that for a few years. Funnily enough, I’m a much better musician now. I’ve kept up practicing and various lessons over the years, but I don’t do anything with it. Someday I’ll get back into it with a force I’m sure. I don’t really regret leaving it behind a while. The web thing has been great. Will your left brain and right brain continue to coexist peacefully to create technically creative things for the future? 7 of 7
(
appliness
TUTORIALS RESPONSIVE DESIGN
BOOKMARK / SHARE / TOC
Building a Better Responsive Website. by Jeremy Girard
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
by Jeremy Girard
“The project before us was the ideal opportunity to experiment and push ourselves to improve our responsive workflow.”
This article was originally published on the Smashing Magazine website on March 5, 2013. You can read it here.
Earlier this year, I was in the beginning stages of a redesign for our company’s website. We had already been planning to use a straightforward responsive approach to Web design, which is our preferred solution for multi-device support. After hearing some frank discussions at An Event Apart conference in Boston about the limitations and challenges of responsive Web design, I realized that our solution needed a bit of adjustment. Thankfully, the project before us was the ideal opportunity to experiment and push ourselves to improve our responsive workflow. In this article, I will detail the process we took, including some of the changes we made along the way, as we worked to build a better responsive website.
The variety of devices being used to access our websites is more diverse than ever. (Image: Blake Patterson)
2 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
DEFINING OUR GOALS The first step in our project was to make a list of the benefits and drawbacks to the responsive approach we had been using. Our list looked like this: BENEFITS 1. A single website to build, maintain and promote. 2. Support for a variety of screen sizes, not just the extreme cases of large desktop monitors and small handheld devices. 3. Future-friendly, because the layout will reflow based on screen size and not just the size of today’s popular devices. DRAWBACKS 1. Content meant only for large-screen devices is often delivered to small screens and simply “turned off” with CSS media queries, creating unnecessary downloads. 2. Because the markup is a one-size-fits-all solution, we are unable to change the source order of that markup (or eliminate unnecessary elements from the markup completely) based on the device or screen size. What you will likely notice here is that the drawbacks we identified with a responsive approach are areas where a mobile-only solution excels. We wanted the best of both worlds for our new website — the advantages that a responsive approach and a mobile-specific solution have to offer. STARTING WITH CONTENT One of the common differences between a responsive design and a dedicated or mobile-only design is in the content or features that are delivered to the browser. A mobile-specific website often features only a subset of content found on the “normal” version of the website. This is one of the ongoing debates about the two approaches, and proponents of mobile-only websites often argue that mobile users want access only to content that is “important” to them. The problem with this line of thinking is that what is “important” to a user — any user — changes according to their situation. Eliminating access to content based solely on the device someone is using is sure to alienate and frustrate anyone who doesn’t fit into the ideal scenario that you envisioned when you decided what to include in and what to eliminate from your mobile website.
3 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
Our belief has always been that all users should have access to all of the content that the website has to offer, but we wanted to make sure this was indeed the right answer for our website and our users. To help us determine the right approach, we turned to our analytics and found no discernible difference between the type of content requested by our mobile visitors and by our visitors on non-mobile devices. Content that was popular for desktop users was similarly popular for mobile visitors. Additionally, we sat down and spoke with some of our current clients, who represent a large part of our website’s audience, and asked them some questions, including “What content are you coming to our website for when on a desktop computer?” and “How about on a tablet or a phone?” The interviews were obviously more in depth than this, but you can see what we were asking. Once again, we found that the content they were seeking was the same, regardless of the device they were using. DATA DICTATES DIRECTION The findings from our research reinforced our belief that a responsive approach, which provides access to the same content across all devices, was the right choice for our website. This research also enabled us to determine what content on our website was not being accessed at all. When we discovered pages that were not being used by our audience, we cut them from our site map. Similarly, content that was most popular was treated appropriately in our content hierarchy and our layout plans for the redesign. By starting the project by looking at our content and gathering data on what was important to our audience and what was not, we were able to move into the design phase with an informed plan for what content our website’s design needed to support.
4 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
DESIGNING TO THE EXTREMES I have heard the arguments for designing in the browser, and I appreciate many of the benefits this approach brings. That being said, having tried designing in the browser on a number of occasions, I have found that my own design workflow is simply better suited to starting in Photoshop. In no way do I think this is the right decision for everyone, but it is the right decision for me, and it is how I began this design. For responsive designs, I use a method that I refer to as “designing to the extremes.” I start by designing the desktop version of the website. In this version, I work out the design’s typography, tone and overall visual direction — as well as the layout for the large screen view of the website. Once I am happy with this version of the design, I work on the small screen or “mobile” version of the website, using the same visual direction, but adjusting the layout as appropriate for the smaller screen. At the end of this process, I have visual examples of the two layouts of the website that will vary the greatest — the biggest and the smallest screen versions of the design. These two examples will guide me as I begin the website’s front-end development.
The “extreme” versions of the new website design 5 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
MOBILE FIRST The “mobile-first” approach to responsive design is not a new idea. This method, whereby you build the mobile experience and layout of a website first and then use media queries to adjust and add to that layout as the screen size grows, has been considered a best practice in responsive Web design for some time now. While not a new approach, it is still an important one, and coupled with our plan to “start with the content,” it helped us to address one of the shortcomings that we identified in our responsive projects — the problem of delivering unnecessary content. By starting with content, we ensured that all of our website’s content was relevant and appropriate to all users, mobile or otherwise. This meant that we didn’t have to worry about delivering large amounts of content in the markup only to have to hide it visually with CSS. The mobile-first approach meant that images would be delivered only to devices they are intended for. For instance, our new design called for a background graphic of a watercolor texture. The image, which is quite large, is intended to be a part of the design only on larger screens (660 pixels and up). Because our CSS starts with the mobile design first, this large graphic is never sent to small-screen devices because the media query that loads the image is activated only by larger screens. That media query, which applies the background to our html element, looks like this: @media only screen and (min-width: 660px) { html { background: url(/images/bg-watercolor.jpg) no-repeat fixed center top; } }
In addition to adding that background image, this media query that is triggered at 660 pixels also introduces a number of other layout changes to the website, transitioning from what we consider the small-screen layout to what will become the various larger-screen versions.
6 of 21
TUTORIALS TBUILDING A BETTER RESPONSIVE WEBSITE
BUILDING TO THE DESIGN, NOT TO DEVICES When we began using responsive design in our Web projects, we focused on known devices and screen sizes, and our media queries often reflected those known devices (iPhones, iPads in both portrait and landscape orientation, laptops, widescreen desktops, etc.). Over time, we found that this was not the best approach because it only addressed the devices and screen sizes that were popular today and not those that may come in future. One of the strengths of responsive Web design is its future-friendly aspect. So, to fully realize that strength, we moved away from building to devices, instead allowing the design to dictate our media query breakpoints. The mobile-first method established the baseline for our website’s CSS. With that in place, we launched the website in a browser and scaled it to the smallest size of our layout (we set a minimum width of 320 pixels in the CSS). Slowly, we increased the size of our browser window to see how the layout responded. As the browser window widened, we noticed that the layout began to feel strained. It was at these points that we would need to establish a new media query to adjust the layout. To help us with this approach, we created a graphic and set it as the background of our desktop. With vertical lines showing us a width of 320 pixels (our smallest size) and then a break at every hundred pixels starting with 400, we used this as a guide as we scaled the browser window to determine This desktop background can be used to help deterwhere the design started mine the breakpoints needed for a responsive design. to break down, and then used those approximate pixel values in the resulting media queries that we added to the CSS.
7 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
This approach of adding media queries based on the needs of the design, rather than on known device sizes, enables a website to better respond to a wider range of screen sizes. It does, however, end up filling the CSS file with more media queries than if you were using device-specific breakpoints. Still, while the number of media queries is higher, the queries themselves tend to be very small because you are making few changes with each one, rather than making the sweeping changes normally needed for device-specific media queries. One area of our website where this increase in media queries is evident is the navigation. RESPONSIVE NAVIGATION Handling navigation is one of the most challenging aspects of responsive design. For our website, we essentially have four main areas of navigation. 1. Primary navigation; 2. What we call the “help navigation,” which links to various portals and services that our clients use; 3. Footer navigation; 4. Section-specific navigation, which is presented on subpages of the website (for the larger-screen layouts) in the left-hand column. Because our CSS is mobile-first, one of the first things we did was to establish the navigation for our small-screen layout. This meant turning off the display of all of the navigation sections except for the primary navigation. #helpNav, .subNav, footer nav { display: none; }
Now, I said earlier that our goal was not to deliver content to devices only then to “turn it off.” That was indeed the goal, but with our navigation, we had to accept that this was how we needed to do it. We weren’t able to find another, simple yet maintainable, solution. Luckily, the content we are delivering and not displaying turns out to be only a few lists, so the impact on downloading for visitors is minimal. The help navigation is the one area of the website that has been considered to be not relevant to most users, because these links and portals are intended only for desktop users. Now that’s a big assumption and a bold statement. The rationale 8 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
behind this was that the portals themselves, which are all third-party applications over which we have no control, are not optimized for very small-screen mobile devices, and the services they offer are geared to supporting corporate clients with large screens on desktops. This situation informed our decision to remove that section from the small-screen version and in the months that the site has been live we received no comments or complaints from our user base regarding that decision. For the other two navigation areas, our subpage section navigation and our footer navigation, this content is presented as part of the primary navigation for small-screen devices. This is why we turn off these three areas by default. Later, as the screen size increases and we get past the 660-pixel point where the larger-screen design begins to show, we will style these navigation areas as needed. Here is the CSS for our help navigation: #helpNav { display: block; position: absolute; top: 1px; right: 0px; width: 100%; text-align: right; } #helpNav ul { padding-left: 10px; } #helpNav li { display: inline; padding-right: 6px; padding-left: 6px; background-color: #2f6a98; } #helpNav a { font-size: 12px; padding: 0 6px; color: #FFF; border-radius: 20px; } #helpNav a:hover { 9 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
}
background-color: #f66606;
And our subpage navigation areas: .subNav { display: block; width: 25%; float: left; } .subNav h4 { padding-bottom: 8px } .subNav ul { list-style: disc; color: #c65204; padding: 0 0 20px 20px; } .subNav li { padding-bottom: 14px; } .subNav a { color: #186483; font-size: 21px; font-family: ‘RokkittRegular’, Times, “Times New Roman”, serif; line-height: 1; }
Finally, our footer navigation: footer nav { display: block; margin-top: 40px; } footer nav ul { list-style: none; } footer nav li { padding-bottom: 24px; width: 19%; padding: 0 5% 20px 0; 10 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
}
float: left;
.innerNav li { width: 100%; float: none; padding-bottom: 4px; } footer nav a { color: #575454; font-size: 12px; } .innerNav a { font-weight: normal; }
PIXELS VS. EMS You will notice that we have used pixel values in our media queries. Using pixel-based media queries is how we, like many front-end developers, began implementing responsive design, and we have maintained the practice as part of our responsive workflow. In the spirit of “building a better responsive website,” though, I’ll point out an article on proportional media queries using ems that was brought to our attention during the editing of this piece. Essentially, to improve the appearance of the site when zoomed in, it’s highly recommended to convert px-media queries into em-media queries by dividing all pixel values by the body font-size. This wonderful article has caused us to rethink our pixel-based approach to media queries, and it is another example of how we continue to refine our responsive approach. While we did not use ems in our media queries in this particular project, we are experimenting with them now, and the approach is worth mentioning here.
11 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
PRIMARY NAVIGATION Our primary navigation is presented on wide screens as a horizontal row across the top of the layout. On small screens, this primary navigation structure changes so that there is a large “Menu” button at the top of each page that links to the navigation at the bottom of the page. To accomplish this, we added a link with an ID of menuLink and a class of tabButton in the header, which is near the start of the markup. We then placed a division with an ID of mainNav at the very end of the markup. Inside that division is our main navigation, which is simply an unordered list with a number of other unordered lists inside it for the subpage section menus. We also have another anchor with an ID of toTop, which acts as a link back to the top of the page.
The small-screen layout presents a “Menu” button at the very top of the layout.
12 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
Continuing our mobile-first approach, we styled the menu link at the top of the small-screen layout to look like a button. #menuLink a { float: right; margin: -56px 8px 0 0; } .tabButton a { color: #FFF; font-family: ‘RokkittRegular’, Times, “Times New Roman”, serif; font-size: 20px; background-color: #45829b; padding: 10px 12px; border-radius: 10px; } .tabButton a:hover { background-color: #f66606; }
Our main navigation menu is set to its small-screen display: #mainNav { margin-top: 30px; width: 100%; } #mainNav #toTop a { float: right; margin: 0 8px 0 0; font-size: 20px; } #mainNav nav { padding-top: 80px; } #mainNav ul { list-style: none; } #mainNav li { background: #45829b; border-bottom: 1px solid #abc7d2; padding: 4px 10px 4px 15px; } 13 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
#mainNav li:hover { background-color: #f66606; } #mainNav a { font-size: 24px; color: #FFF; font-family: ‘RokkittRegular’, Times, “Times New Roman”, serif; }
Our website’s primary navigation as presented for small-screen layouts
14 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
Our submenus, which are set not to display initially, we can now display as the page requires. Each of these submenus has a unique ID, such as servicesTab, and each section of the website has a class applied to the body tag. The class for the “Company” section is companyPage. We use this class to set styles for that entire section of the website. We use the class of the submenu sections to turn on the submenus as needed when a section is active. .companyPage #companyTab ul, .newsPage #newsTab ul, .contactPage #contactTab ul, .servicesPage #servicesTab ul { display: block; }
The subpage navigation displayed for the small-screen layout 15 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
GETTING LARGER As the larger-screen layouts kick in — once again with the media query for 660 pixels and above — we dramatically change the primary navigation’s layout. First, we turn off the display of the menuLink and toTop buttons because they are no longer needed: #menuLink a, #toTop a { display: none; }
Next, we style the mainNav horizontally across the top of the page to achieve the larger-screen design: #mainNav { position: absolute; top: 92px; margin: 18px 2% 0 2%; width: 96%; text-align: center; } #mainNav nav { padding: 5px 0; border-top: 1px solid #bacfd7; border-bottom: 1px solid #bacfd7; } #mainNav li { background: none; display: inline; border-bottom: 0; border-right: 1px solid #bebebe; padding: 0 6px 0 8px; margin: 4px 0; } #mainNav a { font-size: 16px; color: #45829b; } #mainNav a:hover { color: #f66606; } 16 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
These styles set the look of our primary navigation. But to build to the design, instead of to the device, we will need to make small adjustments as the screen size grows. Our primary navigation’s font has eight different sizes in total for the largerscreen layouts, changing as the screen grows and as we have more room to work with. Figuring out how best to display this navigation so that it is both easy to use and visually attractive was one of the challenges we faced while working with this responsive design. Initially, our font size is set to 16 pixels. Once we hit 767 pixels in width, we bump that to 18 pixels. @media only screen and (min-width : 767px) { #mainNav a { font-size: 18px; } }
We continue this pattern a number of times, increasing the font size finally to 27 pixels as the website reaches its largest size. In this way, the website’s navigation truly responds best to the design and to the screen being used to view that design. GETTING HELP FROM THE CMS Our preferred CMS is ExpressionEngine, and the specifics of this next portion of the article refer to that platform, but the general idea of what we accomplished with ExpressionEngine could undoubtedly be applied to other popular CMS platforms as well. One of the biggest drawbacks to the responsive approach is that you cannot deliver different markup or a different source order to different devices. This drawback is what we wanted to overcome with our CMS. During our experimentation and research, we stumbled upon an article titled “Going Truly Adaptive With ExpressionEngine.” Using the approach detailed in this article, we were able to use a device-detection script to set a variable in the system of either mobile or full. We could then conditionally load markup into our website based on which of these variables was met. By going further and using the device detection, we were able to make other very small changes to further improve the mobile experience. To us, this was kind of like 17 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
progressive enhancement, where we created a quality solution and then tried to take it further to deliver a slightly more optimized experience. Make sure to read Chris Coyier’s similar view on combining RWD and mobile templates in which he argues about mixing and matching a variety of techniques for your mobile strategy. STARTING SMALL You could certainly use these variables to deliver completely different markup and source orders to different devices, but our initial approach was a little less extreme. Because we had already decided that all versions of our website would have access to all content, we initially used this variable method to make slight adjustments to how much of that content would be delivered. For instance, on our website’s home page, we show teasers for a variety of content found within the website. For the “Culture” and “Project Spotlight” sections, an image accompanies each post. The images are a nice-to-have addition but certainly not critical, so we do not deliver these images to mobile users at all. Now, I do not mean that we use CSS to turn off their display, which would cause the data to get delivered to the browser anyway; instead, we use the variables we have established to omit the images from the markup unless they need to be shown.
The teaser images are nice to have, but not critical to the content or layout.
18 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
The syntax is quite easy. Once you have established your variables — which the aforementioned article explains how to do easily by adding a little script to the system’s config.php file — you can use those variables like an if statement. {if global:site_version==’full’}{/if} {if global:site_version==’mobile’} {title}{/if}
This is ExpressionEngine syntax, but you should be able to read this and easily see what is happening. If the full variable is met, then we deliver the teaser-image from that article’s entry in the database. If the mobile variable is met instead, then we deliver the title of the article. We use this same approach for the home page’s “News” and “Blog” sections, delivering three short teasers if the full variable is met and only one if the mobile one is. That syntax looks like this: {exp:channel:entries channel=”news” {if global:site_version==’full’}limit=”3”{/ if}{if global:site_version==’mobile’}limit=”1”{/if}}
Here you see that we are accessing the ExpressionEngine channel named news. We use our variable to determine how many recent entries will be displayed from that channel, using the limit parameter. TAKING IT A STEP FURTHER In the website’s “Culture” section, we publish articles that are often accompanied by a number of images. Unlike the teaser images on the website’s home page, the images in the articles themselves are critical to that content, because they help to carry or reinforce the article’s point. Now, while the images are important, they are also quite large — each one is 650 pixels wide, and most articles include at least three images and as many as ten. Because mobile devices will show the images at about half their original size, the downloads for the full-sized images would be quite substantial. To address this, we once again turned to our device detection and variables. For each article, we produce two sets of images: one full sized at 650 pixels wide and a second set at almost half that size. We then use the variables in our article (but first we need to allow ExpressionEngine code in our page’s template), and we include the markup for both sets of images — but only one set is ever delivered to the browser. Mobile devices get the smaller images, while everything else gets 19 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
the normal set. We take a similar approach with the home page’s large billboard area. These rotating banner messages and images are used to promote important items, such as upcoming events, new services and announcements, in a bigger way than we do in the other areas of the home page. The billboard is another nice-to-have element that is intended for large displays only. Once again, we use the variables to deliver the main billboard division, as well as the JavaScript that runs it, to appropriate devices — effectively enabling us to send different markup to different devices and eliminating yet another of the drawbacks that we identified at the start of this project. Through a mobile-first approach and with our CMS’ help, we are able to deliver our home page to desktop users at 738.3 KB and dramatically reduce that to only 174.4 KB for mobile users. FALLBACK PLANS One of the questions that has always bothered me about a mobile-only approach and device detection is, What happens if that detection fails? Is the “normal” version of the website delivered to the mobile device, thereby rendering your carefully designed mobile experience null and void? This possibility is one of the main reasons why I have avoided a mobile-only solution that uses device detection in the past. For our new responsive workflow, we are using device detection, but our process has equipped us with excellent fallbacks in case that detection fails for some reason. Because we are using a responsive approach, even if the full version get delivered to a mobile browser, the layout will be suited to that device because our CSS will adjust the website’s layout accordingly. Additionally, because we went with a mobile-first build, items not intended for small screens, such as the giant background graphic mentioned above, do not get delivered either. The only thing that will fail is what we have done with our device detection-generated variables. If the worst-case scenario happens and our detection fails, then the mobile version would simply get a few extra images or a little markup or JavaScript that it does not need. The experience would still be suited to mobile. Not bad at all for a “worst-case scenario.”
20 of 21
TUTORIALS BUILDING A BETTER RESPONSIVE WEBSITE
PROGRESS, NOT PERFECTION A few years ago, a client said something to me that has stuck with me to this day. Talking about his website, he said:
“D
on’t worry about making my website perfect. Just work on making it better. If we’re constantly making it better, we’re going in
the right direction.”
This idea has guided me over the years and reminded me never to dismiss a better solution simply because it is not perfect. I know this is not a perfect solution, and I am OK with that because it is an improvement to our previous responsive workflow. It has helped us overcome some obstacles that we identified, and we can now bring those improvements to other projects we are working on. Yes, there are still many issues that we have yet to effectively address, such as the delivery of higher-quality images to HD displays as well as the use of em-based media queries referred to earlier in this piece, but we are moving in the right direction for this project and for others. Who knows? Maybe someday someone will build a “perfect website.” In the meantime, we will focus on progress, not perfection, as we continue to make small improvements along the way, working to build a better responsive website.
Jeremy Girard
his blog
share
twitter
github
Director of Web Development
(
appliness
TUTORIALS LIBRARY
A responsive boilerplate by Fernando Monteiro
BOOKMARK / SHARE / TOC
TUTORIALS A RESPONSIVE BOILERPLATE
by Fernando Monteiro
“This is my micro framework to build responsive websites”
SKELETON FRAMEWORK Hello everyone, my name is Fernando Monteiro and i’m front-end developer in Brazil. Today I will write a few lines about the micro framework, ResponsiveBoilerplate, which can be downloaded for free through the url: http://www.responsiveboilerplate.com, and github repository at: https://github.com/newaeonweb/responsiveboilerplate. It began in mid-2010 when I was hired to work in a big project of web software. Our aim was to create a big news portal using some techniques of fluid grids, at that time still unheard effectively responsive design here on our land, everything was very new and unknown even to our team of experienced developers. Then I read the book by Etham Marcote called Responsive Design, it changed my way of thinking and seeing the new reality of web development at the time. In that same season I began researching similar solutions and also trying to develop something solution in this regard. A few minutes of google search brought me a lot of the same options that I had in mind. It was there that I had my first actual contact with a responsive framework: Skeleton Framework, too be more exactly. Since that time already used and researched a lot of frameworks, among them, bootstrap, 1140, 960gs, baseline, Ink among others, I also had the opportunity to develop small websites using these tools so i decide to write myself a micro framework . The ResponsiveBoilerplate is a micro framework, based on columns, to be exact, there are 12 columns and a container. The biggest difference is the simplicity in writing and ease of use. In a more detailed analysis, most frameworks have 50-60% of code (css) is not used in structuring simple pages. I say this without counting the stylesheets that bring additional formatting, colors, prefixes, forms and jquery plugins to do simple tasks like accordion, or slideshow.
2 of 3
TUTORIALS A RESPONSIVE BOILERPLATE
In ResponsiveBoilerplate, everything has been designed to be as simple and intuitive as possible, so the developer gains more flexibility in use and not waste time reading a big documentation. The learning curve is very small compared to other framework. Also, included in download package some snippets for sublime text editor, a template for photoshop and a basic javascript for navigation. Of course he is not the best framework and does not intend to be. But the intention is to provide just the basics needed to build responsive layouts. Some features: - Very Lightweight - Contains only 12 columns and 1 container as the main base. - Low learning curve to use. - Optimized for mobile devices. - Includes four breakpoints for the most common resolutions (320, 480, 768, 1024). - No minimum limit of width. − Fits any screen size, even in screens of 32 inches or more. − Use respond.js and head.js for better performance. - It’s free ... and contributions are most welcome ... A demo: http://riagora.com/appliness/samples/responsive/demo.html Source code of the demo: http://riagora.com/appliness/samples/responsive/source.zip
Fernando Monteiro Web Developer
his blog
share
twitter
github
(
appliness
TUTORIALS HTML
The Progress Element. by Ian Devlin
BOOKMARK / SHARE / TOC
TUTORIALS THE PROGRESS ELEMENT
by Ian Devlin
“HTML5 makes life easier for us by defining the right element.”
This article was originally published on the html5 Doctor website on February 12, 2013. You can read it here.
When building web sites and web applications, we often need to provide essential feedback to a user informing them of the progress of their request or task, be it uploading a file, playing a video, or importing data. HTML5 makes life easier for us by defining an element whose sole purpose is just that: the element.
“The progress element represents the completion progress of a task .”
The HTML5 specification describes it best: “The progress element represents the completion progress of a task.” The task itself is irrelevant, but displaying its progress is not.
2 of 8
TUTORIALS THE PROGRESS ELEMENT
ATTRIBUTES There are four attributes that are specified for the element: max, value, position, and labels. Before taking a look at each of theses attributes in turn, here are a few important notes on them: • If the value attribute exists, then the progress bar is considered to be determinate (i.e., it has exact limits). Otherwise it is considered to be indeterminate. • If the max attribute is not included, the default acceptable range for the progress bar is between 0.0 and 1.0 inclusive. • Authors are encouraged always to include the current value and the maximum value (if used) as inline text to the element so that the information is still visible to users of legacy browsers. And now let’s take a closer look at the attributes themselves: Max The max attribute is a floating point number that indicates how much work the relevant task requires in total before it can be considered complete. The default value is 1.0. Value This is a floating point number that represents the current progress of the relevant task. Its value must be greater than or equal to 0.0 and less than or equal to 1.0 or the value of the max attribute if present. Position This is a read-only attribute that returns the current position of the element. This value is equal to value / max for a determinate progress bar and -1 for an indeterminate progress bar (as the position can’t accurately be determined). Labels This is also a read-only attribute that returns a list of the element’s labels (if there are any).
3 of 8
TUTORIALS THE PROGRESS ELEMENT
EXAMPLES Let’s now take a look at some examples of how the element might be used, including how it might be updated via JavaScript. SIMPLE INDETERMINATE PROGRESS BAR
Since we have no idea how long the task in hand will take, the browser will simply display the progress bar until the task is complete and we either hide it or replace it with a ‘task complete’ message. SIMPLE DETERMINATE PROGRESS BAR 0%
And the JavaScript for updating it: var pBar = document.getElementById(‘p’); var updateProgress = function(value) { pBar.value = value; pBar.getElementsByTagName(‘span’)[0].innerHTML = Math.floor((100 / 70) * value); }
Note that here the progress bar can have a maximum value of 70, so calls to updateProgress will have values between 0 and 70 and that the value is also displayed within the element so that it is visible as a simple percentage string for users of legacy browsers. USING WITH HTML5 VIDEO A good example of using the element is with an HTML5 video, informing the user how much of the video has been played. This won’t be a full example but will just show the necessary HTML and JavaScript.
4 of 8
TUTORIALS THE PROGRESS ELEMENT
Given a element with an id of ‘v’: 0% played
Use this JavaScript: var video = document.getElementById(‘v’); var pBar = document.getElementById(‘p’); video.addEventListener(‘timeupdate’, function() { var percent = Math.floor((100 / video.duration) * video.currentTime); pBar.value = percent; pBar.getElementsByTagName(‘span’)[0].innerHTML = percent; }, false);
The JavaScript uses the timeupdate event, which is constantly triggered as the video is being played. The value is converted into a percentage value using the video’s duration (full length) and currentTime (where in the video it currently is). USING WITH THE FILE API Another useful example is how the element might be used with the File API. Again, this is not a complete example, assuming the existence of a file input and upload button and element, and code for reading the file. The specification itself has some good code examples of this. var p = document.getElementById(‘p’); // ‘reader’ is of type FileReader reader.addEventListener(‘loadstart’, function(evt) { if (evt.lengthComputable) p.max = evt.total; }, false); reader.addEventListener(‘progress’, function(evt) { if (evt.lengthComputable) p.value = evt.loaded; }, false);
Here the loadstart event is used to set the max attribute of the element, and then the progress event is used to update the element’s value attribute.
5 of 8
TUTORIALS THE PROGRESS ELEMENT
BROWSER SUPPORT The element is fairly well-supported in today’s major browsers, although only in version 6+ of Safari (so not on Windows, as the last version there was 5.1) and only in version 10+ of Internet Explorer. STYLING As is usual with such elements, browsers have their own unique styling for the element. You can, however, override this to a certain extent using simple CSS. The default styling tends to consist of an element with rounded corners, a grey background colour, and a green gradient for the actual progress marker.
The default styling for the progress element in Firefox 18.0.2. Let’s say we want to style our progress bar for the HTML5 Doctor website, so that it fits in with the design. We’ll remove the bevel and the gradients using only solid colours. The code below will almost do that: progress { color: #0063a6; font-size: .6em; line-height: 1.5em; text-indent: .5em; width: 15em; height: 1.8em; border: 1px solid #0063a6; background: #fff; }
This, however, won’t change the colour of the progress bar itself, which will remain a green colour. We can change this in Firefox, Internet Explorer 10, Chrome, and Safari using a variety of methods which are outlined below.
6 of 8
TUTORIALS THE PROGRESS ELEMENT
FIREFOX All we need to use here is: progress::-moz-progress-bar { background: #0063a6; }
and Firefox will display the colour correctly.
The progress bar as it appears in Firefox 18.0.2 after being styled. CHROME AND SAFARI UPDATE – 13TH FEBRUARY 2013 Opera have just announced their move to using WebKit as their rendering engine, so eventually the WebKit specifc styling rules will also work in Opera. For Chrome and Safari, we need to use progress::-webkit-progress-value to specify the progress bar colour and progress::-webkit-progress-bar to specify the background colour of the element itself: progress::-webkit-progress-bar { background: #fff; } progress::-webkit-progress-value { background: #0063a6; }
INTERNET EXPLORER 10 Actually the CSS above will be fine to style the element in IE10, but it’s worth noting that this browser interprets the element’s color value as the colour of the progress bar. I’ve uploaded some working examples of determinate and indeterminate progress bars for you to see.
7 of 8
TUTORIALS THE PROGRESS ELEMENT
SUMMARY The element may seem very similar to the element — which was also introduced in HTML5 — but it can be seen as a more specific kind of element that’s only used to measure progress of a task. It’s worth bearing this in mind when deciding which one to use. Since browser support is pretty good, it’s definitely worth using the element where appropriate, but you should also ensure that you provide textual fallback for legacy browsers as has been outlined above.
Ian Devlin
his blog
share
twitter
github
Web Developer
(
appliness
TUTORIALS CSS
BOOKMARK / SHARE / TOC
Dig Deep into CSS Linear Gradients. by Ana Tudor
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
by Ana Tudor
“I had no idea how powerful CSS gradients could be until late 2011.”
INTRODUCTION Ana Tudor is passionate about experimenting and learning new things. Also she loves maths and enjoys playing with code. I had no idea how powerful CSS gradients could be until late 2011, when I found the CSS3 Patterns Gallery made by Lea Verou. The idea that you can obtain many shapes using just gradients was a starting point for many CSS experiments I would later do. Recently, while browsing through the demos on CodePen, I came across a CSS3 Color Wheel and thought hey, I could do it with just one element and gradients. So I did and the result can be seen here. And now I’m going to explain the reasoning behind it. BREAKING IT DOWN The wheel - or you can think of it as a pie - is first split horizontally into two halves and then each half is split into five slices, so there are ten slices in total. Which means that the central angle for each slice is 360°/10 = 36°. The pen shows graphically how to layer the multiple backgrounds. It also has a pause button so that the infinite animation doesn’t turn into a performance problem. 2 of 10
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
For both the original pen and this helper demo, the interesting part is this one: background: linear-gradient(36deg, #272b66 42.34%, transparent 42.34%), linear-gradient(72deg, #2d559f 75.48%, transparent 75.48%), linear-gradient(-36deg, #9ac147 42.34%, transparent 42.34%) 100% 0, linear-gradient(-72deg, #639b47 75.48%, transparent 75.48%) 100% 0, linear-gradient(36deg, transparent 57.66%, #e1e23b 57.66%) 100% 100%, linear-gradient(72deg, transparent 24.52%, #f7941e 24.52%) 100% 100%, linear-gradient(-36deg, transparent 57.66%, #662a6c 57.66%) 0 100%, linear-gradient(-72deg, transparent 24.52%, #9a1d34 24.52%) 0 100%, #43a1cd linear-gradient(#ba3e2e, #ba3e2e) 50% 100%; background-repeat: no-repeat; background-size: 50% 50%;
We first specify the nine gradient backgrounds, their positioning and the background-color using the shorthand background syntax. THE BACKGROUND SHORTHAND For anyone who doesn’t remember, the background layers are listed from the top one to the bottom one and the background-color is specified together with the bottom layer. A background layer includes the following: • • / • • • • If the background-position is not specified, then the background-size isn’t specified either. Also, since background-origin and background-clip both need the same kind of value (that is, a box value like border-box or contentbox), then, if there is only one such value, that value is given to both backgroundorigin and background-clip. Other than that, any value except the one for background-image can be missing and then it is assumed to be the default. Since we have nine background layers and we want to have the same non-default 3 of 10
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
values for background-repeat and background-size for all of them, we specify these outside the shorthand so that we don’t have to write the same thing nine times. In the case of background-size, there is also another reason to do that: Safari doesn’t support background-size inside the shorthand and, until recently (up to and including version 17), Firefox didn’t support that either. Also, two values should be always given when the background-image is a gradient, because giving it just one value is going to produce different results in different browsers (unless that one value is 100%, in which case it might as well be missing as that is the default).
“Safari doesn’t support background-size inside the shorthand”
The background-color is set to be a light blue (#43a1cd) and then, on top of it, there are layered nine non-repeating (background-repeat: no-repeat for all) background images created using CSS gradients. All nine of them are half the width and the height of the element (background-size: 50% 50%). The bottom one - horizontally centred (50%) and at the bottom (100%) - is really simple. It’s just a gradient from a firebrick red to the same color (lineargradient(#ba3e2e, #ba3e2e)), so the result is simply a solid color square. The other eight are gradients from transparent to a solid color or from a solid color to transparent. Four of them look like double slices, having a central angle of 2*36° = 72°, but half of each such double slice gets covered by another single slice (having a central angle of 36°).
4 of 10
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
A FEW THINGS ABOUT LINEAR GRADIENTS In order to better understand gradient angles and how the % values for color stops are computed, let’s see how a linear gradient is defined. Hopefully, this demo that lets you change the gradient angle helps with that - just click the dots.
The gradient angle is the angle - measured clockwise - between the vertical axis and the gradient line (the blue line in the demo). This is for the new syntax, which is not yet supported by WebKit browsers (however, this is going to change). The old syntax measured angles just like on the trigonometric unit circle (counter-clockwise and starting from the horizontal axis). Note: coming from a mathematical background, I have to say the old way feels more natural to me. However, the new way feels consistent with other CSS features, like rotate transforms, for which the angle values are also clockwise. What this means is that we (almost always) have different angle values in the standard syntax and in the current WebKit syntax. So, if we are not using something like -prefix-free (which I do almost all the time), then we should to be able to compute one when knowing the other. That is actually pretty simple. They are going in opposite directions, so the formula for one includes the other with a minus sign.
5 of 10
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
Also, there is a 90° difference between them so this is how we get them: newSyntax = 90° - oldSyntax; oldSyntax = 90° - newSyntax;
Note: if no gradient angle or destination side is specified (for example, linear-gradient(lime, yellow)), then the resulting gradient is going to have a gradient angle of 180°, not 0°. All the points on a line that is perpendicular on the gradient line have the same color. The perpendicular from the corner in the quadrant that’s opposite to the quadrant of the angle is the 0% line (the crimson line in the demo) and its intersection with the gradient line is the starting point of the gradient (let’s call it S). The perpendicular from the opposite corner (the one in the same quadrant as the gradient angle) is the 100% line (the black line in the demo) and its intersection with the gradient line is the ending point of the gradient (let’s call it E).
In order to compute the % value of any point P, we first draw a perpendicular on the gradient line starting from that point. The intersection between the gradient line and this perpendicular is going to be a point we’ll name I. We now compute the ratio between the lengths of SI and SE and the % value for that point is going to be 100% times that ratio.
6 of 10
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
PUTTING IT ALL TO WORK Now let’s see how we apply this for the particular case of the rainbow wheel. Let’s first consider a gradient that creates a single slice (one with a central angle of 36°). This is a square image (see below), with a blue slice having an angle of 36° in the lower part. We draw the horizontal and vertical axes through the point O at which the diagonals intersect. We draw a perpendicular from that point to the line that separates the dark blue part from the transparent part. This is going to be the gradient line. As it can be seen, there is a 36° angle between the vertical axis and the gradient line, so the angle of the gradient is 36°. We now draw a perpendicular from the corner of the square in the quadrant that is opposite to the one in which the gradient angle is found. This is the 0% line. Then
we draw a perpendicular from the corner of the square in the same quadrant (Q I) as the gradient angle - this is the 100% line. The intersection of the diagonals of a square splits each one of them into two, so 7 of 10
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
AO and BO are equal. The BOE and AOS angles are equal, as they are vertical angles. Moreover, the BOE and AOS triangles are right triangles. All these three mean that the two triangles are also congruent. Which in turn means that SO and EO are equal, so the length of SE is going to be twice the length of EO or twice the length of SO. Note: before moving further, let’s go through a couple of trigonometry concepts first. The longest side of a right-angled triangle is the one opposing that right angle and it’s called the hypotenuse. The other two sides (the ones forming the right angle) are called the catheti of the right triangle. The sine of an acute angle in a right triangle is the ratio between the cathetus opposing that angle and the hypotenuse. The cosine of the same angle is the ratio between the adjacent cathetus and the hypothenuse. Computing the length of EO in the right triangle BOE is really simple. If we take the length of the side of the square to be a, then the length of the half diagonal BO is going to be a*sqrt(2)/2. The BOE angle is equal to the difference between the BOM angle, which is 45°, and the EOM angle, which is 36°. This makes BOE have 9°. Since BO is also the hypotenuse in the right triangle BOE, the length of EO is going to be (a*sqrt(2)/2)*cos9°. Which makes the length of SE be a*sqrt(2)*cos9°. We now draw a perpendicular from A to the PI line. ASID is a rectangle, which means that the length of SI equals the length of AD. We now consider the rectangular triangle APD. In this triangle, AP is the hypotenuse and has a length of a. This means that AD is going to have a length of a*sin36°. But SI is equal to AD, so it also has a length of a*sin36°. Since we now know both SI and SE, we can compute their ratio. It is sin36°/ (sqrt(2)*cos9°) = 0.4234. So the % value for the color stop is 42.34%.
8 of 10
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
In this way, we’ve arrived at: linear-gradient(36deg, #272b66 42.34%, transparent 42.34%) Computing the % values for the other background layers is done in the exact same manner. AUTOMATING ALL THIS By now, you’re probably thinking it sucks to do so many computations. And it must be even worse when there are more gradients with different angles... Even though for creating the rainbow wheel experiment I did compute everything on paper... I can only agree with that! This is why I made a really basic little tool that computes the % for any point inside the gradient box. You just need to click inside it and the % value appears in a box at the bottom center.
You can change the dimensions of the gradient box and you can also change the gradient itself. It accepts the newest syntax for linear gradients, with angle values in degrees, to values or no value at all for describing the direction of the gradient. 9 of 10
TUTORIALS DIG DEEP INTO CSS LINEAR GRADIENTS
FINAL WORDS CSS gradients are really powerful and understanding how they work can be really useful for creating all sorts of imageless textures or shapes that would be difficult to obtain otherwise.
Ana Tudor
hER blog
share
twitter
github
CSS & Math Expert
(
appliness
TUTORIALS CSS
BOOKMARK / SHARE / TOC
The Problem of CSS Form Elements. by Gabriele Romanato
TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS
by Gabriele Romanato
“Back in 2004 and later in 2007, Roger Johansson created a complete test suite for form elements and CSS.”
This article was originally published on the Smashing Magazine website on March 31, 2013. You can read it here.
Before 1998, the birth year of CSS Level 2, form elements were already widely implemented in all major browsers. The CSS 2 specification did not address the problem of how form elements should be presented to users. Because these elements are part of the UI of every Web document, the specification’s authors preferred to leave the visual layout of such elements to the default style sheet of Web browsers. Through the years, this lack of detail in the CSS specification has forced Web developers to produce a significant number of tests and examples whose primary goal is to reduce form elements to a common visual denominator in order to get a cross-browser rendering of elements such as input, select, fieldset, legend and textarea. In this article, we will cover some of the CSS patterns used by Web developers to tame the visual layout of form elements. ROGER JOHANSSON’S TESTS Back in 2004 and later in 2007, Roger Johansson created a complete test suite for form elements and CSS. These seminal tests, which can be found in his article “Styling Form Controls With CSS, Revisited,” lead to the frustrating conclusion that Johansson summarizes with the following words:
“S
o what does this experiment show? Like I already stated, it shows that using CSS to style form controls to look exactly the same across browsers and platforms is impossible. It also shows that most browsers ignore many CSS properties when they are applied to form controls.” 2 of 9
TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS
Despite the underlying truth of these conclusions, Web developers continued to extensively test CSS styles on form elements to find the Holy Grail of — or at least a reasonable compromise between — the browser’s default rendering and the author’s styles.
THE DEFAULT MODEL The CSS 2.1 specification states in its proposed default style sheet for HTML4 that form elements such as textarea, input and select are inline-block elements: textarea, input, select { display: inline-block; }
Conversely, the form and fieldset elements are block-level elements: fieldset, form { display: block; }
The default model proposed by the CSS specification stops here. All other visual aspects of form elements rely on the browser’s default style sheet. However, the above rules indicate the following: • Inline-block elements can be styled using an inline formatting context. This implies the use of CSS properties such as line-height and vertical-align to control the height of the box and its vertical alignment. Padding and margins can also be applied to define the outer and inner spacing of the affected box. As well, inline-block elements accept widths and heights because they share the block formatting model. • Block-level elements can be styled using the well-known block formatting context. However, problems arise with the fieldset and legend elements because legend relies entirely on the default styles provided by Web browsers. How do Web developers manage these problems?
3 of 9
TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS
DEFINING DIMENSIONS Web developers soon noticed that Web browsers handle inline-block elements oddly when it comes to defining dimensions. Defining an height often leads to unexpected results: input, select { width: 120px; height: 32px; }
Developers tried to fix this problem by turning these elements into block-level elements: input, select { width: 120px; height: 32px; display: block; }
Results are still poor, except for the textarea element. A common pattern to solve this problem is to avoid the height property and instead to use the fontsize and padding properties. Browsers do not use the same font family and size on these elements, so the first thing to do is normalize them: input, select { width: 120px; font: 1em Arial, sans-serif; }
For an example, see the page “CSS: Defining Form Element Dimensions” on jsFiddle. Once the font in use is normalized, you can add padding to give some inner spacing to the element’s box: input, select { width: 120px; font: 1em Arial, sans-serif; padding: 3px 6px; }
4 of 9
TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS
The input elements and textarea also show a border that affects their box model: input[type=”text”], input[type=”password”], textarea { border: 1px solid #ccc; }
The input elements of the types button and submit have additional padding set by Web browsers. So, a common practice is to normalize them: input[type=”button”], input[type=”submit”] { padding: 2px; }
The problem with this approach is that Web browsers also apply vendor-specific properties to these elements, so our padding is not always able to normalize this property. For example, in a Webkit-based browser, you might have this: input[type=”button”], input[type=”submit”], input[type=”reset”], input[type=”file”]::-webkit-file-upload-button, button { -webkit-box-align: center; text-align: center; cursor: default; color: buttontext; padding: 2px 6px 3px; border: 2px outset buttonface; border-image: initial; background-color: buttonface; box-sizing: border-box; } input[type=”button”], input[type=”submit”], input[type=”reset”] { -webkit-appearance: push-button; white-space: pre; }
5 of 9
TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS
Padding is also used on the fieldset and legend elements but with different results: • Setting the padding on fieldset to 0 will reset the default indentation of the legend elements in some browsers (though not in IE). • Setting the padding on legend to 0 has the effect of making this element shrink. Select boxes, checkboxes and radio buttons can be normalized with good results with only a few properties, namely: • font-family, • font-size, • width (on select boxes), • padding. Applying other properties to this group of elements often leads to inconsistent results across browsers.
ALIGNMENT Form elements can be vertically or horizontally aligned. They can be laid out on the same line or as a group of boxes on multiple rows. To align them on the same line, you can follow one of two approaches: 1. Use floating, 2. Use the default inline-block context on some of these elements. When you use floating, elements are automatically turned into block-level elements. This means that form elements are now subject to the nine rules that govern floated elements. Form elements can be vertically or horizontally aligned.
6 of 9
TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS
With floats, the main challenge is to achieve good vertical alignment on the current line. In this case, using vertical margins or padding is a common practice: input, select { width: 120px; float: left; margin-top: 0.4em; }
This approach works when you do not have to align boxes with text, such as with the contents of a label element. In this case, you could use relative positioning, padding or margins on the element that contains only text: label { float: left; padding-top: 0.4em; width: 5em; margin-right: 1em; }
Another problem arises with buttons. In this case, when you have a button whose dimensions are greater than those of other elements, you can force its vertical alignment with relative positioning: input[type=”submit”] { float: left; width: 90px; position: relative; top: 0.4em; }
This approach with relative positioning also works with checkboxes and radio buttons. Relative positioning can even be applied to normalize the left indentation of the legend element within a fieldset element, the only difference being that you would use the left property instead of top. When using inline formatting, you can rely on the vertical-align property to vertically align elements: label, input[type=”text”] { vertical-align: middle; margin-right: 1em; }
7 of 9
TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS
Good results can be achieved by combining this property with the line-height property. However, this property must be set on the parent element. If you set this property directly on the form’s elements, their computed height would be affected: .form-row { line-height: 1.4; }
Using a declared height on the parent element is also effective when paired with the same value for the line height: .form-row { line-height: 1.8; height: 1.8em; }
With inline formatting, you can also use the text-align property on the parent element to align elements to the right, left or center. THE STRANGE CASE OF FILE INPUTS The file input element — that is, — is a special case. This kind of element must always be visible and recognizable in the browser’s UI for security reasons. This implies that browsers deliberately ignore some style rules (such as those related to visibility) and tend to apply the algorithms defined in their default style sheet. Furthermore, the default rendering varies from browser to browser: some browsers display only a single button, while others add a text field to display the path of the uploaded file. Web developers, however, soon found a way to circumvent these limitations. First, they wrapped the input element in a container:
8 of 9
TUTORIALS THE PROBLEM OF CSS FORM ELEMENTS
Then, they hid the input element using the opacity property and applied certain styles to the input’s container: .upload { width: 157px; height: 57px; background: url(upload.png) no-repeat; overflow: hidden; } .upload input { display: block !important; width: 157px !important; height: 57px !important; opacity: 0 !important; overflow: hidden !important; }
Notice the !important statement. This is the preferred way to override the browser’s default rules. For an example, see the page “CSS: Styling Inputs of Type ‘file’” on jsFiddle. CONCLUSION Totally taming form elements is impossible due to the lack of detail in the CSS specification and because of the default styles applied by Web browsers. However, by following some common practices, reducing (though not eliminating) the differences and achieving good visual results are possible.
Gabriele Romanato
his blog
share
twitter
github
Web Developer
(
appliness
TUTORIALS MOBILE
PhoneGap Q&A by Christophe Coenraets
BOOKMARK / SHARE / TOC
TUTORIALS PHONEGAP Q&A
by Christophe Coenraets
“I’ve answered live questions about PhoneGap. Here is the summary.”
Thanks to all of you who attended my “Architecting a PhoneGap Application” TechLive session, and thanks also for the great feedback. The recording is available here. A lot of my content was based on my PhoneGap Tutorial available here. Here are some questions I wanted to answer about PhoneGap:
“I built an app using PhoneGap, jQuery, and LESS. There is a delay before the app responds to a button click.”
After you tap a button, mobile browsers wait for about 300ms before they fire the click event. This is to make sure you are actually not performing a double tap. One simple solution is to use the touchend event instead of click. But there are two issues with that approach: - You have to change your code (replacing click with touchend), and touchend will not work when testing your app in the browser on your development machine. - Adding logic to the touchend event could interfere with other touch interactions (like scrolling). These two problems can be overcome by adding contextual logic to your event handlers. But before you reinvent the wheel, take a look at existing libraries that already address this problem. Fastclick.js is a good place to start. This Google Developers document is also a great resource to better understand the problem and the solution.
“Will phonegap support upcoming mobile OSs Tizen & Mozilla mobile?” 2 of 8
TUTORIALS PHONEGAP Q&A
Yes. Click the links below for more info: Tizen Firefox OS
“How does one solve the problem of getting client approval for iOS devices without the issues of gathering their UDID for provisioning profiles?”
That’s the Apple process and there is really nothing we can do here. PhoneGap Build can make it easier to distribute your app to beta testers during development, but you still need to get the UDID of their devices.
“What kind of tips would you recommend for creating a responsive layout? I already know about media queries and I used a fittext.js for scaling the text within a div .”
Take a look at Adobe Edge Reflow, a new Responsive Web Design tool (currently in preview).
“How do you stop the tap-and-hold on a link which makes a flyout menu to open to browser/copy in iOS.”
3 of 8
TUTORIALS PHONEGAP Q&A
Try: -webkit-touch-callout:none;
“Now that I have a PhoneGap app build for iOS, how can I send it to my client for testing? In Android, I just have to send him the APK file, how about in iOS ?”
You need to sign up for the Apple Developer Program. Then you have to create an Apple developer certificate, and an application provisioning profile that includes the UDID of your client devices.
“How can I get a link to the recording of this session when it’s over?”
It’s available here.
“I was told that the Facebook iPhone app was built using PhoneGap … can anyone confirm that?”
The current Facebook app on iOS is native.
4 of 8
TUTORIALS PHONEGAP Q&A
“What is a good library for page transitions and page handling in general if not jQuery Mobile?”
Page transitions are really easy to implement with a few lines of CSS. Take a look at Part 13 in the PhoneGap Tutorial. For architectural frameworks, take a look at Backbone.js, Angular.js, Ember.js, and others.
“Which is preferable, draw buttons with gradients or just load a PNG file?”
This may vary depending on the platform. There doesn’t seem to be much of a difference on iOS, but Android (particularly older devices) sometimes struggles with rendering gradients.
“How does the App Store review process work? For native iOS apps there is a code review of any changes.”
PhoneGap apps are native apps. They have a native shell that happens to render a lot of its content using HTML/JS/CSS. The review process is the same as for other iOS apps. The guidelines are available here. Apps are evaluated based on a range of criteria, including user interface design, functionality, content, and the use of specific technologies. As far as I know and based on my own experience submitting apps, a code review is not part of the process. Also based on my experience, the “use of specific technologies” means that if your app doesn’t make use of any device feature (like GPS, accelerometer, camera, contacts, local storage, device events, etc), Apple may consider that it would be better suited as a traditional web app delivered in 5 of 8
TUTORIALS PHONEGAP Q&A
the browser. PhoneGap obviously gives you access to all the device features, so you have all you need to build an app that complies with the guidelines.
“Christophe, can you please create or point us to a good tutorial, that uses the facebook plugin and do some typical things like connecting with facebook, posting something to the timeline? etc”
That’s my next blog post :) Click here
“What is the proper sequence for loading .js files when using cordova.js and jquery/jquery-mobile?”
Here is what I’m typically doing:
“Do I have to create different folders & config.xml for different devices with www/ or can I use the same code for all devices?” 6 of 8
TUTORIALS PHONEGAP Q&A
The easiest way to build is to use PhoneGap Build. In that case, you have a single directory structure with a single config.xml, and you don’t even have to download the PhoneGap SDK: The right cordova.js for each platform will be injected by PhoneGap build. If you don’t want to build in the cloud using PhoneGap Build, I recommend you take a look a the Command Line Tools Interface to create your project structure.
“Can I use PhoneGap build if using Cordova?”
Yes, since the PhoneGap and Cordova libraries are the same. Just add: … to your index.html page, and the right version of Cordova for each platform will be injected by PhoneGap build.
“If I have cordova.js before I send it into PhoneGap will it replace it in PhoneGap or am I running two .js files on PhoneGap build?”
In the app you submit to PhoneGap build, you should just have this:
7 of 8
TUTORIALS PHONEGAP Q&A
… and phonegap.js should actually not be present in the root folder. PhoneGap build will inject the right cordova.js for each platform. Let me know if you have other questions.
Christophe Coenraets
his blog
share
twitter
github
Adobe Evangelist
(
appliness
NEWS BY BRIAN RINALDI
BOOKMARK / SHARE / TOC
Easy High DPI Images by Boris Smus
Building Windows Store Applications With jQuery 2.0 by Jonathan Sampson
Slide In (as you scroll down) Boxes by Chris Coyier
CSS3 transitions and z-index by Zoe Gillenwater
Make a 3D iPhone with CSS by Donovan Hutchinson
“shapeoutside” is in CSS exclusions by Bem Jones-Bey
Brackets Quick Open: That’s No Regex! by Kevin Dangoor Deploying JavaScript Applications by Alex Sexton Getting started with AngularJS by Kris Schultz
(
Google Analytics and PhoneGap by Raymond Camden
appliness
MORE NEWS ON HTTP://REMOTESYNTHESIS.COM/
(
appliness
EOF FOLLOW US
BOOKMARK / SHARE / TOC
Now what? N
subscribe to our monthly newsletter
follow us on twitter
join us on facebook
visit appliness.com
View more...
Comments