Showing posts with label RightJS. Show all posts
Showing posts with label RightJS. Show all posts

Monday, April 4, 2011

Making Tags With Rails And RightJS

As the tags widget appeared recently on the RightJS UI list, I'd like to write a simple how-to about tags in case of using RubyOnRails.

You can see the tags widget in action on this demo page, and over here you can find a demo rails application that has the tags feature implemented, along with some other right-rails features.

Let's start

The Initial Model

When you need to add a tags feature in a ruby-on-rails project, a standard model would look kinda like that

class Article < ActiveRecord::Base
has_and_belongs_to_many :tags, :uniq => true
end

class Tag < ActiveRecord::Base
has_and_belongs_to_many :articles, :uniq => true

validates_presence_of :name
validates_uniqueness_of :name
end

As you can see, it's a pretty much straightforward m2m association, articles have many tags and tags have many articles.


Tags To Strings Conversion

The next standard step is usually to add a couple of methods to convert the list of tags into a coma separated string back and forth. The basic reason is that tags are data-base records and it's not much of user-friendly to use integer ids

class Article < ActiveRecord::Base
has_and_belong_to_many :tags, :uniq => true

def tags_string
tags.map(&:name).join(', ')
end

def tags_string=(string)
self.tags = string.split(',').map do |tag|
unless tag.blank?
Tag.find_or_create_by_name(tag.strip)
end
end.compact
end
end

After that you can use this proxy property in forms directly, like that

<%= form_for @article do |f| %>
<p>
<%= f.label :tags_string %>
<%= f.text_field :tags_string %>
</p>
<% end %>

This way the user will always manipulate the tags list as a simple string and your app will automatically create the tag records and associations on fly


Hooking Up RightJS

At this point your rails app will present a kind of a standard and simple case of tags handling. Time to make it look nice and friendly with a bit of javascript.

To hook up RightJS into your Rails application all you need is just add the right-rails gem into your Gemfile

gem 'right-rails'

And run the following code generator

rails g right_rails

Don't worry when you see a tall list of scripts it copies into your public/javascripts directory, right-rails handles most of them automatically, so you won't really need to look inside of those.


Adding The Tags Widget

Ironically, the actual RightJS part of this enterprise is the shortest one. Once you added right-rails into your application, all you need to do is replace 'f.text_field' with 'f.tags_field' in your form

<%= form_for @article do |f| %>
<p>
<%= f.label :tags_string %>
<%= f.tags_field :tags_string %>
</p>
<% end %>

RightRails handles everything else automatically, it generates all necessary html, includes javascript/css modules, it even switches between minified and source builds of javascript libraries depending on the working environment.

More of that, it can automatically use the google hosted rightjs cdn-server for a superfast, shared scripts delivery.


Adding Autocompletion

By default the f.tags_field will make you a pretty looking tags-field, if you want to add the tags autocompletion feature to it, all you need is to specify a list of known tags in it

....
<%= f.tags_field :tags_string, :tags => Tag.all.map(&:name) %>
....


There is also a few additional options you can use with tags widgets, you can find them at the rightjs.org documentation


Conclusion

This is a good example to show how RightJS is build with server-side developers in mind. As you have noticed we didn't write a single line of javascript in our little exercise, not like we couldn't, just we don't have to bother with those routine things every time we need a simple form with a bunch of standard widgets.

More of that, if you take a look into your HTML code, you'll see that RightRails didn't write a single line of script either, all it did is added the data-tags attribute to your input field.

<input data-tags="{tags: ['one','two','three'}" value="one, two"
id="article_tags_string" name="article[tags_string]" />

This way, even if something will go wrong, the user will still see the standard input field with coma separated tags. All your styles and content will remain were it was.


--
Well, this is pretty much the whole story. If you're interested, go check the RightJS UI collection, it has many more useful widgets that you can use in your applications.

Sunday, January 9, 2011

RightJS 2.2 RC Public Test

My dear fellas rightjslings (or whatever the hell we are) I've got some good news for our species! I took a bit of a break from RRTE those holidays and packed ourselves the next major update in the RightJS core, which will go by the number 2.2.0. And I would really like you to play with the thing. Bring some joy and magic in the routine, and start the year with the new shiny toys!

Awrighty, now to the business. You can download the thing from over here (NOTE: there are updates for all the plugins as well).

And as for the changes, there are quite a few of them actually, so let's get through them one by one


Native Fx Support

The first thing that RightJS 2.2 brings is the support of native css-transitions in the visual effects engine. There is not much of changes in the actual API, RightJS will automatically figure everything out and use native features when available.

