web design – Terminally Incoherent http://www.terminally-incoherent.com/blog I will not fix your computer. Wed, 05 Jan 2022 03:54:09 +0000 en-US hourly 1 https://wordpress.org/?v=4.7.26 Zero Effort Link Minification with WordPress http://www.terminally-incoherent.com/blog/2015/02/17/zero-effort-link-minification-with-wordpress/ http://www.terminally-incoherent.com/blog/2015/02/17/zero-effort-link-minification-with-wordpress/#comments Tue, 17 Feb 2015 16:40:45 +0000 http://www.terminally-incoherent.com/blog/?p=18331 Continue reading ]]> If you have ever linked to my blog, you might have noticed that my URL’s are absolutely monstrous in size. Not only is my long domain name rather long, but I also happen to use the “pretty” style of permalinks which includes full date and abbreviated post title.

There is of course nothing wrong with either of these things. Long domains may not easy to type but they can be memorable. Most people don’t even use the address box in their web browser (which used to drive me nuts until I learned to just accept it). These days it is all about on fuzzy search in Google so as long as someone can manage to type in something close to termanotely incaharet somewhere, they will find my blog.

Similarly, long permalinks are actually useful due to their descriptive nature. I like to be able to glance at a link and not only know what it is about, but also how long ago it might have been posted. I would not want to get rid of an useful feature like that.

That said, my links are just super long. Take this one for example:

http://www.terminally-incoherent.com/blog/2015/01/19/utility-spells-in -video-games/

It is an absolute beast, and I would love to have the option to shorten it when I post it on social media for example. Yes, Twitter does minify links by default but the truncated URL still looks quite ugly in your tweets.

I could use a third party minifier such as bit.ly or goo.gl but that is never a good idea. Not only does it obfuscate the links, but it also sets them up for possible breakage in the future when said 3rd party services shut down which is not uncommon. I have seen quite a few of them appear and go under in just last few years, and being backed by a big company does not seem to help. Google might not be going anywhere anytime soon, but they shut down their services all the time. Personally, I got burned twice with them. First time with Google Notebook (an Evernote precursor), and the second time with Google Reader. URL’s are supposed to be forever so I wouldn’t feel comfortable using any service that is not under my control. Ideally I would want to use my own domain for minification of links.

I noticed that WordPress already does support shortened links in a way. If you have permalinks enabled (and you should), WordPress calls your standard, long and “pretty” links the cannonical URL’s. However it also provides a so called shortlink for each post. You can see it shown in the post header on most themes:


The shortlink format is actually the default style of WordPress URL’s you get if you can’t be bothered (or you are unable) to set up permalinks. It acts as a fallback, and allows you to access blog posts by their internal database ID even if the permalinks are not working correctly.

So if I wanted to, I could link to my posts using the shortlink format like this:

http://www.terminally-incoherent.com/blog/?p=18242

If you have a short domain name, this might be enough for you. Mine is still too long, and I absolutely hate parameters in the URL. IMHO, it looks unprofessional. However, knowing that this format exists allows you to shorten and prettify it using Apache redirects. For example, I could put the following line in my .htaccess file:

RedirectMatch ^/(\b\d+\b)/?$ /blog/?p=$1

This matches any URL that contains only numerical digits followed by an optional trailing slash, and seamlessly redirects them to the shortlink style URL format. This rule allows me to use something like:

terminally-incoherent.com/18242

Because of the way WordPress handles shortlinks, users who follow the link above won’t actually see it in the address box when the page loads. Instead WordPress will automatically unfold it to the “pretty” permalink format, which is exactly what I want.

This is a huge improvement. Still to long though.

To compress my addresses even further I purchased a brand domain: tein.co Unfortunately ti.co and in.co were already taken so this is the next best thing I could think of. It’s not pronounceable, but it is short, and visually similar to my long domain.

All that was left was to set the new domain to “web forward” to my actual blog URL and I was all set. I use iwantmyname as my registrar and it took literally 60 seconds to set it up:

Web Forwarding

Web Forwarding

From there it worked pretty seamlessly. If you are feeling lazy and you don’t want to type in my full web address you can now simply use tein.co. Similarly, every post now has a genuine short link (displayed under post title) in the format:

tein.co/18242

Because the entire thing is implemented via 301 redirects, if you post one of these short links on Twitter you will still get that sweet Twitter Card action.

So there you have it. Zero effort link minification using built in WordPress addressing scheme and a single Apache redirect statement.

]]>
http://www.terminally-incoherent.com/blog/2015/02/17/zero-effort-link-minification-with-wordpress/feed/ 3
Make Your Web Forms Time Lord Friendly http://www.terminally-incoherent.com/blog/2014/10/13/make-your-web-forms-time-lord-friendly/ http://www.terminally-incoherent.com/blog/2014/10/13/make-your-web-forms-time-lord-friendly/#comments Mon, 13 Oct 2014 14:09:23 +0000 http://www.terminally-incoherent.com/blog/?p=17909 Continue reading ]]> This was a conversation rolling through my Twitter feed lately: how do we design good web service signup form? One that is unobtrusive, intuitive and inclusive. How many fields do you need? What is the best way to arrange them? What kind of questions are important to ask your users? Turns out that there is a lot of disagreement on this, and a lot of misinformation and false myths floating around.

For example, is this a good sign up form?

Facebook Signup Form

Facebook Signup Form as of Oct 2014.

