After digging around some SugarCRM code, I ran across an interesting jQuery plugin in /includes/javascript/jquery/jquery.SugarMenu.js. After exploring where this plugin is used throughout the codebase, I learned that it actually powers all of those cool buttons you see on all of the views throughout SugarCRM: above and below list views, above detail views, in every subpanel, etc. Another interesting thing in the plugin is that it is well-documented, thanks to John Barlow and Justin Park at SugarCRM whenever they wrote the plugin! Because of this, I was able to easily see the handy addItem() method that comes with the plugin.

So... on to the good stuff: the easiest way to add items to buttons throughout SugarCRM. You simply use jQuery to select the parent <ul> and tell the plugin to add an item:

$('#selector').sugarActionMenu('addItem',{
item: $('<li><a href="#">New Item!</a></li>'), // a jquery element to add,
index: 1 // (optional) set the exact order the new option will show in the list (1 being the first item)
});
view raw example.js hosted with ❤ by GitHub

The great thing about this and the modularization of SugarCRM is that the underlying markup for the standard views is pretty much the same for all modules: a subpanel is subpanel, a list view is a list view, etc. Because of this, we can reliably use jQuery selectors to select and modify any button that uses this plugin. In all of the base view tpls (such as /includes/ListView/ListViewGeneric.tpl) you'll see that for every page in SugarCRM any unordered list elements with the class clickMenu will be transformed to a sugarActionMenu via this plugin.

For all of the most common action menus throughout SugarCRM, I've created a file of example javascript that it will take to add a menu item:

$(document).ready(function(){
// The button we're adding to the dropdowns
var button = $('<li><a href="javascript:void(0)" onclick="alert(\'Hello, world!\')">New Button!</a></li>")');
// Add item to "select all" dropdown button on list view
$("#selectLinkTop").sugarActionMenu('addItem',{item:button});
$("#selectLinkBottom").sugarActionMenu('addItem',{item:button});
// Add item to the first slot of the "select all" dropdown button on list view
$("#selectLinkTop").sugarActionMenu('addItem',{item:button,index:1});
$("#selectLinkBottom").sugarActionMenu('addItem',{item:button,index:1});
// Add item to action dropdown for selected items on list view
$("#actionLinkTop").sugarActionMenu('addItem',{item:button});
$("#actionLinkBottom").sugarActionMenu('addItem',{item:button});
// Add item to action dropdown on a detail view
$("#detail_header_action_menu").sugarActionMenu('addItem',{item:button});
// Add item to action dropdown for select items for all subpanels on detail view
$("#subpanel_list ul.SugarActionMenu:not(.records)").each(function(){
// need to recreate button variable for scope issues
var button = $('<li><a href="javascript:void(0)" onclick="alert(\'Hello, world!\')">New Button!</a></li>")');
$(this).sugarActionMenu('addItem',{item:button});
});
// Add item to action dropdown for select items for a specific subpanel on detail view
// (activities subpanel on account detail view)
$("#list_subpanel_activities ul.SugarActionMenu:not(.records)").sugarActionMenu('addItem',{item:button});
// Add item to action dropdown for all subpanel records on the detail view
$("#subpanel_list ul.records").each(function(){
var button = $('<li><a href="javascript:void(0)" onclick="alert(\'Hello, world!\')">New Button!</a></li>")');
$(this).sugarActionMenu('addItem',{item:button});
});
// Add item to action dropdown for all subpanel records on a specific detail view
// (activities subpanel records)
$("#list_subpanel_activities ul.records").each(function(){
var button = $('<li><a href="javascript:void(0)" onclick="alert(\'Hello, world!\')">New Button!</a></li>")');
$(this).sugarActionMenu('addItem',{item:button});
});
// Add item to action dropdown for all subpanel records on the detail view (lookup by id)
// may have issues if record appears in mulitple subpanels on same page
$("ul#38455ab8-bd8f-6ecb-213c-50c9eb8eb3d5").sugarActionMenu('addItem',{item:button});
});
view raw buttons.js hosted with ❤ by GitHub

Now that we have the required javascript needed to add items to the various buttons, we need a reliable way to add the javascript into the pages we have menu buttons we want to modify. The best way I've found to do this is by using the after_ui_frame logic hook. To do that, we simply add an entry to a specific module's or global logic hook. I use the Accounts module for the following examples.

<?php
$hook_version = 1;
$hook_array = array();
$hook_array['after_ui_frame'] = array();
$hook_array['after_ui_frame'][] = Array(1, 'Accounts InsideView frame', 'modules/Connectors/connectors/sources/ext/rest/insideview/InsideViewLogicHook.php','InsideViewLogicHook', 'showFrame');
// Add the new hook
$hook_array['after_ui_frame'][] = Array(2, 'Add Buttons to Account Module Views', 'custom/modules/Accounts/AccountButtons.php','AccountButtons', 'add');
view raw logic_hooks.php hosted with ❤ by GitHub

Now we need to create the php script that executes for when this logic hook is triggered. I've called the class AccountButtons and the method add(). The after_ui_frame logic hook will fire for all views for the module you're using, so you need to be sure to only add your relevant javascript to the views that you want. In the code below, I add several buttons to the detail view and list view. To get the javascript to execute in the specific views, you simply need to echo the javascript code.

<?php
class AccountButtons {
function add()
{
// Based on what action we're in, add some buttons!
switch ($GLOBALS['app']->controller->action)
{
case "DetailView": // Add buttons to Detail View
$button_code = <<<EOQ
<script type="text/javascript">
$(document).ready(function(){
var button = $('<li><a href="javascript:void(0)" onclick="alert(\'Hello, world!\')">New Button!</a></li>")');
// Add item to action dropdown on a detail view
$("#detail_header_action_menu").sugarActionMenu('addItem',{item:button});
// Add item to action dropdown for all subpanel records on the detail view
$("#subpanel_list ul.records").each(function(){
var button = $('<li><a href="javascript:void(0)" onclick="alert(\'Hello, world!\')">New Button!</a></li>")');
$(this).sugarActionMenu('addItem',{item:button});
});
});
</script>
EOQ;
echo $button_code;
break;
case "listview": // Add buttons to List View
$button_code = <<<EOQ
<script type="text/javascript">
$(document).ready(function(){
var button = $('<li><a href="javascript:void(0)" onclick="alert(\'Hello, world!\')">New Button!</a></li>")');
// Add item to "select all" dropdown button on list view
$("#selectLinkTop").sugarActionMenu('addItem',{item:button});
$("#selectLinkBottom").sugarActionMenu('addItem',{item:button});
// Add item to the first slot of the "select all" dropdown button on list view
$("#selectLinkTop").sugarActionMenu('addItem',{item:button,index:1});
$("#selectLinkBottom").sugarActionMenu('addItem',{item:button,index:1});
});
</script>
EOQ;
echo $button_code;
break;
}
}
}

And that's it!

If you're wanting to dig deeper into the code, you may find it easier to digest on Github