I recently had an idea for a system where page content (blocks, content types or other page content) could subscribe to being refreshed when the context of the page has changed. This idea is probably best illustrated with an example.

Take for instance, the facebook photo pages. When you navigate through the photos, the photo, comments and all associated metadata (caption, titles, etc...) also update. In Drupal, especially if you are using panels, these parts of the page will likely be built by separate pieces (panes) so refreshing them all in unison would not be so simple.

Here is my idea of how to accomplish this...

We could introduce a new AJAX command, (contentRefresh?), that would accept a hash of new contexts. These contexts would be token:value pairs, like { '%node': 1234 }. The command would loop through Drupal.settings.contentRefresh to look for content that has subscribed to this context. The settings array would look something like:

[
  { context: '%node', url: 'foo/bar/%node/ajax' },
  { context: '%user', url: 'foo/baz/%user/ajax' }
]

For any matching context, the url would have tokens replaced and then fire an ajax request. At this point, it is up to the controlling module to respond to the updated context.

Then any ajax callback that changes the page context (node navigation, etc...) should also contain this command.

This would require:

  • A javascript ajax command.
  • A matching php ajax command function.
  • A php helper function to subscribe to context changes. Basically just adds an entry to the settings array.

I will start to write something up, but wanted to get the idea out in the open to get some feedback.

CommentFileSizeAuthor
#3 ajax.context.patch3.19 KBzroger
#3 ajaxtest.tgz1.11 KBzroger
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

RobLoach’s picture

Could probably take advantage of ajax_command_replace most definitely.

Aaron Winborn shot out Block Refresh into #Drupal one day and I got distracted and started porting it to Drupal 7. The port was pretty much a complete rewrite, and I got pretty far with it, but then ended up getting distracted with jQuery 1.4 in Drupal 7 instead. I think in order to truly test the new AJAX Framework, we should port as many of these modules to 7 as we can, using the new goodness.

andrewlevine’s picture

Just want to add that in practice this would likely require unique IDs per "page content" so that the callback of the ajax request could identify which content to replace.

zroger’s picture

Status: Active » Needs review
FileSize
1.11 KB
3.19 KB

here's a first shot at a patch that will do what i suggested.

Implementation is 2 parts:
1. Any piece of content can subscribe to context changes using ctools_ajax_content_refresh_subscribe(). By subscribing, the url provided will be called in normal ctools ajax style, giving the subscribing content the chance to update itself based on the new content.
2. Any ajax callbacks that change the context of a given page should include a content_refresh command to inform the client that the current page context has changed.

I've included a sample test module that uses a ctools ajax link to update one piece of content with info from a random node. That ajax update uses a content_refresh command to notify all subscribers on the page that a new node is being viewed. The second piece of content display the number of comments for the given node, and will update itself according to the new random node generated by the first callback.

RobLoach’s picture

Do you have a use case in core that could take advantage of this?

merlinofchaos’s picture

I've read through this a few times and I'm trying to wrap my head around it fully.

One of the problems that needs addressing is that there's no way to identify a single pane in page manager. This looks like it's trying to get around that, but what I'd rather do, is provide a way to identify a single pane in page manager and update it. However, there is still the question of how you make multiple panes interact.

I'm having trouble feeling whether or not this really solves very much. In particular, you've got 'initial values' for contexts, but those only work if your contexts come from arguments. But what if they come from other sources? (i.e, relationships?)

andrewlevine’s picture

merlinofchaos, I talked about this patch with zroger a bit before he submitted so I think I can comment.

This patch was meant to be a first stepping towards making panes refresh/interact, but not the solution. The patch uses jquery selectors to update content and therefore can be used by both panels and non-panels pages much like AJAX commands can. I think this makes it more flexible but obviously this doesn't solve the pane refresh problem :) IMHO I think this patch should be committable as long as it doesn't prevent us from solving the pane refresh problem (even if it doesn't solve it).

About refreshing panes:
As I alluded to in comment #2, for this to be useful in a practical application, refreshable content has to have unique IDs, which we have done in R2 (a Sony custom thing that zroger/merlin/I worked on at one point) by stuffing a random ID in the pane configuration array on Pane creation. This could probably be done much more cleanly if such a feature was added to panels itself. But this is how we currently do it in R2: When a pane is outputted to the page it always has a class of "pane-{RANDOM_ID}" (the random ID that was generated on pane creation) and when we need to identify a single pane in page manager by ID, we make an AJAX request that simply loops through all task handlers, displays, and content types on the server side, looking for a pane that has that ID. At this point the serverside has the ability to both access the data and/or call a render on this specific pane AND to modify the HTML by calling an ajax command with the .pane-{RANDOM_ID} class.

About contexts coming from other sources (relationships): I've never played with this but I don't think it would be a problem. Imagine ctools_ajax_content_refresh_subscribe() being called from within a hook_content_type_render function. It would have access to the regular $contexts variable to set its "initial values".

I can post the code that does all this in R2 if you think it would be helpful.

moonray’s picture

Another use case for unique ID's is the following:
When skinr stores settings for a panels pane, it targets the pane number. However, when you export panels, the pane numbers get reindexed making it so skinr settings no longer properly apply (I believe this might happen when you re-order panes as well). Having a unique id per pane instance (which then also gets exported) would solve this issue as well as knowing which pane to target when doing ajax refreshes.

tayzlor’s picture

subscribe - this looks useful. Currently I'm using a round-about method to try and update several areas on the page after an AHAH request has happened in a form.

moonray’s picture

Any updates?

gmclelland’s picture

subscribing

japerry’s picture

Status: Needs review » Closed (outdated)

Closing this issue as outdated as Drupal 6 ctools is not supported. If this issue is relevant for Drupal 7, feel free to re-open and mark for Drupal 7 (or 8)