Categories
Original Tips

Resolve Promises externally with this one weird trick

Those of us who use promises heavily, have often wished there was a Promise.prototype.resolve() method, that would force an existing Promise to resolve. However, for architectural reasons (throw safety), there is no such thing and probably never will be. Therefore, a Promise can only resolve or reject by calling the respective methods in its constructor:

var promise = new Promise((resolve, reject) => {
	if (something) {
		resolve();
	}
	else {
		reject();
	}
});

However, often it is not desirable to put your entire code inside a Promise constructor so you could resolve or reject it at any point. In my latest case today, I wanted a Promise that resolved when a tree was created, so that third-party components could defer code execution until the tree was ready. However, given that plugins could be running on any hook, that meant wrapping a ton of code with the Promise constructor, which was obviously a no-go. I had come across this problem before and usually gave up and created a Promise around all the necessary code. However, this time my aversion to what this would produce got me to think even harder. What could I do to call resolve() asynchronously from outside the Promise?

A custom event? Nah, too slow for my purposes, why involve the DOM when it’s not needed?

Another Promise? Nah, that just transfers the problem.

An setInterval to repeatedly check if the tree is created? OMG, I can’t believe you just thought that Lea, ewwww, gross!

Getters and setters? Hmmm, maybe that could work! If the setter is inside the Promise constructor, then I can resolve the Promise by just setting a property!

My first iteration looked like this:

this.treeBuilt = new Promise((resolve, reject) => {
	Object.defineProperty(this, "_treeBuilt", {
		set: value => {
			if (value) {
				resolve();
			}
		}
	});
});

// Many, many lines below…

this._treeBuilt = true;

However, it really bothered me that I had to define 2 properties when I only needed one. I could of course do some cleanup and delete them after the promise is resolved, but the fact that at some point in time these useless properties existed will still haunt me, and I’m sure the more OCD-prone of you know exactly what I mean. Can I do it with just one property? Turns out I can!

The main idea is realizing that the getter and the setter could be doing completely unrelated tasks. In this case, setting the property would resolve the promise and reading its value would return the promise:

var setter;
var promise = new Promise((resolve, reject) => {
	setter = value => {
		if (value) {
			resolve();
		}
	};
});

Object.defineProperty(this, "treeBuilt", {
	set: setter,
	get: () => promise
});

// Many, many lines below…

this.treeBuilt = true;

For better performance, once the promise is resolved you could even delete the dynamic property and replace it with a normal property that just points to the promise, but be careful because in that case, any future attempts to resolve the promise by setting the property will make you lose your reference to it!

I still think the code looks a bit ugly, so if you can think a more elegant solution, I’m all ears (well, eyes really)!

Update: Joseph Silber gave an interesting solution on twitter:

function defer() {
	var deferred = {
		promise: null,
		resolve: null,
		reject: null
	};

	deferred.promise = new Promise((resolve, reject) => {
		deferred.resolve = resolve;
		deferred.reject = reject;
	});

	return deferred;
}

this.treeBuilt = defer();

// Many, many lines below…

this.treeBuilt.resolve();

I love that this is reusable, and calling resolve() makes a lot more sense than setting something to true. However, I didn’t like that it involved a separate object (deferred) and that people using the treeBuilt property would not be able to call .then() directly on it, so I simplified it a bit to only use one Promise object:

function defer() {
	var res, rej;

	var promise = new Promise((resolve, reject) => {
		res = resolve;
		rej = reject;
	});

	promise.resolve = res;
	promise.reject = rej;

	return promise;
}

this.treeBuilt = defer();

// Many, many lines below…

this.treeBuilt.resolve();

Finally, something I like!

Categories
Original

Markapp: A list of HTML libraries

Screen Shot 2016-08-26 at 17.09.24I have often lamented how many JavaScript developers don’t realize that a large percentage of HTML & CSS authors are not comfortable writing JS, and struggle to use their libraries.

To encourage libraries with HTML APIs, i.e. libraries that can be used without writing a line of JS, I made a website to list and promote them: markapp.io. The list is currently quite short, so I’m counting on you to expand it. Seen any libraries with good HTML APIs? Add them!

Categories
Tips

Copying object properties, the robust way

