So I ventured the JS/CSS high seas and…

Lately I’m spending most of my time in a browser. Deciding to take advantage of it, I’ve coded a little app on a side: a task list. Along the way, I observed a few things.

Bottom line is: learning JS for a newbie may very well be a horrible experience. Aside from that:

  1. jQuery has tentacles everywhere
  2. localStorage is nice, but lacking
  3. I like static types, they’re easy on the mind
  4. JavaScript really encourages hacking
  5. Tim Toady presides not only over Perl
  6. Related materials in the Internet are mostly subpar
  7. People don’t read questions, they classify them based on keywords
  8. Why Quora is so popular despite copying ExpertExchange
  9. Links are not buttons, neither are DIVs or SPANs
  10. CSS really gives lot of display options for pages

 

jQuery has tentacles everywhere

Searching for solution to a problem? Use jQuery.
Want to achieve an effect? jQuery has a plugin for that.
Wanted to search without jQuery? Well, bad boy, even sites that offer pure CSS or pure JS solution mention that word.
Asking a question on StackOverflow? Or browsing through such questions? jQuery awaits there as well, beware! ๐Ÿ˜›
Oh, I also tried asking a friend. He of course bashed me for not using jQuery…

Gosh, frustrating!

SO question parody: jQuery roxxorrs soxxorrs
found on SO, by someone with clearly similar frustration level

I admire jQuery, have been using it professionally, it’s real time-saver in number of ways… but things are moving forward and jQuery is rather on the large side.

Check yourself: 96KB for “production-ready, compressed version 1.11.3”. My whole app, including all icons is contained in 3KB!!

I don’t think that every site should have jQuery, neither, back in the day, did I bought that every system should run Windows 95. ๐Ÿ˜›ย  I wanted API to interact with local storage and some DOM manipulation. I wasn’t interested in any other browser than my fave FF and that was it. Also, I wanted the page to load fast. Thus, I didn’t need jQuery. For those practically-inclined, that want to say, OK, your case is easy, mine is different, read Ditching jQuery please. There are more posts out there, but that’s most practical one (that I found).

 

localStorage is nice, but lacking

As cookies have 4KB limit, local storage has more (5MB). Not that I needed it for a task list. However, since it persists after closing the browser and has JS API built into all modern browsers (Edge?) I wanted to play with it. However.

  1. key and value are Strings
  2. basic API:
    1. getItem(key);
    2. setItem(key);
    3. removeItem(key);
    4. clear();
    5. most tutorials and blog posts fail to mention one really important method: key(index);

 

After working with Java and Scala collections, I found the API… lacking. Only Strings as keys doesn’t help my case, since I input data sequentially. Neither can I get max key out, nor can I quickly see which keys are “good” to use and which aren’t. After removing some items, that’s a problem.

But, perhaps that’s my inner javavore speaking, unused to JS reality. Moving on.

 

Wait! More about localStorage?

Links below are filtered already, I tossed aside all these which failed to mention KEY method, as I spent an hour hacking around NOT having keys in for loop. :-/

 

I like static types, they’re easy on the mind

Number being a number and behaving like a number is really cool. That way I can treat it as a number and focus on other things. With dynamic types in JS I must also remember, whether I’ve did some “tricks” and in what state that left that poor var afterwards.

I also have gotten used to IDEs help. Quick ways of glancing which type offers which behaviours, method, etc. Browser console offering list of all properties is a poor substitute. When you are out of touch – that hurts.

I wonder however, how do you work with dynamic types with large not apps, but SYSTEMS? Me leans towards “you lose a lot”. I’d like to work with someone fluent in JS to see that.

 

JavaScript really encourages hacking

Oh gosh. And HOW!

So, you want to use JS to write HTML?

My first idea for that task list was to store it in local storage and document.write it on a page, once it loads. That worked and was ready in few minutes. Which was nice.

However then I recalled that there was something not so rosy about document.write. A nagging feeling settled down in the back of my head and it kept growing.

One search later, I’ve recalled that this rewrote the DOM. OK, there was innerHTML!

var text = ""
for(i=1;i<=localStorage.length;i++) {
text += "<li>" + localStorage.getItem(i) + "</li>";
}
document.getElementById("TaskList").innerHTML = text;

Simple.

In the meantime I’ve added a header, form to add the tasks, some styling and then I decided I want to be able to remove tasks as well. OK, that called for a “done” icon that would do the removal. Suddenly, I wasn’t just writing contents of local storage with list item tags around them, I also had to add an icon and JS onclick. And icon meant image.

That was one lengthy string, and it looked bad. I tried looking for better solution, but with innerHTML folks either wrote their own functions for String interpolation, or used arrays and pushing, or played with escaping quotes via variables.

Guarh! I’d have to have seven variables just to add list item, button, image, onclick… NO. That was BAD OPTION.

DOM API fortunately had appendChild and createElement.

However right after fresh lesson about JS ways, I decided to read more. Good I did! I learned about document FRAGMENTS. Which are awesome to build a part of DOM aside from your page and then neatly plug it in, and according to some benchmarks, are MUCH faster.

 

 

