From 2d829d390e9eceb270d2715aa2be782ff45caa8b Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Thu, 25 Feb 2016 03:13:28 +0100 Subject: [PATCH] Update Class Manager --- README.md | 23 ++++++++++++---------- src/class_manager/view/ClassTagView.js | 19 ++++++++++++++++++ src/class_manager/view/ClassTagsView.js | 8 +++----- src/code_manager/model/JsonGenerator.js | 25 ++++++++++++++++-------- src/dom_components/view/ComponentView.js | 4 ++++ src/editor/model/Editor.js | 24 +++++++++++++++++------ 6 files changed, 74 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 84075ace5..95b46aa0f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# [GrapesJS](http://grapesjs.com) [![Build Status](https://travis-ci.org/artf/grapesjs.svg?branch=master)](https://travis-ci.org/artf/grapesjs) +# [GrapesJS](http://grapesjs.com) + +[![Build Status](https://travis-ci.org/artf/grapesjs.svg?branch=master)](https://travis-ci.org/artf/grapesjs)

GrapesJS

@@ -8,7 +10,7 @@ Be aware that is not a 'Website Builder' but a tool to create only structure and Try it here: http://grapesjs.com/demo.html -### Features +## Features * Style Manager, for component styling

GrapesJS - Style Manager

@@ -27,12 +29,12 @@ Try it here: http://grapesjs.com/demo.html * Default built-in commands (basically for creating and managing different components) -### Installation +## Installation You can get GrapesJS with `bower install grapesjs` or via `git clone https://github.com/artf/grapesjs.git` to directly use it. For development purpose you should follow instructions below. -### Development +## Development GrapesJS uses [RequireJS](http://requirejs.org/) to organize its files inside `src` folder and [Grunt](http://gruntjs.com/) for build them to `dist` @@ -67,7 +69,8 @@ Tests are already available inside browser on `localhost:8000/test` If [Grunt](http://gruntjs.com/) is already installed globally you could change the port by using `grunt dev --port 9000` -### Usage +## Usage + JQuery is the only hard dependency so you have to include it before use GrapesJS. ```html @@ -92,7 +95,7 @@ Unfortunately with the configuration above you wouldn't see a lot. This because The section below will explain some basic configurations but for a more practical example I suggest to look up the code inside this demo: http://grapesjs.com/demo.html -### Configuration +## Configuration For now I only show up some general settings, for more details check source or demo. Examples will be available soon @@ -142,12 +145,12 @@ var config = { ``` -### API +## API At the moment `render()` is the only available method but others will be public very soon... -### Testing +## Testing **ATTENTION: tests are pretty far away from being complete** @@ -157,7 +160,7 @@ Tests are run by [PhantomJS](http://phantomjs.org/) using [Mocha](https://mochaj $ npm run test ``` -### Acknowledgements +## Acknowledgements GrapesJS is built on top of this amazing open source projects: @@ -169,7 +172,7 @@ GrapesJS is built on top of this amazing open source projects: * [FontAwesome] - the iconic font and CSS framework -### Contributing +## Contributing Any kind of help is welcome. At the moment there is no generic guidelines so use usual pull requests and push to `dev` branch diff --git a/src/class_manager/view/ClassTagView.js b/src/class_manager/view/ClassTagView.js index 4297f2fe8..6a379bcc5 100644 --- a/src/class_manager/view/ClassTagView.js +++ b/src/class_manager/view/ClassTagView.js @@ -7,10 +7,29 @@ define(['backbone', 'text!./../template/classTag.html'], template: _.template(tagTemplate), + events: {}, + initialize: function(o) { this.config = o.config || {}; this.pfx = this.config.stylePrefix; this.className = this.pfx + 'tag'; + this.closeId = this.pfx + 'close'; + this.events['click #' + this.closeId ] = 'removeTag'; + + this.delegateEvents(); + }, + + /** + * Remove tag from the selected component + * @param {Object} e + */ + removeTag: function(e){ + var comp = this.config.target.get('selectedComponent'); + + if(comp) + comp.get('classes').remove(this.model); + + this.remove(); }, /** @inheritdoc */ diff --git a/src/class_manager/view/ClassTagsView.js b/src/class_manager/view/ClassTagsView.js index 52a54de13..b4c40ce23 100644 --- a/src/class_manager/view/ClassTagsView.js +++ b/src/class_manager/view/ClassTagsView.js @@ -18,8 +18,8 @@ define(['backbone', 'text!./../template/classTags.html', './ClassTagView'], this.addBtnId = this.pfx + 'add-tag'; this.newInputId = this.pfx + 'new'; this.events['click #' + this.addBtnId] = 'startNewTag'; - this.events['blur #'+this.newInputId] = 'endNewTag'; - this.events['keyup #'+this.newInputId] = 'onInputKeyUp'; + this.events['blur #' + this.newInputId] = 'endNewTag'; + this.events['keyup #' + this.newInputId] = 'onInputKeyUp'; this.target = this.config.target; @@ -106,11 +106,9 @@ define(['backbone', 'text!./../template/classTags.html', './ClassTagView'], var cm = this.target.get('ClassManager'); var model = cm.addClass(name); - if(this.compTarget){ + if(this.compTarget) this.compTarget.get('classes').add(model); - } - console.log(this.compTarget); } this.endNewTag(); }, diff --git a/src/code_manager/model/JsonGenerator.js b/src/code_manager/model/JsonGenerator.js index d8920f5f7..67c2e5f61 100644 --- a/src/code_manager/model/JsonGenerator.js +++ b/src/code_manager/model/JsonGenerator.js @@ -1,21 +1,22 @@ -define(['backbone'], +define(['backbone'], function (Backbone) { /** * @class JsonGenerator * */ return Backbone.Model.extend({ - + /** @inheritdoc */ getId : function() { - return 'json'; + return 'json'; }, - + /** @inheritdoc */ build: function(model) { var json = model.toJSON(); - + this.beforeEach(json); + // Avoid jshint 'loopfunc' error _.each(json,function(v, attr){ var obj = json[attr]; @@ -30,11 +31,19 @@ define(['backbone'], }, this); } } - + }, this); - + return json; }, - + + /** + * Execute on each object + * @param {Object} obj + */ + beforeEach: function(obj) { + delete obj.status; + } + }); }); diff --git a/src/dom_components/view/ComponentView.js b/src/dom_components/view/ComponentView.js index a3c531b94..2e53786e2 100644 --- a/src/dom_components/view/ComponentView.js +++ b/src/dom_components/view/ComponentView.js @@ -113,9 +113,11 @@ define(['backbone', './ComponentsView'], * */ updateClasses: function(){ var str = ''; + this.model.get('classes').each(function(model){ str += model.get('name') + ' '; }); + this.$el.attr('class',str.trim()); // Regenerate status class @@ -132,12 +134,14 @@ define(['backbone', './ComponentsView'], render: function() { this.updateAttributes(); + this.updateClasses(); this.$el.html(this.model.get('content')); var view = new ComponentsView({ collection : this.components, config : this.config, }); this.$components = view; + // With childNodes lets avoid wrapping 'div' this.$el.append(view.render(this.$el).el.childNodes); return this; diff --git a/src/editor/model/Editor.js b/src/editor/model/Editor.js index 785087eb5..40ea36186 100644 --- a/src/editor/model/Editor.js +++ b/src/editor/model/Editor.js @@ -274,16 +274,23 @@ define([ /** * Triggered when components are updated + * @param {Object} model + * @param {Mixed} val Value + * @param {Object} opt Options * */ - componentsUpdated: function() + componentsUpdated: function(model, val, opt) { - var updatedCount = this.get('changesCount') + 1; + var updatedCount = this.get('changesCount') + 1, + avSt = opt ? opt.avoidStore : 0; this.set('changesCount', updatedCount); if(this.stm.isAutosave() && updatedCount < this.stm.getChangesBeforeSave()){ return; } - this.storeComponents(); - this.set('changesCount', 0 ); + + if(!avSt){ + this.storeComponents(); + this.set('changesCount', 0); + } }, /** @@ -338,6 +345,7 @@ define([ * */ updateComponents: function(model, val, opt){ var comps = model.get('components'), + classes = model.get('classes'), avSt = opt ? opt.avoidStore : 0; // Observe component with Undo Manager @@ -350,8 +358,12 @@ define([ this.listenTo(comps, 'add', this.updateComponents); this.listenTo(comps, 'remove', this.rmComponents); - this.stopListening(model, 'change:style change:content', this.updateComponents); - this.listenTo(model, 'change:style change:content', this.updateComponents); + this.stopListening(classes, 'add remove', this.componentsUpdated); + this.listenTo(classes, 'add remove', this.componentsUpdated); + + var evn = 'change:style change:content'; + this.stopListening(model, evn, this.componentsUpdated); + this.listenTo(model, evn, this.componentsUpdated); if(!avSt) this.componentsUpdated();