If, like me, you try to avoid using heavy libraries when not needed, you must have definitely written a helper to copy properties from one object to another at some point. It’s needed so often that it’s just silly to write the same loops over and over again.

These days, most of my time is spent working on my research project at MIT, which I will hopefully reveal later this year. In that, I’m using a lightweight homegrown helper library, which I might release separately at some point as I think it has potential in its own right, for a number of reasons.

Of course, it needed to have a simple extend() method as well, to copy properties from one object to another. Let’s assume for the purposes of this article that we’re talking about shallow copying, that overwrites are allowed, and let’s omit hasOwnProperty() checks to make code easier to read.

It’s a simple task, right? Our first attempt might look like this:

$.extend = function (to, from) {
	for (var property in from) {
		to[property] = from[property];
	}
	
	return to;
}

This works fine, until you try it on objects with accessors or other types of properties defined via Object.defineProperty() or get/set keywords. What do you do then? Our next iteration could look like this:

$.extend = function (to, from) {
	for (var property in from) {
		Object.defineProperty(to, property, Object.getOwnPropertyDescriptor(from, property));
	}
	
	return to;
}

This works much better, until it fails, and it can fail pretty epically. Try this:

$.extend(document.body.style, {
	backgroundColor: "red"
});

Both in Chrome and Firefox, the results are super weird. Even though reading document.body.style.backgroundColor will return "red", no style will have actually been applied. In Firefox it even destroyed the native setter entirely and any future attempts to set document.body.style.backgroundColor in the console did absolutely nothing.

In contrast, the previous naïve approach worked fine for this. It’s clear that we need to somehow combine the two approaches, using Object.defineProperty() only when actually needed. But when is it actually not needed?

One obvious case is if the descriptor is undefined (such as with some native properties). Also, in simple properties, such as those in our object literal, the descriptor will be of the form {value: somevalue, writable: true, enumerable: true, configurable: true}. So, the next obvious step would be:

$.extend = function (to, from) {
	var descriptor = Object.getOwnPropertyDescriptor(from, property);

	if (descriptor && (!descriptor.writable || !descriptor.configurable || !descriptor.enumerable || descriptor.get || descriptor.set)) {
		Object.defineProperty(to, property, descriptor);
	}
	else {
		to[property] = from[property];
	}
}

This works perfectly, but is a little clumsy. I’ve currently left it at that, but any suggestions for making it more elegant are welcome 🙂

FWIW, I looked at jQuery’s implementation of jQuery.extend() after this, and it seems it doesn’t even handle accessors at all, unless I missed something. Time for a pull request, perhaps…

Edit: As MaxArt pointed out in the comments, there is a similar native method in ES6, Object.assign(). However, it does not deal with copying accessors, so does not deal with this problem either.

Categories
Thoughts

Idea: Extending native DOM prototypes without collisions

As I pointed out in yesterday’s blog post, one of the reasons why I don’t like using jQuery is its wrapper objects. For jQuery, this was a wise decision: Back in 2006 when it was first developed, IE releases had a pretty icky memory leak bug that could be easily triggered when one added properties to elements. Oh, and we also didn’t have access to element prototypes on IE back then, so we had to add these properties manually on every element. Prototype.js attempted to go that route and the result was such a mess that they decided to change their decision in Prototype 2.0 and go with wrapper objects too. There were even long essays being written back then about how much of a monumentally bad idea it was to extend DOM elements.

The first IE release that exposed element prototypes was IE8: We got access to Node.prototype, Element.prototype and a few more. Some were mutable, some were not. On IE9, we got the full bunch, including HTMLElement.prototype and its descendants, such as HTMLParagraphElement. The memory leak bugs were mitigated in IE8 and fixed in IE9. However, we still don’t extend native DOM elements, and for good reason: collisions are still a very real risk. No library wants to add a bunch of methods on elements, it’s just bad form. It’s like being invited in someone’s house and defecating all over the floor.

But what if we could add methods to elements without the chance of collisions? (well, technically, by minimizing said chance). We could only add one property to Element.prototype, and then hang all our methods on that. E.g. if our library was called yolo and had two methods, foo() and bar(), calls to it would look like:

var element = document.querySelector(".someclass");
element.yolo.foo();
element.yolo.bar();
// or you can even chain, if you return the element in each of them!
element.yolo.foo().yolo.bar();

