Leyendo ajaxian em encontre con un muy buen manual sobre como hacer una pagina de inicio similar a igoogle.
Para logra este objetivo utilizaremos prototype.
El diseño que muestra la pagina es muy practico sobre todo si vamos a tener un portal o una pagina de inicio, a continuación les copio y pego el código fuente que mas adelante les diré donde lo pueden consultar, obviamente requeriremos la utilización de librerías como prototype y sus componentes, pueden checar esta y otras librerías en este aquí: Librerías Javascript
Archivo portal.js
Pueden descargarlo de aqui: Portal.js
// Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// “Software”), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// VERSION 1.1-trunk
if(typeof Draggable == ‘undefined’)
throw(“widget.js requires including script.aculo.us’ dragdrop.js library”);
if(typeof Builder == ‘undefined’)
throw(“widget.js requires including script.aculo.us’ builder.js library”);
// Xilinus namespace
if(typeof Xilinus == ‘undefined’)
Xilinus = {}
Builder.dump();
Xilinus.Widget = Class.create();
Xilinus.Widget.lastId = 0;
Object.extend(Xilinus.Widget.prototype, {
initialize: function(className, id) {
className = className || “widget”;
this._id = id || (“widget_” + Xilinus.Widget.lastId++);
this._titleDiv = DIV({className: className + ‘_title’, id: this._getId(“header”)}, “”);
this._contentDiv = DIV({className: className + ‘_content’, id: this._getId(“content”)}, “”);
this._footerDiv = DIV({className: className + ‘_statusbar’, id: this._getId(“footer”)}, “”);
var divHeader = DIV({className: className + ‘_nw’ }, this._titleDiv);
var divContent = DIV({className: className + ‘_w’ }, this._contentDiv);
var divFooter = DIV({className: className + ‘_sw’ }, this._footerDiv);
this._div = DIV({className: className + (className != “widget” ? ” widget” : “”), id: this._getId()}, [divHeader, divContent, divFooter]);
this._div.widget = this;
return this;
},
getElement: function() {
return $(this._getId()) || $(this._div);
},
setTitle: function(title) {
$(this._titleDiv).update(title);
return this;
},
getTitle: function(title) {
return $(this._titleDiv)
},
setFooter: function(title) {
$(this._footerDiv).update(title);
return this;
},
getFooter: function(title) {
return $(this._footerDiv)
},
setContent: function(title) {
$(this._contentDiv).update(title);
return this;
},
getContent: function(title) {
return $(this._contentDiv)
},
updateHeight: function() {
$(this._contentDiv).setStyle({height: null})
var h = $(this._contentDiv).getHeight();
$(this._contentDiv).setStyle({height: h + “px”})
},
// PRIVATE FUNCTIONS
_getId: function(prefix) {
return (prefix ? prefix + “_” : “”) + this._id;
}
});
Xilinus.Portal = Class.create()
Object.extend(Xilinus.Portal.prototype, {
lastEvent: null,
widgets: null,
columns: null,
initialize: function(columns, options) {
this.options = Object.extend({
url: null, // Url called by Ajax.Request after a drop
onOverWidget: null, // Called when the mouse goes over a widget
onOutWidget: null, // Called when the mouse goes out of a widget
onChange: null, // Called a widget has been move during drag and drop
onUpdate: null, // Called a widget has been move after drag and drop
removeEffect: Element.remove // Remove effect (by default no effect), you can set it to Effect.SwitchOff for example
}, options)
this._columns = (typeof columns == “string”) ? $$(columns) : columns;
this._widgets = new Array();
this._columns.each(function(element) {Droppables.add(element, {onHover: this.onHover.bind(this), overlap: “vertical”})}.bind(this));
this._outTimer = null;
// Draggable calls makePositioned for IE fix (??), I had to remove it for all browsers fix
to handle properly zIndex
this._columns.invoke(“undoPositioned”);
this._currentOverWidget = null;
this._widgetMouseOver = this.widgetMouseOver.bindAsEventListener(this);
this._widgetMouseOut = this.widgetMouseOut.bindAsEventListener(this);
Draggables.addObserver({ onEnd: this.endDrag.bind(this), onStart: this.startDrag.bind(this) });
},
add: function(widget, columnIndex, draggable) {
draggable = typeof draggable == “undefined” ? true : draggable
// Add to widgets list
this._widgets.push(widget);
// Add element to column
this._columns[columnIndex].appendChild(widget.getElement());
widget.updateHeight();
// Make header draggable
if (draggable) {
widget.draggable = new Draggable(widget.getElement(),{ handle: widget._titleDiv, revert: false});
widget.getTitle().addClassName(“widget_draggable”);
}
// Update columns heights
this._updateColumnsHeight();
// Add mouse observers
if (this.options.onOverWidget)
widget.getElement().immediateDescendants().invoke(“observe”, “mouseover”, this._widgetMouseOver);
if (this.options.onOutWidget)
widget.getElement().immediateDescendants().invoke(“observe”, “mouseout”, this._widgetMouseOut);
},
remove: function(widget) {
// Remove from the list
this._widgets.reject(function(w) { return w == widget});
// Remove observers
if (this.options.onOverWidget)
widget.getElement().immediateDescendants().invoke(“stopObserving”, “mouseover”, this._widgetMouseOver);
if (this.options.onOutWidget)
widget.getElement().immediateDescendants().invoke(“stopObserving”, “mouseout”, this._widgetMouseOut);
// Remove draggable
if (widget.draggable)
widget.draggable.destroy();
// Remove from the dom
this.options.removeEffect(widget.getElement());
// Update columns heights
this._updateColumnsHeight();
},
serialize: function() {
parameters = “”
this._columns.each(function(column) {
var p = column.immediateDescendants().collect(function(element) {
return column.id + “[]=” + element.id
}).join(“&”)
parameters += p + “&”
});
return parameters;
},
addWidgetControls: function(element) {
$(element).observe(“mouseover”, this._widgetMouseOver);
$(element).observe(“mouseout”, this._widgetMouseOut);
},
// EVENTS CALLBACKS
widgetMouseOver: function(event) {
this._clearTimer();
var element = Event.element(event).up(“.widget”);
if (this._currentOverWidget == null || this._currentOverWidget != element) {
if (this._currentOverWidget && this._currentOverWidget != element)
this.options.onOutWidget(this, this._currentOverWidget.widget)
this._currentOverWidget = element;
this.options.onOverWidget(this, element.widget)
}
},
widgetMouseOut: function(event) {
this._clearTimer();
var element = Event.element(event).up(“.widget”);
this._outTimer = setTimeout(this._doWidgetMouseOut.bind(this, element), 100);
},
_doWidgetMouseOut: function(element) {
this._currentOverWidget = null;
this.options.onOutWidget(this, element.widget)
},
// DRAGGABLE OBSERVER CALLBACKS
startDrag: function(eventName, draggable) {
var widget = draggable.element;
var column = widget.parentNode;
// Create and insert ghost widget
var ghost = DIV({className: ‘widget_ghost’}, “”);
$(ghost).setStyle({height: widget.getHeight() + ‘px’})
column.insertBefore(ghost, widget);
// IE Does not absolutize properly the widget, needs to set width before
widget.setStyle({width: widget.getWidth() + “px”});
// Absolutize and move widget on body
Position.absolutize(widget);
document.body.appendChild(widget);
// Store ghost to drag widget for later use
draggable.element.ghost = ghost;
// Store current position
this._savePosition = this.serialize();
},
endDrag: function(eventName, draggable) {
var widget = draggable.element;
var column = widget.ghost.parentNode;
column.insertBefore(draggable.element, widget.ghost);
widget.ghost.remove();
if (Prototype.Browser.Opera)
widget.setStyle({top: 0, left: 0, width: “100%”, height: widget._originalHeight, zIndex: null, opacity: null, position: “relative”})
else
widget.setStyle({top: null, left: null, width: null, height: widget._originalHeight, zIndex: null, opacity: null, position: “relative”})
widget.ghost = null;
widget.widget.updateHeight();
this._updateColumnsHeight();
// Fire events if changed
if (this._savePosition != this.serialize()) {
if (this.options.url)
new Ajax.Request(this.options.url, {parameters: this.serialize()});
if (this.options.onUpdate)
this.options.onUpdate(this);
}
},
onHover: function(dragWidget, dropon, overlap) {
var offset = Position.cumulativeOffset(dropon);
var x = offset[0] + 10;
var y = offset[1] + (1 – overlap) * dropon.getHeight();
// Check over ghost widget
if (Position.within(dragWidget.ghost, x, y))
return;
// Find if it’s overlapping a widget
var found = false;
var moved = false;
for (var index = 0, len = this._widgets.length; index < len; ++index) {
var w = this._widgets[index].getElement();
if (w == dragWidget || w.parentNode != dropon)
continue;
if (Position.within(w, x, y)) {
var overlap = Position.overlap( 'vertical', w);
// Bottom of the widget
if (overlap < 0.5) {
// Check if the ghost widget is not already below this widget
if (w.next() != dragWidget.ghost) {
w.parentNode.insertBefore(dragWidget.ghost, w.next());
moved = true;
}
}
// Top of the widget
else {
// Check if the ghost widget is not already above this widget
if (w.previous() != dragWidget.ghost) {
w.parentNode.insertBefore(dragWidget.ghost, w);
moved = true;
}
}
found = true;
break;
}
}
// Not found a widget
if (! found) {
// Check if dropon has ghost widget
if (dragWidget.ghost.parentNode != dropon) {
// Get last widget bottom value
var last = dropon.immediateDescendants().last();
var yLast = last ? Position.cumulativeOffset(last)[1] + last.getHeight() : 0;
if (y > yLast && last != dragWidget.ghost) {
dropon.appendChild(dragWidget.ghost);
moved = true;
}
}
}
if (moved && this.options.onChange)
this.options.onChange(this)
this._updateColumnsHeight();
},
// PRIVATE FUNCTIONS
_updateColumnsHeight: function() {
var h = 0;
this._columns.each(function(col) {
h = Math.max(h, col.immediateDescendants().inject(0, function(sum, element) {
return sum + element.getHeight();
}));
})
this._columns.invoke(“setStyle”, {height: h + ‘px’})
},
_clearTimer: function() {
if (this._outTimer) {
clearTimeout(this._outTimer);
this._outTimer = null;
}
}
});
Y nuestro HTMl o php que sera donde deseemos mostrar el portal o la pagina de inicio contendra el siguiente codigo.
Este codigo es el de la pagina llamada test portal y se encuentra en : http://blog.xilinus.com/prototype-portal/test/index.html
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
Portal test page
Recuerden para agregar mas widgets seria de la misma forma ejemplo
portal.add(new Xilinus.Widget().setTitle(“Widget #1.0″).setContent(latin1), 0);
portal.add(new Xilinus.Widget().setTitle(“Widget #1.1″).setContent(latin2), 0);
portal.add(new Xilinus.Widget().setTitle(“Widget #1.2″).setContent(latin3), 0);
portal.add(new Xilinus.Widget().setTitle(“Ventana mia”).setConent(latin1 + latin2 + lation3),0) ;
// La sintaxis a grandes rasgos dice lo siguiente.
//portal.add(new Xilinus.Widget().setTitle(“El titulo de la ventana).setConent(“El contenido”),numero de posición en el portal expresado en columnas 0,1,2)
Los archivos que se necesitar adicionalmente viene con la libreria prototype.
Enlace | Create your own iGoogle with Prototype
Via | Ajaxian
Demo | Protal Test
Google | iGoogle
Les tengo un interesante post si me da tiempo lo publico mañana en el dia (aqui en mexico son las 00:31 de la mañana )si no mañana en la noche.
Proyecto Avance = 90%
Related Photos
No related photos.






3 Responses
Hola, te queria preguntar por esta parte del codigo, no la puedo comprender, ya que estoy buscando como le puedo agregar un campo ${valor}, que sera un valor que reciba y que debe estar dentro de ese div. Nose como se debe agregar
this._contentDiv = DIV({className: className + ‘_content’, id: this._getId(”content”)}, “”); uedo pasar un valor al div adentro del mismo
Buen tutorial, ha ver si lo puedo modificar para que sea dinámico, sabes como guardar las posiciones en un mysql?¿
PD: te linkado en mi blog però he utilizado el link de tufuncion.com te han copiado o tambien es tuyo?¿
Saludos.
Donde se puede conseguir descargar todo en un solo paquete?… porque veo que hasta en la web de prueba: http://blog.xilinus.com/prototype-portal/test/index.html cuando damos a editar, nos lleva a ningun lado!
solo agrega el simbolo de # a index.html