SSD: el síndrome de la Sharepoint dependencia

Sharepoint me proporciona seguridad y me hace sentir más fuerte. Las 10 cosas que más me gustan de Sharepoint.

10 puntos para entender a Project Server 2010

Microsoft Project es quizá la herramienta de gestión de proyectos más conocida y utilizada por los líderes de proyectos...

Diseño Gráfico en SharePoint

Serie de artìculos que nos ayudan a incorporar diseño gráfico en las implementaciones de SharePoint...

Revista CompartiMOSS

Artículos publicados en la revista especializada en SharePoint: CompartiMOSS.

Contacto

Enviame un correo :-)

Mostrando entradas con la etiqueta JavaScript. Mostrar todas las entradas
Mostrando entradas con la etiqueta JavaScript. Mostrar todas las entradas

miércoles, 2 de julio de 2014

Relaciones de Maestro Detalle en SharePoint 2007 con jQuery (simple y efectivo) [Parte 2]

Introducción
Un requerimiento que siempre surge en SharePoint tiene que ver con manejar relaciones de maestro-detalle. He visto y utilizado diferentes formas, con ventajas y desventajas que siempre dependen del escenario en que nos encontremos. En el artículo original mostramos un ejemplo para WSS 3.0 que utiliza programación del lado del cliente.

Si no leíste ese artículo, te recomiendo su lectura en: Relaciones de maestro detalle en SharePoint 2007.

Segunda parte
En esta segunda parte vamos a modificar uno de los 4 scripts, el del padre, para que soporte diferentes tipos de contenido en el hijo. A continuación el código (cambios resaltados):

<script type="text/javascript">

// Agregar esta CEWP debajo de la vista de la lista Padre


// Parámetros importantes

// Posición en que se encuentra la columna ID
var posicion_id = 3;
// Posición en que se encuentra la columna Tipo de Contenido
var posicion_tc = 4;
// Nombre de la lista hija
var lista_hija = "blabla";
// Texto para el botón o imagen
var texto_boton = "<img style='border: none;' src='/_layouts/images/itann.gif'/ title='Agregar ...' >";
// Estilo del botón nuevo
var estilo_boton = "";
// Título columna
var titulo_columna = "Agregar";
// Tipos de Contenido
var tipos_de_contenido = {
Proyecto:"0x010039837982075D1E4490A428B24D078C36", 
Programa:"0x01004B51B7C49BE3CE459ECEE01CACD0CF2F00C53AA5923F258A41A1C1A8354004CF68", 
Producto:"0x01004B51B7C49BE3CE459ECEE01CACD0CF2F00C53AA5923F258A41A1C1A8354004CF68"
};

// Fin de Parámetros importantes



// Id de ítem
var identificador;

// Tipo de Contenido
var tipo_contenido;

// URL del sitio
var sitio= window.location.href;
var origen = encodeURIComponent(sitio);
var posicion_listas = sitio.indexOf("Lists/");
sitio = sitio.substring(0, posicion_listas); 


// URL de nuevo elemento en el hijo
var nuevo_hijo = sitio + "Lists/" + lista_hija + "/NewForm.aspx?source=" + origen + "&padre=";


// Cambiar Título de columna
$(".ms-listviewtable > tbody > tr > th #diidSortID").text(titulo_columna);


// Cambiar columna
// Asumo que la lista usa la vista standar que posee la clase .ms-listviewtable
$(".ms-listviewtable > tbody > tr").each(function( index ) {  

// Obtengo el ID del elemento
identificador = $(this).find("td:nth-child("+posicion_id+")").text();

// Obtengo el Tipo de Contenido
tipo_contenido = $(this).find("td:nth-child("+posicion_tc+")").text();

// Cambio el ID por el botón nuevo
$( this ).find("td:nth-child("+posicion_id+")").html("<a style='" + estilo_boton + "' href='" + nuevo_hijo + identificador + "&ContentTypeId=" + tipos_de_contenido[tipo_contenido] + "'>" + texto_boton + "</a>") ;

}); 

</script>

miércoles, 11 de diciembre de 2013

Relaciones de Maestro Detalle en SharePoint 2007 con jQuery (simple y efectivo)

Introducción

Un requerimiento que siempre surge en SharePoint tiene que ver con manejar relaciones de maestro-detalle. He visto y utilizado diferentes formas, con ventajas y desventajas que siempre dependen del escenario en que nos encontremos. En este artículo vamos a mostrar un ejemplo para WSS 3.0 que utiliza programación del lado del cliente.

Funcionalidades que necesitamos

En esta lista detallo lo que necesitamos. A lo largo del artículo veremos cómo implementaremos cada caso:

· ¿Cómo vincular en las listas al padre y al hijo?

· ¿Cómo mostrar los hijos de un padre?

· ¿Cómo tener un botón que dispare la creación un hijo para el padre seleccionado?

· ¿Cómo crear un hijo sin tener que completar manualmente los datos del padre?

· ¿Cómo ocultar los datos del padre en el momento de editar el hijo?

¿Cómo vincular en las listas el padre y al hijo?

