Sencha (ExtJS) Map Control

En esta semana se me metió la idea a la cabeza de hacer un control de ExtJS para manejar mapas. Por ejemplo, supongamos que tienes que hacer una aplicación donde te dan una imagen de un fraccionamiento y tienes que identificar todas las propiedades en dicha imagen y luego mostrar el mapa con una imagencilla que indica el estatus (si ya esta vendida, en renta, o lo que sea).

Google maps nos saca del apuro muchas veces, pero a veces necesitamos usar nuestras propias imagenes (mapas), es por eso que comenzé a desarrollar este controlillo.

El control en acción:



Antes de comenzar es necesario hacer pruebas de CSS para ver que atributos necesitamos para que el mapa aparezc adentro de un cuadrito (DIV), para esto es necesario poner un div (al que llamaré wrapper) y es necesario que tenga posición "relative" y overflow: hidden. Esto es para que la imagen no se aplaste dentro del wrapper. Despues, a la imagen le ponemos posición "absolute" y listo, ya tenemos una imagen encerrada dentro de un div igual que google maps. Lo que sigue es agregarle la funcionalidad drag a la imagen interna para poder moverla dentro del div. Lo que todos sabemos es que si ponemos un elemento del DOM en posicion absoluta, este ignorará la jerarquia del DOM y "flotará" por encima de los demás, sin embargo, si su padre tiene posición relativa (como el wrapper), entonces este quedará atrapado dentro de su padre.

Esta algo confuso, pero asi funciona y eso no lo sabia jojo.

Apenas llevo la primera etapa, ya funciona el "Drag" del mapa para moverlo y cuando das click pone una marker, el siguiente paso es guardar toda la info de las markers y serializarlas para poder enviarlas al server, tambien falta el setValues, para que puedas regresar las markers desde el server y mostrarlas en el mapa, pero bueno, esto me lo eche en una noche, espero terminarlo pronto y subirlo completo.

Pero bueno, el codigo del control es el siguiente:


Ext.ns('Ext.ux.ImageMap');

Ext.ux.ImageMap = Ext.extend(Ext.form.Field, {
initComponent : function(){
/*Apply modified Properties, Listeners dont work here*/
Ext.apply(this,{
autoCreate : {tag:'div', style:'position:relative; overflow:hidden; border:1px solid black;'}
});
this.markers = [];
/*Change Normal Events*/
Ext.ux.ImageMap.superclass.initComponent.apply(this, arguments);
}
,onRender : function (){
Ext.ux.ImageMap.superclass.onRender.apply(this, arguments);
var me = this;
/*Main Overflown wrapper*/
this.wrapper = this.el;
/*Create inner wrapper with image inside */
this.innerwrapper = this.wrapper.createChild({
tag : 'div'
,style : 'position:absolute;'
,children : [{
id : this.mapId = Ext.id() + 'map'
,tag : 'img'
,src : this.bgimage
}]
});


/*Add click event*/
this.innerwrapper.on({
click: function(evt){
if(!me.endDrag){

me.addMarker(evt.xy);
}else{
//Reste drag flag
me.endDrag = false;
}
}
})
/*Set Draggable Actions*/
this.dd = new Ext.dd.DD(this.innerwrapper, 'group');
Ext.apply(this.dd,{
endDrag : function(e){
/*Flag to avoid firing the click event when its a drag*/
me.endDrag = e.getTarget().id == me.mapId ? true : false;
}
});

}
,addMarker : function(p){
var m = this.innerwrapper.createChild({
tag : 'div'
,html :' '
,cls : this.markerImgClass
});
this.markers.push(m);
var ctXY = this.wrapper.getXY();
var imgXY = this.innerwrapper.getXY(); //absolute to frame

//Calculate position
var pos = [];
pos[0] = ctXY[0] - imgXY[0];
pos[1] = ctXY[1] - imgXY[1];
p[0] = pos[0] + (p[0] - ctXY[0])-8;
p[1] = pos[1] + (p[1] - ctXY[1])-8;
m.setLeftTop(p[0], p[1]);

console.log(this.markers);
}
});



Ext.onReady(function(){

/*To use the control just add it to a form or render it to a div*/
var form = new Ext.form.FormPanel({
renderTo :'container'
,title : 'Image Control'
,items : [

new Ext.ux.ImageMap({
height :200
,width :300
,hideLabel : true
,bgimage : '../assets/images/map.jpg' //map image you want to use
,markerImgClass : 'markerImgClass' //marker image
})
]

});
});



Jerry ;)

Dynamically loading any JS File on Demand (Including Google Maps api)

Developing with ExtJS is a pleasure, the best engineered js framework out there.
At work we decided to start using it to develop a BIG project and its all made with ExtJS and CodeIgniter for the server side code.