I would argue that it is not great. In my opinion splitting the users name is absolutely pointless. Even, assuming your service needs to use the legal names of your customers (which 99.9% of web services do not “need” to do, they just choose to do so because of reasons) you really only need a single field. This is not a very popular opinion, and a lot of programmers are very, very defensive of their first name/last name split.

I get it, though. I too was taught the mantra of “always be normalizing” when it comes to a database scheme design. The software engineer in me wants (even needs) to have human identity split into two or more clearly labeled forms so that it can be properly sorted. But, asking for first and last name does not work for everyone. As soon as you normalize this way, you are automatically starting to exclude swaths of users whose names do not conform to the particular pattern you chose.

You probably heard of this little factoid: in some cultures you list your family name first, and your given name last. That alone should give you a pause, and make you re-consider using a two field strategy. Some people think that simply labeling the fields as “given” and “family” instead of “first” and “last” will do the trick. I also saw a developer claiming that his app is going to be primarily used by English speaking Americans so it does not matter. But that’s wrong too, because even in that narrow demographic you are going to have a number of people whose names do not fit into the first/last pattern. You want examples? How about Madonna, Eminem, Pink, Xzibit, Nelly, Sinbad, Rihanna, Kesha, Mr. T, Lady Gaga or “The Artist Formerly Known as Prince”. There is a strong history of performers adopting mononyms or stage names which either become their legal names, or at the very least are more publicly recognizable than their birth names.

The fact that I could rattle a dozen names of the top of my head, all of which belong to prominent and recognizable celebrities is a proof that this practice is very much part of western culture. Mononyms and funky stage names are as American as apple pie. So you can’t really use “culture” to defend the over-normalization of the name field, when your own culture has a large group of very prominent outliers.

People make a lot of assumptions as to how people’s names work, but all of them are false. Yes, all of them. The single, uniform field for name is not just something I pulled out of my ass for the purpose of this article. It is actually the best practice recommended by W3C.

Same goes for sex. Why does Facebook think it is necessary to ask its users what kind of genitals they have? I can see how this could be a valuable data point for a dating service, since people use those specifically to facilitate mutual mashing of genitals together. So it makes sense to let people sort and filter potential future romantic partners based on their sex and gender preferences in addition to other criteria. Facebook however, like most social and anti-social web apps in existence has virtually no business to ask this question.

Don’t even try to sell me on “demographics” and “advertising” argument because it is bullshit, at least with respect to Facebook since they track your behavior and browsing habits anyone. There is nothing your sex tells their advertisers that they could not get from analyzing your posts, likes and social graph interactions. In fact, the tracking data is more valuable and more accurate way to target advertising than an empty data point that designates you as “man” or “woman”.

Also, why is it a strict binary choice? I mean, unless you’re building something like Christian Mingle type service (where religious dogma only allows you to recognize an arbitrarily chosen set of genders and appropriate parings), why would you want to wantonly ignore biology? If you are going to ask this question (and you have no business doing so in the first place), why not ask it the right way?

Is the Facebook form asking for sex, or gender? Because I honestly can’t tell? This is an important question to ask because Facebook has weird “real name” policies that could result in the suspension of your account if their support staff determines you “lied” on this question. So what do you put down biological sex does not match the gender you identify with? What if you don’t identify neither as male nor as female?

I think Twitter does this right:

Twitter Signup Form

Twitter Signup Form as of Oct 2014.

A single field for “full name” and no unnecessary questions about sex and gender. This is how it should be.

My personal rule of thumb for designing web forms: make them Time Lord friendly. Whenever you want to add or normalize a field, think how the protagonist of BBC’s Doctor Who series would fill it out. Your form should allow one to use The Doctor as the single and only personal identifier.

  • The Doctor does not have a first name
  • The Doctor does not have a last name
  • The Doctor does not have a middle name or middle initial
  • The Doctor does not have a set of initials based on name
  • The Doctor is not a given name
  • The Doctor does not have a family name
  • The Doctor does not use a honorific – it’s just The Doctor
  • No, you can not abbreviate Doctor as Dr. or anything else
  • The Doctor does not have a short name or nickname. You address him as Doctor
  • You can’t use Doctor’s date of birth to calculate age because he is a time traveler
  • The Doctor’s age won’t fit in your two-digit age field
  • The Doctor’s does not have a fixed height, eye color, hair color, etc..
  • The Doctor does not have a fixed ethnicity or skin color
  • The Doctor does not have a fixed gender

If you keep these things in mind you can avoid common pitfalls of web form design and build signup forms that are not only intuitive but also maximally inclusive.

]]>
http://www.terminally-incoherent.com/blog/2014/10/13/make-your-web-forms-time-lord-friendly/feed/ 4
The Beauty of HTML5 http://www.terminally-incoherent.com/blog/2013/03/27/the-beauty-of-html5/ http://www.terminally-incoherent.com/blog/2013/03/27/the-beauty-of-html5/#comments Wed, 27 Mar 2013 14:08:27 +0000 http://www.terminally-incoherent.com/blog/?p=14117 Continue reading ]]> If you are still using HTML4 for your new websites you should stop probably stop. And I’m not saying this because of standards compliance, or some sort of web snobbery. I’m saying this because it is a pragmatic thing to do. HTML5 is just a better standard – and not just because of the fun features you see in the online demos.

While the canvas stuff, the local storage and embedding native video is really cool, I think the biggest improvement HTML5 has on it’s predecessors is the new semantic tags you can use to organize your content.

W3C actually studied how modern websites are designed, and saw that most HTML4 content follows a similar pattern. Here is an example of a very basic HTML4 Strict web page skeleton I just threw up in five minutes. It could be start of a blog template for example:



    
        
        
        
        
        
    
    
        

        