Para vincular, yo prefiero usar el campo ID del padre como referencia en el hijo. No creo que ese campo necesite ser de tipo “búsqueda”, con lo cual, simplemente creamos en el hijo un campo con estas características:

· Nombre = Padre (o lo que se adapte mejor a nuestro caso)

· Tipo = Texto

· Obligatorio

¿Cómo mostrar los hijos de un padre?

Una forma sencilla para evitar programación es usar las conexiones entre elementos web. Con lo cual, simplemente creamos una página de elementos web en donde:

· Agregamos en la parte superior una lista del padre

· Agregamos en la parte inferior la lista con los hijos

· Conectamos los dos elementos web, vinculando el ID del elemento web de arriba con el Padre del elemento web de abajo.

¿Cómo tener un botón que dispare la creación un hijo para el padre seleccionado?

Para disparar la creación de un hijo, vamos a agregar un botón llamado “Nuevo” en cada fila de la lista padre. Este botón puede ser simplemente un enlace. En principio existen al menos tres enfoques para agregar este botón:

· Mediante un flujo de trabajo

· Mediante un manejador de eventos

· Mediante código JavaScript

En este caso vamos a trabajar con código JavaScript. ¿Por qué? Porque las dos primeras opciones son asincrónicas y puede generar la necesidad de que el usuario tenga que actualizar la pantalla luego del alta del padre, para poder ver el botón “Nuevo”. Esto es difícil de explicar al usuario final.

Nuestro enfoque consistirá en:

· Un elemento web de edición de contenido (CEWP) que ejecute código Java Script que reemplace la columna ID por el nuevo botón.

· Para ello trabajaremos con jQuery

· El contenido de la CEWP lo almacenaremos en un archivo en una librería, para facilitar futuros cambios: maestro_dedalle_boton_nuevo.html

A continuación vemos el código necesario.

 

<script type="text/javascript">

// Agregar esta CEWP debajo de la vista de la lista Padre

// Parámetros importantes

// Posición en que se encuentra la columna ID

var posicion_id = 3;

// Nombre de la lista hija

var lista_hija = "Registros SP";

// Texto para el botón o imagen

var texto_boton = "<img style='border: none;' src='/_layouts/images/itann.gif'/ title='Agregar registro' >";

// Estilo del botón nuevo

var estilo_boton = "";

// Título columna

var titulo_columna = "Agregar";

// Fin de Parámetros importantes

// Id de ítem

var identificador;

// URL del sitio

var sitio= window.location.href;

var origen = encodeURIComponent(sitio);

var posicion_listas = sitio.indexOf("Lists/");

sitio = sitio.substring(0, posicion_listas);

// URL de nuevo elemento en el hijo

var nuevo_hijo = sitio + "Lists/" + lista_hija + "/NewForm.aspx?source=" + origen + "&padre=";

// Cambiar Título de columna

$(".ms-listviewtable > tbody > tr > th #diidSortID").text(titulo_columna);

// Cambiar columna

// Asumo que la lista usa la vista standar que posee la clase .ms-listviewtable

$(".ms-listviewtable > tbody > tr > td:nth-child("+posicion_id+")").each(function( index ) {

// Obtengo el ID del elemento

identificador = $( this ).text();

// Cambio el ID por el botón nuevo

$( this ).html("<a style='" + estilo_boton + "' href='" + nuevo_hijo + identificador + "'>" + texto_boton + "</a>") ;

});

</script>

En la imagen, podemos ver cómo se ve la lista antes y cómo se ve luego:

clip_image002

¿Cómo crear un hijo sin tener que completar manualmente los datos del padre?

Dentro de la pantalla NewForm vamos a realizar lo siguiente:

· Completar el valor del campo Padre

· Ocultar el campo Padre (la fila completa)

A continuación el código necesario:

<script type="text/javascript">

// Agregar esta CEWP en la parte de abajo de la pantalla NewForm.aspx

// Para que se abra el editor, utilizar ?toolpaneview=2

// Parámetros importantes

// Nombre del campo Padre

var campo_padre = "ID.";

// Fin de Parámetros importantes

// Completamos el valor del campo Padre

var valor_padre = url_param("padre");

$('input[title="' + campo_padre + '"]').attr("value",valor_padre);

$('input[title="' + campo_padre + '"]').parent().parent().parent().css("display","none");

// Función para leer un valor de parámetro de URL

function url_param ( name ){

name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");

var regexS = "[\\?&]"+name+"=([^&#]*)";

var regex = new RegExp( regexS );

var results = regex.exec( window.location.href );

if( results == null )

return "";

else

return results[1];

}

</script>

¿Cómo ocultar los datos del padre en el momento de editar el hijo?

Esto aplica tanto a la pantalla de edición, como a la pantalla de display. A continuación el código requerido:

Para la pantalla DispForm:

<script type="text/javascript">

// Agregar esta CEWP en la parte de abajo de la pantalla DispForm.aspx

// Para que se abra el editor, utilizar ?toolpaneview=2

// Parámetros importantes

// Nombre del campo Padre

