123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- 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;
- }
- };
- }]);
|