Thomas Bruederli
2014-04-27 b34d67907566663ab46b487b99817673ce4e32e5
program/js/treelist.js
@@ -1,20 +1,33 @@
/*
 +-----------------------------------------------------------------------+
 | Roundcube Treelist widget                                             |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2013, The Roundcube Dev Team                            |
 |                                                                       |
 | Licensed under the GNU General Public License version 3 or            |
 | any later version with exceptions for skins & plugins.                |
 | See the README file for a full license statement.                     |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Authors: Thomas Bruederli <roundcube@gmail.com>                       |
 +-----------------------------------------------------------------------+
 | Requires: common.js                                                   |
 +-----------------------------------------------------------------------+
*/
/**
 * Roundcube Treelist Widget
 *
 * This file is part of the Roundcube Webmail client
 *
 * @licstart  The following is the entire license notice for the
 * JavaScript code in this file.
 *
 * Copyright (c) 2013-2014, The Roundcube Dev Team
 *
 * The JavaScript code in this page is free software: you can
 * redistribute it and/or modify it under the terms of the GNU
 * General Public License (GNU GPL) as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version.  The code is distributed WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
 *
 * As additional permission under GNU GPL version 3 section 7, you
 * may distribute non-source (e.g., minimized or compacted) forms of
 * that code without the copy of the GNU GPL normally required by
 * section 4, provided you include this license notice and a URL
 * through which recipients can access the Corresponding Source.
 *
 * @licend  The above is the entire license notice
 * for the JavaScript code in this file.
 *
 * @author Thomas Bruederli <roundcube@gmail.com>
 * @requires jquery.js, common.js
 */
/**
@@ -28,6 +41,9 @@
    id_prefix: '',
    autoexpand: 1000,
    selectable: false,
    scroll_delay: 500,
    scroll_step: 5,
    scroll_speed: 20,
    check_droptarget: function(node){ return !node.virtual }
  }, p || {});
@@ -42,6 +58,7 @@
    autoexpand_item,
    body_scroll_top = 0,
    list_scroll_top = 0,
    scroll_timer,
    me = this;
@@ -52,6 +69,7 @@
  this.collapse = collapse;
  this.select = select;
  this.render = render;
  this.reset = reset;
  this.drag_start = drag_start;
  this.drag_end = drag_end;
  this.intersects = intersects;
@@ -76,6 +94,7 @@
  // register click handlers on list
  container.on('click', 'div.treetoggle', function(e){
    toggle(dom2id($(this).parent()));
    e.stopPropagation();
  });
  container.on('click', 'li', function(e){
@@ -99,11 +118,6 @@
    if (node = indexbyid[id]) {
      node.collapsed = typeof set == 'undefined' || set;
      update_dom(node);
      // Work around a bug in IE6 and IE7, see #1485309
      if (window.bw && (bw.ie6 || bw.ie7) && node.collapsed) {
        id2dom(node.id).next().children('ul:visible').hide().show();
      }
      if (recursive && node.children) {
        for (var i=0; i < node.children.length; i++) {
@@ -310,6 +324,20 @@
  }
  /**
   *
   */
  function reset()
  {
    select('');
    data = [];
    indexbyid = {};
    drag_active = false;
    container.html('');
  }
  /**
   * Render the tree list from the internal data structure
   */
  function render()
@@ -461,6 +489,7 @@
    body_scroll_top = bw.ie ? 0 : window.pageYOffset;
    list_scroll_top = container.parent().scrollTop();
    pos.top += list_scroll_top;
    drag_active = true;
    box_coords = {
@@ -476,6 +505,7 @@
      item = li.children().first().get(0);
      if (height = item.offsetHeight) {
        pos = $(item).offset();
        pos.top += list_scroll_top;
        item_coords[id] = {
          x1: pos.left,
          y1: pos.top,
@@ -485,6 +515,38 @@
        };
      }
    }
    // enable auto-scrolling of list container
    if (container.height() > container.parent().height()) {
      container.parent()
        .mousemove(function(e) {
          var scroll = 0,
            mouse = rcube_event.get_mouse_pos(e);
          mouse.y -= container.parent().offset().top;
          if (mouse.y < 25 && list_scroll_top > 0) {
            scroll = -1; // up
          }
          else if (mouse.y > container.parent().height() - 25) {
            scroll = 1; // down
          }
          if (drag_active && scroll != 0) {
            if (!scroll_timer)
              scroll_timer = window.setTimeout(function(){ drag_scroll(scroll); }, p.scroll_delay);
          }
          else if (scroll_timer) {
            window.clearTimeout(scroll_timer);
            scroll_timer = null;
          }
        })
        .mouseleave(function() {
          if (scroll_timer) {
            window.clearTimeout(scroll_timer);
            scroll_timer = null;
          }
        });
    }
  }
  /**
@@ -493,6 +555,7 @@
  function drag_end()
  {
    drag_active = false;
    scroll_timer = null;
    if (autoexpand_timer) {
      clearTimeout(autoexpand_timer);
@@ -504,16 +567,33 @@
  }
  /**
   * Scroll list container in the given direction
   */
  function drag_scroll(dir)
  {
    if (!drag_active)
      return;
    var old_top = list_scroll_top;
    container.parent().get(0).scrollTop += p.scroll_step * dir;
    list_scroll_top = container.parent().scrollTop();
    scroll_timer = null;
    if (list_scroll_top != old_top)
      scroll_timer = window.setTimeout(function(){ drag_scroll(dir); }, p.scroll_speed);
  }
  /**
   * Determine if the given mouse coords intersect the list and one if its items
   */
  function intersects(mouse, highlight)
  {
    // offsets to compensate for scrolling while dragging a message
    var boffset = bw.ie ? -document.documentElement.scrollTop : body_scroll_top,
      moffset = list_scroll_top - container.parent().scrollTop(),
      moffset = container.parent().scrollTop(),
      result = null;
    mouse.top = mouse.y + -moffset - boffset;
    mouse.top = mouse.y + moffset - boffset;
    // no intersection with list bounding box
    if (mouse.x < box_coords.x1 || mouse.x >= box_coords.x2 || mouse.top < box_coords.y1 || mouse.top >= box_coords.y2) {