Currently it runs on Safari, Chrome and FF4. Opera also supports them but I have disabled it for Opera by default, because first of all their thing is buggy (doesn't support say font-size and background-position) and secondly our own, javascript based engine works faster than their native feature :)

Anyhow, if you insist to switch it on in Opera or disable in Webkit/FF4, use the new engine option with your effects, it can be either 'javascript' or 'native'


Class and Wrapper merge

The second biggest change is that the Class and Wrapper units were merged to make an uniformed classes structure where the Class unit is the top parent of everything.

The new Wrapper construction won't work anymore, use the standard new Class calls as you do when you define any other class.


Supercalls On Modules

The other outcome of the Class unit update is that now you can call the $super method not only on inherited classes but with injected modules as well. It kinda looks like that


var Klass = new Class({
method: function() {
return "original";
}
});

Klass.include({
method: function() {
return this.$super() + "+module1";
}
});

Klass.include({
method: function() {
return this.$super() + "+module2";
}
});

new Klass().method(); // -> "original+module1+module2"

This comes very handy when you need to overload some certain methods without using the actual inheritance. Before, we used to use all sorts of old_method hacks, now it's all nice and civilized.


Builtin Mouseenter/Mouseleave Handling

RightJS 2.2 will come with built in mouseenter/mouseleave events handler. As usual it all handled automagically, just use the 'mouseenter' and 'mouseleave' event names and be happy. Works both ways, directly with elements and via UJS.


$('element').onMouseenter('addClass', 'hovered');
$('element').on('mouseleave', 'removeClass', 'hovered');

"div.something".onMouseenter('addClass', 'hovered');



Better UJS

Another major update is that now UJS handlers got triggered by nested elements as well, just like with the normal dom-events. Basically it means that if you say have a structure like that


<div class="something">
Some text in here
<div>some inner element</div>
</div>

If you attach your UJS listener like that


"div.something".onClick('toggleClass', 'clicked');

Then it will get triggered no matter if the user has clicked the div.something element itself or any of its internal elements. No more hacking this stuff around.


Pretty Collections Handling

And one more sweet thing the RightJS 2.2 release will bring. I know you all love the String#on method to handle the UJS features, so I had extended it a bit further. Now you can run basically any Element methods from strings, just like that.


"div.something".addClass('red');
"div.something".removeClass('red');
"div.important".highlight();
"div#some-crap".remove('fade');
....

Those basically shortcuts for $$(css_rule).each('method', args); it finds all the elements matching the rule and calls the method on them.


----

There are more fancy things in there, like various performance optimizations, IE8 was kicked out in the olds module, all CSS3 selectors now work everywhere, and so one and so one. I'll describe everything with the actual release.

For now you just have fun with the new sweet features and come back if you have any troubles.

Wednesday, December 22, 2010

RRTE Public Alpha

Hey people, sorry for being quiet recently, been busy with work and stuff. I don't have a pretty picture for you today, but Santa didn't come up giftless today, not at all :)

I've got a cute little link for you!

I just pushed RRTE alpha to github, so you could have a sneak pick on what's going on.

It's still an alpha, it doesn't work under IE yet and you might stumble upon some bugs here and there, but generally, generally it all shapes up and should give you some basic overview of the thing.

Anyhow, you know the drill. Checkout, enjoy and come back with feedback! :)

Wednesday, December 1, 2010

RRTE Status Update

Hey folks! It's been couple of weeks and some of you started to wonder, where's Nik with his RRTE and the world domination, so here is the status update.



As you can see, we are having some serious progress. Most of the things you see on the picture are already working, but I'm trying to explore some possibilities and features.


What's Wrong With the World?

It seems that the design-mode support in browsers is utterly broken. It's ugly, limited, uncomfortable to use and behaves differently in different browsers. Well, just like the whole JavaScript business :)

There is basically two modes how the design-mode works in browsers, the tags mode and the css-mode, in the first one the browser tries to use tags to style the content, in the other one it tries to use styles. The trouble is that IE supports the tags-mode only and FF supports both, but in any case both of them do that wrong.

You see, in the tag mode say they use obsolete FONT tag to style fonts, but in this case FF doesn't support for example proper selections highlighting, they also for example use STRIKE instead of S tag and there is no way specify it. In the css-mode, the browsers try to use things like style="font-weight:bold" instead of the <B> tag pair, which is quite inflexible if not to say idiotic in terms of CSS. It also incorrectly reacts on all sorts of things, like say it will show the U tool "on" when you put your cursor on a link, and you won't be able to switch it off because it's styled with css.

And so one and so one. There is are lots of small and big fuckups like that, and honestly it is quite a mess.


Time To Fix It!

Being an arrogant idiot, I couldn't just pass by this mess, so now I'm building my own engine, which will do precisely what we need on any browser. Basically there are two sets of tools, one of them allows you to work with the style attribute, the other one allows you to format anything with any tag you want, and, what's more important, with any attribute you need, which means that you can use ids and classes as well.

