Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
1cg committed Jun 15, 2023
2 parents 5e7f0c7 + f0ef75f commit 27e9658
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 23 deletions.
79 changes: 59 additions & 20 deletions src/_hyperscript.js
Original file line number Diff line number Diff line change
Expand Up @@ -6637,7 +6637,21 @@

parser.addCommand("take", function (parser, runtime, tokens) {
if (tokens.matchToken("take")) {
var classRef = parser.requireElement("classRef", tokens);
var classRef = parser.parseElement("classRef", tokens);

var attributeRef = null;
var replacementValue = null;

if (classRef == null) {
attributeRef = parser.parseElement("attributeRef", tokens);
if (attributeRef == null) {
parser.raiseParseError(tokens, "Expected either a class reference or attribute expression");
}

if (tokens.matchToken("with")) {
replacementValue = parser.requireElement("expression", tokens);
}
}

if (tokens.matchToken("from")) {
var fromExpr = parser.requireElement("expression", tokens);
Expand All @@ -6651,25 +6665,50 @@
var forExpr = parser.requireElement("implicitMeTarget", tokens);
}

var takeCmd = {
classRef: classRef,
from: fromExpr,
forElt: forExpr,
args: [classRef, fromExpr, forExpr],
op: function (context, eltColl, from, forElt) {
runtime.nullCheck(from, fromExpr);
runtime.nullCheck(forElt, forExpr);
var clazz = eltColl.className;
runtime.implicitLoop(from, function (target) {
target.classList.remove(clazz);
});
runtime.implicitLoop(forElt, function (target) {
target.classList.add(clazz);
});
return runtime.findNext(this, context);
},
};
return takeCmd;
if (classRef) {
var takeCmd = {
classRef: classRef,
from: fromExpr,
forElt: forExpr,
args: [classRef, fromExpr, forExpr],
op: function (context, eltColl, from, forElt) {
runtime.nullCheck(from, fromExpr);
runtime.nullCheck(forElt, forExpr);
var clazz = eltColl.className;
runtime.implicitLoop(from, function (target) {
target.classList.remove(clazz);
});
runtime.implicitLoop(forElt, function (target) {
target.classList.add(clazz);
});
return runtime.findNext(this, context);
},
};
return takeCmd;
} else {
var takeCmd = {
attributeRef: attributeRef,
from: fromExpr,
forElt: forExpr,
args: [fromExpr, forExpr, replacementValue],
op: function (context, from, forElt, replacementValue) {
runtime.nullCheck(from, fromExpr);
runtime.nullCheck(forElt, forExpr);
runtime.implicitLoop(from, function (target) {
if (!replacementValue) {
target.removeAttribute(attributeRef.name);
} else {
target.setAttribute(attributeRef.name, replacementValue)
}
});
runtime.implicitLoop(forElt, function (target) {
target.setAttribute(attributeRef.name, attributeRef.value || "")
});
return runtime.findNext(this, context);
},
};
return takeCmd;
}
}
});

Expand Down
87 changes: 87 additions & 0 deletions test/commands/take.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,91 @@ describe("the take command", function () {
d2.classList.contains("foo").should.equal(true);
d3.classList.contains("foo").should.equal(false);
});

it("can take an attribute from other elements", function () {
var d1 = make("<div class='div' data-foo='bar'></div>");
var d2 = make("<div class='div' _='on click take @data-foo from .div'></div>");
var d3 = make("<div class='div'></div>");
d1.getAttribute("data-foo").should.equal("bar");
assert.isNull(d2.getAttribute("data-foo"))
assert.isNull(d3.getAttribute("data-foo"))
d2.click();
assert.isNull(d1.getAttribute("data-foo"))
d2.getAttribute("data-foo").should.equal("");
assert.isNull(d3.getAttribute("data-foo"))
});

it("can take an attribute with specific value from other elements", function () {
var d1 = make("<div class='div' data-foo='bar'></div>");
var d2 = make("<div class='div' _='on click take @data-foo=baz from .div'></div>");
var d3 = make("<div class='div'></div>");
d1.getAttribute("data-foo").should.equal("bar");
assert.isNull(d2.getAttribute("data-foo"))
assert.isNull(d3.getAttribute("data-foo"))
d2.click();
assert.isNull(d1.getAttribute("data-foo"))
d2.getAttribute("data-foo").should.equal("baz");
assert.isNull(d3.getAttribute("data-foo"))
});