var campo_padre = "ID_x002e_";

// Fin de Parámetros importantes

// Ocultar la fila

$('a[name="SPBookmark_' + campo_padre + '"]').parent().parent().parent().css("display","none");

</script>

 

Para la pantalla EditForm:

<script type="text/javascript">

// Agregar esta CEWP en la parte de abajo de la pantalla EditForm.aspx

// Para que se abra el editor, utilizar ?toolpaneview=2

// Parámetros importantes

// Nombre del campo Padre

var campo_padre = "ID.";

// Fin de Parámetros importantes

// Ocultar la fila

$('input[title="' + campo_padre + '"]').parent().parent().parent().css("display","none");

</script>

Conclusión

Hemos visto un método bastante simple y efectivo para crear relaciones de maestro detalle en SharePoint 2007. No requiere programación del lado del servidor y soporta cambios futuros a las listas al no requerir la programación de pantallas a medida.

Espero les resulte útil. Hasta la próxima.

domingo, 25 de agosto de 2013

Diseño Gráfico en SharePoint Foundation 2010.

Resumen:
En este artículo se detalla un enfoque de desarrollo orientado a aplicar diseño creado por un diseñador gráfico en SharePoint Foundation 2010. Al final del camino, se busca un sitio como el siguiente:
image
Imagen 1 – Ejemplo de página de inicio con diseño gráfico
Dentro de los objetivos perseguidos, hay dos que se consideran los más importantes:
  • Separar dentro de lo posible el trabajo del diseñador gráfico del trabajo del desarrollador
  • Facilitar la mantenibilidad del sistema, evitando utilizar funciones menos conocidas por los desarrolladores, como crear una página maestra desde cero o utilizar código de servidor.
Principales lineamientos:
  • La plataforma es Foundation, no Server.
  • El diseño es de un ancho fijo, diferente al estándar de SharePoint que ocupa el ancho total de la pantalla.
  • Se busca preservar la ribbon porque posee funcionalidad muy importante, pero tratando de que no ocupe tanto el centro de atención.
  • Existen elementos de cabecera que se repiten en todas las páginas, lo que incluye una imagen, el usuario conectado y un menú horizontal. También un pie de página.
  • La imagen de cabecera es más alta que la ribbon de SharePoint.
  • Existen elementos que sólo se ven en la home page, como la efemérides, la fecha del día y el contenido en sí.
  • El contenido de la home page, posee un diseño gráfico, muy diferente al estándar de SharePoint.
Enfoque técnico
  • Se busca maximizar el uso de CSS
  • Se busca minimizar el uso de la Página Maestra
  • Se crea el contenido propio de la home con Cliente Object Model (Java Script) para poder formatearlo con mayor facilidad
Página Maestra
El primer paso consiste en crear nuestra propia página maestra. En muchos casos se parte desde un página maestra básica (starter), pero nosotros preferimos copiar la estándar. Para ello debemos completar los siguientes pasos:
  1. Abrimos nuestro sitio desde SharePoint Designer y nos ubicamos en la sección “Master Pages”
  2. Copiamos la página “v4.master” y le ponemos un nombre como “intranet.master”
  3. Luego elegimos la opción “Set as default master page“
Página de inicio con diferente diseño
Supongamos que necesitamos una página de inicio con tres o cuatro columnas. Si bien, desde SharePoint 2010, es posible elegir cualquier página como home page, vamos a optar por un método que nos dé mayor flexibilidad, siguiendo estos pasos:
  1. Crear una librería de documentos llamada “Internal”
  2. Creamos una archivo llamado “Intranet_Home.htm”
  3. Agregar una CEWP en la home que llame a ese archivo
Ese archivo contendrá scripts y estilos que sólo se apliquen en la home page. Puro HTML, JavaScript, jQuery y CSS.
Hoja de estilos
Creamos un archivo llamado “Intranet.css” para definir los estilos que sobre-escriban los de SharePoint. Este archivo podemos almacenarlo en la librería “Internal”.
Luego modificamos la página maestra (en SharePoint Server no sería necesario modificar la página maestra), agregando el siguiente código antes del “</head>”:
<SharePoint:CssRegistration name="/sites/TUSITIO/Internal/Intranet.css" After="corev4.css" runat="server"/>
Así queda nuestra nueva librería Internal y la librería de páginas maestras:
image
Imagen 2 – Librerías Internal y Master Pages
También modificamos la página maestra para agregar el pie de página, siendo esta nuestra última modificación, ubicada luego de SharePoint:DeveloperDashboard:
<div id="intranet_footer">LA EMPRESA - RECURSOS HUMANOS - PROYECTOS - NOTICIAS</div>
Lo importante, teniendo en cuenta uno de los objetivos, es que apenas hicimos dos simples cambios en la página maestra.
Estilos generales
En el siguiente código, se muestran los estilos generales que buscan:
  • Crear una cabecera con diseño
  • Preservar la ribbon
