All about Event Bubbling

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

I'm feeling so good about our first click listener, let's add another! When I click anywhere on a row, I also want to log a message.

Back in the template, give the entire table a js class so we can select it. How about js-rep-log-table:

... lines 1 - 2
{% block body %}
<div class="row">
<div class="col-md-7">
... lines 6 - 12
<table class="table table-striped js-rep-log-table">
... lines 14 - 47
</table>
... lines 49 - 50
</div>
... lines 52 - 58
</div>
{% endblock %}
... lines 61 - 77

Down below, find that and look inside for the tbody tr elements. Then, .on('click') add a function that prints some fascinating text: console.log('row clicked'):

... lines 1 - 61
{% block javascripts %}
{{ parent() }}
<script>
$(document).ready(function() {
... lines 67 - 70
$('.js-rep-log-table tbody tr').on('click', function() {
console.log('row clicked!');
});
});
</script>
{% endblock %}

Beautiful! Refresh and click the row. No surprises: we see "row clicked". But check this out: click the delete link. Hot diggity - two log messages! Of course it would do this! I clicked the delete link, but the delete link is inside of the row. Both things got clicked!

All about Event Bubbling

Welcome to event bubbling, an important concept in JavaScript that's just boring enough that you've probably avoided reading articles about it in the past. Let's make it awesome.

Here it goes: when we click, we cause a click event. Now technically, when I click the delete icon, the element that I'm actually clicking is the span that holds the icon. Cool! So, your browser goes to that span element and says:

Top of the morning! I'd like to trigger a click event on you!

Then, if there are any listener functions attached on click, those are called. Next, your browser goes up one level to the anchor and says:

Ahoy Matey! I'd like to trigger a click event on you!

And the same thing happens again: if there are any click listener functions attached to that element, those are executed. This includes our listener function. From here, it just keeps going: bubbling all the way up the tree: to the td, the tr, tbody, table, and eventually, to the <body> tag itself.

And that is why we see "todo delete" first: the event bubbling process notifies the link element and then bubles up and notifies the tr.

Prefixing $variables with $

Cool! Let's play with this! First, let's clean up our code a bit and make a minor performance improvement. Add var $table = $('.js-rep-log-table'). Then below, instead of searching the entire page for these delete links, use $table.find() to only look inside that table:

... lines 1 - 61
{% block javascripts %}
{{ parent() }}
<script>
$(document).ready(function() {
var $table = $('.js-rep-log-table');
$table.find('.js-delete-rep-log').on('click', function () {
console.log('todo delete!');
});
... lines 72 - 75
});
</script>
{% endblock %}

Do the same below: $table.find() and look for the tbody tr elements in that:

... lines 1 - 61
{% block javascripts %}
{{ parent() }}
<script>
$(document).ready(function() {
var $table = $('.js-rep-log-table');
... lines 68 - 72
$table.find('tbody tr').on('click', function() {
console.log('row clicked!');
});
});
</script>
{% endblock %}

If you refresh now, it still works great. But some of you might be wondering about my variable name: $table? For PHP developers, that looks weird... because, ya know, $ means something important in PHP. But in JavaScript, $ is not a special character. In fact, it's so not special that - if you want - you can even start a variable name with it. Madness! So the $ in $table isn't doing anything special, but it is a fairly common convention to denote a variable that is a jQuery object.

It's nice because when I see $table, I think:

Oh! This starts with a $! Good show! I bet it's a jQuery object, and I can call find() or any other fancy jQuery method on it. Jolly good!

Now that we understand event bubbling, let's mess with it! Yes, we can actually stop the bubbling process... which is probably not something you want to do... but you might already be doing it accidentally.

Leave a comment!

  • 2020-06-30 Brandon Peterson

    Diego, thank you so much for your help, I got it working by doing the following in case someone else runs into the same problem:
    //app/config/config.yml
    Under fos_user I added
    from_email:
    address: noreply@example.com
    sender_name: Demo App

  • 2020-06-30 Diego Aguiar

    Oh, yes, you mentioned the "fos_user" error in your previous comment. I forgot to talk about it. That error comes from FOSUserBundle, it's telling you that you need to configure the from_email option in order to work. What you need to do is:


    // config/packages/fos_user.yaml
    fos_user:
    from_email: some_email@example.com

    and that's it! If you have more problems let me know :)

  • 2020-06-30 Brandon Peterson

    Diego,
    Sorry to be a pain on this.
    When I add my server IP address, I still get the error can't access the file. When I add my computer's IP address, I get the error, and when I add my WAN address, I get the error as well. When I remove the check, I get the error:
    The child node "from_email" at path "fos_user" must be configured. I did configure Apache to point to the file so I don't have to type it in every time, which is a big help.

  • 2020-06-29 Diego Aguiar

    Hey Brandon Peterson

    You can do a couple of things to workaround the You are not allowed to access this file problem. First, you can edit the app_dev.php file and remove that check, or include your IP, so your computer is allowed to run that file
    Second, you can configure your Apache virtual host config to point to app_dev.php so you don't have to include it your path

    I hope it helps but it not, let me know. Cheers!

  • 2020-06-29 Brandon Peterson

    Ryan,
    Thank you for getting back to me. I've included app_dev.php at the end of the URL but it says You are not allowed to access this file. Check app_dev.php for more information. In my situation, I can't use the local PHP server, I'm on a work computer using Windows and I don't have MySQL installed on it, and when I try to access MySQL from my Linux server on my local network it doesn't connect. I spent a better part of a day trying to get that to work. I access the Linux server from a shared folder and then access Apache by typing the IP of the server in my browser on the Windows computer. Is it possible to run the local web server from Linux and access it over the network without affecting a web site that Apache is serving that needs to remain up? When I try to run the local web server it gives me the error: The child node "from_email" at path "fos_user" must be configured. I'm planning on running through the entire java script courses, and it looks like there are others that use Symfony 3. I've only started learning and using Symfony at version 5 so I don't know much about version 3

  • 2020-06-29 weaverryan

    Hey Brandon Peterson!

    Sorry about the issues! Let's see if we an get things worked out! From what you're telling me, it *sounds* like you're loading the site in "prod" mode (instead of "dev" mode), which would explain why you see things, but things never change (prod mode caches everything). And this might be simply because the version of Symfony that this tutorial is built on is getting old. In Symfony 3, in order to access "dev" mode, you need to execute the web/app_dev.php file. That usually means you need to go to <http: localhost:8000="" app_dev.php<="" code=""> - if you don't have the app_dev.php part, then index.php is executed, which runs Symfony in the prod environment. This is how Symfony *used* to do environments.

    But, you've probably noticed that I do NOT have the app_dev.php part in the URL in this tutorial. That's because if you use Symfony's built-in web server (i.e. bin/console server:run) then it configures itself so that app_dev.php is executed, even if it's not in the URL.

    Phew! That's a long way to say that I *think* I know the problem and you can either solve it by (A) using the Symfony built-in web server or (B) add app_dev.php to the end of the URL.

    Let me know if that helps!

    Cheers!

  • 2020-06-26 Brandon Peterson

    I'm not sure what I'm doing wrong, but when I download the course code and install like the README says, everything is fine until I make changes to the index.html.twig file, the changes aren't showing in the web browser. I've downloaded other course scripts before and never had any issue. If I make a change to base.html.twig none of the changes are presented as well. Like I simply change the title from Find Something to Lift! to Test and it doesn't change. Any suggestions? If I make changes to RepLog.php, those changes happen. Any suggestions?