Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js
12242 views
1
/**
2
* @provides javelin-behavior-aphlict-dropdown
3
* @requires javelin-behavior
4
* javelin-request
5
* javelin-stratcom
6
* javelin-vector
7
* javelin-dom
8
* javelin-uri
9
* javelin-behavior-device
10
* phabricator-title
11
* phabricator-favicon
12
*/
13
14
JX.behavior('aphlict-dropdown', function(config, statics) {
15
// Track the current globally visible menu.
16
statics.visible = statics.visible || null;
17
18
var dropdown = JX.$(config.dropdownID);
19
var bubble = JX.$(config.bubbleID);
20
var icon = JX.DOM.scry(bubble, 'span', 'menu-icon')[0];
21
var favicon = config.favicon;
22
var message_favicon = config.message_favicon;
23
24
var count;
25
if (config.countID) {
26
count = JX.$(config.countID);
27
}
28
29
var request = null;
30
var dirty = config.local ? false : true;
31
32
function _updateFavicon(new_count) {
33
if ((config.countType == 'messages') && (new_count)) {
34
JX.Favicon.setFavicon(message_favicon);
35
} else if (config.countType == 'messages') {
36
JX.Favicon.setFavicon(favicon);
37
}
38
}
39
40
if (config.countType) {
41
JX.Title.setCount(config.countType, config.countNumber);
42
_updateFavicon(config.countNumber);
43
}
44
45
function _updateCount(number) {
46
if (config.countType) {
47
JX.Title.setCount(config.countType, number);
48
_updateFavicon(number);
49
} else {
50
return;
51
}
52
53
JX.DOM.setContent(count, number);
54
if (number === 0) {
55
JX.DOM.alterClass(bubble, config.unreadClass, false);
56
} else {
57
JX.DOM.alterClass(bubble, config.unreadClass, true);
58
}
59
}
60
61
function refresh() {
62
if (dirty) {
63
JX.DOM.setContent(dropdown, config.loadingText);
64
JX.DOM.alterClass(
65
dropdown,
66
'phabricator-notification-menu-loading',
67
true);
68
}
69
70
if (request) {
71
// Already fetching.
72
return;
73
}
74
75
request = new JX.Request(config.uri, function(response) {
76
var number = response.number;
77
_updateCount(number);
78
dirty = false;
79
JX.DOM.alterClass(
80
dropdown,
81
'phabricator-notification-menu-loading',
82
false);
83
JX.DOM.setContent(dropdown, JX.$H(response.content));
84
request = null;
85
});
86
request.send();
87
}
88
89
JX.Stratcom.listen(
90
'quicksand-redraw',
91
null,
92
function (e) {
93
var data = e.getData();
94
if (!data.fromServer) {
95
return;
96
}
97
var new_data = data.newResponse.aphlictDropdownData;
98
update_counts(new_data);
99
});
100
101
JX.Stratcom.listen(
102
'conpherence-redraw-aphlict',
103
null,
104
function (e) {
105
update_counts(e.getData());
106
});
107
108
function update_counts(new_data) {
109
var updated = false;
110
for (var ii = 0; ii < new_data.length; ii++) {
111
if (new_data[ii].countType != config.countType) {
112
continue;
113
}
114
if (!new_data[ii].isInstalled) {
115
continue;
116
}
117
updated = true;
118
_updateCount(parseInt(new_data[ii].count));
119
}
120
if (updated) {
121
dirty = true;
122
}
123
}
124
125
function set_visible(menu, icon) {
126
if (menu) {
127
statics.visible = {menu: menu, icon: icon};
128
if (icon) {
129
JX.DOM.alterClass(icon, 'menu-icon-selected', true);
130
}
131
} else {
132
if (statics.visible) {
133
JX.DOM.hide(statics.visible.menu);
134
if (statics.visible.icon) {
135
JX.DOM.alterClass(statics.visible.icon, 'menu-icon-selected', false);
136
}
137
}
138
statics.visible = null;
139
}
140
}
141
142
JX.Stratcom.listen(
143
'click',
144
null,
145
function(e) {
146
if (!e.getNode('phabricator-notification-menu')) {
147
// Click outside the dropdown; hide it.
148
set_visible(null);
149
return;
150
}
151
152
if (e.getNode('tag:a')) {
153
// User clicked a link. Hide the menu, then follow the link.
154
set_visible(null);
155
return;
156
}
157
158
if (!e.getNode('notification')) {
159
// User clicked somewhere in the dead area of the menu, like the header
160
// or footer.
161
return;
162
}
163
164
// If the user clicked a notification (but missed a link) and it has a
165
// primary URI, go there.
166
var href = e.getNodeData('notification').href;
167
if (href) {
168
JX.$U(href).go();
169
e.kill();
170
set_visible(null);
171
}
172
});
173
174
JX.DOM.listen(
175
bubble,
176
'click',
177
null,
178
function(e) {
179
if (!e.isNormalClick()) {
180
return;
181
}
182
183
if (config.desktop && JX.Device.getDevice() != 'desktop') {
184
return;
185
}
186
187
e.kill();
188
189
// If a menu is currently open, close it.
190
if (statics.visible) {
191
var previously_visible = statics.visible;
192
set_visible(null);
193
194
// If the menu we just closed was the menu attached to the clicked
195
// icon, we're all done -- clicking the icon for an open menu just
196
// closes it. Otherwise, we closed some other menu and still need to
197
// open the one the user just clicked.
198
if (previously_visible.menu === dropdown) {
199
return;
200
}
201
}
202
203
if (dirty) {
204
refresh();
205
}
206
207
var p = JX.$V(bubble);
208
JX.DOM.show(dropdown);
209
210
p.y = null;
211
if (config.containerDivID) {
212
var pc = JX.$V(JX.$(config.containerDivID));
213
p.x -= (JX.Vector.getDim(dropdown).x - JX.Vector.getDim(bubble).x +
214
pc.x);
215
} else if (config.right) {
216
p.x -= (JX.Vector.getDim(dropdown).x - JX.Vector.getDim(bubble).x);
217
} else {
218
p.x -= 6;
219
}
220
p.setPos(dropdown);
221
222
set_visible(dropdown, icon);
223
}
224
);
225
226
JX.Stratcom.listen('notification-panel-update', null, function() {
227
if (config.local) {
228
return;
229
}
230
dirty = true;
231
refresh();
232
});
233
234
JX.Stratcom.listen('notification-panel-close', null, function() {
235
set_visible(null);
236
});
237
});
238
239