From 1bd32763c291af4cbe1c1ec5e5d35648e5a98896 Mon Sep 17 00:00:00 2001 From: gdub22 Date: Fri, 11 Jul 2014 16:37:37 -0400 Subject: [PATCH] link tooltips --- dist/content-kit-editor.js | 75 ++++++++++++++++++++++++++++++++++- gulpfile.js | 3 +- src/css/editor.css | 41 +++++++++++++++++-- src/js/editor.js | 25 +++++++++++- src/js/tooltip.js | 40 +++++++++++++++++++ src/js/utils/element-utils.js | 9 +++++ 6 files changed, 186 insertions(+), 7 deletions(-) create mode 100644 src/js/tooltip.js diff --git a/dist/content-kit-editor.js b/dist/content-kit-editor.js index c53c1d477..d24ce2c30 100644 --- a/dist/content-kit-editor.js +++ b/dist/content-kit-editor.js @@ -93,6 +93,15 @@ function swapElements(elementToShow, elementToHide) { showElement(elementToShow); } +function getTargetNodeDescendentWithTag(tag, target, container) { + while (target && target !== container) { + if (target.tagName === tag) { + return target; + } + target = target.parentNode; + } +} + function getElementOffset(element) { var offset = { left: 0, top: 0 }; var elementStyle = window.getComputedStyle(element); @@ -496,7 +505,8 @@ ContentKit.Editor = (function() { bindTextSelectionEvents(editor); bindTypingEvents(editor); bindPasteEvents(editor); - + bindLinkTooltips(editor); + editor.enable(); if(editor.autofocus) { element.focus(); } } @@ -623,6 +633,28 @@ ContentKit.Editor = (function() { }); } + function bindLinkTooltips(editor) { + var linkTooltip = new Tooltip(); + var editorElement = editor.element; + var tooltipTimeout = null; + editorElement.addEventListener('mouseover', function(e) { + if (!editor.toolbar.isShowing) { + tooltipTimeout = setTimeout(function() { + var linkTarget = getTargetNodeDescendentWithTag(Tags.LINK, e.target, this); + if (linkTarget) { + linkTooltip.showLink(linkTarget.href, linkTarget); + } + }, 200); + } + }); + editorElement.addEventListener('mouseout', function(e) { + clearTimeout(tooltipTimeout); + if (e.toElement && e.toElement.className !== 'ck-tooltip') { + linkTooltip.hide(); + } + }); + } + function plainTextToBlocks(plainText, blockTag) { var blocks = plainText.split(Regex.NEWLINE), len = blocks.length, @@ -822,4 +854,45 @@ var ToolbarButton = (function() { return ToolbarButton; }()); +var Tooltip = (function() { + + var container = document.body; + + function Tooltip() { + var tooltip = this; + tooltip.element = createDiv('ck-tooltip'); + tooltip.isShowing = false; + } + + Tooltip.prototype = { + showMessage: function(message, element) { + var tooltip = this; + var tooltipElement = tooltip.element; + var elementRect = element.getBoundingClientRect(); + + tooltipElement.innerHTML = message; + if (!tooltip.isShowing) { + container.appendChild(tooltipElement); + tooltip.isShowing = true; + } + + tooltipElement.style.left = parseInt(elementRect.left + (element.offsetWidth / 2) - (tooltipElement.offsetWidth / 2), 10) + 'px'; + tooltipElement.style.top = parseInt(window.pageYOffset + elementRect.top + element.offsetHeight + 2, 10) + 'px'; + }, + showLink: function(link, element) { + var message = '' + link + ''; + this.showMessage(message, element); + }, + hide: function() { + var tooltip = this; + if (tooltip.isShowing) { + container.removeChild(tooltip.element); + tooltip.isShowing = false; + } + } + }; + + return Tooltip; +}()); + }(this, document)); diff --git a/gulpfile.js b/gulpfile.js index 0f2901ec5..b7e0c28ae 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -21,7 +21,8 @@ var src = [ './src/js/commands.js', './src/js/editor.js', './src/js/toolbar.js', - './src/js/toolbar-button.js' + './src/js/toolbar-button.js', + './src/js/tooltip.js' ]; var distName = 'content-kit-editor.js'; diff --git a/src/css/editor.css b/src/css/editor.css index f441a04d9..121eab24e 100644 --- a/src/css/editor.css +++ b/src/css/editor.css @@ -127,8 +127,41 @@ z-index: -1; background-color: rgba(76,217,100,0.05); border-bottom: 2px dotted #4CD964; - -webkit-animation: hiliteAppear 0.2s; - animation: hiliteAppear 0.2s; + -webkit-animation: fadeIn 0.2s; + animation: fadeIn 0.2s; +} + +.ck-tooltip { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 0.7em; + white-space: nowrap; + position: absolute; + background-color: rgba(43,43,43,0.9); + border-radius: 3px; + line-height: 1em; + padding: 0.7em 0.9em; + color: #FFF; + -webkit-animation: fadeIn 0.2s; + animation: fadeIn 0.2s; +} +.ck-tooltip:before { + content: ''; + position: absolute; + left: 50%; + width: 0; + height: 0; + border-left: 0.4em solid transparent; + border-right: 0.4em solid transparent; + border-bottom: 0.4em solid rgba(43,43,43,0.9); + top: -0.4em; + margin-left: -0.4em; +} +.ck-tooltip a { + color: #FFF; + text-decoration: none; +} +.ck-tooltip a:hover { + text-decoration: underline; } /* icons */ @@ -187,11 +220,11 @@ } /* animations */ -@-webkit-keyframes hiliteAppear { +@-webkit-keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } } -@keyframes hiliteAppear { +@keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } } diff --git a/src/js/editor.js b/src/js/editor.js index abb4e33db..487b29677 100644 --- a/src/js/editor.js +++ b/src/js/editor.js @@ -72,7 +72,8 @@ ContentKit.Editor = (function() { bindTextSelectionEvents(editor); bindTypingEvents(editor); bindPasteEvents(editor); - + bindLinkTooltips(editor); + editor.enable(); if(editor.autofocus) { element.focus(); } } @@ -199,6 +200,28 @@ ContentKit.Editor = (function() { }); } + function bindLinkTooltips(editor) { + var linkTooltip = new Tooltip(); + var editorElement = editor.element; + var tooltipTimeout = null; + editorElement.addEventListener('mouseover', function(e) { + if (!editor.toolbar.isShowing) { + tooltipTimeout = setTimeout(function() { + var linkTarget = getTargetNodeDescendentWithTag(Tags.LINK, e.target, this); + if (linkTarget) { + linkTooltip.showLink(linkTarget.href, linkTarget); + } + }, 200); + } + }); + editorElement.addEventListener('mouseout', function(e) { + clearTimeout(tooltipTimeout); + if (e.toElement && e.toElement.className !== 'ck-tooltip') { + linkTooltip.hide(); + } + }); + } + function plainTextToBlocks(plainText, blockTag) { var blocks = plainText.split(Regex.NEWLINE), len = blocks.length, diff --git a/src/js/tooltip.js b/src/js/tooltip.js new file mode 100644 index 000000000..96793fafe --- /dev/null +++ b/src/js/tooltip.js @@ -0,0 +1,40 @@ +var Tooltip = (function() { + + var container = document.body; + + function Tooltip() { + var tooltip = this; + tooltip.element = createDiv('ck-tooltip'); + tooltip.isShowing = false; + } + + Tooltip.prototype = { + showMessage: function(message, element) { + var tooltip = this; + var tooltipElement = tooltip.element; + var elementRect = element.getBoundingClientRect(); + + tooltipElement.innerHTML = message; + if (!tooltip.isShowing) { + container.appendChild(tooltipElement); + tooltip.isShowing = true; + } + + tooltipElement.style.left = parseInt(elementRect.left + (element.offsetWidth / 2) - (tooltipElement.offsetWidth / 2), 10) + 'px'; + tooltipElement.style.top = parseInt(window.pageYOffset + elementRect.top + element.offsetHeight + 2, 10) + 'px'; + }, + showLink: function(link, element) { + var message = '' + link + ''; + this.showMessage(message, element); + }, + hide: function() { + var tooltip = this; + if (tooltip.isShowing) { + container.removeChild(tooltip.element); + tooltip.isShowing = false; + } + } + }; + + return Tooltip; +}()); diff --git a/src/js/utils/element-utils.js b/src/js/utils/element-utils.js index eb27e3cd4..328d7b47f 100644 --- a/src/js/utils/element-utils.js +++ b/src/js/utils/element-utils.js @@ -19,6 +19,15 @@ function swapElements(elementToShow, elementToHide) { showElement(elementToShow); } +function getTargetNodeDescendentWithTag(tag, target, container) { + while (target && target !== container) { + if (target.tagName === tag) { + return target; + } + target = target.parentNode; + } +} + function getElementOffset(element) { var offset = { left: 0, top: 0 }; var elementStyle = window.getComputedStyle(element);