Skip to content

Instantly share code, notes, and snippets.

@AnandPilania
Last active April 1, 2024 05:30
Show Gist options
  • Save AnandPilania/e94ec4730d3441cccc532004d2ba09cb to your computer and use it in GitHub Desktop.
Save AnandPilania/e94ec4730d3441cccc532004d2ba09cb to your computer and use it in GitHub Desktop.
Enhanced jQuery Plugin for Observing Events

This gist provides a jQuery plugin for observing events, offering improved flexibility and functionality. The plugin supports various syntaxes, including object-based and chained function-based, and allows for observing both DOM and AJAX events. It also includes error handling and validation for input parameters.

<input id="input">
<select id="select">
  <option value="" selected></option>
  <option value="1">1</option>
</select>
<div id="div">
  <span>div</span>
</div>
$(() => {
  $("#input")
    .observe("paste", () =>
      console.log("Input is pasted!"))
    .observe("input", () =>
      console.log("Input is input!"))
    .observe("change", () =>
      console.log("Input is changed!"));

  $(document).observe("change", "#select", () =>
    console.log("Select is changed!"));

  $(document).observe("ajax", () =>
    console.log("AJAX request completed."));

  $(document).observe("ajax", "https://api.publicapis.org/random", () =>
    console.log("AJAX request to /random completed."));

  $("div#div")
    .observe("added", "p", () => console.log("P added as a child of div#div!"))
    .observe("removed", "p", () => console.log("P removed as a child of div#div!"));
});

$(() => {
  setTimeout(() => $.get("https://api.publicapis.org/entries"), 2000);
  setTimeout(() => $.get("https://api.publicapis.org/random"), 3000);
  setTimeout(() => $("#div").append('<p id="p">Pp</p>'), 4000);
  setTimeout(() => $("#div p").remove(), 6000);
});
(function($) {
$.fn.observe = function(events, selector, callback) {
const $document = $(document);
const _mutationObserve = (events, selector, callback) => {
if (typeof MutationObserver === 'undefined') {
console.warn("Mutation Observer not supported. Falling back to DOM events.");
$document.on(events, selector, callback);
return;
}
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (
mutation.type === "childList" && ["added", "removed"].includes(events)
) {
$(mutation[events === "added" ? "addedNodes" : "removedNodes"])
.filter(selector)
.each(function() {
callback.call(this);
});
} else if (
["attributes", "characterData"].includes(mutation.type) && ["updated", "changed"].includes(events)
) {
if (mutation.target.matches(selector)) {
callback.call(this);
}
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: events === "updated",
characterData: events === "changed"
});
};
const _isAjaxObserver = (type) => type === 'ajax';
const _isElementObserver = (type) => ["added", "removed", "updated", "changed"].includes(type);
if (typeof events === "object" && !$.isFunction(selector)) {
$.each(events, function(eventTypes, eventCallback) {
if (_isAjaxObserver(eventTypes)) {
$document.on("ajaxComplete", eventCallback);
} else if (_isElementObserver(eventTypes)) {
_mutationObserve(eventTypes, selector, eventCallback);
} else {
$(this).on(eventTypes, selector, eventCallback);
}
});
} else if (
typeof events === "string" &&
$.isFunction(selector) &&
!callback
) {
if (_isAjaxObserver(events)) {
$document.on("ajaxComplete", selector);
} else if (_isElementObserver(events)) {
_mutationObserve(events, this.selector, selector);
} else {
$(this).on(events, selector);
}
} else if (
typeof events === "string" &&
typeof selector === "string" &&
$.isFunction(callback)
) {
if (_isAjaxObserver(events)) {
$document.ajaxComplete(function(event, xhr, settings) {
if (settings.url === selector) {
callback.call(this, event, xhr, settings);
}
});
} else if (_isElementObserver(events)) {
_mutationObserve(events, selector, callback);
} else {
$document.on(events, selector, callback);
}
} else {
console.error("Invalid input parameters.");
}
return this;
};
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment