2 * (C) Copyright 2008 Jeremy Maitin-Shepard
3 * (C) Copyright 2008 Nicholas A. Zigarovich
4 * (C) Copyright 2008 John J. Foerch
6 * Use, modification, and distribution are subject to the terms specified in the
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.
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.");
27 * Constructs a tab bar for the given window.
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;
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);
54 * Destroys the tab bar.
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) {
67 this.selected_buffer = null;
68 this.element.parentNode.removeChild(this.element);
73 * Updates the "multiple" attribute of the tab bar.
75 tab_bar.prototype.update_multiple_attribute = function () {
76 if (this.window.buffers.count > 1)
77 this.element.setAttribute("multiple", "true");
79 this.element.setAttribute("multiple", "false");
84 * Adds a tab for the given buffer.
86 function tab_bar_add_buffer (buffer) {
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) {
98 buffer.window.buffers.current = buffer;
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
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) {
118 event.stopPropagation();
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);
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.
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;
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;
158 * Updates the tab of the given buffer to indicate it is the currently open one.
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.
173 function tab_bar_update_buffer_title (b) {
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.
184 function tab_bar_install (window) {
186 throw new Error("tab bar already initialized for window");
192 * Removes the tab bar from the given window.
193 * If the tab bar is not installed, throws an error.
195 function tab_bar_uninstall (window) {
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);
208 function () { // disable
209 remove_hook("window_initialize_hook", tab_bar_install);
210 for_each_window(tab_bar_uninstall);