Skip to content

Commit 5b9eed8

Browse files
committed
Merge branch 'master' of https://github.com/IgniteUI/igniteui-angular into hanastasov/grid-state
2 parents c420e14 + 1f0e051 commit 5b9eed8

17 files changed

+438
-116
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ All notable changes for each version of this project will be documented in this
2929
- `sortingExpressionsChange` event emitter is added, which is fired whenever a change to the sorting expressions has occurred (prior to performing the actual sorting).
3030
- `filteringExpressionsTreeChange` event emitter is added, which is fired whenever a change to the filtering expressions has occurred (prior to performing the actual filtering).
3131
- `advancedFilteringExpressionsTreeChange` event emitter is added, which is fired whenever a change to the advanced filtering expressions has occurred (prior to performing the actual filtering).
32+
- `collapsible` and `expanded` properties are added to the IgxColumnGroupComponent; `collapsible` property identifies that certain column group is collapsible; `expanded` identifies whether the group is expanded or collapsed initially;
33+
- `collapsibleChange` and `expandedChange` events are added to the IgxColumnGroupComponent which are emited whenever `collapsible` and `expanded` properties are changed accordingly;
34+
- `visibleWhenCollapsed` property has been added to the IgxColumnComponent; Allows you to set whether the column stay visible when its parrent is collapsed.
35+
- `visibleWhenCollapsedChange` events is added to the IgxColumnComponent which are emited whenever `visibleWhenCollapsed` property is changed;
36+
- `collapsibleIndicatorTemplate` property is introduced to IgxColumnGroupComponent, which allows you to set a custom template for the expand collapse indicator;
37+
- `igxCollapsibleIndicator` directive has been introduced, which allows you to set a custom template for the expand collapse indicator;
3238
- `IgxGridExcelStyleFilteringComponent` and `IgxAdvancedFilteringDialogComponent` can now be hosted outside of the grid in order to provide the same experience as the built-in filtering UI.
3339
- `IgxOverlayService`:
3440
- `setOffset` method added. It offsets the content along the corresponding axis by the provided amount.

projects/igniteui-angular/src/lib/carousel/carousel.component.spec.ts

