Skip to content

[4.0] Client side, javascript Behavior API#6357

Closed
Fedik wants to merge 43 commits intojoomla:stagingfrom
Fedik:behavior
Closed

[4.0] Client side, javascript Behavior API#6357
Fedik wants to merge 43 commits intojoomla:stagingfrom
Fedik:behavior

Conversation

@Fedik
Copy link
Copy Markdown
Member

@Fedik Fedik commented Mar 7, 2015

Since version 1.5 Joomla made huge step to split HTML and PHP Logic, but JavaScript still in "younger brother" role, and very hard coded.

Here is a try to split PHP and JavaScript.

You ask: How that possible?
Very simple: Write PHP in PHP file, and JavaScript in JS file :neckbeard:
You ask: Then how to connect them?
Well, using JSON, maybe it not the best solution but also not the worst. 👽

So

This pull request introduce Joomla Behavior API for client side.
It:

  • allow write custom Behaviors in JavaScript,
  • provide way to interaction between different Behaviors,
  • provide additional way to override each existing behavior, from client side.

Also introduce JDocument::setScriptOptions() that is important gear in connection betwen PHP Logic and client side.
Each Behavior could be called only if server provide the options for that Behavior, or always.

How it work.

Each Behavior it just a collection of callbacks that called when corresponding event happen.
All behavior could be stored in js files, and splitted by group: behavior-bootstrap.js, behavior-form.js so on.

Register custom behavior:

Joomla.Behavior.add('behaviorname', 'ready update', function(event){
	console.log(event.name, event.target);
}, true);

This will be called only if Server provide options for this behavior $doc->addScriptOptions('behaviorname', array(/*some options*/)), and when happened next events: ready, update

Register custom behavior that will be always called:

Joomla.Behavior.add('behaviorname', 'ready update', function(event){
	console.log(event.name, event.target);
});

You asked: wtf is update event?
update - is a custom event that allow to call one Behavior from another "on fly", also this event must be called if you replace part of DOM, so other Behaviors will know about changes.
There also remove custom event, that could be used to ask Behaviors for clean up in 'container', unbind events and so on.
This events we could rename of course to something more clear, if need 😄
And, of course, anyone could use any custom event that need for his/her needs.

Example:

// Call all behaviors when you change part of DOM
Joomla.Behavior.call('update', changedContainer);
// Call specific behavior by name when you change part of DOM
Joomla.Behavior.call('update.behaviorname', changedContainer);
// Call specific behavior by name when you change part of DOM, and with custom options
Joomla.Behavior.call('update.behaviorname', changedContainer, options);

// Request other Behaviors to "clean up in" container
Joomla.Behavior.call('remove', container);

How it work on Live you can look in repeatable field in repeatable.js (see diff)

How to override existing Behavior.
Very simple, just register own behavior with same name, and it will override any existing:

Joomla.Behavior.add('behaviorname', 'ready update', function(event){
	console.log('I am override');
});

or you could override only specific event callback if need:

Joomla.Behavior.add('behaviorname', 'update', function(event){
	console.log('I am override for Update event');
});

B/C
I tried make it for keep b/c, with count that it could be in the core since ~~3.~~5.0
So you should not see any difference after apply this patch.

Conclusion
Split PHP logic and JavaScript is a small step to big improve 😋
Next step could be dependency management using Requirejs or anything else.

Well to much text, I hope here understandable at least couple words :neckbeard:

ping @phproberto @DGT41 @okonomiyaki3000 @anibalsanchez I need your brains 👻

ps. couple word about jquery 😋

@roland-d
Copy link
Copy Markdown
Contributor

Everybody, a great discussion but we can't seem to reach an agreement as to how to move forward with this. I am going to close this now but feel free to re-open if you plan to continue working on this.

Thank you for your cooperation.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6357.

@dgrammatiko
Copy link
Copy Markdown
Contributor

@roland-d can you add a re evaluate for 4 tag here? This is totally needed IMHO

@brianteeman
Copy link
Copy Markdown
Contributor

Going to reopen so it will be seen even though it is a reevaluate fod 4

@brianteeman brianteeman reopened this Aug 4, 2016
@Fedik Fedik mentioned this pull request Nov 25, 2016
@ghost
Copy link
Copy Markdown