Este estilo se ubica dentro de Intranet.css:
/* -------------------------------------------------
Ocultamiento de secciones
------------------------------------------------- */
/* Oculto Acciones del Sitio */
.ms-siteactionsmenu { display: none; }
/* Ocultar Icono de navegación hacia arriba */
.s4-breadcrumb-anchor { display: none; }
/* -------------------------------------------------
Ajustes estéticos
------------------------------------------------- */
/* Seteo el color de fondo */
body { background-color: #828282; }
/* Aplico un ancho fijo, no 100% */
#s4-ribbonrow, #s4-workspace
{
max-width: 1100px;
margin: 0 auto;
padding: 0px;
background-color: white;
}
/* -------------------------------------------------
Imagen de cabecera
------------------------------------------------- */
/* Agrando la Ribbon porque la imagen es más alta */
#s4-ribbonrow { padding-top:37px; min-height: 133px !important; }
/* Oculto la fila de título y navegación */
#s4-titlerow { margin-top: -88px; }
/* Subo las solapas de la Ribbon para que no molesten a la imagen, especialmente si hay un logo a la izquierda */
.ms-cui-topBar2 { margin-top: -37px; }
.ms-cui-tabContainer { border-top: #B8BABD 1px solid; background-color: white; padding-top: 20px; }
.ms-cui-tabBody { padding-bottom: 17px; background-image: none; }
/* Elimino el fondo del título y del top navigator */
.s4-title { background: none; }
/* Seteo mi imagen de cabecera en la ribbon row */
#s4-ribbonrow { background-image: url('/sites/TUSITIO/Internal/header.png'); }
/* Saco el fondo de la ribbon que molesta a la imagen */
#s4-ribboncont { background: none !important; }
/* Posiciono en forma fija al top navigation */
.menu-horizontal { position: fixed !important; top: 134px !important; }
/* Subo el menú de usuario */
#RibbonContainer-TabRowRight { margin-top: -10px; }
/* Elimino el borde superior de la ribbon */
.ms-cui-topBar2 { border: 0px; }
/* Ajustes de algunos bordes */
#s4-topheader2 { border-top: 0px !important; background: white !important; }
/* Borde derecho a la izquierda de la scrollbar molesta */
#s4-titlerow { border-right: 0px; }
/* -------------------------------------------------
Estilos en barra superior
------------------------------------------------- */
/* Menú de bienvenida*/
.ms-welcomeMenu A:link {
color: #8F8F8F;
font-size: 11px;
font-family: Arial, Helvetica, sans-serif;
}
/* Colores de solapas de la ribbon, tratando de que no sean tan visibles */
.ms-cui-tt-a, .ms-cui-cg-t { color: #B8BABD !important; }
.ms-cui-cg-t, .ms-cui-ct-ul { background: none !important; }
.ms-cui-ct-ul, .ms-cui-cg-i, .ms-cui-cg, .ms-cui-tt-a {border-color: #F4F3F9 !important; }
.ms-cui-cg-i {border-color: transparent !important; }
.ms-cui-cg {border-color: transparent !important; }
/* -------------------------------------------------
Estilos en Top Navigation
------------------------------------------------- */
/* Efecto de margen izquierdo */
.s4-tn .menu-horizontal {
margin-left: 200px;
}
/* Estilo de los links */
.s4-tn .menu-item-text {
color: #FCFCFC;
font-size: 11px;
border-right: #FCFCFC solid 1px;
padding-right: 25px;
font-size: 11px;
font-family: Arial, Helvetica, sans-serif;
}
/* Estilo del link seleccionado */
.s4-tn .selected {
font-weight: bold;
}
.s4-tn .selected .menu-item {
background: none !important;
border: none !important;
}
/* Estilo del link hover */
.s4-tn .menu-item:hover {
text-decoration: none !important;
}
/* -------------------------------------------------
Footer
------------------------------------------------- */
#intranet_footer {
background-color: #ACACAD;
margin-top: 15px;
font-family: Arial, Helvetica, sans-serif;
font-size: 9px;
color: white;
text-align: center;
padding: 4px;
clear: both;
border-top: white solid 40px;
}
En la siguiente imagen, puede observarse la forma que adquiere la Ribbon:
image
Imagen 3 – Ejemplo de ribbon con el diseño gráfico aplicado
Sobre la imagen de cabecera
La imagen de cabecera posee algunas características importantes:
  • Ocupa todo el ancho fijo: 1100px
  • Debe ser de la altura 170px (si se cambia, hay que ajustar la CSS)
  • Posee un sombreado en la parte superior (como parte de la imagen)
  • Posee el logo a la izquierda, dejando algo de espacio en blanco para la botonera (solapas) de la ribbon
  • La zona de abajo es el fondo de los links de la Top Navigation
La imagen de cabecera ejemplo es:
image
Imagen 4 – Ejemplo de imagen para la cabecera
La home page
En la home page, trabajamos sobre estos aspectos principales:
  • Nombre de usuario
  • Efeméride
  • Botón de subsitio
  • Contenido de la home
Buscamos algo como lo siguiente:
image
Imagen 5 – Particularidades de la página de inicio
Nombre de usuario
El nombre de usuario se ve a la izquierda con el agregado del “Bienvenido” y “> > >”. Para ello trabajamos con una técnica jQuery que nos permite insertar HTML:
$('#zz15_Menu span').prepend('Bienvenido&nbsp;');
$('#zz15_Menu span').append(' > > > ');

Efeméride

A la derecha, arriba, agregamos:
  • La fecha actual obtenida con JavaScript
  • La efeméride obtenida con Cliente Object Model
Para obtener la fecha actual, usamos código javascript.

Para obtener la Efeméride, consultamos los datos de una lista usando Cliente Object Model, tal como lo expliqué en un artículo previo, que pueden encontrar en: http://surpoint.blogspot.com.ar/2011/10/introduccion-al-modelo-de-objetos-de.html

Para insertar la efeméride (ítem extraído de una lista), usamos:

ExecuteOrDelayUntilScriptLoaded(cargar_efemeride, "sp.js");
$('.ms-cui-ribbonTopBars').append($('#efemeride'));

Dentro del código que lee la efeméride (cargar_efemeride), se cargó previamente un div de la siguiente forma:

document.getElementById("efemeride").innerHTML = strHtml;

El div debe existir en Intranet_Home.htm:

<div id="efemeride"></div>


Botón de subsitio

Este es un simple botón que agregamos en nuestro HTML de la siguiente forma:

<table id="subsitio_contenedor">
 <tr>
 <td width="990px"></td>
 <td width="100px">
 <a id="subsitio" href="/sites/blablabla.aspx">Subsitio</a>
 </td>
 </tr>
</table>

Resultado

image
Imagen 6 – Botón de acceso a un subsitio


El contenido de la home

Siguiendo el enfoque de las efemérides, cargamos todo el contenido de la home. Lo primero que hacemos es crear una tabla para nuestro contenido, con el diseño que más nos guste. Este es un ejemplo:

<table id="super_contenedor">
 <tr>
 <td>
 <table class="cumples-tabla">
 <thead>
 <tr>
 <th>Para compartir</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td><div id="cumples"></div></td>
 </tr>
 </tbody>
 </table>
 </td>
 <td><strong>Zona reservada para noticias</strong>: Lorem ipsum ad ... </td>
 </tr>
 <tr>
 <td><strong>Zona reservada para anuncios</strong>: Lorem ipsum ad ... </td>
 <td><strong>Zona reservada para noticias en las sedes</strong>: Lorem ipsum ad his scripta blandit partiendo... </td>
 </tr>
</table>

Ocultamos la zona de webparts de la derecha:

$('#ctl00_MSO_ContentDiv table table td:first').width("100%");

Y luego insertamos con client object model los datos que consultamos desde listas de SharePoint, asociando las clases para aplicar  los estilos que nos proporcionó el diseñador gráfico.

Obtenemos algo como lo siguiente:


image

Imagen 7 – Ejemplo de información obtenida con Client Object Model

Los estilos de la home

Habrán notado que algunas cosas son distintas en la home, como el ocultamiento de la ribbon o la ubicación del nombre de usuario. Para ello aplicamos estilos propios:

<style>
/* -------------------------------------------------
 Ajustes generales
 ------------------------------------------------- */
/* Ocultar Inicio Rápido */
#s4-leftpanel { display: none; }
.s4-ca { margin-left: 0px; }
/* Ocultar solapas de Ribbon*/
.ms-cui-tts { display: none; }
/* Y el borde de la top navigation */
#s4-topheader2 { border-bottom: 0px !important; }
/* Nombre de usuario a la izquierda */
#RibbonContainer-TabRowRight { float: left; }
/* Efeméride a la derehca */
#efemeride {
 color: #03935F;
 font-weight: bold;
 text-transform: uppercase;
 font-size: 11px;
 font-family: Arial, Helvetica, sans-serif;
 float: right;
 margin-top: -39px;
 margin-right: 10px;
}
/* Fecha actual a la derecha*/
#fecha {
 font-size: 11px;
 font-family: Arial, Helvetica, sans-serif;
 color: #8F8F8F;
 font-weight: normal;
 text-transform: none;
}
/* Botón de llamada a un subsitio */
#subsitio {
 font-size: 18px;
 font-family: Arial, Helvetica, sans-serif;
 color: white;
 background-color: #F9B10F;
 border: solid 4px white;
 border-right: none;
 padding: 5px 10px;
 text-align: center;
}
#subsitio_contenedor {
 position: fixed;
 top: 91px;
}
/* -------------------------------------------------
 Contenedor de partes
 ------------------------------------------------- */
