Skip to content

Commit c620adb

Browse files
authored
Add accessibility mode attribute to cl-image (#246)
* Add accessibility mode attribute to cl-image
1 parent fdb7417 commit c620adb

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

src/cloudinary-image.component.spec.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,4 +855,67 @@ describe('CloudinaryImage', () => {
855855
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_sepia/c_fit,w_30/e_blur:2000,f_auto,q_1/bear'));
856856
}));
857857
});
858+
describe('cl-image with acessibility modes', () => {
859+
@Component({
860+
template: `<cl-image public-id="bear" accessibility="darkmode"></cl-image>
861+
<cl-image public-id="bear" accessibility="monochrome"></cl-image>
862+
<cl-image public-id="bear" accessibility="brightmode"></cl-image>
863+
<cl-image public-id="bear" accessibility="colorblind"></cl-image>`
864+
})
865+
class TestComponent {}
866+
867+
let fixture: ComponentFixture<TestComponent>;
868+
let des: DebugElement[]; // the elements w/ the directive
869+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
870+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
871+
beforeEach(() => {
872+
fixture = TestBed.configureTestingModule({
873+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent],
874+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
875+
}).createComponent(TestComponent);
876+
fixture.detectChanges(); // initial binding
877+
des = fixture.debugElement.queryAll(By.directive(CloudinaryImage));
878+
});
879+
it('creates an img element with accessibility darkmode', fakeAsync(() => {
880+
const img = des[0].children[0].nativeElement as HTMLImageElement;
881+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_tint:75:black/bear'));
882+
}));
883+
it('creates an img element with accessibility monochrome', fakeAsync(() => {
884+
const img = des[1].children[0].nativeElement as HTMLImageElement;
885+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_grayscale/bear'));
886+
}));
887+
it('creates an img element with accessibility brightmode', fakeAsync(() => {
888+
const img = des[2].children[0].nativeElement as HTMLImageElement;
889+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_tint:50:white/bear'));
890+
}));
891+
it('creates an img element with accessibility colorblind', fakeAsync(() => {
892+
const img = des[3].children[0].nativeElement as HTMLImageElement;
893+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_assist_colorblind/bear'));
894+
}));
895+
});
896+
describe('cl-image with acessibility modes and transformation', () => {
897+
@Component({
898+
template: `<cl-image public-id="bear" accessibility="darkmode" effect="grayscale" overlay="sample">
899+
<cl-transformation effect="sepia"></cl-transformation>
900+
</cl-image>`
901+
})
902+
class TestComponent {}
903+
904+
let fixture: ComponentFixture<TestComponent>;
905+
let des: DebugElement[]; // the elements w/ the directive
906+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
907+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
908+
beforeEach(() => {
909+
fixture = TestBed.configureTestingModule({
910+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent],
911+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
912+
}).createComponent(TestComponent);
913+
fixture.detectChanges(); // initial binding
914+
des = fixture.debugElement.queryAll(By.directive(CloudinaryImage));
915+
});
916+
it('creates an img element with accessibility darkmode without overwriting effect', fakeAsync(() => {
917+
const img = des[0].children[0].nativeElement as HTMLImageElement;
918+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_sepia/e_grayscale,l_sample/e_tint:75:black/bear'));
919+
}));
920+
});
858921
});

src/cloudinary-image.component.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ import { Cloudinary } from './cloudinary.service';
1717
import { CloudinaryTransformationDirective } from './cloudinary-transformation.directive';
1818
import { CloudinaryPlaceHolder } from './cloudinary-placeholder.component';
1919
import { isBrowser } from './cloudinary.service';
20+
import { accessibilityEffect } from './constants';
2021

2122
@Component({
2223
selector: 'cl-image',
2324
template: `<img [ngStyle]="{opacity: shouldShowPlaceHolder ? '0' : '1', position: shouldShowPlaceHolder ? 'absolute' : 'unset'}"(load)="hasLoaded()">
2425
<div [style.display]="shouldShowPlaceHolder ? 'inline' : 'none'">
25-
<ng-content></ng-content>
26+
<ng-content></ng-content>
2627
</div>
2728
`,
2829
})
@@ -33,6 +34,7 @@ export class CloudinaryImage
3334
@Input('loading') loading: string;
3435
@Input('width') width?: string;
3536
@Input('height') height?: string;
37+
@Input('accessibility') accessibility?: string;
3638

3739
@ContentChildren(CloudinaryTransformationDirective)
3840
transformations: QueryList<CloudinaryTransformationDirective>;
@@ -43,6 +45,7 @@ export class CloudinaryImage
4345

4446
observer: MutationObserver;
4547
shouldShowPlaceHolder: boolean = true;
48+
options: object = {};
4649

4750
constructor(private el: ElementRef, private cloudinary: Cloudinary) {}
4851

@@ -109,6 +112,7 @@ export class CloudinaryImage
109112
image.onerror = e => {
110113
this.onError.emit(e);
111114
}
115+
112116
const options = this.cloudinary.toCloudinaryAttributes(
113117
nativeElement.attributes,
114118
this.transformations
@@ -121,6 +125,10 @@ export class CloudinaryImage
121125
if (this.placeholderComponent) {
122126
this.placeholderHandler(options);
123127
}
128+
if (this.accessibility) {
129+
this.options = options;
130+
options.src = this.accessibilityModeHandler();
131+
}
124132
const imageTag = this.cloudinary.imageTag(this.publicId, options);
125133

126134
this.setElementAttributes(image, imageTag.attributes());
@@ -145,4 +153,9 @@ export class CloudinaryImage
145153
})
146154
this.placeholderComponent.options = placeholderOptions;
147155
}
156+
157+
accessibilityModeHandler() {
158+
return this.cloudinary.url(this.publicId, {transformation: [this.options, accessibilityEffect[this.accessibility]]});
159+
}
148160
}
161+

src/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const accessibilityEffect = {
2+
'darkmode': {effect: 'tint:75:black'},
3+
'brightmode': {effect: 'tint:50:white'},
4+
'monochrome': {effect: 'grayscale'},
5+
'colorblind': {effect: 'assist_colorblind'}
6+
}

0 commit comments

Comments
 (0)