CREDITS: update
[conkeror/arlinius.git] / modules / new-tabs.js
blobb3925be34e0b70097f5ed1ee2802a914161f2c23
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 require("mode.js");
16 define_variable("tab_bar_button_select", 0,
17                 "The mouse button that selects tabs." +
18                 "0 = left, 1 = middle, 2 = right, null = disabled.");
20 define_variable("tab_bar_button_close", 2,
21                 "The mouse button that closes tabs." +
22                 "0 = left, 1 = middle, 2 = right, null = disabled.");
24 /**
25  * Constructs a tab bar for the given window.
26  */
27 function tab_bar (window) {
28     window.tab_bar = this;
29     var scrollbox = create_XUL(window, "arrowscrollbox");
30     scrollbox.setAttribute("id", "tab2-bar");
31     scrollbox.setAttribute("orient", "horizontal");
32     var after = window.buffers.container;
33     this.window = window;
34     this.element = scrollbox;
35     after.parentNode.insertBefore(scrollbox, after);
37     add_hook.call(window, "select_buffer_hook", tab_bar_select_buffer);
38     add_hook.call(window, "create_buffer_early_hook", tab_bar_add_buffer);
39     add_hook.call(window, "kill_buffer_hook", tab_bar_kill_buffer);
40     add_hook.call(window, "create_buffer_hook", tab_bar_update_buffer_title);
41     add_hook.call(window, "buffer_title_change_hook", tab_bar_update_buffer_title);
42     add_hook.call(window, "buffer_description_change_hook", tab_bar_update_buffer_title);
43     //    add_hook.call(window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
44     window.buffers.for_each(tab_bar_add_buffer);
45     this.update_multiple_attribute();
46     if (window.buffers.current != null)
47         tab_bar_select_buffer(window.buffers.current);
51 /**
52  * Destroys the tab bar.
53  */
54 tab_bar.prototype.destroy = function () {
55     remove_hook.call(this.window, "select_buffer_hook", tab_bar_select_buffer);
56     remove_hook.call(this.window, "create_buffer_early_hook", tab_bar_add_buffer);
57     remove_hook.call(this.window, "kill_buffer_hook", tab_bar_kill_buffer);
58     remove_hook.call(this.window, "create_buffer_hook", tab_bar_update_buffer_title);
59     remove_hook.call(this.window, "buffer_title_change_hook", tab_bar_update_buffer_title);
60     remove_hook.call(this.window, "buffer_description_change_hook", tab_bar_update_buffer_title);
61     //    remove_hook.call(this.window, "buffer_favicon_change_hook", tab_bar_update_buffer_icon);
62     this.window.buffers.for_each(function (b) {
63             delete b.tab;
64         });
65     this.selected_buffer = null;
66     this.element.parentNode.removeChild(this.element);
70 /**
71  * Updates the "multiple" attribute of the tab bar.
72  */
73 tab_bar.prototype.update_multiple_attribute = function () {
74     if (this.window.buffers.count > 1)
75         this.element.setAttribute("multiple", "true");
76     else
77         this.element.setAttribute("multiple", "false");
81 /**
82  * Adds a tab for the given buffer.
83  */
84 function tab_bar_add_buffer (buffer) {
86     // Get the tab bar
87     var tabbar = buffer.window.tab_bar;
88     tabbar.update_multiple_attribute();
90     // Create a tab and add it to the tab bar
91     var tab = create_XUL(buffer.window, "hbox");
92     tab.setAttribute("class", "tab2");
93     tab.addEventListener("click", function (event) {
94             if (event.button == tab_bar_button_select) {
95                 if (!buffer.dead)
96                     buffer.window.buffers.current = buffer;
97             }
98         }, false /* not capturing */);
99     tab.setAttribute("selected", "false");
101     // Create the label to hold the tab number
102     // TODO: Make the numbers optional and use the favicon if that's what the
103     // user wants.
104     var iconlabel = create_XUL(buffer.window, "label");
105     iconlabel.setAttribute("class", "tab2-icon");
107     // Create the label to hold the tab title
108     var label = create_XUL(buffer.window, "label");
109     label.setAttribute("class", "tab2-label");
110     label.setAttribute("crop", "end");
112     // No close button, just use the designated mouse button.
113     tab.addEventListener("click", function (event) {
114             if (event.button == tab_bar_button_close) {
115                 kill_buffer(buffer);
116                 event.stopPropagation();
117             }
118         }, false /* not capturing */);
120     // Add all the stuff to the new tab
121     tab.appendChild(iconlabel);
122     tab.appendChild(label);
123     tab.tab_label = label;
124     tab.tab_icon = iconlabel;
125     tabbar.element.appendChild(tab);
126     buffer.tab = tab;
127     tab_bar_update_buffer_title(buffer);
129     // Set the tab number. Remember that at this point, the tab has already been
130     // added to the hbox.
131     var total = tabbar.element.getElementsByClassName("tab2").length;
132     iconlabel.value = total;
137  * Removes the tab for the given buffer.
138  */
139 function tab_bar_kill_buffer (b) {
140     var t = b.window.tab_bar;
141     t.update_multiple_attribute();
142     if (t.selected_buffer == b)
143         t.selected_buffer = null;
144     b.tab.parentNode.removeChild(b.tab);
145     t = b.window.tab_bar;
146     delete b.tab;
148     // Renumber the tabs.
149     for (var i = 0; i < t.element.childNodes.length; i++) {
150         t.element.childNodes[i].childNodes[0].value = i + 1;
151     }
156  * Updates the tab of the given buffer to indicate it is the currently open one.
157  */
158 function tab_bar_select_buffer (b) {
159     var t = b.window.tab_bar;
160     if (t.selected_buffer != null)
161         t.selected_buffer.tab.setAttribute("selected", "false");
162     t.selected_buffer = b;
163     b.tab.setAttribute("selected", "true");
164     t.element.ensureElementIsVisible(b.tab);
169  * Updates the tab title for the given buffer.
170  */
171 function tab_bar_update_buffer_title (b) {
172     var title = b.title;
173     if (title == null || title.length == 0)
174         title = b.description;
175     b.tab.tab_label.setAttribute("value", title);
180  * Inserts the tab bar in the given window.
181  */
182 function tab_bar_install (window) {
183     if (window.tab_bar)
184         throw new Error("tab bar already initialized for window");
185     new tab_bar(window);
190  * Removes the tab bar from the given window.
191  * If the tab bar is not installed, throws an error.
192  */
193 function tab_bar_uninstall (window) {
194     if (!window.tab_bar)
195         throw new Error("tab bar not initialized for window");
196     window.tab_bar.destroy();
197     delete window.tab_bar;
201 define_global_mode("tab_bar_mode",
202                    function () { // enable
203                        add_hook("window_initialize_hook", tab_bar_install);
204                        for_each_window(tab_bar_install);
205                    },
206                    function () { // disable
207                        remove_hook("window_initialize_hook", tab_bar_install);
208                        for_each_window(tab_bar_uninstall);
209                    });
211 tab_bar_mode(true);