/* Estilo de la Tabla que contiene cada una de las partes (contenido) */
#super_contenedor {
 width: 100%;
}
#super_contenedor td {
 padding: 10px;
 vertical-align: top;
}
/* -------------------------------------------------
 Para compartir (estilos para mostrar cumpleaños)
 ------------------------------------------------- */
.cumples-tabla th {
 background-color: #288BCE;
 color: white;
 font-family: Arial, Helvetica, sans-serif;
 font-size: 13px;
 font-weight: bold;
}
.cumples-tabla td {
 background-color: #CBE9F6;
}
</style>

Conclusión

En este artículo explicamos un camino para incorporar diseño gráfico a SharePoint. Existen diferentes formas de encarar esta tarea. En este caso buscamos una que no requiera demasiados conocimientos específicos de SharePoint, que no “desarme” funcionalidades como la ribbon, pero que a la vez permita personalizar el diseño haciendo que no se parezca a “SharePoint”.

Hasta la próxima!

Bibliografía

Real World Branding with SharePoint 2010 Publishing Sites
SharePoint Branding 101: Branding Master Pages
SharePoint 2010 branding. A beginners guide
10 Worst Mistakes in SharePoint Branding
SharePoint Ribbon CSS Tips and Tricks
SharePoint 2010 CSS Reference Chart