The main requirement is to make the application as fast and reliable as possible and even though we are no even at the middle of it, we already have like 25+ JS files containing a variety of extended components. We also need to use Googlemaps/map24/M$maps depending on the user configuration and so on.

We've tried compressing all of the source code and putting into one single js file, but the file size is about 500kb + Maps API + ExtJS Api + anything else that we will need later.

So, what to do now? Lazy Load to the rescue =)

For all of you who don't know what that means, is "Loading js files on demand" duh!.

I started looking everywhere and found many different options but any of those satisfied my needs.
Requirements:
  1. Avoid at all cost storing JS code in the database.
  2. Eval Function is Evil!
  3. Need to know when the js code has been loaded.
From all of the options reviewed, only the first 2 requirements where met.

So, I grab the best from all of the approaches reviewed and this is the result:


Ext.ux.lazyLoad is a Singleton, you can copy and paste this code into a js file and start using it as follows:


Ext.ux.lazyLoad.get('gmap', function(obj){
Alert("Google Maps Has Been Loaded");
//Your code goes here and will be executed after loading the js file
},this);


This means that every time we need to call a function that is tied to a class that has been dynamically loaded, we need to do it by proxy-ing using the get function from the lazyLoad object. This object keeps track of what js files has been loaded and if it is loaded already it only calls the callback function supplied by you using the scope that you send.


The lazyLoad Singleton

The function inside the singleton uses the defer function from extjs to check every 2 seconds if the js has been loaded by evaluating the "checkLoad" variable from the "objects" variable. In the mean time, you can put a mask on your components while waiting for the code to load, since this will only happend the first time.

This way, we are sure that the classes, functions and everything we need have been loaded before using em'.

This component is working like a charm on our system, so I hope it can be useful for anyone of my fellow ExtJS developers.

Any questions, critics or suggestions are very welcome =)

Happy Coding , Jerry

