Aside

I saw this on my twitter stream: http://www.ismytwitterpasswordsecure.com/

After a good laugh, it came back to me that passwords are pretty crummy. Then an idea struck – wouldn’t it be great if there was no password?

Humour me. Let’s say for example you want to sign up for Twitter. You click “sign up” and you pick your twitter handle, give them some personal information, follow a few people (this wasn’t required when I started, but apparently now it is). And then you are done. No password to enter, no password to remember.

When you visit the twitter page, you are signed in. When you log out, your browser asks you whether you want to sign in.

Not talking about an external service. Imagine a webpage doing something like :

if (navigator.hasCredentials)
{
        issueAPOSTRequest(navigator.username,
                          navigator.password);
}

or

var password = navigator.createPassword();
setHiddenPasswordInput(password);

There are some caveats. Accessing multiple accounts might be trickey. Also sharing your browser might not be a great idea. API obviously not final, nor well thought out, nor given any security considerations. This idea is in draft only and may never be implemented. There is no warranty of any kind, neither expressed nor implied…

Show more!

One of the issues I hit on beatsearch is that on the Artist page, some artists have long biographies. Really long.

Screenshot of an artist's bio that rambles on

This actually exposes two bugs. The first being the lack of line breaks. The second being, I don’t want to show that much text. This post is about the latter.

There are many different solutions to this rather common problem. Most implementations will stop after a certain number of characters and provide a link for more. I wanted to do something a bit different and instead stop after a certain number of lines. 3 lines to be exact. Oh, and this has to work regardless of whether you are on a mobile device or on a big monitor.

Fun! Especially when it has to work across multiple browsers!

This was actually pretty easy to do. The line-height CSS property was used to figure out the height:

// #biography is the HTML paragraph tag that contains
// the artist's biography
$('#biography').css('line-height');
// 22.4px

Great! Now I can set the height of the paragraph to 3* the line height

$('#biography').css('height', parseFloat("22.4px") * 3);

And cause text that goes beyond that height to be hidden:

$('#biography').css('overflow', 'hidden');

Which gives you this result:

The first 3 lines of an artist's biography shown

Lastly we have to put in a link in the bottom-right corner so that the user can view the full biography if they wish. This is pretty simple as well thanks to absolute positioning. We can make the biography element relative, which makes it a containing block, and inside the biography element put in an absolute positioned tag. You can read more about containing block and positioning from this helpful w3c article.

$('#biography').css('position', 'relative');
// Insert a span tag
var span = $("<span></span>")
           .text('show more')
           .css('position', 'absolute')
           .css('bottom', "0px")
           .css('right', '0px')
           .css('background', 'white');
$('#biography').append(span);

The code should be fairly self-explanatory. We position the text 0 pixels from the right and bottom. We need to set the background colour to white so that we don’t show overlapping text to the user. This is probably the one thing I don’t like about this method is setting the background color.

The big benefit over cutting off after x number of characters is that it works regardless of the width of the biography. On a desktop maybe 70 words can fit in 3 lines but on a mobile only 30 words.

Things are a little complicated in Internet Explorer because line-height may not return the height in pixels but rather a unitless number. This is completely valid, just not very helpful. You can get an idea of how to solve it by viewing the fix.

Last thing to do is to set a click handler to that span that removes the span and removes the styles we added to the biography element. But I’ll leave that as an exercise to the user.

Beatsearch

A few weeks ago I needed an escape project to get my mind off some things, and then I remembered something I could do. A while back I worked on an HTML5 version of Beatport.com. While I didn’t finish a bunch of things I had planned for it, one area that it does excel over the official site is that it loaded much faster so it was more pleasant to search.

Since then, Beatport’s public API has CORS support, which means I can completely remove the server side component and implement it entire in JavaScript and web technologies!

I got to work with a bunch of neat technologies in the process. Most of which I already knew :

  • Foundation CSS framework. The site looks pretty snazzy in mobile as well, but it’s not mobile friendly. More on that later
  • Mustache.js
  • underscore.js and jQuery. Though there is a lot of overlap, and most of the utilities I used in underscore are available in jQuery as well.
  • require.js
  • q.js

