[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/webroot/rsrc/js/application/conpherence/ -> behavior-widget-pane.js (source)

   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  });


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1