viernes, 13 de mayo de 2011

Visio Services API

Ok, antes de comenzar a hablar acerca de la API (Application Programming Interface) expuesta para Visio Services, es importante mencionar que no es estrictamente necesario desarrollar utilizando esta API, existen muchas formas de lograr diagramas ricos visualmente (con sus restricciones) sin necesidad de desarrollo alguno.

Sin embargo, si requerimos de más poooder flexibilidad en la creación de diagramas con una mejor experiencia de usuario, la API de Visio Services es la única mejor opción. De ahí que para esta serie de posts, me haya inclinado más por el uso, explicación y demostración del uso de esta API.

¿Qué es la API de Visio Services?

De manera resumida, la API de Visio Services es un conjunto de clases (solo cuatro), que nos permiten accesar, manipular e inclusive crear objetos dentro de un diagrama que ha sido rendereado utilizando el service application de Visio Graphics Service, a través de la Visio Web Access Web Part.

Punto modular de este tema es el hecho de que la API es expuesta en JavaScript, es decir que, para hacer uso de la misma es necesario escribir código JavaScript. Una de las preguntas más frecuentes es:

¿Por qué en JavaScript?

JavaScript fue elegido porque es el mínimo común denominador para todos los navegadores, si, incluyendo Internet Explorer. La versión soportada de JavaScript es la 1.3.

Desde el punto de vista de un desarrollador, creo que, fue una buena elección ya que JavaScript es ampliamente usado y aceptado además de que actualmente existen varios frameworks (como jquery) los cuales hacen que las tareas, que en el pasado eran verdaderos retos, ahora las puedes realizar con una sola línea de código (llamando a alguna función de jquery).

Ahora describiremos brevemente las clases que conforman esta API.

Vwa.VwaControl

Representa una instancia de la Visio Web Access Webpart, lo que significa que podemos acceder a la alguna de las propiedades de esta webpart desde el lado del cliente. Además provee métodos de mucha utilidad como addHandler, removeHandler y clearHandlers para interactuar con distintos eventos que esta clase expone, algunos de los más interesantes son:
  • diagramcomplete. Este evento es lanzado cuando el diagrama termina de cargarse
  • shapeselectionchanged. Se lanza cuando se selecciona un objeto del diagrama
Vwa.Page

Representa la página del diagrama que actualmente se está visualizando, como sabemos, un diagrama de Visio puede tener una o más páginas, luego entonces este objeto representa la página que se está desplegando en el momento. La forma más fácil de obtener una referencia a una instancia de este objeto es a través del método getActivePage() de la clase Vwa.VwaControl. Inclusive es posible establecer la página activa mediante el método setActivePage()

Vwa.ShapeCollection

Representa una colección de formas (shapes) que se encuentran en la página actualmente activa. Es posible obtener la colección entera de shapes que se encuentran en una página a través del método getShapes() de la clase Vwa.Page

Vwa.Shape

Y por último esta clase representa un shape (forma) que se encuentra dentro de la página activa.



Ahora bien, es tiempo de tirar un poco de código para ejemplificar el uso básico de esta API.

Antes que nada, es necesario publicar un diagrama de Visio web (.vwd), aquí un video bastante claro de cómo hacerlo. Acto seguido en una webpart page, agregamos la Visio Web Access webpart en la que estableceremos la url del diagrama que publicamos en el paso anterior.

Ahora agregamos una webpart de editor de Contenido la que nos servirá para agregar código JavaScript, evidentemente en lugar de agregar el código JavaScript directamente en esta web part, podríamos referenciar solamente un archivo de .js que se encuentre previamente provisionado en nuestro sitio.

Una vez que hemos hecho lo anterior, ya podemos escribir propiamente nuestros primeros pininos utilizando la API de Visio Services, entonces editamos la webpart de editor de contenido y agregamos el código JavaScript siguiente:




Explicando el código anterior:

Lo primero que podemos observar es la inclusión de esta referencia a otro archivo .js que sirve como “Helper” principalmente para obtener la referencia a la instancia de la webpart de Visio Web Access. Notese que para poder crear la instancia de Vwa.VwaControl, en necesario proporcionar el id de la webpart de Visio, para fines de hacer este proceso un poco más “dinamico”, el helper busca todos los elementos div que tengan la clase VisioWebAccess, esta es la manera más eficiente de buscar en el DOM el id de la webpart de Visio. Evidentemente no funciona si existe más de una Visio Web Access Web Part en la página.