ghost commented Apr 7, 2017

@mbabker for [4.0]-Projects?


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/6357.

@joomla-cms-bot joomla-cms-bot changed the title Client side, javascript Behavior API [4.0] Client side, javascript Behavior API Apr 7, 2017
@dgrammatiko
Copy link
Copy Markdown
Contributor

@Fedik can you remove the DomReady? (you can safely user the native DOMContentLoaded)

{
var $target = $(event.target);
$target.find('label.template-isis-radio').removeClass('template-isis-radio').off('click.templateIsisRadio');
});
Copy link
Copy Markdown
Contributor

@dgrammatiko dgrammatiko Apr 7, 2017

Choose a reason for hiding this comment

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

vanilla

var targets = [].slice.call(event.target.querySelectorAll('label.template-isis-radio''));

targets.forEach(function(item) {
   item.classList.remove('template-isis-radio').off('click.templateIsisRadio');
});

@Fedik
Copy link
Copy Markdown
Member Author

Fedik commented May 6, 2017

@DGT41 I need some input here, what do you think

I have made possibility that the behavior can be loaded on the page all the time, but called only when the scriptOptions exists for this behavior.

Joomla.Behavior.add('behaviorname', 'ready update', function(event){
	console.log(event.name, event.target);
}, true <===);

I think about change it to:

Joomla.Behavior.add('behaviorname', 'ready update', function(event){
	console.log(event.name, event.target, event.options);
}, 'script-options-key-blablabla' <===);

it allow to put the behaviors in a single file, load it to the page, and they will be executed only if scriptOptions contain script-options-key-blablabla.

Or I just remove such possibility?

@dgrammatiko
Copy link
Copy Markdown
Contributor

So the ready event corresponds to document.('DOMContentLoaded') ?

What happens if scriptOptions not there? Crash and burn?

@Fedik
Copy link
Copy Markdown
Member Author

Fedik commented May 6, 2017

So the ready event corresponds to document.('DOMContentLoaded') ?

yes right

What happens if scriptOptions not there? Crash and burn?

blue screen with random bright yellow words on it, obviously 😉

well, no
let say you have behavior do-stuff in my-cool-template.js, which loaded with all your scripts, but should be called only if the options there:

Joomla.Behavior.add('do-stuff', 'ready update', function(event){
     console.log(event.name, event.target, event.options);
     event.target.style.background =  event.options.background || '';
}, 'do-stuff-options-key');

for make it run you
OR add the options via PHP (example in template):

$doc->addScriptOptions('do-stuff-options-key', array('background' => 'black'))

so at time of DOMContentLoaded Joomla.Behavior will look at scriptOptions, and if there a do-stuff-options-key, then it will call your behavior. Otherwise it will be ignored.

OR can call it via your another script (or from another extension), with your custom options:

var changedContainer = document.getElementById("main-container")
Joomla.Behavior.call('update.do-stuff', changedContainer, {background:'yellow'});

if there no options at time of DOMContentLoaded (was not added by PHP), then your behavior do-stuff will be ignored.

Fedik added 3 commits May 13, 2017 18:20
 Conflicts:
	administrator/components/com_modules/views/modules/view.html.php
	administrator/templates/isis/js/template.js
	libraries/cms/html/behavior.php
	libraries/cms/html/bootstrap.php
	libraries/cms/html/formbehavior.php
	libraries/joomla/document/document.php
	libraries/joomla/document/html/renderer/head.php
	media/system/js/core-uncompressed.js
	media/system/js/core.js
	media/system/js/repeatable-uncompressed.js
	media/system/js/repeatable.js
	templates/protostar/js/template.js
	tests/unit/suites/libraries/cms/html/JHtmlBehaviorTest.php
	tests/unit/suites/libraries/cms/html/JHtmlBootstrapTest.php
	tests/unit/suites/libraries/cms/html/JHtmlFormbehaviorTest.php
@Fedik
Copy link
Copy Markdown
Member Author

Fedik commented May 14, 2017

I guess the idea is tooooo complicated 😄

"javascript Behavior API" is dead, long live "Joomla! Custom events"! See #16016

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants