Saturday, July 31, 2010

RightJS 2.0.0-rc Is Out

Okay folks, RightJS 2 came to the point where it has a proper number and the '-rc' suffix in it's name. And here are some notes on the new sweet features we have since the beta release.

You can download the build over here, the archive contains both normal and safe-mode builds.

Generally this is almost the final line, I've finished packing it with new features and this is practically all we will have in the actual 2.0.0 release. There might be some tweaks here and there during the plugins and UI modules porting, but nothing dramatic. So lets check what we've got.


Dom Wrappers

In RightJS 2.0 we have a new kick-ass object oriented dom-wrappers system. Our dom-wrappers are essentially classes, with types, inheritance and all the nice functionality injection features. Currently we have the following wrappers Window, Document, Event, Element, Form and Input, which formerly was known as the Form.Element unit.

Dom-wrappers work transparently and have all the same nice API we had in RightJS 1, the only difference is that instead of the actual dom-element all the methods now operate with dom-wrappers.

$('element-id')  // -> dom wrapper
$$('#css .rule') // -> a list of dom-wrappers

All the dom wrappers are inherited from the same unit called `Wrapper` and have a common property called `_` which refers to the raw dom element, for example

$('element-id')   // -> Element wrapper
$('element-id')._ // -> the actual dom-node

$(window) // -> Window wrapper
$(window)._ // -> the window object

$(document) // -> Document wrapper
$(document)._ // -> the document object

So every time when you fill like it, you can always quickly access to the raw unit the same way across all the wrappers.


Dom-Wrappers Typecasting

As you might noticed we have three types of wrappers for dom-elements, the Form and Input classes are subclasses of the Element class and when you access your dom-elements they dynamically typecasted

var element = $('my-form');
element instanceof Element; // -> true
element instanceof Form; // -> true
element instanceof Input; // -> false

var element = $('my-input');
element instanceof Element; // -> true
element instanceof Input; // -> true
element instanceof Form; // -> false

This way you can check which type of element do you have and you can extend all of them separately


Element.include({
global_method: function() {}
});

Form.include({
forms_only_method: function() {}
});

Input.include({
inputs_only_method: function() {}
});

You even can use polymorphism and use the same method names

And you also can define your own types, for example

Element.Wrappers.TABLE = new Wrapper(Element, {
orderBy: function() {}
});

Later on there will be also private dom-wrappers which you can use in your app without extending the RightJS core and interfere with other applications.


Bubbling Dom-Events

RightJS also received several fixes for the traditionally problematic dom-events like focus, blur, change and submit, now all of them properly bubble on all the supported browsers.

There is nothing kinky about it I didn't use any special event names, just use the usual ones like nothing happened.

$(element).on({
focus: ...,
blur: ...,
change: ...,
submit: ...
});

I also added the custom events bubbling. If in RightJS the custom events didn't go anywhere from the node where you fired it, now they properly bubble up to the document object, so you can take advantage of them using the events-delegation technique.

Speaking of which.


New Events Delegation API

In the later releases of RightJS 1.5 we already had some elements of the events-delegation feature support, now it's time to take it to the next level.

First of all the String unit now has all the same API as Element, so you don't need to learn nothing new, just use what you already know.

"#div .span".on('click', function() {...});
"#div .span".onClick(function() {});
"#div .span".onClick('addClass', 'marked');

// you also can make the normal checks
"#div .span".observes('click'); -> true
"#div .span".observes('mouseover'); -> false

// and you can unbind the listeners the usual way
"#div .span".stopObserving('click', function() {});

Then the Event.delegate and Event.behave methods are gone and instead of them we have a proper events delegation API on dom-wrappers which look like that

$(document).delegate('click', '#css.rule', function() {});
$(document).delegate('click', {
'#css.rule1': function() {},
'#css.rule2': function() {}
....
});

// delegation checks
$(document).delegates('click');
$(document).delegates('click', '#css.rule');

// disabling delegation
$(document).undelegate('click');
$(document).undelegate('click', '#css.rule');

More of that the same API was adde to the Element wrapper so you can attach your delegating listeners at any level of your web-page

$('my-list').delegate('click', {
'li.one-thing': function() {}
'li.another': function() {}
});

This way you can scope the delegation to some block of your document and handle the things locally.

You also can delegate custom events too

$(document).delegate('bingo', {
'#one': function() {}
'#another': function() {}
});

$('one').fire('bingo');
$('another').fire('bingo');

Generally there are no limitations and you handle any sort of events simultaneously via the same api.


$$ Is Back!

As you might noticed I moved the $$ function back. I tried to use the jQuery-like unified $ method but didn't like it and brought the $$ back.

