Partager via


Création d'applications HTML5

Ajout de la fonction glisser-déplacer HTML5 aux listes SharePoint

Andrey Markeev

Télécharger l'exemple de code

Microsoft SharePoint est une plate-forme d'entreprise qui se prévaut d'une longue histoire et d'un large éventail de fonctionnalités. C'est pourquoi elle n'est pas toujours en mesure de répondre suffisamment rapidement pour suivre les nouvelles tendances Web en matière de technologie. Bien que SharePoint ait été adoptée à grande échelle par les entreprises et qu'un effort important ait été fourni pour offrir un grand nombre de fonctionnalités, cette plate-forme reste à la traîne derrière des produits CMS modernes en termes d'interfaces utilisateur immersives comme HTML5 et CSS3.

De mon point de vue, HTML5 n'est pas seulement une nouvelle technologie formidable, mais elle présente véritablement de nombreux avantages pratiques : elle est simple, pratique et riche, sans oublier le fait qu'elle soit plus ou moins prise en charge par tous les navigateurs modernes (dont les navigateurs d'appareils mobiles). En outre, HTML5 et JavaScript deviennent des technologies essentielles pour la programmation des postes de travail dans Windows.

Il est donc indéniable que HTML5 mérite sa place dans SharePoint pour faciliter grandement l'utilisation des portails. De plus, l'amélioration des interfaces SharePoint peut véritablement aider les utilisateurs professionnels en leur permettant de travailler mieux et plus rapidement.

Malheureusement, SharePoint ne dispose pas de prise en charge HTML5 intégrée, mais offre une grande flexibilité. Dans cet article, je souhaite vous montrer à quel point il est facile d'ajouter la prise en charge de la fonction glisser-déplacer HTML5 à SharePoint et illustrer la fluidité que cela peut apporter à l'interface standard, comme représenté à la figure 1.

Drag and Drop in SharePointFigure 1 La fonction glisser-déplacer dans SharePoint

Pour implémenter cette fonction, je vais utiliser l'un des blocs principaux de création SharePoint, qui est également l'un de mes outils SharePoint préférés, à savoir XsltListViewWebPart et ses transformations XSL (pour obtenir des informations complémentaires, consultez la page correspondante de la MSDN Library sur bit.ly/wZVSFx).

Pourquoi ne pas utiliser un composant WebPart personnalisé ?

Comme toujours, dès qu'il s'agit d'implémentation, SharePoint offre un large éventail de possibilités et il est extrêmement important de sélectionner celle qui sera la plus utile.

En ce qui concerne le défi présenté par la fonction glisser-déplacer HTML5, si l'on considère que cette dernière est essentiellement destinée à la gestion des données, de nombreux développeurs SharePoint préféreraient probablement créer un composant WebPart personnalisé, qui joue alors le rôle d'un contrôle ASP.NET ordinaire : les données sont stockées dans une liste SharePoint standard, extraites via le modèle d'objet ou le contrôle SPDataSource et rendues avec l'aide du balisage ASCX et de contrôles ASP.NET.

Simple, clair, sobre ... mais est-ce le choix le plus approprié ?

C'est ce que je pensais il y a deux ans. Aujourd'hui, je préférerais personnaliser XsltListViewWebPart à l'aide de ses transformations XSL. Pourquoi ai-je changé d'avis ?

Tout d'abord, dans SharePoint 2010, presque toutes les vues de listes (à la seule exception de Calendriers) sont affichées via ce composant WebPart. Imaginez simplement : tous ces types de données, tous ces différents styles, vues et types de listes, toute cette grande variété de données, tout cela est rendu à l'aide de XsltListViewWebPart et de ses transformations XSL. Il s'agit d'un outil puissant et flexible.

Si vous décidez de mettre votre grain de sel et de créer votre propre composant WebPart personnalisé afin de rendre un balisage HTML5 pour afficher des données de listes, vous allez perdre toutes les fonctionnalités intégrées. Et d'après mon expérience, c'est une perte non négligeable. D'ailleurs, tous les composants WebPart personnalisés que j'ai rencontrés finissaient toujours, au minimum, par implémenter la moitié des fonctionnalités XsltListViewWebPart prêtes à l'emploi.

Mon plan est donc de réutiliser les fonctionnalités existantes au lieu de créer un composant WebPart personnalisé similaire qui serait probablement nettement pire en termes de flexibilité et de puissance.

En fait, XsltListViewWebPart comprend tout un groupe de fonctionnalités utiles. Il est intégré à SharePoint Designer, prend en charge toutes les connexions de composant WebPart possibles et affiche tous les types de données SharePoint correctement. Il prend en charge les regroupements, les sous-totaux, la pagination, les menus contextuels d'éléments, les modifications intralignes, les sélections d'éléments, les indicateurs de présence, etc. Il dispose d'une interface contextuelle en ruban, fournit une interface utilisateur pour le tri et le filtrage, offre certains styles d'affichage de base, et bien plus encore. Pour résumer, XsltListViewWebPart propose de nombreuses fonctionnalités utiles et exceptionnelles qu'il serait très complexe de réimplémenter à l'aide de l'approche de composant WebPart personnalisé.

XsltListViewWebPart

XsltListViewWebPart offre de nombreux points d'intégration aux développeurs : une interface de programmation, une interface CAML et, bien évidemment, des transformations XSL associées à des liaisons de paramètres. En outre, n'oubliez pas que tous ces objets et propriétés ont également leur représentation dans le modèle objet client, ce qui vous permet d'accéder à XsltListViewWebPart depuis JavaScript ou Silverlight également.

XsltListViewWebPart est donc véritablement un outil puissant. Il est vrai que tout ce XML propre à SharePoint (ou XSLT) semble quelque peu effrayant de prime abord, mais je vais vous présenter quelques astuces qui vous aideront à l'apprivoiser.

Le scénario

Avant de plonger dans les détails relatifs à l'implémentation, permettez-moi de décrire le scénario global de cet article.

Je vais injecter la fonction glisser-déplacer HTML5 dans des vues de listes SharePoint de façon à permettre aux utilisateurs de faire glisser des cellules d'une liste vers une autre. L'exemple que je vous propose utilise une liste de tâches nommée Tasks et une liste d'exécuteurs nommée Executors afin que le chef de projet puisse aisément affecter et réaffecter des tâches en faisant glisser des exécuteurs vers les cellules correspondantes de la liste Tasks.

Comme vous le savez peut-être déjà, HTML5 contient plusieurs nouveaux attributs pour la fonction glisser-déplacer, le plus important d'entre eux étant celui que l'on peut faire glisser. Il existe également un certain nombre d'événements qui permettent de gérer différentes étapes du processus de glisser-déplacer. Les fonctions de gestionnaire de ces événements peuvent être associées à l'aide des attributs correspondants, par exemple « ondragstart », « ondragend », etc. Pour plus d'informations, consultez la spécification HTML5 du W3C (World Wide Web Consortium), chapitre 7.6, sur bit.ly/lNL0FO.

Dans le cadre de cet exemple, cela signifie que j'ai simplement besoin d'utiliser XSLT pour ajouter certains attributs de base à certaines cellules de la vue de liste, et probablement de quelques attributs personnalisés supplémentaires afin de relier les valeurs de données (qui seront déplacées en les faisant glisser). En dernier lieu, je proposerai le code JavaScript correspondant pour les fonctions du gestionnaire.

Premières étapes

J'ai besoin de deux listes. Je peux créer une liste Tasks à partir du modèle Tâches standard, ou créer simplement une liste personnalisée et ajouter quelques colonnes, dont une colonne de site obligatoire « Assigned To ». Je crée une deuxième liste, Executors, comme liste personnalisée, puis j'ajoute « Executor » comme colonne de type « Personne ou groupe », en la rendant obligatoire, indexée et unique.

La liste Executors doit afficher uniquement les noms d'utilisateurs, c'est pourquoi elle n'a pas réellement besoin de la colonne « Titre ». Pour masquer cette colonne, je me rends dans les paramètres de liste, j'active la gestion des types de contenu, puis j'accède au type de contenu « Élément », je clique sur la colonne « Title » et je masque la colonne, comme illustré à la figure 2.

Making the Title Column Hidden in SharePoint List SettingsFigure 2 Masquer la colonne Title dans les paramètres de liste SharePoint

J'ai rempli ces listes avec des exemples de données, puis j'ai créé une page de composant WebPart pour mon tableau de bord, dans laquelle j'ai ajouté ces listes côte à côte (Tasks à gauche et Executors à droite), comme illustré à la figure 3.

Adding the Lists to the SharePoint DashboardFigure 3 Ajout de listes au tableau de bord SharePoint

Je dispose maintenant des listes et des données. Il est donc temps de passer à l'implémentation réelle de la fonction glisser-déplacer.

SharePoint Designer

Microsoft SharePoint Designer est un outil totalement gratuit qui permet le développement rapide des applications SharePoint. SharePoint 2010 a connu des améliorations importantes par rapport à SharePoint 2007 et il est aujourd'hui extrêmement utile, y compris pour les développeurs. L'idée est de pouvoir utiliser l'interface utilisateur SharePoint Designer afin de générer un code XSLT vraiment complexe, puis simplement de copier-coller le code généré dans le projet Visual Studio au lieu d'écrire manuellement du XML/XSLT pas toujours bien documenté et susceptible d'inclure des coquilles. J'utilise souvent cette astuce dans les projets réels et je vous assure que je gagne beaucoup de temps.

J'ouvre SharePoint Designer et j'accède à la page de tableau de bord créée précédemment. Je sélectionne une cellule dans la colonne Assigned To (en cliquant avec le bouton droit de la souris, puis en choisissant Sélectionner | Cellule). Et maintenant, voici le tour de magie : dans la barre d'état, je vois le chemin d'accès au modèle XSL (et à la balise HTML correspondante dans ce modèle) qui est chargé d'afficher cette cellule spécifique (voir la figure 4).

The Path to the Current XSL Template in SharePoint DesignerFigure 4 Le chemin d'accès au modèle XSL en cours dans SharePoint Designer

Ces informations peuvent être très utiles pour déterminer quel modèle XSL doit être remplacé afin de modifier le balisage de la cellule. Le code initial des modèles se trouve dans le dossier 14/TEMPLATE/LAYOUTS/XSL. Vous pouvez l'utiliser dans vos propres fichiers XSLT ou dans la balise <Xsl> de XsltListViewWebPart.

Cependant, je n'ai pas besoin d'avoir affaire à ces énormes fichiers XSLT compliqués pour atteindre mon but. Je peux en revanche utiliser la fonctionnalité de mise en forme conditionnelle de SharePoint Designer, qui est conçue de façon à mettre en valeur certaines lignes ou cellules avec une mise en forme spécifique, en fonction de conditions particulières. Vous n'avez besoin d'aucune compétence particulière pour utiliser cette fonctionnalité. En effet, l'interface utilisateur la rend simple d'utilisation. Mais en coulisses, tout est implémenté avec XSLT. Par conséquent, SharePoint Designer comprend un générateur XSLT graphique prêt à l'emploi et je vais m'en servir maintenant pour mon exemple.

Je sélectionne une cellule et je clique sur le bouton Mise en forme conditionnelle sur le Ruban, puis je sélectionne Mettre en forme une colonne, comme illustré à la figure 5.

Setting Conditional Formatting in SharePoint DesignerFigure 5 Paramétrage de la mise en forme conditionnelle dans SharePoint Designer

Je crée ensuite une condition improbable, ID égal à zéro, comme illustré à la figure 6.

The Conditional Formatting Dialog in SharePoint DesignerFigure 6 La boîte de dialogue Mise en forme conditionnelle de SharePoint Designer

Je clique ensuite sur le bouton Définir le style et je sélectionne un style aléatoire (par exemple, « Ornement de texte : Souligné »). J'appuie sur OK et je passe à l'onglet Mode Code, dans lequel je recherche le code généré. Il se trouve bien évidemment dans la balise <Xsl> du contrôle XsltListViewWebPart.

Transformations XSL

Je suis maintenant prêt à modifier le balisage des cellules « Assigned To ». La colonne « Assigned To » est un « accepteur de données » vers lequel je vais faire glisser les exécuteurs. J'ai donc besoin des attributs « ondragover », « ondragenter », « ondragleave » et « ondrop », qui pointeront vers les fonctions de gestionnaire d'événements JavaScript correspondantes.

Le code généré par SharePoint Designer au paragraphe précédent contient le modèle XSL avec la signature suivante :

<xsl:template name="FieldRef_printTableCell_EcbAllowed.AssignedTo"
  match="FieldRef[@Name='AssignedTo']" mode="printTableCellEcbAllowed"
  ddwrt:dvt_mode="body" ddwrt:ghost="" xmlns:ddwrt2="urn:frontpage:internal">

Comme vous le savez peut-être, les modèles XSL peuvent s'appeler l'un l'autre, par nom ou par condition. Le premier type d'appel est effectué à l'aide de l'élément « xsl:call-template » et il est fortement similaire à l'appel d'une fonction, par exemple celui que vous utiliseriez en C#.

La deuxième option est préférable et elle est nettement plus flexible : en utilisant l'élément « xsl:apply-templates », vous pouvez spécifier le mode et le paramètre (qui est sélectionné à l'aide de XPath afin qu'il puisse contenir de nombreux éléments), sans spécifier aucun nom de modèle particulier. Pour chaque élément de paramètre, le modèle correspondant est associé à l'aide de l'attribut « match ». Cette approche est similaire aux surcharges en C#.

Comme vous pouvez le voir dans le code précédent, ce modèle correspondra aux éléments « FieldRef », avec l'attribut Name égal à « Assigned To ». En outre, l'attribut « mode » de l'appel xsl:apply-template correspondant doit être égal à « printTableCellEcbAllowed ». Par conséquent, ce modèle est essentiellement une surcharge de la fonction standard qui affiche les valeurs des champs. De plus, cette surcharge correspond uniquement aux valeurs de champ « Assigned To ».

Observons maintenant ce qui se trouve dans ce modèle, comme illustré à la figure 7 (une partie du code a été supprimée à des fins de clarté).

Figure 7 Au cœur du modèle XSL

<xsl:template match="FieldRef[@Name='AssignedTo']" mode="printTableCellEcbAllowed" ...>
  <xsl:param name="thisNode" select="."/>
  <xsl:param name="class" />
  <td>
    <xsl:attribute name="style">
      <!-- ... -->
    </xsl:attribute>
    <xsl:if test="@ClassInfo='Menu' or @ListItemMenu='TRUE'">
      <xsl:attribute name="height">100%</xsl:attribute>
      <xsl:attribute name="onmouseover">OnChildItem(this)</xsl:attribute>
    </xsl:if>
    <xsl:attribute name="class">
      <!-- ... -->
    </xsl:attribute>
    <xsl:apply-templates select="." mode="PrintFieldWithECB">
      <xsl:with-param name="thisNode" select="$thisNode"/>
    </xsl:apply-templates>
  </td>
</xsl:template>

Comme vous pouvez le constater, le modèle contient deux éléments xsl:param, un élément <td>, plusieurs éléments xsl:attribute et un élément xsl:apply-templates, qui permettra à des modèles de niveau inférieur d'être appliqués.

Pour atteindre mon objectif de glisser-déplacer, j'ai simplement ajouté les attributs de la fonction glisser-déplacer à l'élément <td> de la façon suivante :

<td ondragover="return UserDragOver(event, this)" ondragenter=
  "return UserDragOver(event, this)" ondragleave=
  "UserDragLeave(event, this)" ondrop="UserDrop(event, this)">

La simplicité même, non ?

D'autre part, si jQuery a été déployé dans votre environnement SharePoint, vous pouvez envisager de relier des gestionnaires d'événements JavaScript à l'aide de la méthode jQuery .on.

Le balisage de la colonne « Assigned To » est prêt (j'écrirai ces gestionnaires un peu plus tard). Il est maintenant temps de personnaliser la liste Executors.

Je reviens à l'onglet Mode Création, puis je sélectionne une cellule dans la colonne Executors et je répète l'astuce de la mise en forme conditionnelle afin de générer le code XSLT. J'ajoute ensuite l'attribut « onstartdrag » afin de m'assurer que la fonction glisser-déplacer peut démarrer correctement (je n'ai pas besoin d'un attribut que l'on peut faire glisser ici car les valeurs de champ « Personne ou groupe » sont rendues comme des liens et, selon la spécification, les liens ont l'attribut que l'on peut faire glisser défini sur « true » par défaut) :

<td ondragstart="UserDragStart(event, this)">

Parfait. Mais comment vais-je assurer le suivi des données ? Comment vais-je déterminer à quel exécuteur est appliquée la fonction glisser-déplacer ? Selon toute évidence, j'ai besoin de son nom de connexion, ou mieux encore, de son ID. De mon point de vue, l'analyse de l'ID depuis l'intérieur de l'élément TD est extrêmement compliquée.

Mon raisonnement ici est qu'en XSLT, pour tout champ de type Personne ou Groupe, l'ID de l'utilisateur est disponible et peut être extrait aisément avec une simple requête XPath.

Dans cette requête, j'ai besoin de pointer vers les valeurs de l'élément actuel. L'élément actuel est généralement référencé comme paramètre $thisNode dans tous les modèles standard XsltListViewWebPart. Pour extraire l'ID de l'utilisateur, vous pointez vers l'attribut du paramètre $thisNode, avec le nom égal au nom de la colonne Personne ou Groupe et« id » concaténé à la fin.

Voici donc ma requête :

<td ondragstart="UserDragStart(event, {$thisNode/Executor.id}, this)">

Les accolades permettent d'inclure l'expression XPath directement dans la valeur d'attribut.

Le balisage est prêt et peut en fait être utilisé directement, mais il serait préférable de travailler un peu plus sur ce code afin de le rendre plus réutilisable.

Des modèles réutilisables

Vous avez peut-être remarqué que les modèles sont étroitement liés à des noms de colonnes spécifiques et qu'ils sont uniquement destinés à des listes spécifiques. Mais il est en fait très simple de modifier ces modèles afin de pouvoir les réutiliser pour d'autres listes avec d'autres noms de colonnes.

Pour commencer, si vous examinez la signature de modèle que j'ai présentée précédemment, vous voyez l'attribut suivant :

match="FieldRef[@Name='AssignedTo']"

Selon toute évidence, cela lie le modèle à la colonne « Assigned To ». Pour rendre le modèle un peu plus global, vous pouvez remplacer la liaison de nom par une liaison de type afin que toutes les colonnes Personne ou Groupe puissent correspondre. Eh bien soit ! Voici le code :

match="FieldRef[@Type='User']"

La même modification doit être appliquée au deuxième modèle, dans lequel l'élément « FieldRef » correspond au nom interne du champ « Executor ».

Maintenant, étant donné que je peux avoir n'importe quelle colonne de type Personne ou Groupe et n'importe quelle liste, je dois transmettre des informations complémentaires aux gestionnaires JavaScript. Lorsque le glisser-déplacer est effectué, j'ai besoin de mettre à jour la valeur de la colonne « Assigned To » dans la liste Tasks, c'est pourquoi je dois connaître le nom de la colonne et le GUID de la liste.

Comme je l'ai mentionné précédemment, SharePoint XSLT comporte des paramètres standard qui sont disponibles globalement. Citons notamment $List, qui stocke le GUID de la liste actuelle. En outre, le nom interne du champ peut être extrait aisément de l'élément de correspondance « FieldRef ».

Je vais donc passer le GUID de la liste et le nom de colonne interne au gestionnaire UserDrop, de la façon suivante (j'ai omis les attributs « ondragenter », « ondragover » et « ondragleave » à des fins de clarté) :

<td ... ondrop="UserDrop(event, this, '{$List}', '{./@Name}'">

Le « . » pointe vers l'élément actuel « FieldRef » (avec lequel le modèle a établi une correspondance précédemment).

Ensuite, j'ai besoin de me débarrasser de la chaîne « Executor » dans le paramètre id du XSLT de la liste Executors à l'aide du code suivant :

<td ondragstart="UserDragStart(event, {$thisNode/@*[name()=
  concat(current()/@Name, '.id')]}, this)">