Post Title

Lorem ipsum dolor sit amet...

Posted on March 20, 2013

Note the structural elements in the body of the page. We have a document header on top, a page footer on bottom and a big content div in the middle. Inside said content div we will commonly have “post” or “article” divs, which contain more structural elements: post heading, post content, post metadata.

All of this is accomplished via the magic of the all purpose div and span tags. This works well, and is actually what you are supposed to do in HTML4 but it gives you messy code. You are mostly using id and class attributes to give shape to your structure, and the unfortunately they are only visible on the opening tag. It is not uncommon to see websites which include snippets like this:

           
       
     
 

Or rather it is common to see something like this if you wrote the code yourself, of are working with good guy web designer. Chances are you will probably see something more like this in the code you inherit from other people:

    
       

Because, you know – someone broke the layout and just started closing div tags on the bottom until things stopped being broken. This is not as much of a problem as it is an aesthetic mess.

Not to mention that while everyone seems to follow this header/footer, content, articles type layout there are no rules on how you should implement it. We all just make up our id and class names. For example, navigation section can be called “nav”, “navigation”, “site-links”, “sidebar”, “menu”, “buttons” or just about anything. The main content area may have an id that says “main”, “content” or maybe even “content-area”.

When you are reading a CSS file for a HTML4 page you have to guess whether or not a rule using the #foot selector is referring to page footer, post footer or maybe something else entirely.

HTML5 more or less makes that sort of messiness go away. Observe the same skeleton written in proper HTML5. Can you spot the difference:



    
        
        
        
        
    
    
        

Welcome

Post Title

Lorem ipsum dolor sit amet...

Posted on

1 St, Exampletown, NY

Note how this example drastically cuts down the number of id and class attributes, instead relying on semantically meaningful tags. Everything always has headers and footers and now we have tags designed specifically for that. Blogs and news pages always need to box in and contain blocks of info into visually separate units, and now they can do that using the <article> and <section> tags. Navigation sidebars and pull-down menus are a web staple and they are now standardized as <nav> and <menu> respectively.

Hell, HTML 5.01 even introduces a <main> tag to replace the ubiquitous and ever-present <div id=”main”>.

The CSS you write will actually benefit from these changes. Let me give you an example of how I would probably write the stylesheet for my HTML4 example:

#header {}
#post {}
.heading {}
.metadata {}
.date {}
#footer {}
.address {}

Essentially its a mess of selectors on id and class attributes. Note how I didn’t even bother to try narrowing down my selectors. For example, the smart thing to do would be to use a #post .heading selector for my post headings as it would both improve readability of the CSS and ensure that this particular rule will only get applied within the post body. But… I’m lazy, and I know that I won’t use the .heading class anywhere else so I won’t bother. This will likely create some headaches down the road, but who the fuck cares, right?

Compare this to the selectors I would write for my HTML5 example. Note how now that I got rid of the id and class attributes I actually have to explicitly specify parent-child relationships and how this improves readability?

header {}
article {}
article header {}
article footer {}
article footer time {}
footer {}
footer address {}

I can glance at this and know that the styles from article are going to cascade down to article footer. There was no easy way of establishing that sort of relationship between #post and .metadata in the previous stylesheet because I was lazy and I didn’t bother.

This is what HTML5 brings to the table: improved readability of code and CSS, meaningful semantic tags and better, more intuitive ways of structuring your pages.

]]>
http://www.terminally-incoherent.com/blog/2013/03/27/the-beauty-of-html5/feed/ 2
Building your first Jekyll site in 5 minutes http://www.terminally-incoherent.com/blog/2012/01/25/building-your-first-jekyll-site-in-5-minutes/ http://www.terminally-incoherent.com/blog/2012/01/25/building-your-first-jekyll-site-in-5-minutes/#comments Wed, 25 Jan 2012 15:39:16 +0000 http://www.terminally-incoherent.com/blog/?p=11160 Continue reading ]]> Back in December, I wrote a short post about building websites without server side includes. I used AJAX and magical hasbang url’s to get around the fact that the hosting space I was given on the university servers did not support any kind of scripting. I basically outsourced my scripting to the client side – it happens dynamically in the browser. Unfortunately, my solution lacks in accessibility. It’s still possible to navigate my site without JavaScript but the experience is diminished.

There is alternate way to do this. A proper way if you will – one that still allows you to keep your design templates separate from your data, but one which will produce great looking static html sites with no scripting required. One that moves the heavy lifting (includes, imports, processing, etc..) from run time, to compile time.

Let’s think about this for a second – the main reason we use server side (or client side like in my example) scripting for web design is so that we don’t have to copy and paste the same headers, footers, and css references into every single html file. We design a great looking template, with blank holes. Then at run time, we use some magic to import content into these holes to generate “nice” HTML files that are then served to the user. There is technically no reason why we couldn’t do all that importing and generating at the design stage though. We could easily pre-process our page just before deployment, and then upload only the resulting static HTML to the server. Granted, this is not going to work for pages that accept and process user input. But it is fine for a simple home page, or a blog. All you need is a good pre-processing tool.

That tool is Jekyll.

What the hell is Jekyll, you ask?

Jekyll is a nifty little Ruby gem, that will take your template pages, your content data and transform them into a set of static HTML files that can be deployed anywhere. In other words, it is a “website compiler”.

How does it work, you ask?