Amen.


Semi-Safe Mode

As you might know RightJS 2.0 will have the safe-mode build, which will hide everything behind a single RightJS object and won't extend a thing on the user's page.

A typical use case would look like that

RightJS.$('element-id').onClick(....);

var MyClass = new RightJS.Class({
...
});

There is also a way to access the language unit extensions by passing variables through the RightJS object

RightJS(['boo', 'hoo', 'doh']).filter('includes', 'oo');
RightJS(4).times(function() { .... });
RightJS('boo hoo').endsWith('hoo');

In the RC release I added a semi-safe API for the non-safe builds, meaning you can put your variables through and access the RightJS units via the RightJS object. This way if you need say to write a plugin that supposed to be working in both safe and non-safe modes, you can simply write it for the safe-mode and it will be working in the non-safe mode too.


JSONP Support

In RightJS 2.0 there is the JSONP format support for the Xhr unit. It all works transparently via the same Xhr API with all the same principles, the only thing is that now you have the jsonp option where you can specify your callback name variable, or simply use true for the default 'callback' value.

new Xhr('/some/url', {
jsonp: 'myCallback',
onSuccess: function() {
// ....
}
}).send();

Xhr.load('/some/url', {jsonp: true});

It even will assign the responseJSON and json varaibles

Xhr.load('/some/url', {
jsonp: true,
onSuccess: function() {
console.log(this.json);
}
});



New Language Level Methods

There are also several new javascript level extensions were added. Object.each, Array#reject (which is useful with calls by name), Array#min, Array#max, Array#sum

Probably something else that I have forgotten.



The Next Steps

Now when the core is finished, there are quite a lot of work with porting the plugins to the new version and reworking the documentation. The site also needs to be reworked to support the new building system.

At the moment I estimate it like 2-3 weeks of work. So the delivery-day is somewhere by the end of summer.

Okay, think that's all I have for know.
Take care!

Friday, July 30, 2010

Why Albeit Packing Is A Bad Idea

Okay I did it quite a lot on RightJS, but I've learned my lesson. A quick and self-explanatory example would be like that.

Say you have the following piece of javascript

a1.looooongMethod();
a2.looooongMethod();
a3.looooongMethod();
a4.looooongMethod();
a5.looooongMethod();

Being an optimization junky, you might think, "Oh! I can make it smaller!"

var b = 'looooongMethod';
a1[b]();
a2[b]();
a3[b]();
a4[b]();
a5[b]();

Then you look at the size, the first one weights 104 bytes and the second one 70.

"Woohoo!", you say, "30% optimization!". And will be wrong.

Because when a web-server gzips your code, the first one will weight 61 bytes and your optimized version will be... TADA! 72 bytes. Yup, bigger than it was before 8)

That's the whole story. Gonna go and unoptimize things back now.

Monday, July 19, 2010

Freezing Terminal.app in OS X

I ran in a strange bug yesterday on my macbook. Suddenly the Terminal.app started to freeze when you lunch it or open another window.

I killed half a day trying to figure out what's wrong with my HDD, and trying to restore parts of the system from a backup, but then found out that the problem was in another place.