Juan Pablo Pussacq Laborde
SharePoint MVP
Blog: http://surpoint.blogspot.com/
Facebook: http://facebook.com/surpointblog/
Twitter: http://twitter.com/jpussacq/

lunes, 28 de enero de 2013

Workflow en Project Server 2010 ¿Valores predeterminados en campos de empresa en una PDP?

Cuando trabajamos con PDPs en Project Server 2010, no es sencillo establecer un valor predeterminado para un campo de empresa de tipo obligatorio. Si bien la configuración de campos de empresa permite establecer valores predeterminados, estos funcionan en forma correcta en Project Pro, pero no en la forma esperada dentro de PWA.
Es por ello que en este breve artículo vamos a explicar como manejar los valores predeterminados utilizando un poco de JavaScript. El enfoque de trabajo es el siguiente:
  • Utilizar JavaScript para configurar el valor predeterminado de los campos, sólo si se trata de la PDP usada en una creación de proyecto.
  • Utilizar JavaScript para ocultar dichos campos.
Separaremos el código en dos archivos:
  • Un archivo con el contenido de la CEWP que se insertará en la PDP, debajo de los campos de empresa. .
  • Un archivo de constantes con los guids y demás valores de cada campo.

El código del archivo de contantes

/* Valor predeterminado para el campo Stage en la PDP Request */

STAGE_ID = "ctl00_m_g_80e4b936_45c6_442d_b8de_a93ac30efea1_ctl00_pfp_Repeater_ctl06_idCF_976b5670-7e3b-407d-ad53-1d0343fc3f0c";
STAGE_GUID = "966707bd-8f55-4f0e-97d1-8c94256c55a3";
STAGE_TEXTO = "Planned";

/* Valor predeterminado para el campo Program en la PDP Request */

PROGRAM_ID = "ctl00_m_g_80e4b936_45c6_442d_b8de_a93ac30efea1_ctl00_pfp_Repeater_ctl08_idCF_38852eb9-5126-4fb2-b1ef-45e6edfeb116";
PROGRAM_GUID = "d74da6ee-48ce-491a-ad6e-416da8c99ab2";
PROGRAM_TEXTO = "Yes";

El código de la CEWP 

<script src="/PWA/Internal/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="/PWA/Internal/constantes_workflow.js" type="text/javascript"></script>

<script type="text/javascript">

 $(document).ready(function() { 

     predeterminar_campo (STAGE_ID, STAGE_GUID, STAGE_TEXTO);
     predeterminar_campo (PROGRAM_ID, PROGRAM_GUID, PROGRAM_TEXTO);

   });


function predeterminar_campo ( id_campo, guid_valor, texto_valor ) {

     if ( workflow_url_param ( "NewProject" ) == "yes" ) {
    
         // Valor del campo
         $('#'+id_campo).attr("value",texto_valor);

         // ID del valor del campo
        $('#'+id_campo).attr("LTValue",guid_valor);
     
         }

     // Oculto la fila de la tabla que contiene el campo
    $('#'+id_campo).parent().parent().parent().parent().parent().parent().css("display","none");

}

function workflow_url_param ( name ){  
 name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); 
 var regexS = "[\\?&]"+name+"=([^&#]*)"; 
 var regex = new RegExp( regexS ); 
 var results = regex.exec( window.location.href ); 
 if( results == null ) 
   return "";
  else 
   return results[1];
}

</script>

Opción 2

Una segunda opción que he probado y me ha dado buenos (mejores) resultados consiste en buscar el atributo title en lugar del id. Los cambios con:

En el archivo de constantes:


STAGE_ID = "Stage";


En la CEWP:


$('input[title="'+id_campo+'"]').attr("value",texto_valor);
$('input[title="'+id_campo+'"]').attr("LTValue",guid_valor);
$('input[title="'+id_campo+'"]').parent().parent().parent().parent().parent().parent().css("display","none");


Conclusión

Esta ha sido una forma de resolver el inconveniente de los valores predeterminados en las PDPs de flujos de trabajo en Project Server 2010, utilizando código de cliente JavaScript. Espero les haya resultado útil.

lunes, 23 de julio de 2012

Ocultar columnas en base al valor de otra columna en SharePoint 2007

Introducción