Do you really want to know the details? Do you care? Here is the source code. Go enlighten yourself. Everyone else, here is the functional explanation:

  1. You make a folder
  2. In that folder you put some files
  3. You run Jekyll
  4. A static HTML website pops out in _site directory

That’s about as complicated it gets. The main problem with Jekyll is step #2. Understanding what files to put and where, requires you to essentially RTFM and actually understand how the damn thing works. Who the hell one wants to do that, though? Similarly, most online tutorials I have seen dive in too deep, and try to show you how to create a functional site right away and it quickly becomes overwhelming. I’m not going to do that. I will show you how to create a very shitty, basic website in five minutes. A “Hello World” of Jekyll if you will.

First let’s grab Jekyll and prerequisites. Some of these are native extensions that have to be actually compiled on your system. This will be done automatically by the installer, but not all systems have the required compilers and header files. So first thing you want to do is to install the Ruby Dev Kit. If you are on Debian/Ubunty system you can just do:

sudo apt-get install ruby1.8-dev

If you are on Windows, grab the DevKit 7z file from the Ruby Installer website and then unzip it somewhere easy to find (eg. C:\RubyDevKit). Once you do that, here is how you install it:

cd \RubyDevKit
ruby dk.rb init
ruby dk.rb install

What does this do? It patches your Ruby installation, but honestly – we don’t care. It makes installation of Jekyll work. If you are inquisitive, you can read about the installation process here. Once you satisfied your curiosity, run the following command:

gem install jekyll

It will download and install Jekyll and all the prerequisites. Just so that we are clear, we are not counting the installation time into the 5 minutes time limit. If you want to time yourself, start your stopwatch now.

Let’s create a new directory for our website and call it mypage. Inside of that directory we create bunch of sub-directories like this:

mkdir mypage
cd mypage
touch _config.yml
mkdir _layouts
mkdir _posts
mkdir _site

Jekyll actually expects this folder structure to be present when you run it. The _layouts is where we are gonna put our template files – you know, HTML with holes in it. _posts is where we dump our content files – for example individual blog posts. _site is where Jekyll will dump out our “compiled” site. Easy enough so far, right?

Let’s make templates:

cd _layouts/
vim default.html

This file is going to be our main template with nice headers, footers, navigation sidebar and etc. Or rather would be, but we only have 5 minutes so instead I will make it this:

    
    
	    My Jekyll Test
    
    
	    {{ content }}
    
    

The {{ content }} tag is what tells Jekyll to create a hole in the layout that will be later populated by some content. Namely, by the stuff from your _posts directory. When you pull that data in, you sometimes will want to style it to your liking. Put it in a div, give it a nice heading, perhaps stick a creation date somewhere, etc. So let’s create another template for individual posts:

vim post.html

The contents are as follows:

    ---
    layout: default
    ---

    

{{ page.title }}

{{ content }}

The bizarre thing up top is so called YAML Front Matter. Jekyll will rip it off, and use it to figure out what to do with this file. Here we are basically saying “use the default template”. When you compile, Jekyll will take this and stick it into the “content hole” on the default template. Note that the post template has two “holes” of it’s own that will be populated by an actual content page which we are going to create next:

cd ..
cd _posts/
vim 2012-01-18-hello.markdown

There are two points of interests here:

  1. The file name must start with a date in a YYYY-MM-DD format followed by a title. This is how you tell Jekyll when this post was published. It’s like that by design, to make processing fast and simple. Don’t question it. Just do it.
  2. Yes, this is a markdown file. You can also use Textile, or plain HTML. It’s up to you. Jekyll is fine with either one of these. Using a non HTML markup language makes content creation slightly more streamlined as it really helps to separate content from presentation.

Here are the contents of my file:

    ---
    layout: post
    title: Hello
    ---

    Hello World!

Once again, we have some Front Matter up top. It tells Jekyll that what follows is to be wrapped up into the post template (which will then be wrapped up in default template) and allows you to specify an optional title attribute. If you scroll up to our post.html snippet, you will see this attribute accessed via {{ post.title }}. Neat, eh?

We are almost done. The last thing we need is a landing page:

cd ..
vim index.html

This is essentially going to be the “hello, welcome to my page” type thing. It’s up to you what you put here, but for the sake of simplicity I decided to make my front page to be an itemized list of all the published posts:

    ---
    layout: default
    title: Home
    ---

    
    {% for post in site.posts %}
  • {{ post.title }} ({{ post.date | date_to_string}})
  • {% endfor %}

This ought to be more or less self explanatory. If you can’t read a generic for loop notation then I really can’t help you here. The last thing you want to do is to compile:

jekyll

Yep, that’s all you need to do. Actually, I recommend running this instead:

jekyll --server

It will create a mini-server on your machine, that you can access by going to http://localhost:4000 and inspect your creation.

That’s it. That’s all there is to it. You now have a fully functional Jekyll site. Mess around with it. Add another file in the _posts directory and see how it is linked on the front page. Better yet, grab a free CSS template and use it as your default.html (after adding the {{content}} tag inside) for an instant, gorgeous looking web page.

If you want something that look at least semi-presentable out of the box, you can check out my Simple Jekyll Site layout on Github. It is a very, very basic two column layout with minimalistic design that lends itself to easy extension. It is already formatted as a Jekyll site so all you need to do is to tweak a few of the links and deploy.