/*!
* Visio Web Access JavaScript Library v1.0.1
*
* Copyright 2010, Microsoft
*/

//----------------------------------------------------------
// gets the first instance of the VisioWebAccess web part on this page.
// 
// if you have more than one VWA web part on the page this
// function will return the first one that is found
//----------------------------------------------------------
function getVwaControl() {
    var webPartID = null;

    try {
        webPartID = findVwaControlId();

        if (webPartID == null) {
            throw new Error("VisioWebAccess class not found.  Please contact the site administrator.");
        }

        // get the web part ID that we found on the page
        vwaControl = new Vwa.VwaControl(webPartID);
    }
    catch (ex) {
        alert(ex);
    }
}

//----------------------------------------------------------
// find the ID of the VisioWebAccess web part on this page.
// 
// if you have more than one VWA web part on the page this
// function will return the first one that is found
//----------------------------------------------------------
function findVwaControlId() {
    var retVal = null;

    var divCollection = document.getElementsByTagName("div");

    for (var i = 0; i < divCollection.length; i++) {
        if (divCollection[i].getAttribute("class") == "VisioWebAccess") {
            // the actual id of the VWA web part is two levels higher than this class node
            retVal = divCollection[i].parentNode.parentNode.getAttribute('id');
            break;
        }
    }

    return retVal;
}

//recupera el objeto silverlight en donde se esta pintando el diagrama
function findVwaRenderingObject() {
    var retVal = null;
    var objectCollection = document.getElementsByTagName("object");
    for (var i = 0; i < objectCollection.length; i++) {
        if (objectCollection[i].getAttribute("id").toString().indexOf("VisioWebAccess") != -1
  || objectCollection[i].getAttribute("id").toString().indexOf("silverlight") != -1
  )
        {
            retVal = objectCollection[i].getAttribute('id');
            break;
        }
    }
    return retVal;
}

function findVwaRenderingScript() {
    var retVal = null;
    var objectCollection = document.getElementsByTagName("script");
    alert(objectCollection.length);
    for (var i = 0; i < objectCollection.length; i++) {
        if (objectCollection[i].getAttribute("type") == "text/xaml") {
            retVal = objectCollection[i];
        }
    }
    return retVal;
}

La siguiente instrucción que agregamos es para adjuntar un manejador de eventos al evento load de ASP.NET AJAX.

Sys.Application.add_load(onApplicationLoad); 

Acto seguido, escribimos el manejador de eventos que referenciamos en el punto anterior.

function onApplicationLoad() {
    //obtenemos la instancia de la Visio Web Access Web Part
    getVwaControl();

    //Nos subscribimos a dos de los eventos que son expuestos por la API
    if (vwaControl != null) {
        vwaControl.addHandler("diagramcomplete", onDiagramComplete);
        vwaControl.addHandler("shapeselectionchanged", onShapeSelectionChanged);           
    }
    else {
        alert("Error connecting to Visio Web Part.  Please contact the site administrator.");
    }
}

En el fragmento de código anterior, primero hacemos una llamada a la función getVwaControl(), que se encuentra en la librería Helper, y que se encarga de inicializar la variable vwaControl a través de lo que ya describimos anteriormente, después de que se inicializo esta variable satisfactoriamente, utilizamos la función addHandler de este objeto para suscribirnos a dos de los varios eventos que expone: diagramcomplete y shapeselectionchanged.

Lo siguiente es agregar los manejadores de los eventos a los cuales nos subscribimos (diagramcomplete y shapeselectionchanged).

function onDiagramComplete() {
    //obtenemos la pagina activa con el metodo getActivePage()
    vwaPage = vwaControl.getActivePage();
 //obtenemos la coleccion de formas con el metodo getShapes()
    vwaShapes = vwaPage.getShapes();
    vwaShapeCount = vwaShapes.getCount();
 alert("El diagrama contiene " + vwaShapeCount + " shapes");
    vwaPage.setZoom(50);
}

