diff options
Diffstat (limited to 'app/assets/javascripts/lib/utils/common_utils.js')
-rw-r--r-- | app/assets/javascripts/lib/utils/common_utils.js | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index e14fff7a610..9e22cdc04e9 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -192,8 +192,12 @@ export const contentTop = () => { const mrTabsHeight = $('.merge-request-tabs').height() || 0; const headerHeight = $('.navbar-gitlab').height() || 0; const diffFilesChanged = $('.js-diff-files-changed').height() || 0; + const diffFileLargeEnoughScreen = + 'matchMedia' in window ? window.matchMedia('min-width: 768') : true; + const diffFileTitleBar = + (diffFileLargeEnoughScreen && $('.diff-file .file-title-flex-parent:visible').height()) || 0; - return perfBar + mrTabsHeight + headerHeight + diffFilesChanged; + return perfBar + mrTabsHeight + headerHeight + diffFilesChanged + diffFileTitleBar; }; export const scrollToElement = element => { @@ -226,7 +230,17 @@ export const getParameterByName = (name, urlToParse) => { return decodeURIComponent(results[2].replace(/\+/g, ' ')); }; -const handleSelectedRange = range => { +const handleSelectedRange = (range, restrictToNode) => { + // Make sure this range is within the restricting container + if (restrictToNode && !range.intersectsNode(restrictToNode)) return null; + + // If only a part of the range is within the wanted container, we need to restrict the range to it + if (restrictToNode && !restrictToNode.contains(range.commonAncestorContainer)) { + if (!restrictToNode.contains(range.startContainer)) range.setStart(restrictToNode, 0); + if (!restrictToNode.contains(range.endContainer)) + range.setEnd(restrictToNode, restrictToNode.childNodes.length); + } + const container = range.commonAncestorContainer; // add context to fragment if needed if (container.tagName === 'OL') { @@ -237,14 +251,22 @@ const handleSelectedRange = range => { return range.cloneContents(); }; -export const getSelectedFragment = () => { +export const getSelectedFragment = restrictToNode => { const selection = window.getSelection(); if (selection.rangeCount === 0) return null; + // Most usages of the selection only want text from a part of the page (e.g. discussion) + if (restrictToNode && !selection.containsNode(restrictToNode, true)) return null; + const documentFragment = document.createDocumentFragment(); + documentFragment.originalNodes = []; for (let i = 0; i < selection.rangeCount; i += 1) { const range = selection.getRangeAt(i); - documentFragment.appendChild(handleSelectedRange(range)); + const handledRange = handleSelectedRange(range, restrictToNode); + if (handledRange) { + documentFragment.appendChild(handledRange); + documentFragment.originalNodes.push(range.commonAncestorContainer); + } } if (documentFragment.textContent.length === 0) return null; @@ -403,12 +425,28 @@ export const historyPushState = newUrl => { }; /** + * Returns true for a String "true" and false otherwise. + * This is the opposite of Boolean(...).toString() + * + * @param {String} value + * @returns {Boolean} + */ +export const parseBoolean = value => value === 'true'; + +/** * Converts permission provided as strings to booleans. * * @param {String} string * @returns {Boolean} */ -export const convertPermissionToBoolean = permission => permission === 'true'; +export const convertPermissionToBoolean = permission => { + if (process.env.NODE_ENV !== 'production') { + // eslint-disable-next-line no-console + console.warn('convertPermissionToBoolean is deprecated! Please use parseBoolean instead.'); + } + + return parseBoolean(permission); +}; /** * Back Off exponential algorithm |