Seasoned Jekyll users, have you any advice for those just starting with it? Any gotchas to look out for, or life saving tips? Let us know in the comments.

]]>
http://www.terminally-incoherent.com/blog/2012/01/25/building-your-first-jekyll-site-in-5-minutes/feed/ 5
I hate websites with light text on dark background http://www.terminally-incoherent.com/blog/2010/05/20/i-hate-websites-with-light-text-on-dark-background/ http://www.terminally-incoherent.com/blog/2010/05/20/i-hate-websites-with-light-text-on-dark-background/#comments Thu, 20 May 2010 14:05:44 +0000 http://www.terminally-incoherent.com/blog/?p=5761 Continue reading ]]> When you browse the web do you prefer websites which have light background and dark text or vice versa? I wrote about it some time ago and it seems to be a polarizing issue. Some people seem to prefer one over the other. My mini poll for example was essentially dead tied – almost even 50/50 split:

Dark on light wins by tiniest margin.

Personally, I can’t stand light on dark color schemes. Especially when it is small white-ish font on black or gray background and I’m trying to read it on my laptop. It is an eye straining, headache inducing torture. Not only that but it is also like staring into the sun. Try it – read a few paragraphs squinting at a light-on-dark design and then switch to a dark-on-light website. What happens? You see spots, as your eyes try to frantically re-adjust. Hell, I do one better: now you can experience this for yourself.

Do you see what I’m talking about here? Going from a dark background to a light one wrecks havoc with your eyes. It is unsettling. It usually takes me a second or two to adjust to the sudden change. Going the other way does not produce such side effects. Of course someone could say that as long as you stay on pages with dark background and light text you will be fine, and it’s the dark on light contrast what affects your eyes. Even if that is true, I feel that it takes me more effort to read the former rather than the later.

I decided to do some research regarding contrast and readability and found this interesting quote:

When revers­ing col­our out, eg white text on black, make sure you increase the lead­ing, track­ing and decrease your font-weight. This applies to all widths of Meas­ure. White text on a black back­ground is a higher con­trast to the oppos­ite, so the let­ter­forms need to be wider apart, lighter in weight and have more space between the lines.

Most people don’t actually do this when designing their inverted layouts. So I created another page, this time following these guidelines:

  1. Increased the font size
  2. Decreased font weight
  3. Increased letter spacing
  4. Picked a non-black background
  5. Used a non-white text

You can see the results here. I don’t know about you, but to me this is a vast improvement. The after effect is still there, but it is greatly diminished. The text itself however is much, much easier to read.

Which one do you prefer? The white on black or the cyan on gray (never mind my poor color choices – let’s talk readability)? I find it hard to believe that someone would prefer the former over latter. But I might be wrong.

When I stumble upon a particularly eye-straining light on dark page, I don’t just sit there and squint. After all, I’m viewing it in my own web browser. I can easily tell it to ignore the offending style sheet. Or better yet, I can use Greasemonkey or Stylish to automatically re-format the page in such a way that it does not offend my eyes. The downside of these methods is that they tend to offer site specific solutions. Recently I found something even better: the Readability bookmarklet.

If you haven’t tried it yet, please do. It is brilliant little script that allows you to pick how you want web page to appear on your screen – the font size, weight, light or dark background, margins and etc… It generates a bookmark that you can drag it to your browser toolbar. Once it’s there, you can just press it and see the web page you are viewing transformed fitting your exact specifications. Let me give you and example.

This:

Original Page

Into this:

Page you can actually read

I use this bookmarklet daily, and not just on websites that have a light on dark design. It works for just about every design issue. For example, if the font is to small, if the margins are to wide or if the design is to cluttered, I can fix it with a single mouse click. It is great.

]]>
http://www.terminally-incoherent.com/blog/2010/05/20/i-hate-websites-with-light-text-on-dark-background/feed/ 12
Repeating HTML Table Headers on Each Printed Page http://www.terminally-incoherent.com/blog/2009/10/12/repeating-html-table-headers-on-each-printed-page/ http://www.terminally-incoherent.com/blog/2009/10/12/repeating-html-table-headers-on-each-printed-page/#comments Mon, 12 Oct 2009 14:44:26 +0000 http://www.terminally-incoherent.com/blog/?p=3928 Continue reading ]]> Here is a neat HTML trick for printing HTML tables that most people don’t know about. Btw, designing your page to print well, is actually a joyless task full of insurmountable obstacles such as lack of any page break support in modern browsers. For example, how do you explain to your pointy haired manager that page break support is still pretty much badly broken in most modern browsers? It is usually is met with disbelief and questioning of your skills as a web monkey.

“Microsoft releasing a half assed product? I find that hard to believe, sir!”

Yeah, every time I hear that sentence uttered in a serious, self righteous tone without even a hint of irony I must fight to keep my face straight.

Anyways, if you do need to print HTML tables here is a little hint. You know how a table will usually have headings on the first page, and then no heading on subsequent ones, forcing you to flip back and forward to see which column is what? Well, you can actually make most browsers to repeat your headings on each printed page using the method below.

First, you have to explicitly define the table head and table body:



      . . .

      
First Heading Second Heading Third Heading
foo bar baz
fim fam fom

Yeah, I know that most browsers can do this automatically, but if you want printing to work, you need to have an explicit declaration. Next, you just need a single line of CSS to get things going:

@media print {
   thead {display: table-header-group;}
}

