Personal tools
shadowfax.org.uk logo
Views

Google Docs Listing in Google Sites

From Shadowfax

Jump to: navigation, search

This is my first attempt at scripting Google Sites. The script presented at the bottom of the page allows a script widget to be added to a Google site which adds a browsable Google Docs widget. The script takes one parameter col which provides the root collection from which to start browsing.

Contents

Installing the widget

To add the script to a site:

  • Click Manage Site from the More Actions menu
  • Click Apps Scripts in the left hand sidebar
  • Click Launch Editor
  • Copy the code below to the script editor
  • Click Save
  • Give the script a name and click Save
  • From the Share menu choose Publish as service
  • Copy the full URL listed on this page to the clipboard
  • Tick Enable Service and click Save
  • Close the script editor and return to the site
  • Navigate to the page on the site where you want the widget to appear
  • Click Edit Page
  • Click Apps Script Gadget on the Insert menu
  • Paste the URL you copied earlier into the box labelled "Or paste the URL of your Apps Script already published as a service"
  • Srcoll to the end of the URL and add the text "&col=mycollection" where mycollection is the name of the collection you wish the gadget to connect to
  • Click Select

Important The name of the collection provided is case sensitive. Google should convert spaces to %20, but if it doesn't work it is worth checking that spaces have been replaced.

Current issues with this script

Authorisation

If the script asks for authorization you need to run the script from the script editor first and authorize it. Note that currently it grants access to documents as the authorising user - so don't publish any collections which contain confidential documents.

Duplicate Collections

I've now fixed the script so that it uses folder ids not names to find folders, which means that it will no longer find incorrect sub-collections where multiple collections exist with the same name. However, it still takes a named folder to start from so it is worth ensuring that this folder name is unique

Code

// Version 0.02. Fixed duplicate collection bug
function doGet(e) {
  // Create the various UI Panels
  var app   = UiApp.createApplication();
  var spnl  = app.createScrollPanel();
  var vpnl  = app.createVerticalPanel();
  var hpnl  = app.createHorizontalPanel();
  var bcpnl = app.createHorizontalPanel();
  var gd    = app.createGrid();
  var bc    = app.createLabel('root');
 
  // Apply styles to the breadcrumb
  bc.setStyleAttribute("font-weight","bold");
  bc.setStyleAttribute("margin","5px");
 
  // Set IDs so we can reference items in Button Clicks
  gd.setId('colGrid');
  bc.setId('breadcrumb');
 
  // Use the full gadget width
  spnl.setSize('100%','200px');
  vpnl.setWidth('100%');
 
  // Get Folder
  var root= DocsList.getFolder(e.parameter['col']);
  var rootId = root.getId();
 
  // Create the buttons
  var btnHandler = app.createServerClickHandler('doClick');
  var topBtn = app.createButton("Top",btnHandler);
  topBtn.setId("top|" + e.parameter['col'] + "|" + rootId);
  hpnl.add(topBtn);
 
  var upBtn = app.createButton("Up One",btnHandler);
  upBtn.setId("up");
  upBtn.setEnabled(false);
  hpnl.add(upBtn);
 
  // Build the UI components together
  bcpnl.add(bc);
  app.add(bcpnl);
  app.add(hpnl);
  vpnl.add(gd);  
  spnl.add(vpnl);
  app.add(spnl);
 
  // initiialise the breadcrumb
  ScriptProperties.setProperty('parent',"root");
  ScriptProperties.setProperty('current',rootId);
  showBreadcrumb(bc);
 
  // Populate the grid
  gridDocs(rootId,app,gd);
 
  return app;
}
 
// Click Handler Function
function doClick(e){
  // Connect to the app
  var app = UiApp.getActiveApplication();
 
  // Work out which button has been clicked
  var loc = e.parameter['source'].split("|");
 
  // Work out the folder location from the button & enable/disable buttons as required
  if (loc[0] == "up") {
    var folder = bcPop();
    if (ScriptProperties.getProperty('parent') == "root")
      app.getElementById('up').setEnabled(false);
  }
  else {
    var folder = loc[2];
    if (loc[0] == 'top') {
      ScriptProperties.setProperty('parent','root');
      app.getElementById('up').setEnabled(false);}
    else {
      bcPush(loc[1]);
      app.getElementById('up').setEnabled(true);}
  }
 
  ScriptProperties.setProperty('current', folder);
 
  // Build the folder list and breadcrumb
  gridDocs(folder, app, app.getElementById("colGrid"));
  showBreadcrumb(app.getElementById('breadcrumb'));
  return app;
}
 
// Push an item to the end of the breadcrumb
function bcPush(item) {
  ScriptProperties.setProperty('parent',ScriptProperties.getProperty('parent') + "|" + item);
}
 
