Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-5466] iOS: Expose Current Window of Tab in Tab Group

GitHub Issuen/a
TypeNew Feature
PriorityLow
StatusClosed
ResolutionWon't Fix
Resolution Date2017-05-26T19:30:20.000+0000
Affected Version/sRelease 1.8.0
Fix Version/sn/a
ComponentsiOS
Labelsn/a
ReporterDawson Toth
AssigneeIngo Muschenetz
Created2011-10-07T02:03:19.000+0000
Updated2018-08-02T22:20:03.000+0000

Description

Feature

Expose a currentWindow feature for a tab so that developers can access the visible window on the tab's stack.

Expected Behavior

Whenever a window is opened on the tab, currentWindow would point to the newly opened window. The same applies to whenever you close a window: through clicking a back button, programmatically calling tab.close(someWindow), or tapping the tab's button.

Why This Is Necessary

The end goal of this is to be able to pop back to the root window of a tab group, cleaning up and closing each window along the way. By exposing currentWindow, we give developers access to data we have internally already.

Why Name It "currentWindow"?

For parity with Ti.UI.currentWindow.

Sample Implementation

-(id)currentWindow
{
    return [current window];
}

Sample Documentation

...
  - name: window
    description: the root level tab window.  all tabs must have at least one root level tab window.
    type: Titanium.UI.Window
  - name: currentWindow
    description: The currently visible window in the tab; the window that was last opened in this tab.
    type: Titanium.UI.Window
    permission: read-only
...

Sample Consuming Code

Drop the following in an app.js. Touch "S1: Touch Me" and a series of windows will be popped on to the tab's stack. Then hit "S2: Touch Me", and the code will utilize the new currentWindow property to cascade back to the root window.
function openWindowOnStack(i) {
    var win = Ti.UI.createWindow({
        title: 'Window ' + i,
        rightNavButton: Ti.UI.createButton({ title: 'S2: Touch Me' })
    });
    win.rightNavButton.addEventListener('click', function() {
        popToRoot();
    });
    win.addEventListener('open', function() {
        Ti.API.info('Opened: ' + tab.currentWindow.title);
        if (i < 4) {
            openWindowOnStack(i + 1);
        }
    });
    win.addEventListener('close', function(evt) {
        Ti.API.info('Closed: ' + evt.source.title);
        if (evt.source.cascadeClose && !tab.currentWindow.rootWindow) {
            tab.currentWindow.cascadeClose = true;
            tab.close(tab.currentWindow, { animated: false });
        }
    });
    tab.open(win);
}

function popToRoot() {
    tab.currentWindow.cascadeClose = true;
    tab.close(tab.currentWindow, { animated: false });
}

var outer = Ti.UI.createWindow({
    title: 'Root Window',
    rightNavButton: Ti.UI.createButton({ title: 'S1: Touch Me' }),
    rootWindow: true
});
outer.rightNavButton.addEventListener('click', function() {
    openWindowOnStack(0);
});

var tabGroup = Ti.UI.createTabGroup();
var tab = Ti.UI.createTab({
    window: outer
});
tabGroup.addTab(tab);
tabGroup.open();

Comments

  1. Don Thorp 2011-10-07

    Ti.UI.currentWindow is immutable. It is injected into the JS context that the window was opened with.
  2. Dawson Toth 2011-10-07

    I'm not asking for Ti.UI.currentWindow, but a new property on the tab itself. Ti.UI.createTab({}).currentWindow. Make sense?
  3. Blain Hamon 2011-10-09

    At best, this is only going to add to confusion. CurrentWindow refers to the window which owns the context that is executing the javascript, NOT the visible window. At this late in the game, I feel very uncomfortable adding an API without giving it deep thought, especially if we have to support it in later versions. If this functionality is needed, it should be with a better and more consistent metaphor in 1.9.
  4. Dawson Toth 2011-10-10

    I trust your judgement. I've updated the example with a full JavaScript workaround that will hold the tab group in a consistent state, so long as the three guidelines at the top of the JavaScript are followed:
       /*
        To keep track of and clean up windows that have been opened on a specific tab, you must do the following:
        - Whenever you open a window, use the "openInTab(tab, win)" function.
        - On every window, listen for its "close" event and call the "trackClosedWindow(tab, win)" function.
        - Whenever you want to close all but the root window of a tab, call the "closeAllInTab(tab)" function.
        */
       
       function openWindowOnStack(i) {
           var win = Ti.UI.createWindow({
               title: 'Window ' + i,
               rightNavButton: Ti.UI.createButton({ title: 'S2: Touch Me' })
           });
           win.rightNavButton.addEventListener('click', function() {
               closeAllInTab(tab);
           });
           win.addEventListener('open', function(evt) {
               Ti.API.info('Opened: ' + evt.source.title);
               if (i < 4) {
                   openWindowOnStack(i + 1);
               }
           });
           win.addEventListener('close', function(evt) {
               Ti.API.info('Closed: ' + evt.source.title);
               trackClosedWindow(tab, evt.source);
           });
           openInTab(tab, win);
       }
       
       var outer = Ti.UI.createWindow({
           title: 'Root Window',
           rightNavButton: Ti.UI.createButton({ title: 'S1: Touch Me' })
       });
       outer.rightNavButton.addEventListener('click', function() {
           openWindowOnStack(0);
       });
       
       function trackClosedWindow(tab, window) {
           var windows = tab.windows || [];
           // Iterate through backwards because windows further down the tree are more likely to be removed.
           for (var w = windows.length - 1; w >= 0; w--) {
               if (windows[w] == window) {
                   windows[w] = null;
                   windows.splice(w, 1);
                   break;
               }
           }
           tab.windows = windows;
       }
       function closeAllInTab(tab) {
           var windows = tab.windows || [];
           // Iterate through forwards because we want to close the most recent window last for a nice animation to the root.
           for (var w = 0; w < windows.length; w++) {
               windows[w].close();
               windows[w] = null;
           }
           tab.windows = windows = [];
       }
       function openInTab(tab, window) {
           var windows = tab.windows || [];
           windows.push(window);
           tab.open(window);
           tab.windows = windows;
       }
       
       var tabGroup = Ti.UI.createTabGroup();
       var tab = Ti.UI.createTab({
           window: outer
       });
       tabGroup.addTab(tab);
       tabGroup.open();
       
  5. Blain Hamon 2011-10-10

    While I agree that there is a need, I do want to think about this, especially for parity's sake. We have the opportunity to have multiple classes to have the same design pattern. For iOS, the Root view, tab group, navGroup, and individual tabs (while they have navGroups built in on iOS) all have the same concept of having many windows, with only one visible at a time. On Android, there are some differences, so this should be addressed in planning.
  6. Hans Knöchel 2017-05-26

    Resolving as Won't Fix, since the Ti.UI.currentWindow went away in 6.0.0 as well when removing the Ti.UI.Window.url property.
  7. Eric Merriman 2018-08-02

    Closing old "Won't fix" tickets. If you disagree, please reopen.

JSON Source