Accueil

PWA 2013 : Hooker un bouton

by Jean-Camille Mercier 9. juin 2015 11:12

Si vous souhaitez changer le comportement d'un bouton standard de Project Server 2013, il faut cacher l'ancien puis en créer un nouveau de toute pièce en javascript.

  • Cacher un bouton

Dans Visual studio, dans un projet Sharepoint, ajoutez un "Elément vide", et assurez-vous qu'il est bien déployé dans votre package. 

Ensuite il suffit de trouver le nom du bouton et de créer une custom action vide à la place : 

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!--Cacher le bouton de fermeture du projet pour le remplacer-->
  <CustomAction Id="Ribbon.Tabs.PDP.Home.Project.Close.Remove" Location="CommandUI.Ribbon">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Tabs.PDP.Home.Project.Close"/>
      </CommandUIDefinitions>
    </CommandUIExtension>
  </CustomAction>
</Elements>

Pour trouver le bon nom, vous pouvez introspecter le code HTML : 

 Ou consulter le fichier complet de PWA : 

 C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\FEATURES\PWARibbon\listtemplates\pwaribbon.xml

  • Créer un nouveau bouton
La méthode classique (décrite ici) devrait être de créer un autre CustomAction en xml et d'y associer une "CommandAction" en javascript. Malheureusement, tous mes tests sont restés infructueux, le bouton restait désespérément grisé. Je pense que le gestionnaire de commande fonctionne différemment depuis Sharepoint 2013 et son nouveau Ribbon. Je me suis donc inspirer d'un code trouvé sur le net qui permet de créer un bouton dans le ribbon en full Javascript et d'y associer un gestionnaire de commande :
SP.SOD.executeOrDelayUntilScriptLoaded(onRibbonLoaded, "sp.ribbon.js");

function onRibbonLoaded() {
    (SP.Ribbon.PageManager.get_instance()).add_ribbonInited(createSaveButton);
    SamplePageComponent.initializePageComponent();
}

var btModif;

function createSaveButton(ribbon) {
    // Création du bouton de sauvegarde directement dans le ribbon de PWA
    var ribbon = (SP.Ribbon.PageManager.get_instance()).get_ribbon();
    var tab = ribbon.getChild("Ribbon.Tabs.PDP.Home");
    if (tab == null) return;
    var group = tab.getChild("Ribbon.Tabs.PDP.Home.Project")
    if (group == null) return;
    var layout = group.getChild("Ribbon.Tabs.PDP.Home.Project-LargeLarge");
    if (layout == null) return;
    var section = layout.getChild("Ribbon.Tabs.PDP.Home.Project-LargeLarge-0");
    if (section == null) return;
    var controlProperties = new CUI.ControlProperties();
    controlProperties.Sequence = "20";
    controlProperties.Command = 'FullSaveCommand';
    controlProperties.Id = 'Ribbon.Tabs.PDP.Home.Project.Save.Ugap';
    controlProperties.TemplateAlias = 'o1';
    controlProperties.LabelText = "Enregistrer";
    controlProperties.ToolTipDescription = "Enregistrer et publier le projet.";
    controlProperties.ToolTipTitle = "Enregistrer";
    controlProperties.Image16by16 = "/_layouts/15/1036/images/ps16x16.png?rev=23";
    controlProperties.Image16by16Top = "-112"
    controlProperties.Image16by16Left = "-128"
    controlProperties.Image32by32 = "/_layouts/15/1036/images/ps32x32.png?rev=23";
    controlProperties.Image32by32Top = "-288"
    controlProperties.Image32by32Left = "-224"
    btSave = new CUI.Controls.Button(ribbon, 'Sample.Button', controlProperties);
    var controlComponent = btSave.createComponentForDisplayMode('Large');
    var row1 = section.getRow(1);
    row1.addChildAtIndex(controlComponent, 1);
    // Mémo du bouton 'Modifier' pour gérer le disabled
    btModif = section.getRow(1).getChild("Ribbon.Tabs.PDP.Home.Project.Edit-Large0").$L_1;
}

SamplePageComponent = function () { SamplePageComponent.initializeBase(this); }
SamplePageComponent.registerClass('SamplePageComponent', CUI.Page.PageComponent);

SamplePageComponent.initializePageComponent = function () {
    var ribbonPageManager = SP.Ribbon.PageManager.get_instance();
    if (null !== ribbonPageManager) {
        var rbnInstance = SamplePageComponent.get_instance();
        ribbonPageManager.addPageComponent(rbnInstance);
    }
}
SamplePageComponent.get_instance = function () {
    if (SamplePageComponent.instance == null) {
        SamplePageComponent.instance = new SamplePageComponent();
    }
    return SamplePageComponent.instance;
}

SamplePageComponent.prototype = {
    init: function () {
        var buttonEnabled = true;
        // Ajout de la fonction de sauvegarde au bouton
        this._handledCommands = new Object();
        this._handledCommands['FullSaveCommand'] = 
        { 
          enable: function () { return buttonEnabled; }, 
          handle: function (commandId, props, seq) { UgapFullSave() } 
        };
        this._commands = ['FullSaveCommand'];
    },

    getFocusedCommands: function () { return []; },
    getGlobalCommands: function () { return this._commands; },
    canHandleCommand: function (commandId) {
        // Gestion de la désactivation de la commande
        // Astuce : le bouton save est actif uniquement si le bouton modifier est inactif
        var retval = btModif.get_enabled();
        return !retval;
    },
    handleCommand: function (commandId, properties, sequence) {
        return this._handledCommands[commandId].handle(commandId, properties, sequence);
    },
    isFocusable: function () { return false; },
    yieldFocus: function () { return false; },
    receiveFocus: function () { return true; },
    handleGroup: function () { }
}

// Hook de la sauvegarde : pour nous c'est SAVE + PUBLISH tout le temps
function UgapFullSave() 
{
   if (window.PDPButton != null) 
   {
      var callbackCmdObject = { Execute: function (queue) { queue.Completed(); }, type: '' };
      PDPButton.Publish(callbackCmdObject);
   }
}
Comme pour la première partie, il faut bien trouver les bons ID des conteneurs pour se placer au bon endroit dans le ribbon. Ensuite on associe le bouton à une commande avec le "HandledCommand" en précisant simplement le nom de la function Javascript. 
 
Dans mon cas, j'ai été amené à hooker la commande de sauvegarde qui publie automatiquement (PDPButton.Publish) et la commande de fermeture qui archive automatique (PDPButton.CheckIn). Celà simplifie énormément la gestion des brouillons dans Projet Server 2013.
 
.