I learned a bunch of small things. Such as:

  • Foundation was pretty painless. A weird feature of its grid system (they wrote CSS for this, so it’s likely not a bug) is that two rows in succession causes the inner row to go outside the bounds of the parent row. For example:
    <div class=row>
        <div class=row>
            This row's left and right width will be 15px larger than it's parent.
        </div>
    </div>
    
  • I found myself fighting with mustache.js. It’s logic-less (mostly) but that presents a number of limitations that you have to hack around. Tom is smarter than me
  • Micro-templating! Putting large amount of HTML in your JavaScript felt wrong. Another idea I thought of was to move the HTML to a separate file and load it using AJAX, but micro-templating was just a better idea
  • Foundation is awesome. Just a reminder. I don’t think it’s that much different than bootstrap, but these CSS frameworks are the best thing since sliced bread
  • underscore was ok, but found most of the functionality present in jQuery. One annoying aspect of underscore is that they don’t support require.js AMD support. It was an easy fix however
  • Having a separate development/production version of javascript/css files I found to be a mess that I don’t think anyone has solved yet – at least for client-side only code. I took a stab at it by having a bash script make symbolic links, but it has shortcomings that doesn’t really work very well.
  • While the foundation framework makes it a breeze to create a fluid responsive design, beatsearch is a fairly image heavy site so there are lots and lots of requests. It’s not optimized for high latency connections. Maybe if it’s worth the effort, having a placeholder image could be done instead and the phone will just hit the cache.
  • I didn’t plan for this but it was too tempting not to, but I ended up using jplayer to play beatport’s sample audio files. It was really easy to use, and now I can play tracks! Not able to set-up playlists yet, but that’s a future option.

Hold crap you made it this far. Might as well check beatsearch out.

Ending support for Safe 1.1.2

My safe extension hasn’t changed much for several months. It’s been happy doing it’s thing and AMO has been happy bumping compatibility updates.

Why would I want to interfere with such a perfect system?

One thing that has impressed me about Firebug is that it is a restartless add-on. It is not anything new. But the ease of installing/uninstalling is just wonderful. If Firebug can do it, Safe should also be able to do it.

After a few days worth of work, I finally have Safe 2.0.0 working as a restartless add-on. Great. The next question is – what Firefox version is it compatible with?

The obvious answer was, of course, whatever version I was using. In theory, I could test with all versions of Firefox until Firefox 4 when restartless add-ons was available. But I don’t have that kind of time.

Then I realized during this rewrite (it was a fair amount of work to make an extension restartless) that I used a bunch of relatively new features that was released in Firefox 10. I could do the appropriate workarounds but do I really have to?

I went to my add-ons statistics dashboard and found that about 78% of my users were using the latest release of Firefox. If I go back 2 additional release versions, that increases to ~85%. There is a really long tail here…