En este breve artículo vamos a explicar cómo ocultar o mostrar columnas en base al valor que tome una columna en la pantalla NewForm.aspx. La solución la implementaremos a través de jQuery y JavaScript dentro de una CEWP (content editor webpart).

Comportamiento de la pantalla

Imaginemos que tenemos una pantalla de alta que posee una columna llamada “SiNo” y que dependiendo del valor de esa columna, queremos que se muestren u oculten otras columnas. Si el valor de la columna “SiNo” es “Si”, entonces queremos que la pantalla se vea de esta manera:

image

Pero si el valor de la columna “SiNo” es NO, entonces queremos que se oculte el campo “Eleccion” y se muestren los campos “Texto” y “Busqueda”

image

Enfoque de la solución

Para ello trabajamos con una solución que agrega un evento “click” en la casilla de verificación “SiNo”. Este evento oculta o muestra campos en base al valor de esta casilla.

Esta porción de código está realizada con jQuery y está basada en la idea de este artículo: http://www.codeproject.com/Articles/252468/Hide-column-in-SharePoint-custom-list-based-on-val

La forma de encontrar, ocultar y mostrar columnas en SharePoint se realiza a través de JavaScript, aprovechando los comentarios de SharePoint que indican los nombres internos de las columnas. Nos basamos en este artículo: http://www.cleverworkarounds.com/2008/02/28/more-sharepoint-branding-customisation-using-javascript-part-2/

Configuración del código

Para utilizar el código, podemos pegar el mismo en una CEWP o integrarlo dentro de alguna librería JavaScript. El código posee tres partes a configurar:

1. La indicación de cuál es el campo que nos permite decidir qué campos mostrar u ocultar. Debe ser un campo de tipo “Si/No”

image

2. La especificación de los campos a mostrar u ocultar cuando el valor es Si

image

3. La especificación de los campos a mostrar u ocultar cuando el valor es No

image

Código de la solución

Por último les dejo el código completo, espero les sea útil. Hasta la próxima!

<!--

Esta función oculta y muestra un conjunto de columnas de acuerdo al valor de un campo Si/No
Se aplica dentro de una CEWP en la página NewForm.aspx

Utiliza una variante de la función de CleverWorkarounds para ocultar y encontrar controles de SharePoint
http://www.cleverworkarounds.com/2008/02/28/more-sharepoint-branding-customisation-using-javascript-part-2/

Utiliz una variante de la función de CodeProject para agregar el evento click con jQuery a una columna Si/No
http://www.codeproject.com/Articles/252468/Hide-column-in-SharePoint-custom-list-based-on-val

Requiere jQuery

El código puede ser insertado dentro de una CEWP

-->

<script src="/internal/jquery-1.7.2.min.js">
</script>

<script type="text/javascript">

OcultarMostrarCondicional ('SiNo'); // Internal Name del campo de tipo Si/No que decide

/* Completar en esta función los controles a mostral u ocultar cuando la opción es SI */

function OcultarMostrar_Cuando_SI () {
ocultar_control('Texto');
ocultar_control('Busqueda');
mostrar_control('Eleccion');
}

/* Completar en esta función los controles a mostral u ocultar cuando la opción es NO */

function OcultarMostrar_Cuando_NO () {
mostrar_control('Texto');
mostrar_control('Busqueda');
ocultar_control('Eleccion');
}

/*************************************/
/* A PARTIR DE ACA NO MODIFICAR NADA */
/*************************************/

function OcultarMostrarCondicional (CampoSiNo) {

// Busco el campo Si/No que decide que campos ocultar y qué campos mostrar
var SiNo = retornar_id_control(CampoSiNo);

// Situación predeterminada de la pantalla
if($("#"+SiNo).is(':checked')) {
OcultarMostrar_Cuando_SI ();
}
else {
OcultarMostrar_Cuando_NO ();
}


// Agrego el evento click
$("#"+SiNo).bind('click',function() {

if($(this).is(':checked')) {
OcultarMostrar_Cuando_SI();
}
else {
OcultarMostrar_Cuando_NO();
}
});

}

function ocultar_control (FieldName) {
var arr = document.getElementsByTagName("!");
for (var i=0;i < arr.length; i++ ) {
if (arr[i].innerHTML.indexOf("FieldInternalName=\""+FieldName+"\"") > 0) {
arr[i].parentNode.parentNode.style.display="none";
}
}
}

function mostrar_control (FieldName) {
var arr = document.getElementsByTagName("!");
for (var i=0;i < arr.length; i++ ) {
if (arr[i].innerHTML.indexOf("FieldInternalName=\""+FieldName+"\"") > 0) {
arr[i].parentNode.parentNode.style.display="inline";
}
}
}

function retornar_id_control (FieldName) {
var arr = document.getElementsByTagName("!");
for (var i=0;i < arr.length; i++ ) {
if (arr[i].innerHTML.indexOf("FieldInternalName=\""+FieldName+"\"") > 0) {
return arr[i].parentNode.lastChild.firstChild.id;
}
}
}

</script>

viernes, 24 de febrero de 2012

