You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
srs/trunk/research/console/js/bravo_popover/popover.js

233 lines
9.9 KiB
JavaScript

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

angular.module('bravoUiPopover', [])
.directive("bravoPopover", function($compile, $position, $sce){
// $parse : ng表达式 {{1+2}} {{text}}
// $compile : 编译一段html字符串可以包括ng表达式
return {
restrict: "A",
scope: {
confirm: '&bravoPopoverConfirm'
},
compile: function (elem, attr) {
var confirm_template = attr['bravoPopoverConfirm'] ? '<span>' +
'<a class="btn btn-danger" ng-click="on_confirm()">Confirm</a> ' +
'<a class="btn btn-info" ng-click="on_cancel()">Cancel</a>' +
'</span>' : '';
var template =
'<div class="popover fade {{placement}} in" ng-show="popoover_show == \'in\'">' +
'<div class="arrow"></div>' +
'<h3 class="popover-title">{{title}}</h3>' +
'<div class="popover-content" ng-bind-html="content">' +
'</div>' +
'<div class="popover-content" ng-show="show_confirm_template">' +
confirm_template +
'</div>' +
'</div>';
var linker = $compile(template);
return function (scope, elem, attr) {
scope.popoover_show = "";
scope.title = attr['title'];
scope.content = $sce.trustAsHtml(attr['content']);
scope.placement = attr['placement'] ? attr['placement'] : 'top';
scope.trigger = attr['bravoPopoverConfirm'] ? 'click' : attr['trigger'];
scope.show_confirm_template = attr['bravoPopoverConfirm'] ? true : false;
var tooltip = linker(scope, function (o) {
elem.after(o);
});
tooltip.css({ top: 0, left: 0, display: 'block' });
if (!scope.trigger || scope.trigger == 'click') {
elem.on('click', function (event) {
toggle();
});
} else {
var eventIn = scope.trigger == 'hover' ? 'mouseenter' : 'focus';
var eventOut = scope.trigger == 'hover' ? 'mouseleave' : 'blur';
elem.on(eventIn, function (event) {
show_popover();
});
elem.on(eventOut, function () {
hide_popover();
});
}
var toggle = function() {
scope.popoover_show == 'in'? hide_popover() : show_popover();
render_css(tooltip);
};
var show_popover = function() {
scope.popoover_show = "in";
scope.$apply();
render_css(tooltip);
};
var hide_popover = function() {
scope.popoover_show = "";
scope.$apply();
};
var render_css = function (scope_element) {
var ttPosition = $position.positionElements(elem, scope_element, scope.placement, false);
ttPosition.top += 'px';
ttPosition.left += 'px';
// Now set the calculated positioning.
scope_element.css( ttPosition );
};
render_css(tooltip);
scope.on_cancel = function () {
scope.popoover_show = "";
};
scope.on_confirm = function () {
scope.confirm();
scope.popoover_show = "";
};
}
}
};
})
.factory('$position', ['$document', '$window', function ($document, $window) {
function getStyle(el, cssprop) {
if (el.currentStyle) { //IE
return el.currentStyle[cssprop];
} else if ($window.getComputedStyle) {
return $window.getComputedStyle(el)[cssprop];
}
// finally try and get inline style
return el.style[cssprop];
}
/**
* Checks if a given element is statically positioned
* @param element - raw DOM element
*/
function isStaticPositioned(element) {
return (getStyle(element, 'position') || 'static' ) === 'static';
}
/**
* returns the closest, non-statically positioned parentOffset of a given element
* @param element
*/
var parentOffsetEl = function (element) {
var docDomEl = $document[0];
var offsetParent = element.offsetParent || docDomEl;
while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {
offsetParent = offsetParent.offsetParent;
}
return offsetParent || docDomEl;
};
return {
/**
* Provides read-only equivalent of jQuery's position function:
* http://api.jquery.com/position/
*/
position: function (element) {
var elBCR = this.offset(element);
var offsetParentBCR = { top: 0, left: 0 };
var offsetParentEl = parentOffsetEl(element[0]);
if (offsetParentEl != $document[0]) {
offsetParentBCR = this.offset(angular.element(offsetParentEl));
offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
}
var boundingClientRect = element[0].getBoundingClientRect();
return {
width: boundingClientRect.width || element.prop('offsetWidth'),
height: boundingClientRect.height || element.prop('offsetHeight'),
top: elBCR.top - offsetParentBCR.top,
left: elBCR.left - offsetParentBCR.left
};
},
/**
* Provides read-only equivalent of jQuery's offset function:
* http://api.jquery.com/offset/
*/
offset: function (element) {
var boundingClientRect = element[0].getBoundingClientRect();
return {
width: boundingClientRect.width || element.prop('offsetWidth'),
height: boundingClientRect.height || element.prop('offsetHeight'),
top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),
left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)
};
},
/**
* Provides coordinates for the targetEl in relation to hostEl
*/
positionElements: function (hostEl, targetEl, positionStr, appendToBody) {
var positionStrParts = positionStr.split('-');
var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center';
var hostElPos,
targetElWidth,
targetElHeight,
targetElPos;
hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);
targetElWidth = targetEl.prop('offsetWidth');
targetElHeight = targetEl.prop('offsetHeight');
var shiftWidth = {
center: function () {
return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;
},
left: function () {
return hostElPos.left;
},
right: function () {
return hostElPos.left + hostElPos.width;
}
};
var shiftHeight = {
center: function () {
return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;
},
top: function () {
return hostElPos.top;
},
bottom: function () {
return hostElPos.top + hostElPos.height;
}
};
switch (pos0) {
case 'right':
targetElPos = {
top: shiftHeight[pos1](),
left: shiftWidth[pos0]()
};
break;
case 'left':
targetElPos = {
top: shiftHeight[pos1](),
left: hostElPos.left - targetElWidth
};
break;
case 'bottom':
targetElPos = {
top: shiftHeight[pos0](),
left: shiftWidth[pos1]()
};
break;
default:
targetElPos = {
top: hostElPos.top - targetElHeight,
left: shiftWidth[pos1]()
};
break;
}
return targetElPos;
}
};
}]);