Skip to content

Commit 7935fe8

Browse files
jonathantnealromainmenke
authored andcommitted
0.1.2
1 parent 8570979 commit 7935fe8

File tree

8 files changed

+173
-9
lines changed

8 files changed

+173
-9
lines changed

plugins/css-blank-pseudo/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
node_modules
22
/browser.js*
3+
/browser-legacy.js*
34
/cli.js*
45
/index.js*
56
/index.mjs*
7+
/legacy.js*
8+
/legacy.mjs*
69
/postcss.js*
710
/postcss.mjs*
811
package-lock.json

plugins/css-blank-pseudo/.rollup.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,26 @@ import babel from 'rollup-plugin-babel';
22
import { terser } from 'rollup-plugin-terser';
33

44
const isBrowser = String(process.env.NODE_ENV).includes('browser');
5+
const isLegacy = String(process.env.NODE_ENV).includes('legacy');
56
const isCLI = String(process.env.NODE_ENV).includes('cli');
67
const isPostCSS = String(process.env.NODE_ENV).includes('postcss');
78
const targets = isCLI || isPostCSS || !isBrowser ? { node: 6 } : 'last 2 versions, not dead';
89

9-
const input = `src/${isCLI ? 'cli' : isPostCSS ? 'postcss' : 'browser'}.js`;
10+
const input = `src/${isCLI ? 'cli' : isPostCSS ? 'postcss' : isLegacy ? 'browser-legacy' : 'browser'}.js`;
1011
const output = isCLI
1112
? { file: 'cli.js', format: 'cjs' }
13+
: isBrowser && isLegacy
14+
? { file: 'browser-legacy.js', format: 'cjs' }
1215
: isBrowser
1316
? { file: 'browser.js', format: 'cjs' }
1417
: isPostCSS
1518
? [
1619
{ file: 'postcss.js', format: 'cjs', sourcemap: true },
1720
{ file: 'postcss.mjs', format: 'esm', sourcemap: true }
21+
] : isLegacy
22+
? [
23+
{ file: 'legacy.js', format: 'cjs', sourcemap: true },
24+
{ file: 'legacy.mjs', format: 'esm', sourcemap: true }
1825
] : [
1926
{ file: 'index.js', format: 'cjs', sourcemap: true },
2027
{ file: 'index.mjs', format: 'esm', sourcemap: true }

plugins/css-blank-pseudo/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changes to CSS Blank Pseudo
22

3+
### 0.1.2 (November 17, 2018)
4+
5+
- Provide a version specifically for Internet Explorer 11
6+
37
### 0.1.1 (November 17, 2018)
48

59
- Update documentation

plugins/css-blank-pseudo/README-BROWSER.md

+8
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ const cssBlankPseudo = require('css-blank-pseudo');
3333
cssBlankPseudo(document);
3434
```
3535

36+
To support Internet Explorer 11, include the *browser-legacy* script:
37+
38+
```js
39+
const cssBlankPseudo = require('css-blank-pseudo/legacy');
40+
41+
cssBlankPseudo(document);
42+
```
43+
3644
## Options
3745

3846
[CSS Blank Pseudo] accepts a secondary paramater to configure the attribute or

plugins/css-blank-pseudo/README.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,18 @@ Next, use your transformed CSS with this script:
3333
<script>cssBlankPseudo(document)</script>
3434
```
3535

36-
That’s it. The script is 483 bytes and works in all browsers, as far back as
37-
Internet Explorer 11.
36+
That’s it. The script is 509 bytes and works in all browsers.
37+
38+
---
39+
40+
If you support Internet Explorer 11, use the **browser legacy** script, which
41+
is 671 bytes:
42+
43+
```html
44+
<link rel="stylesheet" href="TRANSFORMED.css">
45+
<script src="https://unpkg.com/css-blank-pseudo/browser-legacy"></script>
46+
<script>cssBlankPseudo(document)</script>
47+
```
3848

3949
## How it works
4050

plugins/css-blank-pseudo/package.json

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "css-blank-pseudo",
3-
"version": "0.1.1",
3+
"version": "0.1.2",
44
"description": "Style form elements when they are empty",
55
"author": "Jonathan Neal <jonathantneal@hotmail.com>",
66
"license": "CC0-1.0",
@@ -14,22 +14,27 @@
1414
},
1515
"files": [
1616
"browser.js",
17+
"browser-legacy.js",
1718
"cli.js",
1819
"index.js",
1920
"index.js.map",
2021
"index.mjs",
2122
"index.mjs.map",
23+
"legacy.js",
24+
"legacy.js.map",
25+
"legacy.mjs",
26+
"legacy.mjs.map",
2227
"postcss.js",
2328
"postcss.js.map",
2429
"postcss.mjs",
2530
"postcss.mjs.map"
2631
],
2732
"scripts": {
2833
"build": "npm run build:browser && npm run build:cli && npm run build:node && npm run build:postcss",
29-
"build:browser": "cross-env NODE_ENV=browser rollup -c .rollup.js --silent",
34+
"build:browser": "cross-env NODE_ENV=browser rollup -c .rollup.js --silent && cross-env NODE_ENV=browser:legacy rollup -c .rollup.js --silent",
3035
"build:cli": "cross-env NODE_ENV=cli rollup -c .rollup.js --silent",
3136
"build:postcss": "cross-env NODE_ENV=postcss rollup -c .rollup.js --silent",
32-
"build:node": "rollup -c .rollup.js --silent",
37+
"build:node": "rollup -c .rollup.js --silent && cross-env NODE_ENV=legacy rollup -c .rollup.js --silent",
3338
"prepublishOnly": "npm build && npm test",
3439
"pretest": "npm run build:postcss",
3540
"pretest:postcss": "npm run build:postcss",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
export default function cssBlankPseudo(document, opts) {
2+
// configuration
3+
const className = Object(opts).className;
4+
const attr = Object(opts).attr || 'blank';
5+
const force = Object(opts).force;
6+
7+
try {
8+
document.querySelector(':blank');
9+
10+
if (!force) {
11+
return;
12+
}
13+
} catch (ignoredError) { /* do nothing and continue */ }
14+
15+
// observe value changes on <input>, <select>, and <textarea>
16+
const window = (document.ownerDocument || document).defaultView;
17+
18+
observeValueOfHTMLElement(window.HTMLInputElement);
19+
observeValueOfHTMLElement(window.HTMLSelectElement);
20+
observeValueOfHTMLElement(window.HTMLTextAreaElement);
21+
observeSelectedOfHTMLElement(window.HTMLOptionElement);
22+
23+
// form control elements selector
24+
const selector = 'INPUT,SELECT,TEXTAREA';
25+
const selectorRegExp = /^(INPUT|SELECT|TEXTAREA)$/;
26+
27+
// conditionally update all form control elements
28+
Array.prototype.forEach.call(
29+
document.querySelectorAll(selector),
30+
node => {
31+
if (node.nodeName === 'SELECT') {
32+
node.addEventListener('change', configureCssBlankAttribute);
33+
} else {
34+
node.addEventListener('input', configureCssBlankAttribute);
35+
}
36+
37+
configureCssBlankAttribute.call(node);
38+
}
39+
);
40+
41+
// conditionally observe added or unobserve removed form control elements
42+
new MutationObserver(mutationsList => {
43+
mutationsList.forEach(mutation => {
44+
Array.prototype.forEach.call(
45+
mutation.addedNodes || [],
46+
node => {
47+
if (node.nodeType === 1 && selectorRegExp.test(node.nodeName)) {
48+
if (node.nodeName === 'SELECT') {
49+
node.addEventListener('change', configureCssBlankAttribute);
50+
} else {
51+
node.addEventListener('input', configureCssBlankAttribute);
52+
}
53+
54+
configureCssBlankAttribute.call(node);
55+
}
56+
}
57+
);
58+
59+
Array.prototype.forEach.call(
60+
mutation.removedNodes || [],
61+
node => {
62+
if (node.nodeType === 1 && selectorRegExp.test(node.nodeName)) {
63+
if (node.nodeName === 'SELECT') {
64+
node.removeEventListener('change', configureCssBlankAttribute);
65+
} else {
66+
node.removeEventListener('input', configureCssBlankAttribute);
67+
}
68+
}
69+
}
70+
);
71+
});
72+
}).observe(document, { childList: true, subtree: true });
73+
74+
// update a form control element’s css-blank attribute
75+
function configureCssBlankAttribute() {
76+
if (this.value || this.nodeName === 'SELECT' && this.options[this.selectedIndex].value) {
77+
if (attr) {
78+
this.removeAttribute(attr);
79+
}
80+
81+
if (className) {
82+
this.classList.remove(className);
83+
}
84+
this.removeAttribute('blank');
85+
} else {
86+
if (attr) {
87+
this.setAttribute('blank', attr);
88+
}
89+
90+
if (className) {
91+
this.classList.add(className);
92+
}
93+
}
94+
}
95+
96+
// observe changes to the "value" property on an HTML Element
97+
function observeValueOfHTMLElement(HTMLElement) {
98+
const descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'value');
99+
const nativeSet = descriptor.set;
100+
101+
descriptor.set = function set(value) { // eslint-disable-line no-unused-vars
102+
nativeSet.apply(this, arguments);
103+
104+
configureCssBlankAttribute.apply(this);
105+
}
106+
107+
Object.defineProperty(HTMLElement.prototype, 'value', descriptor);
108+
}
109+
110+
// observe changes to the "selected" property on an HTML Element
111+
function observeSelectedOfHTMLElement(HTMLElement) {
112+
const descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'selected');
113+
const nativeSet = descriptor.set;
114+
115+
descriptor.set = function set(value) { // eslint-disable-line no-unused-vars
116+
nativeSet.apply(this, arguments);
117+
118+
const event = document.createEvent('Event');
119+
event.initEvent('change', true, true);
120+
this.dispatchEvent(event);
121+
}
122+
123+
Object.defineProperty(HTMLElement.prototype, 'selected', descriptor);
124+
}
125+
}

plugins/css-blank-pseudo/src/browser.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ export default function cssBlankPseudo(document, opts) {
1313
} catch (ignoredError) { /* do nothing and continue */ }
1414

1515
// observe value changes on <input>, <select>, and <textarea>
16-
observeValueOfHTMLElement(HTMLInputElement);
17-
observeValueOfHTMLElement(HTMLSelectElement);
18-
observeValueOfHTMLElement(HTMLTextAreaElement);
16+
const window = (document.ownerDocument || document).defaultView;
17+
18+
observeValueOfHTMLElement(window.HTMLInputElement);
19+
observeValueOfHTMLElement(window.HTMLSelectElement);
20+
observeValueOfHTMLElement(window.HTMLTextAreaElement);
1921

2022
// form control elements selector
2123
const selector = 'input,select,textarea';

0 commit comments

Comments
 (0)