css-blank-pseudo 3.0.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +141 -53
- package/dist/browser-global.js +1 -124
- package/dist/browser-global.js.map +1 -1
- package/dist/browser.cjs +1 -119
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.mjs +1 -119
- package/dist/browser.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.mjs +1 -1
- package/package.json +106 -83
- package/browser.js +0 -125
- package/dist/cli.cjs +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changes to CSS Blank Pseudo
|
|
2
2
|
|
|
3
|
+
### 4.1.0 (July 30, 2022)
|
|
4
|
+
|
|
5
|
+
- Added: `disablePolyfillReadyClass` plugin option to prevent `.js-blank-pseudo` from being added.
|
|
6
|
+
|
|
7
|
+
### 4.0.0 (July 8, 2022)
|
|
8
|
+
|
|
9
|
+
- Updated: The polyfill now only attaches a single listener to the body so it's
|
|
10
|
+
more efficient and also does less work at the MutationObserver handler.
|
|
11
|
+
- Breaking: removed old CDN urls
|
|
12
|
+
- Breaking: removed old CLI
|
|
13
|
+
- Fix case insensitive matching.
|
|
14
|
+
|
|
15
|
+
#### How to migrate:
|
|
16
|
+
|
|
17
|
+
- If you use a CDN url, please update it.
|
|
18
|
+
- Re-build your CSS with the new version of the library.
|
|
19
|
+
|
|
20
|
+
```diff
|
|
21
|
+
- <script src="https://unpkg.com/css-blank-pseudo/browser"></script>
|
|
22
|
+
- <script src="https://unpkg.com/css-blank-pseudo/browser.min"></script>
|
|
23
|
+
+ <script src="https://unpkg.com/css-blank-pseudo/dist/browser-global.js"></script>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```diff
|
|
27
|
+
- cssBlankPseudo(document)
|
|
28
|
+
+ cssBlankPseudoInit()
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```diff
|
|
32
|
+
- cssBlankPseudo({
|
|
33
|
+
- attr: false,
|
|
34
|
+
- className: 'blank'
|
|
35
|
+
- })
|
|
36
|
+
+ cssBlankPseudoInit({
|
|
37
|
+
+ replaceWith: '.blank'
|
|
38
|
+
+ })
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 3.0.3 (February 5, 2022)
|
|
42
|
+
|
|
43
|
+
- Rebuild of browser polyfills
|
|
44
|
+
|
|
3
45
|
### 3.0.2 (January 2, 2022)
|
|
4
46
|
|
|
5
47
|
- Removed Sourcemaps from package tarball.
|
package/README.md
CHANGED
|
@@ -1,105 +1,193 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PostCSS Blank Pseudo [<img src="https://postcss.github.io/postcss/logo.svg" alt="PostCSS Logo" width="90" height="90" align="right">][postcss]
|
|
2
2
|
|
|
3
|
-
[
|
|
4
|
-
[![Support Chat][git-img]][git-url]
|
|
3
|
+
[<img alt="npm version" src="https://img.shields.io/npm/v/css-blank-pseudo.svg" height="20">][npm-url] [<img alt="CSS Standard Status" src="https://cssdb.org/images/badges/blank-pseudo-class.svg" height="20">][css-url] [<img alt="Build Status" src="https://github.com/csstools/postcss-plugins/workflows/test/badge.svg" height="20">][cli-url] [<img alt="Discord" src="https://shields.io/badge/Discord-5865F2?logo=discord&logoColor=white">][discord]
|
|
5
4
|
|
|
6
|
-
[
|
|
5
|
+
[PostCSS Blank Pseudo] lets you style form elements when they are empty, following
|
|
7
6
|
the [Selectors Level 4] specification.
|
|
8
7
|
|
|
9
|
-
```
|
|
10
|
-
input {
|
|
11
|
-
|
|
8
|
+
```pcss
|
|
9
|
+
input:blank {
|
|
10
|
+
background-color: yellow;
|
|
12
11
|
}
|
|
13
12
|
|
|
13
|
+
/* becomes */
|
|
14
|
+
|
|
15
|
+
input[blank].js-blank-pseudo, .js-blank-pseudo input[blank] {
|
|
16
|
+
background-color: yellow;
|
|
17
|
+
}
|
|
14
18
|
input:blank {
|
|
15
|
-
|
|
19
|
+
background-color: yellow;
|
|
16
20
|
}
|
|
17
21
|
```
|
|
18
22
|
|
|
19
23
|
## Usage
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
Add [PostCSS Blank Pseudo] to your project:
|
|
22
26
|
|
|
23
27
|
```bash
|
|
24
|
-
|
|
28
|
+
npm install postcss css-blank-pseudo --save-dev
|
|
25
29
|
```
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
Use it as a [PostCSS] plugin:
|
|
28
32
|
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
```js
|
|
34
|
+
const postcss = require('postcss');
|
|
35
|
+
const postcssBlankPseudo = require('css-blank-pseudo');
|
|
36
|
+
|
|
37
|
+
postcss([
|
|
38
|
+
postcssBlankPseudo(/* pluginOptions */)
|
|
39
|
+
]).process(YOUR_CSS /*, processOptions */);
|
|
33
40
|
```
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
[PostCSS Blank Pseudo] runs in all Node environments, with special
|
|
43
|
+
instructions for:
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
| [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Create React App](INSTALL.md#create-react-app) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) |
|
|
46
|
+
| --- | --- | --- | --- | --- | --- |
|
|
40
47
|
|
|
41
|
-
|
|
48
|
+
## Options
|
|
42
49
|
|
|
43
|
-
|
|
50
|
+
### preserve
|
|
44
51
|
|
|
45
|
-
The
|
|
46
|
-
|
|
52
|
+
The `preserve` option determines whether the original notation
|
|
53
|
+
is preserved. By default, it is preserved.
|
|
47
54
|
|
|
48
|
-
```
|
|
55
|
+
```js
|
|
56
|
+
postcssBlankPseudo({ preserve: false })
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```pcss
|
|
49
60
|
input:blank {
|
|
50
|
-
|
|
61
|
+
background-color: yellow;
|
|
51
62
|
}
|
|
52
63
|
|
|
53
64
|
/* becomes */
|
|
54
65
|
|
|
55
|
-
input[blank] {
|
|
56
|
-
|
|
66
|
+
input[blank].js-blank-pseudo, .js-blank-pseudo input[blank] {
|
|
67
|
+
background-color: yellow;
|
|
57
68
|
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### replaceWith
|
|
72
|
+
|
|
73
|
+
The `replaceWith` option determines the selector to use when replacing
|
|
74
|
+
the `:blank` pseudo. By default is `[blank]`
|
|
58
75
|
|
|
76
|
+
```js
|
|
77
|
+
postcssBlankPseudo({ replaceWith: '.css-blank' })
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```pcss
|
|
59
81
|
input:blank {
|
|
60
|
-
|
|
82
|
+
background-color: yellow;
|
|
61
83
|
}
|
|
62
|
-
```
|
|
63
84
|
|
|
64
|
-
|
|
65
|
-
elements otherwise matching `:blank` natively.
|
|
85
|
+
/* becomes */
|
|
66
86
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
87
|
+
.foo {
|
|
88
|
+
color: blue;
|
|
89
|
+
color: red;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.baz {
|
|
93
|
+
color: green;
|
|
94
|
+
}
|
|
70
95
|
```
|
|
71
96
|
|
|
72
|
-
|
|
97
|
+
Note that changing this option implies that it needs to be passed to the
|
|
98
|
+
browser polyfill as well.
|
|
99
|
+
|
|
100
|
+
### disablePolyfillReadyClass
|
|
101
|
+
|
|
102
|
+
The `disablePolyfillReadyClass` option determines if selectors are prefixed with an indicator class.
|
|
103
|
+
This class is only set on your document if the polyfill loads and is needed.
|
|
104
|
+
|
|
105
|
+
By default this option is `false`.
|
|
106
|
+
Set this to `true` to prevent the class from being added.
|
|
73
107
|
|
|
74
|
-
|
|
108
|
+
```js
|
|
109
|
+
postcssBlankPseudo({ disablePolyfillReadyClass: true })
|
|
110
|
+
```
|
|
75
111
|
|
|
76
|
-
```
|
|
77
|
-
input:
|
|
78
|
-
|
|
112
|
+
```pcss
|
|
113
|
+
input:blank {
|
|
114
|
+
background-color: yellow;
|
|
79
115
|
}
|
|
80
116
|
|
|
81
117
|
/* becomes */
|
|
82
118
|
|
|
83
|
-
input
|
|
84
|
-
|
|
119
|
+
input[blank], input[blank] {
|
|
120
|
+
background-color: yellow;
|
|
85
121
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
background-color: yellow;
|
|
122
|
+
input:blank {
|
|
123
|
+
background-color: yellow;
|
|
89
124
|
}
|
|
90
125
|
```
|
|
91
126
|
|
|
92
|
-
|
|
93
|
-
|
|
127
|
+
## Browser
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
import cssBlankPseudoInit from 'css-blank-pseudo/browser';
|
|
131
|
+
|
|
132
|
+
cssBlankPseudoInit();
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
or
|
|
136
|
+
|
|
137
|
+
```html
|
|
138
|
+
<!-- When using a CDN url you will have to manually update the version number -->
|
|
139
|
+
<script src="https://unpkg.com/css-blank-pseudo@4.1.0/dist/browser-global.js"></script>
|
|
140
|
+
<script>cssBlankPseudoInit()</script>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
[PostCSS Blank Pseudo] works in all major browsers, including Safari 6+ and
|
|
144
|
+
Internet Explorer 9+ without any additional polyfills.
|
|
145
|
+
|
|
146
|
+
This plugin conditionally uses `MutationObserver` to ensure recently inserted
|
|
147
|
+
inputs get correct styling upon insertion. If you intend to rely on that
|
|
148
|
+
behaviour for browsers that do not support `MutationObserver`, you have two
|
|
149
|
+
options:
|
|
150
|
+
|
|
151
|
+
1. Polyfill `MutationObserver`. As long as it runs before `cssBlankPseudoInit`,
|
|
152
|
+
the polyfill will work.
|
|
153
|
+
2. If you don't want to polyfill `MutationObserver` you can also manually fire
|
|
154
|
+
a `change` event upon insertion so they're automatically inspected by the
|
|
155
|
+
polyfill.
|
|
156
|
+
|
|
157
|
+
### Browser Usage
|
|
158
|
+
|
|
159
|
+
#### force
|
|
160
|
+
|
|
161
|
+
The `force` option determines whether the library runs even if the browser
|
|
162
|
+
supports the selector or not. By default, it won't run if the browser does
|
|
163
|
+
support the selector.
|
|
94
164
|
|
|
95
|
-
|
|
165
|
+
```js
|
|
166
|
+
cssBlankPseudoInit({ force: true });
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### replaceWith
|
|
170
|
+
|
|
171
|
+
Similar to the option for the PostCSS Plugin, `replaceWith` determines the
|
|
172
|
+
attribute or class to apply to an element when it's considered to be `:blank`.
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
cssBlankPseudoInit({ replaceWith: '.css-blank' });
|
|
176
|
+
```
|
|
96
177
|
|
|
178
|
+
This option should be used if it was changed at PostCSS configuration level.
|
|
179
|
+
Please note that using a class, leverages `classList` under the hood which
|
|
180
|
+
might not be supported on some old browsers such as IE9, so you may need
|
|
181
|
+
to polyfill `classList` in those cases.
|
|
97
182
|
|
|
98
|
-
[
|
|
99
|
-
[
|
|
100
|
-
[
|
|
183
|
+
[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test
|
|
184
|
+
[css-url]: https://cssdb.org/#blank-pseudo-class
|
|
185
|
+
[discord]: https://discord.gg/bUadyRwkJS
|
|
101
186
|
[npm-url]: https://www.npmjs.com/package/css-blank-pseudo
|
|
102
187
|
|
|
103
|
-
[
|
|
104
|
-
[PostCSS
|
|
105
|
-
[
|
|
188
|
+
[Gulp PostCSS]: https://github.com/postcss/gulp-postcss
|
|
189
|
+
[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss
|
|
190
|
+
[PostCSS]: https://github.com/postcss/postcss
|
|
191
|
+
[PostCSS Loader]: https://github.com/postcss/postcss-loader
|
|
192
|
+
[PostCSS Blank Pseudo]: https://github.com/csstools/postcss-plugins/tree/main/plugins/css-blank-pseudo
|
|
193
|
+
[Selectors Level 4]: https://www.w3.org/TR/selectors-4/#blank
|
package/dist/browser-global.js
CHANGED
|
@@ -1,125 +1,2 @@
|
|
|
1
|
-
(function () {
|
|
2
|
-
|
|
3
|
-
/* global MutationObserver */
|
|
4
|
-
function cssBlankPseudo(document, opts) {
|
|
5
|
-
// configuration
|
|
6
|
-
var className = Object(opts).className;
|
|
7
|
-
var attr = Object(opts).attr || 'blank';
|
|
8
|
-
var force = Object(opts).force;
|
|
9
|
-
|
|
10
|
-
try {
|
|
11
|
-
document.querySelector(':blank');
|
|
12
|
-
|
|
13
|
-
if (!force) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
} catch (ignoredError) {
|
|
17
|
-
/* do nothing and continue */
|
|
18
|
-
} // observe value changes on <input>, <select>, and <textarea>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
var window = (document.ownerDocument || document).defaultView;
|
|
22
|
-
observeValueOfHTMLElement(window.HTMLInputElement);
|
|
23
|
-
observeValueOfHTMLElement(window.HTMLSelectElement);
|
|
24
|
-
observeValueOfHTMLElement(window.HTMLTextAreaElement);
|
|
25
|
-
observeSelectedOfHTMLElement(window.HTMLOptionElement); // form control elements selector
|
|
26
|
-
|
|
27
|
-
var selector = 'INPUT,SELECT,TEXTAREA';
|
|
28
|
-
var selectorRegExp = /^(INPUT|SELECT|TEXTAREA)$/; // conditionally update all form control elements
|
|
29
|
-
|
|
30
|
-
Array.prototype.forEach.call(document.querySelectorAll(selector), function (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
|
-
}); // conditionally observe added or unobserve removed form control elements
|
|
39
|
-
|
|
40
|
-
new MutationObserver(function (mutationsList) {
|
|
41
|
-
mutationsList.forEach(function (mutation) {
|
|
42
|
-
Array.prototype.forEach.call(mutation.addedNodes || [], function (node) {
|
|
43
|
-
if (node.nodeType === 1 && selectorRegExp.test(node.nodeName)) {
|
|
44
|
-
if (node.nodeName === 'SELECT') {
|
|
45
|
-
node.addEventListener('change', configureCssBlankAttribute);
|
|
46
|
-
} else {
|
|
47
|
-
node.addEventListener('input', configureCssBlankAttribute);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
configureCssBlankAttribute.call(node);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
Array.prototype.forEach.call(mutation.removedNodes || [], function (node) {
|
|
54
|
-
if (node.nodeType === 1 && selectorRegExp.test(node.nodeName)) {
|
|
55
|
-
if (node.nodeName === 'SELECT') {
|
|
56
|
-
node.removeEventListener('change', configureCssBlankAttribute);
|
|
57
|
-
} else {
|
|
58
|
-
node.removeEventListener('input', configureCssBlankAttribute);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
}).observe(document, {
|
|
64
|
-
childList: true,
|
|
65
|
-
subtree: true
|
|
66
|
-
}); // update a form control element’s css-blank attribute
|
|
67
|
-
|
|
68
|
-
function configureCssBlankAttribute() {
|
|
69
|
-
if (this.value || this.nodeName === 'SELECT' && this.options[this.selectedIndex].value) {
|
|
70
|
-
if (attr) {
|
|
71
|
-
this.removeAttribute(attr);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (className) {
|
|
75
|
-
this.classList.remove(className);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
this.removeAttribute('blank');
|
|
79
|
-
} else {
|
|
80
|
-
if (attr) {
|
|
81
|
-
this.setAttribute('blank', attr);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (className) {
|
|
85
|
-
this.classList.add(className);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
} // observe changes to the "value" property on an HTML Element
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
function observeValueOfHTMLElement(HTMLElement) {
|
|
92
|
-
var descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'value');
|
|
93
|
-
var nativeSet = descriptor.set;
|
|
94
|
-
|
|
95
|
-
descriptor.set = function set(value) {
|
|
96
|
-
// eslint-disable-line no-unused-vars
|
|
97
|
-
nativeSet.apply(this, arguments);
|
|
98
|
-
configureCssBlankAttribute.apply(this);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
Object.defineProperty(HTMLElement.prototype, 'value', descriptor);
|
|
102
|
-
} // observe changes to the "selected" property on an HTML Element
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
function observeSelectedOfHTMLElement(HTMLElement) {
|
|
106
|
-
var descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'selected');
|
|
107
|
-
var nativeSet = descriptor.set;
|
|
108
|
-
|
|
109
|
-
descriptor.set = function set(value) {
|
|
110
|
-
// eslint-disable-line no-unused-vars
|
|
111
|
-
nativeSet.apply(this, arguments);
|
|
112
|
-
var event = document.createEvent('Event');
|
|
113
|
-
event.initEvent('change', true, true);
|
|
114
|
-
this.dispatchEvent(event);
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
Object.defineProperty(HTMLElement.prototype, 'selected', descriptor);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/* global self */
|
|
122
|
-
self.cssBlankPseudo = cssBlankPseudo;
|
|
123
|
-
|
|
124
|
-
})();
|
|
1
|
+
!function(){var e=[" ",">","~",":","+","@","#","(",")"];var t="js-blank-pseudo";function n(e){return"INPUT"===e.nodeName||"SELECT"===e.nodeName||"TEXTAREA"===e.nodeName}function r(e){var t;return"function"==typeof Event?t=new Event(e,{bubbles:!0}):(t=document.createEvent("Event")).initEvent(e,!0,!1),t}function o(e,t){var n=Object.getOwnPropertyDescriptor(e.prototype,"value"),r=n.set;n.set=function(){r.apply(this,arguments),t({target:this})},Object.defineProperty(e.prototype,"value",n)}self.cssBlankPseudoInit=function(c){var i={force:!1,replaceWith:"[blank]"};if(void 0!==c&&"force"in c&&(i.force=c.force),void 0!==c&&"replaceWith"in c&&(i.replaceWith=c.replaceWith),!function(t){for(var n=!0,r=0,o=e.length;r<o&&n;r++)t.indexOf(e[r])>-1&&(n=!1);return n}(i.replaceWith))throw new Error(i.replaceWith+" is not a valid replacement since it can't be applied to single elements.");try{if(document.querySelector(":blank"),!i.force)return}catch(e){}var a,d,l,u,s,f,p,v=("."===(a=i.replaceWith)[0]?(d=a.slice(1),l=function(e){return e.classList.remove(d)},u=function(e){return e.classList.add(d)}):(d=a.slice(1,-1),l=function(e){return e.removeAttribute(d,"")},u=function(e){return e.setAttribute(d,"")}),function(e){var t=e.target;n(t)&&(("SELECT"===t.nodeName?t.options[t.selectedIndex].value:t.value)?l(t):u(t))}),m=function(){document.body&&(document.body.addEventListener("change",v),document.body.addEventListener("input",v))},E=function(){Array.prototype.forEach.call(document.querySelectorAll("input, select, textarea"),(function(e){v({target:e})}))};if(document.body?m():window.addEventListener("load",m),-1===document.documentElement.className.indexOf(t)&&(document.documentElement.className+=" js-blank-pseudo"),o(self.HTMLInputElement,v),o(self.HTMLSelectElement,v),o(self.HTMLTextAreaElement,v),s=self.HTMLOptionElement,f=Object.getOwnPropertyDescriptor(s.prototype,"selected"),p=f.set,f.set=function(e){p.apply(this,arguments);var t=r("change");this.parentElement.dispatchEvent(t)},Object.defineProperty(s.prototype,"selected",f),E(),void 0!==self.MutationObserver)new MutationObserver((function(e){e.forEach((function(e){Array.prototype.forEach.call(e.addedNodes||[],(function(e){1===e.nodeType&&n(e)&&v({target:e})}))}))})).observe(document,{childList:!0,subtree:!0});else{var y=function(){return E()};window.addEventListener("load",y),window.addEventListener("DOMContentLoaded",y)}}}();
|
|
125
2
|
//# sourceMappingURL=browser-global.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-global.js","sources":["../src/browser.js","../src/browser-global.js"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"browser-global.js","sources":["../src/is-valid-replacement.mjs","../src/browser.js","../src/browser-global.js"],"sourcesContent":["const INVALID_SELECTOR_CHAR = [\n\t' ', // Can't use child selector\n\t'>', // Can't use direct child selector\n\t'~', // Can't use sibling selector\n\t':', // Can't use pseudo selector\n\t'+', // Can't use adjacent selector\n\t'@', // Can't use at\n\t'#', // Can't use id selector\n\t'(', // Can't use parenthesis\n\t')', // Can't use parenthesis\n];\n\nexport default function isValidReplacement(selector) {\n\tlet isValid = true;\n\n\t// Purposely archaic so it's interoperable in old browsers\n\tfor (let i = 0, length = INVALID_SELECTOR_CHAR.length; i < length && isValid; i++) {\n\t\tif (selector.indexOf(INVALID_SELECTOR_CHAR[i]) > -1) {\n\t\t\tisValid = false;\n\t\t}\n\t}\n\n\treturn isValid;\n}\n","/* global document,window,self,MutationObserver */\nimport isValidReplacement from './is-valid-replacement.mjs';\n\nconst CSS_CLASS_LOADED = 'js-blank-pseudo';\n\n// form control elements selector\nfunction isFormControlElement(element) {\n\tif (element.nodeName === 'INPUT' || element.nodeName === 'SELECT' || element.nodeName === 'TEXTAREA') {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nfunction createNewEvent(eventName) {\n\tlet event;\n\n\tif (typeof(Event) === 'function') {\n\t\tevent = new Event(eventName, { bubbles: true });\n\t} else {\n\t\tevent = document.createEvent('Event');\n\t\tevent.initEvent(eventName, true, false);\n\t}\n\n\treturn event;\n}\n\nfunction generateHandler(replaceWith) {\n\tlet selector;\n\tlet remove;\n\tlet add;\n\n\tif (replaceWith[0] === '.') {\n\t\tselector = replaceWith.slice(1);\n\t\tremove = (el) => el.classList.remove(selector);\n\t\tadd = (el) => el.classList.add(selector);\n\t} else {\n\t\t// A bit naive\n\t\tselector = replaceWith.slice(1, -1);\n\t\tremove = (el) => el.removeAttribute(selector, '');\n\t\tadd = (el) => el.setAttribute(selector, '');\n\t}\n\n\treturn function handleInputOrChangeEvent(event) {\n\t\tconst element = event.target;\n\t\tif (!isFormControlElement(element)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isSelect = element.nodeName === 'SELECT';\n\t\tconst hasValue = isSelect\n\t\t\t? !!element.options[element.selectedIndex].value\n\t\t\t: !!element.value;\n\n\t\tif (hasValue) {\n\t\t\tremove(element);\n\t\t} else {\n\t\t\tadd(element);\n\t\t}\n\t};\n}\n\n// observe changes to the \"selected\" property on an HTML Element\nfunction observeSelectedOfHTMLElement(HTMLElement) {\n\tconst descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'selected');\n\tconst nativeSet = descriptor.set;\n\n\tdescriptor.set = function set(value) { // eslint-disable-line no-unused-vars\n\t\tnativeSet.apply(this, arguments);\n\n\t\tconst event = createNewEvent('change');\n\t\tthis.parentElement.dispatchEvent(event);\n\t};\n\n\tObject.defineProperty(HTMLElement.prototype, 'selected', descriptor);\n}\n\n// observe changes to the \"value\" property on an HTML Element\nfunction observeValueOfHTMLElement(HTMLElement, handler) {\n\tconst descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'value');\n\tconst nativeSet = descriptor.set;\n\n\tdescriptor.set = function set() {\n\t\tnativeSet.apply(this, arguments);\n\t\thandler({ target: this });\n\t};\n\n\tObject.defineProperty(HTMLElement.prototype, 'value', descriptor);\n}\n\nexport default function cssBlankPseudoInit(opts) {\n\t// configuration\n\tconst options = {\n\t\tforce: false,\n\t\treplaceWith: '[blank]',\n\t};\n\n\tif (typeof opts !== 'undefined' && 'force' in opts) {\n\t\toptions.force = opts.force;\n\t}\n\n\tif (typeof opts !== 'undefined' && 'replaceWith' in opts) {\n\t\toptions.replaceWith = opts.replaceWith;\n\t}\n\n\tif (!isValidReplacement(options.replaceWith)) {\n\t\tthrow new Error(`${options.replaceWith} is not a valid replacement since it can't be applied to single elements.`);\n\t}\n\n\ttry {\n\t\tdocument.querySelector(':blank');\n\n\t\tif (!options.force) {\n\t\t\treturn;\n\t\t}\n\t} catch (ignoredError) { /* do nothing and continue */ }\n\n\tconst handler = generateHandler(options.replaceWith);\n\tconst bindEvents = () => {\n\t\tif (document.body) {\n\t\t\tdocument.body.addEventListener('change', handler);\n\t\t\tdocument.body.addEventListener('input', handler);\n\t\t}\n\t};\n\tconst updateAllCandidates = () => {\n\t\tArray.prototype.forEach.call(\n\t\t\tdocument.querySelectorAll('input, select, textarea'),\n\t\t\tnode => {\n\t\t\t\thandler({ target: node });\n\t\t\t},\n\t\t);\n\t};\n\n\tif (document.body) {\n\t\tbindEvents();\n\t} else {\n\t\twindow.addEventListener('load', bindEvents);\n\t}\n\n\tif (document.documentElement.className.indexOf(CSS_CLASS_LOADED) === -1) {\n\t\tdocument.documentElement.className += ` ${CSS_CLASS_LOADED}`;\n\t}\n\n\tobserveValueOfHTMLElement(self.HTMLInputElement, handler);\n\tobserveValueOfHTMLElement(self.HTMLSelectElement, handler);\n\tobserveValueOfHTMLElement(self.HTMLTextAreaElement, handler);\n\tobserveSelectedOfHTMLElement(self.HTMLOptionElement, handler);\n\n\t// conditionally update all form control elements\n\tupdateAllCandidates();\n\n\tif (typeof self.MutationObserver !== 'undefined') {\n\t\t// conditionally observe added or unobserve removed form control elements\n\t\tnew MutationObserver(mutationsList => {\n\t\t\tmutationsList.forEach(mutation => {\n\t\t\t\tArray.prototype.forEach.call(\n\t\t\t\t\tmutation.addedNodes || [],\n\t\t\t\t\tnode => {\n\t\t\t\t\t\tif (node.nodeType === 1 && isFormControlElement(node)) {\n\t\t\t\t\t\t\thandler({ target: node });\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t});\n\t\t}).observe(document, { childList: true, subtree: true });\n\t} else {\n\t\tconst handleOnLoad = () => updateAllCandidates();\n\n\t\twindow.addEventListener('load', handleOnLoad);\n\t\twindow.addEventListener('DOMContentLoaded', handleOnLoad);\n\t}\n}\n","/* global self */\nimport { default as cssBlankPseudoInit } from './browser';\nself.cssBlankPseudoInit = cssBlankPseudoInit;\n"],"names":["INVALID_SELECTOR_CHAR","CSS_CLASS_LOADED","isFormControlElement","element","nodeName","createNewEvent","eventName","event","Event","bubbles","document","createEvent","initEvent","observeValueOfHTMLElement","HTMLElement","handler","descriptor","Object","getOwnPropertyDescriptor","prototype","nativeSet","set","apply","this","arguments","target","defineProperty","self","cssBlankPseudoInit","opts","options","force","replaceWith","selector","isValid","i","length","indexOf","isValidReplacement","Error","querySelector","ignoredError","remove","add","slice","el","classList","removeAttribute","setAttribute","selectedIndex","value","bindEvents","body","addEventListener","updateAllCandidates","Array","forEach","call","querySelectorAll","node","window","documentElement","className","HTMLInputElement","HTMLSelectElement","HTMLTextAreaElement","HTMLOptionElement","parentElement","dispatchEvent","MutationObserver","mutationsList","mutation","addedNodes","nodeType","observe","childList","subtree","handleOnLoad"],"mappings":"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"}
|
package/dist/browser.cjs
CHANGED
|
@@ -1,120 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
function cssBlankPseudo(document, opts) {
|
|
3
|
-
// configuration
|
|
4
|
-
var className = Object(opts).className;
|
|
5
|
-
var attr = Object(opts).attr || 'blank';
|
|
6
|
-
var force = Object(opts).force;
|
|
7
|
-
|
|
8
|
-
try {
|
|
9
|
-
document.querySelector(':blank');
|
|
10
|
-
|
|
11
|
-
if (!force) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
} catch (ignoredError) {
|
|
15
|
-
/* do nothing and continue */
|
|
16
|
-
} // observe value changes on <input>, <select>, and <textarea>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
var window = (document.ownerDocument || document).defaultView;
|
|
20
|
-
observeValueOfHTMLElement(window.HTMLInputElement);
|
|
21
|
-
observeValueOfHTMLElement(window.HTMLSelectElement);
|
|
22
|
-
observeValueOfHTMLElement(window.HTMLTextAreaElement);
|
|
23
|
-
observeSelectedOfHTMLElement(window.HTMLOptionElement); // form control elements selector
|
|
24
|
-
|
|
25
|
-
var selector = 'INPUT,SELECT,TEXTAREA';
|
|
26
|
-
var selectorRegExp = /^(INPUT|SELECT|TEXTAREA)$/; // conditionally update all form control elements
|
|
27
|
-
|
|
28
|
-
Array.prototype.forEach.call(document.querySelectorAll(selector), function (node) {
|
|
29
|
-
if (node.nodeName === 'SELECT') {
|
|
30
|
-
node.addEventListener('change', configureCssBlankAttribute);
|
|
31
|
-
} else {
|
|
32
|
-
node.addEventListener('input', configureCssBlankAttribute);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
configureCssBlankAttribute.call(node);
|
|
36
|
-
}); // conditionally observe added or unobserve removed form control elements
|
|
37
|
-
|
|
38
|
-
new MutationObserver(function (mutationsList) {
|
|
39
|
-
mutationsList.forEach(function (mutation) {
|
|
40
|
-
Array.prototype.forEach.call(mutation.addedNodes || [], function (node) {
|
|
41
|
-
if (node.nodeType === 1 && selectorRegExp.test(node.nodeName)) {
|
|
42
|
-
if (node.nodeName === 'SELECT') {
|
|
43
|
-
node.addEventListener('change', configureCssBlankAttribute);
|
|
44
|
-
} else {
|
|
45
|
-
node.addEventListener('input', configureCssBlankAttribute);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
configureCssBlankAttribute.call(node);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
Array.prototype.forEach.call(mutation.removedNodes || [], function (node) {
|
|
52
|
-
if (node.nodeType === 1 && selectorRegExp.test(node.nodeName)) {
|
|
53
|
-
if (node.nodeName === 'SELECT') {
|
|
54
|
-
node.removeEventListener('change', configureCssBlankAttribute);
|
|
55
|
-
} else {
|
|
56
|
-
node.removeEventListener('input', configureCssBlankAttribute);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
}).observe(document, {
|
|
62
|
-
childList: true,
|
|
63
|
-
subtree: true
|
|
64
|
-
}); // update a form control element’s css-blank attribute
|
|
65
|
-
|
|
66
|
-
function configureCssBlankAttribute() {
|
|
67
|
-
if (this.value || this.nodeName === 'SELECT' && this.options[this.selectedIndex].value) {
|
|
68
|
-
if (attr) {
|
|
69
|
-
this.removeAttribute(attr);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (className) {
|
|
73
|
-
this.classList.remove(className);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
this.removeAttribute('blank');
|
|
77
|
-
} else {
|
|
78
|
-
if (attr) {
|
|
79
|
-
this.setAttribute('blank', attr);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (className) {
|
|
83
|
-
this.classList.add(className);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
} // observe changes to the "value" property on an HTML Element
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
function observeValueOfHTMLElement(HTMLElement) {
|
|
90
|
-
var descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'value');
|
|
91
|
-
var nativeSet = descriptor.set;
|
|
92
|
-
|
|
93
|
-
descriptor.set = function set(value) {
|
|
94
|
-
// eslint-disable-line no-unused-vars
|
|
95
|
-
nativeSet.apply(this, arguments);
|
|
96
|
-
configureCssBlankAttribute.apply(this);
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
Object.defineProperty(HTMLElement.prototype, 'value', descriptor);
|
|
100
|
-
} // observe changes to the "selected" property on an HTML Element
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
function observeSelectedOfHTMLElement(HTMLElement) {
|
|
104
|
-
var descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'selected');
|
|
105
|
-
var nativeSet = descriptor.set;
|
|
106
|
-
|
|
107
|
-
descriptor.set = function set(value) {
|
|
108
|
-
// eslint-disable-line no-unused-vars
|
|
109
|
-
nativeSet.apply(this, arguments);
|
|
110
|
-
var event = document.createEvent('Event');
|
|
111
|
-
event.initEvent('change', true, true);
|
|
112
|
-
this.dispatchEvent(event);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
Object.defineProperty(HTMLElement.prototype, 'selected', descriptor);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
module.exports = cssBlankPseudo;
|
|
1
|
+
var e=[" ",">","~",":","+","@","#","(",")"];function t(e){return"INPUT"===e.nodeName||"SELECT"===e.nodeName||"TEXTAREA"===e.nodeName}function n(e){var t;return"function"==typeof Event?t=new Event(e,{bubbles:!0}):(t=document.createEvent("Event")).initEvent(e,!0,!1),t}function r(e,t){var n=Object.getOwnPropertyDescriptor(e.prototype,"value"),r=n.set;n.set=function(){r.apply(this,arguments),t({target:this})},Object.defineProperty(e.prototype,"value",n)}module.exports=function(o){var c={force:!1,replaceWith:"[blank]"};if(void 0!==o&&"force"in o&&(c.force=o.force),void 0!==o&&"replaceWith"in o&&(c.replaceWith=o.replaceWith),!function(t){for(var n=!0,r=0,o=e.length;r<o&&n;r++)t.indexOf(e[r])>-1&&(n=!1);return n}(c.replaceWith))throw new Error(c.replaceWith+" is not a valid replacement since it can't be applied to single elements.");try{if(document.querySelector(":blank"),!c.force)return}catch(e){}var i,a,d,l,u,s,p,f=("."===(i=c.replaceWith)[0]?(a=i.slice(1),d=function(e){return e.classList.remove(a)},l=function(e){return e.classList.add(a)}):(a=i.slice(1,-1),d=function(e){return e.removeAttribute(a,"")},l=function(e){return e.setAttribute(a,"")}),function(e){var n=e.target;t(n)&&(("SELECT"===n.nodeName?n.options[n.selectedIndex].value:n.value)?d(n):l(n))}),v=function(){document.body&&(document.body.addEventListener("change",f),document.body.addEventListener("input",f))},m=function(){Array.prototype.forEach.call(document.querySelectorAll("input, select, textarea"),(function(e){f({target:e})}))};if(document.body?v():window.addEventListener("load",v),-1===document.documentElement.className.indexOf("js-blank-pseudo")&&(document.documentElement.className+=" js-blank-pseudo"),r(self.HTMLInputElement,f),r(self.HTMLSelectElement,f),r(self.HTMLTextAreaElement,f),u=self.HTMLOptionElement,s=Object.getOwnPropertyDescriptor(u.prototype,"selected"),p=s.set,s.set=function(e){p.apply(this,arguments);var t=n("change");this.parentElement.dispatchEvent(t)},Object.defineProperty(u.prototype,"selected",s),m(),void 0!==self.MutationObserver)new MutationObserver((function(e){e.forEach((function(e){Array.prototype.forEach.call(e.addedNodes||[],(function(e){1===e.nodeType&&t(e)&&f({target:e})}))}))})).observe(document,{childList:!0,subtree:!0});else{var E=function(){return m()};window.addEventListener("load",E),window.addEventListener("DOMContentLoaded",E)}};
|
|
120
2
|
//# sourceMappingURL=browser.cjs.map
|