Monday, February 2, 2015

Can We Get To The Bottom Of This?

If you followed the link here from today's comic, you may have just experienced an infinite scroll. If not, I'm sure you've experienced it on Twitter, Facebook, or Pinterest. No matter how far down on the page you go, more stuff keeps getting added to the bottom. You can never reach the end!

Obviously, the comic today invokes the stuck-in-a-loop element from the Bill Murray film Groundhog Day as well as the tendency for web pages to scroll forever these days. The "invention" of the infinite scroll web page was a response to the rise in mobile web access. It is more natural to keep moving your thumb to access more information than it is to touch "previous" or "next" buttons.

If you want to add the infinite scroll element to your own web application, be careful. As a design paradigm, it doesn't work for all situations. Consider what type of information is to be displayed. Will all data be of equal relevance, or will the most important be near the top? Is the data on a timeline? Facebook and Twitter show you the newest items at the top (more or less) and the more you scroll, the farther back in time you go. They make some exceptions to that in the case of conversations because most people want to read the beginning before the end. Also, consider how navigation is affected. In my comic, the links to this blog, the social media buttons, and the previous/next navigation links are at the bottom of the page. I had to make special accommodations for today's comic in the form of a fixed-position panel at the bottom than can be shown and hidden. You could have a similar issue if your navigation is at the top and your user has scrolled 4800 feet down on the page. One final issue is that if your dynamically-added content waaaaay down on the page is a link to something else, the user might be disappointed when the use the back button and don't really go back to the same place they left.

If you're okay with all those issues and want to make your own page scroll forever, it is very easy to do with jQuery. Here is an example of what I did for my comic.

$(function() {

    var addPoint = 300;

    $(window).scroll(function(){

        if ($(this).scrollTop() > addPoint) {

            // get some new data
            // add it to your page

            addPoint += 800;

        } 

    });
 
});

My code sets up a function that will listen for scroll events on the window. The value returned from scrollTop() will be the number of pixels hidden from view due to the page scrolling down. Initially, I want to add more data when the user scrolls past 300 pixels. But as I add more data, the point at which I want to add more data will increase as well. Typically, the data you want to add will come from your server via an asynchronous call - so make sure you start the process before the user gets the whole way to to bottom to ensure you get it added in time.

If you want to address the navigation issue as well, I like to sometimes use the Affix tool that comes with Twitter Bootstrap. I make use of it in my comic editor even - though it doesn't scroll forever, there are some things I like to keep visible on the page at all times, no matter how far down I have to go. It's extremely simple to set up on your Bootstrap-enabled page.

<div data-spy="affix" data-offset-top="50">
    <div>
        <p>You can put navigation or whatever here.</p>
    </div>
</div>

But you also need some of your own styles to make it work. Here is some CSS to go along with the HTML code above.

.affix {
    top: 8px;
    left: 8px;
}

.affix-top {
    position: fixed;
    top: 110px;
    left: 8px;
}

As soon as the page loads, the Bootstrap JavaScript adds the affix-top class to your element. What that means is totally up to you - in my example I specify the affix-top class to mean the element has a fixed position 110 pixels from the top of the page and 8 pixels from the left. When the user scrolls down farther than the value given in the data-offset-top attribute, 50 pixels in my example, the affix-top class is removed and replaced with the affix class. Again, what this means is up to you. Bootstrap specifies "position: fixed" but nothing more. In my CSS, I specify the position as 8 pixels from the top and 8 from the left. That will keep it in view no matter how far the page is scrolled. When you scroll back up to the top, Bootstrap reverses the process and puts the affix-top class back on in place of the affix class.

If you're in the mood for a scroll that's a little more finite, there's always One Mile Scroll. Which is, you know, one mile. Slightly shorter than infinity.

Amphibian.com comic for 2 February 2015

Friday, January 30, 2015

The Super Bowl - The Only Use For Roman Numerals!

Alright, so today's comic is my poor attempt at humor combining Super Bowl advertising with online advertising. The Super Bowl is a big deal. I had to at least mention it in the comic.

The Super Bowl is actually the only sports program I watch. I hardly watch any television at all. I gave it up a few years ago and don't regret it. The only thing I really miss is seeing interesting and funny commercials. Fortunately, the Super Bowl rarely disappoints in that category.

But why would the frogs run a Super Bowl ad? Even they aren't sure what their company does, but it seems to be related to the latest trendy technologies. Tech companies have a long history of running Super Bowl commercials, going all the way back to 1984 with Apple's famous ad.

This year, a 30-second spot is said to cost $4 million. Any "normal" company would have a hard time justifying that much marketing money for one commercial. But for today's super-successful technology businesses, $4 million is nothing. Why not have some fun with a Super Bowl ad? Do something really creating and people will be talking about it for weeks. Apparently, people have already started talking about one of GoDaddy's ads...

What I find really interesting is how television commercials for things like web hosting companies have become so mainstream. I remember when the Internet was just for nerds. Nerds who never watched the Super Bowl.

Amphibian.com comic for 30 January 2015

