Index: webfm.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webfm/webfm.module,v
retrieving revision 1.52
diff -u -p -r1.52 webfm.module
--- webfm.module	17 Jul 2010 19:56:19 -0000	1.52
+++ webfm.module	22 Jul 2010 16:30:28 -0000
@@ -955,7 +955,25 @@ function webfm_ajax () {
         }
 
         if(count($trees)) {
-          webfm_json(array('status' => TRUE, 'tree' => $trees, 'current' => $webfm_root_path, 'admin' => $webfm_perm == WEBFM_ADMIN, 'err' => $err));
+          // Set current directory to requested (if valid) or the first tree root. 
+          $current = key(reset($trees));
+          if(isset($_POST["param1"]) ) {
+            $req_current = trim(rawurldecode($_POST["param1"]));
+            $found = false;
+            foreach ( $trees as $key => $tree ) {
+              foreach( $tree as $rPath => $info ) {
+                if ( webfm_check_path($req_current, $rPath)) {
+                  $current = $req_current;
+                  $found = true;
+                  break;
+                }
+              }
+              if ( $found ) {
+                break;
+              }
+            }
+          }
+          webfm_json(array('status' => TRUE, 'tree' => $trees, 'current' => $current, 'admin' => $webfm_perm == WEBFM_ADMIN, 'err' => $err));
         } else {
           webfm_json(array('status' => FALSE, 'err' => t('No trees found')));
         }
@@ -3159,3 +3177,99 @@ function webfm_pathauto_bulkupdate() {
     'Bulk generation of webfm file paths completed, @count aliases generated.'));
 }
 
+/**
+ * Create custom layouts for use by themes and modules.  This will add WebFM's 
+ * required js and css files to the header. This will create a webfm display 
+ * based on the specified parameters.
+ * 
+ * Notes:
+ * 
+ * Some combinations of options may not make sense or work. E.g suppressing both
+ * the tree folder and dir lists.
+ * 
+ * Only one webfm layout can be used on a page.  E.g. have two blocks with 
+ * different current directories will not work.
+ * 
+ * @param String $path The "current" directory to use.  This is the path as a 
+ *                 normal user would see it.  E.g. /roleDir/subdirA/subdirA1
+ *                     
+ * @param boolean $displayTree If false, suppress the folder tree display on left.
+ *  
+ * @param boolean $displayDir If false, suppress the directory list on right.
+ * 
+ * @param String $breadcrumbRoot A path used to "truncate" the dir list breadcrumb. 
+ *                 E.g. /roleDir/subDirA will cause the breadcrumb display to start 
+ *                 with /subDirA.  Useful to "psuedo-lock" users to a subtree.
+ *                        
+ * @param Array $displayColumns An array of "column_name => boolean" that determines
+ *                 which columns to display. "column_name" is one of:  name, 
+ *                 modified, size, or owner.  A true value = display (the default).
+ *                 A false value = do not display.  Generally, you only need to
+ *                 turn off column.  E.g. array( 'modified' => false) will display
+ *                 the other three.  Note, if the owner column is turned off in 
+ *                 the admin, it will never be displayed.
+ * 
+ * @return String  The HTML outout to display webfm.
+ */
+function webfm_custom_layout( $path = NULL, 
+                              $displayTree = NULL, 
+                              $displayDir = NULL,
+                              $breadcrumbRoot = NULL,
+                              $displayColumns = NULL  ) {
+  global $user;
+
+  // Test if user has Webfm access
+  if(($user->uid == 1) || user_access('administer webfm')) {
+    // Admins have total access
+    $webfm_perm = WEBFM_ADMIN;
+  } else if(user_access('access webfm')) {
+    $webfm_perm = WEBFM_USER;
+  } else {
+    return t('WebFM File Access Denied.');
+  }
+  
+  // Create current directory path based on admin or normal user
+  $webfm_root_path = webfm_get_root_path();
+  if($webfm_root_path == NULL ) {
+    //WebFM root dir must exist
+    drupal_set_message(
+           t('The WebFM root directory must be set in the admin settings.'), 'error');
+    return;
+  }
+  if ($webfm_perm == WEBFM_ADMIN) {
+    $path = $webfm_root_path .$path;
+  }
+  
+  // Construct the Javascript options needed for display
+  $options = '';
+  if ($path) {
+    $options .= "Webfm.current='$path';";
+  }
+  if ( isset($displayTree) ) {
+    $options .= "Webfm.options.displayTree=" . ($displayTree ? "true" : "false") .";";
+  } 
+  if ( isset($displayDir) ) {
+    $options .= "Webfm.options.displayDir=" . ($displayDir ? "true" : "false") . ";";
+  }
+  if ($breadcrumbRoot) {
+    $options .= "Webfm.options.breadcrumbRoot='$breadcrumbRoot';";
+  }
+  if ( $displayColumns ) {
+    $validColumns = array("name", "modified", "size", "owner");
+    foreach ( $displayColumns as $column => $state ) {
+      if ( in_array($column, $validColumns) ) {
+        $options .= "Webfm.options.displayColumns.$column=" . 
+                               ($state ? "true" : "false") . ";";
+      } else {
+        drupal_set_message(t('Invalid column name, %name, specified.', 
+                           array('%name' => $column)), 'warning');
+      }
+    }
+  }
+
+  $output = webfm_main();
+  if ( $options ) {
+    drupal_add_js($options, 'inline');
+  }
+  return $output; 
+}
Index: css/webfm.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webfm/css/webfm.css,v
retrieving revision 1.13
diff -u -p -r1.13 webfm.css
--- css/webfm.css	19 Aug 2009 15:31:51 -0000	1.13
+++ css/webfm.css	22 Jul 2010 16:30:28 -0000
@@ -18,6 +18,8 @@ img { border: 0; }
 #webfm-dirlist .navi a:hover { color: red; text-decoration: none; }
 #webfm-dirlist .txt { font-weight: normal; font-size: 8pt; text-align: left; padding-left: 5px; padding-right: 5px; }
 #webfm-dirlist-ctls .selected { background-color: #2092d0; cursor:pointer; }
