qTip2 :: Pre-release changes (AKA What happened to my qTip styles!?)

qTip2 is under-going to considerable changes over the next few weeks, with a new website on it’s way, a brand new build system to go along with it, and several new features and documentation updates. However, there are some breaking changes as qTip2 marches on to it’s final 2.0 release, and firmly out of nightly status!

As many of you watching GitHub repository will know, the class_rename branch, which removes dependency upon the ui-tooltip* classes used by jQuery UI, has been merged back in the master branch. This means of course, that any of you relying on the old class structure in your code, need to update to the new classes names. A list of old and new class names is listed below to ease this!

  • #ui-tooltip-<id>  → #qtip-<id>
  • .ui-tooltip  → .qtip
  • .ui-tooltip-content  → .qtip-content
  • .ui-tooltip-titlebar  → .qtip-titlebar
  • .ui-tooltip-title  → .qtip-title
  • .ui-tooltip-button  → .qtip-close
  • .ui-tooltip-icon  → .qtip-icon
  • .ui-tooltip-focus  → .qtip-focus
  • .ui-tooltip-hover  → .qtip-hover
  • .ui-tooltip-default  → .qtip-default

As you can see, the ui-tooltip- prefix has simply been replace with the qtip- prefix. This applies to every in-built and CSS3 style too (in basic.css and css3.css respectively).

A full list of changes is forth-coming, but for now this is the only breaking change you’re likely to encounter. LEt me know via the issue tracker if you notice any more!

flattr this!

var, commas and equals

Working with JavaScript for a while (or any other language for that matter) you tend to pick up on a lot of nuances particular to the language, but even long time users get tripped up every now and again, as did I with a recent namespace issue involving… you guessed it: var, commas and equals!

Take for example this: 

function invoke() {
	var foo = bar = 'uhoh'; // bar pollutes upper scope!
}
invoke(); // Invoke the invoke!

At first glance, it might seem as if both foo and bar variables should be declared within the local invoke methods scope, but this alas is not the case, and for good reason!

Since statements are evaluated right to left, the script first attempts to set the bar variable to “uhoh”, and since no bar variable is defined in our local scope (yet), it travels up the scope chain checking for a defined foo variable, until it gets to the window object, (or possibly some other scope if this is embedded within other methods…), and sets foo as a property of that scope… we’ve just polluted the global namespace!

Perhaps not what you’d expect upon first glance, and an easy thing to get tripped up on. The solution is simple,and actually a little syntactically nicer (i.e. more explicit) in my opinion:

flattr this!

Holiday

If you’re looking to get in touch over the next week (til the 17th) I’ll be over in sunny Greece getting my tan on and attempting to spend my euros before they revert to the Drachma! The support forums will look a bit dead during this time, so please be patient if you’re filing a bug or support request on there! Caio for now.

flattr this!

JavaScript iOS version detection

Small JavaScript snippet to detect the iOS version in use by the user. Note: This relys on the user agent always being correctly set, which it isn’t!

flattr this!

qTip2 styles update

In the recent commit today a re-factoring of the CSS stylesheets took place in order to simply the styles qTip2 uses, as well as changes  to the underlying tips code to cope with these changes. The biggest change is the movement of the border and border-radius declarations from the titlebar and content elements to the main ui-tooltip element. Thanks to this, many duplicate styles could be removed from the stylesheet for a 10% size saving!

This will likely effect the styling of your tooltips upon updating, and you may see black borders on your tooltip “tips” until you move the border colour declarations to the top ui-tooltip element. The ui-tooltip-shadow class now only works in IE9+ now because of this modification and removal of the IE9> filter declarations. This was done because applying a filter to any element renders the overflow property useless, as reference from this blog post comment:

What I think happens in IE<9 is it “designates” a square where DirectX can render on top of a hasLayout box based on `width`+`height` properties, and if content tries to expand outside that box then it’ll be cut off. I think that in block elements which have filters in them that everything in them is also rendered by DirectX. (As a side effect which you may already be aware of, text rendered by DirectX wasn’t ClearType aware and so in particular bolded text rendered garbled in IE6, leading to the devs to turn off ClearType entirely in filtered elements in IE7-8.)

