Skip to content

Commit

Permalink
feat(util:other:lazy): add attriburte property (#1548)
Browse files Browse the repository at this point in the history
  • Loading branch information
cipchk authored Nov 11, 2022
1 parent a408cbb commit a197bb1
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 18 deletions.
27 changes: 24 additions & 3 deletions packages/util/other/lazy.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ describe('utils: lazy', () => {
doc = TestBed.inject(DOCUMENT);
});

it('should be load via LazyLoadItem', () => {
const res: NzSafeAny = {};
const content = 'var a = 1;';
spyOn(doc, 'createElement').and.callFake(() => res);
srv.load([{ path: '1.js', options: { innerContent: content } }]);
expect(res.innerHTML).toBe(content);
});

describe('Scripts', () => {
it('should be load a js resource', done => {
srv.change
Expand All @@ -66,7 +74,7 @@ describe('utils: lazy', () => {
const res: NzSafeAny = {};
const content = 'var a = 1;';
spyOn(doc, 'createElement').and.callFake(() => res);
srv.loadScript('/1.js', content);
srv.loadScript('/1.js', { innerContent: content });
expect(res.innerHTML).toBe(content);
});
});
Expand All @@ -80,7 +88,7 @@ describe('utils: lazy', () => {
srv.load('/1.css');
});
it('should be load a less resource', done => {
srv.loadStyle('/1.less', 'stylesheet/less').then(res => {
srv.loadStyle('/1.less', { rel: 'stylesheet/less' }).then(res => {
expect(res.status).toBe('ok');
done();
});
Expand All @@ -91,7 +99,7 @@ describe('utils: lazy', () => {
};
const content = 'var a = 1;';
spyOn(doc, 'createElement').and.callFake(() => res);
srv.loadStyle('/1.js', 'stylesheet/less', content);
srv.loadStyle('/1.js', { rel: 'stylesheet/less', innerContent: content });
expect(res.innerHTML).toBe(content);
});
});
Expand Down Expand Up @@ -128,4 +136,17 @@ describe('utils: lazy', () => {
});
srv.load('/3.js');
});

describe('#attributes', () => {
it('should be working', () => {
const res: NzSafeAny = {
setAttribute(key: string, value: string): void {
res[key] = value;
}
};
spyOn(doc, 'createElement').and.callFake(() => res);
srv.loadScript('/1.js', { innerContent: '', attributes: { a: 'b' } });
expect(res.a).toBe('b');
});
});
});
103 changes: 88 additions & 15 deletions packages/util/other/lazy.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,20 @@ export interface LazyResult {
error?: NzSafeAny;
}

export interface LazyLoadItem {
path: string;
options?: LazyLoadOptions;
}

export interface LazyLoadOptions {
innerContent?: string;
attributes?: { [qualifiedName: string]: string };
rel?: string;
}

/**
* `LazyService` delay loading JS or CSS files.
*
* 延迟加载资源(js 或 css)服务
*/
@Injectable({ providedIn: 'root' })
Expand All @@ -33,27 +46,59 @@ export class LazyService {
this.cached = {};
}

load(paths: string | string[]): Promise<LazyResult[]> {
private attachAttributes(el: HTMLElement, attributes?: { [qualifiedName: string]: string }): void {
if (attributes == null) return;

Object.entries(attributes).forEach(([key, value]) => {
el.setAttribute(key, value);
});
}

/**
* Load script or style files
*/
load(paths: string | LazyLoadItem | Array<string | LazyLoadItem>): Promise<LazyResult[]> {
if (!Array.isArray(paths)) {
paths = [paths];
}

const promises: Array<Promise<LazyResult>> = [];
paths.forEach(path => {
if (path.endsWith('.js')) {
promises.push(this.loadScript(path));
} else {
promises.push(this.loadStyle(path));
}
});
paths
.map(v => (typeof v !== 'object' ? ({ path: v } as LazyLoadItem) : v))
.forEach(item => {
if (item.path.endsWith('.js')) {
promises.push(this.loadScript(item.path, item.options));
} else {
promises.push(this.loadStyle(item.path, item.options));
}
});

return Promise.all(promises).then(res => {
this._notify.next(res);
return Promise.resolve(res);
});
}

loadScript(path: string, innerContent?: string): Promise<LazyResult> {
/**
* @deprecated Will be removed in 15.0.0, Please use `loadScript(path, options)` instead
*/
loadScript(path: string, innerContent: string, attributes?: { [qualifiedName: string]: string }): Promise<LazyResult>;
/**
* Load a script file
*/
loadScript(path: string, options?: LazyLoadOptions): Promise<LazyResult>;
loadScript(
path: string,
innerContent?: string | LazyLoadOptions,
attributes?: { [qualifiedName: string]: string }
): Promise<LazyResult> {
const options: LazyLoadOptions =
typeof innerContent === 'object'
? innerContent
: {
innerContent,
attributes
};
return new Promise(resolve => {
if (this.list[path] === true) {
resolve({ ...this.cached[path], status: 'loading' });
Expand All @@ -70,8 +115,9 @@ export class LazyService {
const node = this.doc.createElement('script') as HTMLScriptElement;
node.type = 'text/javascript';
node.src = path;
if (innerContent) {
node.innerHTML = innerContent;
this.attachAttributes(node, options.attributes);
if (options.innerContent) {
node.innerHTML = options.innerContent;
}
node.onload = () =>
onSuccess({
Expand All @@ -88,7 +134,33 @@ export class LazyService {
});
}

loadStyle(path: string, rel: string = 'stylesheet', innerContent?: string): Promise<LazyResult> {
/**
* @deprecated Will be removed in 15.0.0, Please use `loadStyle(path, options)` instead
*/
loadStyle(
path: string,
rel: string,
innerContent?: string,
attributes?: { [qualifiedName: string]: string }
): Promise<LazyResult>;
/**
* Load a style file
*/
loadStyle(path: string, options?: LazyLoadOptions): Promise<LazyResult>;
loadStyle(
path: string,
rel?: string | LazyLoadOptions,
innerContent?: string,
attributes?: { [qualifiedName: string]: string }
): Promise<LazyResult> {
const options: LazyLoadOptions =
typeof rel === 'object'
? rel
: {
rel,
innerContent,
attributes
};
return new Promise(resolve => {
if (this.list[path] === true) {
resolve(this.cached[path]);
Expand All @@ -98,11 +170,12 @@ export class LazyService {
this.list[path] = true;

const node = this.doc.createElement('link') as HTMLLinkElement;
node.rel = rel;
node.rel = options.rel ?? 'stylesheet';
node.type = 'text/css';
node.href = path;
if (innerContent) {
node.innerHTML = innerContent;
this.attachAttributes(node, options.attributes);
if (options.innerContent) {
node.innerHTML = options.innerContent;
}
this.doc.getElementsByTagName('head')[0].appendChild(node);
const item: LazyResult = {
Expand Down

0 comments on commit a197bb1

Please sign in to comment.