Les modèles sont maintenant prêts et réutilisables et je vais écrire le code JavaScript correspondant afin d'implémenter les gestionnaires.

Écriture des gestionnaires JavaScript

Bien qu'il y ait quatre gestionnaires différents à écrire, la plupart d'entre eux sont primitifs et ils sont tous plutôt évidents.

En règle générale, je recommanderais de placer ce code dans un fichier JavaScript distinct. Et il est généralement conseillé d'utiliser Visual Studio pour le créer car cela vous permet de bénéficier d'IntelliSense. Dans certains cas, toutefois, il est raisonnable de mettre ce code dans le XSLT afin de remplacer le modèle racine (match="/") à cet effet. Cela vous permet d'utiliser certaines variables et certains paramètres XSLT dans votre code JavaScript et cela signifie également que vous n'avez pas besoin de vous préoccuper du déploiement des fichiers JavaScript.

Observons donc le code des gestionnaires, DragStart, DragEnter, DragOver, DragLeave et Drop.

Dans le gestionnaire UserDragStart, vous devez initialiser le transfert des données. Cela signifie que vous devez stocker les données que l'on a fait glisser dans un objet DataTransfer HTML5 spécial, de la façon suivante :

function UserDragStart(e, id, element) {
  e.dataTransfer.effectAllowed = 'copy';
  e.dataTransfer.setData('Text', id + '|' + element.innerHTML);
}

