Thursday, September 10, 2009

Using jQuery to build a feature carrousel

Well, it's been a while since my last post, but now I'm back!

After talking a little about GWT, i will start talking a little about jQuery as well and show some sort of animations that can be made using jQuery.

As my first example, we will build a very stylish carrousel, not to just show some image, but also show the features of your site.

You will need:
  • some large images for the features background.
  • some small images to use as menu items.
  • some images with the same height/width as the large one, but transparent with the text you want to show with the background image.
Also if your large image is named photo1.png, the small one should be photo1_small.png and the text image photo1_text.png

we will start by coding the HTML elements of the carrousel:
<div id="main-carrousel">
<div id="shadow"></div>
<img id="text-img" src="/images/foto1_text.png"/>
<div id="bottom">
<div id="controls">
<img src="/images/foto1_small.jpg" class="select"/>
<img src="/images/foto2_small.jpg"/>
<img src="/images/foto3_small.jpg"/>
</div>
</div>
</div>

The div main-carrousel will have in it's background the current feature image.
The div shadow will give the transition effect
The img text-img will have the image with the text of the feature.
The div bottom will hold the controls to change the feature.

Now the javascript code:
$(function(){
var carrousel = $("#main-carrousel");
if (carrousel != null && carrousel != undefined){
$("#controls img").each(function(){
$(this).click(function(){
if (!$(this).hasClass("select")){
var photoUrl = "url("+ $(this).attr("src").replace(/_small/,"") +")";
var textUrl = $(this).attr("src").replace(/_small/,"_text").replace(/jpg/,"png");
$("#text-img").fadeOut("fast",function(){
$(this).attr("src",textUrl);
$("#shadow").fadeIn("fast",function(){
carrousel.css("background-image",photoUrl);
$("#shadow").fadeOut("fast",function(){
$("#text-img").fadeIn("slow");
});
});
});
$("#controls .select").removeClass("select");
$(this).addClass("select");
}
});
});
}
});
Well, we start by getting all the images in the "controls" div.
For each one we add a listerner to the "click" action where our magic will happen.
In this function we confirm if the current item is the not one selected.
After we find the photo url by removing the "_small" from the src of the img. Also we find the text image by replacing the "_small" with "_text".
Now that we know the new urls we start the animation.
First we fade out the text image and replace its src attribute with the new text-img url.
the we fade in the shadow div, so we can update the main-carrousel background with the new image url.
After we fade out the shadow div and fade in the text image.

To speed up the images loading process you can create a invisible div to pre-load the images.
<div id="pre-loader" style="display:none">
<img src="/images/foto1.jpg"/>
<img src="/images/foto2.jpg"/>
<img src="/images/foto3.jpg"/>
</div>

You can also style the carrousel, here is an example:
#main-carrousel{
width:700px;
height:300px;
background:#fff url(/images/foto1.jpg) no-repeat;
position:relative;
top:-25px;
margin:0 auto;
border:1px solid #999;
}
#shadow {
width:100%;
height:100%;
background:#DDD;
display:none;
}
#bottom {
position:absolute;
bottom:0;
width:100%;
height:50px;
background:url(/images/transpBlack25.png);
}
#controls {
float:right;
padding-top:10px;
padding-right:10px;
}
#controls img {
margin-left:10px;
float:left;
cursor:pointer;
}
.select {
border:3px solid #DDD;
margin-top:-3px;
}


you can see it live at http://brunogb.appspot.com

Hope you enjoyed it.

Wednesday, August 19, 2009

fast coding with Java



Java projects have a very slow startup time. We need to configure many things, put our frameworks to work together, configure the dependencies and many other stuff.

Just imagine how much times you wanted to start a new project and gave up because you had so much things to download and configure?

Some script languages, like ruby and python, have a application generator, that make it easy to start coding with almost any configuration.

So why cant we do the same with Java? Why do we have to download every framework again and configure all the xml's files every time?

This is the main purpose of the Rocket Science project.

There you will find a basic project, featuring all you need to start coding right after you donwload the package.

This basic project features nice urls, page templates, inversion of control, json serialization and jquery with jquery UI.

