Item5569: ActionTracker: safely closing the pop-up window
Priority: Enhancement
Current State: No Action Required
Released In:
Target Release: n/a
Here's a javascript fix to safely close the pop-up window for edit action items:
<script language='JavaScript' type='text/javascript'>
// If arrived here (which is possibly an old meeting) from the
// action editor, the data has already been successfully saved.
// So it is now safe to reload the opener, and close this window.
myRE = /skin=action%2cpattern;atp_action/;
if (document.referrer.match(myRE)) {
window.opener.location.reload(true); // 'true' forces the cache to be ignored
window.close();
}
</script>
After editing an action item, the pop-up window displays the topic that the action item was created in: if you are using this for meeting minutes, that will usually be the minutes for a previous meeting and not the current one. So to implement this, the script needs to appear in each topic where items are created, so that the old minutes are closed, and the new ones are reloaded. If you have used a template (e.g., MeetingViewTemplate), just put it in there, and you're done.
Further enhancement: when it reloads the parent, it's at the top of the page, rather than at the position where the 'edit' link was first clicked. The user has to scroll-down to see the change. Obviously a 'name' tag on the item and reload would help.
--
TWiki:Main/SeanCMorgan - 27 Apr 2008
Sounds good.
- Does this work on all the commonest browsers (Firefox, IE, Safari)?
- Your RE is specific to
pattern
skin, which is too inflexible. It might be better to use some unique parameter - for example, myRE = /atp_return=thisisuniquetoaviewafteranactionedit/. That way you are not limiting it to use with =pattern
skin. However care has to be taken to ensure that parameter doesn't get passed on to other URLs (e.g. REST calls).
- It is possible to determine a scroll position for a window that could be passed on to the action editor, and then targeted in the return.
function getScrollPosition() {
var y = ((typeof window.pageYOffset != 'undefined') ? window.pageYOffset : document.scrollTop);
var x = ((typeof window.pageXOffset != 'undefined') ? window.pageXOffset : document.scrollLeft);
return {x: x, y: y};
};
Then, when the document is shown again, you just:
window.scrollTo(x, y);
Of course this requires some additional logic in the perl code. If you passed the scroll location as the value of the
atp_return
parameter, you could kill two birds with one stone.
i look forward to checking in your patch.....
--
CrawfordCurrie - 12 May 2008
- It works on IE6 and IE7, and should work on all but ancient browsers (according to http://en.wikipedia.org/wiki/Comparison_of_web_browsers#JavaScript_support).
- Yes, searching for
pattern
was bad (what was I thinking?). Until atp_return
is available (next item), the combination of /bin/edit
and atp_action
should be sufficient to detect the desired state. Adding the line alert(document.referrer)
for debugging provides the string
<protocol>://<host>/bin/edit/<topic>?skin=action%2cpattern;atp_action=<uid>;...
So a better Regular Expression would be
myRE = /.*\/bin\/edit\/.*\?.*;atp_action=\d*;.*/;
- That's cool. I looked for something like that a while ago for another app and couldn't find anything. I'll definitely look into it.
--
TWiki:Main.SeanCMorgan - 12 May 2008
On point #3, here a fix for the scrolling
Just before the pop-up closes, the parent browser window is reloaded to ensure that the updated information is displayed. Unfortunately a reload leaves the browser at the top of the page instead of where the 'edit' link was clicked. If there are a lot of action items on the pge, it can take time find where we were. A javascript modification was used to write the scroll offset into the topic itself, and to scroll back down to it.
Perhaps it's a bit of overkill, but it updates the scroll position every second, so that the correct value is used when an 'edit' link is clicked.
[SMELL: instead of polling, add an
onclick
call to ActionTracker's edit links?].
There are two components to this hack: 1) an invisible 'div' tag, and 2) custom javascript:
- The
div
tag (<div id="DivPos" style="display:none;"></div>)
serves two purposes:
- It stores the location that the browser is currently scrolled to.
- By placing the
<div>
at the end of the document, the fact that it can be accessed means that the page has fully loaded. The page can then be scrolled down to the saved position. [SMELL: I had difficulty detecting when the page was finished loading, and finally settled on this method, even though it means more of a lag before the pop-up window can close. Normally the scrollTo
command would be included in the onLoad
event, but it isn't accessible in TWiki?]
- The javascript to close the edit window isn't quite so simple anymore...
<script language='JavaScript' type='text/javascript'>
myRegExp = /.*\/bin\/edit\/.*\?.*;atp_action=\d*;.*/;
if (document.referrer.match(myRegExp)) {
// Arrived here (which is possibly an old meeting) from the action
// edit window, which means the data was successfully saved. So it
// is now safe to reload the opener and close this window.
yOffset = window.opener.DivPos.innerHTML;
window.opener.location.reload(true); // 'true' forces cache to be ignored
scrollAfterLoad(yOffset); // Can't scroll down before the page has loaded
} else {
setInterval("scrollPos()", 1000); // Start polling for scroll position
}
function scrollAfterLoad(yOffset)
{
try {
window.opener.DivPos.innerHTML; // The page has loaded if DivPos is accessible.
} catch(err) {
setTimeout('scrollAfterLoad(yOffset);', 250); // wait then try it again
}
if(!err) {
// *Not* part of 'try', else the window will close. Only do this if 'try' worked.
window.opener.scrollTo(0,yOffset);
window.close();
}
}
function scrollPos() {
// Browser-tolerant detection of scroll position, from http://javascript.about.com/library/blbomfunc.htm
DivPos.innerHTML =
typeof window.pageYOffset != 'undefined' ?
window.pageYOffset :
document.documentElement && document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop;
}
</script>
--
TWiki:Main.SeanCMorgan - 20 May 2008
Crikey Sean, that one is almost worthy of a "most obscure solution" award!
I don't understand why this wouldn't work; assume there is an 'onclick' handler on action edit links. That handler does this:
function onclick_actionEdit(e) {
if (!e) var e = window.event; // IE
var targ;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
while (targ && (targ.nodeType == 3 || targ.tagName != "A"))
targ = targ.parentNode;
if (!targ) return true;
var y = ((typeof window.pageYOffset != 'undefined') ? window.pageYOffset : document.scrollTop);
var x = ((typeof window.pageXOffset != 'undefined') ? window.pageXOffset : document.scrollLeft);
targ.href += ";atp_return=" + x + "," + y;
return true;
}
then using your first code again:
// If arrived here (which is possibly an old meeting) from the
// action editor, the data has already been successfully saved.
// So it is now safe to reload the opener, and close this window.
if (var match = /atp_return=(\d+),(\d+)/.exec(document.referrer)) {
var opener = window.opener;
window.close();
opener.location.reload(true); // 'true' forces the cache to be ignored
opener.scrollTo(match[1], match[2]);
}
I haven't tried this, but I
think it should work. OK, so it won't always scroll to exactly the right place, but it seems a lot simpler to me....
--
CrawfordCurrie - 21 May 2008
ok, to ask a stupid q, why are you not using twistie plugin to show&hide your 'popup'? It works, and is already in the default install.
Basically, if you have a twistie that contains a div that you
position:absolute
, and otherwise style, you get popup dialogs.
--
TWiki:Main.SvenDowideit - 21 May 2008
For that matter, why am I not using Dojo widgets? Because the action tracker predates all of that, that's why. Some day I'll recode it to make use of all the new features that have come along since it was written, but not any time soon, I fear.
--
TWiki:Main.CrawfordCurrie - 21 May 2008