/**
* Ext.ux.lazyLoad
*
* @author Jerry Sosa (sosamv) Published with the permission of Near It Services (nearitservices.com)
* @version Ext.ux.lazyLoad.js
* @date 10. February 2001
*
* @license Ext.ux.lazyLoad is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/


Ext.namespace('Ext.ux.lazyLoad');
/********************************************************************
*@name Ext.ux {Singleton}
* Load javascript files onDemand
**/
Ext.ux.lazyLoad = function() {

var debug = false;
var objects = {
gmap:{
loaded:false
,checkLoad : 'GMap2' /*Variable that must exists to confirm load*/
,url:'http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAZtXebGuEUyPUsb16TunzchQH1vzzQPdXCsLMkqVnPRtWvfSdoRToJrguncXU9Z0FgvbgReXeej9BDQ&sensor=false&async=2'
}
,ctrlPropertiesGrid:{
loaded:false
,checkLoad : 'Ext.ux.customControl'
,url:'/app/properties/Ext.ux.customControl.js'
}
//.....ADD HERE MORE FILES
}
return{
/*
* @name Ext.ux.lazyLoad.get
* Retrieve js files on demand if not loaded
* @params
* -jsKey {String}: Js File name to load
* -callback {function}: function to be executed after
* -scope {Object}: Object scope to run the callback function
**/
get : function(jsKey, callback, scope){
/*Return if is not a valid object*/
if(!objects[jsKey]) return;

/*Run thread*/
var waitCounter = 0;
this.thread(jsKey, callback, scope, waitCounter, 'loadScript' + Ext.id());
}
/*
*@name Ext.ux.lazyLoad.thread
*Reusable thread to check if js file has been loaded
*@params
* -jsKey{String}: js key from the objects array
* -callback{Function}: function to execute when file is loaded
* -waitCointer{Integer}: Current cycle number
* -id{String}: Id used to identify the script tag
**/
,thread : function(jsKey, callback, scope, waitCounter, id){

/*If its loaded*/
if(this.isLoaded(jsKey)){
callback.call(scope);
}else{
/*If script object hasnt been included, do it*/
if(!Ext.get(id)){
/*If hasnt been loaded*/
/*Prepare url*/
var url = objects[jsKey].url;

this.head = document.getElementsByTagName('head').item(0);
script = document.createElement('script');
script.src = url;
script.type = 'text/javascript';
script.id = id;
this.head.appendChild(script);
}
if(debug)Ext.get('testdiv').insertHtml('beforeEnd',jsKey + ' wait counter:'+ waitCounter+'
');
try{
var checkVar = eval(objects[jsKey].checkLoad);
objects[jsKey].loaded = true;
callback.call(scope);
this.clean(id);
return;
}catch(e){
if(waitCounter++ <10){
/*Will check 10 times every 2 seconds if the js has been loaded*/
this.thread.defer(2000, this, [jsKey, callback, scope, waitCounter,id]);
}else{
this.clean(id);
alert("Problem loading libraries");
}
}

}
}
/*
* @name Ext.ux.lazyLoad.clean
* Removes recently used script tag from dom
**/
,clean : function(id){
var scriptTag = document.getElementById(id);
if(scriptTag) this.head.removeChild(scriptTag);
}
/*
* @name Ext.ux.lazyLoad.isLoaded
* Getter function to retrieve status
**/
,isLoaded : function(jsKey){
return objects[jsKey].loaded;
}
}
}();


/*USAGE EXAMPLE*/
Ext.onReady(function() {

Ext.ux.lazyLoad.get('gmap', function(obj){
Alert("Google Maps Has Been Loaded");
//Your code goes here and will be executed after loading the js file
},this);

});


Protocolos de comunicación AJAX

Un protocolo es una serie de reglas a seguir para poder establecer una comunicación entre 2 o mas programas, computadoras, entre otras.

Si haz desarrollado en Java usando threads y sockets, probablemente sabes a que me refiero, es importante establecer reglas y eviarlas "over the wire" para que se pueda establecer una conversación coherente.

Esto tiene mucho que ver con respuestas de XMLHttpRequest. En la arquitectura web tenemos 2 lugares de "trabajo", el server y el cliente. Estos 2 workspaces trabajan en un universo completamente diferente, esto quiere decir que variables del server no pueden ser vistas por el cliente, al menos de manera directa y por lo tanto una sentencia o accion de server no puede provocar un refresh del cliente (vdd nena? jaja) o viceversa. Cada dia salen mas y mas nuevas tecnologias que buscan acortar la distancia entre ambos "universos", sin embargo esto es solo una ilusion, al menos por ahora, pues solo son procedimientos que te hacen pensar que el lenguaje cliente y lenguaje server pudieran ser uno mismo cuando en realidad existen todo tipo de metodos o tweaks por atras. Para que este fuera posible, la arquitectura cliente-servidor deberia de rehacerse.

Muy bien, una vez aclarado esto es tiempo de comenzar.


Accion de server a Cliente

Muy bien, supongamos que tenemos una aplicación de chat en la web que se actualiza por medio de llamadas asincronas conectandose con el server cada 5 segundos, que sucede si en una de esas llamadas se nos niega la conección (Ya sea porque lo tumbaron, ya no esta loggeado u otras), como le hacemos para redirigirlo a la pagina de login??

Lo que tenemos que hacer es desarrollar un mini protocolo de comunicación entre el cliente y el server, que ambos lo entiendan (o al menos que nosotros lo entendamos).

por ejemplo:

Server (PHP)
 echo "{success:false, errorType:1, data:{...}}"

Cliente (Javascript)
 //Obtenemos la respuesta por medio de un XMLHttpRequest
 var response = eval(ajaxResponse);
 //Apartir de aqui, podemos hacer lo que queramos con el JSON
 if(response.errorType == 1){
   window.location = "../index.php"
 }

*El ejemplo es solo para motivos didacticos

Este tip es de lo mas sencillo, lo dificil para algunos es la arquitectura web, que se puede hacer y que no =P

Una vez que le agarramos la onda, todo tipo de loqueras se nos empiezan a ocurrir jaja.


Introduction to ExtJS

Hi! in my previous posts I talked about some basic tips and tricks any web and javascript developer should know and posted a very handy video that explains the rest of them. That should be more than enough to start learning the amazing world of ExtJS.

I'd like to add that I "discovered" ExtJS existence when I downloaded an open source project management application called opengoo which all of its main UI components were made by ExtJS.

What's ExtJS?


It's an amazing javascript framework!!...Amazing you say? indeed! It is a complete toolkit that enable us to make professional ajaxed web applications in minutes, without caring about css styling or performance, ExtJS does it for you.

In a Nutshell

The framework can be devided in two:

ExtJS Core : This is the utility library, whats that? well, have you heard of JQuery, prototype, yui? it's the same thing, it contains DOM Selectors, Animations, Event Handling and many more, but if you are more familiar with those above, ExtJS has something called "Adapters", this adapters will let you use Jquery or prototype as your core library insted of Ext's it will work the same.

ExtJS : This is an efficient, powerful and very well engineered widget library which has out of the box Grid Panels, Trees, Modal windows, menus, form controls and many more. All of this components were crafted using the best javascript patterns and practices that even enable you to extend all of the components functionality and even mix components to adapt to your application needs without making changes to the framework source.


ExtJS is going UP!

This framework has been rated by Gartner as "promising" for the near future along with adobe flex and others.

Since it is made of pure javascript code, html and css, its is possible to use this framework with adobe air and create desktop applications.

Avery day more developers are starting to use ExtJS, however the current user base have already created a bunch of custom opensource controls for you to use, you'll be amazed by those eye candy controls ;)


In the next post i'll create a "Hello ExtJS" till we get to "Creating Big Applications Using ExtJS" =) it's going to be interesting, stay tunned !

Bye!

All you need to know About javascript


This is one of the best tutorials I've found about javascript out there, its a compilation of the best techniques important for our everyday work.

I should've put this video instead of my last 2 posts ¬¬ hahaha

It's one hour long, but it's worth it!!!



How to structure your javascript. Part 2


Hi and welcome to the second edition of this javascript tutorial =)