That’s it. This will force most browsers to repeat the contents of thead node on every printed page. Having discovered this myself somewhat recently, I keep being amazed how many online applications don’t actually do this. Even commercial web suites whose only purpose is to generate long HTML reports often fail to implement this properly. As a consolation they offer you features that will export the reports to PDF or Excel formats, but they never even try to make the HTML version more accessible.

]]>
http://www.terminally-incoherent.com/blog/2009/10/12/repeating-html-table-headers-on-each-printed-page/feed/ 35
jQuery: Grid like table with keyboard navigation http://www.terminally-incoherent.com/blog/2009/10/08/jquery-grid-like-table-with-keyboard-navigation/ http://www.terminally-incoherent.com/blog/2009/10/08/jquery-grid-like-table-with-keyboard-navigation/#comments Thu, 08 Oct 2009 14:35:38 +0000 http://www.terminally-incoherent.com/blog/?p=3900 Continue reading ]]> Guess what time is it kids? It’s time for yet another boring, technical post. It’s that sort of week. Or rather it was – I usually queue my posts approximately 8-10 days in advance. This means that if I get hit by a bus one day, you won’t know anything is wrong until a week or so later. But I digress…

One of the web apps I maintain has a big table that looks like this:



	. . .
	. . .
	. . .

	

Basically, every cell contains an input box. Each of them has an onChange trigger which will submit it’s contents to the database via AJAX call. It basically allows the user to pull up a full page of records and edit them en masse without doing a lot of clicking.

Unfortunately this setup is a pain in the ass to navigate. Tabbing over works fine but only in one direction. The most intuitive way to traverse such a structure would be with the arrow keys – you know, just like a big spreadsheet. Sadly it just doesn’t work that way. But we can make it work like that with just a pinch of jQuery magic:

$(document).ready(function() {
    $("input.flat").keypress( function (e) {
        switch(e.keyCode)
        {
            // left arrow
            case 37:
                $(this).parent()
                        .prev()
                        .children("input.flat")
                        .focus();
                break;
			
            // right arrow
            case 39:
                $(this).parent()
                        .next()
                        .children("input.flat")
                        .focus();
                break;

            // up arrow
            case 40:
                $(this).parent()
                        .parent()
                        .next()
                        .children("td")
                        .children("input.flat[name="
                            +$(this).attr("name")+"]")
                        .focus();
                break;

            // down arrow
            case 38:
                $(this).parent()
                        .parent()
                        .prev()
                        .children("td")
                        .children("input.flat[name="
                            +$(this).attr("name")+"]")
                        .focus();
                break;
        }
    });
});

How does this work? Each time you press a key while one of the input boxes is in focus, I check the key code. If the code corresponds to one of the arrow key values I switch focus. The statements up there look a bit convoluted so let me explain one in more detail. Let’s do the left arrow:

  1. First we use the parent() function to get the parent node of the input box. This gives us the <td> tag
  2. Second, we use the prev() to get the previous sibling of our <td> node
  3. Third, we get the list of children of that node – and we narrow it down to just input boxes with the specific class. Because of the way our table is structured, we know there will always be exactly one child there
  4. Finally we call the focus() function on all the children (remember, there is only one there) which moves the cursor over

Moving up and down, requires extra steps. We call parent() twice to back out to the <tr> tag and grab previous or next sibling of that. Then we grab all the <td> children, and their children but narrowing it down to input boxes with the same name as the one that triggered the focus change. Once again there will always be exactly one node there.

End result is intuitive keyboard navigation that allows you to move in the table very much the way you move around in an Excel spreadsheet. I thought this was a pretty neat effect so I decided to share it here.

I created a live demo to demonstrate this effect. Mess around with it and let me know what you think. It’s a simple little tweak, but makes a huge usability difference – at least in my opinion.

Does anyone has an idea how to make this prettier, faster, better, stronger and etc? This code is probably suboptimal, but it works. I actually tested it on large-ish data sets, and it didn’t seem to cause visible slowdowns. But of course I’m always open for constructive criticism.

]]>
http://www.terminally-incoherent.com/blog/2009/10/08/jquery-grid-like-table-with-keyboard-navigation/feed/ 13
Forcing IE8 Compatibility Mode in IIS http://www.terminally-incoherent.com/blog/2009/07/27/forcing-ie8-compatibility-mode-in-iis/ http://www.terminally-incoherent.com/blog/2009/07/27/forcing-ie8-compatibility-mode-in-iis/#comments Mon, 27 Jul 2009 14:41:10 +0000 http://www.terminally-incoherent.com/blog/?p=3495 Continue reading ]]> When I saw IE8 being pushed out via Windows Update I was ecstatic. This meant that in a few months the number of installations of the first semi-standards compliant browser made by Microsoft will reach a critical mass. At that point I will be finally able to stop supporting IE6 on some of our web apps. Or rather I will be fairly justified for beating people up for not upgrading their browsers.

IE8 is the current version that was automatically installed on the company computers via Windows update. IE7 is the obsolete, outdated version that was replaced by IE8. IE6 is an 8 year old blast from the past. Anyone still running it is probably using a private computer, on which they are obviously not keeping updated, and which may be riddled with trojans and keyloggers. Considering that we have to write custom css, and javascript code to work in that dinosaur, which is costing many man-hours (and probably some woman-hours as well) should we support it for our internal web apps?

At this point most managers will agree that it probably doesn’t make sense to waste time learning IE6 specific hacks anymore. They might still want to support “the previous version” just in case. Up until now, that version was IE6. Now it’s IE7. Whee!

Internet facing stuff will probably still need to be hacked for IE6 but internal stuff that is only used by the staff can now be free of the nightmarish “oh, wait – how do we degrade this gracefully in IE6” phase which usually ends up taking 80% total development and testing time. Instead we can just put little passive aggressive notes on our websites that say something along the lines “Why are you accessing this website with an insecure obsolete browser? Click here to upgrade”

