The modern way of emphasizing cleanliness, sharpness and objectivity in your designs is by trying to avoid all lavish stylistic choices such as textures, fake feeling of 3d dimension, illusory decorations, shiny/glossy effects and giving the flat style a shot. Being here not just since yesterday, it certainly becomes obvious that this trend not only has put down its roots but also has matured dramatically in a short period of time. The concept implies getting the most out of minimalism, harmoniously marrying Swiss style with a bright coloring and some interesting solutions (such as a long 5 o’clock shadow). It sticks to simple shapes, solid color backdrops, neat sharp typography, generous portions of whitespace, intuitive glyphs, gorgeous bright coloring in order to provide designs with an absolutely clean, crisp, brilliantly simple, properly-balanced and highly enticing look. Not only the large-scale artworks are able to gain considerable advantages from it, but basic GUI elements such as buttons, icons, and controls can benefit as well.
Successful developers all have something in common: the desire to create. To fully realize that creativity, they need to continually improve their skills. The web industry has grown from this desire to learn. You only need to look at the unwavering demand for conferences, workshops and training days for evidence of this.
For many companies, however, these sources of training require time and money that simply might not be available — especially when you consider that technologies evolve all the time. The cost of continually sending your team to workshops and training days can quickly become unsustainable.
People in the web industry in particular believe in sharing what they’ve learned and helping others to improve their skills. This is the perfect premise on which to develop an internal training program. Within your team lies a wealth of skills, knowledge and experience that can be shared and developed further. With a little effort and using resources freely available on the web, you can increase the technical competence of the team organically, with much lighter demands on time and cost.
Why Bother?
Good developers will teach themselves anyway, right? Well, yes. But significant benefits are to be gained from formalizing and actively championing training within the company.
Developers who excel in a particular technology can teach it to others, gaining morale-boosting recognition and a reputation for being the go-to person for that skill. Junior members of the team will learn what the team is capable of and who they should query with specific questions. This is much more valuable than you might realize — knowing exactly where to go when a problem arises can quickly prevent bottlenecks in a project and make the team much more responsive.
As developers spend structured time together, they will learn the strengths and weaknesses of the team and form a more cohesive unit. They will be more able and willing to innovate and push boundaries if they know the full capabilities of their colleagues.
Most importantly, regular well-executed training will make developers better at their job and probably much happier. They will understand more, be challenged more and be significantly more productive.
Developers will always be more committed when value is put on their current skills and when their potential is invested in. In an industry that has so many attractive and flexible places to work, training can be a significant perk that helps to retain and attract talent.
Let’s Get Started Already!
The first challenge you will likely face in implementing regular training sessions is getting the company to buy into what you are trying to achieve. Explain the aforementioned benefits to aid your cause. However, you might have to get creative if your work environment is less flexible. For example, consider reducing the investment of time by proposing a “brown bag” approach. Get team members to bring their own food and make the training session an informal lunch meeting.
Management is much more likely to offer its full support if it can see evidence of the benefits. Clearly explain that not only are you looking for their approval, but you want to keep them in the loop as the training progresses. Showing a comprehensive plan and clear metrics for how the team will improve will go a long way to convincing management that the investment of time will benefit the company.
The Training Plan
To formulate the plan, look through the most recent projects that your team has worked on. Analyze the skill sets that were used. Talk to project managers about any issues that may have arisen. Keep an eye on developments in the wider industry and how they might bear on future projects.
Most importantly, look at the developers’ personal development plans and see how training could facilitate their goals. This will also help you to identify senior members of the team and those with specific expertise who would benefit from leading the training sessions themselves. Senior members in particular will have a wealth of development and commercial experience.
Of course, make sure that the senior members of the team are on board and would be comfortable leading training sessions. Give them enough time to prepare, and provide guidance on what is expected, while still allowing them sufficient freedom to make the session their own.
Keep the training plan simple. List the specific sessions you wish to include, briefly describe them, and assign them to developers who have the skills to lead them.
Order the training sessions by importance, but don’t feel you have to attach dates. Depending on the size of the team, you might find that key members will be absent for some of them and that you will need to reschedule.
At the end of each session, date it and mark it as completed in the training plan. Write any relevant notes next to the entry, such as problems, areas not covered and new avenues to explore in future sessions. Make the document a collaborative spreadsheet to make it easier to share internally.
Measuring Skill Level
Exactly measuring a developer’s skill level is difficult, but a generalized indication will help.
One way is to use a skills matrix, listing each team member down the left column, languages and skills along the top, and a scale of 0 to 10 as measurements:
0
no experience
1–3
understands the basics
4–7
competent with practical experience
8–10
expert
Adapt the scale to your needs. You could make it more general, with terms such as beginner, intermediate and expert. Or make it more complex, depending on the skills required by your team. Review it when training sessions are completed and after significant projects.
A matrix that is up to date makes for a useful tool to allocate resources, schedule work and inform the wider company of the development team’s capabilities.
Stick To Your Principles
Before planning the content of the training sessions, consider some underlying principles.
Timing
Due to the nature of development, finding a regular time when all members of the development team can step away from their work is tricky. Avoid standard release dates and the preceding and succeeding days.
Aim for once a week. Greater frequency could threaten deadlines and meet with resistance from management. Keep the sessions consistent; too much rescheduling or skipping of sessions will devalue the importance of the training in the eyes of the developers.
Friday is often a good time, especially in the afternoon. Most of the company will be winding down at this time, and disruption will probably be minimal. If homework is assigned, this also gives developers the opportunity to dabble with it on the weekend.
Plan the sessions in advance. Keep them short and sweet, no longer than an hour to keep everyone engaged.
Environment
A meeting room with a large screen and wireless Internet would be ideal. Ensure that there is enough comfortable seating so that everyone can participate easily.
Such rooms are usually designed for client presentations, which can make them difficult to book. Again, scheduling the training sessions for a slow period of the week and booking in advance should help with that. Send out calendar invitations so that the team blocks out that time, too.
Let any potentially disruptive colleagues know that training sessions should not be interrupted. Once everyone has arrived, close the door. Shut out everything (and everyone) that could be a distraction.
Don’t forget about off-site members of the team. Being included will give them the benefit of the training and also remind them that they are considered part of the team. Use Skype or Google Hangouts to include them. Ensure that their supervisor knows about the training session so that they can allocate the time and, ideally, a quiet, comfortable environment.
Discipline
To protect the time, both the company and the team need to agree that attendance at training sessions is mandatory. Exceptions and rescheduling should happen only in extreme circumstances.
Phones and laptops are distractions and should be discouraged. Attention should be focused on the presenter and their material.
Goals
When planning the sessions, try to align the individual developers’ targets with the company’s goals for growth. Focus on technologies and techniques that will not only benefit the team, but increase the company’s expertise.
The skill-level matrix mentioned above can be distributed to other departments to help them understand the development team’s capabilities.
Homework
Without practical application, training will be quickly forgotten. To achieve real progress, assign a task for the participants to practice the skills they’ve learned in the session.
The assignment should be small enough to achieve in the downtime between projects or outside of normal working hours if necessary. More importantly, it should be interesting enough that a developer would want to do it, especially if it needs to be completed in their spare time.
Reviewing an assignment could be the focus of the subsequent session, in which you would explore different approaches and techniques, as well as identify and reward those who have excelled.
Homework is, of course, optional. Not everyone will want to do it, and, despite their best intentions, developers won’t always have the time to tackle it.
But if the training sessions are aligned with both the company’s goals and their personal development plans, you might be surprised by how willing the developers are to complete homework. They’ll be inspired by the chance to show off their skill, gain recognition from colleagues and maybe even win a prize.
Record
Not everyone will make it to every training session. Developers take vacations, and urgent bugs and tight deadlines will sometimes intrude. Recording sessions is a good way to give those who miss one a chance to catch up.
Also, share the slides and links from each session with attendees. The best way to do this is to set up a Github Pages website using Jekyll3, and get everyone to contribute. The website could also be used as an internal knowledge base.
Fun
Keep it fun! If the training sessions become a chore, then they probably won’t be successful. A friendly, open and honest environment will create the right culture for growth, fostering connections between team members, and improving communication and cohesiveness.
Let’s Break It Down
So, how do you go about structuring a training session? As mentioned, this is highly subjective and depends on both the facilitator and the team. However, if you’re struggling to know where to begin, let’s make a meal out of it!
The Appetizer
Everyone likes to have a taste of what is going on, so start with a quick business update, detailing the company’s latest wins and the progress of work underway. If you have any other news about the company, including potential opportunities within, consider sharing it, too.
An update on the wider industry could also be beneficial. If any key developments have happened, discuss these and share links to relevant articles. The beginning of the session is also a good opportunity to review homework and single out the best solution with recognition (and a trophy if you’re feeling generous!).
Don’t dwell on any of these things for long. This section shouldn’t last longer than 20 minutes.
The Main Course
The meat of the session should focus on the designated topic.
The most common type of session will probably be a tutorial on a particular language or technique. Don’t assume anything. Introduce the technology, explaining its purpose and situations when it is best used, not forgetting its limitations. Ask for opinions and experiences from any team members who have experience with the technology.
Showing examples is the easiest way to demonstrate a technology. Prepare these carefully, especially if you plan to follow a similar approach in your development projects. Keep them succinct. Either use multiple small examples, or break down a single big example into digestible modules. Avoid live coding unless it is simple and prepared in advance.
Deposit all of the coding examples in your knowledge base or Github repository so that the team can examine them after the session.
With more complex, substantial areas, consider splitting the training into multiple sessions. Start with the basics, and increase the learning curve each week. Don’t rely on tutorials alone — mix things up. Plenty of different formats will give developers valuable knowledge and insight.
Deconstruct a project completed by the team. Identify successful approaches, and analyze any issues that arose. Review the techniques used, and get feedback from developers who worked on the project. This will help to account for contingencies if any changes need to be made and will demonstrate good ways to tackle future projects.
If your company is more creative and pioneering, consider devoting sessions to new hardware that has been acquired. Play around with it and inspire your developers.
Collaboration within the team and with other departments could also be incorporated into training sessions. Consider two speakers from different areas presenting the same technology — programmers and designers will often have very different views. Or venture even further and invite a project manager to lead a session, which could improve processes, communication and understanding between departments.
The Dessert
Finally, finish the session by mulling over what you’ve covered. Invite questions and encourage discussion.
Before everyone leaves, assign the homework. Choose it ahead of time, and clearly explain it. The assignment should relate to the material covered in the session — and perhaps extend it.
Continual Improvement
Continually review the effectiveness of the training sessions. Once they have become a regular fixture, solicit feedback.
Keep the training collaborative. Invite the development team to tell you what works for them and what doesn’t, and be prepared to alter the training plan. Also, look to the wider company to see what impact the training is having and whether particular areas might need more focus.
Every team and every company continually evolves. Training will help to keep both aligned and at the forefront of the industry, enabling them to shine.
Just before the Summer vacation we ran a row of giveaways. We had very interesting prizes to be won. In the meantime, all the winners should have received their notifications. Here’s what we gave away and whom we gave it to. Make sure to check out these sponsors. Their offerings are great, even if you have to pay for them. Their products are worth each and every cent…
There’s a false belief in the web development community that CSS animation is the only performant way to animate on the web. This myth has coerced many developers to abandon JavaScript-based animation altogether, thereby (1) forcing themselves to manage complex UI interaction within style sheets, (2) locking themselves out of supporting Internet Explorer 8 and 9, and (3) forgoing the beautiful motion design physics that are possible only with JavaScript.
Reality check: JavaScript-based animation is often as fast as CSS-based animation — sometimes even faster. CSS animation only appears to have a leg up because it’s typically compared to jQuery’s $.animate(), which is, in fact, very slow. However, JavaScript animation libraries that bypass jQuery deliver incredible performance by avoiding DOM manipulation as much as possible. These libraries can be up to 20 times faster than jQuery.
So, let’s smash some myths, dive into some real-world animation examples and improve our design skills in the process. If you love designing practical UI animations for your projects, this article is for you.
Why JavaScript?
CSS animations are convenient when you need to sprinkle property transitions into your style sheets. Plus, they deliver fantastic performance out of the box — without your having to add libraries to the page. However, when you use CSS transitions to power rich motion design (the kind you see in the latest versions of iOS and Android), they become too difficult to manage or their features simply fall short.
Ultimately, CSS animations limit you to what the specification provides. In JavaScript, by the very nature of any programming language, you have an infinite amount of logical control. JavaScript animation engines leverage this fact to provide novel features that let you pull off some very useful tricks:
The two most popular JavaScript animation libraries are Velocity.js9 and GSAP10. They both work with and without11 jQuery. When these libraries are used alongside jQuery, there is no performance degradation because they completely bypass jQuery’s animation stack.
If jQuery is present on your page, you can use Velocity and GSAP just like you would jQuery’s $.animate(). For example, $element.animate({ opacity: 0.5 }); simply becomes $element.velocity({ opacity: 0.5 }).
These two libraries also work when jQuery is not present on the page. This means that instead of chaining an animation call onto a jQuery element object — as just shown — you would pass the target element(s) to the animation call:
As shown, Velocity retains the same syntax as jQuery’s $.animate(), even when it’s used without jQuery; just shift all arguments rightward by one position to make room for passing in the targeted elements in the first position.
GSAP, in contrast, uses an object-oriented API design, as well as convenient static methods. So, you can get full control over animations.
In both cases, you’re no longer animating a jQuery element object, but rather a raw DOM node. As a reminder, you access raw DOM nodes by using document.getElementByID, document.getElementsByTagName, document.getElementsByClassName or document.querySelectorAll (which works similarly to jQuery’s selector engine). We’ll briefly work with these functions in the next section.
Working Without jQuery
(Note: If you need a basic primer on working with jQuery’s $.animate(), refer to the first few panes in Velocity’s documentation.12)
Let’s explore querySelectorAll further because it will likely be your weapon of choice when selecting elements without jQuery:
document.querySelectorAll("body"); // Get the body element
document.querySelectorAll(".squares"); // Get all elements with the "square" class
document.querySelectorAll("div"); // Get all divs
document.querySelectorAll("#main"); // Get the element with an id of "main"
document.querySelectorAll("#main div"); // Get the divs contained by "main"
As shown, you simply pass querySelectorAll a CSS selector (the same selectors you would use in your style sheets), and it will return all matched elements in an array. Hence, you can do this:
/* Get all div elements. */
var divs = document.querySelectorAll("div");
/* Animate all divs at once. */
Velocity(divs, { opacity: 0.5 }, 1000); // Velocity
TweenMax.to(divs, 1, { opacity: 0.5 }); // GSAP
Because we’re no longer attaching animations to jQuery element objects, you may be wondering how we can chain animations back to back, like this:
Animating this way has no performance drawback (as long as you cache the element being animated to a variable, instead of repeatedly doing querySelectorAll lookups for the same element).
(Tip: With Velocity’s UI pack, you can create your own multi-call animations and give them custom names that you can later reference as Velocity’s first argument. See Velocity’s UI Pack documentation13 for more information.)
This one-Velocity-call-at-a-time process has a huge benefit: If you’re using promises14 with your Velocity animations, then each Velocity call will return an actionable promise object. You can learn more about working with promises in Jake Archibald’s article15. They’re incredibly powerful.
In the case of GSAP, its expressive object-oriented API allows you to place your animations in a timeline, giving you control over scheduling and synchronization. You’re not limited to one-after-the-other chained animations; you can nest timelines, make animations overlap, etc:
var tl = new TimelineMax();
/* GSAP tweens chain by default, but you can specify exact insertion points in the timeline, including relative offsets. */
tl
.to(element, 1, { opacity: 0.5 })
.to(element, 1, { opacity: 1 });
JavaScript Awesomeness: Workflow
Animation is inherently an experimental process in which you need to play with timing and easings to get exactly the feel that your app needs. Of course, even once you think a design is perfect, a client will often request non-trivial changes. In these situations, a manageable workflow becomes critical.
While CSS transitions are impressively easy to sprinkle into a project for effects such as hovers, they become unmanageable when you attempt to sequence even moderately complex animations. That’s why CSS provides keyframe animations, which allow you to group animation logic into sections.
However, a core deficiency of the keyframes API is that you must define sections in percentages, which is unintuitive. For example:
What happens if the client asks you to make the translateX animation 1 second longer? Yikes. That requires redoing the math and changing all (or most) of the percentages.
Velocity has its UI pack16 to deal with multi-animation complexity, and GSAP offers nestable timelines17. These features allow for entirely new workflow possibilities.
But let’s stop preaching about workflow and actually dive into fun animation examples.
JavaScript Awesomeness: Physics
Many powerful effects are achievable exclusively via JavaScript. Let’s examine a few, starting with physics-based animation.
The utility of physics in motion design hits upon the core principle of what makes for a great UX: interfaces that flow naturally from the user’s input — in other words, interfaces that adhere to how motion works in the real world.
GSAP offers physics plugins that adapt to the constraints of your UI. For example, the ThrowPropsPlugin tracks the dynamic velocity of a user’s finger or mouse, and when the user releases, ThrowPropsPlugin matches that corresponding velocity to naturally glide the element to a stop. The resulting animation is a standard tween that can be time-manipulated (paused, reversed, etc.):
Velocity offers an easing type based on spring physics. Typically with easing options, you pass in a named easing type; for example, ease, ease-in-out or easeInOutSine. With spring physics, you pass a two-item array consisting of tension and friction values (in brackets below):
A higher tension (a default of 500) increases the total speed and bounciness. A lower friction (a default of 20) increases ending vibration speed. By tweaking these values, you can separately fine-tune your animations to have different personalities. Try it out:
In Velocity, you can enable the user to scroll the browser to the edge of any element by passing in scroll as Velocity’s first argument (instead of a properties map). The scroll command behaves identically to a standard Velocity call; it can take options and can be queued.
In GSAP, you can retain a reference to the animation object, then invoke its reverse() method at any time:
var tween = TweenMax.to(element, 1, {opacity:0.5});
tween.reverse();
JavaScript Awesomeness: Transform Control
With CSS animation, all transform components — scale, translation, rotation and skew — are contained in a single CSS property and, consequently, cannot be animated independently using different durations, easings and start times.
For rich motion design, however, independent control is imperative. Let’s look at the dynamic transform control that’s achievable only in JavaScript. Click the buttons at any point during the animation:
Both Velocity and GSAP allow you to individually animate transform components:
// Velocity
/* First animation */
Velocity(element, { translateX: 500 }, 1000);
/* Trigger a second (concurrent) animation after 500 ms */
Velocity(element, { rotateZ: 45 }, { delay: 500, duration: 2000, queue: false });
// GSAP
/* First animation */
TweenMax.to(element, 1, { x: 500 });
/* Trigger a second (concurrent) animation after 500 ms */
TweenMax.to(element, 2, { rotation: 45, delay: 0.5 });
Wrapping Up
Compared to CSS animation, JavaScript animation has better browser support and typically more features, and it provides a more manageable workflow for animation sequences.
Animating in JavaScript doesn’t entail sacrificing speed (or hardware acceleration). Both Velocity and GSAP deliver blistering speed and hardware acceleration under the hood. No more messing around with null-transform hacks.
You don’t need to use jQuery to take advantage of dedicated JavaScript animation libraries. However, if you do, you will not lose out on performance.
Today we have a stack of 40 fonts for you. And although these fonts all look like they will be created sometime in the future, they are actually available in the world of today. Most of the fonts are equipped with special characters from several languages. More than half of all the fonts are suitable for commercial use right away. Concerning the other half, as always we advise you to get into contact with the creator of the font to clarify conditions. This is true for today and will still be true in the future. Now enjoy our collection of 40 free futuristic fonts of today.
In the early days of mobile, debugging was quite a challenge. Sure, you could get ahold of a device and perform a quick visual assessment, but what would you do after discovering a bug?
With a distinct lack of debugging tools, developers turned to a variety of hacks. In general, these hacks were an attempt to recreate a given issue in a desktop browser and then debug with Chrome Developer Tools or a similar desktop toolkit. For instance, a developer might shrink the size of the desktop browser’s window to test a responsive website or alter the user agent to spoof a particular mobile device.
To put it bluntly, these hacks don’t work. If you’re recreating issues on the desktop, then you can’t be certain that any of your fixes will work. This means you’ll be constantly bouncing back and forth between the mobile device and the hacks in your desktop browser.
Fast forward to today, when we have a robust suite of debugging tools that provide meaningful debugging information directly from a physical device. Best of all, you can use the same desktop debugging tools that you know and love, all on an actual mobile device.
In this article, we’ll explore a variety of emulators and simulators that you can use for quick and easy testing. Then, we’ll look at remote debugging tools, which enable you to connect a desktop computer to a mobile device and leverage a rich debugging interface.
Emulators And Simulators
Testing on real physical devices always pays off. But that doesn’t mean you shouldn’t also test on emulators and simulators. These virtual environments not only expand your testing coverage to more devices, but also are a quick and easy way to test small changes on the fly.
iOS Simulator
To test iOS devices, such as the iPhone and iPad, you have a number of options, most notably Apple’s official iOS Simulator. Included as part of Xcode, this simulator enables you to test across different software and hardware combinations, but only from a Mac.
First, install and open Xcode. Then, in Xcode, right-click and select “Show Package Contents.” Go to “Contents” ? “Applications” ? “iPhone Simulator.”
Although iOS Simulator is difficult to find, using it is fortunately easy. Simply open up Safari in the simulator and test your website. You can switch between different iPhone and iPad devices, change the iOS version, rotate the viewport and more.
Note: If you’re not working on a Mac, you’ll have to find another option. You could look to iPadian6, a Windows-based iPad simulator. Beyond that, a handful of other simulators exist, including certain web-based offerings7. But, to be honest, none of these are very promising.
Android Emulator
Android also provides an emulator. Luckily, this one is cross-platform. Unfortunately, setting it up is a bit of a pain.
First, download the bundle8 that includes Android Development Tools (ADT) for Eclipse and the Android software development kit (SDK). Next, follow Google’s instructions9 to install the SDK packages, making sure to install the default selections as well as the “Intel x86 Emulator Accelerator (HAXM installer)”. You’ll also need to track down HAXM — search your Mac for IntelHaxm.dmg or your PC for IntelHaxm.exe, and run the file to install it.
Next, create an Android virtual device (AVD) for whichever device you’re testing. If you go into the AVD manager, you’ll see a list of preset devices in “Device Definitions.” These cover a variety of Google products and some generic devices. To get started, select one of these presets and click “Create AVD.”
Set whatever you like for the CPU, and set “No skin“ and “Use host GPU.” Now you can run the virtual device and use Android’s browser to test your website.
Emulators and simulators are useful, but they’re not 100% accurate. Always test on as many real devices as possible.
That doesn’t mean you need to buy a hundred phones and tablets. You can take advantage of remote testing resources, which provide a web-based interface to interact with real physical devices. You’ll be able to interact with a phone remotely and view any changes in the screencast that is sent back to your machine.
If you want to test a Samsung device, such as the Galaxy S5, you can do so for free using Samsung’s Remote Test Lab21, which enables you to test on a wide selection of Samsung devices.
Additionally, you can use the resources in Keynote Mobile Testing22. They’re not cheap, but the number of devices offered is pretty astonishing, and you can test a handful of devices for free.
Note: If you’re looking to get your hands on real devices, Open Device Lab23 can point you to a lab in your area, where you can test on a range of devices for free.
Remote Debugging
Remote debugging addresses a variety of the challenges presented by mobile debugging. Namely, how do you get meaningful debugging information from a small and relatively underpowered device?
Remote debugging tools provide an interface to connect to a mobile device from a desktop computer. Doing this, you can debug for a mobile device using the development tools on a more powerful, easier-to-use desktop machine.
iOS
With the release of iOS 6.0, Apple introduced a tool that enables you to use desktop Safari’s Web Inspector to debug iOS devices.
To get started, enable remote debugging on your iOS device by going to “Settings” ? “Safari” ? “Advanced” and enabling “Web Inspector.”
Next, physically connect your phone or tablet to your machine using a USB cable. Then, open Safari (version 6.0 or higher), and in “Preferences” ? “Advanced,” select “Show Develop menu in menu bar.”
Now, in the “Develop” menu you should see your iOS device, along with any open pages in mobile Safari.
Select one of these pages, and you’ll have a wide range of developer tools at your fingertips. For example, try out the DOM Inspector, which enables you to tap DOM elements on your mobile device and see debugging information on the desktop.
The DOM Inspector is really just the beginning. iOS’ remote developer tools provide a ton of features, such as:
timelines to track network requests, layout and rendering tasks and JavaScript;
a debugger to set breakpoints and to profile the JavaScript;
Note: Much like iOS Simulator, you can only do remote debugging for iOS on Mac OS X.
Android
Similar to iOS, Android has a remote debugging solution. The tools in it enable you to debug an Android device from a desktop machine using Chrome’s Developer Tools. Best of all, Android’s remote debugging is cross-platform.
First, go to “Settings” ? “About Phone” on your Android 4.4+ phone (or “Settings” ? “About Tablet”). Next, tap the “Build Number” seven (7) times. (No, I’m not joking. You’ll see a message about being a developer at the end.) Now, go back to the main settings and into “Developer Options.” Here, enable “USB debugging,” and you’re all set.
Go into your desktop Chrome browser, and type about:inspect in the address bar. Enable “Discover USB devices,” and you’ll see your device in the menu.
You should also see any open tabs in your mobile browser. Select whichever tab you want to debug, and you’ll be able to leverage a ton of useful tools, such as:
a DOM Inspector,
a network panel for external resources,
a sources panel to watch JavaScript and to set breakpoints,
Note: You can also remotely debug with the Android emulator.
Weinre
You now know how to remotely debug a variety of devices. But if you want to debug iOS on Windows or on Linux or debug other devices, such as Windows Phone or BlackBerry, then try Weinre, which works on any device.
Setting up Weinre is a bit more complicated because you have to install it on both the server and the page. To get started, install Node, and then install the Weinre module with the following command:
npm install –g weinre
Next, run the debugging server using your development machine’s IP:
weinre --boundHost 10.0.0.1
Note: Make sure to insert your own IP in the command above. You can find your IP on a Mac using the command ipconfig getifaddr en0 and on Windows using ipconfig.
Next, go to the development server that is outputted by Weinre in the console (in my case, it’s localhost:8080). Here, look at the “Target Script” section, and grab the tag. You’ll need to include that on whichever pages you want to debug.
Finally, click on the link at the top of this page for the user interface for debugging clients (in my case, it’s http://localhost:8080/client/#anonymous). Now, once you open the page in your device, you should see it in the list of targets.
Note: If you’re having trouble connecting a device to your localhost, consider setting up a public tunnel with ngrok43.
At this point, you can leverage a lot of WebKit Developer Tools to debug the page. You can use handy tools such as the DOM Inspector:
Once you get past the initial installation, Weinre lets you debug any device on any network. However, it’s not as powerful as the native solutions for iOS and Android. For example, you can’t use the “Sources” panel to debug JavaScript or take advantage of the profiler.
Note: Ghostlab48 is another remote testing option that supports multiple platforms.
Conclusion
In this article, we’ve learned how to set up a robust testing suite using a combination of physical devices, emulators, simulators and remote testing tools. With these tools, you are now able to test a mobile website or app across a wide variety of devices and platforms.
We’ve also explored remote debugging tools, which provide useful information directly from a mobile device. Hopefully, you now realize the benefits of remote debugging for mobile. Without it, we’re really just taking stabs in the dark.
Facebook covers are the only design you can add to your Facebook page. If your profile or fan page is supposed to sport a professional look, you shouldn’t simply go scaling your website header or any random image you were able to find. Instead you should put proper effort into making your Facebook cover look as professional as your services are, well hopefully. Ain’t got enough time? Keep calm and read on. We’ve got something great for you…
They used to say content is king. But what really makes up content? Gone are the days when “content” meant purely text. Today, if you want to engage and enchant your customers, your content must have some visual cues. The human brain processes visual information much quicker than text. And with web 2.0 visuals like infographics, you can convey complex, boring data in a meaningful manner. Although infographics make things simpler, it can be time-consuming to create them. Here is a list of my top 10 tools to create your own beautiful infographics and more visual content (no Photoshop required!).
Making an application work offline can be a daunting task. In this article, Matthew Andrews, a lead developer behind FT Labs, shares a few insights he had learned along the way while building the FT application. Matthew will also be running a “Making It Work Offline” workshop1 at our upcoming Smashing Conference in Freiburg in mid-September 2014. — Ed.
We’re going to make a simple offline-first to-do application2 with HTML5 technology. Here is what the app will do:
store data offline and load without an Internet connection;
allow the user to add and delete items in the to-do list;
store all data locally, with no back end;
run on the first- and second-most recent versions of all major desktop and mobile browsers.
Veterans of the offline-first world might now be thinking, “But we could just use localStorage6, which has the benefits of a much simpler API, and we wouldn’t need to worry about the complexity of using both IndexedDB and WebSQL.” While that is technically true, localStorage has number of problems7, the most important of which is that the amount of storage space available with it is significantly less than IndexedDB and WebSQL.
Luckily, while we’ll need to use both, we’ll only need to think about IndexedDB. To support WebSQL, we’ll use an IndexedDB polyfill8. This will keep our code clean and easy to maintain, and once all browsers that we care about support IndexedDB natively, we can simply delete the polyfill.
Note: If you’re starting a new project and are deciding whether to use IndexedDB or WebSQL, I strongly advocate using IndexedDB and the polyfill. In my opinion, there is no reason to write any new code that integrates with WebSQL directly.
I’ll go through all of the steps using Google Chrome (and its developer tools), but there’s no reason why you couldn’t develop this application using any other modern browser.
1. Scaffolding The Application And Opening A Database
We will create the following files in a single directory:
Nothing surprising here: just a standard HTML web page, with an input field to add to-do items, and an empty unordered list that will be filled with those items.
Again, this should be quite familiar: just some simple styles to make the to-do list look tidy. You may choose not to have any styles at all or create your own.
/application.js
(function() {
// 'global' variable to store reference to the database
var db;
databaseOpen(function() {
alert("The database has been opened");
});
function databaseOpen(callback) {
// Open a database, specify the name and version
var version = 1;
var request = indexedDB.open('todos', version);
request.onsuccess = function(e) {
db = e.target.result;
callback();
};
request.onerror = databaseError;
}
function databaseError(e) {
console.error('An IndexedDB error has occurred', e);
}
}());
All this code does is create a database with indexedDB.open and then show the user an old-fashioned alert if it is successful. Every IndexedDB database needs a name (in this case, todos) and a version number (which I’ve set to 1).
To check that it’s working, open the application in the browser, open up “Developer Tools” and click on the “Resources” tab.
By clicking on the triangle next to “IndexedDB,” you should see that a database named todos has been created.
2. Creating The Object Store
Like many database formats that you might be familiar with, you can create many tables in a single IndexedDB database. These tables are called “objectStores.” In this step, we’ll create an object store named todo. To do this, we simply add an event listener on the database’s upgradeneeded event.
The data format that we will store to-do items in will be JavaScript objects, with two properties:
timeStamp
This timestamp will also act as our key.
text
This is the text that the user has entered.
For example:
{ timeStamp: 1407594483201, text: 'Wash the dishes' }
Now, /application.js looks like this (the new code starts at request.onupgradeneeded):
(function() {
// 'global' variable to store reference to the database
var db;
databaseOpen(function() {
alert("The database has been opened");
});
function databaseOpen(callback) {
// Open a database, specify the name and version
var version = 1;
var request = indexedDB.open('todos', version);
// Run migrations if necessary
request.onupgradeneeded = function(e) {
db = e.target.result;
e.target.transaction.onerror = databaseError;
db.createObjectStore('todo', { keyPath: 'timeStamp' });
};
request.onsuccess = function(e) {
db = e.target.result;
callback();
};
request.onerror = databaseError;
}
function databaseError(e) {
console.error('An IndexedDB error has occurred', e);
}
}());
This will create an object store keyed by timeStamp and named todo.
Or will it?
Having updated application.js, if you open the web app again, not a lot happens. The code in onupgradeneeded never runs; try adding a console.log in the onupgradeneeded callback to be sure. The problem is that we haven’t incremented the version number, so the browser doesn’t know that it needs to run the upgrade callback.
How to Solve This?
Whenever you add or remove object stores, you will need to increment the version number. Otherwise, the structure of the data will be different from what your code expects, and you risk breaking the application.
Because this application doesn’t have any real users yet, we can fix this another way: by deleting the database. Copy this line of code into the “Console,” and then refresh the page:
indexedDB.deleteDatabase('todos');
After refreshing, the “Resources” pane of “Developer Tools” should have changed and should now show the object store that we added:
3. Adding Items
The next step is to enable the user to add items.
/application.js
Note that I’ve omitted the database’s opening code, indicated by ellipses (…) below:
(function() {
// Some global variables (database, references to key UI elements)
var db, input;
databaseOpen(function() {
input = document.querySelector('input');
document.body.addEventListener('submit', onSubmit);
});
function onSubmit(e) {
e.preventDefault();
databaseTodosAdd(input.value, function() {
input.value = '';
});
}
[…]
function databaseTodosAdd(text, callback) {
var transaction = db.transaction(['todo'], 'readwrite');
var store = transaction.objectStore('todo');
var request = store.put({
text: text,
timeStamp: Date.now()
});
request.onsuccess = function(e) {
callback();
};
request.onerror = databaseError;
}
}());
We’ve added two bits of code here:
The event listener responds to every submit event, prevents that event’s default action (which would otherwise refresh the page), calls databaseTodosAdd with the value of the input element, and (if the item is successfully added) sets the value of the input element to be empty.
A function named databaseTodosAdd stores the to-do item in the local database, along with a timestamp, and then runs a callback.
To test that this works, open up the web app again. Type some words into the input element and press “Enter.” Repeat this a few times, and then open up “Developer Tools” to the “Resources” tab again. You should see the items that you typed now appear in the todo object store.
4. Retrieving Items
Now that we’ve stored some data, the next step is to work out how to retrieve it.
/application.js
Again, the ellipses indicate code that we have already implemented in steps 1, 2 and 3.
(function() {
// Some global variables (database, references to key UI elements)
var db, input;
databaseOpen(function() {
input = document.querySelector('input');
document.body.addEventListener('submit', onSubmit);
databaseTodosGet(function(todos) {
console.log(todos);
});
});
[…]
function databaseTodosGet(callback) {
var transaction = db.transaction(['todo'], 'readonly');
var store = transaction.objectStore('todo');
// Get everything in the store
var keyRange = IDBKeyRange.lowerBound(0);
var cursorRequest = store.openCursor(keyRange);
// This fires once per row in the store. So, for simplicity,
// collect the data in an array (data), and pass it in the
// callback in one go.
var data = [];
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
// If there's data, add it to array
if (result) {
data.push(result.value);
result.continue();
// Reach the end of the data
} else {
callback(data);
}
};
}
}());
After the database has been initialized, this will retrieve all of the to-do items and output them to the “Developer Tools” console.
Notice how the onsuccess callback is called after each item is retrieved from the object store. To keep things simple, we put each result into an array named data, and when we run out of results (which happens when we’ve retrieved all of the items), we call the callback with that array. This approach is simple, but other approaches might be more efficient.
If you reopen the application again, the “Developer Tools” console should look a bit like this:
5. Displaying Items
The next step after retrieving the items is to display them.
/application.js
(function() {
// Some global variables (database, references to key UI elements)
var db, input, ul;
databaseOpen(function() {
input = document.querySelector('input');
ul = document.querySelector('ul');
document.body.addEventListener('submit', onSubmit);
databaseTodosGet(renderAllTodos);
});
function renderAllTodos(todos) {
var html = '';
todos.forEach(function(todo) {
html += todoToHtml(todo);
});
ul.innerHTML = html;
}
function todoToHtml(todo) {
return '
'+todo.text+'
';
}
[…]
All we’ve added are a couple of very simple functions that render the to-do items:
todoToHtml
This takes a todos object (i.e. the simple JavaScript object that we defined earlier).
renderAllTodos
This takes an array of todos objects, converts them to an HTML string and sets the unordered list’s innerHTML to it.
Finally, we’re at a point where we can actually see what our application is doing without having to look in “Developer Tools”! Open up the app again, and you should see something like this:
But we’re not done yet. Because the application only displays items when it launches, if we add any new ones, they won’t appear unless we refresh the page.
6. Displaying New Items
We can fix this with a single line of code.
/application.js
The new code is just the line databaseTodosGet(renderAllTodos);.
[…]
function onSubmit(e) {
e.preventDefault();
databaseTodosAdd(input.value, function() {
// After new items have been added, re-render all items
databaseTodosGet(renderAllTodos);
input.value = '';
});
}
[…]
Although this is very simple, it’s not very efficient. Every time we add an item, the code will retrieve all items from the database again and render them on screen.
7. Deleting Items
To keep things as simple as possible, we will let users delete items by clicking on them. (For a real application, we would probably want a dedicated “Delete” button or show a dialog so that an item doesn’t get deleted accidentally, but this will be fine for our little prototype.)
To achieve this, we will be a little hacky and give each item an ID set to its timeStamp. This will enable the click event listener, which we will add to the document’s body, to detect when the user clicks on an item (as opposed to anywhere else on the page).
/application.js
(function() {
// Some global variables (database, references to key UI elements)
var db, input, ul;
databaseOpen(function() {
input = document.querySelector('input');
ul = document.querySelector('ul');
document.body.addEventListener('submit', onSubmit);
document.body.addEventListener('click', onClick);
databaseTodosGet(renderAllTodos);
});
function onClick(e) {
// We'll assume that any element with an ID
// attribute is a to-do item. Don't try this at home!
if (e.target.hasAttribute('id')) {
// Because the ID is stored in the DOM, it becomes
// a string. So, we need to make it an integer again.
databaseTodosDelete(parseInt(e.target.getAttribute('id'), 10), function() {
// Refresh the to-do list
databaseTodosGet(renderAllTodos);
});
}
}
[…]
function todoToHtml(todo) {
return '<li id="'+todo.timeStamp+'">'+todo.text+'</li>';
}
[…]
function databaseTodosDelete(id, callback) {
var transaction = db.transaction(['todo'], 'readwrite');
var store = transaction.objectStore('todo');
var request = store.delete(id);
request.onsuccess = function(e) {
callback();
};
request.onerror = databaseError;
}
}());
We’ve made the following enhancements:
We’ve added a new event handler (onClick) that listens to click events and checks whether the target element has an ID attribute. If it has one, then it converts that back into an integer with parseInt, calls databaseTodosDelete with that value and, if the item is successfully deleted, re-renders the to-do list following the same approach that we took in step 6.
We’ve enhanced the todoToHtml function so that every to-do item is outputted with an ID attribute, set to its timeStamp.
We’ve added a new function, databaseTodosDelete, which takes that timeStamp and a callback, deletes the item and then runs the callback.
Our to-do app is basically feature-complete. We can add and delete items, and it works in any browser that supports WebSQL or IndexedDB (although it could be a lot more efficient).
Almost There
Have we actually built an offline-first to-do app? Almost, but not quite. While we can now store all data offline, if you switch off your device’s Internet connection and try loading the application, it won’t open. To fix this, we need to use the HTML5 Application Cache14.
Warning
While HTML5 Application Cache works reasonably well for a simple single-page application like this, it doesn’t always. Thoroughly research how it works15 before considering whether to apply it to your website.
Service Worker16 might soon replace HTML5 Application Cache, although it is not currently usable in any browser, and neither Apple nor Microsoft have publicly committed to supporting it.
8. Truly Offline
To enable the application cache, we’ll add a manifest attribute to the html element of the web page.
Then, we’ll create a manifest file, which is a simple text file in which we crudely specify the files to make available offline and how we want the cache to behave.
The section that begins CACHE MANIFEST tells the browser the following:
When the application is first accessed, download each of those files and store them in the application cache.
Any time any of those files are needed from then on, load the cached versions of the files, rather than redownload them from the Internet.
The section that begins NETWORK tells the browser that all other files must be downloaded fresh from the Internet every time they are needed.
Success!
We’ve created a quick and simple to-do app17 that works offline and that runs in all major modern browsers, thanks to both IndexedDB and WebSQL (via a polyfill).
While prototyping interface designs, we are always striving for the spur that will force our imagination to run riot. Inspiration gives us a boost, but when it comes to an actual workflow, we are in need of something more pragmatic and effective such as sets of pre-defined components. Even if you are a great supporter of creating everything from scratch, sometimes you can be caught in a situation where you are running out of time and the more modular approach is like a lifebuoy to a drowning person. It allows killing two birds with one stone: invest your precious time in a project and still save some money.