// Pop an item off the end of the breadcrumb
function bcPop() {
  var bcArr = ScriptProperties.getProperty('parent').split("|");
  var item = bcArr.pop("|");
  ScriptProperties.setProperty('parent', bcArr.join("|"));
  return item;
}
 
// Function to display the breadcrumb (path to current location)
function showBreadcrumb(bc) {
  // Construct the breadcrumb string
  var s="";
  var bcArr = ScriptProperties.getProperty('parent').split("|");
  for (var i in bcArr) {
    if (bcArr[i] == 'root') s = "Start";
    else s = s + " > " + DocsList.getFolderById(bcArr[i]).getName();
  }
 
  s = s + " > " + DocsList.getFolderById(ScriptProperties.getProperty('current')).getName();
 
  // display the breadcrumb string
  bc.setText(s);
}
 
// Function to populate the file grid
function gridDocs (f, app,gd)
{
  // Grab the top level collection plus lists of all collections and docs in it
  var root= DocsList.getFolderById(f);
  var colList = root.getFolders();
  var docs = root.getFiles();
 
  var ch = app.createServerClickHandler('doClick');
 
  // Size the grid to contain the data
  gd.resize(colList.length + docs.length, 3);
  gd.setWidth('100%');
 
  var row=0;
 
  // Build collection List
  for (i in colList) {
    addLine (colList[i].getName(),colList[i].getId(), "collection",
             colList[i].getUrl(), row, gd, app, f, ch);
    row++;
  }
 
  // build file list
  for (i in docs) {
    addLine (docs[i].getName(), docs[i].getId(), docs[i].getType(),
             docs[i].getUrl(), row, gd, app, f, ch);
    row++;
    }
}
 
// Function to add & style a line in the file grid
function addLine (fName, fId, fType, fURL, row, gd, app, folder, ch) {
  // Create labels for file and type
  var lbl = app.createLabel(fName);
  var typ = app.createLabel(fType);
 
  // Build the open/view links
  if (fType=="collection") {
    var url = app.createLabel("Open");
 
    // Style the link
    url.addClickHandler(ch);
    url.setStyleAttribute("font-weight","bold");
    url.setStyleAttribute("text-decoration","underline");
    // Can't currently set the cursor to change on hover on the link!?
    //url.setStyleAttribute("cursor","pointer");
    url.setId("open|" + folder + "|" + fId);
  }
  else var url = app.createAnchor("View",fURL);
 
  // Move the labels & links into the grid
  gd.setWidget(row,0,lbl);
  gd.setWidget(row,1,typ);
  gd.setWidget(row,2,url);
 
  // Stlye alternate rows
  if (row%2==0) {
    lbl.setStyleAttribute("background-color", "#eeeeff");
    url.setStyleAttribute("background-color", "#eeeeff");
    typ.setStyleAttribute("background-color", "#eeeeff");}
}


Leave your comment

Comments

Ian Lee. I've looked at this further and I get the error you listed if the collection that the script calls no longer exists or permissions have changed. Can you check that the collection is valid? Otherwise it does still work for me
Ian Thanks Lee. Yes; I get the same problem. Not sure why that should be. Will take a look and see if I can find out!
Lee Worked like a charm for months, but I just discovered today that it isn't working. Re-added the script to my Sites environment, and same problem. Did the change to Google Drive break the functionality of this script?

Widget displays this message:

Google Docs has encountered a server error. If reloading the page doesn't help, please contact us.

To discuss this or other issues, visit the Google Docs Help forum. To see the list of known problems, check the Google Docs Known Issues page.


Sorry, and thanks for your help!
- The Google Docs Team
Rajesh Good, very innovative work, thanks
James Excellent script! works like a charm.
tbone Great script! I modded it to get the current user info so I could map it to a specific folder ID in the user's directory. If you use something like: currentUser = Session.getActiveUser(); you can pull a folder from the current user and not have to map the folder via an id in the published service url...like so...

var root = DocsList.getFolder(userFolder);
var rootId = root.getId();
Ian @Bill. Interesting. Not sure why this should be. I'm not doing much in the way of Google scripting at present, so unlikely to find a fix in the short term. Do keep me updated though if you figure it out
Bill There is an error when the script runs for an extended period of time. It cannot find the ID of the current or previous folder...strange...
Jaime Thank you for your script, I'm using it as a test in my GA domain.
Ian If the sub-collection name is unique you can just use that. If not you could try using %2f instead of the forward slash eg folder%2fsubfolder
Filipe Pinto Hi, thanks so much for sharing your ideas.

I'm using your code. I would like to define a subcollection. How should I define a start path that is a subcollection?

Thanks!
Menu