Ocultar columnas en formularios de #SharePoint

No dejen de leer este post de Juan Carlos en donde encontraremos varios links para cumplir con este requerimiento con distintas opciones: PowerShell, Tipos de contenido, JavaScript, InfoPath y programáticamente.
Recomendado: http://geeks.ms/blogs/ciin/archive/2012/02/20/sharepoint-2010-ocultar-des-ocultar-campos-de-formulario-de-lista-i.aspx

lunes, 13 de febrero de 2012

Obtener datos de perfil de usuario con #JavaScript en #SharePoint

Desde el blog de SharePoint Java Scripts nos muestran una utilidad para obtener datos de perfil de usuario como: ID, Name, Title, EMail, Department, JobTitle, Notes, Picture, IsSiteAdmin, Created, Author, Modified, Editor, SipAddress.

Como siempre, se trata de una combinación de CEWP con jQuery. Espero les resulte útil. Pueden obtener el código desde este artículo: http://sharepointjavascript.wordpress.com/2011/09/18/accessing-user-profile-information-in-sharepoint-with-javascript-updated-version/.

Saludos!

viernes, 20 de enero de 2012

Pantallas dinámicas en #Sharepoint

¿Qué pasaría si las pantallas de alta y modificación de listas pudieran variar la obligatoriedad o visibilidad de sus campos de acuerdo a una condición?


Pues esto es lo que propone Alexander en su blog. Les dejo el enlace:
http://sharepointjavascript.wordpress.com/2012/01/19/dynamic-forms-for-sharepoint/

Qué lo disfruten!

martes, 10 de enero de 2012

Cargar una #CSS en forma dinámica desde #javascript

A continuación les dejo un método sencillo que nos permite cargar una hoja de estilos desde una función dentro de un script JavaScript:

La forma de invocación:

activar_css ("/SURPOINT/Style%20Library/surpoint.css");

La función:

function activar_css (css_file) {       
    var fileref=document.createElement("link");
    fileref.setAttribute("rel", "stylesheet");
    fileref.setAttribute("type", "text/css");
    fileref.setAttribute("href", css_file);
    document.getElementsByTagName("head")[0].appendChild(fileref);
}

El artículo que explica cómo hacerlo:

http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml

Espero les sea útil. Hasta la próxima!

jueves, 8 de diciembre de 2011

HTML en una columna dentro de una vista de #SharePoint con #JavaScript o #jQuery

Hace unos días preguntaban en un foro cómo agregar HTML dentro de una columna para generar cierto comportamiento en una vista. Hay varias soluciones y creo que dependen un poco del objetivo que se persiga.

Mi primera recomendación es el método mediante el cual se escribe el código HTML en una columna calculada y luego de hace el render mediante JavaScript o jQuery. Se usó mucho durante un tiempo, creo que por su facilidad de implementación y su potencial. La famosa HTML calculated column. Acá los enlaces:

http://blog.pathtosharepoint.com/2008/09/01/using-calculated-columns-to-write-html/

http://www.pathtosharepoint.com/HTMLcc/default.aspx

https://www.nothingbutsharepoint.com/sites/eusp/Pages/jquery-for-everyone-html-calculated-column-plugin.aspx

Si queremos profundizar un poco más, otras soluciones que no necesitan ser instaladas en el servidor pueden implementarse con jQuery o Client Object  Model. Un script muy básico de jQuery que se puede usar para tomar de base y luego hacerlo todo lo complejo que necesitemos se encuentra en: http://www.sharepointkings.com/2010/04/sharepoint-custom-so-called-kpi.html

Client Object Model es quizá lo más potente. Sólo funciona en SharePoint 2010. Acá les dejo una introducción: http://surpoint.blogspot.com/2011/10/introduccion-al-modelo-de-objetos-de.html

Espero que les sea útil. Pueden ver la discusión en el foro en este enlace: http://social.msdn.microsoft.com/Forums/es-ES/mossdeves/thread/42671890-3f5c-49ee-b432-17282c1e3e5a/ (Html en una custom list)

Hasta la próxima!

miércoles, 16 de noviembre de 2011

Crear un ítem y redireccionar a la pantalla del ítem creado

Una pregunta bastante común en los foros es si es posible que luego de crear un ítem en una lista, SharePoint nos redireccione en forma automática a la pantalla DispForm o EditForm del ítem creado.

Si bien este no es el comportamiento estándar de SharePoint, otra ves Alexander Bautz (http://sharepointjavascript.wordpress.com) nos propone una solución que a continuación resumo:

  • Agregar una CEWP en NewForm para realizar el direccionamiento a la pantalla DispForm o EditForm.
  • Agregar una CEWP en la página DispForm que sólo se ejecuta cuando el ID es 0. Lo que hace es buscar el último elemento creado por el usuario y enviarnos a la pantalla correspondiente.

Un enfoque muy interesante que pueden descargar desde el blog del autor en http://sharepointjavascript.wordpress.com/2011/04/23/redirect-from-newform-to-dispform-or-editform/.

Espero les sea útil. Hasta la próxima!