Browse Source

Add script-props property to Component

ui-module
Artur Arseniev 6 years ago
parent
commit
59fc111ab4
  1. 17
      src/canvas/view/CanvasView.js
  2. 45
      src/code_manager/model/JsGenerator.js
  3. 60
      src/dom_components/model/Component.js

17
src/canvas/view/CanvasView.js

@ -296,14 +296,17 @@ export default Backbone.View.extend({
// In editor, I make use of setTimeout as during the append process of elements // In editor, I make use of setTimeout as during the append process of elements
// those will not be available immediately, therefore 'item' variable // those will not be available immediately, therefore 'item' variable
const script = document.createElement('script'); const script = document.createElement('script');
const scriptFn = model.getScriptString();
const scriptFnStr = model.get('script-props')
? scriptFn
: `function(){${scriptFn};}`;
const scriptProps = JSON.stringify(model.__getScriptProps());
script.innerHTML = ` script.innerHTML = `
setTimeout(function() { setTimeout(function() {
var item = document.getElementById('${id}'); var item = document.getElementById('${id}');
if (!item) return; if (!item) return;
(function(){ (${scriptFnStr}.bind(item))(${scriptProps})
${model.getScriptString()}; }, 1);`;
}.bind(item))()
}, 1);`;
// #873 // #873
// Adding setTimeout will make js components work on init of the editor // Adding setTimeout will make js components work on init of the editor
setTimeout(() => view.scriptContainer.get(0).appendChild(script), 0); setTimeout(() => view.scriptContainer.get(0).appendChild(script), 0);

45
src/code_manager/model/JsGenerator.js

@ -15,17 +15,26 @@ export default Backbone.Model.extend({
attr = extend({}, attr, { id }); attr = extend({}, attr, { id });
model.set('attributes', attr, { silent: 1 }); model.set('attributes', attr, { silent: 1 });
var scrStr = model.getScriptString(script); var scrStr = model.getScriptString(script);
const scrProps = model.get('script-props');
// If the script was updated, I'll put its code in a separate container // If the script was updated, I'll put its code in a separate container
if (model.get('scriptUpdated')) { if (model.get('scriptUpdated') && !scrProps) {
this.mapJs[type + '-' + id] = { ids: [id], code: scrStr }; this.mapJs[type + '-' + id] = { ids: [id], code: scrStr };
} else { } else {
var mapType = this.mapJs[type]; let props;
const mapType = this.mapJs[type];
if (scrProps) {
props = model.__getScriptProps();
}
if (mapType) { if (mapType) {
mapType.ids.push(id); mapType.ids.push(id);
if (props) mapType.props[id] = props;
} else { } else {
this.mapJs[type] = { ids: [id], code: scrStr }; const res = { ids: [id], code: scrStr };
if (props) res.props = { [id]: props };
this.mapJs[type] = res;
} }
} }
} }
@ -40,17 +49,29 @@ export default Backbone.Model.extend({
build(model) { build(model) {
this.mapJs = {}; this.mapJs = {};
this.mapModel(model); this.mapModel(model);
let code = '';
var code = ''; for (let type in this.mapJs) {
const mapType = this.mapJs[type];
for (var type in this.mapJs) { if (mapType.props) {
var mapType = this.mapJs[type]; code += `
var ids = '#' + mapType.ids.join(', #'); var props = ${JSON.stringify(mapType.props)};
code += ` var ids = Object.keys(props).map(function(id) { return '#'+id }).join(',');
var items = document.querySelectorAll('${ids}'); var els = document.querySelectorAll(ids);
for (var i = 0, len = items.length; i < len; i++) { for (var i = 0, len = els.length; i < len; i++) {
(function(){${mapType.code}}.bind(items[i]))(); var el = els[i];
}`; (${mapType.code}.bind(el))(props[el.id]);
}`;
} else {
// Deprecated
const ids = '#' + mapType.ids.join(', #');
code += `
var items = document.querySelectorAll('${ids}');
for (var i = 0, len = items.length; i < len; i++) {
(function(){${mapType.code}}.bind(items[i]))();
}`;
}
} }
return code; return code;

60
src/dom_components/model/Component.js

@ -116,6 +116,7 @@ const Component = Backbone.Model.extend(Styleable).extend(
style: '', // Component related style style: '', // Component related style
classes: '', // Array of classes classes: '', // Array of classes
script: '', script: '',
'script-props': '',
'script-export': '', 'script-export': '',
attributes: '', attributes: '',
traits: ['id', 'title'], traits: ['id', 'title'],
@ -1259,6 +1260,15 @@ const Component = Backbone.Model.extend(Styleable).extend(
return this.getView(frame); return this.getView(frame);
}, },
__getScriptProps() {
const modelProps = this.props();
const scrProps = this.get('script-props') || [];
return scrProps.reduce((acc, prop) => {
acc[prop] = modelProps[prop];
return acc;
}, {});
},
/** /**
* Return script in string format, cleans 'function() {..' from scripts * Return script in string format, cleans 'function() {..' from scripts
* if it's a function * if it's a function
@ -1267,35 +1277,39 @@ const Component = Backbone.Model.extend(Styleable).extend(
* @private * @private
*/ */
getScriptString(script) { getScriptString(script) {
var scr = script || this.get('script'); let scr = script || this.get('script');
if (!scr) { if (!scr) {
return scr; return scr;
} }
// Need to convert script functions to strings if (this.get('script-props')) {
if (typeof scr == 'function') { scr = scr.toString().trim();
var scrStr = scr.toString().trim(); } else {
scrStr = scrStr // Deprecated
.replace(/^function[\s\w]*\(\)\s?\{/, '') // Need to convert script functions to strings
.replace(/\}$/, ''); if (typeof scr == 'function') {
scr = scrStr.trim(); var scrStr = scr.toString().trim();
} scrStr = scrStr
.replace(/^function[\s\w]*\(\)\s?\{/, '')
var config = this.em.getConfig(); .replace(/\}$/, '');
var tagVarStart = escapeRegExp(config.tagVarStart || '{[ '); scr = scrStr.trim();
var tagVarEnd = escapeRegExp(config.tagVarEnd || ' ]}'); }
var reg = new RegExp(`${tagVarStart}([\\w\\d-]*)${tagVarEnd}`, 'g');
scr = scr.replace(reg, (match, v) => {
// If at least one match is found I have to track this change for a
// better optimization inside JS generator
this.scriptUpdated();
const result = this.attributes[v] || '';
return isArray(result) || typeof result == 'object'
? JSON.stringify(result)
: result;
});
var config = this.em.getConfig();
var tagVarStart = escapeRegExp(config.tagVarStart || '{[ ');
var tagVarEnd = escapeRegExp(config.tagVarEnd || ' ]}');
var reg = new RegExp(`${tagVarStart}([\\w\\d-]*)${tagVarEnd}`, 'g');
scr = scr.replace(reg, (match, v) => {
// If at least one match is found I have to track this change for a
// better optimization inside JS generator
this.scriptUpdated();
const result = this.attributes[v] || '';
return isArray(result) || typeof result == 'object'
? JSON.stringify(result)
: result;
});
}
return scr; return scr;
}, },

Loading…
Cancel
Save