Why Microsoft isn’t the smartphone leader it should be

Why Microsoft isn’t the smartphone leader it should be

Earlier this year, I read a piece at ArsTechnica about Microsoft’s annual shareholder meeting, where many in attendance expressed their belief to CEO Satya Nadella that Microsoft had effectively ceded control of the smartphone market to Apple and Google, and had ceased to be a serious competitor.

One Windows Phone-using shareholder, Dana Vance, expressed his dismay that Microsoft had released certain apps on iOS and Android before Windows 10 Mobile. Vance also brought up the claims that development of the Microsoft Band had been discontinued.

Another audience member was more blunt, and asked Nadella straight up whether Microsoft was committed to Windows Mobile.

A slow and steady decline

So, here’s the thing. Eons ago, Microsoft was one of the market leaders when it came to mobile productivity. This was before Steve Jobs had even conceived the iPhone. Back then, the smartphone race was bitterly-fought between four main players: Palm, BlackBerry, Symbian, and Microsoft. Windows Mobile 6 – Microsoft’s offering – had a respectable market share of around 30 percent.

Windows Mobile did well with overworked office managers and financiers who wanted a convenient way to access their emails and tap out office documents, but its popular appeal was limited. The vast majority of handsets were just too drab and clunky for most ordinary consumers to even consider buying them.

But in 2007, everything went to shit for Microsoft. Apple released the iPhone, and in turn transformed the smartphone market into something that hadn’t been seen before.

iphone, apple, lock screen hack
Credit: ymgerman/Shutterstock

The iPhone was a phone that allowed people to get shit done while actually looking the part. It was the first truly aspirational smartphone. Everyone from teens to executives wanted their hands on one. And then shortly after Google unveiled Android which allowed companies like Samsung and HTC to offer iPhone-like functionality but at a fraction of the cost.

At that point, the final nail in the Windows Phone 6’s coffin had been all but hammered. It started to hemorrhage users. Microsoft tried to stem the flow with Windows Mobile 6.5, which worked slightly better on touch-only handsets and had a better browser, but it just wasn’t enough.

By the time the company released its first real modern smartphone OS – Windows Phone 7 – Microsoft’s overall share had shrunk to a fraction of what it was in 2005. This was a profoundly humbling moment for a company that had dominated the world of computing since the early 1990’s.

Despite the subsequent launches of Windows Phone 8, Windows Phone 8.1, and Windows Mobile 10, Microsoft has never recovered in the mobile space.

It shouldn’t have to be this way

The most tragic thing about Microsoft’s unstoppable decline in the mobile is that it feels completely unnecessary.

There’s literally no reason why Microsoft – a company with vast financial resources and some of the world’s most talented developers and researchers on its payroll – should struggle like this.

Perhaps the biggest reason why Windows Phone (and later Windows Mobile) suffocated was that there was a vacuum of consumer enthusiasm. Nobody really cared about it. What frustrates me the most is that there were things that Microsoft could have done (and indeed, can do) to turn this around.

The struggling app store

Let’s address the ten-ton elephant in the room: the app store. Right now, the biggest reason why you shouldn’t buy a Windows Phone is that there’s a veritable drought of apps. Worse, of the scattering of apps that do exist, many of them haven’t received an update in a really long time.

Straight out of the gate, Microsoft should have taken a leaf out of RIM’s book and offered some serious financial incentives to developers.

Yes, I know that in 2013 it briefly offered to pay developers a whopping $100 for each newly-published app. Yes, I know that there were some private (and hefty) financial incentives given to larger companies, like Foursquare.

Clearly, these weren’t sufficient, and they weren’t sustained to ensure that these apps had feature-parity with their Android and iOS equivalents.

Taking control of hardware

The erstwhile CEO of Microsoft, Steven Ballmer, has some pretty strong thoughts on this subject. He (rightly) thinks that Microsoft should have gotten into the hardware game way sooner. Doing so would have allowed Microsoft to release phones where it can exercise control over every aspect of the device, much like Apple is with the iPhone.

This makes a lot of sense. During the brief halcyon days of Windows Phone, there were a smattering of devices running the software from a variety of manufacturers including Nokia, Blu, HTC, Alcatel, and ZTE.

Many of these were, at face value, pretty identical. In terms of industrial design and internal specifications, there wasn’t much to choose from. Moreover, it’s hard to differentiate between a Windows Phone device and an Android device because Microsoft only allows a certain amount of software customization.

From a consumer perspective, this was pretty confusing. I imagine that many people took a look at the then dizzying Windows Phone device ecosystem and promptly gave up, instead choosing to spend their money on an Android or iPhone.

Credit: Shutterstock

In retrospect, buying Nokia was a great idea. The Finnish mobile icon made great phones. Their industrial design was top-notch, and they were perhaps the most visible and committed manufacturer of Windows devices.

The biggest mistake Microsoft made was its inertia to retire the Nokia brand and take control of the Windows Phone ecosystem.

When it bought the company in 2014, it should have immediately stopped licensing its software and instead have committed to releasing three phones per year: a low-end, a mid-tier, and a premium flagship device.

This would have allowed Microsoft to take a holistic look at how people use its devices, and allow it to take the same detail-oriented approach to user experience that Apple takes with the iPhone.

Microsoft can make amazing hardware. This fact has been proven time-and-again with the likes of the Xbox One, Surface, Surface Book, and Surface Studio. Imagine what it would be like if the only Windows Phones on the market were a range of enticing, well-built Surface Phones?

Microsoft should have put on its dreaming cap

Over the past five years, Microsoft has evolved from a company obsessed with making incremental improvements to its software, to one that’s fundamentally adventurous and is obsessed with the new and undiscovered. Hololens anyone?

But this hasn’t really materialized on the mobile front.

I’ve got a theory about this. Since 2007, when Apple launched the iPhone, Microsoft has been playing catchup. It’s been so obsessed with ensuring that things work and that the essential features are present, it hasn’t been able to bring its vision for things like augmented reality to its mobile product.

From early on, Microsoft should have explored how it can differentiate its mobile offering from Apple and Google. It should have been bold. It wasn’t, and today Windows Phone languishes as an also-ran smartphone OS.

The last hurrah?

There were other things I wanted to mention. I wanted to bring up the confusing, inconsistent branding (note how many times I switch between Windows Phone and Windows Mobile in this article). I desperately wanted to rant about how I thought the platform was badly marketed. But time is short, and there just weren’t the column inches.

Some of you will read my article and furiously type out a comment about how I’m “an bias”  and an Apple fanboy. You’d be wrong. Not that it matters, but this Monday I bought a Dell XPS 13, and over my lifetime I’ve owned four different Windows phones. As a platform, I’ve given it plenty of chances. Perhaps more than it deserves.

