Changeset 7083


Ignore:
Timestamp:
Mar 1, 2016, 1:02:17 PM (8 years ago)
Author:
Nicklas Nordborg
Message:

References #1983: Re-order columns in table listings by drag-n-drop

This seems to be working now. Tested with Firefox, IE 11, Edge and Chrome. Some cross-browser issues to get everything working in all browsers at the same time.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/clients/web/net/sf/basedb/clients/web/taglib/table/ColumnDef.java

    r6881 r7083  
    673673      if (isVisible)
    674674      {
     675        boolean allowColumnDrag = table.allowColumnDrag();
    675676        StringBuilder sb = new StringBuilder();
    676677        sb.append("<th");
    677         addIdAndStyles(sb);
     678        addIdAndStyles(sb, allowColumnDrag ? "table-col-draggable" : null);
    678679        addDynamicAttributes(sb);
     680        if (allowColumnDrag)
     681        {
     682          sb.append(" draggable=\"true\"");
     683        }
     684        sb.append(" data-column-id=\"").append(getId()).append("\"");
    679685        sb.append(">");
    680686        if (!isSortable())
  • trunk/src/clients/web/net/sf/basedb/clients/web/taglib/table/Table.java

    r6881 r7083  
    7070      subcontext=...
    7171      action=...
     72      dragcolumns=true|false|null
    7273   &gt;
    7374</pre>
     
    197198      The name of the current subcontext. Used by some child taglibs for
    198199      generating context sensitive information (ie. PresetSelector).
     200    </td>
     201  </tr>
     202  <tr>
     203    <td>dragcolumns</td>
     204    <td>null</td>
     205    <td>no</td>
     206    <td>
     207      If set, controls if columns can be re-ordered by dragging them in
     208      the GUI. If null, the feature is enabled only if the "action" and "item"
     209      attributes are not null.
    199210    </td>
    200211  </tr>
     
    325336  }
    326337
     338  private Boolean dragColumns;
     339 
     340  /**
     341    @since 3.8
     342  */
     343  public void setDragcolumns(Boolean dragColumns)
     344  {
     345    this.dragColumns = dragColumns;
     346  }
     347 
     348  public Boolean getDragcolumns()
     349  {
     350    return dragColumns;
     351  }
     352 
    327353  /**
    328354    @since 3.5
     
    586612  {
    587613    return extensionColumns;
     614  }
     615 
     616  /**
     617    Can header columns be dragged for re-ordering?
     618    If {@link #setDragcolumns(Boolean)} has been set
     619    we use that value, otherwise we only allow it
     620    if the "action" attribute has been set.
     621    @since 3.8
     622  */
     623  boolean allowColumnDrag()
     624  {
     625    return dragColumns != null ? dragColumns : getAction() != null && getItem() != null;
    588626  }
    589627 
  • trunk/www/WEB-INF/table.tld

    r6697 r7083  
    9191      <rtexprvalue>true</rtexprvalue>
    9292    </attribute>
     93    <attribute>
     94      <name>dragcolumns</name>
     95      <rtexprvalue>true</rtexprvalue>
     96    </attribute>
    9397    <dynamic-attributes>true</dynamic-attributes>
    9498  </tag>
  • trunk/www/include/scripts/table.js

    r6840 r7083  
    7878    {
    7979      Events.addEventHandler(sort[i], 'click', table.sortOnClick, attributes);
     80    }
     81   
     82    // Add 'drag-drop' handlers for moving columns
     83    var cols = element.getElementsByClassName('table-col-draggable');
     84    for (var i = 0; i < cols.length; i++)
     85    {
     86      var dropTarget = cols[i];
     87      Data.set(dropTarget, 'column-index', i);
     88      Events.addEventHandler(dropTarget, 'dragstart', table.beginColumnDrag, attributes);
     89      Events.addEventHandler(dropTarget, 'dragover', table.checkColumnDropTarget);
     90      Events.addEventHandler(dropTarget, 'dragleave', table.leaveColumnDropTarget);
     91      Events.addEventHandler(dropTarget, 'drop', table.columnDropped);
     92      Events.addEventHandler(dropTarget, 'dragend', table.endColumnDrag);
    8093    }
    8194   
     
    193206 
    194207  /**
     208    Start dragging a table column. Store table-id, column-id
     209    and column-index on the table element.
     210  */
     211  table.beginColumnDrag = function(event)
     212  {
     213    var dragSrc = {};
     214    dragSrc.tableId = Data.get(event.currentTarget, 'table-id');
     215    dragSrc.columnId = Data.get(event.currentTarget, 'column-id');
     216    dragSrc.columnIndex = Data.int(event.currentTarget, 'column-index');
     217   
     218    // Store the drag data on the <table> div
     219    Doc.element(dragSrc.tableId).dragSrc = dragSrc;
     220    event.dataTransfer.effectAllowed = 'move';
     221    // In FF, we also need to call setData() or the drag event will not start
     222    // but this results in an exception in IE!!!
     223    try
     224    {
     225      event.dataTransfer.setData('application/json', JSON.stringify(dragSrc));
     226    }
     227    catch (e)
     228    {}
     229  }
     230 
     231  /**
     232    Clean up after dragging.
     233   */
     234  table.endColumnDrag = function(event)
     235  {
     236    var tableId = Data.get(event.currentTarget, 'table-id');
     237    Doc.element(tableId).dragSrc = null;
     238  }
     239 
     240  /**
     241    Checks if dropping is allowed at this target.
     242    We only allow dragging within the same table,
     243    and the target column must be different from the
     244    source column.
     245  */
     246  table.checkColumnDropTarget = function(event)
     247  {
     248    var tableId = Data.get(event.currentTarget, 'table-id');
     249    var dragSrc = Doc.element(tableId).dragSrc;
     250   
     251    var dropLocation = table.checkTheDropTarget(dragSrc, event.currentTarget);
     252    if (dropLocation)
     253    {
     254      // Enable drop target!
     255      event.preventDefault();
     256      event.dataTransfer.dropEffect = 'move';
     257      // Left or right depending on the order or columns
     258      Doc.addClass(event.currentTarget, dropLocation < 0 ? 'table-drop-left' : 'table-drop-right');
     259    }
     260  }
     261
     262  /**
     263    Checks if dropping is allowed at this target.
     264    We only allow dragging within the same table,
     265    and the target column must be different from the
     266    source column.
     267    returns: 0 = no drop, -1 drop to left, +1 drop to right
     268  */
     269  table.checkTheDropTarget = function(dragSrc, dragTarget)
     270  {
     271    if (!dragSrc) return false;
     272    var tableId = Data.get(dragTarget, 'table-id');
     273    var columnIndex = Data.int(dragTarget, 'column-index');
     274    return tableId == dragSrc.tableId ? columnIndex - dragSrc.columnIndex : 0;
     275  }
     276 
     277  /**
     278    Remove drop indicator classes when leaving.
     279  */
     280  table.leaveColumnDropTarget = function(event)
     281  {
     282    Doc.removeClass(event.currentTarget, 'table-drop-right');
     283    Doc.removeClass(event.currentTarget, 'table-drop-left');
     284  }
     285
     286  /**
     287    Another column was dropped here!
     288  */
     289  table.columnDropped = function(event)
     290  {
     291    Doc.removeClass(event.currentTarget, 'table-drop-right');
     292    Doc.removeClass(event.currentTarget, 'table-drop-left');
     293   
     294    // Check that we can drop here
     295    var tableId = Data.get(event.currentTarget, 'table-id');
     296    var dragSrc = Doc.element(tableId).dragSrc;
     297    if (!table.checkTheDropTarget(dragSrc, event.currentTarget)) return;
     298   
     299    // Get the existing columns as an array
     300    var columns = table.getColumns(tableId);
     301    var colArray;
     302    if (columns == 'all')
     303    {
     304      // Special case, load the existing columns
     305      var colDefs = table.getColumnDefs(tableId);
     306      colArray = [];
     307      for (var colNo = 0; colNo < colDefs.length; colNo++)
     308      {
     309        var col = colDefs[colNo];
     310        if (!col.alwaysHide) colArray[colArray.length] = col.id;
     311      }
     312    }
     313    else
     314    {
     315      colArray = columns.split(',');
     316    }
     317   
     318    var indexSrc = colArray.indexOf(dragSrc.columnId);
     319    var indexDest = colArray.indexOf(Data.get(event.currentTarget, 'column-id'));
     320    // Remove the dragged column from the array
     321    if (indexSrc >= 0) colArray.splice(indexSrc, 1);
     322    // Insert the dragged column before or after the column it was dropped on
     323    if (indexDest >= 0) colArray.splice(indexDest, 0, dragSrc.columnId);
     324   
     325    // Update and submit the table
     326    columns = colArray.join(',');
     327    table.setColumns(tableId, columns);
     328  }
     329 
     330
     331  /**
    195332    Event handler for the page navigator. The actual target should
    196333    have a table-page attribute that specify the page to move to.
  • trunk/www/include/styles/main.css

    r7030 r7083  
    9797{
    9898  text-decoration: none;
     99}
     100
     101/* Draggable items have a 'drag' cursor */
     102*[draggable]
     103{
     104  cursor: move; /* IE only support 'move', but 'grab' is looking better in FF */
     105  cursor: grab;
    99106}
    100107
  • trunk/www/include/styles/table.css

    r6837 r7083  
    205205}
    206206
     207/* Indicates drop position for dragged column */
     208.itemlist div.data th.table-drop-right
     209{
     210  border-right-width: 3px;
     211  border-right-color: black;
     212  border-right-style: solid;
     213}
     214.itemlist div.data th.table-drop-left
     215{
     216  border-left-width: 3px;
     217  border-left-color: black;
     218  border-left-style: solid;
     219}
     220
    207221/* The <tbody> section defining data rows */
    208222.itemlist div.data > table > tbody.rows > tr
Note: See TracChangeset for help on using the changeset viewer.