Sure, it’s more awkward than wrapper objects, but the benefit of using native DOM elements is worth it if you ask me. Of course, YMMV.

It’s basically exactly the same thing we do with globals: We all know that adding tons of global variables is bad practice, so every library adds one global and hangs everything off of that.

However, if we try to implement something like this in the naïve way, we will find that it’s kind of hard to reference the element used from our namespaced functions:

Element.prototype.yolo = {
	foo: function () {
		console.log(this); 
	},
	
	bar: function () { /* ... */ }
};

someElement.yolo.foo(); // Object {foo: function, bar: function}

What happened here? this inside any of these functions refers to the object that they are called on, not the element that object is hanging on! We need to be a bit more clever to get around this issue.

Keep in mind that this in the object inside yolo would have access to the element we’re trying to hang these methods off of. But we’re not running any code there, so we’re not taking advantage of that. If only we could get a reference to that object’s context! However, running a function (e.g. element.yolo().foo()) would spoil our nice API.

Wait a second. We can run code on properties, via ES5 accessors! We could do something like this:

Object.defineProperty(Element.prototype, "yolo", {
	get: function () {
		return {
			element: this,
			foo: function() {
				console.log(this.element);
			},
			
			bar: function() { /* ... */ }
		}
	},
	configurable: true,
	writeable: false
});

someElement.yolo.foo(); // It works! (Logs our actual element)

This works, but there is a rather annoying issue here: We are generating this object and redefining our functions every single time this property is called. This is a rather bad idea for performance. Ideally, we want to generate this object once, and then return the generated object. We also don’t want every element to have its own completely separate instance of the functions we defined, we want to define these functions on a prototype, and use the wonderful JS inheritance for them, so that our library is also dynamically extensible. Luckily, there is a way to do all this too:

var Yolo = function(element) {
	this.element = element;
};

Yolo.prototype = {
	foo: function() {
		console.log(this.element);
	},
	
	bar: function() { /* ... */ }
};

Object.defineProperty(Element.prototype, "yolo", {
	get: function () {
		Object.defineProperty(this, "yolo", {
			value: new Yolo(this)
		});
		
		return this.yolo;
	},
	configurable: true,
	writeable: false
});

someElement.yolo.foo(); // It works! (Logs our actual element)

// And it’s dynamically extensible too!
Yolo.prototype.baz = function(color) {
	this.element.style.background = color;
};

someElement.yolo.baz("red") // Our element gets a red background

Note that in the above, the getter is only executed once. After that, it overwrites the yolo property with a static value: An instance of the Yolo object. Since we’re using Object.defineProperty() we also don’t run into the issue of breaking enumeration (for..in loops), since these properties have enumerable: false by default.

There is still the wart that these methods need to use this.element instead of this. We could fix this by wrapping them:

for (let method in Yolo.prototype) {
	Yolo.prototype[method] = function(){
		var callback = Yolo.prototype[method];
		
		Yolo.prototype[method] = function () {
			var ret = callback.apply(this.element, arguments);
			
			// Return the element, for chainability!
			return ret === undefined? this.element : ret;
		}
	}
}

However, now you can’t dynamically add methods to Yolo.prototype and have them automatically work like the native Yolo methods in element.yolo, so it kinda hurts extensibility (of course you could still add methods that use this.element and they would work).

Thoughts?

Categories
Apps & scripts

Awesomplete: 2KB autocomplete with zero dependencies

awesompleteSorry for the lack of posts for the past 7 (!) months, I’ve been super busy working on my book, which up to a certain point, I couldn’t even imagine finishing, but I’m finally there! I’ve basically tried to cram all the CSS wisdom I’ve accumulated over the years in it 😛 (which is partly why it took so long, I kept remembering more things that just *had* to be in it. Its page count on the O’Reilly website had to be updated 3 times, from 250 to 300 to 350 and it looks like the final is gonna be closer to 400 pages) and it’s gonna be super awesome (preorder here!) 😀 . I have been posting a few CSS tricks now and then on my twitter account, but haven’t found any time to write a proper blog post.

