/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
goog.provide('cam.PermanodePage');
goog.require('goog.dom');
goog.require('goog.string');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventType');
goog.require('goog.events.FileDropHandler');
goog.require('goog.ui.Component');
goog.require('cam.BlobItem');
goog.require('cam.BlobItemContainer');
goog.require('cam.ServerConnection');
// @param {cam.ServerType.DiscoveryDocument} config Global config of the current server this page is being rendered for.
// @param {goog.dom.DomHelper=} opt_domHelper DOM helper to use.
// @extends {goog.ui.Component}
// @constructor
cam.PermanodePage = function(config, opt_domHelper) {
goog.base(this, opt_domHelper);
this.config_ = config;
this.connection_ = new cam.ServerConnection(config);
this.blobItemContainer_ = new cam.BlobItemContainer(this.connection_, opt_domHelper);
this.blobItemContainer_.thumbnailSize_ = cam.BlobItemContainer.THUMBNAIL_SIZES_[3];
this.describeResponse_ = null;
};
goog.inherits(cam.PermanodePage, goog.ui.Component);
cam.PermanodePage.prototype.decorateInternal = function(element) {
cam.PermanodePage.superClass_.decorateInternal.call(this, element);
var el = this.getElement();
goog.dom.classes.add(el, 'cam-permanode-page');
};
cam.PermanodePage.prototype.disposeInternal = function() {
cam.PermanodePage.superClass_.disposeInternal.call(this);
this.eh_.dispose();
};
cam.PermanodePage.prototype.enterDocument = function() {
cam.PermanodePage.superClass_.enterDocument.call(this);
var permanode = getPermanodeParam();
if (permanode) {
goog.dom.getElement('permanode').innerHTML = "" + permanode + "";
goog.dom.getElement('permanodeBlob').innerHTML = "view blob";
}
// TODO(mpl): use this.eh_ instead?
// set up listeners
goog.events.listen(goog.dom.getElement('formTitle'), goog.events.EventType.SUBMIT, this.handleFormTitleSubmit_, false, this);
goog.events.listen(goog.dom.getElement('formTags'), goog.events.EventType.SUBMIT, this.handleFormTagsSubmit_, false, this);
goog.events.listen(goog.dom.getElement('formAccess'), goog.events.EventType.SUBMIT, this.handleFormAccessSubmit_, false, this);
goog.events.listen(goog.dom.getElement('btnGallery'), goog.events.EventType.CLICK, function() {
var btnGallery = goog.dom.getElement('btnGallery');
if (btnGallery.value == "list") {
goog.dom.setTextContent(btnGallery, "List");
btnGallery.value = "thumbnails";
} else {
goog.dom.setTextContent(btnGallery, "Thumbnails");
btnGallery.value = "list";
}
this.reloadMembers_();
}, false, this);
// set publish roots
this.setupRootsDropdown_();
// set dnd and form for file upload
this.setupFilesHandlers_();
this.describeBlob_()
this.buildPathsList_()
this.blobItemContainer_.render(goog.dom.getElement('membersThumbs'));
};
// Gets the |p| query parameter, assuming that it looks like a blobref.
function getPermanodeParam() {
var blobRef = getQueryParam('p');
return (blobRef && isPlausibleBlobRef(blobRef)) ? blobRef : null;
};
cam.PermanodePage.prototype.exitDocument = function() {
cam.PermanodePage.superClass_.exitDocument.call(this);
};
cam.PermanodePage.prototype.describeBlob_ = function() {
var permanode = getPermanodeParam();
var constraint = {
blobRefPrefix: permanode,
camliType: 'permanode'
};
var describeReq = {
depth: 1,
thumbnailSize: this.blobItemContainer_.thumbnailSize_,
rules: [
{
attrs: ['camliContent', 'camliContentImage', 'camliMember']
}
],
};
this.connection_.search(constraint, describeReq, null, null,
goog.bind(this.handleDescribeBlob_, this, permanode)
);
};
// @param {string} permanode Node to describe.
// @param {Object} searchResponse Response for the search query on the permanode.
cam.PermanodePage.prototype.handleDescribeBlob_ = function(permanode, searchResponse) {
var describeResult = searchResponse.description;
var meta = describeResult.meta;
if (!meta[permanode]) {
alert("didn't get blob " + permanode);
return;
}
var permObj = meta[permanode].permanode;
if (!permObj) {
alert("blob " + permanode + " isn't a permanode");
return;
}
this.describeResponse_ = describeResult;
// title form
var permTitleValue = permAttr(permObj, "title") ? permAttr(permObj, "title") : "";
var inputTitle = goog.dom.getElement("inputTitle");
inputTitle.value = permTitleValue;
inputTitle.disabled = false;
var btnSaveTitle = goog.dom.getElement("btnSaveTitle");
btnSaveTitle.disabled = false;
// tags form
this.reloadTags_(permanode, describeResult);
var inputNewTag = goog.dom.getElement("inputNewTag");
inputNewTag.disabled = false;
var btnAddTag = goog.dom.getElement("btnAddTag");
btnAddTag.disabled = false;
// access form
var selectAccess = goog.dom.getElement("selectAccess");
var accessValue = permAttr(permObj,"camliAccess") ? permAttr(permObj,"camliAccess") : "private";
selectAccess.value = accessValue;
selectAccess.disabled = false;
var btnSaveAccess = goog.dom.getElement("btnSaveAccess");
btnSaveAccess.disabled = false;
// handle type detection
handleType(permObj);
// TODO(mpl): add a line showing something like
// "Content: file (blobref)" or
// "Content: directory (blobref)" or
// "Content: None (has members)".
// members
this.reloadMembers_();
// TODO(mpl): use a permanent blobItemContainer instead?
/* blob content */
var camliContent = permObj.attr.camliContent;
if (camliContent && camliContent.length > 0) {
var content = goog.dom.getElement('content');
content.innerHTML = '';
var useFileBlobrefAsLink = "true";
var blobItem = new cam.BlobItem(permanode, meta, useFileBlobrefAsLink);
blobItem.decorate(content);
blobItem.setSize(300, 300);
// TODO(mpl): ideally this should be done by handleType, but it's easier
// to do it now that we have a blobItem object to work with.
var isdir = blobItem.getDirBlobref_()
var mountTip = goog.dom.getElement("cammountTip");
goog.dom.removeChildren(mountTip);
if (isdir != "") {
var tip = "Mount with:";
goog.dom.setTextContent(mountTip, tip);
goog.dom.appendChild(mountTip, goog.dom.createDom("br"));
var codeTip = goog.dom.createDom("code");
goog.dom.setTextContent(codeTip, "$ cammount /some/mountpoint " + isdir);
goog.dom.appendChild(mountTip, codeTip);
}
}
// debug attrs
goog.dom.setTextContent(goog.dom.getElement("debugattrs"), JSON.stringify(permObj.attr, null, 2));
};
// TODO(mpl): pass directly the permanode object
// @param {string} permanode Node to describe.
// @param {Object} describeResult Object of properties for the node.
cam.PermanodePage.prototype.reloadTags_ = function(permanode, describeResult) {
var permanodeObject = describeResult.meta[permanode].permanode;
var spanTags = document.getElementById("spanTags");
while (spanTags.firstChild) {
spanTags.removeChild(spanTags.firstChild);
}
var tags = permanodeObject.attr.tag;
for (idx in tags) {
var tag = tags[idx];
var tagSpan = goog.dom.createDom("span");
tagSpan.className = 'cam-permanode-tag-c';
var tagTextEl = goog.dom.createDom("span");
tagTextEl.className = 'cam-permanode-tag';
goog.dom.setTextContent(tagTextEl, tag);
goog.dom.appendChild(tagSpan, tagTextEl);
var tagDel = goog.dom.createDom("span");
tagDel.className = 'cam-permanode-del';
goog.dom.setTextContent(tagDel, "x");
goog.events.listen(tagDel, goog.events.EventType.CLICK, this.deleteTagFunc_(tag, tagTextEl, tagSpan), false, this);
goog.dom.appendChild(tagSpan, tagDel);
goog.dom.appendChild(spanTags, tagSpan);
}
};
// @param {Object} tag tag value to remove.
// @param {Object} strikeEle text element to strike while we wait for the removal to take effect.
// @param {Object} removeEle element to remove.
// @return {Function}
cam.PermanodePage.prototype.deleteTagFunc_ = function(tag, strikeEle, removeEle) {
var delFunc = function(e) {
strikeEle.innerHTML = "" + strikeEle.innerHTML + "";
this.connection_.newDelAttributeClaim(getPermanodeParam(), "tag", tag,
function() { removeEle.parentNode.removeChild(removeEle); },
function(msg) { alert(msg); }
);
};
return goog.bind(delFunc, this);
};
cam.PermanodePage.prototype.isCamliPathAttribute_ = function(name) {
return goog.string.startsWith(name, "camliPath:");
};
cam.PermanodePage.prototype.reloadMembers_ = function() {
var membersList = goog.dom.getElement('membersList');
var membersThumbs = goog.dom.getElement('membersThumbs');
membersList.innerHTML = '';
var meta = this.describeResponse_.meta;
var permanode = meta[getPermanodeParam()].permanode;
var attrs = permanode.attr;
var hasMembers = false;
var btnGallery = goog.dom.getElement('btnGallery');
var doThumbnails = (btnGallery.value == "thumbnails");
if (attrs.camliMember) {
attrs.camliMember.forEach(function(m) {
this.addMember_(m, "camliMember", meta, doThumbnails);
hasMembers = true;
}.bind(this));
}
for (var name in attrs) {
if (this.isCamliPathAttribute_(name)) {
var attr = permAttr(permanode, name);
if (attr) {
this.addMember_(attr, name, meta, doThumbnails);
hasMembers = true;
}
}
}
if (hasMembers) {
if (doThumbnails) {
this.blobItemContainer_.show_();
} else {
this.blobItemContainer_.hide_();
this.blobItemContainer_.resetChildren_();
}
}
};
// @param {string} pn child permanode.
// @param {Object} meta meta in describe response.
// @param {boolean} thumbnails whether to display thumbnails or a list
cam.PermanodePage.prototype.addMember_ = function(pn, path, meta, thumbnails) {
var blobItem = new cam.BlobItem(pn, meta);
if (thumbnails) {
this.blobItemContainer_.addChild(blobItem, true)
} else {
var membersList = goog.dom.getElement("membersList");
var ul;
if (membersList.innerHTML == "") {
ul = goog.dom.createDom("ul");
goog.dom.appendChild(membersList, ul);
} else {
ul = membersList.firstChild;
}
var li = goog.dom.createDom("li");
var a = goog.dom.createDom("a");
a.href = "./?p=" + pn;
goog.dom.setTextContent(a, blobItem.getTitle_());
var del = goog.dom.createDom("span");
del.className = 'cam-permanode-del';
goog.dom.setTextContent(del, "x");
goog.events.listen(del, goog.events.EventType.CLICK, this.deleteMemberFunc_(pn, path, a, li), false, this);
goog.dom.appendChild(li, a);
goog.dom.appendChild(li, del);
goog.dom.appendChild(ul, li);
}
};
// @param {string} member child permanode
// @param {Object} strikeEle text element to strike while we wait for the removal to take effect.
// @param {Object} removeEle element to remove.
// @return {Function}
cam.PermanodePage.prototype.deleteMemberFunc_ = function(member, path, strikeEle, removeEle) {
var delFunc = function(e) {
strikeEle.innerHTML = "" + strikeEle.innerHTML + "";
this.connection_.newDelAttributeClaim(getPermanodeParam(), path, member,
goog.bind(function() {
removeEle.parentNode.removeChild(removeEle);
// TODO(mpl): refreshing the whole thing is kindof heavy, maybe?
this.describeBlob_();
}, this),
function(msg) {
alert(msg);
}
);
};
return goog.bind(delFunc, this);
};
// @param {string} sourcePermanode permanode pointed by the path.
// @param {string} path path to remove.
// @param {Object} strikeEle element to remove.
// @return {Function}
cam.PermanodePage.prototype.deletePathFunc_ = function(sourcePermanode, path, strikeEle) {
var delFunc = function(e) {
strikeEle.innerHTML = "" + strikeEle.innerHTML + "";
this.connection_.newDelAttributeClaim(
sourcePermanode,
"camliPath:" + path,
getPermanodeParam(),
goog.bind(function() {
this.buildPathsList_();
}, this),
function(msg) {
alert(msg);
}
);
};
return goog.bind(delFunc, this);
};
cam.PermanodePage.prototype.handleFormTitleSubmit_ = function(e) {
e.stopPropagation();
e.preventDefault();
var inputTitle = goog.dom.getElement("inputTitle");
inputTitle.disabled = true;
var btnSaveTitle = goog.dom.getElement("btnSaveTitle");
btnSaveTitle.disabled = true;
var startTime = new Date();
this.connection_.newSetAttributeClaim(
getPermanodeParam(), "title", inputTitle.value,
goog.bind(function() {
var elapsedMs = new Date().getTime() - startTime.getTime();
setTimeout(goog.bind(function() {
inputTitle.disabled = false;
btnSaveTitle.disabled = false;
this.describeBlob_();
},this), Math.max(250 - elapsedMs, 0));
}, this),
function(msg) {
alert(msg);
inputTitle.disabled = false;
btnSaveTitle.disabled = false;
}
);
};
cam.PermanodePage.prototype.handleFormTagsSubmit_ = function(e) {
e.stopPropagation();
e.preventDefault();
var input = goog.dom.getElement("inputNewTag");
var btn = goog.dom.getElement("btnAddTag");
if (input.value == "") {
return;
}
input.disabled = true;
btn.disabled = true;
var startTime = new Date();
var tags = input.value.split(/\s*,\s*/);
var nRemain = tags.length;
var oneDone = goog.bind(function() {
nRemain--;
if (nRemain == 0) {
var elapsedMs = new Date().getTime() - startTime.getTime();
setTimeout(goog.bind(function() {
input.value = '';
input.disabled = false;
btn.disabled = false;
this.describeBlob_();
}, this), Math.max(250 - elapsedMs, 0));
}
}, this);
for (idx in tags) {
var tag = tags[idx];
this.connection_.newAddAttributeClaim(
getPermanodeParam(), "tag", tag, oneDone,
function(msg) {
alert(msg);
oneDone();
}
);
}
};
cam.PermanodePage.prototype.handleFormAccessSubmit_ = function(e) {
e.stopPropagation();
e.preventDefault();
var selectAccess = goog.dom.getElement("selectAccess");
selectAccess.disabled = true;
var btnSaveAccess = goog.dom.getElement("btnSaveAccess");
btnSaveAccess.disabled = true;
var operation = this.connection_.newDelAttributeClaim;
var value = "";
if (selectAccess.value != "private") {
operation = this.connection_.newSetAttributeClaim;
value = selectAccess.value;
}
var startTime = new Date();
operation = goog.bind(operation, this.connection_);
operation(
getPermanodeParam(),
"camliAccess",
value,
function() {
var elapsedMs = new Date().getTime() - startTime.getTime();
setTimeout(function() {
selectAccess.disabled = false;
btnSaveAccess.disabled = false;
}, Math.max(250 - elapsedMs, 0));
},
function(msg) {
alert(msg);
selectAccess.disabled = false;
btnSaveAccess.disabled = false;
}
);
};
cam.PermanodePage.prototype.setupRootsDropdown_ = function() {
var selRoots = goog.dom.getElement("selectPublishRoot");
if (!this.config_.publishRoots) {
console.log("no publish roots");
return;
}
for (var rootName in this.config_.publishRoots) {
var opt = goog.dom.createElement("option");
opt.setAttribute("value", rootName);
goog.dom.appendChild(opt, goog.dom.createTextNode(this.config_.publishRoots[rootName].prefix[0]));
goog.dom.appendChild(selRoots, opt);
}
goog.events.listen(goog.dom.getElement("btnSavePublish"), goog.events.EventType.CLICK, this.handleSavePublish_, false, this);
};
cam.PermanodePage.prototype.handleSavePublish_ = function(e) {
var selRoots = goog.dom.getElement("selectPublishRoot");
var suffix = goog.dom.getElement("publishSuffix");
var ourPermanode = getPermanodeParam();
if (!ourPermanode) {
return;
}
var publishRoot = selRoots.value;
if (!publishRoot) {
alert("no publish root selected");
return;
}
var pathSuffix = suffix.value;
if (!pathSuffix) {
alert("no path suffix specified");
return;
}
selRoots.disabled = true;
suffix.disabled = true;
var enabled = function() {
selRoots.disabled = false;
suffix.disabled = false;
};
// Step 1: resolve selRoots.value -> blobref of the root's permanode.
// Step 2: set attribute on the root's permanode, or a sub-permanode
// if multiple path components in suffix:
// "camliPath:" => permanode-of-ourselves
var sigconf = this.config_.signing;
var handleFindCamliRoot = function(pnres) {
if (!pnres.permanode) {
alert("failed to publish root's permanode");
enabled();
return;
}
var handleSetCamliPath = function() {
console.log("success.");
enabled();
selRoots.value = "";
suffix.value = "";
this.buildPathsList_();
};
var handleFailCamliPath = function() {
alert("failed to set attribute");
enabled();
};
this.connection_.newSetAttributeClaim(
pnres.permanode, "camliPath:" + pathSuffix, ourPermanode,
goog.bind(handleSetCamliPath, this), handleFailCamliPath
);
};
var handleFailFindCamliRoot = function() {
alert("failed to find publish root's permanode");
enabled();
};
this.connection_.permanodeOfSignerAttrValue(
sigconf.publicKeyBlobRef, "camliRoot", publishRoot,
goog.bind(handleFindCamliRoot, this), handleFailFindCamliRoot
);
};
cam.PermanodePage.prototype.buildPathsList_ = function() {
var ourPermanode = getPermanodeParam();
if (!ourPermanode) {
return;
}
var sigconf = this.config_.signing;
var handleFindPath = function(jres) {
var div = goog.dom.getElement("existingPaths");
// TODO: there can be multiple paths in this list, but the HTML
// UI only shows one. The UI should show all, and when adding a new one
// prompt users whether they want to add to or replace the existing one.
// For now we just update the UI to show one.
// alert(JSON.stringify(jres, null, 2));
if (jres.paths && jres.paths.length > 0) {
div.innerHTML = "Existing paths for this permanode:";
var ul = goog.dom.createElement("ul");
goog.dom.appendChild(div,ul);
for (var idx in jres.paths) {
var path = jres.paths[idx];
var li = goog.dom.createElement("li");
var span = goog.dom.createElement("span");
goog.dom.appendChild(li,span);
var blobLink = goog.dom.createElement("a");
blobLink.href = ".?p=" + path.baseRef;
goog.dom.setTextContent(blobLink, path.baseRef);
goog.dom.appendChild(span,blobLink);
goog.dom.appendChild(span,goog.dom.createTextNode(" - "));
var pathLink = goog.dom.createElement("a");
pathLink.href = "";
goog.dom.setTextContent(pathLink, path.suffix);
for (var key in this.config_.publishRoots) {
var root = this.config_.publishRoots[key];
if (root.currentPermanode == path.baseRef) {
// Prefix should include a trailing slash.
pathLink.href = root.prefix[0] + path.suffix;
// TODO: Check if we're the latest permanode
// for this path and display some "old" notice
// if not.
break;
}
}
goog.dom.appendChild(span,pathLink);
var del = goog.dom.createElement("span");
del.className = "cam-permanode-del";
goog.dom.setTextContent(del, "x");
goog.events.listen(del, goog.events.EventType.CLICK, this.deletePathFunc_(path.baseRef, path.suffix, span), false, this);
goog.dom.appendChild(span,del);
goog.dom.appendChild(ul,li);
}
} else {
div.innerHTML = "";
}
};
this.connection_.pathsOfSignerTarget(sigconf.publicKeyBlobRef, ourPermanode, goog.bind(handleFindPath, this), alert);
};
// TODO(mpl): reuse blobitem code for dnd?
cam.PermanodePage.prototype.setupFilesHandlers_ = function() {
var dnd = goog.dom.getElement("dnd");
goog.events.listen(goog.dom.getElement("fileForm"), goog.events.EventType.SUBMIT, this.handleFilesSubmit_, false, this);
goog.events.listen(goog.dom.getElement("fileInput"), goog.events.EventType.CHANGE, onFileInputChange, false, this);
var stop = function(e) {
this.classList &&
goog.dom.classes.add(this, 'cam-permanode-dnd-over');
e.stopPropagation();
e.preventDefault();
};
goog.events.listen(dnd, goog.events.EventType.DRAGENTER, stop, false, this);
goog.events.listen(dnd, goog.events.EventType.DRAGOVER, stop, false, this);
goog.events.listen(dnd, goog.events.EventType.DRAGLEAVE,
goog.bind(function() {
goog.dom.classes.remove(this, 'cam-permanode-dnd-over');
}, this), false, this);
var drop = function(e) {
goog.dom.classes.remove(this, 'cam-permanode-dnd-over');
stop(e);
var dt = e.getBrowserEvent().dataTransfer;
var files = dt.files;
goog.dom.getElement("info").innerHTML = "";
this.handleFiles_(files);
};
goog.events.listen(dnd, goog.events.FileDropHandler.EventType.DROP, goog.bind(drop, this), false, this);
};
cam.PermanodePage.prototype.handleFilesSubmit_ = function(e) {
e.stopPropagation();
e.preventDefault();
this.handleFiles_(document.getElementById("fileInput").files);
};
// @param {Array} files the files to upload.
cam.PermanodePage.prototype.handleFiles_ = function(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
this.startFileUpload_(file);
}
};
cam.PermanodePage.prototype.startFileUpload_ = function(file) {
var dnd = goog.dom.getElement("dnd");
var up = goog.dom.createElement("div");
up.className= 'cam-permanode-dnd-item';
goog.dom.appendChild(dnd, up);
var info = "name=" + file.name + " size=" + file.size + "; type=" + file.type;
var setStatus = function(status) {
up.innerHTML = info + " " + status;
};
setStatus("(scanning)");
var onFail = function(msg) {
up.innerHTML = info + " fail: ";
goog.dom.appendChild(up, goog.dom.createTextNode(msg));
};
var onGotFileSchemaRef = function(fileref) {
setStatus(" fileref: " + fileref + "");
this.connection_.createPermanode(
goog.bind(function(filepn) {
var doneWithAll = goog.bind(function() {
setStatus("- done");
this.describeBlob_();
}, this);
var addMemberToParent = function() {
setStatus("adding member");
this.connection_.newAddAttributeClaim(
getPermanodeParam(), "camliMember", filepn,
doneWithAll, onFail
);
};
var makePermanode = goog.bind(function() {
setStatus("making permanode");
this.connection_.newSetAttributeClaim(
filepn, "camliContent", fileref,
goog.bind(addMemberToParent, this), onFail
);
}, this);
makePermanode();
}, this),
onFail
);
};
this.connection_.uploadFile(file, goog.bind(onGotFileSchemaRef, this), onFail,
function(contentsRef) {
setStatus("(checking for dup of " + contentsRef + ")");
});
};
// Returns the first value from the query string corresponding to |key|.
// Returns null if the key isn't present.
getQueryParam = function(key) {
var params = document.location.search.substring(1).split('&');
for (var i = 0; i < params.length; ++i) {
var parts = params[i].split('=');
if (parts.length == 2 && decodeURIComponent(parts[0]) == key)
return decodeURIComponent(parts[1]);
}
return null;
};
// Returns true if the passed-in string might be a blobref.
isPlausibleBlobRef = function(blobRef) {
return /^\w+-[a-f0-9]+$/.test(blobRef);
};
function hasNamedMembers(permanode) {
for (var name in permanode.attr) {
if (/^camliPath:/.test(name)) {
return Boolean(permAttr(permanode, name));
}
}
return false;
}
function hasUnnamedMembers(permanode) {
return permAttr(permanode, "camliMember");
}
function permAttr(permanodeObject, name) {
if (!(name in permanodeObject.attr)) {
return null;
}
if (permanodeObject.attr[name].length == 0) {
return null;
}
return permanodeObject.attr[name][0];
};
function handleType(permObj) {
var disablePublish = false;
var selType = goog.dom.getElement("type");
var dnd = goog.dom.getElement("dnd");
var btnGallery = goog.dom.getElement("btnGallery");
var membersDiv = goog.dom.getElement("members");
dnd.style.display = "none";
btnGallery.style.visibility = 'hidden';
goog.dom.setTextContent(membersDiv, "");
if (permAttr(permObj, "camliRoot")) {
disablePublish = true; // can't give a URL to a root with a claim
} else if (hasNamedMembers(permObj) || hasUnnamedMembers(permObj)) {
dnd.style.display = "block";
btnGallery.style.visibility = 'visible';
goog.dom.setTextContent(membersDiv, "Members:");
}
goog.dom.getElement("selectPublishRoot").disabled = disablePublish;
goog.dom.getElement("publishSuffix").disabled = disablePublish;
goog.dom.getElement("btnSavePublish").disabled = disablePublish;
};
function $(id) { return goog.dom.getElement(id) }
function onFileInputChange(e) {
var s = "";
var files = $("fileInput").files;
for (var i = 0; i < files.length; i++) {
var file = files[i];
s += "" + file.name + "
";
}
var fl = $("filelist");
fl.innerHTML = s;
}