The formatting setting is not limited to the H1-H6, PRE and ADDRESS tags anymore. You can easily specify say things like that

Rte.Formats = {
'h2': "Header 2",
'tt': "Typetext",
'blockquote': "Block quote",
'div.blue': "Blue block",
'div.green': "Green block"
};

Etc, etc. The basic plan is to create some sort of a mixed, truly css-oriented mode. We will use SPAN + style attribute for things like custom colors and fonts, but for everything else use normal tags and classes, so that the editor produced a nice and easy to process and support content.

It's a bit tricky, but we will get through it.


Advanced Tools

The other thing which I'm trying to figure out is how small an RTE can be, or how much features can we squeeze in 10k? Advanced OOP features of RightJS are really helpful in this case, because all the inheritance and functionality injection features allow us to create really compact and flexible code. As you can see I already added the color tools, font name and size tools, formatting options and some other things. At the moment all of that weights about 8k of gzipped code (and that includes all the css).

So I'm trying to add more features in the standard package than I originally planed and see where it will lead us. We might drop some of them into the extensions pack later on, or, if everything will go smoothly, we might not need one and all the standard functionality will be available in the basic build, so that we will have just a core and plugins. Or something like that. Will see.


--
Well, this is basically it for the moment.
To be continued...

Friday, November 12, 2010

RightJS RTE Concept

In case you were wondering why it was quiet around here for last couple of weeks, I'd like to share some stuff I've been secretly working on and what are the future plans.

Basically we are taking a little pause until Mozilla guys sort their stuff out and release FF4 or at least 3.7, which we need to execute our evil plan for RightJS 2.2.

Meanwhile I've been working on this puppy



Yup, it's a RightJS based RTE that will most definitely take over the world, and so you started to want it for xmas, I'd like to put some words in about what's what and stuff.


Meet RRTE The Frameless

One of the major differences from usual RTEs is that our RTE (which goes under the codename RRTE) does not use any frakking frames. Instead, it uses an inlined DIV with contenteditable="true" property.

If now you're wondering what it gives you, then this is what:

Because it's an inlined div, all the content inside of it will follow all the styles on the page, which means no more headache with transferring and applying your styles to some iframe. If you take a look at the picture, you'll see that the header text inside of the editor has exactly the same font and size as the header on the main page. The blockquote and pre tags are also painted through usual CSS right on the page.

Secondly, because it's just a small inlined piece of page, RRTE works and feels much faster than any IFRAME based editors. It is super fast, practically it feels almost like a plain textarea element.

Thirdly, because all widgets in RightJS UI are plain elements, you will be allowed to easily access and manipulate any content right inside of the editor via standard API.


Modular

The second most important feature of RRTE is that it will be modular. Unlike all the other heavy duty RTEs, our RTE, by default will be mainly social networks oriented. It's main purpose will be to work as a lightweight embeddable RTE for all sorts of things like comments and blog posts where you already have all styles in place and just need some nice and shiny thing instead of textareas.

For this reason the default package will contain the main core/engine and provide basic editing tools which you can see on the picture above. Currently it weights just 4k of gzipped code (including stylesheets) and my intention is to keep it under 10k size.

And for all the advanced functionality, like file-pickers, fonts, tables, etc. we will have a separated package, which will turn the editor in a normal heavy duty RTE.


Extendable

As you can see, my plan for RRTE is to extend it via plugins. I don't have any intention to implement everything in it, instead of that RRTE will have a proper OOP design in best RightJS traditions, so that you could make your own tools and extensions, using classes and inheritance. In case if you're wondering how it's gonna look like, here is an example how the Save button is implemented


Rte.Tool.Save = new Class(Rte.Tool, {
shortcut: 'S',

initialize: function(rte) {
this.$super(rte);
if (!rte.textarea.form()) {
this.disable();
}
},

exec: function() {
if (!this.disabled) {
this.rte.textarea.form().submit();
}
}
});

RRTE will provide you with basic tools and open API, so I expect it to be pretty civilized and easy to extend.


What and When

Currently I keep all the fun for myself. This thing is not on github yet, basically because I hack and refactor it alot. Some parts are still quite flimsy and as I don't want you to have a wrong impression about it I'm going to keep it locally for the next week or two.

At the moment it appears to me that I'm done on about 40-50%, but as I'm a bit busy those days it is hard to estimate the exact schedule. Judging by my guts I should push something worth of seeing on github in about couple of weeks and probably will have the first release by the end of November/beginning of December.


This is basically it. Enjoy the news!

--
Oh, and one more thing. I could use some help with a default iconset for this widget. Currently I use some free stuff that I found over the internet, but if you can and willing to draw some particularly cool uber-iconset, that would be much appreciated!