More about document.write, innerHTML and document.createFragment

SO question explaining why you want to use DOM API
MDN document fragment
Why and how document fragments are better

 

So, you want to load JS scripts?

Sure, pardner. Let me help.

Do you want to load them like that? They may block page rendering.

Or do you want to defer loading until they don’t? But of course… though not in all browsers.

HTML5 to the rescue? Well, why not, there’s async loading. Though it doesn’t always work.

Async can be set to false of course! Though, some browsers won’t know what that is…

So, perhaps let’s use document.write to load the script just like that, ok?

 

Dear Lord, learning all that was exasperating. Bottom line was, put your scripts (especially if the play with DOM) at the end of the body. Or use defer or async, where async is preferred, though do check if your browser supports it well. And beware of bugs, that can cause random loading (if load order is important for ya).

For those unfamiliar with async and defer:

click for HTML spec page detailing `script` element attributes, including `defer` and `async` ones, show here on screen

Good reading here:

WAI intro to specs, in our case click to go to HTML spec on scripting

Of course the spec is number one here.

After some time, by accident I’ve stumbled upon excellent piece that nicely sums it up:

header from Jake's post
Jake Archibald’s post header, click to go to his post directly.

So, you want to create JS objects?

Sure! Nothing easier.

var myObject = {};

There. Done.

Oh, you meant useful objects! Some idioms perhaps? Well, sure. Why not. Few searches later, you’ll have a way that emulates class, a way that creates a function (function can be an object), a way to have singleton, to do it via prototype, via closure (auto-executes!)…

All of this boils down to one thing.

Tim Toady presides not only over Perl

A toad. Captioned Tim.
Eponymous Tim

All those cases above are prime example of TIMTOWTDI (Tim Toady) – the famous Perl programmers motto:

There Is More Than One Way To Do It

And yeah, there certainly is, but for new folks that just makes things difficult. Add content to page – choose between four ways, add JS to page, choose between six ways… Ugh.

Of course, it’s not just “stoopid JS”. There’s more to that and in general, Tim Toady ain’t so bad. However in JS, that seems like it’s there for every step you take. To the point where taking up a library that “solves” those problems or proposes you follow it’s convention seems quite attractive.

More examples:

  1. JS constructor without new and three solutions – title says it all
  2. Idiomatic object on SO – 4 answers, now compare between them

Related materials in the Internet are mostly subpar

Now that’s obvious if you look at it calmly right? First of all, materials can be as good as current knowledge is. JS evolved incredibly and some practices that were great a decade ago are quite shunned now. Secondly, JS is a language of the Web. That means, it’s directed used not just at by programmers*. It’s something that everybody who wants a page is likely to use. It’s like Personal Home Page replacement or extension (depends how you look at it). Obviously, those folks won’t always be programmers, they’ll often be DIY people. I can craft a table, but a carpenter would most likely felt immense sadness upon looking at it. And there’s more. JS snippets for wannabe hackers, obfuscation, minification, forums tips and all that. Also, lots of links tying the solution to this or that library, framework or “best way”. Magazines and outdated articles, claiming this or that is leading edge and that newest Firefox 3.5 will support it.

Of course, the links above aren’t links to bad articles. Three solutions to JS constructor or 4 ways to create object via idioms ain’t bad. It’s just a symptom of a problem, and problem here lies with the language itself. With how it’s been twisted by browser wars, spec ambiguity, changes in the web itself and it’s own design. Folks who worked with JS came to have their own tools and techniques, now, when you want to learn it, you cannot just pick at random, because there are subtle differences here and there. This makes it much harder to quickly pick up technique from a random article on the web.

All in all: problems I had were exacerbated with JS materials that I kept stumbling upon – each link required deeper study than I assumed it would (and I knew front-end world was different and more ‘twisted’ in a way, so I assumed more time will be needed).

*uhm, I don’t think JS was directed at programmers…

People don’t read questions, they classify them based on keywords

In a world where everybody’s busy – that’s a given, right? Well, I guess it wasn’t as much for me.

During work on that little app I’ve asked a question on SO, about how can I make that CSS ::after actionable. And… what came after was:

  1. an answer how to add HTML content with code::after/code, which I already had
  2. a downvote and a comment that said my question was a duplicate because there already was a question on how to add HTML with CSS ::after and ::before
  3. a vote to close
  4. a comment from a person who actually READ my question
  5. a downvote on the answer that told me how to add HTML content via CSS (that I already had)
  6. my edit, to clarify question intent and cut any words that triggered wrong classification of my question
  7. a real answer
  8. some upvotes, unflagging as dupe from #2
  9. flagging as duplicate of how to achieve what I wanted WITH JQuery (I specifically said that I want NO FRAMEWORKS)
  10. my another edit, to hoist “no frameworks” to first line and to add “and no libraries”

All that in measly 15 minutes. I do believe there’s 50k folks on SO at any time. Most of them are real fast, some are perhaps a tad too fast.

