Skip to content

Commit ba101eb

Browse files
committed
MC-3939: Can't select or edit text ranges inside of a live edit block
- Rewrite tabs focus logic to utilise buttons new implementation - Resolve numerous issues with focusing on buttons and tabs - Enable ability to select text with selectAll enabled in Firefox
1 parent 275433b commit ba101eb

File tree

10 files changed

+208
-78
lines changed

10 files changed

+208
-78
lines changed

app/code/Magento/PageBuilder/view/adminhtml/web/js/binding/live-edit.js

Lines changed: 23 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/code/Magento/PageBuilder/view/adminhtml/web/js/content-type/button-item/preview.js

Lines changed: 6 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/code/Magento/PageBuilder/view/adminhtml/web/js/content-type/tab-item/preview.js

Lines changed: 63 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/code/Magento/PageBuilder/view/adminhtml/web/js/content-type/tabs/preview.js

Lines changed: 12 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/code/Magento/PageBuilder/view/adminhtml/web/template/content-type/button-item/default/preview.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
<a attr="data.link.attributes"
1414
ko-style="data.link.style"
1515
css="data.link.css"
16-
draggable="false"
1716
click="function (context, event) { onClick($index(), event); }">
1817
<span class="button-item-drag-handle" css="{disabled: parent.parent.children().length <= 1}"></span>
1918
<span attr="data.link_text.attributes"

app/code/Magento/PageBuilder/view/adminhtml/web/template/content-type/tabs/default/preview.html

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
<with args="preview">
1515
<li role="tab" class="tab-header"
1616
css="{focused: parent.parent.preview.focusedTab() === $index()}"
17-
click="function (context, event) { parent.parent.preview.onTabClick($index(), event); }"
1817
ko-style="parent.parent.preview.getTabHeaderStyles()"
19-
event="{ focusin: function () { parent.parent.preview.setFocusedTab($index(), true) }, focusout: function () { window.getSelection().removeAllRanges(); parent.parent.preview.setFocusedTab(null); } }">
20-
<a href="#no-tab" class="tab-title focus-options" attr="{ href: '#' + parent.id }" draggable="false">
18+
click="function (context, event) { onClick($index(), event); }"
19+
event="{ focusin: function (context, event) { onFocusIn($index(), event); }, focusout: function (context, event) { onFocusOut($index(), event); } }">
20+
<a href="#no-tab"
21+
class="tab-title focus-options"
22+
attr="{ href: '#' + parent.id }">
2123
<render args="getOptions().template" />
2224
<span class="tab-drag-handle" css="{disabled: parent.parent.children().length <= 1}"></span>
23-
<span class="tab-title tab-name" data-tab-title="true" data-bind="liveEdit: { field: 'tab_name', placeholder: $t('...'), selectAll: true }, hasFocusNoScroll: parent.parent.preview.focusedTab() === $index()"></span>
25+
<span class="tab-title tab-name"
26+
data-tab-title="true"
27+
data-bind="liveEdit: { field: 'tab_name', placeholder: $t('...'), selectAll: true }, hasFocusNoScroll: parent.parent.preview.focusedTab() === $index()"></span>
2428
</a>
2529
</li>
2630
</with>

app/code/Magento/PageBuilder/view/adminhtml/web/ts/js/binding/live-edit.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ ko.bindingHandlers.liveEdit = {
3838
init(element, valueAccessor, allBindings, viewModel, bindingContext) {
3939
const {field, placeholder, selectAll = false} = valueAccessor();
4040
let focusedValue = element.innerHTML;
41+
let previouslyFocused: boolean = false;
42+
let blurTimeout: number;
4143

4244
/**
4345
* Strip HTML and return text
@@ -56,19 +58,32 @@ ko.bindingHandlers.liveEdit = {
5658
* Record the value on focus, only conduct an update when data changes
5759
*/
5860
const onFocus = () => {
61+
clearTimeout(blurTimeout);
5962
focusedValue = stripHtml(element.innerHTML);
6063

61-
if (selectAll && element.innerHTML !== "") {
64+
if (selectAll && element.innerHTML !== "" && !previouslyFocused) {
6265
_.defer(() => {
6366
const selection = window.getSelection();
6467
const range = document.createRange();
6568
range.selectNodeContents(element);
6669
selection.removeAllRanges();
6770
selection.addRange(range);
71+
previouslyFocused = true;
6872
});
6973
}
7074
};
7175

76+
/**
77+
* On blur change our timeout for previously focused. We require a flag to track whether the input has been
78+
* focused and selected previously due to a bug in Firefox which doesn't handle focus events correctly when
79+
* contenteditable is placed within an anchor.
80+
*/
81+
const onBlur = () => {
82+
blurTimeout = setTimeout(() => {
83+
previouslyFocused = false;
84+
}, 100);
85+
};
86+
7287
/**
7388
* Mousedown event on element
7489
*
@@ -132,6 +147,7 @@ ko.bindingHandlers.liveEdit = {
132147
element.textContent = viewModel.parent.dataStore.get(field);
133148
element.contentEditable = true;
134149
element.addEventListener("focus", onFocus);
150+
element.addEventListener("blur", onBlur);
135151
element.addEventListener("mousedown", onMouseDown);
136152
element.addEventListener("keydown", onKeyDown);
137153
element.addEventListener("keyup", onKeyUp);
@@ -146,6 +162,11 @@ ko.bindingHandlers.liveEdit = {
146162
element.textContent = viewModel.parent.dataStore.get(field);
147163
handlePlaceholderClass(element);
148164
}, field);
165+
166+
// Resolve issues of content editable being within an anchor
167+
if ($(element).parent().is("a")) {
168+
$(element).parent().attr("draggable", "false");
169+
}
149170
},
150171

151172
/**

app/code/Magento/PageBuilder/view/adminhtml/web/ts/js/content-type/button-item/preview.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,8 @@ export default class Preview extends BasePreview {
4141
* @param {JQueryEventObject} event
4242
*/
4343
public onClick(index: number, event: JQueryEventObject): void {
44-
const contentEditable = $(event.currentTarget).find("[contenteditable]");
45-
if (!$(":focus").is(contentEditable)) {
46-
$(event.currentTarget).find("[contenteditable]").focus();
47-
event.stopPropagation();
48-
}
44+
$(event.currentTarget).find("[contenteditable]").focus();
45+
event.stopPropagation();
4946
}
5047

5148
/**
@@ -89,7 +86,9 @@ export default class Preview extends BasePreview {
8986
*/
9087
public onFocusIn(index: number, event: Event): void {
9188
const parentPreview = this.parent.parent.preview as ButtonsPreview;
92-
parentPreview.focusedButton(index);
89+
if (parentPreview.focusedButton() !== index) {
90+
parentPreview.focusedButton(index);
91+
}
9392
}
9493

9594
/**

0 commit comments

Comments
 (0)