+#webfm-dirlist td.icon { width: 30px; }
+#webfm-dirlist td.ctls-td { text-align: right; }
 
 #webfm-tree { float:left; clear:both; position:relative; }
 #webfm-tree .selected { background-color: #e7e7e7; }
Index: js/webfm.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webfm/js/webfm.js,v
retrieving revision 1.36
diff -u -p -r1.36 webfm.js
--- js/webfm.js	17 Jul 2010 19:56:19 -0000	1.36
+++ js/webfm.js	22 Jul 2010 16:30:29 -0000
@@ -60,6 +60,7 @@ Webfm.js_msg["not-inserted"] = Drupal.t(
 Webfm.js_msg["metadata"] = Drupal.t("Metadata");
 Webfm.js_msg["fix_input"] = Drupal.t("correct input");
 Webfm.js_msg["perm"] = Drupal.t("File Permissions");
+Webfm.js_msg["no-attachments"] = Drupal.t("No files attached.");
 
 Webfm.meta_msg = [];
 Webfm.meta_msg["fid"] = Drupal.t("fid");
@@ -103,7 +104,20 @@ Webfm.menu_msg["clip"] = Drupal.t("Copy 
 Webfm.menu_msg["paste"] = Drupal.t("Paste link in editor window");
 //Do not translate any code below this line
 
-Webfm.current = null;
+Webfm.current = null; // current directory
+
+// Options that modify behaviour.
+Webfm.options = { displayTree: true,  // Display trees div. 
+		          displayDir: true,   // Display directory
+		          breadcrumbRoot: null, // Psuedo root for breadcrumb display.
+		          displayColumns: { 
+	                name: true, 
+	                modified: true, 
+	                size: true,
+	                owner: true
+	              } 
+		        };
+Webfm.numColumns = -1; //Number of display columns
 
 Webfm.dragCont = null;
 Webfm.metaCont = null;
@@ -321,10 +335,26 @@ function webfmLayout() {
   if(layoutDiv) {
     Webfm.commonInterface(layoutDiv);
 
+    if ( Webfm.options.displayTree ) {
+
     //first param forces trees refresh
     //second param forces list refresh
     Webfm.dirTreeObj.fetch(true, true);
   } else {
+      Webfm.dirListObj.refresh();
+    }
+    return;
+  }
+
+  // Shortcut to displaying files only via 'webfm-dir' div id.
+  layoutDiv = Webfm.$('webfm-dir');
+  if ( layoutDiv ) {
+	Webfm.options.displayTree = false;
+    Webfm.commonInterface(layoutDiv);
+    Webfm.dirListObj.refresh();
+    return;
+  }
+
     layoutDiv = Webfm.$('webfm-inline');
 
     if(layoutDiv) {
@@ -344,7 +374,15 @@ function webfmLayout() {
       Webfm.attachObj = new Webfm.attach('webfm-attach');
       Webfm.attachObj.fetch();
 
+    if ( Webfm.options.displayTree ) {
+
+        //first param forces trees refresh
+        //second param forces list refresh
       Webfm.dirTreeObj.fetch(true, true);
+      } else {
+   	    if ( Webfm.options.displayDir ) {
+          Webfm.dirListObj.refresh();
+   	    }
     }
   }
 }
@@ -441,16 +479,23 @@ Webfm.commonInterface = function(parent)
   Webfm.alrtObj = new Webfm.alert(layout_cont, 'webfm-alert');
 
   //Container for tree(s)
+  if ( Webfm.options.displayTree ) {
   var elTreeDiv = Webfm.ce('div');
   elTreeDiv.setAttribute('id', 'webfm-tree'); //css id
   layout_cont.appendChild(elTreeDiv);
-  Webfm.dirTreeObj = new Webfm.treeBuilder(elTreeDiv, Webfm.menuHT.get('root'), Webfm.menuHT.get('dir'));
+    Webfm.dirTreeObj = new Webfm.treeBuilder( elTreeDiv, Webfm.menuHT.get('root'), 
+                                              Webfm.menuHT.get('dir'));
+  }
 
   //progress indicator
   Webfm.progressObj = new Webfm.progress(layout_cont, 'webfm-progress');
 
   //Directory Listing
-  Webfm.dirListObj = new Webfm.list(layout_cont, 'webfm-dirlist', 'file', 'narrow', true, Webfm.menuHT.get('dir'), Webfm.menuHT.get('file'));
+  if ( Webfm.options.displayDir ) {
+	var claz = Webfm.options.displayTree ? 'narrow' : 'wide';
+    Webfm.dirListObj = new Webfm.list(layout_cont, 'webfm-dirlist', 'file', claz, 
+                             true, Webfm.menuHT.get('dir'), Webfm.menuHT.get('file'));
+  }
 
   //insert trees, listing, search, metadata, progress and alert divs before upload fset built in php
   parent.insertBefore(layout_cont, parent.firstChild);
@@ -630,7 +675,14 @@ Webfm.list = function(parent, id, type, 
   this.file_menu = file_menu;
   //directory cache hashtable (key= directory path, val= directory contents)
   this.cache = new Webfm.ht();
-  this.eventListeners = []
+  this.eventListeners = [];
+  
+//Get the number of columns being displayed
+  Webfm.numColumns = 0;
+  if (Webfm.options.displayColumns.name) Webfm.numColumns++;
+  if (Webfm.options.displayColumns.modified) Webfm.numColumns++;
+  if (Webfm.options.displayColumns.size) Webfm.numColumns++;
+  if (getWebfmOwnerColumn() && Webfm.options.displayColumns.owner) Webfm.numColumns++;
 
   var node = Webfm.ce("div");
   node.setAttribute('id', this.id);
@@ -648,7 +700,7 @@ Webfm.list = function(parent, id, type, 
 
   // Refresh Icon
   var elTd = Webfm.ce('td');
-  elTd.className = 'navi';
+  elTd.className = 'navi icon';
   var elA = Webfm.ce('a');
   elA.setAttribute('href', '#');
   elA.setAttribute('title', Webfm.js_msg["refresh"]);
@@ -662,7 +714,7 @@ Webfm.list = function(parent, id, type, 
 
   // Breadcrumb trail
   var elTd = Webfm.ce('td');
-  elTd.colSpan = getWebfmOwnerColumn() ? 4 : 3
+  elTd.colSpan =  Webfm.numColumns < 2 ? 2 : Webfm.numColumns;
   elTd.setAttribute('id','webfm-bcrumb-td');
   elTd.setAttribute('class','navi');
   // Build breadcrumb trail inside span
@@ -683,7 +735,9 @@ Webfm.list = function(parent, id, type, 
   elTr.appendChild(elTd);
 
   // Sort dir/files column
+  if ( Webfm.options.displayColumns.name ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   elTd.className = 'head';
   var elA = Webfm.ce('a');
   elA.setAttribute('href', '#');
@@ -697,9 +751,12 @@ Webfm.list = function(parent, id, type, 
   elA.appendChild(Webfm.ctn(Webfm.js_msg["column1"]));
   elTd.appendChild(elA);
   elTr.appendChild(elTd);
+  }
 
   // date/time column
+  if ( Webfm.options.displayColumns.modified ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   elTd.className = 'head';
   var elA = Webfm.ce('a');
   elA.setAttribute('href', '#');
@@ -712,9 +769,12 @@ Webfm.list = function(parent, id, type, 
   elA.appendChild(Webfm.ctn(Webfm.js_msg["column2"]));
   elTd.appendChild(elA);
   elTr.appendChild(elTd);
+  }
 
   // size column
+  if ( Webfm.options.displayColumns.size ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   elTd.className = 'head';
   var elA = Webfm.ce('a');
   elA.setAttribute('href', '#');
@@ -727,10 +787,12 @@ Webfm.list = function(parent, id, type, 
   elA.appendChild(Webfm.ctn(Webfm.js_msg["column3"]));
   elTd.appendChild(elA);
   elTr.appendChild(elTd);
+  }
 
   // owner column
-  if(getWebfmOwnerColumn()) {
+  if(getWebfmOwnerColumn()  && Webfm.options.displayColumns.owner ) {
     var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
     elTd.className = 'head';
     var elA = Webfm.ce('a');
     elA.setAttribute('href', '#');
@@ -756,9 +818,23 @@ Webfm.list.prototype.bcrumb = function()
   var cp = this;
   Webfm.clearNodeById(this.id + 'bcrumb');
   elSpan = Webfm.$(this.id + 'bcrumb');
+  var broot = [];
+  if ( Webfm.options.breadcrumbRoot ) {
+    var l = this.content.current.indexOf(Webfm.options.breadcrumbRoot );
+    var adminPrefix = this.content.current.substring(0, l);
+    var bRoot = adminPrefix + Webfm.options.breadcrumbRoot;
+    broot = bRoot.split('/');
+    if ( broot[0] == '' ) {
+	  broot.shift();
+    }
+    broot.pop();
+  }
   var pth = [];
   for(var i = 0; i < this.content.bcrumb.length - 1; i++) {
     pth.push(this.content.bcrumb[i]);
+    if ( this.content.bcrumb[i] == broot[i] ) {
+    	continue;
+    }
     elSpan.appendChild(Webfm.ctn(" / "));
     // No breadcrumb link necessary for current directory
     var elA = Webfm.ce('a');
@@ -867,13 +943,14 @@ Webfm.list.prototype.callback = function
 //build admin icons for create dir and file db insertion
 //maintain 4 column table
 Webfm.list.prototype.adminCtl = function(admin) {
-  col_span = getWebfmOwnerColumn() ? 4 : 3
+  col_span = Webfm.numColumns < 2 ? 2 : Webfm.numColumns;
   if(admin) {
     if(Webfm.$('webfm-bcrumb-td').colSpan == col_span) {
       var wl = this;
       Webfm.$('webfm-bcrumb-td').colSpan = col_span - 1;
       // Create New Directory and allow db insertions
       var elTd = Webfm.ce('td');
+      elTd.className = "ctls-td";
       var elSpan = Webfm.ce('span');
       elSpan.id = this.id + "-ctls";
 
@@ -1058,7 +1135,9 @@ Webfm.dirrow = function(parent, dir, ind
   elTd.appendChild(elImg);
   elTr.appendChild(elTd);
 
+  if ( Webfm.options.displayColumns.name ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   // Title of link = path
   this.clickObj = Webfm.ce('a');
   this.clickObj.setAttribute('href', '#');
@@ -1067,23 +1146,31 @@ Webfm.dirrow = function(parent, dir, ind
   this.clickObj.appendChild(Webfm.ctn(dir.n));
   elTd.appendChild(this.clickObj);
   elTr.appendChild(elTd);
+  }
 
+  if ( Webfm.options.displayColumns.modified ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   elTd.className = 'txt';
   elTd.appendChild(Webfm.ctn(Webfm.convertunixtime(parseInt(dir.m))));
   elTr.appendChild(elTd);
+  }
 
+  if ( Webfm.options.displayColumns.size ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   elTd.className = 'txt';
   if(dir.s) {
     var size = Webfm.size(dir.s);
     elTd.appendChild(Webfm.ctn(size));
   }
   elTr.appendChild(elTd);
+  }
 
   // Add td if owner column enabled
-  if(getWebfmOwnerColumn()) {
+  if(getWebfmOwnerColumn() && Webfm.options.displayColumns.owner ) {
     var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
     elTd.className = 'txt';
     if(dir.o) {
       var owner = Webfm.ce(dir.o);
@@ -1219,7 +1306,9 @@ Webfm.filerow = function(parent, fileObj
   elTd.appendChild(elImg);
   elTr.appendChild(elTd);
 
+  if ( Webfm.options.displayColumns.name ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   this.clickObj = Webfm.ce('a');
   this.clickObj.setAttribute('href', '#');
   if((typeof fileObj.id == "undefined") || fileObj.id == 0) {
@@ -1235,21 +1324,29 @@ Webfm.filerow = function(parent, fileObj
     this.clickObj.appendChild(Webfm.ctn(fileObj.n));
   elTd.appendChild(this.clickObj);
   elTr.appendChild(elTd);
+  }
 
+  if ( Webfm.options.displayColumns.modified ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   elTd.className = 'txt';
   elTd.appendChild(Webfm.ctn(Webfm.convertunixtime(parseInt(fileObj.m))));
   elTr.appendChild(elTd);
+  }
 
+  if ( Webfm.options.displayColumns.size ) {
   var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
   elTd.className = 'txt';
   var size = Webfm.size(fileObj.s);
   elTd.appendChild(Webfm.ctn(size));
   elTr.appendChild(elTd);
+  }
 
   //owner field to row
-  if(getWebfmOwnerColumn()) {
+  if(getWebfmOwnerColumn() && Webfm.options.displayColumns.owner ) {
     var elTd = Webfm.ce('td');
+    if ( Webfm.numColumns < 2 ) elTd.colSpan = 2;
     elTd.className = 'txt';
     elTd.appendChild(Webfm.ctn(fileObj.un));
     elTr.appendChild(elTd);
@@ -1345,6 +1442,9 @@ Webfm.treeBuilder.prototype.fetch = func
   var postObj = { action:encodeURIComponent("readtrees") };
   if(tree_refresh)
     postObj.param0 = encodeURIComponent(true);
+  if(Webfm.current) {  // Allow themers to request the current tree.
+    postObj.param1 = encodeURIComponent(Webfm.current);
+  }
   Webfm.admin = false;
   Webfm.HTTPPost(url, this.callback, this, postObj);
 }
@@ -1361,19 +1461,14 @@ Webfm.treeBuilder.prototype.callback = f
       Webfm.admin = result.admin;
       // build directory trees from php associative array
       // first var used to fetch listing of first tree
-      var first = true;
       for(var i in result.tree) {
 //        Webfm.dbgObj.dbg("tree" + i, Webfm.dump(result.tree[i]));
         if(!cp.trees[i]) {
           cp.trees[i] = new Webfm.tree(cp.parent, i, cp.root_menu, cp.dir_menu);
         }
-        if(first) {
-          cp.trees[i].fetch(cp.tree_refresh, cp.list_refresh);
-        } else {
           cp.trees[i].fetch(cp.tree_refresh, false);
         }
-        first = false;
-      }
+      Webfm.dirListObj.refresh(result.current);
     } else {
       Webfm.alrtObj.msg(result.err);
     }
@@ -1942,6 +2037,9 @@ Webfm.menuDetach = function(obj) {
       }
     }
     Webfm.$(Webfm.attachFormInput).value = new_attach_arr.join(',');
+    if ( ! new_attach_arr.length ) {
+      Webfm.attach.noAttachments(true);	
+    }
   }
 }
 
@@ -2027,6 +2125,8 @@ Webfm.insert_callback = function(string,
       }
     } else if(result.data.err) {
         Webfm.alrtObj.str_arr(result.data.err);
+    } else {
+      Webfm.alrtObj.msg(result.data);
     }
   } else {
     Webfm.alrtObj.msg(Webfm.js_msg["ajax-err"]);
@@ -2140,6 +2240,8 @@ Webfm.ctxMenuAttachCallback = function(s
       var filerow = new Webfm.filerow(Webfm.attachObj.body, result.data, 'attach', '', true, Webfm.menuHT.get('det'), Webfm.attachObj.eventListeners);
       var elInput = Webfm.$(Webfm.attachFormInput);
       elInput.setAttribute('value', (elInput.getAttribute('value')?elInput.getAttribute('value')+',':'') + result.data.id);
+      // Clear no file msg
+      Webfm.attach.noAttachments(false);
     } else
       Webfm.alrtObj.msg(result.data);
   } else {
@@ -2683,6 +2785,8 @@ Webfm.attach.prototype.callback = functi
             elInput.setAttribute('value', (elInput.getAttribute('value')?elInput.getAttribute('value')+',':'') + result.data[i].id);
           }
         }
+      } else {
+    	Webfm.attach.noAttachments(true);
       }
     } else
       Webfm.alrtObj.msg(result.data);
@@ -2691,6 +2795,16 @@ Webfm.attach.prototype.callback = functi
   }
 }
 
+// Turn on/off no attachments display as needed.
+Webfm.attach.noAttachments = function ( show ) {
+  if ( show ) {
+    $('#webfm-attach').append( '<div id="webfm-no-attachments">' + 
+                               Webfm.js_msg["no-attachments"] + '</div>');
+  } else {
+	$('#webfm-no-attachments').remove();
+  }
+}
+
 /**
  * Webfm.search constructor
  * 1st param is popup container obj