Anyhow, despite being super busy with MIT (which btw is amazing, challenging in a good way, and full of fantastic people. So glad to be here!) and the book, I recently needed an autocomplete widget for something. Surprisingly, I don’t think I ever had needed to choose one in the past. I’ve worked with apps that had it, but in those cases it was already there.

At first, I didn’t fret. Finally, a chance to use the HTML5 <datalist>, so exciting! However, the more I played with it, the more my excitement was dying a slow death, taking my open web standards dreams and hopes along with it. Not only it’s incredibly inconsistent across browsers (e.g. Chrome matches only from the start, Firefox anywhere!), it’s also not hackable or customizable in any way. Not even if I got my hands dirty and used proprietary CSS, I still couldn’t do anything as simple as changing how the matching happens, styling the dropdown or highlighting the matching text!

So, with a heavy heart, I decided to use a script. However, when I looked into it, everything seemed super bloated for my needs and anything with half decent usability required jQuery, which results in even more bloat.

So, I did what every crazy person with a severe case of NIH Syndrome would: I wrote one. It was super fun, and I don’t regret it, although now I’m even more pressed for time to meet my real deadlines. I wrote it primarily for myself, so even if nobody else uses it, ho hum, it was more fun than alternative ways to take a break. However, it’s my duty to put it on Github, in case someone else wants it and in case the community wants to take it into its loving, caring hands and pull request the hell out of it.

To be honest, I think it’s both pretty and pretty useful and even though it won’t suit complex needs out of the box, it’s pretty hackable/extensible. I even wrote quite a bit of documentation at some point this week when I was too sleepy to work and not sufficiently sleepy to sleep — because apparently that’s what was missing from my life: even more technical writing.

I saved the best for last: It’s so lightweight you might end up chasing it around if there’s a lot of wind when you download it. It’s currently a little under 1.5KB minified & gzipped (the website says 2KB because it will probably grow with commits and I don’t want to have to remember to update it all the time), with zero dependencies! 😀

And it’s even been verified to work in IE9 (sorta), IE10+, Chrome, Firefox, Safari 5+, Mobile Safari!

’Nuff said. Get it now!

PS: If you’re about to leave a comment on how it’s not called “autocomplete”, but “typeahead”, please go choke on a bucket of cocks instead. 😛

Categories
Speaking

Simple script: Automatic talks list

I guess this will not be useful to many, but thought I’d open source it anyway, in case someone else finds it useful. I mostly wrote it because after 50+ conferences, I got seriously fed up updating the list by editing the HTML manually. Now I will only have to edit a JSON file manually! 😛

Admittedly, it’s not my best code (more like a quick hack), but it should be pretty easy to adapt to your needs, even to adapt it to lists of different things instead of talks. Using it for talks is very straight forward: Include the CSS and JS, add a list with a class of “talks” where you want it, done.

Hope you enjoy it 🙂

Links: Live demo | Github repo | Script page

Categories
Articles

Optimizing long lists of yes/no values with JavaScript

My newest article on Smashing Magazine’s coding section is for the geekiest among you. It’s about how you can pack long lists of boolean values into a string in the most space-efficient way. Hope you enjoy it 🙂

Categories
News Original Personal

Detecting CSS selectors support + my JSConf EU talk

I’ll start with a little backstory, if you want to jump straight to the meat, skip the next 4 paragraphs.

In the past few months, my CSS research has been getting some attention and I’ve been starting to become somewhat well-known in the CSS industry. A little known fact about me is that JavaScript has always been one of my loves, almost as much as CSS (even more than it in the past). Ironically, the first time I was asked to speak in a big conference, it was about JavaScript, even though I ended up choosing to speak about CSS3 instead.

Lately, I’ve started wanting to get more into the JavaScript industry as well. I’m quite reluctant to submit speaking proposals myself (every conference or meetup I’ve given a talk so far has asked me to speak, not the other way around) and most JavaScript conferences expect you to submit a proposal yourself. I also couldn’t think of a good topic, something I was passionate about and hasn’t already been extensively covered.

This changed a few weeks ago. While I was writing my <progress> polyfill, it dawned on me: Polyfills is something that’s JS-related and I’m passionate about! I love studying them, writing them, talking about them. I quickly searched if there were any talks about polyfill writing already and I couldn’t find any. So, I decided to submit a proposal to JSConf EU, even though the call for speakers had passed 10 days ago. When I read @cramforce’s tweet that they had decided on most of the speakers, I spent a few days stressed as hell, checking my inbox every few minutes and hoping that my gut feeling that I would get accepted was right.

