People have been asking how to refresh a part of the page after something has been flagged. (example.)
While refreshing part of the page is the task of some other rmodule, not of ours, our module at least has the duty to notify contributed code that "I've just flagged something".
This patch addresses this problem. It introduces a "flagSuccess" event contributed code can subscribe to.
For example, a user can add the following to her theme's javascript:
$(document).bind('flagSuccess', function(event, data) {
if (data.contentType == 'node') {
alert('Node number ' + data.contentId + ' has been ' + data.flagStatus + ' using flag ' + data.flagName);
// ...refresh some block on the page...
}
});
Comments
Comment #1
mooffie commentedComments:
data.link) in case the user wants to to something with that area of the page. (Incidentally, users are asking: "How can I remove the message popup after 5 seconds?" Now there's the means to do this.)Comment #2
smitty commentedThat's really good news!
I applied this patch to the 5.x-1.0-beta6 version and at least it seems to cause no problems.
But now I don't know where to put the js-code and what to fill in to "// ...refresh some block on the page...".
Sadly I have only very little experience in js and I don't know the first thing about ajax.
I'm using the garland theme and the block is based on views (it's almost the same, which you delivered as flags_bookmarks. The only differences are: less fields and it’s a block-view instead of a page-view).
Perhaps you could give me a hint, how to go on with this or where I should look for more information? Thanks a lot!
Comment #3
mooffie commentedSmitty, the ultimate intention of this patch is that a handbook page be written and in it answers for all your questions.
I have an early draft of this page. There are still some peripheral tasks to do (like porting the 'component' module to D6, which I've just done).
Comment #4
quicksketchThis looks pretty good. I wonder if it would be better to call the "flagSuccess" event on the link rather than on the entire document. This would give some contextual information to the flagging event about which link was actually clicked.
Comment #5
mooffie commentedI don't see how this can be implemented for D5: if links are updated, or new links are brought in, the event has to be re-attached to them. D6 has Drupal.behaviors, but D5 hasn't.
That's why I put the link in 'data.link', so the event handler can see it.
The event isn't attached to the "entire" document. I happened to attach it to the document element, because it's a safe one: ajax snippets aren't likely to overwrite it.
What the
$.event.trigger('flagSuccess', [data])line does is "broadcast" the event to all 'flagSuccess' handlers, on any element. (This isn't inefficient, because jQuery keeps track of the handlers.)BTW, calling bind() doesn't remove the previous event handler, so we don't have to worry lest different snippets all doing
$(document).bind(...will clash.Comment #6
quicksketchThanks, I'm not entirely sure how the binding of custom events works so this is new territory to me. I didn't notice the
data.link = updateLink(element, data.newLink);line, which is exactly the concern I had regarding finding the "context" of which link was actually clicked.This looks like a great approach (way better than what I currently have in Fivestar, which offers something similar), so let's put it in. :)
Comment #7
mooffie commentedThis is a revised version. I splitted this event into two: "beforeLinkUpdate" and "afterLinkUpdate" (the actual namse have a "flagGlobal" prefix).
I wrote a handbook page explaining this:
Triggering JavaScript actions
Comment #8
mooffie commented(When this feature gets committed I think I'll "wontfix" the #312241: Refreshing a group of links feature request, because that feature could be implemented by refreshing part(s) of the page, as demonstrated in the handbook page.)
Comment #9
mooffie commentedNathan, are you ok with the new patch?
Comment #10
quicksketchYep, sorry I was contemplating the namespace choice of calling the method "flagGlobalAfterLinkUpdate", which seemed a bit long-winded. However after looking at the docs you put up, I think it's a reasonable name choice considering the event occurs on the entire document but actually references a single link. So, all in all, looks ready to me!
Comment #11
mooffie commentedCommitted.
http://drupal.org/cvs?commit=159199
http://drupal.org/cvs?commit=159200
The "Global" in the names is in case we have per-element events in the future.
Yeah, I don't like these long names either ...and they remind me of Win32 API.
Comment #13
witzel commentedI'm using Drupal 6. I think the handbookpage describes exactly what i need, but I haven't really understood, how to do it : I'm using Panels 3 and want to refresh the flag-view-block in my right column, when someone clicks the flag-link in my left column.
1. Do I have to install the component module?
2. What do I have to change in this handbook-page-code:
I just found these classes in my css: view-display-id-block_1 and view-dom-id-1. Is that the block ID, that i have to replace in the code and which module name do i have to fill in the code?
Sorry, you see I dont really understand what the code means, but i'd like to get it working. Thanks
Comment #14
ju.ri commentedI have exactly the same problem, just can't get it to work. can someone help with a little walk-through? I'm not even sure if my theme picks up the script correctly..
Comment #15
turbanov commentedYes, you do need to install the component module. The component module provides a way to access the specific content via an url, which we then use to replace the existing content. I'm sure there's a better way to do this all but since I don't really understand anything about javascript, this is what I managed to hack together for Drupal 6 (put this in you page.tpl.php or a separate .js file and remember to include this in your theme's info-file):
First of all, notice the Drupal.setting.base_path, there's an error in the example here. What I was trying to achieve is a live front page where users pickup items which are then added to their list of items (displayed in a block) and subsequently removed from the main view. Based on the example provided, I derived the url the Component-module provides for individual views and added the function to refresh the view.
Additionally I added the full page refresh at the end with the location.reload(true). I had a problem where the content would get loaded correctly after setting the flag once, but the second time around I would get redirected to the url from the Component module, for whatever reason. However refreshing the page in between would fix this. Thus I added the refresh call.
I've also ignored the check for whether or not the block/view exists at this point.
As you can see, I'm no javascript developer and admittedly do not fully understand what is actually going on here. However, after hours and hours of pondering I managed to achieve what I set out for, so I figured I'd share it with you. Hope it's of some help to you.