Created
October 12, 2019 19:43
-
-
Save ambrosiora/6d5d0501c51caa03749bc040e57cdf34 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(document).ready(function() { | |
initHighlights(); | |
}); | |
var currentAnchor = null; | |
var tooltipPointerPositions = { | |
left: 46, | |
width: 14 | |
}; | |
var setCurrentAnchor = function(val) { | |
currentAnchor = val; | |
} | |
var hasTooltip = function() { | |
return ($('.tooltip-container').length == 1); | |
} | |
var canShowTooltip = function(selection) { | |
if (hasTooltip()) { | |
return false; | |
} | |
if (selection.type != 'Range' || selection.rangeCount <= 0) { | |
return false; | |
} | |
var range = selection.getRangeAt(0); | |
var start_parent = $(range.startContainer.parentNode); | |
var end_parent = $(range.endContainer.parentNode); | |
if (start_parent.closest('p').is(':not(.highlightable)')) { | |
return false; | |
} | |
if (start_parent.closest('p')[0] != end_parent.closest('p')[0]) { | |
return false; | |
} | |
return true; | |
} | |
var getAnchorType = function(anchor) { | |
var ret = false; | |
if (anchor) { | |
ret = anchor.constructor.name; | |
} | |
return ret; | |
} | |
var getTooltipTemplate = function() { | |
return '<div class="tooltip-container" tabindex=-1>\ | |
<div class="tooltip-body";>\ | |
<div class="tooltip-animation">\ | |
<div class="tooltip-content">\ | |
<div class="tooltip-adjuster">\ | |
<div class="tooltip-item-container">\ | |
<div class="tooltip-item">\ | |
<button class="btnHighlight hyellow" data-hcolor="hyellow">\ | |
<svg width="25" height="25" viewBox="0 0 25 25"><path d="M13.7 15.96l5.2-9.38-4.72-2.62-5.2 9.38 4.72 2.62zm-.5.89l-1.3 2.37-1.26.54-.7 1.26-3.8-.86 1.23-2.22-.2-1.35 1.31-2.37 4.73 2.62z" fill-rule="evenodd"></path></svg>\ | |
</button>\ | |
</div>\ | |
</div>\ | |
<div class="tooltip-item-container">\ | |
<div class="tooltip-item">\ | |
<button class="btnHighlight hblue" data-hcolor="hblue">\ | |
<svg width="25" height="25" viewBox="0 0 25 25"><path d="M13.7 15.96l5.2-9.38-4.72-2.62-5.2 9.38 4.72 2.62zm-.5.89l-1.3 2.37-1.26.54-.7 1.26-3.8-.86 1.23-2.22-.2-1.35 1.31-2.37 4.73 2.62z" fill-rule="evenodd"></path></svg>\ | |
</button>\ | |
</div>\ | |
</div>\ | |
</div>\ | |
<div class="tooltip-pointer" style="left: ' + tooltipPointerPositions.left + 'px;"></div>\ | |
</div>\ | |
</div>\ | |
</div>\ | |
</div>'; | |
} | |
var getTooltipPlacement = function(clientRect) { | |
var bodyClientRect = document.body.getBoundingClientRect(); | |
var tooltipHeight = $('.tooltip-body')[0].getClientRects()[0].height; | |
var computedLeft = (clientRect.left + (clientRect.width / 2)) - (tooltipPointerPositions.left + (tooltipPointerPositions.width / 2)); | |
var computedTop = ((clientRect.top - tooltipHeight) - bodyClientRect.top) - 1; | |
return { | |
left: computedLeft, | |
top: computedTop, | |
tpClass: 'tp-down' | |
}; | |
} | |
var tryShowTooltip = function(anchor) { | |
var clientRect = null; | |
removeTooltip(); | |
switch (getAnchorType(anchor)) { | |
case 'Selection': | |
if (!canShowTooltip(anchor)) { | |
return false; | |
} | |
var range = anchor.getRangeAt(0); | |
clientRect = range.getClientRects()[0]; | |
break; | |
case 'HTMLElement': | |
clientRect = anchor.getClientRects()[0]; | |
break; | |
default: | |
return false; | |
} | |
setCurrentAnchor(anchor); | |
var html = getTooltipTemplate(); | |
$('body').append(html); | |
var tooltipPlacement = getTooltipPlacement(clientRect); | |
var tooltipContainer = $('.tooltip-container'); | |
tooltipContainer.find('.tooltip-body').css('transform', 'translate3d(' + tooltipPlacement.left + 'px, ' + tooltipPlacement.top + 'px, 0px)'); | |
tooltipContainer.find('.tooltip-pointer').removeClass('tp-down, tp-up').addClass(tooltipPlacement.tpClass); | |
} | |
var removeTooltip = function() { | |
$('.tooltip-container').remove(); | |
setCurrentAnchor(null); | |
} | |
var initHighlights = function() { | |
//buscar o json | |
/*mock resultado request recuperar seleções*/ | |
$.ajax({ | |
url: 'http://www.mocky.io/v2/5da207bb2f00007b00f418fe', | |
method: 'GET', | |
dataType: 'jsonp' | |
}).done(function(data, textStatus, jqXHR) { | |
$.each(data, function(index, item){ | |
var selection = addSelection(item); | |
addHighlight(selection, item.highlightClassColor); | |
}); | |
}).fail(function(jqXHR, textStatus, errorThrown) { | |
alert('Desculpe, não foi possível carregar suas marcações') | |
}); | |
} | |
var addSelection = function (item) { | |
var el = $('#'+item.id); | |
if (!el || el.length == 0) { | |
return false; | |
} | |
el = el[0]; | |
var range = document.createRange(); | |
range.setStart(el.firstChild, item.startOffset); | |
range.setEnd(el.firstChild, item.endOffset); | |
var selection = window.getSelection(); | |
selection.removeAllRanges(); | |
selection.addRange(range); | |
return selection; | |
} | |
var removeHighlight = function (currentAnchor) { | |
var p = $(currentAnchor).closest('p'); | |
innerHtml = $(currentAnchor).html(); | |
$(currentAnchor).replaceWith(innerHtml); | |
//Normalizando html | |
p.html(p.html().replace(/(\r\n|\n|\r)/gm, " ")); | |
} | |
var addHighlight = function (currentAnchor, highlightClassColor) { | |
highlightClassColor = highlightClassColor || 'hyellow'; | |
var className = 'highlightedText ' + highlightClassColor; | |
var elementMarkerName = 'mark'; | |
if (currentAnchor.type != 'Range') { | |
return false; | |
} | |
var text = currentAnchor.toString(); | |
var range = currentAnchor.getRangeAt(0); | |
var start_parent = $(range.startContainer.parentNode); | |
var end_parent = $(range.endContainer.parentNode); | |
//Não é um elemento highlightable ou Começou em um parágrafo e terminou em outro (não pode, igual medium não deixa) | |
if (start_parent.closest('p').is(':not(.highlightable)') || start_parent.closest('p')[0] != end_parent.closest('p')[0]) { | |
currentAnchor.removeAllRanges(); | |
return false; | |
} | |
/*Começou a selecionar por cima de uma seleção*/ | |
if (range.startOffset > 0 && start_parent.hasClass(className)) { | |
// var prefix = '<' + elementMarkerName + ' class="' + className + '">' + start_parent.html().substr(0, currentAnchor.focusOffset); | |
prefix = '<' + elementMarkerName + ' class="' + className + '">' + start_parent.html().substr(0, range.startOffset); | |
range.deleteContents(); | |
var suffix = /*'<' + elementMarkerName + ' class="' + className + '">' +*/ text + '</' + elementMarkerName + '>'; | |
start_parent.replaceWith(prefix + suffix); | |
} else { | |
range.deleteContents(); | |
range.insertNode($('<' + elementMarkerName + ' class="' + className + '">' + text + '</' + elementMarkerName + '>')[0]); | |
//Remove all empty elements (deleteContents leaves the HTML in place) | |
$(elementMarkerName + '.' + className + ':empty').remove(); | |
} | |
//retirando a seleção após executar as coisas | |
currentAnchor.removeAllRanges(); | |
} | |
$('body').on('mouseup touchend', function(e) { | |
if ($(e.target).closest('.tooltip-container').length == 1 || (window.getSelection().type != 'Range' && $(e.target).is('mark.highlightedText'))) { | |
// if ($(e.target).closest('.tooltip-container').length == 1) { | |
e.preventDefault(); | |
return false; | |
} | |
if (e.cancelable) { | |
e.preventDefault(); | |
} | |
var selection = window.getSelection(); | |
tryShowTooltip(selection); | |
}); | |
$('body').on('click', '.btnHighlight', function(e) { | |
switch (getAnchorType(currentAnchor)) { | |
case 'Selection': | |
addHighlight(currentAnchor, $(this).data('hcolor')); | |
break; | |
case 'HTMLElement': | |
removeHighlight(currentAnchor); | |
break; | |
default: | |
return false; | |
} | |
removeTooltip(); | |
}); | |
$('body').on('click', 'mark.highlightedText', function(e) { | |
if (window.getSelection().type != 'Range') { | |
tryShowTooltip(this); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment