2018-02-10 15:18:01 +00:00
|
|
|
import ngModule from '../../module';
|
2017-06-08 07:29:03 +00:00
|
|
|
import './style.css';
|
|
|
|
|
2017-06-15 05:45:01 +00:00
|
|
|
tooltip.$inject = ['$document', '$compile', '$interpolate', '$sce', '$templateCache', '$http', '$q'];
|
|
|
|
function tooltip($document, $compile, $interpolate, $sce, $templateCache, $http, $q) {
|
|
|
|
var promise;
|
|
|
|
|
|
|
|
function _getTemplate(tooltipTemplateUrl) {
|
2017-06-14 07:54:00 +00:00
|
|
|
var template = $templateCache.get(tooltipTemplateUrl);
|
|
|
|
if (typeof template === 'undefined') {
|
|
|
|
template = $http.get(tooltipTemplateUrl).then(function onGetTemplateSuccess(response) {
|
2017-06-15 05:45:01 +00:00
|
|
|
if (promise) {
|
|
|
|
promise.resolve(response.data);
|
|
|
|
}
|
|
|
|
promise = undefined;
|
2017-06-14 07:54:00 +00:00
|
|
|
return response.data;
|
|
|
|
});
|
|
|
|
$templateCache.put(tooltipTemplateUrl, template);
|
|
|
|
}
|
|
|
|
return template;
|
|
|
|
}
|
|
|
|
|
2017-06-15 05:45:01 +00:00
|
|
|
function getTemplate(tooltipTemplateUrl) {
|
|
|
|
var _promise = $q.defer();
|
|
|
|
var template = _getTemplate(tooltipTemplateUrl);
|
|
|
|
if (template) {
|
|
|
|
_promise.resolve(template);
|
|
|
|
} else {
|
|
|
|
promise = _promise;
|
|
|
|
}
|
|
|
|
return _promise.promise;
|
|
|
|
}
|
|
|
|
|
2017-06-08 07:29:03 +00:00
|
|
|
return {
|
|
|
|
restrict: 'A',
|
2017-06-14 07:54:00 +00:00
|
|
|
priority: -1,
|
2018-02-21 12:42:47 +00:00
|
|
|
link: function($scope, element, attrs) {
|
|
|
|
let tipHtml = '<div class="mdl-shadow--2dp" ng-class="tipClass"><div class="tooltip-text" translate>{{::text}}</div><div ng-if="isHtmlContent" ng-bind-html="htmlContent"></div><div class="tooltip-arrow"></div></div>';
|
|
|
|
let tip;
|
|
|
|
let tipClassName = 'tooltip';
|
|
|
|
let tipActiveClassName = 'tooltip-show';
|
|
|
|
let scope = $scope.$new();
|
2017-06-08 07:29:03 +00:00
|
|
|
|
|
|
|
scope.tipClass = [tipClassName];
|
2017-06-14 07:54:00 +00:00
|
|
|
scope.text = attrs.vnTooltip || '';
|
|
|
|
|
|
|
|
if (attrs.tooltipHtml) {
|
|
|
|
scope.isHtmlContent = true;
|
|
|
|
scope.htmlContent = $sce.trustAsHtml(attrs.tooltipHtml);
|
2017-06-15 05:45:01 +00:00
|
|
|
_compileTip();
|
2017-06-14 07:54:00 +00:00
|
|
|
} else if (attrs.tooltipTemplate) {
|
2017-06-15 05:45:01 +00:00
|
|
|
getTemplate(attrs.tooltipTemplate).then(template => {
|
|
|
|
scope.isHtmlContent = true;
|
|
|
|
scope.htmlContent = $sce.trustAsHtml($interpolate(template)(scope));
|
|
|
|
_compileTip();
|
|
|
|
});
|
2017-06-14 07:54:00 +00:00
|
|
|
} else {
|
|
|
|
scope.isHtmlContent = false;
|
|
|
|
scope.htmlContent = null;
|
2017-06-15 05:45:01 +00:00
|
|
|
_compileTip();
|
2017-06-14 07:54:00 +00:00
|
|
|
}
|
2017-06-08 07:29:03 +00:00
|
|
|
|
|
|
|
if (attrs.tooltipPosition) {
|
|
|
|
scope.tipClass.push('tooltip-' + attrs.tooltipPosition);
|
|
|
|
} else {
|
|
|
|
scope.tipClass.push('tooltip-down');
|
|
|
|
}
|
|
|
|
|
2017-06-15 05:45:01 +00:00
|
|
|
function _compileTip() {
|
|
|
|
tip = $compile(tipHtml)(scope);
|
|
|
|
$document.find('body').append(tip);
|
|
|
|
_bindEvents();
|
|
|
|
}
|
2017-06-08 07:29:03 +00:00
|
|
|
|
2017-06-15 05:45:01 +00:00
|
|
|
function _bindEvents() {
|
|
|
|
element.bind('mouseover', function(e) {
|
2018-02-28 08:12:48 +00:00
|
|
|
_showTooltip(e);
|
2017-06-15 05:45:01 +00:00
|
|
|
});
|
2017-06-08 07:29:03 +00:00
|
|
|
|
2017-06-15 05:45:01 +00:00
|
|
|
element.on('mouseout', function() {
|
2018-02-28 08:12:48 +00:00
|
|
|
_hideTooltip();
|
2017-06-15 05:45:01 +00:00
|
|
|
});
|
|
|
|
|
2018-02-28 08:12:48 +00:00
|
|
|
tip.on('mouseover', function(e) {
|
|
|
|
_showTooltip(e);
|
2017-06-15 05:45:01 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
tip.on('mouseout', function() {
|
2018-02-28 08:12:48 +00:00
|
|
|
_hideTooltip();
|
2017-06-15 05:45:01 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
element.on('$destroy', function() {
|
|
|
|
tip.remove();
|
2018-02-21 12:42:47 +00:00
|
|
|
scope.$destroy();
|
2017-06-15 05:45:01 +00:00
|
|
|
});
|
|
|
|
}
|
2018-02-28 08:12:48 +00:00
|
|
|
|
|
|
|
function _calculatePosition(e) {
|
|
|
|
let pos = element[0].getBoundingClientRect();
|
|
|
|
let tipPos = tip[0].getBoundingClientRect();
|
|
|
|
let offset = {top: 0, left: 0};
|
|
|
|
let tipWidth = tipPos.width || tipPos.right - tipPos.left;
|
|
|
|
let tipHeight = tipPos.height || tipPos.bottom - tipPos.top;
|
|
|
|
let elWidth = pos.width || pos.right - pos.left;
|
|
|
|
let elHeight = pos.height || pos.bottom - pos.top;
|
|
|
|
let tipOffset = 10;
|
|
|
|
|
|
|
|
if (tip.hasClass('tooltip-right')) {
|
|
|
|
offset.top = pos.top - (tipHeight / 2) + (elHeight / 2);
|
|
|
|
offset.left = pos.right + tipOffset;
|
|
|
|
} else if (tip.hasClass('tooltip-left')) {
|
|
|
|
offset.top = pos.top - (tipHeight / 2) + (elHeight / 2);
|
|
|
|
offset.left = pos.left - tipWidth - tipOffset;
|
|
|
|
} else if (tip.hasClass('tooltip-down')) {
|
|
|
|
offset.top = pos.top + elHeight + tipOffset;
|
|
|
|
offset.left = pos.left - (tipWidth / 2) + (elWidth / 2);
|
|
|
|
} else {
|
|
|
|
offset.top = pos.top - tipHeight - tipOffset;
|
|
|
|
offset.left = pos.left - (tipWidth / 2) + (elWidth / 2);
|
|
|
|
}
|
|
|
|
// outsides
|
|
|
|
if (offset.left + tipPos.width > window.innerWidth) { // right outside
|
|
|
|
let diffLeft = (offset.left + tipPos.width) - window.innerWidth;
|
|
|
|
offset.left -= diffLeft + 10;
|
|
|
|
|
|
|
|
let arrow = tip[0].querySelector('.tooltip-arrow');
|
|
|
|
if (arrow) {
|
|
|
|
angular.element(arrow).css('margin-left', diffLeft + 'px');
|
|
|
|
}
|
|
|
|
} else if (offset.left < 10) { // left outside
|
|
|
|
offset.left = 10;
|
|
|
|
let arrow = tip[0].querySelector('.tooltip-arrow');
|
|
|
|
if (arrow) {
|
|
|
|
angular.element(arrow).css('margin-left', '10px');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (offset.top > window.innerHeight) { // down outside
|
|
|
|
offset.top = pos.top - tipHeight - tipOffset;
|
|
|
|
} else if (offset.top < 10) { // top outside
|
|
|
|
offset.top = pos.top + elHeight + tipOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
tip.css('top', offset.top + 'px');
|
|
|
|
tip.css('left', offset.left + 'px');
|
|
|
|
}
|
|
|
|
|
|
|
|
function _showTooltip(e) {
|
|
|
|
tip.addClass(tipActiveClassName);
|
|
|
|
_calculatePosition(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hideTooltip() {
|
|
|
|
tip.removeClass(tipActiveClassName);
|
|
|
|
}
|
2017-06-08 07:29:03 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-02-10 15:18:01 +00:00
|
|
|
ngModule.directive('vnTooltip', tooltip);
|