Solved

Custom Ribbon Action - Disabled with Document Set Selection

Posted on 2014-04-06
13
767 Views
Last Modified: 2014-07-20
The custom action enables/disables when a list item or folder is selected/deselected. The issue I'm running into is when a document set is selected, the custom action remains disabled.


Custom Ribbon Action:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
      Id="LinkDocsCustom"
      Location="CommandUI.Ribbon"
      RegistrationType="ContentType"
      RegistrationId="0x01">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Groups._children">
          <Group
              Id="LinkDocsCustomGroup"
              Sequence="15"
              Description="Copy permanent link to clipboard"
              Title="Permanent Link"
              Template="LinkDocsCustomGroupTemplate">
            <Controls Id="LinkDocsCustomGroupControl">
              <Button
                  Id="LinkDocsCustomGroupControlButton"
                  Sequence="5"
                  Command="SimpleAlert"
                  Image32by32="/_layouts/1033/images/formatmap32x32.png" Image32by32Left="-448" Image32by32Top="-128"
                  Description="Copies a permanent link to the clipboard"
                  LabelText="Copy Link to Clipboard"
                  ToolTipTitle="Copy Link to Clipboard"
                  TemplateAlias="o1" />
            </Controls>
          </Group>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.Templates._children">
          <GroupTemplate Id="LinkDocsCustomGroupTemplate">
            <Layout Title="LargeLarge">
              <OverflowSection Type="OneRow" TemplateAlias="o1" DisplayMode="Large"/>
              <OverflowSection Type="OneRow" TemplateAlias="o2" DisplayMode="Large"/>
            </Layout>
          </GroupTemplate>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.Documents.Scaling._children">
          <MaxSize Id="Ribbon.Documents.Scaling.Custom.MaxSize" Sequence="15" GroupId="LinkDocsCustomGroup" Size="LargeLarge" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler
          Command="SimpleAlert"
          CommandAction="javascript:CopyLinkToClipboard();"
          EnabledScript="javascript:EnableCopyLinkToClipboard();"/>
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>

  <CustomAction
     Id="CopyLinkToClipboardScript"
     Location="ScriptLink"
     ScriptSrc ="/_layouts/15/CustomMenuAction/CopyLinkToClipboard.js"/>
</Elements>

Open in new window


JavaScript:

