(function ($) { /** * debounce * @param {integer} milliseconds This param indicates the number of milliseconds * to wait after the last call before calling the original function. * @param {object} What "this" refers to in the returned function. * @return {function} This returns a function that when called will wait the * indicated number of milliseconds after the last call before * calling the original function. */ Function.prototype.debounce = function (milliseconds, context) { var baseFunction = this, timer = null, wait = milliseconds; return function () { var self = context || this, args = arguments; function complete() { baseFunction.apply(self, args); timer = null; } if (timer) { clearTimeout(timer); } timer = setTimeout(complete, wait); }; }; /** * throttle * @param {integer} milliseconds This param indicates the number of milliseconds * to wait between calls before calling the original function. * @param {object} What "this" refers to in the returned function. * @return {function} This returns a function that when called will wait the * indicated number of milliseconds between calls before * calling the original function. */ Function.prototype.throttle = function (milliseconds, context) { var baseFunction = this, lastEventTimestamp = null, limit = milliseconds; return function () { var self = context || this, args = arguments, now = Date.now(); if (!lastEventTimestamp || now - lastEventTimestamp >= limit) { lastEventTimestamp = now; baseFunction.apply(self, args); } }; }; $.fn.highlightLines = function (configurations) { return this.each(function () { const $pre = $(this); const textContent = $pre.text(); const lines = textContent.split(/\r?\n/); // Handles both \n and \r\n line endings // Build a map of line numbers to styles const lineStyles = {}; configurations.forEach(config => { const {color, lines: lineNumbers} = config; lineNumbers.forEach(lineNumber => { lineStyles[lineNumber] = color; }); }); // Function to escape HTML characters function escapeHtml(text) { return text.replace(/[&<>"'`=\/]/g, function (s) { return "&#" + s.charCodeAt(0) + ";"; }); } // Process each line const processedLines = lines.map((line, index) => { const lineNumber = index + 1; // Line numbers start at 1 const escapedLine = escapeHtml(line); const color = lineStyles[lineNumber]; if (color) { // Wrap the line in a span with inline style return `${escapedLine}`; } else { return escapedLine; } }); // Join the lines back together const newContent = processedLines.join('\n'); // Set the new content as HTML $pre.html(newContent); }); }; $.fn.miniTabs = function (tabsConfig, options) { const settings = { tabClass: 'minitab', tabsContainerClass: 'minitabs', activeClass: 'active', ...(options || {}) }; return this.each(function () { const $wrapper = $(this); const $contents = $wrapper.find('div[id]').hide(); const $tabsContainer = $('
', {class: settings.tabsContainerClass}).prependTo($wrapper); // Generate tabs Object.entries(tabsConfig).forEach(([tabTitle, contentSelector], index) => { const $content = $wrapper.find(contentSelector); if (index === 0) $content.show(); // Show first content by default $('', { class: `${settings.tabClass}${index === 0 ? ` ${settings.activeClass}` : ''}`, text: tabTitle, 'data-target': contentSelector }).appendTo($tabsContainer); }); // Tab click event $tabsContainer.on('click', `.${settings.tabClass}`, function (e) { e.preventDefault(); const $tab = $(this); const target = $tab.data('target'); // Update active tab $tabsContainer.find(`.${settings.tabClass}`).removeClass(settings.activeClass); $tab.addClass(settings.activeClass); // Show/hide content $contents.hide(); $wrapper.find(target).show(); }); }); }; // Object to store ongoing requests by namespace const requests = {}; $.abortiveSingularAjax = function (options) { const namespace = options.namespace || 'default'; // Abort the current request in this namespace if it's still ongoing if (requests[namespace]) { requests[namespace].abort(); } // Start a new AJAX request and store its reference in the correct namespace requests[namespace] = $.ajax(options); // Return the current request in case it's needed return requests[namespace]; }; })(jQuery);