276 lines
7.4 KiB
JavaScript
276 lines
7.4 KiB
JavaScript
|
(function ($) {
|
||
|
// register namespace
|
||
|
$.extend(true, window, {
|
||
|
"Slick": {
|
||
|
"Plugins": {
|
||
|
"HeaderMenu": HeaderMenu
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
/***
|
||
|
* A plugin to add drop-down menus to column headers.
|
||
|
*
|
||
|
* USAGE:
|
||
|
*
|
||
|
* Add the plugin .js & .css files and register it with the grid.
|
||
|
*
|
||
|
* To specify a menu in a column header, extend the column definition like so:
|
||
|
*
|
||
|
* var columns = [
|
||
|
* {
|
||
|
* id: 'myColumn',
|
||
|
* name: 'My column',
|
||
|
*
|
||
|
* // This is the relevant part
|
||
|
* header: {
|
||
|
* menu: {
|
||
|
* items: [
|
||
|
* {
|
||
|
* // menu item options
|
||
|
* },
|
||
|
* {
|
||
|
* // menu item options
|
||
|
* }
|
||
|
* ]
|
||
|
* }
|
||
|
* }
|
||
|
* }
|
||
|
* ];
|
||
|
*
|
||
|
*
|
||
|
* Available menu options:
|
||
|
* tooltip: Menu button tooltip.
|
||
|
*
|
||
|
*
|
||
|
* Available menu item options:
|
||
|
* title: Menu item text.
|
||
|
* disabled: Whether the item is disabled.
|
||
|
* tooltip: Item tooltip.
|
||
|
* command: A command identifier to be passed to the onCommand event handlers.
|
||
|
* iconCssClass: A CSS class to be added to the menu item icon.
|
||
|
* iconImage: A url to the icon image.
|
||
|
*
|
||
|
*
|
||
|
* The plugin exposes the following events:
|
||
|
* onBeforeMenuShow: Fired before the menu is shown. You can customize the menu or dismiss it by returning false.
|
||
|
* Event args:
|
||
|
* grid: Reference to the grid.
|
||
|
* column: Column definition.
|
||
|
* menu: Menu options. Note that you can change the menu items here.
|
||
|
*
|
||
|
* onCommand: Fired on menu item click for buttons with 'command' specified.
|
||
|
* Event args:
|
||
|
* grid: Reference to the grid.
|
||
|
* column: Column definition.
|
||
|
* command: Button command identified.
|
||
|
* button: Button options. Note that you can change the button options in your
|
||
|
* event handler, and the column header will be automatically updated to
|
||
|
* reflect them. This is useful if you want to implement something like a
|
||
|
* toggle button.
|
||
|
*
|
||
|
*
|
||
|
* @param options {Object} Options:
|
||
|
* buttonCssClass: an extra CSS class to add to the menu button
|
||
|
* buttonImage: a url to the menu button image (default '../images/down.gif')
|
||
|
* @class Slick.Plugins.HeaderButtons
|
||
|
* @constructor
|
||
|
*/
|
||
|
function HeaderMenu(options) {
|
||
|
var _grid;
|
||
|
var _self = this;
|
||
|
var _handler = new Slick.EventHandler();
|
||
|
var _defaults = {
|
||
|
buttonCssClass: null,
|
||
|
buttonImage: null
|
||
|
};
|
||
|
var $menu;
|
||
|
var $activeHeaderColumn;
|
||
|
|
||
|
|
||
|
function init(grid) {
|
||
|
options = $.extend(true, {}, _defaults, options);
|
||
|
_grid = grid;
|
||
|
_handler
|
||
|
.subscribe(_grid.onHeaderCellRendered, handleHeaderCellRendered)
|
||
|
.subscribe(_grid.onBeforeHeaderCellDestroy, handleBeforeHeaderCellDestroy);
|
||
|
|
||
|
// Force the grid to re-render the header now that the events are hooked up.
|
||
|
_grid.setColumns(_grid.getColumns());
|
||
|
|
||
|
// Hide the menu on outside click.
|
||
|
$(document.body).bind("mousedown", handleBodyMouseDown);
|
||
|
}
|
||
|
|
||
|
|
||
|
function destroy() {
|
||
|
_handler.unsubscribeAll();
|
||
|
$(document.body).unbind("mousedown", handleBodyMouseDown);
|
||
|
}
|
||
|
|
||
|
|
||
|
function handleBodyMouseDown(e) {
|
||
|
if ($menu && $menu[0] != e.target && !$.contains($menu[0], e.target)) {
|
||
|
hideMenu();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function hideMenu() {
|
||
|
if ($menu) {
|
||
|
$menu.remove();
|
||
|
$menu = null;
|
||
|
$activeHeaderColumn
|
||
|
.removeClass("slick-header-column-active");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function handleHeaderCellRendered(e, args) {
|
||
|
var column = args.column;
|
||
|
var menu = column.header && column.header.menu;
|
||
|
|
||
|
if (menu) {
|
||
|
var $el = $("<div></div>")
|
||
|
.addClass("slick-header-menubutton")
|
||
|
.data("column", column)
|
||
|
.data("menu", menu);
|
||
|
|
||
|
if (options.buttonCssClass) {
|
||
|
$el.addClass(options.buttonCssClass);
|
||
|
}
|
||
|
|
||
|
if (options.buttonImage) {
|
||
|
$el.css("background-image", "url(" + options.buttonImage + ")");
|
||
|
}
|
||
|
|
||
|
if (menu.tooltip) {
|
||
|
$el.attr("title", menu.tooltip);
|
||
|
}
|
||
|
|
||
|
$el
|
||
|
.bind("click", showMenu)
|
||
|
.appendTo(args.node);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function handleBeforeHeaderCellDestroy(e, args) {
|
||
|
var column = args.column;
|
||
|
|
||
|
if (column.header && column.header.menu) {
|
||
|
$(args.node).find(".slick-header-menubutton").remove();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function showMenu(e) {
|
||
|
var $menuButton = $(this);
|
||
|
var menu = $menuButton.data("menu");
|
||
|
var columnDef = $menuButton.data("column");
|
||
|
|
||
|
// Let the user modify the menu or cancel altogether,
|
||
|
// or provide alternative menu implementation.
|
||
|
if (_self.onBeforeMenuShow.notify({
|
||
|
"grid": _grid,
|
||
|
"column": columnDef,
|
||
|
"menu": menu
|
||
|
}, e, _self) == false) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!$menu) {
|
||
|
$menu = $("<div class='slick-header-menu'></div>")
|
||
|
.appendTo(_grid.getContainerNode());
|
||
|
}
|
||
|
$menu.empty();
|
||
|
|
||
|
|
||
|
// Construct the menu items.
|
||
|
for (var i = 0; i < menu.items.length; i++) {
|
||
|
var item = menu.items[i];
|
||
|
|
||
|
var $li = $("<div class='slick-header-menuitem'></div>")
|
||
|
.data("command", item.command || '')
|
||
|
.data("column", columnDef)
|
||
|
.data("item", item)
|
||
|
.bind("click", handleMenuItemClick)
|
||
|
.appendTo($menu);
|
||
|
|
||
|
if (item.disabled) {
|
||
|
$li.addClass("slick-header-menuitem-disabled");
|
||
|
}
|
||
|
|
||
|
if (item.tooltip) {
|
||
|
$li.attr("title", item.tooltip);
|
||
|
}
|
||
|
|
||
|
var $icon = $("<div class='slick-header-menuicon'></div>")
|
||
|
.appendTo($li);
|
||
|
|
||
|
if (item.iconCssClass) {
|
||
|
$icon.addClass(item.iconCssClass);
|
||
|
}
|
||
|
|
||
|
if (item.iconImage) {
|
||
|
$icon.css("background-image", "url(" + item.iconImage + ")");
|
||
|
}
|
||
|
|
||
|
$("<span class='slick-header-menucontent'></span>")
|
||
|
.text(item.title)
|
||
|
.appendTo($li);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Position the menu.
|
||
|
$menu
|
||
|
.offset({ top: $(this).offset().top + $(this).height(), left: $(this).offset().left });
|
||
|
|
||
|
|
||
|
// Mark the header as active to keep the highlighting.
|
||
|
$activeHeaderColumn = $menuButton.closest(".slick-header-column");
|
||
|
$activeHeaderColumn
|
||
|
.addClass("slick-header-column-active");
|
||
|
|
||
|
// Stop propagation so that it doesn't register as a header click event.
|
||
|
e.preventDefault();
|
||
|
e.stopPropagation();
|
||
|
}
|
||
|
|
||
|
|
||
|
function handleMenuItemClick(e) {
|
||
|
var command = $(this).data("command");
|
||
|
var columnDef = $(this).data("column");
|
||
|
var item = $(this).data("item");
|
||
|
|
||
|
if (item.disabled) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
hideMenu();
|
||
|
|
||
|
if (command != null && command != '') {
|
||
|
_self.onCommand.notify({
|
||
|
"grid": _grid,
|
||
|
"column": columnDef,
|
||
|
"command": command,
|
||
|
"item": item
|
||
|
}, e, _self);
|
||
|
}
|
||
|
|
||
|
// Stop propagation so that it doesn't register as a header click event.
|
||
|
e.preventDefault();
|
||
|
e.stopPropagation();
|
||
|
}
|
||
|
|
||
|
$.extend(this, {
|
||
|
"init": init,
|
||
|
"destroy": destroy,
|
||
|
|
||
|
"onBeforeMenuShow": new Slick.Event(),
|
||
|
"onCommand": new Slick.Event()
|
||
|
});
|
||
|
}
|
||
|
})(jQuery);
|