Wednesday, January 28, 2015

I Won't Stand For This

A Standing Desk
I sit a lot. Most of the day really. I sit when I drive to work. I sit at work when I write software. I sit when I eat lunch. I sit when I drive home from work. I sit when I eat dinner. I sit after dinner when I write blogs and comics and sometimes other software. Always sitting.

In today's comic, the frogs are picking a new chair of the board, which to them means a new thing to sit on when they have their meetings. Frogs also sit most of the time, but they aren't bipedal. Humans are designed to stand up on two legs. So why do we sit so much?

It turns out that sitting all the time is probably taking years off my life. The sedentary lifestyle that so many of us have is dangerous. I need to sit less. Could a standing desk be the answer?

If you are unfamiliar with standing desks, they're basically just really high desks. Instead of a chair in front of it, you stand up to use it. You can write or type on it. Supposedly they are better for you than sitting at a normal desk all day.

I found this article on Lifehacker than can help me find the perfect standing desk:
Five Best Standing Desks
Then I found this other article on Lifehacker that can help me deal with pain caused by standing all day:
Take the Pain Out of Standing All Day
Draw your own conclusions.

Amphibian.com comic for 28 January 2015

Monday, January 26, 2015

Your Browser is Lying to You

There's a little trick I do on my comic to make sharing easier. Since the content changes three times per week, if you send someone the link to "amphibian.com" and they don't click on it until 2 days later there's a good chance they'll see a different comic than you did. That's why as soon as you navigate to amphibian.com I re-write the URL to include the id of the latest comic. Then when you copy the contents of your browser's location bar into the "share" field on Facebook, everyone will see the same thing you did - even if they don't click on it for a year.

And speaking of Facebook, you may have noticed this trick there as well. When you click on a picture, it will show up larger and cover most of your news feed. If you take note of the URL in your browser, it will change to a direct link to that picture. Copy that URL and use it later, or give it to a friend, and it will take you right to that picture.

You are looking at www.facebook.com...
...but click on that picture and the URL changes!

But technically speaking, your browser never left the page it was on before you clicked on the image. Just like amphibian.com doesn't redirect you to a new URL when you first visit the site or even when you navigate around using the "Previous" and "Next" links - the URL bar can lie to you!

Doing this yourself is fairly simple. Look at this code:

var newPath = "whatnot";
if (history.replaceState) {
    history.replaceState({
        nowShowing: newPath,
        yourData: "whatever you need",
        storeIt: "in this object"
    }, "page title not really used", newPath);
} else {
    // you are using an old Internet Explorer
}

The history.replaceState function is what makes the magic happen. You should check to see if it exists (I still hate you, IE 9) before calling it, but I haven't found a good fallback option or polyfill. There are some that try, but in my opinion they aren't worth the hassle. Anyway, let's unpack this a little. The replaceState function takes 3 parameters. The first is an object. Any object you want. More on this later. The second parameter is the page title for the new URL. Nothing is really done with this, but it may be used someday according to the browser documentation. Just put some text in here and forget about it. The third parameter is the new path. In my example it's "whatnot" - so if you were to execute this on www.example.com, the URL would change to www.example.com/whatnot.

Alright, so what's up with that generic, whatever-you-want, first parameter object? It comes into play when the browser's back button gets used after you've changed the URL. To have consistent behavior, you need to handle what happens when the user wants to return to where they were before you changed the URL. For example, I change the URL to www.example.com/whatnot, based on something on which the user clicked. Then I change it to www.example.com/something when they click on something else. Then they hit the back button. The browser takes them back to www.example.com/whatnot - but they didn't really never left the page. I have to know how to re-create what I had on the screen when I made up the /whatnot path in the first place.

To handle situations like this, bind a function to the "popstate" event on the window object. This function will be called whenever the back button is used. In it, you can access that object you made when you replaced the URL. Just put enough information in there to recreate the user experience you created the first time you changed the URL. Here's an example which uses jQuery for the even binding:

$(window).bind("popstate", function(event) {
    var s = event.originalEvent.state;
    if (s && s.nowShowing) {
        console.log("welcome back to " + s.nowShowing);
    }
});

Your object that you passed in to replaceState is now available via the event.originalEvent.state object. So when /whatnot becomes the URL again, you'll know as long as you put some identifying information in that object. In my example, the field nowShowing contained the path.

These tricks are often useful when developing something like a single-page web application and you want to gracefully handle the back button, but clearly they have other applications as well. Just another browser/JavaScript feature to think about when you are looking for creative solutions to web-based problems.

Amphibian.com comic for 26 January 2015

Friday, January 23, 2015

Portmantoad

Not since the spork has a portmanteau been as beloved by the tech industry as the acqui-hire. These days, it seems like the best way to get a job at a big-name Silicon Valley company is to start your own small, insignificant company and wait to get acquired.
For Sale: Team. Used but in good condition.

There is some debate over whether or not the practice of buying a company just to get its employees really works. I think the biggest benefit has to be the fact that the larger company can immediately get a team of people who already work well together. If they can keep that team together and redirect them to some other (possibly related) project, it could be much easier than trying to put together a new team. The downside is that they may be paying more for the team that it is really worth.