But time is running out for Microsoft’s mobile ambitions. Microsoft is rumored to be working on a Surface Phone. Satya Nadella says that this will be the “ultimate mobile device”. Will this be the company’s last hurrah before it eventually consigns itself to building apps and services for the other two big incumbents?

Maybe. But I hope not.

I’m a perennial optimist, and as a result haven’t written Windows 10 Mobile off quite just yet. I feel that if Microsoft somehow manages to convince developers to return to the platform, and if it can build a device that can compete with the current range of desirable flagships, then maybe – just maybe – it’ll have a chance.

Maybe. But I doubt it.


LinkedIn app for Windows 10 Mobile gets a stealth “upgrade”

Earlier this month we reported on the disappearance of the LinkedIn app for Windows 10 Mobile from the Windows Store.

Microsoft never made an official announcement regarding the disappearance of the app, but we assumed Microsoft intended Windows Phone users to use the Edge browser to access their own enterprise social network.

It seems this was not far off the mark, even when the app has recently been updated.

We have received a number of messages today, and there have also been other posts on various web forums, that the app, which can still not be found in the Windows Store, has been updated.

The new app has a whole new look, and closer scrutiny reveals the old app has been replaced with a link to the LinkedIn Mobile website, still prominently displaying a banner linking to the Google Play Store urging users on more vibrant platforms to download “a faster” mobile app.

Beggars can of course not be choosers, and we assume after paying $26.2 billion for LinkedIn Microsoft did not have any spare change left to develop a proper UWP app.

The LinkedIn app for Windows 10 Mobile can not be found (but may make a reappearance) at the link below.


Have you had bad experiences with Microsoft’s Windows 10 Mobile tech support?

Image result for Have you had bad experiences with Microsoft's Windows 10 Mobile tech support?



Companies today find it difficult to score the right balance when it comes to customer support. Microsoft is no exception, and we want to hear about your experiences with the company related to mobile product support, good or bad. Community member 73blazer experienced an issue with Windows 10 Mobile and the official Mail app from Microsoft. After updating it to the latest version, it ceased to work in Continuum mode.

As expected, 73blazer decided to hit up Microsoft for some assistance. What wasn’t expected was the bad experience. First off, Microsoft Office support was involved, and they were unable to offer assistance and eventually redirected our poor member over to B2x, an outsourced support platform Microsoft uses for hardware and other support. After providing the IMEI number of an HP Elite X3, 73blazer was informed that only Lumia phones are covered for support through this particular channel.

Do they even have it? I tried desperately Friday to get some insight into an issue that is clearly a bug, to no avail. Basically, the issue is the new version of the mail app that came out earlier this week, won’t launch in continuum mode. Elite x3 had it. I pull out my 950xl which hadn’t updated in a while mail launches there in continuum mode, update the mail app, mail won’t launch in…


After supplying the same information for a Lumia 950, both soft and hard resets were recommended (clearly we’re looking at someone reading from a list of instructions to hand to consumers). It got worse from there, and so our forum member contacted HP support. They were more helpful and offered to take the problem up with Microsoft directly, supplying 73blazer with a case number to reference.How have your past experiences gone down when you got in touch with Microsoft for support? Do you have any tips when it comes to Windows 10 Mobile and specifically Lumia devices? Hit the link below and sound off in our community forum.


Oracle re-spins legacy software into cloud growth game

oracle.pngThe demise of legacy enterprise software vendors may be a bit overblown and Oracle appears to be showing a blueprint and a ground game that leverages its customer base into an as-a-service recurring revenue stream.

Oracle’s fourth quarter was strong on many fronts, but can be summed up in two words: Legacy lives. And if you couple Oracle’s results with strong performances from Red Hat and VMware you’ll find that the giants are adapting.
Brad Reback, an analyst at Stifel, put it best in a research note following Oracle’s fourth quarter:

Oracle’s strong print combined with recent solid results from Red Hat and VMware suggest that legacy software vendors continue to improve execution despite the changing IT landscape. It further goes to show how sticky enterprise software is and that legacy players can adjust as they leverage their privileged position within their massive installed base footprint.

You could also add SAP into that mix.

Perhaps these enterprise giants are melding license and cloud models into something hybrid.

The upshot: Enterprise software giants don’t necessarily have to win new cloud customers as much as convert the ones they have into an as-a-service model. Meanwhile, the power of Oracle’s bundle–database, HRM, CRM, ERP, infrastructure–means that customers can cut deals. Oracle has about 13,550 customers in its active software-as-a-service base.

And now let’s toss in Oracle’s cloud at customer play. Oracle noted that AT&T is moving its on-premise database to the cloud. The revenue didn’t show up in Oracle’s fourth quarter, but the deal was strategic. Oracle’s plan is to bridge hybrid and public cloud by running its services in a customer’s data center.

CTO Larry Ellison and CEO Mark Hurd outlined the deal. Ellison noted that there are similar deals to AT&T in the pipeline. “During this new fiscal year, we expect both our PaaS and IaaS businesses to accelerate into hyper-growth, the same kind of growth we’re seeing with SaaS, as our customers begin to migrate their millions of Oracle databases to Generation2 of the Oracle Public Cloud,” said Ellison.

Hurd added the following details on the AT&T deal.

  • AT&T’s deal is ratable over time and Oracle nets more revenue.
  • There are more than 10,000 Oracle databases at AT&T.
  • AT&T wanted the data on-premise due to regulations.
  • “We take our Oracle Cloud machine and we are able now to do all of that with them on their premise and give them all the benefits of the cloud. We manage. We patch. We basically run the cloud for them and we help them get all of that done,” said Hurd.
  • Financials weren’t disclosed, but Hurd said the AT&T transaction is important because of what it represents for the Oracle customer base.
  • Meanwhile, Oracle added several ERP, HCM and CRM customers. These customers are also moving up from on-premises to the cloud.

Oracle’s bet is that on-premise database licenses become cloud machine similar to the way customers have moved apps to the cloud.


Software export growth set to slow: Nasscom

Domestic market expected to grow faster than exports and may touch $26.5 million in FY18

The country’s software export growth is set to slow to 7-8% this fiscal year, down from 8.6% a year earlier, according to industry body Nasscom.

Nasscom expects software export revenue to be between $124-125 billion in the current fiscal year to March 2018. Software exports during the last year ended March 2017 were $116 billion and domestic market revenue, excluding that of hardware, was $24 billion, both in constant currency terms. The domestic market was projected to grow faster than the export market during this fiscal, Nasscom president R.Chandrashekhar said. Revenue from the domestic market may increase 10-11% and touch $26-26.5 billion.

Last fiscal, the industry added $11 billion in revenue, an increase of 8.6% in constant currency and 7.6% in reported currency, despite headwinds in the form of “increased rhetoric on protectionism, elections, Brexit and visa issues.

