Skip to content

Commit

Permalink
feat(Collapse): implementa il componente Collapse
Browse files Browse the repository at this point in the history
fix #19
  • Loading branch information
Pasquale02 authored and ciccio86 committed Sep 14, 2018
1 parent 489f32b commit eb63459
Show file tree
Hide file tree
Showing 35 changed files with 1,165 additions and 0 deletions.
59 changes: 59 additions & 0 deletions e2e/src/collapse/collapse.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { CollapsePage } from './collapse.po';

describe('Collapse', () => {
let page: CollapsePage;

beforeEach(async() => {
page = new CollapsePage();
await page.go();
});

it('dovrebbe essere inizialmente non visibile nel DOM', async () => {
expect(await page.isDiv0Visible()).toBeFalsy();
});

it('dovrebbe essere effettuato il toggle quando si clicca il bottone', async () => {
expect(await page.isDiv0Visible()).toBeFalsy();
await page.clickButton();
expect(await page.isDiv0Visible()).toBeTruthy();
await page.clickButton();
expect(await page.isDiv0Visible()).toBeFalsy();
});

it('gli item del group dovrebbero essere inizialmente chiusi', async () => {
expect(await page.isItem0Visible()).toBeFalsy();
expect(await page.isItem1Visible()).toBeFalsy();
expect(await page.isItem2Visible()).toBeFalsy();
});

it('gli item del group non dovrebbero essere mutuamente esclusivi', async () => {
await page.clickGroup0Button();
expect(await page.isItem0Visible()).toBeTruthy();
expect(await page.isItem1Visible()).toBeFalsy();
expect(await page.isItem2Visible()).toBeFalsy();
await page.clickGroup1Button();
expect(await page.isItem0Visible()).toBeTruthy();
expect(await page.isItem1Visible()).toBeTruthy();
expect(await page.isItem2Visible()).toBeFalsy();
await page.clickGroup2Button();
expect(await page.isItem0Visible()).toBeTruthy();
expect(await page.isItem1Visible()).toBeTruthy();
expect(await page.isItem2Visible()).toBeTruthy();
});

it('gli item del group dovrebbero essere mutuamente esclusivi', async () => {
await page.clickCheckbox();
await page.clickGroup0Button();
expect(await page.isItem0Visible()).toBeTruthy();
expect(await page.isItem1Visible()).toBeFalsy();
expect(await page.isItem2Visible()).toBeFalsy();
await page.clickGroup1Button();
expect(await page.isItem0Visible()).toBeFalsy();
expect(await page.isItem1Visible()).toBeTruthy();
expect(await page.isItem2Visible()).toBeFalsy();
await page.clickGroup2Button();
expect(await page.isItem0Visible()).toBeFalsy();
expect(await page.isItem1Visible()).toBeFalsy();
expect(await page.isItem2Visible()).toBeTruthy();
});
});
70 changes: 70 additions & 0 deletions e2e/src/collapse/collapse.po.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { browser, by, element } from 'protractor';

