You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

272 rivejä
7.3 KiB

  1. (function ($) {
  2. // register namespace
  3. $.extend(true, window, {
  4. "Slick": {
  5. "Plugins": {
  6. "HeaderMenu": HeaderMenu
  7. }
  8. }
  9. });
  10. /***
  11. * A plugin to add drop-down menus to column headers.
  12. *
  13. * USAGE:
  14. *
  15. * Add the plugin .js & .css files and register it with the grid.
  16. *
  17. * To specify a menu in a column header, extend the column definition like so:
  18. *
  19. * var columns = [
  20. * {
  21. * id: 'myColumn',
  22. * name: 'My column',
  23. *
  24. * // This is the relevant part
  25. * header: {
  26. * menu: {
  27. * items: [
  28. * {
  29. * // menu item options
  30. * },
  31. * {
  32. * // menu item options
  33. * }
  34. * ]
  35. * }
  36. * }
  37. * }
  38. * ];
  39. *
  40. *
  41. * Available menu options:
  42. * tooltip: Menu button tooltip.
  43. *
  44. *
  45. * Available menu item options:
  46. * title: Menu item text.
  47. * disabled: Whether the item is disabled.
  48. * tooltip: Item tooltip.
  49. * command: A command identifier to be passed to the onCommand event handlers.
  50. * iconCssClass: A CSS class to be added to the menu item icon.
  51. * iconImage: A url to the icon image.
  52. *
  53. *
  54. * The plugin exposes the following events:
  55. * onBeforeMenuShow: Fired before the menu is shown. You can customize the menu or dismiss it by returning false.
  56. * Event args:
  57. * grid: Reference to the grid.
  58. * column: Column definition.
  59. * menu: Menu options. Note that you can change the menu items here.
  60. *
  61. * onCommand: Fired on menu item click for buttons with 'command' specified.
  62. * Event args:
  63. * grid: Reference to the grid.
  64. * column: Column definition.
  65. * command: Button command identified.
  66. * button: Button options. Note that you can change the button options in your
  67. * event handler, and the column header will be automatically updated to
  68. * reflect them. This is useful if you want to implement something like a
  69. * toggle button.
  70. *
  71. *
  72. * @param options {Object} Options:
  73. * buttonCssClass: an extra CSS class to add to the menu button
  74. * buttonImage: a url to the menu button image (default '../images/down.gif')
  75. * @class Slick.Plugins.HeaderButtons
  76. * @constructor
  77. */
  78. function HeaderMenu(options) {
  79. var _grid;
  80. var _self = this;
  81. var _handler = new Slick.EventHandler();
  82. var _defaults = {
  83. buttonCssClass: null,
  84. buttonImage: "../images/down.gif"
  85. };
  86. var $menu;
  87. var $activeHeaderColumn;
  88. function init(grid) {
  89. options = $.extend(true, {}, _defaults, options);
  90. _grid = grid;
  91. _handler
  92. .subscribe(_grid.onHeaderCellRendered, handleHeaderCellRendered)
  93. .subscribe(_grid.onBeforeHeaderCellDestroy, handleBeforeHeaderCellDestroy);
  94. // Force the grid to re-render the header now that the events are hooked up.
  95. _grid.setColumns(_grid.getColumns());
  96. // Hide the menu on outside click.
  97. $(document.body).bind("mousedown", handleBodyMouseDown);
  98. }
  99. function destroy() {
  100. _handler.unsubscribeAll();
  101. $(document.body).unbind("mousedown", handleBodyMouseDown);
  102. }
  103. function handleBodyMouseDown(e) {
  104. if ($menu && $menu[0] != e.target && !$.contains($menu[0], e.target)) {
  105. hideMenu();
  106. }
  107. }
  108. function hideMenu() {
  109. if ($menu) {
  110. $menu.remove();
  111. $menu = null;
  112. $activeHeaderColumn
  113. .removeClass("slick-header-column-active");
  114. }
  115. }
  116. function handleHeaderCellRendered(e, args) {
  117. var column = args.column;
  118. var menu = column.header && column.header.menu;
  119. if (menu) {
  120. var $el = $("<div></div>")
  121. .addClass("slick-header-menubutton")
  122. .data("column", column)
  123. .data("menu", menu);
  124. if (options.buttonCssClass) {
  125. $el.addClass(options.buttonCssClass);
  126. }
  127. if (options.buttonImage) {
  128. $el.css("background-image", "url(" + options.buttonImage + ")");
  129. }
  130. if (menu.tooltip) {
  131. $el.attr("title", menu.tooltip);
  132. }
  133. $el
  134. .bind("click", showMenu)
  135. .appendTo(args.node);
  136. }
  137. }
  138. function handleBeforeHeaderCellDestroy(e, args) {
  139. var column = args.column;
  140. if (column.header && column.header.menu) {
  141. $(args.node).find(".slick-header-menubutton").remove();
  142. }
  143. }
  144. function showMenu(e) {
  145. var $menuButton = $(this);
  146. var menu = $menuButton.data("menu");
  147. var columnDef = $menuButton.data("column");
  148. // Let the user modify the menu or cancel altogether,
  149. // or provide alternative menu implementation.
  150. if (_self.onBeforeMenuShow.notify({
  151. "grid": _grid,
  152. "column": columnDef,
  153. "menu": menu
  154. }, e, _self) == false) {
  155. return;
  156. }
  157. if (!$menu) {
  158. $menu = $("<div class='slick-header-menu'></div>")
  159. .appendTo(document.body);
  160. }
  161. $menu.empty();
  162. // Construct the menu items.
  163. for (var i = 0; i < menu.items.length; i++) {
  164. var item = menu.items[i];
  165. var $li = $("<div class='slick-header-menuitem'></div>")
  166. .data("command", item.command || '')
  167. .data("column", columnDef)
  168. .data("item", item)
  169. .bind("click", handleMenuItemClick)
  170. .appendTo($menu);
  171. if (item.disabled) {
  172. $li.addClass("slick-header-menuitem-disabled");
  173. }
  174. if (item.tooltip) {
  175. $li.attr("title", item.tooltip);
  176. }
  177. var $icon = $("<div class='slick-header-menuicon'></div>")
  178. .appendTo($li);
  179. if (item.iconCssClass) {
  180. $icon.addClass(item.iconCssClass);
  181. }
  182. if (item.iconImage) {
  183. $icon.css("background-image", "url(" + item.iconImage + ")");
  184. }
  185. $("<span class='slick-header-menucontent'></span>")
  186. .text(item.title)
  187. .appendTo($li);
  188. }
  189. // Position the menu.
  190. $menu
  191. .css("top", $(this).offset().top + $(this).height())
  192. .css("left", $(this).offset().left);
  193. // Mark the header as active to keep the highlighting.
  194. $activeHeaderColumn = $menuButton.closest(".slick-header-column");
  195. $activeHeaderColumn
  196. .addClass("slick-header-column-active");
  197. }
  198. function handleMenuItemClick(e) {
  199. var command = $(this).data("command");
  200. var columnDef = $(this).data("column");
  201. var item = $(this).data("item");
  202. if (item.disabled) {
  203. return;
  204. }
  205. hideMenu();
  206. if (command != null && command != '') {
  207. _self.onCommand.notify({
  208. "grid": _grid,
  209. "column": columnDef,
  210. "command": command,
  211. "item": item
  212. }, e, _self);
  213. }
  214. // Stop propagation so that it doesn't register as a header click event.
  215. e.preventDefault();
  216. e.stopPropagation();
  217. }
  218. $.extend(this, {
  219. "init": init,
  220. "destroy": destroy,
  221. "onBeforeMenuShow": new Slick.Event(),
  222. "onCommand": new Slick.Event()
  223. });
  224. }
  225. })(jQuery);