Notez que l'ID de l'utilisateur n'est pas la seule partie des données qui est transférée. J'ai également ajouté le HTML interne de l'élément <td> afin de ne pas avoir besoin de rafraîchir la page après avoir déposé les données (consultez le code du gestionnaire UserDrop à la figure 8 pour plus de détails).

Figure 8 Le gestionnaire d'événements Drop

function UserDrop(e, toElement, listGuid, columnName) {
  // Terminate the event processing
  if (e.stopPropagation)
      e.stopPropagation();
  // Prevent default browser action
  if (e.preventDefault)
      e.preventDefault();
  // Remove styles from the placeholder
  toElement.style.backgroundColor = '';
  //toElement.className = '';
  // iid attribute is attached to tr element by SharePoint
  // and contains ID of the current element
  var elementId = toElement.parentNode.getAttribute('iid').split(',')[1];
  // Transferred data
  var data = e.dataTransfer.getData('Text');
  var userId = data.split('|')[0];
  var userLinkHtml = data.split('|')[1];
  // Setting value of the field using SharePoint
  // EcmaScript Client Object Model
  var ctx = new SP.ClientContext.get_current();
  var list = ctx.get_web().get_lists().getById(listGuid);
  var item = list.getItemById(elementId);
  item.set_item(columnName, userId);
  item.update();
  // Asynchronous call
  ctx.executeQueryAsync(
    function () { toElement.innerHTML = userLinkHtml; },
    function (sender, args) { alert('Drag-and-drop failed.
      Message: ' + args.get_message()) }
    );
  return false;
}

Dans ce cas, pour les événements DragEnter et DragOver, les gestionnaires sont identiques et j'utilise donc une seule fonction. Vous devez indiquer dans ces événements que l'utilisateur peut déplacer ses données ici. D'après la spécification, vous devez pour cela appeler la méthode event.preventDefault (si elle est disponible), puis retourner false.

Le gestionnaire DragEnter/DragOver est l'endroit idéal pour appliquer des styles personnalisés à l'espace réservé glisser-déplacer afin d'avertir l'utilisateur qu'il peut effectivement déposer les données qu'il a fait glisser. Afin de simplifier cet exemple, je vais utiliser des styles CSS insérés. Toutefois, dans un projet réel, je vous recommanderais d'utiliser des classes CSS (reportez-vous aux lignes commentées de la figure 9).

Figure 9 Les gestionnaires d'événements DragOver et DragLeave

function UserDragOver(e, toElement) {
  // Highlight the placeholder
  toElement.style.backgroundColor = '#efe';
  // toElement.className = 'userDragOver';
  // Denote the ability to drop
  if (e.preventDefault)
      e.preventDefault();
  e.dataTransfer.dropEffect = 'copy';
  return false;
}
function UserDragLeave(e, toElement) {
  // Remove styles
  toElement.style.backgroundColor = '';
  // toElement.className = '';

Il est évident que je dois supprimer de DragLeave les styles appliqués précédemment, comme illustré à la figure 9.

Au cours de l'événement Drop de la figure 8, deux actions importantes doivent être effectuées :

  1. Appliquez les modifications. À l'aide du modèle d'objet client EcmaScript de SharePoint, définissez la valeur de champ sur l'ID utilisateur transféré.
  2. Remplacez le code HTML interne de la cellule active (TD) par le code provenant de la cellule transférée afin de faire apparaître les modifications sans avoir besoin de rafraîchir la page.

Maintenant, tous les gestionnaires ont été implémentés et vous pouvez déployer le JavaScript. En fait, vous pouvez procéder de plusieurs façons : personnaliser la page maître, utiliser la délégation de contrôle, créer une action personnalisée avec Location défini sur « ScriptLink » ou, comme je l'ai mentionné précédemment, inclure JavaScript directement dans le XSLT.

Dans le cas présent, la solution la plus simple consiste à personnaliser le fichier de la page maître à l'aide de SharePoint Designer, dans la mesure où cela ne requiert aucune compétence particulière. Toutefois, étant donné que vous êtes développeur, vous préférerez probablement regrouper toutes ces personnalisations JavaScript et XSLT et créer une solution déployable. Alors allons-y !

Création d'une solution déployable

Pour créer une solution prête à être utilisée que vous pourrez envoyer à vos clients, vous devez suivre quelques étapes très simples :

  1. Ouvrez Visual Studio et créez un projet SharePoint vide. Sélectionnez ensuite « Déployer en tant que solution de batterie » dans la boîte de dialogue des paramètres du projet.
  2. Ajoutez un dossier mappé « Dispositions » Sharepoint au projet, puis ajoutez-lui trois nouveaux fichiers : UserDragHandlers.js, UserDragProvider.xsl et UserDragConsumer.xsl.
  3. Collez le code JavaScript créé précédemment et le code XSLT (généré dans SharePoint Designer) dans les fichiers correspondants.
  4. Ajoutez un élément de projet Élément vide, ouvrez Elements.xml et collez le code suivant à cet emplacement :
            <CustomAction ScriptSrc="/_layouts/SPDragAndDrop/UserDragHandlers.js" Location="ScriptLink" Sequence="10" />
    Cela permet de déployer sur toutes les pages du site le lien vers le fichier JavaScript.
  5. En dernier lieu, ajoutez un récepteur d'événements à Fonctionnalité1 (dont la création a été faite automatiquement lors de l'ajout de l'élément de projet Élément vide), annulez les marques de commentaire de la méthode FeatureActivated et collez le code suivant à l'intérieur :
var web = properties.Feature.Parent as SPWeb;
        SPList list;
        SPView view;
        list = web.Lists["Tasks"];
        view = list.DefaultView;
        view.XslLink = "../SPDragAndDrop/UserDragConsumer.xsl";
        view.Update();
        list = web.Lists["Executors"];
        view = list.DefaultView;
        view.XslLink = "../SPDragAndDrop/UserDragProvider.xsl";
        view.Update();

Eh oui, c'est tout, vous avez terminé ! La simplicité même, non ? Maintenant, si vous construisez et déployez la solution avec les listes Tasks et Executors créées précédemment, puis que vous créez un tableau de bord comportant des vues par défaut de chacune d'entre elles, le tableau de bord affichera une fonction glisser-déplacer bien pratique.

Prise en charge par le navigateur

À l'heure actuelle, presque tous les navigateurs principaux, à l'exception d'Opera, prennent en charge la fonction de glisser-déplacer HTML5. J'ai testé Internet Explorer 9.0.8112.16421, Chrome 16.0.912.75 et Firefox 3.6.12, et ils sont tous totalement compatibles avec la solution décrite. J'espère que certaines versions plus anciennes de ces navigateurs fonctionneront également. En fait, Safari devrait également fonctionner, mais à l'heure où j'écris cet article, il présente des bogues bizarres dans son implémentation de la fonction glisser-déplacer HTML5 qui empêchent la solution de fonctionner normalement.

Et maintenant ?

Dans la solution que je vous propose, ni les modèles XSLT ni le JavaScript ne contiennent de code propre aux listes ; il n'y a aucun GUID, aucun nom ni aucun titre codés en dur, ni quoi que ce soit de similaire. Par conséquent, ces transformations pourraient éventuellement être appliquées à toutes les listes ou bibliothèques de documents et vous pourriez ajouter une prise en charge de la fonction glisser-déplacer à toutes les colonnes de type Personne ou Groupe. N'est-ce pas génial ?

Évidemment, il est possible de faire en sorte que l'on puisse faire glisser d'autres types de colonnes de la même façon. Vous pourriez en fait créer une solution dans laquelle il serait possible de faire glisser toutes les cellules de toutes les listes SharePoint. De plus, dans toutes les pages du tableau de bord, les utilisateurs pourraient ensuite faire glisser des cellules d'une liste à l'autre, ce qui est également pratique.

L'implémentation d'une fonction glisser-déplacer par ligne pourrait également être un défi très intéressant. L'idée est essentiellement la même, mais pour obtenir le modèle approprié, vous devriez utiliser la mise en forme conditionnelle de ligne. Cela pourrait permettre de lier les éléments de listes ou, par exemple, de modifier leur ordre. Vous pourriez, par exemple, faire en sorte qu'un lien « Corbeille » du menu de lancement rapide joue le rôle d'un accepteur de glisser-déplacer, et l'utiliser afin de supprimer des éléments des listes.

Les possibilités sont tellement nombreuses. Il vous suffit de réfléchir, d'expérimenter et de tester : votre portail SharePoint deviendra un endroit nettement plus convivial.

Andrey Markeev est un MVP SharePoint Server qui travaille comme développeur SharePoint chez Softline Group en Russie. M. Markeev est l'un des 10 grands experts en SharePoint StackExchange (bit.ly/w9e4NP), le créateur de plusieurs projets open source sur CodePlex, ainsi qu'un blogeur et conférencier actif. Vous pouvez le suivre sur Twitter à l'adresse twitter.com/amarkeev.

Merci aux experts techniques suivants d'avoir relu cet article : Michael Nemtsev et Brandon Satrom