Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new section - update uri (format) even if field hidden #13355

Merged
merged 3 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Fixed a bug where Matrx fields with custom propagation methods were being marked as translatable if the rendered translation key was blank. ([#13329](https://github.com/craftcms/cms/issues/13329))
- Fixed a bug where transformed images’ `width` or `height` properties could be `null` if the transform didn’t specify both dimensions. ([#13335](https://github.com/craftcms/cms/issues/13335))
- Fixed a bug where heading UI elements within field layouts were getting a top border if they were preceeded by conditionally-hidden fields. ([#13308](https://github.com/craftcms/cms/issues/13308))
- Fixed a bug where new Single sections could get URIs filled in on form submit based on the section name, if the input was blank and hadn’t been directly edited. ([#13350](https://github.com/craftcms/cms/issues/13350), [#13355](https://github.com/craftcms/cms/pull/13355))
- Fixed two RCE vulnerabilities.

## 4.4.14 - 2023-06-13
Expand Down
18 changes: 15 additions & 3 deletions src/templates/settings/sections/_edit.twig
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,21 @@
new Craft.HandleGenerator('#name', '#handle');

{% for site in craft.app.sites.getAllSites() %}
new Craft.UriFormatGenerator('#name', '#sites tr[data-id="{{ site.handle }}"] textarea[name$="[singleUri]"]');
new Craft.UriFormatGenerator('#name', '#sites tr[data-id="{{ site.handle }}"] textarea[name$="[uriFormat]"]', { suffix: '/{slug}' });
new Craft.UriFormatGenerator('#name', '#sites tr[data-id="{{ site.handle }}"] input[name$="[template]"]', { suffix: '/_entry' });
new Craft.UriFormatGenerator(
'#name',
'#sites tr[data-id="{{ site.handle }}"] textarea[name$="[singleUri]"]',
{ updateWhenHidden: true }
);
new Craft.UriFormatGenerator(
'#name',
'#sites tr[data-id="{{ site.handle }}"] textarea[name$="[uriFormat]"]',
{ suffix: '/{slug}', updateWhenHidden: true }
);
new Craft.UriFormatGenerator(
'#name',
'#sites tr[data-id="{{ site.handle }}"] input[name$="[template]"]',
{ suffix: '/_entry', updateWhenHidden: true }
);
{% endfor %}
{% endjs %}
{% endif %}
2 changes: 1 addition & 1 deletion src/web/assets/cp/dist/cp.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/cp/dist/cp.js.map

Large diffs are not rendered by default.

225 changes: 118 additions & 107 deletions src/web/assets/cp/src/js/BaseInputGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,119 +3,130 @@
/**
* Input Generator
*/
Craft.BaseInputGenerator = Garnish.Base.extend({
$source: null,
$target: null,
$form: null,
settings: null,
Craft.BaseInputGenerator = Garnish.Base.extend(
{
$source: null,
$target: null,
$form: null,
settings: null,

listening: null,
timeout: null,
listening: null,
timeout: null,

init: function (source, target, settings) {
this.$source = $(source);
this.$target = $(target);
this.$form = this.$source.closest('form');
init: function (source, target, settings) {
this.$source = $(source);
this.$target = $(target);
this.$form = this.$source.closest('form');

this.setSettings(settings);
this.setSettings(settings, Craft.BaseInputGenerator.defaults);
this.setSettings(settings);

this.startListening();
},

setNewSource: function (source) {
var listening = this.listening;
this.stopListening();

this.$source = $(source);

if (listening) {
this.startListening();
}
},

startListening: function () {
if (this.listening) {
return;
}

this.listening = true;

this.addListener(this.$source, 'input', 'onSourceTextChange');
this.addListener(this.$target, 'input', 'onTargetTextChange');
this.addListener(this.$form, 'submit', 'onFormSubmit');
},

stopListening: function () {
if (!this.listening) {
return;
}

this.listening = false;

if (this.timeout) {
clearTimeout(this.timeout);
}

this.removeAllListeners(this.$source);
this.removeAllListeners(this.$target);
this.removeAllListeners(this.$form);
},

onSourceTextChange: function () {
if (this.timeout) {
clearTimeout(this.timeout);
}
},

this.timeout = setTimeout(this.updateTarget.bind(this), 250);
},

onTargetTextChange: function () {
if (this.$target.get(0) === document.activeElement) {
setNewSource: function (source) {
var listening = this.listening;
this.stopListening();
}
},

onFormSubmit: function () {
if (this.timeout) {
clearTimeout(this.timeout);
}

this.updateTarget();
},

updateTarget: function () {
if (!this.$target.is(':visible')) {
return;
}

var sourceVal = this.$source.val();

if (typeof sourceVal === 'undefined') {
// The source input may not exist anymore
return;
}

var targetVal = this.generateTargetValue(sourceVal);

this.$target.val(targetVal);

for (let i = 0; i < this.$target.length; i++) {
this.$target[i].dispatchEvent(
new InputEvent('input', {
inputType: 'insertText',
})
);
this.$target[i].dispatchEvent(new Event('input'));
}

// If the target already has focus, select its whole value to mimic
// the behavior if the value had already been generated and they just tabbed in
if (this.$target.is(':focus')) {
Craft.selectFullValue(this.$target);
}
},

generateTargetValue: function (sourceVal) {
return sourceVal;
this.$source = $(source);

if (listening) {
this.startListening();
}
},

startListening: function () {
if (this.listening) {
return;
}

this.listening = true;

this.addListener(this.$source, 'input', 'onSourceTextChange');
this.addListener(this.$target, 'input', 'onTargetTextChange');
this.addListener(this.$form, 'submit', 'onFormSubmit');
},

stopListening: function () {
if (!this.listening) {
return;
}

this.listening = false;

if (this.timeout) {
clearTimeout(this.timeout);
}

this.removeAllListeners(this.$source);
this.removeAllListeners(this.$target);
this.removeAllListeners(this.$form);
},

onSourceTextChange: function () {
if (this.timeout) {
clearTimeout(this.timeout);
}

this.timeout = setTimeout(this.updateTarget.bind(this), 250);
},

onTargetTextChange: function () {
if (this.$target.get(0) === document.activeElement) {
this.stopListening();
}
},

onFormSubmit: function () {
if (this.timeout) {
clearTimeout(this.timeout);
}

this.updateTarget();
},

updateTarget: function () {
if (
!this.$target.is(':visible') &&
this.settings.updateWhenHidden == false
) {
return;
}

var sourceVal = this.$source.val();

if (typeof sourceVal === 'undefined') {
// The source input may not exist anymore
return;
}

var targetVal = this.generateTargetValue(sourceVal);

this.$target.val(targetVal);

for (let i = 0; i < this.$target.length; i++) {
this.$target[i].dispatchEvent(
new InputEvent('input', {
inputType: 'insertText',
})
);
this.$target[i].dispatchEvent(new Event('input'));
}

// If the target already has focus, select its whole value to mimic
// the behavior if the value had already been generated and they just tabbed in
if (this.$target.is(':focus')) {
Craft.selectFullValue(this.$target);
}
},

generateTargetValue: function (sourceVal) {
return sourceVal;
},
},
});
{
defaults: {
updateWhenHidden: false,
},
}
);