lunes, 11 de octubre de 2010

Error JavaScript en LookupField Control

Hoy he estado peleándome con uno de esos errores que odias encontrar, ya que son de esos errores que cuesta un poco reproducir, y por lo tanto su resolución no se prevé facilona.

Voy a intentar situarlos en contexto:

Cuando mostramos un LookupField control, por ejemplo al editar un item de una lista que uno de sus campos es un lookup hacia otra lista (editform.aspx), éste se puede mostrar de dos maneras diferentes, una cuando la lista a la que hacemos el lookup tiene menos de 20 items o 20 items y otra cuando tiene más de 20 items. En el primer caso, el control muestra un DropDownList y en el segundo muestra un textbox, un par de literales y una imagen (para no hacer que el dropdown sea demasiado largo), con ciertas llamadas a funciones javascript.

Una de estas llamadas se ejecuta al hacer click en la imagen, concretamente es una llamada a la función ShowDropdown que se encuentra en el fichero core.js. Esta función acaba llamando a otras dos funciones AbsLeft y AbsTop, que son el objeto de este post.

Código original de las funciones:

function AbsLeft(obj)
{
var x=obj.offsetLeft;
var parent=obj.offsetParent;
while (parent.tagName !="BODY")
{
x+=parent.offsetLeft;
parent=parent.offsetParent;
}
x+=parent.offsetLeft;
return x;
}

function AbsTop(obj)
{
var y=obj.offsetTop;
var parent=obj.offsetParent;
while (parent.tagName !="BODY")
{
y+=parent.offsetTop;
parent=parent.offsetParent;
}
y+=parent.offsetTop;
return y;
}


Resulta que estas dos funciones lanzan un null reference exception cuando el control lookup esta contenido dentro de un div y ese div contiene un position:relative.



Googleando un poco me he encontrado que este era un error conocido, pero la resolución que daban en un foro de sharepoint no me parecía la correcta, a saber, eliminar el position:relative.



http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/91f91a91-434f-444d-8a96-7823c91f862e



Mi solución final ha sido sobreescribir estas funciones en la master page de mi solución:



function AbsLeft(obj) {
var x = obj.offsetLeft;
var parent = obj.offsetParent;

while (parent != null && parent.tagName != "DIV" && parent.tagName != "BODY") {
x += parent.offsetLeft;
parent = parent.offsetParent;
}

if (parent != null && parent.tagName != "DIV" && parent != null) x += parent.offsetLeft;

return x;
}

function AbsTop(obj) {
var y = obj.offsetTop;
var parent = obj.offsetParent;

while (parent != null && parent.tagName != "DIV" && parent.tagName != "BODY") {
y += parent.offsetTop;
parent = parent.offsetParent;
}

if (parent != null && parent.tagName != "DIV" && parent != null) y += parent.offsetTop;

return y;
}


Pero aquí no ha acabado todo, estas funciones estan dentro del core.js y el core.js tiene el atributo defer=True, por lo tanto, nunca se llamaban a las funciones que había sobreescrito. Solución: cambiar este attributo añadiendo lo siguiente en la master page.

<SharePoint:ScriptLink language="javascript" name="core.js" Defer="false" runat="server"/>



Para más información sobre el attribute defer, aquí.

No hay comentarios: