Tuesday, March 15, 2011
Sencha Touch Bits
http://www.senchatouchbits.com
I also have been increasingly working with Ext JS 4, Ruby 1.9 and Rails 3 lately. So this blog might awake again soon. :)
Btw, Ext JS 4 Preview Version 4 has been released today: http://www.sencha.com/forum/showthread.php?125072-Ext-JS-4-Releases-and-Notes-(4.0PR4)
Great stuff!
Friday, February 5, 2010
Theming an Ext.Window in 10 minutes
There are a few ready to install themes available (search the forums) that you can choose from and I know that Ext is working on 1. making it easier to customize the theme of your app and 2. finding themes (marketplace).
But, after all, it isn't already that hard to do.
I wanted to add a free floating "Getting Started" panel to my new application Spreadnotes yesterday. Free floating so the new users can start trying out the application without having to close the "Getting Started" info just yet, but rather can move it to the side.
I thought an Ext.Window would have all requirements I need. The only thing I need to do was to make the design fit with the application's design.
Here's a quick walk through to maybe take the fear of customizing your theme from some of you. :)
1. The default Ext.Window
Through the configuration I already could customize some things I didn't want to show up,
such as a header (leaving the title blank), no close button on top right (closable: false) and scrolling of the content (autoScroll: true).
The content itself I put into a div with the id 'getting-started', rather then having to deal with a lot of text in JavaScript.
The contentEl configuration option is there to use that content.
var gettingStarted = new Ext.Window({
id: 'getting-started-window',
contentEl: 'getting-started',
width: 400,
height: 300,
closable: false,
resizable: false,
autoScroll: true,
fbar: [{
text: 'Ok, I got it',
handler: function () {
Ext.getCmp('getting-started-window').close();
}
}]
});
gettingStarted.show();
That's the result with the default blue theme:
2. Finding the window's theme images
Most Ext JS widgets use background images for special borders and design elements.
Firebug or the WebKit's HTML Inspector help you to find the DOM elements and CSS classes which specify the background images.
Since some widgets use quite a few DOM element layers, you need to click around a little in the DOM tree to find the specific DOM element with the CSS configuration. See picture below.
3. Color the images and save them to a different place
I obviously didn't do a lot of design magic, I basically just colored the images to
use two gray shades I already use in the top toolbar.
4. Set your CSS
I put class by class with the custom background image into my application's CSS file. You could group them a little better, but that's what the result is: (By the way, that's why I love native CSS instead of SASS, since you can copy the styles right from the Firefox CSS panel :P)
.x-window-tc,
.x-window-bc {
background-image: url("/images/ext/window/top-bottom.png");
}
.x-window-ml,
.x-window-mr {
background-image: url("/images/ext/window/left-right.png");
}
.x-window-tl,
.x-window-bl {
background-image: url("/images/ext/window/left-corners.png");
}
.x-window-tr,
.x-window-br {
background-image: url("/images/ext/window/right-corners.png");
}
So this is the current state:
As you see, the content part is still blue, that's why we set the following CSS as well:
.x-window-ml {
background-color: white;
}
.x-window-mc {
background-color: white;
border-width: 0px;
}
5. Customize the ghost
There's one more special thing of the Ext.Window we need to modify. When moving the window it shows a semi transparent window which Ext calls a "ghost".
Since we can't move it and inspect the DOM tree at the same time, you can activate the ghost by simply adding the following command temporary.
gettingStarted.ghost(); // after calling gettingStarted.show()
That's how the original ghost looks:
To modify its look, we add the following CSS
.x-panel-ghost {
background-color: #e6e6e6;
}
.x-panel-ghost ul {
border-color: #afafaf;
}
.x-panel-ghost .x-window-tl {
border-bottom-color: #afafaf;
}
The result is the following
6. Finish
I know that my custom window design isn't a very spectacular one, but my only goal was to make it at least fit to the application's design.
Of course, the amount of work customizing your apps increases with the amount of widgets you use. But then you're also reusing a lot of widgets.
So I hope I could show to some that never really looked into theming their Ext application that it's fairly easy.
Happy theming! :)
Monday, November 9, 2009
Ext JS vs. Google Closure
Hello World
The entry point for getting started with a library is usually a small "Hello World" application.
Ext.util.Observable
Ext.Component
Ext.BoxComponent
Ext.Container
Ext.Panel
(Ext.tree.TreePanel)
goog.Disposable
goog.events.EventTarget
goog.ui.Component
(goog.ui.tree.BaseNode)
goog.events.EventTarget
class seems to be the equivalent of Ext JS's Ext.util.Observable
class, goog.Disposable
and goog.ui.Component
seem to be the equivalent of Ext JS's Ext.Component class.Ext.BoxComponent
, Ext.Container
and Ext.Panel
classes, which handle components layouts, can't be found in the Google Closure's hierarchy since Google Closure seems to be missing a layout manager.events.EventTarget
class, whereas Ext JS's event handling logic can be found in the Ext.util.Observable
class.addEventListener
for adding listeners, and dispatchEvent
for firing events, which is the equivalent of Ext JS's fireEvent
method.Documentation aka API reference
Library's Age & Developer community
I don't know how long Google Closure has been existing within Google, but it just has come to see the light of the outer-Google world.
Thursday, June 4, 2009
RESTful store example with Rails
It included a new restful configuration option for the Ext.data.Store and an example for its usage.
Update April 9, 2010: It's now compatible with the latest Ext JS 3.2.0 version.
Impressed by Ext's Chris Scott's lightweight Rails-like PHP MVC framework, I still wanted to get a feeling for this new feature by writing a Rails backend for this example.
Here it is
http://github.com/steffen/extjswithrails.restful.sample/
Here is what I did
On the frontend, I only changed the Proxy's URL from
var proxy = new Ext.data.HttpProxy({
url: 'app.php/users'
});
to
var proxy = new Ext.data.HttpProxy({
url: '/users'
});
Update April 9, 2010: Also added the "encode: false" config option to the JsonWriter and changed the root option from 'data' to 'users'. The latter is just for making the example a little more clearer.
On the backend side, I created the User model, added the model to the routes.rb file, and created the following users controller:
(I didn't do all by hand, thanks to script/generate scaffold user
email:string first:string last:string :))
class UsersController < ApplicationController
def index
@users = User.all
render :json => { :users => @users }
end
def create
@user = User.new(params[:users])
if @user.save
render :json => { :success => true, :message => "Created new User #{@user.id}", :users => @user }
else
render :json => { :message => "Failed to create user"}
end
end
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:users])
render :json => { :success => true, :message => "Updated User #{@user.id}", :users => @user }
else
render :json => { :message => "Failed to update User"}
end
end
def destroy
@user = User.find(params[:id])
if @user.destroy
render :json => { :success => true, :message => "Destroyed User #{@user.id}" }
else
render :json => { :message => "Failed to destroy User" }
end
end
end
Notice that the scaffold actions expects the data through the user parameter (params[:user]), but Ext's example is using data as root, that's why we have to use params[:data] here.
Check the commit log for details regarding the steps it took me to create this example.
Here is how you can try it out
- $ git clone git://github.com/steffen/extjswithrails.restful.sample.git
- $ cd extjswithrails.restful.sample
- Make sure you have ruby 1.8, rubygems, rails 2.3.2 and sqlite3-ruby installed.
- $ rake db:migrate
- $ script/server
- Open http://localhost:3000/ in browser.
Update April 9, 2010: The headaches were fixed with later versions.
Here is what gave me a headache
Unfortunately, Ext JS isn't sending the whole data in JSON, but rather as normal POST parameters with one parameter that carries the JSON string. That parameter's name is taken from the root option from your reader, in our example its data.
I think there should be two things fixed:
- Send the whole data in JSON, such as { id: 1, data: { first: 'First', last: 'Last', email: 'Email' } } and not as id=1&data={ first: 'First', last: 'Last', email: 'Email' }.
The current workaround is to use ActiveSupport::JSON.decode
for the data parameter, since Rails can't automatically decode the parameters because the request isn't completely in JSON. - Send the AJAX request with the request header 'Content-Type': application/json. This way, if the request would completely be in JSON, Rails could figure out that it receives JSON data.
A workaround would be to add Ext.Ajax.defaultHeaders = { 'Content-Type': 'application/json' }
Here is my conclusion for today
I like the restful option, but dislike Ext's AJAX code (not the new stuff, I mean the one that's in the Connection class and ext-base file), blogger.com's BR tags all over the place, blogger not allowing to change post's URLs, and MarsEdit enabling comments with every save and messing up my third party commenting system. :-)
Friday, May 1, 2009
A day the Hashrocket way
Thanks to their open nature and their utilities such as presentations, posts, tweets and videos, I already knew a lot about “The Hashrocket Way”. I must say though that I didn’t really believe in some of their techniques and practices, mostly because I haven’t tried them out. ;) Therefore the visit since I like to learn and am open to change. (Who isn’t?)
With this post I’m sharing what I’ve learned during my visit at Hashrocket. I’m writing it in the form of Hashrocket’s way versus My way of developing software. Only a few sections are Ruby on Rails specific.
To give you a quick impression on how my day at Hashrocket started, look at the following picture.
This is actually the way to work of some of the Hashrocket developers. That’s hard to beat.
Just in time at 9 am, I arrived with Hashrocket’s new Designer Andrew Maier (who’s working on an awesome new Hashrocket site) for the daily stand-up meeting at Hashrocket's office. It’s a short kick-off meeting for the day. We talked a little about who’s going to work on what, about a few technical things from the day before, I introduced myself to Hashrocket’s people and Hashrocket’s project manager Sal assigned me Matt Remsik as my pair programming partner for the day. More on that later.
Let’s get started with Hashrocket’s way versus My way ...
Always pairing vs. Occasional pairing
Hashrocket is a (maybe the only) well-known coding shop that practices full-time pair programming . I was wondering myself if that’s really worth the money from the stakeholders side and worth the time from the coders side.
The way I looked at pair programming before coming to Hashrocket was that pairing is a coding technique to overcome a developer’s block, get a new project rolling or designing the implementation of a new feature. Most of the time though, a developer should embrace his flows (between the pairing sessions) and get things done. Ideally, the other developer gets other things done during the same time. Summed up, this would suggest to be a faster technique for moving forward with software development.
Ish don’t think so anymore. At least, I don’t believe anymore that it’s that easy to calculate. The reason is that I was pretty surprised on how often me and my pair Matt Remsik called on each other's action. With called I’m referring to giving ideas, suggesting better solutions, correcting and optimizing code.
This results in my new impression that situations where a pair can help, occur more randomly and often than I thought, even or especially in a developer’s flow and not only during the usually suspects such as developer’s block and starting a new project or feature.
This impression should be taken with a grain of salt though, since this is my impression from only a few hours. Unfortunately, I don’t have a pair at my side right now to test pairing over a longer period of time.
Pairing locally vs. Pairing remotely
Today, a lot of people work together remotely such as me with my peer Samuel Goebert . We're using remote screensharing (via Teamviewer or iChat ) and a remote audio connection (via Skype or iChat ). Somehow I had in my mind that pairing locally means sharing one keyboard, one (small) screen and rolling around with chairs. Therefore, remote pairing has been a clear winner for me, since both peers can easily access their keyboard, their screen and don't need to roll around when switching sides. Well, turned out that Hashrocket has a very cool setup which addresses all three of these issues. They use two external USB keyboards, one huge (30”) screen and two chairs side-by-side. You can see that in this video and in this one.
I talked with Matt Remsik about their setup, which I once saw, with two huge screens, one for each peer. He made an interesting point by saying that they felt a big difference between working on two separate or one screen. He said one screen helps to communicate since you also can take the other ones gestures in account. So, basically, you can easier notice where the other one is looking or pointing at.
Working in an open office vs. Working in a quite room
My opinion was that it makes more sense to put each pair in a separate room. Especially if you have multiple pairs in a room (instead of single developers), it can get a little noisy as you can sometimes tell from Hashrocket's videos . ;)
I won an interesting insight on this topic which in fact weakens my standpoint. I assumed that a lot of pairs in one room is worse in respect of higher distraction rate than a lot of single developers in one room. It turned out to be the other way. Noise (conversations, videos, sounds) from other teams feel less distracting in a room with pairs than in a room of single developers.
To explain that, Matt told me about a very interesting cocktail hour theory, which is that when talking at a bar or cocktail party to someone, you can concentrate on that conversation fine even though there's a lot of noise from other people and music in the background. The cool thing about your ear and brain is, that it still can filter interesting bits of information out of that background noise. So if somebody at that party mentions a movie or a place you just have seen or visited, you can catch that up and decide if you want to join that conversion or not.
The same counts for the office. If somebody for example mentions Rails on Google App Engine or a specific problem when upgrading to Rails 2.3 and you have been reading about it or are interested in it, you quickly can join the conversion and learn. Most of the times so, the other pairs are talking about their current code and task, which doesn't interest and therefore distract you from your conversation with your pair, and pair programming is a lot about conversation.
Working in an office vs. Working at home
I’m often wondering about what gives a lonely freelancer the ultimate satisfaction and highest productivity while working. ;) So the work environment plays an important part. I have tried working at an office with coworkers as an employee, working at an office alone as a freelancer and working alone from home. I unfortunately haven’t tried sharing office space with other freelancer yet, though.
Hashrocket actually makes you feel a lot like you’re a freelancer and sharing office space with others. That’s definitely a big plus and eventually helps satisfaction and productivity. There aren’t many companies and offices out there where you can play a bit of ping pong during your working hours.
Anyway, I have been working alone from home lately. Sometimes I wouldn’t mind to get out and breath a little office atmosphere. I guess a mixture might be the best (for me), since I wouldn’t like to have to go to an office every day.
Matt Linderman from 37signals also just reminded me to take in account the time you lose every day and week for your commute when working outside of home. Also, Hashrocket’s online book club is bringing you an office with smart programmers to your home every Tuesday to kind catch up with the missing office atmosphere. After all, working “on the road” also might not be a bad idea.
Vim vs. Textmate
At the stand up meeting in the morning I mentioned that I’m using Textmate as my editor for Rails projects. Gestures of some attendees let me know that I’m old-school (or new-school?). Anyway, it turned out that Hashrocket’s editor of choice is Vim (with a rails.vim plugin from their own Tim Pope).
I could see the advantages such as vertical split screen (i.e. model file on the left, model’s spec file on the right), faster copying & pasting and having all in the console. Together with the keyboard issue, about which I’m talking in the next section, this has admittedly giving me a kind of hard time throughout the day though, since I just wasn’t used to it. Anyway, vim will be worth a try.
English Keyboard vs. German Keyboard
I’m German and I have been using German keyboards throughout my life time. Unfortunately, they don’t use German keyboards in America. ;) So typing y and z’s or Ruby common characters _, @ and ? was a little tricky and time intensive.
Coincidentally, I had a German external Apple keyboard with me.
Unfortunately, Apple doesn’t support the most needed feature of supporting different keyboard layouts for two different USB keyboards. What a flaw! ;) So, a German keyboard with an English keyboard layout wasn’t making things better and I returned to the English keyboard.
Git vs. Svn
I'm (still) using Subversion for my source code version control for internal projects. (Git users, you can roll your eyes now, I don’t see it anyway. ;)) It’s not because I live behind a mountain (I actually do). I noticed the git storm through my internet connection and I have been using git for a few open source projects of mine.
Internally, I still like Subversion, though. Especially its simplicity and usability. In git, you can do the same things in 5 different ways. In Subversion there’s practically only one command for each action. Maybe these two points are not technically correct, it’s just my feeling. Also, I somehow like to have a linear and non-manipulated history. Subversion makes sure of that.
Moreover, I feel like that some people switched to git because it’s easier to switch between branches. After all, it’s not Subversion’s fault, they just didn’t know about the svn switch command.
Also, the latest Subversion releases (1.5 and 1.6) introduced some git-like features that makes it actually even more difficult for me to find reasons to switch to git.
For example, since version 1.5 Subversion keeps track of merges. No need to specify revisions by hand when merging anymore. Also, since version 1.6 Subversion allows relative remote paths.
So I’m pretty cool with the following commands I use daily:
# merge latest trunk into a branch
svn merge ^/trunk
# merge a branch into trunk
svn merge --reintegrate ^/branches/feature-x
# tag a version
svn cp ^/trunk ^/tags/version-x
Ok, enough Subversion love. After all, I don’t want to claim that I’ll never end up with using git someday. One thing that sometimes bothers me about Subversion are slow merges. So speed may sell git for me, as for many others I guess, too.
Anyway, Hashrocket uses git. In the next chapter Their RSpec practices vs. My RSpec practices I discuss one git-ish workflow they follow, which wouldn’t be possible with Subversion.
One last cool tidbit from Hashrocket regarding source code control: After pair programming sessions, they actually commit in the names of both programmers, which is cool since you actually see the pairs in your version history. They also have a wildcard email account that accepts emails in the following format prog1+prog2@email, which you assign in git to the actually commit names.
Their RSpec practices vs. My RSpec practices
For model and controller testing, Hashrocket uses RSpec. So do I. For testing with data, Hashrocket uses Factory Girl (instead of Mocks and Fixtures). So do I, too. In a later section I’ll talk about integration testing.
From the videos you can tell that they are using autotest sometimes. I stopped using it since it got kind of annoying.
There’re basically two things I learned regarding RSpec. (I’m sure there’s more to learn, but it was only one day.)
The first one regards sorting and arranging of the RSpec contexts. I’m wondering sometimes if I should just put the new context for let’s say a new method at the end of the spec file. My pair, Matt Remsik, sorts them the same as the methods are defined in the corresponding model or controller file. This may especially helpful when you have split screen as I mentioned in the previous Vim vs. Textmate section.
The second thing we were talking about was about their workflow of committing and running full specs. They commit first and then run the full specs, which can take a couple of minutes. The git-ish trick here is, that if the spec run reveals regressions bugs, they fix them and merge these fixes via the git rebase command into the last commit. The goal is to have an atomic working code commit for each story or feature they have been working on. The reason is to be able to easily revert these commits which represent features or stories. However, I think that this is a kind of belief from an ideal world and in my experience removing code is almost always preferred instead of reverting a commit. Matt Remsik agreed on that one, too.
After all, I wonder if rewriting history is necessary at all and actually helpful. One argument from Hashrocket was, though, that their continuous integration tool is checking every commit, therefore, every commit should be working code, even in branches. I agree with that on the master branch, but myself likes to be able to commit to development branches non-working code. That’s actually why I belief you split the development of bigger features into branches.
jQuery vs. Prototype (vs. Ext Core)
I remember, some time ago Hashrocket switched from Prototype JS to jQuery. Hashrocket’s boss Obie mentioned it in this blog post . (Damn, I just noticed Obie used the same “vs.” style in his blog post, now mine looks like a copy cat. Whatever, this blog post is worth a look, since it has the same style but different content.)
Unfortunately, I forgot to talk about their experience with jQuery and reasons for the switch. Looks like I have to visit them again. ;)
Anyway, it will be interesting to see how the recently released Ext Core is mixing up the market. It will definitely be my choice of lightweight Javascript lib for future projects, since I like Ext’s API and clean code and am familiar with it from the Ext JS lib.
Cucumber-based GUI testing vs. Ruby Selenium GUI testing
I didn’t actually see Hashrocket’s Cucumber GUI tests in action (I’m sure I could have though, if I would have remembered to ask) but still learned about a new gem: Culerity, which “integrates Cucumber and Celerity in order to test your application's full stack including Javascript.”
Celerity (not the just mentioned Culerity) is “a JRuby wrapper around HtmlUnit – a headless Java browser with JavaScript support.” You always can use Cucumber with Selenium, too, but the tests have to run in the actual browser, which can be a bit slow.
I heard from the Hashrocket crew though, that Culerity or Celerity have some issues with testing Javascript sites. Basically there seems to be a caching issue, which is why they are still “forced” to use Selenium.
After all, my opinion is that Selenium isn’t that bad at all. It surely doesn’t scale well, but what does? ;) In my case, it actually runs pretty fast (remember to GUI test your Rails app in production mode). Also you already can write your Selenium tests in Ruby and additionally I wrote my own little Selenium helpers to help me with testing Ext JS apps, about which I’ll blog shortly.
Pivotal Tracker vs. Basecamp
I knew that Hashrocket uses Pivotal Tracker and I have seen it before. But the interface didn’t really make me love it at the first sight. Seeing it in action during my visit at Hashrocket made the trick, though. I have been using Basecamp with my clients for a while (only the todo section, though). Basecamp definitely helps to communicate and collect open tasks. It gets a little messy though when trying to prioritize and plan. Certainly you can make todo lists for each iteration, add estimate points and status flags to the todo item names and prioritize by drag & drop in Basecamp. But you have to do all that manually, again and again.
Pivotal Tracker’s user interface and automatization features simplify these workflows.
Depending on your virtual velocity, Pivotal Tracker plans your iterations itself. The vertical view split of your different “todo lists” eases dragging & dropping of items. (Try to drag &
drop an item in Basecamp throughout a page break. Also try to drop an item in an empty todo list. The first is tricky, the latter not possible.) An item’s status is easily visibly through their Start, Finish, Deliver, Accept & Reject Buttons.
When I came home from my trip to Hashrocket, my question was, what needs to be done for the next iteration on my current projects. Basecamp didn’t tell me, so I switched to Pivotal Tracker right away, since it tells you automatically. (Manually copied & pasted todo items and comments from Basecamp to Pivotal Tracker, don’t know about a migration client.)
So far, I’m very happy with Pivotal Tracker. Here’s a good link that summarizes some other advantages of Pivotal Tracker. Also, just a few days ago, Hashrocket posted a video about how they use Pivotal Tracker, check it out.
One thing I’m missing right now is an integrated time tracker, or a time tracker that integrates with Pivotal Tracker. Anybody knows one?
Bonus: Their office view in Jacksonville vs. My office view in Dubai :)
I round this blog post up with a kind of fun comparison. After all it influences your work environment.
For a year I worked at an office in Dubai, UAE, which was almost as close to the beach as Haskrocket’s office. But Hashrocket wins this comparison (as many others), since they actually can see the beach (I couldn’t, only a little bit blue of the sea between the Palm Island’s leaves and construction sites). Also the Burj Al Arab view has been ruined by another highrise by now. Oh, and as almost its name suggests, you can see Space Shuttle launches from Hashrocket’s place.
Résumé
It was a really awesome day. I wouldn’t want to miss that day in my life and career. I didn’t actually feel like a guest, rather like a Hashtronaut a.k.a. a developer working at Hashrocket. :)
I hope I could pass along some of the value I enjoyed be receiving from my day at Hashrocket with this blog post to other known and unknown people out there in the cloud.
My exciting day at Hashrocket ended with a very productive sit-down meeting with I few of their developers.
Thanks a million to my pair @veezus , my project managers @beebe4 and @salc1219, my housemate @andrewmaier, my colleagues @sandrot, @l4rk, @tpope, @cgrusden, @the_mug, @wesgibbs, Jen, Les (and all I forgot) and last but not least the boss @obie! :)
Monday, April 20, 2009
Short Ext Conference Résumé
- Check out all tweets with the #extconf tag.
- Read Tim Sporcic's opinionated but therefore interesting daily round-ups.
- See pictures from Nils Dehl and Sergei Kozlov.
- Or wait for the session presentations and videos to be online. :-)
With this post, I basically want to thank the Ext team and all people I have been able to meet and talk to!
- The Ext team is a very talented team. They really know what they talk about and they work their butts off to make Ext better every day and night!
- The conference's location was awesome. Having the conference in the hotel where almost all attendees stayed, made it a lot easier to actually meet a lot of people after the sessions. Some argued a luxurious hotel as the Ritz-Carlton isn't a hotel for geeks. I think though most of the team and attendees have deserved a few days off in the luxurious world.
- The food was superb. Haven't really ever seen food looking so perfectly prepared. To be fair to all other high-class restaurants, I'm usually not eating in those restaurants.
- A lot Ruby-less, Test-less, Mac-less, Twitter-less community than I'm used to from the Ruby on Rails community.
- I met a bunch of interesting and fun people. That really made the 50% of the overall return on investment for me.
- It's great to know the people behind the commit names and forum avatars, which really makes it a lot more feel like a community.
- None of the sessions I attended were boring, which might have been a fear for me and some others after having worked with Ext JS for quite some time.
- The Ext company is a great venture which already came very far, and my impression is, that they have a bag full of secrets and surprises for the future (Ext Marketplace) to rock the javascript and user interface world even more. Point 1 supports this impression strongly.
Thanks again to all I've met and talked to! Hopefully keeping in touch with some of you!