bootstrap-table-contextmenu.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /**
  2. * @author David Graham <prograhammer@gmail.com>
  3. * @version v1.1.4
  4. * @link https://github.com/prograhammer/bootstrap-table-contextmenu
  5. */
  6. !function($) {
  7. 'use strict';
  8. $.extend($.fn.bootstrapTable.defaults, {
  9. // Option defaults
  10. contextMenu: undefined,
  11. contextMenuTrigger: 'right',
  12. contextMenuAutoClickRow: true,
  13. contextMenuButton: undefined,
  14. beforeContextMenuRow: function (e, row, buttonElement) {
  15. // return false here to prevent menu showing
  16. },
  17. // Event default handlers
  18. onContextMenuItem: function (row, $element) {
  19. return false;
  20. },
  21. onContextMenuRow: function (row, $element) {
  22. return false;
  23. }
  24. });
  25. // Methods
  26. $.fn.bootstrapTable.methods.push('showContextMenu');
  27. // Events
  28. $.extend($.fn.bootstrapTable.Constructor.EVENTS, {
  29. 'contextmenu-item.bs.table': 'onContextMenuItem',
  30. 'contextmenu-row.bs.table': 'onContextMenuRow'
  31. });
  32. var BootstrapTable = $.fn.bootstrapTable.Constructor,
  33. _initBody = BootstrapTable.prototype.initBody;
  34. BootstrapTable.prototype.initBody = function () {
  35. // Init Body
  36. _initBody.apply(this, Array.prototype.slice.apply(arguments));
  37. // Init Context menu
  38. if (this.options.contextMenu || this.options.contextMenuButton || this.options.beforeContextMenuRow) {
  39. this.initContextMenu();
  40. }
  41. };
  42. // Init context menu
  43. BootstrapTable.prototype.initContextMenu = function () {
  44. var that = this;
  45. // Context menu on Right-click
  46. if (that.options.contextMenuTrigger == 'right' || that.options.contextMenuTrigger == 'both') {
  47. that.$body.find('> tr[data-index]').off('contextmenu.contextmenu').on('contextmenu.contextmenu', function (e) {
  48. var rowData = that.data[$(this).data('index')],
  49. beforeShow = that.options.beforeContextMenuRow.apply(this, [e, rowData, null]);
  50. if(beforeShow !== false){
  51. that.showContextMenu({event: e});
  52. }
  53. return false;
  54. });
  55. }
  56. // Context menu on Left-click
  57. if (that.options.contextMenuTrigger == 'left' || that.options.contextMenuTrigger == 'both') {
  58. that.$body.find('> tr[data-index]').off('click.contextmenu').on('click.contextmenu', function (e) {
  59. var rowData = that.data[$(this).data('index')],
  60. beforeShow = that.options.beforeContextMenuRow.apply(this, [e, rowData, null]);
  61. if(beforeShow !== false){
  62. that.showContextMenu({event: e});
  63. }
  64. return false;
  65. });
  66. }
  67. // Context menu on mobile clikc
  68. if (that.options.contextMenuTriggerMobile == 'click') {
  69. var timeOutEvent=0;
  70. that.$body.find('> tr[data-index]').on({
  71. touchstart: function(e){
  72. e.clientX = e.originalEvent.changedTouches[0].clientX;
  73. e.clientY = e.originalEvent.changedTouches[0].clientY;
  74. timeOutEvent = 0;
  75. var rowData = that.data[$(this).data('index')],
  76. beforeShow = that.options.beforeContextMenuRow.apply(this, [e, rowData, null]);
  77. if(beforeShow !== false){
  78. that.showContextMenu({event: e});
  79. }
  80. },
  81. touchmove: function(e){
  82. $(that.options.contextMenu).hide();
  83. },
  84. touchend: function(e){
  85. return true;
  86. }
  87. })
  88. }
  89. // Context menu on mobile, touch
  90. if (that.options.contextMenuTriggerMobile == 'press') {
  91. var timeOutEvent=0;
  92. that.$body.find('> tr[data-index]').on({
  93. touchstart: function(e){
  94. timeOutEvent = setTimeout(function(){
  95. e.clientX = e.originalEvent.changedTouches[0].clientX;
  96. e.clientY = e.originalEvent.changedTouches[0].clientY;
  97. timeOutEvent = 0;
  98. var rowData = that.data[$(this).data('index')],
  99. beforeShow = that.options.beforeContextMenuRow.apply(this, [e, rowData, null]);
  100. if(beforeShow !== false){
  101. that.showContextMenu({event: e});
  102. }
  103. },500);
  104. },
  105. touchmove: function(e){
  106. clearTimeout(timeOutEvent);
  107. timeOutEvent = 0;
  108. $(that.options.contextMenu).hide();
  109. },
  110. touchend: function(e){
  111. clearTimeout(timeOutEvent);
  112. return true;
  113. }
  114. })
  115. }
  116. // Context menu on Button-click
  117. if (typeof that.options.contextMenuButton === 'string') {
  118. that.$body.find('> tr[data-index]').find(that.options.contextMenuButton).off('click.contextmenu').on('click.contextmenu', function (e) {
  119. var rowData = that.data[$(this).closest('tr[data-index]').data('index')],
  120. beforeShow = that.options.beforeContextMenuRow.apply(this, [e, rowData, this]);
  121. if(beforeShow !== false){
  122. that.showContextMenu({event: e, buttonElement: this});
  123. }
  124. return false;
  125. });
  126. }
  127. };
  128. // Show context menu
  129. BootstrapTable.prototype.showContextMenu = function (params) {
  130. if(!params || !params.event){ return false; }
  131. if(params && !params.contextMenu && typeof this.options.contextMenu !== 'string'){ return false; }
  132. var that = this,
  133. $menu, screenPosX, screenPosY,
  134. $tr = $(params.event.target).closest('tr[data-index]'),
  135. item = that.data[$tr.data('index')];
  136. if(params && !params.contextMenu && typeof this.options.contextMenu === 'string'){
  137. screenPosX = params.event.clientX;
  138. screenPosY = params.event.clientY;
  139. $menu = $(this.options.contextMenu);
  140. }
  141. if(params && params.contextMenu){
  142. screenPosX = params.event.clientX;
  143. screenPosY = params.event.clientY;
  144. $menu = $(params.contextMenu);
  145. }
  146. if (params && params.buttonElement) {
  147. screenPosX = params.buttonElement.getBoundingClientRect().left;
  148. screenPosY = params.buttonElement.getBoundingClientRect().bottom;
  149. }
  150. function getMenuPosition($menu, screenPos, direction, scrollDir) {
  151. var win = $(window)[direction](),
  152. scroll = $(window)[scrollDir](),
  153. menu = $menu[direction](),
  154. position = screenPos + scroll;
  155. if (screenPos + menu > win && menu < screenPos)
  156. position -= menu;
  157. return position;
  158. }
  159. // Bind click on menu item
  160. $menu.find('li').off('click.contextmenu').on('click.contextmenu', function (e) {
  161. var rowData = that.data[$menu.data('index')];
  162. that.trigger('contextmenu-item', rowData, $(this));
  163. });
  164. // Click anywhere to hide the menu
  165. $(document).triggerHandler('click.contextmenu');
  166. $(document).off('click.contextmenu').on('click.contextmenu', function (e) {
  167. // Fixes problem on Mac OSX
  168. if(that.pageX != e.pageX || that.pageY != e.pageY){
  169. $menu.hide();
  170. $(document).off('click.contextmenu');
  171. }
  172. });
  173. that.pageX = params.event.pageX;
  174. that.pageY = params.event.pageY;
  175. // Show the menu
  176. $menu.data('index', $tr.data('index'))
  177. .appendTo($('body'))
  178. .css({
  179. position: "absolute",
  180. left: getMenuPosition($menu, screenPosX, 'width', 'scrollLeft'),
  181. top: getMenuPosition($menu, screenPosY, 'height', 'scrollTop'),
  182. zIndex: 1100
  183. })
  184. .show();
  185. // Trigger events
  186. that.trigger('contextmenu-row', item, $tr);
  187. if(that.options.contextMenuAutoClickRow && that.options.contextMenuTrigger == 'right') {
  188. that.trigger('click-row', item, $tr);
  189. }
  190. };
  191. }(jQuery);