Item5569: ActionTracker: safely closing the pop-up window

pencil
Priority: Enhancement
Current State: No Action Required
Released In:
Target Release: n/a
Applies To: Extension
Component: ActionTrackerPlugin
Branches:
Reported By: TWiki:Main.SeanCMorgan
Waiting For:
Last Change By: CrawfordCurrie
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.
  1. Does this work on all the commonest browsers (Firefox, IE, Safari)?
  2. 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).
  3. 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

  1. 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).
  2. 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*;.*/;
  3. 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:
  1. The div tag (<div id="DivPos" style="display:none;"></div>) serves two purposes:
    1. It stores the location that the browser is currently scrolled to.
    2. 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?]
  2. 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! wink

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

ItemTemplate edit

Summary ActionTracker: safely closing the pop-up window
ReportedBy TWiki:Main.SeanCMorgan
Codebase
SVN Range TWiki-5.0.0, Tue, 15 Apr 2008, build 16676
AppliesTo Extension
Component ActionTrackerPlugin
Priority Enhancement
CurrentState No Action Required
WaitingFor
Checkins
TargetRelease n/a
ReleasedIn
Topic revision: r10 - 26 Aug 2010, CrawfordCurrie
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy