Skip to content
This repository was archived by the owner on Aug 7, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 56 additions & 11 deletions packages/oui-popover/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
### Using value of `oui-popover` attribute

```html:preview
<button type="button"
class="oui-button oui-button_primary"
<button type="button"
class="oui-button oui-button_primary"
oui-popover="This is an awesome popover content.">
Click to toggle popover
</button>
Expand All @@ -17,14 +17,38 @@
### Using value of `title` attribute

```html:preview
<button type="button"
class="oui-button oui-button_primary"
title="This is an awesome popover content."
<button type="button"
class="oui-button oui-button_primary"
title="This is an awesome popover content."
oui-popover>
Click to toggle popover
</button>
```

### Using `open` attribute

<oui-message type="info">
Use <code class="oui-doc-codespan">oui-popover-open</code> to control the open state of the popover.<br />
No event handler will be registered from the trigger element.
</oui-message>

```html:preview
<p>
<span title="This is an awesome popover content."
ng-init="$ctrl.isOpen = true"
oui-popover
oui-popover-open="$ctrl.isOpen"
oui-popover-on-close="$ctrl.isOpen = false">
This is an awesome text
</span>
</p>
<button type="button"
class="oui-button oui-button_primary"
ng-click="$ctrl.isOpen = !$ctrl.isOpen">
Click to toggle popover
</button>
```

### Using a template with `oui-popover-template` attribute

<oui-message type="warning">
Expand All @@ -37,7 +61,7 @@
ng-init="$ctrl.awesome = 'awesome'"
ng-model="$ctrl.awesome">
<button type="button"
class="oui-button oui-button_primary"
class="oui-button oui-button_primary"
oui-popover
oui-popover-scope="$ctrl"
oui-popover-template="popover.html">
Expand Down Expand Up @@ -94,14 +118,14 @@
### Alignments

```html:preview
<button type="button" class="oui-button oui-button_primary"
oui-popover="This is an awesome popover content."
<button type="button" class="oui-button oui-button_primary"
oui-popover="This is an awesome popover content."
oui-popover-placement="bottom-start">
Align start
</button>

<button type="button" class="oui-button oui-button_primary"
oui-popover="This is an awesome popover content."
<button type="button" class="oui-button oui-button_primary"
oui-popover="This is an awesome popover content."
oui-popover-placement="bottom-end">
Align end
</button>
Expand All @@ -117,19 +141,40 @@

```html:preview
<input type="text" class="oui-input oui-input_inline"
ng-init="$ctrl.popoverText = 'Lorem ipsum'"
ng-init="$ctrl.popoverText = 'Lorem ipsum'"
ng-model="$ctrl.popoverText"
oui-popover="{{ $ctrl.popoverText }}">
```

### Using `on-open` & `on-close`

```html:preview
<div class="oui-doc-preview-only">
<p><strong>onOpen counter:</strong> {{$ctrl.numOpen }}</p>
<p><strong>onClose counter:</strong> {{$ctrl.numClose }}</p>
</div>

<button type="button" class="oui-button oui-button_primary"
ng-init="$ctrl.numOpen = 0; $ctrl.numClose = 0;"
title="This is an awesome popover content."
oui-popover
oui-popover-on-open="$ctrl.numOpen = $ctrl.numOpen + 1"
oui-popover-on-close="$ctrl.numClose = $ctrl.numClose + 1">
Click to toggle popover
</button>
```

## API