But with the barrage of “this is a duplicate”, downvote, answers to something else and NOT reading my question and it all happening in such a rush, I kinda understood why some newbies don’t wanna be there.

Because they don’t know how they should search.

In my case (making CSS ::after actionable) I could’ve searched in two or three more ways than I did. I don’t believe a JS newbie would have made the connection and exhausted all searches prior to asking. Would he got the answer? I hope… but am not certain.

Which explains, why Quora is so popular despite copying ExpertExchange stupid business model. If I felt some pressure with all the critique I was getting, I imagine people from Asia, India and other cultures must feel it even more strongly. Therefore, even with broken model (‘sign up to see more answers and meet real experts’ anyone?) some will choose that place…

 

Links are not buttons, neither are DIVs and SPANs

The excellent piece by Karl Groves was a final nail to the coffin of my actionable ::after content. After reading I just abandoned the flawed idea, because it was just out of place.

I think I may reblog the piece, it’s worth it, but in the meantime:

Karl starts with “quick, what is this?” and shows a…

a rounded rectangular with large OK on it
what is it? Taken straight from Karl’s post (click to go). This is a…?

a what? A BUTTON, yes, you won! ๐Ÿ™‚

Then he shows sample markups you may use to get it (span, a, a href, a img…) and lists button considerations. I’ll quote that part:

  1. Device independence: Users must not be required to use any specific device to operate the control. In other words, users must be able to gain focus on it and activate it using a keyboard or voice commands as well as a mouse
  2. Color Contrast: The design of the button must have sufficient color contrast, and the button must not disappear in high contrast mode.
  3. Name, State, Role, Value: […] these are ARIA things, for availability API. A good topic in itself, but one too large here. Let’s just say, that this tells what button does, it’s state and purpose.

Then he proceeds to eliminate everything, that’s NOT a button. And so:

  • DIV is not a button, as it
    • lacks DOM interface API that a button needs to have,
    • can’t be accessible by keyboard (device independence),
    • fails with regards to ARIA (WAI-ARIA states don’t use elements out of their purpose, famous <I> vs <EM> debate).
  • SPAN … see all above.
  • A element (link) usually has a hypertext reference and is used for navigation. It doesn’t trigger the action. Though looking consideration-wise it’s nearly as good as button. ๐Ÿ™‚
  • Which leaves… a BUTTON! ๐Ÿ™‚ Meets all considerations and also performs an action or a command, doesn’t navigate to some other page (unless it’s a commitment / wizard step).

Overall, go and read the piece, it’s really full of links to sources and specs and clearly explains what is a button and when you want one. I read a number of tutorials, style guides and techniques on styling X to look like a button, pieces telling how to hack box model to put span or something underneath something else so you can click it… and I really disliked all that. The piece was a great relief.

CSS really gives lot of display options for pages

CSS Garden. Nuff said.

I still like CSS.

Summarizing

JS is hacky, CSS is nice, front-end folks have reaaally tough jobs with JS Perl-like qualities coupled with not only language quirks and it’s design decisions (arrays and objects, classes and prototypes), but also overall “Tim-Toadiness” and browser wacky implementation differences. Adding to that how folks come up with JS libraries to do the job and the average ratio of new best lib JavaScripter must know (beside jQuery, you MUST know jQuery, it’s THE BESTESTEST) it’s a place for – like a friend put it – programmer-explorator. One needs to be able to learn ‘newest’ lib fast. HTML5 and CSS3 look nice, pains that Flash had most of this a long time ago. :/

 

Overall, that was a nice and refreshing ride. And the app will be on GitHub, so do criticise me and tell me how to make it better. ๐Ÿ™‚

Oh, and if you already forgot the links, read these:

Dive into HTML5 – explains in European style – with “why”, not just “what” it does.

CSS Garden – steel layout – well, visit more than read, but still.

Book of speed by Stefan Stoyanov – seems interesting, and that’s all I can say for now, as I’m just reading it

Advertisements

2 Comments

  1. Hi! Thanks for linking to my Ditching jQuery post. I’m delighted you found it useful.

    Regarding your frustration with localStorage—there actually is a relatively simple way to save a set of data as a single localStorage value. Simply right your data a standard JSON object, and then use the JSON.stringify() method to convert it to a string. When you pull the data back out of localStorage, you can use JSON.parse() to convert it back to JSON. Example:

    var obj = {
    	something: 'la la la',
    	somethingElse: true,
    	anotherThing: 123
    };
    
    localStorage.setItem( 'myStorage', JSON.stringify(obj) );
    
    var storedData = JSON.parse( localStorage.getItem('myStorage') );

    Hope that helps!

    1. Chris, I found your post the best when it came to dealing with that subject. Linking was a given. ๐Ÿ™‚

      Thanks for that tip! I’ll remember, though in my app I’m filling the storage via form input, so one line / task at a time. But I was thinking on how to extend that to multiple projects (like, tasklist-app-related things to do, and say, this blog post things to do). There your tip certainly comes in handy!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s