From b41b217f81d054033476cbe7af1ed572f2a29772 Mon Sep 17 00:00:00 2001 From: Xaxis Date: Mon, 1 Oct 2018 08:20:47 -0700 Subject: [PATCH 1/6] Added package.json to make npm installable --- package.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..38eb3a5 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "jquery-menu-aim", + "version": "1.0.0", + "description": "NPM installable version of jquery-menu-aim.", + "main": "jquery.menu-aim.js", + "directories": { + "example": "example" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Xaxis/jQuery-menu-aim.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/Xaxis/jQuery-menu-aim/issues" + }, + "homepage": "https://github.com/Xaxis/jQuery-menu-aim#readme" +} From 4076b566a809a46b631741eaf5a501e2a5940c76 Mon Sep 17 00:00:00 2001 From: Xaxis Date: Mon, 1 Oct 2018 09:41:58 -0700 Subject: [PATCH 2/6] Added ability to override default delay time used when a user appears to be entering a sub menu --- .gitignore | 1 + README.md | 6 +++++- jquery.menu-aim.js | 10 +++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62c8935 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/README.md b/README.md index cb5292c..8ac2932 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,11 @@ the relevant row's HTML element as the execution context ('this'): // controls which direction is "forgiving" as the user moves their // cursor from the main menu into the submenu. Can be one of "right", // "left", "above", or "below". Defaults to "right". - submenuDirection: "right" + submenuDirection: "right", + + // The default number of ms to delay if a user appears to be entering + // a submenu. + delay: 300 }); menu-aim assumes that you are using a menu with submenus that expand diff --git a/jquery.menu-aim.js b/jquery.menu-aim.js index 0c32941..828855e 100644 --- a/jquery.menu-aim.js +++ b/jquery.menu-aim.js @@ -65,6 +65,10 @@ * // Direction the submenu opens relative to the main menu. Can be * // left, right, above, or below. Defaults to "right". * submenuDirection: "right" + * + * // The default number of ms to delay if a user appears to be entering + * // a submenu. Defaults to 300 ms. + * delay: 300 * }); * * https://github.com/kamens/jQuery-menu-aim @@ -91,6 +95,7 @@ submenuSelector: "*", submenuDirection: "right", tolerance: 75, // bigger = more forgivey when entering submenu + delay: 300, // ms delay when user appears to be entering submenu enter: $.noop, exit: $.noop, activate: $.noop, @@ -98,8 +103,7 @@ exitMenu: $.noop }, opts); - var MOUSE_LOCS_TRACKED = 3, // number of past mouse locations to track - DELAY = 300; // ms delay when user appears to be entering submenu + var MOUSE_LOCS_TRACKED = 3; // number of past mouse locations to track; /** * Keep track of the last few locations of the mouse. @@ -299,7 +303,7 @@ // currently activated submenu. Delay before activating a // new menu row, because user may be moving into submenu. lastDelayLoc = loc; - return DELAY; + return options.delay; } lastDelayLoc = null; From bf9c9121b2741765ef548a5c09483e65f9aba520 Mon Sep 17 00:00:00 2001 From: Xaxis Date: Mon, 1 Oct 2018 11:52:02 -0700 Subject: [PATCH 3/6] Added basic trajectory path feature - testing stage 1 --- example/example.html | 3 +- jquery.menu-aim.js | 90 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/example/example.html b/example/example.html index c81ede4..fff7ebc 100644 --- a/example/example.html +++ b/example/example.html @@ -203,7 +203,8 @@

jQuery-menu-aim example

// Hook up events to be fired on menu row activation. $menu.menuAim({ activate: activateSubmenu, - deactivate: deactivateSubmenu + deactivate: deactivateSubmenu, + drawTrajectory: true }); // jQuery-menu-aim: diff --git a/jquery.menu-aim.js b/jquery.menu-aim.js index 828855e..40e6fc9 100644 --- a/jquery.menu-aim.js +++ b/jquery.menu-aim.js @@ -96,6 +96,11 @@ submenuDirection: "right", tolerance: 75, // bigger = more forgivey when entering submenu delay: 300, // ms delay when user appears to be entering submenu + trajectory: false, + trajectoryLineColor: '#222222', + trajectoryLineWidth: '2', + trajectoryFillColor: '#FFCC00', + trajectoryOpacity: '0.5', enter: $.noop, exit: $.noop, activate: $.noop, @@ -103,7 +108,10 @@ exitMenu: $.noop }, opts); - var MOUSE_LOCS_TRACKED = 3; // number of past mouse locations to track; + var MOUSE_LOCS_TRACKED = 3, // number of past mouse locations to track; + TRAJECTORY_CANVAS = null, + $TRAJECTORY_CANVAS = null, + TRAJECTORY_CANVAS_CTX = null; /** * Keep track of the last few locations of the mouse. @@ -310,10 +318,90 @@ return 0; }; + /** + * Activate a menu row. + */ + var drawTrajectory = function(menu) { + + // Create canvas if not yet created + if (!TRAJECTORY_CANVAS) { + TRAJECTORY_CANVAS = document.createElement('canvas'); + TRAJECTORY_CANVAS_CTX = TRAJECTORY_CANVAS.getContext("2d"); + + // Initialize canvas + TRAJECTORY_CANVAS.id = "jquery-menu-aim-trajectory-canvas"; + TRAJECTORY_CANVAS.width = $menu.outerWidth(); + TRAJECTORY_CANVAS.height = $menu.outerHeight(); + TRAJECTORY_CANVAS.style.position = "absolute"; + TRAJECTORY_CANVAS.style.opacity = options.trajectoryOpacity; + + // Append canvas to body + $('body').append(TRAJECTORY_CANVAS); + + // Quick reference to trajectory canvas + $TRAJECTORY_CANVAS = $('#jquery-menu-aim-trajectory-canvas'); + + // Initially position of canvas + $TRAJECTORY_CANVAS.css({ + top: $menu.offset().top, + left: $menu.offset().left + }); + + // Move the canvas away if mouseenters it so that the menu still has context + $TRAJECTORY_CANVAS.mouseenter(function(e) { + $(this).css({ + 'z-index': -9999 + }); + }); + } + + // Reference new canvas dimensions/positions + var menu_offs = $menu.offset(); + var menu_w = $menu.outerWidth(); + var menu_h = $menu.outerHeight(); + var canvas_w = Math.abs((menu_offs.left + menu_w) - menu.pageX); + var canvas_h = menu_h; + + // Proceed while mouse is within menu + if (menu.pageX < (menu_offs.left + menu_w)) { + + // Set dimensions of canvas with mouse movement + TRAJECTORY_CANVAS.width = canvas_w; + TRAJECTORY_CANVAS.height = canvas_h; + + // Reposition canvas with mouse movement making sure canvas isn't directly + // below the cursor. + $TRAJECTORY_CANVAS.css({ + left: menu.pageX + 5, + 'z-index': 9999 + }); + } + + // Clear the previous trajectory path + TRAJECTORY_CANVAS_CTX.clearRect(0, 0, TRAJECTORY_CANVAS.width, TRAJECTORY_CANVAS.height); + + // Trajectory path + TRAJECTORY_CANVAS_CTX.beginPath(); + TRAJECTORY_CANVAS_CTX.moveTo(options.trajectoryLineWidth, menu.pageY - menu_offs.top); + TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width, 0); + TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width, TRAJECTORY_CANVAS.height); + TRAJECTORY_CANVAS_CTX.closePath(); + + // Draw the path outline + TRAJECTORY_CANVAS_CTX.lineWidth = options.trajectoryLineWidth; + TRAJECTORY_CANVAS_CTX.strokeStyle = options.trajectoryLineColor; + TRAJECTORY_CANVAS_CTX.stroke(); + + // Fill the trajectory triangle + TRAJECTORY_CANVAS_CTX.fillStyle = options.trajectoryFillColor; + TRAJECTORY_CANVAS_CTX.fill(); + }; + /** * Hook up initial menu events */ $menu + .mousemove(drawTrajectory) .mouseleave(mouseleaveMenu) .find(options.rowSelector) .mouseenter(mouseenterRow) From 6aeaa786e45621a7b1a61fcb281661904477f03f Mon Sep 17 00:00:00 2001 From: Xaxis Date: Mon, 1 Oct 2018 12:03:25 -0700 Subject: [PATCH 4/6] Accounted for trajectory distance from mouse in regard to its positioning --- example/example.html | 2 +- jquery.menu-aim.js | 137 ++++++++++++++++++++++--------------------- 2 files changed, 72 insertions(+), 67 deletions(-) diff --git a/example/example.html b/example/example.html index fff7ebc..f1b9b92 100644 --- a/example/example.html +++ b/example/example.html @@ -204,7 +204,7 @@

jQuery-menu-aim example

$menu.menuAim({ activate: activateSubmenu, deactivate: deactivateSubmenu, - drawTrajectory: true + trajectory: true }); // jQuery-menu-aim: diff --git a/jquery.menu-aim.js b/jquery.menu-aim.js index 40e6fc9..88518e2 100644 --- a/jquery.menu-aim.js +++ b/jquery.menu-aim.js @@ -323,78 +323,83 @@ */ var drawTrajectory = function(menu) { - // Create canvas if not yet created - if (!TRAJECTORY_CANVAS) { - TRAJECTORY_CANVAS = document.createElement('canvas'); - TRAJECTORY_CANVAS_CTX = TRAJECTORY_CANVAS.getContext("2d"); - - // Initialize canvas - TRAJECTORY_CANVAS.id = "jquery-menu-aim-trajectory-canvas"; - TRAJECTORY_CANVAS.width = $menu.outerWidth(); - TRAJECTORY_CANVAS.height = $menu.outerHeight(); - TRAJECTORY_CANVAS.style.position = "absolute"; - TRAJECTORY_CANVAS.style.opacity = options.trajectoryOpacity; - - // Append canvas to body - $('body').append(TRAJECTORY_CANVAS); - - // Quick reference to trajectory canvas - $TRAJECTORY_CANVAS = $('#jquery-menu-aim-trajectory-canvas'); - - // Initially position of canvas - $TRAJECTORY_CANVAS.css({ - top: $menu.offset().top, - left: $menu.offset().left - }); - - // Move the canvas away if mouseenters it so that the menu still has context - $TRAJECTORY_CANVAS.mouseenter(function(e) { - $(this).css({ - 'z-index': -9999 + // Proceed only when activated + if (options.trajectory) { + + // Create canvas if not yet created + if (!TRAJECTORY_CANVAS) { + TRAJECTORY_CANVAS = document.createElement('canvas'); + TRAJECTORY_CANVAS_CTX = TRAJECTORY_CANVAS.getContext("2d"); + + // Initialize canvas + TRAJECTORY_CANVAS.id = "jquery-menu-aim-trajectory-canvas"; + TRAJECTORY_CANVAS.width = $menu.outerWidth(); + TRAJECTORY_CANVAS.height = $menu.outerHeight(); + TRAJECTORY_CANVAS.style.position = "absolute"; + TRAJECTORY_CANVAS.style.opacity = options.trajectoryOpacity; + + // Append canvas to body + $('body').append(TRAJECTORY_CANVAS); + + // Quick reference to trajectory canvas + $TRAJECTORY_CANVAS = $('#jquery-menu-aim-trajectory-canvas'); + + // Initially position of canvas + $TRAJECTORY_CANVAS.css({ + top: $menu.offset().top, + left: $menu.offset().left }); - }); - } - // Reference new canvas dimensions/positions - var menu_offs = $menu.offset(); - var menu_w = $menu.outerWidth(); - var menu_h = $menu.outerHeight(); - var canvas_w = Math.abs((menu_offs.left + menu_w) - menu.pageX); - var canvas_h = menu_h; - - // Proceed while mouse is within menu - if (menu.pageX < (menu_offs.left + menu_w)) { - - // Set dimensions of canvas with mouse movement - TRAJECTORY_CANVAS.width = canvas_w; - TRAJECTORY_CANVAS.height = canvas_h; - - // Reposition canvas with mouse movement making sure canvas isn't directly - // below the cursor. - $TRAJECTORY_CANVAS.css({ - left: menu.pageX + 5, - 'z-index': 9999 - }); - } + // Move the canvas away if mouseenters it so that the menu still has context + $TRAJECTORY_CANVAS.mouseenter(function(e) { + $(this).css({ + 'z-index': -9999 + }); + }); + } - // Clear the previous trajectory path - TRAJECTORY_CANVAS_CTX.clearRect(0, 0, TRAJECTORY_CANVAS.width, TRAJECTORY_CANVAS.height); + // Reference new canvas dimensions/positions + var menu_offs = $menu.offset(); + var menu_w = $menu.outerWidth(); + var menu_h = $menu.outerHeight(); + var canvas_w = Math.abs((menu_offs.left + menu_w) - menu.pageX); + var canvas_h = menu_h; + var canvas_dist_from_mouse = 5; + + // Proceed while mouse is within menu + if (menu.pageX < (menu_offs.left + menu_w)) { + + // Set dimensions of canvas with mouse movement + TRAJECTORY_CANVAS.width = canvas_w - canvas_dist_from_mouse; + TRAJECTORY_CANVAS.height = canvas_h; + + // Reposition canvas with mouse movement making sure canvas isn't directly + // below the cursor. + $TRAJECTORY_CANVAS.css({ + left: menu.pageX + canvas_dist_from_mouse, + 'z-index': 9999 + }); + } - // Trajectory path - TRAJECTORY_CANVAS_CTX.beginPath(); - TRAJECTORY_CANVAS_CTX.moveTo(options.trajectoryLineWidth, menu.pageY - menu_offs.top); - TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width, 0); - TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width, TRAJECTORY_CANVAS.height); - TRAJECTORY_CANVAS_CTX.closePath(); + // Clear the previous trajectory path + TRAJECTORY_CANVAS_CTX.clearRect(0, 0, TRAJECTORY_CANVAS.width, TRAJECTORY_CANVAS.height); - // Draw the path outline - TRAJECTORY_CANVAS_CTX.lineWidth = options.trajectoryLineWidth; - TRAJECTORY_CANVAS_CTX.strokeStyle = options.trajectoryLineColor; - TRAJECTORY_CANVAS_CTX.stroke(); + // Trajectory path + TRAJECTORY_CANVAS_CTX.beginPath(); + TRAJECTORY_CANVAS_CTX.moveTo(options.trajectoryLineWidth, menu.pageY - menu_offs.top); + TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width, 0); + TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width, TRAJECTORY_CANVAS.height); + TRAJECTORY_CANVAS_CTX.closePath(); - // Fill the trajectory triangle - TRAJECTORY_CANVAS_CTX.fillStyle = options.trajectoryFillColor; - TRAJECTORY_CANVAS_CTX.fill(); + // Draw the path outline + TRAJECTORY_CANVAS_CTX.lineWidth = options.trajectoryLineWidth; + TRAJECTORY_CANVAS_CTX.strokeStyle = options.trajectoryLineColor; + TRAJECTORY_CANVAS_CTX.stroke(); + + // Fill the trajectory triangle + TRAJECTORY_CANVAS_CTX.fillStyle = options.trajectoryFillColor; + TRAJECTORY_CANVAS_CTX.fill(); + } }; /** From 99706bc0d6573d73ebf40d136814bce6e862515c Mon Sep 17 00:00:00 2001 From: Xaxis Date: Mon, 1 Oct 2018 12:09:43 -0700 Subject: [PATCH 5/6] Modified default behavior of trajectory to only show when menu is open --- jquery.menu-aim.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/jquery.menu-aim.js b/jquery.menu-aim.js index 88518e2..b5ab4aa 100644 --- a/jquery.menu-aim.js +++ b/jquery.menu-aim.js @@ -356,6 +356,13 @@ 'z-index': -9999 }); }); + + // Account for hiding of the trajectory + $menu.mouseleave(function(e) { + $TRAJECTORY_CANVAS.css({ + display: 'none' + }); + }); } // Reference new canvas dimensions/positions @@ -367,9 +374,10 @@ var canvas_dist_from_mouse = 5; // Proceed while mouse is within menu - if (menu.pageX < (menu_offs.left + menu_w)) { + if (menu.pageX < (menu_offs.left + menu_w - canvas_dist_from_mouse)) { // Set dimensions of canvas with mouse movement + TRAJECTORY_CANVAS.style.display = "block"; TRAJECTORY_CANVAS.width = canvas_w - canvas_dist_from_mouse; TRAJECTORY_CANVAS.height = canvas_h; @@ -379,6 +387,10 @@ left: menu.pageX + canvas_dist_from_mouse, 'z-index': 9999 }); + + // Hide the canvas otherwise + } else { + TRAJECTORY_CANVAS.style.display = "none"; } // Clear the previous trajectory path From 23e1db198657aa03eedc5649b00dad4dc4235c27 Mon Sep 17 00:00:00 2001 From: Xaxis Date: Mon, 1 Oct 2018 13:12:47 -0700 Subject: [PATCH 6/6] Modified trajectory globals so as to work across multiple menus --- example/example.html | 2 +- jquery.menu-aim.js | 308 ++++++++++++++++++++++--------------------- 2 files changed, 156 insertions(+), 154 deletions(-) diff --git a/example/example.html b/example/example.html index f1b9b92..ecd611e 100644 --- a/example/example.html +++ b/example/example.html @@ -204,7 +204,7 @@

jQuery-menu-aim example

$menu.menuAim({ activate: activateSubmenu, deactivate: deactivateSubmenu, - trajectory: true + trajectory: false }); // jQuery-menu-aim: diff --git a/jquery.menu-aim.js b/jquery.menu-aim.js index b5ab4aa..043e3b6 100644 --- a/jquery.menu-aim.js +++ b/jquery.menu-aim.js @@ -72,9 +72,14 @@ * }); * * https://github.com/kamens/jQuery-menu-aim -*/ + */ (function($) { + // ... + var TRAJECTORY_CANVAS = null, + $TRAJECTORY_CANVAS = null, + TRAJECTORY_CANVAS_CTX = null; + $.fn.menuAim = function(opts) { // Initialize menu-aim for all elements in jQuery collection this.each(function() { @@ -98,7 +103,7 @@ delay: 300, // ms delay when user appears to be entering submenu trajectory: false, trajectoryLineColor: '#222222', - trajectoryLineWidth: '2', + trajectoryLineWidth: 2, trajectoryFillColor: '#FFCC00', trajectoryOpacity: '0.5', enter: $.noop, @@ -108,40 +113,37 @@ exitMenu: $.noop }, opts); - var MOUSE_LOCS_TRACKED = 3, // number of past mouse locations to track; - TRAJECTORY_CANVAS = null, - $TRAJECTORY_CANVAS = null, - TRAJECTORY_CANVAS_CTX = null; + var MOUSE_LOCS_TRACKED = 3; // number of past mouse locations to track /** * Keep track of the last few locations of the mouse. */ var mousemoveDocument = function(e) { - mouseLocs.push({x: e.pageX, y: e.pageY}); + mouseLocs.push({x: e.pageX, y: e.pageY}); - if (mouseLocs.length > MOUSE_LOCS_TRACKED) { - mouseLocs.shift(); - } - }; + if (mouseLocs.length > MOUSE_LOCS_TRACKED) { + mouseLocs.shift(); + } + }; /** * Cancel possible row activations when leaving the menu entirely */ var mouseleaveMenu = function() { - if (timeoutId) { - clearTimeout(timeoutId); - } - - // If exitMenu is supplied and returns true, deactivate the - // currently active row on menu exit. - if (options.exitMenu(this)) { - if (activeRow) { - options.deactivate(activeRow); - } + if (timeoutId) { + clearTimeout(timeoutId); + } - activeRow = null; + // If exitMenu is supplied and returns true, deactivate the + // currently active row on menu exit. + if (options.exitMenu(this)) { + if (activeRow) { + options.deactivate(activeRow); } - }; + + activeRow = null; + } + }; /** * Trigger a possible row activation whenever entering a new row. @@ -163,24 +165,24 @@ * Immediately activate a row if the user clicks on it. */ var clickRow = function() { - activate(this); - }; + activate(this); + }; /** * Activate a menu row. */ var activate = function(row) { - if (row == activeRow) { - return; - } + if (row == activeRow) { + return; + } - if (activeRow) { - options.deactivate(activeRow); - } + if (activeRow) { + options.deactivate(activeRow); + } - options.activate(row); - activeRow = row; - }; + options.activate(row); + activeRow = row; + }; /** * Possibly activate a menu row. If mouse movement indicates that we @@ -188,16 +190,16 @@ * a submenu's content, then delay and check again later. */ var possiblyActivate = function(row) { - var delay = activationDelay(); - - if (delay) { - timeoutId = setTimeout(function() { - possiblyActivate(row); - }, delay); - } else { - activate(row); - } - }; + var delay = activationDelay(); + + if (delay) { + timeoutId = setTimeout(function() { + possiblyActivate(row); + }, delay); + } else { + activate(row); + } + }; /** * Return the amount of time that should be used as a delay before the @@ -208,115 +210,115 @@ * checking again to see if the row should be activated. */ var activationDelay = function() { - if (!activeRow || !$(activeRow).is(options.submenuSelector)) { - // If there is no other submenu row already active, then - // go ahead and activate immediately. - return 0; - } + if (!activeRow || !$(activeRow).is(options.submenuSelector)) { + // If there is no other submenu row already active, then + // go ahead and activate immediately. + return 0; + } - var offset = $menu.offset(), - upperLeft = { - x: offset.left, - y: offset.top - options.tolerance - }, - upperRight = { - x: offset.left + $menu.outerWidth(), - y: upperLeft.y - }, - lowerLeft = { - x: offset.left, - y: offset.top + $menu.outerHeight() + options.tolerance - }, - lowerRight = { - x: offset.left + $menu.outerWidth(), - y: lowerLeft.y - }, - loc = mouseLocs[mouseLocs.length - 1], - prevLoc = mouseLocs[0]; - - if (!loc) { - return 0; - } + var offset = $menu.offset(), + upperLeft = { + x: offset.left, + y: offset.top - options.tolerance + }, + upperRight = { + x: offset.left + $menu.outerWidth(), + y: upperLeft.y + }, + lowerLeft = { + x: offset.left, + y: offset.top + $menu.outerHeight() + options.tolerance + }, + lowerRight = { + x: offset.left + $menu.outerWidth(), + y: lowerLeft.y + }, + loc = mouseLocs[mouseLocs.length - 1], + prevLoc = mouseLocs[0]; + + if (!loc) { + return 0; + } - if (!prevLoc) { - prevLoc = loc; - } + if (!prevLoc) { + prevLoc = loc; + } - if (prevLoc.x < offset.left || prevLoc.x > lowerRight.x || - prevLoc.y < offset.top || prevLoc.y > lowerRight.y) { - // If the previous mouse location was outside of the entire - // menu's bounds, immediately activate. - return 0; - } + if (prevLoc.x < offset.left || prevLoc.x > lowerRight.x || + prevLoc.y < offset.top || prevLoc.y > lowerRight.y) { + // If the previous mouse location was outside of the entire + // menu's bounds, immediately activate. + return 0; + } - if (lastDelayLoc && - loc.x == lastDelayLoc.x && loc.y == lastDelayLoc.y) { - // If the mouse hasn't moved since the last time we checked - // for activation status, immediately activate. - return 0; - } + if (lastDelayLoc && + loc.x == lastDelayLoc.x && loc.y == lastDelayLoc.y) { + // If the mouse hasn't moved since the last time we checked + // for activation status, immediately activate. + return 0; + } - // Detect if the user is moving towards the currently activated - // submenu. - // - // If the mouse is heading relatively clearly towards - // the submenu's content, we should wait and give the user more - // time before activating a new row. If the mouse is heading - // elsewhere, we can immediately activate a new row. - // - // We detect this by calculating the slope formed between the - // current mouse location and the upper/lower right points of - // the menu. We do the same for the previous mouse location. - // If the current mouse location's slopes are - // increasing/decreasing appropriately compared to the - // previous's, we know the user is moving toward the submenu. - // - // Note that since the y-axis increases as the cursor moves - // down the screen, we are looking for the slope between the - // cursor and the upper right corner to decrease over time, not - // increase (somewhat counterintuitively). - function slope(a, b) { - return (b.y - a.y) / (b.x - a.x); - }; - - var decreasingCorner = upperRight, - increasingCorner = lowerRight; - - // Our expectations for decreasing or increasing slope values - // depends on which direction the submenu opens relative to the - // main menu. By default, if the menu opens on the right, we - // expect the slope between the cursor and the upper right - // corner to decrease over time, as explained above. If the - // submenu opens in a different direction, we change our slope - // expectations. - if (options.submenuDirection == "left") { - decreasingCorner = lowerLeft; - increasingCorner = upperLeft; - } else if (options.submenuDirection == "below") { - decreasingCorner = lowerRight; - increasingCorner = lowerLeft; - } else if (options.submenuDirection == "above") { - decreasingCorner = upperLeft; - increasingCorner = upperRight; - } + // Detect if the user is moving towards the currently activated + // submenu. + // + // If the mouse is heading relatively clearly towards + // the submenu's content, we should wait and give the user more + // time before activating a new row. If the mouse is heading + // elsewhere, we can immediately activate a new row. + // + // We detect this by calculating the slope formed between the + // current mouse location and the upper/lower right points of + // the menu. We do the same for the previous mouse location. + // If the current mouse location's slopes are + // increasing/decreasing appropriately compared to the + // previous's, we know the user is moving toward the submenu. + // + // Note that since the y-axis increases as the cursor moves + // down the screen, we are looking for the slope between the + // cursor and the upper right corner to decrease over time, not + // increase (somewhat counterintuitively). + function slope(a, b) { + return (b.y - a.y) / (b.x - a.x); + }; - var decreasingSlope = slope(loc, decreasingCorner), - increasingSlope = slope(loc, increasingCorner), - prevDecreasingSlope = slope(prevLoc, decreasingCorner), - prevIncreasingSlope = slope(prevLoc, increasingCorner); - - if (decreasingSlope < prevDecreasingSlope && - increasingSlope > prevIncreasingSlope) { - // Mouse is moving from previous location towards the - // currently activated submenu. Delay before activating a - // new menu row, because user may be moving into submenu. - lastDelayLoc = loc; - return options.delay; - } + var decreasingCorner = upperRight, + increasingCorner = lowerRight; + + // Our expectations for decreasing or increasing slope values + // depends on which direction the submenu opens relative to the + // main menu. By default, if the menu opens on the right, we + // expect the slope between the cursor and the upper right + // corner to decrease over time, as explained above. If the + // submenu opens in a different direction, we change our slope + // expectations. + if (options.submenuDirection == "left") { + decreasingCorner = lowerLeft; + increasingCorner = upperLeft; + } else if (options.submenuDirection == "below") { + decreasingCorner = lowerRight; + increasingCorner = lowerLeft; + } else if (options.submenuDirection == "above") { + decreasingCorner = upperLeft; + increasingCorner = upperRight; + } - lastDelayLoc = null; - return 0; - }; + var decreasingSlope = slope(loc, decreasingCorner), + increasingSlope = slope(loc, increasingCorner), + prevDecreasingSlope = slope(prevLoc, decreasingCorner), + prevIncreasingSlope = slope(prevLoc, increasingCorner); + + if (decreasingSlope < prevDecreasingSlope && + increasingSlope > prevIncreasingSlope) { + // Mouse is moving from previous location towards the + // currently activated submenu. Delay before activating a + // new menu row, because user may be moving into submenu. + lastDelayLoc = loc; + return options.delay; + } + + lastDelayLoc = null; + return 0; + }; /** * Activate a menu row. @@ -360,7 +362,7 @@ // Account for hiding of the trajectory $menu.mouseleave(function(e) { $TRAJECTORY_CANVAS.css({ - display: 'none' + display: 'none' }); }); } @@ -388,7 +390,7 @@ 'z-index': 9999 }); - // Hide the canvas otherwise + // Hide the canvas otherwise } else { TRAJECTORY_CANVAS.style.display = "none"; } @@ -399,8 +401,8 @@ // Trajectory path TRAJECTORY_CANVAS_CTX.beginPath(); TRAJECTORY_CANVAS_CTX.moveTo(options.trajectoryLineWidth, menu.pageY - menu_offs.top); - TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width, 0); - TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width, TRAJECTORY_CANVAS.height); + TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width + options.trajectoryLineWidth, -options.trajectoryLineWidth); + TRAJECTORY_CANVAS_CTX.lineTo(TRAJECTORY_CANVAS.width + options.trajectoryLineWidth, TRAJECTORY_CANVAS.height + options.trajectoryLineWidth); TRAJECTORY_CANVAS_CTX.closePath(); // Draw the path outline @@ -421,9 +423,9 @@ .mousemove(drawTrajectory) .mouseleave(mouseleaveMenu) .find(options.rowSelector) - .mouseenter(mouseenterRow) - .mouseleave(mouseleaveRow) - .click(clickRow); + .mouseenter(mouseenterRow) + .mouseleave(mouseleaveRow) + .click(clickRow); $(document).mousemove(mousemoveDocument);