The excitement was short lived of course, IE8 support tickets started piling up. Most of these said something like “Users computer freezes while filling out the time sheet” or “User loses internet connectivity after logging into the time sheet system”. It doesn’t sound like and IE issue, does it. At least not on the surface. That’s because you are not thinking like a user.

What was happening is this: the 3rd party online time sheet system we were using was not IE8 ready. Or if an IE8 patch existed, was held up somewhere at our end due to the classic “well, can’t you patch the production server when we are not using it – like at 3am on Christmas Eve – but call Bob and his team before you do anything, because they might be using it even then” issue.

Either way, the “clever” Javascript it uses for redirecting and setting up pages somehow managed to cause IE8 to freak out and go into some very resource intensive infinite loop. The users would see a blank page, and the browser would simply stop responding and wouldn’t close unless killed via the task manager. This would happen just after logging into the time sheet system and only on IE8.

For a lot of our users IE == Internet so they interpreted this problem as network connectivity issue or a general system failure. A lot of people don’t even know you can kill processes via Task Manager so they would automatically reboot their system when this happened. And thus we started collecting all these weird tickets that hinted at wide variety of falsely perceived symptoms.

Users who preferred Firefox did not report this issue. Neither did people working from home their personal computers with IE6 and IE7. It was a unique IE8 centric bug and it needed to get fixed. Quick investigation confirmed that enabling the IE Compatibility Mode prior to logging in would work as a workaround.

We briefly considered sending out a memmo about this but the help desk informed us that several users literally broke into tears when they were told they needed to press an additional button before logging in. One person claimed that he will need an extension on his report because of this “inconvenience”. Several people simply said they will not input their time sheets until the matter is resolved because the workaround is too confusing. Someone also threatened to quit the job over this. Of course we got that person an intensive 20 minute in-person, hands-on training with several of the IT people and in the end he decided it was actually a fairly easy workaround.

Needless to say, we needed a better solution than trying to train our users. It’s sad but these people react to knowledge the same way most people react to the smell of a freshly ripped fart – they make a face, and try to excuse themselves and leave the room as soon as possible. Which makes me wonder how do they acquire the much needed on-the-job skills such as using Excel formulas and such… Oh wait… Never mind, they use pre-made templates with formulas already entered in, and when they need to add/remove rows, create totals or do anything out of the ordinary they call the help desk.

“What if we just put that stupid meta tag in the header” someone suggested. Of course that would involve digging through the mountain of outside code that constituted the time sheet app. It was something no one really wanted to do. So yeah… Trying to teach them something new seemed to be a lost cause.

Fortunately there is a better way. You can force the compatibility mode by sending a special header to the browser. In IIS you can do it by going to the properties dialog for your website and adding it on the HTTP Headers tab:

Add a Custom Header

Add a Custom Header

Simply click on the button and type in X-UA-Compatible as the header name, and IE=7 as the value:

X-UA-Compatible: IE=7

X-UA-Compatible: IE=7

This will globally force the compatibility mode for the whole site. Users won’t even see that silly little button, and the pages will render in the IE7 mode. This method is much better than the meta-tag because it can be easily removed on the fly without ever touching the code. And of course it is much easier to deploy than pushing out some custom settings to all your users.

If you ever need to do this, here is how. I hope you won’t ever have to resort to this method for the code you write. If you do, it means that you are clearly doing something very, very wrong.

]]>
http://www.terminally-incoherent.com/blog/2009/07/27/forcing-ie8-compatibility-mode-in-iis/feed/ 5
360 Degree Design http://www.terminally-incoherent.com/blog/2009/07/20/360-degree-design/ http://www.terminally-incoherent.com/blog/2009/07/20/360-degree-design/#comments Mon, 20 Jul 2009 14:08:29 +0000 http://www.terminally-incoherent.com/blog/?p=3436 Continue reading ]]> What I am about to show you is known as the Design Circle or 360 Degree Design principle. It states that you initial design and/or layout is usually correct, but it will never be accepted by the client who will keep changing it until he gets back exactly what he started with.

Let me illustrate this using an example. I was asked to put together a simple static page existing website. It was a bio of a VIP of some sort with name, title, picture and some text. The headers, footers, color scheme and the off-color sidebar part seen in the picture below were all parts of the existing design. All I really needed to do is to copy and paste the text into the template and then put the picture somewhere.

The sidebar area on the page is not really used for navigation but for displaying quotes and/or images related to the content (the navigation is in the header). Thus, it seemed a natural place to put the picture. My original layout looked like this:

First Layout Prototype

First Layout Prototype

I sent the sample to the client and she was not entirely pleased. She asked me if we could “move the picture under the name”. I didn’t really know what that meant, and she could not explain it. About 6 emails and a phone call did nothing to actually make this any clearer so I took a guess and did this:

Can we move it under the name?

Can we move it under the name?

“Better”, she responded, “but it should be to the right”. Fair enough, I flipped the image around and sent it back to her:

I meant on the right side

I meant on the right side

Apparently that was not what she wanted. She wanted it “under the name”. We went back and forward trying to define what exactly did it mean. I even took a screenshot of the website and put a grid over with letters and numbers. I was like “right now the picture is in square F5. Please tell me which square should it be now and I will make it happen”. Of course she ignored the grid and after 5 or 6 more emails she finally told me she wanted it to be “above the text, right aligned”.

Hoping that we were finally getting somewhere I repositioned the heading a little bit to accommodate the picture:

Above the text please

Above the Text