And it was! 3 days ago I received an email from JSConf EU that my proposal was accepted!! I can’t even begin to describe how happy and excited I am about it. And nervous too: What if they know everything I’m going to say? What if they hate my talk? What if the JavaScript industry is really as sexist as some people claim and they dismiss me because of my gender? I decided to put my fears aside and start working on my slides, as I couldn’t wait until later (even though I have multiple deadlines creeping up on me right now…).

A big part of writing polyfills is feature detection. Before trying to implement a feature with JavaScript, you first have to check if it’s already supported. So, a substantial portion of my talk will be about that. How to detect if APIs, HTML elements, CSS properties/values/selectors etc are supported. There are already established solutions and techniques about most of these, except CSS selectors. Modernizr doesn’t detect any, and judging from my Google search nobody has written about any techniques for doing so in a generic fashion.

A really simple way to detect CSS selectors support is using document.querySelector() in a try...catch statement. If the selector is not supported, an error will be thrown. However, that’s not really reliable, as the Selectors API is not supported in IE < 8. So, I thought of another idea: What if I turn the hassle of reading out a stylesheet via the DOM methods (browsers drop stuff they don’t understand) into a feature detection method?

The basic idea is creating a new <style> element with an empty rule and the selector we want to test support for, and then read out the stylesheet through the DOM methods to see if a rule actually exists. I’ve so far tested it in Firefox, Opera and Chrome and it seems to work. I haven’t tested it in IE yet, as I currently have too many apps running to turn on the vm, so it might need a few fixes to work there (or I might be unlucky and the idea might not work at all).

You can test it out yourself in this fiddle, just check the console: http://fiddle.jshell.net/leaverou/Pmn8m/show/light/

Apologies if this has already been documented elsewhere, I really couldn’t find anything.

Edit: James Long worked on fixing my example’s issues with IE

Categories
Thoughts

jQuery Pure: Call for contributors

This post is about an idea I’ve had for ages, but never found the time to actually start working on it. Maybe because it looks like a quite big project if done properly, so it’s scary to do it on my own without any help.

jQuery has a huge amount of code that deals with browser bugs and lack of implementations. For example, it needs a full-fledged selector engine, to cater for old browsers that don’t support the Selectors API. Or, it needs code that essentially does what the classList API is supposed to do, because old browsers don’t support it. Same goes for nextElementSibling (the .next() method) and tons of other stuff. However, not everyone needs all this. Some projects don’t need older browsers support, either due to the developer mindset or due to their tech-savvy target group. Also, some people only write demos/proof-of-concepts for modern browsers only and don’t need all this code. Same goes for intranet apps that are only designed for a particular modern browser. Last but not least, this code bloat makes the jQuery library hard to study for educational purposes.

However, even in a browser that supports all the modern stuff, the jQuery API is still more concise than the native methods. Besides, there are tons of plugins that depend on it, so if you decide to implement everything in native JavaScript, you can’t use them.

What I want to build is a fork of jQuery that is refactored so that all the extra code for working around browser bugs removed and all the code replaced by native functionality, where possible. All the ugliness removed, leaving a small, concise abstraction that only uses the current standards. Something like jQuery: The good parts. It could also serve as a benchmark for browser standards support.

The API will work in the exact same way and pass all unit tests (in modern browsers, in cases where they are not buggy) so that almost every plugin built on top of it will continue to function just as well. However, the jQuery library itself will be much smaller, with more elegant and easy to understand code.

So, who’s with me? Do you find such an idea interesting and useful? Would you want to contribute? If so, leave a comment below or send me an email (it’s in the about page). Also, please let me know if you can think of any other uses, or if there’s already something like that that I’ve missed.

Categories
Tips

Get your hash — the bulletproof way

This is probably one of the things that everyone thinks they know how to do but many end up doing it wrong. After coming accross yet one more super fragile snippet of code for this, I decided a blog post was in order.

The problem

You want to remove the pound sign (#) from location.hash. For example, when the hash is "#foo", you want to get a string containing "foo". That’s really simple, right?