diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 60afcf9b57..d8336847e0 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -244,6 +244,15 @@ table td.filename a.name { line-height: 50px; padding: 0; } +table td.filename .thumbnail { + display: inline-block; + width: 32px; + height: 32px; + margin-left: 8px; + margin-top: 9px; + cursor: pointer; + float: left; +} table td.filename input.filename { width: 70%; margin-top: 1px; @@ -348,7 +357,7 @@ table td.filename .uploadtext { } /* File checkboxes */ -#fileList tr td.filename>input[type="checkbox"]:first-child { +#fileList tr td.filename>.selectCheckBox { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); opacity: 0; @@ -357,36 +366,33 @@ table td.filename .uploadtext { margin: 32px 0 4px 32px; /* bigger clickable area doesn’t work in FF width:2.8em; height:2.4em;*/ } /* Show checkbox when hovering, checked, or selected */ -#fileList tr:hover td.filename>input[type="checkbox"]:first-child, -#fileList tr:focus td.filename>input[type="checkbox"]:first-child, -#fileList tr td.filename>input[type="checkbox"]:checked:first-child, -#fileList tr.selected td.filename>input[type="checkbox"]:first-child { +#fileList tr:hover td.filename>.selectCheckBox, +#fileList tr:focus td.filename>.selectCheckBox, +#fileList tr td.filename>.selectCheckBox:checked, +#fileList tr.selected td.filename>.selectCheckBox { opacity: 1; } -.lte9 #fileList tr:hover td.filename>input[type="checkbox"]:first-child, -.lte9 #fileList tr:focus td.filename>input[type="checkbox"]:first-child, -.lte9 #fileList tr td.filename>input[type="checkbox"][checked=checked]:first-child, -.lte9 #fileList tr.selected td.filename>input[type="checkbox"]:first-child { +.lte9 #fileList tr:hover td.filename>.selectCheckBox, +.lte9 #fileList tr:focus td.filename>.selectCheckBox, +.lte9 #fileList tr td.filename>.selectCheckBox[checked=checked], +.lte9 #fileList tr.selected td.filename>.selectCheckBox { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter: alpha(opacity=100); } /* Use label to have bigger clickable size for checkbox */ -#fileList tr td.filename>input[type="checkbox"] + label, +#fileList tr td.filename>.selectCheckBox + label, .select-all + label { height: 50px; position: absolute; width: 50px; z-index: 5; } -#fileList tr td.filename>input[type="checkbox"]{ +#fileList tr td.filename>.selectCheckBox { /* sometimes checkbox height is bigger (KDE/Qt), so setting to absolute * to prevent it to increase the height */ position: absolute; -} -#fileList tr td.filename>input[type="checkbox"] + label { - left: 0; - top: 0; + z-index: 10; } .select-all + label { top: 0; @@ -395,6 +401,7 @@ table td.filename .uploadtext { position: absolute; top: 18px; left: 18px; + z-index: 10; } #fileList tr td.filename { diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 7abbf2c80b..b20bdf23e1 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -93,6 +93,12 @@ */ fileActions: null, + /** + * Whether selection is allowed, checkboxes and selection overlay will + * be rendered + */ + _allowSelection: true, + /** * Map of file id to file data * @type Object. @@ -203,7 +209,7 @@ this.$el.on('show', this._onResize); this.$fileList.on('click','td.filename>a.name', _.bind(this._onClickFile, this)); - this.$fileList.on('change', 'td.filename>input:checkbox', _.bind(this._onClickFileCheckbox, this)); + this.$fileList.on('change', 'td.filename>.selectCheckBox', _.bind(this._onClickFileCheckbox, this)); this.$el.on('urlChanged', _.bind(this._onUrlChanged, this)); this.$el.find('.select-all').click(_.bind(this._onClickSelectAll, this)); this.$el.find('.download').click(_.bind(this._onClickDownloadSelected, this)); @@ -281,7 +287,7 @@ * @param state true to select, false to deselect */ _selectFileEl: function($tr, state) { - var $checkbox = $tr.find('td.filename>input:checkbox'); + var $checkbox = $tr.find('td.filename>.selectCheckBox'); var oldData = !!this._selectedFiles[$tr.data('id')]; var data; $checkbox.prop('checked', state); @@ -330,7 +336,7 @@ else { this._lastChecked = $tr; } - var $checkbox = $tr.find('td.filename>input:checkbox'); + var $checkbox = $tr.find('td.filename>.selectCheckBox'); this._selectFileEl($tr, !$checkbox.prop('checked')); this.updateSelectionSummary(); } else { @@ -372,7 +378,7 @@ */ _onClickSelectAll: function(e) { var checked = $(e.target).prop('checked'); - this.$fileList.find('td.filename>input:checkbox').prop('checked', checked) + this.$fileList.find('td.filename>.selectCheckBox').prop('checked', checked) .closest('tr').toggleClass('selected', checked); this._selectedFiles = {}; this._selectionSummary.clear(); @@ -560,7 +566,7 @@ this.$fileList.append(tr); if (isAllSelected || this._selectedFiles[fileData.id]) { tr.addClass('selected'); - tr.find('input:checkbox').prop('checked', true); + tr.find('.selectCheckBox').prop('checked', true); } if (animate) { tr.addClass('appear transparent'); @@ -685,10 +691,8 @@ } // filename td - td = $('').attr({ - "class": "filename", - "style": 'background-image:url(' + icon + '); background-size: 32px;' - }); + td = $(''); + // linkUrl if (type === 'dir') { @@ -697,8 +701,16 @@ else { linkUrl = this.getDownloadUrl(name, path); } - td.append(''); + if (this._allowSelection) { + td.append( + '' + ); + } else { + td.append('
'); + } var linkElem = $('').attr({ "class": "name", "href": linkUrl @@ -894,6 +906,7 @@ this.fileActions.display(filenameTd, !options.silent, this); if (fileData.isPreviewAvailable) { + var iconDiv = filenameTd.find('.thumbnail'); // lazy load / newly inserted td ? if (options.animate) { this.lazyLoadPreview({ @@ -901,7 +914,7 @@ mime: mime, etag: fileData.etag, callback: function(url) { - filenameTd.css('background-image', 'url(' + url + ')'); + iconDiv.css('background-image', 'url(' + url + ')'); } }); } @@ -913,7 +926,7 @@ }; var previewUrl = this.generatePreviewUrl(urlSpec); previewUrl = previewUrl.replace('(', '%28').replace(')', '%29'); - filenameTd.css('background-image', 'url(' + previewUrl + ')'); + iconDiv.css('background-image', 'url(' + previewUrl + ')'); } } return tr; @@ -1519,7 +1532,7 @@ var fileEl = self.remove(file, {updateSummary: false}); // FIXME: not sure why we need this after the // element isn't even in the DOM any more - fileEl.find('input[type="checkbox"]').prop('checked', false); + fileEl.find('.selectCheckBox').prop('checked', false); fileEl.removeClass('selected'); self.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')}); }); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 21f8a12f4b..83ff532313 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -955,8 +955,8 @@ describe('OCA.Files.FileList tests', function() { name: 'testFile.txt' }; var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); + var $imgDiv = $tr.find('td.filename .thumbnail'); + expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); expect(previewLoadStub.notCalled).toEqual(true); }); it('renders default icon for dir when none provided and no preview is available', function() { @@ -965,8 +965,8 @@ describe('OCA.Files.FileList tests', function() { name: 'test dir' }; var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/folder.svg'); + var $imgDiv = $tr.find('td.filename .thumbnail'); + expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/folder.svg'); expect(previewLoadStub.notCalled).toEqual(true); }); it('renders provided icon for file when provided', function() { @@ -976,8 +976,8 @@ describe('OCA.Files.FileList tests', function() { icon: OC.webroot + '/core/img/filetypes/application-pdf.svg' }; var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/application-pdf.svg'); + var $imgDiv = $tr.find('td.filename .thumbnail'); + expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/application-pdf.svg'); expect(previewLoadStub.notCalled).toEqual(true); }); it('renders preview when no icon was provided and preview is available', function() { @@ -988,11 +988,11 @@ describe('OCA.Files.FileList tests', function() { }; var $tr = fileList.add(fileData); var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); + expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); expect(previewLoadStub.calledOnce).toEqual(true); // third argument is callback previewLoadStub.getCall(0).args[0].callback(OC.webroot + '/somepath.png'); - expect(OC.TestUtil.getImageUrl($td)).toEqual(OC.webroot + '/somepath.png'); + expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.webroot + '/somepath.png'); }); it('renders default file type icon when no icon was provided and no preview is available', function() { var fileData = { @@ -1001,8 +1001,8 @@ describe('OCA.Files.FileList tests', function() { isPreviewAvailable: false }; var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); + var $imgDiv = $tr.find('td.filename .thumbnail'); + expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); expect(previewLoadStub.notCalled).toEqual(true); }); }); diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js index bd26b13b78..2c7d6c7d43 100644 --- a/apps/files_sharing/js/sharedfilelist.js +++ b/apps/files_sharing/js/sharedfilelist.js @@ -38,6 +38,7 @@ _sharedWithUser: false, _linksOnly: false, _clientSideSort: true, + _allowSelection: false, /** * @private diff --git a/apps/files_sharing/tests/js/shareSpec.js b/apps/files_sharing/tests/js/shareSpec.js index 33c9c83b97..e5b5de314d 100644 --- a/apps/files_sharing/tests/js/shareSpec.js +++ b/apps/files_sharing/tests/js/shareSpec.js @@ -99,7 +99,7 @@ describe('OCA.Sharing.Util tests', function() { $action = $tr.find('.action-share'); expect($action.hasClass('permanent')).toEqual(false); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); - expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder.svg'); expect($action.find('img').length).toEqual(1); }); it('shows simple share text with share icon', function() { @@ -119,7 +119,7 @@ describe('OCA.Sharing.Util tests', function() { expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text()).toEqual('Shared'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); - expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-shared.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); expect($action.find('img').length).toEqual(1); }); it('shows simple share text with public icon when shared with link', function() { @@ -140,7 +140,7 @@ describe('OCA.Sharing.Util tests', function() { expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text()).toEqual('Shared'); expect(OC.basename($action.find('img').attr('src'))).toEqual('public.svg'); - expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-public.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-public.svg'); expect($action.find('img').length).toEqual(1); }); it('shows owner name when owner is available', function() { @@ -161,7 +161,7 @@ describe('OCA.Sharing.Util tests', function() { expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text()).toEqual('User One'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); - expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-shared.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); }); it('shows recipients when recipients are available', function() { var $action, $tr; @@ -181,7 +181,7 @@ describe('OCA.Sharing.Util tests', function() { expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text()).toEqual('Shared with User One, User Two'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); - expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-shared.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); expect($action.find('img').length).toEqual(1); }); it('shows static share text when file shared with user that has no share permission', function() { @@ -203,7 +203,7 @@ describe('OCA.Sharing.Util tests', function() { expect($action.hasClass('permanent')).toEqual(true); expect($action.find('>span').text().trim()).toEqual('User One'); expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg'); - expect(OC.basename(getImageUrl($tr.find('.filename')))).toEqual('folder-shared.svg'); + expect(OC.basename(getImageUrl($tr.find('.filename .thumbnail')))).toEqual('folder-shared.svg'); expect($action.find('img').length).toEqual(1); }); }); diff --git a/core/js/share.js b/core/js/share.js index 80a2d7d169..bcb604feaa 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -131,7 +131,7 @@ OC.Share={ } for(i = 0; i < files.length; i++) { if ($(files[i]).closest('tr').data('type') === 'dir') { - $(files[i]).css('background-image', 'url('+shareFolder+')'); + $(files[i]).find('.thumbnail').css('background-image', 'url('+shareFolder+')'); } } } @@ -238,10 +238,10 @@ OC.Share={ else { shareFolderIcon = OC.imagePath('core', 'filetypes/folder-shared'); } - $tr.children('.filename').css('background-image', 'url(' + shareFolderIcon + ')'); + $tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')'); } else if (type === 'dir') { shareFolderIcon = OC.imagePath('core', 'filetypes/folder'); - $tr.children('.filename').css('background-image', 'url(' + shareFolderIcon + ')'); + $tr.find('.filename .thumbnail').css('background-image', 'url(' + shareFolderIcon + ')'); } // update share action text / icon if (hasShares || owner) { diff --git a/core/js/tests/specs/shareSpec.js b/core/js/tests/specs/shareSpec.js index f714b41dda..4859ba782d 100644 --- a/core/js/tests/specs/shareSpec.js +++ b/core/js/tests/specs/shareSpec.js @@ -509,7 +509,7 @@ describe('OC.Share tests', function() { beforeEach(function() { tipsyStub = sinon.stub($.fn, 'tipsy'); - $file = $('File name'); + $file = $('
File name'); $file.find('.filename').append( '' + '' + @@ -581,7 +581,7 @@ describe('OC.Share tests', function() { describe('displaying the folder icon', function() { function checkIcon(expectedImage) { - var imageUrl = OC.TestUtil.getImageUrl($file.find('.filename')); + var imageUrl = OC.TestUtil.getImageUrl($file.find('.filename .thumbnail')); expectedIcon = OC.imagePath('core', expectedImage); expect(imageUrl).toEqual(expectedIcon); }