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!

Tuesday, May 18, 2010

Automatic Records Search in Rails

There is one neat trick I'd like to share. In many cases, especially when you work on intranet applications, you need say to check some security settings against the data-records before you let the request to access the actual method in your controller. Normally, most folks do that by adding before filters to find the records, like that

before_filter :find_this
before_filter :find_that

def find_this
def find_that

When your application grows and starts having something like a dozen models, plus you might have nested routes where you need to check the security against the nested elements too, those things tend to get really messy.

So here is a simple method which I use on my projects

before_filter :find_restful_units
def find_restful_units
params.each do |key, value|
if key == 'id' || key.ends_with?('_id')
unit_name = key == 'id' ? controller_name.singularize : key.gsub('_id', '')
unit_class = Object.const_get(unit_name.camelize)
instance_variable_set("@#{unit_name}", unit_class.find(params[key]))
end
end

rescue NameError # just hung up if there is no such unit
nil
end

You put this in your ApplicationController and it will automatically find and assign all your models, the actual and the nested ones.

This makes controllers much cleaner and you always have your models extracted and ready to use in the standard way.

Wednesday, April 28, 2010

RightJS vs. MooTools In The Game of Mines

This weekend I had some fun implementing the good old game of mines using RightJS. The result is pretty cute, you should check it out. No, really, you will like it.

The thing is that about year and a half ago I implemented the same exact game using MooTools, you can check it out over here, and well, I have some words to say on this regard.

