buffer.override_keymaps: dealt with privately inside buffer
[conkeror.git] / modules / new-tabs.js
blobde9a4dd8617907a511b4d10879b8efab7bef3219
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  * (C) Copyright 2008 Nicholas A. Zigarovich
4  * (C) Copyright 2008 John J. Foerch
5  *
6  * Use, modification, and distribution are subject to the terms specified in the
7  * COPYING file.
8  *
9  * This is a tab bar which is based on tab-bar.js but makes customization of the
10  * tabs much easier. It provides sensible default styles but lets the user
11  * simply override these defaults by normal CSS.
12  **/
14 in_module(null);
16 require("mode.js");
18 define_variable("tab_bar_button_select", 0,
19                 "The mouse button that selects tabs." +
20                 "0 = left, 1 = middle, 2 = right, null = disabled.");
22 define_variable("tab_bar_button_close", 2,
23                 "The mouse button that closes tabs." +
24                 "0 = left, 1 = middle, 2 = right, null = disabled.");
26 /**
27  * Constructs a tab bar for the given window.
28  */
29 function tab_bar (window) {
30     window.tab_bar = this;
31     var scrollbox = create_XUL(window, "arrowscrollbox");
32     scrollbox.setAttribute("id", "tab2-bar");
33     scrollbox.setAttribute("orient", "horizontal");
34     var after = window.buffers.container;
35     this.window = window;
36     this.element = scrollbox;
37     after.parentNode.insertBefore(scrollbox, after);
39     add_hook.call(window, "select_buffer_hook", tab_bar_select_buffer);
40     add_hook.call(window, "create_buffer_early_hook", tab_bar_add_buffer);
41     add_hook.call(window, "kill_buffer_hook", tab_bar_kill_buffer);
42     add_hook.call(window, "create_buffer_hook", tab_bar_update_buffer_title);
43     add_hook.call(window, "buffer_title_change_hook", tab_bar_update_buffer_title);
44     add_hook.call(window, "buffer_description_change_hook", tab_bar_update_buffer_title);
45     //    add_hook.call(window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
46     window.buffers.for_each(tab_bar_add_buffer);
47     this.update_multiple_attribute();
48     if (window.buffers.current != null)
49         tab_bar_select_buffer(window.buffers.current);
53 /**
54  * Destroys the tab bar.
55  */
56 tab_bar.prototype.destroy = function () {
57     remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
58     remove_hook.call(this.window, "create_buffer_early_hook", tab_bar_add_buffer);
59     remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
60     remove_hook.call(this.window, "create_buffer_hook", tab_bar_update_buffer_title);
61     remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
62     remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
63     //    remove_hook.call(this.window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
64     this.window.buffers.for_each(function (b) {
65             delete b.tab;
66         });
67     this.selected_buffer = null;
68     this.element.parentNode.removeChild(this.element);
72 /**
73  * Updates the "multiple" attribute of the tab bar.
74  */
75 tab_bar.prototype.update_multiple_attribute = function () {
76     if (this.window.buffers.count > 1)
77         this.element.setAttribute("multiple", "true");
78     else
79         this.element.setAttribute("multiple", "false");
83 /**
84  * Adds a tab for the given buffer.
85  */
86 function tab_bar_add_buffer (buffer) {
88     // Get the tab bar
89     var tabbar = buffer.window.tab_bar;
90     tabbar.update_multiple_attribute();
92     // Create a tab and add it to the tab bar
93     var tab = create_XUL(buffer.window, "hbox");
94     tab.setAttribute("class", "tab2");
95     tab.addEventListener("click", function (event) {
96             if (event.button == tab_bar_button_select) {
97                 if (!buffer.dead)
98                     buffer.window.buffers.current = buffer;
99             }
100         }, false /* not capturing */);
101     tab.setAttribute("selected", "false");
103     // Create the label to hold the tab number
104     // TODO: Make the numbers optional and use the favicon if that's what the
105     // user wants.
106     var iconlabel = create_XUL(buffer.window, "label");
107     iconlabel.setAttribute("class", "tab2-icon");
109     // Create the label to hold the tab title
110     var label = create_XUL(buffer.window, "label");
111     label.setAttribute("class", "tab2-label");
112     label.setAttribute("crop", "end");
114     // No close button, just use the designated mouse button.
115     tab.addEventListener("click", function (event) {
116             if (event.button == tab_bar_button_close) {
117                 kill_buffer(buffer);
118                 event.stopPropagation();
119             }
120         }, false /* not capturing */);
122     // Add all the stuff to the new tab
123     tab.appendChild(iconlabel);
124     tab.appendChild(label);
125     tab.tab_label = label;
126     tab.tab_icon = iconlabel;
127     tabbar.element.appendChild(tab);
128     buffer.tab = tab;
129     tab_bar_update_buffer_title(buffer);
131     // Set the tab number. Remember that at this point, the tab has already been
132     // added to the hbox.
133     var total = tabbar.element.getElementsByClassName("tab2").length;
134     iconlabel.value = total;
139  * Removes the tab for the given buffer.
140  */
141 function tab_bar_kill_buffer (b) {
142     var t = b.window.tab_bar;
143     t.update_multiple_attribute();
144     if (t.selected_buffer == b)
145         t.selected_buffer = null;
146     b.tab.parentNode.removeChild(b.tab);
147     t = b.window.tab_bar;
148     delete b.tab;
150     // Renumber the tabs.
151     for (var i = 0; i < t.element.childNodes.length; i++) {
152         t.element.childNodes[i].childNodes[0].value = i + 1;
153     }
158  * Updates the tab of the given buffer to indicate it is the currently open one.
159  */
160 function tab_bar_select_buffer (b) {
161     var t = b.window.tab_bar;
162     if (t.selected_buffer != null)
163         t.selected_buffer.tab.setAttribute("selected", "false");
164     t.selected_buffer = b;
165     b.tab.setAttribute("selected", "true");
166     t.element.ensureElementIsVisible(b.tab);
171  * Updates the tab title for the given buffer.
172  */
173 function tab_bar_update_buffer_title (b) {
174     var title = b.title;
175     if (title == null || title.length == 0)
176         title = b.description;
177     b.tab.tab_label.setAttribute("value", title);
182  * Inserts the tab bar in the given window.
183  */
184 function tab_bar_install (window) {
185     if (window.tab_bar)
186         throw new Error("tab bar already initialized for window");
187     new tab_bar(window);
192  * Removes the tab bar from the given window.
193  * If the tab bar is not installed, throws an error.
194  */
195 function tab_bar_uninstall (window) {
196     if (!window.tab_bar)
197         throw new Error("tab bar not initialized for window");
198     window.tab_bar.destroy();
199     delete window.tab_bar;
203 define_global_mode("tab_bar_mode",
204                    function () { // enable
205                        add_hook("window_initialize_hook", tab_bar_install);
206                        for_each_window(tab_bar_install);
207                    },
208                    function () { // disable
209                        remove_hook("window_initialize_hook", tab_bar_install);
210                        for_each_window(tab_bar_uninstall);
211                    });
213 tab_bar_mode(true);
215 provide("tab-bar");
216 provide("new-tabs");