+73-23
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
TestBed,
55
ComponentFixture,
66
fakeAsync,
7-
tick
7+
tick,
8+
flush
89
} from '@angular/core/testing';
910
import { By } from '@angular/platform-browser';
1011
import {
@@ -19,6 +20,8 @@ import { configureTestSuite } from '../test-utils/configure-suite';
1920
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
2021
import { IgxSlideComponent } from './slide.component';
2122

23+
declare var Simulator: any;
24+
2225
describe('Carousel', () => {
2326
configureTestSuite();
2427
let fixture;
@@ -427,7 +430,7 @@ describe('Carousel', () => {
427430
expect(carousel.onSlideChanged.emit).toHaveBeenCalledTimes(1);
428431
});
429432

430-
it('should stop/play on mouse enter/leave and on tab key', () => {
433+
it('should stop/play on mouse enter/leave ', () => {
431434
carousel.interval = 1000;
432435
carousel.play();
433436
fixture.detectChanges();
@@ -450,17 +453,64 @@ describe('Carousel', () => {
450453
expect(carousel.onCarouselPlaying.emit).toHaveBeenCalledTimes(1);
451454
expect(carousel.onCarouselPaused.emit).toHaveBeenCalledTimes(1);
452455

453-
UIInteractions.triggerKeyDownEvtUponElem('Tab', carousel.nativeElement, true);
456+
// When the carousel is stopped mouseleave does not start playing
457+
carousel.stop();
454458
fixture.detectChanges();
455459

456460
expect(carousel.isPlaying).toBeFalsy();
461+
expect(carousel.onCarouselPlaying.emit).toHaveBeenCalledTimes(1);
457462
expect(carousel.onCarouselPaused.emit).toHaveBeenCalledTimes(2);
458463

459-
UIInteractions.triggerKeyDownEvtUponElem('Tab', carousel.nativeElement, true);
464+
UIInteractions.hoverElement(carousel.nativeElement, true);
460465
fixture.detectChanges();
466+
467+
expect(carousel.isPlaying).toBeFalsy();
468+
469+
UIInteractions.unhoverElement(carousel.nativeElement, true);
470+
fixture.detectChanges();
471+
expect(carousel.isPlaying).toBeFalsy();
472+
expect(carousel.onCarouselPlaying.emit).toHaveBeenCalledTimes(1);
473+
});
474+
475+
it('should stop/play on tap ', async () => {
476+
carousel.interval = 1000;
477+
carousel.play();
478+
fixture.detectChanges();
479+
480+
spyOn(carousel.onCarouselPaused, 'emit');
481+
spyOn(carousel.onCarouselPlaying, 'emit');
482+
461483
expect(carousel.isPlaying).toBeTruthy();
462-
expect(carousel.onCarouselPlaying.emit).toHaveBeenCalledTimes(2);
463-
expect(carousel.onCarouselPaused.emit).toHaveBeenCalledTimes(2);
484+
485+
Simulator.gestures.press(carousel.nativeElement, { duration: 180 });
486+
fixture.detectChanges();
487+
await wait(200);
488+
489+
expect(carousel.isPlaying).toBeFalsy();
490+
491+
Simulator.gestures.press(carousel.nativeElement, { duration: 180 });
492+
fixture.detectChanges();
493+
await wait(200);
494+
495+
expect(carousel.isPlaying).toBeTruthy();
496+
497+
// When the carousel is stopped tap does not start playing
498+
carousel.stop();
499+
fixture.detectChanges();
500+
501+
expect(carousel.isPlaying).toBeFalsy();
502+
503+
Simulator.gestures.press(carousel.nativeElement, { duration: 180 });
504+
fixture.detectChanges();
505+
await wait(200);
506+
507+
expect(carousel.isPlaying).toBeFalsy();
508+
509+
Simulator.gestures.press(carousel.nativeElement, { duration: 180 });
510+
fixture.detectChanges();
511+
await wait(200);
512+
513+
expect(carousel.isPlaying).toBeFalsy();
464514
});
465515
});
466516

@@ -601,19 +651,19 @@ describe('Carousel', () => {
601651
HelperTestFunctions.verifyActiveSlide(carousel, 0);
602652
}));
603653

604-
it('should add slides to the carousel when collection is changed', fakeAsync(() => {
654+
it('should add slides to the carousel when collection is changed', fakeAsync(() => {
605655
tick();
606656
spyOn(carousel.onSlideAdded, 'emit');
607657

608658
// add a slide
609-
slides.push({text: 'Slide 5'});
659+
slides.push({ text: 'Slide 5' });
610660
fixture.detectChanges();
611661

612662
HelperTestFunctions.verifyActiveSlide(carousel, 2);
613663
expect(carousel.total).toEqual(5);
614664

615665
// add an active slide
616-
slides.push({text: 'Slide 6', active: true});
666+
slides.push({ text: 'Slide 6', active: true });
617667
fixture.detectChanges();
618668
tick(100);
619669

@@ -623,7 +673,7 @@ describe('Carousel', () => {
623673
expect(carousel.onSlideAdded.emit).toHaveBeenCalledTimes(2);
624674
}));
625675

626-
it('should remove slides in the carousel', fakeAsync(() => {
676+
it('should remove slides in the carousel', fakeAsync(() => {
627677
tick();
628678
spyOn(carousel.onSlideRemoved, 'emit');
629679

@@ -646,7 +696,7 @@ describe('Carousel', () => {
646696
expect(carousel.onSlideRemoved.emit).toHaveBeenCalledTimes(2);
647697
}));
648698

649-
it('should not render navigation buttons and indicators when carousel does not have slides', fakeAsync(() => {
699+
it('should not render navigation buttons and indicators when carousel does not have slides', fakeAsync(() => {
650700
fixture.componentInstance.removeAllSlides();
651701
fixture.detectChanges();
652702
tick(200);
@@ -657,13 +707,13 @@ describe('Carousel', () => {
657707
expect(HelperTestFunctions.getNextButton(fixture).hidden).toBeTruthy();
658708
expect(HelperTestFunctions.getPreviousButton(fixture).hidden).toBeTruthy();
659709

660-
// add a slide
661-
fixture.componentInstance.addSlides();
662-
fixture.detectChanges();
663-
tick(200);
710+
// add a slide
711+
fixture.componentInstance.addSlides();
712+
fixture.detectChanges();
713+
tick(200);
664714

665-
expect(carousel.total).toEqual(2);
666-
expect(HelperTestFunctions.getIndicatorsContainer(fixture)).toBeDefined();
715+
expect(carousel.total).toEqual(2);
716+
expect(HelperTestFunctions.getIndicatorsContainer(fixture)).toBeDefined();
667717
expect(HelperTestFunctions.getIndicatorsContainer(fixture, CarouselIndicatorsOrientation.top)).toBeDefined();
668718
expect(HelperTestFunctions.getNextButton(fixture).hidden).toBeFalsy();
669719
expect(HelperTestFunctions.getPreviousButton(fixture).hidden).toBeFalsy();
@@ -824,10 +874,10 @@ class CarouselDynamicSlidesComponent {
824874

825875
addNewSlide() {
826876
this.slides.push(
827-
{text: 'Slide 1', active: false},
828-
{text: 'Slide 2', active: false},
829-
{text: 'Slide 3', active: true},
830-
{text: 'Slide 4', active: false}
877+
{ text: 'Slide 1', active: false },
878+
{ text: 'Slide 2', active: false },
879+
{ text: 'Slide 3', active: true },
880+
{ text: 'Slide 4', active: false }
831881
);
832882
}
833883

@@ -837,8 +887,8 @@ class CarouselDynamicSlidesComponent {
837887

838888
public addSlides() {
839889
this.slides.push(
840-
{text: 'Slide 1'},
841-
{text: 'Slide 2'}
890+
{ text: 'Slide 1' },
891+
{ text: 'Slide 2' }
842892
);
843893
}
844894
}

projects/igniteui-angular/src/lib/carousel/carousel.component.ts

+43-31
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
176176
*/
177177
set interval(value: number) {
178178
this._interval = +value;
179-
this._restartInterval();
179+
this.restartInterval();
180180
}
181181

182182
/**
@@ -333,20 +333,21 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
333333
@Output() public onCarouselPlaying = new EventEmitter<IgxCarouselComponent>();
334334

335335
private _interval: number;
336-
private _lastInterval: any;
337-
private _playing: boolean;
338-
private _destroyed: boolean;
339336
private _resourceStrings = CurrentResourceStrings.CarouselResStrings;
337+
private lastInterval: any;
338+
private playing: boolean;
339+
private stoppedByInteraction: boolean;
340+
private destroyed: boolean;
340341
private destroy$ = new Subject<any>();
341-
private _differ: IterableDiffer<IgxSlideComponent> | null = null;
342+
private differ: IterableDiffer<IgxSlideComponent> | null = null;
342343
private enterAnimationPlayer?: AnimationPlayer;
343344
private leaveAnimationPlayer?: AnimationPlayer;
344345
private currentSlide: IgxSlideComponent;
345346
private previousSlide: IgxSlideComponent;
346347
private animationDuration = 320;
347348

348-
constructor(private element: ElementRef, private _iterableDiffers: IterableDiffers, private builder: AnimationBuilder) {
349-
this._differ = this._iterableDiffers.find([]).create(null);
349+
constructor(private element: ElementRef, private iterableDiffers: IterableDiffers, private builder: AnimationBuilder) {
350+
this.differ = this.iterableDiffers.find([]).create(null);
350351
}
351352

352353
/**
@@ -366,9 +367,9 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
366367
public ngOnDestroy() {
367368
this.destroy$.next(true);
368369
this.destroy$.complete();
369-
this._destroyed = true;
370-
if (this._lastInterval) {
371-
clearInterval(this._lastInterval);
370+
this.destroyed = true;
371+
if (this.lastInterval) {
372+
clearInterval(this.lastInterval);
372373
}
373374
}
374375

@@ -405,7 +406,7 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
405406
this.currentSlide = slide;
406407
}
407408
this.onSlideChanged.emit({ carousel: this, slide });
408-
this._restartInterval();
409+
this.restartInterval();
409410
}
410411
}
411412

@@ -496,7 +497,7 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
496497
}
497498

498499
private initSlides(change: QueryList<IgxSlideComponent>) {
499-
const diff = this._differ.diff(change.toArray());
500+
const diff = this.differ.diff(change.toArray());
500501
if (diff) {
501502
this.slides.reduce((any, c, ind) => c.index = ind, 0); // reset slides indexes
502503
diff.forEachAddedItem((record: IterableChangeRecord<IgxSlideComponent>) => {
@@ -614,7 +615,7 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
614615
* @memberOf IgxCarouselComponent
615616
*/
616617
public get isPlaying(): boolean {
617-
return this._playing;
618+
return this.playing;
618619
}
619620

620621
/**
@@ -625,7 +626,7 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
625626
* @memberOf IgxCarouselComponent
626627
*/
627628
public get isDestroyed(): boolean {
628-
return this._destroyed;
629+
return this.destroyed;
629630
}
630631
/**
631632
* Returns a reference to the carousel element in the DOM.
@@ -738,10 +739,11 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
738739
* @memberOf IgxCarouselComponent
739740
*/
740741
public play() {
741-
if (!this._playing) {
742-
this._playing = true;
742+
if (!this.playing) {
743+
this.playing = true;
743744
this.onCarouselPlaying.emit(this);
744-
this._restartInterval();
745+
this.restartInterval();
746+
this.stoppedByInteraction = false;
745747
}
746748
}
747749

@@ -756,26 +758,26 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
756758
*/
757759
public stop() {
758760
if (this.pause) {
759-
this._playing = false;
761+
this.playing = false;
760762
this.onCarouselPaused.emit(this);
761-
this._resetInterval();
763+
this.resetInterval();
762764
}
763765
}
764766

765-
private _resetInterval() {
766-
if (this._lastInterval) {
767-
clearInterval(this._lastInterval);
768-
this._lastInterval = null;
767+
private resetInterval() {
768+
if (this.lastInterval) {
769+
clearInterval(this.lastInterval);
770+
this.lastInterval = null;
769771
}
770772
}
771773

772-
private _restartInterval() {
773-
this._resetInterval();
774+
private restartInterval() {
775+
this.resetInterval();
774776

775777
if (!isNaN(this.interval) && this.interval > 0) {
776-
this._lastInterval = setInterval(() => {
778+
this.lastInterval = setInterval(() => {
777779
const tick = +this.interval;
778-
if (this._playing && this.total && !isNaN(tick) && tick > 0) {
780+
if (this.playing && this.total && !isNaN(tick) && tick > 0) {
779781
this.next();
780782
} else {
781783
this.stop();
@@ -807,12 +809,17 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
807809
}
808810

809811
/** @hidden */
810-
@HostListener('keydown.Tab')
811-
public onTab() {
812+
@HostListener('tap')
813+
public onTap() {
812814
if (this.isPlaying) {
815+
if (this.pause && this.isPlaying) {
816+
this.stoppedByInteraction = true;
817+
}
813818
this.stop();
814819
} else {
815-
this.play();
820+
if (this.stoppedByInteraction) {
821+
this.play();
822+
}
816823
}
817824
}
818825

@@ -845,6 +852,9 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
845852
*/
846853
@HostListener('mouseenter')
847854
public onMouseEnter() {
855+
if (this.pause && this.isPlaying) {
856+
this.stoppedByInteraction = true;
857+
}
848858
this.stop();
849859
}
850860

@@ -853,7 +863,9 @@ export class IgxCarouselComponent implements OnDestroy, AfterContentInit {
853863
*/
854864
@HostListener('mouseleave')
855865
public onMouseLeave() {
856-
this.play();
866+
if ( this.stoppedByInteraction ) {
867+
this.play();
868+
}
857869
}
858870

859871
/**

projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-component.scss

+12
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,18 @@
205205
@extend %grid-cell-header !optional;
206206
}
207207

208+
@include e(th-expander) {
209+
@extend %igx-grid__th-expander !optional
210+
}
211+
212+
@include e(th-group-title) {
213+
@extend %igx-grid__th-group-title !optional
214+
}
215+
216+
@include e(th, $m: collapsible) {
217+
@extend %igx-grid__th--collapsible !optional;
218+
}
219+
208220
@include e(th, $m: sortable) {
209221
@extend %igx-grid__th--sortable !optional;
210222
}

0 commit comments

Comments
 (0)