Skip to content

Commit

Permalink
feat: change callback to array when bind the same event, Javey/Intact#9
Browse files Browse the repository at this point in the history
  • Loading branch information
Javey committed Aug 2, 2018
1 parent 202bad1 commit 631447e
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 28 deletions.
38 changes: 30 additions & 8 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ var utils = (Object.freeze || Object)({
isArray: isArray,
indexOf: indexOf,
SelfClosingTags: selfClosingTags,
isEventProp: isEventProp,
Type: Type$1,
TypeName: TypeName$1,
TextTags: TextTags,
Expand Down Expand Up @@ -1387,6 +1388,20 @@ Stringifier.prototype = {

_visitJSXAttribute: function _visitJSXAttribute(element, individualClassName, individualKeyAndRef) {
var ret = [],
events = {},

// support bind multiple callbacks for the same event
addEvent = function addEvent(name, value) {
var v = events[name];
if (v) {
if (!isArray(v)) {
events[name] = [v];
}
events[name].push(value);
} else {
events[name] = value;
}
},
attributes = element.attributes,
className$$1,
key,
Expand Down Expand Up @@ -1441,14 +1456,21 @@ Stringifier.prototype = {
type = value;
} else if (name === 'value') {
addition.value = value;
} else if (isEventProp(name)) {
addEvent(name, value);
return;
}
ret.push("'" + name + "': " + value);
}, this);

for (var i = 0; i < models.length; i++) {
this._visitJSXAttributeModel(element, models[i], ret, type, addition);
this._visitJSXAttributeModel(element, models[i], ret, type, addition, addEvent);
}

each(events, function (value, name) {
ret.push('\'' + name + '\': ' + (isArray(value) ? '[' + value.join(',') + ']' : value));
});

return {
props: ret.length ? '{' + ret.join(', ') + '}' : 'null',
className: className$$1 || 'null',
Expand All @@ -1457,7 +1479,7 @@ Stringifier.prototype = {
};
},

_visitJSXAttributeModel: function _visitJSXAttributeModel(element, model, ret, type, addition) {
_visitJSXAttributeModel: function _visitJSXAttributeModel(element, model, ret, type, addition, addEvent) {
var valueName = model.name,
value = model.value,
eventName = 'change';
Expand All @@ -1476,14 +1498,14 @@ Stringifier.prototype = {
inputValue = addition.value;
if (isNullOrUndefined(inputValue)) {
ret.push('checked: _getModel(self, ' + value + ') === ' + trueValue);
ret.push('\'ev-change\': function(__e) {\n _setModel(self, ' + value + ', __e.target.checked ? ' + trueValue + ' : ' + falseValue + ', $this);\n }');
addEvent('ev-change', 'function(__e) {\n _setModel(self, ' + value + ', __e.target.checked ? ' + trueValue + ' : ' + falseValue + ', $this);\n }');
} else {
if (type === "'radio'") {
ret.push('checked: _getModel(self, ' + value + ') === ' + inputValue);
ret.push('\'ev-change\': function(__e) { \n _setModel(self, ' + value + ', __e.target.checked ? ' + inputValue + ' : ' + falseValue + ', $this);\n }');
addEvent('ev-change', 'function(__e) { \n _setModel(self, ' + value + ', __e.target.checked ? ' + inputValue + ' : ' + falseValue + ', $this);\n }');
} else {
ret.push('checked: _detectCheckboxChecked(self, ' + value + ', ' + inputValue + ')');
ret.push('\'ev-change\': function(__e) { \n _setCheckboxModel(self, ' + value + ', ' + inputValue + ', ' + falseValue + ', __e, $this);\n }');
addEvent('ev-change', 'function(__e) { \n _setCheckboxModel(self, ' + value + ', ' + inputValue + ', ' + falseValue + ', __e, $this);\n }');
}
}
return;
Expand All @@ -1494,17 +1516,17 @@ Stringifier.prototype = {
break;
case 'select':
ret.push('value: _getModel(self, ' + value + ')');
ret.push('\'ev-change\': function(__e) {\n _setSelectModel(self, ' + value + ', __e, $this);\n }');
addEvent('ev-change', 'function(__e) {\n _setSelectModel(self, ' + value + ', __e, $this);\n }');
return;
case 'textarea':
eventName = 'input';
break;
default:
break;
}
ret.push('\'ev-' + eventName + '\': function(__e) { _setModel(self, ' + value + ', __e.target.value, $this) }');
addEvent('ev-' + eventName, 'function(__e) { _setModel(self, ' + value + ', __e.target.value, $this) }');
} else if (element.type === Type$2.JSXWidget) {
ret.push('\'ev-$change:' + valueName + '\': function(__c, __n) { _setModel(self, ' + value + ', __n, $this) }');
addEvent('ev-$change:' + valueName, 'function(__c, __n) { _setModel(self, ' + value + ', __n, $this) }');
}
ret.push(valueName + ': _getModel(self, ' + value + ')');
},
Expand Down
38 changes: 30 additions & 8 deletions dist/vdt.js
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ var utils = (Object.freeze || Object)({
isArray: isArray,
indexOf: indexOf,
SelfClosingTags: selfClosingTags,
isEventProp: isEventProp,
Type: Type$1,
TypeName: TypeName$1,
TextTags: TextTags,
Expand Down Expand Up @@ -1387,6 +1388,20 @@ Stringifier.prototype = {

_visitJSXAttribute: function _visitJSXAttribute(element, individualClassName, individualKeyAndRef) {
var ret = [],
events = {},

// support bind multiple callbacks for the same event
addEvent = function addEvent(name, value) {
var v = events[name];
if (v) {
if (!isArray(v)) {
events[name] = [v];
}
events[name].push(value);
} else {
events[name] = value;
}
},
attributes = element.attributes,
className$$1,
key,
Expand Down Expand Up @@ -1440,14 +1455,21 @@ Stringifier.prototype = {
type = value;
} else if (name === 'value') {
addition.value = value;
} else if (isEventProp(name)) {
addEvent(name, value);
return;
}
ret.push("'" + name + "': " + value);
}, this);

for (var i = 0; i < models.length; i++) {
this._visitJSXAttributeModel(element, models[i], ret, type, addition);
this._visitJSXAttributeModel(element, models[i], ret, type, addition, addEvent);
}

each(events, function (value, name) {
ret.push('\'' + name + '\': ' + (isArray(value) ? '[' + value.join(',') + ']' : value));
});

return {
props: ret.length ? '{' + ret.join(', ') + '}' : 'null',
className: className$$1 || 'null',
Expand All @@ -1456,7 +1478,7 @@ Stringifier.prototype = {
};
},

_visitJSXAttributeModel: function _visitJSXAttributeModel(element, model, ret, type, addition) {
_visitJSXAttributeModel: function _visitJSXAttributeModel(element, model, ret, type, addition, addEvent) {
var valueName = model.name,
value = model.value,
eventName = 'change';
Expand All @@ -1475,14 +1497,14 @@ Stringifier.prototype = {
inputValue = addition.value;
if (isNullOrUndefined(inputValue)) {
ret.push('checked: _getModel(self, ' + value + ') === ' + trueValue);
ret.push('\'ev-change\': function(__e) {\n _setModel(self, ' + value + ', __e.target.checked ? ' + trueValue + ' : ' + falseValue + ', $this);\n }');
addEvent('ev-change', 'function(__e) {\n _setModel(self, ' + value + ', __e.target.checked ? ' + trueValue + ' : ' + falseValue + ', $this);\n }');
} else {
if (type === "'radio'") {
ret.push('checked: _getModel(self, ' + value + ') === ' + inputValue);
ret.push('\'ev-change\': function(__e) { \n _setModel(self, ' + value + ', __e.target.checked ? ' + inputValue + ' : ' + falseValue + ', $this);\n }');
addEvent('ev-change', 'function(__e) { \n _setModel(self, ' + value + ', __e.target.checked ? ' + inputValue + ' : ' + falseValue + ', $this);\n }');
} else {
ret.push('checked: _detectCheckboxChecked(self, ' + value + ', ' + inputValue + ')');
ret.push('\'ev-change\': function(__e) { \n _setCheckboxModel(self, ' + value + ', ' + inputValue + ', ' + falseValue + ', __e, $this);\n }');
addEvent('ev-change', 'function(__e) { \n _setCheckboxModel(self, ' + value + ', ' + inputValue + ', ' + falseValue + ', __e, $this);\n }');
}
}
return;
Expand All @@ -1493,17 +1515,17 @@ Stringifier.prototype = {
break;
case 'select':
ret.push('value: _getModel(self, ' + value + ')');
ret.push('\'ev-change\': function(__e) {\n _setSelectModel(self, ' + value + ', __e, $this);\n }');
addEvent('ev-change', 'function(__e) {\n _setSelectModel(self, ' + value + ', __e, $this);\n }');
return;
case 'textarea':
eventName = 'input';
break;
default:
break;
}
ret.push('\'ev-' + eventName + '\': function(__e) { _setModel(self, ' + value + ', __e.target.value, $this) }');
addEvent('ev-' + eventName, 'function(__e) { _setModel(self, ' + value + ', __e.target.value, $this) }');
} else if (element.type === Type$2.JSXWidget) {
ret.push('\'ev-$change:' + valueName + '\': function(__c, __n) { _setModel(self, ' + value + ', __n, $this) }');
addEvent('ev-$change:' + valueName, 'function(__c, __n) { _setModel(self, ' + value + ', __n, $this) }');
}
ret.push(valueName + ': _getModel(self, ' + value + ')');
},
Expand Down
2 changes: 1 addition & 1 deletion dist/vdt.min.js

Large diffs are not rendered by default.

36 changes: 28 additions & 8 deletions src/lib/stringifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,19 @@ Stringifier.prototype = {

_visitJSXAttribute: function(element, individualClassName, individualKeyAndRef) {
var ret = [],
events = {},
// support bind multiple callbacks for the same event
addEvent = (name, value) => {
const v = events[name];
if (v) {
if (!Utils.isArray(v)) {
events[name] = [v];
}
events[name].push(value);
} else {
events[name] = value;
}
},
attributes = element.attributes,
className,
key,
Expand Down Expand Up @@ -276,14 +289,21 @@ Stringifier.prototype = {
type = value;
} else if (name === 'value') {
addition.value = value;
} else if (Utils.isEventProp(name)) {
addEvent(name, value);
return;
}
ret.push("'" + name + "': " + value);
}, this);

for (let i = 0; i < models.length; i++) {
this._visitJSXAttributeModel(element, models[i], ret, type, addition);
this._visitJSXAttributeModel(element, models[i], ret, type, addition, addEvent);
}

Utils.each(events, (value, name) => {
ret.push(`'${name}': ${Utils.isArray(value) ? '[' + value.join(',') + ']' : value}`);
});

return {
props: ret.length ? '{' + ret.join(', ') + '}' : 'null',
className: className || 'null',
Expand All @@ -292,7 +312,7 @@ Stringifier.prototype = {
};
},

_visitJSXAttributeModel: function(element, model, ret, type, addition) {
_visitJSXAttributeModel: function(element, model, ret, type, addition, addEvent) {
var valueName = model.name,
value = model.value,
eventName = 'change';
Expand All @@ -311,18 +331,18 @@ Stringifier.prototype = {
inputValue = addition.value;
if (Utils.isNullOrUndefined(inputValue)) {
ret.push(`checked: _getModel(self, ${value}) === ${trueValue}`);
ret.push(`'ev-change': function(__e) {
addEvent('ev-change', `function(__e) {
_setModel(self, ${value}, __e.target.checked ? ${trueValue} : ${falseValue}, $this);
}`);
} else {
if (type === "'radio'") {
ret.push(`checked: _getModel(self, ${value}) === ${inputValue}`);
ret.push(`'ev-change': function(__e) {
addEvent('ev-change', `function(__e) {
_setModel(self, ${value}, __e.target.checked ? ${inputValue} : ${falseValue}, $this);
}`);
} else {
ret.push(`checked: _detectCheckboxChecked(self, ${value}, ${inputValue})`);
ret.push(`'ev-change': function(__e) {
addEvent('ev-change', `function(__e) {
_setCheckboxModel(self, ${value}, ${inputValue}, ${falseValue}, __e, $this);
}`);
}
Expand All @@ -335,7 +355,7 @@ Stringifier.prototype = {
break;
case 'select':
ret.push(`value: _getModel(self, ${value})`);
ret.push(`'ev-change': function(__e) {
addEvent('ev-change', `function(__e) {
_setSelectModel(self, ${value}, __e, $this);
}`);
return;
Expand All @@ -345,9 +365,9 @@ Stringifier.prototype = {
default:
break;
}
ret.push(`'ev-${eventName}': function(__e) { _setModel(self, ${value}, __e.target.value, $this) }`);
addEvent(`ev-${eventName}`, `function(__e) { _setModel(self, ${value}, __e.target.value, $this) }`);
} else if (element.type === Type.JSXWidget) {
ret.push(`'ev-$change:${valueName}': function(__c, __n) { _setModel(self, ${value}, __n, $this) }`);
addEvent(`ev-$change:${valueName}`, `function(__c, __n) { _setModel(self, ${value}, __n, $this) }`);
}
ret.push(`${valueName}: _getModel(self, ${value})`);
},
Expand Down
8 changes: 5 additions & 3 deletions src/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
* @date 15-4-22
*/

import {isNullOrUndefined, isArray, indexOf,
selfClosingTags as SelfClosingTags
import {
isNullOrUndefined, isArray, indexOf,
selfClosingTags as SelfClosingTags,
isEventProp,
} from 'misstime/src/utils';

export {isNullOrUndefined, isArray, indexOf, SelfClosingTags};
export {isNullOrUndefined, isArray, indexOf, SelfClosingTags, isEventProp};

let i = 0;
export const Type = {
Expand Down
26 changes: 26 additions & 0 deletions test/vdt.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -762,3 +762,29 @@ describe 'Vdt', ->
return h('div', null, function() {try {return [test][0]} catch(e) {_e(e)}}.call($this))
"""

it 'Stringify multiple events', ->
source = """
<div ev-click={a} ev-click={b} ev-dbclick={c}></div>
"""

Vdt.stringifier.stringify(Vdt.parser.parse(source)).should.eql """
return h('div', {'ev-click': [function() {try {return [a][0]} catch(e) {_e(e)}}.call($this),function() {try {return [b][0]} catch(e) {_e(e)}}.call($this)], 'ev-dbclick': function() {try {return [c][0]} catch(e) {_e(e)}}.call($this)})
"""

it 'Stringify event with model', ->
source = """
<input v-model="a" ev-input={b} />
"""

Vdt.stringifier.stringify(Vdt.parser.parse(source)).should.eql """
return h('input', {'v-model': 'a', value: _getModel(self, 'a'), 'ev-input': [function() {try {return [b][0]} catch(e) {_e(e)}}.call($this),function(__e) { _setModel(self, 'a', __e.target.value, $this) }]})
"""

it 'Strigify event with model in Component', ->
source = """
<Input v-model="a" ev-$change:value={b} />
"""

Vdt.stringifier.stringify(Vdt.parser.parse(source)).should.eql """
return h(Input, {'v-model': 'a', 'children': null, '_context': $this, value: _getModel(self, 'a'), 'ev-$change:value': [function() {try {return [b][0]} catch(e) {_e(e)}}.call($this),function(__c, __n) { _setModel(self, 'a', __n, $this) }]})
"""

0 comments on commit 631447e

Please sign in to comment.