aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--example/index.css36
-rw-r--r--example/index.html47
-rw-r--r--sass/ns-popover.scss2
-rw-r--r--src/nsPopover.js144
4 files changed, 135 insertions, 94 deletions
diff --git a/example/index.css b/example/index.css
new file mode 100644
index 0000000..3792232
--- /dev/null
+++ b/example/index.css
@@ -0,0 +1,36 @@
+body {
+ font-family: arial, sans-serif;
+ font-size: 16px;
+}
+
+a {
+ cursor: pointer;
+}
+
+button {
+ box-sizing: border-box;
+ font-size: 12px;
+ padding: 6px 12px;
+ border-radius: 3px;
+ border: solid 1px #0096d6;
+ background: linear-gradient(#0096d6, #0081b8);
+ color: #fff;
+}
+
+button:hover,
+button:focus,
+button:active {
+ background: #0081b8;
+ border: solid 1px #0081b8;
+}
+
+section {
+ position: relative;
+ width: 100%;
+}
+
+article {
+ position: relative;
+ margin: 0 auto;
+ float: left;
+} \ No newline at end of file
diff --git a/example/index.html b/example/index.html
index 015e41d..a08c885 100644
--- a/example/index.html
+++ b/example/index.html
@@ -5,16 +5,7 @@
<title>nsPopover demo</title>
<link rel="stylesheet" href="../build/nsPopover.css">
-
- <style>
- body {
- font-family: arial, sans-serif;
- }
-
- a {
- cursor: pointer;
- }
- </style>
+ <link rel="stylesheet" href="index.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js"></script>
<script src="../build/nsPopover.js"></script>
@@ -29,8 +20,38 @@
</head>
<body ng-controller="MainCtrl">
-<button ns-popover ns-popover-template="popover" ns-popover-trigger="mouseover">
- Menu
-</button>
+<section>
+ <h1> Popovers </h1>
+ <article>
+ <button ns-popover
+ ns-popover-template="popover"
+ ns-popover-trigger="click"
+ ns-popover-placement="bottom">
+ Popover on bottom
+ </button>
+
+ <button ns-popover
+ ns-popover-template="popover"
+ ns-popover-trigger="click"
+ ns-popover-placement="top">
+ Popover on top
+ </button>
+
+ <button ns-popover
+ ns-popover-template="popover"
+ ns-popover-trigger="click"
+ ns-popover-placement="left">
+ Popover on left
+ </button>
+
+ <button ns-popover
+ ns-popover-template="popover"
+ ns-popover-trigger="click"
+ ns-popover-placement="right">
+ Popover on right
+ </button>
+ </article>
+</section>
+
</body>
</html> \ No newline at end of file
diff --git a/sass/ns-popover.scss b/sass/ns-popover.scss
index 21344e2..e4fe2a9 100644
--- a/sass/ns-popover.scss
+++ b/sass/ns-popover.scss
@@ -2,6 +2,8 @@
box-sizing: border-box;
border: solid 1px #d2d2d2;
border-radius: 3px;
+ z-index: 100;
+ background-color: #fff;
ul {
padding: 0;
diff --git a/src/nsPopover.js b/src/nsPopover.js
index d9f72b3..d31aad5 100644
--- a/src/nsPopover.js
+++ b/src/nsPopover.js
@@ -26,73 +26,6 @@
});
};
- /*module.provider('nsPopover', function() {
- var defaults_ = this.default_ = {
- placement: 'right',
- plain: false
- };
-
- var globalId_ = 0;
-
- this.$get('$document','$templateCache', '$compile', '$q', '$http', '$rootScope', '$timeout',
- function ($document, $templateCache, $compile, $q, $http, $rootScope, $timeout) {
- var $body = $document.find('body');
-
- var methods_ = {
- show: function(opts) {
- var options = angular.copy(defaults_);
-
- opts = opts || {};
- extend_(options, opts);
-
- globalId_ += 1;
-
- var scope = angular.isObject(options.scope) ? options.scope : $rootScope.$new();
- var $popover;
-
- $q.when(loadTemplate(options.template)).then(function(template) {
- template = angular.isString(template) ?
- template :
- template.data && angular.isString(template.data) ?
- template.data :
- '';
-
- $popover = $el('<div> class="ns-popover" id="ns-popover' + globalId_ + '"></div>');
- $popover.html(template);
-
- if (options.theme) {
- $popover.addClass(options.theme);
- }
-
- $timeout(function() {
- $compile($popover)(scope);
- });
-
- scope.$on('$destroy', function() {
- $popover.remove();
- });
-
- $body.append($popover);
-
- return methods_;
- });
-
- function loadTemplate(template) {
- if (!template) {
- return 'Empty template';
- }
-
- if (angular.isString(template) && options.plain) {
- return template;
- }
-
- return $templateCache.get(template) || $http.get(template, { cache : true });
- }
- }
- }
- });
- });*/
-
module.directive('nsPopover', function($timeout, $templateCache, $q, $http, $compile, $document) {
return {
restrict: 'A',
@@ -102,7 +35,8 @@
theme: attrs.nsPopoverTheme || 'ns-popover-default-theme',
plain: attrs.nsPopoverPlain,
trigger: attrs.nsPopoverTrigger || 'click',
- container: attrs.nsPopoverContainer
+ container: attrs.nsPopoverContainer,
+ placement: attrs.nsPopoverPlacement || 'bottom'
};
var timeoutId_ = {};
@@ -114,7 +48,7 @@
var $popover = $el('<div></div>');
- $q.when(loadTemplate(options.template)).then(function(template) {
+ $q.when(loadTemplate(options.template, options.plain)).then(function(template) {
template = angular.isString(template) ?
template :
template.data && angular.isString(template.data) ?
@@ -147,44 +81,92 @@
$timeout.cancel(timeoutId_);
- var rect = elm[0].getBoundingClientRect();
- $popover
- .css('display', 'block')
- .css('top', rect.bottom + 1 + 'px')
- .css('left', rect.left + 'px');
+ $popover.css('display', 'block');
+ // position the popover accordingly to the defined placement around the
+ // |elm|.
+ move($popover, options.placement, elm[0].getBoundingClientRect());
+
+ // Hide the popover without delay on click events.
$popover.on('click', function() {
- timeoutId_ = hide(0);
+ timeoutId_ = hide($popover, 0);
});
});
+ elm.on('mouseout', function() {
+ timeoutId_ = hide($popover);
+ });
+
$popover
.on('mouseout', function(e) {
- timeoutId_ = hide();
+ timeoutId_ = hide($popover);
})
.on('mouseover', function() {
$timeout.cancel(timeoutId_);
});
- function hide(delay) {
+ /**
+ * Move the popover to the |placement| position of the object located on the |rect|.
+ *
+ * @param popover {Object} The popover object to be moved.
+ * @param placement {String} The relative position to move the popover - top | bottom | left | right.
+ * @param rect {ClientRect} The ClientRect of the object to move the popover around.
+ */
+ function move(popover, placement, rect) {
+ var popoverRect = popover[0].getBoundingClientRect();
+ var top, left;
+ if (placement === 'top') {
+ top = rect.top - popoverRect.height - 1;
+ left = rect.left;
+ } else if (placement === 'right') {
+ top = rect.top;
+ left = rect.right +1;
+ } else if (placement === 'bottom') {
+ top = rect.bottom + 1;
+ left = rect.left;
+ } else if (placement === 'left') {
+ top = rect.top;
+ left = rect.left - popoverRect.width - 1;
+ }
+ popover
+ .css('top', top.toString() + 'px')
+ .css('left', left.toString() + 'px');
+ }
+
+ /**
+ * Set the display property of the popover to 'none' after |delay| milliseconds.
+ *
+ * @param popover {Object} The popover to set the display property.
+ * @param delay {Number} The time (in milliseconds) to wait before set the display property.
+ * @returns {Object|promise} A promise returned from the $timeout service that can be used
+ * to cancel the hiding operation.
+ */
+ function hide(popover, delay) {
$timeout.cancel(timeoutId_);
- // delay the hide to 1.5s by default.
+ // delay the hiding operation for 1.5s by default.
if (!isDef(delay)) {
delay = 1500;
}
return $timeout(function() {
- $popover.css('display', 'none');
+ popover.css('display', 'none');
}, delay);
}
- function loadTemplate(template) {
+ /**
+ * Load the given template in the cache if it is not already loaded.
+ *
+ * @param template The URI of the template to be loaded.
+ * @returns {String} A promise that the template will be loaded.
+ * @remarks If the template is null or undefined a empty string will be returned.
+ */
+ function loadTemplate(template, plain) {
if (!template) {
return '';
}
- if (angular.isString(template) && options.plain) {
+ if (angular.isString(template) && plain) {
return template;
}