Found while hardening selector handling for #731. Not introduced by that work, this is pre-existing on master.
Problem
src/jquery.contextMenu.js:2363:
if (!o.context || !o.context.length) {
o.context = document;
}
A plain DOM Element has no .length property, so !o.context.length is true and the registration silently falls back to document. The menu still works, but it is registered globally instead of being scoped to the element the caller passed.
Only a jQuery object or a selector string actually scopes a registration today. There is no error and no warning, so the caller has no way to notice.
// scopes correctly
$.contextMenu({selector: '.item', context: $('#panel'), items: {...}});
$.contextMenu({selector: '.item', context: '#panel', items: {...}});
// silently global
$.contextMenu({selector: '.item', context: document.getElementById('panel'), items: {...}});
Note the .length check also misfires the other way for <form> and <select> elements, which do have a length property (their control/option count). An empty <form> passed as context has length === 0 and is ignored; a non-empty one is accepted.
Why it matters now
cf26191 added support for selector being an Element or a jQuery object, so it is reasonable for a caller to expect context to accept the same shapes. It does not.
Suggested fix
Normalise context by type rather than by truthiness of .length, in the same spirit as the existing isElementSelector() helper used for selector.
Found while hardening selector handling for #731. Not introduced by that work, this is pre-existing on
master.Problem
src/jquery.contextMenu.js:2363:A plain DOM
Elementhas no.lengthproperty, so!o.context.lengthis true and the registration silently falls back todocument. The menu still works, but it is registered globally instead of being scoped to the element the caller passed.Only a jQuery object or a selector string actually scopes a registration today. There is no error and no warning, so the caller has no way to notice.
Note the
.lengthcheck also misfires the other way for<form>and<select>elements, which do have alengthproperty (their control/option count). An empty<form>passed ascontexthaslength === 0and is ignored; a non-empty one is accepted.Why it matters now
cf26191 added support for
selectorbeing anElementor a jQuery object, so it is reasonable for a caller to expectcontextto accept the same shapes. It does not.Suggested fix
Normalise
contextby type rather than by truthiness of.length, in the same spirit as the existingisElementSelector()helper used forselector.