2014-05-25 25 views
0

使用GAS我創建了一個UIapp,其中包含一棵樹和幾個(嵌套的)treeitems。 其中一些treeitems確實有複選框。關於GAS和treeitems的問題

我想知道:

1)如果一個treeitem不知道父窗口部件是已被附接到

2)如何遍歷從根開始的樹

3 )確實的方法存在檢索項目(如:item = tree.getItemById(<id>);

4)我注意到一個treeItem的onSelectionHandler將被稱爲如果(那treeitem)複選框不具有onClickHandler連接。但是如果複選框已經附加到treeitem,它將不會被調用。這可以由某人確認嗎?如果是這樣:爲什麼獨木舟會發生?我是否需要在複選框上使用回調函數才能讓treeitem知道? 5)由於使用幾百(嵌套)treeitems創建一棵樹需要很長的時間(但它的工作原理),我想要創建可見的樹部件,並且在單擊+按鈕以展開級別後,我只需添加我需要擴展樹的項目。如何檢測用戶是否單擊了treeitem旁邊的+按鈕以擴展它(使用哪個eventhandler)?

6)是否有可能重寫類樹並創建一個實現上面討論的缺失功能的派生類?

回答

0

大約三個星期前我開始調查GAS,在搜索SO時發現很多事情與其他語言相比並不容易。

難以理解的事情之一是找出事件處理程序中eventInfo中存在哪些參數。我沒有找到一篇文章如何獲取控件的名稱。但我知道這應該是可能的,因爲JSON.stringify(e)確實寫入參數的名稱。

在檢查樹時,我需要對treeItems的引用,所以我想出瞭如何獲取在事件處理程序中添加的控件的名稱。

我在樹上執行UI操作時使用onMouseUpHandler,但也可以使用其他處理程序。

函數validateParameter允許找出參數是否引用控件。 在我的應用程序中,我創建了包含複選框的treeItems,以允許識別我想顯示的文件夾。 爲了識別控件,我使用了folderId和一個包含下劃線的前綴,以便區分我添加的控件和eventInfo的其他參數。因爲我的目標是在需要的時候填充樹的某些部分(所以:在用戶點擊樹形目錄旁邊的擴展分支按鈕之後),我只是在創建時添加了「級別」指示符樹。當然這個功能可以刪除。

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

正如我使用JSON。然後再對其輸出進行解碼,這種獲得控制的方法肯定會得到改進。但就像我之前寫的那樣:我沒有找到如何做到這一點,所以我自己做了。

我想創建一個從樹派生類(也許從TreeItem爲好)做的事情是在其他語言中常見的(即檢索ITEMCOUNT()在任何層次,走在兩個方向上的樹;檢索狀態在任何時候對treeItems的複選框等),因爲那是當時真的缺失(至少在我看來),使其很難發展。

顯然,在GAS(和Javascript)僅僅3周後,我不能期望知道很多東西。由於這裏有很多人有我缺少的知識,我希望他們能通過改進代碼並告訴我如何實現。

最後一條評論: 我發現BetterLog確實使開發比標準Logger更容易。看看https://sites.google.com/site/scriptsexamples/custom-methods/betterlog#TOC-Documentation-Support-Resources