Just unpack the ZIP file and import the project into eclipse, and you are done to start coding.

Soon we will release a pre-configured AppEngine/GWT project that works in the same way.

Monday, July 27, 2009

Authenticate user using the google accounts

It's very easy to use the google accounts login system in your website.
First let's create a class to represent the User state in the view.
public class LoginInfo implements Serializable {    private boolean loggedIn = false;   private String loginUrl;   private String logoutUrl;   private String emailAddress;   private String nickname;
(we hided the getters and setters)

Now we must create the service interface that will fill this object:
import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;  @RemoteServiceRelativePath("login") public interface LoginService extends RemoteService {   public LoginInfo login(String requestUri); }
the service Async interface:
import com.google.gwt.user.client.rpc.AsyncCallback;  public interface LoginServiceAsync {   public void login(String requestUri, AsyncCallback async); }
and the service implementation:
import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; import com.google.gwt.sample.stockwatcher.client.LoginInfo; import com.google.gwt.sample.stockwatcher.client.LoginService; import com.google.gwt.user.server.rpc.RemoteServiceServlet;  public class LoginServiceImpl extends RemoteServiceServlet implements     LoginService {    public LoginInfo login(String requestUri) {     UserService userService = UserServiceFactory.getUserService();     User user = userService.getCurrentUser();     LoginInfo loginInfo = new LoginInfo();      if (user != null) {       loginInfo.setLoggedIn(true);       loginInfo.setEmailAddress(user.getEmail());       loginInfo.setNickname(user.getNickname());       loginInfo.setLogoutUrl(userService.createLogoutURL(requestUri));     } else {       loginInfo.setLoggedIn(false);       loginInfo.setLoginUrl(userService.createLoginURL(requestUri));     }     return loginInfo;   }  }
Note that to use the UserService of google accounts you need to instantiate a user Object. If the user is already logged in, the call of userService.getCurrentUser(); will return this user. Else it will return null and we will need to redirect the user to login. We create the login URL using the:userService.createLoginURL(requestUri) . It will return the login url for your application. Also to get the logout url you just need to call:userService.createLogoutURL(requestUri) .
Don't forget to configure the LoginServiceImpl in the web.xml file (you can see an example of how to do this here).

To call this service in the view use:
LoginServiceAsync loginService = GWT.create(LoginService.class);     loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback() {       public void onFailure(Throwable error) {       }        public void onSuccess(LoginInfo result) {         loginInfo = result;         if(loginInfo.isLoggedIn()) {           loadUserData();         } else {           loadLogin();         }       }     });
That's it.
You may also save this LoginInfo object to the database, because it does not contain any password or anything like that.

To learn more you may visit the google code tutorial. All the source code of this post was taken from this tutorial.


Friday, July 24, 2009

AGILEBOTS - Another GWT Interface Libary

After playing a while with the GWT framework i decided to create a question-like twitter, focused on improving the knowledge of all the community.
To help create this site, i've started another project called AGILEBOTS. The main purpose of this project is to increase even more the speedy of GWT page building.

Many people that starts using GWT does not know how to create a page, or get too much time to create some basic widgets. Of course that GWT already has many widgets ready to be used. But AGILEBOTS will have much more widgets to be used on many kind of websites.

So it will be very different of frameworks that are on the market right now, like ExtGWT and many others. They have amazing widgets, but their widgets are more focused on form like websites. AGILEBOTS will aim all kind of sites. From a blog, to a company site that desire to have a very cool help system. That will be the focus of AGILEBOT.

If you want to give a look at what we are doing with agilebots you may go to the agilebots site where there is some of the widgets i've created until now.

Some of the widgets AGILEBOTS will have are:
  • Easy menu-like frontpage
  • Dynamic HELP
  • FormFields
  • Tooltips
and much more.

Wednesday, July 22, 2009

DivPanel - Creating a new Widget

Create a composite or extend a widget ?

This question has many answers. In the end it all depends on what is your needs.

When you want to make many widgets work together, like the labeltextbox we created before it's better to create a composite. But when you need to create a new behavior for your widget, maybe it's better to extend a base widget.

As example we will extend the simplePanel, that supports only one widget inside it, to support as many widgets as we need.

