Thursday, May 24, 2012

Namespaces, inheritance and dynamic loading in JavaScript

It is said that every job has its tool. Some of them are yet to be created. Just recently I needed the right tool for some job, namely managing namespaces, inheritance and dynamic loading in JavaScript. I believe the trio is intrinsically linked and as such requires just one tool.

I was quite specific about what that tool should allow me to do. I wanted to:

  • have namespaces that reflect the structure of my code
  • store any values in my namespaces, even primitives
  • load a file simply by requesting a namespace
  • define dependences between different parts of code within the code itself
  • not to worry about including all JavaScript files statically
  • have  inheritance supported by the namespaces
Sadly, I failed to find such a tool.

Luckily, I have created it and it is pretty hot. It does namespaces, dynamic loading and inheritance. The tool is called wn(), after WebNicer. Here's an overview of the most important things I felt I had to get right.

Namespaces

I have read quite a few articles about implementing namespaces in JavaScript and to be fair I haven't found one that would get it right when it comes to nested namespaces. How so? Imagine you have a namespace:

MyApplication.SomeModule

Now, let's say SomeModule represents a constructor function. Then you want to create a child constructor function which inherits after SomeModule. Acting innocently and intuitively you would probably create a child namespace for it like so:

MyApplication.SomeModule.ChildModule

Looks ok but it isn't. ChildModule just became a property of SomeModule constructor function! You didn't want that, right? All you wanted was to create a child namespace and not a property of the function you have assigned to the parent namespace.

That approach is fundamentally wrong.

I had to fix it, so the above example works just fine in wn(). Namespace object is completely separated from the value represented by that namespace. Therefore ChildModule is a child namespace of SomeModule and does not become a property of the constructor function stored in SomeModule

Dynamic loading

I think that RequireJS is not a bad piece of software but I don't really like a loader to dictate how I should write or organize my code. I believe that the loader should be helping in the background rather than trying to change my coding preferences.

On the other hand, defining dependences between namespaces rather than files is quite tempting. By doing so you can create code which is more reusable and less prone to environmental issues. It should not mean however, that each dynamically loaded files has to define a namespace. That would be just wrong. What if you wanted to load dynamically jQuery from the Google CDN?

Closely related matter is translating namespaces to URLs. Should the namespaces reflect the directory tree or, for example, represent just the filenames? Maybe. There is no one good answer. I believe that decision should be in discretion of the developer and not necessarily the one implementing the loader.

I wanted wn() to help developers do things, not make them do things. Therefore the mapping is up to you, although the default one is included for you convenience. Dynamically loaded files don't have to define namespaces if you don't want them to. And any file can define multiple namespaces if that is your wish. Some other libraries require just one namespace per file.

Inheritance

The trickiest of them all. Obviously the language has no native mechanism for inheritance, so it needs to be implemented. Therefore there a few different approaches to inheritance in JavaScript. The two most common models are the prototypal and classical inheritance. People fight holy wars trying to argue how one is superior to the other and I strongly believe it to be pointless. They would better spend their time watching paint dry.

Both approaches have advantages and both can be used by the same code only for different things.

For main building blocks of my application I would rather use classical inheritance. I would be able to check if an object is derived from certain constructor function or whether that constructor function is present up the inheritance chain (instanceof). When the code grows, type checking becomes priceless ally of code maintainability.

On the other hand prototypal inheritance is much more useful for ad-hoc objects. One of the best examples in my opinion is default values. Imagine parent constructor's prototype with a property defaults pointing to an object with some default values. Now, in the child constructors's prototype we would like to add one more default value. We don't want to recreate the whole object, though. The easiest and cleanest thing to do - use prototypal inheritance on the defaults object.

As wn() is focused on main building blocks of an application, it supports classical inheritance. Being built around namespaces, wn() allows to express inheritance using namespaces as well. Just an extra sugar.

Again, you can find examples of inheritance on the wn() Wiki.


I hope you will find wn() useful. I made every effort to make it easy to use as well as the examples easy to read and understand. Nothing's perfect but you can help improving the library by simply dropping a line.

Thanks for reading.
Jacek

Friday, May 18, 2012

How to add form tag to Typo3 RTE

Obviously it's simple when you know how to do it but it's hard to find on Google. I gave up after seeing a few advices like "use HTML element" or "read documentation". Thing is, I always start with reading documentation. The final resort is usually reading the source which might be a bit more time consuming but always gives definitive answer.

The following solution has been tested in Typo3 version 4.6.4. It should work fine elsewhere. Any feedback welcome, feel free to drop a line in the comments saying "version x.x.x works" or "version x.x.x doesn't work".

