1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * 27 */ 28 29 /** 30 * Creates the briefcase detail list view. 31 * @class 32 * This class represents the briefcase detail list view. 33 * 34 * @param {ZmControl} parent the parent 35 * @param {ZmBriefcaseController} controller the controller 36 * @param {DwtDropTarget} dropTgt the drop target 37 * 38 * @extends ZmBriefcaseBaseView 39 */ 40 ZmDetailListView = function(parent, controller, dropTgt) { 41 42 this._controller = controller; 43 44 var headerList = this._getHeaderList(parent); 45 46 var params = {parent:parent, className:"ZmBriefcaseDetailListView", 47 view: controller.getCurrentViewId(), 48 controller:controller, headerList:headerList, dropTgt:dropTgt}; 49 ZmBriefcaseBaseView.call(this, params); 50 51 this.enableRevisionView(true); 52 53 this._expanded = {}; 54 this._itemRowIdList = {}; 55 56 if (controller.supportsDnD()) { 57 this._dragSrc = new DwtDragSource(Dwt.DND_DROP_MOVE); 58 this._dragSrc.addDragListener(this._dragListener.bind(this)); 59 this.setDragSource(this._dragSrc); 60 61 this._dropTgt = new DwtDropTarget("ZmDetailListView"); 62 this._dropTgt.markAsMultiple(); 63 this._dropTgt.addDropListener(this._dropListener.bind(this)); 64 this.setDropTarget(this._dropTgt); 65 } 66 // Finder to DetailView drag and drop 67 this._initDragAndDrop(); 68 }; 69 70 ZmDetailListView.prototype = new ZmBriefcaseBaseView; 71 ZmDetailListView.prototype.constructor = ZmDetailListView; 72 73 ZmDetailListView.ROW_DOUBLE_CLASS = "RowDouble"; 74 75 76 ZmDetailListView.SINGLE_COLUMN_SORT = [ 77 {field:ZmItem.F_NAME, msg:"name"}, 78 {field:ZmItem.F_SIZE, msg:"size"}, 79 {field:ZmItem.F_DATE, msg:"date"} 80 ]; 81 82 83 /** 84 * Returns a string representation of the object. 85 * 86 * @return {String} a string representation of the object 87 */ 88 ZmDetailListView.prototype.toString = 89 function() { 90 return "ZmDetailListView"; 91 }; 92 93 // Constants 94 95 ZmDetailListView.KEY_ID = "_keyId"; 96 97 ZmDetailListView.COLWIDTH_ICON = 20; 98 99 // Protected methods 100 101 ZmDetailListView.prototype.enableRevisionView = 102 function(enabled){ 103 this._revisionView = enabled; 104 }; 105 106 ZmDetailListView.prototype._changeListener = 107 function(ev){ 108 if(ev.event == ZmEvent.E_MOVE || ev.event == ZmEvent.E_DELETE){ 109 if (this.getDnDSelection() && this.getDnDSelection instanceof AjxVector) 110 this.dragDeselect(this.getDnDSelection().get(0)); 111 else if (this.getDnDSelection()) 112 this.dragDeselect(this.getDnDSelection()); 113 } 114 115 116 ZmBriefcaseBaseView.prototype._changeListener.call(this, ev); 117 if (this._revisionView && ( ev.event == ZmEvent.E_DELETE || ev.event == ZmEvent.E_MOVE )) { 118 var items = ev.getDetail("items") ? ev.getDetail("items") : [this._getItemFromEvent(ev)]; 119 for (var i = 0, len = items.length; i < len; i++) { 120 var item = items[i]; 121 this.collapse(item, true); 122 } 123 } 124 }; 125 126 ZmDetailListView.prototype._getHeaderList = 127 function(parent) { 128 // Columns: tag, name, type, size, date, owner, folder 129 var headers = []; 130 var view = this._view; 131 if (appCtxt.get(ZmSetting.SHOW_SELECTION_CHECKBOX)) { 132 headers.push(new DwtListHeaderItem({field:ZmItem.F_SELECTION, icon:"CheckboxUnchecked", width:ZmListView.COL_WIDTH_ICON, 133 name:ZmMsg.selection})); 134 } 135 if(this.isMultiColumn()){ 136 137 if(this._revisionView){ 138 headers.push(new DwtListHeaderItem({field:ZmItem.F_EXPAND, icon: "NodeCollapsed", width:ZmDetailListView.COLWIDTH_ICON, name:ZmMsg.expand})); 139 } 140 141 if (appCtxt.get(ZmSetting.TAGGING_ENABLED)) { 142 headers.push(new DwtListHeaderItem({field:ZmItem.F_TAG, icon:"Tag", width:ZmDetailListView.COLWIDTH_ICON, 143 name:ZmMsg.tag})); 144 } 145 headers.push( 146 new DwtListHeaderItem({field:ZmItem.F_LOCK, icon: "Padlock", width:ZmDetailListView.COLWIDTH_ICON, name:ZmMsg.lock}), 147 new DwtListHeaderItem({field:ZmItem.F_TYPE, icon:"GenericDoc", width:ZmDetailListView.COLWIDTH_ICON, name:ZmMsg.icon}), 148 new DwtListHeaderItem({field:ZmItem.F_NAME, text:ZmMsg._name, sortable:ZmItem.F_NAME}), 149 new DwtListHeaderItem({field:ZmItem.F_FILE_TYPE, text:ZmMsg.type, width:ZmMsg.COLUMN_WIDTH_TYPE_DLV}), 150 new DwtListHeaderItem({field:ZmItem.F_SIZE, text:ZmMsg.size, width:ZmMsg.COLUMN_WIDTH_SIZE_DLV, sortable:ZmItem.F_SIZE}), 151 new DwtListHeaderItem({field:ZmItem.F_DATE, text:ZmMsg.modified, width:ZmMsg.COLUMN_WIDTH_DATE_DLV, sortable:ZmItem.F_DATE}), 152 new DwtListHeaderItem({field:ZmItem.F_FROM, text:ZmMsg.author, width:ZmMsg.COLUMN_WIDTH_OWNER_DLV}), 153 new DwtListHeaderItem({field:ZmItem.F_FOLDER, text:ZmMsg.folder, width:ZmMsg.COLUMN_WIDTH_FOLDER_DLV}), 154 new DwtListHeaderItem({field:ZmItem.F_VERSION, text:ZmMsg.version, width:ZmMsg.COLUMN_WIDTH_VERSION_DLV}) 155 ); 156 }else{ 157 headers.push(new DwtListHeaderItem({field:ZmItem.F_SORTED_BY, text:AjxMessageFormat.format(ZmMsg.arrangedBy, ZmMsg.name), sortable:ZmItem.F_NAME, resizeable:false})); 158 } 159 return headers; 160 }; 161 162 ZmDetailListView.prototype._getHeaderToolTip = 163 function(field, itemIdx, isOutboundFolder) { 164 165 var tooltip; 166 if(field == ZmItem.F_EXPAND){ 167 tooltip = ZmMsg.expandCollapse; 168 }else if(field == ZmItem.F_LOCK){ 169 tooltip = ZmMsg.fileLockStatus; 170 }else if(field == ZmItem.F_DATE){ 171 tooltip = ZmMsg.sortByModified; 172 }else if(field == ZmItem.F_FROM){ 173 tooltip = ZmMsg.author; 174 }else if(field == ZmItem.F_VERSION){ 175 tooltip = ZmMsg.latestVersion; 176 }else if(field == ZmItem.F_NAME){ 177 tooltip = ZmMsg.sortByName; 178 }else{ 179 tooltip = ZmBriefcaseBaseView.prototype._getHeaderToolTip.call(this, field, itemIdx, isOutboundFolder); 180 } 181 return tooltip; 182 }; 183 184 185 ZmDetailListView.prototype._getActionMenuForColHeader = 186 function(force) { 187 188 if (!this.isMultiColumn()) { 189 if (!this._colHeaderActionMenu || force) { 190 this._colHeaderActionMenu = this._getSortMenu(ZmDetailListView.SINGLE_COLUMN_SORT, ZmItem.F_NAME); 191 } 192 return this._colHeaderActionMenu; 193 } 194 195 var menu = ZmListView.prototype._getActionMenuForColHeader.call(this, force); 196 197 return menu; 198 }; 199 200 201 202 ZmDetailListView.prototype._isExpandable = 203 function(item){ 204 return (!item.isFolder && !item.isRevision && parseInt(item.version) > 1 ); 205 }; 206 207 ZmDetailListView.prototype._getCellContents = 208 function(htmlArr, idx, item, field, colIdx, params) { 209 210 if (field == ZmItem.F_SELECTION) { 211 var icon = params.bContained ? "CheckboxChecked" : "CheckboxUnchecked"; 212 idx = this._getImageHtml(htmlArr, idx, icon, this._getFieldId(item, field)); 213 } else if (field == ZmItem.F_EXPAND) { 214 idx = this._getImageHtml(htmlArr, idx, 215 this._isExpandable(item) ? (this._expanded[item.id] ? "NodeExpanded" : "NodeCollapsed" ) 216 : null, this._getFieldId(item, field)); 217 } else if (field == ZmItem.F_TYPE) { 218 htmlArr[idx++] = AjxImg.getImageHtml(item.getIcon()); 219 } else if (field == ZmItem.F_LOCK) { 220 idx = this._getImageHtml(htmlArr, idx, (item.locked ? "Padlock" : "Blank_16") , this._getFieldId(item, field)); //AjxImg.getImageHtml(item.locked ? "Padlock" : "Blank_16"); 221 } else if (field == ZmItem.F_VERSION) { 222 htmlArr[idx++] = item.version; 223 } else if (field == ZmItem.F_NAME || field == ZmItem.F_SUBJECT) { 224 htmlArr[idx++] = "<div id='"+this._getFieldId(item, ZmItem.F_NAME)+"'>"+this._getDisplayName(item)+"</div>"; 225 } else if (field == ZmItem.F_FILE_TYPE) { 226 if(item.isFolder){ 227 htmlArr[idx++] = ZmMsg.folder; 228 }else{ 229 var mimeInfo = item.contentType ? ZmMimeTable.getInfo(item.contentType) : null; 230 htmlArr[idx++] = mimeInfo ? mimeInfo.desc : " "; 231 } 232 } else if (field == ZmItem.F_SIZE) { 233 htmlArr[idx++] = item.isFolder ? ZmMsg.folder : AjxUtil.formatSize(item.size); 234 } else if (field == ZmItem.F_DATE) { 235 if (item.contentChangeDate || item.modifyDate || item.createDate) { 236 var displayDate; 237 if (item.contentChangeDate) { 238 displayDate = item.contentChangeDate; 239 } else if (item.modifyDate) { 240 displayDate = item.modifyDate; 241 } else { 242 displayDate = item.createDate; 243 } 244 htmlArr[idx++] = AjxDateUtil.simpleComputeDateStr(displayDate); 245 } 246 } else if (field == ZmItem.F_FROM) { 247 var creator = item.modifier || item.creator; 248 creator = creator ? creator.split("@") : [""]; 249 var cname = creator[0]; 250 var uname = appCtxt.get(ZmSetting.USERNAME); 251 if (uname) { 252 var user = uname.split("@"); 253 if (creator[1] != user[1]) { 254 cname = creator.join("@"); 255 } 256 } 257 htmlArr[idx++] = "<span style='white-space:nowrap'>"; 258 htmlArr[idx++] = cname; 259 htmlArr[idx++] = "</span>"; 260 } else if (field == ZmItem.F_FOLDER) { 261 var briefcase = appCtxt.getById(item.folderId); 262 htmlArr[idx++] = briefcase ? briefcase.getName() : item.folderId; 263 } else if (field == ZmItem.F_SORTED_BY){ 264 htmlArr[idx++] = this._getAbridgedContent(item, colIdx); 265 } 266 else { 267 idx = ZmListView.prototype._getCellContents.apply(this, arguments); 268 } 269 270 return idx; 271 }; 272 273 ZmDetailListView.prototype._getDisplayName = 274 function(item){ 275 var subject; 276 if(item.isRevision){ 277 subject = (item.subject); 278 }else if(parseInt(item.version) > 1){ 279 subject = AjxMessageFormat.format(ZmMsg.briefcaseFileVersion, [AjxStringUtil.htmlEncode(item.name), item.version]) 280 } 281 return subject || (AjxStringUtil.htmlEncode(item.name)); 282 }; 283 284 ZmDetailListView.prototype._getAbridgedContent = 285 function(item, colIdx) { 286 287 var idx=0, html=[]; 288 var width = (AjxEnv.isIE || AjxEnv.isSafari) ? 22 : 16; 289 290 html[idx++] = "<table width=100% class='TopRow'><tr>"; 291 292 if(this._revisionView){ 293 html[idx++] = "<td width=" + width + " id='" + this._getFieldId(item, ZmItem.F_FOLDER) + "'><center>"; 294 idx = this._getCellContents(html, idx, item, ZmItem.F_EXPAND, colIdx); 295 html[idx++] = "</center></td>"; 296 } 297 298 html[idx++] = "<td width=20 id='" + this._getFieldId(item, ZmItem.F_FOLDER) + "'><center>"; 299 html[idx++] = AjxImg.getImageHtml(item.getIcon()); 300 html[idx++] = "</center></td>"; 301 html[idx++] = "<td style='vertical-align:middle;' width=100% id='" + this._getFieldId(item, ZmItem.F_NAME) + "'>"; 302 html[idx++] = this._getDisplayName(item); 303 html[idx++] = "</td>"; 304 305 html[idx++] = "<td style='vertical-align:middle;text-align:right;' width=40 id='" + this._getFieldId(item, ZmItem.F_SIZE) + "'>"; 306 idx = this._getCellContents(html, idx, item, ZmItem.F_SIZE, colIdx); 307 html[idx++] = "</td>"; 308 309 html[idx++] = "<td style='text-align:right' width=" + width + " >"; 310 idx = this._getImageHtml(html, idx, item.getTagImageInfo(), this._getFieldId(item, ZmItem.F_TAG)); 311 html[idx++] = "</td>"; 312 313 html[idx++] = "</tr>"; 314 html[idx++] = "</table>"; 315 316 html[idx++] = "<table width=100% class='BottomRow'><tr>"; 317 html[idx++] = "<td style='vertical-align:middle;padding-left:50px;'>"; 318 idx = this._getCellContents(html, idx, item, ZmItem.F_FROM, colIdx); 319 html[idx++] = "<td style='vertical-align:middle;text-align:right;'>"; 320 idx = this._getCellContents(html, idx, item, ZmItem.F_DATE, colIdx); 321 html[idx++] = "</td>"; 322 html[idx++] = "<td style='text-align:center;' width=" + width + " id='" + this._getFieldId(item, ZmItem.F_LOCK)+"'> "; 323 idx = this._getImageHtml(html, idx, (item.locked ? "Padlock" : "Blank_16") , this._getFieldId(item, ZmItem.F_LOCK)); 324 html[idx++] = "</td>"; 325 html[idx++] = "</tr></table>"; 326 327 return html.join(''); 328 }; 329 330 ZmDetailListView.prototype._getDivClass = 331 function(base, item, params) { 332 if (item.isRevision) { 333 return [base, "BriefcaseItemExpanded"].join(" "); 334 } else { 335 return ZmBriefcaseBaseView.prototype._getDivClass.apply(this, arguments); 336 } 337 }; 338 339 ZmDetailListView.prototype.expandItem = 340 function(item) { 341 if (item && this._isExpandable(item) && this._revisionView) { 342 this.parent._toggle(item); 343 } 344 }; 345 346 ZmDetailListView.prototype.expand = 347 function(item, revisions){ 348 349 if(!item || !revisions || revisions.size() == 0 ) return; 350 351 this._addRevisionRows(item, revisions); 352 353 this._setImage(item, ZmItem.F_EXPAND, "NodeExpanded"); 354 this._expanded[item.id] = true; 355 }; 356 357 ZmDetailListView.prototype._addRevisionRows = 358 function(item, revisions){ 359 360 var rowIds = this._itemRowIdList[item.id]; 361 if (rowIds && rowIds.length && rowIds.length == revisions.size() && this._rowsArePresent(item)){ 362 this._showRows(rowIds, true); 363 }else{ 364 var index = this._getRowIndex(item); 365 this._itemRowIdList[item.id] = []; 366 for(var i=0; i< revisions.size(); i++){ 367 var rev = revisions.get(i); 368 var div = this._createItemHtml(rev); 369 //check if item exists before adding row 370 if (!document.getElementById(div.id)) 371 this._addRow(div, index+i+1); 372 else 373 this._showRows([div.id],true); 374 this._itemRowIdList[item.id].push(div.id); 375 } 376 } 377 378 }; 379 380 ZmDetailListView.prototype.collapse = 381 function(item, clear){ 382 var rowIds = this._itemRowIdList[item.id]; 383 this._showRows(rowIds, false); 384 this._setImage(item, ZmItem.F_EXPAND, "NodeCollapsed"); 385 this._expanded[item.id] = false; 386 if(clear && rowIds){ 387 var divId; 388 var el; 389 for (var i = 0; i < rowIds.length; i++) { 390 divId = rowIds[i]; 391 el = document.getElementById(divId); 392 if (el && el.parentNode) { 393 el.parentNode.removeChild(el); 394 } 395 } 396 this._itemRowIdList[item.id] = null; 397 } 398 }; 399 400 ZmDetailListView.prototype.collapseAll = 401 function(){ 402 var list = this.getItemList(), item; 403 for(var id in this._expanded){ 404 if(this._expanded[id]){ 405 item = list.getById(id); 406 if(item) this.collapse(item); 407 } 408 } 409 }; 410 411 ZmDetailListView.prototype.refreshItem = 412 function(item){ 413 if(item && this._expanded[item.id]){ 414 var rowIds = this._itemRowIdList[item.id]; 415 } 416 }; 417 418 ZmDetailListView.prototype._showRows = 419 function(rowIds, show){ 420 if (rowIds && rowIds.length) { 421 for (var i = 0; i < rowIds.length; i++) { 422 var row = document.getElementById(rowIds[i]); 423 if (row) { 424 Dwt.setVisible(row, show); 425 } 426 } 427 } 428 }; 429 430 ZmDetailListView.prototype._rowsArePresent = 431 function(item) { 432 var rowIds = this._itemRowIdList[item.id]; 433 if (rowIds && rowIds.length) { 434 for (var i = 0; i < rowIds.length; i++) { 435 if (document.getElementById(rowIds[i])) { 436 return true; 437 } 438 } 439 } 440 this._itemRowIdList[item.id] = []; // start over 441 this._expanded[item.id] = false; 442 return false; 443 }; 444 445 446 447 ZmDetailListView.prototype._allowFieldSelection = 448 function(id, field) { 449 // allow left selection if clicking on blank icon 450 if (field == ZmItem.F_EXPAND) { 451 var item = appCtxt.getById(id); 452 return (item && !this._isExpandable(item)); 453 } else { 454 return ZmListView.prototype._allowFieldSelection.apply(this, arguments); 455 } 456 }; 457 458 // listeners 459 460 ZmDetailListView.prototype._sortColumn = 461 function(columnItem, bSortAsc) { 462 463 // call base class to save the new sorting pref 464 ZmBriefcaseBaseView.prototype._sortColumn.apply(this, arguments); 465 466 var query = this._controller.getSearchString(); 467 var queryHint = this._controller.getSearchStringHint(); 468 469 if (this._sortByString && (query || queryHint)) { 470 var params = { 471 query: query, 472 queryHint: queryHint, 473 types: [ZmItem.BRIEFCASE_ITEM], 474 sortBy: this._sortByString 475 }; 476 appCtxt.getSearchController().search(params); 477 } 478 }; 479 480 ZmDetailListView.prototype.isMultiColumn = 481 function(controller) { 482 var ctlr = controller || this._controller; 483 return !ctlr.isReadingPaneOnRight(); 484 }; 485 486 487 ZmDetailListView.prototype.reRenderListView = 488 function(force) { 489 var isMultiColumn = this.isMultiColumn(); 490 if (isMultiColumn != this._isMultiColumn || force) { 491 this._saveState({selection:true, focus:true, scroll:true, expansion:true}); 492 this._isMultiColumn = isMultiColumn; 493 this.headerColCreated = false; 494 this._headerList = this._getHeaderList(); 495 this._rowHeight = null; 496 this._normalClass = isMultiColumn ? DwtListView.ROW_CLASS : ZmDetailListView.ROW_DOUBLE_CLASS; 497 var list = this._zmList || this.getList() || (new AjxVector()); 498 this.set(list); 499 this._restoreState(); 500 } 501 }; 502 503 ZmDetailListView.prototype.setSize = 504 function(width, height) { 505 ZmListView.prototype.setSize.call(this, width, height); 506 this._resetColWidth(); 507 }; 508 509 ZmDetailListView.prototype.resetSize = 510 function(newWidth, newHeight) { 511 this.setSize(newWidth, newHeight); 512 var height = (newHeight == Dwt.DEFAULT) ? newHeight : newHeight - DwtListView.HEADERITEM_HEIGHT; 513 Dwt.setSize(this._parentEl, newWidth, height); 514 }; 515 516 ZmDetailListView.prototype._resetColWidth = 517 function() { 518 519 if (!this.headerColCreated) { return; } 520 521 var lastColIdx = this._getLastColumnIndex(); 522 if (lastColIdx) { 523 var lastCol = this._headerList[lastColIdx]; 524 if (lastCol._field != ZmItem.F_SORTED_BY) { 525 DwtListView.prototype._resetColWidth.apply(this, arguments); 526 } 527 } 528 }; 529 530 ZmDetailListView.prototype._getToolTip = 531 function(params) { 532 533 if( params.field == ZmItem.F_LOCK){ 534 var item = params.item; 535 if(item.locked){ 536 var dateFormatter = AjxDateFormat.getDateTimeInstance(AjxDateFormat.LONG, AjxDateFormat.SHORT); 537 var subs = { 538 title: ZmMsg.checkedOutFile, 539 fileProperties: [ 540 {name: ZmMsg.checkoutTo, value:item.lockUser}, 541 {name: ZmMsg.when, value: dateFormatter.format(item.lockTime)} 542 ] 543 }; 544 return AjxTemplate.expand("briefcase.Briefcase#Tooltip", subs); 545 } 546 } 547 548 return ZmBriefcaseBaseView.prototype._getToolTip.call(this, params); 549 }; 550 551 ZmDetailListView.prototype._folderChangeListener = 552 function(ev){ 553 554 // make sure this is current list view 555 if (appCtxt.getCurrentController() != this._controller) { return; } 556 557 ZmBriefcaseBaseView.prototype._folderChangeListener.call(this, ev); 558 559 var organizers = ev.getDetail("organizers"); 560 var organizer = (organizers && organizers.length) ? organizers[0] : ev.source; 561 var currentFolderId = this._controller._folderId; 562 563 var refresh = false; 564 if (ev.event == ZmEvent.E_CREATE) { 565 if(organizer && currentFolderId == organizer.parent.id) 566 refresh = true; 567 }else if(ev.event == ZmEvent.E_MODIFY) { 568 var fields = ev.getDetail("fields"); 569 if( fields[ZmOrganizer.F_NAME] || fields[ZmOrganizer.F_COLOR] ) 570 refresh = true; 571 }else if(ev.event == ZmEvent.E_MOVE || ev.event == ZmEvent.E_DELETE){ 572 refresh = true; 573 if (this.getDnDSelection() && this.getDnDSelection instanceof AjxVector) 574 this.dragDeselect(this.getDnDSelection().get(0)); 575 else if (this.getDnDSelection()) 576 this.dragDeselect(this.getDnDSelection()); 577 if(currentFolderId != organizer.id){ 578 this.collapseAll(); 579 } 580 } 581 582 if(refresh) { 583 appCtxt.getApp(ZmApp.BRIEFCASE).search({folderId: currentFolderId}); 584 } 585 586 }; 587 588 //drag and drop listeners 589 ZmDetailListView.prototype._dropListener = 590 function(ev) { 591 var data = ev.srcData.data; 592 var div = this.getTargetItemDiv(ev.uiEvent); 593 var dropFolder = this.getItemFromElement(div); 594 595 //handle drag from tree to listview by calling controller 596 if (ev.srcData && ev.srcData.controller != appCtxt.getCurrentController()){ 597 appCtxt.getCurrentController()._dropListener(ev); 598 return; 599 } 600 601 // only briefcase items can be dropped on us 602 if (ev.action == DwtDropEvent.DRAG_ENTER) { 603 ev.doIt = (dropFolder && (dropFolder instanceof ZmBriefcaseFolderItem) && (dropFolder.folder && dropFolder.folder.mayContain(data))); 604 DBG.println(AjxDebug.DBG3, "DRAG_ENTER: doIt = " + ev.doIt); 605 this.dragSelect(div); 606 } else if (ev.action == DwtDropEvent.DRAG_DROP) { 607 this.dragDeselect(div); 608 appCtxt.getCurrentController()._doMove(data, dropFolder.folder); 609 } else if (ev.action == DwtDropEvent.DRAG_LEAVE) { 610 view.dragDeselect(div); 611 } else if (ev.action == DwtDropEvent.DRAG_OP_CHANGED) { 612 // nothing 613 } 614 615 }; 616 617 ZmDetailListView.prototype._dragListener = 618 function(ev) { 619 if (ev.action == DwtDragEvent.SET_DATA) { 620 ev.srcData = {data: ev.srcControl.getDnDSelection(), controller: this}; 621 } 622 }; 623 624 ZmDetailListView.prototype._createHeader = 625 function(htmlArr, idx, headerCol, i, numCols, id, defaultColumnSort) { 626 627 if (headerCol._field == ZmItem.F_SORTED_BY) { 628 var field = headerCol._field; 629 var textTdId = this._itemCountTextTdId = DwtId.makeId(this.view, ZmSetting.RP_RIGHT, "td"); 630 htmlArr[idx++] = "<td id='"; 631 htmlArr[idx++] = id; 632 htmlArr[idx++] = "' class='"; 633 htmlArr[idx++] = (id == this._currentColId) ? "DwtListView-Column DwtListView-ColumnActive'" : 634 "DwtListView-Column'"; 635 htmlArr[idx++] = " width='auto'><table width='100%'><tr><td id='"; 636 htmlArr[idx++] = DwtId.getListViewHdrId(DwtId.WIDGET_HDR_LABEL, this._view, field); 637 htmlArr[idx++] = "' class='DwtListHeaderItem-label'>"; 638 htmlArr[idx++] = headerCol._label; 639 htmlArr[idx++] = "</td>"; 640 641 // sort icon 642 htmlArr[idx++] = "<td class='itemSortIcon' id='"; 643 htmlArr[idx++] = DwtId.getListViewHdrId(DwtId.WIDGET_HDR_ARROW, this._view, field); 644 htmlArr[idx++] = "'>"; 645 htmlArr[idx++] = AjxImg.getImageHtml(this._bSortAsc ? "ColumnUpArrow" : "ColumnDownArrow"); 646 htmlArr[idx++] = "</td>"; 647 648 // item count text 649 htmlArr[idx++] = "<td align=right class='itemCountText' id='"; 650 htmlArr[idx++] = textTdId; 651 htmlArr[idx++] = "'></td></tr></table></div></td>"; 652 } else { 653 return DwtListView.prototype._createHeader.apply(this, arguments); 654 } 655 }; 656 657 ZmDetailListView.prototype._initDragAndDrop = 658 function() { 659 this._dnd = new ZmDragAndDrop(this); 660 }; 661 662 ZmDetailListView.prototype._submitMyComputerAttachments = 663 function(files, node, isInline) { 664 var selectionCallback = this._controller._uploadFileListener.bind(this._controller); 665 var briefcaseApp = appCtxt.getApp(ZmApp.BRIEFCASE); 666 briefcaseApp.initExternalDndUpload(files, node, isInline, selectionCallback); 667 }; 668 669 670 ZmDetailListView.prototype._handleRename = function(item) { 671 // Always collapse - should be harmless if already collapsed or has no versions. We need 672 // to insure any divs created for revisions are removed before moving the item - otherwise 673 // they will be reused in their old location. 674 this.collapse(item, true); 675 676 this.removeItem(item); 677 var indices = this._sortIndex(this._list, item); 678 if (indices) { 679 this.addItem(item, indices.displayIndex, false, indices.listIndex); 680 } 681 item._nameUpdated = false; 682 }; 683 684 685 /** 686 * Override the sorted Index calculation. The DetailListView has a mismatch between its list 687 * and the actual displayed rows, which can contain versions of a file. 688 * 689 * @param {AjxVector} list vector containing the file entries 690 * @param {ZmBriefcaseItem} item file entry - find the position to insert it 691 * 692 * @return Object See DwtListView.addItem 693 * {number} displayIndex the index at which to add item to list view 694 * {number} listIndex index at which to add item to list 695 */ 696 ZmDetailListView.prototype._sortIndex = function(list, item){ 697 if (!list) { 698 return null; 699 } 700 701 var lItem; 702 var rowIds; 703 var a = list.getArray(); 704 var displayIndex = 0; 705 var itemName = item.name.toLowerCase(); 706 var i; 707 for (i = 0; i < a.length; i++) { 708 lItem = a[i]; 709 if (!lItem.isFolder && (itemName < lItem.name.toLowerCase())) { 710 break; 711 } 712 rowIds = this._itemRowIdList[lItem.id]; 713 if (rowIds && rowIds.length) { 714 displayIndex += rowIds.length + 1; 715 } else { 716 displayIndex++; 717 } 718 } 719 // listIndex = insertion into the underlying list vector. 720 // displayIndex: 721 return { listIndex: i, displayIndex: displayIndex}; 722 };