In this tutorial I'm going to show Object Oriented capabilities (emulation) in javascript.
As you may know, javascript is an interpreted language and was not conceived to be object oriented for many reasons, actually nobody though it would be used as it is right now.

You can probably be wondering, why would I need this in js? well, I you like to become a javascript ninja, this is were you need to start.

In all of the next examples we're going to be using JSON (javascript object notation). If you have no clue what this is, take a look at this tutorial.

Let's begin =)

One of the neat features of the OO paradigm is to create "objects" which have methods and properties that "encapsulate" this characteristics within the object. In our first example we will create a car.


//car object first approach
var car = {
speed : 0
,accelerate : function(){
this.speed++;
}
,tachometer : function(){
alert(this.speed);
}
}

//Accelerate the car
for(var i = 0; i<=100; i++){
car.accelerate();
}

//How fast am I going?
car.tachometer();


In this example we created a car object which has properties (speed) and methods (accelerate, tachometer), using this approach we can only have one car, the one we just created and that's it, it is like a super variable (Singleton) with methods and properties and that's not too object oriented :S.
I use this approach as my application entry point were I initialize all of my components.


The second approach is as follows:

//car object second approach
var car = function(){
//Private Variables
var speed = 0;

return{
//Prublic variables
doors : 4
//Public functions with access to private variables
,accelerate : function(){
speed++;
}
,tachometer : function(){
alert(speed);
}
}
};

//create car instances
var bmw = new car();
var audi = new car();

//Accelerate the car
for(var i = 0; i<=100; i++){
bmw.accelerate();
}
//Notice that we haven't move our audi from the garage =P
bmw.tachometer(); // alerts 99
audi.tachometer(); // alerts 0


This example has more OO properties that the first one, here we have public and private variables and also methods plus with this approach we can create instances of the object and use it several times.

Important Note: Notice how some variables are declared using var and others not, when we use "var" inside a function the variable is "trapped" inside the scope of that function and any other that might be inside of it. I you declare variables without the "var" you're creating global variables attached to the "window" namespace.

I know i raised the bar a little bit in this post, so if I confuse any of you, let me know and I will modify the post.

Thanx for reading =)

How to structure your javascript. Part 1

Hi everyone, today i'll talk about javascript coding practices and how to structure your code to avoid variable collisions when making big js applications.

Every time a page is loaded, the client (browser) creates a variable/namespace called "window" which is like a little native framework provided on any page by the browser.
This namespace contains basic information about the client like view port width and height, the document variable, and many others. The naming of each variable can change from browser to browser and that's the primarily reason why javascript frameworks are created.

When we declare a js variable it is "stored" within the window namespace:

//run this code in Firebug console
foo = 1;
alert(window.foo);
alert(foo);

//Alerts 1 two times


As we can see, everything we declare this way is going to be saved withing the window namespace. Right now everything works perfect because we are using only one foo var, but what happen if we start creating a javascript widget which has a lot of functions and variables, we will "pollute" this namespace and ran out of names sooner or later.

If we want to keep our global namespace (window) clean, we can use an "anonymous" function to create a "closure" and encapsulate our variables inside. If you dont know what a javascript closure is, what are you waiting? take a look at this link.

Example:


//delete the foo variable from last example
delete foo;

(function(){
var foo = 1;

})();

//undefined uh?
alert(foo);



After running this snippet, we can take a look to the window variable in firebug and see that there's no "foo" variable listed inside, which means we can only use our foo variable inside that closure. Anonymous functions are very useful, it is also important to remember that a function in javascript is also a variable type along with strings, ints, arrays and objects:


var foo = function(){
alert("Function as a variable =)");
}

alert(typeof(foo));

//use it like this
foo();


This examples are very basic but i've found that no so many web developers know about 'em.

In part 2 we will continue with JSON classes and how they help us to emulate Object Oriented capabilities in javascript =) its going to be interesting and hopefully by the end of this series we will be able to start writing our own javascript framework =)

Thanx for reading!