Friday, December 21, 2012

3D user interfaces: Navigating in space between information nodes

Each information node is displayed in the middle and the related ones are grouped around it, by relation type. Tapping another information node, takes you to it, and it brings it's own related content into the scene.

In our cases the information nodes can either be iPad apps or people that recommend them.






www.taia76.com

Thursday, December 20, 2012

3D user interfaces: lists and scrolling in 3D

In a 3D UI traditional vertical, or even touch horizontal scroll doesn't work anymore. Instead, the information is divided in pages, and they are stacked one in from of the other. When the user swipes the page it moves to become the last in the stack, and the one behind it becomes first. Swiping in the other direction reverses the action.







More on the app website:
www.taia76.com

Sunday, December 16, 2012

3D user interfaces in HTML5/JavaScript

I have always thought, that the next step in UI design, is adding the 3rd dimension. Throughout the history, there have been many attempts, but all of them failed because instead of simplifying the user experience they just made it harder.

Last night, I and a friend released our first app, for iPad, that is our approach on 3d user interfaces.


There have been many challenges, especially since the entire UI is HTML5/Javascript based. But one by one we managed to overcome them. How would you think scrolling in 3d works? :)

More information on the website: www.taia76.com

Monday, September 17, 2012

MVC in javascript

See code, running application and qunit test here: http://www.danbunea.ro/blogspot/mvcjs/

Problem

