(function () { 'use strict'; var name = 'adPopup'; angular.module('app.directive') .directive('adPopup', ['$timeout', '$rootScope', 'cfg', function ($timeout, $rootScope, cfg) { var defaults = { placement: 'top', delay: null, trigger: 'click' }; var triggerMap = { 'mouseenter': 'mouseleave', 'click': 'click', 'focus': 'blur' }; return { replace: true, transclude: true, templateUrl: 'directive/' + name + '/' + name + '.html', scope: { visible: '=' + name + 'Visible' }, link: function (scope, element, attributes, controller) { var popupName = attributes[name] ? attributes[name] : ''; cfg.debug && console.log(name, popupName); var triggers; var targetName = attributes[name + 'Target'] ? attributes[name + 'Target'] : null; var trigger = attributes[name + 'Trigger'] ? attributes[name + 'Trigger'] : null; var group = attributes[name + 'Group'] ? attributes[name + 'Group'] : null; var options = angular.extend({}, defaults); var transitionTimeout; var popupTimeout; var hasRegisteredTriggers; var getTriggers = function (trigger) { var show = trigger || options.trigger || defaults.trigger; var hide = triggerMap[show] || show; return { show: show, hide: hide }; }; var getTarget = function () { return targetName ? angular.element(targetName) : element.parent(); }; var getContentElement = function () { return element.find('[ng-transclude] > *'); }; var show = function () { cfg.debug && console.log(name, popupName, 'show'); $rootScope.$emit(name + 'BeforeShow', {name: popupName, group: group}); var targetSize, elementSize, position; if (transitionTimeout) { $timeout.cancel(transitionTimeout); } var target = getTarget(); targetSize = target.offset(); targetSize.height = target.outerHeight(); targetSize.width = target.outerWidth(); elementSize = { width: element.outerWidth(), height: element.outerHeight() }; switch (scope.placement) { case 'right': position = { top: targetSize.top + targetSize.height / 2 - elementSize.height / 2, left: targetSize.left + targetSize.width }; break; case 'bottom': position = { top: targetSize.top + targetSize.height, left: targetSize.left + targetSize.width / 2 - elementSize.width / 2 }; break; case 'left': position = { top: targetSize.top + targetSize.height / 2 - elementSize.height / 2, left: targetSize.left - elementSize.width }; break; default: position = { top: targetSize.top - elementSize.width, left: targetSize.left + targetSize.width / 2 - elementSize.height / 2 }; break; } position.top += 'px'; position.left += 'px'; element.css(position); scope.opened = true; getContentElement().trigger(name + 'Show', {name: popupName, group: group}); }; var hide = function () { cfg.debug && console.log(name, popupName, 'hide'); scope.opened = false; element.css({top: 0, left: 0}); if (popupTimeout) { $timeout.cancel(popupTimeout); popupTimeout = null; } getContentElement().trigger(name + 'Hide', {name: popupName, group: group}); }; var onActionToggle = function () { if (scope.opened) { onActionHide(); } else { onActionShow(); } }; var onActionShow = function () { if (popupTimeout) { $timeout.cancel(popupTimeout); popupTimeout = null; } if (scope.delay) { popupTimeout = $timeout(show, scope.delay); } else { scope.$apply(show); } LOGINZA.init(); }; var onActionHide = function () { if (popupTimeout) { $timeout.cancel(popupTimeout); popupTimeout = null; } if (scope.delay) { popupTimeout = $timeout(hide, scope.delay); } else { scope.$apply(hide); } }; scope.opened = false; scope.show = show; scope.hide = hide; var init = function () { var target = getTarget(); triggers = getTriggers(trigger); if (triggers.show === triggers.hide) { target.bind(triggers.show, onActionToggle); } else { target.bind(triggers.show, onActionShow); target.bind(triggers.hide, onActionHide); } hasRegisteredTriggers = true; }; scope.$watch(function () { return scope.visible; }, function (value) { if (scope.opened && !value) { scope.opened = false; } }); attributes.$observe(name + 'Placement', function (val) { scope.placement = angular.isDefined(val) ? val : options.placement; }); attributes.$observe(name + 'Delay', function (val) { scope.delay = angular.isDefined(val) ? val : options.delay; }); $rootScope.$on(name + 'BeforeShow', function (e, options) { if (null !== group && scope.opened && group === options.group) { hide(); } }); scope.$on('$destroy', function onDestroyPopup() { cfg.debug && console.log(name, popupName, '$destroy'); scope.opened = false; if (hasRegisteredTriggers) { getTarget() .unbind(triggers.show, onActionShow) .unbind(triggers.hide, onActionHide); } }); init(); } }; }]); })();