So if you run into the same issue the cure is simple.
sudo rm -rf /private/var/log/asl/*

Apparently there is some problem with the log files that cause circular read/write calls, so when you nuke the old logs, it will get just fine

Tuesday, June 29, 2010

The RightJS DOM-Wrappers Speed

Okay folks, there is your next brainwashing session to keep you hooked to the right stuff.

When I announced that RightJS is switching to dom-wrappers, some of you seems started to panic. "Oh, no!", you said, "RightJS is going down, because native extensions murk dom-wrappers any day at any time!"

Well people, you just haven't seen the right wrappers yet 8). Here is the shot of the new engine in its raw, not fully optimized state.


FF 3.6.6


And so you didn't think that it's just FF, here is a shot in Opera.


Opera 10.54


Don't have a short for IE though, because didn't quite make it there yet, but you can imagine that it will go sky rocket, because there will be no elements extending anymore.

Some of you, young and sharp, might notice that, the ID access went down for a notch. That's all because of you guys, that's because in RightJS 2, you'll have the same $ method behavior as you have in your beloved jQuery, meaning you'll navigate it like that.
$('#boo-hoo'); // -> an element by id
$('div.boo, div.hoo'); // -> elements by the css-rule

There also will be things like $(window) and $(document), so you'll feel yourself like home.

That's about it. Hold on to the next session!

Saturday, June 26, 2010

RightJS Development Status

Hey folks, to keep in touch, some notes on the RightJS development status.

As you probably already know the next step in the RightJS evolution is coming. Currently I do all the fixes and main feature updates in the 'master' branch and all the dramatic changes go into the 'two.o.o' branch. So if you'd like to see what's going on, go and check it out from github.

So what's actually going on?

New building system

First of all I move the source code building system from the amaturish concatenation of some pieces of code to more serious layouts based builds.

What does it mean?

It's fairly simple. Instead of having all sorts of small isolated pieces of code, now we have one global function which isolates the RightJS initialization process inside. It doesn't mean that RightJS now closes its insides like jQuery does. No, all the crazy monkey patching abilities remain in place and it is still an open architecture, but now we don't need to worry about accidentally polluting the global scope with some temporary variables, plus it gives us a great deal of optimization abilities in speed and size.

Secondly, now we use the google's closure compiler to compact the javascript code. It works a bit faster and provides slightly better results than my FrontCompiler.

I haven't finished yet with all the size optimizations yet, but the layout based builds + google-compiler are already giving us some benefits. Despite that I already added quite a few new features and methods, the size of the builds went down at about 1K and goes like 40K of the minified (not packed) code, which is about 15K in gzip.

Then it seems like I'm going to get rid of the albeit-packed builds. The reason is that most of the web-servers those days use gzip compression and in this case there is no significant difference between the packed and minified versions. And as the packed version initializes slower than the minified one I think there is not much of reasons to continue to support it.

In any case, you'll be able to albeit-pack RightJS with FrontCompiler at any moment by yourself.


The Safe Mode

The are another reason for the layouts based builds - the safe-mode development. And currently there are several directions which the safe-mode development goes.

First of all the name spaced mode. Now as RigthJS initializes inside of a layout, it extends the global scope only at the very end. So you can easily have a name spaced build by removing one line of code from the end of the file and all the RightJS global objects will be available in the scope of the RightJS object.

You still will have all the native and dom object extensions with all the benefits and troubles and your code would look like that

with (RightJS) {
var MyClass = new Class({
include: Options,

initialize: function(id) {
this.element = $(id);
}
}
}

Or, if you're against the with calls, like that

var MyClass = new RightJS.Class({
include: RightJS.Options,

initialize: function(id) {
this.element = RightJS.$(id);
}
}


The second direction is so called condom-mode. The idea is that we initialize RightJS in a separated IFrame and then hook up the main window to the functionality via the RightJS object. In this case you have almost complete isolation of the contexts, RightJS won't touch the main window units and you also will have access to the RightJS fancy native extensions like that.

var R = RightJS;

R('boo.hoo').endsWith('hoo');
R(4).times(...);
R(function() { }).bind(...);
R([1,2,3,4]).without(2,3);
R.$('element-id').onClick(....);

RightJS will extend only those dom-elements which you actually work with. So you'll still have the RightJS speed and easy goingness, but you also have the ability to safely implement say widgets on someones page.

The condom mode is mostly ready, it still has some unfinished parts with the window and document access, but all the other things are already working. you can build and play with it in the `two.o.o` branch like so

rake build OPTIONS=safe



The DOM-Wrappers

The condom-mode is just a step to the next level, it is an interesting thing but it still does extend dom-elements you access. So I'm currently working on the next step which is the dom-wrappers.

The idea is to replace the direct dom-elements access with some artificial proxy which will have all the same interface as a normal dom-element but without actually extending the dom-elements themselves. The reasons are obvious, it's a peaceful coexistence with another scripts on the page and better cross-frame scripting abilities/performance.

This feature is still in progress and you'll see the first results in about couple of weeks.

After that, that's it, we release.


The Summary

One way or another, with the 2.0.0 release we should fix the only problem that wrong with the right javascript framework, the safety. We will have normal quick and naughty builds as we have now, but we also will have options with the namespaced and condom modes.

Which means we will have a rock-solid safety against the anxious MSIE or any other browser that will think its smarter than others, and you also will have the ability to use RightJS to develop widgets in the safe-mode.


That's about it.
Have fun!

Wednesday, June 2, 2010

Postion fixed in IE6

If you old enough you might remember that wonder of technology we used to admire something like ten years ago, which also known those days as the zombi-browser aka IE6. And if you old enough and unlucky enough to have a need to make something with "position:fixed" under that browser, you might think about the usual approach with hooking up the window.scroll event with some piece of javascript and move the thing manually.

My dear friend, there is a better way to hack the shit out of it. Presenting you the CSS hack which will keep your element fixed at the bottom of the window
div.sweet-div {
position: fixed;
bottom: 0;

/* IE6 position:fixed hack */
_position: absolute;
_bottom: none;
_top:expression(eval(document.compatMode && document.compatMode=='CSS1Compat') ? documentElement.scrollTop +(documentElement.clientHeight-this.clientHeight) : document.body.scrollTop+(document.body.clientHeight-this.clientHeight));
}