export class CollapsePage {
private readonly COLLAPSE_URL = '/#/componenti/collapse';
private readonly ID_EXAMPLE_TAB = 'collapse-examples-tab';

private readonly ID_BUTTON = 'button-0';
private readonly ID_DIV_0 = 'collapseExample';

private readonly ID_CHECKBOX_ACCORDION = this.getLabelForAttribute('checkbox-0');

private readonly ID_ITEM_0_HEADING = 'collapse-item-0-heading';
private readonly ID_ITEM_0 = 'collapse-item-0';

private readonly ID_ITEM_1_HEADING = 'collapse-item-1-heading';
private readonly ID_ITEM_1 = 'collapse-item-1';

private readonly ID_ITEM_2_HEADING = 'collapse-item-2-heading';
private readonly ID_ITEM_2 = 'collapse-item-2';

async go() {
await browser.get(this.COLLAPSE_URL);
await element(by.id(this.ID_EXAMPLE_TAB)).click();
return await browser.sleep(500);
}

private getLabelForAttribute(attr: string) {
return `[for="${attr}"]`;
}

async existsButton() {
return await element(by.id(this.ID_BUTTON)).isPresent();
}

async clickButton() {
await element(by.id(this.ID_BUTTON)).click();
}

async isDiv0Visible() {
return await element(by.id(this.ID_DIV_0)).isDisplayed();
}

async clickCheckbox() {
await element(by.css(this.ID_CHECKBOX_ACCORDION)).click();
}

async clickGroup0Button() {
await element(by.id(this.ID_ITEM_0_HEADING)).click();
}

async clickGroup1Button() {
await element(by.id(this.ID_ITEM_1_HEADING)).click();
}

async clickGroup2Button() {
await element(by.id(this.ID_ITEM_2_HEADING)).click();
}

async isItem0Visible() {
return await element(by.id(this.ID_ITEM_0)).isDisplayed();
}

async isItem1Visible() {
return await element(by.id(this.ID_ITEM_1)).isDisplayed();
}

async isItem2Visible() {
return await element(by.id(this.ID_ITEM_2)).isDisplayed();
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div [id]="id" class="collapse-div" role="tablist">
<ng-content></ng-content>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Component, ContentChildren, forwardRef, QueryList,
Input, HostListener, SimpleChanges, OnChanges } from '@angular/core';
import { CollapseItemComponent } from './collapse-item.component';
import { Util } from '../util/util';

let identifier = 0;

@Component({
selector: 'it-collapse-group',
templateUrl: './collapse-group.component.html',
styleUrls: ['./collapse-group.component.css']
})
export class CollapseGroupComponent implements OnChanges {
id = `collapse-group-${identifier++}`;

/**
* Indica se gli item del gruppo sono mutuamente richiudibili (o accordion)
*/
@Input()
get accordion(): boolean { return this._accordion; }
set accordion(value: boolean) { this._accordion = Util.coerceBooleanProperty(value); }
private _accordion = false;

@ContentChildren(forwardRef(() => CollapseItemComponent), { descendants: true })
private _items: QueryList<CollapseItemComponent>; // tslint:disable-line

@HostListener('click', ['$event.target'])
onClick(target) {
if (this.accordion) {
const items = this._items.toArray();
items.forEach(currentItem => {
const isTargetPartOfItem = (currentItem.elementRef.nativeElement as HTMLElement).contains(target);
if (!isTargetPartOfItem) {
if (currentItem.directive.isShown()) {
currentItem.directive.hide();
}
}
});
}
}

ngOnChanges(simpleChanges: SimpleChanges) {
if (simpleChanges['accordion']) {
const isAccordion = simpleChanges['accordion'].currentValue;
if (isAccordion) {
const items = this._items.toArray();
items.forEach(currentItem => {
if (currentItem.directive.isShown()) {
currentItem.directive.hide();
}
});
}
}
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<div class="collapse-header" [id]="headingId">
<button #toggleButton data-toggle="collapse" [attr.aria-expanded]="collapse.isShown()" [attr.aria-controls]="id" (click)="collapse.toggle()" [ngClass]="{'collapsed' : collapse.isShown()}">
{{header}}
</button>
</div>
<div [id]="id" #collapse="it-collapse" it-collapse
(show)="show()" (hide)="hide()" (shown)="shown()" (hidden)="hidden()" role="tabpanel" [attr.aria-labelledby]="headingId">
<div class="collapse-body">
<ng-content></ng-content>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Component, Input, ViewChild, ElementRef, Output, EventEmitter } from '@angular/core';
import { CollapseDirective } from './collapse.directive';

let identifier = 0;

@Component({
selector: 'it-collapse-item',
templateUrl: './collapse-item.component.html',
styleUrls: ['./collapse-item.component.css']
})
export class CollapseItemComponent {
@ViewChild(CollapseDirective) readonly directive: CollapseDirective;

id = `collapse-item-${identifier++}`;
headingId = `${this.id}-heading`;

/**
* Testo del bottone di apertura/chiusura del collapse item
*/
@Input()
get header(): string { return this._header; }
set header(value: string) { this._header = value; }
private _header;

/**
* Evento da emettere quando il collapse sta per essere mostrato
*/
@Output('show')
get showEvent(): EventEmitter<CollapseItemComponent> { return this._showEvent; }
set showEvent(value: EventEmitter<CollapseItemComponent>) { this._showEvent = value; }
private _showEvent = new EventEmitter<CollapseItemComponent>();

/**
* Evento da emettere quando il collapse è mostrato
*/
@Output('shown')
get shownEvent(): EventEmitter<CollapseItemComponent> { return this._shownEvent; }
set shownEvent(value: EventEmitter<CollapseItemComponent>) { this._shownEvent = value; }
private _shownEvent = new EventEmitter<CollapseItemComponent>();

/**
* Evento da emettere quando il collapse sta per essere nascosto
*/
@Output('hide')
get hideEvent(): EventEmitter<CollapseItemComponent> { return this._hideEvent; }
set hideEvent(value: EventEmitter<CollapseItemComponent>) { this._hideEvent = value; }
private _hideEvent = new EventEmitter<CollapseItemComponent>();

/**
* Evento da emettere quando il collapse è nascosto
*/
@Output('hidden')
get hiddenEvent(): EventEmitter<CollapseItemComponent> { return this._hiddenEvent; }
set hiddenEvent(value: EventEmitter<CollapseItemComponent>) { this._hiddenEvent = value; }
private _hiddenEvent = new EventEmitter<CollapseItemComponent>();

show() {
this.showEvent.emit(this);
}

hide() {
this.hideEvent.emit(this);
}

shown() {
this.shownEvent.emit(this);
}

hidden() {
this.hiddenEvent.emit(this);
}

constructor(readonly elementRef: ElementRef) { }
}
Loading

0 comments on commit eb63459

Please sign in to comment.