File->Join Tabs experiment. Can disable through prefs.js, and I may make disabled...
authorphasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 29 Jun 2010 18:20:02 +0000 (18:20 +0000)
committerphasefx <phasefx@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Tue, 29 Jun 2010 18:20:02 +0000 (18:20 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@16830 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/web/opac/locale/en-US/lang.dtd
Open-ILS/xul/staff_client/chrome/content/main/menu.js
Open-ILS/xul/staff_client/chrome/content/main/menu_frame_menus.xul
Open-ILS/xul/staff_client/defaults/preferences/prefs.js

index 365f92e..f8ec360 100644 (file)
 <!ENTITY staff.main.menu.file.new.label "New Window">
 <!ENTITY staff.main.menu.file.new_tab.accesskey "T">
 <!ENTITY staff.main.menu.file.new_tab.label "New Tab">
+<!ENTITY staff.main.menu.file.join_tabs_horizontal.accesskey "J">
+<!ENTITY staff.main.menu.file.join_tabs_horizontal.label "Join Tabs (Horizontal)">
+<!ENTITY staff.main.menu.file.join_tabs_vertical.accesskey "V">
+<!ENTITY staff.main.menu.file.join_tabs_vertical.label "Join Tabs (Vertical)">
 <!ENTITY staff.main.menu.file.open.key "O">
 <!ENTITY staff.main.menu.file.open.label "Open Session">
 <!ENTITY staff.main.menu.file.save.key "S">
index ff628ce..9c9282f 100644 (file)
@@ -35,6 +35,11 @@ main.menu = function () {
             tabs.childNodes[i].setAttribute('accesskey','');
         }
     }