Okay, I certainly did get better during this last year and you might say that I know RightJS better than MooTools, but here are some numbers. (For the sake of a clean experiment I specifically didn't look into the old code before or during the development and eventually gone in a different approach in the implementation.)

With MooTools I was working on the game almost the whole week, I didn't work full time and as I recall it you could say it were good three, three and a half days of work. The result is 14k build of JavaScript + about 5k of CSS, which is about 19k in total.

In case of RightJS it took me about 6 hours to implement the whole thing from top to bottom, and the result built of JavaScript + CSS is just 9K of code.

Yup, a twice as compact result and about four times less time spent. More of that I believe that RightJS implementation has much cleaner and easy to understand code.

The really sweet things in case of RightJS were the number extensions, simplified collections processing and built in Observer unit. It feels so good and natural to implement game logic with them! I really enjoyed those things!

Well, that's about it.

Monday, March 29, 2010

RightJS + Rails = Love

As the right-rails (the Ruby On Rails plugin for RightJS) was updated recently, lets have another brainwashing session. This time for Rails people.

If you're a kind of a pragmatic developer, you're probably asking yourself "why would I fall in love with this new thing? I already know Prototype and jQuery why would I need something else?", and believe me, I know precisely what you mean.

But ask yourself, being a Rails developer, were you ever happy of doing AJAX features in Rails? No, I mean, not like first two weeks on rails, or things like "it's working". I mean really happy, did you feel funny about Prototype or jQuery? Did they make the butterflies in your stomach fly? Literally.

Think about it. The Prototype support on Rails was always a kind of a flimsy hack and most serious developers don't really use those RJS stuff. And with jQuery you were always left alone to deal with all those kinky JavaScript stuff. That's good if you are a JavaScript guru and know your magic. But what if you are not, and what about the actual Rails business anyway? Did any of the frameworks really helped you in any way to be an actual Ruby/Rails developer?


How Is RightJS Different?

First and most important thing you should know about RightJS is that it was written by a Ruby/Rails developer for Ruby/Rails developers. And despite the fact that from time to time we have all those arrogant promotions and we mock jQuery folks constantly. RightJS is not really about JavaScript itself. It is something quite opposite.

RightJS is all about getting JavaScript off your hair. RightJS is made to help Ruby developers to deal with JavaScript tasks, it reflects Ruby way of handling things, has mostly Ruby syntax and many of its key features are copies of Rails features.

RightJS civilizes JavaScript and brings it closer to Ruby developers.

But we didn't came here to talk about JavaScript, right? What about Rails itself?


Lets Make The Butter Fly

How much time does it take to make a date-time field with a calendar in your framework?

Let me spare you the calculations time and show how it looks like in RightJS + RightRails.

<% form_for(@zing) do |f| %>

<%= f.calendar_field :dead_line %>

<% end %>

Nope. I didn't forget nothing. `calendar_field` is all what it takes. RightRails automatically includes all necessary JavaScript, CSS and I18n modules on your page and initializes the fields, so you don't need to worry about a thing.

More of that, it will automatically swap between builds and source code for JavaScript in production and development modes.

So, would you like some rater or slider on your form?

<%= f.rater_field :rating %>
<%= f.slider_field :completeness %>

Oh, I know! You'd like some autocompleter, right?

<%= f.autocomplete_field :category, :url => categories_path %>

Would you like the autocompleter to be RESTful design and hard-caching friendly? No problem!

<%= f.autocomplete_field :category, :url => "/categories/%{search}.js" %>

Here you go.


And That's Not All

The fun is not over, not by a long shot. The next feature is that RightRails comes with a brand new RJS generator, and that's not just a collection of dummy functions like in the case of the Rails original RJS templates.

The new generator lets you literally write JavaScript in Ruby and more of that it allows you to mix Ruby and JavaScript calls in one flow escaping and transforming variables on fly.

For example this is how the annoying nested forms look like when you make them with RightRails.

<% form_for(@zing) do |f| >

<div id="categories">
<%= render @zing.categories %>
</div>

<%= link_to_function 'add' {|page|
page[:categories].insert(render(Category.new))
} %>

<% end %>

See, the `insert` method is a JavaScript function, the `render` is the ActiveView method, `Category` is your model. All in one flow with automatic types conversion. And it is not just a list of predefined functions, you can literally do whatever you want.

update_page do |page|
page[:todos].update render(@todos)

page[:todos_count].innerHTML = @todos.size + ' Items'

page[:todos].select('li').each do |item|
item.onClick('toggleClass', 'marked')
end

page.json_variable = @todos.to_json
page.items_count = @todos.size
page.list_updated = true

page.alert "There are #{@todos.size} items left on the list"
end

There are no limiatations.

Mommy Look, More Fancy Stuff!

Oh yes mommy, there are! On top of all RightRails has a conventional interface to cover the most common AJAX CRUD operations. Let me show you.

Say here's your remote form

<% remote_form_for(@zing) do |f| %>

<%= f.text_field :name %>
<%= f.file_field :picture %>

<%= f.submit 'Create' %>
<%= image_tag 'spinner.gif', :class => :spinner %>

<% end %>

And here is your controller method

dev create
@zing = Zing.new(params[:zing])
if @zing.save
render rjs.insert(@zing)
else
render rjs.replace_form_for(@zing)
end
end

The `rjs` method provides access to the new RJS generator from the controllers, and `insert` and `replace_form_for` are the AJAX operations interface.

It all works over the Rails conventions, the `insert` method looks for the class of the `@zing` model, finds related partial, renders it and generates a piece of JavaScript that inserts the HTML into an element with the `zings` ID.

The `replace_form_for` method will render a new form with all the error messages for the @zing model and generate JavaScript that will update the form on the page.

RightRails has a collection of such methods for all CRUD operations.

Note also that I've put a file field and a spinner image on the form. RightRails automatically and transparently processes files uploading too, basically there is no difference whether your form has files or not, it all has the same API. And the RightJS when submits a form via AJAX, automatically searches for images with the `spinner` class and uses them as spinners, you don't need to hook them up with callbacks manually.

Summary

I'm not going to indulge you with obvious conclusions, I'll just tell you that I've already used RightJS + RightRails on two production projects and it saved me hell of a lot of time and nerves on JavaScript and AJAX development.

Well, it was designed to.

Saturday, March 27, 2010

Supervisor Mode With Authlogic

Supervisor mode is a feature that allows site admins to quickly switch to any other user (say customers) and take a look at the site the same way the customers see it, may be perform some actions from this user, etc.

So here is a simple tip how you do that using the Authlogic plugin for Rails.

First of all you'll need couple new routes, one to switch to some user, another to get back to the admin mode.

map.super_login '/login/:id', :controller => 'user_sessions', :action => 'super'
map.back_login '/login/back', :controller => 'user_sessions', :action => 'back'

I used two new methods named 'super' and 'back', which are not exactly RESTful, but you can use 'edit' and 'update' if feel particularly evil about it. They are normally not used in the 'user_sessions' controller.

After that on the list of customers you add links to switch under this user, for example like that

....
%td= link_to 'Supervision', super_login(user)
....

And finally you'll need those two methods in your `UserSessions` controller

class UserSessions
.....
# switches under this user
def super
raise AccessDenied if !admin?
session[:original_admin_id] = @current_user_session.user.id
@current_user_session = UserSession.create(User.find(params[:id]))
redirect_to '/'
end

# switches back to the admin -mode
def back
raise AccessDenied unless @current_user_session && session[:original_admin_id]
@current_user_session = UserSession.create(User.find(session[:original_admin_id])
session[:original_admin_id] = nil
redirect_to '/'
end
.....
end

The idea is simple, in the first method you stash the original user_id in a session variable, then create new user session with that specific user. And in the second one we restore the original user in the session.

You also might consider to add two methods like `current_user` and `current_user=` in your application controller they are pretty useful and will make your code cleaner.

class ApplicationController
...
# returns the currently logged in user
def current_user
@current_user_session.user if @current_user_session
end

# assigns the currently logged in user
def current_user=(user)
@current_user_session = UserSession.create(user)
end
...
end


That's all. Have fun!

Friday, March 5, 2010

Mechanize and MultiSelect fields

Mechanize is a little handy tool that allows you to perform all sorts of HTTP requests in Ruby. It automatically emulates all sorts of browsers, handles cookies, headers and stuff, which is really useful when you need to harvest some data from sites that don't have any computer friendly feeds.

I'm using it on my current project and run into a small problem. It doesn't work nicely with array data, like for example multiselect fields emulation, so when you do something like that

agent = Mechanize.new

agent.post('http://boo.boo/boo', {
'param[]' => ['one', 'two', 'three']
});

In the reality it sends the 'one' value only. I've sent a little patch to the devs, but it seems like it will take time before they do something about it. So here is how you fix it in your rails app.

In any initializers in your `config/initializers/` directory add the following lines.

class Mechanize::Form::Field
def query_value
if @value.is_a?(Array)
@value.collect{ |v| [@name, v || '']}
else
[[@name, @value || '']]
end
end
end

After that it will be just fine.

Tuesday, March 2, 2010

My Top 5 on that RightJS vs. jQuery Question

During the last several months of RightJS promotion, the absolute hit among the questions of 'what?' and 'why?' was understandable the question of what is the difference between RightJS and jQuery.

There were lots of talks about RightJS speed and then more about speed, and then we had some abstract talks about its philosophy and its way among the others and we also have that simple comparison page.

And what I find important in a brainwashing process is systematicness and methodicalness. We did some talks on an abstract matter, we did some talks on the opposite side of scale with performance tests, now lets touch something real. Something in the middle. And probably summarize some previous talks.

So here it is, your next session; my top 5 as I see it at this morning.


1. Syntax

When I'm saying "jQuery is like PHP", first of all I mean the nature of its syntax. When you boil it down to the essence, both of them are just collections of helper functions. And as PHP defines a new kinda language upon C, almost the same way jQuery defines a new language upon JavaScript.

RightJS on the other hand is built right into JavaScript itself. In 90% it is the good old JavaScript, where we bring features from later JavaScript specifications and spice it with some standard features from more serious dynamic languages like Ruby and Python.

As the result, when you learn jQuery, you mostly learn jQuery, I've seen many nice fellas around, who know jQuery quite well, but stuck when they needed to do simplest things in pure JavaScript.

When you learn RightJS, you learn the actual JavaScript, yes we have some funny shortcuts and features that make mature web-developers happily giggling like school girls, but all of them are built upon JavaScript standards.

RightJS makes you do the things in JavaScript and do them right. And because of that, whatever the future brings, your knowledge and skills will remain with you.


2. The Actual STL

When I read someone saying "jQuery is the JavaScript STL", it usually makes me laughing so much, that my neighbors probably think that I've finally went nuts and going to blow off the Kremlin.

Now, don't get me wrong, I have no problems with jQuery's popularity and I respect that. Well, at least, as long as it keeps me away from people who doesn't know the difference between popularity and standards.

jQuery is a DOM DSL at best. First of all it doesn't have anything to do with JavaScript itself, because it's a DOM wrapper, secondly there is nothing standard about jQuery in terms of JavaScript. Take for example a look at the .each() function where the arguments are in just the opposite order than they are in the JavaScript own Array#forEach method.

If you need something that actually follows the standards, you should take a look at RightJS. It brings many standard features from later JavaScript specifications, plus many other none the less standard features from server-side programming languages, for example methods like String#startsWith or Array#random.

The DOM interfaces are just one part of RightJS and it has much more. We even have a build of RightJS without DOM features which you can use on the server-side with Node.js or say writing scripts in Qt.


3. Multiple Paradigms

As jQuery is simply a wrapper over DOM interface, it doesn't give you any alternatives but use its own way of dealing with the things. Yes, you might imagine that you're practicing Lisp in JavaScript, but the reality is that 99% of jQuery code (including jQuery itself) is just a spaghettish pieces of crap.

RightJS on the other hand is not just a DOM wrapper, it is a multi-paradigm framework. We have an advanced OOP stack that allows you to write clean and properly designed applications that are easy to support and refactor. We also have most of the standard FP features, like binding, curring, chains and stuff. We also have some standard native units extensions that are most helpful in procedural programming.

RightJS gives you options and flexibility, so that you could deal with your work in the most effective way.


4. Open Sandbox

Maybe jQuery forces you to write a spaghetti code, but there is a bigger problem. Most of jQuery and its plugins code are closed behind anonymous scopes that makes it impossible to change them part by part.

You know, people are actually already invented OOP, inheritance, functionality injection and other fancy stuff to deal with those sort of things. And that's why in RightJS we have radically opposite architecture.

RightJS is built using proper OOP structures and modules and it represents an open sandbox where virtually everything is accessible and customizable. You can easily bend and tune RightJS for your needs, changing and replacing its parts, adding your own features, methods and so one.

And because of that it is super easy to write any sort of plugins and extensions for RightJS. Take for example a look at the right-rails plugin; couple of dozens of lines of code and RightJS API was completely transformed to have the naming system of Ruby, with underscored syntax and other features.

RightJS gives you the same flexibility and hacker's joy as Ruby or Python.


5. Official Plugins

I'm sure you know what they say "jQuery has a gazillion of plugins that will do everything for you". It kinda reminds me other folks who was saying "Everything in Java has already been done".

Normal people usually add on that "badly".

That gazillion of plugins has actually a pretty nasty back side. The problem is in the closed architecture and inflexibility. For every case there are usually half a dozen of implementations, and quite often the choice is like "bad, bad or bad?". At the end you might spend more time looking for a proper plugin than you could spend writing it yourself, and at the finish your app will look like a Frankenstein, all stitched of different parts.

Yes I know, I know, Frankenstein is a romantic figure in gothic culture, but there is so few romantic in supporting such an app.

With RightJS we don't have the luxury of too many plugins, but we have several good points on that matter too. First of all, many common and frequently used features that you have as plugins for jQuery, are already baked into the RightJS core, like for example, additional form features, Ajax via iframes functionality, cookies and stuff.

Then we have all the standard plugins, like D'n'D, JSON, Behaviors, plus most of the standard UI elements like Calendar, Autocompleter, Tabs, Lightbox, etc. already implemented and served in the official plugins repository.

And what's different about RightJS plugins is that all of them are implemented in the same way, using the same set of rules. All events handling, options, usage principles all are the same. So that if you had experience with one plugin, you will be familiar with the rest of them too.

Then all the plugins follow the open-sandbox principles of the RightJS Core. All of them are implemented using proper OOP approach and can be easily extended using inheritance, functionality injection or even monkey patching if you will.

This way you don't need a dozen of variations of the same plugin, you can easily tweak any standard one to do exactly what you need.