jquery.contextMenu.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // jQuery Context Menu Plugin
  2. //
  3. // Version 1.01
  4. //
  5. // Cory S.N. LaViska
  6. // A Beautiful Site (http://abeautifulsite.net/)
  7. // Modified by Alexis Deveria
  8. //
  9. // More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
  10. //
  11. // Terms of Use
  12. //
  13. // This plugin is dual-licensed under the GNU General Public License
  14. // and the MIT License and is copyright A Beautiful Site, LLC.
  15. //
  16. if(jQuery)( function() {
  17. var win = $(window);
  18. var doc = $(document);
  19. $.extend($.fn, {
  20. contextMenu: function(o, callback) {
  21. // Defaults
  22. if( o.menu == undefined ) return false;
  23. if( o.inSpeed == undefined ) o.inSpeed = 150;
  24. if( o.outSpeed == undefined ) o.outSpeed = 75;
  25. // 0 needs to be -1 for expected results (no fade)
  26. if( o.inSpeed == 0 ) o.inSpeed = -1;
  27. if( o.outSpeed == 0 ) o.outSpeed = -1;
  28. // Loop each context menu
  29. $(this).each( function() {
  30. var el = $(this);
  31. var offset = $(el).offset();
  32. var menu = $('#' + o.menu);
  33. // Add contextMenu class
  34. menu.addClass('contextMenu');
  35. // Simulate a true right click
  36. $(this).bind( "mousedown", function(e) {
  37. var evt = e;
  38. $(this).mouseup( function(e) {
  39. var srcElement = $(this);
  40. srcElement.unbind('mouseup');
  41. if( evt.button === 2 || o.allowLeft || (evt.ctrlKey && svgedit.browser.isMac()) ) {
  42. e.stopPropagation();
  43. // Hide context menus that may be showing
  44. $(".contextMenu").hide();
  45. // Get this context menu
  46. if( el.hasClass('disabled') ) return false;
  47. // Detect mouse position
  48. var d = {}, x = e.pageX, y = e.pageY;
  49. var x_off = win.width() - menu.width(),
  50. y_off = win.height() - menu.height();
  51. if(x > x_off - 15) x = x_off-15;
  52. if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF
  53. // Show the menu
  54. doc.unbind('click');
  55. menu.css({ top: y, left: x }).fadeIn(o.inSpeed);
  56. // Hover events
  57. menu.find('A').mouseover( function() {
  58. menu.find('LI.hover').removeClass('hover');
  59. $(this).parent().addClass('hover');
  60. }).mouseout( function() {
  61. menu.find('LI.hover').removeClass('hover');
  62. });
  63. // Keyboard
  64. doc.keypress( function(e) {
  65. switch( e.keyCode ) {
  66. case 38: // up
  67. if( !menu.find('LI.hover').length ) {
  68. menu.find('LI:last').addClass('hover');
  69. } else {
  70. menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
  71. if( !menu.find('LI.hover').length ) menu.find('LI:last').addClass('hover');
  72. }
  73. break;
  74. case 40: // down
  75. if( menu.find('LI.hover').length == 0 ) {
  76. menu.find('LI:first').addClass('hover');
  77. } else {
  78. menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
  79. if( !menu.find('LI.hover').length ) menu.find('LI:first').addClass('hover');
  80. }
  81. break;
  82. case 13: // enter
  83. menu.find('LI.hover A').trigger('click');
  84. break;
  85. case 27: // esc
  86. doc.trigger('click');
  87. break
  88. }
  89. });
  90. // When items are selected
  91. menu.find('A').unbind('mouseup');
  92. menu.find('LI:not(.disabled) A').mouseup( function() {
  93. doc.unbind('click').unbind('keypress');
  94. $(".contextMenu").hide();
  95. // Callback
  96. if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
  97. return false;
  98. });
  99. // Hide bindings
  100. setTimeout( function() { // Delay for Mozilla
  101. doc.click( function() {
  102. doc.unbind('click').unbind('keypress');
  103. menu.fadeOut(o.outSpeed);
  104. return false;
  105. });
  106. }, 0);
  107. }
  108. });
  109. });
  110. // Disable text selection
  111. if( $.browser.mozilla ) {
  112. $('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
  113. } else if( $.browser.msie ) {
  114. $('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
  115. } else {
  116. $('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
  117. }
  118. // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
  119. $(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });
  120. });
  121. return $(this);
  122. },
  123. // Disable context menu items on the fly
  124. disableContextMenuItems: function(o) {
  125. if( o == undefined ) {
  126. // Disable all
  127. $(this).find('LI').addClass('disabled');
  128. return( $(this) );
  129. }
  130. $(this).each( function() {
  131. if( o != undefined ) {
  132. var d = o.split(',');
  133. for( var i = 0; i < d.length; i++ ) {
  134. $(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
  135. }
  136. }
  137. });
  138. return( $(this) );
  139. },
  140. // Enable context menu items on the fly
  141. enableContextMenuItems: function(o) {
  142. if( o == undefined ) {
  143. // Enable all
  144. $(this).find('LI.disabled').removeClass('disabled');
  145. return( $(this) );
  146. }
  147. $(this).each( function() {
  148. if( o != undefined ) {
  149. var d = o.split(',');
  150. for( var i = 0; i < d.length; i++ ) {
  151. $(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
  152. }
  153. }
  154. });
  155. return( $(this) );
  156. },
  157. // Disable context menu(s)
  158. disableContextMenu: function() {
  159. $(this).each( function() {
  160. $(this).addClass('disabled');
  161. });
  162. return( $(this) );
  163. },
  164. // Enable context menu(s)
  165. enableContextMenu: function() {
  166. $(this).each( function() {
  167. $(this).removeClass('disabled');
  168. });
  169. return( $(this) );
  170. },
  171. // Destroy context menu(s)
  172. destroyContextMenu: function() {
  173. // Destroy specified context menus
  174. $(this).each( function() {
  175. // Disable action
  176. $(this).unbind('mousedown').unbind('mouseup');
  177. });
  178. return( $(this) );
  179. }
  180. });
  181. })(jQuery);