Macroeconomic uncertainties also led to delay in the decision-making process of customers, while in traditional services the growth was slower on account of the focus on cost optimisation. Currency volatility led to a difference of 1-3% between constant currency and reported currency growth, the National Association of Software & Services Companies (Nasscom) said.

Stating that it was the first instance of Nasscom making the guidance announcement in Hyderabad, Chairman Raman Roy said it is a precursor to the focus that will remain on the city over 8-12 months ahead. Hyderabad will play host to several programmes of Nasscom as well as the prestigious World Congress on IT, which is coming to India for the first time.

‘Inflection point’

The outlook, Nasscom chairman Raman Roy said, comes in the backdrop of the industry being at an interesting “inflection point.”

Mr. Chandrashekhar said improvements in financial services and a high potential in digital businesses would be the key growth drivers. Nasscom had deferred making the announcement in February. Then it had lowered the projections for the last fiscal year.

“The direction today is far clear… have a greater visibility and reasonably confident of what we are talking about,” he said.

An improvement in legacy business and increased automation-based projects would be among the growth drivers, Mr. Chandrashekhar said. The industry also foresaw itself as a net hirer. The number of people to be hired this year would be between 1.3 lakh and 1.5 lakh, he said. The demand will be for technology-skilled professionals and it was imperative for new and existing people to reskill themselves.

Vice-chairman Rishad Premji said a big opportunity for reskilling was emerging and unlike in the past many in the workforce were coming forward to equip themselves with new skills.


BlackBerry’s Banner Year Hits Snag as Software Sales Falter

Image result for BlackBerry’s Banner Year Hits Snag as Software Sales Falter

The Canadian company, which exited the hardware business last year, missed analysts’ estimates for total revenue, the majority of which is now made up of software sales. Revenue excluding some costs was $244 million in the fiscal first quarter compared with the average analyst estimate of $265.4 million.

The shares fell 5.2 percent to $10.49 in early market trading at 7:58 a.m. in New York.

The lower-than-projected sales struck a negative note in what has otherwise been a banner year for the Waterloo, Ontario-based company. Shares have surged more than 60 percent as investors started treating BlackBerry like the growing software company it has turned itself into. An $814 million windfallawarded to end a dispute with Qualcomm Inc. over royalty payments and positive comments from short seller Andrew Left didn’t hurt either.

The Qualcomm payment bolstered BlackBerry’s cash reserves, which now stand at $2.6 billion. That means Chief Executive Officer John Chen could resume making acquisitions to bolster software revenue, a tactic that helped replace some of the company’s evaporating hardware sales over the last three years.

Share Buyback

Some of that cash will go toward share buybacks, with BlackBerry authorizing TD Securities to buy back as much as 6.4 percent of the company’s circulating shares on its behalf. Buybacks have been part of Chen’s tool box in his bid to revive the company’s fortunes. Shares taken out of public circulation are used to offset the company’s employees equity inventive plan.

BlackBerry also re-organized how it reported revenue to reflect its current reality as a software company with a side business in licensing old hardware patents. The new software and services segment accounted for $92 million in revenue, up 12 percent from what would have been $82 million in the same quarter last year.

Chen has said he wants to increase that software number faster than 13 percent a year, as he fights with competitors like International Business Machines Corp. and MobileIron Inc. for the growing market in software that helps companies and governments keep their employees’ devices safe from hackers.

Licensing revenue was $32 million, compared with $25 million last year. Handheld devices revenue, which is made up of licensing agreements for the company’s phone brand to company’s like TCL Corp., was $37 million, compared to $152 million last year when the company still produced its own phones.


How to Create Interactive JavaScript Charts from Custom Data Sets

Image result for DeCaffeinate Converts CoffeeScript To JavaScriptCharts are a great way of visualizing complex data quickly and effectively. Whether you want to identify a trend, highlight a relationship, or make a comparison, charts help you communicate with your audience in a precise and meaningful manner.

In my previous article — Getting Started with AnyChart: 10 Practical Examples — I introduced the AnyChart library and demonstrated how it is a great fit for your data visualization needs. Today, I want to dig a little deeper and look at AnyChart’s data mapping features which allow you to create beautiful charts from custom data sets with a minimum of fuss.

I also want to look at the many ways you can customize AnyChart to suit your requirements, as well as how you can change the look and feel of AnyChart charts by using themes. There are currently 17 out-of-the-box themes to choose from, or you can create your own. And if you’ve not got the best eye for design, why not buy our book to get a leg up.

As the Head of R&D at AnyChart, I could spend all day talking about this library, but now it’s time to get down to business.

Data Mapping in AnyChart

More from this author

  • Getting Started with AnyChart — 10 Practical Examples
  • Introducing GraphicsJS, a Powerful Lightweight Graphics Library

To facilitate the integration of custom data sources into charting applications, AnyChart has special objects called data sets. These objects act as intermediate containers for data. When data is stored in data sets, AnyChart can track changes to it, analyze it, and work with this data in a more robust and effective manner. In short: interactive JavaScript charts have never been easier!

No matter if you have an array of objects, an array of arrays, or a .csvfile, you can use data sets to:

  • ensure full and explicit control over the series created
  • define which column is an argument (x-axis)
  • define which columns hold values for which series
  • filter data
  • sort data

Basics of Data Mapping

The best way to learn how data mapping works in AnyChart is to look at an example. Let’s imagine an array with the following custom data set:

