', {class: ppfx + 'offset-v'}).get(0);
this.fixedOffsetEl = $('
', {class: ppfx + 'offset-fixed-v'}).get(0);
- this.placerEl.appendChild(this.placerIntEl);
- toolsEl.appendChild(this.hlEl);
- toolsEl.appendChild(this.badgeEl);
- toolsEl.appendChild(this.placerEl);
- toolsEl.appendChild(this.ghostEl);
- toolsEl.appendChild(this.toolbarEl);
- toolsEl.appendChild(this.resizerEl);
+ this.placerEl.appendChild(this.placerIntEl);
+ toolsEl.appendChild(this.hlEl);
+ toolsEl.appendChild(this.badgeEl);
+ toolsEl.appendChild(this.placerEl);
+ toolsEl.appendChild(this.ghostEl);
+ toolsEl.appendChild(this.toolbarEl);
+ toolsEl.appendChild(this.resizerEl);
toolsEl.appendChild(this.offsetEl);
toolsEl.appendChild(this.fixedOffsetEl);
- this.$el.append(toolsEl);
+ this.$el.append(toolsEl);
var rte = this.em.get('rte');
if(rte)
toolsEl.appendChild(rte.render());
this.toolsEl = toolsEl;
- this.$el.attr({class: this.className});
- return this;
- },
+ this.$el.attr({class: this.className});
+ return this;
+ },
- });
+ });
});
diff --git a/src/demo.js b/src/demo.js
index 3305d794c..8daabcfb8 100644
--- a/src/demo.js
+++ b/src/demo.js
@@ -12,9 +12,40 @@ require(['config/require-config'], function() {
noticeOnUnload: 0,
container : '#gjs',
height: '100%',
- fromElement: true,
- /*
+ //fromElement: true,
+
components: [{
+ script: 'this.innerHTML= "test1";',
+ style: {
+ background: 'red',
+ width:'500px',
+ height:'100px',
+ margin: '50px auto',
+ }
+ },{
+ script: 'this.innerHTML= "test1";',
+ style: {
+ background: 'blue',
+ width:'500px',
+ height:'100px',
+ margin: '50px auto',
+ }
+ },{
+ script: 'this.innerHTML= "test2";',
+ style: {
+ background: 'green',
+ width:'500px',
+ height:'100px',
+ margin: '50px auto',
+ }
+ },{
+ style: {
+ background: 'yellow',
+ width:'500px',
+ height:'100px',
+ margin: '50px auto',
+ }
+ },{
type: 'text',
style:{
width:'100px',
@@ -35,7 +66,7 @@ require(['config/require-config'], function() {
type: 'textnode',
content: " More text node --- ",
}],
- }],*/
+ }],
storageManager:{
autoload: 0,
diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js
index c86a5cb99..a92c98ee8 100644
--- a/src/dom_components/model/Component.js
+++ b/src/dom_components/model/Component.js
@@ -59,6 +59,9 @@ define(['backbone','./Components', 'SelectorManager/model/Selectors', 'TraitMana
// Array of classes
classes: '',
+ // Component's javascript
+ script: '',
+
// Traits
traits: ['id', 'title'],
diff --git a/src/dom_components/view/ComponentView.js b/src/dom_components/view/ComponentView.js
index ef5a08edf..afef70b8e 100644
--- a/src/dom_components/view/ComponentView.js
+++ b/src/dom_components/view/ComponentView.js
@@ -1,280 +1,301 @@
define(['backbone', './ComponentsView'],
- function (Backbone, ComponentsView) {
-
- return Backbone.View.extend({
-
- events: {
- 'click': 'initResize',
- },
-
- className : function(){
- return this.getClasses();
- },
-
- tagName: function(){
- return this.model.get('tagName');
- },
-
- initialize: function(opt){
- this.opts = opt || {};
- this.config = opt.config || {};
- this.pfx = this.config.stylePrefix || '';
- this.ppfx = this.config.pStylePrefix || '';
- this.components = this.model.get('components');
- this.attr = this.model.get("attributes");
- this.classe = this.attr.class || [];
- this.listenTo(this.model, 'destroy remove', this.remove);
- this.listenTo(this.model, 'change:style', this.updateStyle);
- this.listenTo(this.model, 'change:attributes', this.updateAttributes);
- this.listenTo(this.model, 'change:status', this.updateStatus);
- this.listenTo(this.model, 'change:state', this.updateState);
- this.listenTo(this.model.get('classes'), 'add remove change', this.updateClasses);
- this.$el.data('model', this.model);
- this.model.view = this;
- this.$el.data("collection", this.components);
-
- if(this.model.get('classes').length)
- this.importClasses();
-
- this.init();
- },
-
- /**
+ function (Backbone, ComponentsView) {
+
+ return Backbone.View.extend({
+
+ events: {
+ 'click': 'initResize',
+ },
+
+ className : function(){
+ return this.getClasses();
+ },
+
+ tagName: function(){
+ return this.model.get('tagName');
+ },
+
+ initialize: function(opt) {
+ this.opts = opt || {};
+ this.config = this.opts.config || {};
+ this.em = this.config.em || '';
+ this.pfx = this.config.stylePrefix || '';
+ this.ppfx = this.config.pStylePrefix || '';
+ this.components = this.model.get('components');
+ this.attr = this.model.get("attributes");
+ this.classe = this.attr.class || [];
+ this.listenTo(this.model, 'destroy remove', this.remove);
+ this.listenTo(this.model, 'change:style', this.updateStyle);
+ this.listenTo(this.model, 'change:attributes', this.updateAttributes);
+ this.listenTo(this.model, 'change:status', this.updateStatus);
+ this.listenTo(this.model, 'change:state', this.updateState);
+ this.listenTo(this.model, 'change:script', this.render);
+ this.listenTo(this.model.get('classes'), 'add remove change', this.updateClasses);
+ this.$el.data('model', this.model);
+ this.model.view = this;
+ this.$el.data("collection", this.components);
+
+ if(this.model.get('classes').length)
+ this.importClasses();
+
+ this.init();
+ },
+
+ /**
* Initialize callback
*/
init: function () {},
- /**
- * Import, if possible, classes inside main container
- * @private
- * */
- importClasses: function(){
- var clm = this.config.em.get('SelectorManager');
-
- if(clm){
- this.model.get('classes').each(function(m){
- clm.add(m.get('name'));
- });
- }
- },
-
- /**
- * Fires on state update. If the state is not empty will add a helper class
- * @param {Event} e
- * @private
- * */
- updateState: function(e){
- var cl = 'hc-state';
- var state = this.model.get('state');
-
- if(state){
- this.$el.addClass(cl);
- }else{
- this.$el.removeClass(cl);
- }
- },
-
- /**
- * Update item on status change
- * @param {Event} e
- * @private
- * */
- updateStatus: function(e){
- var s = this.model.get('status'),
- pfx = this.pfx;
- switch(s) {
- case 'selected':
- this.$el.addClass(pfx + 'selected');
- break;
- case 'moving':
- break;
- default:
- this.$el.removeClass(pfx + 'selected');
- }
- },
-
- /**
- * Get classes from attributes.
- * This method is called before initialize
- *
- * @return {Array}|null
- * @private
- * */
- getClasses: function(){
- var attr = this.model.get("attributes"),
- classes = attr['class'] || [];
- if(classes.length){
- return classes.join(" ");
- }else
- return null;
- },
-
- /**
- * Update attributes
- * @private
- * */
- updateAttributes: function(){
- var attributes = {},
- attr = this.model.get("attributes");
- for(var key in attr) {
- if(attr.hasOwnProperty(key))
- attributes[key] = attr[key];
- }
- // Update src
- if(this.model.get("src"))
- attributes.src = this.model.get("src");
-
- var styleStr = this.getStyleString();
-
- if(styleStr)
- attributes.style = styleStr;
-
- this.$el.attr(attributes);
- },
-
- /**
- * Update style attribute
- * @private
- * */
- updateStyle: function(){
- this.$el.attr('style', this.getStyleString());
- },
-
- /**
- * Return style string
- * @return {string}
- * @private
- * */
- getStyleString: function(){
- var style = '';
- this.style = this.model.get('style');
- for(var key in this.style) {
- if(this.style.hasOwnProperty(key))
- style += key + ':' + this.style[key] + ';';
- }
-
- return style;
- },
-
- /**
- * Update classe attribute
- * @private
- * */
- updateClasses: function(){
- var str = '';
-
- this.model.get('classes').each(function(model){
- str += model.get('name') + ' ';
- });
- str = str.trim();
-
- if(str)
- this.$el.attr('class', str);
- else
- this.$el.removeAttr('class');
-
- // Regenerate status class
- this.updateStatus();
- },
-
- /**
- * Reply to event call
- * @param object Event that generated the request
- * @private
- * */
- eventCall: function(event){
- event.viewResponse = this;
- },
-
- /**
- * Init component for resizing
- */
- initResize: function () {
- var em = this.opts.config.em;
- var editor = em ? em.get('Editor') : '';
- var config = em ? em.get('Config') : '';
- var pfx = config.stylePrefix || '';
- var attrName = 'data-' + pfx + 'handler';
- var resizeClass = pfx + 'resizing';
- var model = this.model;
- var modelToStyle;
-
- var toggleBodyClass = function(method, e, opts) {
- var handlerAttr = e.target.getAttribute(attrName);
- var resizeHndClass = pfx + 'resizing-' + handlerAttr;
- var classToAdd = resizeClass;// + ' ' +resizeHndClass;
- if (opts.docs) {
- opts.docs.find('body')[method](classToAdd);
- }
- };
-
- if(editor && this.model.get('resizable')) {
- editor.runCommand('resize', {
- el: this.el,
- options: {
- onStart: function (e, opts) {
- toggleBodyClass('addClass', e, opts);
- modelToStyle = em.get('StyleManager').getModelToStyle(model);
- },
- // Update all positioned elements (eg. component toolbar)
- onMove: function () {
- editor.trigger('change:canvasOffset');
- },
- onEnd: function (e, opts) {
- toggleBodyClass('removeClass', e, opts);
- editor.trigger('change:canvasOffset');
- },
- updateTarget: function(el, rect, store) {
- if (!modelToStyle) {
- return;
- }
- var unit = 'px';
- var style = _.clone(modelToStyle.get('style'));
- var width = rect.w + (store ? 1 : 0);
- style.width = width + unit;
- style.height = rect.h + unit;
- modelToStyle.set('style', style, {avoidStore: 1});
- em.trigger('targetStyleUpdated');
-
- // This trick will trigger the Undo Manager. To trigger "change:style"
- // on the Model you need to provide a new object and after that
- // Undo Manager will trigger only if values are different (this is why
- // above I've added + 1 to width if store required)
- if(store) {
- var style3 = _.clone(style);
- style3.width = (width - 1) + unit;
- modelToStyle.set('style', style3);
- }
- }
- }
- });
- }
- },
-
- /**
- * Prevent default helper
- * @param {Event} e
- * @private
- */
- prevDef: function (e) {
- e.preventDefault();
- },
-
- render: function() {
- this.updateAttributes();
- this.updateClasses();
- this.$el.html(this.model.get('content'));
- var view = new ComponentsView({
- collection: this.model.get('components'),
- config: this.config,
- defaultTypes: this.opts.defaultTypes,
- componentTypes: this.opts.componentTypes,
- });
-
- // With childNodes lets avoid wrapping 'div'
- this.$el.append(view.render(this.$el).el.childNodes);
- return this;
- },
-
- });
+ /**
+ * Import, if possible, classes inside main container
+ * @private
+ * */
+ importClasses: function(){
+ var clm = this.config.em.get('SelectorManager');
+
+ if(clm){
+ this.model.get('classes').each(function(m){
+ clm.add(m.get('name'));
+ });
+ }
+ },
+
+ /**
+ * Fires on state update. If the state is not empty will add a helper class
+ * @param {Event} e
+ * @private
+ * */
+ updateState: function(e){
+ var cl = 'hc-state';
+ var state = this.model.get('state');
+
+ if(state){
+ this.$el.addClass(cl);
+ }else{
+ this.$el.removeClass(cl);
+ }
+ },
+
+ /**
+ * Update item on status change
+ * @param {Event} e
+ * @private
+ * */
+ updateStatus: function(e){
+ var s = this.model.get('status'),
+ pfx = this.pfx;
+ switch(s) {
+ case 'selected':
+ this.$el.addClass(pfx + 'selected');
+ break;
+ case 'moving':
+ break;
+ default:
+ this.$el.removeClass(pfx + 'selected');
+ }
+ },
+
+ /**
+ * Get classes from attributes.
+ * This method is called before initialize
+ *
+ * @return {Array}|null
+ * @private
+ * */
+ getClasses: function(){
+ var attr = this.model.get("attributes"),
+ classes = attr['class'] || [];
+ if(classes.length){
+ return classes.join(" ");
+ }else
+ return null;
+ },
+
+ /**
+ * Update attributes
+ * @private
+ * */
+ updateAttributes: function(){
+ var attributes = {},
+ attr = this.model.get("attributes");
+ for(var key in attr) {
+ if(attr.hasOwnProperty(key))
+ attributes[key] = attr[key];
+ }
+ // Update src
+ if(this.model.get("src"))
+ attributes.src = this.model.get("src");
+
+ var styleStr = this.getStyleString();
+
+ if(styleStr)
+ attributes.style = styleStr;
+
+ this.$el.attr(attributes);
+ },
+
+ /**
+ * Update style attribute
+ * @private
+ * */
+ updateStyle: function(){
+ this.$el.attr('style', this.getStyleString());
+ },
+
+ /**
+ * Return style string
+ * @return {string}
+ * @private
+ * */
+ getStyleString: function(){
+ var style = '';
+ this.style = this.model.get('style');
+ for(var key in this.style) {
+ if(this.style.hasOwnProperty(key))
+ style += key + ':' + this.style[key] + ';';
+ }
+
+ return style;
+ },
+
+ /**
+ * Update classe attribute
+ * @private
+ * */
+ updateClasses: function(){
+ var str = '';
+
+ this.model.get('classes').each(function(model){
+ str += model.get('name') + ' ';
+ });
+ str = str.trim();
+
+ if(str)
+ this.$el.attr('class', str);
+ else
+ this.$el.removeAttr('class');
+
+ // Regenerate status class
+ this.updateStatus();
+ },
+
+ /**
+ * Reply to event call
+ * @param object Event that generated the request
+ * @private
+ * */
+ eventCall: function(event){
+ event.viewResponse = this;
+ },
+
+ /**
+ * Init component for resizing
+ */
+ initResize: function () {
+ var em = this.opts.config.em;
+ var editor = em ? em.get('Editor') : '';
+ var config = em ? em.get('Config') : '';
+ var pfx = config.stylePrefix || '';
+ var attrName = 'data-' + pfx + 'handler';
+ var resizeClass = pfx + 'resizing';
+ var model = this.model;
+ var modelToStyle;
+
+ var toggleBodyClass = function(method, e, opts) {
+ var handlerAttr = e.target.getAttribute(attrName);
+ var resizeHndClass = pfx + 'resizing-' + handlerAttr;
+ var classToAdd = resizeClass;// + ' ' +resizeHndClass;
+ if (opts.docs) {
+ opts.docs.find('body')[method](classToAdd);
+ }
+ };
+
+ if(editor && this.model.get('resizable')) {
+ editor.runCommand('resize', {
+ el: this.el,
+ options: {
+ onStart: function (e, opts) {
+ toggleBodyClass('addClass', e, opts);
+ modelToStyle = em.get('StyleManager').getModelToStyle(model);
+ },
+ // Update all positioned elements (eg. component toolbar)
+ onMove: function () {
+ editor.trigger('change:canvasOffset');
+ },
+ onEnd: function (e, opts) {
+ toggleBodyClass('removeClass', e, opts);
+ editor.trigger('change:canvasOffset');
+ },
+ updateTarget: function(el, rect, store) {
+ if (!modelToStyle) {
+ return;
+ }
+ var unit = 'px';
+ var style = _.clone(modelToStyle.get('style'));
+ var width = rect.w + (store ? 1 : 0);
+ style.width = width + unit;
+ style.height = rect.h + unit;
+ modelToStyle.set('style', style, {avoidStore: 1});
+ em.trigger('targetStyleUpdated');
+
+ // This trick will trigger the Undo Manager. To trigger "change:style"
+ // on the Model you need to provide a new object and after that
+ // Undo Manager will trigger only if values are different (this is why
+ // above I've added + 1 to width if store required)
+ if(store) {
+ var style3 = _.clone(style);
+ style3.width = (width - 1) + unit;
+ modelToStyle.set('style', style3);
+ }
+ }
+ }
+ });
+ }
+ },
+
+ /**
+ * Prevent default helper
+ * @param {Event} e
+ * @private
+ */
+ prevDef: function (e) {
+ e.preventDefault();
+ },
+
+ /**
+ * Render component's script
+ * @private
+ */
+ updateScript: function () {
+ var em = this.em;
+ if(em) {
+ var canvas = em.get('Canvas');
+ canvas.getCanvasView().updateScript(this);
+ }
+ },
+
+ render: function() {
+ var model = this.model;
+ this.updateAttributes();
+ this.updateClasses();
+ this.$el.html(this.model.get('content'));
+ var view = new ComponentsView({
+ collection: this.model.get('components'),
+ config: this.config,
+ defaultTypes: this.opts.defaultTypes,
+ componentTypes: this.opts.componentTypes,
+ });
+
+ // With childNodes lets avoid wrapping 'div'
+ this.$el.append(view.render(this.$el).el.childNodes);
+
+ // Render script
+ if(model.get('script')) {
+ this.updateScript();
+ }
+
+ return this;
+ },
+
+ });
});