Monday, October 25, 2010

RightJS 2.2 Notes

I'm cooking a new evil plan for RightJS 2.2 release and would like to share some thoughts and notes, so you knew what's going on and where are we heading.


Native Fx

We are living in an interesting moment. Native CSS transitions are finally becoming reality. Safari does it, Chrome does it, Opera does it, FF4 does it (they promised they will include the feature into the 3.7 release). IE9b does not. Rumors has it, the feature will be in the final release, but I have my doubts it will happen.

Anyways, now, when the majority of sane browsers support the feature, I think it's the right time to start using native CSS transitions as a default option for our dom-morph effects. It is faster, simpler and more reliable.


Better UJS

The current implementation of UJS in RightJS works with an event target property only. The trouble with this solution is that when you have something like

<div id="one">first
<div id="two">second
<div id="three">third</div>
</div>
</div>

and you attach an event listener to say the top one

"div#one".onClick(function() {
...
});

it will reacts only if the user clicks on the div#one itself and will successfully ignoring clicks on the inner element. Sometimes that's what you need, but in majority of the cases it creates more confusion than helping.

I'm still thinking about this one, but there is a good chance that the logic will be changed and our UJS will mimic the normal event listeners behavior and react on inner elements as well.

Hey! You will be able to make UJS stuff within UJS stuff! :)


Cookie plugin

At the beginning it seemed like a good idea to have a basic Cookie wrapper out of the box, but later I realized that on majority of my projects I don't use it. Well I assume you have pretty much the same experience.

So I think the cookie module will be kicked out of the core into an officially supported plugin. it's not much, just half a KB of gzipped code, but I guess we can fill this half a K with something more useful in everyday life.


IE8 And Pals

IE8, or as it known in some circles "IE7 on steroids" is kinda of troubling browser. The problem is that on a good half of the pages this darn things automatically falls into IE7 mode and therefore downloads the "olds" module, on the other half, it still has some troubles with native css selectors because some of CSS3 constructions are not supported, which consequentially makes some wonder-people to wonder how "right" right.js exactly is?

Furthermore the change/submit events still don't bubble and we carry quite large chunk of code in the core, to work this thing around.

So I was having that wild thought in my head, that we could ditch IE8 and pals support into the olds module so we could fix those things in there and not bother the core.

Currently, I'm considering the idea of making the line between the old and new browsers right where the CSS transitions support starts, which will effectively drop the whole IE support into the olds module.

That probably will make some jquery folks to moan that we are unfair towards them, but I'm looking into my glass ball and it says that after all the cutting and stitching, RightJS core size could drop below 12k.

Well, at least that the target. Besides there is still a tiny chance that IE9 folks will hear the voice of sanity and add css-transitions into it, then this distinction will be perfectly justified.


---

Anyhow, those are the notes and thoughts. Let me know if you have something on your mind about that

Thursday, September 9, 2010

RightJS 2 jQuerysh Plugin

Hey folks. I had couple of minutes of free time and cooked a fancy plugin for RightJS 2.

It's called 'jQuerysh' and provides the jquery-like behavior for the $() function. You can copypast or build it from over here jquerysh on github

Basically it does three things with the $() function. You can navigate in jquery-style

$('#element-id').onClick('addClass', 'marked');

$('div.class').each('addClass', 'marked');

And you can call the onReady via it, same way as in jQuery

$(function() {
// will be executed when on ready
});

This is pretty much it, might be useful for people who need to work with both jQuery and RightJS.

And yes, it works with RightJS 2 only. Not like I want to make you switch to RJS2 (which I actually want), RJS1 is simply not built for that.

Cheers

Friday, August 27, 2010

RightJS 2 Release Plan Updates

My dear fellas, this lovely Friday's evening I'd like to share with you some updates on the RightJS 2.0 release plan. And yes, by "updates" I mean delays.

No need for dirty swears, because there are two good reasons for that. 1) Rails 3 which should come out any moment now, and 2) upcoming IE 9 beta which is scheduled to September 15th. And as we all know well those funny MS folks, I think you'll agree that it's better to wait couple of weeks rather than pull your hair off later.

And it's not all that bad, there are good news too. I'm almost finished porting the UI modules to RJS 2, which means there well be the RC2 release in about couple of days I think. RC2 will include the core with all the latest updates and all the plugins and widgets ported to the new system. Generally this will be the final version and unless someone find a bug it will go to the actual release as is.

You'll have couple of weeks to play with it until the IE 9 release, and I'll have couple of weeks to brush up the docs, update rightjs.org and rework right-rails. Thinks that should give as a good runaway for a nice and smooth release.

This is about it. Take care!