Getting to the subject, in order to add form support to RTE in Typo3 you will need to add some TypoScript to your page TSconfig and TypoScript template. The former is to make sure that content is properly saved in the database, the latter to avoid escaping tags in the frontend.

Let's start with page TSconfig:


RTE.default.proc {
  allowTags := addToList(form, fieldset, input, select, option, label)
  allowTagsOutside := addToList(form, fieldset, input, select, option, label)
  denyTags := removeFromList(form, fieldset, input, select, option, label)
  entryHTMLparser_db {
    allowTags < RTE.default.proc.allowTags
  }
}


Feel free to add more tags if you need them.

Now we need to get the frontend sorted. This should go to your TypoScript template:

lib.parseFunc_RTE.allowTags := addToList(form, fieldset, input, select, option, label)


It's a good idea to make sure that the lists of tags from TSconfig and TypoScript template are matching up. Enjoy.

Wednesday, January 11, 2012

How IE6 caused the Dark Decade of the Web

If each developer in the world gave me a penny for every time they were swearing at IE6 then I could possibly be the richest man on the planet. The money spent in web development worldwide just for fighting IE6 bugs could probably buy the Cure For Cancer. Dealing with IE6 was not fun by the slightest. And now, finally, this global generator of frustration is dying a death celebrated by the whole Web Community as well as its own creators. It is really the time to crack a bottle of champagne.


No doubt, we could have been saved from the Dark Decade of the Web. Netscape Navigator was once the best browser on the Web, holding nearly 80% of the market in 1996. It was a strong competitor for IE and competition drives innovation. Unfortunately Netscape couldn't keep up the pace and finally lost the Browser Wars. When the dust settled eventually, we found ourselves left with far from perfection IE6 and on the brink of the decade of frustration.

For nearly 10 years we couldn't do much other then learn how to compensate for IE6 bugs and its devilish quirks. We did care about IE6 not because we liked it. I don't know about you but I still hate it with passion. It gives me nightmares. We cared about IE6 because we cared about our users. What choice did they have after all? With no sensible alternatives at the time it became the most popular browser. The reference experience. The blocker of the Web innovation.

How many times, with pondering heart, were you launching IE6 to view your newest, inventive piece of work and asking yourself: "Will it work in IE?" How many times were you dreading this question so often thrown casually into a conversation by your customer: "That looks cool. Can we have a quick look at it in IE?"And it had to look good in IE. It had to look the same in every browser.

It was going on for so long as to became our second nature. Even after Firefox and then Chrome started gaining popularity and could deliver better experience at a lower price it had always to be the same. We were consciously downgrading the experience in more capable browsers in order to keep it "consistent". Now IE6 is good as dead but will we still carry on? Will we pick another "reference browser", the worst on the market (let me guess... IE7?) to bring our work down to its level?

I sincerely hope we know better than that now. If you had a CRT TV you probably wouldn't expect to watch HD programs on it. With browsers it is not that much different. IE7 is nothing like new Chrome. There is no reason to try and make our websites look and behave identical in both. The experience can downgrade and that is OK. As long as we define and deliver acceptable minimum the rest becomes pure fun. We don't have to worry about how it would look in IE7. We know it will be different. And that is OK.

Even though I am concerned I believe the black scenario is not very likely to happen. The Web becomes less and less desktop-centric. Many more other devices are being used for browsing the Web today and the numbers are growing. Mobile phones, tables, game consoles - they all have different resolutions and provide different experience. The game is no longer about minimum screen resolution. Responsive design becomes a necessity. We are slowly growing used to the fact that the same website can look differently when we switch to another device. From here it takes just a small step to accept that it can also differ depending on the browser we use.

I am sure that the challenges that are yet to be taken are going to be interesting. I imagine designers would be required to provide scalable designs, probably in several variations mitigating scaling stress points. Implementation of those designs would be relying more on scalable CSS3 effects rather than their graphics heavy counterparts. The focus of testing would shift to different resolutions and graceful downgrade of experience in less capable browsers. It's the whole new world.

Seems that the Web has just evolved, we have a lot to learn and even more fun ahead and IE6 is nearly dead. Isn't that exciting?

Jacek


PS.
I would like to thank two remarkable people who inspired me and opened my eyes. Paul Irish, the Lead Developer of Modernizr who gave a presentation on Developing HTML5 in cross-browser world and Ethan Marcotte who contributed to "An Event Apart" (Jan 2012) giving great presentation entitled "A Dao of flexibility".