|
360 | 360 | };
|
361 | 361 | })(jQuery);
|
362 | 362 |
|
| 363 | +/** |
| 364 | + * Creates and manages a context menu UI component with support for nested submenus. |
| 365 | + * The menu supports keyboard navigation, touch events, and intelligent submenu positioning. |
| 366 | + * |
| 367 | + * @param {Object} options - Configuration options for the context menu |
| 368 | + * @param {Array<Object|string>} options.items - Array of menu items or dividers ('-') |
| 369 | + * @param {string} options.items[].html - HTML content for the menu item |
| 370 | + * @param {string} [options.items[].html_active] - HTML content when item is active/hovered |
| 371 | + * @param {string} [options.items[].icon] - Icon for the menu item |
| 372 | + * @param {string} [options.items[].icon_active] - Icon when item is active/hovered |
| 373 | + * @param {boolean} [options.items[].disabled] - Whether the item is disabled |
| 374 | + * @param {boolean} [options.items[].checked] - Whether to show a checkmark |
| 375 | + * @param {Function} [options.items[].onClick] - Click handler with event parameter |
| 376 | + * @param {Function} [options.items[].action] - Alternative click handler without event parameter |
| 377 | + * @param {Array<Object>} [options.items[].items] - Nested submenu items |
| 378 | + * @param {string} [options.id] - Unique identifier for the menu |
| 379 | + * @param {Object} [options.position] - Custom positioning for the menu |
| 380 | + * @param {number} options.position.top - Top position in pixels |
| 381 | + * @param {number} options.position.left - Left position in pixels |
| 382 | + * @param {boolean|number} [options.delay] - Animation delay for menu appearance |
| 383 | + * true/1/undefined = 50ms fade |
| 384 | + * false = no animation |
| 385 | + * number = custom fade duration |
| 386 | + * @param {Object} [options.css] - Additional CSS properties to apply to menu |
| 387 | + * @param {HTMLElement} [options.parent_element] - Parent element for the menu |
| 388 | + * @param {string} [options.parent_id] - ID of parent menu for nested menus |
| 389 | + * @param {boolean} [options.is_submenu] - Whether this is a nested submenu, default: false |
| 390 | + * @param {Function} [options.onClose] - Callback function when menu closes |
| 391 | + * |
| 392 | + * @example |
| 393 | + * // Basic usage with simple items |
| 394 | + * UIContextMenu({ |
| 395 | + * items: [ |
| 396 | + * { html: 'Copy', icon: '📋', onClick: () => console.log('Copy clicked') }, |
| 397 | + * '-', // divider |
| 398 | + * { html: 'Paste', icon: '📌', disabled: true } |
| 399 | + * ] |
| 400 | + * }); |
| 401 | + * |
| 402 | + * @example |
| 403 | + * // Usage with nested submenus and custom positioning |
| 404 | + * UIContextMenu({ |
| 405 | + * position: { top: 100, left: 200 }, |
| 406 | + * items: [ |
| 407 | + * { |
| 408 | + * html: 'File', |
| 409 | + * items: [ |
| 410 | + * { html: 'New', icon: '📄' }, |
| 411 | + * { html: 'Open', icon: '📂' } |
| 412 | + * ] |
| 413 | + * }, |
| 414 | + * { |
| 415 | + * html: 'Edit', |
| 416 | + * items: [ |
| 417 | + * { html: 'Cut', icon: '✂️' }, |
| 418 | + * { html: 'Copy', icon: '📋' } |
| 419 | + * ] |
| 420 | + * } |
| 421 | + * ] |
| 422 | + * }); |
| 423 | + * |
| 424 | + * @example |
| 425 | + * // Usage with menu controller |
| 426 | + * const menu = UIContextMenu({ |
| 427 | + * items: [{ html: 'Close', onClick: () => menu.cancel() }] |
| 428 | + * }); |
| 429 | + * menu.onClose = () => console.log('Menu closed'); |
| 430 | + * |
| 431 | + * @fires ctxmenu-will-open - Dispatched on window before menu opens |
| 432 | + * @listens mousemove - Tracks mouse position for submenu positioning |
| 433 | + * @listens click - Handles menu item selection |
| 434 | + * @listens contextmenu - Prevents default context menu |
| 435 | + * @listens mouseenter - Handles submenu activation |
| 436 | + * @listens mouseleave - Handles menu item deactivation |
| 437 | + * |
| 438 | + * @requires jQuery |
| 439 | + * @requires jQuery-menu-aim |
| 440 | + */ |
| 441 | + |
363 | 442 | function UIContextMenu(options){
|
364 | 443 | $('.window-active .window-app-iframe').css('pointer-events', 'none');
|
365 | 444 |
|
@@ -654,17 +733,16 @@ function UIContextMenu(options){
|
654 | 733 | if(options.parent_element){
|
655 | 734 | $(options.parent_element).parent().removeClass('children-have-open-contextmenu');
|
656 | 735 |
|
657 |
| - // if the parent element is not a window, make it scrollable again |
658 |
| - if (!$(options.parent_element).hasClass('window-body')) { |
659 |
| - $(options.parent_element).css('overflow', 'scroll'); |
660 |
| - } |
| 736 | + // make parent scrollable again |
| 737 | + $(options.parent_element).css('overflow', 'scroll'); |
661 | 738 |
|
662 | 739 | $(options.parent_element).removeClass('has-open-contextmenu');
|
663 | 740 | if($(options.parent_element).hasClass('taskbar-item')){
|
664 | 741 | window.make_taskbar_sortable()
|
665 | 742 | }
|
666 | 743 | }
|
667 | 744 | })
|
| 745 | + |
668 | 746 | $(contextMenu).on("contextmenu", function (e) {
|
669 | 747 | e.preventDefault();
|
670 | 748 | e.stopPropagation();
|
|
0 commit comments