From 97aa749578a05b207d54dbbcd8580201b5eba359 Mon Sep 17 00:00:00 2001 From: silverwind Date: Wed, 6 Sep 2023 02:02:44 +0200 Subject: [PATCH] Vendor `jquery.are-you-sure` with strict mode fixes (#26901) Extract from https://github.com/go-gitea/gitea/pull/25940 and because https://github.com/go-gitea/gitea/pull/26743 does seem to need more work. This will be required if we are to run our JS in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode). Previously, the two variables `$fields` and `$dirtyForms` polluted `window`: image --- package-lock.json | 12 -- package.json | 1 - web_src/js/features/common-global.js | 2 +- web_src/js/vendor/jquery.are-you-sure.js | 195 +++++++++++++++++++++++ webpack.config.js | 1 - 5 files changed, 196 insertions(+), 15 deletions(-) create mode 100644 web_src/js/vendor/jquery.are-you-sure.js diff --git a/package-lock.json b/package-lock.json index dda23bcbd4..db0480a5e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,6 @@ "escape-goat": "4.0.0", "fast-glob": "3.3.1", "jquery": "3.7.1", - "jquery.are-you-sure": "1.9.0", "katex": "0.16.8", "license-checker-webpack-plugin": "0.2.1", "lightningcss-loader": "2.1.0", @@ -6466,17 +6465,6 @@ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" }, - "node_modules/jquery.are-you-sure": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/jquery.are-you-sure/-/jquery.are-you-sure-1.9.0.tgz", - "integrity": "sha512-2r0uFx8CyAopjeHGOdvvwpFP921TnW1+v1uJXcAWQYHYGB1tryTDhQY+5u6HsVeMwbWiRTKVZFWnLaFpDvIqZQ==", - "dependencies": { - "jquery": ">=1.4.2" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/js-levenshtein-esm": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/js-levenshtein-esm/-/js-levenshtein-esm-1.2.0.tgz", diff --git a/package.json b/package.json index e4f1743feb..224a1422ec 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "escape-goat": "4.0.0", "fast-glob": "3.3.1", "jquery": "3.7.1", - "jquery.are-you-sure": "1.9.0", "katex": "0.16.8", "license-checker-webpack-plugin": "0.2.1", "lightningcss-loader": "2.1.0", diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js index d02a82a2ef..03169e6815 100644 --- a/web_src/js/features/common-global.js +++ b/web_src/js/features/common-global.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import 'jquery.are-you-sure'; +import '../vendor/jquery.are-you-sure.js'; import {clippie} from 'clippie'; import {createDropzone} from './dropzone.js'; import {initCompColorPicker} from './comp/ColorPicker.js'; diff --git a/web_src/js/vendor/jquery.are-you-sure.js b/web_src/js/vendor/jquery.are-you-sure.js new file mode 100644 index 0000000000..e06da39fc9 --- /dev/null +++ b/web_src/js/vendor/jquery.are-you-sure.js @@ -0,0 +1,195 @@ +// Fork of the upstream module. The only changes are the addition of `const` on +// lines 93 and 161 to make it strict mode compatible. + +/*! + * jQuery Plugin: Are-You-Sure (Dirty Form Detection) + * https://github.com/codedance/jquery.AreYouSure/ + * + * Copyright (c) 2012-2014, Chris Dance and PaperCut Software http://www.papercut.com/ + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Author: chris.dance@papercut.com + * Version: 1.9.0 + * Date: 13th August 2014 + */ +(function($) { + + $.fn.areYouSure = function(options) { + + var settings = $.extend( + { + 'message' : 'You have unsaved changes!', + 'dirtyClass' : 'dirty', + 'change' : null, + 'silent' : false, + 'addRemoveFieldsMarksDirty' : false, + 'fieldEvents' : 'change keyup propertychange input', + 'fieldSelector': ":input:not(input[type=submit]):not(input[type=button])" + }, options); + + var getValue = function($field) { + if ($field.hasClass('ays-ignore') + || $field.hasClass('aysIgnore') + || $field.attr('data-ays-ignore') + || $field.attr('name') === undefined) { + return null; + } + + if ($field.is(':disabled')) { + return 'ays-disabled'; + } + + var val; + var type = $field.attr('type'); + if ($field.is('select')) { + type = 'select'; + } + + switch (type) { + case 'checkbox': + case 'radio': + val = $field.is(':checked'); + break; + case 'select': + val = ''; + $field.find('option').each(function(o) { + var $option = $(this); + if ($option.is(':selected')) { + val += $option.val(); + } + }); + break; + default: + val = $field.val(); + } + + return val; + }; + + var storeOrigValue = function($field) { + $field.data('ays-orig', getValue($field)); + }; + + var checkForm = function(evt) { + + var isFieldDirty = function($field) { + var origValue = $field.data('ays-orig'); + if (undefined === origValue) { + return false; + } + return (getValue($field) != origValue); + }; + + var $form = ($(this).is('form')) + ? $(this) + : $(this).parents('form'); + + // Test on the target first as it's the most likely to be dirty + if (isFieldDirty($(evt.target))) { + setDirtyStatus($form, true); + return; + } + + const $fields = $form.find(settings.fieldSelector); + + if (settings.addRemoveFieldsMarksDirty) { + // Check if field count has changed + var origCount = $form.data("ays-orig-field-count"); + if (origCount != $fields.length) { + setDirtyStatus($form, true); + return; + } + } + + // Brute force - check each field + var isDirty = false; + $fields.each(function() { + var $field = $(this); + if (isFieldDirty($field)) { + isDirty = true; + return false; // break + } + }); + + setDirtyStatus($form, isDirty); + }; + + var initForm = function($form) { + var fields = $form.find(settings.fieldSelector); + $(fields).each(function() { storeOrigValue($(this)); }); + $(fields).unbind(settings.fieldEvents, checkForm); + $(fields).bind(settings.fieldEvents, checkForm); + $form.data("ays-orig-field-count", $(fields).length); + setDirtyStatus($form, false); + }; + + var setDirtyStatus = function($form, isDirty) { + var changed = isDirty != $form.hasClass(settings.dirtyClass); + $form.toggleClass(settings.dirtyClass, isDirty); + + // Fire change event if required + if (changed) { + if (settings.change) settings.change.call($form, $form); + + if (isDirty) $form.trigger('dirty.areYouSure', [$form]); + if (!isDirty) $form.trigger('clean.areYouSure', [$form]); + $form.trigger('change.areYouSure', [$form]); + } + }; + + var rescan = function() { + var $form = $(this); + var fields = $form.find(settings.fieldSelector); + $(fields).each(function() { + var $field = $(this); + if (!$field.data('ays-orig')) { + storeOrigValue($field); + $field.bind(settings.fieldEvents, checkForm); + } + }); + // Check for changes while we're here + $form.trigger('checkform.areYouSure'); + }; + + var reinitialize = function() { + initForm($(this)); + } + + if (!settings.silent && !window.aysUnloadSet) { + window.aysUnloadSet = true; + $(window).bind('beforeunload', function() { + const $dirtyForms = $("form").filter('.' + settings.dirtyClass); + if ($dirtyForms.length == 0) { + return; + } + // Prevent multiple prompts - seen on Chrome and IE + if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) { + if (window.aysHasPrompted) { + return; + } + window.aysHasPrompted = true; + window.setTimeout(function() {window.aysHasPrompted = false;}, 900); + } + return settings.message; + }); + } + + return this.each(function(elem) { + if (!$(this).is('form')) { + return; + } + var $form = $(this); + + $form.submit(function() { + $form.removeClass(settings.dirtyClass); + }); + $form.bind('reset', function() { setDirtyStatus($form, false); }); + // Add a custom events + $form.bind('rescan.areYouSure', rescan); + $form.bind('reinitialize.areYouSure', reinitialize); + $form.bind('checkform.areYouSure', checkForm); + initForm($form); + }); + }; +})(jQuery); diff --git a/webpack.config.js b/webpack.config.js index c6b28068f0..f95296c380 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -206,7 +206,6 @@ export default { }).join('\n'); }, override: { - 'jquery.are-you-sure@*': {licenseName: 'MIT'}, // https://github.com/codedance/jquery.AreYouSure/pull/147 'khroma@*': {licenseName: 'MIT'}, // https://github.com/fabiospampinato/khroma/pull/33 }, emitError: true,