My extension is also available for SeaMonkey, for which I only have between 0-3 users :( I haven’t tested my code with SeaMonkey, but if it’s cheap to support than I rather support it because SeaMonkey is great browser.

So it looks like my time is best spent checking that my extension works for the latest release of Firefox on Windows/Linux and Mac if I had it. I am really glad I took a step back and evaluated the best decision rather than falling into my usual trap of mismanaging time/effort.

JavaScript funk

There are two reasons why I hate reading other people’s code:

  1. Their code is so much prettier and better organized than mine
  2. It sometimes leaves my head scratching

While reading about restart-less add-ons so I can make my safe add-on be restartless as well, I came across some example code by Edward Lee that looked like this:

const {classes: Cc, interfaces: Ci, manager: Cm, utils: Cu} = Components;

When writing Firefox extensions, by convention Cc and Ci are shortcuts to Components.classes and Components.interfaces. I was able to piece together what it was tring to do (eventually), but I could not understand why this was working.

In my feeble attempt I looked up ECMA-262 which I think provides the answer but I am not so sure. The SpiderMonkey JavaScript engine seems to be the only one that supports this syntax as well as some examples below. Running these examples produced a syntax error in Chakra on IE and V8 on Chrome using the developer tools.

Here is some other fun things I found:

let [ a, b, c ] = [ 1, 2, 3 ];
c; // 3

It is similar to how you can do multiple assignments in python. :

a,b,c = [ 1, 2, 3 ];
c; // 3

This is a neat shortcut to get variables pointing to some function

let { abs } = Math;
abs(-5); // 5

And going back to Edward’s code, we can assign a different variable name to the function.

let { abs : a } = Math;
a(-14.2); // 14.2

Still wondering whether this a SpiderMonkey (and therefore only Firefox/Seamonkey) extension or whether other JavaScript implementations will support this someday as well.

Q

A number of months ago someone told me about Q which is an implementation of the promises framework. I did not understand the problems it was trying to solve at the time, so I never bothered going to deep into it.

My good friend Tom mentioned promises and when.js during our normal chats which I misheard as WinJS (another promises javascript library, but only available for Windows Store apps). when.js seems like a node thing and not really for a web page (by that I mean it’s multiple files, which is a bit odd for a JavaScript library). If you don’t know what promises are, I suggest visiting other literature that will do a much better job than I to explain it.

So I went back to Q but I still had the problem I had before. The documentation is very weird to me as it starts going into what promises can do but doesn’t explain how to actually make a promise until half-way into the documentation. It’s amazing how well one simple when.js example goes into explaining how promises work. Q eventually does put the pieces together, but the non-sequential structure doesn’t work well for me and I got frustrated.

So here is an example I would use to explain promises. I got a bit all over the place, but that’s because I was trying to get the basics down to one sample

Debug Console:

This message appears first
Max Power blah blah
true
Hello World!

Aside

A few weeks ago, Qu33riousity has blogged about starting a new job that was littered with racism and douchebaggery. He gave me the impression that this was widespread in San Francisco’s start-ups, but I am not certain since the blog post has been taken down as a lawsuit is apparently in the works, but businessinsider has some screenshots and paraphrased much of the post. The blogger did not mention the company by name, but did post an advertising poster which people suspected was Kixeye, and it was confirmed since. When I looked up Kixeye, I saw one of their games – Battle Pirates. Why does that sound so familiar…. oh right, their shitty advertising. I guess it works.

Django generic views

When I first started using Django, requests were handled by functions. This has changed somewhat recently and now the new hip way is to use generic views. I decided to make a blog post on this topic because I found the documentation a bit difficult to digest. The documentation is available here but I found looking at the source and this stackoverflow response to be a big help.

Generic views are useful because we often employ the same pattern when we try a create/update/view an object. We often display a new object, do validation, and save it. Generic views automatically do object validation/CRUD but at the same time flexible enough that you over-ride certain parts of the process if you need to.

My sample program is one where I have users and users are engaged in many activities (watching a movie for example), but a user can provide additional details about themselves (only after 19:00) and have an expiry date (because they have other things to do). First we start off with our models:

Here is the forms. I don’t want the user to decide when they expire. I am arbitrarily deciding that a user expires in 3 hours. Here I decide to overload the save method of the form.

I have to be careful not to extend the expiration date when the User object gets updated, so I check whether the pk object is set.

Next is the views. The views are pretty simple. I set the template, form (or model in some cases), and the success url. Validation and saving is already done for me. I overload the post method of the CreateView function so I can save the user’s id in their session.

By default, the object form will be available in the template. For ListView, the objects will be exposed as a list called object_list.

One question you might ask yourself is how the EditView knows which object to edit. It actually passed to the get() method using the pk keyword argument. You have to specify this parameter in the urls.py file:

Now going to /edit/1 will modify the object with primary key of 1

Generic views are definitely more customizable than what I am presenting, but it’s out of scope for this post. This was just an intro to Create/View/Update/Delete a fairly simple object.

Task management

A few days ago I was searching for programs to keep track of a todo list that I was tired of trying to remember. This one program caught my eye – iKog. Mainly because it’s a command-line app and thought “this looks like a good novelty” and tried it out.

It was ok, kinda neat I suppose. It needed some configuration because it does something awful with your data that makes the program an unwise choice to install globally by default.

Remember the Milk

A number of years ago Remember The Milk was this new hip thing because it used some (at the time) new technologies to save your items offline and resync once you went online (using Google Gears, which has since been discontinued and they are in the process of moving that to offline storage). It’s an task management website, as you might have guessed.

It has by far more features and more flexibility, and your data is online and can be accessed anywhere. It many ways it is the superior choice.

Does it surprise anyone that I went with the command-line tool?

I wrote down 1 to-do item on RTM and thought “this is nice, but I’ll never use this again”.

It’s not that it’s not good, but that it’s stuck in the paradigm of the web. I will need it to be in a tab, or in another window, and it will rarely be in my face saying “hey idiot, you have shit to do”. It will be forgotten in a sea of tabs and windows and possibly in a panorama group. Integration is key to a todo list – I need easy access and it needs to be just there.

Contrast that to the command-line tool that next to my mutt e-mail client and IRC client on a split-screen terminal. I am constantly reminded that I should stop wasting time and get back to do something productive because I check e-mail and IRC on a regular basis.

RTM also has apps. I may eventually go back to RTM if I find iKog to be insufficient and the RTM’s apps solve my needs. There might be a lesson here about web applications being unable to truly compete with desktop software, but I’m not learning it at this late at night.

*yawn*