+
+    if (xulG.pref.getBoolPref('open-ils.enable_join_tabs')) {
+        document.getElementById('join_tabs_menuitem_vertical').hidden = false;
+        document.getElementById('join_tabs_menuitem_horizontal').hidden = false;
+    }
 }
 
 main.menu.prototype = {
@@ -157,6 +162,14 @@ main.menu.prototype = {
                 ['oncommand'],
                 function() { obj.new_tab(null,{'focus':true},null); }
             ],
+            'cmd_join_tabs_vertical' : [
+                ['oncommand'],
+                function() { obj.join_tabs({'orient':'vertical'}); }
+            ],
+            'cmd_join_tabs_horizontal' : [
+                ['oncommand'],
+                function() { obj.join_tabs({'orient':'horizontal'}); }
+            ],
             'cmd_close_tab' : [
                 ['oncommand'],
                 function() { obj.close_tab(); }
@@ -1277,6 +1290,11 @@ main.menu.prototype = {
         }
     },
 
+    // We keep a reference to content_params fed to tabs, so if we manipulate the DOM (say, via join_tabs),
+    // we can re-inject the content_params into the content if needed.  We have to watch out for memory leaks
+    // doing this.
+    'preserved_content_params' : {},
+
     'close_all_tabs' : function() {
         var obj = this;
         try {
@@ -1288,8 +1306,8 @@ main.menu.prototype = {
         }
     },
 
-    'close_tab' : function () {
-        var idx = this.controller.view.tabs.selectedIndex;
+    'close_tab' : function (specific_idx) {
+        var idx = specific_idx || this.controller.view.tabs.selectedIndex;
         var tab = this.controller.view.tabs.childNodes[idx];
         var panel = this.controller.view.panels.childNodes[ idx ];
         while ( panel.lastChild ) panel.removeChild( panel.lastChild );
@@ -1338,6 +1356,66 @@ main.menu.prototype = {
         }
     },
 
+    'join_tabs' : function(params) {
+        try {
+            if (!params) { params = {}; }
+            if (!params.orient) { params.orient = 'horizontal'; }
+
+            var left_idx = params.specific_idx || this.controller.view.tabs.selectedIndex;
+            var left_tab = this.controller.view.tabs.childNodes[left_idx];
+            var left_panel = this.controller.view.panels.childNodes[ left_idx ];
+
+            // Find next not-hidden tab
+            var right_idx;
+            for (var i = left_idx + 1; i<this.controller.view.tabs.childNodes.length; i++) {
+                var tab = this.controller.view.tabs.childNodes[i];
+                if (!tab.hidden && !right_idx) {
+                    right_idx = i;
+                }
+            }
+            if (!right_idx) { return; }
+
+            // Grab the content
+            var right_tab = this.controller.view.tabs.childNodes[right_idx];
+            var right_panel = this.controller.view.panels.childNodes[ right_idx ];
+
+            var left_content = left_panel.removeChild( left_panel.firstChild );
+            var right_content = right_panel.removeChild( right_panel.firstChild );
+
+            // Create a wrapper and shuffle the content
+            var box = params.orient == 'vertical' ? document.createElement('vbox') : document.createElement('hbox');
+            box.setAttribute('flex',1);
+            left_panel.appendChild(box);
+            box.appendChild(left_content);
+            var splitter = document.createElement('splitter');
+            splitter.appendChild( document.createElement('grippy') );
+            box.appendChild(splitter);
+            box.appendChild(right_content);
+
+            right_tab.hidden = true;
+            // FIXME: if we really want to combine labels for joined tabs, need to handle the cases where the content dynamically set their tab 
+            // labels with xulG.set_tab_name
+            left_tab.setAttribute('unadornedlabel', left_tab.getAttribute('unadornedlabel') + ' / ' + right_tab.getAttribute('unadornedlabel'));
+            left_tab.setAttribute('label', left_tab.getAttribute('label') + ' / ' + right_tab.getAttribute('unadornedlabel'));
+
+            // Re-apply content params, etc.
+            var left_params = this.preserved_content_params[ left_idx ];
+            var right_params = this.preserved_content_params[ right_idx ];
+            this.preserved_content_params[ left_idx ] = function() {
+                try {
+                    left_params();
+                    right_params();
+                } catch(E) {
+                    alert('Error re-applying content params after join_tabs');
+                }
+            };
+            this.preserved_content_params[ left_idx ]();
+
+        } catch(E) {
+            alert('Error in menu.js with join_tabs(): ' + E);
+        }
+    },
+
     'find_free_tab' : function() {
         var last_not_hidden = -1;
         for (var i = 0; i<this.controller.view.tabs.childNodes.length; i++) {
@@ -1507,19 +1585,8 @@ main.menu.prototype = {
             if (params.src) { help_btn.setAttribute('src', params.src); }
         }
     },
-    'set_tab' : function(url,params,content_params) {
+    'augment_content_params' : function(idx,tab,params,content_params) {
         var obj = this;
-        if (!url) url = '/xul/server/';
-        if (!url.match(/:\/\//) && !url.match(/^data:/)) url = urls.remote + url;
-        if (!params) params = {};
-        if (!content_params) content_params = {};
-        var idx = this.controller.view.tabs.selectedIndex;
-        if (params && typeof params.index != 'undefined') idx = params.index;
-        var tab = this.controller.view.tabs.childNodes[ idx ];
-        if (params.focus) tab.focus();
-        var panel = this.controller.view.panels.childNodes[ idx ];
-        while ( panel.lastChild ) panel.removeChild( panel.lastChild );
-
         content_params.new_tab = function(a,b,c) { return obj.new_tab(a,b,c); };
         content_params.set_tab = function(a,b,c) { return obj.set_tab(a,b,c); };
         content_params.close_tab = function() { return obj.close_tab(); };
@@ -1528,7 +1595,7 @@ main.menu.prototype = {
         content_params.volume_item_creator = function(a) { return obj.volume_item_creator(a); };
         content_params.get_new_session = function(a) { return obj.get_new_session(a); };
         content_params.holdings_maintenance_tab = function(a,b,c) { return obj.holdings_maintenance_tab(a,b,c); };
-        content_params.set_tab_name = function(name) { tab.setAttribute('label',(idx + 1) + ' ' + name); };
+        content_params.set_tab_name = function(name) { tab.setAttribute('unadornedlabel',name); tab.setAttribute('label',(idx + 1) + ' ' + name); };
         content_params.set_help_context = function(params) { return obj.set_help_context(params); };
         content_params.open_chrome_window = function(a,b,c) { return xulG.window.open(a,b,c); };
         content_params.url_prefix = function(url) { return obj.url_prefix(url); };
@@ -1541,6 +1608,24 @@ main.menu.prototype = {
         content_params.chrome_xulG = xulG;
         content_params._sound = xulG._sound;
         content_params._data = xulG._data;
+
+        return content_params;
+    },
+    'set_tab' : function(url,params,content_params) {
+        var obj = this;
+        if (!url) url = '/xul/server/';
+        if (!url.match(/:\/\//) && !url.match(/^data:/)) url = urls.remote + url;
+        if (!params) params = {};
+        if (!content_params) content_params = {};
+        var idx = this.controller.view.tabs.selectedIndex;
+        if (obj.preserved_content_params[idx]) { delete obj.preserved_content_params[ idx ]; }
+        if (params && typeof params.index != 'undefined') idx = params.index;
+        var tab = this.controller.view.tabs.childNodes[ idx ];
+        if (params.focus) tab.focus();
+        var panel = this.controller.view.panels.childNodes[ idx ];
+        while ( panel.lastChild ) panel.removeChild( panel.lastChild );
+
+        content_params = obj.augment_content_params(idx,tab,params,content_params);
         if (params && params.tab_name) content_params.set_tab_name( params.tab_name );
         
         var frame;
@@ -1567,6 +1652,9 @@ main.menu.prototype = {
                             'passthru_content_params' : content_params,
                         }
                     );
+                    obj.preserved_content_params[ idx ] = function() {
+                        b.passthru_content_params = content_params;
+                    }
                 } catch(E) {
                     alert(E);
                 }
@@ -1576,37 +1664,40 @@ main.menu.prototype = {
                 panel.appendChild(frame);
                 dump('creating iframe with src = ' + url + '\n');
                 frame.setAttribute('src',url);
-                try {
-                    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-                    var cw = frame.contentWindow;
-                    if (typeof cw.wrappedJSObject != 'undefined') cw = cw.wrappedJSObject;
-                    cw.IAMXUL = true;
-                    cw.xulG = content_params;
-                    cw.addEventListener(
-                        'load',
-                        function() {
-                            try {
-                                if (typeof cw.help_context_set_locally == 'undefined') {
-                                    var help_params = {
-                                        'protocol' : cw.location.protocol,
-                                        'hostname' : cw.location.hostname,
-                                        'port' : cw.location.port,
-                                        'pathname' : cw.location.pathname,
-                                        'src' : ''
-                                    };
-                                    obj.set_help_context(help_params);
-                                } else if (typeof cw.default_focus == 'function') {
-                                    cw.default_focus();
+                obj.preserved_content_params[ idx ] = function() {
+                    try {
+                        netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+                        var cw = frame.contentWindow;
+                        if (typeof cw.wrappedJSObject != 'undefined') cw = cw.wrappedJSObject;
+                        cw.IAMXUL = true;
+                        cw.xulG = content_params;
+                        cw.addEventListener(
+                            'load',
+                            function() {
+                                try {
+                                    if (typeof cw.help_context_set_locally == 'undefined') {
+                                        var help_params = {
+                                            'protocol' : cw.location.protocol,
+                                            'hostname' : cw.location.hostname,
+                                            'port' : cw.location.port,
+                                            'pathname' : cw.location.pathname,
+                                            'src' : ''
+                                        };
+                                        obj.set_help_context(help_params);
+                                    } else if (typeof cw.default_focus == 'function') {
+                                        cw.default_focus();
+                                    }
+                                } catch(E) {
+                                    obj.error.sdump('D_ERROR', 'main.menu, set_tab, onload: ' + E);
                                 }
-                            } catch(E) {
-                                obj.error.sdump('D_ERROR', 'main.menu, set_tab, onload: ' + E);
-                            }
-                        },
-                        false
-                    );
-                } catch(E) {
-                    this.error.sdump('D_ERROR', 'main.menu: ' + E);
-                }
+                            },
+                            false
+                        );
+                    } catch(E) {
+                        this.error.sdump('D_ERROR', 'main.menu: ' + E);
+                    }
+                };
+                obj.preserved_content_params[ idx ]();
             }
         } catch(E) {
             this.error.sdump('D_ERROR', 'main.menu:2: ' + E);
index 8a737ec..56731f5 100644 (file)
@@ -13,6 +13,8 @@
     <command id="cmd_new_tab" key="new-tab-key" />
     <command id="cmd_close_tab" key="close-tab-key" />
     <command id="cmd_close_all_tabs" key="close-all-tabs-key" />
+    <command id="cmd_join_tabs_vertical" label="&staff.main.menu.file.join_tabs_vertical.label;" accesskey="&staff.main.menu.file.join_tabs_vertical.accesskey;" />
+    <command id="cmd_join_tabs_horizontal" label="&staff.main.menu.file.join_tabs_horizontal.label;" accesskey="&staff.main.menu.file.join_tabs_horizontal.accesskey;" />
     <command id="cmd_shutdown" />
 
     <command id="cmd_edit_copy_buckets" />
     <menupopup id="main.menu.file.popup">
         <menuitem label="&staff.main.menu.file.new.label;" accesskey="&staff.main.menu.file.new.accesskey;" key="new-window-key" command="cmd_new_window"/>
         <menuitem label="&staff.main.menu.file.new_tab.label;" accesskey="&staff.main.menu.file.new_tab.accesskey;" key="new-tab-key" command="cmd_new_tab"/>
+        <menuitem id="join_tabs_menuitem_horizontal" hidden="true" command="cmd_join_tabs_horizontal"/>
+        <menuitem id="join_tabs_menuitem_vertical" hidden="true" command="cmd_join_tabs_vertical"/>
         <menuseparator />
         <menuitem label="&staff.main.menu.file.close_tab.label;" accesskey="&staff.main.menu.file.close_tab.accesskey;" oldaccesskey="&staff.main.menu.file.close_tab.key;" key="close-tab-key" command="cmd_close_tab"/>
         <menuitem label="&staff.main.menu.tabs.close;" accesskey="&staff.main.menu.tabs.close.accesskey;" key="close-all-tabs-key" command="cmd_close_all_tabs"/>
index 4156d4e..a89baa6 100644 (file)
@@ -6,6 +6,9 @@
 pref("open-ils.write_in_user_chrome_directory", true);
 pref("open-ils.disable_accesskeys_on_tabs", false);
 
+// Toggles for experimental features that may later become org unit settings
+pref("open-ils.enable_join_tabs", true);
+
 // We'll use this one to help brand some build information into the client, and rely on subversion keywords
 pref("open-ils.repository.headURL","$HeadURL$");
 pref("open-ils.repository.author","$Author$");