Enjoy!

Friday, May 21, 2010

Making a Colorpicker

The other day I've been implementing this colorpicker widget for RightJS and now I'd like to share some mathematics and mechanics behind the widget.

I won't bore you to death describing the actual layout, just some necessary theory and math. And I also will use RightJS semantics. Well, just because I love it.

The Color Theory

Lets start with a bit of a theory. Every giggling school girl those days knows that any color can be created by a proper mix of three basic colors, red, green and blue. That's a brilliant idea, but the problem is that not many people actually can use it. Personally me, I don't know anyone who can instantly say how much of every color you need to take to create say a color of coffee and milk.

And because of this problem the humanity created another, more natural way of color picking which is based on another three dimensions: tone, saturation and brightness. And the main idea of the colorpicker widget is to convert one system into another.

The Tone Parameter

The tone picker usually looks like a vertical bar and represents the following system of colors.



The principle is that with this tone scale you can have any tints available with full saturation and brightness. Note also that in every point of the scale, one of the colors is always has a zero value, and at least one of them has the full value.

Keep also in mind that this scale is some sort of closed circle, the end on the right is actually joined with the beginning on the left.

The Saturation And Brightness

The saturation and brightness field usually looks like that.



The saturation parameter is zero at the left side and have the full value on the right. The brightness is full at the top and zero at the bottom. This way, you will always have the white color at the top left corner, your current tint color at the top-right corner and a black line at the bottom side.

With those three handlers you also can chose any visible color but in more natural way.

Converting TSB into RGB

The first task of the colorpicker is to convert the tint, saturation and brightness parameters which the user picks into the actual RGB value.

It was proven that the best way of keeping your values in this case is if you keep your TSB parameters in float values of range 0..1 and RGB values in integers of range 0..255. This way you won't have systematic round up errors and it will be working faster.

So your TSB -> RGB script will look like that
var tint = [1, 0.5, 0];
var saturation = 0.6;
var brightness = 0.4;

var color = [0, 0, 0];

for (var i=0; i < 3; i++) {
color[i] = 1 + saturation * (tint[i] - 1);
color[i] = (color[i] * brightness * 255).round();
}
The principle is simple, first we combine the tint and saturation which will give as a raw color in range 0..1, then we apply the brightness parameter and convert the float value into a 0..255 integer.

Converting RGB into STB

The backward conversion is a bit trickier. I've drown a simple picture to help you understand the principle



Say you have some RGB color with values in range of 0..255. Remember our tint picture, where one value is always 1 and another is always 0. So this smaller area between the green and red values is the same thing, if you take it and normalize to the 0..1 range you'll have your clear tint values. The brightness parameter will be the proportion between the brightest color and the 255 value, and your saturation is relation between the minimal color to the maximum.

The script looks like that
// the initial RGB value
var color = [200, 100, 50];

// finding the minimal and maximal values
var color_sorted = color.clone().sort(function(a,b) { return a-b; });
var max = color_sorted[2];
var min = color_sorted[0];

// calculating the brightness and saturation
var brightness = max / 255;
var saturation = 1 - min / (max || 1);

// calculating the tint
var tint = [0, 0, 0];
for (var i=0; i < 3; i++) {
tint[i] = ((!min && !max) || min == max) ? i == 0 ? 1 : 0 :
(color[i] - min) / (max - min);
}
It is pretty much straight forward, but we also have some failsafe conditions like (max || 1) and (!min && !max) in case if all the RGB values are zeros.


HEX to RGB Conversions

And couple more things which you also will need. Converting your 0..255 colors array into HEX and RGB formatted strings back and forth.

Converting an array to a HEX value is simple
'#'+ color.map(function(c) {
return (c < 16 ? '0' : '') + c.toString(16);
}).join('');

Converting RGB string into an array of values looks like that
if (match = /rgb\((\d+),(\d+),(\d+)\)/.exec(value)) {
return [match[1], match[2], match[3]].map('toInt');
}

And converting any HEX color into an array can be done like that
// converting the shortified hex in to the full-length version
if (match = /^#([\da-f])([\da-f])([\da-f])$/.exec(value))
value = '#'+match[1]+match[1]+match[2]+match[2]+match[3]+match[3];

if (match = /#([\da-f]{2})([\da-f]{2})([\da-f]{2})/.exec(value)) {
return [match[1], match[2], match[3]].map('toInt', 16);
}

Well, that all you need to know to make one cool colorpicker of yours.
Enjoy!