This turned out to be wrong. Apparently this was “above the name” according to her. It didn’t look “above” to me – it was aligned with the heading, but whatever. She explained wanted it “below the name but above the text”. I figured that this translates into not wanting the text to wrap around the picture.

Now that confused me a little bit as it just seemed awkward. That would push the paragraph down and create a huge gap in the middle of the page. She said she doesn’t mind. I asked if she wanted to make the picture smaller, but she said it was the right size.

So I did it, knowing full well that it will get rejected:

No, under the name

No, under the name

She admitted that this created to much of a gap the page and she asked me to move it back to the left and have the top of the picture align itself with the top of the name:

Let's put it back on the left

Let's put it back on the left

Guess what? Wrong again. She wanted the “far left” or the sidebar. Where does this get us? Back to the square one:

First Layout Prototype

First Layout Prototype

I took the original design and re-sent it to her. Verdict: Perfect!

Actually she was very proud of herself for figuring out the right layout.

“It took quite a bit of tweaking but I think we finally got the right design for this page! Thanks for your help Luke.”

No problem! It’s not like I have like 20 other projects that are due yesterday sitting on my desk. It was totally worth the time. I mean, I’m really glad we didn’t go with that first draft layout I sent to you. That would have been a disaster.

I probably should mention this is not the first time this has happened, and not the first person who insisted on going through this exercise. This is actually a typical design procedure for me. I make something, they change it and re-design it until they get back to the initial design.

The downside of this is that a simple 5-10 minute task turned into a drawn out project that took 3 days to accomplish and required over 20 emails and 4 phone calls to complete.

Fun times.

]]>
http://www.terminally-incoherent.com/blog/2009/07/20/360-degree-design/feed/ 16
SQL Emulation Tool in Javascript Part 2 http://www.terminally-incoherent.com/blog/2009/05/19/sql-emulation-tool-in-javascript-part-2/ http://www.terminally-incoherent.com/blog/2009/05/19/sql-emulation-tool-in-javascript-part-2/#comments Tue, 19 May 2009 14:51:07 +0000 http://www.terminally-incoherent.com/blog/?p=3083 Continue reading ]]> As promised, I’m posting my semi-working sql parser below. You should keep in mind that the code is still very immature and full of bugs. One of my reasons for posting it here is that people will start playing around with it and break it in numerous ways helping me to discover the way I can improve the code.

I think I covered most of the architecture in the previous post. One bit of code I wanted to share here is my metaprogramming function generator. This bit of code takes in a list of conditions, and will generate a jaascript function that will test for these conditions and return a boolean value.

When my SQL parser evaluates the WHERE condition it constructs an array that looks a little bit like this:

Conditions Array (click to embigen)

Conditions Array (click to embigen)

Each member object is composed of five elements. The first one is the name of the column, the second one is the value that is used in comparison, and the third one is the comparison symbol. The fourth value is just a flag which indicates whether or not the parser was able to successfully generate this object. It is needed there since malformed SQL could produce only partially generated object to be added into this array. All new objects are generated with this flag set to false, and it is changed only after they are populated without errors. This let’s us spot and ignore malformed and incomplete entries.

The fifth field is the logical operator which is used to join the comparison described in the current object to the previous one. The first element of the array will always have it’s logic field un-initialized. The following elements will have it set to a legal logical operator – this is enforced by the parser.

Once I have this array I pass it into this function:

function generateCondFunction (conditions) {
		
	var tmp = "cond = function(row) { if(";

	for(i in conditions)
	{
		current = conditions[i];

		if(!current.full)
			throw "Incomplete WHERE statement";

		if(current.action == "<>")
			action = "!=";
		else if(current.action == "=")
			action = "==";
		else
			action = current.action;

		if(current.logic != null)
		{
			if(current.logic == "and")
				tmp += " && ";
			else 
				tmp += " || ";
		}

		tmp += " row[\"" + current.first + "\"] " + 
			action + " " + current.second;
	}

	tmp += ") return true; else return false; };";
	
	eval(tmp);

	return cond;
}

The beauty of Javascript is that you can build a string, and then execute it as code. This is precisely what I’m doing here. I use the elements from my array to build a comparison function, then evaluate it and return a function pointer. For example, the array from the picture above will yield the following function:

function(row)
{ 
    if( row["foo"] > 2 and row["bar"] != "poo" ) 
        return true; 
    else 
       return false; 
}

I take this function pointer and pass it into the table rendering function. Then as I iterate over the elements stored in my mock db-obects I pass them through this function fitst to see if they ought to be displayed or not. This is of course not the most efficient way of doing things, but it works.

Anyway, go check out the working demo here and let me know of weird bugs that you encounter. Please keep in mind that a lot of stuff still doesn’t work the way you would expect it. Here is the stuff that I know is still broken:

  • The canonical SELECT * FROM FOO doesn’t work – I have not implemented the wildcard selectors yet
  • If you don’t put spaces between listed columns, the thing will break
  • If you don’t put spaces in the WHERE condition, things will break. Typing in “foo < 2” works fine but “foo<2” does not
  • No common procedures (like NOW() and etc..) are implemented

Don’t report these things. Anything else though, will help me debugging the code. If you want to read through the whole thing, and nitpick or criticize my questionable coding practices you can find all the code here.

Also, Chris already told me that someone already created an SQL parser in Javascript. As far as I can tell TrimQuery is far superior to my hackish code here, so if you would want to use something like this in your project, you are probably much better off stealing code from there rather than from here.

]]>
http://www.terminally-incoherent.com/blog/2009/05/19/sql-emulation-tool-in-javascript-part-2/feed/ 4