Skip to content

Commit

Permalink
Add x-show
Browse files Browse the repository at this point in the history
  • Loading branch information
calebporzio committed Dec 4, 2019
1 parent 657fea0 commit 526ddc1
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 14 deletions.
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Think of it like [Tailwind](https://tailwindcss.com/) for JavaScript.
## Install
Add the following script to the end of your `<head>` section.
```html
<script src="https://cdn.jsdelivr.net/gh/calebporzio/project-x@v0.3.0/dist/project-x.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/gh/calebporzio/project-x@v0.4.0/dist/project-x.min.js" defer></script>
```

## Use
Expand All @@ -24,8 +24,7 @@ Add the following script to the end of your `<head>` section.
<button x-on:click="open = true">Open Dropdown</button>

<ul
class="hidden"
x-bind:class="{ 'hidden': ! open }"
x-show="open"
x-on:click.away="open = false"
>
Dropdown Body
Expand All @@ -39,8 +38,8 @@ Add the following script to the end of your `<head>` section.
<button x-bind:class="{ 'active': tab === 'foo' }" x-on:click="tab = 'foo'">Foo</button>
<button x-bind:class="{ 'active': tab === 'bar' }" x-on:click="tab = 'bar'">Bar</button>

<div class="hidden" x-bind:class="{ 'hidden': tab !== 'foo' }">Tab Foo</div>
<div class="hidden" x-bind:class="{ 'hidden': tab !== 'bar' }">Tab Bar</div>
<div x-show="tab === 'foo'">Tab Foo</div>
<div x-show="tab === 'bar'">Tab Bar</div>
</div>
```

Expand All @@ -51,6 +50,7 @@ There are 7 directives available to you:
| Directive
| --- |
| [`x-data`](#x-data) |
| [`x-show`](#x-show) |
| [`x-bind`](#x-bind) |
| [`x-on`](#x-on) |
| [`x-model`](#x-model) |
Expand Down Expand Up @@ -105,6 +105,15 @@ You can also mix-in multiple data objects using object destructuring:

---

### `x-show`
**Example:** `<div x-show="open"></div>`

**Structure:** `<div x-show="[expression]"></div>`

`x-show` toggles the `display: none;` style on the element depending if the expression resolves to `true` or `false`.

---

### `x-bind`
**Example:** `<input x-bind:type="inputType">`

Expand Down
4 changes: 2 additions & 2 deletions dist/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"/project-x.js": "/project-x.js?id=bd450a04a07206020f63",
"/project-x.min.js": "/project-x.min.js?id=aca2ba4b017885bdd4a5"
"/project-x.js": "/project-x.js?id=a11dbcb0d5ba1786312d",
"/project-x.min.js": "/project-x.min.js?id=d07f1a5dd55fedec39a4"
}
38 changes: 36 additions & 2 deletions dist/project-x.js
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,14 @@ function () {

break;

case 'show':
var _this$evaluateReturnE4 = _this.evaluateReturnExpression(expression),
output = _this$evaluateReturnE4.output;

_this.updateVisibility(el, output);

break;

case 'cloak':
el.removeAttribute('x-cloak');
break;
Expand Down Expand Up @@ -1019,6 +1027,19 @@ function () {

break;

case 'show':
var _self$evaluateReturnE4 = self.evaluateReturnExpression(expression),
output = _self$evaluateReturnE4.output,
deps = _self$evaluateReturnE4.deps;

if (self.concernedData.filter(function (i) {
return deps.includes(i);
}).length > 0) {
self.updateVisibility(el, output);
}

break;

default:
break;
}
Expand Down Expand Up @@ -1111,6 +1132,19 @@ function () {
value: function updateTextValue(el, value) {
el.innerText = value;
}
}, {
key: "updateVisibility",
value: function updateVisibility(el, value) {
if (!value) {
el.style.display = 'none';
} else {
if (el.style.length === 1 && el.style.display !== '') {
el.removeAttribute('style');
} else {
el.style.removeProperty('display');
}
}
}
}, {
key: "updateAttributeValue",
value: function updateAttributeValue(el, attrName, value) {
Expand Down Expand Up @@ -1388,12 +1422,12 @@ function saferEvalNoReturn(expression, dataContext) {
return new Function(['$data'].concat(_toConsumableArray(Object.keys(additionalHelperVariables))), "with($data) { ".concat(expression, " }")).apply(void 0, [dataContext].concat(_toConsumableArray(Object.values(additionalHelperVariables))));
}
function isXAttr(attr) {
var xAttrRE = /x-(on|bind|data|text|model|cloak|ref)/;
var xAttrRE = /x-(on|bind|data|text|model|show|cloak|ref)/;
return xAttrRE.test(attr.name);
}
function getXAttrs(el, type) {
return Array.from(el.attributes).filter(isXAttr).map(function (attr) {
var typeMatch = attr.name.match(/x-(on|bind|data|text|model|cloak|ref)/);
var typeMatch = attr.name.match(/x-(on|bind|data|text|model|show|cloak|ref)/);
var valueMatch = attr.name.match(/:([a-zA-Z\-]+)/);
var modifiers = attr.name.match(/\.[^.\]]+(?=[^\]]*$)/g) || [];
return {
Expand Down
2 changes: 1 addition & 1 deletion dist/project-x.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[x-cloak] { display: none; }
</style>

<script src="https://cdn.jsdelivr.net/gh/calebporzio/project-x@v0.3.0/dist/project-x.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/gh/calebporzio/project-x@v0.4.0/dist/project-x.min.js" defer></script>
</head>
<body>
<div x-data="{ foo: 'bar' }">
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"main": "dist/project-x.js",
"name": "project-x",
"version": "0.3.0",
"version": "0.4.0",
"repository": {
"type": "git",
"url": "git://github.com/calebporzio/project-x.git"
Expand Down
25 changes: 25 additions & 0 deletions src/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ export default class Component {
this.updateTextValue(el, output)
break;

case 'show':
var { output } = this.evaluateReturnExpression(expression)
this.updateVisibility(el, output)
break;

case 'cloak':
el.removeAttribute('x-cloak')
break;
Expand Down Expand Up @@ -114,6 +119,14 @@ export default class Component {
}
break;

case 'show':
var { output, deps } = self.evaluateReturnExpression(expression)

if (self.concernedData.filter(i => deps.includes(i)).length > 0) {
self.updateVisibility(el, output)
}
break;

default:
break;
}
Expand Down Expand Up @@ -208,6 +221,18 @@ export default class Component {
el.innerText = value
}

updateVisibility(el, value) {
if (! value) {
el.style.display = 'none'
} else {
if (el.style.length === 1 && el.style.display !== '') {
el.removeAttribute('style')
} else {
el.style.removeProperty('display')
}
}
}

updateAttributeValue(el, attrName, value) {
if (attrName === 'value') {
if (el.type === 'radio') {
Expand Down
4 changes: 2 additions & 2 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function saferEvalNoReturn(expression, dataContext, additionalHelperVaria
}

export function isXAttr(attr) {
const xAttrRE = /x-(on|bind|data|text|model|cloak|ref)/
const xAttrRE = /x-(on|bind|data|text|model|show|cloak|ref)/

return xAttrRE.test(attr.name)
}
Expand All @@ -70,7 +70,7 @@ export function getXAttrs(el, type) {
return Array.from(el.attributes)
.filter(isXAttr)
.map(attr => {
const typeMatch = attr.name.match(/x-(on|bind|data|text|model|cloak|ref)/)
const typeMatch = attr.name.match(/x-(on|bind|data|text|model|show|cloak|ref)/)
const valueMatch = attr.name.match(/:([a-zA-Z\-]+)/)
const modifiers = attr.name.match(/\.[^.\]]+(?=[^\]]*$)/g) || []

Expand Down
42 changes: 42 additions & 0 deletions test/show.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import projectX from 'project-x'
import { wait } from 'dom-testing-library'

global.MutationObserver = class {
observe() {}
}

test('x-show toggles display: none; with no other style attributes', async () => {
document.body.innerHTML = `
<div x-data="{ show: true }">
<span x-show="show"></span>
<button x-on:click="show = false"></button>
</div>
`

projectX.start()

expect(document.querySelector('span').getAttribute('style')).toEqual(null)

document.querySelector('button').click()

await wait(() => { expect(document.querySelector('span').getAttribute('style')).toEqual('display: none;') })
})

test('x-show toggles display: none; with no other style attributes', async () => {
document.body.innerHTML = `
<div x-data="{ show: true }">
<span x-show="show" style="color: blue;"></span>
<button x-on:click="show = false"></button>
</div>
`

projectX.start()

expect(document.querySelector('span').getAttribute('style')).toEqual('color: blue;')

document.querySelector('button').click()

await wait(() => { expect(document.querySelector('span').getAttribute('style')).toEqual('color: blue; display: none;') })
})

0 comments on commit 526ddc1

Please sign in to comment.