github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/server/camlistored/ui/filetree.js (about)

     1  /*
     2  Copyright 2011 The Camlistore Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  goog.provide('cam.FiletreePage');
    18  
    19  goog.require('goog.dom');
    20  goog.require('goog.events.EventType');
    21  goog.require('goog.ui.Component');
    22  
    23  goog.require('cam.ServerConnection');
    24  
    25  // @param {cam.ServerType.DiscoveryDocument} config Global config of the current server this page is being rendered for.
    26  // @param {goog.dom.DomHelper=} opt_domHelper DOM helper to use.
    27  // @extends {goog.ui.Component}
    28  // @constructor
    29  cam.FiletreePage = function(config, opt_domHelper) {
    30  	goog.base(this, opt_domHelper);
    31  
    32  	this.config_ = config;
    33  	this.connection_ = new cam.ServerConnection(config);
    34  
    35  };
    36  goog.inherits(cam.FiletreePage, goog.ui.Component);
    37  
    38  cam.FiletreePage.prototype.indentStep_ = 20;
    39  
    40  function getDirBlobrefParam() {
    41  	var blobRef = getQueryParam('d');
    42  	return (blobRef && isPlausibleBlobRef(blobRef)) ? blobRef : null;
    43  }
    44  
    45  // Returns the first value from the query string corresponding to |key|. Returns null if the key isn't present.
    46  getQueryParam = function(key) {
    47  	var params = document.location.search.substring(1).split('&');
    48  	for (var i = 0; i < params.length; ++i) {
    49  		var parts = params[i].split('=');
    50  		if (parts.length == 2 && decodeURIComponent(parts[0]) == key)
    51  			return decodeURIComponent(parts[1]);
    52  	}
    53  	return null;
    54  };
    55  
    56  // Returns true if the passed-in string might be a blobref.
    57  isPlausibleBlobRef = function(blobRef) {
    58  	return /^\w+-[a-f0-9]+$/.test(blobRef);
    59  };
    60  
    61  cam.FiletreePage.prototype.enterDocument = function() {
    62  	cam.FiletreePage.superClass_.enterDocument.call(this);
    63  	var blobref = getDirBlobrefParam();
    64  
    65  	if (blobref) {
    66  		this.connection_.describeWithThumbnails(
    67  			blobref,
    68  			0,
    69  			goog.bind(this.handleDescribeBlob_, this, blobref),
    70  			function(msg) {
    71  				alert("failed to get blob description: " + msg);
    72  			}
    73  		);
    74  	}
    75  }
    76  
    77  // @param {string} blobref blob to describe.
    78  // @param {cam.ServerType.DescribeResponse} describeResult Object of properties for the node.
    79  cam.FiletreePage.prototype.handleDescribeBlob_ =
    80  function(blobref, describeResult) {
    81  	var meta = describeResult.meta;
    82  	if (!meta[blobref]) {
    83  		alert("didn't get blob " + blobref);
    84  		return;
    85  	}
    86  	var binfo = meta[blobref];
    87  	if (!binfo) {
    88  		alert("Error describing blob " + blobref);
    89  		return;
    90  	}
    91  	if (binfo.camliType != "directory") {
    92  		alert("Does not contain a directory");
    93  		return;
    94  	}
    95  	this.connection_.getBlobContents(
    96  		blobref,
    97  		goog.bind(function(data) {
    98  			var finfo = JSON.parse(data);
    99  			var fileName = finfo.fileName;
   100  			var curDir = document.getElementById('curDir');
   101  			curDir.innerHTML = "<a href='./?b=" + blobref + "'>" + fileName + "</a>";
   102  			this.buildTree_();
   103  		}, this),
   104  		function(msg) {
   105  			alert("failed to get blobcontents: " + msg);
   106  		}
   107  	);
   108  }
   109  
   110  cam.FiletreePage.prototype.buildTree_ = function() {
   111  	var blobref = getDirBlobrefParam();
   112  	var children = goog.dom.getElement("children");
   113  	this.connection_.getFileTree(blobref,
   114  		goog.bind(function(jres) {
   115  			this.onChildrenFound_(children, 0, jres);
   116  		}, this)
   117  	);
   118  }
   119  
   120  // @param {string} div node used as root for the tree
   121  // @param {number} depth how deep we are in the tree, for indenting
   122  // @param {cam.ServerType.DescribeResponse} jres describe result
   123  cam.FiletreePage.prototype.onChildrenFound_ = function(div, depth, jres) {
   124  	var indent = depth// cam.FiletreePage.prototype.indentStep_;
   125  	div.innerHTML = "";
   126  	for (var i = 0; i < jres.children.length; i++) {
   127  		var children = jres.children;
   128  		var pdiv = goog.dom.createElement("div");
   129  		var alink = goog.dom.createElement("a");
   130  		alink.style.paddingLeft=indent + "px"
   131  		alink.id = children[i].blobRef;
   132  		switch (children[i].type) {
   133  		case 'directory':
   134  			goog.dom.setTextContent(alink, "+ " + children[i].name);
   135  			goog.events.listen(alink,
   136  				goog.events.EventType.CLICK,
   137  				goog.bind(function (b, d) {
   138  					this.unFold_(b, d);
   139  				}, this, alink.id, depth),
   140  				false, this
   141  			);
   142  			break;
   143  		case 'file':
   144  			goog.dom.setTextContent(alink, " " + children[i].name);
   145  			alink.href = "./?b=" + alink.id;
   146  			break;
   147  		default:
   148  			alert("not a file or dir");
   149  			break;
   150  		}
   151  		var newPerm = goog.dom.createElement("span");
   152  		newPerm.className = "cam-filetree-newp";
   153  		goog.dom.setTextContent(newPerm, "P");
   154  		goog.events.listen(newPerm,
   155  			goog.events.EventType.CLICK,
   156  			this.newPermWithContent_(alink.id),
   157  			false, this
   158  		);
   159  		goog.dom.appendChild(pdiv, alink);
   160  		goog.dom.appendChild(pdiv, newPerm);
   161  		goog.dom.appendChild(div, pdiv);
   162  	}
   163  }
   164  
   165  cam.FiletreePage.prototype.newPermWithContent_ = function(content) {
   166  	var fun = function(e) {
   167  		this.connection_.createPermanode(
   168  			goog.bind(function(permanode) {
   169  				this.connection_.newAddAttributeClaim(
   170  					permanode, "camliContent", content,
   171  					function() {
   172  						alert("permanode created");
   173  					},
   174  					function(msg) {
   175  						// TODO(mpl): "cancel" new permanode
   176  						alert("set permanode content failed: " + msg);
   177  					}
   178  				);
   179  			}, this),
   180  			function(msg) {
   181  				alert("create permanode failed: " + msg);
   182  			}
   183  		);
   184  	}
   185  	return goog.bind(fun, this);
   186  }
   187  
   188  // @param {string} blobref dir to unfold.
   189  // @param {number} depth so we know how much to indent.
   190  cam.FiletreePage.prototype.unFold_ = function(blobref, depth) {
   191  	var node = goog.dom.getElement(blobref);
   192  	var div = goog.dom.createElement("div");
   193  	this.connection_.getFileTree(blobref,
   194  		goog.bind(function(jres) {
   195  			this.onChildrenFound_(div, depth+1, jres);
   196  			insertAfter(node, div);
   197  			goog.events.removeAll(node);
   198  			goog.events.listen(node,
   199  				goog.events.EventType.CLICK,
   200  				goog.bind(function(b, d) {
   201  					this.fold_(b, d);
   202  				}, this, blobref, depth),
   203  				false, this
   204  			);
   205  		}, this)
   206  	);
   207  }
   208  
   209  function insertAfter( referenceNode, newNode ) {
   210  	// nextSibling X2 because of the "P" span
   211  	referenceNode.parentNode.insertBefore( newNode, referenceNode.nextSibling.nextSibling );
   212  }
   213  
   214  // @param {string} nodeid id of the node to fold.
   215  // @param {depth} depth so we know how much to indent.
   216  cam.FiletreePage.prototype.fold_ = function(nodeid, depth) {
   217  	var node = goog.dom.getElement(nodeid);
   218  	// nextSibling X2 because of the "P" span
   219  	node.parentNode.removeChild(node.nextSibling.nextSibling);
   220  	goog.events.removeAll(node);
   221  	goog.events.listen(node,
   222  		goog.events.EventType.CLICK,
   223  		goog.bind(function(b, d) {
   224  			this.unFold_(b, d);
   225  		}, this, nodeid, depth),
   226  		false, this
   227  	);
   228  }