Today, in modern web applications, more and more code is moved from being generated server side (in java, c# with asp.net , ruby on ror, php) to be executed on the client browser, in javascript. This created a massive problem for all those used to having code well organized in modern web frameworks using the very powerfull Model View Controller pattern, since most of the code is written now in javascript.

Could MVC in javascript be a solution?

Well, there are more and more frameworks trying to adress the problem of having tons of javascript, whioch becomes a nightmare as well as replace the dynamic generation on the server , thinks such backbone.js, but I find it not very MVC. So why wouldn't I actually write my own MVC framework.

The first thing we want to do it actually list the users on the page, so that means the controller is invoked, it takes the decistion to load the users from the server into the model, and after that send the model to the view to render the users as html. So we have an html file index.html

...
<body>

<div id="list">
 <a href="http://www.blogger.com/blogger.g?blogID=9648422#" id="add" onclick="controller.add();">Add</a>
 <div id="usersList">
 </div>
</div>
<div id="form">
</div>
<div id="tests">
 <h1 id="qunit-header">
mvc.js</h1>
</div>
</body>  
    <h2 id="qunit-userAgent">
</h2>
<ol id="qunit-tests">  
    </ol>
</pre>
<script>


 


jQuery(window).load(function () {

    controller = new UsersController();
    controller.index();
});

</script>


</body>

</html>
 

now the controller class:

UsersController.prototype = new Object;
//constructor definition
UsersController.prototype.constructor = UsersController;


function UsersController() {
 this.model = new UsersModel();
 this.view=new UsersView();
};


UsersController.prototype.index=function(){
 this.model.loadUsers();
 this.view.renderUsersList(this.model);
};

and the model:

UsersModel.prototype = new Object;
//constructor definition
UsersModel.prototype.constructor = UsersModel;

function UsersModel()
{
 this.users=[];
}

UsersModel.prototype.loadUsers=function()
{
 this.users = eval(new HttpRequest().get("http://localhost/users/list.aspx"));
};
 
now let's see the view that renders the list. For it we actually use jQuery templates:

UsersView.prototype = new Object;
//constructor definition
UsersView.prototype.constructor = UsersView;

function UsersView()
{
    //templates
    this.userLine = "<div if='user${user.id}' class='user' >"+
 " <div id='fullName${user.id}' class='cell'>${user.fullName}</div>"+
 " <div id='username${user.id}' class='cell'>${user.username}</div>"+
 " <div id='email${user.id}' class='cell'>${user.email}</div>"+
 " <div class='cell'><a id='edit${user.id}' href='#' onClick='controller.edit(${user.id})'>Edit</a></div>"+
 " <div class='cell'><a id='delete${user.id}' href='#' onClick='controller.delete(${user.id})'>Delete</a></div>"+
 "</div>";
 jQuery.template("userLine", this.userLine);

}

UsersView.prototype.renderUsersList=function(model)
{
 jQuery("#usersList").html("");
 jQuery("#list").show();
 jQuery("#form").hide();

 for(var i=0;i<model.users.length;i++)
 {
  jQuery.tmpl("userLine", { user: model.users[i] }).appendTo("#usersList");
 }
};

Hmmm, very simple. Now let's implement the add:

UsersController.prototype.add=function(){
 this.view.renderAdd();
};

UsersController.prototype.save=function(id,fullName,username,password,email){
  id=this.model.users.length+1;
  this.model.users.push({id:id,fullName:fullName,username:username,password:password, email:email});

};
 
and in the view:

UsersView.prototype = new Object;
//constructor definition
UsersView.prototype.constructor = UsersView;

function UsersView()
{
    //templates
    this.userLine = "<div if='user${user.id}' class='user' >"+
 " <div id='fullName${user.id}' class='cell'>${user.fullName}</div>"+
 " <div id='username${user.id}' class='cell'>${user.username}</div>"+
 " <div id='email${user.id}' class='cell'>${user.email}</div>"+
 " <div class='cell'><a id='edit${user.id}' href='#' onClick='controller.edit(${user.id})'>Edit</a></div>"+
 " <div class='cell'><a id='delete${user.id}' href='#' onClick='controller.delete(${user.id})'>Delete</a></div>"+
 "</div>";
 jQuery.template("userLine", this.userLine);

    this.userForm = "<div class='fields'  style='display:table-row'>"+
 " <div id='fullName_${user.id}' style='display:table-row'>Full Name:<input id='fullName' type='text' value='${user.fullName}'/></div>"+
 " <div id='username_${user.id}' style='display:table-row'>Username:<input id='username' type='text' value='${user.username}'/></div>"+
 " <div id='password_${user.id}' style='display:table-row'>Password:<input id='password' type='password' value='${user.password}'/></div>"+
 " <div id='email_${user.id}' style='display:table-row'>Email:<input id='email' type='text' value='${user.email}'/></div>"+
 " <a id='save' href='#' onClick='controller.save(\"${user.id}\",jQuery(\"#fullName\").val(),jQuery(\"#username\").val(),jQuery(\"#password\").val(),jQuery(\"#email\").val());'>Save</a>"+
 " <a id='cancel' href='#' onClick='controller.list();'>Cancel</a>"+
 "</div>";
 jQuery.template("userForm", this.userForm);
}


...



UsersView.prototype.renderAdd=function()

{

    var user={fullName:"",username:"",password:"",email:"" };



    jQuery("#form").html("").show();

    jQuery("#list").hide();



    jQuery.tmpl("userForm", { user: user}).appendTo("#form");

};

Now what about edit?

UsersController.prototype.edit=function(id){
 var user = this.model.findUserById(id);
 this.view.renderEdit(user);
};

UsersController.prototype.save=function(id,fullName,username,password,email){
 if(id=="") 
 {
  id=this.model.users.length+1;
  this.model.users.push({id:id,fullName:fullName,username:username,password:password, email:email});
 }
 else
 {
  var user = this.model.findUserById(id);
  user.fullName=fullName;
  user.username=username;
  user.password=password;
  user.email=email;
 }
 this.view.renderUsersList(this.model);
};

and in the model:

UsersModel.prototype.findUserById=function(id)
{
 for(var i=0;i<this.users.length;i++)
 {
  if(this.users[i].id==id)
  return this.users[i];
 }
 return null;
};

and the view is refactored to:

UsersView.prototype = new Object;
//constructor definition
UsersView.prototype.constructor = UsersView;

function UsersView()
{
    //templates
    this.userLine = "<div if='user${user.id}' class='user' >"+
 " <div id='fullName${user.id}' class='cell'>${user.fullName}</div>"+
 " <div id='username${user.id}' class='cell'>${user.username}</div>"+
 " <div id='email${user.id}' class='cell'>${user.email}</div>"+
 " <div class='cell'><a id='edit${user.id}' href='#' onClick='controller.edit(${user.id})'>Edit</a></div>"+
 " <div class='cell'><a id='delete${user.id}' href='#' onClick='controller.delete(${user.id})'>Delete</a></div>"+
 "</div>";
 jQuery.template("userLine", this.userLine);

    this.userForm = "<div class='fields'  style='display:table-row'>"+
 " <div id='fullName_${user.id}' style='display:table-row'>Full Name:<input id='fullName' type='text' value='${user.fullName}'/></div>"+
 " <div id='username_${user.id}' style='display:table-row'>Username:<input id='username' type='text' value='${user.username}'/></div>"+
 " <div id='password_${user.id}' style='display:table-row'>Password:<input id='password' type='password' value='${user.password}'/></div>"+
 " <div id='email_${user.id}' style='display:table-row'>Email:<input id='email' type='text' value='${user.email}'/></div>"+
 " <a id='save' href='#' onClick='controller.save(\"${user.id}\",jQuery(\"#fullName\").val(),jQuery(\"#username\").val(),jQuery(\"#password\").val(),jQuery(\"#email\").val());'>Save</a>"+
 " <a id='cancel' href='#' onClick='controller.list();'>Cancel</a>"+
 "</div>";
 jQuery.template("userForm", this.userForm);
}

UsersView.prototype.renderUsersList=function(model)
{
 jQuery("#usersList").html("");
 jQuery("#list").show();
 jQuery("#form").hide();

 for(var i=0;i<model.users.length;i++)
 {
  jQuery.tmpl("userLine", { user: model.users[i] }).appendTo("#usersList");
 }
};

UsersView.prototype.renderAdd=function()
{
 var user={fullName:"",username:"",password:"",email:"" };
 this.renderForm(user);
};

UsersView.prototype.renderEdit=function(user)
{ 
 this.renderForm(user);
};


UsersView.prototype.renderForm=function(user)
{
 jQuery("#form").html("").show();
 jQuery("#list").hide();

 jQuery.tmpl("userForm", { user: user}).appendTo("#form");
};

Conclusion

As you can see above, implementing MVC in javascript can be very simple and doesn't require any sort of frameworks. Once MVC is implemented the code is well organized depending on concerns: who commands - controller, where by one look you can see what the entire code does (list, add, save, edit) the model who holds the data and exchanges it with the server and the view which actually renders it in html when asked by the controller.Simple to implement, well organized, easy to follow the code, very extensible.