// This method contains the code needed to request the unique url to the document
function CopyLinkToClipboard() {
    // First get the context and web
    var ctx = SP.ClientContext.get_current();
    this.web = ctx.get_web();
    // Get the current selected list, then load the list using the getById method of Web (SPWeb)
    var listId = SP.ListOperation.Selection.getSelectedList();
    var sdlist = this.web.get_lists().getById(listId);
    // Get the currently selected item of the list. This will return a dicustonary with an id field
    var items = SP.ListOperation.Selection.getSelectedItems(ctx);
    var mijnid = items[0];
    // Request the list item from the server using the getItemById method. This will load all properties.   
    // If needed, one could pre-request the fields to be loaded to preserve bandwidth.
    this.listItem = sdlist.getItemById(mijnid.id);
    // load the item in the context for batch operation.
    ctx.load(this.listItem);
    //Execute the actual script on the server side. Specify delegates to handle the response. 
    ctx.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

// Delegate that is called when server operation is complete upon success.
function onQuerySucceeded(sender, args) {
    // Request url by using the get_item method. It will return the Url field type, which has a Url property. 
    var url = this.listItem.get_item('_dlc_DocIdUrl').get_url();
    // Request the name of the document. 
    var title = this.listItem.get_item('FileLeafRef');
    // Copy Link To Clipboard (Only works in Internet Explorer)
    window.clipboardData.setData('Text', url);
    // Notify the user that the link was successfully copied
    var notificationId = SP.UI.Notify.addNotification('Link Successfully Copied to Clipboard');
}

// Delegate that is called when server operation is completed with errors.
function onQueryFailed(sender, args) {
    alert('failed ' + args.toString());
}

// Method to enable/disable the button on the ribbon or ECB. 
function EnableCopyLinkToClipboard() {
    var enable = true;
    var context = SP.ClientContext.get_current();
    var selection = SP.ListOperation.Selection.getSelectedItems(context);

    // Check if more than one item is selected, disable the button if items > 1
    if (CountDictionary(selection) == 1)
        this.enable = true;
    else
        return false;
    // Check if a folder is selected
    var item;
    for (item in selection) {
        if (selection[item].fsObjType != 0)
            enable = false;
    }
    return enable;
}

Open in new window

0
Comment
Question by:brendanlefavre
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
13 Comments
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39982399
0
 

Author Comment

by:brendanlefavre
ID: 39983390
I'm trying this, but get an error when it tries to load the content type

function EnableCopyLinkToClipboard() {
    var enable = true;
    var context = SP.ClientContext.get_current();
    var selection = SP.ListOperation.Selection.getSelectedItems(context);

    // Check if more than one item is selected, disable the button if items > 1
    if (CountDictionary(selection) == 1)
        this.enable = true;
    else
        return false;
    // Check if a folder is selected
    var item;
	var _contentType = item.get_contentType();
    for (item in selection) {
	    alert(_contentType);
        if (selection[item]._contentType != 'Document')
            enable = false;
    }
    return enable;
}

Open in new window

0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39983543
Did you get 'PropertyOrFieldNotInitializedException' or something else?

Line 13?
0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 

Author Comment

by:brendanlefavre
ID: 39983571
I'm getting "Object doesn't support property or method 'get_contentType'" on line 13
0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39983617
// Check if a folder is selected
    var item;
	var _contentType = item.get_contentType();

Open in new window


Looking at the above code, Item gets declared but never initialized to any type of object?
0
 

Author Comment

by:brendanlefavre
ID: 39984517
what do I need to do to get the object initialized?
0
 
LVL 31

Accepted Solution

by:
Jamie McAllister MVP earned 500 total points
ID: 39985306
Check out the sample from the link I sent (shown below).

After getting the selected item, the actual list item instance is obtained; this.listItem =  list.getItemById(items[k].id);

Then in the Product received function it looks like your code except the Var is initialized as so;
var item = this.listItem;
              var _contentType =  item.get_contentType();



var listItem;
function someFunction()
{
var ctx = SP.ClientContext.get_current();            
            items = SP.ListOperation.Selection.getSelectedItems(ctx);
for (k in items)
            {
              this.listItem =  list.getItemById(items[k].id);
              ctx.load(this.listItem,'Title', 'ContentType');
              ctx.executeQueryAsync(Function.createDelegate(this, this.productReceived), Function.createDelegate(this, this.failed));

            }
}


 function productReceived() {
              var item = this.listItem;
              var _contentType =  item.get_contentType();
              if(_contentType.get_name() == 'Document Set')
              {
                 alert('Document Set Item is selected')                 
              }
            }

function failed(sender, args) {
                alert('failed. Message:' + args.get_message());
            }

Open in new window

0
 

Author Comment

by:brendanlefavre
ID: 39987810
I have tried your suggestion, and get the following error

script error

this is how i'm calling the custom script
get content type action
0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39988140
Please post your latest script here.
0
 

Author Comment

by:brendanlefavre
ID: 39991650
var listItem;
function someFunction() {
    var ctx = SP.ClientContext.get_current();
    items = SP.ListOperation.Selection.getSelectedItems(ctx);
    for (k in items) {
        this.listItem = list.getItemById(items[k].id);
        ctx.load(this.listItem, 'Title', 'ContentType');
        ctx.executeQueryAsync(Function.createDelegate(this, this.productReceived), Function.createDelegate(this, this.failed));
    }
}

function productReceived() {
    var item = this.listItem;
    var _contentType = item.get_contentType();
    if (_contentType.get_name() == 'Document Set') {
        alert('Document Set Item is selected')
    }
}

function failed(sender, args) {
    alert('failed. Message:' + args.get_message());
}

Open in new window

0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39991737
It looks OK to me.

I'd put some diagnostics after var item = this.listItem; to ensure you really have a List Item at that point. Put some Alerts in there to examine the item title or whether it's null. That will narrow down the investigation as to whether there's an item or .get_contentType() is the problem.
0
 

Author Comment

by:brendanlefavre
ID: 40085310
I got this work, and will post the final code
0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 40085585
Good work!
0

Featured Post

U.S. Department of Agriculture and Acronis Access

With the new era of mobile computing, smartphones and tablets, wireless communications and cloud services, the USDA sought to take advantage of a mobilized workforce and the blurring lines between personal and corporate computing resources.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

If you create your solutions on SharePoint sooner or later you will come upon a request to set  permissions of the item depending on some of the item's meta-data - the author, people assigned as approvers, divisions, categories etc. The most natu…
Summary In SharePoint 2010 it is easy to create custom color themes to jazz up a site. Theme colors can also be created in PowerPoint 2010 with a few clicks. But how do the chosen colors actually look in the SharePoint site? The attached PowerPoint…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

697 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question