ContextInstitute / bfcom

http://bfn.context.org
GNU General Public License v3.0
4 stars 1 forks source link

JS challenges with the member lists #106

Closed rgilman closed 5 years ago

rgilman commented 5 years ago

BuddyPress apparently uses ajax to load member lists. If you look at bfcom/buddypress/groups/single/members.php – which is the overall template for the group member list – you will see it ends with:

<div id="members-group-list" class="group_members dir-list" data-bp-list="group_members">
    <div id="bp-ajax-loader"><?php bp_nouveau_user_feedback( 'group-members-loading' ); ?></div>
</div><!-- .group_members.dir-list -->

rather than a direct call to the bfcom/buddypress/groups/single/members-loop.php template file that is used to fill in the list. With my general lack of JS knowledge and also my lack of understanding ajax, I'm stumped on two issue:

1) I would like more flexibility on choosing which template to use for listing the members based on a) information that can be known server-side (like how many members and what kind of group) and b) user choice (e.g. among different views). Perhaps this can all be handled in one template file each for the directory listing and the group-member listing, but I feel it would be good to have a better understand of what's going on inside the to-me black box of ajax.

2) I tried attaching a dropdown pane to the avatar images in the group-member list without success. We are already using this without issue in the header with the logo and the user image. I'm suspicious that the ajax process is getting in the way of the Foundation JS needed to create the dropdown.

I've noticed the following: In the PHP file, the user dropdown starts with <span data-toggle="user-dropdown"> . However, if you examine the page with the browser inspector, it shows <span data-toggle="user-dropdown" aria-controls="user-dropdown" data-is-focus="false" data-yeti-box="user-dropdown" aria-haspopup="true" aria-expanded="false" class="">.

When I put a comparable <span data-toggle="groupmember-dropdown-[userID]"> in the members-loop.php template, there is no such transformation and the dropdown doesn't function.

Any light you could shed on these challenges would be welcome.

iangilman commented 5 years ago

Interesting. Well, it would be good to figure out which JavaScript file is handling the loading. I'm actually having a hard time figuring that out just poking around the code base, so it might be worth doing some reading up on it. It looks like the actual AJAX call is to admin-ajax.php with a number of parameters including an action of members_filter. Whatever is doing it cleans the bp-ajax-loader out of the members-group-list and fills it with the data.

As for the fact that Foundation isn't doing the right thing, presumably that's because it runs automatically on the HTML that exists when the page loads, but it doesn't know to also run on any HTML that's created later. Presumably there's a way to tell Foundation to do its magic on a particular section of HTML. Of course you'd need to know when the AJAX call completes, which once again requires finding the code that does the AJAX call. A dumb hack for starters would be to do a setTimeout for a few seconds and running then.

iangilman commented 5 years ago

I don't know if this is relevant, but it came up in my searching:

https://codex.wordpress.org/AJAX_in_Plugins

rgilman commented 5 years ago

Thanks for this start. I'll do some more research and attempt to find the JS files for both the WP AJAX and the Foundation dropdown.

If we knew the relevant Foundation code, could we tweak it to act later/slower? It doesn't need to do it act right away since the results stay hidden until you hover over an avatar. That can't happen until the WP AJAX does its thing.

rgilman commented 5 years ago

I found a section on the Foundation JavaScript page called Adding Plugins After Page Load. Does that give you any clues about how we can work around the WP AJAX?

iangilman commented 5 years ago

Indeed... so something like this might work:

setTimeout(function() {
  $(document).foundation();
}, 2000); // Assuming 2 seconds is long enough for the data to arrive.

It's not ideal, since it won't work for people with super slow connections, but it should cover most cases. To make it better we'd have to know when the data has been loaded. Ideally we can do that by hooking into the Wordpress AJAX system some how, but I suppose another option would be to periodically check to see if bp-ajax-loader still exists or something.

rgilman commented 5 years ago

That works! I put it at the end of bfcom/buddypress/groups/single/members.php, which is the file that includes bp-ajax-loader.

Hopefully we can refine it from here but this will let me move forward on the dropdown panes.

rgilman commented 5 years ago

I think I may have a more direct solution. I've put:

<script>
    jQuery(document).foundation();
</script>

at the end of bfcom/buddypress/groups/single/members-loop.php, which is the template file called by the AJAX request. It seems to work fine and won't be run until that template is loaded.

I wonder if this could be more efficiently targeted by using reInit in some form like Foundation.reInit('dropdown-pane');.

iangilman commented 5 years ago

Great idea putting it in the template file! That might be all we need. :)

As for reInit it's hard for me to tell what the difference is. I'm basing my suggestion of using foundation off of the "Adding Plugins After Page Load" section above the section that describes reInit; it seems to describe our use case. One thing that could be done to be more efficient would be to explicitly target the area we know has added content, rather than the entire document. For instance:

jQuery('#members-group-list').foundation();

That said, if you're not noticing any performance problem perhaps it's best to stick with the more generic solution.

rgilman commented 5 years ago

The approach of putting the Foundation script in the template file called by the AJAX request seems to be good enough for now so I'm closing this issue.