grapesjs_codeapps
Version:
Free and Open Source Web Builder Framework/SC Modification
226 lines (197 loc) • 5.73 kB
JavaScript
/**
* Selectors in GrapesJS are used in CSS Composer inside Rules and in Components as classes. To get better this concept let's take
* a look at this code:
*
* ```css
* span > #send-btn.btn{
* ...
* }
* ```
* ```html
* <span>
* <button id="send-btn" class="btn"></button>
* </span>
* ```
*
* In this scenario we get:
* * span -> selector of type `tag`
* * send-btn -> selector of type `id`
* * btn -> selector of type `class`
*
* So, for example, being `btn` the same class entity it'll be easier to refactor and track things.
*
* You can customize the initial state of the module from the editor initialization, by passing the following [Configuration Object](https://github.com/artf/grapesjs/blob/master/src/selector_manager/config/config.js)
* ```js
* const editor = grapesjs.init({
* selectorManager: {
* // options
* }
* })
* ```
*
* Once the editor is instantiated you can use its API. Before using these methods you should get the module from the instance
*
* ```js
* const selectorManager = editor.SelectorManager;
* ```
*
* * [getConfig](#getconfig)
* * [add](#add)
* * [addClass](#addclass)
* * [get](#get)
* * [getAll](#getAll)
*
* @module SelectorManager
*/
import { isString, isElement, isObject } from 'underscore';
const isId = str => isString(str) && str[0] == '#';
const isClass = str => isString(str) && str[0] == '.';
module.exports = config => {
var c = config || {},
defaults = require('./config/config'),
Selector = require('./model/Selector'),
Selectors = require('./model/Selectors'),
ClassTagsView = require('./view/ClassTagsView');
var selectors, selectorTags;
return {
Selector,
Selectors,
/**
* Name of the module
* @type {String}
* @private
*/
name: 'SelectorManager',
/**
* Get configuration object
* @return {Object}
*/
getConfig() {
return c;
},
/**
* Initialize module. Automatically called with a new instance of the editor
* @param {Object} config Configurations
* @return {this}
* @private
*/
init(conf) {
c = conf || {};
for (var name in defaults) {
if (!(name in c)) c[name] = defaults[name];
}
const em = c.em;
const ppfx = c.pStylePrefix;
if (ppfx) {
c.stylePrefix = ppfx + c.stylePrefix;
}
selectorTags = new ClassTagsView({
collection: new Selectors([], { em, config: c }),
config: c
});
// Global selectors container
selectors = new Selectors(c.selectors);
selectors.on('add', model => em.trigger('selector:add', model));
return this;
},
postRender() {
const elTo = this.getConfig().appendTo;
if (elTo) {
const el = isElement(elTo) ? elTo : document.querySelector(elTo);
el.appendChild(this.render([]));
}
},
/**
* Add a new selector to collection if it's not already exists. Class type is a default one
* @param {String} name Selector name
* @param {Object} opts Selector options
* @param {String} [opts.label=''] Label for the selector, if it's not provided the label will be the same as the name
* @param {String} [opts.type=1] Type of the selector. At the moment, only 'class' (1) is available
* @return {Model}
* @example
* var selector = selectorManager.add('selectorName');
* // Same as
* var selector = selectorManager.add('selectorName', {
* type: 1,
* label: 'selectorName'
* });
* */
add(name, opts = {}) {
if (isObject(name)) {
opts = name;
} else {
opts.name = name;
}
if (isId(opts.name)) {
opts.name = opts.name.substr(1);
opts.type = Selector.TYPE_ID;
}
if (opts.label && !opts.name) {
opts.name = Selector.escapeName(opts.label);
}
const cname = opts.name;
const selector = cname
? this.get(cname, opts.type)
: selectors.where(opts)[0];
if (!selector) {
return selectors.add(opts);
}
return selector;
},
/**
* Add class selectors
* @param {Array|string} classes Array or string of classes
* @return {Array} Array of added selectors
* @example
* sm.addClass('class1');
* sm.addClass('class1 class2');
* sm.addClass(['class1', 'class2']);
* // -> [SelectorObject, ...]
*/
addClass(classes) {
const added = [];
if (isString(classes)) {
classes = classes.trim().split(' ');
}
classes.forEach(name => added.push(selectors.add({ name })));
return added;
},
/**
* Get the selector by its name
* @param {String} name Selector name
* @param {String} tyoe Selector type
* @return {Model|null}
* @example
* var selector = selectorManager.get('selectorName');
* */
get(name, type = Selector.TYPE_CLASS) {
if (isId(name)) {
name = name.substr(1);
type = Selector.TYPE_ID;
}
return selectors.where({ name, type })[0];
},
/**
* Get all selectors
* @return {Collection}
* */
getAll() {
return selectors;
},
/**
* Render class selectors. If an array of selectors is provided a new instance of the collection will be rendered
* @param {Array<Object>} selectors
* @return {HTMLElement}
* @private
*/
render(selectors) {
if (selectors) {
var view = new ClassTagsView({
collection: new Selectors(selectors),
config: c
});
return view.render().el;
} else return selectorTags.render().el;
}
};
};