UNPKG

grapesjs_codeapps

Version:

Free and Open Source Web Builder Framework/SC Modification

190 lines (157 loc) 5.16 kB
import _ from 'underscore'; import Backbone from 'backbone'; import Styleable from 'domain_abstract/model/Styleable'; import { isEmpty, forEach } from 'underscore'; var Selectors = require('selector_manager/model/Selectors'); module.exports = Backbone.Model.extend(Styleable).extend({ defaults: { // Css selectors selectors: {}, // Additional string css selectors selectorsAdd: '', // Css properties style style: {}, // On which device width this rule should be rendered, eg. @media (max-width: 1000px) mediaText: '', // State of the rule, eg: hover | pressed | focused state: '', // Indicates if the rule is stylable stylable: true, // Type of at-rule, eg. 'media', 'font-face', etc. atRuleType: '', // This particolar property is used only on at-rules, like 'page' or // 'font-face', where the block containes only style declarations singleAtRule: 0, // If true, sets '!important' on all properties // You can use an array to specify properties to set important // Used in view important: 0 }, initialize(c, opt = {}) { this.config = c || {}; const em = opt.em; let selectors = this.config.selectors || []; this.em = em; if (em) { const sm = em.get('SelectorManager'); const slct = []; selectors.forEach(selector => { slct.push(sm.add(selector)); }); selectors = slct; } this.set('selectors', new Selectors(selectors)); }, /** * Returns an at-rule statement if possible, eg. '@media (...)', '@keyframes' * @return {string} */ getAtRule() { const type = this.get('atRuleType'); const condition = this.get('mediaText'); // Avoid breaks with the last condition const typeStr = type ? `@${type}` : condition ? '@media' : ''; return typeStr + (condition && typeStr ? ` ${condition}` : ''); }, /** * Return selectors fo the rule as a string * @return {string} */ selectorsToString(opts = {}) { const result = []; const { em } = this; const state = this.get('state'); const wrapper = this.get('wrapper'); const addSelector = this.get('selectorsAdd'); const isBody = wrapper && em && em.getConfig('wrappesIsBody'); const selectors = isBody ? 'body' : this.get('selectors').getFullString(); const stateStr = state ? `:${state}` : ''; selectors && result.push(`${selectors}${stateStr}`); addSelector && !opts.skipAdd && result.push(addSelector); return result.join(', '); }, /** * Get declaration block * @param {Object} [opts={}] Options * @return {string} */ getDeclaration(opts = {}) { let result = ''; const selectors = this.selectorsToString(); const style = this.styleToString(opts); const singleAtRule = this.get('singleAtRule'); if ((selectors || singleAtRule) && style) { result = singleAtRule ? style : `${selectors}{${style}}`; } return result; }, /** * Returns CSS string of the rule * @param {Object} [opts={}] Options * @return {string} */ toCSS(opts = {}) { let result = ''; const atRule = this.getAtRule(); const block = this.getDeclaration(opts); block && (result = block); if (atRule && result) { result = `${atRule}{${result}}`; } return result; }, toJSON(...args) { const obj = Backbone.Model.prototype.toJSON.apply(this, args); if (this.em.getConfig('avoidDefaults')) { const defaults = this.defaults; forEach(defaults, (value, key) => { if (obj[key] === value) { delete obj[key]; } }); if (isEmpty(obj.selectors)) delete obj.selectors; if (isEmpty(obj.style)) delete obj.style; } return obj; }, /** * Compare the actual model with parameters * @param {Object} selectors Collection of selectors * @param {String} state Css rule state * @param {String} width For which device this style is oriented * @param {Object} ruleProps Other rule props * @return {Boolean} * @private */ compare(selectors, state, width, ruleProps = {}) { var st = state || ''; var wd = width || ''; var selectorsAdd = ruleProps.selectorsAdd || ''; var atRuleType = ruleProps.atRuleType || ''; var cId = 'cid'; //var a1 = _.pluck(selectors.models || selectors, cId); //var a2 = _.pluck(this.get('selectors').models, cId); if (!(selectors instanceof Array) && !selectors.models) selectors = [selectors]; var a1 = _.map(selectors.models || selectors, model => model.get('name')); var a2 = _.map(this.get('selectors').models, model => model.get('name')); var f = false; if (a1.length !== a2.length) return f; for (var i = 0; i < a1.length; i++) { var re = 0; for (var j = 0; j < a2.length; j++) { if (a1[i] === a2[j]) re = 1; } if (re === 0) return f; } if ( this.get('state') !== st || this.get('mediaText') !== wd || this.get('selectorsAdd') !== selectorsAdd || this.get('atRuleType') !== atRuleType ) { return f; } return true; } });