it("can take an attribute value from other elements and set specific values instead", function () {
var d1 = make("<div class='div' data-foo='bar'></div>");
var d2 = make("<div class='div' _='on click take @data-foo=baz with \"qux\" from .div'></div>");
var d3 = make("<div class='div'></div>");

d1.getAttribute("data-foo").should.equal("bar");
assert.isNull(d2.getAttribute("data-foo"))
assert.isNull(d3.getAttribute("data-foo"))
d2.click();
d1.getAttribute("data-foo").should.equal("qux");
d2.getAttribute("data-foo").should.equal("baz");
d3.getAttribute("data-foo").should.equal("qux");
});

it("can take an attribute value from other elements and set value from an expression instead", function () {
var d1 = make("<div class='div' data-foo='bar'></div>");
var d2 = make("<div class='div' data-foo='qux' _='on click take @data-foo=baz with my @data-foo from .div'></div>");
var d3 = make("<div class='div'></div>");

d1.getAttribute("data-foo").should.equal("bar");
d2.getAttribute("data-foo").should.equal("qux");
assert.isNull(d3.getAttribute("data-foo"))
d2.click();
d1.getAttribute("data-foo").should.equal("qux");
d2.getAttribute("data-foo").should.equal("baz");
d3.getAttribute("data-foo").should.equal("qux");
});

it("can take an attribute for other elements", function () {
var d1 = make("<div class='div' data-foo='bar'></div>");
var d2 = make("<div class='div' _='on click take @data-foo from .div for #d3'></div>");
var d3 = make("<div id='d3' class='div'></div>");
d1.getAttribute("data-foo").should.equal("bar");
assert.isNull(d2.getAttribute("data-foo"))
assert.isNull(d3.getAttribute("data-foo"))
d2.click();
assert.isNull(d1.getAttribute("data-foo"))
assert.isNull(d2.getAttribute("data-foo"))
d3.getAttribute("data-foo").should.equal("");
});

it("a parent can take an attribute for other elements", function () {
var div = make(
"<div _='on click take @data-foo from .div for event.target'>" +
"<div id='d1' class='div' data-foo='bar'></div>" +
"<div id='d2' class='div'></div>" +
"<div id='d3' class='div'></div>" +
"</div>"
);
var d1 = byId("d1");
var d2 = byId("d2");
var d3 = byId("d3");
d1.getAttribute("data-foo").should.equal("bar");
assert.isNull(d2.getAttribute("data-foo"))
assert.isNull(d3.getAttribute("data-foo"))
d2.click();
assert.isNull(d1.getAttribute("data-foo"))
d2.getAttribute("data-foo").should.equal("");
assert.isNull(d3.getAttribute("data-foo"))
});
});
18 changes: 16 additions & 2 deletions www/commands/take.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ title: take - ///_hyperscript
### Syntax

```ebnf
take <class-ref> [from <expression>] [for <expression>]
take <class-ref or attribute-ref [with <expression>]> [from <expression>] [for <expression>]
```

### Description

The `take` command allows you to take a class from a set of elements (or all elements) and add it to the current element (or the targeted element).
The `take` command allows you to take a class or an attribute from a set of elements (or all elements) and add it to the current element (or the targeted element).

When using `take` with attributes, elements matching `from` expression will have their attributes with the same name removed regardless of value.
You can specify a new value to be assigned instead via `with` clause (in this case the attribute will be added even if the element didn't have it originally).
### Examples

```html
Expand All @@ -24,4 +26,16 @@ The `take` command allows you to take a class from a set of elements (or all ele
<a class="tab">Tab 2</a>
<a class="tab">Tab 3</a>
</div>

<div _="on click take [@aria-curent=page] from .step for event.target">
<a class="step">Step 1</a>
<a class="step">Step 2</a>
<a class="step">Step 3</a>
</div>

<div _="on click take [@aria-selected=true] with 'false' from .item for event.target">
<a class="item">Option 1</a>
<a class="item">Option 2</a>
<a class="item">Option 3</a>
</div>
```
2 changes: 1 addition & 1 deletion www/commands/toggle.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ If you provide an `until <event name>` the class or attribute will be toggled un

<div _="on click toggle .toggled on #another-div">Toggle Another Div!</div>

<button _="on click toggle [disabled='true']">Toggle Disabled!</button>
<button _="on click toggle [@disabled='true']">Toggle Disabled!</button>

<div _="on click toggle .toggled for 2s">Toggle for 2 seconds</div>

Expand Down

0 comments on commit 27e9658

Please sign in to comment.