1/** 2* ownCloud 3* 4* @author Vincent Petry 5* @copyright 2014 Vincent Petry <[email protected]> 6* 7* This library is free software; you can redistribute it and/or 8* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE 9* License as published by the Free Software Foundation; either 10* version 3 of the License, or any later version. 11* 12* This library is distributed in the hope that it will be useful, 13* but WITHOUT ANY WARRANTY; without even the implied warranty of 14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15* GNU AFFERO GENERAL PUBLIC LICENSE for more details. 16* 17* You should have received a copy of the GNU Affero General Public 18* License along with this library. If not, see <http://www.gnu.org/licenses/>. 19* 20*/ 21 22(function() { 23 /** 24 * The FileSummary class encapsulates the file summary values and 25 * the logic to render it in the given container 26 * 27 * @constructs FileSummary 28 * @memberof OCA.Files 29 * 30 * @param $tr table row element 31 * @param {OC.Backbone.Model} [options.filesConfig] files app configuration 32 */ 33 var FileSummary = function($tr, options) { 34 options = options || {}; 35 var self = this; 36 this.$el = $tr; 37 var filesConfig = options.config; 38 if (filesConfig) { 39 this._showHidden = !!filesConfig.show_hidden; 40 window._nc_event_bus.subscribe('files:config:updated', ({ key, value }) => { 41 if (key === 'show_hidden') { 42 self._showHidden = !!value; 43 self.update(); 44 } 45 }); 46 } 47 this.clear(); 48 this.render(); 49 }; 50 51 FileSummary.prototype = { 52 _showHidden: null, 53 54 summary: { 55 totalFiles: 0, 56 totalDirs: 0, 57 totalHidden: 0, 58 totalSize: 0, 59 filter:'', 60 sumIsPending:false 61 }, 62 63 /** 64 * Returns whether the given file info must be hidden 65 * 66 * @param {OC.Files.FileInfo} fileInfo file info 67 * 68 * @return {boolean} true if the file is a hidden file, false otherwise 69 */ 70 _isHiddenFile: function(file) { 71 return file.name && file.name.charAt(0) === '.'; 72 }, 73 74 /** 75 * Adds file 76 * @param {OC.Files.FileInfo} file file to add 77 * @param {boolean} update whether to update the display 78 */ 79 add: function(file, update) { 80 if (file.name && file.name.toLowerCase().indexOf(this.summary.filter) === -1) { 81 return; 82 } 83 if (file.type === 'dir' || file.mime === 'httpd/unix-directory') { 84 this.summary.totalDirs++; 85 } 86 else { 87 this.summary.totalFiles++; 88 } 89 if (this._isHiddenFile(file)) { 90 this.summary.totalHidden++; 91 } 92 93 var size = parseInt(file.size, 10) || 0; 94 if (size >=0) { 95 this.summary.totalSize += size; 96 } else { 97 this.summary.sumIsPending = true; 98 } 99 if (!!update) { 100 this.update(); 101 } 102 }, 103 /** 104 * Removes file 105 * @param {OC.Files.FileInfo} file file to remove 106 * @param {boolean} update whether to update the display 107 */ 108 remove: function(file, update) { 109 if (file.name && file.name.toLowerCase().indexOf(this.summary.filter) === -1) { 110 return; 111 } 112 if (file.type === 'dir' || file.mime === 'httpd/unix-directory') { 113 this.summary.totalDirs--; 114 } 115 else { 116 this.summary.totalFiles--; 117 } 118 if (this._isHiddenFile(file)) { 119 this.summary.totalHidden--; 120 } 121 var size = parseInt(file.size, 10) || 0; 122 if (size >=0) { 123 this.summary.totalSize -= size; 124 } 125 if (!!update) { 126 this.update(); 127 } 128 }, 129 setFilter: function(filter, files){ 130 this.summary.filter = filter.toLowerCase(); 131 this.calculate(files); 132 }, 133 /** 134 * Returns the total of files and directories 135 */ 136 getTotal: function() { 137 return this.summary.totalDirs + this.summary.totalFiles; 138 }, 139 /** 140 * Recalculates the summary based on the given files array 141 * @param files array of files 142 */ 143 calculate: function(files) { 144 var file; 145 var summary = { 146 totalDirs: 0, 147 totalFiles: 0, 148 totalHidden: 0, 149 totalSize: 0, 150 filter: this.summary.filter, 151 sumIsPending: false 152 }; 153 154 for (var i = 0; i < files.length; i++) { 155 file = files[i]; 156 if (file.name && file.name.toLowerCase().indexOf(this.summary.filter) === -1) { 157 continue; 158 } 159 if (file.type === 'dir' || file.mime === 'httpd/unix-directory') { 160 summary.totalDirs++; 161 } 162 else { 163 summary.totalFiles++; 164 } 165 if (this._isHiddenFile(file)) { 166 summary.totalHidden++; 167 } 168 var size = parseInt(file.size, 10) || 0; 169 if (size >=0) { 170 summary.totalSize += size; 171 } else { 172 summary.sumIsPending = true; 173 } 174 } 175 this.setSummary(summary); 176 }, 177 /** 178 * Clears the summary 179 */ 180 clear: function() { 181 this.calculate([]); 182 }, 183 /** 184 * Sets the current summary values 185 * @param summary map 186 */ 187 setSummary: function(summary) { 188 this.summary = summary; 189 if (typeof this.summary.filter === 'undefined') { 190 this.summary.filter = ''; 191 } 192 this.update(); 193 }, 194 195 _infoTemplate: function(data) { 196 /* NOTE: To update the template make changes in filesummary.handlebars 197 * and run: 198 * 199 * handlebars -n OCA.Files.FileSummary.Templates filesummary.handlebars -f filesummary_template.js 200 */ 201 return OCA.Files.Templates['filesummary'](_.extend({ 202 connectorLabel: t('files', '{dirs} and {files}', {dirs: '', files: ''}) 203 }, data)); 204 }, 205 206 /** 207 * Renders the file summary element 208 */ 209 update: function() { 210 if (!this.$el) { 211 return; 212 } 213 if (!this.summary.totalFiles && !this.summary.totalDirs) { 214 this.$el.addClass('hidden'); 215 return; 216 } 217 // There's a summary and data -> Update the summary 218 this.$el.removeClass('hidden'); 219 var $dirInfo = this.$el.find('.dirinfo'); 220 var $fileInfo = this.$el.find('.fileinfo'); 221 var $connector = this.$el.find('.connector'); 222 var $filterInfo = this.$el.find('.filter'); 223 var $hiddenInfo = this.$el.find('.hiddeninfo'); 224 225 // Substitute old content with new translations 226 $dirInfo.html(n('files', '%n folder', '%n folders', this.summary.totalDirs)); 227 $fileInfo.html(n('files', '%n file', '%n files', this.summary.totalFiles)); 228 $hiddenInfo.html(' (' + n('files', 'including %n hidden', 'including %n hidden', this.summary.totalHidden) + ')'); 229 var fileSize = this.summary.sumIsPending ? t('files', 'Pending') : OC.Util.humanFileSize(this.summary.totalSize, false, false); 230 this.$el.find('.filesize').html(fileSize); 231 232 // Show only what's necessary (may be hidden) 233 if (this.summary.totalDirs === 0) { 234 $dirInfo.addClass('hidden'); 235 $connector.addClass('hidden'); 236 } else { 237 $dirInfo.removeClass('hidden'); 238 } 239 if (this.summary.totalFiles === 0) { 240 $fileInfo.addClass('hidden'); 241 $connector.addClass('hidden'); 242 } else { 243 $fileInfo.removeClass('hidden'); 244 } 245 if (this.summary.totalDirs > 0 && this.summary.totalFiles > 0) { 246 $connector.removeClass('hidden'); 247 } 248 $hiddenInfo.toggleClass('hidden', this.summary.totalHidden === 0 || this._showHidden) 249 if (this.summary.filter === '') { 250 $filterInfo.html(''); 251 $filterInfo.addClass('hidden'); 252 } else { 253 $filterInfo.html(' ' + n('files', 'matches "{filter}"', 'match "{filter}"', this.summary.totalDirs + this.summary.totalFiles, {filter: this.summary.filter})); 254 $filterInfo.removeClass('hidden'); 255 } 256 }, 257 render: function() { 258 if (!this.$el) { 259 return; 260 } 261 var summary = this.summary; 262 263 // don't show the filesize column, if filesize is NaN (e.g. in trashbin) 264 var fileSize = ''; 265 if (!isNaN(summary.totalSize)) { 266 fileSize = summary.sumIsPending ? t('files', 'Pending') : OC.Util.humanFileSize(summary.totalSize, false, false); 267 fileSize = '<td class="filesize">' + fileSize + '</td>'; 268 } 269 270 var $summary = $( 271 '<td class="filesummary">'+ this._infoTemplate() + '</td>' + 272 fileSize + 273 '<td class="date"></td>' 274 ); 275 this.$el.addClass('hidden'); 276 this.$el.append($summary); 277 this.update(); 278 } 279 }; 280 OCA.Files.FileSummary = FileSummary; 281})(); 282
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.