It sucks, but if you want native shadows in IE you’re going to need to do some hacking! Sorry guys.

Thanks to Tanguy Krotoff for the motivation and bug reports behind this!

flattr this!

qTip2 – Tip plugin’s dimension options updated

For those of you using the qTip2 nightly builds, as of commit 970cfabacd the tip plugin’s width and height options have changed slightly to become relative  to the tips position on the tooltip.

When the position of the tip is on the horizontal sides of the tooltip i.e. the left or right, the width and height are switched. This is done to ensure the tip dimensions stay as you’d expect no matter what position the actual tooltip is in. To demonstrate this, see the jsFiddle example below of the past and current implementations.

Special thanks to sparky672 for pointing out this inconsistency.

flattr this!

Efficient JavaScript Delta-encoding – Merging JSON objects

As I’m now in my 3rd year at Newcastle University, I was expected to produce a 40-page thesis over the last few months on a subject of my choice: 2D Multiplayer game using browser-native HTML5 standards and the Node.js run-time.

I decided early on to use the Client-Server architecture after reading up on several articles, particularly Glenn Fiedler’s “What every programmer needs to know about game networking” and Valve’s awesome multiplayer networking overview. However this meant a lot of extra work would be needed to make it playable, including the topic of this post: Delta-encoding.

Delta encoding is a way of storing or transmitting data in the form of differences between sequential data rather than complete files.

That is, instead of sending a full game state to every client, we send only the differences between the new and last state, which gives us considerable bandwidth savings.

How do you implement something like this efficiently in JavaScript? It has no native method for merging objects, and using loops just doesn’t cut it performance-wise cross-browser. Thankfully though, since the objects we’ll be merging have a pre-determined number of properties, we can avoid looping on each merge and take a shortcut.

First off here’s the full code listing for you to digest before I go into the details of how it works:

var Entity = function(params) {
	this.merge(Entity.defaults);
	this.merge(params);
};

Entity.defaults = {
	position: [0, 0],
	velocity: [0, 0],
	acceleration: [1, 1]
};

Entity.merge = function(obj1, obj2) {
	var cons = obj1.constructor,
		func = obj1._mergeFunc, props, p, i;

	// Create the merge function if one isn't already defined
	if(!func) {
		func = '';

		// Loop over the first objects default properties and create our merge function
		if((props = cons.defaults)) {
			for(p in props) {
				func += 'if(typeof obj2.'+p+' !== "undefined") {' +
					'obj.'+p+' = obj2.'+p+';' +
				'} ';
			}
		}

		// Create and store the new function
		func = cons._mergeFunc = new Function('obj', 'obj2', func);
	}

	// Run the merge function and return the first object
	return func(obj1, obj2), obj1;
};

Entity.prototype.merge = function(obj) {
	return obj ? Entity.merge(this, obj) : false;
}

Important notes:

  1. This will only merge properties defined in the Entity.defaults object.
  2. Variables passed by reference i.e. Objects and Arrays, are not copied but simply set by reference.
  3. Hence, any Arrays or Objects which are merged into the first object are references to those in the second, so any changes will appear in both as it is the same object.
  4. This method should only be used when you intend to discard the object that is to be merged i.e. the second object, which is the case in merging delta state objects.

The general idea behind the code is simple: Rather than using a loop to iterate over the second objects properties and merge them in upon each call to the merge function, we take advantage of the Function constructor, which allows us to compile functions dynamically. This dynamically created function does the following when executed:

  1. For every property in the obj1‘s constructor property (Entity.defaults):
  2. Check if the property within the defaults object is also defined in the second object.
  3. If it is, set the first objects property value to that of the second object.

Check out the jsPerf results that compare the usual iterative loop method with the above cached merge method.  We can see a pretty tremendous increase in cross-browser ops/second using this approach, staggeringly so in Chrome and it’s open-source counterpart, making handling multiple merges between several objects a breeze.

So there you have it, an efficient way to merge objects with pre-determined properties for use in Delta-encoding. Stay tuned for the next article which I will discuss an efficient way of producing delta states on the fly.

flattr this!