Unlike the HorizontalPanel and the VerticalPanel, that uses tables to align the widgets inside it, the simplePanel uses a div to wrap its widget.

Here is the code:

public class DivPanel extends SimplePanel {


private WidgetCollection children = new WidgetCollection(this);


public DivPanel() {

super();

}


public Widget getWidget(int index) {

return getChildren().get(index);

}


public int getWidgetCount() {

return getChildren().size();

}


public int getWidgetIndex(Widget child) {

return getChildren().indexOf(child);

}


public Iterator iterator() {

return getChildren().iterator();

}


public boolean remove(int index) {

return remove(getWidget(index));

}


@Override

public boolean remove(Widget w) {

// Validate.

if (w.getParent() != this) {

return false;

}

// Orphan.

orphan(w);


// Physical detach.

Element elem = w.getElement();

DOM.removeChild(DOM.getParent(elem), elem);


// Logical detach.

getChildren().remove(w);

return true;

}

public void add(Widget child){

add(child,getElement());

}


protected void add(Widget child, Element container) {

// Detach new child.

child.removeFromParent();


// Logical attach.

getChildren().add(child);


// Physical attach.

DOM.appendChild(container, child.getElement());


// Adopt.

adopt(child);

}


protected WidgetCollection getChildren() {

return children;

}


}

First and most important we need to rewrite the add method (the simplePanel.add method verify if you already added a widget and throws an exception).
Second we need to create a WidgetCollection to hold all the widgets that will be accessed.
Let's take a look at the add(Container,widget).
If we use the DOM.appendChild method our page will look like we want, but we need also to call the adopt(widget) method, so the events and handlers already associated with the widget still works.

Also when extending an widget it's very important to know what will be your base class.
It could be the widget class, some Panel class, maybe a TextBox... and so on. Choosing the rigth base widget is a key factor.

Note that when extending the widget class you need also to create a DOM element and call the setElement method. This is the method responsable for binding your element to the page.

Here is another example:

public class DockDiv extends DivPanel{


public final static int NORTH = 0;

public final static int SOUTH = 1;

public final static int EAST = 2;

public final static int WEST = 3;

public final static int CENTER = 4;

private Element north = DOM.createDiv();

private Element south = DOM.createDiv();

private Element east = DOM.createDiv();

private Element west = DOM.createDiv();

private Element center = DOM.createDiv();

private Element row = DOM.createDiv();

private Element container = DOM.createDiv();

public DockDiv(){

container.appendChild(north);

container.appendChild(row);

container.appendChild(south);

row.appendChild(west);

row.appendChild(center);

row.appendChild(east);

getElement().appendChild(container);

east.getStyle().setProperty("float", "left");

west.getStyle().setProperty("float", "left");

center.getStyle().setProperty("float", "left");

}

public void add(Widget child){

add(child,center);

}

public void add(Widget child, int pos){

switch (pos) {

case NORTH:

add(child,north);

break;

case SOUTH:

add(child,south);

break;

case EAST:

add(child,east);

break;

case WEST:

add(child, west);

break;

default:

add(child, center);

break;

}

}

public Element getRegion(int region){

switch (region) {

case NORTH:

return north;

case SOUTH:

return south;

case EAST:

return east;

case WEST:

return west;

default:

return center;

}

}

@Override

public void setWidth(String width) {

super.setWidth(width);

north.getStyle().setProperty("width", width);

row.getStyle().setProperty("width", width);

south.getStyle().setProperty("width", width);

}

public void setCenterSize(String west, String center, String east){

if (west != null && !west.equals("")){

this.west.getStyle().setProperty("width", west);

}

if (center != null && !center.equals("")){

this.center.getStyle().setProperty("width", center);

}

if (east != null && !east.equals("")){

this.east.getStyle().setProperty("width", east);

}

}

}

as you see this DockDiv extends the divPanel (working with divs, not tables).
Also there is some DOM Elements and in the add method we decide what element will be the container of the widget. This shows that you may create as many elements you need.

Friday, July 17, 2009

Composites - When you need to group widgets

