Skip to content

Commit

Permalink
ensure floating toolbar always stays onscreen
Browse files Browse the repository at this point in the history
  • Loading branch information
gpoitch committed Feb 26, 2015
1 parent bf5b57f commit c3ea10d
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 31 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
10 changes: 7 additions & 3 deletions src/css/toolbar.less
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down
26 changes: 11 additions & 15 deletions src/js/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 12 additions & 8 deletions src/js/utils/element-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 8 additions & 4 deletions src/js/views/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down Expand Up @@ -112,15 +114,17 @@ 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;
break;
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) {
Expand Down

0 comments on commit c3ea10d

Please sign in to comment.