| Attribute | Type | Binding | One-time Binding | Values | Default | Description
| ---- | ---- | ---- | ---- | ---- | ---- | ----
| `oui-popover` | string | @ | no | n/a | `title` attribute | popover content
| `oui-popover-open` | boolean | <? | no | `true`, `false` | `false` | open or close the popover
| `oui-popover-placement` | string | @? | yes | See [Popper placements](https://popper.js.org/popper-documentation.html#Popper.placements) | `right` | modifier for alignment
| `oui-popover-scope` | string | <? | no | n/a | n/a | scope of the popover template
| `oui-popover-template` | string | @? | no | n/a | n/a | id of the popover template
| `oui-popover-on-open` | function | & | no | n/a | n/a | called when popover is opened
| `oui-popover-on-close` | function | & | no | n/a | n/a | called when popover is closed

## Deprecated

Expand Down
57 changes: 57 additions & 0 deletions packages/oui-popover/src/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,63 @@ describe("ouiPopover", () => {
trigger.triggerHandler("click");
expect(trigger.attr("aria-expanded")).toBe("false");
});

it("should open the popover if specified", () => {
const component = testUtils.compileTemplate(
`<div>
<button class="trigger" oui-popover="foo" oui-popover-open="$ctrl.open"></button>
</div>`, {
open: true
}
);

$timeout.flush();

const trigger = angular.element(component[0].querySelector(".trigger"));
expect(trigger.attr("aria-expanded")).toBe("true");

component.scope().$ctrl.open = false;
component.scope().$apply();

expect(trigger.attr("aria-expanded")).toBe("false");
});

it("should not register event handler on trigger element if open is specified", () => {
const component = testUtils.compileTemplate('<div><button class="trigger" oui-popover="foo" oui-popover-open="false"></button></div>');

$timeout.flush();

const trigger = angular.element(component[0].querySelector(".trigger")).triggerHandler("click");
const popover = trigger.next();

expect(popover.attr("x-placement")).toBe(undefined);
});

it("should trigger on-open and on-close", () => {
const openSpy = jasmine.createSpy("open");
const closeSpy = jasmine.createSpy("close");
const component = testUtils.compileTemplate(
`<div>
<button class="trigger" oui-popover="foo" oui-popover-on-open="$ctrl.open()" oui-popover-on-close="$ctrl.close()"></button>
</div>`, {
open: openSpy,
close: closeSpy
}
);

$timeout.flush();
angular.element(component[0].querySelector(".trigger")).triggerHandler("click");
$timeout.flush();

expect(openSpy).toHaveBeenCalled();
expect(openSpy.calls.count()).toEqual(1);

angular.element(component[0].querySelector(".trigger")).triggerHandler("click");
$timeout.flush();

expect(closeSpy).toHaveBeenCalled();
expect(closeSpy.calls.count()).toEqual(1);
});
});

describe("Deprecated support", () => {
Expand Down
37 changes: 31 additions & 6 deletions packages/oui-popover/src/popover.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,31 @@ export default class PopoverController {
}

$postLink () {
this.setPopover();
this.setTrigger();
this.setPopover()
.then(() => this.setTrigger())
.then(() => {
if (this.open) {
this.openPopover();
}
});
}

$onChanges (changes) {
if (angular.isDefined(changes.open) && this.triggerElement) {
if (changes.open.currentValue) {
this.openPopover();
} else {
this.closePopover();
}
}
}

$onDestroy () {
this.closePopover();
}

setPopover () {
this.$timeout(() => {
return this.$timeout(() => {
// Deprecated: Support for component `oui-popover-content`
if (this.isComponent) {
this.popperElement = this.$element[0].querySelector(".oui-popover");
Expand All @@ -67,7 +82,7 @@ export default class PopoverController {
}

setTrigger () {
this.$timeout(() => {
return this.$timeout(() => {
// Deprecated: Support for component `oui-popover-trigger`
if (this.isComponent) {
this.triggerElement = this.$element[0].querySelector(".oui-popover__trigger");
Expand All @@ -84,8 +99,12 @@ export default class PopoverController {
.attr({
"aria-haspopup": true,
"aria-expanded": false
})
.on("click", () => this.onTriggerClick());
});

if (angular.isUndefined(this.$attrs.ouiPopoverOpen)) {
this.$triggerElement
.on("click", () => this.onTriggerClick());
}
});
}

Expand Down Expand Up @@ -119,6 +138,9 @@ export default class PopoverController {

// Support for attribute `oui-popover`
this.$element.attr("aria-expanded", true);

// force the digest because the popover is outside the angular digest loop
this.$timeout(() => this.onOpen(), 0);
}

closePopover () {
Expand All @@ -134,6 +156,9 @@ export default class PopoverController {

// Support for attribute `oui-popover`
this.$element.attr("aria-expanded", false);

// force the digest because the popover is outside the angular digest loop
this.$timeout(() => this.onClose(), 0);
}

createPopper () {
Expand Down
5 changes: 4 additions & 1 deletion packages/oui-popover/src/popover.directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ export default () => {
title: "@?",
placement: "@?ouiPopoverPlacement",
scope: "<?ouiPopoverScope",
template: "@?ouiPopoverTemplate"
template: "@?ouiPopoverTemplate",
open: "<?ouiPopoverOpen",
onOpen: "&ouiPopoverOnOpen",
onClose: "&ouiPopoverOnClose"
},
controller,
controllerAs: "$popoverCtrl"
Expand Down