diff --git a/src/lib/constants.js b/src/lib/constants.js index e5afd80ab..c6ef9fa30 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -47,6 +47,7 @@ export const CLASS_MULTI_IMAGE_PAGE = 'bp-multi-image-page'; export const CLASS_INVISIBLE = 'bp-is-invisible'; export const CLASS_IS_TRANSPARENT = 'bp-is-transparent'; export const CLASS_IS_VISIBLE = 'bp-is-visible'; +export const CLASS_IS_PRINTABLE = 'bp-is-printable'; export const CLASS_IS_SCROLLABLE = 'bp-is-scrollable'; export const CLASS_IS_SELECTABLE = 'bp-is-selectable'; export const CLASS_IS_BUFFERING = 'bp-is-buffering'; diff --git a/src/lib/viewers/text/CSV.scss b/src/lib/viewers/text/CSV.scss index 20cb98354..e6f5a132b 100644 --- a/src/lib/viewers/text/CSV.scss +++ b/src/lib/viewers/text/CSV.scss @@ -1,4 +1,5 @@ @import '../../boxuiVariables'; +@import 'base'; .bp-text-csv { position: absolute; @@ -17,11 +18,6 @@ white-space: pre; word-wrap: normal; word-break: normal; - user-select: none; - - .bp-is-selectable & { - user-select: auto; - } .bp-text-csv-grid { width: 100%; diff --git a/src/lib/viewers/text/PlainTextViewer.js b/src/lib/viewers/text/PlainTextViewer.js index 1c6597363..2642a37b2 100644 --- a/src/lib/viewers/text/PlainTextViewer.js +++ b/src/lib/viewers/text/PlainTextViewer.js @@ -2,7 +2,7 @@ import './Text.scss'; import TextBaseViewer from './TextBaseViewer'; import Browser from '../../Browser'; import Popup from '../../Popup'; -import { CLASS_HIDDEN, TEXT_STATIC_ASSETS_VERSION, CLASS_IS_SCROLLABLE } from '../../constants'; +import { CLASS_HIDDEN, CLASS_IS_SCROLLABLE, TEXT_STATIC_ASSETS_VERSION } from '../../constants'; import { ICON_PRINT_CHECKMARK } from '../../icons/icons'; import { HIGHLIGHTTABLE_EXTENSIONS } from '../../extensions'; import { openContentInsideIframe, createAssetUrlCreator, createStylesheet } from '../../util'; @@ -116,7 +116,7 @@ class PlainTextViewer extends TextBaseViewer { this.textEl.tabIndex = '0'; this.codeEl = this.textEl.appendChild(document.createElement('code')); - this.codeEl.classList.add(this.options.file.extension); + this.codeEl.className = `bp-text-code ${this.options.file.extension}`; // Whether or not we truncated text shown due to performance issues this.truncated = false; diff --git a/src/lib/viewers/text/Text.scss b/src/lib/viewers/text/Text.scss index b68837233..f5a283ae6 100644 --- a/src/lib/viewers/text/Text.scss +++ b/src/lib/viewers/text/Text.scss @@ -1,4 +1,5 @@ @import '../../boxuiVariables'; +@import 'base'; .bp-text-plain { position: absolute; @@ -12,11 +13,6 @@ text-align: left; word-wrap: break-word; background-color: $white; - user-select: none; - - .bp-is-selectable & { - user-select: auto; - } /* Override Github CSS */ .bp & { diff --git a/src/lib/viewers/text/TextBaseViewer.js b/src/lib/viewers/text/TextBaseViewer.js index 32f9eb4bd..c5c9632a1 100644 --- a/src/lib/viewers/text/TextBaseViewer.js +++ b/src/lib/viewers/text/TextBaseViewer.js @@ -1,7 +1,7 @@ import Controls from '../../Controls'; import BaseViewer from '../BaseViewer'; import { checkPermission } from '../../file'; -import { CLASS_IS_SELECTABLE, PERMISSION_DOWNLOAD } from '../../constants'; +import { CLASS_IS_PRINTABLE, CLASS_IS_SELECTABLE, PERMISSION_DOWNLOAD } from '../../constants'; import { ICON_ZOOM_IN, ICON_ZOOM_OUT, ICON_FULLSCREEN_IN, ICON_FULLSCREEN_OUT } from '../../icons/icons'; @@ -97,6 +97,7 @@ class TextBaseViewer extends BaseViewer { load() { // Enable text selection if user has download permissions and 'disableTextLayer' option is not true if (checkPermission(this.options.file, PERMISSION_DOWNLOAD) && !this.getViewerOption('disableTextLayer')) { + this.containerEl.classList.add(CLASS_IS_PRINTABLE); this.containerEl.classList.add(CLASS_IS_SELECTABLE); } diff --git a/src/lib/viewers/text/__tests__/TextBaseViewer-test.js b/src/lib/viewers/text/__tests__/TextBaseViewer-test.js index f9b298f99..ce69dc8ef 100644 --- a/src/lib/viewers/text/__tests__/TextBaseViewer-test.js +++ b/src/lib/viewers/text/__tests__/TextBaseViewer-test.js @@ -95,16 +95,29 @@ describe('lib/viewers/text/TextBaseViewer', () => { }); describe('load()', () => { - it('should add selectable class if user has download permissions', () => { + it('should add selectable/printable classes if user has download permissions', () => { sandbox .stub(file, 'checkPermission') .withArgs(textBase.options.file, PERMISSION_DOWNLOAD) .returns(true); textBase.load(); + + expect(textBase.containerEl).to.have.class('bp-is-printable'); expect(textBase.containerEl).to.have.class('bp-is-selectable'); }); - it('should not add selectable class if disableTextViewer option is true', () => { + it('should not add selectable/printable classes if user does not have download permissions', () => { + sandbox + .stub(file, 'checkPermission') + .withArgs(textBase.options.file, PERMISSION_DOWNLOAD) + .returns(false); + textBase.load(); + + expect(textBase.containerEl).to.not.have.class('bp-is-printable'); + expect(textBase.containerEl).to.not.have.class('bp-is-selectable'); + }); + + it('should not add selectable/printable classes if disableTextViewer option is true', () => { sandbox .stub(file, 'checkPermission') .withArgs(textBase.options.file, PERMISSION_DOWNLOAD) @@ -116,6 +129,7 @@ describe('lib/viewers/text/TextBaseViewer', () => { textBase.load(); + expect(textBase.containerEl).to.not.have.class('bp-is-printable'); expect(textBase.containerEl).to.not.have.class('bp-is-selectable'); }); }); diff --git a/src/lib/viewers/text/_base.scss b/src/lib/viewers/text/_base.scss new file mode 100644 index 000000000..4f17db0d4 --- /dev/null +++ b/src/lib/viewers/text/_base.scss @@ -0,0 +1,27 @@ +.bp-content { + .bp-text { + user-select: none; + } + + &.bp-is-selectable { + .bp-text { + user-select: auto; + } + + .bp-text-code { + cursor: text; + } + } +} + +@media print { + .bp-content { + .bp-text { + display: none; // Hide text in app-level print preview window + } + + &.bp-is-printable .bp-text { + display: block; + } + } +}