TypeScript Source
You can view the full source code for jquery.agjVersionless.ts below.
Minified Source for Production Use
Use jquery.agjVersionless.min.js in production environments.
jquery.agjVersionless.ts
/**
* The agjVersionless jQuery plugin.
*
* Copyright (c) 2026 Andrew G. Johnson <andrew@andrewgjohnson.com>
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* @file The source code for the agjVersionless jQuery plugin.
* @copyright 2026 Andrew G. Johnson <andrew@andrewgjohnson.com>
* @license MIT
* @see {@link https://github.com/andrewgjohnson/agjVersionless GitHub Repository}
* @see {@link https://agjVersionless.agjjQuery.org/ Online Documentation}
* @author Andrew G. Johnson <andrew@andrewgjohnson.com>
* @version 1.0.0
*/
/// <reference types="jquery" />
interface JQueryStatic {
agjVersionless: {
bind(
element: JQuery,
event: string,
data: JQuery.EventHandler<HTMLElement> | JQuery.PlainObject | undefined,
fn?: JQuery.EventHandler<HTMLElement>,
): JQuery;
unbind(element: JQuery, event: string): JQuery;
on(
element: JQuery,
event: string,
data: JQuery.EventHandler<HTMLElement> | JQuery.PlainObject | undefined,
fn?: JQuery.EventHandler<HTMLElement>,
): JQuery;
off(element: JQuery, event: string): JQuery;
};
}
interface JQuery {
agjVersionless: {
bind(
event: string,
data: JQuery.EventHandler<HTMLElement> | JQuery.PlainObject | undefined,
fn?: JQuery.EventHandler<HTMLElement>,
): JQuery;
unbind(event: string): JQuery;
on(
event: string,
data: JQuery.EventHandler<HTMLElement> | JQuery.PlainObject | undefined,
fn?: JQuery.EventHandler<HTMLElement>,
): JQuery;
off(event: string): JQuery;
};
}
/**
* The agjVersionless plugin is built entirely in an IIFE (immediately invoked
* function expression) to avoid polluting the global namespace.
* @param $ - A reference to the global jQuery object.
*/
(function ($: JQueryStatic) {
'use strict';
const jQueryMajorVersion: number = parseInt($.fn.jquery.split('.')[0], 10);
/**
* The versionlessBind() function will bind an event handler to an element
* regardless of jQuery version.
* @param element - The element to bind the event handler to.
* @param event - The event to bind the event handler to.
* @param data - Optional data to pass to the event handler or the event
* handler itself if no data is passed.
* @param fn - The event handler.
* @returns Returns the element to allow for chaining.
*/
const versionlessBind = (
element: JQuery,
event: string,
data: JQuery.EventHandler<HTMLElement> | JQuery.PlainObject | undefined,
fn?: JQuery.EventHandler<HTMLElement>,
): JQuery => {
// the data field is optional so this will handle calls to
// versionlessBind(element, event, fn)
if (typeof data === 'function' && typeof fn === 'undefined') {
fn = data as JQuery.EventHandler<HTMLElement>;
data = undefined;
}
/* istanbul ignore next -- older jQuery versions aren’t available to test via command line */
switch (jQueryMajorVersion) {
/* istanbul ignore next -- older jQuery versions aren’t available to test via command line */
case 1:
if (data === undefined) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return element.bind(event, fn as any);
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return element.bind(event, data, fn as any);
}
case 2:
case 3:
default:
if (data === undefined) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return element.on(event, fn as any);
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return element.on(event, data as JQuery.PlainObject, fn as any);
}
}
};
/**
* The versionlessUnbind() function will unbind an event handler from an
* element regardless of jQuery version.
* @param element - The element to unbind the event handler from.
* @param event - The event to unbind the event handler from.
* @returns Returns the element to allow for chaining.
*/
const versionlessUnbind = (element: JQuery, event: string): JQuery => {
/* istanbul ignore next -- older jQuery versions aren’t available to test via command line */
switch (jQueryMajorVersion) {
/* istanbul ignore next -- older jQuery versions aren’t available to test via command line */
case 1:
return element.unbind(event);
case 2:
case 3:
default:
return element.off(event);
}
};
/**
* The $.agjVersionless object exposes the versionless functions as a jQuery
* plugin namespace.
*/
$.agjVersionless = {
bind: versionlessBind,
unbind: versionlessUnbind,
on: versionlessBind,
off: versionlessUnbind,
};
/**
* The $.fn.agjVersionless getter exposes the versionless functions on
* individual jQuery elements, allowing element.agjVersionless.bind() style
* calls in addition to $.agjVersionless.bind(element) style calls.
* The try/catch handles IE8 and below where Object.defineProperty either
* does not exist or does not support plain objects like $.fn.
*/
try {
Object.defineProperty($.fn, 'agjVersionless', {
get: function (this: JQuery) {
return {
bind: (
event: string,
data?: JQuery.EventHandler<HTMLElement> | JQuery.PlainObject,
fn?: JQuery.EventHandler<HTMLElement>,
): JQuery => {
return versionlessBind(this, event, data, fn);
},
unbind: (event: string): JQuery => {
return versionlessUnbind(this, event);
},
on: (
event: string,
data?: JQuery.EventHandler<HTMLElement> | JQuery.PlainObject,
fn?: JQuery.EventHandler<HTMLElement>,
): JQuery => {
return versionlessBind(this, event, data, fn);
},
off: (event: string): JQuery => {
return versionlessUnbind(this, event);
},
};
},
});
} catch {
// IE8 and below: element.agjVersionless is unavailable; use $.agjVersionless instead
}
})(jQuery);