Cómo modificar la Ribbon en SharePoint 2010
abr.
17
Escrito el:
17/04/2012
En este segundo Post sobre la Ribbon, quiero mostrar las principales personalizaciones que como desarrolladores suelen ser interesantes para aplicar en proyectos de adaptación.
Las más habituales son:
- Agregar un botón a un grupo existente
- Deshabilitar o cambiar el comportamiento de un botón
- Agregar un nuevo grupo
Cómo empezar
Por supuesto, para comenzar, necesitamos Visual Studio 2010, donde comenzaremos con un Empty Sharepoint Project.
Añadimos una nueva Feature, y elegimos el ámbito (Site, Web, Web Application).
Añadimos un Empty Element al proyecto, de modo que tendremos su correspondiente Elements.xml, el cual será la base para implementar la definición de nuestra modificación de la Ribbon (o cinta, como suele ser el convenio de traducción).
Definición del fichero Elements.xml
En realidad, las modificaciones de la Ribbon se llevan a cabo dentro de un CustomAction, con su correspondiente ámbito de aplicación, y por tanto, nuestro esquema del XML será:
|
Definiremos el ámbito de la modificación de la Ribbon (un Content Type, una List Definition, global, etc.) |
|
Lo veremos más en detalle abajo |
Custom Action
Una de las primeras dudas que surgen es en qué ámbito vamos a aplicar la personalización de la Ribbon.
Aquí veremos la referencia de la MSDN:
http://msdn.microsoft.com/en-us/library/ms460194.aspx
Custom Action para modificar la Ribbon en Biblioteca de Documentos
Alternativa 1: la mostraremos en cualquier biblioteca que herede del Template de Document Library:
<
CustomAction
Id
=
"Internav.CA.Ribbon.CheckGroups"
RegistrationId
=
"101"
RegistrationType
=
"List"
Location
=
"CommandUI.Ribbon"
>
Alternativa 2: nos basamos en el Content Type:
<
CustomAction
Id
=
"Internav.CA.Ribbon.CheckGroups"
RegistrationId
=
"0x0101"
RegistrationType
=
"ContentType"
Location
=
"CommandUI.Ribbon"
>
Alternativa no válida: omitir RegistrationId y RegistrationType. Veremos adelante que un CustomAction no vinculado a ninguna lista no ContentType sólo es válido para lugares que no estén vinculados directamente a ningún tipo de lista de Sharepoint.
En el ejemplo desarrollado abajo, que es la página de modificación de permisos, no debemos especificar ningún RegistrationType, ya que no estamos vinculando realmente a una lista.
CommandUIDefinition
En primer lugar, tengamos una cosa en cuenta: todos los Contextual Tabs, Tabs, Grupos y botones de la Ribbon están ya definidas en ..\14\template\global\xml\CMDUI.XML.
En realidad con un CommandUIDefinition lo que hacemos es de forma declarativa, modificar dicho fichero XML, por lo que cada elemento CommandUIDefinition lo que hará es modificar la definición estándar, añadiendo, o sobrescribiendo.
Así, por ejemplo, si un Location define RUTAXML._children, lo que hará es que el elemento definido dentro del CommandUIDefinition se insertará como hijo del elemento RUTAXML.
Así, por ejemplo:
Añadir un grupo al Ribbon.Permission
El padre es, por tanto, un Tab llamado Ribbon.Permission. Es interesante abrir siempre el CMDUI.XML, para copiar y pegar desde ahí el nombre del elemento padre.
Así pues, en este caso: Location=Ribbon.Permission.Groups._children
En el interior del CommandUIDefinition, tendremos pues que incluir, esta jerarquía:
Además, un grupo tiene que tener un determinado Scaling, con lo que habría que definir otro elemento adicional CommandUIDefinition con Location=Ribbon.Permission.Scaling._children, con este contenido:
- MaxSize Id=”id_elegido_por_nosotros” Sequence=”101” GroupId=”GroupId_definido_anteriormente” Size=”LargeLarge”
En este caso, hacemos que nuestro grupo sólo se pueda mostrar con iconos grandes. La definición LargeLarge en realidad viene determinada por el Template que hayamos asignado a nuestro Group.
Consejo: usemos siempre, salvo que tengamos necesidades especiales, el mismo GroupTemplate que los grupos hermanos del que estamos añadiendo. Si usamos otro GroupTemplate, y no lo utiliza la Ribbon en otro grupo distinto, no funcionaría si no forzamos por servercode que se cargue explícitamente.
Añadir un botón a un grupo
Este caso es mucho más sencillo, ya que nuestro CommandUIDefinition será: Ribbon.Permission.Check.Controls._children
Cuidado: reitero la importancia de copiar y pegar desde el CMDUI.XML, ya que hay casos como el grupo de añadir permisos, cuyo Id tiene controls en minúscula, así que tengámoslo en cuenta. Los Id los podemos escoger libremente, pero en Location no puede haber errores.
En un ejemplo posterior veremos cómo personalizar la página de modificación de permisos.
Modificar la Ribbon en la página de modificación de permisos
Esta página es accesible mediante /_layouts/User.aspx, y en realidad tiene una Ribbon vinculada a una lista especial interna de Sharepoint que, por tanto, no podremos encontrar su definición en ninguna Feature estándar, con lo que buscarla no ayudará demasiado.
Este sería el fichero Elements.xml completo:
Location
=
"CommandUI.Ribbon"
> <
CommandUIExtension
> <
CommandUIDefinitions
> <
CommandUIDefinition
Location
=
"Ribbon.Permission.Check.Controls._children"
> <
Button
Id
=
"Evotec.CA.Ribbon.CheckGroups.BtnVerGrupos"
Command
=
"Evotec.CA.Ribbon.VerGruposAction"
Sequence
=
"101"
Image16by16
=
"/_layouts/$Resources:core,Language;/images/formatmap16x16.png"
Image16by16Top
=
"-176"
Image16by16Left
=
"-192"
Image32by32
=
"/_layouts/$Resources:core,Language;/images/formatmap32x32.png"
Image32by32Top
=
"-256"
Image32by32Left
=
"-64"
LabelText
=
"Ver grupos"
Alt
=
"Ver grupos"
ToolTipTitle
=
"Ver grupos"
ToolTipDescription
=
"Ver grupos"
TemplateAlias
=
"o1"
/> CommandUIDefinition
> CommandUIDefinitions
> <
CommandUIHandlers
> <
CommandUIHandler
Command
=
"Evotec.CA.Ribbon.VerGruposAction"
CommandAction
=
"javascript: function AccionBoton() { var items = GetSelectedPrincipals(); var mensaje = items.strNames; mensaje = $.url.decode(mensaje); SP.UI.Notify.addNotification('Has seleccionado: ' + mensaje); } AccionBoton();"
EnabledScript="javascript: function CheckBoton() { var
items
=
GetSelectedPrincipals
(); return (items.strIds.length > 0); } CheckBoton();"/> CommandUIHandlers
> CommandUIExtension
> CustomAction
> Elements
>
Éste es el resultado:
CommandUIDefinition.Location |
Este es el parámetro más importante cuando definimos una modificación/añadido sobre una Ribbon.En nuestro caso lo que hacemos es añadir un elemento sobre la colección Ribbon.Permission.Check.Controls.El último token: _children es especial, e indica que el contenido interior del CommandUIDefinition se añadirá como un nuevo miembro en una colección ya definida previamente en el CMDUI.XML. |
Id |
Los Id en general son libres y los podemos usar como queramos con la convención interna de nuestro proyecto. Suele ser buena práctica usar Namespaces separados con puntos, comenzando con el nombre de nuestra empresa, para evitar colisiones. Importante no confundirnos con los Location mencionados antes, ya que estos nos tenemos que ceñir. |
Command |
El Command definido dentro del “Button” tiene que coincidir con el definido en el CommandUIHandler. En este caso también es una notación interna nuestra, con lo que no hay ninguna regla a seguir. |
EnabledScript |
Este será el código ECMAScript a ejecutar para verificar si el botón estará o no deshabilitado. El patrón más habitual es habilitar el botón si hay algún elemento seleccionado en la lista.Habitualmente esta operación se consigue haciendo referencia a la ECMAScript Class Library que incluye Sharepoint 2010: SP.ListOperation.Selection.getSelectedItems()…Sin embargo, en una página de edición de permisos no es una lista normal, y este método devuelve siempre un Array vacío.
Por supuesto, siempre hay alternativa, y de hecho, la ApplicationPage /_layouts/user.aspx incluye definida una función que los propios de Microsoft utilizan para habilitar o no el resto de botones de la Ribbon: esta es GetSelectedPrincipals(), que nos devuelve un objeto con los Ids y con los nombres, separados con comas.
|
CommandAction |
En nuestro ejemplo, simplemente tomaremos los nombres seleccionados, los descodificamos (recordemos, están URLEncoded).En este ejemplo, usamos la librería jQuery $.url.decode, que previamente hemos incluido mediante otro proyecto que nos permite utilizar jQuery y cualquier otra libraría JS necesaria en Sharepoint 2010. |
Consejos importantes
La ribbon es un componente que depende 100% de ECMAScript, y por tanto, muy sensible a cualquier error u omisión. Es decir, si activamos nuestra Feature y tiene algún error, nos podemos encontrar que la Ribbon completa deja de funcionar, o está deshabilitada. Probablemente nunca encontremos error de compilación, ni al activar la Feature (salvo tengamos un Elements.xml mal formado, claro).
Cuidado con las cachés
Mención especial son las cachés del navegador. Consejo importante al desarrollar: usemos el modo privado de Internet Explorer (o Firefox), y entre prueba y prueba cerramos la sesión InPrivate de Internet Explorer y volvemos a abrirlo, ya que hay Scripts de ECMAScript que se quedan en caché en memoria y un Control + F5 no es suficiente, puesto que hay muchos JS que se cargan en diferido.
De forma alternativa, podemos usar la DevBar de Internet Explorer, o Firebug, y deshabilitar toda caché del navegador. Esto nos puede ahorrar muchas horas de problemas.
¿Ribbon o Menú ECB (Edit Control Block)?
Desde el punto de vista de usabilidad, especialmente cuando hablamos de una biblioteca de documentos, un usuario está acostumbrado a realizar acciones tanto desde el menú ECB como desde la Ribbon. Esto nos lleva a una cuestión importante: si añadimos un botón en la Ribbon, probablemente sea pertinente incluirlo también en el ECB. Este último caso se resuelve fácilmente mediante una Custom Action.