mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
parent
3eb3c286e8
commit
fc82ef0cf0
@ -264,7 +264,7 @@ And, here is the corresponding Marko template for the UI component:
|
||||
<div>
|
||||
You clicked the button ${data.clickCount} ${data.timesMessage}.
|
||||
</div>
|
||||
<button type="button" w-onclick="handleButtonClick">
|
||||
<button type="button" onClick("handleButtonClick")>
|
||||
Click Me
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -51,6 +51,7 @@ var SequenceExpression = require('./ast/SequenceExpression');
|
||||
var parseExpression = require('./util/parseExpression');
|
||||
var parseStatement = require('./util/parseStatement');
|
||||
var parseJavaScriptArgs = require('./util/parseJavaScriptArgs');
|
||||
var replacePlaceholderEscapeFuncs = require('./util/replacePlaceholderEscapeFuncs');
|
||||
var isValidJavaScriptIdentifier = require('./util/isValidJavaScriptIdentifier');
|
||||
|
||||
var DEFAULT_BUILDER;
|
||||
@ -420,6 +421,10 @@ class Builder {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
replacePlaceholderEscapeFuncs(node, context) {
|
||||
return replacePlaceholderEscapeFuncs(node, context);
|
||||
}
|
||||
|
||||
program(body) {
|
||||
return new Program({body});
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
var ok = require('assert').ok;
|
||||
var AttributePlaceholder = require('./ast/AttributePlaceholder');
|
||||
var replacePlaceholderEscapeFuncs = require('./util/replacePlaceholderEscapeFuncs');
|
||||
|
||||
var COMPILER_ATTRIBUTE_HANDLERS = {
|
||||
'preserve-whitespace': function(attr, context) {
|
||||
@ -17,24 +17,6 @@ function isIEConditionalComment(comment) {
|
||||
return ieConditionalCommentRegExp.test(comment);
|
||||
}
|
||||
|
||||
function replacePlaceholderEscapeFuncs(node, context) {
|
||||
var walker = context.createWalker({
|
||||
exit: function(node, parent) {
|
||||
if (node.type === 'FunctionCall' &&
|
||||
node.callee.type === 'Identifier') {
|
||||
|
||||
if (node.callee.name === '$noEscapeXml') {
|
||||
return new AttributePlaceholder({escape: false, value: node.args[0]});
|
||||
} else if (node.callee.name === '$escapeXml') {
|
||||
return new AttributePlaceholder({escape: true, value: node.args[0]});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return walker.walk(node);
|
||||
}
|
||||
|
||||
function mergeShorthandClassNames(el, shorthandClassNames, context) {
|
||||
var builder = context.builder;
|
||||
let classNames = shorthandClassNames.map((className) => {
|
||||
|
||||
19
compiler/util/replacePlaceholderEscapeFuncs.js
Normal file
19
compiler/util/replacePlaceholderEscapeFuncs.js
Normal file
@ -0,0 +1,19 @@
|
||||
var AttributePlaceholder = require('../ast/AttributePlaceholder');
|
||||
|
||||
module.exports = function replacePlaceholderEscapeFuncs(node, context) {
|
||||
var walker = context.createWalker({
|
||||
exit: function(node, parent) {
|
||||
if (node.type === 'FunctionCall' &&
|
||||
node.callee.type === 'Identifier') {
|
||||
|
||||
if (node.callee.name === '$noEscapeXml') {
|
||||
return new AttributePlaceholder({escape: false, value: node.args[0]});
|
||||
} else if (node.callee.name === '$escapeXml') {
|
||||
return new AttributePlaceholder({escape: true, value: node.args[0]});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return walker.walk(node);
|
||||
};
|
||||
@ -308,8 +308,8 @@ Listeners can be attached declaratively as shown in the following sample code:
|
||||
|
||||
```xml
|
||||
<div w-bind>
|
||||
<form w-onsubmit="handleFormSubmit">
|
||||
<input type="text" value="email" w-onchange="handleEmailChange">
|
||||
<form onsubmit("handleFormSubmit")>
|
||||
<input type="text" value="email" onchange("handleEmailChange")>
|
||||
<button>Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
@ -406,7 +406,7 @@ Listeners can be attached declaratively as shown in the following sample code:
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<app-overlay title="My Overlay"
|
||||
w-onBeforeHide="handleOverlayBeforeHide">
|
||||
onBeforeHide("handleOverlayBeforeHide")>
|
||||
|
||||
Content for overlay
|
||||
|
||||
@ -699,7 +699,7 @@ ___src/components/app-hello/template.marko:___
|
||||
|
||||
```xml
|
||||
<div w-bind
|
||||
w-on-click="handleClick">
|
||||
on-click("handleClick")>
|
||||
Hello ${data.name}!
|
||||
</div>
|
||||
```
|
||||
@ -736,7 +736,7 @@ ___src/components/app-hello/template.marko:___
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget"
|
||||
w-on-click="handleClick">
|
||||
on-click("handleClick")>
|
||||
Hello ${data.name}!
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -113,7 +113,7 @@ __src/components/app-hello/template.marko__
|
||||
|
||||
```xml
|
||||
<div w-bind
|
||||
w-onClick="handleClick">
|
||||
onClick("handleClick")>
|
||||
|
||||
Hello ${data.name}!
|
||||
|
||||
@ -154,7 +154,7 @@ __src/components/app-hello/template.marko__
|
||||
|
||||
```xml
|
||||
<div w-bind
|
||||
w-onClick="handleClick"
|
||||
onClick("handleClick")
|
||||
style="background-color: ${data.color}">
|
||||
|
||||
Hello ${data.name}!
|
||||
@ -202,7 +202,7 @@ __src/components/app-hello/template.marko__
|
||||
|
||||
```xml
|
||||
<div w-bind
|
||||
w-onClick="handleClick"
|
||||
onClick("handleClick")
|
||||
style="background-color: ${data.color}">
|
||||
|
||||
Hello ${data.name}!
|
||||
@ -258,17 +258,17 @@ module.exports = require('marko-widgets').defineComponent({
|
||||
<div w-bind>
|
||||
<app-overlay title="My Overlay"
|
||||
ref="overlay"
|
||||
w-onBeforeHide="handleOverlayBeforeHide">
|
||||
onBeforeHide("handleOverlayBeforeHide")>
|
||||
Body content for overlay.
|
||||
</app-overlay>
|
||||
|
||||
<button type="button"
|
||||
w-onClick="handleShowButtonClick">
|
||||
onClick("handleShowButtonClick")>
|
||||
Show Overlay
|
||||
</button>
|
||||
|
||||
<button type="button"
|
||||
w-onClick="handleHideButtonClick">
|
||||
onClick("handleHideButtonClick")>
|
||||
Hide Overlay
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -85,7 +85,7 @@ NOTE: For DOM events that bubble, efficient DOM event delegation will automatica
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<button w-onclick="handleMyButtonClick" type="button">My Button</button>
|
||||
<button onClick("handleMyButtonClick") type="button">My Button</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -113,7 +113,7 @@ var myButton = this.getEl('myButton');
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<app-button w-onSomeCustomEvent="handleSomeCustomEvent" label="My Button" />
|
||||
<app-button onSomeCustomEvent("handleSomeCustomEvent") label="My Button" />
|
||||
</div>
|
||||
```
|
||||
|
||||
|
||||
@ -28,5 +28,6 @@
|
||||
"no-update-if",
|
||||
"no-update-body-if",
|
||||
"w-preserve-attrs",
|
||||
"on*",
|
||||
"w-on*"
|
||||
]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -5,8 +5,8 @@
|
||||
<app-bar ref="barArray[]" label="1"/>
|
||||
<app-bar ref="barArray[]" label="2"/>
|
||||
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" ref="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent2" channel="customEvents-${widget.id}" />
|
||||
<app-custom-events onTestEvent("handleTestEvent1") ref="customEvents" />
|
||||
<app-custom-events onTestEvent("handleTestEvent2") channel="customEvents-${widget.id}" />
|
||||
|
||||
<ul>
|
||||
<li for(color in ['red', 'green', 'blue']) ref="colorListItems[]">${color}</li>
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
<app-bar ref="barArray[]" label="1"/>
|
||||
<app-bar ref="barArray[]" label="2"/>
|
||||
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" ref="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent2" channel="customEvents-${widget.id}" />
|
||||
<app-custom-events onTestEvent("handleTestEvent1") ref="customEvents" />
|
||||
<app-custom-events onTestEvent("handleTestEvent2") channel="customEvents-${widget.id}" />
|
||||
|
||||
<ul>
|
||||
<li for(color in ['red', 'green', 'blue']) ref="colorListItems[]">${color}</li>
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
<app-bar ref="barArray[]" label="1"/>
|
||||
<app-bar ref="barArray[]" label="2"/>
|
||||
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" ref="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent2" channel="customEvents-${widget.id}" />
|
||||
<app-custom-events onTestEvent("handleTestEvent1") ref="customEvents" />
|
||||
<app-custom-events onTestEvent("handleTestEvent2") channel="customEvents-${widget.id}" />
|
||||
|
||||
<ul>
|
||||
<li for(color in ['red', 'green', 'blue']) ref="colorListItems[]">${color}</li>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<button type="button" class="app-legacy-button"
|
||||
w-bind="./widget"
|
||||
w-onmousedown="handleRootMouseDown">
|
||||
onMousedown("handleRootMouseDown")>
|
||||
<invoke data.renderBody(out)/>
|
||||
</button>
|
||||
@ -1,6 +1,6 @@
|
||||
<div w-bind>
|
||||
<a href="#foo" ref="fooLink"
|
||||
w-ondblclick="handleFooLinkDblClick"
|
||||
w-onmouseout="handleFooLinkMouseOut">
|
||||
onDblclick("handleFooLinkDblClick")
|
||||
onMouseout("handleFooLinkMouseOut")>
|
||||
</a>
|
||||
</div>
|
||||
@ -1,6 +1,6 @@
|
||||
<div w-bind>
|
||||
<ul>
|
||||
<li w-onMouseMove="handleMouseMove" ref="foo-${loop.getIndex()}"
|
||||
<li onMouseMove("handleMouseMove") ref="foo-${loop.getIndex()}"
|
||||
for(color in ['red', 'green', 'blue'] | status-var=loop)>${color}</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
<button type="button" class="app-legacy-button"
|
||||
w-bind="./widget"
|
||||
w-onmousedown="handleRootMouseDown">
|
||||
onMousedown("handleRootMouseDown")>
|
||||
<invoke data.renderBody(out)/>
|
||||
</button>
|
||||
@ -1,20 +1,20 @@
|
||||
<div class="app-dom-events"
|
||||
w-bind="./widget"
|
||||
w-onmousemove="handleRootMouseMove"
|
||||
w-onClick="handleRootClick">
|
||||
onMousemove("handleRootMouseMove")
|
||||
onClick("handleRootClick")>
|
||||
<button type="button" ref="button"
|
||||
w-onclick="handleButtonClick">
|
||||
<span w-onmousemove="handleButtonSpanMouseMove">
|
||||
onClick("handleButtonClick")>
|
||||
<span onMousemove("handleButtonSpanMouseMove")>
|
||||
Button
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<a href="#foo" id="fooLink"
|
||||
w-ondblclick="handleFooLinkDblClick"
|
||||
w-onmouseout="handleFooLinkMouseOut">
|
||||
onDblclick("handleFooLinkDblClick")
|
||||
onMouseout("handleFooLinkMouseOut")>
|
||||
</a>
|
||||
|
||||
<app-legacy-button ref="appButton">
|
||||
<span ref="helloWorld" w-onmousedown="handleHelloWorldMouseDown">Hello World</span>
|
||||
<span ref="helloWorld" onMousedown("handleHelloWorldMouseDown")>Hello World</span>
|
||||
</app-legacy-button>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
<div w-bind>
|
||||
<input w-onclick=(false && 'handleButtonClick') ref="inputWithoutHandler" type="button">
|
||||
<input w-onclick=(true && 'handleButtonClick') ref="inputWithHandler" type="button">
|
||||
<input w-onclick='handleButtonClick' ref="inputWithLiteralHandler" type="button">
|
||||
<input onClick(false && 'handleButtonClick') ref="inputWithoutHandler" type="button">
|
||||
<input onClick(true && 'handleButtonClick') ref="inputWithHandler" type="button">
|
||||
<input onClick('handleButtonClick') ref="inputWithLiteralHandler" type="button">
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
<div w-bind>
|
||||
<input w-onMouseMove=(false && "handleMouseMove") ref="inputWithoutHandler" type="button">
|
||||
<input w-onMouseMove=(true && 'handleMouseMove') ref="inputWithHandler" type="button">
|
||||
<input w-onMouseMove='handleMouseMove' ref="inputWithLiteralHandler" type="button">
|
||||
<input onMouseMove(false && "handleMouseMove") ref="inputWithoutHandler" type="button">
|
||||
<input onMouseMove(true && 'handleMouseMove') ref="inputWithHandler" type="button">
|
||||
<input onMouseMove('handleMouseMove') ref="inputWithLiteralHandler" type="button">
|
||||
</div>
|
||||
@ -1,7 +1,7 @@
|
||||
<div w-bind>
|
||||
<h1>app-macro-events</h1>
|
||||
<macro renderButton(id, label, handler)>
|
||||
<button ref="${id}" type="button" w-onClick="${handler}">
|
||||
<button ref="${id}" type="button" onClick("${handler}")>
|
||||
$label
|
||||
</button>
|
||||
</macro>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind="./widget">
|
||||
|
||||
<if(data.label)>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
include()></button>
|
||||
@ -1,7 +1,7 @@
|
||||
<div w-bind>
|
||||
<div w-onclick="handleDivClick">
|
||||
<div onClick("handleDivClick")>
|
||||
Hello
|
||||
<button ref="button" type="button" w-onclick="handleButtonClick">
|
||||
<button ref="button" type="button" onClick("handleButtonClick")>
|
||||
Button
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
div w-bind
|
||||
button ref="button" w-onMouseMove='handleButtonMouseMove' w-onClick="handleButtonClick"
|
||||
button ref="button" onMouseMove('handleButtonMouseMove') onClick("handleButtonClick")
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
w-onclick="handleClick"
|
||||
onClick("handleClick")
|
||||
w-bind
|
||||
w-body></button>
|
||||
@ -48,7 +48,7 @@ var attachBubbleEventListeners = function() {
|
||||
var target;
|
||||
|
||||
// Attributes will have the following form:
|
||||
// w-on<event_type>="<target_method>|<widget_id>"
|
||||
// on<event_type>("<target_method>|<widget_id>")
|
||||
|
||||
do {
|
||||
if ((target = getEventAttribute(curNode, attrName))) {
|
||||
|
||||
@ -89,6 +89,7 @@ function addCustomEventListener(transformHelper, eventType, targetMethod) {
|
||||
module.exports = function handleWidgetEvents() {
|
||||
var el = this.el;
|
||||
var builder = this.builder;
|
||||
var context = this.context;
|
||||
var isCustomTag = el.type !== 'HtmlElement';
|
||||
// We configured the Marko compiler to attach a flag to nodes that
|
||||
// have one or more attributes that match the "w-on*" pattern.
|
||||
@ -100,16 +101,35 @@ module.exports = function handleWidgetEvents() {
|
||||
var attrs = el.getAttributes().concat([]);
|
||||
|
||||
attrs.forEach((attr) => {
|
||||
var eventType;
|
||||
var targetMethod;
|
||||
var attrName = attr.name;
|
||||
if (!attrName || !attrName.startsWith('w-on')) {
|
||||
var args = attr.argument;
|
||||
|
||||
if (!attrName) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (attrName.startsWith('on') && args) {
|
||||
eventType = attrName.substring(2); // Chop off "on"
|
||||
try {
|
||||
var parsedArgs = builder.parseExpression(args);
|
||||
targetMethod = builder.replacePlaceholderEscapeFuncs(parsedArgs, context);
|
||||
} catch (err) {
|
||||
this.addError('Invalid Javascript Expression for "' + attrName + '": ' + err);
|
||||
}
|
||||
} else if (attrName.startsWith('w-on')) {
|
||||
console.warn('"w-on*" attributes are deprecated. Please use "on*()" instead. (' + (el.pos ? context.getPosInfo(el.pos) : context.filename) + ')');
|
||||
eventType = attrName.substring(4); // Chop off "w-on"
|
||||
targetMethod = attr.value;
|
||||
}
|
||||
|
||||
if (!eventType || !targetMethod) {
|
||||
return;
|
||||
}
|
||||
|
||||
el.removeAttribute(attrName);
|
||||
|
||||
var eventType = attrName.substring(4); // Chop off "w-on"
|
||||
var targetMethod = attr.value;
|
||||
|
||||
if (isCustomTag) {
|
||||
var widgetArgs = this.getWidgetArgs();
|
||||
if (widgetArgs.getId() == null) {
|
||||
@ -165,4 +185,4 @@ module.exports = function handleWidgetEvents() {
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -64,6 +64,20 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"@on*": {
|
||||
"pattern": true,
|
||||
"type": "statement",
|
||||
"allow-expressions": true,
|
||||
"preserve-name": true,
|
||||
"set-flag": "hasWidgetEvents",
|
||||
"autocomplete": [
|
||||
{
|
||||
"displayText": "on<event>(\"<method>\")",
|
||||
"snippet": "on${1:Click}(\"handle${2:Button}${1:Click}\")",
|
||||
"descriptionMoreURL": "http://markojs.com/docs/marko-widgets/get-started/#adding-dom-event-listeners"
|
||||
}
|
||||
]
|
||||
},
|
||||
"@w-on*": {
|
||||
"pattern": true,
|
||||
"type": "string",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user