context.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Context.js
  3. * Copyright Jacob Kelley
  4. * MIT License
  5. */
  6. var context = context || (function () {
  7. var options = {
  8. fadeSpeed: 100,
  9. filter: function ($obj) {
  10. // Modify $obj, Do not return
  11. },
  12. above: 'auto',
  13. preventDoubleContext: true,
  14. compress: false
  15. };
  16. function initialize(opts) {
  17. options = $.extend({}, options, opts);
  18. $(document).on('click', 'html', function () {
  19. $('.dropdown-context').fadeOut(options.fadeSpeed, function(){
  20. $('.dropdown-context').css({display:''}).find('.drop-left').removeClass('drop-left');
  21. });
  22. });
  23. if(options.preventDoubleContext){
  24. $(document).on('contextmenu', '.dropdown-context', function (e) {
  25. e.preventDefault();
  26. });
  27. }
  28. $(document).on('mouseenter', '.dropdown-submenu', function(){
  29. var $sub = $(this).find('.dropdown-context-sub:first'),
  30. subWidth = $sub.width(),
  31. subLeft = $sub.offset().left,
  32. collision = (subWidth+subLeft) > window.innerWidth;
  33. if(collision){
  34. $sub.addClass('drop-left');
  35. }
  36. });
  37. }
  38. function updateOptions(opts){
  39. options = $.extend({}, options, opts);
  40. }
  41. function buildMenu(data, id, subMenu) {
  42. var subClass = (subMenu) ? ' dropdown-context-sub' : '',
  43. compressed = options.compress ? ' compressed-context' : '',
  44. $menu = $('<ul class="dropdown-menu dropdown-context' + subClass + compressed+'" id="dropdown-' + id + '"></ul>');
  45. var i = 0, linkTarget = '';
  46. for(i; i<data.length; i++) {
  47. if (typeof data[i].divider !== 'undefined') {
  48. $menu.append('<li class="divider"></li>');
  49. } else if (typeof data[i].header !== 'undefined') {
  50. $menu.append('<li class="nav-header">' + data[i].header + '</li>');
  51. } else {
  52. if (typeof data[i].href == 'undefined') {
  53. data[i].href = '#';
  54. }
  55. if (typeof data[i].target !== 'undefined') {
  56. linkTarget = ' target="'+data[i].target+'"';
  57. }
  58. if (typeof data[i].subMenu !== 'undefined') {
  59. $sub = ('<li class="dropdown-submenu"><a tabindex="-1" href="' + data[i].href + '">' + data[i].text + '</a></li>');
  60. } else {
  61. $sub = $('<li><a tabindex="-1" href="' + data[i].href + '"'+linkTarget+'>' + data[i].text + '</a></li>');
  62. }
  63. if (typeof data[i].action !== 'undefined') {
  64. var actiond = new Date(),
  65. actionID = 'event-' + actiond.getTime() * Math.floor(Math.random()*100000),
  66. eventAction = data[i].action;
  67. $sub.find('a').attr('id', actionID);
  68. $('#' + actionID).addClass('context-event');
  69. $(document).on('click', '#' + actionID, eventAction);
  70. }
  71. $menu.append($sub);
  72. if (typeof data[i].subMenu != 'undefined') {
  73. var subMenuData = buildMenu(data[i].subMenu, id, true);
  74. $menu.find('li:last').append(subMenuData);
  75. }
  76. }
  77. if (typeof options.filter == 'function') {
  78. options.filter($menu.find('li:last'));
  79. }
  80. }
  81. return $menu;
  82. }
  83. function addContext(selector, data) {
  84. var d = new Date(),
  85. id = d.getTime(),
  86. $menu = buildMenu(data, id);
  87. $('body').append($menu);
  88. $(document).on('contextmenu', selector, function (e) {
  89. e.preventDefault();
  90. e.stopPropagation();
  91. $('.dropdown-context:not(.dropdown-context-sub)').hide();
  92. $dd = $('#dropdown-' + id);
  93. if (typeof options.above == 'boolean' && options.above) {
  94. // console.log("2:",e)
  95. $dd.addClass('dropdown-context-up').css({
  96. top: e.pageY - 20 - $('#dropdown-' + id).height(),
  97. left: e.pageX - 13
  98. }).fadeIn(options.fadeSpeed);
  99. } else if (typeof options.above == 'string' && options.above == 'auto') {
  100. // console.log("3:",e)
  101. $dd.removeClass('dropdown-context-up');
  102. var autoH = $dd.height() + 12;
  103. // console.log("3:",autoH," e.pageY ",e.pageY," e.pageY + autoH:",(e.pageY + autoH)," html').height ",$('html').height())
  104. if (autoH < e.pageY) {
  105. $dd.addClass('dropdown-context-up').css({
  106. top: e.pageY - 20 - autoH,
  107. left: e.pageX - 13
  108. }).fadeIn(options.fadeSpeed);
  109. } else {
  110. // console.log("4:",e)
  111. $dd.css({
  112. top: e.pageY + 10,
  113. left: e.pageX - 13
  114. }).fadeIn(options.fadeSpeed);
  115. }
  116. }
  117. });
  118. }
  119. function destroyContext(selector) {
  120. $(document).off('contextmenu', selector).off('click', '.context-event');
  121. }
  122. return {
  123. init: initialize,
  124. settings: updateOptions,
  125. attach: addContext,
  126. destroy: destroyContext
  127. };
  128. })();