When developing an user interface it's quite common to need components more complex than the ones that are available to us. By example the textfield widget does not have a label by default and every time we need to put a text field on a form, we also need to put a label with it.
And if we could create a new widget that was composed of a label and a textfield?
That's the main purpose of the Composite class. The Composite is a widget composed of widgets.
You may create a LabelTextBox composite, that has a label and a textfield. This way you don't need anymore to create each time a label and a textbox (and maybe some panel to layout them). Now you just need to create a LabelTextBox.
Also, using the composite helps you to keep your code clean and organized, by encapsulating all the logic and configuration of those widgets inside the composite class.
Here is an example of a composite:

public class LabelTextField extends Composite {


private HorizontalPanel hPanel;

private Label lblField;

private TextBox txtField;

public LabelTextField(Label lbl, TextBox txt) {

lblField = lbl;

txtField = txt;

hPanel = new HorizontalPanel();

hPanel.add(lblField);

hPanel.add(txtField);

initWidget(hPanel);

}

public String getValue(){

return txtField.getText();

}

public String getLabel(){

return lblField.getText();

}

}

One of the rules to use the composite class is that we must associate another widget as the main widget of this composite, through the method initWidget(Widget w).
In this case the main widget is a HorizontalPanel.
Also note that we hided the TextBox and the Label objects from the external access, and only exposed the getText() methods of the objects.

Thursday, July 16, 2009

How to upload the chat application to google AppEngine

In the last post we finished the chat application. Now we will learn how to upload it to google appengine.