I believe team dynamics have been overlooked for too long when explaining why some projects succeed and others fail. But think about your own experiences. I know when I have been forced to work with people who just didn't get along, it didn't matter how talented each of us might have been individually. The project fell apart. That doesn't mean that anyone in particular was to blame, but the team as a whole just wasn't right for the task.

But when I am able to pick my own team, or when I work with friends on a project, it seems like nothing can go wrong! Or at least, nothing that we can't overcome.

Getting the right team together is difficult. When a company is small, the team grows by current employees getting their friends to come join them. Thus the team tends to work well together. At a large company, a team can be formed by a manager picking people out of a database of names and skills. It doesn't have to be like that, however. If the manager had access to some sort of personality profiles along with skill profiles, algorithms could be used to select better teams. It would be a bit like online dating - employees fill out profiles and get matched up with other employees with whom they would work well. I am not aware of any companies that have tried this, although there may be some.

The frogs have their own unique take on this practice today.

Amphibian.com comic for 23 January 2015

Wednesday, January 21, 2015

The Origin of Toads.co

Today's comic got a little complicated. So some sinister-looking toad has started a new company to compete with Amphibian.com and has hired away all the worker frogs. Since everybody's over at the other company today, the comic is actually at the toad's company website - toads.co.

I thought it would be simple to point toads.co to the same server as amphibian.com and have the application just use a different stylesheet when the toads URL is detected. As it turns out, it wasn't really that simple.

One of the things I forgot about was how picky browsers can be about cross-domain loading. While there's no issue with sourcing images or JavaScript from other domains, I ran into a minor issue with Font Awesome loading font files cross-domain.

If you haven't heard of Font Awesome, you should check it out. By creating a custom font of pictures (remember Wingdings? It's like that, but useful) it essentially gives you a library of scalable vector icons that can be customized with CSS.

Due to the way Cross-Origin Resource Sharing is designed, a server is expect to specify in a response header if the requesting domain is allowed to use a web font. The header is called Access-Control-Allow-Origin. If amphibian.com is hosting the font, by default only pages at amphibian.com can use it. But if I add the special header to the response when I serve the font, I can specify other domains that are allowed to access it.

My goal, therefore, was to set the "Access-Control-Allow-Origin" header to "http://toads.co" so my social media icons wouldn't be missing when viewed from toads.co. Initially I wasn't sure how to do that, since all static content is served automatically by Express's static middleware. This is the only middleware that is still "built-in" to Express, but it is really just a wrapper for the serve-static module.

To add a certain response header to only some files, I had to supply a setHeaders function when I set up the middleware.

app.use(express.static("public", {
    "setHeaders": function(res, path, stat) {
        if (path.match(/\.(ttf|ttc|otf|eot|woff|font.css|css)$/)) {
            res.setHeader("Access-Control-Allow-Origin", "http://toads.co");
        }
    }
}));

Personally, I think the name of the function is a little misleading. While the intention is certainly to give you a place to set headers, you can pretty much do whatever you want inside. You get access to the response object, the path of the request, and the file stat for the file at that path. There's a small caveat - because the function doesn't return anything, you can't really make any asynchronous calls that defer any processing. You have to do whatever you need to do synchronously. Set the headers you need to set and move on.

My method simply checks to see if the requested file ends with one of the font extensions, and if it does the special header gets set.

I set out to do something that I thought would be simple, and ended up learning something new. Not a bad deal. I hope those frogs got as good of a deal at their new jobs...

Amphibian.com comic for 21 January 2015

Monday, January 19, 2015

Do Crazy Perks Attract Crazy Employees?

At my job we get two perks in addition to our salaries. One, we get free coffee. And two, we get the privilege of working there.
I Love Free Coffee!
Photo by Nevit Dilmen

Once I worked for a guy who constantly reminded us that he shouldn't even really be paying us. We were learning so much from him, he said, that we should have been paying him to work there. I guess since he couldn't find people to take him up on that offer, he had to resort to paying me.

Needless to say, I'm really not accustomed to the crazy perks people get while working for Google or other trendy and cool software companies.

Still, looking at the list of benefits Silicon Valley software companies are offering makes me jealous at times. Free lunches. On-site barber shop. Massages on demand. Free dry cleaning. Free bus to work with on-board WiFi. Almost makes me wish I went to a better university so I'd have a chance at employment with one of those companies. I guess I'd have to be really smart too. And an amazing software engineer. Oh well...

The cynical side of me wonders if the companies really offer those perks because they want to make their employees so totally dependent on them that they can never quit. If you always get your hair cut at the Google barber and get all your laundry done at work, you seem pretty dependent on your employer for more than just your paycheck. The line between home and work is blurry. Your whole identity is wrapped up in the company for which you work. Could be dangerous.

But I don't have to worry about any of that. Perks are overrated. I don't have to pay my employer rent for my cubicle space, so I'm happy.

Amphibian.com comic for 19 January 2015