From c3ea10d2e2d58eb5b149c21648665ed121e6d0ac Mon Sep 17 00:00:00 2001 From: gdub22 Date: Sun, 15 Feb 2015 16:24:56 -0500 Subject: [PATCH] ensure floating toolbar always stays onscreen --- package.json | 2 +- src/css/toolbar.less | 10 +++++++--- src/js/editor/editor.js | 26 +++++++++++--------------- src/js/utils/element-utils.js | 20 ++++++++++++-------- src/js/views/toolbar.js | 12 ++++++++---- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 32555ddbe..efeb024b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "content-kit-editor", - "version": "0.1.0", + "version": "0.1.1", "description": "A modern, minimalist WYSIWYG editor.", "repository": "https://github.com/bustlelabs/content-kit-editor", "main": "dist/content-kit-editor.js", diff --git a/src/css/toolbar.less b/src/css/toolbar.less index 10ac30c70..901d61300 100644 --- a/src/css/toolbar.less +++ b/src/css/toolbar.less @@ -6,9 +6,6 @@ text-align: center; position: absolute; z-index: @z-index--toolbar; - background: linear-gradient(to bottom, rgba(74,74,74,0.97) 0%,rgba(43,43,43,1) 100%); - box-shadow: 0 1px 3px -1px rgba(0,0,0,0.8), inset 0 2px 0 rgba(255,255,255,0.12), inset 1px 1px 0 #282828, inset -1px -1px 0 #282828; - border-radius: 3px; transition: left @elementMoveSpeed, top @elementMoveSpeed; margin-bottom: 0.45em; // space for arrow } @@ -78,9 +75,16 @@ background-color: #eee; } +.ck-toolbar-content { + border-radius: 3px; + background: linear-gradient(to bottom, rgba(74,74,74,0.97) 0%,rgba(43,43,43,1) 100%); + box-shadow: 0 1px 3px -1px rgba(0,0,0,0.8), inset 0 2px 0 rgba(255,255,255,0.12), inset 1px 1px 0 #282828, inset -1px -1px 0 #282828; +} + .ck-toolbar-buttons { border-radius: 5px; overflow: hidden; + white-space: nowrap; } .ck-toolbar-btn { diff --git a/src/js/editor/editor.js b/src/js/editor/editor.js index a1c26d5eb..1b8ff4254 100644 --- a/src/js/editor/editor.js +++ b/src/js/editor/editor.js @@ -49,22 +49,18 @@ var defaults = { }) }; +function isNaughtyKeystroke(e) { + return (!e.shiftKey && e.which === Keycodes.ENTER) || + (e.ctrlKey && e.which === Keycodes.M) || + (e.which === Keycodes.BKSP); +} + function bindContentEditableTypingListeners(editor) { - // Correct some contentEditable woes before reparsing - editor.element.addEventListener('keyup', function(e) { - // Assure there is always a supported block tag, and not empty text nodes or divs. - // On a carrage return, make sure to always generate a 'p' tag - if (!getSelectionBlockElement() || - !editor.element.textContent || - (!e.shiftKey && e.which === Keycodes.ENTER) || (e.ctrlKey && e.which === Keycodes.M)) { - document.execCommand('formatBlock', false, Type.PARAGRAPH.tag); - } //else if (e.which === Keycodes.BKSP) { - // TODO: Need to rerender when backspacing 2 blocks together - //var cursorIndex = editor.getCursorIndexInCurrentBlock(); - //var currentBlockElement = getSelectionBlockElement(); - //editor.renderBlockAt(editor.getCurrentBlockIndex(), true); - //setCursorIndexInElement(currentBlockElement, cursorIndex); - //} + + editor.element.addEventListener('keydown', function(e) { + if (isNaughtyKeystroke(e)) { + e.preventDefault(); + } }); // On 'PASTE' sanitize and insert diff --git a/src/js/utils/element-utils.js b/src/js/utils/element-utils.js index fa9077bd4..1cba840dd 100644 --- a/src/js/utils/element-utils.js +++ b/src/js/utils/element-utils.js @@ -70,44 +70,48 @@ function positionElementToRect(element, rect, topOffset, leftOffset) { var relativeOffset = getElementRelativeOffset(element); var style = element.style; var round = Math.round; + var left, top; topOffset = topOffset || 0; leftOffset = leftOffset || 0; - style.left = round(rect.left - relativeOffset.left - leftOffset) + 'px'; - style.top = round(rect.top - relativeOffset.top - topOffset) + 'px'; + left = round(rect.left - relativeOffset.left - leftOffset); + top = round(rect.top - relativeOffset.top - topOffset); + style.left = left + 'px'; + style.top = top + 'px'; + return { left: left, top: top }; } function positionElementHorizontallyCenteredToRect(element, rect, topOffset) { var horizontalCenter = (element.offsetWidth / 2) - (rect.width / 2); - positionElementToRect(element, rect, topOffset, horizontalCenter); + return positionElementToRect(element, rect, topOffset, horizontalCenter); } function positionElementCenteredAbove(element, aboveElement) { var elementMargin = getElementComputedStyleNumericProp(element, 'marginBottom'); - positionElementHorizontallyCenteredToRect(element, aboveElement.getBoundingClientRect(), element.offsetHeight + elementMargin); + return positionElementHorizontallyCenteredToRect(element, aboveElement.getBoundingClientRect(), element.offsetHeight + elementMargin); } function positionElementCenteredBelow(element, belowElement) { var elementMargin = getElementComputedStyleNumericProp(element, 'marginTop'); - positionElementHorizontallyCenteredToRect(element, belowElement.getBoundingClientRect(), -element.offsetHeight - elementMargin); + return positionElementHorizontallyCenteredToRect(element, belowElement.getBoundingClientRect(), -element.offsetHeight - elementMargin); } function positionElementCenteredIn(element, inElement) { var verticalCenter = (inElement.offsetHeight / 2) - (element.offsetHeight / 2); - positionElementHorizontallyCenteredToRect(element, inElement.getBoundingClientRect(), -verticalCenter); + return positionElementHorizontallyCenteredToRect(element, inElement.getBoundingClientRect(), -verticalCenter); } function positionElementToLeftOf(element, leftOfElement) { var verticalCenter = (leftOfElement.offsetHeight / 2) - (element.offsetHeight / 2); var elementMargin = getElementComputedStyleNumericProp(element, 'marginRight'); - positionElementToRect(element, leftOfElement.getBoundingClientRect(), -verticalCenter, element.offsetWidth + elementMargin); + return positionElementToRect(element, leftOfElement.getBoundingClientRect(), -verticalCenter, element.offsetWidth + elementMargin); } function positionElementToRightOf(element, rightOfElement) { var verticalCenter = (rightOfElement.offsetHeight / 2) - (element.offsetHeight / 2); var elementMargin = getElementComputedStyleNumericProp(element, 'marginLeft'); var rightOfElementRect = rightOfElement.getBoundingClientRect(); - positionElementToRect(element, rightOfElementRect, -verticalCenter, -rightOfElement.offsetWidth - elementMargin); + return positionElementToRect(element, rightOfElementRect, -verticalCenter, -rightOfElement.offsetWidth - elementMargin); } export { createDiv, hideElement, showElement, swapElements, getEventTargetMatchingTag, nodeIsDescendantOfElement, diff --git a/src/js/views/toolbar.js b/src/js/views/toolbar.js index 11cae3000..d63344c2e 100644 --- a/src/js/views/toolbar.js +++ b/src/js/views/toolbar.js @@ -45,10 +45,12 @@ function Toolbar(options) { toolbar.activePrompt = null; toolbar.buttons = []; + toolbar.contentElement = createDiv('ck-toolbar-content'); toolbar.promptContainerElement = createDiv('ck-toolbar-prompt'); toolbar.buttonContainerElement = createDiv('ck-toolbar-buttons'); - toolbar.element.appendChild(toolbar.promptContainerElement); - toolbar.element.appendChild(toolbar.buttonContainerElement); + toolbar.contentElement.appendChild(toolbar.promptContainerElement); + toolbar.contentElement.appendChild(toolbar.buttonContainerElement); + toolbar.element.appendChild(toolbar.contentElement); for(i = 0; i < commandCount; i++) { this.addCommand(commands[i]); @@ -112,7 +114,7 @@ Toolbar.prototype.updateForSelection = function(selection) { Toolbar.prototype.positionToContent = function(content) { var directions = ToolbarDirection; - var positioningMethod; + var positioningMethod, position, sideEdgeOffset; switch(this.direction) { case directions.RIGHT: positioningMethod = positionElementToRightOf; @@ -120,7 +122,9 @@ Toolbar.prototype.positionToContent = function(content) { default: positioningMethod = positionElementCenteredAbove; } - positioningMethod(this.element, content); + position = positioningMethod(this.element, content); + sideEdgeOffset = Math.min(Math.max(10, position.left), document.body.clientWidth - this.element.offsetWidth - 10); + this.contentElement.style.transform = 'translateX(' + (sideEdgeOffset - position.left) + 'px)'; }; Toolbar.prototype.setDirection = function(direction) {