[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 /** 2 * @requires javelin-behavior 3 * javelin-dom 4 * javelin-stratcom 5 * javelin-workflow 6 * javelin-util 7 * phabricator-notification 8 * javelin-behavior-device 9 * phuix-dropdown-menu 10 * phuix-action-list-view 11 * phuix-action-view 12 * @provides javelin-behavior-conpherence-widget-pane 13 */ 14 15 JX.behavior('conpherence-widget-pane', function(config) { 16 17 /** 18 * There can be race conditions around loading the messages or the widgets 19 * first. Keep track of what widgets we've loaded with this variable. 20 */ 21 var _loadedWidgetsID = null; 22 23 /** 24 * At any given time there can be only one selected widget. Keep track of 25 * which one it is by the user-facing name for ease of use with 26 * PhabricatorDropdownMenuItems. 27 */ 28 var _selectedWidgetName = null; 29 30 /** 31 * This is potentially built each time the user switches conpherence threads 32 * or when the result JX.Device.getDevice() changes from desktop to some 33 * other value. 34 */ 35 var buildDeviceWidgetSelector = function (data) { 36 var device_header = _getDeviceWidgetHeader(); 37 if (!device_header) { 38 return; 39 } 40 JX.DOM.show(device_header); 41 var device_menu = new JX.PHUIXDropdownMenu(device_header); 42 data.deviceMenu = true; 43 _buildWidgetSelector(device_menu, data); 44 }; 45 46 /** 47 * This is potentially built each time the user switches conpherence threads 48 * or when the result JX.Device.getDevice() changes from mobile or tablet to 49 * desktop. 50 */ 51 var buildDesktopWidgetSelector = function (data) { 52 var root = JX.DOM.find(document, 'div', 'conpherence-layout'); 53 var widget_pane = JX.DOM.find(root, 'div', 'conpherence-widget-pane'); 54 var widget_header = JX.DOM.find(widget_pane, 'a', 'widgets-selector'); 55 56 var menu = new JX.PHUIXDropdownMenu(widget_header); 57 menu 58 .setAlign('left') 59 .setOffsetY(4); 60 61 data.deviceMenu = false; 62 _buildWidgetSelector(menu, data); 63 }; 64 65 /** 66 * Workhorse that actually builds the widget selector. Note some fancy bits 67 * where we listen for the "open" event and enable / disable widgets as 68 * appropos. 69 */ 70 var _buildWidgetSelector = function (menu, data) { 71 _loadedWidgetsID = data.threadID; 72 73 var list = new JX.PHUIXActionListView(); 74 var map = {}; 75 76 var widgets = config.widgetRegistry; 77 for (var widget in widgets) { 78 var widget_data = widgets[widget]; 79 if (widget_data.deviceOnly && data.deviceMenu === false) { 80 continue; 81 } 82 83 var item = new JX.PHUIXActionView() 84 .setIcon(widget_data.icon || 'none') 85 .setName(widget_data.name) 86 .setHandler( 87 JX.bind(null, function(widget, e) { 88 toggleWidget({widget: widget}); 89 e.prevent(); 90 menu.close(); 91 }, widget)); 92 93 map[widget_data.name] = item; 94 list.addItem(item); 95 } 96 97 menu 98 .setWidth(200) 99 .setContent(list.getNode()); 100 101 menu.listen('open', function() { 102 for (var k in map) { 103 map[k].setDisabled((k == _selectedWidgetName)); 104 } 105 }); 106 }; 107 108 /** 109 * Since this is not always on the page, avoid having a repeat 110 * try / catch block and consolidate into this helper function. 111 */ 112 var _getDeviceWidgetHeader = function () { 113 var root = JX.DOM.find(document, 'div', 'conpherence-layout'); 114 var device_header = null; 115 try { 116 device_header = JX.DOM.find( 117 root, 118 'a', 119 'device-widgets-selector'); 120 } catch (ex) { 121 // is okay - no deviceWidgetHeader yet... but bail time 122 } 123 return device_header; 124 }; 125 126 /** 127 * Responder to the 'conpherence-did-redraw-thread' event, this bad boy 128 * hides or shows the device widget selector as appropros. 129 */ 130 var _didRedrawThread = function (data) { 131 if (_loadedWidgetsID === null || _loadedWidgetsID != data.threadID) { 132 return; 133 } 134 var device = JX.Device.getDevice(); 135 var device_selector = _getDeviceWidgetHeader(); 136 if (device == 'desktop') { 137 JX.DOM.hide(device_selector); 138 } else { 139 JX.DOM.show(device_selector); 140 } 141 if (data.buildDeviceWidgetSelector) { 142 buildDeviceWidgetSelector(data); 143 } 144 toggleWidget(data); 145 }; 146 JX.Stratcom.listen( 147 'conpherence-did-redraw-thread', 148 null, 149 function (e) { 150 _didRedrawThread(e.getData()); 151 } 152 ); 153 154 /** 155 * Toggling a widget involves showing / hiding the appropriate widget 156 * bodies as well as updating the selectors to have the label on the 157 * newly selected widget. 158 */ 159 var toggleWidget = function (data) { 160 var widgets = config.widgetRegistry; 161 var widget_data = widgets[data.widget]; 162 var device = JX.Device.getDevice(); 163 var is_desktop = device == 'desktop'; 164 165 if (widget_data.deviceOnly && is_desktop) { 166 return; 167 } 168 _selectedWidgetName = widget_data.name; 169 170 var device_header = _getDeviceWidgetHeader(); 171 if (device_header) { 172 // this is fragile but adding a sigil to this element is awkward 173 var device_header_spans = JX.DOM.scry(device_header, 'span'); 174 var device_header_span = device_header_spans[1]; 175 JX.DOM.setContent( 176 device_header_span, 177 widget_data.name); 178 } 179 180 // don't update the non-device selector with device only widget stuff 181 if (!widget_data.deviceOnly) { 182 var root = JX.DOM.find(document, 'div', 'conpherence-layout'); 183 var widget_pane = JX.DOM.find(root, 'div', 'conpherence-widget-pane'); 184 var widget_header = JX.DOM.find(widget_pane, 'a', 'widgets-selector'); 185 var adder = JX.DOM.find(widget_pane, 'a', 'conpherence-widget-adder'); 186 JX.DOM.setContent( 187 widget_header, 188 widget_data.name); 189 JX.DOM.appendContent( 190 widget_header, 191 JX.$N('span', { className : 'caret' })); 192 if (widget_data.hasCreate) { 193 JX.DOM.show(adder); 194 } else { 195 JX.DOM.hide(adder); 196 } 197 } 198 199 for (var widget in config.widgetRegistry) { 200 widget_data = widgets[widget]; 201 if (widget_data.deviceOnly && is_desktop) { 202 // some one off code for conpherence messages which are device-only 203 // as a widget, but shown always on the desktop 204 if (widget == 'conpherence-message-pane') { 205 JX.$(widget).style.display = 'block'; 206 JX.Stratcom.invoke('conpherence-redraw-thread', null, {}); 207 } 208 continue; 209 } 210 if (widget == data.widget) { 211 JX.$(widget).style.display = 'block'; 212 // some one off code for conpherence messages - fancier refresh tech 213 if (widget == 'conpherence-message-pane') { 214 JX.Stratcom.invoke('conpherence-redraw-thread', null, {}); 215 JX.Stratcom.invoke('conpherence-update-page-data', null, {}); 216 } 217 } else { 218 JX.$(widget).style.display = 'none'; 219 } 220 } 221 }; 222 223 JX.Stratcom.listen( 224 'conpherence-update-widgets', 225 null, 226 function (e) { 227 var data = e.getData(); 228 if (data.buildSelectors) { 229 buildDesktopWidgetSelector(data); 230 buildDeviceWidgetSelector(data); 231 } 232 if (data.toggleWidget) { 233 toggleWidget(data); 234 } 235 }); 236 237 /** 238 * Generified adding new stuff to widgets technology! 239 */ 240 JX.Stratcom.listen( 241 ['click'], 242 'conpherence-widget-adder', 243 function (e) { 244 e.kill(); 245 246 var widgets = config.widgetRegistry; 247 // the widget key might be in node data, but otherwise use the 248 // selected widget 249 var event_data = e.getNodeData('conpherence-widget-adder'); 250 var widget_key = _selectedWidgetName; 251 if (event_data.widget) { 252 widget_key = widgets[event_data.widget].name; 253 } 254 255 var widget_to_update = null; 256 var create_data = null; 257 for (var widget in widgets) { 258 if (widgets[widget].name == widget_key) { 259 create_data = widgets[widget].createData; 260 widget_to_update = widget; 261 break; 262 } 263 } 264 // this should be impossible, but hey 265 if (!widget_to_update) { 266 return; 267 } 268 var href = config.widgetBaseUpdateURI + _loadedWidgetsID + '/'; 269 if (create_data.customHref) { 270 href = create_data.customHref; 271 } 272 273 var root = JX.DOM.find(document, 'div', 'conpherence-layout'); 274 var latest_transaction_dom = JX.DOM.find( 275 root, 276 'input', 277 'latest-transaction-id'); 278 var data = { 279 latest_transaction_id : latest_transaction_dom.value, 280 action : create_data.action 281 }; 282 283 new JX.Workflow(href, data) 284 .setHandler(function (r) { 285 latest_transaction_dom.value = r.latest_transaction_id; 286 if (create_data.refreshFromResponse) { 287 var messages = null; 288 try { 289 messages = JX.DOM.find(root, 'div', 'conpherence-messages'); 290 } catch (ex) { 291 } 292 if (messages) { 293 JX.DOM.appendContent(messages, JX.$H(r.transactions)); 294 messages.scrollTop = messages.scrollHeight; 295 } 296 297 if (r.people_widget) { 298 try { 299 var people_root = JX.DOM.find(root, 'div', 'widgets-people'); 300 // update the people widget 301 JX.DOM.setContent( 302 people_root, 303 JX.$H(r.people_widget)); 304 } catch (ex) { 305 } 306 } 307 308 // otherwise let's redraw the widget somewhat lazily 309 } else { 310 JX.Stratcom.invoke( 311 'conpherence-reload-widget', 312 null, 313 { 314 threadID : _loadedWidgetsID, 315 widget : widget_to_update 316 }); 317 } 318 }) 319 .start(); 320 } 321 ); 322 323 JX.Stratcom.listen( 324 ['touchstart', 'mousedown'], 325 'remove-person', 326 function (e) { 327 var href = config.widgetBaseUpdateURI + _loadedWidgetsID + '/'; 328 var data = e.getNodeData('remove-person'); 329 // we end up re-directing to conpherence home 330 new JX.Workflow(href, data) 331 .start(); 332 } 333 ); 334 335 /* settings widget */ 336 var onsubmitSettings = function (e) { 337 e.kill(); 338 var form = e.getNode('tag:form'); 339 var button = JX.DOM.find(form, 'button'); 340 JX.Workflow.newFromForm(form) 341 .setHandler(JX.bind(this, function (r) { 342 new JX.Notification() 343 .setDuration(6000) 344 .setContent(r) 345 .show(); 346 button.disabled = ''; 347 JX.DOM.alterClass(button, 'disabled', false); 348 })) 349 .start(); 350 }; 351 352 JX.Stratcom.listen( 353 ['submit', 'didSyntheticSubmit'], 354 'notifications-update', 355 onsubmitSettings 356 ); 357 358 });
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |