Skip to content

Comments

[4.0] Update choices.js and fix a bug with detaching#23455

Closed
Fedik wants to merge 6 commits intojoomla:4.0-devfrom
Fedik:choices-update
Closed

[4.0] Update choices.js and fix a bug with detaching#23455
Fedik wants to merge 6 commits intojoomla:4.0-devfrom
Fedik:choices-update

Conversation

@Fedik
Copy link
Member

@Fedik Fedik commented Jan 5, 2019

Pull Request for Issue #23448 and #23402 (comment)

Summary of Changes

Update choices.js and fix issue caused by moving the element in DOM tree.

Before testing, run npm install

Testing Instructions

Please read #23448

@Hackwar please test it, it should fix your issue also.

Documentation Changes Required

none

side note: @dgrammatiko I would suggest to review joomla-tab.js behavior, it should not move content around on resize. It mess up DOM tree, and will cause many more bugs in future.

@dgrammatiko
Copy link
Contributor

I would suggest to review joomla-tab.js

That code is really bad, I know! But Is exposing all the wrong things that we did in the custom elements, so don't expect an update before all the custom elements are correctly implemented.

It mess up DOM tree

There is no rule that prohibits anyone to move nodes around the tree. Actually this behaviour reveals our bad implementation of custom elements... On the practical side, I guess the idea to transform tabs to accordion should be dropped for the production code, although it's a great accessibility win, for the reasons you also mention: future bugs (eg devs bad scripts)

This PR is taking this component one step close to production but there are 2 more things that needs to be patched here:

  • You should be able to create the element without any content and append the content later one (mutation observer) so the custom element satisfy:
x = document.createElement('joomla-field-fancy-select');

document.body.appendChild(x)

x.innerHTML = `<select><option value="zzzz" selected>oooo</option>`
  • The choices.js should be integral part of the custom element code, relying on an external script to be already available is wrong in this context. Custom elements by nature are async, in Joomla we're doing something weird loading them after the rest of the scripts (lazily). This behaviour works right now but once you change the order (for whatever reason) then the custom element here will be broken...


disconnectedCallback() {
// Destroy Choices instance, to unbind an event listeners
if (this.choicesInstance) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this part is correct. You need to destroy the current instance and recreate it. The missing part here is that you need a value attribute in the custom element that keeps the value (json). Also if you do it this way I guess you can skip the select element altogether and just create hidden input with the value so PHP is also happy...

@Fedik
Copy link
Member Author

Fedik commented Jan 6, 2019

There is no rule that prohibits anyone to move nodes around the tree...

There one golden rule: "Do not mess the DOM" :neckbeard:

Actually this behaviour reveals our bad implementation of custom elements...

It not only about CE. Joomla! forms are heavy already (can have 100+ inputs), moving nodes just force a browser re-evaluate everything. Additionally Developers can have a custom scripts (even more fancy than CE), that no one know how they will behavior if you change DOM in way tabs.js doing.

Instead of moving content, the tabs.js can just move the "navigation buttons", or even render them twice and switch by media query in CSS, that even more flexible. Also, example when you have just a 2 tab, you do not need to switch them to accordion. It should not be forced and hardcoded to 920px.

You should be able to create the element without ...

A <select> already required, you just will get an error about. So I do not see a problem.
This is correct use:

x = document.createElement('joomla-field-fancy-select');
x.innerHTML = '<select><option value="zzzz" selected>oooo</option>';
document.body.appendChild(x);

It can be change later on demand, when someone really really need it.

The choices.js should be integral part of the custom element code...

Injecting choicies.js (or any othe blablba.js) in to CE also wrong

@dgrammatiko
Copy link
Contributor

Injecting choicies.js (or any othe blablba.js) in to CE also wrong

It's the second best choice since we cannot use imports which is the right way.

This is correct use:

x = document.createElement('joomla-field-fancy-select');
x.innerHTML = '<select><option value="zzzz" selected>oooo</option>';
document.body.appendChild(x);

I'm afraid that the DOM can also work the other way around (create an empty element and inject the contents later on). You can force people to do it your way but you're not complying with the specs...

It should not be forced and hardcoded to 920px

Tabs shouldn't really change to accordion, that was a suggestion from the a11y group that I rushed to code. Anyways tabs already have been rewritten without this part, once the rest of the custom elements in this repo have been corrected I'll pull that code in

@Fedik
Copy link
Member Author

Fedik commented Jan 7, 2019

It's the second best choice since we cannot use imports

I have changed, will be safe now, without injecting and without "while" loops :neckbeard:

not complying with the specs...

I am who do the specs here 😄
So it require <select> to be preset. And any direct manipulation of CE children not allowed.
It like a single CE with shadow DOM, but without shadow DOM 😉

@dgrammatiko
Copy link
Contributor

And any direct manipulation of CE children not allowed.

Not really, check this:
Setting up a mutation observer:

// Watch for children changes.
// eslint-disable-next-line no-return-assign
new MutationObserver(() => this.childrenChange())
.observe(this, { childList: true });

and then care only for a specific element (in that case textarea)
/**
* Called when element's child list changes
*/
childrenChange() {
// Ensure the first child is an input with a textarea type.
if (this.firstElementChild
&& this.firstElementChild.tagName
&& this.firstElementChild.tagName.toLowerCase() === 'textarea'
&& this.firstElementChild.getAttribute('id')) {
this.editor = this.firstElementChild;
this.unregisterEditor();
this.registerEditor();
}
}

But anyways this is good enough for the time, let's patch the rest as well...

"@webcomponents/webcomponentsjs": "2.1.2",
"awesomplete": "github:LeaVerou/awesomplete",
"bootstrap": "4.1.3",
"choices.js": "^3.0.4",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the package lock

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@Fedik
Copy link
Member Author

Fedik commented Jan 10, 2019

@dgrammatiko but you know the cost of MutationObserver ? 😉
Especially when choices.js (or other script that used with CE, eg editors scripts etc) doing a changes itself.

From my point of view it doesn't worth to bother about it 😉

@Fedik
Copy link
Member Author

Fedik commented Feb 22, 2019

this is broken now, need full redo

@Fedik Fedik closed this Feb 22, 2019
@joomla-cms-bot joomla-cms-bot added the NPM Resource Changed This Pull Request can't be tested by Patchtester label Feb 22, 2019
@dgrammatiko
Copy link
Contributor

@Fedik oops sorry, copying the js to a new PR should be easy tho

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

NPM Resource Changed This Pull Request can't be tested by Patchtester

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants