Skip to content

Commit

Permalink
feat(style-manager): for change theme runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
pimenovoleg committed Mar 21, 2018
1 parent cef64c2 commit b9deb7d
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/cdk/style-manager/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

export * from './public-api';
2 changes: 2 additions & 0 deletions src/cdk/style-manager/public-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

export * from './style-manager';
56 changes: 56 additions & 0 deletions src/cdk/style-manager/style-manager.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { inject, TestBed } from '@angular/core/testing';
import { HttpClientModule } from '@angular/common/http';

import { StyleManager } from './style-manager';


describe('StyleManager', () => {
let styleManager: StyleManager;

beforeEach(() => TestBed.configureTestingModule({
imports: [HttpClientModule],
providers: [StyleManager]
}));

beforeEach(inject([StyleManager], (sm: StyleManager) => {
styleManager = sm;
}));

afterEach(() => {
const links = document.head.querySelectorAll('link');

for (const link of Array.prototype.slice.call(links)) {
if (link.className.includes('style-manager-')) {
document.head.removeChild(link);
}
}
});

it('should add stylesheet to head', () => {
styleManager.setStyle('test', 'test.css');
const styleEl = document.head.querySelector('.style-manager-test') as HTMLLinkElement;
expect(styleEl).not.toBeNull();
expect(styleEl.href.endsWith('test.css')).toBe(true);
});

it('should change existing stylesheet', () => {
styleManager.setStyle('test', 'test.css');
const styleEl = document.head.querySelector('.style-manager-test') as HTMLLinkElement;
expect(styleEl).not.toBeNull();
expect(styleEl.href.endsWith('test.css')).toBe(true);

styleManager.setStyle('test', 'new.css');
expect(styleEl.href.endsWith('new.css')).toBe(true);
});

it('should remove existing stylesheet', () => {
styleManager.setStyle('test', 'test.css');
let styleEl = document.head.querySelector('.style-manager-test') as HTMLLinkElement;
expect(styleEl).not.toBeNull();
expect(styleEl.href.endsWith('test.css')).toBe(true);

styleManager.removeStyle('test');
styleEl = document.head.querySelector('.style-manager-test') as HTMLLinkElement;
expect(styleEl).toBeNull();
});
});
47 changes: 47 additions & 0 deletions src/cdk/style-manager/style-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Injectable } from '@angular/core';


/**
* Class for managing stylesheets. Stylesheets are loaded into named slots so that they can be
* removed or changed later.
*/
@Injectable()
export class StyleManager {
/**
* Set the stylesheet with the specified key.
*/
setStyle(key: string, href: string) {
getLinkElementForKey(key).setAttribute('href', href);
}

/**
* Remove the stylesheet with the specified key.
*/
removeStyle(key: string) {
const existingLinkElement = getExistingLinkElementByKey(key);
if (existingLinkElement) {
document.head.removeChild(existingLinkElement);
}
}
}

function getLinkElementForKey(key: string) {
return getExistingLinkElementByKey(key) || createLinkElementWithKey(key);
}

function getExistingLinkElementByKey(key: string) {
return document.head.querySelector(`link[rel="stylesheet"].${getClassNameForKey(key)}`);
}

function createLinkElementWithKey(key: string) {
const linkEl = document.createElement('link');
linkEl.setAttribute('rel', 'stylesheet');
linkEl.classList.add(getClassNameForKey(key));
document.head.appendChild(linkEl);

return linkEl;
}

function getClassNameForKey(key: string) {
return `style-manager-${key}`;
}
14 changes: 14 additions & 0 deletions src/cdk/style-manager/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "../tsconfig.build",
"files": [
"public-api.ts"
],
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"strictMetadataEmit": false,
"flatModuleOutFile": "index.js",
"flatModuleId": "@ptsecurity/cdk/style-manager",
"skipTemplateCodegen": true,
"fullTemplateTypeCheck": true
}
}

0 comments on commit b9deb7d

Please sign in to comment.