function onShapeSelectionChanged(source, args){
 alert(args);
 alert(source);
}

En primer lugar, dentro de la función onDiagramComplete, obtenemos la referencia a la página activa del diagrama, recordemos que un diagrama de Visio puede tener más de una página pero solo una activa, mediante la función getActivePage() de la clase Vwa.Page. Inmediatamente después obtenemos toda la colección de shapes (instancia de la clase Vwa.ShapeCollection), para después solo obtener el número de elementos de esta colección y mostrarlo en un alert. Por ultimo vemos que se llama a la función setZoom() de la clase Vwa.Page para establecer el valor del zoom del diagrama.

Espero que esta explicación sirva como primer acercamiento al uso de esta interesante API, y sobre todo, sirva como fundamento de los siguientes posts de esta serie. Si tienen alguna duda o comentario no duden en hacermela saber.

Ya por último dejo algunas referencias para que puedan adentrarse más en el uso de esta API

The Visio Services JavaScript Mashup API
Roadmap: Publish Visio drawings to a SharePoint site
Evento load de ASP.NET AJAX

Happy Coding!

0 comentarios:

Etiquetas

SharePoint 2010 (38) Microsoft (32) Desarrollo SharePoint (31) Gerardo Reyes Ortiz (27) SharePoint (20) SharePoint 2013 (18) Errores SharePoint (12) México (10) PowerShell (9) Silverlight (8) Visio Services (7) Features (6) MVP (6) Silverlight 3 (6) WebCast (6) Workflows (6) Configuracion SharePoint 2010 (5) D.F. (5) API REST (4) Configuracion SharePoint 2010; (4) Troubleshooting (4) Visual Studio 2010 (4) Visual studio (4) WSS (4) Web parts (4) Apps (3) Comunidad SharePoint (3) Configuración SharePoint 2013 (3) ODATA (3) SharePoint Server (3) SharePoint; Instalación SharePoint; Troubleshooting; Search Service (3) Silverlight 3.0 (3) Silverlight Toolkit (3) WebParts (3) javascript (3) jquery (3) Eventos SharePoint (2) Office 2010 (2) PeoplePicker (2) REST (2) SQL Server (2) Scripting (2) Search Service Application (2) SharePoint Designer (2) UPA (2) UPS (2) Workflows SharePoint (2) host header (2) Apps Development (1) Big Bang (1) CAS (1) CSOM (1) Codeplex (1) CompartiMOSS (1) Configuracion SharePoint 2010; Errores SharePoint (1) Configuracion SharePoint 2010; SharePoint 2010 (1) Custom Actions (1) Custom Editor Parts (1) Delegate Controls (1) Deployment (1) DisableLoopbackCheck (1) Document Library (1) Entrevista (1) Examenes de Certificación (1) Extract WSP (1) FBA (1) FS4SP (1) Fakes (1) Fast Search Server 2010 For SharePoint (1) Fiddler (1) HTTP.SYS (1) HTTPS (1) JSON (1) Language Pack's (1) Latam (1) MAXDOP (1) MCSM (1) MSExpertos (1) MVC (1) Microsoft México (1) Microsoft; Codeplex; Screencast; (1) My Sites (1) SQL Server 2012 (1) SQL Server Reporting Services (1) Screencast (1) Screencast; (1) Service Applications (1) Service Pack (1) SharePoint 2007 (1) SharePoint 2010 SP 1 (1) SharePoint API (1) SharePoint Conference (1) SharePoint Emulators (1) SharePoint Farm (1) SharePoint Health Analyzer (1) SharePoint Magazine (1) SharePoint Online (1) SharePoint Search (1) SharePoint Test (1) SharePoint; Desarrollo SharePoint (1) Shims (1) Simposio (1) Simposio Latinoamericano (1) SkyDrive Pro (1) Soporte Microsoft (1) Templates (1) Tip (1) VSeWSS (1) Virtual Machine (1) Visual Studio 2012 (1) WCF (1) WSS; IIS 7 (1) Web API (1) Web Content Management (1) Web Services (1) Windows 8 (1) Windows Live ID (1) Xml (1) appcmd (1) iOS (1) jqGrid (1) onload function (1)