First log in to the appEngine site with your google account.
If this is the first time you log in into appengine it will ask to validate your mobile number. (Please, don't forget to put also the country code and the area code. )
After you validate you will be able to create your first application.
Choose an application ID avaliable and the application title hit the save button.

After all you need to do is open your eclipse project. Select the project properties -> Google -> AppEngine and set the id of the application. You may also set the version of the application(the AppEngine keeps track of the versions, and you can make any version the one default). After just click on the appengine icon (its close to the button you hit to create a google project and the button to compile the gwt). Fillin your email and password, and you're done.
That's all you need to create a chat application and publish it to the internet.

Wednesday, July 15, 2009

How to create a simple chat using GWT and AppEngine - Second Part

Now comes the second part of the tutorial to create a basic chat.

In the last part we created the base of the interface and the base of the server.
Now we will create the Persistence Manager.

Create a new package under the server package named persist.

Now create a Class named PMF. Here is the code:

public final class PMF {


private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");


private PMF(){ }

public static final PersistenceManagerFactory getFactory(){

return pmfInstance;

}

public static final PersistenceManager getManager(){

return getFactory().getPersistenceManager();

}

public static final void saveObject(Object obj){

getManager().makePersistent(obj);

}

}

This class uses the PersistenceManagerFactory to get a PersistenceManager. This manager is responsable for saving, updating and deleting the objects. (Notice that this class is very simple just to explain this example).
Now open the Shout class. We need to set the time that the message was sent.
Add the Date field sentAt to it.

@Persistent

private Date sentAt;

also great the get and set for this field.
Now change the shoutToServer method of the ShoutServiceImpl class. This is the code:

public String shoutToServer(Shout s){

s.setSentAt(new Date());

PMF.saveObject(s);

return s.getMessage();

}

we just set the date to today and save the message.
Now all of our messages been saved. We need now to display them on the browser.
Create a method getAllShouts in the ShoutServiceImpl class. This is the code:

public List getAllShouts() {

Query query = PMF.getManager().newQuery(Shout.class);

query.setOrdering("sentAt ascending");

List resultset = (List)query.execute();

return resultset;

}

Here we get the PersistenceManager and create a new query based on the Shout class.
next we order the results acording to the sentAt field.
This will return all the messages in the server.
Next we need to create a method that will return only messages newer than a date we will pass.
Create a method called get getNewerThan that will receive a Date parameter. This is the code:

public List getNewerThan(Date now) {

PersistenceManager manager = PMF.getManager();

Query q = manager.newQuery(Shout.class);

ArrayList result = new ArrayList();

List resultset = (List)q.execute();

for (Shout a: resultset){

if (a.getSentAt().after(now)){

result.add(a);

}

}

return result;

}

Here we filter the messages to the ones that were sent only after some specific date. We will need this to update the browser with new messages.
Now we need to update the ShoutService and ShoutServiceAsync with this methods too. Here are the codes:
ShoutService:

public List getAllShouts();

public List getNewerThan(Date now);

ShoutServiceAsycn:

void getAllShouts(AsyncCallback> callback);

void getNewerThan(Date now, AsyncCallback> callback);

Now that your interfaces are updated let's change the EntryPoint (The .java).

First create a Date attribute called lastUpdatedAt and a Timer attribute caled t.
Here is the code:

final VerticalPanel messagesPanel = new VerticalPanel();

private Date lastUpdatedAt;

Timer t;

private void checkMessages(){

t.schedule(1000);

}

private void configureTimers(){

t = new Timer(){

@Override

public void run() {

shoutService.getNewerThan(lastUpdatedAt, new AsyncCallback>(){

public void onFailure(Throwable caught) {

checkMessages();

}

public void onSuccess(List result) {

if (result.size() > 0){

for (Shout i: result){

messagesPanel.add(new HTML(i.getMessage()));

}

lastUpdatedAt = result.get(result.size()-1).getSentAt();

}

checkMessages();

};

});

}

};

}

Here we created the Timer and the Date attributes and also changed the scope of the messagesPanel, making it accessible to all methods in the class.
In the checkMessages() method we just start the Timer, and the timer will get all the messages that were sent after the last message received.
Don't forget to remove the messagesPanel from inside the onModuleLoad method.

Finally add this to the end of the onModuleLoad method:

configureTimers();

shoutService.getAllShouts(new AsyncCallback>(){

public void onFailure(Throwable caught) {

checkMessages();

}

public void onSuccess(List result) {

for (Shout i: result){

messagesPanel.add(new HTML(i.getMessage()));

if (i.getSentAt().after(lastUpdatedAt)){

lastUpdatedAt = i.getSentAt();

}

}

checkMessages();

}

});

this will configure the timer object and also get all the messages that were sent before opening the page.
This will also start the Timer, that will loop now forever.

Here we got our chat. Later you may add a name's field to identify who is sending the message if you want.

That's all folks!
Next i will teach how to send this project online to Google AppEngine.

Until there!

Tuesday, July 14, 2009

How to create a simple chat using GWT and AppEngine - First Part

UPDATED - 2009-07-15 - WEB-INF info

Well, today i will start a series of tutorials about making some stuff in gwt.
We will begin transforming the default project the google eclipse plugin generates.

After installing the google plugin for eclipse (you may find here how to install the plugin), let's create a web application project, by clicking the google blue icon in the toolbar

After you choose your Project Name and the initial package of the project

Also select to use both GWT and App Engine sdks.

This will create a simple project with two main packages:
  • Client
  • Server
In the client package will stay all the code GWT will compile to javascript, and in the server package will stay all the code that will run on the app engine server.

Also the plugin already creates a page with a server communication. It has a textbox and a button, and when you click the button it sends the content of the textbox to the server and get a string to show in the page.

We will also add to this page a list with all the messages sent previously and also update it often using ajax.

So these are the steps we will take:
  1. add a new line to the table in the html
  2. Create a Panel and add it to the line created
  3. Create a model class to represent the message sent - We will call this class "Shout"
  4. Create a service to send this shout to the server
  5. implements the client call to the service

First we will create in the html page (it has the name of the project and stay in the war package) a place to put all of the messages.
We will do this by adding a new line to the table:


what we are doing here is creating a new container to put our panel with the messages.


Now we need to edit the java code to add a new panel in this row.
Open the .java (it is the client package) - We will call this file the EntryPoint, as it implements the EntryPoint interface. We will edit the onModuleLoad method.

Add a new final VerticalPanel and call it messagesPanel

public void onModuleLoad() {

final VerticalPanel messagesPanel = new VerticalPanel();

final Button sendButton = new Button("Send");

final TextBox nameField = new TextBox();


now we will add this panel to the row we created in the html :

// Add the nameField and sendButton to the RootPanel

// Use RootPanel.get() to get the entire body element

RootPanel.get("nameFieldContainer").add(nameField);

RootPanel.get("sendButtonContainer").add(sendButton);

RootPanel.get("messagesContainer").add(messagesPanel);


The RootPanel.get(id) method returns the element in the page with the id we passed, so we can add widgets to it.
Now our panel will be placed right under the textbox and the button.
Well now we need to create the Model class tha will represent the message we are sending.
First let's create a new package under the client package, named "model", and inside this package lets create a new Class, called "Shout".
This class must implements the serialize interface.
Also we need to put some JDO information to be able to save it in the database.
This is the code to the Shout class:

@PersistenceCapable(identityType=IdentityType.APPLICATION)

public class Shout implements Serializable{


@PrimaryKey

@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)

private Long id;

@Persistent

private String message;

public Shout(){}

public Shout(String message){

this.message = message;

}


public String getMessage() {

return message;

}


public void setMessage(String message) {

this.message = message;

}


public Long getId() {

return id;

}

}

The @PersistenceCapable annotation mark this class as persistance and each field that shoud be stored must have the @Persistence annotation on it.

Well now that we have our model we must create a service to send it to the server.
First let's create a ShoutService interface in the client package and also a ShoutServiceAsync interface.
In the first we should add a method that will receive a Shout and return a String, this is the code of the ShoutService:

@RemoteServiceRelativePath("shout")

public interface ShoutService extends RemoteService{


String shoutToServer(Shout s);

}

this interface must extends the RemoteService and also must define the path to access this service using the RemoteServiceRelativePath annottation.

In the ShoutServiceAsync we should add a void method that will receive a Shout object and a AsyncCallback object.
This is the code to the ShoutServiceAsync:

public interface ShoutServiceAsync {


void shoutToServer(Shout s, AsyncCallback callback);

}

Now we need to create the server side service.
Let's create the ShoutServiceImpl in the server package.

@SuppressWarnings("serial")

public class ShoutServiceImpl extends RemoteServiceServlet implements ShoutService{


public String shoutToServer(Shout s){

return s.getMessage();

}

}

this class must extend te RemoteServiceServlet and also implements the interface of the Service we created before. Notice that it implements the Service and not the ServiceAsync.
For now our method will just return the message of the Shout object.
Well, now we are almost there.
Let's change now the behavior of the click of the send button.
Get back to the entrypoint class and create a ShoutServiceAsync final variable:

/**

* Create a remote service proxy to talk to the server-side Greeting service.

*/

private final GreetingServiceAsync greetingService = GWT

.create(GreetingService.class);

private final ShoutServiceAsync shoutService = GWT.create(ShoutService.class);


notice that we declare the service using the Asycn interface, but in the GWT method we use the Service class.

Now, look for the method "sendNameToServer". and remove the code inside it, we wont need it anymore.
next put this code:

sendButton.setEnabled(false);

Shout s = new Shout(nameField.getText());

nameField.setText("");

shoutService.shoutToServer(s, new AsyncCallback(){

public void onFailure(Throwable caught) {};

public void onSuccess(String result) {

messagesPanel.add(new HTML(result));

sendButton.setEnabled(true);

};

});

we are just creating a shout using the text in the textfield, reseting the textfield and calling the service method, passing our shout and the asyncCallback.
In the callback we can do something if the method fails, like by connection reset or a exception in the server using the onFailure method.
In the onSuccess method we put our code to treat the answer of the server.
In this case we are just adding the string into a HTML widget inside the panel. As the panel is a VerticalPanel all this widgets will be placed one under the other.

----UPDATED----------

Also you need to edit the web.xml file inside the WEB-INF directory.
You need to configure your servlets (The ShoutServiceImpl).
Just copy and paste the greetServlet and change the servlet-name to shoutServlet and the servlet-class to your.path.to.ShoutServiceImpl . Also copy and paste the servlet-mapping of the greetServlet and change the servlet-name to shoutServlet and the url-pattern to /[module-name]/shout .
Observe that this /shout is the name we put on the service interface annottation: @RemoteServiceRelativePath("shout").

-----UPDATED-----------

In this is it. In the next post we will save this shout in the database and load the shout list when the page is loaded and keeping updating the list while the page is open.

See you there!