Checkbox 关于气体和树木的问题

Checkbox 关于气体和树木的问题,checkbox,google-apps-script,treeview,Checkbox,Google Apps Script,Treeview,我使用GAS创建了一个UIapp,其中包含一棵树和几个(嵌套的)树。 有些树确实有复选框 我想知道: 1) 如果treeitem确实知道父窗口小部件已附加到 2) 如何从根开始遍历树 3) 是否存在检索项的方法(如:item=tree.getItemById();) 4) 我注意到,如果(树项的)复选框没有连接onClickHandler,则会调用树项的onSelectionHandler。但是,如果已将复选框附加到树项,则不会调用它。有人能证实吗?如果是:为什么会发生这种情况?我是否需要复选框

我使用GAS创建了一个UIapp,其中包含一棵树和几个(嵌套的)树。 有些树确实有复选框

我想知道:

1) 如果treeitem确实知道父窗口小部件已附加到

2) 如何从根开始遍历树

3) 是否存在检索项的方法(如:
item=tree.getItemById();

4) 我注意到,如果(树项的)复选框没有连接onClickHandler,则会调用树项的onSelectionHandler。但是,如果已将复选框附加到树项,则不会调用它。有人能证实吗?如果是:为什么会发生这种情况?我是否需要复选框上的callback函数来让树元素也知道

5) 由于创建一个包含几百个(嵌套的)树元素的树需要很长时间(但效果很好),因此我想创建可见的树元素,在单击+按钮展开一个级别后,我将只添加展开树所需的项目。如何检测用户是否单击treeitem旁边的+按钮以展开它(使用什么eventhandler)


6) 有没有可能重写类树并创建一个派生类来实现上面讨论的缺少的功能?

我大约3周前开始研究GAS,在搜索GAS时,我发现与其他语言相比,很多事情都不容易

困难之一是找出eventhandler中的eventInfo中存在哪些参数。我没有找到如何获取控件名称的帖子。但是我知道这应该是可能的,因为
JSON.stringify(e)
会编写参数的名称

在检查一棵树时,我需要对treeItems的引用,因此我研究了如何获取添加到eventhandler中的控件的名称

我在树上执行UI操作时使用了onMouseUpHandler,但也可以使用其他处理程序

函数validateParameter允许查明参数是否引用控件。 在我的应用程序中,我创建了包含复选框的树元素,允许识别我要显示的文件夹。 为了识别控件,我使用了folderId和包含下划线的前缀,以便区分我添加的控件和eventInfo的其他参数

由于我的目标是在需要时填充树的各个部分(因此:在用户单击树项旁边的expand-a-branch按钮后),所以我在创建树时添加了一个“级别”指示器。当然,此功能可以删除

var chkPrefix = "chk_"; // Prefix for names and ids of checkboxes on treeitems
var triPrefix = "tri_"; // Prefix for names and ids for treeitems  

var useCheckBox = true; // Test using checkboxes --> change accordingly
                        // false = Do not use checkboxes on treeitems
                        // true  = Use checkboxes on treeitems

  // Create various handlers
  var onSelectHandler = app.createServerHandler("onSelectHandler");
  var onMouseUpHandler = app.createServerHandler("onMouseUpHandler");
  var onCheckBoxHandler = app.createServerHandler("onCheckBoxHandler");  

// Create a tree of folders starting from 'My Drive' -->  to the folder you want
  var tree = app.createTree().setAnimationEnabled(true);
  var rootTree = DriveApp.getRootFolder();            // Root of the drive --> change to the folder you want
  var level = 3;    // Allowed maximum depth of the tree (0 = ALL) --> avoiding excessive runtime --> building treeitems when needed 
  var rootItem = populateFolderTree_(rootTree, tree, level); // 

  function populateFolderTree_(folder, parentItem, level)
  { // Internal function 
     var itemName = folder.getName();
     var itemId = folder.getId();
     if (useCheckBox === false)
     { // Just sho the name of the folder
        var treeItem = app.createTreeItem(itemName);
     }  
     else
     { // Create a checkbox on every treeitem 
        var chkBox = app.createCheckBox(itemName)
                        .setId(chkPrefix + itemId).setName(chkPrefix + itemId);
        chkBox.addClickHandler(onCheckBoxHandler);  // Add a handler
        var treeItem = app.createTreeItem(chkBox);
     }  
     treeItem.setId(triPrefix + itemId);
     parentItem.addItem(treeItem);

     if ((level === 0) || (level > 1))
     { // Maximum depth of the tree has not been reached (yet)
        var subLevel = level - 1;
        var subFolders = folder.getFolders();
        while (subFolders.hasNext())
        { // Recursively add subfolders
           var subFolder = subFolders.next();
           populateFolderTree_(subFolder, treeItem, subLevel);
        }  
     }

     return treeItem; // Will eventually return the root of the tree
  }  
尽管这段代码并不完整,但我相信这两部分(部分生成文件夹树,检索evenInfo的参数名称)对其他人也很有用

function onMouseUpHandler(e)
{ 
  var app = UiApp.getActiveApplication();
  var source = e.parameter.source;               // Contains the Id of the tree
  var widget = app.getElementById(source);

  Logger.log('\nOnMouseUpHandler ' + source + '    widget=' + widget.getId() + ' = ' + widget.getType());

  var eventParameters = extractParameters(e, validateParameter);
  var numParams = eventParameters.length
  if (numParams > 0)
  {  
     var keys = eventParameters.keys();
     var values = eventParameters.values(); 

     for (var i=0; i<numParams; i++)
     {
        Logger.log('key[' + i + '] = ' + keys[i] + '   value = ' + values[i]);
     };  
  };   
  return app;
}

function validateParameter(namePar, valuePar)
{ // Skip all parameters not referring to treeitems
   var accept = false;
  var xx = namePar.substr(0, chkPrefix.length);
   if (chkPrefix === namePar.substr(0, chkPrefix.length))
   {
      accept = true;
   }
   else if (triPrefix === namePar.substr(0, triPrefix.length))
   {
      accept = true;
   };
   Logger.log('namePar=' + namePar + '   accept=' + accept + '   xx=' + xx);
   return accept;
}  

function extractParameters(e, validateFunction)
{
   var text = JSON.stringify(e);

   start = text.indexOf(':{') + 1;
   letters = text.indexOf('}') - start; 

   Logger.log('text=' + text);
   var arrParameters = text.replace('"','').substr(start, letters).split(",");

   var skipValidation = ((validateFunction === null) || (validateFunction === undefined));

  // Store parameters in a hashtable 
   var statusControls = new HashTable();   // Any hashtable will do 
   var numParameters = arrParameters.length;
   for (var i=0; i<numParameters; i++)
   {
      var parameter = arrParameters[i];
      var pos = parameter.indexOf(":");
      var nameVar = parameter.substr(1, pos - 2);
      var valueVar = parameter.substr(pos + 2, parameter.length - pos - 3);
      var accept = true;
      if (skipValidation === false) accept = validateFunction(nameVar, valueVar);
      if (accept === true) statusControls.addItem(nameVar, valueVar); // Only store acceptable parameters
   }  

   return statusControls;
}
函数onMouseUpHandler(e) { var app=UiApp.getActiveApplication(); var source=e.parameter.source;//包含树的Id var widget=app.getElementById(源); Logger.log('\nMouseUpHandler'+source+'widget='+widget.getId()+'='+widget.getType()); var eventParameters=提取参数(e,validateParameter); var numParams=eventParameters.length 如果(数值大于0) { var keys=eventParameters.keys(); var values=eventParameters.values(); 对于(var i=0;i