var rawData = [
  ["A", 5, 4, 5, 8, 1, "bad"],
  ["B", 7, 1, 7, 9, 2, "good"],
  ["C", 9, 3, 5, 4, 3, "normal"],
  ["D", 1, 4, 9, 2, 4, "bad"]

There’s nothing too wild going on here — this kind of custom data structure is common in a lot of existing applications. But now you want to use this array in AnyChart. With many other charting libraries you would be forced to transform the data to a format that the library can work with. Well, with AnyChart things are a lot simpler — just look what we can do. First, load the array into a data set:

var rawData = [
  ["A", 5, 4, 5, 8, 1, "bad"],
  ["B", 7, 1, 7, 9, 2, "good"],
  ["C", 9, 3, 5, 4, 3, "normal"],
  ["D", 1, 4, 9, 2, 4, "bad"]

var dataSet = anychart.data.set(rawData);

And then, once the data has been loaded into the data set, the real magic begins: you can now create so called views. These are data sets derived from other data sets.

var rawData = [
  ["A", 5, 4, 5, 8, 1, "bad"],
  ["B", 7, 1, 7, 9, 2, "good"],
  ["C", 9, 3, 5, 4, 3, "normal"],
  ["D", 1, 4, 9, 2, 4, "bad"]

var dataSet = anychart.data.set(rawData);

var view1 = dataSet.mapAs({x: 0, value: 1});
var view2 = dataSet.mapAs({x: 0, value: 2});
var view3 = dataSet.mapAs({x: 0, high: 3, low: 4});
var view4 = dataSet.mapAs({x: 0, value: 5, meta: 6});

You’ll notice that when defining a view, you determine which columns from the original array are included and what names these columns get. You can then use them to create whichever kind of charts you like. For example, here’s how to create a pie chart from the custom data in the 5th column.

Note: AnyChart needs only x and value fields to create a pie chart, but the views also contain a meta field with the data from the 6th column. You can map any number of optional fields and use them as you like. For example, these fields can contain additional data to be shown as labels or as tooltips:

anychart.onDocumentLoad(function() {
  var rawData = [
    ["A", 5, 4, 5, 8, 3, "Bad"],
    ["B", 7, 1, 7, 9, 5, "Good"],
    ["C", 9, 3, 5, 4, 4, "Normal"],
    ["D", 1, 4, 9, 2, 3, "Bad"]

  var dataSet = anychart.data.set(rawData);
  var view4 = dataSet.mapAs({x: 0, value: 5, meta: 6});

  // create chart
  var chart = anychart.pie(view4);
  chart.title("AnyChart: Pie Chart from Custom Data Set");
  chart.labels().format("{%meta}: {%Value}");

And this is what we end up with:

Note: You can find all of the demos in this article as a CodePen collection.

Multi-Series Combination Chart with Custom Data Set

Now, let’s see how we can use the same custom data to create a combination chart with line and range area charts on the same plot. This section is going to be very short since now you know what views are. All you need to do is choose the proper views and create the necessary series explicitly:

anychart.onDocumentLoad(function() {
  var rawData = [
    ["A", 5, 4, 5, 8, 3, "Bad"],
    ["B", 7, 1, 7, 9, 5, "Good"],
    ["C", 9, 3, 5, 4, 4, "Normal"],
    ["D", 1, 4, 9, 2, 3, "Bad"]

  var dataSet = anychart.data.set(rawData);

  var view1 = dataSet.mapAs({x: 0, value: 1});
  var view2 = dataSet.mapAs({x: 0, value: 2});
  var view3 = dataSet.mapAs({x: 0, high: 3, low: 4});

  // create chart
  var chart = anychart.line();
  // create two line series
  // create range area series

  // set title and draw chart
  chart.title("AnyChart: Combined Chart from Data Set");

This is what it looks like:

Live Data Streaming and Filtering

And now, to showcase the beauty of views and data sets. For this we’ll create a column chart and a multi-line chart, live stream data into a data set, and accept only certain values into the column chart. Sound complicated? It isn’t really!

anychart.onDocumentLoad(function() {
  var rawData = [
    ["A", 5, 4, 2, 6, 3, "Bad"],
    ["B", 7, 2, 1, 9, 5, "Good"],
    ["C", 8, 3, 2, 9, 4, "Normal"],
    ["D", 1, 4, 1, 4, 3, "Bad"]

  dataSet = anychart.data.set(rawData);

  var view1 = dataSet.mapAs({ x: 0, value: 1 });
  var view2 = dataSet.mapAs({ x: 0, value: 2 });
  var view3 = dataSet.mapAs({ x: 0, value: 3 });
  var view4 = dataSet.mapAs({ x: 0, value: 4 });
  var view5 = dataSet.mapAs({ x: 0, value: 5 });

  // create chart
  var chart1 = anychart.line();
  // create several line series

  // create column chart
  // based on filtered view
  // that accepts values of less than 5 only
  var chart2 = anychart.column(
    view5.filter("value", function(v) {
      return v < 5;

  // set title and draw multi-line chart
  chart1.title("Line: Streaming from Data Set");

  // set title and draw column chart
  chart2.title("Column: Filtering Stream");

// streaming function
var streamId;
function stream() {
  if (streamId === undefined) {
    streamId = setInterval(function() {
    }, 1000);
  } else {
    streamId = undefined;

// function to add new value and remove first one
function addValue() {
  // generate next letter/symbol as argument
  var x = String.fromCharCode(
    dataSet.row(dataSet.getRowsCount() - 1)[0].charCodeAt(0) + 1
  // append row of random values to data set
    Math.random() * 10,
    Math.random() * 10,
    Math.random() * 10,
    Math.random() * 10,
    Math.random() * 10
  // remove first row

You see that we’ve created a custom data set and five derived views. Four of them are used as is to create lines, but when creating our column chart, we apply the filtering function and let only values of less than 5 into the view. Then we stream data by adding and removing rows from the main data set, and all the views automatically receive data and charts are updated — no coding is needed to implement this!

This is just the tip of the iceberg as far as data mapping goes! You can do the same with arrays of objects and CSV data, and you can sort, search, listen to changes, go through values, as well as change existing rows. There are also special views for hierarchical data utilized in Tree Maps and Gantt Charts, and such views can be searched and traversed.

Customizing Chart Visualization

AnyChart is extremely versatile when it comes to chart customization. You can change line styles, fill colors, use gradient fill or image fill on almost any element. Colors can be set using String constants, HEX or RGB notation, or a function that returns one of these values. The library also offers a number of built-in patterns, as well as an option to create patterns of your own.


The easiest way to change the look and feel of AnyChart charts is to change the theme.

In fact, you can create your own theme or use one of those that already come with the library. There are currently 17 out-of-the-box themes available in AnyChart: Coffee, Dark Blue, Dark Earth, Dark Glamour, Dark Provence, Dark Turquoise, Default Theme, Light Blue, Light Earth, Light Glamour, Light Provence, Light Turquoise, Monochrome, Morning, Pastel, Sea, Wines. The files for these themes can be obtained from the Themes Section at AnyChart CDN.

You can reference them like so:

<script src="https://cdn.anychart.com/js/latest/anychart-bundle.min.js"></script>
<script src="https://cdn.anychart.com/themes/latest/coffee.min.js"></script>

And activate the theme with just one line:


Let’s use the basic chart from the previous article by way of an example.

anychart.onDocumentLoad(function() {
  // set theme referenced in scripts section from
  // https://cdn.anychart.com/themes/latest/coffee.min.js
  // create chart and set data
  var chart = anychart.column([
    ["Winter", 2],
    ["Spring", 7],
    ["Summer", 6],
    ["Fall", 10]
  // set chart title
  chart.title("AnyChart Coffee Theme");
  // set chart container and draw

Now the look and feel of that chart is completely different.

Note: you can browse through all the themes and see how they work with different chart types and series on the AnyChart Themes Demo Page. Please refer to the AnyChart Documentation to learn how to create your own themes and read about other options.


As you have seen, it’s quite trivial to color elements in the AnyChart charting library. But there’s more! It is also possible to color shapes with solid colors with opacity, use radial and linear gradients, and make lines dashed. You can apply colors by their web constant names, HEX codes, or RGB, RGBA, HSL, HSLA values — just as you can in CSS.

To showcase all of this in one powerful sample, I want to highlight another option along the way — namely that you can color elements using your own custom functions. This may come in handy in many data visualization situations, for example when you want to set a custom color depending on the value of the element. Let’s test this out on a Pareto chart. AnyChart can build this chart from raw data and calculate everything it needs.

anychart.onDocumentReady(function() {

  // create Pareto chart
  var chart = anychart.pareto([
    {x: "Defect 1", value: 19},
    {x: "Defect 2", value: 9},
    {x: "Defect 3", value: 28},
    {x: "Defect 4", value: 87},
    {x: "Defect 5", value: 14},

  // set chart title
  chart.title("Pareto Chart: Conditional coloring");

  // set container id and draw

But say we want to highlight the elements that have relative frequency of less than 10%. All we need to do in this case is to add some coloring functions:

// Get Pareto column series
// and configure fill and stroke
var column = chart.getSeriesAt(0);
column.fill(function () {
  if (this.rf < 10) {
    return '#E24B26 0.5'
  } else {
    return this.sourceColor;
column.stroke(function () {
  if (this.rf < 10) {
    return {color: anychart.color.darken('#E24B26'), dash:"5 5"};
  } else {
    return this.sourceColor;

As is shown in the example, we can access the coloring function context with the help of the this keyword, then we create a condition and output whichever color or line setting we need. We use a simple HEX string with opacity for the color: '#E24B26 0.5'. For the line, we calculate a darker color using AnyChart’s special color transformation function and also set an appropriate dash parameter: {color: anychart.color.darken('#E24B26'), dash:"5 5"}.

Here’s what we end up with:

Default Pattern Fill

The AnyChart JavaScript charting library also provides a very flexible way to work with pattern (hatch) fills. To start with, you have 32 pattern fill types. They can be arranged into your own custom pallets, and you can directly set which one to use for a certain series, element, etc. Here’s what the code for a monochrome pie chart might look like:

anychart.onDocumentReady(function() {
  // create a Pie chart and set data
  chart = anychart.pie([
    ["Apple", 2],
    ["Banana", 2],
    ["Orange", 2],
    ["Grape", 2],
    ["Pineapple", 2],
    ["Strawberry", 2],
    ["Pear", 2],
    ["Peach", 2]

  // configure chart using chaining calls to shorten sample
    .fill("Black 1")

  // draw a chart

The only thing we did to enable the pattern fill is chart.hatchFill(true).

Custom Pattern Fill

AnyChart gets its ability to use custom patterns from the underlying GraphicsJS library. I introduced this library and showcased some really cool drawing samples in my article here on SitePoint: Introducing GraphicsJS, a Powerful Lightweight Graphics Library. The fact that AnyChart is powered by GraphicsJS allows for some really amazing results, but a picture is worth a thousand words, so let’s proceed to the next example.

We’ll create patterns using one old font that used to be rather popular among geologists – Interdex. I remember one of AnyChart customers asking us how to use this in his project, and he was very happy to learn just how easy it was.

First, if you want to use a font that is not present on your system, you need to create a web font and properly reference it in the CSS file. A sample of such file for our Interdex font can be found on the AnyChart CDN. We need to reference it along with the font management library being used and the AnyChart charting library:

<link rel="stylesheet" type="text/css" href="https://cdn.anychart.com/fonts/interdex/interdex.css"/>

<script src="https://cdn.anychart.com/js/latest/anychart-bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fontfaceobserver/2.0.7/fontfaceobserver.js"></script>

After that, we can proceed with the coding:

var fontLoad = new FontFaceObserver("Conv_interdex");

// create chart when font is loaded using
// https://cdnjs.cloudflare.com/ajax/libs/fontfaceobserver/2.0.7/fontfaceobserver.js
fontLoad.load().then(function() {
  anychart.onDocumentReady(function() {
    // enable hatch fill by default and make chart monochrome
      chart: {
        defaultSeriesSettings: {
          base: {
            hatchFill: true,
            fill: "White",
            hoverFill: "White",
            stroke: "Black"

    // create a stage, it is needed to create a custom pattern fill
    stage = anychart.graphics.create("container");

    // create a column chart and set title
    chart = anychart.column();
    chart.title("AnyChart Custom Pattern");
    // set the data
      ["Jan", 1000, 1200, 1500, 1000, 1200, 1500],
      ["Feb", 1200, 1500, 1600, 1200, 1500, 1600],
      ["Mar", 1800, 1600, 1700, 1800, 1600, 1700],
      ["Apr", 1100, 1300, 1600, 1100, 1300, 1600],
      ["May", 1900, 1900, 1500, 1900, 1900, 1500]

    // set custom hatch palette
    // it can be populated with any number of patterns

    // set container and draw chart

// function to create patterns
function getPattern(letter) {
  var size = 40;
  // create a text object
  var text = anychart.graphics
      "<span " +
        "style='font-family:Conv_interdex;font-size:" +
        size +
        ";'>" +
        letter +
  // create a pattern object
  var pattern = stage.pattern(text.getBounds());
  //  add text to a pattern
  return pattern;

I’ve included all the explanations in the comments, but just to sum up – you can create custom patterns, arrange them in custom pattern palettes, which you can then apply to an entire chart. If you’re paying attention, you’ll notice that we’ve made use of the AnyChart themes mechanism to set defaults.

Here’s the end result. Lovely, I’m sure you’ll agree…

Custom Series

And the final sample in this article is for those who want even more flexibility and customization. While AnyChart strives to provide an ever-increasing number of chart types out of the box, data visualization is an enormous field, and each project has different requirements. In order to make (and keep) everyone as happy as possible and provide a way to create the visualizations of their choice, AnyChart open-sourced the JavaScript drawing library of GraphicsJS and also opened the source of the AnyChart JavaScript charting library itself.

But if you really, really want to go with 100% custom drawing, you’ll have to do a lot of work if you decide to fork the source code. For example, customizing might be a pain, and you could potentially have problems merging future versions if AnyChart doesn’t accept your pull request.

Luckily, there is a third option. With most of AnyChart’s basic chart types, you can override the rendering function and change the appearance of chart elements, while keeping all of the other things AnyChart provides.

Below you will find a code sample that shows how to transform a widely used range column chart (which is supported in the AnyChart charting library), into a less common cherry chart (which isn’t). The main thing to bare in mind when you override AnyChart’s rendering function, is that this function calculates everything from values supplied to a series, and your own (custom) series should be created out of a series with the same number of values.

anychart.onDocumentReady(function() {
  // create a chart
  var chart = anychart.cartesian();
  chart.yAxis().title("Cherry price");

  // create a data set
  var data = [
    { x: "Apr", low: 29, high: 37 },
    { x: "May" },
    { x: "Jun", low: 29, high: 47 },
    { x: "Jul", low: 12, high: 27 },
    { x: "Aug", low: 20, high: 33, color: "#ff0000" },
    { x: "Sep", low: 35, high: 44 },
    { x: "Oct", low: 20, high: 31 },
    { x: "Nov", low: 44, high: 51 }

  // create a range column series
  var series = chart.rangeColumn(data);
  // set a meta field to use as a cherry size
  // series.meta("cherry", 50);
  // set a meta field to use as a stem thickness
  // series.meta("stem", 1);

  // optional: configurable select fill

  // call a custom function that changes series rendering

  // set container id for the chart and initiate chart drawing

// custom function to change range column series rendering to
// cherry chart with a special value line markers
function cherryChartRendering(series) {
  // cherry fill color
  series.fill(function() {
    // check if color is set for the point and use it or series color
    color = this.iterator.get("color") || this.sourceColor;
    return anychart.color.lighten(color, 0.25);
  // cherry stroke color
  series.stroke(function() {
    // check if color is set for the point and use it or series color
    color = this.iterator.get("color") || this.sourceColor;
    return anychart.color.darken(color, 0.1);

  // set rendering settings
  series.rendering()// set point function to drawing

// custom drawer function to draw a cherry chart
function drawer() {
  // if value is missing - skip drawing
  if (this.missing) return;

  // get cherry size or set default
  var cherry = this.series.meta("cherry") || this.categoryWidth / 15;
  // get stem thickness or set default
  var stem = this.series.meta("stem") || this.categoryWidth / 50;

  // get shapes group
  var shapes = this.shapes || this.getShapesGroup(this.pointState);
  // calculate the left value of the x-axis
  var leftX = this.x - stem / 2;
  // calculate the right value of the x-axis
  var rightX = leftX + stem / 2;

    // resets all 'path' operations
    // draw bulb
    .moveTo(leftX, this.low - cherry)
    .lineTo(leftX, this.high)
    .lineTo(rightX, this.high)
    .lineTo(rightX, this.low - cherry)
    .arcToByEndPoint(leftX, this.low - cherry, cherry, cherry, true, true)
    // close by connecting the last point with the first

Here’s what we end up with


I hope you’ve found this look at AnyChart’s more advanced functionality useful and that this has given you plenty ideas and inspiration for your own data vizualizations.

If you’ve not tried AnyChart yet, I urge you to give it a go. Our latest release (version 7.14.0) added eight new chart types, five new technical indicators, Google Spreadsheet data loader, marquee select and zoom, text wrap and other cool new features.

And if you’re using AnyChart in your projects and have any comments or questions regarding the library, I’d love to hear these in the comments below.


DeCaffeinate Converts CoffeeScript To JavaScript

Image result for DeCaffeinate Converts CoffeeScript To JavaScriptImage result for DeCaffeinate Converts CoffeeScript To JavaScriptA new tool lets you automatically convert your CoffeeScript source to modern JavaScript. Decaffeinate is available now on GitHub.

CoffeeScript has been relatively successful because its code compiles one-to-one into JavaScript. Compiled output remains readable, passes through JavaScript Lint without warnings, will work in every JavaScript runtime. However, with JavaScript ES6 many of the things that CoffeeScript supplied are standard in JavaScript.

The advantage offered by ECMAScript 2015 (ES6) is that it defines the standard for the JavaScript implementation used in web browsers, is supported natively, and as it is an official standard it overcomes the need to rely on a project such as CoffeeScript that lacks such global definition and support.

CoffeeScript still has a lot of supporters, even taking ES6 into account. Developers praise its conciseness, and point out that CoffeeScript can compile to ES6 as a separate build step. Its supporters argue that CoffeeScript programs have fewer lines of code, and avoided contentious issues such as problems with undeclared vars, and JavaScript’s distinction between == and ===.

Those backing decaffeinate and ES6 say that despite such reservations, the momentum is with ES6. They credit many of ES6’s good points as having been derived from CoffeeScript. The strongest argument for conversion, and for using decaffeinate, is that as a redundant technology, CoffeeScript will eventually become defunct.




The decaffeinate project can be used to convert a single file or a whole project as a batch operation. The bulk conversion tool can check a codebase for decaffeinate-readiness, and once the code (or a part of it) is ready, will run the conversion and do some of the cleaning up necessary after the conversion.

There’s a fork of the CoffeeScript implementation with some small patches that are useful to the decaffeinate project.




Nodejs v6 Released

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on, Twitter, Facebook, Google+ or Linkedin.


A Beginner’s Guide to Testing Functional JavaScript

Functional programming and testing. Maybe you’ve given them a try in isolation, but somehow you never made either a part of your regular practice. They may sound innocent by themselves, but together testing and functional programming can create an irresistible temptation, almost compelling you to write cleaner, tighter, more maintainable code.

Testing Functional JavaScript — A crash test dummy sits at a computer with a mug of coffee

Well the good news is that working with both techniques together can offer some real advantages. In fact, once you’ve tasted how sweet this combination can be, you might find yourself as addicted to it as I am, and I’d be willing to bet that you’ll be coming back for more.

In this article, I’ll introduce you to the principles of testing functional JavaScript. I’ll show you how to get up and running with the Jasmine framework and build out a pure function using a test-driven approach.

Testing is about making sure that the code in your application does what you expect it to do, and keeps doing what you expect it to do when you make changes so you have a working product when you’re done. You write a test that defines your expected functionality under a defined set of circumstances, run that test against the code, and if the result isn’t what the test says it should be, you get a warning. And you keep getting that warning until you’ve fixed your code.

Then you get the reward.

And yes, it will make you feel good.

Testing comes in a lot of flavors, and there is room for healthy debate about where the borders are drawn, but in a nutshell:

  • Unit tests validate the functionality of isolated code
  • Integration tests verify the flow of data and the interaction of components
  • Functional tests look at the behavior of the overall application

Note: Don’t get distracted by the fact that there’s a type of testing called functional testing. That’s not what we’ll be focusing on in this article about testing functional JavaScript. In fact, the approach you’ll use for functional testing of the overall behavior of an application probably won’t change all that much whether or not you’re using functional programming techniques in your JavaScript. Where functional programming really helps out is when you’re building your unit tests.

You can write a test at any point in the coding process, but I’ve always found that its most efficient to write a unit test before writing the function you’re planning to test. This practice, known as test-driven development (TDD), encourages you to break down the functionality of your application before you start writing and determine what results you want from each section of code, writing the test first, then coding to produce that result.

A side benefit is that TDD often forces you to have detailed conversations with the people who are paying you to write your programs, to make sure that what you’re writing is actually what they’re looking for. After all, it’s easy to make a single test pass. What’s hard is determining what to do with all the likely inputs you’re going to encounter and handle them all correctly without breaking things.

Why Functional?

As you can imagine, the way you write your code has a lot to do with how easy it is to test. There are some code patterns, such as tightly coupling the behavior of one function to another, or relying heavily on global variables, that can make code much more difficult to unit test. Sometimes you may have to use inconvenient techniques such as “mocking” the behavior of an external database or simulating a complicated runtime environment in order to establish testable parameters and results. These situations can’t always be avoided, but it is usually possible to isolate the places in the code where they are required so that the rest of the code can be tested more easily.

Functional programming allows you to deal with the data and the behavior in your application independently. You build your application by creating a set of independent functions that each work in isolation and don’t rely on external state. As a result, your code becomes almost self-documenting, tying together small clearly defined functions that behave in consistent and understandable ways.

Functional programming is often contrasted against imperative programming and object-oriented programming. JavaScript can support all of these techniques, and even mix-and-match them. Functional programming can be a worthwhile alternative to creating sequences of imperative code that track the state of the application across multiple steps until a result is returned. Or building your application out of interactions across complex objects that encapsulate all of the methods that apply to a specific data structure.

How Pure Functions Work

Functional programming encourages you to build your application out of tiny, reusable, composable functions that just do one specific thing and return the same value for the same input every single time. A function like this is called a pure function. Pure functions are the foundation of functional programming, and they all share these three qualities:

  • Don’t rely on external state or variables
  • Don’t cause side effects or alter external variables
  • Always return the same result for the same input

Another advantage of writing functional code is that it makes it much easier to do unit testing. The more of your code that you can unit test, the more comfortably you can count on your ability to refactor the code in the future without breaking essential functionality.

What Makes Functional Code Easy to Test?

If you think about the concepts that we just discussed, you probably already see why functional code is easier to test. Writing tests for a pure function is trivial, because every single input has a consistent output. All you have to do is set the expectations and run them against the code. There’s no context that needs to be established, there are no inter-functional dependencies to keep track of, there’s no changing state outside of the function that needs to be simulated, and there are no variable external data sources to be mocked out.

There are a lot of testing options out there ranging from full-fledged frameworks to utility libraries and simple testing harnesses. These include Jasmine, Mocha, Enzyme, Jest, and a host of others. Each one has different advantages and disadvantages, best use cases, and a loyal following. Jasmine is a robust framework that can be used in a wide variety of circumstances, so here’s a quick demonstration of how you might use Jasmine and TDD to develop a pure function in the browser.

You can create an HTML document that pulls in the Jasmine testing library either locally or from a CDN. An example of a page including the Jasmine library and test runner might look something like this:

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8">
    <title>Jasmine Test</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.1/jasmine.min.css">

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.1/jasmine.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.1/jasmine-html.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.1/boot.min.js"></script>

This brings in the Jasmine library, along with the Jasmine HTML boot script and styling. In this case the body of the document is empty, waiting for your JavaScript to test, and your Jasmine tests.

Testing Functional JavaScript — Our First Test

To get started, let’s write our first test. We can do this in a separate document, or by including it inside a <script> element on the page. We’re going to use the describe function defined by the Jasmine library to describe the desired behavior for a new function we haven’t written yet.

The new function we’re going to write will be called isPalindrome and it will return true if the string passed in is the same forwards and backwards, and return false otherwise. The test will look like this:

describe("isPalindrome", () => {
  it("returns true if the string is a palindrome", () => {

When we add this to a script in our page and load it a browser, we get a working Jasmine report page showing an error. Which is what we want at this point. We want to know that the test is being run, and that it’s failing. That way our approval-hungry brain knows that we have something to fix.

So let’s write a simple function in JavaScript, with just enough logic to get our test to pass. In this case it’s just going to be a function that makes our one test pass by returning the value expected.

const isPalindrome = (str) => true;

Yes, really. I know it looks ridiculous, but hang in there with me.

When the test runner again, it passes. Of course. But obviously this simple code does not do what we might expect a palindrome tester to do. We’ve written the minimal amount of code that makes the test pass. But we know that our code would fail to evaluate palindromes effectively. What we need at this point are additional expectations. So let’s add another assertion to our describe function:

describe("isPalindrome", () => {
  it("returns true if the string is a palindrome", () => {
  it("returns false if the string isn't a palindrome", () => {

Reloading our page now makes the test output turn red and fail. We get a messages saying what the problem is, and the test result turns red.


Our brains sense that there’s a problem.

Of course there is. Now our simple isPalindrome function that just returns true every time has been demonstrated not to work effectively against this new test. So let’s update isPalindrome adding the ability to compare a string passed in forward and backward.

const isPalindrome = (str) => {
  return str
    .join("") === str;

Testing Is Addictive

Green again. Now that’s satisfying. Did you get that little dopamine rush when you reloaded the page?

With these changes in place, our test passes again. Our new code effectively compares the forward and backward string, and returns true when the string is the same forward and backward, and false otherwise.

This code is a pure function because it is just doing one thing, and doing it consistently given a consistent input value without creating any side effects, making any changes to variables outside of itself, or relying on the state of the application. Every time you pass this function a string, it does a comparison between the forward and backward string, and returns the result regardless of when or how it is called.

You can see how easy that kind of consistency makes this this function to unit test. In fact, writing test-driven code can encourage you to write pure functions because they are so much easier to test and modify.

And you want the satisfaction of a passing test. You know you do.

Refactoring a Pure Function

At this point it’s trivial to add additional functionality, such as handling non-string input, ignoring differences between uppercase and lowercase letters, etc. Just ask the product owner how they want the program to behave. Since we already have tests in place to verify that strings will be handled consistently, we can now add error checking or string coercion or whatever behavior we like for non-string values.

For example, let’s see what happens if we add a test for a number like 1001 that might be interpreted a palindrome if it were a string:

describe("isPalindrome", () => {
  it("returns true if the string is a palindrome", () => {
  it("returns false if the string isn't a palindrome", () => {
  it("returns true if a number is a palindrome", () => {

Doing this gives us a red screen and a failing test again because our current is isPalindrome function doesn’t know how to deal with non-string inputs.

Panic sets in. We see red. The test is failing.

But now we can safely update it to handle non-string inputs, coercing them into strings and checking them that way. We might come up with a function that looks a little bit more like this:

const isPalindrome = (str) => {
  return str
    .join("") === str.toString();

And now all our tests pass, we’re seeing green, and that sweet, sweet dopamine is flooding into our our test-driven brains.

By adding toString() to the evaluation chain, we’re able to accommodate non-string inputs and convert them to strings before testing. And best of all, because our other tests are still being run every time, we can be confident that we haven’t broken the functionality we got before by adding this new capability to our pure function. Here’s what we end up with:

Play around with this test, and start writing some of your own, using Jasmine or any other testing library that suits you.

Once you incorporate testing into your code design workflow, and start writing pure functions to unit test, you may find it hard to go back to your old life. But you won’t ever want to.

This article was peer reviewed by Vildan Softic. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!


6 great Android features missing from iOS 11

6 great Android features missing from iOS 11

Credit: Ben Patterson

Call me a flip-flopper, but the new features in iOS 11 have me thinking of jumping back to iOS after switching to Android barely a year ago.

Indeed, the new version of iOS brings such enticing features as a revamped App Store, a customizable Control Center, and drag-and-drop for iPad users, plus such catch-up features as one-handed typing and easy person-to-person payments.

But returning to iOS would mean leaving behind many Android features I’ve grown to love, from the ability to set up multiple user profiles to one-touch Google searches on whatever’s onscreen at a given moment.

Read on for six awesome Android features that iOS 11 has yet to match, starting with…

Multiple user profiles

Given all the innovations coming to the iPad courtesy of iOS 11, from the ability to drag-and-drop elements from one side of the split screen to the other and the new, persistent app dock, you’d think Apple would toss in a feature that’s been standard on Android for years: user profiles, perfect for letting family members in a one-iPad household create their own personal iPad spaces.

Multiple user profiles

Ben Patterson

If you’ve been waiting for Android-like user profiles to arrive on iOS, bad news: they’re still missing in iOS 11.

For whatever reason, though (privacy concerns, perhaps?), Apple has yet again passed on adding user profiles to the iPhone or iPad. That means if you share your iPad with your toddler or teenager, you’re sharing all your iPad data, too, including your e-mail, your open browser tabs, your Facebook app, everything.

Multiple Do Not Disturb schedules

Android has really spoiled me with its “automatic rules” for Do Not Disturb mode. With automatic rules, you can set up multiple Do Not Disturb schedules for weeknights, weekends, meetings, and any other scenarios you dream up. For example, I have Do Not Disturb set to turn itself off early (as in 6 a.m.) on weekday mornings, while on weekends, Do Not Disturb keeps things quiet until about 8.

Multiple Do Not Disturb schedules

Ben Patterson

Android’s “automatic rules” let you create multiple Do Not Disturb schedules, as opposed to the single Do Not Disturb schedule in iOS 11.

In iOS 11, though, Do Not Disturb mode still lets you set only a single schedule, meaning you can’t set Do Not Disturb to give you more quiet time on weekends or during meetings.

Yes, the new “Do Not Disturb While Driving” feature (which automatically silences notifications whenever your iPhone senses you’re driving) is a nice innovation, but it’s too bad iOS 11 didn’t catch up to Android’s Do Not Disturb features.

Search the entire screen

As with previous versions of Apple’s mobile software, iOS 11 lets you perform quick web searches on selected text via Spotlight, iOS’s universal search feature. That’s helpful if you want a deep search on a narrow selection of text, but sometimes I’m looking for a broader search of everything on my screen.

Scan the screen

Ben Patterson

Android’s “screen search” feature lets you do a one-tap Google search on everything that’s on your screen, a feat that iOS 11 has yet to master.

Here’s where Android’s Screen Search feature comes in handy. With a single tap of the What’s on my screen button in Google Assistant, Android will scan the entire screen and return any relevant search results, handy if you want a quick, 360-degree cheat sheet on a news article or web page. Pretty neat, and there’s no real equivalent on iOS, not even once iOS 11 arrives.

Clear all app windows

Here’s an Android feature I’d sorely miss even though I know it’s more cosmetic than anything else. The “Clear All” button on Android’s Overview screen instantly closes all your open app windows, leaving you with a soothing “No recent items” message when you tap the Overview button again. For a neat-freak like me, tapping the Clear All button never gets old.

Clear all app windows

Ben Patterson

The “Clear All” button on Android’s Overview screen might be the feature that Android-to-iOS 11 switchers miss the most.

On iOS, though—and yes, this includes iOS 11—there’s no easy way to clear out the massive stack of app windows on the multitasking screen, forcing you to flick up on dozens of individual windows until the coast is clear.

Now, I’m sure iOS comes with marvelous under-the-hood tools that manage the resources used by your apps and automatically suspends those that have been sitting untouched in the background for too long.

Still, though, I know it’ll kill me the first time my thumb reaches for the non-existent Clear All button on my new iPhone 8 (assuming I actually make the big leap).

Delete all local photos & videos from the Photos app

You’ve probably heard about the new storage-saving features in iOS 11, particularly when it comes to the storage-hogging Photos app.

Delete all local photos & videos from the Photos app

Ben Patterson

iCloud Photo Library will help shave some of the storage space consumed by your iPhone snapshots, but Google Photos for Android can wipe all local pictures and videos, perfect for keeping photo storage to an absolute minimum.

For example, Apple announced support for a new image format (HEIF, for “High Efficiency Image Format”) that can halve the amount of storage gobbled up by your snapshots.

Also coming in iOS 11: shortcuts that do a better job of recommending storage-saving features like iCloud Photo Library, which uploads all your pictures and videos to the cloud and then automatically pares down the number of images sitting on your iPhone or iPad.

Those are worthwhile improvements, but here’s something I’d sorely miss if I went back to iOS: the “free up space” feature in Android’s Photos app, which instantly zaps each and every local snapshot and video stored on your handset.

Thanks to the “free up space” feature, photos take up less than 100MB of space on my 16GB Nexus 5X. On the other hand, the Photos app on my old iPhone 6 consumes a ridiculous 17GB of storage, even with iCloud Photo Library turned on (and yes, with the Optimize iPhone Storage option enabled).

Bonus tip: The iOS version of Google Photos has a “free up space” feature just like its Android counterpart, meaning you could clear up tons of storage space on your iPhone or iPad by uploading your photos to Google and then using the “free up space” option to delete your local copies. Keep in mind, though, that if you’re using Google Photos and iCloud Photo Library at the same time, wiping your local images and videos with Google Photo’s “free up space” feature will also delete those photos from iCloud, so make sure all your local image files are safely backed up first.

Symbol shortcuts on iPhone letter keys

As with the latest version of Google Keyboard for Android, iOS 11 will bring symbol shortcuts to letter keys on the iPad keyboard, handy for saving a few keystrokes when you need to type a number key, an ampersand, or another common symbol.

Symbol shortcuts on iPhone letter keys

Ben Patterson

Thanks to iOS 11, symbol shortcuts on letter keys (shown here on Google Keyboard for Android phones) are finally coming to the iPad; not so for iPhone, unfortunately.

That’s a welcome change, but unfortunately, iOS 11’s so-called “QuickType” keyboard is only coming to iPad, not iPhone. Now, you could argue that the iPhone keypad is too small for symbol shortcuts, but the shortcuts on Google Keyboard work just fine on my five-inch Nexus 5X.