mirror of https://github.com/artf/grapesjs.git
345 changed files with 20218 additions and 29374 deletions
@ -1,252 +0,0 @@ |
|||||
module.exports = function(grunt) { |
|
||||
|
|
||||
var appPath = 'src', |
|
||||
buildPath = 'dist', |
|
||||
stylePath = 'styles', |
|
||||
configPath = 'config/require-config.js', |
|
||||
port = grunt.option('port') || 8000; |
|
||||
|
|
||||
grunt.loadNpmTasks('grunt-contrib-requirejs'); |
|
||||
grunt.loadNpmTasks('grunt-contrib-connect'); |
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify'); |
|
||||
grunt.loadNpmTasks('grunt-contrib-cssmin'); |
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint'); |
|
||||
grunt.loadNpmTasks('grunt-contrib-concat'); |
|
||||
grunt.loadNpmTasks('grunt-contrib-watch'); |
|
||||
grunt.loadNpmTasks('grunt-contrib-clean'); |
|
||||
grunt.loadNpmTasks('grunt-contrib-copy'); |
|
||||
grunt.loadNpmTasks('grunt-bowercopy'); |
|
||||
grunt.loadNpmTasks('grunt-mocha'); |
|
||||
grunt.loadNpmTasks('grunt-sass'); |
|
||||
|
|
||||
grunt.initConfig({ |
|
||||
appDir: appPath, |
|
||||
builtDir: buildPath, |
|
||||
styleDir: stylePath, |
|
||||
pkg: grunt.file.readJSON("package.json"), |
|
||||
|
|
||||
requirejs:{ |
|
||||
compile:{ |
|
||||
options: { |
|
||||
mainConfigFile: '<%= appDir %>/' + configPath, |
|
||||
appDir: '<%= appDir %>', |
|
||||
dir: '<%= builtDir %>', |
|
||||
baseUrl: './', |
|
||||
name: 'main', |
|
||||
include: ["./../node_modules/almond/almond"], |
|
||||
removeCombined: true, |
|
||||
findNestedDependencies: true, |
|
||||
keepBuildDir: true, |
|
||||
inlineText: true, |
|
||||
optimize: 'none', |
|
||||
wrap: { |
|
||||
start: "(function (root, factory) {"+ |
|
||||
"if (typeof define === 'function' && define.amd)"+ |
|
||||
"define([], factory);"+ |
|
||||
"else if(typeof exports === 'object' && typeof module === 'object')"+ |
|
||||
"module.exports = factory();"+ |
|
||||
"else "+ |
|
||||
"root.<%= pkg.name %> = root.GrapesJS = factory();"+ |
|
||||
"}(this, function () {", |
|
||||
end: "return require('grapesjs/main'); }));" |
|
||||
}, |
|
||||
|
|
||||
paths: { |
|
||||
"jquery": "wrappers/jquery", |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
jshint: { |
|
||||
all: [ |
|
||||
'Gruntfile.js', |
|
||||
'<%= appDir %>/**/*.js', |
|
||||
] |
|
||||
}, |
|
||||
|
|
||||
uglify: { |
|
||||
options: { |
|
||||
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> */\n' |
|
||||
}, |
|
||||
build:{ |
|
||||
files: { |
|
||||
'<%= builtDir %>/grapes.min.js': ['<%= builtDir %>/main.js'] |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
sass: { |
|
||||
dist: { |
|
||||
files: [{ |
|
||||
expand: true, |
|
||||
cwd: '<%= styleDir %>/scss', |
|
||||
src: ['**/*.scss'], |
|
||||
dest: '<%= styleDir %>/css', |
|
||||
ext: '.css' |
|
||||
}] |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
cssmin: { |
|
||||
target: { |
|
||||
files: [{ |
|
||||
expand: true, |
|
||||
flatten: true, |
|
||||
src: [ |
|
||||
'<%= styleDir %>/css/main.css', |
|
||||
'node_modules/codemirror/lib/codemirror.css', |
|
||||
'node_modules/codemirror/theme/hopscotch.css' |
|
||||
], |
|
||||
dest: '<%= builtDir %>', |
|
||||
ext: '.min.css' |
|
||||
}] |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
concat: { |
|
||||
css: { |
|
||||
src: ['<%= builtDir %>/*.min.css'], |
|
||||
dest: '<%= builtDir %>/css/grapes.min.css' |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
mocha: { |
|
||||
test: { |
|
||||
src: ['test/index.html'], |
|
||||
options: { log: true, }, |
|
||||
}, |
|
||||
}, |
|
||||
|
|
||||
connect: { |
|
||||
server: { |
|
||||
options: { |
|
||||
port: port, |
|
||||
open: true |
|
||||
} |
|
||||
}, |
|
||||
}, |
|
||||
/* |
|
||||
bowercopy: { |
|
||||
options: { |
|
||||
srcPrefix: 'bower_components' |
|
||||
}, |
|
||||
scripts: { |
|
||||
options: { |
|
||||
destPrefix: 'vendor' |
|
||||
}, |
|
||||
files: { |
|
||||
'almond/almond.js' : 'almond/almond.js', |
|
||||
'jquery/jquery.js' : 'jquery/dist/jquery.min.js', |
|
||||
'underscore/underscore.js' : 'underscore/underscore-min.js', |
|
||||
'backbone/backbone.js' : 'backbone/backbone-min.js', |
|
||||
'backbone-undo/backbone-undo.js' : 'Backbone.Undo/Backbone.Undo.js', |
|
||||
'keymaster/keymaster.js' : 'keymaster/keymaster.js', |
|
||||
'require/require.js' : 'requirejs/require.js', |
|
||||
'require-text/text.js' : 'requirejs-text/text.js', |
|
||||
'spectrum/spectrum.js' : 'spectrum/spectrum.js', |
|
||||
'codemirror' : 'codemirror', |
|
||||
'codemirror-formatting' : 'codemirror-formatting/formatting.js', |
|
||||
'mocha' : 'mocha', |
|
||||
'chai' : 'chai/chai.js', |
|
||||
'sinon' : 'sinonjs/sinon.js', |
|
||||
}, |
|
||||
} |
|
||||
}, |
|
||||
*/ |
|
||||
watch: { |
|
||||
script: { |
|
||||
files: [ '<%= appDir %>/**/*.js' ], |
|
||||
tasks: ['jshint'] |
|
||||
}, |
|
||||
css: { |
|
||||
files: '**/*.scss', |
|
||||
tasks: ['sass'] |
|
||||
}, |
|
||||
test: { |
|
||||
files: ['test/specs/**/*.js'], |
|
||||
tasks: ['mocha'], |
|
||||
//options: { livereload: true }, //default port 35729
|
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
clean: { |
|
||||
all: ["<%= builtDir %>/*", "!<%= builtDir %>/grapes.min.js", "!<%= builtDir %>/css"] |
|
||||
}, |
|
||||
|
|
||||
copy: { |
|
||||
fonts: { |
|
||||
cwd: '<%= styleDir %>/fonts', |
|
||||
src: '**/*', |
|
||||
dest: '<%= builtDir %>/fonts', |
|
||||
expand: true |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
/** |
|
||||
* Have to copy require configs cause r.js will try to load them from the path indicated inside |
|
||||
* main.js file. This is the only way I have found to do it |
|
||||
* */ |
|
||||
grunt.registerTask('before-rjs', function() { |
|
||||
if(grunt.file.exists(buildPath)) |
|
||||
grunt.file.delete(buildPath); |
|
||||
grunt.file.mkdir(buildPath); |
|
||||
grunt.file.copy(appPath + '/' + configPath, buildPath + '/' + appPath + '/' + configPath); |
|
||||
}); |
|
||||
|
|
||||
grunt.registerTask('webfont-custom', function() { |
|
||||
var dir = './styles/fonts/'; |
|
||||
var destName = 'main-fonts'; |
|
||||
var donePromise = this.async(); |
|
||||
var svg2ttf = { |
|
||||
cmd: 'svg2ttf', |
|
||||
args: [dir + destName + '.svg', dir + destName + '.ttf'], |
|
||||
}; |
|
||||
var ttf2woff = { |
|
||||
cmd: 'ttf2woff', |
|
||||
args: [dir + destName + '.ttf', dir + destName + '.woff'], |
|
||||
}; |
|
||||
var ttf2woff2 = { |
|
||||
cmd: 'cat', |
|
||||
//args: [dir + destName + '.ttf', dir + destName + '.woff2'],
|
|
||||
args: [dir + destName + '.ttf', '|', 'ttf2woff2', '>>', dir + destName + '.woff2'], |
|
||||
}; |
|
||||
var ttf2eot = { |
|
||||
cmd: 'ttf2eot', |
|
||||
args: [dir + destName + '.ttf', dir + destName + '.eot'], |
|
||||
}; |
|
||||
grunt.util.spawn(svg2ttf, function done(error, result, code) { |
|
||||
grunt.log.ok('.ttf file created'); |
|
||||
|
|
||||
grunt.util.spawn(ttf2woff, function done(error, result, code) { |
|
||||
grunt.log.ok('.woff file created'); |
|
||||
|
|
||||
grunt.util.spawn(ttf2eot, function done(error, result, code) { |
|
||||
grunt.log.ok('.eot file created'); |
|
||||
donePromise(); |
|
||||
/* |
|
||||
grunt.util.spawn(ttf2woff2, function done(error, result, code) { |
|
||||
grunt.log.ok('.woff2 file created'); |
|
||||
donePromise(); |
|
||||
}); |
|
||||
*/ |
|
||||
}); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
grunt.registerTask('dev', ['connect', 'watch']); |
|
||||
|
|
||||
grunt.registerTask('test', ['jshint', 'mocha']); |
|
||||
|
|
||||
grunt.registerTask('build:fonts', ['webfont-custom']); |
|
||||
|
|
||||
grunt.registerTask('build', ['jshint', 'sass', 'before-rjs', 'requirejs', 'uglify', 'cssmin', 'concat', 'clean', 'copy']); |
|
||||
|
|
||||
grunt.registerTask('default', ['dev']); |
|
||||
|
|
||||
}; |
|
||||
@ -1,53 +0,0 @@ |
|||||
{ |
|
||||
"name": "grapesjs", |
|
||||
"description": "Open source Web Template Editor", |
|
||||
"version": "0.5.41", |
|
||||
"author": "Artur Arseniev", |
|
||||
"homepage": "http://grapesjs.com", |
|
||||
"main": [ |
|
||||
"dist/grapes.min.js", |
|
||||
"dist/grapes.min.css" |
|
||||
], |
|
||||
"keywords": [ |
|
||||
"grapes", |
|
||||
"wte", |
|
||||
"web template editor", |
|
||||
"site builder", |
|
||||
"newsletter builder", |
|
||||
"wysiwyg", |
|
||||
"template", |
|
||||
"editor" |
|
||||
], |
|
||||
"license": "BSD-3-Clause", |
|
||||
"ignore": [ |
|
||||
"**/.*", |
|
||||
"styles", |
|
||||
"src", |
|
||||
"test", |
|
||||
"Gruntfile.js", |
|
||||
"index.html", |
|
||||
"README.md", |
|
||||
"package.json" |
|
||||
], |
|
||||
"dependencies": { |
|
||||
"jquery": "~2.2.0" |
|
||||
}, |
|
||||
"devDependencies": { |
|
||||
"mocha": "~2.3.4", |
|
||||
"chai": "~3.4.2", |
|
||||
"sinonjs": "~1.17.1", |
|
||||
"backbone": "~1.2.3", |
|
||||
"Backbone.Undo": "~0.2.5", |
|
||||
"keymaster": "~1.6.3", |
|
||||
"requirejs": "~2.1.22", |
|
||||
"requirejs-text": "~2.0.14", |
|
||||
"spectrum": "~1.8.0", |
|
||||
"underscore": "~1.8.3", |
|
||||
"codemirror": "~5.10.0", |
|
||||
"codemirror-formatting": "*", |
|
||||
"almond": "~0.3.1" |
|
||||
}, |
|
||||
"resolutions": { |
|
||||
"backbone": "~1.2.3" |
|
||||
} |
|
||||
} |
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,18 +1,16 @@ |
|||||
define(function () { |
module.exports = { |
||||
return { |
// Default assets
|
||||
// Default assets
|
assets: [], |
||||
assets: [], |
|
||||
|
|
||||
// Style prefix
|
// Style prefix
|
||||
stylePrefix: 'am-', |
stylePrefix: 'am-', |
||||
|
|
||||
// Url where uploads will be send, set false to disable upload
|
// Url where uploads will be send, set false to disable upload
|
||||
upload: 'http://localhost/assets/upload', |
upload: 'http://localhost/assets/upload', |
||||
|
|
||||
// Text on upload input
|
// Text on upload input
|
||||
uploadText: 'Drop files here or click to upload', |
uploadText: 'Drop files here or click to upload', |
||||
|
|
||||
// Label for the add button
|
// Label for the add button
|
||||
addBtnText: 'Add image', |
addBtnText: 'Add image', |
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -0,0 +1,239 @@ |
|||||
|
/** |
||||
|
* * [add](#add) |
||||
|
* * [get](#get) |
||||
|
* * [getAll](#getall) |
||||
|
* * [remove](#remove) |
||||
|
* * [store](#store) |
||||
|
* * [load](#load) |
||||
|
* * [onClick](#onClick) |
||||
|
* * [onDblClick](#onDblClick) |
||||
|
* |
||||
|
* Before using this methods you should get first the module from the editor instance, in this way: |
||||
|
* |
||||
|
* ```js
|
||||
|
* var assetManager = editor.AssetManager; |
||||
|
* ``` |
||||
|
* |
||||
|
* @module AssetManager |
||||
|
* @param {Object} config Configurations |
||||
|
* @param {Array<Object>} [config.assets=[]] Default assets |
||||
|
* @param {String} [config.uploadText='Drop files here or click to upload'] Upload text |
||||
|
* @param {String} [config.addBtnText='Add image'] Text for the add button |
||||
|
* @param {String} [config.upload=''] Where to send upload data. Expects as return a JSON with asset/s object |
||||
|
* as: {data: [{src:'...'}, {src:'...'}]} |
||||
|
* @return {this} |
||||
|
* @example |
||||
|
* ... |
||||
|
* { |
||||
|
* assets: [ |
||||
|
* {src:'path/to/image.png'}, |
||||
|
* ... |
||||
|
* ], |
||||
|
* upload: 'http://dropbox/path', // Set to false to disable it
|
||||
|
* uploadText: 'Drop files here or click to upload', |
||||
|
* } |
||||
|
*/ |
||||
|
|
||||
|
module.exports = () => { |
||||
|
var c = {}, |
||||
|
Assets = require('./model/Assets'), |
||||
|
AssetsView = require('./view/AssetsView'), |
||||
|
FileUpload = require('./view/FileUploader'), |
||||
|
assets, am, fu; |
||||
|
|
||||
|
return { |
||||
|
|
||||
|
/** |
||||
|
* Name of the module |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
name: 'AssetManager', |
||||
|
|
||||
|
/** |
||||
|
* Mandatory for the storage manager |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
storageKey: 'assets', |
||||
|
|
||||
|
/** |
||||
|
* Initialize module |
||||
|
* @param {Object} config Configurations |
||||
|
* @private |
||||
|
*/ |
||||
|
init(config) { |
||||
|
c = config || {}; |
||||
|
var defaults = require('./config/config'); |
||||
|
|
||||
|
for (var name in defaults) { |
||||
|
if (!(name in c)) |
||||
|
c[name] = defaults[name]; |
||||
|
} |
||||
|
|
||||
|
var ppfx = c.pStylePrefix; |
||||
|
if(ppfx) |
||||
|
c.stylePrefix = ppfx + c.stylePrefix; |
||||
|
|
||||
|
assets = new Assets(c.assets); |
||||
|
var obj = { |
||||
|
collection: assets, |
||||
|
config: c, |
||||
|
}; |
||||
|
am = new AssetsView(obj); |
||||
|
fu = new FileUpload(obj); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new asset/s to the collection. URLs are supposed to be unique |
||||
|
* @param {string|Object|Array<string>|Array<Object>} asset URL strings or an objects representing the resource. |
||||
|
* @return {Model} |
||||
|
* @example |
||||
|
* // In case of strings, would be interpreted as images
|
||||
|
* assetManager.add('http://img.jpg'); |
||||
|
* assetManager.add(['http://img.jpg', './path/to/img.png']); |
||||
|
* |
||||
|
* // Using objects you could indicate the type and other meta informations
|
||||
|
* assetManager.add({ |
||||
|
* src: 'http://img.jpg', |
||||
|
* //type: 'image', //image is default
|
||||
|
* height: 300, |
||||
|
* width: 200, |
||||
|
* }); |
||||
|
* assetManager.add([{ |
||||
|
* src: 'http://img.jpg', |
||||
|
* },{ |
||||
|
* src: './path/to/img.png', |
||||
|
* }]); |
||||
|
*/ |
||||
|
add(asset) { |
||||
|
return assets.add(asset); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns the asset by URL |
||||
|
* @param {string} src URL of the asset |
||||
|
* @return {Object} Object representing the asset |
||||
|
* @example |
||||
|
* var asset = assetManager.get('http://img.jpg'); |
||||
|
*/ |
||||
|
get(src) { |
||||
|
return assets.where({src})[0]; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Return all assets |
||||
|
* @return {Collection} |
||||
|
*/ |
||||
|
getAll() { |
||||
|
return assets; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Remove the asset by its URL |
||||
|
* @param {string} src URL of the asset |
||||
|
* @return {this} |
||||
|
* @example |
||||
|
* assetManager.remove('http://img.jpg'); |
||||
|
*/ |
||||
|
remove(src) { |
||||
|
var asset = this.get(src); |
||||
|
this.getAll().remove(asset); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Store assets data to the selected storage |
||||
|
* @param {Boolean} noStore If true, won't store |
||||
|
* @return {Object} Data to store |
||||
|
* @example |
||||
|
* var assets = assetManager.store(); |
||||
|
*/ |
||||
|
store(noStore) { |
||||
|
var obj = {}; |
||||
|
var assets = JSON.stringify(this.getAll().toJSON()); |
||||
|
obj[this.storageKey] = assets; |
||||
|
if(!noStore && c.stm) |
||||
|
c.stm.store(obj); |
||||
|
return obj; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Load data from the passed object, if the object is empty will try to fetch them |
||||
|
* autonomously from the storage manager. |
||||
|
* The fetched data will be added to the collection |
||||
|
* @param {Object} data Object of data to load |
||||
|
* @return {Object} Loaded assets |
||||
|
* @example |
||||
|
* var assets = assetManager.load(); |
||||
|
* // The format below will be used by the editor model
|
||||
|
* // to load automatically all the stuff
|
||||
|
* var assets = assetManager.load({ |
||||
|
* assets: [...] |
||||
|
* }); |
||||
|
* |
||||
|
*/ |
||||
|
load(data) { |
||||
|
var d = data || ''; |
||||
|
var name = this.storageKey; |
||||
|
if(!d && c.stm) |
||||
|
d = c.stm.load(name); |
||||
|
var assets = []; |
||||
|
try{ |
||||
|
assets = JSON.parse(d[name]); |
||||
|
}catch(err){} |
||||
|
this.getAll().add(assets); |
||||
|
return assets; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Render assets |
||||
|
* @param {Boolean} f Force to render, otherwise cached version will be returned |
||||
|
* @return {HTMLElement} |
||||
|
* @private |
||||
|
*/ |
||||
|
render(f) { |
||||
|
if(!this.rendered || f) |
||||
|
this.rendered = am.render().$el.add(fu.render().$el); |
||||
|
return this.rendered; |
||||
|
}, |
||||
|
|
||||
|
//-------
|
||||
|
|
||||
|
/** |
||||
|
* Set new target |
||||
|
* @param {Object} m Model |
||||
|
* @private |
||||
|
* */ |
||||
|
setTarget(m) { |
||||
|
am.collection.target = m; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Set callback after asset was selected |
||||
|
* @param {Object} f Callback function |
||||
|
* @private |
||||
|
* */ |
||||
|
onSelect(f) { |
||||
|
am.collection.onSelect = f; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Set callback to fire when the asset is clicked |
||||
|
* @param {function} func |
||||
|
*/ |
||||
|
onClick(func) { |
||||
|
c.onClick = func; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Set callback to fire when the asset is double clicked |
||||
|
* @param {function} func |
||||
|
*/ |
||||
|
onDblClick(func) { |
||||
|
c.onDblClick = func; |
||||
|
}, |
||||
|
|
||||
|
}; |
||||
|
}; |
||||
@ -1,241 +0,0 @@ |
|||||
/** |
|
||||
* * [add](#add) |
|
||||
* * [get](#get) |
|
||||
* * [getAll](#getall) |
|
||||
* * [remove](#remove) |
|
||||
* * [store](#store) |
|
||||
* * [load](#load) |
|
||||
* * [onClick](#onClick) |
|
||||
* * [onDblClick](#onDblClick) |
|
||||
* |
|
||||
* Before using this methods you should get first the module from the editor instance, in this way: |
|
||||
* |
|
||||
* ```js
|
|
||||
* var assetManager = editor.AssetManager; |
|
||||
* ``` |
|
||||
* |
|
||||
* @module AssetManager |
|
||||
* @param {Object} config Configurations |
|
||||
* @param {Array<Object>} [config.assets=[]] Default assets |
|
||||
* @param {String} [config.uploadText='Drop files here or click to upload'] Upload text |
|
||||
* @param {String} [config.addBtnText='Add image'] Text for the add button |
|
||||
* @param {String} [config.upload=''] Where to send upload data. Expects as return a JSON with asset/s object |
|
||||
* as: {data: [{src:'...'}, {src:'...'}]} |
|
||||
* @return {this} |
|
||||
* @example |
|
||||
* ... |
|
||||
* { |
|
||||
* assets: [ |
|
||||
* {src:'path/to/image.png'}, |
|
||||
* ... |
|
||||
* ], |
|
||||
* upload: 'http://dropbox/path', // Set to false to disable it
|
|
||||
* uploadText: 'Drop files here or click to upload', |
|
||||
* } |
|
||||
*/ |
|
||||
define(function(require) { |
|
||||
|
|
||||
return function() { |
|
||||
var c = {}, |
|
||||
Assets = require('./model/Assets'), |
|
||||
AssetsView = require('./view/AssetsView'), |
|
||||
FileUpload = require('./view/FileUploader'), |
|
||||
assets, am, fu; |
|
||||
|
|
||||
return { |
|
||||
|
|
||||
/** |
|
||||
* Name of the module |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
name: 'AssetManager', |
|
||||
|
|
||||
/** |
|
||||
* Mandatory for the storage manager |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
storageKey: 'assets', |
|
||||
|
|
||||
/** |
|
||||
* Initialize module |
|
||||
* @param {Object} config Configurations |
|
||||
* @private |
|
||||
*/ |
|
||||
init: function(config){ |
|
||||
c = config || {}; |
|
||||
var defaults = require('./config/config'); |
|
||||
|
|
||||
for (var name in defaults) { |
|
||||
if (!(name in c)) |
|
||||
c[name] = defaults[name]; |
|
||||
} |
|
||||
|
|
||||
var ppfx = c.pStylePrefix; |
|
||||
if(ppfx) |
|
||||
c.stylePrefix = ppfx + c.stylePrefix; |
|
||||
|
|
||||
assets = new Assets(c.assets); |
|
||||
var obj = { |
|
||||
collection: assets, |
|
||||
config: c, |
|
||||
}; |
|
||||
am = new AssetsView(obj); |
|
||||
fu = new FileUpload(obj); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new asset/s to the collection. URLs are supposed to be unique |
|
||||
* @param {string|Object|Array<string>|Array<Object>} asset URL strings or an objects representing the resource. |
|
||||
* @return {Model} |
|
||||
* @example |
|
||||
* // In case of strings, would be interpreted as images
|
|
||||
* assetManager.add('http://img.jpg'); |
|
||||
* assetManager.add(['http://img.jpg', './path/to/img.png']); |
|
||||
* |
|
||||
* // Using objects you could indicate the type and other meta informations
|
|
||||
* assetManager.add({ |
|
||||
* src: 'http://img.jpg', |
|
||||
* //type: 'image', //image is default
|
|
||||
* height: 300, |
|
||||
* width: 200, |
|
||||
* }); |
|
||||
* assetManager.add([{ |
|
||||
* src: 'http://img.jpg', |
|
||||
* },{ |
|
||||
* src: './path/to/img.png', |
|
||||
* }]); |
|
||||
*/ |
|
||||
add: function(asset){ |
|
||||
return assets.add(asset); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns the asset by URL |
|
||||
* @param {string} src URL of the asset |
|
||||
* @return {Object} Object representing the asset |
|
||||
* @example |
|
||||
* var asset = assetManager.get('http://img.jpg'); |
|
||||
*/ |
|
||||
get: function(src){ |
|
||||
return assets.where({src: src})[0]; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Return all assets |
|
||||
* @return {Collection} |
|
||||
*/ |
|
||||
getAll: function(){ |
|
||||
return assets; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Remove the asset by its URL |
|
||||
* @param {string} src URL of the asset |
|
||||
* @return {this} |
|
||||
* @example |
|
||||
* assetManager.remove('http://img.jpg'); |
|
||||
*/ |
|
||||
remove: function(src){ |
|
||||
var asset = this.get(src); |
|
||||
this.getAll().remove(asset); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Store assets data to the selected storage |
|
||||
* @param {Boolean} noStore If true, won't store |
|
||||
* @return {Object} Data to store |
|
||||
* @example |
|
||||
* var assets = assetManager.store(); |
|
||||
*/ |
|
||||
store: function(noStore){ |
|
||||
var obj = {}; |
|
||||
var assets = JSON.stringify(this.getAll().toJSON()); |
|
||||
obj[this.storageKey] = assets; |
|
||||
if(!noStore && c.stm) |
|
||||
c.stm.store(obj); |
|
||||
return obj; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Load data from the passed object, if the object is empty will try to fetch them |
|
||||
* autonomously from the storage manager. |
|
||||
* The fetched data will be added to the collection |
|
||||
* @param {Object} data Object of data to load |
|
||||
* @return {Object} Loaded assets |
|
||||
* @example |
|
||||
* var assets = assetManager.load(); |
|
||||
* // The format below will be used by the editor model
|
|
||||
* // to load automatically all the stuff
|
|
||||
* var assets = assetManager.load({ |
|
||||
* assets: [...] |
|
||||
* }); |
|
||||
* |
|
||||
*/ |
|
||||
load: function(data){ |
|
||||
var d = data || ''; |
|
||||
var name = this.storageKey; |
|
||||
if(!d && c.stm) |
|
||||
d = c.stm.load(name); |
|
||||
var assets = []; |
|
||||
try{ |
|
||||
assets = JSON.parse(d[name]); |
|
||||
}catch(err){} |
|
||||
this.getAll().add(assets); |
|
||||
return assets; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Render assets |
|
||||
* @param {Boolean} f Force to render, otherwise cached version will be returned |
|
||||
* @return {HTMLElement} |
|
||||
* @private |
|
||||
*/ |
|
||||
render: function(f){ |
|
||||
if(!this.rendered || f) |
|
||||
this.rendered = am.render().$el.add(fu.render().$el); |
|
||||
return this.rendered; |
|
||||
}, |
|
||||
|
|
||||
//-------
|
|
||||
|
|
||||
/** |
|
||||
* Set new target |
|
||||
* @param {Object} m Model |
|
||||
* @private |
|
||||
* */ |
|
||||
setTarget: function(m){ |
|
||||
am.collection.target = m; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Set callback after asset was selected |
|
||||
* @param {Object} f Callback function |
|
||||
* @private |
|
||||
* */ |
|
||||
onSelect: function(f){ |
|
||||
am.collection.onSelect = f; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Set callback to fire when the asset is clicked |
|
||||
* @param {function} func |
|
||||
*/ |
|
||||
onClick: function(func) { |
|
||||
c.onClick = func; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Set callback to fire when the asset is double clicked |
|
||||
* @param {function} func |
|
||||
*/ |
|
||||
onDblClick: function(func) { |
|
||||
c.onDblClick = func; |
|
||||
}, |
|
||||
|
|
||||
}; |
|
||||
}; |
|
||||
}); |
|
||||
@ -1,31 +1,30 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function (Backbone) { |
|
||||
return Backbone.Model.extend({ |
|
||||
|
|
||||
idAttribute: 'src', |
module.exports = Backbone.Model.extend({ |
||||
|
|
||||
defaults: { |
idAttribute: 'src', |
||||
type: '', |
|
||||
src: '', |
|
||||
}, |
|
||||
|
|
||||
/** |
defaults: { |
||||
* Get filename of the asset |
type: '', |
||||
* @return {string} |
src: '', |
||||
* @private |
}, |
||||
* */ |
|
||||
getFilename: function(){ |
|
||||
return this.get('src').split('/').pop(); |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Get extension of the asset |
* Get filename of the asset |
||||
* @return {string} |
* @return {string} |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
getExtension: function(){ |
getFilename() { |
||||
return this.getFilename().split('.').pop(); |
return this.get('src').split('/').pop(); |
||||
}, |
}, |
||||
|
|
||||
|
/** |
||||
|
* Get extension of the asset |
||||
|
* @return {string} |
||||
|
* @private |
||||
|
* */ |
||||
|
getExtension() { |
||||
|
return this.getFilename().split('.').pop(); |
||||
|
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,13 +1,13 @@ |
|||||
define(['backbone', './Asset'], |
var Backbone = require('backbone'); |
||||
function (Backbone, Asset) { |
var Asset = require('./Asset'); |
||||
return Asset.extend({ |
|
||||
|
|
||||
defaults: _.extend({}, Asset.prototype.defaults, { |
module.exports = Asset.extend({ |
||||
type: 'image', |
|
||||
unitDim: 'px', |
defaults: _.extend({}, Asset.prototype.defaults, { |
||||
height: 0, |
type: 'image', |
||||
width: 0, |
unitDim: 'px', |
||||
}), |
height: 0, |
||||
|
width: 0, |
||||
|
}), |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,67 +1,68 @@ |
|||||
define(['backbone', './Asset', './AssetImage'], |
var Backbone = require('backbone'); |
||||
function (Backbone, Asset, AssetImage) { |
var Asset = require('./Asset'); |
||||
return Backbone.Collection.extend({ |
var AssetImage = require('./AssetImage'); |
||||
|
|
||||
model: AssetImage, |
module.exports = Backbone.Collection.extend({ |
||||
|
|
||||
initialize: function(models, opt){ |
model: AssetImage, |
||||
|
|
||||
this.model = function(attrs, options) { |
initialize(models, opt) { |
||||
var model; |
|
||||
switch(attrs.type){ |
this.model = (attrs, options) => { |
||||
default: |
var model; |
||||
model = new AssetImage(attrs, options); |
switch(attrs.type){ |
||||
} |
default: |
||||
return model; |
model = new AssetImage(attrs, options); |
||||
}; |
} |
||||
|
return model; |
||||
}, |
}; |
||||
|
|
||||
/** |
}, |
||||
* Add new image asset to the collection |
|
||||
* @param {string} url URL of the image |
/** |
||||
* @param {Object} opts Options |
* Add new image asset to the collection |
||||
* @return {this} |
* @param {string} url URL of the image |
||||
* @private |
* @param {Object} opts Options |
||||
*/ |
* @return {this} |
||||
addImg: function(url, opts){ |
* @private |
||||
this.add({ |
*/ |
||||
type: 'image', |
addImg(url, opts) { |
||||
src: url, |
this.add({ |
||||
}, opts); |
type: 'image', |
||||
return this; |
src: url, |
||||
}, |
}, opts); |
||||
|
return this; |
||||
/** |
}, |
||||
* Prevent inserting assets with the same 'src' |
|
||||
* Seems like idAttribute is not working with dynamic model assignament |
/** |
||||
* @private |
* Prevent inserting assets with the same 'src' |
||||
*/ |
* Seems like idAttribute is not working with dynamic model assignament |
||||
add: function(models, opt) { |
* @private |
||||
var mods = []; |
*/ |
||||
models = models instanceof Array ? models : [models]; |
add(models, opt) { |
||||
|
var mods = []; |
||||
for (var i = 0, len = models.length; i < len; i++) { |
models = models instanceof Array ? models : [models]; |
||||
var model = models[i]; |
|
||||
|
for (var i = 0, len = models.length; i < len; i++) { |
||||
if(typeof model === 'string') |
var model = models[i]; |
||||
model = {src: model, type: 'image'}; |
|
||||
|
if(typeof model === 'string') |
||||
if(!model || !model.src) |
model = {src: model, type: 'image'}; |
||||
continue; |
|
||||
|
if(!model || !model.src) |
||||
var found = this.where({src: model.src}); |
continue; |
||||
|
|
||||
if(!found.length) |
var found = this.where({src: model.src}); |
||||
mods.push(model); |
|
||||
} |
if(!found.length) |
||||
|
mods.push(model); |
||||
if(mods.length == 1) |
} |
||||
mods = mods[0]; |
|
||||
|
if(mods.length == 1) |
||||
return Backbone.Collection.prototype.add.apply(this, [mods, opt]); |
mods = mods[0]; |
||||
}, |
|
||||
|
return Backbone.Collection.prototype.add.apply(this, [mods, opt]); |
||||
|
}, |
||||
}); |
|
||||
|
|
||||
}); |
}); |
||||
|
|||||
@ -1,10 +0,0 @@ |
|||||
<div id="<%= pfx %>preview-cont"> |
|
||||
<div id="<%= pfx %>preview" style="background-image: url(<%= src %>);"></div> |
|
||||
<div id="<%= pfx %>preview-bg" class="<%= ppfx %>checker-bg"></div> |
|
||||
</div> |
|
||||
<div id="<%= pfx %>meta"> |
|
||||
<div id="<%= pfx %>name"><%= name %></div> |
|
||||
<div id="<%= pfx %>dimensions"><%= dim %></div> |
|
||||
</div> |
|
||||
<div id="<%= pfx %>close">⨯</div> |
|
||||
<div style="clear:both"></div> |
|
||||
@ -1,17 +0,0 @@ |
|||||
<div class="<%= pfx %>assets-cont"> |
|
||||
<div class="<%= pfx %>assets-header"> |
|
||||
<form class="<%= pfx %>add-asset"> |
|
||||
<div class="<%= ppfx %>field <%= pfx %>add-field"> |
|
||||
<input placeholder="http://path/to/the/image.jpg"/> |
|
||||
</div> |
|
||||
<button class="<%= ppfx %>btn-prim"><%= btnText %></button> |
|
||||
<div style="clear:both"></div> |
|
||||
</form> |
|
||||
<div class="<%= pfx %>dips" style="display:none"> |
|
||||
<button class="fa fa-th <%= ppfx %>btnt"></button> |
|
||||
<button class="fa fa-th-list <%= ppfx %>btnt"></button> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="<%= pfx %>assets"></div> |
|
||||
<div style="clear:both"></div> |
|
||||
</div> |
|
||||
@ -1,5 +0,0 @@ |
|||||
<form> |
|
||||
<div id="<%= pfx %>title"><%= title %></div> |
|
||||
<input type="file" id="<%= uploadId %>" name="file" accept="image/*" <%= disabled ? 'disabled' : '' %> multiple/> |
|
||||
<div style="clear:both;"></div> |
|
||||
</form> |
|
||||
@ -1,97 +1,108 @@ |
|||||
define(['./AssetView','text!./../template/assetImage.html'], |
var AssetView = require('./AssetView'); |
||||
function (AssetView, assetTemplate) { |
var assetTemplate = ` |
||||
return AssetView.extend({ |
<div id="<%= pfx %>preview-cont"> |
||||
|
<div id="<%= pfx %>preview" style="background-image: url(<%= src %>);"></div> |
||||
|
<div id="<%= pfx %>preview-bg" class="<%= ppfx %>checker-bg"></div> |
||||
|
</div> |
||||
|
<div id="<%= pfx %>meta"> |
||||
|
<div id="<%= pfx %>name"><%= name %></div> |
||||
|
<div id="<%= pfx %>dimensions"><%= dim %></div> |
||||
|
</div> |
||||
|
<div id="<%= pfx %>close">⨯</div> |
||||
|
<div style="clear:both"></div> |
||||
|
`;
|
||||
|
|
||||
events:{ |
module.exports = AssetView.extend({ |
||||
'click': 'handleClick', |
|
||||
'dblclick': 'handleDblClick', |
|
||||
}, |
|
||||
|
|
||||
template: _.template(assetTemplate), |
events:{ |
||||
|
'click': 'handleClick', |
||||
|
'dblclick': 'handleDblClick', |
||||
|
}, |
||||
|
|
||||
initialize: function(o) { |
template: _.template(assetTemplate), |
||||
AssetView.prototype.initialize.apply(this, arguments); |
|
||||
this.className += ' ' + this.pfx + 'asset-image'; |
|
||||
this.events['click #' + this.pfx + 'close'] = 'removeItem'; |
|
||||
this.delegateEvents(); |
|
||||
}, |
|
||||
|
|
||||
/** |
initialize(o) { |
||||
* Trigger when the asset is clicked |
AssetView.prototype.initialize.apply(this, arguments); |
||||
* @private |
this.className += ' ' + this.pfx + 'asset-image'; |
||||
* */ |
this.events['click #' + this.pfx + 'close'] = 'removeItem'; |
||||
handleClick: function() { |
this.delegateEvents(); |
||||
var onClick = this.config.onClick; |
}, |
||||
var model = this.model; |
|
||||
model.collection.trigger('deselectAll'); |
|
||||
this.$el.addClass(this.pfx + 'highlight'); |
|
||||
|
|
||||
if (typeof onClick === 'function') { |
/** |
||||
onClick(model); |
* Trigger when the asset is clicked |
||||
} else { |
* @private |
||||
this.updateTarget(model.get('src')); |
* */ |
||||
} |
handleClick() { |
||||
}, |
var onClick = this.config.onClick; |
||||
|
var model = this.model; |
||||
|
model.collection.trigger('deselectAll'); |
||||
|
this.$el.addClass(this.pfx + 'highlight'); |
||||
|
|
||||
/** |
if (typeof onClick === 'function') { |
||||
* Trigger when the asset is double clicked |
onClick(model); |
||||
* @private |
} else { |
||||
* */ |
this.updateTarget(model.get('src')); |
||||
handleDblClick: function() { |
} |
||||
var onDblClick = this.config.onDblClick; |
}, |
||||
var model = this.model; |
|
||||
|
|
||||
if (typeof onDblClick === 'function') { |
/** |
||||
onDblClick(model); |
* Trigger when the asset is double clicked |
||||
} else { |
* @private |
||||
this.updateTarget(model.get('src')); |
* */ |
||||
} |
handleDblClick() { |
||||
|
var onDblClick = this.config.onDblClick; |
||||
|
var model = this.model; |
||||
|
|
||||
var onSelect = model.collection.onSelect; |
if (typeof onDblClick === 'function') { |
||||
if(typeof onSelect == 'function'){ |
onDblClick(model); |
||||
onSelect(this.model); |
} else { |
||||
} |
this.updateTarget(model.get('src')); |
||||
}, |
} |
||||
|
|
||||
/** |
var onSelect = model.collection.onSelect; |
||||
* Update target if exists |
if(typeof onSelect == 'function'){ |
||||
* @param {String} v Value |
onSelect(this.model); |
||||
* @private |
} |
||||
* */ |
}, |
||||
updateTarget: function(v){ |
|
||||
var target = this.model.collection.target; |
|
||||
if(target && target.set) { |
|
||||
var attr = _.clone( target.get('attributes') ); |
|
||||
target.set('attributes', attr ); |
|
||||
target.set('src', v ); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Remove asset from collection |
* Update target if exists |
||||
* @private |
* @param {String} v Value |
||||
* */ |
* @private |
||||
removeItem: function(e){ |
* */ |
||||
e.stopPropagation(); |
updateTarget(v) { |
||||
this.model.collection.remove(this.model); |
var target = this.model.collection.target; |
||||
}, |
if(target && target.set) { |
||||
|
var attr = _.clone( target.get('attributes') ); |
||||
|
target.set('attributes', attr ); |
||||
|
target.set('src', v ); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
render : function(){ |
/** |
||||
var name = this.model.get('name'), |
* Remove asset from collection |
||||
dim = this.model.get('width') && this.model.get('height') ? |
* @private |
||||
this.model.get('width')+' x '+this.model.get('height') : ''; |
* */ |
||||
name = name ? name : this.model.get('src').split("/").pop(); |
removeItem(e) { |
||||
name = name && name.length > 30 ? name.substring(0, 30)+'...' : name; |
e.stopPropagation(); |
||||
dim = dim ? dim + (this.model.get('unitDim') ? this.model.get('unitDim') : ' px' ) : ''; |
this.model.collection.remove(this.model); |
||||
this.$el.html( this.template({ |
}, |
||||
name: name, |
|
||||
src: this.model.get('src'), |
render() { |
||||
dim: dim, |
var name = this.model.get('name'), |
||||
pfx: this.pfx, |
dim = this.model.get('width') && this.model.get('height') ? |
||||
ppfx: this.ppfx |
this.model.get('width')+' x '+this.model.get('height') : ''; |
||||
})); |
name = name ? name : this.model.get('src').split("/").pop(); |
||||
this.$el.attr('class', this.className); |
name = name && name.length > 30 ? name.substring(0, 30)+'...' : name; |
||||
return this; |
dim = dim ? dim + (this.model.get('unitDim') ? this.model.get('unitDim') : ' px' ) : ''; |
||||
}, |
this.$el.html( this.template({ |
||||
}); |
name, |
||||
|
src: this.model.get('src'), |
||||
|
dim, |
||||
|
pfx: this.pfx, |
||||
|
ppfx: this.ppfx |
||||
|
})); |
||||
|
this.$el.attr('class', this.className); |
||||
|
return this; |
||||
|
}, |
||||
}); |
}); |
||||
|
|||||
@ -1,14 +1,12 @@ |
|||||
define(['backbone'], function (Backbone) { |
var Backbone = require('backbone'); |
||||
|
|
||||
return Backbone.View.extend({ |
|
||||
initialize: function(o) { |
|
||||
this.options = o; |
|
||||
this.config = o.config || {}; |
|
||||
this.pfx = this.config.stylePrefix || ''; |
|
||||
this.ppfx = this.config.pStylePrefix || ''; |
|
||||
this.className = this.pfx + 'asset'; |
|
||||
this.listenTo( this.model, 'destroy remove', this.remove); |
|
||||
}, |
|
||||
}); |
|
||||
|
|
||||
|
module.exports = Backbone.View.extend({ |
||||
|
initialize(o) { |
||||
|
this.options = o; |
||||
|
this.config = o.config || {}; |
||||
|
this.pfx = this.config.stylePrefix || ''; |
||||
|
this.ppfx = this.config.pStylePrefix || ''; |
||||
|
this.className = this.pfx + 'asset'; |
||||
|
this.listenTo( this.model, 'destroy remove', this.remove); |
||||
|
}, |
||||
}); |
}); |
||||
|
|||||
@ -1,131 +1,153 @@ |
|||||
define(['backbone', './AssetView', './AssetImageView', './FileUploader', 'text!./../template/assets.html'], |
var Backbone = require('backbone'); |
||||
function (Backbone, AssetView, AssetImageView, FileUploader, assetsTemplate) { |
var AssetView = require('./AssetView'); |
||||
return Backbone.View.extend({ |
var AssetImageView = require('./AssetImageView'); |
||||
|
var FileUploader = require('./FileUploader'); |
||||
template: _.template(assetsTemplate), |
var assetsTemplate = ` |
||||
|
<div class="<%= pfx %>assets-cont"> |
||||
initialize: function(o) { |
<div class="<%= pfx %>assets-header"> |
||||
this.options = o; |
<form class="<%= pfx %>add-asset"> |
||||
this.config = o.config; |
<div class="<%= ppfx %>field <%= pfx %>add-field"> |
||||
this.pfx = this.config.stylePrefix || ''; |
<input placeholder="http://path/to/the/image.jpg"/> |
||||
this.ppfx = this.config.pStylePrefix || ''; |
</div> |
||||
this.listenTo( this.collection, 'add', this.addToAsset ); |
<button class="<%= ppfx %>btn-prim"><%= btnText %></button> |
||||
this.listenTo( this.collection, 'deselectAll', this.deselectAll ); |
<div style="clear:both"></div> |
||||
this.className = this.pfx + 'assets'; |
</form> |
||||
|
<div class="<%= pfx %>dips" style="display:none"> |
||||
this.events = {}; |
<button class="fa fa-th <%= ppfx %>btnt"></button> |
||||
this.events.submit = 'addFromStr'; |
<button class="fa fa-th-list <%= ppfx %>btnt"></button> |
||||
this.delegateEvents(); |
</div> |
||||
}, |
</div> |
||||
|
<div class="<%= pfx %>assets"></div> |
||||
/** |
<div style="clear:both"></div> |
||||
* Add new asset to the collection via string |
</div> |
||||
* @param {Event} e Event object |
|
||||
* @return {this} |
`;
|
||||
* @private |
|
||||
*/ |
module.exports = Backbone.View.extend({ |
||||
addFromStr: function(e){ |
|
||||
e.preventDefault(); |
template: _.template(assetsTemplate), |
||||
|
|
||||
var input = this.getInputUrl(); |
initialize(o) { |
||||
|
this.options = o; |
||||
var url = input.value.trim(); |
this.config = o.config; |
||||
|
this.pfx = this.config.stylePrefix || ''; |
||||
if(!url) |
this.ppfx = this.config.pStylePrefix || ''; |
||||
return; |
this.listenTo( this.collection, 'add', this.addToAsset ); |
||||
|
this.listenTo( this.collection, 'deselectAll', this.deselectAll ); |
||||
this.collection.addImg(url, {at: 0}); |
this.className = this.pfx + 'assets'; |
||||
|
|
||||
this.getAssetsEl().scrollTop = 0; |
this.events = {}; |
||||
input.value = ''; |
this.events.submit = 'addFromStr'; |
||||
return this; |
this.delegateEvents(); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Returns assets element |
* Add new asset to the collection via string |
||||
* @return {HTMLElement} |
* @param {Event} e Event object |
||||
* @private |
* @return {this} |
||||
*/ |
* @private |
||||
getAssetsEl: function(){ |
*/ |
||||
//if(!this.assets) // Not able to cache as after the rerender it losses the ref
|
addFromStr(e) { |
||||
this.assets = this.el.querySelector('.' + this.pfx + 'assets'); |
e.preventDefault(); |
||||
return this.assets; |
|
||||
}, |
var input = this.getInputUrl(); |
||||
|
|
||||
/** |
var url = input.value.trim(); |
||||
* Returns input url element |
|
||||
* @return {HTMLElement} |
if(!url) |
||||
* @private |
return; |
||||
*/ |
|
||||
getInputUrl: function(){ |
this.collection.addImg(url, {at: 0}); |
||||
if(!this.inputUrl || !this.inputUrl.value) |
|
||||
this.inputUrl = this.el.querySelector('.'+this.pfx+'add-asset input'); |
this.getAssetsEl().scrollTop = 0; |
||||
return this.inputUrl; |
input.value = ''; |
||||
}, |
return this; |
||||
|
}, |
||||
/** |
|
||||
* Add asset to collection |
/** |
||||
* @private |
* Returns assets element |
||||
* */ |
* @return {HTMLElement} |
||||
addToAsset: function(model){ |
* @private |
||||
this.addAsset(model); |
*/ |
||||
}, |
getAssetsEl() { |
||||
|
//if(!this.assets) // Not able to cache as after the rerender it losses the ref
|
||||
/** |
this.assets = this.el.querySelector('.' + this.pfx + 'assets'); |
||||
* Add new asset to collection |
return this.assets; |
||||
* @param Object Model |
}, |
||||
* @param Object Fragment collection |
|
||||
* @return Object Object created |
/** |
||||
* @private |
* Returns input url element |
||||
* */ |
* @return {HTMLElement} |
||||
addAsset: function(model, fragmentEl){ |
* @private |
||||
var fragment = fragmentEl || null; |
*/ |
||||
var viewObject = AssetView; |
getInputUrl() { |
||||
|
if(!this.inputUrl || !this.inputUrl.value) |
||||
if(model.get('type').indexOf("image") > -1) |
this.inputUrl = this.el.querySelector('.'+this.pfx+'add-asset input'); |
||||
viewObject = AssetImageView; |
return this.inputUrl; |
||||
|
}, |
||||
var view = new viewObject({ |
|
||||
model : model, |
/** |
||||
config : this.config, |
* Add asset to collection |
||||
}); |
* @private |
||||
var rendered = view.render().el; |
* */ |
||||
|
addToAsset(model) { |
||||
if(fragment){ |
this.addAsset(model); |
||||
fragment.appendChild( rendered ); |
}, |
||||
}else{ |
|
||||
var assetsEl = this.getAssetsEl(); |
/** |
||||
if(assetsEl) |
* Add new asset to collection |
||||
assetsEl.insertBefore(rendered, assetsEl.firstChild); |
* @param Object Model |
||||
} |
* @param Object Fragment collection |
||||
|
* @return Object Object created |
||||
return rendered; |
* @private |
||||
}, |
* */ |
||||
|
addAsset(model, fragmentEl) { |
||||
/** |
var fragment = fragmentEl || null; |
||||
* Deselect all assets |
var viewObject = AssetView; |
||||
* @private |
|
||||
* */ |
if(model.get('type').indexOf("image") > -1) |
||||
deselectAll: function(){ |
viewObject = AssetImageView; |
||||
this.$el.find('.' + this.pfx + 'highlight').removeClass(this.pfx + 'highlight'); |
|
||||
}, |
var view = new viewObject({ |
||||
|
model, |
||||
render: function() { |
config : this.config, |
||||
var fragment = document.createDocumentFragment(); |
}); |
||||
this.$el.empty(); |
var rendered = view.render().el; |
||||
|
|
||||
this.collection.each(function(model){ |
if(fragment){ |
||||
this.addAsset(model, fragment); |
fragment.appendChild( rendered ); |
||||
},this); |
}else{ |
||||
|
var assetsEl = this.getAssetsEl(); |
||||
this.$el.html(this.template({ |
if(assetsEl) |
||||
pfx: this.pfx, |
assetsEl.insertBefore(rendered, assetsEl.firstChild); |
||||
ppfx: this.ppfx, |
} |
||||
btnText: this.config.addBtnText, |
|
||||
})); |
return rendered; |
||||
|
}, |
||||
this.$el.find('.'+this.pfx + 'assets').append(fragment); |
|
||||
return this; |
/** |
||||
} |
* Deselect all assets |
||||
}); |
* @private |
||||
|
* */ |
||||
|
deselectAll() { |
||||
|
this.$el.find('.' + this.pfx + 'highlight').removeClass(this.pfx + 'highlight'); |
||||
|
}, |
||||
|
|
||||
|
render() { |
||||
|
var fragment = document.createDocumentFragment(); |
||||
|
this.$el.empty(); |
||||
|
|
||||
|
this.collection.each(function(model){ |
||||
|
this.addAsset(model, fragment); |
||||
|
},this); |
||||
|
|
||||
|
this.$el.html(this.template({ |
||||
|
pfx: this.pfx, |
||||
|
ppfx: this.ppfx, |
||||
|
btnText: this.config.addBtnText, |
||||
|
})); |
||||
|
|
||||
|
this.$el.find('.'+this.pfx + 'assets').append(fragment); |
||||
|
return this; |
||||
|
} |
||||
}); |
}); |
||||
|
|||||
@ -1,97 +1,103 @@ |
|||||
define(['backbone', 'text!./../template/fileUploader.html'], |
var Backbone = require('backbone'); |
||||
function (Backbone, fileUploaderTemplate) { |
var fileUploaderTemplate = ` |
||||
return Backbone.View.extend({ |
<form> |
||||
|
<div id="<%= pfx %>title"><%= title %></div> |
||||
|
<input type="file" id="<%= uploadId %>" name="file" accept="image/*" <%= disabled ? 'disabled' : '' %> multiple/> |
||||
|
<div style="clear:both;"></div> |
||||
|
</form> |
||||
|
`;
|
||||
|
|
||||
template: _.template(fileUploaderTemplate), |
module.exports = Backbone.View.extend({ |
||||
|
|
||||
events: {}, |
template: _.template(fileUploaderTemplate), |
||||
|
|
||||
initialize: function(o) { |
events: {}, |
||||
this.options = o || {}; |
|
||||
this.config = o.config || {}; |
|
||||
this.pfx = this.config.stylePrefix || ''; |
|
||||
this.target = this.collection || {}; |
|
||||
this.uploadId = this.pfx + 'uploadFile'; |
|
||||
this.disabled = !this.config.upload; |
|
||||
this.events['change #' + this.uploadId] = 'uploadFile'; |
|
||||
this.delegateEvents(); |
|
||||
}, |
|
||||
|
|
||||
/** |
initialize(o) { |
||||
* Upload files |
this.options = o || {}; |
||||
* @param {Object} e Event |
this.config = o.config || {}; |
||||
* @private |
this.pfx = this.config.stylePrefix || ''; |
||||
* */ |
this.target = this.collection || {}; |
||||
uploadFile : function(e){ |
this.uploadId = this.pfx + 'uploadFile'; |
||||
var files = e.dataTransfer ? e.dataTransfer.files : e.target.files, |
this.disabled = !this.config.upload; |
||||
formData = new FormData(); |
this.events['change #' + this.uploadId] = 'uploadFile'; |
||||
for (var i = 0; i < files.length; i++) { |
this.delegateEvents(); |
||||
formData.append('files[]', files[i]); |
}, |
||||
} |
|
||||
var target = this.target; |
|
||||
$.ajax({ |
|
||||
url : this.config.upload, |
|
||||
type : 'POST', |
|
||||
data : formData, |
|
||||
beforeSend : this.config.beforeSend, |
|
||||
complete : this.config.onComplete, |
|
||||
xhrFields : { |
|
||||
onprogress: function (e) { |
|
||||
if (e.lengthComputable) { |
|
||||
/*var result = e.loaded / e.total * 100 + '%';*/ |
|
||||
} |
|
||||
}, |
|
||||
onload: function (e) { |
|
||||
//progress.value = 100;
|
|
||||
} |
|
||||
}, |
|
||||
cache: false, contentType: false, processData: false |
|
||||
}).done(function(data){ |
|
||||
target.add(data.data); |
|
||||
}).always(function(){ |
|
||||
//turnOff loading
|
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Make input file droppable |
* Upload files |
||||
* @private |
* @param {Object} e Event |
||||
* */ |
* @private |
||||
initDrop: function(){ |
* */ |
||||
var that = this; |
uploadFile(e) { |
||||
if(!this.uploadForm){ |
var files = e.dataTransfer ? e.dataTransfer.files : e.target.files, |
||||
this.uploadForm = this.$el.find('form').get(0); |
formData = new FormData(); |
||||
if( 'draggable' in this.uploadForm ){ |
for (var i = 0; i < files.length; i++) { |
||||
var uploadFile = this.uploadFile; |
formData.append('files[]', files[i]); |
||||
this.uploadForm.ondragover = function(){ |
} |
||||
this.className = that.pfx + 'hover'; |
var target = this.target; |
||||
return false; |
$.ajax({ |
||||
}; |
url : this.config.upload, |
||||
this.uploadForm.ondragleave = function(){ |
type : 'POST', |
||||
this.className = ''; |
data : formData, |
||||
return false; |
beforeSend : this.config.beforeSend, |
||||
}; |
complete : this.config.onComplete, |
||||
this.uploadForm.ondrop = function(e){ |
xhrFields : { |
||||
this.className = ''; |
onprogress(e) { |
||||
e.preventDefault(); |
if (e.lengthComputable) { |
||||
that.uploadFile(e); |
/*var result = e.loaded / e.total * 100 + '%';*/ |
||||
return; |
} |
||||
}; |
}, |
||||
} |
onload(e) { |
||||
} |
//progress.value = 100;
|
||||
}, |
} |
||||
|
}, |
||||
|
cache: false, contentType: false, processData: false |
||||
|
}).done(data => { |
||||
|
target.add(data.data); |
||||
|
}).always(() => { |
||||
|
//turnOff loading
|
||||
|
}); |
||||
|
}, |
||||
|
|
||||
render : function(){ |
/** |
||||
this.$el.html( this.template({ |
* Make input file droppable |
||||
title: this.config.uploadText, |
* @private |
||||
uploadId: this.uploadId, |
* */ |
||||
disabled: this.disabled, |
initDrop() { |
||||
pfx: this.pfx |
var that = this; |
||||
}) ); |
if(!this.uploadForm){ |
||||
this.initDrop(); |
this.uploadForm = this.$el.find('form').get(0); |
||||
this.$el.attr('class', this.pfx + 'file-uploader'); |
if( 'draggable' in this.uploadForm ){ |
||||
return this; |
var uploadFile = this.uploadFile; |
||||
}, |
this.uploadForm.ondragover = function(){ |
||||
|
this.className = that.pfx + 'hover'; |
||||
|
return false; |
||||
|
}; |
||||
|
this.uploadForm.ondragleave = function(){ |
||||
|
this.className = ''; |
||||
|
return false; |
||||
|
}; |
||||
|
this.uploadForm.ondrop = function(e){ |
||||
|
this.className = ''; |
||||
|
e.preventDefault(); |
||||
|
that.uploadFile(e); |
||||
|
return; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
render() { |
||||
|
this.$el.html( this.template({ |
||||
|
title: this.config.uploadText, |
||||
|
uploadId: this.uploadId, |
||||
|
disabled: this.disabled, |
||||
|
pfx: this.pfx |
||||
|
}) ); |
||||
|
this.initDrop(); |
||||
|
this.$el.attr('class', this.pfx + 'file-uploader'); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,7 +1,5 @@ |
|||||
define(function () { |
module.exports = { |
||||
return { |
|
||||
|
|
||||
'blocks': [], |
'blocks': [], |
||||
|
|
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -0,0 +1,118 @@ |
|||||
|
/** |
||||
|
* * [add](#add) |
||||
|
* * [get](#get) |
||||
|
* * [getAll](#getall) |
||||
|
* * [render](#render) |
||||
|
* |
||||
|
* Block manager helps managing various, draggable, piece of contents that could be easily reused inside templates. |
||||
|
* |
||||
|
* Before using methods you should get first the module from the editor instance, in this way: |
||||
|
* |
||||
|
* ```js
|
||||
|
* var blockManager = editor.BlockManager; |
||||
|
* ``` |
||||
|
* |
||||
|
* @module BlockManager |
||||
|
* @param {Object} config Configurations |
||||
|
* @param {Array<Object>} [config.blocks=[]] Default blocks |
||||
|
* @example |
||||
|
* ... |
||||
|
* { |
||||
|
* blocks: [ |
||||
|
* {id:'h1-block' label: 'Heading', content:'<h1>...</h1>'}, |
||||
|
* ... |
||||
|
* ], |
||||
|
* } |
||||
|
* ... |
||||
|
*/ |
||||
|
module.exports = () => { |
||||
|
var c = {}, |
||||
|
defaults = require('./config/config'), |
||||
|
Blocks = require('./model/Blocks'), |
||||
|
BlocksView = require('./view/BlocksView'); |
||||
|
var blocks, view; |
||||
|
|
||||
|
return { |
||||
|
|
||||
|
/** |
||||
|
* Name of the module |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
name: 'BlockManager', |
||||
|
|
||||
|
/** |
||||
|
* Initialize module. Automatically called with a new instance of the editor |
||||
|
* @param {Object} config Configurations |
||||
|
* @return {this} |
||||
|
* @private |
||||
|
*/ |
||||
|
init(config) { |
||||
|
c = config || {}; |
||||
|
for (var name in defaults) { |
||||
|
if (!(name in c)) |
||||
|
c[name] = defaults[name]; |
||||
|
} |
||||
|
blocks = new Blocks(c.blocks); |
||||
|
view = new BlocksView({ collection: blocks }, c); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new block to the collection. |
||||
|
* @param {string} id Block id |
||||
|
* @param {Object} opts Options |
||||
|
* @param {string} opts.label Name of the block |
||||
|
* @param {string} opts.content HTML content |
||||
|
* @param {Object} [opts.attributes={}] Block attributes |
||||
|
* @return {Block} Added block |
||||
|
* @example |
||||
|
* blockManager.add('h1-block', { |
||||
|
* label: 'Heading', |
||||
|
* content: '<h1>Put your title here</h1>', |
||||
|
* attributes: { |
||||
|
* title: 'Insert h1 block' |
||||
|
* } |
||||
|
* }); |
||||
|
*/ |
||||
|
add(id, opts) { |
||||
|
var obj = opts || {}; |
||||
|
obj.id = id; |
||||
|
return blocks.add(obj); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Return block by id |
||||
|
* @param {string} id Block id |
||||
|
* @example |
||||
|
* var block = blockManager.get('h1-block'); |
||||
|
* console.log(JSON.stringify(block)); |
||||
|
* // {label: 'Heading', content: '<h1>Put your ...', ...}
|
||||
|
*/ |
||||
|
get(id) { |
||||
|
return blocks.get(id); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Return all blocks |
||||
|
* @return {Collection} |
||||
|
* @example |
||||
|
* var blocks = blockManager.getAll(); |
||||
|
* console.log(JSON.stringify(blocks)); |
||||
|
* // [{label: 'Heading', content: '<h1>Put your ...'}, ...]
|
||||
|
*/ |
||||
|
getAll() { |
||||
|
return blocks; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Render blocks |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
render() { |
||||
|
return view.render().el; |
||||
|
}, |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
}; |
||||
@ -1,122 +0,0 @@ |
|||||
/** |
|
||||
* * [add](#add) |
|
||||
* * [get](#get) |
|
||||
* * [getAll](#getall) |
|
||||
* * [render](#render) |
|
||||
* |
|
||||
* Block manager helps managing various, draggable, piece of contents that could be easily reused inside templates. |
|
||||
* |
|
||||
* Before using methods you should get first the module from the editor instance, in this way: |
|
||||
* |
|
||||
* ```js
|
|
||||
* var blockManager = editor.BlockManager; |
|
||||
* ``` |
|
||||
* |
|
||||
* @module BlockManager |
|
||||
* @param {Object} config Configurations |
|
||||
* @param {Array<Object>} [config.blocks=[]] Default blocks |
|
||||
* @example |
|
||||
* ... |
|
||||
* { |
|
||||
* blocks: [ |
|
||||
* {id:'h1-block' label: 'Heading', content:'<h1>...</h1>'}, |
|
||||
* ... |
|
||||
* ], |
|
||||
* } |
|
||||
* ... |
|
||||
*/ |
|
||||
define(function(require) { |
|
||||
|
|
||||
return function() { |
|
||||
var c = {}, |
|
||||
defaults = require('./config/config'), |
|
||||
Blocks = require('./model/Blocks'), |
|
||||
BlocksView = require('./view/BlocksView'); |
|
||||
var blocks, view; |
|
||||
|
|
||||
return { |
|
||||
|
|
||||
/** |
|
||||
* Name of the module |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
name: 'BlockManager', |
|
||||
|
|
||||
/** |
|
||||
* Initialize module. Automatically called with a new instance of the editor |
|
||||
* @param {Object} config Configurations |
|
||||
* @return {this} |
|
||||
* @private |
|
||||
*/ |
|
||||
init: function(config) { |
|
||||
c = config || {}; |
|
||||
for (var name in defaults) { |
|
||||
if (!(name in c)) |
|
||||
c[name] = defaults[name]; |
|
||||
} |
|
||||
blocks = new Blocks(c.blocks); |
|
||||
view = new BlocksView({ collection: blocks }, c); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new block to the collection. |
|
||||
* @param {string} id Block id |
|
||||
* @param {Object} opts Options |
|
||||
* @param {string} opts.label Name of the block |
|
||||
* @param {string} opts.content HTML content |
|
||||
* @param {Object} [opts.attributes={}] Block attributes |
|
||||
* @return {Block} Added block |
|
||||
* @example |
|
||||
* blockManager.add('h1-block', { |
|
||||
* label: 'Heading', |
|
||||
* content: '<h1>Put your title here</h1>', |
|
||||
* attributes: { |
|
||||
* title: 'Insert h1 block' |
|
||||
* } |
|
||||
* }); |
|
||||
*/ |
|
||||
add: function(id, opts){ |
|
||||
var obj = opts || {}; |
|
||||
obj.id = id; |
|
||||
return blocks.add(obj); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Return block by id |
|
||||
* @param {string} id Block id |
|
||||
* @example |
|
||||
* var block = blockManager.get('h1-block'); |
|
||||
* console.log(JSON.stringify(block)); |
|
||||
* // {label: 'Heading', content: '<h1>Put your ...', ...}
|
|
||||
*/ |
|
||||
get: function(id){ |
|
||||
return blocks.get(id); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Return all blocks |
|
||||
* @return {Collection} |
|
||||
* @example |
|
||||
* var blocks = blockManager.getAll(); |
|
||||
* console.log(JSON.stringify(blocks)); |
|
||||
* // [{label: 'Heading', content: '<h1>Put your ...'}, ...]
|
|
||||
*/ |
|
||||
getAll: function(){ |
|
||||
return blocks; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Render blocks |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
render: function(){ |
|
||||
return view.render().el; |
|
||||
}, |
|
||||
|
|
||||
}; |
|
||||
|
|
||||
}; |
|
||||
|
|
||||
}); |
|
||||
@ -1,13 +1,11 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function(Backbone){ |
|
||||
|
|
||||
return Backbone.Model.extend({ |
module.exports = Backbone.Model.extend({ |
||||
|
|
||||
defaults :{ |
defaults :{ |
||||
label: '', |
label: '', |
||||
content: '', |
content: '', |
||||
attributes: {}, |
attributes: {}, |
||||
}, |
}, |
||||
|
|
||||
}); |
}); |
||||
}); |
|
||||
|
|||||
@ -1,9 +1,6 @@ |
|||||
define(['backbone','./Block'], |
var Backbone = require('backbone'); |
||||
function (Backbone, Block) { |
var Block = require('./Block'); |
||||
|
|
||||
return Backbone.Collection.extend({ |
module.exports = Backbone.Collection.extend({ |
||||
|
model: Block, |
||||
model: Block, |
|
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,50 +1,48 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function(Backbone) { |
|
||||
|
|
||||
return Backbone.View.extend({ |
module.exports = Backbone.View.extend({ |
||||
|
|
||||
events: { |
events: { |
||||
mousedown: 'onDrag' |
mousedown: 'onDrag' |
||||
}, |
}, |
||||
|
|
||||
initialize: function(o, config) { |
initialize(o, config) { |
||||
_.bindAll(this, 'onDrop'); |
_.bindAll(this, 'onDrop'); |
||||
this.config = config || {}; |
this.config = config || {}; |
||||
this.ppfx = this.config.pStylePrefix || ''; |
this.ppfx = this.config.pStylePrefix || ''; |
||||
this.listenTo(this.model, 'destroy', this.remove); |
this.listenTo(this.model, 'destroy', this.remove); |
||||
this.doc = $(document); |
this.doc = $(document); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Start block dragging |
* Start block dragging |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
onDrag: function(e) { |
onDrag(e) { |
||||
if(!this.config.getSorter) |
if(!this.config.getSorter) |
||||
return; |
return; |
||||
this.config.em.refreshCanvas(); |
this.config.em.refreshCanvas(); |
||||
var sorter = this.config.getSorter(); |
var sorter = this.config.getSorter(); |
||||
sorter.setDragHelper(this.el, e); |
sorter.setDragHelper(this.el, e); |
||||
sorter.startSort(this.el); |
sorter.startSort(this.el); |
||||
sorter.setDropContent(this.model.get('content')); |
sorter.setDropContent(this.model.get('content')); |
||||
this.doc.on('mouseup', this.onDrop); |
this.doc.on('mouseup', this.onDrop); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Drop block |
* Drop block |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
onDrop: function() { |
onDrop() { |
||||
this.doc.off('mouseup', this.onDrop); |
this.doc.off('mouseup', this.onDrop); |
||||
this.config.getSorter().endMove(); |
this.config.getSorter().endMove(); |
||||
}, |
}, |
||||
|
|
||||
render: function() { |
render() { |
||||
var className = this.ppfx + 'block'; |
var className = this.ppfx + 'block'; |
||||
this.$el.addClass(className); |
this.$el.addClass(className); |
||||
this.el.innerHTML = '<div class="' + className + '-label">' + this.model.get('label') + '</div>'; |
this.el.innerHTML = '<div class="' + className + '-label">' + this.model.get('label') + '</div>'; |
||||
return this; |
return this; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,121 +1,120 @@ |
|||||
define(['backbone', './BlockView'], |
var Backbone = require('backbone'); |
||||
function(Backbone, BlockView) { |
var BlockView = require('./BlockView'); |
||||
|
|
||||
return Backbone.View.extend({ |
module.exports = Backbone.View.extend({ |
||||
|
|
||||
initialize: function(opts, config) { |
initialize(opts, config) { |
||||
_.bindAll(this, 'getSorter', 'onDrag', 'onDrop'); |
_.bindAll(this, 'getSorter', 'onDrag', 'onDrop'); |
||||
this.config = config || {}; |
this.config = config || {}; |
||||
this.ppfx = this.config.pStylePrefix || ''; |
this.ppfx = this.config.pStylePrefix || ''; |
||||
this.listenTo(this.collection, 'add', this.addTo); |
this.listenTo(this.collection, 'add', this.addTo); |
||||
this.em = this.config.em; |
this.em = this.config.em; |
||||
this.tac = 'test-tac'; |
this.tac = 'test-tac'; |
||||
this.grabbingCls = this.ppfx + 'grabbing'; |
this.grabbingCls = this.ppfx + 'grabbing'; |
||||
|
|
||||
if(this.em){ |
if(this.em){ |
||||
this.config.getSorter = this.getSorter; |
this.config.getSorter = this.getSorter; |
||||
this.canvas = this.em.get('Canvas'); |
this.canvas = this.em.get('Canvas'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get sorter |
||||
|
* @private |
||||
|
*/ |
||||
|
getSorter() { |
||||
|
if(!this.em) |
||||
|
return; |
||||
|
if(!this.sorter){ |
||||
|
var utils = this.em.get('Utils'); |
||||
|
var canvas = this.canvas; |
||||
|
this.sorter = new utils.Sorter({ |
||||
|
container: canvas.getBody(), |
||||
|
placer: canvas.getPlacerEl(), |
||||
|
containerSel: '*', |
||||
|
itemSel: '*', |
||||
|
pfx: this.ppfx, |
||||
|
onStart: this.onDrag, |
||||
|
onEndMove: this.onDrop, |
||||
|
document: canvas.getFrameEl().contentDocument, |
||||
|
direction: 'a', |
||||
|
wmargin: 1, |
||||
|
nested: 1, |
||||
|
em: this.em, |
||||
|
canvasRelative: 1, |
||||
|
}); |
||||
|
} |
||||
|
return this.sorter; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Callback when block is on drag |
||||
|
* @private |
||||
|
*/ |
||||
|
onDrag() { |
||||
|
this.em.stopDefault(); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Callback when block is dropped |
||||
|
* @private |
||||
|
*/ |
||||
|
onDrop(model) { |
||||
|
this.em.runDefault(); |
||||
|
|
||||
|
if (model && model.get) { |
||||
|
if(model.get('activeOnRender')) { |
||||
|
model.trigger('active'); |
||||
|
model.set('activeOnRender', 0); |
||||
} |
} |
||||
}, |
|
||||
|
// Register all its components (eg. for the Undo Manager)
|
||||
/** |
this.em.initChildrenComp(model); |
||||
* Get sorter |
} |
||||
* @private |
}, |
||||
*/ |
|
||||
getSorter: function(){ |
/** |
||||
if(!this.em) |
* Add new model to the collection |
||||
return; |
* @param {Model} model |
||||
if(!this.sorter){ |
* @private |
||||
var utils = this.em.get('Utils'); |
* */ |
||||
var canvas = this.canvas; |
addTo(model) { |
||||
this.sorter = new utils.Sorter({ |
this.add(model); |
||||
container: canvas.getBody(), |
}, |
||||
placer: canvas.getPlacerEl(), |
|
||||
containerSel: '*', |
/** |
||||
itemSel: '*', |
* Render new model inside the view |
||||
pfx: this.ppfx, |
* @param {Model} model |
||||
onStart: this.onDrag, |
* @param {Object} fragment Fragment collection |
||||
onEndMove: this.onDrop, |
* @private |
||||
document: canvas.getFrameEl().contentDocument, |
* */ |
||||
direction: 'a', |
add(model, fragment) { |
||||
wmargin: 1, |
var frag = fragment || null; |
||||
nested: 1, |
var view = new BlockView({ |
||||
em: this.em, |
model, |
||||
canvasRelative: 1, |
attributes: model.get('attributes'), |
||||
}); |
}, this.config); |
||||
} |
var rendered = view.render().el; |
||||
return this.sorter; |
|
||||
}, |
if(frag) |
||||
|
frag.appendChild(rendered); |
||||
/** |
else |
||||
* Callback when block is on drag |
this.$el.append(rendered); |
||||
* @private |
}, |
||||
*/ |
|
||||
onDrag: function(){ |
|
||||
this.em.stopDefault(); |
|
||||
}, |
render() { |
||||
|
var frag = document.createDocumentFragment(); |
||||
/** |
this.$el.empty(); |
||||
* Callback when block is dropped |
|
||||
* @private |
this.collection.each(function(model){ |
||||
*/ |
this.add(model, frag); |
||||
onDrop: function(model){ |
}, this); |
||||
this.em.runDefault(); |
|
||||
|
this.$el.append(frag); |
||||
if (model && model.get) { |
this.$el.addClass(this.ppfx + 'blocks-c'); |
||||
if(model.get('activeOnRender')) { |
return this; |
||||
model.trigger('active'); |
}, |
||||
model.set('activeOnRender', 0); |
|
||||
} |
|
||||
|
|
||||
// Register all its components (eg. for the Undo Manager)
|
|
||||
this.em.initChildrenComp(model); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new model to the collection |
|
||||
* @param {Model} model |
|
||||
* @private |
|
||||
* */ |
|
||||
addTo: function(model){ |
|
||||
this.add(model); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Render new model inside the view |
|
||||
* @param {Model} model |
|
||||
* @param {Object} fragment Fragment collection |
|
||||
* @private |
|
||||
* */ |
|
||||
add: function(model, fragment){ |
|
||||
var frag = fragment || null; |
|
||||
var view = new BlockView({ |
|
||||
model: model, |
|
||||
attributes: model.get('attributes'), |
|
||||
}, this.config); |
|
||||
var rendered = view.render().el; |
|
||||
|
|
||||
if(frag) |
|
||||
frag.appendChild(rendered); |
|
||||
else |
|
||||
this.$el.append(rendered); |
|
||||
}, |
|
||||
|
|
||||
|
|
||||
|
|
||||
render: function() { |
|
||||
var frag = document.createDocumentFragment(); |
|
||||
this.$el.empty(); |
|
||||
|
|
||||
this.collection.each(function(model){ |
|
||||
this.add(model, frag); |
|
||||
}, this); |
|
||||
|
|
||||
this.$el.append(frag); |
|
||||
this.$el.addClass(this.ppfx + 'blocks-c'); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,16 +1,14 @@ |
|||||
define(function () { |
module.exports = { |
||||
return { |
|
||||
|
|
||||
stylePrefix: 'cv-', |
stylePrefix: 'cv-', |
||||
|
|
||||
// Coming soon
|
// Coming soon
|
||||
rulers: false, |
rulers: false, |
||||
|
|
||||
/* |
/* |
||||
* append scripts in head of iframe before renderBody content |
* append scripts in head of iframe before renderBody content |
||||
* need to manually maintain the same scripts in cms's render template |
* need to manually maintain the same scripts in cms's render template |
||||
*/ |
*/ |
||||
scripts: [] |
scripts: [] |
||||
|
|
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -0,0 +1,325 @@ |
|||||
|
module.exports = () => { |
||||
|
var c = {}, |
||||
|
defaults = require('./config/config'), |
||||
|
Canvas = require('./model/Canvas'), |
||||
|
CanvasView = require('./view/CanvasView'); |
||||
|
var canvas; |
||||
|
|
||||
|
return { |
||||
|
|
||||
|
/** |
||||
|
* Used inside RTE |
||||
|
* @private |
||||
|
*/ |
||||
|
getCanvasView() { |
||||
|
return CanvasView; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Name of the module |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
name: 'Canvas', |
||||
|
|
||||
|
/** |
||||
|
* Initialize module. Automatically called with a new instance of the editor |
||||
|
* @param {Object} config Configurations |
||||
|
*/ |
||||
|
init(config) { |
||||
|
c = config || {}; |
||||
|
for (var name in defaults) { |
||||
|
if (!(name in c)) |
||||
|
c[name] = defaults[name]; |
||||
|
} |
||||
|
|
||||
|
var ppfx = c.pStylePrefix; |
||||
|
if(ppfx) |
||||
|
c.stylePrefix = ppfx + c.stylePrefix; |
||||
|
|
||||
|
canvas = new Canvas(config); |
||||
|
CanvasView = new CanvasView({ |
||||
|
model: canvas, |
||||
|
config: c, |
||||
|
}); |
||||
|
|
||||
|
var cm = c.em.get('DomComponents'); |
||||
|
if(cm) |
||||
|
this.setWrapper(cm); |
||||
|
|
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add wrapper |
||||
|
* @param {Object} wrp Wrapper |
||||
|
* |
||||
|
* */ |
||||
|
setWrapper(wrp) { |
||||
|
canvas.set('wrapper', wrp); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns canvas element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getElement() { |
||||
|
return CanvasView.el; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns frame element of the canvas |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getFrameEl() { |
||||
|
return CanvasView.frame.el; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns body element of the frame |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getBody() { |
||||
|
return CanvasView.frame.el.contentDocument.body; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns body wrapper element of the frame |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getWrapperEl() { |
||||
|
return this.getBody().querySelector('#wrapper'); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns element containing canvas tools |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getToolsEl() { |
||||
|
return CanvasView.toolsEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns highlighter element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getHighlighter() { |
||||
|
return CanvasView.hlEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns badge element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getBadgeEl() { |
||||
|
return CanvasView.badgeEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns placer element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getPlacerEl() { |
||||
|
return CanvasView.placerEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns ghost element |
||||
|
* @return {HTMLElement} |
||||
|
* @private |
||||
|
*/ |
||||
|
getGhostEl() { |
||||
|
return CanvasView.ghostEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns toolbar element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getToolbarEl() { |
||||
|
return CanvasView.toolbarEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns resizer element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getResizerEl() { |
||||
|
return CanvasView.resizerEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns offset viewer element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getOffsetViewerEl() { |
||||
|
return CanvasView.offsetEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns fixed offset viewer element |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
getFixedOffsetViewerEl() { |
||||
|
return CanvasView.fixedOffsetEl; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Render canvas |
||||
|
* */ |
||||
|
render() { |
||||
|
return CanvasView.render().el; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get frame position |
||||
|
* @return {Object} |
||||
|
* @private |
||||
|
*/ |
||||
|
getOffset() { |
||||
|
var frameOff = this.offset(this.getFrameEl()); |
||||
|
var canvasOff = this.offset(this.getElement()); |
||||
|
return { |
||||
|
top: frameOff.top - canvasOff.top, |
||||
|
left: frameOff.left - canvasOff.left |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get the offset of the element |
||||
|
* @param {HTMLElement} el |
||||
|
* @return {Object} |
||||
|
* @private |
||||
|
*/ |
||||
|
offset(el) { |
||||
|
var rect = el.getBoundingClientRect(); |
||||
|
return { |
||||
|
top: rect.top + document.body.scrollTop, |
||||
|
left: rect.left + document.body.scrollLeft |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get element position relative to the canvas |
||||
|
* @param {HTMLElement} el |
||||
|
* @return {Object} |
||||
|
*/ |
||||
|
getElementPos(el) { |
||||
|
return CanvasView.getElementPos(el); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* This method comes handy when you need to attach something like toolbars |
||||
|
* to elements inside the canvas, dealing with all relative position, |
||||
|
* offsets, etc. and returning as result the object with positions which are |
||||
|
* viewable by the user (when the canvas is scrolled the top edge of the element |
||||
|
* is not viewable by the user anymore so the new top edge is the one of the canvas) |
||||
|
* |
||||
|
* The target should be visible before being passed here as invisible elements |
||||
|
* return empty string as width |
||||
|
* @param {HTMLElement} target The target in this case could be the toolbar |
||||
|
* @param {HTMLElement} element The element on which I'd attach the toolbar |
||||
|
* @param {Object} options Custom options |
||||
|
* @param {Boolean} options.toRight Set to true if you want the toolbar attached to the right |
||||
|
* @return {Object} |
||||
|
*/ |
||||
|
getTargetToElementDim(target, element, options) { |
||||
|
var opts = options || {}; |
||||
|
var canvasPos = CanvasView.getPosition(); |
||||
|
var pos = opts.elPos || CanvasView.getElementPos(element); |
||||
|
var toRight = options.toRight || 0; |
||||
|
var targetHeight = opts.targetHeight || target.offsetHeight; |
||||
|
var targetWidth = opts.targetWidth || target.offsetWidth; |
||||
|
var eventToTrigger = opts.event || null; |
||||
|
|
||||
|
var elTop = pos.top - targetHeight; |
||||
|
var elLeft = pos.left; |
||||
|
elLeft += toRight ? pos.width : 0; |
||||
|
elLeft = toRight ? (elLeft - targetWidth) : elLeft; |
||||
|
|
||||
|
var leftPos = elLeft < canvasPos.left ? canvasPos.left : elLeft; |
||||
|
var topPos = elTop < canvasPos.top ? canvasPos.top : elTop; |
||||
|
topPos = topPos > (pos.top + pos.height) ? (pos.top + pos.height) : topPos; |
||||
|
|
||||
|
var result = { |
||||
|
top: topPos, |
||||
|
left: leftPos, |
||||
|
elementTop: pos.top, |
||||
|
elementLeft: pos.left, |
||||
|
elementWidth: pos.width, |
||||
|
elementHeight: pos.height, |
||||
|
targetWidth: target.offsetWidth, |
||||
|
targetHeight: target.offsetHeight, |
||||
|
canvasTop: canvasPos.top, |
||||
|
canvasLeft: canvasPos.left, |
||||
|
}; |
||||
|
|
||||
|
// In this way I can catch data and also change the position strategy
|
||||
|
if(eventToTrigger && c.em) { |
||||
|
c.em.trigger(eventToTrigger, result); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Instead of simply returning e.clientX and e.clientY this function |
||||
|
* calculates also the offset based on the canvas. This is helpful when you |
||||
|
* need to get X and Y position while moving between the editor area and |
||||
|
* canvas area, which is in the iframe |
||||
|
* @param {Event} e |
||||
|
* @return {Object} |
||||
|
*/ |
||||
|
getMouseRelativePos(e, options) { |
||||
|
var opts = options || {}; |
||||
|
var addTop = 0; |
||||
|
var addLeft = 0; |
||||
|
var subWinOffset = opts.subWinOffset; |
||||
|
var doc = e.target.ownerDocument; |
||||
|
var win = doc.defaultView || doc.parentWindow; |
||||
|
var frame = win.frameElement; |
||||
|
var yOffset = subWinOffset ? win.pageYOffset : 0; |
||||
|
var xOffset = subWinOffset ? win.pageXOffset : 0; |
||||
|
|
||||
|
if (frame) { |
||||
|
var frameRect = frame.getBoundingClientRect(); |
||||
|
addTop = frameRect.top || 0; |
||||
|
addLeft = frameRect.left || 0; |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
y: e.clientY + addTop - yOffset, |
||||
|
x: e.clientX + addLeft - xOffset, |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* X and Y mouse position relative to the canvas |
||||
|
* @param {Event} e |
||||
|
* @return {Object} |
||||
|
*/ |
||||
|
getMouseRelativeCanvas(e, options) { |
||||
|
var opts = options || {}; |
||||
|
var frame = this.getFrameEl(); |
||||
|
var body = this.getBody(); |
||||
|
var addTop = frame.offsetTop || 0; |
||||
|
var addLeft = frame.offsetLeft || 0; |
||||
|
var yOffset = body.scrollTop || 0; |
||||
|
var xOffset = body.scrollLeft || 0; |
||||
|
|
||||
|
return { |
||||
|
y: e.clientY + addTop + yOffset, |
||||
|
x: e.clientX + addLeft + xOffset, |
||||
|
}; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns wrapper element |
||||
|
* @return {HTMLElement} |
||||
|
* ???? |
||||
|
*/ |
||||
|
getFrameWrapperEl() { |
||||
|
return CanvasView.frame.getWrapper(); |
||||
|
}, |
||||
|
}; |
||||
|
}; |
||||
@ -1,329 +0,0 @@ |
|||||
define(function(require) { |
|
||||
|
|
||||
return function() { |
|
||||
var c = {}, |
|
||||
defaults = require('./config/config'), |
|
||||
Canvas = require('./model/Canvas'), |
|
||||
CanvasView = require('./view/CanvasView'); |
|
||||
var canvas; |
|
||||
|
|
||||
return { |
|
||||
|
|
||||
/** |
|
||||
* Used inside RTE |
|
||||
* @private |
|
||||
*/ |
|
||||
getCanvasView: function() { |
|
||||
return CanvasView; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Name of the module |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
name: 'Canvas', |
|
||||
|
|
||||
/** |
|
||||
* Initialize module. Automatically called with a new instance of the editor |
|
||||
* @param {Object} config Configurations |
|
||||
*/ |
|
||||
init: function(config) { |
|
||||
c = config || {}; |
|
||||
for (var name in defaults) { |
|
||||
if (!(name in c)) |
|
||||
c[name] = defaults[name]; |
|
||||
} |
|
||||
|
|
||||
var ppfx = c.pStylePrefix; |
|
||||
if(ppfx) |
|
||||
c.stylePrefix = ppfx + c.stylePrefix; |
|
||||
|
|
||||
canvas = new Canvas(config); |
|
||||
CanvasView = new CanvasView({ |
|
||||
model: canvas, |
|
||||
config: c, |
|
||||
}); |
|
||||
|
|
||||
var cm = c.em.get('DomComponents'); |
|
||||
if(cm) |
|
||||
this.setWrapper(cm); |
|
||||
|
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add wrapper |
|
||||
* @param {Object} wrp Wrapper |
|
||||
* |
|
||||
* */ |
|
||||
setWrapper: function(wrp) { |
|
||||
canvas.set('wrapper', wrp); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns canvas element |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getElement: function(){ |
|
||||
return CanvasView.el; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns frame element of the canvas |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getFrameEl: function(){ |
|
||||
return CanvasView.frame.el; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns body element of the frame |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getBody: function(){ |
|
||||
return CanvasView.frame.el.contentDocument.body; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns body wrapper element of the frame |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getWrapperEl: function(){ |
|
||||
return this.getBody().querySelector('#wrapper'); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns element containing canvas tools |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getToolsEl: function(){ |
|
||||
return CanvasView.toolsEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns highlighter element |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getHighlighter: function(){ |
|
||||
return CanvasView.hlEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns badge element |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getBadgeEl: function(){ |
|
||||
return CanvasView.badgeEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns placer element |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getPlacerEl: function(){ |
|
||||
return CanvasView.placerEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns ghost element |
|
||||
* @return {HTMLElement} |
|
||||
* @private |
|
||||
*/ |
|
||||
getGhostEl: function(){ |
|
||||
return CanvasView.ghostEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns toolbar element |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getToolbarEl: function() { |
|
||||
return CanvasView.toolbarEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns resizer element |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getResizerEl: function() { |
|
||||
return CanvasView.resizerEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns offset viewer element |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getOffsetViewerEl: function() { |
|
||||
return CanvasView.offsetEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns fixed offset viewer element |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
getFixedOffsetViewerEl: function() { |
|
||||
return CanvasView.fixedOffsetEl; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Render canvas |
|
||||
* */ |
|
||||
render: function() { |
|
||||
return CanvasView.render().el; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get frame position |
|
||||
* @return {Object} |
|
||||
* @private |
|
||||
*/ |
|
||||
getOffset: function() { |
|
||||
var frameOff = this.offset(this.getFrameEl()); |
|
||||
var canvasOff = this.offset(this.getElement()); |
|
||||
return { |
|
||||
top: frameOff.top - canvasOff.top, |
|
||||
left: frameOff.left - canvasOff.left |
|
||||
}; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get the offset of the element |
|
||||
* @param {HTMLElement} el |
|
||||
* @return {Object} |
|
||||
* @private |
|
||||
*/ |
|
||||
offset: function(el){ |
|
||||
var rect = el.getBoundingClientRect(); |
|
||||
return { |
|
||||
top: rect.top + document.body.scrollTop, |
|
||||
left: rect.left + document.body.scrollLeft |
|
||||
}; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get element position relative to the canvas |
|
||||
* @param {HTMLElement} el |
|
||||
* @return {Object} |
|
||||
*/ |
|
||||
getElementPos: function(el) { |
|
||||
return CanvasView.getElementPos(el); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* This method comes handy when you need to attach something like toolbars |
|
||||
* to elements inside the canvas, dealing with all relative position, |
|
||||
* offsets, etc. and returning as result the object with positions which are |
|
||||
* viewable by the user (when the canvas is scrolled the top edge of the element |
|
||||
* is not viewable by the user anymore so the new top edge is the one of the canvas) |
|
||||
* |
|
||||
* The target should be visible before being passed here as invisible elements |
|
||||
* return empty string as width |
|
||||
* @param {HTMLElement} target The target in this case could be the toolbar |
|
||||
* @param {HTMLElement} element The element on which I'd attach the toolbar |
|
||||
* @param {Object} options Custom options |
|
||||
* @param {Boolean} options.toRight Set to true if you want the toolbar attached to the right |
|
||||
* @return {Object} |
|
||||
*/ |
|
||||
getTargetToElementDim: function (target, element, options) { |
|
||||
var opts = options || {}; |
|
||||
var canvasPos = CanvasView.getPosition(); |
|
||||
var pos = opts.elPos || CanvasView.getElementPos(element); |
|
||||
var toRight = options.toRight || 0; |
|
||||
var targetHeight = opts.targetHeight || target.offsetHeight; |
|
||||
var targetWidth = opts.targetWidth || target.offsetWidth; |
|
||||
var eventToTrigger = opts.event || null; |
|
||||
|
|
||||
var elTop = pos.top - targetHeight; |
|
||||
var elLeft = pos.left; |
|
||||
elLeft += toRight ? pos.width : 0; |
|
||||
elLeft = toRight ? (elLeft - targetWidth) : elLeft; |
|
||||
|
|
||||
var leftPos = elLeft < canvasPos.left ? canvasPos.left : elLeft; |
|
||||
var topPos = elTop < canvasPos.top ? canvasPos.top : elTop; |
|
||||
topPos = topPos > (pos.top + pos.height) ? (pos.top + pos.height) : topPos; |
|
||||
|
|
||||
var result = { |
|
||||
top: topPos, |
|
||||
left: leftPos, |
|
||||
elementTop: pos.top, |
|
||||
elementLeft: pos.left, |
|
||||
elementWidth: pos.width, |
|
||||
elementHeight: pos.height, |
|
||||
targetWidth: target.offsetWidth, |
|
||||
targetHeight: target.offsetHeight, |
|
||||
canvasTop: canvasPos.top, |
|
||||
canvasLeft: canvasPos.left, |
|
||||
}; |
|
||||
|
|
||||
// In this way I can catch data and also change the position strategy
|
|
||||
if(eventToTrigger && c.em) { |
|
||||
c.em.trigger(eventToTrigger, result); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Instead of simply returning e.clientX and e.clientY this function |
|
||||
* calculates also the offset based on the canvas. This is helpful when you |
|
||||
* need to get X and Y position while moving between the editor area and |
|
||||
* canvas area, which is in the iframe |
|
||||
* @param {Event} e |
|
||||
* @return {Object} |
|
||||
*/ |
|
||||
getMouseRelativePos: function (e, options) { |
|
||||
var opts = options || {}; |
|
||||
var addTop = 0; |
|
||||
var addLeft = 0; |
|
||||
var subWinOffset = opts.subWinOffset; |
|
||||
var doc = e.target.ownerDocument; |
|
||||
var win = doc.defaultView || doc.parentWindow; |
|
||||
var frame = win.frameElement; |
|
||||
var yOffset = subWinOffset ? win.pageYOffset : 0; |
|
||||
var xOffset = subWinOffset ? win.pageXOffset : 0; |
|
||||
|
|
||||
if (frame) { |
|
||||
var frameRect = frame.getBoundingClientRect(); |
|
||||
addTop = frameRect.top || 0; |
|
||||
addLeft = frameRect.left || 0; |
|
||||
} |
|
||||
|
|
||||
return { |
|
||||
y: e.clientY + addTop - yOffset, |
|
||||
x: e.clientX + addLeft - xOffset, |
|
||||
}; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* X and Y mouse position relative to the canvas |
|
||||
* @param {Event} e |
|
||||
* @return {Object} |
|
||||
*/ |
|
||||
getMouseRelativeCanvas: function (e, options) { |
|
||||
var opts = options || {}; |
|
||||
var frame = this.getFrameEl(); |
|
||||
var body = this.getBody(); |
|
||||
var addTop = frame.offsetTop || 0; |
|
||||
var addLeft = frame.offsetLeft || 0; |
|
||||
var yOffset = body.scrollTop || 0; |
|
||||
var xOffset = body.scrollLeft || 0; |
|
||||
|
|
||||
return { |
|
||||
y: e.clientY + addTop + yOffset, |
|
||||
x: e.clientX + addLeft + xOffset, |
|
||||
}; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns wrapper element |
|
||||
* @return {HTMLElement} |
|
||||
* ???? |
|
||||
*/ |
|
||||
getFrameWrapperEl: function(){ |
|
||||
return CanvasView.frame.getWrapper(); |
|
||||
}, |
|
||||
}; |
|
||||
}; |
|
||||
|
|
||||
}); |
|
||||
@ -1,18 +1,17 @@ |
|||||
define(['backbone', './Frame'], |
var Backbone = require('backbone'); |
||||
function(Backbone, Frame){ |
var Frame = require('./Frame'); |
||||
|
|
||||
return Backbone.Model.extend({ |
module.exports = Backbone.Model.extend({ |
||||
|
|
||||
defaults :{ |
defaults :{ |
||||
frame: '', |
frame: '', |
||||
wrapper: '', |
wrapper: '', |
||||
rulers: false, |
rulers: false, |
||||
}, |
}, |
||||
|
|
||||
initialize: function(config) { |
initialize(config) { |
||||
var conf = this.conf || {}; |
var conf = this.conf || {}; |
||||
this.set('frame', new Frame(conf.frame)); |
this.set('frame', new Frame(conf.frame)); |
||||
}, |
}, |
||||
|
|
||||
}); |
}); |
||||
}); |
|
||||
|
|||||
@ -1,14 +1,12 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function(Backbone){ |
|
||||
|
|
||||
return Backbone.Model.extend({ |
module.exports = Backbone.Model.extend({ |
||||
|
|
||||
defaults :{ |
defaults :{ |
||||
wrapper: '', |
wrapper: '', |
||||
width: '', |
width: '', |
||||
height: '', |
height: '', |
||||
attributes: {}, |
attributes: {}, |
||||
}, |
}, |
||||
|
|
||||
}); |
}); |
||||
}); |
|
||||
|
|||||
@ -1,269 +1,266 @@ |
|||||
define(['backbone','./FrameView'], |
var Backbone = require('backbone'); |
||||
function(Backbone, FrameView) { |
var FrameView = require('./FrameView'); |
||||
/** |
|
||||
* @class CanvasView |
|
||||
* */ |
|
||||
return Backbone.View.extend({ |
|
||||
|
|
||||
initialize: function(o) { |
module.exports = Backbone.View.extend({ |
||||
_.bindAll(this, 'renderBody', 'onFrameScroll', 'clearOff'); |
|
||||
this.config = o.config || {}; |
|
||||
this.em = this.config.em || {}; |
|
||||
this.ppfx = this.config.pStylePrefix || ''; |
|
||||
this.className = this.config.stylePrefix + 'canvas'; |
|
||||
this.listenTo(this.em, 'change:canvasOffset', this.clearOff); |
|
||||
this.frame = new FrameView({ |
|
||||
model: this.model.get('frame'), |
|
||||
config: this.config |
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
/** |
initialize(o) { |
||||
* Update tools position |
_.bindAll(this, 'renderBody', 'onFrameScroll', 'clearOff'); |
||||
* @private |
this.config = o.config || {}; |
||||
*/ |
this.em = this.config.em || {}; |
||||
onFrameScroll: function(){ |
this.ppfx = this.config.pStylePrefix || ''; |
||||
var u = 'px'; |
this.className = this.config.stylePrefix + 'canvas'; |
||||
var body = this.frame.el.contentDocument.body; |
this.listenTo(this.em, 'change:canvasOffset', this.clearOff); |
||||
this.toolsEl.style.top = '-' + body.scrollTop + u; |
this.frame = new FrameView({ |
||||
this.toolsEl.style.left = '-' + body.scrollLeft + u; |
model: this.model.get('frame'), |
||||
this.em.trigger('canvasScroll'); |
config: this.config |
||||
}, |
}); |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Insert scripts into head, it will call renderBody after all scripts loaded or failed |
* Update tools position |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
renderScripts: function () { |
onFrameScroll() { |
||||
var frame = this.frame; |
var u = 'px'; |
||||
var that = this; |
var body = this.frame.el.contentDocument.body; |
||||
|
this.toolsEl.style.top = '-' + body.scrollTop + u; |
||||
|
this.toolsEl.style.left = '-' + body.scrollLeft + u; |
||||
|
this.em.trigger('canvasScroll'); |
||||
|
}, |
||||
|
|
||||
frame.el.onload = function () { |
/** |
||||
var scripts = that.config.scripts.slice(0), // clone
|
* Insert scripts into head, it will call renderBody after all scripts loaded or failed |
||||
counter = 0; |
* @private |
||||
|
*/ |
||||
|
renderScripts() { |
||||
|
var frame = this.frame; |
||||
|
var that = this; |
||||
|
|
||||
function appendScript(scripts) { |
frame.el.onload = () => { |
||||
if (scripts.length > 0) { |
var scripts = that.config.scripts.slice(0), // clone
|
||||
var script = document.createElement('script'); |
counter = 0; |
||||
script.type = 'text/javascript'; |
|
||||
script.src = scripts.shift(); |
function appendScript(scripts) { |
||||
script.onerror = script.onload = appendScript.bind(null, scripts); |
if (scripts.length > 0) { |
||||
frame.el.contentDocument.head.appendChild(script); |
var script = document.createElement('script'); |
||||
} else { |
script.type = 'text/javascript'; |
||||
that.renderBody(); |
script.src = scripts.shift(); |
||||
} |
script.onerror = script.onload = appendScript.bind(null, scripts); |
||||
|
frame.el.contentDocument.head.appendChild(script); |
||||
|
} else { |
||||
|
that.renderBody(); |
||||
} |
} |
||||
appendScript(scripts); |
} |
||||
}; |
appendScript(scripts); |
||||
}, |
}; |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Render inside frame's body |
* Render inside frame's body |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
renderBody: function() { |
renderBody() { |
||||
var wrap = this.model.get('frame').get('wrapper'); |
var wrap = this.model.get('frame').get('wrapper'); |
||||
var em = this.config.em; |
var em = this.config.em; |
||||
if(wrap) { |
if(wrap) { |
||||
var ppfx = this.ppfx; |
var ppfx = this.ppfx; |
||||
var body = this.frame.$el.contents().find('body'); |
var body = this.frame.$el.contents().find('body'); |
||||
var cssc = em.get('CssComposer'); |
var cssc = em.get('CssComposer'); |
||||
var conf = em.get('Config'); |
var conf = em.get('Config'); |
||||
body.append(wrap.render()).append(cssc.render()); |
body.append(wrap.render()).append(cssc.render()); |
||||
var protCss = conf.protectedCss; |
var protCss = conf.protectedCss; |
||||
|
|
||||
// I need all this styles to make the editor work properly
|
// I need all this styles to make the editor work properly
|
||||
var frameCss = '* {box-sizing: border-box;} body{margin:0;height:auto;background-color:#fff} #wrapper{min-height:100%; overflow:auto}' + |
var frameCss = '* {box-sizing: border-box;} body{margin:0;height:auto;background-color:#fff} #wrapper{min-height:100%; overflow:auto}' + |
||||
'.' + ppfx + 'dashed :not([contenteditable]) > *[data-highlightable]{outline: 1px dashed rgba(170,170,170,0.7); outline-offset: -2px}' + |
'.' + ppfx + 'dashed :not([contenteditable]) > *[data-highlightable]{outline: 1px dashed rgba(170,170,170,0.7); outline-offset: -2px}' + |
||||
'.' + ppfx + 'comp-selected{outline: 3px solid #3b97e3 !important}' + |
'.' + ppfx + 'comp-selected{outline: 3px solid #3b97e3 !important}' + |
||||
'.' + ppfx + 'no-select{user-select: none; -webkit-user-select:none; -moz-user-select: none}'+ |
'.' + ppfx + 'no-select{user-select: none; -webkit-user-select:none; -moz-user-select: none}'+ |
||||
'.' + ppfx + 'freezed{opacity: 0.5; pointer-events: none}' + |
'.' + ppfx + 'freezed{opacity: 0.5; pointer-events: none}' + |
||||
'.' + ppfx + 'no-pointer{pointer-events: none}' + |
'.' + ppfx + 'no-pointer{pointer-events: none}' + |
||||
'.' + ppfx + 'plh-image{background:#f5f5f5; border:none; height:50px; width:50px; display:block; outline:3px solid #ffca6f; cursor:pointer}' + |
'.' + ppfx + 'plh-image{background:#f5f5f5; border:none; height:50px; width:50px; display:block; outline:3px solid #ffca6f; cursor:pointer}' + |
||||
'.' + ppfx + 'grabbing{cursor: grabbing; cursor: -webkit-grabbing}' + |
'.' + ppfx + 'grabbing{cursor: grabbing; cursor: -webkit-grabbing}' + |
||||
'* ::-webkit-scrollbar-track {background: rgba(0, 0, 0, 0.1)}' + |
'* ::-webkit-scrollbar-track {background: rgba(0, 0, 0, 0.1)}' + |
||||
'* ::-webkit-scrollbar-thumb {background: rgba(255, 255, 255, 0.2)}' + |
'* ::-webkit-scrollbar-thumb {background: rgba(255, 255, 255, 0.2)}' + |
||||
'* ::-webkit-scrollbar {width: 10px}' + |
'* ::-webkit-scrollbar {width: 10px}' + |
||||
(conf.canvasCss || ''); |
(conf.canvasCss || ''); |
||||
frameCss += protCss || ''; |
frameCss += protCss || ''; |
||||
body.append('<style>' + frameCss + '</style>'); |
body.append('<style>' + frameCss + '</style>'); |
||||
body.append(this.getJsContainer()); |
body.append(this.getJsContainer()); |
||||
em.trigger('loaded'); |
em.trigger('loaded'); |
||||
this.frame.el.contentWindow.onscroll = this.onFrameScroll; |
this.frame.el.contentWindow.onscroll = this.onFrameScroll; |
||||
this.frame.udpateOffset(); |
this.frame.udpateOffset(); |
||||
|
|
||||
// When the iframe is focused the event dispatcher is not the same so
|
// When the iframe is focused the event dispatcher is not the same so
|
||||
// I need to delegate all events to the parent document
|
// I need to delegate all events to the parent document
|
||||
var doc = document; |
var doc = document; |
||||
var fdoc = this.frame.el.contentDocument; |
var fdoc = this.frame.el.contentDocument; |
||||
fdoc.addEventListener('keydown', function(e){ |
fdoc.addEventListener('keydown', e => { |
||||
doc.dispatchEvent(new KeyboardEvent(e.type, e)); |
doc.dispatchEvent(new KeyboardEvent(e.type, e)); |
||||
}); |
}); |
||||
fdoc.addEventListener('keyup', function(e){ |
fdoc.addEventListener('keyup', e => { |
||||
doc.dispatchEvent(new KeyboardEvent(e.type, e)); |
doc.dispatchEvent(new KeyboardEvent(e.type, e)); |
||||
}); |
}); |
||||
} |
} |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Get the offset of the element |
* Get the offset of the element |
||||
* @param {HTMLElement} el |
* @param {HTMLElement} el |
||||
* @return {Object} |
* @return {Object} |
||||
*/ |
*/ |
||||
offset: function(el){ |
offset(el) { |
||||
var rect = el.getBoundingClientRect(); |
var rect = el.getBoundingClientRect(); |
||||
var docBody = el.ownerDocument.body; |
var docBody = el.ownerDocument.body; |
||||
return { |
return { |
||||
top: rect.top + docBody.scrollTop, |
top: rect.top + docBody.scrollTop, |
||||
left: rect.left + docBody.scrollLeft |
left: rect.left + docBody.scrollLeft |
||||
}; |
}; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Cleare cached offsets |
* Cleare cached offsets |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
clearOff: function(){ |
clearOff() { |
||||
this.frmOff = null; |
this.frmOff = null; |
||||
this.cvsOff = null; |
this.cvsOff = null; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Return frame offset |
* Return frame offset |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getFrameOffset: function () { |
getFrameOffset() { |
||||
if(!this.frmOff) |
if(!this.frmOff) |
||||
this.frmOff = this.offset(this.frame.el); |
this.frmOff = this.offset(this.frame.el); |
||||
return this.frmOff; |
return this.frmOff; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Return canvas offset |
* Return canvas offset |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getCanvasOffset: function () { |
getCanvasOffset() { |
||||
if(!this.cvsOff) |
if(!this.cvsOff) |
||||
this.cvsOff = this.offset(this.el); |
this.cvsOff = this.offset(this.el); |
||||
return this.cvsOff; |
return this.cvsOff; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Returns element's data info |
* Returns element's data info |
||||
* @param {HTMLElement} el |
* @param {HTMLElement} el |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getElementPos: function(el) { |
getElementPos(el) { |
||||
var frmOff = this.getFrameOffset(); |
var frmOff = this.getFrameOffset(); |
||||
var cvsOff = this.getCanvasOffset(); |
var cvsOff = this.getCanvasOffset(); |
||||
var eo = this.offset(el); |
var eo = this.offset(el); |
||||
var top = eo.top + frmOff.top - cvsOff.top; |
var top = eo.top + frmOff.top - cvsOff.top; |
||||
var left = eo.left + frmOff.left - cvsOff.left; |
var left = eo.left + frmOff.left - cvsOff.left; |
||||
return { |
return { |
||||
top: top, |
top, |
||||
left: left, |
left, |
||||
height: el.offsetHeight, |
height: el.offsetHeight, |
||||
width: el.offsetWidth |
width: el.offsetWidth |
||||
}; |
}; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Returns position data of the canvas element |
* Returns position data of the canvas element |
||||
* @return {Object} obj Position object |
* @return {Object} obj Position object |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getPosition: function() { |
getPosition() { |
||||
var bEl = this.frame.el.contentDocument.body; |
var bEl = this.frame.el.contentDocument.body; |
||||
var fo = this.getFrameOffset(); |
var fo = this.getFrameOffset(); |
||||
var co = this.getCanvasOffset(); |
var co = this.getCanvasOffset(); |
||||
return { |
return { |
||||
top: fo.top + bEl.scrollTop - co.top, |
top: fo.top + bEl.scrollTop - co.top, |
||||
left: fo.left + bEl.scrollLeft - co.left |
left: fo.left + bEl.scrollLeft - co.left |
||||
}; |
}; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Update javascript of a specific component passed by its View |
* Update javascript of a specific component passed by its View |
||||
* @param {View} view Component's View |
* @param {View} view Component's View |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
updateScript: function(view) { |
updateScript(view) { |
||||
if(!view.scriptContainer) { |
if(!view.scriptContainer) { |
||||
view.scriptContainer = $('<div>'); |
view.scriptContainer = $('<div>'); |
||||
this.getJsContainer().append(view.scriptContainer.get(0)); |
this.getJsContainer().append(view.scriptContainer.get(0)); |
||||
} |
} |
||||
|
|
||||
var id = view.model.cid; |
var id = view.model.cid; |
||||
var script = view.model.get('script'); |
var script = view.model.get('script'); |
||||
var scrStr = 'function(){' + script + '}'; |
var scrStr = 'function(){' + script + '}'; |
||||
scrStr = typeof script == 'function' ? script.toString() : scrStr; |
scrStr = typeof script == 'function' ? script.toString() : scrStr; |
||||
|
|
||||
view.el.id = id; |
view.el.id = id; |
||||
view.scriptContainer.html(''); |
view.scriptContainer.html(''); |
||||
|
|
||||
view.scriptContainer.append('<script>' + |
view.scriptContainer.append('<script>' + |
||||
'var item = document.getElementById("'+id+'");' + |
'var item = document.getElementById("'+id+'");' + |
||||
'(' + scrStr + '.bind(item))()</script>'); |
'(' + scrStr + '.bind(item))()</script>'); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Get javascript container |
* Get javascript container |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getJsContainer: function () { |
getJsContainer() { |
||||
if (!this.jsContainer) { |
if (!this.jsContainer) { |
||||
this.jsContainer = $('<div>', {class: this.ppfx + 'js-cont'}).get(0); |
this.jsContainer = $('<div>', {class: this.ppfx + 'js-cont'}).get(0); |
||||
} |
} |
||||
return this.jsContainer; |
return this.jsContainer; |
||||
}, |
}, |
||||
|
|
||||
|
|
||||
render: function() { |
render() { |
||||
this.wrapper = this.model.get('wrapper'); |
this.wrapper = this.model.get('wrapper'); |
||||
|
|
||||
if(this.wrapper && typeof this.wrapper.render == 'function'){ |
if(this.wrapper && typeof this.wrapper.render == 'function'){ |
||||
this.model.get('frame').set('wrapper', this.wrapper); |
this.model.get('frame').set('wrapper', this.wrapper); |
||||
this.$el.append(this.frame.render().el); |
this.$el.append(this.frame.render().el); |
||||
var frame = this.frame; |
var frame = this.frame; |
||||
if (this.config.scripts.length === 0) { |
if (this.config.scripts.length === 0) { |
||||
frame.el.onload = this.renderBody; |
frame.el.onload = this.renderBody; |
||||
} else { |
} else { |
||||
this.renderScripts(); // will call renderBody later
|
this.renderScripts(); // will call renderBody later
|
||||
} |
|
||||
} |
} |
||||
var ppfx = this.ppfx; |
} |
||||
toolsEl = $('<div>', { id: ppfx + 'tools' }).get(0); |
var ppfx = this.ppfx; |
||||
this.hlEl = $('<div>', { class: ppfx + 'highlighter' }).get(0); |
var toolsEl = $('<div>', { id: ppfx + 'tools' }).get(0); |
||||
this.badgeEl = $('<div>', {class: ppfx + 'badge'}).get(0); |
this.hlEl = $('<div>', { class: ppfx + 'highlighter' }).get(0); |
||||
this.placerEl = $('<div>', {class: ppfx + 'placeholder'}).get(0); |
this.badgeEl = $('<div>', {class: ppfx + 'badge'}).get(0); |
||||
this.placerIntEl = $('<div>', {class: ppfx + 'placeholder-int'}).get(0); |
this.placerEl = $('<div>', {class: ppfx + 'placeholder'}).get(0); |
||||
this.ghostEl = $('<div>', {class: ppfx + 'ghost'}).get(0); |
this.placerIntEl = $('<div>', {class: ppfx + 'placeholder-int'}).get(0); |
||||
this.toolbarEl = $('<div>', {class: ppfx + 'toolbar'}).get(0); |
this.ghostEl = $('<div>', {class: ppfx + 'ghost'}).get(0); |
||||
this.resizerEl = $('<div>', {class: ppfx + 'resizer'}).get(0); |
this.toolbarEl = $('<div>', {class: ppfx + 'toolbar'}).get(0); |
||||
this.offsetEl = $('<div>', {class: ppfx + 'offset-v'}).get(0); |
this.resizerEl = $('<div>', {class: ppfx + 'resizer'}).get(0); |
||||
this.fixedOffsetEl = $('<div>', {class: ppfx + 'offset-fixed-v'}).get(0); |
this.offsetEl = $('<div>', {class: ppfx + 'offset-v'}).get(0); |
||||
this.placerEl.appendChild(this.placerIntEl); |
this.fixedOffsetEl = $('<div>', {class: ppfx + 'offset-fixed-v'}).get(0); |
||||
toolsEl.appendChild(this.hlEl); |
this.placerEl.appendChild(this.placerIntEl); |
||||
toolsEl.appendChild(this.badgeEl); |
toolsEl.appendChild(this.hlEl); |
||||
toolsEl.appendChild(this.placerEl); |
toolsEl.appendChild(this.badgeEl); |
||||
toolsEl.appendChild(this.ghostEl); |
toolsEl.appendChild(this.placerEl); |
||||
toolsEl.appendChild(this.toolbarEl); |
toolsEl.appendChild(this.ghostEl); |
||||
toolsEl.appendChild(this.resizerEl); |
toolsEl.appendChild(this.toolbarEl); |
||||
toolsEl.appendChild(this.offsetEl); |
toolsEl.appendChild(this.resizerEl); |
||||
toolsEl.appendChild(this.fixedOffsetEl); |
toolsEl.appendChild(this.offsetEl); |
||||
this.$el.append(toolsEl); |
toolsEl.appendChild(this.fixedOffsetEl); |
||||
var rte = this.em.get('rte'); |
this.$el.append(toolsEl); |
||||
|
var rte = this.em.get('rte'); |
||||
|
|
||||
if(rte) |
if(rte) |
||||
toolsEl.appendChild(rte.render()); |
toolsEl.appendChild(rte.render()); |
||||
|
|
||||
this.toolsEl = toolsEl; |
this.toolsEl = toolsEl; |
||||
this.$el.attr({class: this.className}); |
this.$el.attr({class: this.className}); |
||||
return this; |
return this; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,55 +1,51 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function(Backbone) { |
|
||||
|
module.exports = Backbone.View.extend({ |
||||
|
|
||||
|
tagName: 'iframe', |
||||
|
|
||||
|
attributes: { |
||||
|
src: 'about:blank', |
||||
|
allowfullscreen: 'allowfullscreen' |
||||
|
}, |
||||
|
|
||||
|
initialize(o) { |
||||
|
_.bindAll(this, 'udpateOffset'); |
||||
|
this.config = o.config || {}; |
||||
|
this.ppfx = this.config.pStylePrefix || ''; |
||||
|
this.em = this.config.em; |
||||
|
this.motionsEv = 'transitionend oTransitionEnd transitionend webkitTransitionEnd'; |
||||
|
this.listenTo(this.em, 'change:device', this.updateWidth); |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* @class CanvasView |
* Update width of the frame |
||||
* */ |
* @private |
||||
return Backbone.View.extend({ |
*/ |
||||
|
updateWidth(model) { |
||||
tagName: 'iframe', |
var device = this.em.getDeviceModel(); |
||||
|
this.el.style.width = device ? device.get('width') : ''; |
||||
attributes: { |
this.udpateOffset(); |
||||
src: 'about:blank', |
this.$el.on(this.motionsEv, this.udpateOffset); |
||||
allowfullscreen: 'allowfullscreen' |
}, |
||||
}, |
|
||||
|
udpateOffset() { |
||||
initialize: function(o) { |
var offset = this.em.get('Canvas').getOffset(); |
||||
_.bindAll(this, 'udpateOffset'); |
this.em.set('canvasOffset', offset); |
||||
this.config = o.config || {}; |
this.$el.off(this.motionsEv, this.udpateOffset); |
||||
this.ppfx = this.config.pStylePrefix || ''; |
}, |
||||
this.em = this.config.em; |
|
||||
this.motionsEv = 'transitionend oTransitionEnd transitionend webkitTransitionEnd'; |
getBody() { |
||||
this.listenTo(this.em, 'change:device', this.updateWidth); |
this.$el.contents().find('body'); |
||||
}, |
}, |
||||
|
|
||||
/** |
getWrapper() { |
||||
* Update width of the frame |
return this.$el.contents().find('body > div'); |
||||
* @private |
}, |
||||
*/ |
|
||||
updateWidth: function(model){ |
render() { |
||||
var device = this.em.getDeviceModel(); |
this.$el.attr({class: this.ppfx + 'frame'}); |
||||
this.el.style.width = device ? device.get('width') : ''; |
return this; |
||||
this.udpateOffset(); |
}, |
||||
this.$el.on(this.motionsEv, this.udpateOffset); |
|
||||
}, |
|
||||
|
|
||||
udpateOffset: function(){ |
|
||||
var offset = this.em.get('Canvas').getOffset(); |
|
||||
this.em.set('canvasOffset', offset); |
|
||||
this.$el.off(this.motionsEv, this.udpateOffset); |
|
||||
}, |
|
||||
|
|
||||
getBody: function(){ |
|
||||
this.$el.contents().find('body'); |
|
||||
}, |
|
||||
|
|
||||
getWrapper: function(){ |
|
||||
return this.$el.contents().find('body > div'); |
|
||||
}, |
|
||||
|
|
||||
render: function() { |
|
||||
this.$el.attr({class: this.ppfx + 'frame'}); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,8 +1,6 @@ |
|||||
define(function () { |
module.exports = { |
||||
return { |
// Style prefix
|
||||
// Style prefix
|
stylePrefix: 'cm-', |
||||
stylePrefix: 'cm-', |
|
||||
|
|
||||
inlineCss: false, |
inlineCss: false, |
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -0,0 +1,221 @@ |
|||||
|
/** |
||||
|
* - [addGenerator](#addgenerator) |
||||
|
* - [getGenerator](#getgenerator) |
||||
|
* - [getGenerators](#getgenerators) |
||||
|
* - [addViewer](#addviewer) |
||||
|
* - [getViewer](#getviewer) |
||||
|
* - [getViewers](#getviewers) |
||||
|
* - [updateViewer](#updateviewer) |
||||
|
* - [getCode](#getcode) |
||||
|
* |
||||
|
* |
||||
|
* Before using methods you should get first the module from the editor instance, in this way: |
||||
|
* |
||||
|
* ```js
|
||||
|
* var codeManager = editor.CodeManager; |
||||
|
* ``` |
||||
|
* |
||||
|
* @module CodeManager |
||||
|
*/ |
||||
|
module.exports = () => { |
||||
|
|
||||
|
var c = {}, |
||||
|
defaults = require('./config/config'), |
||||
|
gHtml = require('./model/HtmlGenerator'), |
||||
|
gCss = require('./model/CssGenerator'), |
||||
|
gJson = require('./model/JsonGenerator'), |
||||
|
gJs = require('./model/JsGenerator'), |
||||
|
eCM = require('./model/CodeMirrorEditor'), |
||||
|
editorView = require('./view/EditorView'); |
||||
|
|
||||
|
var generators = {}, |
||||
|
defGenerators = {}, |
||||
|
viewers = {}, |
||||
|
defViewers = {}; |
||||
|
|
||||
|
return { |
||||
|
|
||||
|
getConfig() { |
||||
|
return c; |
||||
|
}, |
||||
|
|
||||
|
config: c, |
||||
|
|
||||
|
EditorView: editorView, |
||||
|
|
||||
|
/** |
||||
|
* Name of the module |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
name: 'CodeManager', |
||||
|
|
||||
|
/** |
||||
|
* Initialize module. Automatically called with a new instance of the editor |
||||
|
* @param {Object} config Configurations |
||||
|
*/ |
||||
|
init(config) { |
||||
|
c = config || {}; |
||||
|
for (var name in defaults) { |
||||
|
if (!(name in c)) |
||||
|
c[name] = defaults[name]; |
||||
|
} |
||||
|
|
||||
|
var ppfx = c.pStylePrefix; |
||||
|
if(ppfx) |
||||
|
c.stylePrefix = ppfx + c.stylePrefix; |
||||
|
|
||||
|
defGenerators.html = new gHtml(); |
||||
|
defGenerators.css = new gCss(); |
||||
|
defGenerators.json = new gJson(); |
||||
|
defGenerators.js = new gJs(); |
||||
|
|
||||
|
defViewers.CodeMirror = new eCM(); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Callback on load |
||||
|
*/ |
||||
|
onLoad() { |
||||
|
this.loadDefaultGenerators().loadDefaultViewers(); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new code generator to the collection |
||||
|
* @param {string} id Code generator ID |
||||
|
* @param {Object} generator Code generator wrapper |
||||
|
* @param {Function} generator.build Function that builds the code |
||||
|
* @return {this} |
||||
|
* @example |
||||
|
* codeManager.addGenerator('html7',{ |
||||
|
* build: function(model){ |
||||
|
* return 'myCode'; |
||||
|
* } |
||||
|
* }); |
||||
|
* */ |
||||
|
addGenerator(id, generator) { |
||||
|
generators[id] = generator; |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get code generator by id |
||||
|
* @param {string} id Code generator ID |
||||
|
* @return {Object|null} |
||||
|
* @example |
||||
|
* var generator = codeManager.getGenerator('html7'); |
||||
|
* generator.build = function(model){ |
||||
|
* //extend
|
||||
|
* }; |
||||
|
* */ |
||||
|
getGenerator(id) { |
||||
|
return generators[id] || null; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns all code generators |
||||
|
* @return {Array<Object>} |
||||
|
* */ |
||||
|
getGenerators() { |
||||
|
return generators; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new code viewer |
||||
|
* @param {string} id Code viewer ID |
||||
|
* @param {Object} viewer Code viewer wrapper |
||||
|
* @param {Function} viewer.init Set element on which viewer will be displayed |
||||
|
* @param {Function} viewer.setContent Set content to the viewer |
||||
|
* @return {this} |
||||
|
* @example |
||||
|
* codeManager.addViewer('ace',{ |
||||
|
* init: function(el){ |
||||
|
* var ace = require('ace-editor'); |
||||
|
* this.editor = ace.edit(el.id); |
||||
|
* }, |
||||
|
* setContent: function(code){ |
||||
|
* this.editor.setValue(code); |
||||
|
* } |
||||
|
* }); |
||||
|
* */ |
||||
|
addViewer(id, viewer) { |
||||
|
viewers[id] = viewer; |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get code viewer by id |
||||
|
* @param {string} id Code viewer ID |
||||
|
* @return {Object|null} |
||||
|
* @example |
||||
|
* var viewer = codeManager.getViewer('ace'); |
||||
|
* */ |
||||
|
getViewer(id) { |
||||
|
return viewers[id] || null; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns all code viewers |
||||
|
* @return {Array<Object>} |
||||
|
* */ |
||||
|
getViewers() { |
||||
|
return viewers; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Update code viewer content |
||||
|
* @param {Object} viewer Viewer instance |
||||
|
* @param {string} code Code string |
||||
|
* @example |
||||
|
* var AceViewer = codeManager.getViewer('ace'); |
||||
|
* // ...
|
||||
|
* var viewer = AceViewer.init(el); |
||||
|
* // ...
|
||||
|
* codeManager.updateViewer(AceViewer, 'code'); |
||||
|
* */ |
||||
|
updateViewer(viewer, code) { |
||||
|
viewer.setContent(code); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get code from model |
||||
|
* @param {Object} model Any kind of model that will be passed to the build method of generator |
||||
|
* @param {string} genId Code generator id |
||||
|
* @param {Object} [opt] Options |
||||
|
* @return {string} |
||||
|
* @example |
||||
|
* var codeStr = codeManager.getCode(model, 'html'); |
||||
|
* */ |
||||
|
getCode(model, genId, opt) { |
||||
|
var generator = this.getGenerator(genId); |
||||
|
return generator ? generator.build(model, opt) : ''; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Load default code generators |
||||
|
* @return {this} |
||||
|
* @private |
||||
|
* */ |
||||
|
loadDefaultGenerators() { |
||||
|
for (var id in defGenerators) |
||||
|
this.addGenerator(id, defGenerators[id]); |
||||
|
|
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Load default code viewers |
||||
|
* @return {this} |
||||
|
* @private |
||||
|
* */ |
||||
|
loadDefaultViewers() { |
||||
|
for (var id in defViewers) |
||||
|
this.addViewer(id, defViewers[id]); |
||||
|
|
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
}; |
||||
@ -1,227 +0,0 @@ |
|||||
/** |
|
||||
* - [addGenerator](#addgenerator) |
|
||||
* - [getGenerator](#getgenerator) |
|
||||
* - [getGenerators](#getgenerators) |
|
||||
* - [addViewer](#addviewer) |
|
||||
* - [getViewer](#getviewer) |
|
||||
* - [getViewers](#getviewers) |
|
||||
* - [updateViewer](#updateviewer) |
|
||||
* - [getCode](#getcode) |
|
||||
* |
|
||||
* |
|
||||
* Before using methods you should get first the module from the editor instance, in this way: |
|
||||
* |
|
||||
* ```js
|
|
||||
* var codeManager = editor.CodeManager; |
|
||||
* ``` |
|
||||
* |
|
||||
* @module CodeManager |
|
||||
*/ |
|
||||
define(function(require) { |
|
||||
|
|
||||
var CodeManager = function() { |
|
||||
|
|
||||
var c = {}, |
|
||||
defaults = require('./config/config'), |
|
||||
gHtml = require('./model/HtmlGenerator'), |
|
||||
gCss = require('./model/CssGenerator'), |
|
||||
gJson = require('./model/JsonGenerator'), |
|
||||
gJs = require('./model/JsGenerator'), |
|
||||
eCM = require('./model/CodeMirrorEditor'), |
|
||||
editorView = require('./view/EditorView'); |
|
||||
|
|
||||
var generators = {}, |
|
||||
defGenerators = {}, |
|
||||
viewers = {}, |
|
||||
defViewers = {}; |
|
||||
|
|
||||
return { |
|
||||
|
|
||||
getConfig: function() { |
|
||||
return c; |
|
||||
}, |
|
||||
|
|
||||
config: c, |
|
||||
|
|
||||
EditorView: editorView, |
|
||||
|
|
||||
/** |
|
||||
* Name of the module |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
name: 'CodeManager', |
|
||||
|
|
||||
/** |
|
||||
* Initialize module. Automatically called with a new instance of the editor |
|
||||
* @param {Object} config Configurations |
|
||||
*/ |
|
||||
init: function(config) { |
|
||||
c = config || {}; |
|
||||
for (var name in defaults) { |
|
||||
if (!(name in c)) |
|
||||
c[name] = defaults[name]; |
|
||||
} |
|
||||
|
|
||||
var ppfx = c.pStylePrefix; |
|
||||
if(ppfx) |
|
||||
c.stylePrefix = ppfx + c.stylePrefix; |
|
||||
|
|
||||
defGenerators.html = new gHtml(); |
|
||||
defGenerators.css = new gCss(); |
|
||||
defGenerators.json = new gJson(); |
|
||||
defGenerators.js = new gJs(); |
|
||||
|
|
||||
defViewers.CodeMirror = new eCM(); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Callback on load |
|
||||
*/ |
|
||||
onLoad: function(){ |
|
||||
this.loadDefaultGenerators().loadDefaultViewers(); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new code generator to the collection |
|
||||
* @param {string} id Code generator ID |
|
||||
* @param {Object} generator Code generator wrapper |
|
||||
* @param {Function} generator.build Function that builds the code |
|
||||
* @return {this} |
|
||||
* @example |
|
||||
* codeManager.addGenerator('html7',{ |
|
||||
* build: function(model){ |
|
||||
* return 'myCode'; |
|
||||
* } |
|
||||
* }); |
|
||||
* */ |
|
||||
addGenerator: function(id, generator) { |
|
||||
generators[id] = generator; |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get code generator by id |
|
||||
* @param {string} id Code generator ID |
|
||||
* @return {Object|null} |
|
||||
* @example |
|
||||
* var generator = codeManager.getGenerator('html7'); |
|
||||
* generator.build = function(model){ |
|
||||
* //extend
|
|
||||
* }; |
|
||||
* */ |
|
||||
getGenerator: function(id) { |
|
||||
return generators[id] || null; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns all code generators |
|
||||
* @return {Array<Object>} |
|
||||
* */ |
|
||||
getGenerators: function() { |
|
||||
return generators; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new code viewer |
|
||||
* @param {string} id Code viewer ID |
|
||||
* @param {Object} viewer Code viewer wrapper |
|
||||
* @param {Function} viewer.init Set element on which viewer will be displayed |
|
||||
* @param {Function} viewer.setContent Set content to the viewer |
|
||||
* @return {this} |
|
||||
* @example |
|
||||
* codeManager.addViewer('ace',{ |
|
||||
* init: function(el){ |
|
||||
* var ace = require('ace-editor'); |
|
||||
* this.editor = ace.edit(el.id); |
|
||||
* }, |
|
||||
* setContent: function(code){ |
|
||||
* this.editor.setValue(code); |
|
||||
* } |
|
||||
* }); |
|
||||
* */ |
|
||||
addViewer: function(id, viewer) { |
|
||||
viewers[id] = viewer; |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get code viewer by id |
|
||||
* @param {string} id Code viewer ID |
|
||||
* @return {Object|null} |
|
||||
* @example |
|
||||
* var viewer = codeManager.getViewer('ace'); |
|
||||
* */ |
|
||||
getViewer: function(id) { |
|
||||
return viewers[id] || null; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns all code viewers |
|
||||
* @return {Array<Object>} |
|
||||
* */ |
|
||||
getViewers: function() { |
|
||||
return viewers; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Update code viewer content |
|
||||
* @param {Object} viewer Viewer instance |
|
||||
* @param {string} code Code string |
|
||||
* @example |
|
||||
* var AceViewer = codeManager.getViewer('ace'); |
|
||||
* // ...
|
|
||||
* var viewer = AceViewer.init(el); |
|
||||
* // ...
|
|
||||
* codeManager.updateViewer(AceViewer, 'code'); |
|
||||
* */ |
|
||||
updateViewer: function(viewer, code) { |
|
||||
viewer.setContent(code); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get code from model |
|
||||
* @param {Object} model Any kind of model that will be passed to the build method of generator |
|
||||
* @param {string} genId Code generator id |
|
||||
* @param {Object} [opt] Options |
|
||||
* @return {string} |
|
||||
* @example |
|
||||
* var codeStr = codeManager.getCode(model, 'html'); |
|
||||
* */ |
|
||||
getCode: function(model, genId, opt) { |
|
||||
var generator = this.getGenerator(genId); |
|
||||
return generator ? generator.build(model, opt) : ''; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Load default code generators |
|
||||
* @return {this} |
|
||||
* @private |
|
||||
* */ |
|
||||
loadDefaultGenerators: function() { |
|
||||
for (var id in defGenerators) |
|
||||
this.addGenerator(id, defGenerators[id]); |
|
||||
|
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Load default code viewers |
|
||||
* @return {this} |
|
||||
* @private |
|
||||
* */ |
|
||||
loadDefaultViewers: function() { |
|
||||
for (var id in defViewers) |
|
||||
this.addViewer(id, defViewers[id]); |
|
||||
|
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
}; |
|
||||
|
|
||||
}; |
|
||||
|
|
||||
return CodeManager; |
|
||||
|
|
||||
}); |
|
||||
@ -1,51 +1,44 @@ |
|||||
define(['backbone', |
var Backbone = require('backbone'); |
||||
'codemirror/lib/codemirror', |
var CodeMirror = require('codemirror/lib/codemirror'); |
||||
'codemirror/mode/htmlmixed/htmlmixed', |
var htmlMode = require('codemirror/mode/htmlmixed/htmlmixed'); |
||||
'codemirror/mode/css/css', |
var cssMode = require('codemirror/mode/css/css'); |
||||
'formatting' |
var formatting = require('codemirror-formatting'); |
||||
], |
|
||||
function(Backbone, CodeMirror, htmlMode, cssMode, formatting) { |
|
||||
/** |
|
||||
* @class CodeViewer |
|
||||
* */ |
|
||||
return Backbone.Model.extend({ |
|
||||
|
|
||||
defaults: { |
module.exports = Backbone.Model.extend({ |
||||
input : '', |
|
||||
label : '', |
|
||||
codeName : '', |
|
||||
theme : '', |
|
||||
readOnly : true, |
|
||||
lineNumbers : true, |
|
||||
}, |
|
||||
|
|
||||
/** @inheritdoc */ |
defaults: { |
||||
init: function(el) |
input : '', |
||||
{ |
label : '', |
||||
this.editor = CodeMirror.fromTextArea(el, { |
codeName : '', |
||||
dragDrop: false, |
theme : '', |
||||
lineWrapping: true, |
readOnly : true, |
||||
lineNumbers: this.get('lineNumbers'), |
lineNumbers : true, |
||||
readOnly: this.get('readOnly'), |
}, |
||||
mode: this.get('codeName'), |
|
||||
theme: this.get('theme'), |
|
||||
}); |
|
||||
|
|
||||
return this; |
/** @inheritdoc */ |
||||
}, |
init(el) { |
||||
|
this.editor = CodeMirror.fromTextArea(el, { |
||||
|
dragDrop: false, |
||||
|
lineWrapping: true, |
||||
|
lineNumbers: this.get('lineNumbers'), |
||||
|
readOnly: this.get('readOnly'), |
||||
|
mode: this.get('codeName'), |
||||
|
theme: this.get('theme'), |
||||
|
}); |
||||
|
|
||||
/** @inheritdoc */ |
return this; |
||||
setContent : function(v) |
}, |
||||
{ |
|
||||
if(!this.editor) |
|
||||
return; |
|
||||
this.editor.setValue(v); |
|
||||
if(this.editor.autoFormatRange){ |
|
||||
CodeMirror.commands.selectAll(this.editor); |
|
||||
this.editor.autoFormatRange(this.editor.getCursor(true), this.editor.getCursor(false) ); |
|
||||
CodeMirror.commands.goDocStart(this.editor); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
}); |
/** @inheritdoc */ |
||||
}); |
setContent(v) { |
||||
|
if(!this.editor) |
||||
|
return; |
||||
|
this.editor.setValue(v); |
||||
|
if(this.editor.autoFormatRange){ |
||||
|
CodeMirror.commands.selectAll(this.editor); |
||||
|
this.editor.autoFormatRange(this.editor.getCursor(true), this.editor.getCursor(false) ); |
||||
|
CodeMirror.commands.goDocStart(this.editor); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
}); |
||||
|
|||||
@ -1,151 +1,147 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function (Backbone) { |
|
||||
/** |
module.exports = Backbone.Model.extend({ |
||||
* @class CssGenerator |
|
||||
* */ |
initialize() { |
||||
return Backbone.Model.extend({ |
this.compCls = []; |
||||
|
}, |
||||
initialize: function() { |
|
||||
this.compCls = []; |
/** |
||||
}, |
* Get CSS from component |
||||
|
* @param {Model} model |
||||
/** |
* @return {String} |
||||
* Get CSS from component |
*/ |
||||
* @param {Model} model |
buildFromModel(model) { |
||||
* @return {String} |
var code = ''; |
||||
*/ |
var style = model.get('style'); |
||||
buildFromModel: function (model) { |
var classes = model.get('classes'); |
||||
var code = ''; |
|
||||
var style = model.get('style'); |
// Let's know what classes I've found
|
||||
var classes = model.get('classes'); |
if(classes) { |
||||
|
classes.each(function(model){ |
||||
// Let's know what classes I've found
|
this.compCls.push(model.get('name')); |
||||
if(classes) { |
}, this); |
||||
classes.each(function(model){ |
} |
||||
this.compCls.push(model.get('name')); |
|
||||
}, this); |
if(style && Object.keys(style).length !== 0) { |
||||
|
code += '#' + model.cid + '{'; |
||||
|
for(var prop in style){ |
||||
|
if(style.hasOwnProperty(prop)) |
||||
|
code += prop + ':' + style[prop] + ';'; |
||||
|
} |
||||
|
code += '}'; |
||||
|
} |
||||
|
|
||||
|
return code; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get CSS from components |
||||
|
* @param {Model} model |
||||
|
* @return {String} |
||||
|
*/ |
||||
|
buildFromComp(model) { |
||||
|
var coll = model.get('components') || model, |
||||
|
code = ''; |
||||
|
|
||||
|
coll.each(function(m) { |
||||
|
var cln = m.get('components'); |
||||
|
code += this.buildFromModel(m); |
||||
|
|
||||
|
if(cln.length){ |
||||
|
code += this.buildFromComp(cln); |
||||
|
} |
||||
|
|
||||
|
}, this); |
||||
|
|
||||
|
return code; |
||||
|
}, |
||||
|
|
||||
|
/** @inheritdoc */ |
||||
|
build(model, cssc) { |
||||
|
this.compCls = []; |
||||
|
var code = this.buildFromModel(model); |
||||
|
code += this.buildFromComp(model); |
||||
|
var compCls = this.compCls; |
||||
|
|
||||
|
if(cssc){ |
||||
|
var rules = cssc.getAll(); |
||||
|
var mediaRules = {}; |
||||
|
rules.each(function(rule) { |
||||
|
var width = rule.get('mediaText'); |
||||
|
|
||||
|
// If width setted will render it later
|
||||
|
if(width){ |
||||
|
var mRule = mediaRules[width]; |
||||
|
if(mRule) |
||||
|
mRule.push(rule); |
||||
|
else |
||||
|
mediaRules[width] = [rule]; |
||||
|
return; |
||||
} |
} |
||||
|
|
||||
if(style && Object.keys(style).length !== 0) { |
code += this.buildFromRule(rule); |
||||
code += '#' + model.cid + '{'; |
}, this); |
||||
for(var prop in style){ |
|
||||
if(style.hasOwnProperty(prop)) |
|
||||
code += prop + ':' + style[prop] + ';'; |
|
||||
} |
|
||||
code += '}'; |
|
||||
} |
|
||||
|
|
||||
return code; |
// Get media rules
|
||||
}, |
for (var ruleW in mediaRules) { |
||||
|
var meRules = mediaRules[ruleW]; |
||||
/** |
var ruleC = ''; |
||||
* Get CSS from components |
for(var i = 0, len = meRules.length; i < len; i++){ |
||||
* @param {Model} model |
ruleC += this.buildFromRule(meRules[i]); |
||||
* @return {String} |
} |
||||
*/ |
|
||||
buildFromComp: function(model) { |
|
||||
var coll = model.get('components') || model, |
|
||||
code = ''; |
|
||||
|
|
||||
coll.each(function(m) { |
|
||||
var cln = m.get('components'); |
|
||||
code += this.buildFromModel(m); |
|
||||
|
|
||||
if(cln.length){ |
|
||||
code += this.buildFromComp(cln); |
|
||||
} |
|
||||
|
|
||||
}, this); |
|
||||
|
|
||||
return code; |
|
||||
}, |
|
||||
|
|
||||
/** @inheritdoc */ |
|
||||
build: function(model, cssc) { |
|
||||
this.compCls = []; |
|
||||
var code = this.buildFromModel(model); |
|
||||
code += this.buildFromComp(model); |
|
||||
var compCls = this.compCls; |
|
||||
|
|
||||
if(cssc){ |
|
||||
var rules = cssc.getAll(); |
|
||||
var mediaRules = {}; |
|
||||
rules.each(function(rule) { |
|
||||
var width = rule.get('mediaText'); |
|
||||
|
|
||||
// If width setted will render it later
|
|
||||
if(width){ |
|
||||
var mRule = mediaRules[width]; |
|
||||
if(mRule) |
|
||||
mRule.push(rule); |
|
||||
else |
|
||||
mediaRules[width] = [rule]; |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
code += this.buildFromRule(rule); |
|
||||
}, this); |
|
||||
|
|
||||
// Get media rules
|
|
||||
for (var ruleW in mediaRules) { |
|
||||
var meRules = mediaRules[ruleW]; |
|
||||
var ruleC = ''; |
|
||||
for(var i = 0, len = meRules.length; i < len; i++){ |
|
||||
ruleC += this.buildFromRule(meRules[i]); |
|
||||
} |
|
||||
|
|
||||
if (ruleC) { |
|
||||
code += '@media ' + ruleW + '{' + ruleC + '}'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
if (ruleC) { |
||||
|
code += '@media ' + ruleW + '{' + ruleC + '}'; |
||||
} |
} |
||||
return code; |
} |
||||
}, |
|
||||
|
} |
||||
/** |
return code; |
||||
* Get CSS from the rule model |
}, |
||||
* @param {Model} rule |
|
||||
* @return {string} CSS string |
/** |
||||
*/ |
* Get CSS from the rule model |
||||
buildFromRule: function(rule) { |
* @param {Model} rule |
||||
var result = ''; |
* @return {string} CSS string |
||||
var selectorsAdd = rule.get('selectorsAdd'); |
*/ |
||||
var selectors = rule.get('selectors'); |
buildFromRule(rule) { |
||||
var ruleStyle = rule.get('style'); |
var result = ''; |
||||
var state = rule.get('state'); |
var selectorsAdd = rule.get('selectorsAdd'); |
||||
var strSel = ''; |
var selectors = rule.get('selectors'); |
||||
var found = 0; |
var ruleStyle = rule.get('style'); |
||||
var compCls = this.compCls; |
var state = rule.get('state'); |
||||
|
var strSel = ''; |
||||
// Get string of selectors
|
var found = 0; |
||||
selectors.each(function(selector){ |
var compCls = this.compCls; |
||||
strSel += '.' + selector.get('name'); |
|
||||
if(compCls.indexOf(selector.get('name')) > -1) |
// Get string of selectors
|
||||
found = 1; |
selectors.each(selector => { |
||||
}); |
strSel += '.' + selector.get('name'); |
||||
|
if(compCls.indexOf(selector.get('name')) > -1) |
||||
// With 'found' will skip rules which selectors are not found in
|
found = 1; |
||||
// canvas components.
|
}); |
||||
if ((strSel && found) || selectorsAdd) { |
|
||||
strSel += state ? ':' + state : ''; |
// With 'found' will skip rules which selectors are not found in
|
||||
strSel += selectorsAdd ? (strSel ? ', ' : '') + selectorsAdd : ''; |
// canvas components.
|
||||
var strStyle = ''; |
if ((strSel && found) || selectorsAdd) { |
||||
|
strSel += state ? ':' + state : ''; |
||||
// Get string of style properties
|
strSel += selectorsAdd ? (strSel ? ', ' : '') + selectorsAdd : ''; |
||||
if(ruleStyle && Object.keys(ruleStyle).length !== 0){ |
var strStyle = ''; |
||||
for(var prop2 in ruleStyle){ |
|
||||
if(ruleStyle.hasOwnProperty(prop2)) |
// Get string of style properties
|
||||
strStyle += prop2 + ':' + ruleStyle[prop2] + ';'; |
if(ruleStyle && Object.keys(ruleStyle).length !== 0){ |
||||
} |
for(var prop2 in ruleStyle){ |
||||
} |
if(ruleStyle.hasOwnProperty(prop2)) |
||||
|
strStyle += prop2 + ':' + ruleStyle[prop2] + ';'; |
||||
if(strStyle) |
|
||||
result += strSel + '{' + strStyle + '}'; |
|
||||
} |
} |
||||
|
} |
||||
|
|
||||
return result; |
if(strStyle) |
||||
}, |
result += strSel + '{' + strStyle + '}'; |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,23 +1,19 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function (Backbone) { |
|
||||
/** |
|
||||
* @class HtmlGenerator |
|
||||
* */ |
|
||||
return Backbone.Model.extend({ |
|
||||
|
|
||||
/** @inheritdoc */ |
module.exports = Backbone.Model.extend({ |
||||
build: function(model, cssc){ |
|
||||
var coll = model.get('components') || model, |
|
||||
code = ''; |
|
||||
|
|
||||
coll.each(function(m){ |
/** @inheritdoc */ |
||||
code += m.toHTML({ |
build(model, cssc) { |
||||
cssc: cssc |
var coll = model.get('components') || model, |
||||
}); |
code = ''; |
||||
}, this); |
|
||||
|
|
||||
return code; |
coll.each(m => { |
||||
}, |
code += m.toHTML({ |
||||
|
cssc |
||||
|
}); |
||||
|
}, this); |
||||
|
|
||||
|
return code; |
||||
|
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,62 +1,61 @@ |
|||||
define(['backbone'], function (Backbone) { |
var Backbone = require('backbone'); |
||||
|
|
||||
return Backbone.Model.extend({ |
module.exports = Backbone.Model.extend({ |
||||
|
|
||||
mapModel: function (model) { |
mapModel(model) { |
||||
var code = ''; |
var code = ''; |
||||
var script = model.get('script'); |
var script = model.get('script'); |
||||
var type = model.get('type'); |
var type = model.get('type'); |
||||
var comps = model.get('components'); |
var comps = model.get('components'); |
||||
var id = model.cid; |
var id = model.cid; |
||||
|
|
||||
if (script) { |
if (script) { |
||||
// If the component has scripts we need to expose his ID
|
// If the component has scripts we need to expose his ID
|
||||
var attr = model.get('attributes'); |
var attr = model.get('attributes'); |
||||
attr = _.extend({}, attr, {id: id}); |
attr = _.extend({}, attr, {id}); |
||||
model.set('attributes', attr); |
model.set('attributes', attr); |
||||
|
|
||||
var scrStr = 'function(){' + script + '}'; |
var scrStr = 'function(){' + script + '}'; |
||||
scrStr = typeof script == 'function' ? script.toString() : scrStr; |
scrStr = typeof script == 'function' ? script.toString() : scrStr; |
||||
|
|
||||
// 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')) { |
||||
this.mapJs[type+'-'+id] = {ids: [id], code: scrStr}; |
this.mapJs[type+'-'+id] = {ids: [id], code: scrStr}; |
||||
} else { |
} else { |
||||
var mapType = this.mapJs[type]; |
var mapType = this.mapJs[type]; |
||||
|
|
||||
if(mapType) { |
if(mapType) { |
||||
mapType.ids.push(id); |
mapType.ids.push(id); |
||||
} else { |
} else { |
||||
this.mapJs[type] = {ids: [id], code: scrStr}; |
this.mapJs[type] = {ids: [id], code: scrStr}; |
||||
} |
|
||||
} |
|
||||
} |
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
comps.each(function(model) { |
comps.each(function(model) { |
||||
code += this.mapModel(model); |
code += this.mapModel(model); |
||||
}, this); |
}, this); |
||||
|
|
||||
return code; |
return code; |
||||
}, |
}, |
||||
|
|
||||
build: function(model) { |
build(model) { |
||||
this.mapJs = {}; |
this.mapJs = {}; |
||||
this.mapModel(model); |
this.mapModel(model); |
||||
|
|
||||
var code = ''; |
var code = ''; |
||||
|
|
||||
for(var type in this.mapJs) { |
for(var type in this.mapJs) { |
||||
var mapType = this.mapJs[type]; |
var mapType = this.mapJs[type]; |
||||
var ids = '#' + mapType.ids.join(', #'); |
var ids = '#' + mapType.ids.join(', #'); |
||||
code += 'var items = document.querySelectorAll("'+ids+'");' + |
code += 'var items = document.querySelectorAll("'+ids+'");' + |
||||
'for (var i = 0, len = items.length; i < len; i++) {'+ |
'for (var i = 0, len = items.length; i < len; i++) {'+ |
||||
'(' + mapType.code + '.bind(items[i]))();' + |
'(' + mapType.code + '.bind(items[i]))();' + |
||||
'}'; |
'}'; |
||||
} |
} |
||||
|
|
||||
|
|
||||
return code; |
return code; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,40 +1,36 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function (Backbone) { |
|
||||
/** |
|
||||
* @class JsonGenerator |
|
||||
* */ |
|
||||
return Backbone.Model.extend({ |
|
||||
|
|
||||
/** @inheritdoc */ |
module.exports = Backbone.Model.extend({ |
||||
build: function(model) { |
|
||||
var json = model.toJSON(); |
|
||||
this.beforeEach(json); |
|
||||
|
|
||||
_.each(json,function(v, attr){ |
/** @inheritdoc */ |
||||
var obj = json[attr]; |
build(model) { |
||||
if(obj instanceof Backbone.Model){ |
var json = model.toJSON(); |
||||
json[attr] = this.build(obj); |
this.beforeEach(json); |
||||
}else if(obj instanceof Backbone.Collection){ |
|
||||
var coll = obj; |
|
||||
json[attr] = []; |
|
||||
if(coll.length){ |
|
||||
coll.each(function (el, index) { |
|
||||
json[attr][index] = this.build(el); |
|
||||
}, this); |
|
||||
} |
|
||||
} |
|
||||
}, this); |
|
||||
|
|
||||
return json; |
_.each(json,function(v, attr){ |
||||
}, |
var obj = json[attr]; |
||||
|
if(obj instanceof Backbone.Model){ |
||||
|
json[attr] = this.build(obj); |
||||
|
}else if(obj instanceof Backbone.Collection){ |
||||
|
var coll = obj; |
||||
|
json[attr] = []; |
||||
|
if(coll.length){ |
||||
|
coll.each(function (el, index) { |
||||
|
json[attr][index] = this.build(el); |
||||
|
}, this); |
||||
|
} |
||||
|
} |
||||
|
}, this); |
||||
|
|
||||
/** |
return json; |
||||
* Execute on each object |
}, |
||||
* @param {Object} obj |
|
||||
*/ |
/** |
||||
beforeEach: function(obj) { |
* Execute on each object |
||||
delete obj.status; |
* @param {Object} obj |
||||
} |
*/ |
||||
|
beforeEach(obj) { |
||||
|
delete obj.status; |
||||
|
} |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,4 +0,0 @@ |
|||||
<div class="<%= pfx %>editor" id="<%= pfx %><%= codeName %>"> |
|
||||
<div id="<%= pfx %>title"><%= label %></div> |
|
||||
<div id="<%= pfx %>code"></div> |
|
||||
</div> |
|
||||
@ -1,25 +1,25 @@ |
|||||
define(['backbone', 'text!./../template/editor.html'], |
var Backbone = require('backbone'); |
||||
function (Backbone, vTemplate) { |
|
||||
/** |
module.exports = Backbone.View.extend({ |
||||
* @class EditorView |
|
||||
* */ |
template: _.template(` |
||||
return Backbone.View.extend({ |
<div class="<%= pfx %>editor" id="<%= pfx %><%= codeName %>"> |
||||
|
<div id="<%= pfx %>title"><%= label %></div> |
||||
template: _.template(vTemplate), |
<div id="<%= pfx %>code"></div> |
||||
|
</div>`), |
||||
initialize: function(o){ |
|
||||
this.config = o.config || {}; |
initialize(o) { |
||||
this.pfx = this.config.stylePrefix; |
this.config = o.config || {}; |
||||
}, |
this.pfx = this.config.stylePrefix; |
||||
|
}, |
||||
render : function(){ |
|
||||
var obj = this.model.toJSON(); |
render() { |
||||
obj.pfx = this.pfx; |
var obj = this.model.toJSON(); |
||||
this.$el.html( this.template(obj) ); |
obj.pfx = this.pfx; |
||||
this.$el.attr('class', this.pfx + 'editor-c'); |
this.$el.html( this.template(obj) ); |
||||
this.$el.find('#'+this.pfx+'code').html(this.model.get('input')); |
this.$el.attr('class', this.pfx + 'editor-c'); |
||||
return this; |
this.$el.find('#'+this.pfx+'code').html(this.model.get('input')); |
||||
}, |
return this; |
||||
|
}, |
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,25 +1,23 @@ |
|||||
define(function () { |
module.exports = { |
||||
return { |
|
||||
|
|
||||
ESCAPE_KEY : 27, |
ESCAPE_KEY: 27, |
||||
|
|
||||
stylePrefix : 'com-', |
stylePrefix: 'com-', |
||||
|
|
||||
defaults : [], |
defaults: [], |
||||
|
|
||||
// Editor model
|
// Editor model
|
||||
em : null, |
em: null, |
||||
|
|
||||
// If true center new first-level components
|
// If true center new first-level components
|
||||
firstCentered : true, |
firstCentered: true, |
||||
|
|
||||
// If true the new component will created with 'height', else 'min-height'
|
// If true the new component will created with 'height', else 'min-height'
|
||||
newFixedH : false, |
newFixedH: false, |
||||
|
|
||||
// Minimum height (in px) of new component
|
// Minimum height (in px) of new component
|
||||
minComponentH : 50, |
minComponentH: 50, |
||||
|
|
||||
// Minimum width (in px) of component on creation
|
// Minimum width (in px) of component on creation
|
||||
minComponentW : 50, |
minComponentW: 50, |
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -0,0 +1,236 @@ |
|||||
|
/** |
||||
|
* |
||||
|
* * [add](#add) |
||||
|
* * [get](#get) |
||||
|
* * [has](#has) |
||||
|
* |
||||
|
* You can init the editor with all necessary commands via configuration |
||||
|
* |
||||
|
* ```js
|
||||
|
* var editor = grapesjs.init({ |
||||
|
* ... |
||||
|
* commands: {...} // Check below for the properties
|
||||
|
* ... |
||||
|
* }); |
||||
|
* ``` |
||||
|
* |
||||
|
* Before using methods you should get first the module from the editor instance, in this way: |
||||
|
* |
||||
|
* ```js
|
||||
|
* var commands = editor.Commands; |
||||
|
* ``` |
||||
|
* |
||||
|
* @module Commands |
||||
|
* @param {Object} config Configurations |
||||
|
* @param {Array<Object>} [config.defaults=[]] Array of possible commands |
||||
|
* @example |
||||
|
* ... |
||||
|
* commands: { |
||||
|
* defaults: [{ |
||||
|
* id: 'helloWorld', |
||||
|
* run: function(editor, sender){ |
||||
|
* alert('Hello world!'); |
||||
|
* }, |
||||
|
* stop: function(editor, sender){ |
||||
|
* alert('Stop!'); |
||||
|
* }, |
||||
|
* }], |
||||
|
* }, |
||||
|
* ... |
||||
|
*/ |
||||
|
|
||||
|
module.exports = () => { |
||||
|
var c = {}, |
||||
|
commands = {}, |
||||
|
defaultCommands = {}, |
||||
|
defaults = require('./config/config'), |
||||
|
AbsCommands = require('./view/CommandAbstract'); |
||||
|
|
||||
|
// Need it here as it would be used below
|
||||
|
var add = function(id, obj){ |
||||
|
delete obj.initialize; |
||||
|
commands[id] = AbsCommands.extend(obj); |
||||
|
return this; |
||||
|
}; |
||||
|
|
||||
|
return { |
||||
|
|
||||
|
/** |
||||
|
* Name of the module |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
name: 'Commands', |
||||
|
|
||||
|
/** |
||||
|
* Initialize module. Automatically called with a new instance of the editor |
||||
|
* @param {Object} config Configurations |
||||
|
* @private |
||||
|
*/ |
||||
|
init(config) { |
||||
|
c = config || {}; |
||||
|
for (var name in defaults) { |
||||
|
if (!(name in c)) |
||||
|
c[name] = defaults[name]; |
||||
|
} |
||||
|
|
||||
|
var ppfx = c.pStylePrefix; |
||||
|
if(ppfx) |
||||
|
c.stylePrefix = ppfx + c.stylePrefix; |
||||
|
|
||||
|
// Load commands passed via configuration
|
||||
|
for( var k in c.defaults) { |
||||
|
var obj = c.defaults[k]; |
||||
|
if(obj.id) |
||||
|
this.add(obj.id, obj); |
||||
|
} |
||||
|
|
||||
|
defaultCommands['select-comp'] = require('./view/SelectComponent'); |
||||
|
defaultCommands['create-comp'] = require('./view/CreateComponent'); |
||||
|
defaultCommands['delete-comp'] = require('./view/DeleteComponent'); |
||||
|
defaultCommands['image-comp'] = require('./view/ImageComponent'); |
||||
|
defaultCommands['move-comp'] = require('./view/MoveComponent'); |
||||
|
defaultCommands['text-comp'] = require('./view/TextComponent'); |
||||
|
defaultCommands['insert-custom'] = require('./view/InsertCustom'); |
||||
|
defaultCommands['export-template'] = require('./view/ExportTemplate'); |
||||
|
defaultCommands['sw-visibility'] = require('./view/SwitchVisibility'); |
||||
|
defaultCommands['open-layers'] = require('./view/OpenLayers'); |
||||
|
defaultCommands['open-sm'] = require('./view/OpenStyleManager'); |
||||
|
defaultCommands['open-tm'] = require('./view/OpenTraitManager'); |
||||
|
defaultCommands['open-blocks'] = require('./view/OpenBlocks'); |
||||
|
defaultCommands['open-assets'] = require('./view/OpenAssets'); |
||||
|
defaultCommands['show-offset'] = require('./view/ShowOffset'); |
||||
|
defaultCommands.fullscreen = require('./view/Fullscreen'); |
||||
|
defaultCommands.preview = require('./view/Preview'); |
||||
|
defaultCommands.resize = require('./view/Resize'); |
||||
|
|
||||
|
defaultCommands['tlb-delete'] = { |
||||
|
run(ed) { |
||||
|
var sel = ed.getSelected(); |
||||
|
|
||||
|
if(!sel || !sel.get('removable')) { |
||||
|
console.warn('The element is not removable'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
sel.set('status', ''); |
||||
|
sel.destroy(); |
||||
|
ed.trigger('component:update', sel); |
||||
|
ed.editor.set('selectedComponent', null); |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
defaultCommands['tlb-clone'] = { |
||||
|
run(ed) { |
||||
|
var sel = ed.getSelected(); |
||||
|
|
||||
|
if(!sel || !sel.get('copyable')) { |
||||
|
console.warn('The element is not clonable'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var collection = sel.collection; |
||||
|
var index = collection.indexOf(sel); |
||||
|
collection.add(sel.clone(), {at: index + 1}); |
||||
|
ed.trigger('component:update', sel); |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
defaultCommands['tlb-move'] = { |
||||
|
run(ed) { |
||||
|
var sel = ed.getSelected(); |
||||
|
|
||||
|
if(!sel || !sel.get('draggable')) { |
||||
|
console.warn('The element is not draggable'); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var toolbarEl = ed.Canvas.getToolbarEl(); |
||||
|
var cmdMove = ed.Commands.get('move-comp'); |
||||
|
|
||||
|
cmdMove.onEndMoveFromModel = () => { |
||||
|
ed.editor.runDefault(); |
||||
|
ed.editor.set('selectedComponent', sel); |
||||
|
ed.trigger('component:update', sel); |
||||
|
}; |
||||
|
|
||||
|
ed.editor.stopDefault(); |
||||
|
cmdMove.initSorterFromModel(sel); |
||||
|
sel.set('status', 'selected'); |
||||
|
toolbarEl.style.display = 'none'; |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
if(c.em) |
||||
|
c.model = c.em.get('Canvas'); |
||||
|
|
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* On load callback |
||||
|
* @private |
||||
|
*/ |
||||
|
onLoad() { |
||||
|
this.loadDefaultCommands(); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new command to the collection |
||||
|
* @param {string} id Command's ID |
||||
|
* @param {Object} command Object representing you command. Methods `run` and `stop` are required |
||||
|
* @return {this} |
||||
|
* @example |
||||
|
* commands.add('myCommand', { |
||||
|
* run: function(editor, sender){ |
||||
|
* alert('Hello world!'); |
||||
|
* }, |
||||
|
* stop: function(editor, sender){ |
||||
|
* }, |
||||
|
* }); |
||||
|
* */ |
||||
|
add, |
||||
|
|
||||
|
/** |
||||
|
* Get command by ID |
||||
|
* @param {string} id Command's ID |
||||
|
* @return {Object} Object representing the command |
||||
|
* @example |
||||
|
* var myCommand = commands.get('myCommand'); |
||||
|
* myCommand.run(); |
||||
|
* */ |
||||
|
get(id) { |
||||
|
var el = commands[id]; |
||||
|
|
||||
|
if(typeof el == 'function'){ |
||||
|
el = new el(c); |
||||
|
commands[id] = el; |
||||
|
} |
||||
|
|
||||
|
return el; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Check if command exists |
||||
|
* @param {string} id Command's ID |
||||
|
* @return {Boolean} |
||||
|
* */ |
||||
|
has(id) { |
||||
|
return !!commands[id]; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Load default commands |
||||
|
* @return {this} |
||||
|
* @private |
||||
|
* */ |
||||
|
loadDefaultCommands() { |
||||
|
for (var id in defaultCommands) { |
||||
|
this.add(id, defaultCommands[id]); |
||||
|
} |
||||
|
|
||||
|
return this; |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
}; |
||||
@ -1,238 +0,0 @@ |
|||||
/** |
|
||||
* |
|
||||
* * [add](#add) |
|
||||
* * [get](#get) |
|
||||
* * [has](#has) |
|
||||
* |
|
||||
* You can init the editor with all necessary commands via configuration |
|
||||
* |
|
||||
* ```js
|
|
||||
* var editor = grapesjs.init({ |
|
||||
* ... |
|
||||
* commands: {...} // Check below for the properties
|
|
||||
* ... |
|
||||
* }); |
|
||||
* ``` |
|
||||
* |
|
||||
* Before using methods you should get first the module from the editor instance, in this way: |
|
||||
* |
|
||||
* ```js
|
|
||||
* var commands = editor.Commands; |
|
||||
* ``` |
|
||||
* |
|
||||
* @module Commands |
|
||||
* @param {Object} config Configurations |
|
||||
* @param {Array<Object>} [config.defaults=[]] Array of possible commands |
|
||||
* @example |
|
||||
* ... |
|
||||
* commands: { |
|
||||
* defaults: [{ |
|
||||
* id: 'helloWorld', |
|
||||
* run: function(editor, sender){ |
|
||||
* alert('Hello world!'); |
|
||||
* }, |
|
||||
* stop: function(editor, sender){ |
|
||||
* alert('Stop!'); |
|
||||
* }, |
|
||||
* }], |
|
||||
* }, |
|
||||
* ... |
|
||||
*/ |
|
||||
define(function(require) { |
|
||||
|
|
||||
return function() { |
|
||||
var c = {}, |
|
||||
commands = {}, |
|
||||
defaultCommands = {}, |
|
||||
defaults = require('./config/config'), |
|
||||
AbsCommands = require('./view/CommandAbstract'); |
|
||||
|
|
||||
// Need it here as it would be used below
|
|
||||
var add = function(id, obj){ |
|
||||
delete obj.initialize; |
|
||||
commands[id] = AbsCommands.extend(obj); |
|
||||
return this; |
|
||||
}; |
|
||||
|
|
||||
return { |
|
||||
|
|
||||
/** |
|
||||
* Name of the module |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
name: 'Commands', |
|
||||
|
|
||||
/** |
|
||||
* Initialize module. Automatically called with a new instance of the editor |
|
||||
* @param {Object} config Configurations |
|
||||
* @private |
|
||||
*/ |
|
||||
init: function(config) { |
|
||||
c = config || {}; |
|
||||
for (var name in defaults) { |
|
||||
if (!(name in c)) |
|
||||
c[name] = defaults[name]; |
|
||||
} |
|
||||
|
|
||||
var ppfx = c.pStylePrefix; |
|
||||
if(ppfx) |
|
||||
c.stylePrefix = ppfx + c.stylePrefix; |
|
||||
|
|
||||
// Load commands passed via configuration
|
|
||||
for( var k in c.defaults) { |
|
||||
var obj = c.defaults[k]; |
|
||||
if(obj.id) |
|
||||
this.add(obj.id, obj); |
|
||||
} |
|
||||
|
|
||||
defaultCommands['select-comp'] = require('./view/SelectComponent'); |
|
||||
defaultCommands['create-comp'] = require('./view/CreateComponent'); |
|
||||
defaultCommands['delete-comp'] = require('./view/DeleteComponent'); |
|
||||
defaultCommands['image-comp'] = require('./view/ImageComponent'); |
|
||||
defaultCommands['move-comp'] = require('./view/MoveComponent'); |
|
||||
defaultCommands['text-comp'] = require('./view/TextComponent'); |
|
||||
defaultCommands['insert-custom'] = require('./view/InsertCustom'); |
|
||||
defaultCommands['export-template'] = require('./view/ExportTemplate'); |
|
||||
defaultCommands['sw-visibility'] = require('./view/SwitchVisibility'); |
|
||||
defaultCommands['open-layers'] = require('./view/OpenLayers'); |
|
||||
defaultCommands['open-sm'] = require('./view/OpenStyleManager'); |
|
||||
defaultCommands['open-tm'] = require('./view/OpenTraitManager'); |
|
||||
defaultCommands['open-blocks'] = require('./view/OpenBlocks'); |
|
||||
defaultCommands['open-assets'] = require('./view/OpenAssets'); |
|
||||
defaultCommands['show-offset'] = require('./view/ShowOffset'); |
|
||||
defaultCommands.fullscreen = require('./view/Fullscreen'); |
|
||||
defaultCommands.preview = require('./view/Preview'); |
|
||||
defaultCommands.resize = require('./view/Resize'); |
|
||||
|
|
||||
defaultCommands['tlb-delete'] = { |
|
||||
run: function(ed) { |
|
||||
var sel = ed.getSelected(); |
|
||||
|
|
||||
if(!sel || !sel.get('removable')) { |
|
||||
console.warn('The element is not removable'); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
sel.set('status', ''); |
|
||||
sel.destroy(); |
|
||||
ed.trigger('component:update', sel); |
|
||||
ed.editor.set('selectedComponent', null); |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
defaultCommands['tlb-clone'] = { |
|
||||
run: function(ed) { |
|
||||
var sel = ed.getSelected(); |
|
||||
|
|
||||
if(!sel || !sel.get('copyable')) { |
|
||||
console.warn('The element is not clonable'); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var collection = sel.collection; |
|
||||
var index = collection.indexOf(sel); |
|
||||
collection.add(sel.clone(), {at: index + 1}); |
|
||||
ed.trigger('component:update', sel); |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
defaultCommands['tlb-move'] = { |
|
||||
run: function(ed){ |
|
||||
var sel = ed.getSelected(); |
|
||||
|
|
||||
if(!sel || !sel.get('draggable')) { |
|
||||
console.warn('The element is not draggable'); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var toolbarEl = ed.Canvas.getToolbarEl(); |
|
||||
var cmdMove = ed.Commands.get('move-comp'); |
|
||||
|
|
||||
cmdMove.onEndMoveFromModel = function() { |
|
||||
ed.editor.runDefault(); |
|
||||
ed.editor.set('selectedComponent', sel); |
|
||||
ed.trigger('component:update', sel); |
|
||||
}; |
|
||||
|
|
||||
ed.editor.stopDefault(); |
|
||||
cmdMove.initSorterFromModel(sel); |
|
||||
sel.set('status', 'selected'); |
|
||||
toolbarEl.style.display = 'none'; |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
if(c.em) |
|
||||
c.model = c.em.get('Canvas'); |
|
||||
|
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* On load callback |
|
||||
* @private |
|
||||
*/ |
|
||||
onLoad: function() { |
|
||||
this.loadDefaultCommands(); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new command to the collection |
|
||||
* @param {string} id Command's ID |
|
||||
* @param {Object} command Object representing you command. Methods `run` and `stop` are required |
|
||||
* @return {this} |
|
||||
* @example |
|
||||
* commands.add('myCommand', { |
|
||||
* run: function(editor, sender){ |
|
||||
* alert('Hello world!'); |
|
||||
* }, |
|
||||
* stop: function(editor, sender){ |
|
||||
* }, |
|
||||
* }); |
|
||||
* */ |
|
||||
add: add, |
|
||||
|
|
||||
/** |
|
||||
* Get command by ID |
|
||||
* @param {string} id Command's ID |
|
||||
* @return {Object} Object representing the command |
|
||||
* @example |
|
||||
* var myCommand = commands.get('myCommand'); |
|
||||
* myCommand.run(); |
|
||||
* */ |
|
||||
get: function(id) { |
|
||||
var el = commands[id]; |
|
||||
|
|
||||
if(typeof el == 'function'){ |
|
||||
el = new el(c); |
|
||||
commands[id] = el; |
|
||||
} |
|
||||
|
|
||||
return el; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Check if command exists |
|
||||
* @param {string} id Command's ID |
|
||||
* @return {Boolean} |
|
||||
* */ |
|
||||
has: function(id) { |
|
||||
return !!commands[id]; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Load default commands |
|
||||
* @return {this} |
|
||||
* @private |
|
||||
* */ |
|
||||
loadDefaultCommands: function(){ |
|
||||
for (var id in defaultCommands) { |
|
||||
this.add(id, defaultCommands[id]); |
|
||||
} |
|
||||
|
|
||||
return this; |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
}; |
|
||||
}); |
|
||||
@ -1,13 +1,9 @@ |
|||||
define([ 'backbone'], |
var Backbone = require('backbone'); |
||||
function (Backbone) { |
|
||||
/** |
module.exports = Backbone.Model.extend({ |
||||
* @class Command |
|
||||
* */ |
defaults :{ |
||||
return Backbone.Model.extend({ |
id: '', |
||||
|
} |
||||
defaults :{ |
|
||||
id : '', |
|
||||
} |
|
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,11 +1,8 @@ |
|||||
define([ 'backbone','./Command'], |
var Backbone = require('backbone'); |
||||
function (Backbone, Command) { |
var Command = require('./Command'); |
||||
/** |
|
||||
* @class Commands |
module.exports = Backbone.Collection.extend({ |
||||
* */ |
|
||||
return Backbone.Collection.extend({ |
model: Command, |
||||
|
|
||||
model: Command, |
|
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,116 +1,111 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function(Backbone) { |
|
||||
/** |
module.exports = Backbone.View.extend({ |
||||
* @class CommandAbstract |
|
||||
* @private |
/** |
||||
* */ |
* Initialize method that can't be removed |
||||
return Backbone.View.extend({ |
* @param {Object} o Options |
||||
|
* @private |
||||
/** |
* */ |
||||
* Initialize method that can't be removed |
initialize(o) { |
||||
* @param {Object} o Options |
this.config = o || {}; |
||||
* @private |
this.editorModel = this.em = this.config.em || {}; |
||||
* */ |
this.pfx = this.config.stylePrefix; |
||||
initialize: function(o) { |
this.ppfx = this.config.pStylePrefix; |
||||
this.config = o || {}; |
this.hoverClass = this.pfx + 'hover'; |
||||
this.editorModel = this.em = this.config.em || {}; |
this.badgeClass = this.pfx + 'badge'; |
||||
this.pfx = this.config.stylePrefix; |
this.plhClass = this.pfx + 'placeholder'; |
||||
this.ppfx = this.config.pStylePrefix; |
this.freezClass = this.ppfx + 'freezed'; |
||||
this.hoverClass = this.pfx + 'hover'; |
|
||||
this.badgeClass = this.pfx + 'badge'; |
this.canvas = this.em.get && this.em.get('Canvas'); |
||||
this.plhClass = this.pfx + 'placeholder'; |
|
||||
this.freezClass = this.ppfx + 'freezed'; |
if(this.em.get) |
||||
|
this.setElement(this.getCanvas()); |
||||
this.canvas = this.em.get && this.em.get('Canvas'); |
|
||||
|
if(this.canvas){ |
||||
if(this.em.get) |
this.$canvas = this.$el; |
||||
this.setElement(this.getCanvas()); |
this.$wrapper = $(this.getCanvasWrapper()); |
||||
|
this.frameEl = this.canvas.getFrameEl(); |
||||
if(this.canvas){ |
this.canvasTool = this.getCanvasTools(); |
||||
this.$canvas = this.$el; |
this.bodyEl = this.getCanvasBody(); |
||||
this.$wrapper = $(this.getCanvasWrapper()); |
} |
||||
this.frameEl = this.canvas.getFrameEl(); |
|
||||
this.canvasTool = this.getCanvasTools(); |
this.init(this.config); |
||||
this.bodyEl = this.getCanvasBody(); |
}, |
||||
} |
|
||||
|
/** |
||||
this.init(this.config); |
* On frame scroll callback |
||||
}, |
* @param {[type]} e [description] |
||||
|
* @return {[type]} [description] |
||||
/** |
*/ |
||||
* On frame scroll callback |
onFrameScroll(e) {}, |
||||
* @param {[type]} e [description] |
|
||||
* @return {[type]} [description] |
/** |
||||
*/ |
* Returns canval element |
||||
onFrameScroll: function(e){}, |
* @return {HTMLElement} |
||||
|
*/ |
||||
/** |
getCanvas() { |
||||
* Returns canval element |
return this.canvas.getElement(); |
||||
* @return {HTMLElement} |
}, |
||||
*/ |
|
||||
getCanvas: function(){ |
/** |
||||
return this.canvas.getElement(); |
* Get canvas body element |
||||
}, |
* @return {HTMLElement} |
||||
|
*/ |
||||
/** |
getCanvasBody() { |
||||
* Get canvas body element |
return this.canvas.getBody(); |
||||
* @return {HTMLElement} |
}, |
||||
*/ |
|
||||
getCanvasBody: function(){ |
/** |
||||
return this.canvas.getBody(); |
* Get canvas wrapper element |
||||
}, |
* @return {HTMLElement} |
||||
|
*/ |
||||
/** |
getCanvasWrapper() { |
||||
* Get canvas wrapper element |
return this.canvas.getWrapperEl(); |
||||
* @return {HTMLElement} |
}, |
||||
*/ |
|
||||
getCanvasWrapper: function(){ |
/** |
||||
return this.canvas.getWrapperEl(); |
* Get canvas wrapper element |
||||
}, |
* @return {HTMLElement} |
||||
|
*/ |
||||
/** |
getCanvasTools() { |
||||
* Get canvas wrapper element |
return this.canvas.getToolsEl(); |
||||
* @return {HTMLElement} |
}, |
||||
*/ |
|
||||
getCanvasTools: function(){ |
/** |
||||
return this.canvas.getToolsEl(); |
* Get the offset of the element |
||||
}, |
* @param {HTMLElement} el |
||||
|
* @return {Object} |
||||
/** |
*/ |
||||
* Get the offset of the element |
offset(el) { |
||||
* @param {HTMLElement} el |
var rect = el.getBoundingClientRect(); |
||||
* @return {Object} |
return { |
||||
*/ |
top: rect.top + el.ownerDocument.body.scrollTop, |
||||
offset: function(el){ |
left: rect.left + el.ownerDocument.body.scrollLeft |
||||
var rect = el.getBoundingClientRect(); |
}; |
||||
return { |
}, |
||||
top: rect.top + el.ownerDocument.body.scrollTop, |
|
||||
left: rect.left + el.ownerDocument.body.scrollLeft |
/** |
||||
}; |
* Callback triggered after initialize |
||||
}, |
* @param {Object} o Options |
||||
|
* @private |
||||
/** |
* */ |
||||
* Callback triggered after initialize |
init(o) {}, |
||||
* @param {Object} o Options |
|
||||
* @private |
/** |
||||
* */ |
* Method that run command |
||||
init: function(o){}, |
* @param {Object} em Editor model |
||||
|
* @param {Object} sender Button sender |
||||
/** |
* @private |
||||
* Method that run command |
* */ |
||||
* @param {Object} em Editor model |
run(em, sender) {}, |
||||
* @param {Object} sender Button sender |
|
||||
* @private |
/** |
||||
* */ |
* Method that stop command |
||||
run: function(em, sender) {}, |
* @param {Object} em Editor model |
||||
|
* @param {Object} sender Button sender |
||||
/** |
* @private |
||||
* Method that stop command |
* */ |
||||
* @param {Object} em Editor model |
stop(em, sender) {}, |
||||
* @param {Object} sender Button sender |
|
||||
* @private |
}); |
||||
* */ |
|
||||
stop: function(em, sender) {}, |
|
||||
|
|
||||
}); |
|
||||
}); |
|
||||
|
|||||
@ -1,231 +1,230 @@ |
|||||
define(['backbone','./SelectPosition'], |
var Backbone = require('backbone'); |
||||
function(Backbone, SelectPosition) { |
var SelectPosition = require('./SelectPosition'); |
||||
|
|
||||
return _.extend({}, SelectPosition, { |
module.exports = _.extend({}, SelectPosition, { |
||||
|
|
||||
init: function(opt) { |
init(opt) { |
||||
_.bindAll(this,'startDraw','draw','endDraw','rollback'); |
_.bindAll(this,'startDraw','draw','endDraw','rollback'); |
||||
this.config = opt || {}; |
this.config = opt || {}; |
||||
this.hType = this.config.newFixedH ? 'height' : 'min-height'; |
this.hType = this.config.newFixedH ? 'height' : 'min-height'; |
||||
this.allowDraw = 1; |
this.allowDraw = 1; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Start with enabling to select position and listening to start drawning |
* Start with enabling to select position and listening to start drawning |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
enable: function() { |
enable(...args) { |
||||
SelectPosition.enable.apply(this, arguments); |
SelectPosition.enable.apply(this, args); |
||||
this.$wr.css('cursor','crosshair'); |
this.$wr.css('cursor','crosshair'); |
||||
if(this.allowDraw) |
if(this.allowDraw) |
||||
this.$wr.on('mousedown', this.startDraw); |
this.$wr.on('mousedown', this.startDraw); |
||||
this.ghost = this.canvas.getGhostEl(); |
this.ghost = this.canvas.getGhostEl(); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Start drawing component |
* Start drawing component |
||||
* @param {Object} e Event |
* @param {Object} e Event |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
startDraw : function(e) { |
startDraw(e) { |
||||
e.preventDefault(); |
e.preventDefault(); |
||||
this.stopSelectPosition(); |
this.stopSelectPosition(); |
||||
this.ghost.style.display = 'block'; |
this.ghost.style.display = 'block'; |
||||
this.frameOff = this.getOffsetDim(); |
this.frameOff = this.getOffsetDim(); |
||||
this.startPos = { |
this.startPos = { |
||||
top : e.pageY + this.frameOff.top, |
top : e.pageY + this.frameOff.top, |
||||
left: e.pageX + this.frameOff.left |
left: e.pageX + this.frameOff.left |
||||
}; |
}; |
||||
this.isDragged = false; |
this.isDragged = false; |
||||
this.tempComponent = {style: {}}; |
this.tempComponent = {style: {}}; |
||||
this.beforeDraw(this.tempComponent); |
this.beforeDraw(this.tempComponent); |
||||
this.updateSize(this.startPos.top, this.startPos.left, 0, 0); |
this.updateSize(this.startPos.top, this.startPos.left, 0, 0); |
||||
this.toggleEvents(1); |
this.toggleEvents(1); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Enable/Disable events |
* Enable/Disable events |
||||
* @param {Boolean} enable |
* @param {Boolean} enable |
||||
*/ |
*/ |
||||
toggleEvents: function(enable) { |
toggleEvents(enable) { |
||||
var method = enable ? 'on' : 'off'; |
var method = enable ? 'on' : 'off'; |
||||
this.$wr[method]('mousemove', this.draw); |
this.$wr[method]('mousemove', this.draw); |
||||
this.$wr[method]('mouseup', this.endDraw); |
this.$wr[method]('mouseup', this.endDraw); |
||||
this.$canvas[method]('mousemove', this.draw); |
this.$canvas[method]('mousemove', this.draw); |
||||
$(document)[method]('mouseup', this.endDraw); |
$(document)[method]('mouseup', this.endDraw); |
||||
$(document)[method]('keypress', this.rollback); |
$(document)[method]('keypress', this.rollback); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* While drawing the component |
* While drawing the component |
||||
* @param {Object} e Event |
* @param {Object} e Event |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
draw: function(e) { |
draw(e) { |
||||
this.isDragged = true; |
this.isDragged = true; |
||||
this.updateComponentSize(e); |
this.updateComponentSize(e); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* End drawing component |
* End drawing component |
||||
* @param {Object} e Event |
* @param {Object} e Event |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
endDraw : function(e) { |
endDraw(e) { |
||||
this.toggleEvents(); |
this.toggleEvents(); |
||||
var model = {}; |
var model = {}; |
||||
// Only if the mouse was moved
|
// Only if the mouse was moved
|
||||
if(this.isDragged){ |
if(this.isDragged){ |
||||
this.updateComponentSize(e); |
this.updateComponentSize(e); |
||||
this.setRequirements(this.tempComponent); |
this.setRequirements(this.tempComponent); |
||||
var lp = this.sorter.lastPos; |
var lp = this.sorter.lastPos; |
||||
model = this.create(this.sorter.target, this.tempComponent, lp.index, lp.method); |
model = this.create(this.sorter.target, this.tempComponent, lp.index, lp.method); |
||||
this.sorter.prevTarget = null; |
this.sorter.prevTarget = null; |
||||
} |
} |
||||
this.ghost.style.display = 'none'; |
this.ghost.style.display = 'none'; |
||||
this.startSelectPosition(); |
this.startSelectPosition(); |
||||
this.afterDraw(model); |
this.afterDraw(model); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Create new component inside the target |
* Create new component inside the target |
||||
* @param {Object} target Tha target collection |
* @param {Object} target Tha target collection |
||||
* @param {Object} component New component to create |
* @param {Object} component New component to create |
||||
* @param {number} index Index inside the collection, 0 if no children inside |
* @param {number} index Index inside the collection, 0 if no children inside |
||||
* @param {string} method Before or after of the children |
* @param {string} method Before or after of the children |
||||
* @param {Object} opts Options |
* @param {Object} opts Options |
||||
*/ |
*/ |
||||
create: function(target, component, index, method, opts) { |
create(target, component, index, method, opts) { |
||||
index = method === 'after' ? index + 1 : index; |
index = method === 'after' ? index + 1 : index; |
||||
var opt = opts || {}; |
var opt = opts || {}; |
||||
var $trg = $(target); |
var $trg = $(target); |
||||
var trgModel = $trg.data('model'); |
var trgModel = $trg.data('model'); |
||||
var trgCollection = $trg.data('collection'); |
var trgCollection = $trg.data('collection'); |
||||
var droppable = trgModel ? trgModel.get('droppable') : 1; |
var droppable = trgModel ? trgModel.get('droppable') : 1; |
||||
opt.at = index; |
opt.at = index; |
||||
if(trgCollection && droppable) |
if(trgCollection && droppable) |
||||
return trgCollection.add(component, opt); |
return trgCollection.add(component, opt); |
||||
else |
else |
||||
console.warn("Invalid target position"); |
console.warn("Invalid target position"); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Check and set basic requirements for the component |
* Check and set basic requirements for the component |
||||
* @param {Object} component New component to be created |
* @param {Object} component New component to be created |
||||
* @return {Object} Component updated |
* @return {Object} Component updated |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
setRequirements: function(component) { |
setRequirements(component) { |
||||
var c = this.config; |
var c = this.config; |
||||
var compStl = component.style; |
var compStl = component.style; |
||||
// Check min width
|
// Check min width
|
||||
if(compStl.width.replace(/\D/g,'') < c.minComponentW) |
if(compStl.width.replace(/\D/g,'') < c.minComponentW) |
||||
compStl.width = c.minComponentW +'px'; |
compStl.width = c.minComponentW +'px'; |
||||
// Check min height
|
// Check min height
|
||||
if(compStl[this.hType].replace(/\D/g,'') < c.minComponentH) |
if(compStl[this.hType].replace(/\D/g,'') < c.minComponentH) |
||||
compStl[this.hType] = c.minComponentH +'px'; |
compStl[this.hType] = c.minComponentH +'px'; |
||||
// Set overflow in case of fixed height
|
// Set overflow in case of fixed height
|
||||
if(c.newFixedH) |
if(c.newFixedH) |
||||
compStl.overflow = 'auto'; |
compStl.overflow = 'auto'; |
||||
if(!this.absoluteMode){ |
if(!this.absoluteMode){ |
||||
delete compStl.left; |
delete compStl.left; |
||||
delete compStl.top; |
delete compStl.top; |
||||
}else |
}else |
||||
compStl.position = 'absolute'; |
compStl.position = 'absolute'; |
||||
var lp = this.sorter.lastPos; |
var lp = this.sorter.lastPos; |
||||
|
|
||||
if(this.nearFloat(lp.index, lp.method, this.sorter.lastDims)) |
if(this.nearFloat(lp.index, lp.method, this.sorter.lastDims)) |
||||
compStl.float = 'left'; |
compStl.float = 'left'; |
||||
|
|
||||
if(this.config.firstCentered && |
if(this.config.firstCentered && |
||||
this.getCanvasWrapper() == this.sorter.target){ |
this.getCanvasWrapper() == this.sorter.target){ |
||||
compStl.margin = '0 auto'; |
compStl.margin = '0 auto'; |
||||
} |
} |
||||
|
|
||||
return component; |
return component; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Update new component size while drawing |
* Update new component size while drawing |
||||
* @param {Object} e Event |
* @param {Object} e Event |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
updateComponentSize : function (e) { |
updateComponentSize(e) { |
||||
var y = e.pageY + this.frameOff.top; |
var y = e.pageY + this.frameOff.top; |
||||
var x = e.pageX + this.frameOff.left; |
var x = e.pageX + this.frameOff.left; |
||||
var start = this.startPos; |
var start = this.startPos; |
||||
var top = start.top; |
var top = start.top; |
||||
var left = start.left; |
var left = start.left; |
||||
var height = y - top; |
var height = y - top; |
||||
var width = x - left; |
var width = x - left; |
||||
if (x < left) { |
if (x < left) { |
||||
left = x; |
left = x; |
||||
width = start.left - x; |
width = start.left - x; |
||||
} |
} |
||||
if (y < top) { |
if (y < top) { |
||||
top = y; |
top = y; |
||||
height = start.top - y; |
height = start.top - y; |
||||
} |
} |
||||
this.updateSize(top, left, width, height); |
this.updateSize(top, left, width, height); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Update size |
* Update size |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
updateSize: function(top, left, width, height){ |
updateSize(top, left, width, height) { |
||||
var u = 'px'; |
var u = 'px'; |
||||
var ghStl = this.ghost.style; |
var ghStl = this.ghost.style; |
||||
var compStl = this.tempComponent.style; |
var compStl = this.tempComponent.style; |
||||
ghStl.top = compStl.top = top + u; |
ghStl.top = compStl.top = top + u; |
||||
ghStl.left = compStl.left = left + u; |
ghStl.left = compStl.left = left + u; |
||||
ghStl.width = compStl.width = width + u; |
ghStl.width = compStl.width = width + u; |
||||
ghStl[this.hType] = compStl[this.hType] = height + u; |
ghStl[this.hType] = compStl[this.hType] = height + u; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Used to bring the previous situation before event started |
* Used to bring the previous situation before event started |
||||
* @param {Object} e Event |
* @param {Object} e Event |
||||
* @param {Boolean} forse Indicates if rollback in anycase |
* @param {Boolean} forse Indicates if rollback in anycase |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
rollback: function(e, force) { |
rollback(e, force) { |
||||
var key = e.which || e.keyCode; |
var key = e.which || e.keyCode; |
||||
if(key == this.config.ESCAPE_KEY || force){ |
if(key == this.config.ESCAPE_KEY || force){ |
||||
this.isDragged = false; |
this.isDragged = false; |
||||
this.endDraw(); |
this.endDraw(); |
||||
} |
} |
||||
return; |
return; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* This event is triggered at the beginning of a draw operation |
* This event is triggered at the beginning of a draw operation |
||||
* @param {Object} component Object component before creation |
* @param {Object} component Object component before creation |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
beforeDraw: function(component){ |
beforeDraw(component) { |
||||
component.editable = false;//set this component editable
|
component.editable = false;//set this component editable
|
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* This event is triggered at the end of a draw operation |
* This event is triggered at the end of a draw operation |
||||
* @param {Object} model Component model created |
* @param {Object} model Component model created |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
afterDraw: function(model){}, |
afterDraw(model) {}, |
||||
|
|
||||
|
|
||||
run: function(editor, sender, opts){ |
run(editor, sender, opts) { |
||||
this.editor = editor; |
this.editor = editor; |
||||
this.sender = sender; |
this.sender = sender; |
||||
this.$wr = this.$wrapper; |
this.$wr = this.$wrapper; |
||||
this.enable(); |
this.enable(); |
||||
}, |
}, |
||||
|
|
||||
stop: function(){ |
stop() { |
||||
this.stopSelectPosition(); |
this.stopSelectPosition(); |
||||
this.$wrapper.css('cursor',''); |
this.$wrapper.css('cursor',''); |
||||
this.$wrapper.unbind(); |
this.$wrapper.unbind(); |
||||
} |
} |
||||
}); |
}); |
||||
}); |
|
||||
|
|||||
@ -1,88 +1,79 @@ |
|||||
define(['backbone', './SelectComponent'], |
var Backbone = require('backbone'); |
||||
function(Backbone, SelectComponent) { |
var SelectComponent = require('./SelectComponent'); |
||||
/** |
|
||||
* @class DeleteComponent |
|
||||
* @private |
|
||||
* */ |
|
||||
return _.extend({},SelectComponent,{ |
|
||||
|
|
||||
init: function(o){ |
module.exports = _.extend({},SelectComponent,{ |
||||
_.bindAll(this, 'startDelete', 'stopDelete', 'onDelete'); |
|
||||
this.hoverClass = this.pfx + 'hover-delete'; |
|
||||
this.badgeClass = this.pfx + 'badge-red'; |
|
||||
}, |
|
||||
|
|
||||
enable: function() |
init(o) { |
||||
{ |
_.bindAll(this, 'startDelete', 'stopDelete', 'onDelete'); |
||||
var that = this; |
this.hoverClass = this.pfx + 'hover-delete'; |
||||
this.$el.find('*') |
this.badgeClass = this.pfx + 'badge-red'; |
||||
.mouseover(this.startDelete) |
}, |
||||
.mouseout(this.stopDelete) |
|
||||
.click(this.onDelete); |
|
||||
}, |
|
||||
|
|
||||
/** |
enable() { |
||||
* Start command |
var that = this; |
||||
* @param {Object} e |
this.$el.find('*') |
||||
* @private |
.mouseover(this.startDelete) |
||||
*/ |
.mouseout(this.stopDelete) |
||||
startDelete: function(e) |
.click(this.onDelete); |
||||
{ |
}, |
||||
e.stopPropagation(); |
|
||||
var $this = $(e.target); |
|
||||
|
|
||||
// Show badge if possible
|
/** |
||||
if($this.data('model').get('removable')){ |
* Start command |
||||
$this.addClass(this.hoverClass); |
* @param {Object} e |
||||
this.attachBadge($this.get(0)); |
* @private |
||||
} |
*/ |
||||
|
startDelete(e) { |
||||
|
e.stopPropagation(); |
||||
|
var $this = $(e.target); |
||||
|
|
||||
}, |
// Show badge if possible
|
||||
|
if($this.data('model').get('removable')){ |
||||
|
$this.addClass(this.hoverClass); |
||||
|
this.attachBadge($this.get(0)); |
||||
|
} |
||||
|
|
||||
/** |
}, |
||||
* Stop command |
|
||||
* @param {Object} e |
|
||||
* @private |
|
||||
*/ |
|
||||
stopDelete: function(e) |
|
||||
{ |
|
||||
e.stopPropagation(); |
|
||||
var $this = $(e.target); |
|
||||
$this.removeClass(this.hoverClass); |
|
||||
|
|
||||
// Hide badge if possible
|
/** |
||||
if(this.badge) |
* Stop command |
||||
this.badge.css({ left: -1000, top:-1000 }); |
* @param {Object} e |
||||
}, |
* @private |
||||
|
*/ |
||||
|
stopDelete(e) { |
||||
|
e.stopPropagation(); |
||||
|
var $this = $(e.target); |
||||
|
$this.removeClass(this.hoverClass); |
||||
|
|
||||
/** |
// Hide badge if possible
|
||||
* Delete command |
if(this.badge) |
||||
* @param {Object} e |
this.badge.css({ left: -1000, top:-1000 }); |
||||
* @private |
}, |
||||
*/ |
|
||||
onDelete: function(e) |
|
||||
{ |
|
||||
e.stopPropagation(); |
|
||||
var $this = $(e.target); |
|
||||
|
|
||||
// Do nothing in case can't remove
|
/** |
||||
if(!$this.data('model').get('removable')) |
* Delete command |
||||
return; |
* @param {Object} e |
||||
|
* @private |
||||
|
*/ |
||||
|
onDelete(e) { |
||||
|
e.stopPropagation(); |
||||
|
var $this = $(e.target); |
||||
|
|
||||
$this.data('model').destroy(); |
// Do nothing in case can't remove
|
||||
this.removeBadge(); |
if(!$this.data('model').get('removable')) |
||||
this.clean(); |
return; |
||||
}, |
|
||||
|
|
||||
/** |
$this.data('model').destroy(); |
||||
* Updates badge label |
this.removeBadge(); |
||||
* @param {Object} model |
this.clean(); |
||||
* @private |
}, |
||||
* */ |
|
||||
updateBadgeLabel: function (model) |
|
||||
{ |
|
||||
this.badge.html( 'Remove ' + model.getName() ); |
|
||||
}, |
|
||||
|
|
||||
}); |
/** |
||||
}); |
* Updates badge label |
||||
|
* @param {Object} model |
||||
|
* @private |
||||
|
* */ |
||||
|
updateBadgeLabel(model) { |
||||
|
this.badge.html( 'Remove ' + model.getName() ); |
||||
|
}, |
||||
|
|
||||
|
}); |
||||
|
|||||
@ -1,78 +1,72 @@ |
|||||
define(function() { |
module.exports = { |
||||
/** |
|
||||
* @class ExportTemplate |
|
||||
* @private |
|
||||
* */ |
|
||||
return { |
|
||||
|
|
||||
run: function(editor, sender) { |
run(editor, sender) { |
||||
this.sender = sender; |
this.sender = sender; |
||||
this.wrapper = editor.DomComponents.getWrapper(); |
this.wrapper = editor.DomComponents.getWrapper(); |
||||
this.components = editor.DomComponents.getComponents(); |
this.components = editor.DomComponents.getComponents(); |
||||
this.modal = editor.Modal || null; |
this.modal = editor.Modal || null; |
||||
this.cm = editor.CodeManager || null; |
this.cm = editor.CodeManager || null; |
||||
this.cssc = editor.CssComposer || null; |
this.cssc = editor.CssComposer || null; |
||||
this.protCss = editor.Config.protectedCss; |
this.protCss = editor.Config.protectedCss; |
||||
this.pfx = editor.Config.stylePrefix || ''; |
this.pfx = editor.Config.stylePrefix || ''; |
||||
this.enable(); |
this.enable(); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Build editor |
* Build editor |
||||
* @param {String} codeName |
* @param {String} codeName |
||||
* @param {String} theme |
* @param {String} theme |
||||
* @param {String} label |
* @param {String} label |
||||
* |
* |
||||
* @return {Object} Editor |
* @return {Object} Editor |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
buildEditor: function(codeName, theme, label) { |
buildEditor(codeName, theme, label) { |
||||
if(!this.codeMirror) |
if(!this.codeMirror) |
||||
this.codeMirror = this.cm.getViewer('CodeMirror'); |
this.codeMirror = this.cm.getViewer('CodeMirror'); |
||||
|
|
||||
var $input = $('<textarea>'), |
var $input = $('<textarea>'), |
||||
|
|
||||
editor = this.codeMirror.clone().set({ |
editor = this.codeMirror.clone().set({ |
||||
label : label, |
label, |
||||
codeName : codeName, |
codeName, |
||||
theme : theme, |
theme, |
||||
input : $input[0], |
input : $input[0], |
||||
}), |
}), |
||||
|
|
||||
$editor = new this.cm.EditorView({ |
$editor = new this.cm.EditorView({ |
||||
model : editor, |
model : editor, |
||||
config : this.cm.getConfig() |
config : this.cm.getConfig() |
||||
}).render().$el; |
}).render().$el; |
||||
|
|
||||
editor.init( $input[0] ); |
editor.init( $input[0] ); |
||||
|
|
||||
return { el: editor, $el: $editor }; |
return { el: editor, $el: $editor }; |
||||
}, |
}, |
||||
|
|
||||
enable: function() { |
enable() { |
||||
if(!this.$editors){ |
if(!this.$editors){ |
||||
var oHtmlEd = this.buildEditor('htmlmixed', 'hopscotch', 'HTML'), |
var oHtmlEd = this.buildEditor('htmlmixed', 'hopscotch', 'HTML'), |
||||
oCsslEd = this.buildEditor('css', 'hopscotch', 'CSS'); |
oCsslEd = this.buildEditor('css', 'hopscotch', 'CSS'); |
||||
this.htmlEditor = oHtmlEd.el; |
this.htmlEditor = oHtmlEd.el; |
||||
this.cssEditor = oCsslEd.el; |
this.cssEditor = oCsslEd.el; |
||||
this.$editors = $('<div>', {class: this.pfx + 'export-dl'}); |
this.$editors = $('<div>', {class: this.pfx + 'export-dl'}); |
||||
this.$editors.append(oHtmlEd.$el).append(oCsslEd.$el); |
this.$editors.append(oHtmlEd.$el).append(oCsslEd.$el); |
||||
} |
} |
||||
|
|
||||
if(this.modal){ |
if(this.modal){ |
||||
this.modal.setTitle('Export template'); |
this.modal.setTitle('Export template'); |
||||
this.modal.setContent(this.$editors); |
this.modal.setContent(this.$editors); |
||||
this.modal.open(); |
this.modal.open(); |
||||
} |
} |
||||
var addCss = this.protCss || ''; |
var addCss = this.protCss || ''; |
||||
//this.htmlEditor.setContent(this.cm.getCode(this.components, 'html', this.cssc));
|
//this.htmlEditor.setContent(this.cm.getCode(this.components, 'html', this.cssc));
|
||||
this.htmlEditor.setContent(this.em.getHtml()); |
this.htmlEditor.setContent(this.em.getHtml()); |
||||
this.cssEditor.setContent(addCss + this.cm.getCode(this.wrapper, 'css', this.cssc)); |
this.cssEditor.setContent(addCss + this.cm.getCode(this.wrapper, 'css', this.cssc)); |
||||
|
|
||||
if(this.sender) |
if(this.sender) |
||||
this.sender.set('active',false); |
this.sender.set('active',false); |
||||
}, |
}, |
||||
|
|
||||
stop: function(){} |
stop() {} |
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -1,86 +1,83 @@ |
|||||
define(function() { |
module.exports = { |
||||
|
/** |
||||
|
* Check if fullscreen mode is enabled |
||||
|
* @return {Boolean} |
||||
|
*/ |
||||
|
isEnabled() { |
||||
|
var d = document; |
||||
|
if(d.fullscreenElement || d.webkitFullscreenElement || d.mozFullScreenElement) |
||||
|
return 1; |
||||
|
else |
||||
|
return 0; |
||||
|
}, |
||||
|
|
||||
return { |
/** |
||||
/** |
* Enable fullscreen mode and return browser prefix |
||||
* Check if fullscreen mode is enabled |
* @param {HTMLElement} el |
||||
* @return {Boolean} |
* @return {string} |
||||
*/ |
*/ |
||||
isEnabled: function(){ |
enable(el) { |
||||
var d = document; |
var pfx = ''; |
||||
if(d.fullscreenElement || d.webkitFullscreenElement || d.mozFullScreenElement) |
if (el.requestFullscreen) |
||||
return 1; |
el.requestFullscreen(); |
||||
else |
else if (el.webkitRequestFullscreen) { |
||||
return 0; |
pfx = 'webkit'; |
||||
}, |
el.webkitRequestFullscreen(); |
||||
|
}else if (el.mozRequestFullScreen) { |
||||
|
pfx = 'moz'; |
||||
|
el.mozRequestFullScreen(); |
||||
|
}else if (el.msRequestFullscreen) |
||||
|
el.msRequestFullscreen(); |
||||
|
else |
||||
|
console.warn('Fullscreen not supported'); |
||||
|
return pfx; |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Enable fullscreen mode and return browser prefix |
* Disable fullscreen mode |
||||
* @param {HTMLElement} el |
*/ |
||||
* @return {string} |
disable() { |
||||
*/ |
var d = document; |
||||
enable: function(el){ |
if (d.exitFullscreen) |
||||
var pfx = ''; |
d.exitFullscreen(); |
||||
if (el.requestFullscreen) |
else if (d.webkitExitFullscreen) |
||||
el.requestFullscreen(); |
d.webkitExitFullscreen(); |
||||
else if (el.webkitRequestFullscreen) { |
else if (d.mozCancelFullScreen) |
||||
pfx = 'webkit'; |
d.mozCancelFullScreen(); |
||||
el.webkitRequestFullscreen(); |
else if (d.msExitFullscreen) |
||||
}else if (el.mozRequestFullScreen) { |
d.msExitFullscreen(); |
||||
pfx = 'moz'; |
}, |
||||
el.mozRequestFullScreen(); |
|
||||
}else if (el.msRequestFullscreen) |
|
||||
el.msRequestFullscreen(); |
|
||||
else |
|
||||
console.warn('Fullscreen not supported'); |
|
||||
return pfx; |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Disable fullscreen mode |
* Triggered when the state of the fullscreen is changed. Inside detects if |
||||
*/ |
* it's enabled |
||||
disable: function(){ |
* @param {strinf} pfx Browser prefix |
||||
var d = document; |
* @param {Event} e |
||||
if (d.exitFullscreen) |
*/ |
||||
d.exitFullscreen(); |
fsChanged(pfx, e) { |
||||
else if (d.webkitExitFullscreen) |
var d = document; |
||||
d.webkitExitFullscreen(); |
var ev = (pfx || '') + 'fullscreenchange'; |
||||
else if (d.mozCancelFullScreen) |
if(!this.isEnabled()){ |
||||
d.mozCancelFullScreen(); |
this.stop(null, this.sender); |
||||
else if (d.msExitFullscreen) |
document.removeEventListener(ev, this.fsChanged); |
||||
d.msExitFullscreen(); |
} |
||||
}, |
}, |
||||
|
|
||||
/** |
run(editor, sender) { |
||||
* Triggered when the state of the fullscreen is changed. Inside detects if |
this.sender = sender; |
||||
* it's enabled |
var pfx = this.enable(editor.getContainer()); |
||||
* @param {strinf} pfx Browser prefix |
this.fsChanged = this.fsChanged.bind(this, pfx); |
||||
* @param {Event} e |
document.addEventListener(pfx + 'fullscreenchange', this.fsChanged); |
||||
*/ |
if(editor) |
||||
fsChanged: function(pfx, e){ |
editor.trigger('change:canvasOffset'); |
||||
var d = document; |
}, |
||||
var ev = (pfx || '') + 'fullscreenchange'; |
|
||||
if(!this.isEnabled()){ |
|
||||
this.stop(null, this.sender); |
|
||||
document.removeEventListener(ev, this.fsChanged); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
run: function(editor, sender){ |
stop(editor, sender) { |
||||
this.sender = sender; |
if(sender && sender.set) |
||||
var pfx = this.enable(editor.getContainer()); |
sender.set('active', false); |
||||
this.fsChanged = this.fsChanged.bind(this, pfx); |
this.disable(); |
||||
document.addEventListener(pfx + 'fullscreenchange', this.fsChanged); |
if(editor) |
||||
if(editor) |
editor.trigger('change:canvasOffset'); |
||||
editor.trigger('change:canvasOffset'); |
} |
||||
}, |
|
||||
|
|
||||
stop: function(editor, sender){ |
}; |
||||
if(sender && sender.set) |
|
||||
sender.set('active', false); |
|
||||
this.disable(); |
|
||||
if(editor) |
|
||||
editor.trigger('change:canvasOffset'); |
|
||||
} |
|
||||
|
|
||||
}; |
|
||||
}); |
|
||||
|
|||||
@ -1,39 +1,35 @@ |
|||||
define(['backbone', './InsertCustom'], |
var Backbone = require('backbone'); |
||||
function(Backbone, InsertCustom) { |
var InsertCustom = require('./InsertCustom'); |
||||
/** |
|
||||
* @class ImageComponent |
|
||||
* @private |
|
||||
* */ |
|
||||
return _.extend({}, InsertCustom, { |
|
||||
|
|
||||
/** |
module.exports = _.extend({}, InsertCustom, { |
||||
* Trigger before insert |
|
||||
* @param {Object} object |
|
||||
* @private |
|
||||
* |
|
||||
* */ |
|
||||
beforeInsert: function(object){ |
|
||||
object.type = 'image'; |
|
||||
object.style = {}; |
|
||||
object.attributes = {}; |
|
||||
object.attributes.onmousedown = 'return false'; |
|
||||
if (this.config.firstCentered && |
|
||||
this.getCanvasWrapper() == this.sorter.target ) { |
|
||||
object.style.margin = '0 auto'; |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Trigger after insert |
* Trigger before insert |
||||
* @param {Object} model Model created after insert |
* @param {Object} object |
||||
* @private |
* @private |
||||
* */ |
* |
||||
afterInsert: function(model){ |
* */ |
||||
model.trigger('dblclick'); |
beforeInsert(object) { |
||||
if(this.sender) |
object.type = 'image'; |
||||
this.sender.set('active', false); |
object.style = {}; |
||||
}, |
object.attributes = {}; |
||||
|
object.attributes.onmousedown = 'return false'; |
||||
|
if (this.config.firstCentered && |
||||
|
this.getCanvasWrapper() == this.sorter.target ) { |
||||
|
object.style.margin = '0 auto'; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Trigger after insert |
||||
|
* @param {Object} model Model created after insert |
||||
|
* @private |
||||
|
* */ |
||||
|
afterInsert(model) { |
||||
|
model.trigger('dblclick'); |
||||
|
if(this.sender) |
||||
|
this.sender.set('active', false); |
||||
|
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,83 +1,79 @@ |
|||||
define(['backbone', './CreateComponent'], |
var Backbone = require('backbone'); |
||||
function(Backbone, CreateComponent) { |
var CreateComponent = require('./CreateComponent'); |
||||
/** |
|
||||
* @class InsertCustom |
|
||||
* @private |
|
||||
* */ |
|
||||
return _.extend({}, CreateComponent, { |
|
||||
|
|
||||
init: function(){ |
module.exports = _.extend({}, CreateComponent, { |
||||
CreateComponent.init.apply(this, arguments); |
|
||||
_.bindAll(this, 'insertComponent'); |
|
||||
this.allowDraw = 0; |
|
||||
}, |
|
||||
|
|
||||
/** |
init(...args) { |
||||
* Run method |
CreateComponent.init.apply(this, args); |
||||
* @private |
_.bindAll(this, 'insertComponent'); |
||||
* */ |
this.allowDraw = 0; |
||||
run: function(em, sender, options) { |
}, |
||||
this.em = em; |
|
||||
this.sender = sender; |
|
||||
this.opt = options || {}; |
|
||||
this.$wr = this.$wrapper; |
|
||||
this.enable(); |
|
||||
}, |
|
||||
|
|
||||
enable: function(){ |
/** |
||||
CreateComponent.enable.apply(this, arguments); |
* Run method |
||||
this.$wr.on('click', this.insertComponent); |
* @private |
||||
}, |
* */ |
||||
|
run(em, sender, options) { |
||||
|
this.em = em; |
||||
|
this.sender = sender; |
||||
|
this.opt = options || {}; |
||||
|
this.$wr = this.$wrapper; |
||||
|
this.enable(); |
||||
|
}, |
||||
|
|
||||
/** |
enable(...args) { |
||||
* Start insert event |
CreateComponent.enable.apply(this, args); |
||||
* @private |
this.$wr.on('click', this.insertComponent); |
||||
* */ |
}, |
||||
insertComponent: function(){ |
|
||||
this.$wr.off('click', this.insertComponent); |
|
||||
this.stopSelectPosition(); |
|
||||
var object = this.buildContent(); |
|
||||
this.beforeInsert(object); |
|
||||
var index = this.sorter.lastPos.index; |
|
||||
// By default, collections do not trigger add event, so silent is used
|
|
||||
var model = this.create(this.sorter.target, object, index, null, {silent: false}); |
|
||||
|
|
||||
if(this.opt.terminateAfterInsert && this.sender) |
/** |
||||
this.sender.set('active', false); |
* Start insert event |
||||
else |
* @private |
||||
this.enable(); |
* */ |
||||
|
insertComponent() { |
||||
|
this.$wr.off('click', this.insertComponent); |
||||
|
this.stopSelectPosition(); |
||||
|
var object = this.buildContent(); |
||||
|
this.beforeInsert(object); |
||||
|
var index = this.sorter.lastPos.index; |
||||
|
// By default, collections do not trigger add event, so silent is used
|
||||
|
var model = this.create(this.sorter.target, object, index, null, {silent: false}); |
||||
|
|
||||
if(!model) |
if(this.opt.terminateAfterInsert && this.sender) |
||||
return; |
this.sender.set('active', false); |
||||
|
else |
||||
|
this.enable(); |
||||
|
|
||||
if(this.em) |
if(!model) |
||||
this.em.editor.initChildrenComp(model); |
return; |
||||
|
|
||||
this.afterInsert(model, this); |
if(this.em) |
||||
}, |
this.em.editor.initChildrenComp(model); |
||||
|
|
||||
/** |
this.afterInsert(model, this); |
||||
* Trigger before insert |
}, |
||||
* @param {Object} obj |
|
||||
* @private |
|
||||
* */ |
|
||||
beforeInsert: function(obj){}, |
|
||||
|
|
||||
/** |
/** |
||||
* Trigger after insert |
* Trigger before insert |
||||
* @param {Object} model Model created after insert |
* @param {Object} obj |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
afterInsert: function(model){}, |
beforeInsert(obj) {}, |
||||
|
|
||||
/** |
/** |
||||
* Create different object, based on content, to insert inside canvas |
* Trigger after insert |
||||
* |
* @param {Object} model Model created after insert |
||||
* @return {Object} |
* @private |
||||
* @private |
* */ |
||||
* */ |
afterInsert(model) {}, |
||||
buildContent: function(){ |
|
||||
return this.opt.content || {}; |
/** |
||||
}, |
* Create different object, based on content, to insert inside canvas |
||||
}); |
* |
||||
}); |
* @return {Object} |
||||
|
* @private |
||||
|
* */ |
||||
|
buildContent() { |
||||
|
return this.opt.content || {}; |
||||
|
}, |
||||
|
}); |
||||
|
|||||
@ -1,148 +1,148 @@ |
|||||
define(['backbone', './SelectComponent','./SelectPosition'], |
var Backbone = require('backbone'); |
||||
function(Backbone, SelectComponent, SelectPosition) { |
var SelectComponent = require('./SelectComponent'); |
||||
|
var SelectPosition = require('./SelectPosition'); |
||||
return _.extend({}, SelectPosition, SelectComponent, { |
|
||||
|
module.exports = _.extend({}, SelectPosition, SelectComponent, { |
||||
init: function(o){ |
|
||||
SelectComponent.init.apply(this, arguments); |
init(o) { |
||||
_.bindAll(this, 'initSorter','rollback', 'onEndMove'); |
SelectComponent.init.apply(this, arguments); |
||||
this.opt = o; |
_.bindAll(this, 'initSorter','rollback', 'onEndMove'); |
||||
this.hoverClass = this.ppfx + 'highlighter-warning'; |
this.opt = o; |
||||
this.badgeClass = this.ppfx + 'badge-warning'; |
this.hoverClass = this.ppfx + 'highlighter-warning'; |
||||
this.noSelClass = this.ppfx + 'no-select'; |
this.badgeClass = this.ppfx + 'badge-warning'; |
||||
}, |
this.noSelClass = this.ppfx + 'no-select'; |
||||
|
}, |
||||
enable: function() { |
|
||||
SelectComponent.enable.apply(this, arguments); |
enable(...args) { |
||||
this.getBadgeEl().addClass(this.badgeClass); |
SelectComponent.enable.apply(this, args); |
||||
this.getHighlighterEl().addClass(this.hoverClass); |
this.getBadgeEl().addClass(this.badgeClass); |
||||
var wp = this.$wrapper; |
this.getHighlighterEl().addClass(this.hoverClass); |
||||
wp.css('cursor','move'); |
var wp = this.$wrapper; |
||||
wp.on('mousedown', this.initSorter); |
wp.css('cursor','move'); |
||||
|
wp.on('mousedown', this.initSorter); |
||||
// Avoid strange moving behavior
|
|
||||
wp.addClass(this.noSelClass); |
// Avoid strange moving behavior
|
||||
}, |
wp.addClass(this.noSelClass); |
||||
|
}, |
||||
/** |
|
||||
* Overwrite for doing nothing |
/** |
||||
* @private |
* Overwrite for doing nothing |
||||
*/ |
* @private |
||||
toggleClipboard: function(){}, |
*/ |
||||
|
toggleClipboard() {}, |
||||
/** |
|
||||
* Delegate sorting |
/** |
||||
* @param {Event} e |
* Delegate sorting |
||||
* @private |
* @param {Event} e |
||||
* */ |
* @private |
||||
initSorter: function(e){ |
* */ |
||||
var el = $(e.target).data('model'); |
initSorter(e) { |
||||
var drag = el.get('draggable'); |
var el = $(e.target).data('model'); |
||||
if(!drag) |
var drag = el.get('draggable'); |
||||
return; |
if(!drag) |
||||
|
return; |
||||
// Avoid badge showing on move
|
|
||||
this.cacheEl = null; |
// Avoid badge showing on move
|
||||
this.startSelectPosition(e.target, this.frameEl.contentDocument); |
this.cacheEl = null; |
||||
this.sorter.draggable = drag; |
this.startSelectPosition(e.target, this.frameEl.contentDocument); |
||||
this.sorter.onEndMove = this.onEndMove.bind(this); |
this.sorter.draggable = drag; |
||||
this.stopSelectComponent(); |
this.sorter.onEndMove = this.onEndMove.bind(this); |
||||
this.$wrapper.off('mousedown', this.initSorter); |
this.stopSelectComponent(); |
||||
this.getContentWindow().on('keydown', this.rollback); |
this.$wrapper.off('mousedown', this.initSorter); |
||||
}, |
this.getContentWindow().on('keydown', this.rollback); |
||||
|
}, |
||||
/** |
|
||||
* Init sorter from model |
/** |
||||
* @param {Object} model |
* Init sorter from model |
||||
* @private |
* @param {Object} model |
||||
*/ |
* @private |
||||
initSorterFromModel: function(model) { |
*/ |
||||
var drag = model.get('draggable'); |
initSorterFromModel(model) { |
||||
if(!drag) |
var drag = model.get('draggable'); |
||||
return; |
if(!drag) |
||||
// Avoid badge showing on move
|
return; |
||||
this.cacheEl = null; |
// Avoid badge showing on move
|
||||
var el = model.view.el; |
this.cacheEl = null; |
||||
this.startSelectPosition(el, this.frameEl.contentDocument); |
var el = model.view.el; |
||||
this.sorter.draggable = drag; |
this.startSelectPosition(el, this.frameEl.contentDocument); |
||||
this.sorter.onEndMove = this.onEndMoveFromModel.bind(this); |
this.sorter.draggable = drag; |
||||
|
this.sorter.onEndMove = this.onEndMoveFromModel.bind(this); |
||||
/* |
|
||||
this.sorter.setDragHelper(el); |
/* |
||||
var dragHelper = this.sorter.dragHelper; |
this.sorter.setDragHelper(el); |
||||
dragHelper.className = this.ppfx + 'drag-helper'; |
var dragHelper = this.sorter.dragHelper; |
||||
dragHelper.innerHTML = ''; |
dragHelper.className = this.ppfx + 'drag-helper'; |
||||
dragHelper.backgroundColor = 'white'; |
dragHelper.innerHTML = ''; |
||||
*/ |
dragHelper.backgroundColor = 'white'; |
||||
|
*/ |
||||
this.stopSelectComponent(); |
|
||||
this.getContentWindow().on('keydown', this.rollback); |
this.stopSelectComponent(); |
||||
}, |
this.getContentWindow().on('keydown', this.rollback); |
||||
|
}, |
||||
onEndMoveFromModel: function() { |
|
||||
this.getContentWindow().off('keydown', this.rollback); |
onEndMoveFromModel() { |
||||
}, |
this.getContentWindow().off('keydown', this.rollback); |
||||
|
}, |
||||
/** |
|
||||
* Callback after sorting |
/** |
||||
* @private |
* Callback after sorting |
||||
*/ |
* @private |
||||
onEndMove: function(){ |
*/ |
||||
this.enable(); |
onEndMove() { |
||||
this.getContentWindow().off('keydown', this.rollback); |
this.enable(); |
||||
}, |
this.getContentWindow().off('keydown', this.rollback); |
||||
|
}, |
||||
/** |
|
||||
* Say what to do after the component was selected (selectComponent) |
/** |
||||
* @param {Event} e |
* Say what to do after the component was selected (selectComponent) |
||||
* @param {Object} Selected element |
* @param {Event} e |
||||
* @private |
* @param {Object} Selected element |
||||
* */ |
* @private |
||||
onSelect: function(e,el){}, |
* */ |
||||
|
onSelect(e, el) {}, |
||||
/** |
|
||||
* Used to bring the previous situation before start moving the component |
/** |
||||
* @param {Event} e |
* Used to bring the previous situation before start moving the component |
||||
* @param {Boolean} Indicates if rollback in anycase |
* @param {Event} e |
||||
* @private |
* @param {Boolean} Indicates if rollback in anycase |
||||
* */ |
* @private |
||||
rollback: function(e, force){ |
* */ |
||||
var key = e.which || e.keyCode; |
rollback(e, force) { |
||||
if(key == this.opt.ESCAPE_KEY || force){ |
var key = e.which || e.keyCode; |
||||
this.sorter.moved = false; |
if(key == this.opt.ESCAPE_KEY || force){ |
||||
this.sorter.endMove(); |
this.sorter.moved = false; |
||||
} |
this.sorter.endMove(); |
||||
return; |
} |
||||
}, |
return; |
||||
|
}, |
||||
/** |
|
||||
* Returns badge element |
/** |
||||
* @return {HTMLElement} |
* Returns badge element |
||||
* @private |
* @return {HTMLElement} |
||||
*/ |
* @private |
||||
getBadgeEl: function(){ |
*/ |
||||
if(!this.$badge) |
getBadgeEl() { |
||||
this.$badge = $(this.getBadge()); |
if(!this.$badge) |
||||
return this.$badge; |
this.$badge = $(this.getBadge()); |
||||
}, |
return this.$badge; |
||||
|
}, |
||||
/** |
|
||||
* Returns highlighter element |
/** |
||||
* @return {HTMLElement} |
* Returns highlighter element |
||||
* @private |
* @return {HTMLElement} |
||||
*/ |
* @private |
||||
getHighlighterEl: function(){ |
*/ |
||||
if(!this.$hl) |
getHighlighterEl() { |
||||
this.$hl = $(this.canvas.getHighlighter()); |
if(!this.$hl) |
||||
return this.$hl; |
this.$hl = $(this.canvas.getHighlighter()); |
||||
}, |
return this.$hl; |
||||
|
}, |
||||
stop: function(){ |
|
||||
SelectComponent.stop.apply(this, arguments); |
stop(...args) { |
||||
this.getBadgeEl().removeClass(this.badgeClass); |
SelectComponent.stop.apply(this, args); |
||||
this.getHighlighterEl().removeClass(this.hoverClass); |
this.getBadgeEl().removeClass(this.badgeClass); |
||||
var wp = this.$wrapper; |
this.getHighlighterEl().removeClass(this.hoverClass); |
||||
wp.css('cursor', '').unbind().removeClass(this.noSelClass); |
var wp = this.$wrapper; |
||||
} |
wp.css('cursor', '').unbind().removeClass(this.noSelClass); |
||||
}); |
} |
||||
}); |
}); |
||||
|
|||||
@ -1,24 +1,21 @@ |
|||||
define(function() { |
module.exports = { |
||||
|
|
||||
return { |
run(editor, sender, opts) { |
||||
|
var opt = opts || {}; |
||||
|
var config = editor.getConfig(); |
||||
|
var modal = editor.Modal; |
||||
|
var assetManager = editor.AssetManager; |
||||
|
|
||||
run: function(editor, sender, opts) { |
assetManager.onClick(opt.onClick); |
||||
var opt = opts || {}; |
assetManager.onDblClick(opt.onDblClick); |
||||
var config = editor.getConfig(); |
|
||||
var modal = editor.Modal; |
|
||||
var assetManager = editor.AssetManager; |
|
||||
|
|
||||
assetManager.onClick(opt.onClick); |
// old API
|
||||
assetManager.onDblClick(opt.onDblClick); |
assetManager.setTarget(opt.target); |
||||
|
assetManager.onSelect(opt.onSelect); |
||||
|
|
||||
// old API
|
modal.setTitle(opt.modalTitle || 'Select image'); |
||||
assetManager.setTarget(opt.target); |
modal.setContent(assetManager.render()); |
||||
assetManager.onSelect(opt.onSelect); |
modal.open(); |
||||
|
}, |
||||
|
|
||||
modal.setTitle(opt.modalTitle || 'Select image'); |
}; |
||||
modal.setContent(assetManager.render()); |
|
||||
modal.open(); |
|
||||
}, |
|
||||
|
|
||||
}; |
|
||||
}); |
|
||||
|
|||||
@ -1,28 +1,26 @@ |
|||||
define(function() { |
module.exports = { |
||||
|
|
||||
return { |
run(editor, sender) { |
||||
|
var config = editor.Config; |
||||
|
var pfx = config.stylePrefix; |
||||
|
var bm = editor.BlockManager; |
||||
|
var panelC; |
||||
|
if(!this.blocks){ |
||||
|
this.blocks = $('<div/>').get(0); |
||||
|
this.blocks.appendChild(bm.render()); |
||||
|
var panels = editor.Panels; |
||||
|
if(!panels.getPanel('views-container')) |
||||
|
panelC = panels.addPanel({id: 'views-container'}); |
||||
|
else |
||||
|
panelC = panels.getPanel('views-container'); |
||||
|
panelC.set('appendContent', this.blocks).trigger('change:appendContent'); |
||||
|
} |
||||
|
|
||||
run: function(editor, sender) { |
this.blocks.style.display = 'block'; |
||||
var config = editor.Config; |
}, |
||||
var pfx = config.stylePrefix; |
|
||||
var bm = editor.BlockManager; |
|
||||
if(!this.blocks){ |
|
||||
this.blocks = $('<div/>').get(0); |
|
||||
this.blocks.appendChild(bm.render()); |
|
||||
var panels = editor.Panels; |
|
||||
if(!panels.getPanel('views-container')) |
|
||||
panelC = panels.addPanel({id: 'views-container'}); |
|
||||
else |
|
||||
panelC = panels.getPanel('views-container'); |
|
||||
panelC.set('appendContent', this.blocks).trigger('change:appendContent'); |
|
||||
} |
|
||||
|
|
||||
this.blocks.style.display = 'block'; |
stop() { |
||||
}, |
if(this.blocks) |
||||
|
this.blocks.style.display = 'none'; |
||||
stop: function() { |
} |
||||
if(this.blocks) |
}; |
||||
this.blocks.style.display = 'none'; |
|
||||
} |
|
||||
}; |
|
||||
}); |
|
||||
|
|||||
@ -1,38 +1,34 @@ |
|||||
define(['Navigator'], function(Layers) { |
var Layers = require('navigator'); |
||||
/** |
|
||||
* @class OpenStyleManager |
|
||||
* @private |
|
||||
* */ |
|
||||
return { |
|
||||
|
|
||||
run: function(em, sender) { |
module.exports = { |
||||
if(!this.$layers) { |
|
||||
var collection = em.DomComponents.getComponent().get('components'), |
|
||||
config = em.getConfig(), |
|
||||
panels = em.Panels, |
|
||||
lyStylePfx = config.layers.stylePrefix || 'nv-'; |
|
||||
|
|
||||
config.layers.stylePrefix = config.stylePrefix + lyStylePfx; |
run(em, sender) { |
||||
config.layers.pStylePrefix = config.stylePrefix; |
if(!this.$layers) { |
||||
config.layers.em = em.editor; |
var collection = em.DomComponents.getComponent().get('components'), |
||||
config.layers.opened = em.editor.get('opened'); |
config = em.getConfig(), |
||||
var layers = new Layers(collection, config.layers); |
panels = em.Panels, |
||||
this.$layers = layers.render(); |
lyStylePfx = config.layers.stylePrefix || 'nv-'; |
||||
|
|
||||
// Check if panel exists otherwise crate it
|
config.layers.stylePrefix = config.stylePrefix + lyStylePfx; |
||||
if(!panels.getPanel('views-container')) |
config.layers.pStylePrefix = config.stylePrefix; |
||||
this.panel = panels.addPanel({id: 'views-container'}); |
config.layers.em = em.editor; |
||||
else |
config.layers.opened = em.editor.get('opened'); |
||||
this.panel = panels.getPanel('views-container'); |
var layers = new Layers(collection, config.layers); |
||||
|
this.$layers = layers.render(); |
||||
|
|
||||
this.panel.set('appendContent', this.$layers).trigger('change:appendContent'); |
// Check if panel exists otherwise crate it
|
||||
} |
if(!panels.getPanel('views-container')) |
||||
this.$layers.show(); |
this.panel = panels.addPanel({id: 'views-container'}); |
||||
}, |
else |
||||
|
this.panel = panels.getPanel('views-container'); |
||||
|
|
||||
stop: function() { |
this.panel.set('appendContent', this.$layers).trigger('change:appendContent'); |
||||
if(this.$layers) |
|
||||
this.$layers.hide(); |
|
||||
} |
} |
||||
}; |
this.$layers.show(); |
||||
}); |
}, |
||||
|
|
||||
|
stop() { |
||||
|
if(this.$layers) |
||||
|
this.$layers.hide(); |
||||
|
} |
||||
|
}; |
||||
|
|||||
@ -1,82 +1,78 @@ |
|||||
define(['StyleManager'], function(StyleManager) { |
var StyleManager = require('style_manager'); |
||||
/** |
|
||||
* @class OpenStyleManager |
|
||||
* @private |
|
||||
* */ |
|
||||
return { |
|
||||
|
|
||||
run: function(em, sender) { |
module.exports = { |
||||
this.sender = sender; |
|
||||
if(!this.$cn){ |
|
||||
var config = em.getConfig(), |
|
||||
panels = em.Panels; |
|
||||
// Main container
|
|
||||
this.$cn = $('<div/>'); |
|
||||
// Secondary container
|
|
||||
this.$cn2 = $('<div/>'); |
|
||||
this.$cn.append(this.$cn2); |
|
||||
|
|
||||
// Device Manager
|
run(em, sender) { |
||||
var dvm = em.DeviceManager; |
this.sender = sender; |
||||
if(dvm && config.showDevices){ |
if(!this.$cn){ |
||||
var devicePanel = panels.addPanel({ id: 'devices-c'}); |
var config = em.getConfig(), |
||||
devicePanel.set('appendContent', dvm.render()).trigger('change:appendContent'); |
panels = em.Panels; |
||||
} |
// Main container
|
||||
|
this.$cn = $('<div/>'); |
||||
|
// Secondary container
|
||||
|
this.$cn2 = $('<div/>'); |
||||
|
this.$cn.append(this.$cn2); |
||||
|
|
||||
// Class Manager container
|
// Device Manager
|
||||
var clm = em.SelectorManager; |
var dvm = em.DeviceManager; |
||||
if(clm) |
if(dvm && config.showDevices){ |
||||
this.$cn2.append(clm.render([])); |
var devicePanel = panels.addPanel({ id: 'devices-c'}); |
||||
|
devicePanel.set('appendContent', dvm.render()).trigger('change:appendContent'); |
||||
|
} |
||||
|
|
||||
this.$cn2.append(em.StyleManager.render()); |
// Class Manager container
|
||||
var smConfig = em.StyleManager.getConfig(); |
var clm = em.SelectorManager; |
||||
// Create header
|
if(clm) |
||||
this.$header = $('<div>', { |
this.$cn2.append(clm.render([])); |
||||
class: smConfig.stylePrefix + 'header', |
|
||||
text: smConfig.textNoElement, |
|
||||
}); |
|
||||
//this.$cn = this.$cn.add(this.$header);
|
|
||||
this.$cn.append(this.$header); |
|
||||
|
|
||||
// Create panel if not exists
|
this.$cn2.append(em.StyleManager.render()); |
||||
if(!panels.getPanel('views-container')) |
var smConfig = em.StyleManager.getConfig(); |
||||
this.panel = panels.addPanel({ id: 'views-container'}); |
// Create header
|
||||
else |
this.$header = $('<div>', { |
||||
this.panel = panels.getPanel('views-container'); |
class: smConfig.stylePrefix + 'header', |
||||
|
text: smConfig.textNoElement, |
||||
|
}); |
||||
|
//this.$cn = this.$cn.add(this.$header);
|
||||
|
this.$cn.append(this.$header); |
||||
|
|
||||
// Add all containers to the panel
|
// Create panel if not exists
|
||||
this.panel.set('appendContent', this.$cn).trigger('change:appendContent'); |
if(!panels.getPanel('views-container')) |
||||
|
this.panel = panels.addPanel({ id: 'views-container'}); |
||||
|
else |
||||
|
this.panel = panels.getPanel('views-container'); |
||||
|
|
||||
this.target = em.editor; |
// Add all containers to the panel
|
||||
this.listenTo( this.target ,'change:selectedComponent', this.toggleSm); |
this.panel.set('appendContent', this.$cn).trigger('change:appendContent'); |
||||
} |
|
||||
this.toggleSm(); |
|
||||
}, |
|
||||
|
|
||||
/** |
this.target = em.editor; |
||||
* Toggle Style Manager visibility |
this.listenTo( this.target ,'change:selectedComponent', this.toggleSm); |
||||
* @private |
} |
||||
*/ |
this.toggleSm(); |
||||
toggleSm: function() { |
}, |
||||
if(!this.sender.get('active')) |
|
||||
return; |
|
||||
if(this.target.get('selectedComponent')){ |
|
||||
this.$cn2.show(); |
|
||||
this.$header.hide(); |
|
||||
}else{ |
|
||||
this.$cn2.hide(); |
|
||||
this.$header.show(); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
stop: function() { |
/** |
||||
// Hide secondary container if exists
|
* Toggle Style Manager visibility |
||||
if(this.$cn2) |
* @private |
||||
this.$cn2.hide(); |
*/ |
||||
|
toggleSm() { |
||||
|
if(!this.sender.get('active')) |
||||
|
return; |
||||
|
if(this.target.get('selectedComponent')){ |
||||
|
this.$cn2.show(); |
||||
|
this.$header.hide(); |
||||
|
}else{ |
||||
|
this.$cn2.hide(); |
||||
|
this.$header.show(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
// Hide header container if exists
|
stop() { |
||||
if(this.$header) |
// Hide secondary container if exists
|
||||
this.$header.hide(); |
if(this.$cn2) |
||||
} |
this.$cn2.hide(); |
||||
}; |
|
||||
}); |
// Hide header container if exists
|
||||
|
if(this.$header) |
||||
|
this.$header.hide(); |
||||
|
} |
||||
|
}; |
||||
|
|||||
@ -1,32 +1,30 @@ |
|||||
define(function() { |
module.exports = { |
||||
|
|
||||
return { |
run(editor, sender) { |
||||
|
var config = editor.Config; |
||||
|
var pfx = config.stylePrefix; |
||||
|
var tm = editor.TraitManager; |
||||
|
var panelC; |
||||
|
if(!this.obj){ |
||||
|
var tmView = tm.getTraitsViewer(); |
||||
|
var confTm = tm.getConfig(); |
||||
|
this.obj = $('<div/>') |
||||
|
.append('<div class="'+pfx+'traits-label">' + confTm.labelContainer + '</div>') |
||||
|
.get(0); |
||||
|
this.obj.appendChild(tmView.render().el); |
||||
|
var panels = editor.Panels; |
||||
|
if(!panels.getPanel('views-container')) |
||||
|
panelC = panels.addPanel({id: 'views-container'}); |
||||
|
else |
||||
|
panelC = panels.getPanel('views-container'); |
||||
|
panelC.set('appendContent', this.obj).trigger('change:appendContent'); |
||||
|
} |
||||
|
|
||||
run: function(editor, sender) { |
this.obj.style.display = 'block'; |
||||
var config = editor.Config; |
}, |
||||
var pfx = config.stylePrefix; |
|
||||
var tm = editor.TraitManager; |
|
||||
if(!this.obj){ |
|
||||
var tmView = tm.getTraitsViewer(); |
|
||||
var confTm = tm.getConfig(); |
|
||||
this.obj = $('<div/>') |
|
||||
.append('<div class="'+pfx+'traits-label">' + confTm.labelContainer + '</div>') |
|
||||
.get(0); |
|
||||
this.obj.appendChild(tmView.render().el); |
|
||||
var panels = editor.Panels; |
|
||||
if(!panels.getPanel('views-container')) |
|
||||
panelC = panels.addPanel({id: 'views-container'}); |
|
||||
else |
|
||||
panelC = panels.getPanel('views-container'); |
|
||||
panelC.set('appendContent', this.obj).trigger('change:appendContent'); |
|
||||
} |
|
||||
|
|
||||
this.obj.style.display = 'block'; |
stop() { |
||||
}, |
if(this.obj) |
||||
|
this.obj.style.display = 'none'; |
||||
stop: function() { |
} |
||||
if(this.obj) |
}; |
||||
this.obj.style.display = 'none'; |
|
||||
} |
|
||||
}; |
|
||||
}); |
|
||||
|
|||||
@ -1,68 +1,65 @@ |
|||||
define(function() { |
module.exports = { |
||||
|
|
||||
return { |
getPanels(editor) { |
||||
|
if(!this.panels) |
||||
|
this.panels = editor.Panels.getPanelsEl(); |
||||
|
return this.panels; |
||||
|
}, |
||||
|
|
||||
getPanels: function(editor){ |
tglPointers(editor, v) { |
||||
if(!this.panels) |
var elP = editor.Canvas.getBody().querySelectorAll('.' + this.ppfx + 'no-pointer'); |
||||
this.panels = editor.Panels.getPanelsEl(); |
_.each(elP, item => { |
||||
return this.panels; |
item.style.pointerEvents = v ? '' : 'all'; |
||||
}, |
}); |
||||
|
}, |
||||
|
|
||||
tglPointers: function(editor, v) { |
run(editor, sender) { |
||||
var elP = editor.Canvas.getBody().querySelectorAll('.' + this.ppfx + 'no-pointer'); |
if(sender && sender.set) |
||||
_.each(elP, function(item){ |
sender.set('active', false); |
||||
item.style.pointerEvents = v ? '' : 'all'; |
editor.stopCommand('sw-visibility'); |
||||
}); |
var that = this; |
||||
}, |
var panels = this.getPanels(editor); |
||||
|
var canvas = editor.Canvas.getElement(); |
||||
|
var editorEl = editor.getEl(); |
||||
|
var pfx = editor.Config.stylePrefix; |
||||
|
if(!this.helper) { |
||||
|
this.helper = document.createElement('span'); |
||||
|
this.helper.className = pfx + 'off-prv fa fa-eye-slash'; |
||||
|
editorEl.appendChild(this.helper); |
||||
|
this.helper.onclick = () => { |
||||
|
that.stop(editor); |
||||
|
}; |
||||
|
} |
||||
|
this.helper.style.display = 'inline-block'; |
||||
|
this.tglPointers(editor); |
||||
|
|
||||
run: function(editor, sender) { |
/* |
||||
if(sender && sender.set) |
editor.Canvas.getBody().querySelectorAll('.' + pfx + 'no-pointer').forEach(function(){ |
||||
sender.set('active', false); |
this.style.pointerEvents = 'all'; |
||||
editor.stopCommand('sw-visibility'); |
});*/ |
||||
var that = this; |
|
||||
var panels = this.getPanels(editor); |
|
||||
var canvas = editor.Canvas.getElement(); |
|
||||
var editorEl = editor.getEl(); |
|
||||
var pfx = editor.Config.stylePrefix; |
|
||||
if(!this.helper) { |
|
||||
this.helper = document.createElement('span'); |
|
||||
this.helper.className = pfx + 'off-prv fa fa-eye-slash'; |
|
||||
editorEl.appendChild(this.helper); |
|
||||
this.helper.onclick = function(){ |
|
||||
that.stop(editor); |
|
||||
}; |
|
||||
} |
|
||||
this.helper.style.display = 'inline-block'; |
|
||||
this.tglPointers(editor); |
|
||||
|
|
||||
/* |
panels.style.display = 'none'; |
||||
editor.Canvas.getBody().querySelectorAll('.' + pfx + 'no-pointer').forEach(function(){ |
var canvasS = canvas.style; |
||||
this.style.pointerEvents = 'all'; |
canvasS.width = '100%'; |
||||
});*/ |
canvasS.height = '100%'; |
||||
|
canvasS.top = '0'; |
||||
|
canvasS.left = '0'; |
||||
|
canvasS.padding = '0'; |
||||
|
canvasS.margin = '0'; |
||||
|
editor.trigger('change:canvasOffset'); |
||||
|
}, |
||||
|
|
||||
panels.style.display = 'none'; |
stop(editor, sender) { |
||||
var canvasS = canvas.style; |
var panels = this.getPanels(editor); |
||||
canvasS.width = '100%'; |
editor.runCommand('sw-visibility'); |
||||
canvasS.height = '100%'; |
editor.getModel().runDefault(); |
||||
canvasS.top = '0'; |
panels.style.display = 'block'; |
||||
canvasS.left = '0'; |
var canvas = editor.Canvas.getElement(); |
||||
canvasS.padding = '0'; |
canvas.setAttribute('style', ''); |
||||
canvasS.margin = '0'; |
if(this.helper) { |
||||
editor.trigger('change:canvasOffset'); |
this.helper.style.display = 'none'; |
||||
}, |
} |
||||
|
editor.trigger('change:canvasOffset'); |
||||
stop: function(editor, sender) { |
this.tglPointers(editor, 1); |
||||
var panels = this.getPanels(editor); |
} |
||||
editor.runCommand('sw-visibility'); |
}; |
||||
editor.getModel().runDefault(); |
|
||||
panels.style.display = 'block'; |
|
||||
var canvas = editor.Canvas.getElement(); |
|
||||
canvas.setAttribute('style', ''); |
|
||||
if(this.helper) { |
|
||||
this.helper.style.display = 'none'; |
|
||||
} |
|
||||
editor.trigger('change:canvasOffset'); |
|
||||
this.tglPointers(editor, 1); |
|
||||
} |
|
||||
}; |
|
||||
}); |
|
||||
|
|||||
@ -1,32 +1,30 @@ |
|||||
define(function() { |
module.exports = { |
||||
return { |
|
||||
|
|
||||
run: function(editor, sender, opts) { |
run(editor, sender, opts) { |
||||
var el = (opts && opts.el) || ''; |
var el = (opts && opts.el) || ''; |
||||
var canvas = editor.Canvas; |
var canvas = editor.Canvas; |
||||
var canvasResizer = this.canvasResizer; |
var canvasResizer = this.canvasResizer; |
||||
var options = opts.options || {}; |
var options = opts.options || {}; |
||||
|
|
||||
// Create the resizer for the canvas if not yet created
|
// Create the resizer for the canvas if not yet created
|
||||
if(!canvasResizer) { |
if(!canvasResizer) { |
||||
var canvasView = canvas.getCanvasView(); |
var canvasView = canvas.getCanvasView(); |
||||
options.ratioDefault = 1; |
options.ratioDefault = 1; |
||||
options.appendTo = canvas.getResizerEl(); |
options.appendTo = canvas.getResizerEl(); |
||||
options.prefix = editor.getConfig().stylePrefix; |
options.prefix = editor.getConfig().stylePrefix; |
||||
options.posFetcher = canvasView.getElementPos.bind(canvasView); |
options.posFetcher = canvasView.getElementPos.bind(canvasView); |
||||
options.mousePosFetcher = canvas.getMouseRelativePos; |
options.mousePosFetcher = canvas.getMouseRelativePos; |
||||
this.canvasResizer = editor.Utils.Resizer.init(options); |
this.canvasResizer = editor.Utils.Resizer.init(options); |
||||
canvasResizer = this.canvasResizer; |
canvasResizer = this.canvasResizer; |
||||
} |
} |
||||
|
|
||||
canvasResizer.setOptions(options); |
canvasResizer.setOptions(options); |
||||
canvasResizer.focus(el); |
canvasResizer.focus(el); |
||||
}, |
}, |
||||
|
|
||||
stop: function() { |
stop() { |
||||
if(this.canvasResizer) |
if(this.canvasResizer) |
||||
this.canvasResizer.blur(); |
this.canvasResizer.blur(); |
||||
}, |
}, |
||||
|
|
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
File diff suppressed because it is too large
@ -1,103 +1,100 @@ |
|||||
define(function() { |
module.exports = { |
||||
|
|
||||
return { |
/** |
||||
|
* Start select position event |
||||
|
* @param {HTMLElement} trg |
||||
|
* @private |
||||
|
* */ |
||||
|
startSelectPosition(trg, doc) { |
||||
|
this.isPointed = false; |
||||
|
var utils = this.editorModel.get('Utils'); |
||||
|
if(utils && !this.sorter) |
||||
|
this.sorter = new utils.Sorter({ |
||||
|
container: this.getCanvasBody(), |
||||
|
placer: this.canvas.getPlacerEl(), |
||||
|
containerSel: '*', |
||||
|
itemSel: '*', |
||||
|
pfx: this.ppfx, |
||||
|
direction: 'a', |
||||
|
document: doc, |
||||
|
wmargin: 1, |
||||
|
nested: 1, |
||||
|
em: this.editorModel, |
||||
|
canvasRelative: 1, |
||||
|
}); |
||||
|
this.sorter.startSort(trg); |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Start select position event |
* Get frame position |
||||
* @param {HTMLElement} trg |
* @return {Object} |
||||
* @private |
* @private |
||||
* */ |
*/ |
||||
startSelectPosition: function(trg, doc) { |
getOffsetDim() { |
||||
this.isPointed = false; |
var frameOff = this.offset(this.canvas.getFrameEl()); |
||||
var utils = this.editorModel.get('Utils'); |
var canvasOff = this.offset(this.canvas.getElement()); |
||||
if(utils && !this.sorter) |
var top = frameOff.top - canvasOff.top; |
||||
this.sorter = new utils.Sorter({ |
var left = frameOff.left - canvasOff.left; |
||||
container: this.getCanvasBody(), |
return { top, left }; |
||||
placer: this.canvas.getPlacerEl(), |
}, |
||||
containerSel: '*', |
|
||||
itemSel: '*', |
|
||||
pfx: this.ppfx, |
|
||||
direction: 'a', |
|
||||
document: doc, |
|
||||
wmargin: 1, |
|
||||
nested: 1, |
|
||||
em: this.editorModel, |
|
||||
canvasRelative: 1, |
|
||||
}); |
|
||||
this.sorter.startSort(trg); |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Get frame position |
* Stop select position event |
||||
* @return {Object} |
* @private |
||||
* @private |
* */ |
||||
*/ |
stopSelectPosition() { |
||||
getOffsetDim: function() { |
this.posTargetCollection = null; |
||||
var frameOff = this.offset(this.canvas.getFrameEl()); |
this.posIndex = this.posMethod=='after' && this.cDim.length!==0 ? this.posIndex + 1 : this.posIndex; //Normalize
|
||||
var canvasOff = this.offset(this.canvas.getElement()); |
if(this.sorter){ |
||||
var top = frameOff.top - canvasOff.top; |
this.sorter.moved = 0; |
||||
var left = frameOff.left - canvasOff.left; |
this.sorter.endMove(); |
||||
return { top: top, left: left }; |
} |
||||
}, |
if(this.cDim){ |
||||
|
this.posIsLastEl = this.cDim.length!==0 && this.posMethod=='after' && this.posIndex==this.cDim.length; |
||||
|
this.posTargetEl = (this.cDim.length===0 ? $(this.outsideElem) : |
||||
|
(!this.posIsLastEl && this.cDim[this.posIndex] ? $(this.cDim[this.posIndex][5]).parent() : $(this.outsideElem) )); |
||||
|
this.posTargetModel = this.posTargetEl.data("model"); |
||||
|
this.posTargetCollection = this.posTargetEl.data("model-comp"); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Stop select position event |
* Enabel select position |
||||
* @private |
* @private |
||||
* */ |
*/ |
||||
stopSelectPosition: function() { |
enable() { |
||||
this.posTargetCollection = null; |
this.startSelectPosition(); |
||||
this.posIndex = this.posMethod=='after' && this.cDim.length!==0 ? this.posIndex + 1 : this.posIndex; //Normalize
|
}, |
||||
if(this.sorter){ |
|
||||
this.sorter.moved = 0; |
|
||||
this.sorter.endMove(); |
|
||||
} |
|
||||
if(this.cDim){ |
|
||||
this.posIsLastEl = this.cDim.length!==0 && this.posMethod=='after' && this.posIndex==this.cDim.length; |
|
||||
this.posTargetEl = (this.cDim.length===0 ? $(this.outsideElem) : |
|
||||
(!this.posIsLastEl && this.cDim[this.posIndex] ? $(this.cDim[this.posIndex][5]).parent() : $(this.outsideElem) )); |
|
||||
this.posTargetModel = this.posTargetEl.data("model"); |
|
||||
this.posTargetCollection = this.posTargetEl.data("model-comp"); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* Enabel select position |
* Check if the pointer is near to the float component |
||||
* @private |
* @param {number} index |
||||
*/ |
* @param {string} method |
||||
enable: function() { |
* @param {Array<Array>} dims |
||||
this.startSelectPosition(); |
* @return {Boolean} |
||||
}, |
* @private |
||||
|
* */ |
||||
|
nearFloat(index, method, dims) { |
||||
|
var i = index || 0; |
||||
|
var m = method || 'before'; |
||||
|
var len = dims.length; |
||||
|
var isLast = len !== 0 && m == 'after' && i == len; |
||||
|
if(len !== 0 && ( |
||||
|
(!isLast && !dims[i][4]) || |
||||
|
(dims[i-1] && !dims[i-1][4]) || |
||||
|
(isLast && !dims[i-1][4]) ) ) |
||||
|
return 1; |
||||
|
return 0; |
||||
|
}, |
||||
|
|
||||
/** |
|
||||
* Check if the pointer is near to the float component |
|
||||
* @param {number} index |
|
||||
* @param {string} method |
|
||||
* @param {Array<Array>} dims |
|
||||
* @return {Boolean} |
|
||||
* @private |
|
||||
* */ |
|
||||
nearFloat: function(index, method, dims) { |
|
||||
var i = index || 0; |
|
||||
var m = method || 'before'; |
|
||||
var len = dims.length; |
|
||||
var isLast = len !== 0 && m == 'after' && i == len; |
|
||||
if(len !== 0 && ( |
|
||||
(!isLast && !dims[i][4]) || |
|
||||
(dims[i-1] && !dims[i-1][4]) || |
|
||||
(isLast && !dims[i-1][4]) ) ) |
|
||||
return 1; |
|
||||
return 0; |
|
||||
}, |
|
||||
|
|
||||
|
run() { |
||||
|
this.enable(); |
||||
|
}, |
||||
|
|
||||
run: function() { |
stop() { |
||||
this.enable(); |
this.stopSelectPosition(); |
||||
}, |
this.$wrapper.css('cursor',''); |
||||
|
this.$wrapper.unbind(); |
||||
stop: function() { |
} |
||||
this.stopSelectPosition(); |
}; |
||||
this.$wrapper.css('cursor',''); |
|
||||
this.$wrapper.unbind(); |
|
||||
} |
|
||||
}; |
|
||||
}); |
|
||||
|
|||||
@ -1,149 +1,147 @@ |
|||||
define(function() { |
module.exports = { |
||||
return { |
|
||||
|
getOffsetMethod(state) { |
||||
getOffsetMethod: function(state) { |
var method = state || ''; |
||||
var method = state || ''; |
return 'get' + method + 'OffsetViewerEl'; |
||||
return 'get' + method + 'OffsetViewerEl'; |
}, |
||||
}, |
|
||||
|
run(editor, sender, opts) { |
||||
run: function(editor, sender, opts) { |
var opt = opts || {}; |
||||
var opt = opts || {}; |
var state = opt.state || ''; |
||||
var state = opt.state || ''; |
var config = editor.getConfig(); |
||||
var config = editor.getConfig(); |
|
||||
|
if (!config.showOffsets || |
||||
if (!config.showOffsets || |
(!config.showOffsetsSelected && state == 'Fixed') ) { |
||||
(!config.showOffsetsSelected && state == 'Fixed') ) { |
return; |
||||
return; |
} |
||||
} |
|
||||
|
var canvas = editor.Canvas; |
||||
var canvas = editor.Canvas; |
var el = opt.el || ''; |
||||
var el = opt.el || ''; |
var pos = opt.elPos || canvas.getElementPos(el); |
||||
var pos = opt.elPos || canvas.getElementPos(el); |
var style = window.getComputedStyle(el); |
||||
var style = window.getComputedStyle(el); |
var ppfx = this.ppfx; |
||||
var ppfx = this.ppfx; |
var stateVar = state + 'State'; |
||||
var stateVar = state + 'State'; |
var method = this.getOffsetMethod(state); |
||||
var method = this.getOffsetMethod(state); |
var offsetViewer = canvas[method](); |
||||
var offsetViewer = canvas[method](); |
offsetViewer.style.display = 'block'; |
||||
offsetViewer.style.display = 'block'; |
|
||||
|
var marginT = this['marginT' + state]; |
||||
var marginT = this['marginT' + state]; |
var marginB = this['marginB' + state]; |
||||
var marginB = this['marginB' + state]; |
var marginL = this['marginL' + state]; |
||||
var marginL = this['marginL' + state]; |
var marginR = this['marginR' + state]; |
||||
var marginR = this['marginR' + state]; |
var padT = this['padT' + state]; |
||||
var padT = this['padT' + state]; |
var padB = this['padB' + state]; |
||||
var padB = this['padB' + state]; |
var padL = this['padL' + state]; |
||||
var padL = this['padL' + state]; |
var padR = this['padR' + state]; |
||||
var padR = this['padR' + state]; |
|
||||
|
if(!this[stateVar]) { |
||||
if(!this[stateVar]) { |
var stateLow = state.toLowerCase(); |
||||
var stateLow = state.toLowerCase(); |
var marginName = stateLow + 'margin-v'; |
||||
var marginName = stateLow + 'margin-v'; |
var paddingName = stateLow + 'padding-v'; |
||||
var paddingName = stateLow + 'padding-v'; |
var marginV = $('<div>', {class: ppfx + marginName}).get(0); |
||||
var marginV = $('<div>', {class: ppfx + marginName}).get(0); |
var paddingV = $('<div>', {class: ppfx + paddingName}).get(0); |
||||
var paddingV = $('<div>', {class: ppfx + paddingName}).get(0); |
var marginEls = ppfx + marginName + '-el'; |
||||
var marginEls = ppfx + marginName + '-el'; |
var paddingEls = ppfx + paddingName + '-el'; |
||||
var paddingEls = ppfx + paddingName + '-el'; |
marginT = $('<div>', {class: ppfx + marginName + '-top ' + marginEls}).get(0); |
||||
marginT = $('<div>', {class: ppfx + marginName + '-top ' + marginEls}).get(0); |
marginB = $('<div>', {class: ppfx + marginName + '-bottom ' + marginEls}).get(0); |
||||
marginB = $('<div>', {class: ppfx + marginName + '-bottom ' + marginEls}).get(0); |
marginL = $('<div>', {class: ppfx + marginName + '-left ' + marginEls}).get(0); |
||||
marginL = $('<div>', {class: ppfx + marginName + '-left ' + marginEls}).get(0); |
marginR = $('<div>', {class: ppfx + marginName + '-right ' + marginEls}).get(0); |
||||
marginR = $('<div>', {class: ppfx + marginName + '-right ' + marginEls}).get(0); |
padT = $('<div>', {class: ppfx + paddingName + '-top ' + paddingEls}).get(0); |
||||
padT = $('<div>', {class: ppfx + paddingName + '-top ' + paddingEls}).get(0); |
padB = $('<div>', {class: ppfx + paddingName + '-bottom ' + paddingEls}).get(0); |
||||
padB = $('<div>', {class: ppfx + paddingName + '-bottom ' + paddingEls}).get(0); |
padL = $('<div>', {class: ppfx + paddingName + '-left ' + paddingEls}).get(0); |
||||
padL = $('<div>', {class: ppfx + paddingName + '-left ' + paddingEls}).get(0); |
padR = $('<div>', {class: ppfx + paddingName + '-right ' + paddingEls}).get(0); |
||||
padR = $('<div>', {class: ppfx + paddingName + '-right ' + paddingEls}).get(0); |
this['marginT' + state] = marginT; |
||||
this['marginT' + state] = marginT; |
this['marginB' + state] = marginB; |
||||
this['marginB' + state] = marginB; |
this['marginL' + state] = marginL; |
||||
this['marginL' + state] = marginL; |
this['marginR' + state] = marginR; |
||||
this['marginR' + state] = marginR; |
this['padT' + state] = padT; |
||||
this['padT' + state] = padT; |
this['padB' + state] = padB; |
||||
this['padB' + state] = padB; |
this['padL' + state] = padL; |
||||
this['padL' + state] = padL; |
this['padR' + state] = padR; |
||||
this['padR' + state] = padR; |
marginV.appendChild(marginT); |
||||
marginV.appendChild(marginT); |
marginV.appendChild(marginB); |
||||
marginV.appendChild(marginB); |
marginV.appendChild(marginL); |
||||
marginV.appendChild(marginL); |
marginV.appendChild(marginR); |
||||
marginV.appendChild(marginR); |
paddingV.appendChild(padT); |
||||
paddingV.appendChild(padT); |
paddingV.appendChild(padB); |
||||
paddingV.appendChild(padB); |
paddingV.appendChild(padL); |
||||
paddingV.appendChild(padL); |
paddingV.appendChild(padR); |
||||
paddingV.appendChild(padR); |
offsetViewer.appendChild(marginV); |
||||
offsetViewer.appendChild(marginV); |
offsetViewer.appendChild(paddingV); |
||||
offsetViewer.appendChild(paddingV); |
this[stateVar] = '1'; |
||||
this[stateVar] = '1'; |
} |
||||
} |
|
||||
|
var unit = 'px'; |
||||
var unit = 'px'; |
var marginLeftSt = style.marginLeft.replace(unit, ''); |
||||
var marginLeftSt = style.marginLeft.replace(unit, ''); |
var marginTopSt = parseInt(style.marginTop.replace(unit, '')); |
||||
var marginTopSt = parseInt(style.marginTop.replace(unit, '')); |
var marginBottomSt = parseInt(style.marginBottom.replace(unit, '')); |
||||
var marginBottomSt = parseInt(style.marginBottom.replace(unit, '')); |
var mtStyle = marginT.style; |
||||
var mtStyle = marginT.style; |
var mbStyle = marginB.style; |
||||
var mbStyle = marginB.style; |
var mlStyle = marginL.style; |
||||
var mlStyle = marginL.style; |
var mrStyle = marginR.style; |
||||
var mrStyle = marginR.style; |
var ptStyle = padT.style; |
||||
var ptStyle = padT.style; |
var pbStyle = padB.style; |
||||
var pbStyle = padB.style; |
var plStyle = padL.style; |
||||
var plStyle = padL.style; |
var prStyle = padR.style; |
||||
var prStyle = padR.style; |
var posLeft = parseInt(pos.left); |
||||
var posLeft = parseInt(pos.left); |
|
||||
|
// Margin style
|
||||
// Margin style
|
mtStyle.height = style.marginTop; |
||||
mtStyle.height = style.marginTop; |
mtStyle.width = style.width; |
||||
mtStyle.width = style.width; |
mtStyle.top = pos.top - style.marginTop.replace(unit, '') + unit; |
||||
mtStyle.top = pos.top - style.marginTop.replace(unit, '') + unit; |
mtStyle.left = posLeft + unit; |
||||
mtStyle.left = posLeft + unit; |
|
||||
|
mbStyle.height = style.marginBottom; |
||||
mbStyle.height = style.marginBottom; |
mbStyle.width = style.width; |
||||
mbStyle.width = style.width; |
mbStyle.top = pos.top + pos.height + unit; |
||||
mbStyle.top = pos.top + pos.height + unit; |
mbStyle.left = posLeft + unit; |
||||
mbStyle.left = posLeft + unit; |
|
||||
|
var marginSideH = pos.height + marginTopSt + marginBottomSt + unit; |
||||
var marginSideH = pos.height + marginTopSt + marginBottomSt + unit; |
var marginSideT = pos.top - marginTopSt + unit; |
||||
var marginSideT = pos.top - marginTopSt + unit; |
mlStyle.height = marginSideH; |
||||
mlStyle.height = marginSideH; |
mlStyle.width = style.marginLeft; |
||||
mlStyle.width = style.marginLeft; |
mlStyle.top = marginSideT; |
||||
mlStyle.top = marginSideT; |
mlStyle.left = posLeft - marginLeftSt + unit; |
||||
mlStyle.left = posLeft - marginLeftSt + unit; |
|
||||
|
mrStyle.height = marginSideH; |
||||
mrStyle.height = marginSideH; |
mrStyle.width = style.marginRight; |
||||
mrStyle.width = style.marginRight; |
mrStyle.top = marginSideT; |
||||
mrStyle.top = marginSideT; |
mrStyle.left = posLeft + pos.width + unit; |
||||
mrStyle.left = posLeft + pos.width + unit; |
|
||||
|
// Padding style
|
||||
// Padding style
|
var padTop = parseInt(style.paddingTop.replace(unit, '')); |
||||
var padTop = parseInt(style.paddingTop.replace(unit, '')); |
ptStyle.height = style.paddingTop; |
||||
ptStyle.height = style.paddingTop; |
ptStyle.width = style.width; |
||||
ptStyle.width = style.width; |
ptStyle.top = pos.top + unit; |
||||
ptStyle.top = pos.top + unit; |
ptStyle.left = posLeft + unit; |
||||
ptStyle.left = posLeft + unit; |
|
||||
|
var padBot = parseInt(style.paddingBottom.replace(unit, '')); |
||||
var padBot = parseInt(style.paddingBottom.replace(unit, '')); |
pbStyle.height = style.paddingBottom; |
||||
pbStyle.height = style.paddingBottom; |
pbStyle.width = style.width; |
||||
pbStyle.width = style.width; |
pbStyle.top = pos.top + pos.height - padBot + unit; |
||||
pbStyle.top = pos.top + pos.height - padBot + unit; |
pbStyle.left = posLeft + unit; |
||||
pbStyle.left = posLeft + unit; |
|
||||
|
var padSideH = (pos.height - padBot - padTop) + unit; |
||||
var padSideH = (pos.height - padBot - padTop) + unit; |
var padSideT = pos.top + padTop + unit; |
||||
var padSideT = pos.top + padTop + unit; |
plStyle.height = padSideH; |
||||
plStyle.height = padSideH; |
plStyle.width = style.paddingLeft; |
||||
plStyle.width = style.paddingLeft; |
plStyle.top = padSideT; |
||||
plStyle.top = padSideT; |
plStyle.left = pos.left + unit; |
||||
plStyle.left = pos.left + unit; |
|
||||
|
var padRight = parseInt(style.paddingRight.replace(unit, '')); |
||||
var padRight = parseInt(style.paddingRight.replace(unit, '')); |
prStyle.height = padSideH; |
||||
prStyle.height = padSideH; |
prStyle.width = style.paddingRight; |
||||
prStyle.width = style.paddingRight; |
prStyle.top = padSideT; |
||||
prStyle.top = padSideT; |
prStyle.left = pos.left + pos.width - padRight + unit; |
||||
prStyle.left = pos.left + pos.width - padRight + unit; |
}, |
||||
}, |
|
||||
|
stop(editor, sender, opts) { |
||||
stop: function(editor, sender, opts) { |
var opt = opts || {}; |
||||
var opt = opts || {}; |
var state = opt.state || ''; |
||||
var state = opt.state || ''; |
var method = this.getOffsetMethod(state); |
||||
var method = this.getOffsetMethod(state); |
var canvas = editor.Canvas; |
||||
var canvas = editor.Canvas; |
var offsetViewer = canvas[method](); |
||||
var offsetViewer = canvas[method](); |
offsetViewer.style.display = 'none'; |
||||
offsetViewer.style.display = 'none'; |
}, |
||||
}, |
|
||||
|
}; |
||||
}; |
|
||||
}); |
|
||||
|
|||||
@ -1,13 +1,11 @@ |
|||||
define(function() { |
module.exports = { |
||||
return { |
|
||||
|
|
||||
run: function(ed) { |
run(ed) { |
||||
ed.Canvas.getBody().className = this.ppfx + 'dashed'; |
ed.Canvas.getBody().className = this.ppfx + 'dashed'; |
||||
}, |
}, |
||||
|
|
||||
stop: function(ed) { |
stop(ed) { |
||||
ed.Canvas.getBody().className = ""; |
ed.Canvas.getBody().className = ""; |
||||
} |
} |
||||
|
|
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -1,35 +1,31 @@ |
|||||
define(['backbone', './CreateComponent'], |
var Backbone = require('backbone'); |
||||
function(Backbone, CreateComponent) { |
var CreateComponent = require('./CreateComponent'); |
||||
/** |
|
||||
* @class TextComponent |
|
||||
* @private |
|
||||
* */ |
|
||||
return _.extend({}, CreateComponent, { |
|
||||
|
|
||||
/** |
module.exports = _.extend({}, CreateComponent, { |
||||
* This event is triggered at the beginning of a draw operation |
|
||||
* @param {Object} component Object component before creation |
|
||||
* @private |
|
||||
* */ |
|
||||
beforeDraw: function(component){ |
|
||||
component.type = 'text'; |
|
||||
if(!component.style) |
|
||||
component.style = {}; |
|
||||
component.style.padding = '10px'; |
|
||||
}, |
|
||||
|
|
||||
/** |
/** |
||||
* This event is triggered at the end of a draw operation |
* This event is triggered at the beginning of a draw operation |
||||
* @param {Object} model Component model created |
* @param {Object} component Object component before creation |
||||
* @private |
* @private |
||||
* */ |
* */ |
||||
afterDraw: function(model){ |
beforeDraw(component) { |
||||
if(!model || !model.set) |
component.type = 'text'; |
||||
return; |
if(!component.style) |
||||
model.trigger('focus'); |
component.style = {}; |
||||
if(this.sender) |
component.style.padding = '10px'; |
||||
this.sender.set('active', false); |
}, |
||||
}, |
|
||||
|
|
||||
}); |
/** |
||||
}); |
* This event is triggered at the end of a draw operation |
||||
|
* @param {Object} model Component model created |
||||
|
* @private |
||||
|
* */ |
||||
|
afterDraw(model) { |
||||
|
if(!model || !model.set) |
||||
|
return; |
||||
|
model.trigger('focus'); |
||||
|
if(this.sender) |
||||
|
this.sender.set('active', false); |
||||
|
}, |
||||
|
|
||||
|
}); |
||||
|
|||||
@ -1,59 +0,0 @@ |
|||||
require.config({ |
|
||||
shim: { |
|
||||
underscore: { |
|
||||
exports: '_' |
|
||||
}, |
|
||||
backbone: { |
|
||||
deps: [ 'underscore', 'jquery' ], |
|
||||
exports: 'Backbone' |
|
||||
}, |
|
||||
rte: { |
|
||||
deps: [ 'jquery' ], |
|
||||
exports: 'rte' |
|
||||
}, |
|
||||
backboneUndo: { |
|
||||
deps: ['backbone'], |
|
||||
exports: 'backboneUndo' |
|
||||
}, |
|
||||
keymaster: { |
|
||||
exports: 'keymaster' |
|
||||
}, |
|
||||
}, |
|
||||
|
|
||||
paths: { |
|
||||
jquery: '../node_modules/jquery/dist/jquery', |
|
||||
underscore: '../node_modules/underscore/underscore', |
|
||||
backbone: '../node_modules/backbone/backbone', |
|
||||
backboneUndo: '../node_modules/backbone-undo/Backbone.Undo', |
|
||||
keymaster: '../node_modules/keymaster/keymaster', |
|
||||
text: '../node_modules/requirejs-text/text', |
|
||||
Spectrum: '../node_modules/spectrum-colorpicker/spectrum', |
|
||||
codemirror: '../node_modules/codemirror', |
|
||||
formatting: '../node_modules/codemirror-formatting/formatting', |
|
||||
}, |
|
||||
|
|
||||
packages : [ |
|
||||
{ name: 'GrapesJS', location: 'grapesjs' }, |
|
||||
{ name: 'Abstract', location: 'domain_abstract' }, |
|
||||
{ name: 'Editor', location: 'editor', }, |
|
||||
{ name: 'AssetManager', location: 'asset_manager', }, |
|
||||
{ name: 'BlockManager', location: 'block_manager', }, |
|
||||
{ name: 'TraitManager', location: 'trait_manager', }, |
|
||||
{ name: 'StyleManager', location: 'style_manager', }, |
|
||||
{ name: 'DeviceManager', location: 'device_manager', }, |
|
||||
{ name: 'StorageManager', location: 'storage_manager', }, |
|
||||
{ name: 'PluginManager', location: 'plugin_manager', }, |
|
||||
{ name: 'Navigator', location: 'navigator', }, |
|
||||
{ name: 'DomComponents', location: 'dom_components', }, |
|
||||
{ name: 'RichTextEditor', location: 'rich_text_editor', }, |
|
||||
{ name: 'SelectorManager', location: 'selector_manager', }, |
|
||||
{ name: 'ModalDialog', location: 'modal_dialog', }, |
|
||||
{ name: 'CodeManager', location: 'code_manager', }, |
|
||||
{ name: 'CssComposer', location: 'css_composer', }, |
|
||||
{ name: 'Commands', location: 'commands', }, |
|
||||
{ name: 'Canvas', location: 'canvas', }, |
|
||||
{ name: 'Panels', location: 'panels', }, |
|
||||
{ name: 'Parser', location: 'parser', }, |
|
||||
{ name: 'Utils', location: 'utils', } |
|
||||
] |
|
||||
}); |
|
||||
@ -1,14 +1,12 @@ |
|||||
define(function () { |
module.exports = { |
||||
return { |
|
||||
|
|
||||
// Style prefix
|
// Style prefix
|
||||
stylePrefix: 'css-', |
stylePrefix: 'css-', |
||||
|
|
||||
// Custom CSS string to render on top
|
// Custom CSS string to render on top
|
||||
'staticRules': '', |
'staticRules': '', |
||||
|
|
||||
// Default CSS style
|
// Default CSS style
|
||||
rules: [], |
rules: [], |
||||
|
|
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -0,0 +1,272 @@ |
|||||
|
/** |
||||
|
* * [add](#add) |
||||
|
* * [get](#get) |
||||
|
* * [getAll](#getall) |
||||
|
* * [load](#load) |
||||
|
* * [store](#store) |
||||
|
* |
||||
|
* This module contains and manage CSS rules for the template inside the canvas |
||||
|
* Before using the methods you should get first the module from the editor instance, in this way: |
||||
|
* |
||||
|
* ```js
|
||||
|
* var cssComposer = editor.CssComposer; |
||||
|
* ``` |
||||
|
* |
||||
|
* @module CssComposer |
||||
|
* @param {Object} config Configurations |
||||
|
* @param {string|Array<Object>} [config.rules=[]] CSS string or an array of rule objects |
||||
|
* @example |
||||
|
* ... |
||||
|
* CssComposer: { |
||||
|
* rules: '.myClass{ color: red}', |
||||
|
* } |
||||
|
*/ |
||||
|
|
||||
|
module.exports = () => { |
||||
|
var c = {}, |
||||
|
defaults = require('./config/config'), |
||||
|
CssRule = require('./model/CssRule'), |
||||
|
CssRules = require('./model/CssRules'), |
||||
|
Selectors = require('./model/Selectors'), |
||||
|
CssRulesView = require('./view/CssRulesView'); |
||||
|
|
||||
|
var rules, rulesView; |
||||
|
|
||||
|
return { |
||||
|
|
||||
|
Selectors, |
||||
|
|
||||
|
/** |
||||
|
* Name of the module |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
name: 'CssComposer', |
||||
|
|
||||
|
/** |
||||
|
* Mandatory for the storage manager |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
storageKey() { |
||||
|
var keys = []; |
||||
|
var smc = (c.stm && c.stm.getConfig()) || {}; |
||||
|
if(smc.storeCss) |
||||
|
keys.push('css'); |
||||
|
if(smc.storeStyles) |
||||
|
keys.push('styles'); |
||||
|
return keys; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Initializes module. Automatically called with a new instance of the editor |
||||
|
* @param {Object} config Configurations |
||||
|
* @private |
||||
|
*/ |
||||
|
init(config) { |
||||
|
c = config || {}; |
||||
|
for (var name in defaults) { |
||||
|
if (!(name in c)) |
||||
|
c[name] = defaults[name]; |
||||
|
} |
||||
|
|
||||
|
var ppfx = c.pStylePrefix; |
||||
|
if(ppfx) |
||||
|
c.stylePrefix = ppfx + c.stylePrefix; |
||||
|
|
||||
|
var elStyle = (c.em && c.em.config.style) || ''; |
||||
|
c.rules = elStyle || c.rules; |
||||
|
|
||||
|
c.sm = c.em; // TODO Refactor
|
||||
|
rules = new CssRules([], c); |
||||
|
rules.add(c.rules); |
||||
|
|
||||
|
rulesView = new CssRulesView({ |
||||
|
collection: rules, |
||||
|
config: c, |
||||
|
}); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* On load callback |
||||
|
* @private |
||||
|
*/ |
||||
|
onLoad() { |
||||
|
if(c.stm && c.stm.getConfig().autoload) |
||||
|
this.load(); |
||||
|
|
||||
|
if(c.stm && c.stm.isAutosave()) |
||||
|
c.em.listenRules(this.getAll()); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Load data from the passed object, if the object is empty will try to fetch them |
||||
|
* autonomously from the storage manager. |
||||
|
* The fetched data will be added to the collection |
||||
|
* @param {Object} data Object of data to load |
||||
|
* @return {Object} Loaded rules |
||||
|
*/ |
||||
|
load(data) { |
||||
|
var d = data || ''; |
||||
|
if(!d && c.stm) |
||||
|
d = c.em.getCacheLoad(); |
||||
|
var obj = ''; |
||||
|
if(d.styles) { |
||||
|
try{ |
||||
|
obj = JSON.parse(d.styles); |
||||
|
}catch(err){} |
||||
|
} else if (d.css) { |
||||
|
obj = c.em.get('Parser').parseCss(d.css); |
||||
|
} |
||||
|
|
||||
|
if(obj) |
||||
|
rules.reset(obj); |
||||
|
return obj; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Store data to the selected storage |
||||
|
* @param {Boolean} noStore If true, won't store |
||||
|
* @return {Object} Data to store |
||||
|
*/ |
||||
|
store(noStore) { |
||||
|
if(!c.stm) |
||||
|
return; |
||||
|
var obj = {}; |
||||
|
var keys = this.storageKey(); |
||||
|
if(keys.indexOf('css') >= 0) |
||||
|
obj.css = c.em.getCss(); |
||||
|
if(keys.indexOf('styles') >= 0) |
||||
|
obj.styles = JSON.stringify(rules); |
||||
|
if(!noStore) |
||||
|
c.stm.store(obj); |
||||
|
return obj; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new rule to the collection, if not yet exists with the same selectors |
||||
|
* @param {Array<Selector>} selectors Array of selectors |
||||
|
* @param {String} state Css rule state |
||||
|
* @param {String} width For which device this style is oriented |
||||
|
* @param {Object} opts Other options for the rule |
||||
|
* @return {Model} |
||||
|
* @example |
||||
|
* var sm = editor.SelectorManager; |
||||
|
* var sel1 = sm.add('myClass1'); |
||||
|
* var sel2 = sm.add('myClass2'); |
||||
|
* var rule = cssComposer.add([sel1, sel2], 'hover'); |
||||
|
* rule.set('style', { |
||||
|
* width: '100px', |
||||
|
* color: '#fff', |
||||
|
* }); |
||||
|
* */ |
||||
|
add(selectors, state, width, opts) { |
||||
|
var s = state || ''; |
||||
|
var w = width || ''; |
||||
|
var opt = opts || {}; |
||||
|
var rule = this.get(selectors, s, w, opt); |
||||
|
if(rule) |
||||
|
return rule; |
||||
|
else { |
||||
|
opt.state = s; |
||||
|
opt.mediaText = w; |
||||
|
opt.selectors = ''; |
||||
|
rule = new CssRule(opt); |
||||
|
rule.get('selectors').add(selectors); |
||||
|
rules.add(rule); |
||||
|
return rule; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get the rule |
||||
|
* @param {Array<Selector>} selectors Array 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 {Model|null} |
||||
|
* @example |
||||
|
* var sm = editor.SelectorManager; |
||||
|
* var sel1 = sm.add('myClass1'); |
||||
|
* var sel2 = sm.add('myClass2'); |
||||
|
* var rule = cssComposer.get([sel1, sel2], 'hover'); |
||||
|
* // Update the style
|
||||
|
* rule.set('style', { |
||||
|
* width: '300px', |
||||
|
* color: '#000', |
||||
|
* }); |
||||
|
* */ |
||||
|
get(selectors, state, width, ruleProps) { |
||||
|
var rule = null; |
||||
|
rules.each(m => { |
||||
|
if(rule) |
||||
|
return; |
||||
|
if(m.compare(selectors, state, width, ruleProps)) |
||||
|
rule = m; |
||||
|
}); |
||||
|
return rule; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get the collection of rules |
||||
|
* @return {Collection} |
||||
|
* */ |
||||
|
getAll() { |
||||
|
return rules; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add a raw collection of rule objects |
||||
|
* This method overrides styles, in case, of already defined rule |
||||
|
* @param {Array<Object>} data Array of rule objects, eg . [{selectors: ['class1'], style: {....}}, ..] |
||||
|
* @param {Object} opts Options |
||||
|
* @return {Array<Model>} |
||||
|
* @private |
||||
|
*/ |
||||
|
addCollection(data, opts) { |
||||
|
var opt = opts || {}; |
||||
|
var result = []; |
||||
|
var d = data instanceof Array ? data : [data]; |
||||
|
|
||||
|
for (var i = 0, l = d.length; i < l; i++) { |
||||
|
var rule = d[i] || {}; |
||||
|
if(!rule.selectors) |
||||
|
continue; |
||||
|
var sm = c.em && c.em.get('SelectorManager'); |
||||
|
if(!sm) |
||||
|
console.warn('Selector Manager not found'); |
||||
|
var sl = rule.selectors; |
||||
|
var sels = sl instanceof Array ? sl : [sl]; |
||||
|
var newSels = []; |
||||
|
|
||||
|
for (var j = 0, le = sels.length; j < le; j++) { |
||||
|
var selec = sm.add(sels[j]); |
||||
|
newSels.push(selec); |
||||
|
} |
||||
|
|
||||
|
var model = this.add(newSels, rule.state, rule.mediaText, rule); |
||||
|
if (opt.extend) { |
||||
|
var newStyle = _.extend({}, model.get('style'), rule.style || {}); |
||||
|
model.set('style', newStyle); |
||||
|
} else { |
||||
|
model.set('style', rule.style || {}); |
||||
|
} |
||||
|
|
||||
|
result.push(model); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Render the block of CSS rules |
||||
|
* @return {HTMLElement} |
||||
|
* @private |
||||
|
*/ |
||||
|
render() { |
||||
|
return rulesView.render().el; |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
}; |
||||
@ -1,274 +0,0 @@ |
|||||
/** |
|
||||
* * [add](#add) |
|
||||
* * [get](#get) |
|
||||
* * [getAll](#getall) |
|
||||
* * [load](#load) |
|
||||
* * [store](#store) |
|
||||
* |
|
||||
* This module contains and manage CSS rules for the template inside the canvas |
|
||||
* Before using the methods you should get first the module from the editor instance, in this way: |
|
||||
* |
|
||||
* ```js
|
|
||||
* var cssComposer = editor.CssComposer; |
|
||||
* ``` |
|
||||
* |
|
||||
* @module CssComposer |
|
||||
* @param {Object} config Configurations |
|
||||
* @param {string|Array<Object>} [config.rules=[]] CSS string or an array of rule objects |
|
||||
* @example |
|
||||
* ... |
|
||||
* CssComposer: { |
|
||||
* rules: '.myClass{ color: red}', |
|
||||
* } |
|
||||
*/ |
|
||||
define(function(require) { |
|
||||
return function() { |
|
||||
var c = {}, |
|
||||
defaults = require('./config/config'), |
|
||||
CssRule = require('./model/CssRule'), |
|
||||
CssRules = require('./model/CssRules'), |
|
||||
Selectors = require('./model/Selectors'), |
|
||||
CssRulesView = require('./view/CssRulesView'); |
|
||||
|
|
||||
var rules, rulesView; |
|
||||
|
|
||||
return { |
|
||||
|
|
||||
Selectors: Selectors, |
|
||||
|
|
||||
/** |
|
||||
* Name of the module |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
name: 'CssComposer', |
|
||||
|
|
||||
/** |
|
||||
* Mandatory for the storage manager |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
storageKey: function(){ |
|
||||
var keys = []; |
|
||||
var smc = (c.stm && c.stm.getConfig()) || {}; |
|
||||
if(smc.storeCss) |
|
||||
keys.push('css'); |
|
||||
if(smc.storeStyles) |
|
||||
keys.push('styles'); |
|
||||
return keys; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Initializes module. Automatically called with a new instance of the editor |
|
||||
* @param {Object} config Configurations |
|
||||
* @private |
|
||||
*/ |
|
||||
init: function(config) { |
|
||||
c = config || {}; |
|
||||
for (var name in defaults) { |
|
||||
if (!(name in c)) |
|
||||
c[name] = defaults[name]; |
|
||||
} |
|
||||
|
|
||||
var ppfx = c.pStylePrefix; |
|
||||
if(ppfx) |
|
||||
c.stylePrefix = ppfx + c.stylePrefix; |
|
||||
|
|
||||
var elStyle = (c.em && c.em.config.style) || ''; |
|
||||
c.rules = elStyle || c.rules; |
|
||||
|
|
||||
c.sm = c.em; // TODO Refactor
|
|
||||
rules = new CssRules([], c); |
|
||||
rules.add(c.rules); |
|
||||
|
|
||||
rulesView = new CssRulesView({ |
|
||||
collection: rules, |
|
||||
config: c, |
|
||||
}); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* On load callback |
|
||||
* @private |
|
||||
*/ |
|
||||
onLoad: function(){ |
|
||||
if(c.stm && c.stm.getConfig().autoload) |
|
||||
this.load(); |
|
||||
|
|
||||
if(c.stm && c.stm.isAutosave()) |
|
||||
c.em.listenRules(this.getAll()); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Load data from the passed object, if the object is empty will try to fetch them |
|
||||
* autonomously from the storage manager. |
|
||||
* The fetched data will be added to the collection |
|
||||
* @param {Object} data Object of data to load |
|
||||
* @return {Object} Loaded rules |
|
||||
*/ |
|
||||
load: function(data) { |
|
||||
var d = data || ''; |
|
||||
if(!d && c.stm) |
|
||||
d = c.em.getCacheLoad(); |
|
||||
var obj = ''; |
|
||||
if(d.styles) { |
|
||||
try{ |
|
||||
obj = JSON.parse(d.styles); |
|
||||
}catch(err){} |
|
||||
} else if (d.css) { |
|
||||
obj = c.em.get('Parser').parseCss(d.css); |
|
||||
} |
|
||||
|
|
||||
if(obj) |
|
||||
rules.reset(obj); |
|
||||
return obj; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Store data to the selected storage |
|
||||
* @param {Boolean} noStore If true, won't store |
|
||||
* @return {Object} Data to store |
|
||||
*/ |
|
||||
store: function(noStore){ |
|
||||
if(!c.stm) |
|
||||
return; |
|
||||
var obj = {}; |
|
||||
var keys = this.storageKey(); |
|
||||
if(keys.indexOf('css') >= 0) |
|
||||
obj.css = c.em.getCss(); |
|
||||
if(keys.indexOf('styles') >= 0) |
|
||||
obj.styles = JSON.stringify(rules); |
|
||||
if(!noStore) |
|
||||
c.stm.store(obj); |
|
||||
return obj; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new rule to the collection, if not yet exists with the same selectors |
|
||||
* @param {Array<Selector>} selectors Array of selectors |
|
||||
* @param {String} state Css rule state |
|
||||
* @param {String} width For which device this style is oriented |
|
||||
* @param {Object} opts Other options for the rule |
|
||||
* @return {Model} |
|
||||
* @example |
|
||||
* var sm = editor.SelectorManager; |
|
||||
* var sel1 = sm.add('myClass1'); |
|
||||
* var sel2 = sm.add('myClass2'); |
|
||||
* var rule = cssComposer.add([sel1, sel2], 'hover'); |
|
||||
* rule.set('style', { |
|
||||
* width: '100px', |
|
||||
* color: '#fff', |
|
||||
* }); |
|
||||
* */ |
|
||||
add: function(selectors, state, width, opts) { |
|
||||
var s = state || ''; |
|
||||
var w = width || ''; |
|
||||
var opt = opts || {}; |
|
||||
var rule = this.get(selectors, s, w, opt); |
|
||||
if(rule) |
|
||||
return rule; |
|
||||
else { |
|
||||
opt.state = s; |
|
||||
opt.mediaText = w; |
|
||||
opt.selectors = ''; |
|
||||
rule = new CssRule(opt); |
|
||||
rule.get('selectors').add(selectors); |
|
||||
rules.add(rule); |
|
||||
return rule; |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get the rule |
|
||||
* @param {Array<Selector>} selectors Array 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 {Model|null} |
|
||||
* @example |
|
||||
* var sm = editor.SelectorManager; |
|
||||
* var sel1 = sm.add('myClass1'); |
|
||||
* var sel2 = sm.add('myClass2'); |
|
||||
* var rule = cssComposer.get([sel1, sel2], 'hover'); |
|
||||
* // Update the style
|
|
||||
* rule.set('style', { |
|
||||
* width: '300px', |
|
||||
* color: '#000', |
|
||||
* }); |
|
||||
* */ |
|
||||
get: function(selectors, state, width, ruleProps) { |
|
||||
var rule = null; |
|
||||
rules.each(function(m) { |
|
||||
if(rule) |
|
||||
return; |
|
||||
if(m.compare(selectors, state, width, ruleProps)) |
|
||||
rule = m; |
|
||||
}); |
|
||||
return rule; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get the collection of rules |
|
||||
* @return {Collection} |
|
||||
* */ |
|
||||
getAll: function() { |
|
||||
return rules; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add a raw collection of rule objects |
|
||||
* This method overrides styles, in case, of already defined rule |
|
||||
* @param {Array<Object>} data Array of rule objects, eg . [{selectors: ['class1'], style: {....}}, ..] |
|
||||
* @param {Object} opts Options |
|
||||
* @return {Array<Model>} |
|
||||
* @private |
|
||||
*/ |
|
||||
addCollection: function(data, opts) { |
|
||||
var opt = opts || {}; |
|
||||
var result = []; |
|
||||
var d = data instanceof Array ? data : [data]; |
|
||||
|
|
||||
for (var i = 0, l = d.length; i < l; i++) { |
|
||||
var rule = d[i] || {}; |
|
||||
if(!rule.selectors) |
|
||||
continue; |
|
||||
var sm = c.em && c.em.get('SelectorManager'); |
|
||||
if(!sm) |
|
||||
console.warn('Selector Manager not found'); |
|
||||
var sl = rule.selectors; |
|
||||
var sels = sl instanceof Array ? sl : [sl]; |
|
||||
var newSels = []; |
|
||||
|
|
||||
for (var j = 0, le = sels.length; j < le; j++) { |
|
||||
var selec = sm.add(sels[j]); |
|
||||
newSels.push(selec); |
|
||||
} |
|
||||
|
|
||||
var model = this.add(newSels, rule.state, rule.mediaText, rule); |
|
||||
if (opt.extend) { |
|
||||
var newStyle = _.extend({}, model.get('style'), rule.style || {}); |
|
||||
model.set('style', newStyle); |
|
||||
} else { |
|
||||
model.set('style', rule.style || {}); |
|
||||
} |
|
||||
|
|
||||
result.push(model); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Render the block of CSS rules |
|
||||
* @return {HTMLElement} |
|
||||
* @private |
|
||||
*/ |
|
||||
render: function() { |
|
||||
return rulesView.render().el; |
|
||||
} |
|
||||
|
|
||||
}; |
|
||||
}; |
|
||||
|
|
||||
}); |
|
||||
@ -1,93 +1,89 @@ |
|||||
define(['backbone', './Selectors'], |
var Backbone = require('backbone'); |
||||
function (Backbone, Selectors) { |
var Selectors = require('./Selectors'); |
||||
return Backbone.Model.extend({ |
|
||||
|
module.exports = Backbone.Model.extend({ |
||||
defaults: { |
|
||||
// Css selectors
|
defaults: { |
||||
selectors: {}, |
// Css selectors
|
||||
|
selectors: {}, |
||||
// Additional string css selectors
|
|
||||
selectorsAdd: '', |
// Additional string css selectors
|
||||
|
selectorsAdd: '', |
||||
// Css properties style
|
|
||||
style: {}, |
// Css properties style
|
||||
|
style: {}, |
||||
// On which device width this rule should be rendered, eg. @media (max-width: 1000px)
|
|
||||
mediaText: '', |
// On which device width this rule should be rendered, eg. @media (max-width: 1000px)
|
||||
|
mediaText: '', |
||||
// State of the rule, eg: hover | pressed | focused
|
|
||||
state: '', |
// State of the rule, eg: hover | pressed | focused
|
||||
|
state: '', |
||||
// Indicates if the rule is stylable
|
|
||||
stylable: true, |
// Indicates if the rule is stylable
|
||||
}, |
stylable: true, |
||||
|
}, |
||||
initialize: function(c, opt) { |
|
||||
this.config = c || {}; |
initialize(c, opt) { |
||||
this.sm = opt ? opt.sm || {} : {}; |
this.config = c || {}; |
||||
this.slct = this.config.selectors || []; |
this.sm = opt ? opt.sm || {} : {}; |
||||
|
this.slct = this.config.selectors || []; |
||||
if(this.sm.get){ |
|
||||
var slct = []; |
if(this.sm.get){ |
||||
for(var i = 0; i < this.slct.length; i++) |
var slct = []; |
||||
slct.push(this.sm.get('SelectorManager').add(this.slct[i].name || this.slct[i])); |
for(var i = 0; i < this.slct.length; i++) |
||||
this.slct = slct; |
slct.push(this.sm.get('SelectorManager').add(this.slct[i].name || this.slct[i])); |
||||
} |
this.slct = slct; |
||||
|
} |
||||
this.set('selectors', new Selectors(this.slct)); |
|
||||
}, |
this.set('selectors', new Selectors(this.slct)); |
||||
|
}, |
||||
/** |
|
||||
* Compare the actual model with parameters |
/** |
||||
* @param {Object} selectors Collection of selectors |
* Compare the actual model with parameters |
||||
* @param {String} state Css rule state |
* @param {Object} selectors Collection of selectors |
||||
* @param {String} width For which device this style is oriented |
* @param {String} state Css rule state |
||||
* @param {Object} ruleProps Other rule props |
* @param {String} width For which device this style is oriented |
||||
* @return {Boolean} |
* @param {Object} ruleProps Other rule props |
||||
* @private |
* @return {Boolean} |
||||
*/ |
* @private |
||||
compare: function(selectors, state, width, ruleProps){ |
*/ |
||||
var otherRule = ruleProps || {}; |
compare(selectors, state, width, ruleProps) { |
||||
var st = state || ''; |
var otherRule = ruleProps || {}; |
||||
var wd = width || ''; |
var st = state || ''; |
||||
var selectorsAdd = otherRule.selectorsAdd || ''; |
var wd = width || ''; |
||||
var cId = 'cid'; |
var selectorsAdd = otherRule.selectorsAdd || ''; |
||||
//var a1 = _.pluck(selectors.models || selectors, cId);
|
var cId = 'cid'; |
||||
//var a2 = _.pluck(this.get('selectors').models, cId);
|
//var a1 = _.pluck(selectors.models || selectors, cId);
|
||||
if(!(selectors instanceof Array) && !selectors.models) |
//var a2 = _.pluck(this.get('selectors').models, cId);
|
||||
selectors = [selectors]; |
if(!(selectors instanceof Array) && !selectors.models) |
||||
var a1 = _.map((selectors.models || selectors), function(model) { |
selectors = [selectors]; |
||||
return model.get('name'); |
var a1 = _.map((selectors.models || selectors), model => model.get('name')); |
||||
}); |
var a2 = _.map(this.get('selectors').models, model => model.get('name')); |
||||
var a2 = _.map(this.get('selectors').models, function(model) { |
var f = false; |
||||
return model.get('name'); |
|
||||
}); |
if(a1.length !== a2.length) |
||||
var f = false; |
return f; |
||||
|
|
||||
if(a1.length !== a2.length) |
for (var i = 0; i < a1.length; i++) { |
||||
return f; |
var re = 0; |
||||
|
for (var j = 0; j < a2.length; j++) { |
||||
for (var i = 0; i < a1.length; i++) { |
if (a1[i] === a2[j]) |
||||
var re = 0; |
re = 1; |
||||
for (var j = 0; j < a2.length; j++) { |
} |
||||
if (a1[i] === a2[j]) |
if(re === 0) |
||||
re = 1; |
return f; |
||||
} |
} |
||||
if(re === 0) |
|
||||
return f; |
if(this.get('state') !== st) |
||||
} |
return f; |
||||
|
|
||||
if(this.get('state') !== st) |
if(this.get('mediaText') !== wd) |
||||
return f; |
return f; |
||||
|
|
||||
if(this.get('mediaText') !== wd) |
if(this.get('selectorsAdd') !== selectorsAdd) |
||||
return f; |
return f; |
||||
|
|
||||
if(this.get('selectorsAdd') !== selectorsAdd) |
return true; |
||||
return f; |
}, |
||||
|
|
||||
return true; |
|
||||
}, |
|
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,34 +1,34 @@ |
|||||
define(['backbone','./CssRule'], |
var Backbone = require('backbone'); |
||||
function (Backbone, CssRule) { |
var CssRule = require('./CssRule'); |
||||
return Backbone.Collection.extend({ |
|
||||
|
|
||||
initialize: function(models, opt){ |
module.exports = Backbone.Collection.extend({ |
||||
|
|
||||
// Inject editor
|
initialize(models, opt) { |
||||
if(opt && opt.sm) |
|
||||
this.editor = opt.sm; |
|
||||
|
|
||||
this.model = function(attrs, options) { |
// Inject editor
|
||||
var model; |
if(opt && opt.sm) |
||||
|
this.editor = opt.sm; |
||||
|
|
||||
if(!options.sm && opt && opt.sm) |
this.model = (attrs, options) => { |
||||
options.sm = opt.sm; |
var model; |
||||
|
|
||||
switch(1){ |
if(!options.sm && opt && opt.sm) |
||||
default: |
options.sm = opt.sm; |
||||
model = new CssRule(attrs, options); |
|
||||
} |
|
||||
|
|
||||
return model; |
switch(1){ |
||||
}; |
default: |
||||
|
model = new CssRule(attrs, options); |
||||
|
} |
||||
|
|
||||
}, |
return model; |
||||
|
}; |
||||
|
|
||||
add: function(models, opt){ |
}, |
||||
if(typeof models === 'string') |
|
||||
models = this.editor.get('Parser').parseCss(models); |
add(models, opt) { |
||||
return Backbone.Collection.prototype.add.apply(this, [models, opt]); |
if(typeof models === 'string') |
||||
}, |
models = this.editor.get('Parser').parseCss(models); |
||||
|
return Backbone.Collection.prototype.add.apply(this, [models, opt]); |
||||
|
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,25 +1,24 @@ |
|||||
define([ 'backbone', 'require'], |
var Backbone = require('backbone'); |
||||
function (Backbone, require) { |
|
||||
return Backbone.Collection.extend({ |
|
||||
|
|
||||
initialize: function(models, opt){ |
module.exports = Backbone.Collection.extend({ |
||||
|
|
||||
this.model = function(attrs, opts) { |
initialize(models, opt) { |
||||
var model; |
|
||||
|
|
||||
switch(1){ |
this.model = function(attrs, opts) { |
||||
|
var model; |
||||
|
|
||||
default: |
switch(1){ |
||||
if(!this.ClassTag) |
|
||||
this.ClassTag = require("SelectorManager/model/Selector"); |
|
||||
model = new this.ClassTag(attrs, opts); |
|
||||
|
|
||||
} |
default: |
||||
|
if(!this.ClassTag) |
||||
|
this.ClassTag = require("selector_manager/model/Selector"); |
||||
|
model = new this.ClassTag(attrs, opts); |
||||
|
|
||||
return model; |
} |
||||
}; |
|
||||
|
|
||||
}, |
return model; |
||||
|
}; |
||||
|
|
||||
|
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,78 +1,77 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function (Backbone) { |
|
||||
return Backbone.View.extend({ |
|
||||
|
|
||||
tagName: 'style', |
module.exports = Backbone.View.extend({ |
||||
|
|
||||
initialize: function(o) { |
tagName: 'style', |
||||
this.config = o.config || {}; |
|
||||
this.listenTo(this.model, 'change:style', this.render); |
|
||||
this.listenTo(this.model, 'change:state', this.render); |
|
||||
this.listenTo(this.model, 'destroy remove', this.remove); |
|
||||
this.listenTo(this.model, 'change:mediaText', this.render); |
|
||||
this.listenTo(this.model.get('selectors'), 'change', this.selChanged); |
|
||||
}, |
|
||||
|
|
||||
/** |
initialize(o) { |
||||
* Triggered when some selector is changed |
this.config = o.config || {}; |
||||
* @private |
this.listenTo(this.model, 'change:style', this.render); |
||||
*/ |
this.listenTo(this.model, 'change:state', this.render); |
||||
selChanged: function(){ |
this.listenTo(this.model, 'destroy remove', this.remove); |
||||
this.selStr = this.renderSelectors(); |
this.listenTo(this.model, 'change:mediaText', this.render); |
||||
this.render(); |
this.listenTo(this.model.get('selectors'), 'change', this.selChanged); |
||||
}, |
}, |
||||
|
|
||||
|
/** |
||||
|
* Triggered when some selector is changed |
||||
|
* @private |
||||
|
*/ |
||||
|
selChanged() { |
||||
|
this.selStr = this.renderSelectors(); |
||||
|
this.render(); |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Returns string of selectors |
* Returns string of selectors |
||||
* @return {String} |
* @return {String} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
renderSelectors: function() { |
renderSelectors() { |
||||
var sel = []; |
var sel = []; |
||||
var model = this.model; |
var model = this.model; |
||||
var add = model.get('selectorsAdd'); |
var add = model.get('selectorsAdd'); |
||||
model.get('selectors').each(function(m){ |
model.get('selectors').each(m => { |
||||
sel.push('.' + m.get('name')); |
sel.push('.' + m.get('name')); |
||||
}); |
}); |
||||
var sels = sel.join(''); |
var sels = sel.join(''); |
||||
return sels + (sels && add ? ', ' : '') + add; |
return sels + (sels && add ? ', ' : '') + add; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Returns string of properties |
* Returns string of properties |
||||
* @return {String} |
* @return {String} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
renderProperties: function(){ |
renderProperties() { |
||||
var sel = [], |
var sel = [], |
||||
props = this.model.get('style'); |
props = this.model.get('style'); |
||||
for (var prop in props){ |
for (var prop in props){ |
||||
sel.push(prop + ':' + props[prop] + ';'); |
sel.push(prop + ':' + props[prop] + ';'); |
||||
} |
} |
||||
return sel.join(''); |
return sel.join(''); |
||||
}, |
}, |
||||
|
|
||||
render : function(){ |
render() { |
||||
var block = '', |
var block = '', |
||||
selStr = ''; |
selStr = '', |
||||
o = ''; |
o = ''; |
||||
if(!this.selStr) |
if(!this.selStr) |
||||
this.selStr = this.renderSelectors(); |
this.selStr = this.renderSelectors(); |
||||
var prpStr = this.renderProperties(); |
var prpStr = this.renderProperties(); |
||||
var stateStr = this.model.get('state'); |
var stateStr = this.model.get('state'); |
||||
var mediaText = this.model.get('mediaText'); |
var mediaText = this.model.get('mediaText'); |
||||
if(this.selStr){ |
if(this.selStr){ |
||||
stateStr = stateStr ? ':' + stateStr : ''; |
stateStr = stateStr ? ':' + stateStr : ''; |
||||
block = prpStr !== '' ? '{' + prpStr + '}' : ''; |
block = prpStr !== '' ? '{' + prpStr + '}' : ''; |
||||
} |
} |
||||
o = this.selStr && block ? this.selStr + stateStr + block : ''; |
o = this.selStr && block ? this.selStr + stateStr + block : ''; |
||||
|
|
||||
if(mediaText && o) |
if(mediaText && o) |
||||
o = '@media ' + mediaText + '{' + o + '}'; |
o = '@media ' + mediaText + '{' + o + '}'; |
||||
|
|
||||
this.$el.html(o); |
this.$el.html(o); |
||||
return this; |
return this; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,61 +1,61 @@ |
|||||
define(['backbone','./CssRuleView'], |
var Backbone = require('backbone'); |
||||
function (Backbone, CssRuleView) { |
var CssRuleView = require('./CssRuleView'); |
||||
return Backbone.View.extend({ |
|
||||
|
module.exports = Backbone.View.extend({ |
||||
initialize: function(o) { |
|
||||
this.config = o.config || {}; |
initialize(o) { |
||||
this.pfx = this.config.stylePrefix || ''; |
this.config = o.config || {}; |
||||
this.className = this.pfx + 'rules'; |
this.pfx = this.config.stylePrefix || ''; |
||||
this.listenTo( this.collection, 'add', this.addTo ); |
this.className = this.pfx + 'rules'; |
||||
this.listenTo( this.collection, 'reset', this.render ); |
this.listenTo( this.collection, 'add', this.addTo ); |
||||
}, |
this.listenTo( this.collection, 'reset', this.render ); |
||||
|
}, |
||||
/** |
|
||||
* Add to collection |
/** |
||||
* @param {Object} model |
* Add to collection |
||||
* @private |
* @param {Object} model |
||||
* */ |
* @private |
||||
addTo: function(model){ |
* */ |
||||
//console.log('Added');
|
addTo(model) { |
||||
this.addToCollection(model); |
//console.log('Added');
|
||||
}, |
this.addToCollection(model); |
||||
|
}, |
||||
/** |
|
||||
* Add new object to collection |
/** |
||||
* @param {Object} model |
* Add new object to collection |
||||
* @param {Object} fragmentEl |
* @param {Object} model |
||||
* @return {Object} |
* @param {Object} fragmentEl |
||||
* @private |
* @return {Object} |
||||
* */ |
* @private |
||||
addToCollection: function(model, fragmentEl){ |
* */ |
||||
var fragment = fragmentEl || null; |
addToCollection(model, fragmentEl) { |
||||
var viewObject = CssRuleView; |
var fragment = fragmentEl || null; |
||||
|
var viewObject = CssRuleView; |
||||
var view = new viewObject({ |
|
||||
model: model, |
var view = new viewObject({ |
||||
config: this.config, |
model, |
||||
}); |
config: this.config, |
||||
var rendered = view.render().el; |
}); |
||||
|
var rendered = view.render().el; |
||||
if(fragment) |
|
||||
fragment.appendChild( rendered ); |
if(fragment) |
||||
else |
fragment.appendChild( rendered ); |
||||
this.$el.append(rendered); |
else |
||||
|
this.$el.append(rendered); |
||||
return rendered; |
|
||||
}, |
return rendered; |
||||
|
}, |
||||
render: function() { |
|
||||
var fragment = document.createDocumentFragment(); |
render() { |
||||
this.$el.empty(); |
var fragment = document.createDocumentFragment(); |
||||
|
this.$el.empty(); |
||||
this.collection.each(function(model){ |
|
||||
this.addToCollection(model, fragment); |
this.collection.each(function(model){ |
||||
}, this); |
this.addToCollection(model, fragment); |
||||
|
}, this); |
||||
this.$el.append(fragment); |
|
||||
this.$el.attr('class', this.className); |
this.$el.append(fragment); |
||||
return this; |
this.$el.attr('class', this.className); |
||||
} |
return this; |
||||
}); |
} |
||||
}); |
}); |
||||
|
|||||
@ -1,369 +0,0 @@ |
|||||
require(['config/require-config'], function() { |
|
||||
|
|
||||
require(['grapesjs/main'],function (grapesjs){ |
|
||||
|
|
||||
var editor = grapesjs.init( |
|
||||
|
|
||||
|
|
||||
{ |
|
||||
allowScripts: 1, |
|
||||
showOffsets: 1, |
|
||||
autorender: 0, |
|
||||
noticeOnUnload: 0, |
|
||||
container : '#gjs', |
|
||||
height: '100%', |
|
||||
fromElement: true, |
|
||||
clearOnRender: 0, |
|
||||
|
|
||||
storageManager:{ |
|
||||
autoload: 0, |
|
||||
storeComponents: 1, |
|
||||
storeStyles: 1, |
|
||||
}, |
|
||||
|
|
||||
/* |
|
||||
components: [{ |
|
||||
//script: 'var el = this; setInterval(function(){el.style.marginLeft = Math.random() * 50 +"px";}, 1000)',
|
|
||||
script: 'loadScript = function(){console.log("loaded INSIDE", $);}', |
|
||||
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', |
|
||||
height:'100px', |
|
||||
margin: '50px auto', |
|
||||
}, |
|
||||
traits: ['title'], |
|
||||
components: [{ |
|
||||
type: 'textnode', |
|
||||
content: 'text node row', |
|
||||
},{ |
|
||||
type: 'textnode', |
|
||||
content: ', another text node', |
|
||||
},{ |
|
||||
type: 'link', |
|
||||
content: 'someLink', |
|
||||
},{ |
|
||||
type: 'textnode', |
|
||||
content: " More text node --- ", |
|
||||
}], |
|
||||
}], |
|
||||
*/ |
|
||||
|
|
||||
commands: { |
|
||||
defaults : [{ |
|
||||
id: 'open-github', |
|
||||
run: function(editor, sender){ |
|
||||
sender.set('active',false); |
|
||||
window.open('https://github.com/artf/grapesjs','_blank'); |
|
||||
} |
|
||||
},{ |
|
||||
id: 'undo', |
|
||||
run: function(editor, sender){ |
|
||||
sender.set('active',false); |
|
||||
editor.UndoManager.undo(true); |
|
||||
} |
|
||||
},{ |
|
||||
id: 'redo', |
|
||||
run: function(editor, sender){ |
|
||||
sender.set('active',false); |
|
||||
editor.UndoManager.redo(true); |
|
||||
} |
|
||||
},{ |
|
||||
id: 'clean-all', |
|
||||
run: function(editor, sender){ |
|
||||
sender.set('active',false); |
|
||||
if(confirm('Are you sure to clean the canvas?')){ |
|
||||
var comps = editor.DomComponents.clear(); |
|
||||
} |
|
||||
} |
|
||||
}], |
|
||||
}, |
|
||||
|
|
||||
assetManager: { |
|
||||
storageType : '', |
|
||||
storeOnChange : true, |
|
||||
storeAfterUpload : true, |
|
||||
assets : [ |
|
||||
{ type: 'image', src : 'http://placehold.it/350x250/78c5d6/fff/image1.jpg', height:350, width:250}, |
|
||||
{ type: 'image', src : 'http://placehold.it/350x250/459ba8/fff/image2.jpg', height:350, width:250}, |
|
||||
{ type: 'image', src : 'http://placehold.it/350x250/79c267/fff/image3.jpg', height:350, width:250}, |
|
||||
{ type: 'image', src : 'http://placehold.it/350x250/c5d647/fff/image4.jpg', height:350, width:250}, |
|
||||
{ type: 'image', src : 'http://placehold.it/350x250/f28c33/fff/image5.jpg', height:350, width:250}, |
|
||||
{ type: 'image', src : 'http://placehold.it/350x250/e868a2/fff/image6.jpg', height:350, width:250}, |
|
||||
{ type: 'image', src : 'http://placehold.it/350x250/cc4360/fff/image7.jpg', height:350, width:250}, |
|
||||
{ type: 'image', src : './img/work-desk.jpg', date: '2015-02-01',height:1080, width:1728}, |
|
||||
{ type: 'image', src : './img/phone-app.png', date: '2015-02-01',height:650, width:320}, |
|
||||
{ type: 'image', src : './img/bg-gr-v.png', date: '2015-02-01',height:1, width:1728}, |
|
||||
] |
|
||||
}, |
|
||||
|
|
||||
|
|
||||
styleManager : { |
|
||||
sectors: [{ |
|
||||
name: 'General', |
|
||||
open: false, |
|
||||
buildProps: ['float', 'display', 'position', 'top', 'right', 'left', 'bottom'], |
|
||||
},{ |
|
||||
name: 'Dimension', |
|
||||
open: false, |
|
||||
buildProps: ['width', 'height', 'max-width', 'min-height', 'margin', 'padding'], |
|
||||
},{ |
|
||||
name: 'Typography', |
|
||||
open: false, |
|
||||
buildProps: ['font-family', 'font-size', 'font-weight', 'letter-spacing', 'color', 'line-height', 'text-align', 'text-shadow'], |
|
||||
properties: [{ |
|
||||
property: 'text-align', |
|
||||
list : [ |
|
||||
{value: 'left', className: 'fa fa-align-left'}, |
|
||||
{value: 'center', className: 'fa fa-align-center' }, |
|
||||
{value: 'right', className: 'fa fa-align-right'}, |
|
||||
{value: 'justify', className: 'fa fa-align-justify'} |
|
||||
], |
|
||||
}] |
|
||||
},{ |
|
||||
name: 'Decorations', |
|
||||
open: false, |
|
||||
buildProps: ['border-radius-c', 'background-color', 'border-radius', 'border', 'box-shadow', 'background'], |
|
||||
},{ |
|
||||
name: 'Extra', |
|
||||
open: false, |
|
||||
buildProps: ['transition', 'perspective', 'transform'], |
|
||||
},{ |
|
||||
name: 'Flex', |
|
||||
open: false, |
|
||||
properties: [{ |
|
||||
name : 'Flex Container', |
|
||||
property : 'display', |
|
||||
type : 'select', |
|
||||
defaults : 'block', |
|
||||
list : [{ |
|
||||
value : 'block', |
|
||||
name : 'Disable', |
|
||||
},{ |
|
||||
value : 'flex', |
|
||||
name : 'Enable', |
|
||||
}], |
|
||||
},{ |
|
||||
name: 'Flex Parent', |
|
||||
property: 'label-parent-flex', |
|
||||
},{ |
|
||||
name : 'Direction', |
|
||||
property : 'flex-direction', |
|
||||
type : 'radio', |
|
||||
defaults : 'row', |
|
||||
list : [{ |
|
||||
value : 'row', |
|
||||
name : 'Row', |
|
||||
className : 'icons-flex icon-dir-row', |
|
||||
title : 'Row', |
|
||||
},{ |
|
||||
value : 'row-reverse', |
|
||||
name : 'Row reverse', |
|
||||
className : 'icons-flex icon-dir-row-rev', |
|
||||
title : 'Row reverse', |
|
||||
},{ |
|
||||
value : 'column', |
|
||||
name : 'Column', |
|
||||
title : 'Column', |
|
||||
className : 'icons-flex icon-dir-col', |
|
||||
},{ |
|
||||
value : 'column-reverse', |
|
||||
name : 'Column reverse', |
|
||||
title : 'Column reverse', |
|
||||
className : 'icons-flex icon-dir-col-rev', |
|
||||
}], |
|
||||
},{ |
|
||||
name : 'Wrap', |
|
||||
property : 'flex-wrap', |
|
||||
type : 'radio', |
|
||||
defaults : 'nowrap', |
|
||||
list : [{ |
|
||||
value : 'nowrap', |
|
||||
title : 'Single line', |
|
||||
},{ |
|
||||
value : 'wrap', |
|
||||
title : 'Multiple lines', |
|
||||
},{ |
|
||||
value : 'wrap-reverse', |
|
||||
title : 'Multiple lines reverse', |
|
||||
}], |
|
||||
},{ |
|
||||
name : 'Justify', |
|
||||
property : 'justify-content', |
|
||||
type : 'radio', |
|
||||
defaults : 'flex-start', |
|
||||
list : [{ |
|
||||
value : 'flex-start', |
|
||||
className : 'icons-flex icon-just-start', |
|
||||
title : 'Start', |
|
||||
},{ |
|
||||
value : 'flex-end', |
|
||||
title : 'End', |
|
||||
className : 'icons-flex icon-just-end', |
|
||||
},{ |
|
||||
value : 'space-between', |
|
||||
title : 'Space between', |
|
||||
className : 'icons-flex icon-just-sp-bet', |
|
||||
},{ |
|
||||
value : 'space-around', |
|
||||
title : 'Space around', |
|
||||
className : 'icons-flex icon-just-sp-ar', |
|
||||
},{ |
|
||||
value : 'center', |
|
||||
title : 'Center', |
|
||||
className : 'icons-flex icon-just-sp-cent', |
|
||||
}], |
|
||||
},{ |
|
||||
name : 'Align', |
|
||||
property : 'align-items', |
|
||||
type : 'radio', |
|
||||
defaults : 'center', |
|
||||
list : [{ |
|
||||
value : 'flex-start', |
|
||||
title : 'Start', |
|
||||
className : 'icons-flex icon-al-start', |
|
||||
},{ |
|
||||
value : 'flex-end', |
|
||||
title : 'End', |
|
||||
className : 'icons-flex icon-al-end', |
|
||||
},{ |
|
||||
value : 'stretch', |
|
||||
title : 'Stretch', |
|
||||
className : 'icons-flex icon-al-str', |
|
||||
},{ |
|
||||
value : 'center', |
|
||||
title : 'Center', |
|
||||
className : 'icons-flex icon-al-center', |
|
||||
}], |
|
||||
},{ |
|
||||
name: 'Flex Children', |
|
||||
property: 'label-parent-flex', |
|
||||
},{ |
|
||||
name: 'Order', |
|
||||
property: 'order', |
|
||||
type: 'integer', |
|
||||
defaults : 0, |
|
||||
min: 0 |
|
||||
},{ |
|
||||
name : 'Flex', |
|
||||
property : 'flex', |
|
||||
type : 'composite', |
|
||||
properties : [{ |
|
||||
name: 'Grow', |
|
||||
property: 'flex-grow', |
|
||||
type: 'integer', |
|
||||
defaults : 0, |
|
||||
min: 0 |
|
||||
},{ |
|
||||
name: 'Shrink', |
|
||||
property: 'flex-shrink', |
|
||||
type: 'integer', |
|
||||
defaults : 0, |
|
||||
min: 0 |
|
||||
},{ |
|
||||
name: 'Basis', |
|
||||
property: 'flex-basis', |
|
||||
type: 'integer', |
|
||||
units: ['px','%',''], |
|
||||
unit: '', |
|
||||
defaults : 'auto', |
|
||||
}], |
|
||||
},{ |
|
||||
name : 'Align', |
|
||||
property : 'align-self', |
|
||||
type : 'radio', |
|
||||
defaults : 'auto', |
|
||||
list : [{ |
|
||||
value : 'auto', |
|
||||
name : 'Auto', |
|
||||
},{ |
|
||||
value : 'flex-start', |
|
||||
title : 'Start', |
|
||||
className : 'icons-flex icon-al-start', |
|
||||
},{ |
|
||||
value : 'flex-end', |
|
||||
title : 'End', |
|
||||
className : 'icons-flex icon-al-end', |
|
||||
},{ |
|
||||
value : 'stretch', |
|
||||
title : 'Stretch', |
|
||||
className : 'icons-flex icon-al-str', |
|
||||
},{ |
|
||||
value : 'center', |
|
||||
title : 'Center', |
|
||||
className : 'icons-flex icon-al-center', |
|
||||
}], |
|
||||
}] |
|
||||
} |
|
||||
|
|
||||
], |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
|
|
||||
}); |
|
||||
|
|
||||
window.editor = editor; |
|
||||
|
|
||||
var pnm = editor.Panels; |
|
||||
pnm.addButton('options', [{ |
|
||||
id: 'undo', |
|
||||
className: 'fa fa-undo icon-undo', |
|
||||
command: function(editor, sender) { |
|
||||
sender.set('active', 0); |
|
||||
editor.UndoManager.undo(1); |
|
||||
}, |
|
||||
attributes: { title: 'Undo (CTRL/CMD + Z)'} |
|
||||
},{ |
|
||||
id: 'redo', |
|
||||
className: 'fa fa-repeat icon-redo', |
|
||||
command: function(editor, sender) { |
|
||||
sender.set('active', 0); |
|
||||
editor.UndoManager.redo(1); |
|
||||
}, |
|
||||
attributes: { title: 'Redo (CTRL/CMD + SHIFT + Z)' } |
|
||||
},{ |
|
||||
id: 'clean-all', |
|
||||
className: 'fa fa-trash icon-blank', |
|
||||
command: function(editor, sender) { |
|
||||
if(sender) sender.set('active', false); |
|
||||
if(confirm('Are you sure to clean the canvas?')) { |
|
||||
var comps = editor.DomComponents.clear(); |
|
||||
localStorage.clear(); |
|
||||
} |
|
||||
}, |
|
||||
attributes: { title: 'Empty canvas' } |
|
||||
}]); |
|
||||
|
|
||||
editor.render(); |
|
||||
}); |
|
||||
}); |
|
||||
@ -1,9 +1,7 @@ |
|||||
define(function () { |
module.exports = { |
||||
return { |
|
||||
|
|
||||
devices: [], |
devices: [], |
||||
|
|
||||
deviceLabel: 'Device', |
deviceLabel: 'Device', |
||||
|
|
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -0,0 +1,111 @@ |
|||||
|
/** |
||||
|
* * [add](#add) |
||||
|
* * [get](#get) |
||||
|
* * [getAll](#getall) |
||||
|
* |
||||
|
* Before using methods you should get first the module from the editor instance, in this way: |
||||
|
* |
||||
|
* ```js
|
||||
|
* var deviceManager = editor.DeviceManager; |
||||
|
* ``` |
||||
|
* |
||||
|
* @module DeviceManager |
||||
|
*/ |
||||
|
module.exports = () => { |
||||
|
var c = {}, |
||||
|
defaults = require('./config/config'), |
||||
|
Devices = require('./model/Devices'), |
||||
|
DevicesView = require('./view/DevicesView'); |
||||
|
var devices, view; |
||||
|
|
||||
|
return { |
||||
|
|
||||
|
/** |
||||
|
* Name of the module |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
name: 'DeviceManager', |
||||
|
|
||||
|
/** |
||||
|
* Initialize module. Automatically called with a new instance of the editor |
||||
|
* @param {Object} config Configurations |
||||
|
* @param {Array<Object>} [config.devices=[]] Default devices |
||||
|
* @example |
||||
|
* ... |
||||
|
* { |
||||
|
* devices: [ |
||||
|
* {name: 'Desktop', width: ''} |
||||
|
* {name: 'Tablet', width: '991px'} |
||||
|
* ], |
||||
|
* } |
||||
|
* ... |
||||
|
* @return {this} |
||||
|
*/ |
||||
|
init(config) { |
||||
|
c = config || {}; |
||||
|
for (var name in defaults) { |
||||
|
if (!(name in c)) |
||||
|
c[name] = defaults[name]; |
||||
|
} |
||||
|
|
||||
|
devices = new Devices(c.devices); |
||||
|
view = new DevicesView({ |
||||
|
collection: devices, |
||||
|
config: c |
||||
|
}); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new device to the collection. URLs are supposed to be unique |
||||
|
* @param {string} name Device name |
||||
|
* @param {string} width Width of the device |
||||
|
* @param {Object} opts Custom options |
||||
|
* @return {Device} Added device |
||||
|
* @example |
||||
|
* deviceManager.add('Tablet', '900px'); |
||||
|
*/ |
||||
|
add(name, width, opts) { |
||||
|
var obj = opts || {}; |
||||
|
obj.name = name; |
||||
|
obj.width = width; |
||||
|
return devices.add(obj); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Return device by name |
||||
|
* @param {string} name Name of the device |
||||
|
* @example |
||||
|
* var device = deviceManager.get('Tablet'); |
||||
|
* console.log(JSON.stringify(device)); |
||||
|
* // {name: 'Tablet', width: '900px'}
|
||||
|
*/ |
||||
|
get(name) { |
||||
|
return devices.get(name); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Return all devices |
||||
|
* @return {Collection} |
||||
|
* @example |
||||
|
* var devices = deviceManager.getAll(); |
||||
|
* console.log(JSON.stringify(devices)); |
||||
|
* // [{name: 'Desktop', width: ''}, ...]
|
||||
|
*/ |
||||
|
getAll() { |
||||
|
return devices; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Render devices |
||||
|
* @return {string} HTML string |
||||
|
* @private |
||||
|
*/ |
||||
|
render() { |
||||
|
return view.render().el; |
||||
|
}, |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
}; |
||||
@ -1,115 +0,0 @@ |
|||||
/** |
|
||||
* * [add](#add) |
|
||||
* * [get](#get) |
|
||||
* * [getAll](#getall) |
|
||||
* |
|
||||
* Before using methods you should get first the module from the editor instance, in this way: |
|
||||
* |
|
||||
* ```js
|
|
||||
* var deviceManager = editor.DeviceManager; |
|
||||
* ``` |
|
||||
* |
|
||||
* @module DeviceManager |
|
||||
*/ |
|
||||
define(function(require) { |
|
||||
|
|
||||
return function() { |
|
||||
var c = {}, |
|
||||
defaults = require('./config/config'), |
|
||||
Devices = require('./model/Devices'), |
|
||||
DevicesView = require('./view/DevicesView'); |
|
||||
var devices, view; |
|
||||
|
|
||||
return { |
|
||||
|
|
||||
/** |
|
||||
* Name of the module |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
name: 'DeviceManager', |
|
||||
|
|
||||
/** |
|
||||
* Initialize module. Automatically called with a new instance of the editor |
|
||||
* @param {Object} config Configurations |
|
||||
* @param {Array<Object>} [config.devices=[]] Default devices |
|
||||
* @example |
|
||||
* ... |
|
||||
* { |
|
||||
* devices: [ |
|
||||
* {name: 'Desktop', width: ''} |
|
||||
* {name: 'Tablet', width: '991px'} |
|
||||
* ], |
|
||||
* } |
|
||||
* ... |
|
||||
* @return {this} |
|
||||
*/ |
|
||||
init: function(config) { |
|
||||
c = config || {}; |
|
||||
for (var name in defaults) { |
|
||||
if (!(name in c)) |
|
||||
c[name] = defaults[name]; |
|
||||
} |
|
||||
|
|
||||
devices = new Devices(c.devices); |
|
||||
view = new DevicesView({ |
|
||||
collection: devices, |
|
||||
config: c |
|
||||
}); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new device to the collection. URLs are supposed to be unique |
|
||||
* @param {string} name Device name |
|
||||
* @param {string} width Width of the device |
|
||||
* @param {Object} opts Custom options |
|
||||
* @return {Device} Added device |
|
||||
* @example |
|
||||
* deviceManager.add('Tablet', '900px'); |
|
||||
*/ |
|
||||
add: function(name, width, opts){ |
|
||||
var obj = opts || {}; |
|
||||
obj.name = name; |
|
||||
obj.width = width; |
|
||||
return devices.add(obj); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Return device by name |
|
||||
* @param {string} name Name of the device |
|
||||
* @example |
|
||||
* var device = deviceManager.get('Tablet'); |
|
||||
* console.log(JSON.stringify(device)); |
|
||||
* // {name: 'Tablet', width: '900px'}
|
|
||||
*/ |
|
||||
get: function(name){ |
|
||||
return devices.get(name); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Return all devices |
|
||||
* @return {Collection} |
|
||||
* @example |
|
||||
* var devices = deviceManager.getAll(); |
|
||||
* console.log(JSON.stringify(devices)); |
|
||||
* // [{name: 'Desktop', width: ''}, ...]
|
|
||||
*/ |
|
||||
getAll: function(){ |
|
||||
return devices; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Render devices |
|
||||
* @return {string} HTML string |
|
||||
* @private |
|
||||
*/ |
|
||||
render: function(){ |
|
||||
return view.render().el; |
|
||||
}, |
|
||||
|
|
||||
}; |
|
||||
|
|
||||
}; |
|
||||
|
|
||||
}); |
|
||||
@ -1,14 +1,12 @@ |
|||||
define(['backbone'], |
var Backbone = require('backbone'); |
||||
function(Backbone){ |
|
||||
|
|
||||
return Backbone.Model.extend({ |
module.exports = Backbone.Model.extend({ |
||||
|
|
||||
idAttribute: 'name', |
idAttribute: 'name', |
||||
|
|
||||
defaults :{ |
defaults :{ |
||||
name: '', |
name: '', |
||||
width: '', |
width: '', |
||||
}, |
}, |
||||
|
|
||||
}); |
}); |
||||
}); |
|
||||
|
|||||
@ -1,9 +1,6 @@ |
|||||
define(['backbone','./Device'], |
var Backbone = require('backbone'); |
||||
function (Backbone, Device) { |
var Device = require('./Device'); |
||||
|
|
||||
return Backbone.Collection.extend({ |
module.exports = Backbone.Collection.extend({ |
||||
|
model: Device, |
||||
model: Device, |
|
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,10 +0,0 @@ |
|||||
<div class="<%= ppfx %>device-label"><%= deviceLabel %></div> |
|
||||
<div class="<%= ppfx %>field <%= ppfx %>select"> |
|
||||
<span id="<%= ppfx %>input-holder"> |
|
||||
<select class="<%= ppfx %>devices"></select> |
|
||||
</span> |
|
||||
<div class="<%= ppfx %>sel-arrow"> |
|
||||
<div class="<%= ppfx %>d-s-arrow"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<button style="display:none" class="<%= ppfx %>add-trasp">+</button> |
|
||||
@ -1,82 +1,90 @@ |
|||||
define(['backbone', 'text!./../template/devices.html'], |
var Backbone = require('backbone'); |
||||
function(Backbone, devicesTemplate) { |
|
||||
|
|
||||
return Backbone.View.extend({ |
module.exports = Backbone.View.extend({ |
||||
|
|
||||
template: _.template(devicesTemplate), |
template: _.template(` |
||||
|
<div class="<%= ppfx %>device-label"><%= deviceLabel %></div> |
||||
|
<div class="<%= ppfx %>field <%= ppfx %>select"> |
||||
|
<span id="<%= ppfx %>input-holder"> |
||||
|
<select class="<%= ppfx %>devices"></select> |
||||
|
</span> |
||||
|
<div class="<%= ppfx %>sel-arrow"> |
||||
|
<div class="<%= ppfx %>d-s-arrow"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<button style="display:none" class="<%= ppfx %>add-trasp">+</button>`), |
||||
|
|
||||
events: { |
events: { |
||||
'change': 'updateDevice' |
'change': 'updateDevice' |
||||
}, |
}, |
||||
|
|
||||
initialize: function(o) { |
initialize(o) { |
||||
this.config = o.config || {}; |
this.config = o.config || {}; |
||||
this.em = this.config.em; |
this.em = this.config.em; |
||||
this.ppfx = this.config.pStylePrefix || ''; |
this.ppfx = this.config.pStylePrefix || ''; |
||||
this.events['click .' + this.ppfx + 'add-trasp'] = this.startAdd; |
this.events['click .' + this.ppfx + 'add-trasp'] = this.startAdd; |
||||
this.listenTo(this.em, 'change:device', this.updateSelect); |
this.listenTo(this.em, 'change:device', this.updateSelect); |
||||
this.delegateEvents(); |
this.delegateEvents(); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Start adding new device |
* Start adding new device |
||||
* @return {[type]} [description] |
* @return {[type]} [description] |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
startAdd: function(){}, |
startAdd() {}, |
||||
|
|
||||
/** |
/** |
||||
* Update device of the editor |
* Update device of the editor |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
updateDevice: function(){ |
updateDevice() { |
||||
var em = this.em; |
var em = this.em; |
||||
if(em){ |
if(em){ |
||||
var devEl = this.devicesEl; |
|
||||
var val = devEl ? devEl.val() : ''; |
|
||||
em.set('device', val); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Update select value on device update |
|
||||
* @private |
|
||||
*/ |
|
||||
updateSelect: function(){ |
|
||||
var em = this.em; |
|
||||
var devEl = this.devicesEl; |
var devEl = this.devicesEl; |
||||
if(em && em.getDeviceModel && devEl){ |
var val = devEl ? devEl.val() : ''; |
||||
var device = em.getDeviceModel(); |
em.set('device', val); |
||||
var name = device ? device.get('name') : ''; |
} |
||||
devEl.val(name); |
}, |
||||
} |
|
||||
}, |
/** |
||||
|
* Update select value on device update |
||||
|
* @private |
||||
|
*/ |
||||
|
updateSelect() { |
||||
|
var em = this.em; |
||||
|
var devEl = this.devicesEl; |
||||
|
if(em && em.getDeviceModel && devEl){ |
||||
|
var device = em.getDeviceModel(); |
||||
|
var name = device ? device.get('name') : ''; |
||||
|
devEl.val(name); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* Return devices options |
* Return devices options |
||||
* @return {string} String of options |
* @return {string} String of options |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getOptions: function(){ |
getOptions() { |
||||
var result = ''; |
var result = ''; |
||||
this.collection.each(function(device){ |
this.collection.each(device => { |
||||
var name = device.get('name'); |
var name = device.get('name'); |
||||
result += '<option value="' + name+ '">' + name + '</option>'; |
result += '<option value="' + name+ '">' + name + '</option>'; |
||||
}); |
}); |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
render: function() { |
render() { |
||||
var pfx = this.ppfx; |
var pfx = this.ppfx; |
||||
this.$el.html(this.template({ |
this.$el.html(this.template({ |
||||
ppfx: pfx, |
ppfx: pfx, |
||||
deviceLabel: this.config.deviceLabel |
deviceLabel: this.config.deviceLabel |
||||
})); |
})); |
||||
this.devicesEl = this.$el.find('.' + pfx + 'devices'); |
this.devicesEl = this.$el.find('.' + pfx + 'devices'); |
||||
this.devicesEl.append(this.getOptions()); |
this.devicesEl.append(this.getOptions()); |
||||
this.el.className = pfx + 'devices-c'; |
this.el.className = pfx + 'devices-c'; |
||||
return this; |
return this; |
||||
}, |
}, |
||||
|
|
||||
}); |
}); |
||||
}); |
|
||||
|
|||||
@ -1,32 +1,30 @@ |
|||||
define(function () { |
module.exports = { |
||||
return { |
stylePrefix: 'comp-', |
||||
stylePrefix: 'comp-', |
|
||||
|
|
||||
wrapperId: 'wrapper', |
wrapperId: 'wrapper', |
||||
|
|
||||
// Default wrapper configuration
|
// Default wrapper configuration
|
||||
wrapper: { |
wrapper: { |
||||
//classes: ['body'],
|
//classes: ['body'],
|
||||
removable: false, |
removable: false, |
||||
copyable: false, |
copyable: false, |
||||
stylable: ['background','background-color','background-image', 'background-repeat','background-attachment','background-position'], |
stylable: ['background','background-color','background-image', 'background-repeat','background-attachment','background-position'], |
||||
draggable: false, |
draggable: false, |
||||
badgable: false, |
badgable: false, |
||||
components: [], |
components: [], |
||||
}, |
}, |
||||
|
|
||||
// Could be used for default components
|
// Could be used for default components
|
||||
components: [], |
components: [], |
||||
|
|
||||
rte: {}, |
rte: {}, |
||||
|
|
||||
// Class for new image component
|
// Class for new image component
|
||||
imageCompClass : 'fa fa-picture-o', |
imageCompClass : 'fa fa-picture-o', |
||||
|
|
||||
// Open assets manager on create of image component
|
// Open assets manager on create of image component
|
||||
oAssetsOnCreate : true, |
oAssetsOnCreate : true, |
||||
|
|
||||
// List of void elements
|
// List of void elements
|
||||
voidElements: ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'], |
voidElements: ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'], |
||||
}; |
}; |
||||
}); |
|
||||
|
|||||
@ -0,0 +1,395 @@ |
|||||
|
/** |
||||
|
* |
||||
|
* * [getWrapper](#getwrapper) |
||||
|
* * [getComponents](#getcomponents) |
||||
|
* * [addComponent](#addcomponent) |
||||
|
* * [clear](#clear) |
||||
|
* * [load](#load) |
||||
|
* * [store](#store) |
||||
|
* * [render](#render) |
||||
|
* |
||||
|
* With this module is possible to manage components inside the canvas. |
||||
|
* Before using methods you should get first the module from the editor instance, in this way: |
||||
|
* |
||||
|
* ```js
|
||||
|
* var domComponents = editor.DomComponents; |
||||
|
* ``` |
||||
|
* |
||||
|
* @module DomComponents |
||||
|
* @param {Object} config Configurations |
||||
|
* @param {string|Array<Object>} [config.components=[]] HTML string or an array of possible components |
||||
|
* @example |
||||
|
* ... |
||||
|
* domComponents: { |
||||
|
* components: '<div>Hello world!</div>', |
||||
|
* } |
||||
|
* // Or
|
||||
|
* domComponents: { |
||||
|
* components: [ |
||||
|
* { tagName: 'span', style: {color: 'red'}, content: 'Hello'}, |
||||
|
* { style: {width: '100px', content: 'world!'}} |
||||
|
* ], |
||||
|
* } |
||||
|
* ... |
||||
|
*/ |
||||
|
module.exports = () => { |
||||
|
var c = {}, |
||||
|
componentTypes = {}, |
||||
|
defaults = require('./config/config'), |
||||
|
Component = require('./model/Component'), |
||||
|
ComponentView = require('./view/ComponentView'); |
||||
|
|
||||
|
var component, componentView; |
||||
|
var defaultTypes = [ |
||||
|
{ |
||||
|
id: 'cell', |
||||
|
model: require('./model/ComponentTableCell'), |
||||
|
view: require('./view/ComponentTableCellView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'row', |
||||
|
model: require('./model/ComponentTableRow'), |
||||
|
view: require('./view/ComponentTableRowView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'table', |
||||
|
model: require('./model/ComponentTable'), |
||||
|
view: require('./view/ComponentTableView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'map', |
||||
|
model: require('./model/ComponentMap'), |
||||
|
view: require('./view/ComponentMapView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'link', |
||||
|
model: require('./model/ComponentLink'), |
||||
|
view: require('./view/ComponentLinkView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'video', |
||||
|
model: require('./model/ComponentVideo'), |
||||
|
view: require('./view/ComponentVideoView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'image', |
||||
|
model: require('./model/ComponentImage'), |
||||
|
view: require('./view/ComponentImageView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'script', |
||||
|
model: require('./model/ComponentScript'), |
||||
|
view: require('./view/ComponentScriptView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'textnode', |
||||
|
model: require('./model/ComponentTextNode'), |
||||
|
view: require('./view/ComponentTextNodeView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'text', |
||||
|
model: require('./model/ComponentText'), |
||||
|
view: require('./view/ComponentTextView'), |
||||
|
}, |
||||
|
{ |
||||
|
id: 'default', |
||||
|
model: Component, |
||||
|
view: ComponentView, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
return { |
||||
|
|
||||
|
componentTypes: defaultTypes, |
||||
|
|
||||
|
/** |
||||
|
* Name of the module |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
name: 'DomComponents', |
||||
|
|
||||
|
/** |
||||
|
* Returns config |
||||
|
* @return {Object} Config object |
||||
|
* @private |
||||
|
*/ |
||||
|
getConfig() { |
||||
|
return c; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Mandatory for the storage manager |
||||
|
* @type {String} |
||||
|
* @private |
||||
|
*/ |
||||
|
storageKey() { |
||||
|
var keys = []; |
||||
|
var smc = (c.stm && c.stm.getConfig()) || {}; |
||||
|
if(smc.storeHtml) |
||||
|
keys.push('html'); |
||||
|
if(smc.storeComponents) |
||||
|
keys.push('components'); |
||||
|
return keys; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Initialize module. Called on a new instance of the editor with configurations passed |
||||
|
* inside 'domComponents' field |
||||
|
* @param {Object} config Configurations |
||||
|
* @private |
||||
|
*/ |
||||
|
init(config) { |
||||
|
c = config || {}; |
||||
|
if(c.em) |
||||
|
c.components = c.em.config.components || c.components; |
||||
|
|
||||
|
for (var name in defaults) { |
||||
|
if (!(name in c)) |
||||
|
c[name] = defaults[name]; |
||||
|
} |
||||
|
|
||||
|
var ppfx = c.pStylePrefix; |
||||
|
if(ppfx) |
||||
|
c.stylePrefix = ppfx + c.stylePrefix; |
||||
|
|
||||
|
// Load dependencies
|
||||
|
if(c.em){ |
||||
|
c.rte = c.em.get('rte') || ''; |
||||
|
c.modal = c.em.get('Modal') || ''; |
||||
|
c.am = c.em.get('AssetManager') || ''; |
||||
|
c.em.get('Parser').compTypes = defaultTypes; |
||||
|
} |
||||
|
|
||||
|
component = new Component(c.wrapper, { |
||||
|
sm: c.em, |
||||
|
config: c, |
||||
|
defaultTypes, |
||||
|
componentTypes, |
||||
|
}); |
||||
|
component.set({ attributes: {id: 'wrapper'}}); |
||||
|
|
||||
|
if(c.em && !c.em.config.loadCompsOnRender) { |
||||
|
component.get('components').add(c.components); |
||||
|
} |
||||
|
|
||||
|
componentView = new ComponentView({ |
||||
|
model: component, |
||||
|
config: c, |
||||
|
defaultTypes, |
||||
|
componentTypes, |
||||
|
}); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* On load callback |
||||
|
* @private |
||||
|
*/ |
||||
|
onLoad() { |
||||
|
if(c.stm && c.stm.getConfig().autoload) |
||||
|
this.load(); |
||||
|
|
||||
|
if(c.stm && c.stm.isAutosave()){ |
||||
|
c.em.initUndoManager(); |
||||
|
c.em.initChildrenComp(this.getWrapper()); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Load components from the passed object, if the object is empty will try to fetch them |
||||
|
* autonomously from the selected storage |
||||
|
* The fetched data will be added to the collection |
||||
|
* @param {Object} data Object of data to load |
||||
|
* @return {Object} Loaded data |
||||
|
*/ |
||||
|
load(data) { |
||||
|
var d = data || ''; |
||||
|
if(!d && c.stm) |
||||
|
d = c.em.getCacheLoad(); |
||||
|
var obj = ''; |
||||
|
if(d.components){ |
||||
|
try{ |
||||
|
obj = JSON.parse(d.components); |
||||
|
}catch(err){} |
||||
|
}else if(d.html) |
||||
|
obj = d.html; |
||||
|
|
||||
|
if(obj) |
||||
|
this.getComponents().reset(obj); |
||||
|
return obj; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Store components on the selected storage |
||||
|
* @param {Boolean} noStore If true, won't store |
||||
|
* @return {Object} Data to store |
||||
|
*/ |
||||
|
store(noStore) { |
||||
|
if(!c.stm) |
||||
|
return; |
||||
|
var obj = {}; |
||||
|
var keys = this.storageKey(); |
||||
|
if(keys.indexOf('html') >= 0) |
||||
|
obj.html = c.em.getHtml(); |
||||
|
if(keys.indexOf('components') >= 0) |
||||
|
obj.components = JSON.stringify(c.em.getComponents()); |
||||
|
if(!noStore) |
||||
|
c.stm.store(obj); |
||||
|
return obj; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns privately the main wrapper |
||||
|
* @return {Object} |
||||
|
* @private |
||||
|
*/ |
||||
|
getComponent() { |
||||
|
return component; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns root component inside the canvas. Something like <body> inside HTML page |
||||
|
* The wrapper doesn't differ from the original Component Model |
||||
|
* @return {Component} Root Component |
||||
|
* @example |
||||
|
* // Change background of the wrapper and set some attribute
|
||||
|
* var wrapper = domComponents.getWrapper(); |
||||
|
* wrapper.set('style', {'background-color': 'red'}); |
||||
|
* wrapper.set('attributes', {'title': 'Hello!'}); |
||||
|
*/ |
||||
|
getWrapper() { |
||||
|
return this.getComponent(); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Returns wrapper's children collection. Once you have the collection you can |
||||
|
* add other Components(Models) inside. Each component can have several nested |
||||
|
* components inside and you can nest them as more as you wish. |
||||
|
* @return {Components} Collection of components |
||||
|
* @example |
||||
|
* // Let's add some component
|
||||
|
* var wrapperChildren = domComponents.getComponents(); |
||||
|
* var comp1 = wrapperChildren.add({ |
||||
|
* style: { 'background-color': 'red'} |
||||
|
* }); |
||||
|
* var comp2 = wrapperChildren.add({ |
||||
|
* tagName: 'span', |
||||
|
* attributes: { title: 'Hello!'} |
||||
|
* }); |
||||
|
* // Now let's add an other one inside first component
|
||||
|
* // First we have to get the collection inside. Each
|
||||
|
* // component has 'components' property
|
||||
|
* var comp1Children = comp1.get('components'); |
||||
|
* // Procede as before. You could also add multiple objects
|
||||
|
* comp1Children.add([ |
||||
|
* { style: { 'background-color': 'blue'}}, |
||||
|
* { style: { height: '100px', width: '100px'}} |
||||
|
* ]); |
||||
|
* // Remove comp2
|
||||
|
* wrapperChildren.remove(comp2); |
||||
|
*/ |
||||
|
getComponents() { |
||||
|
return this.getWrapper().get('components'); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new components to the wrapper's children. It's the same |
||||
|
* as 'domComponents.getComponents().add(...)' |
||||
|
* @param {Object|Component|Array<Object>} component Component/s to add |
||||
|
* @param {string} [component.tagName='div'] Tag name |
||||
|
* @param {string} [component.type=''] Type of the component. Available: ''(default), 'text', 'image' |
||||
|
* @param {boolean} [component.removable=true] If component is removable |
||||
|
* @param {boolean} [component.draggable=true] If is possible to move the component around the structure |
||||
|
* @param {boolean} [component.droppable=true] If is possible to drop inside other components |
||||
|
* @param {boolean} [component.badgable=true] If the badge is visible when the component is selected |
||||
|
* @param {boolean} [component.stylable=true] If is possible to style component |
||||
|
* @param {boolean} [component.copyable=true] If is possible to copy&paste the component |
||||
|
* @param {string} [component.content=''] String inside component |
||||
|
* @param {Object} [component.style={}] Style object |
||||
|
* @param {Object} [component.attributes={}] Attribute object |
||||
|
* @return {Component|Array<Component>} Component/s added |
||||
|
* @example |
||||
|
* // Example of a new component with some extra property
|
||||
|
* var comp1 = domComponents.addComponent({ |
||||
|
* tagName: 'div', |
||||
|
* removable: true, // Can't remove it
|
||||
|
* draggable: true, // Can't move it
|
||||
|
* copyable: true, // Disable copy/past
|
||||
|
* content: 'Content text', // Text inside component
|
||||
|
* style: { color: 'red'}, |
||||
|
* attributes: { title: 'here' } |
||||
|
* }); |
||||
|
*/ |
||||
|
addComponent(component) { |
||||
|
return this.getComponents().add(component); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Render and returns wrapper element with all components inside. |
||||
|
* Once the wrapper is rendered, and it's what happens when you init the editor, |
||||
|
* the all new components will be added automatically and property changes are all |
||||
|
* updated immediately |
||||
|
* @return {HTMLElement} |
||||
|
*/ |
||||
|
render() { |
||||
|
return componentView.render().el; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Remove all components |
||||
|
* @return {this} |
||||
|
*/ |
||||
|
clear() { |
||||
|
var c = this.getComponents(); |
||||
|
for(var i = 0, len = c.length; i < len; i++) |
||||
|
c.pop(); |
||||
|
return this; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Set components |
||||
|
* @param {Object|string} components HTML string or components model |
||||
|
* @return {this} |
||||
|
* @private |
||||
|
*/ |
||||
|
setComponents(components) { |
||||
|
this.clear().addComponent(components); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Add new component type |
||||
|
* @param {string} type |
||||
|
* @param {Object} methods |
||||
|
* @private |
||||
|
*/ |
||||
|
addType(type, methods) { |
||||
|
var compType = this.getType(type); |
||||
|
if(compType) { |
||||
|
compType.model = methods.model; |
||||
|
compType.view = methods.view; |
||||
|
} else { |
||||
|
methods.id = type; |
||||
|
defaultTypes.unshift(methods); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get component type |
||||
|
* @param {string} type |
||||
|
* @private |
||||
|
*/ |
||||
|
getType(type) { |
||||
|
var df = defaultTypes; |
||||
|
|
||||
|
for (var it = 0; it < df.length; it++) { |
||||
|
var dfId = df[it].id; |
||||
|
if(dfId == type) { |
||||
|
return df[it]; |
||||
|
} |
||||
|
} |
||||
|
return; |
||||
|
}, |
||||
|
|
||||
|
}; |
||||
|
}; |
||||
@ -1,398 +0,0 @@ |
|||||
/** |
|
||||
* |
|
||||
* * [getWrapper](#getwrapper) |
|
||||
* * [getComponents](#getcomponents) |
|
||||
* * [addComponent](#addcomponent) |
|
||||
* * [clear](#clear) |
|
||||
* * [load](#load) |
|
||||
* * [store](#store) |
|
||||
* * [render](#render) |
|
||||
* |
|
||||
* With this module is possible to manage components inside the canvas. |
|
||||
* Before using methods you should get first the module from the editor instance, in this way: |
|
||||
* |
|
||||
* ```js
|
|
||||
* var domComponents = editor.DomComponents; |
|
||||
* ``` |
|
||||
* |
|
||||
* @module DomComponents |
|
||||
* @param {Object} config Configurations |
|
||||
* @param {string|Array<Object>} [config.components=[]] HTML string or an array of possible components |
|
||||
* @example |
|
||||
* ... |
|
||||
* domComponents: { |
|
||||
* components: '<div>Hello world!</div>', |
|
||||
* } |
|
||||
* // Or
|
|
||||
* domComponents: { |
|
||||
* components: [ |
|
||||
* { tagName: 'span', style: {color: 'red'}, content: 'Hello'}, |
|
||||
* { style: {width: '100px', content: 'world!'}} |
|
||||
* ], |
|
||||
* } |
|
||||
* ... |
|
||||
*/ |
|
||||
define(function(require) { |
|
||||
|
|
||||
return function (){ |
|
||||
var c = {}, |
|
||||
componentTypes = {}, |
|
||||
defaults = require('./config/config'), |
|
||||
Component = require('./model/Component'), |
|
||||
ComponentView = require('./view/ComponentView'); |
|
||||
|
|
||||
var component, componentView; |
|
||||
var defaultTypes = [ |
|
||||
{ |
|
||||
id: 'cell', |
|
||||
model: require('./model/ComponentTableCell'), |
|
||||
view: require('./view/ComponentTableCellView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'row', |
|
||||
model: require('./model/ComponentTableRow'), |
|
||||
view: require('./view/ComponentTableRowView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'table', |
|
||||
model: require('./model/ComponentTable'), |
|
||||
view: require('./view/ComponentTableView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'map', |
|
||||
model: require('./model/ComponentMap'), |
|
||||
view: require('./view/ComponentMapView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'link', |
|
||||
model: require('./model/ComponentLink'), |
|
||||
view: require('./view/ComponentLinkView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'video', |
|
||||
model: require('./model/ComponentVideo'), |
|
||||
view: require('./view/ComponentVideoView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'image', |
|
||||
model: require('./model/ComponentImage'), |
|
||||
view: require('./view/ComponentImageView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'script', |
|
||||
model: require('./model/ComponentScript'), |
|
||||
view: require('./view/ComponentScriptView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'textnode', |
|
||||
model: require('./model/ComponentTextNode'), |
|
||||
view: require('./view/ComponentTextNodeView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'text', |
|
||||
model: require('./model/ComponentText'), |
|
||||
view: require('./view/ComponentTextView'), |
|
||||
}, |
|
||||
{ |
|
||||
id: 'default', |
|
||||
model: Component, |
|
||||
view: ComponentView, |
|
||||
}, |
|
||||
]; |
|
||||
|
|
||||
return { |
|
||||
|
|
||||
componentTypes: defaultTypes, |
|
||||
|
|
||||
/** |
|
||||
* Name of the module |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
name: 'DomComponents', |
|
||||
|
|
||||
/** |
|
||||
* Returns config |
|
||||
* @return {Object} Config object |
|
||||
* @private |
|
||||
*/ |
|
||||
getConfig: function () { |
|
||||
return c; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Mandatory for the storage manager |
|
||||
* @type {String} |
|
||||
* @private |
|
||||
*/ |
|
||||
storageKey: function(){ |
|
||||
var keys = []; |
|
||||
var smc = (c.stm && c.stm.getConfig()) || {}; |
|
||||
if(smc.storeHtml) |
|
||||
keys.push('html'); |
|
||||
if(smc.storeComponents) |
|
||||
keys.push('components'); |
|
||||
return keys; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Initialize module. Called on a new instance of the editor with configurations passed |
|
||||
* inside 'domComponents' field |
|
||||
* @param {Object} config Configurations |
|
||||
* @private |
|
||||
*/ |
|
||||
init: function(config) { |
|
||||
c = config || {}; |
|
||||
if(c.em) |
|
||||
c.components = c.em.config.components || c.components; |
|
||||
|
|
||||
for (var name in defaults) { |
|
||||
if (!(name in c)) |
|
||||
c[name] = defaults[name]; |
|
||||
} |
|
||||
|
|
||||
var ppfx = c.pStylePrefix; |
|
||||
if(ppfx) |
|
||||
c.stylePrefix = ppfx + c.stylePrefix; |
|
||||
|
|
||||
// Load dependencies
|
|
||||
if(c.em){ |
|
||||
c.rte = c.em.get('rte') || ''; |
|
||||
c.modal = c.em.get('Modal') || ''; |
|
||||
c.am = c.em.get('AssetManager') || ''; |
|
||||
c.em.get('Parser').compTypes = defaultTypes; |
|
||||
} |
|
||||
|
|
||||
component = new Component(c.wrapper, { |
|
||||
sm: c.em, |
|
||||
config: c, |
|
||||
defaultTypes: defaultTypes, |
|
||||
componentTypes: componentTypes, |
|
||||
}); |
|
||||
component.set({ attributes: {id: 'wrapper'}}); |
|
||||
|
|
||||
if(c.em && !c.em.config.loadCompsOnRender) { |
|
||||
component.get('components').add(c.components); |
|
||||
} |
|
||||
|
|
||||
componentView = new ComponentView({ |
|
||||
model: component, |
|
||||
config: c, |
|
||||
defaultTypes: defaultTypes, |
|
||||
componentTypes: componentTypes, |
|
||||
}); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* On load callback |
|
||||
* @private |
|
||||
*/ |
|
||||
onLoad: function(){ |
|
||||
if(c.stm && c.stm.getConfig().autoload) |
|
||||
this.load(); |
|
||||
|
|
||||
if(c.stm && c.stm.isAutosave()){ |
|
||||
c.em.initUndoManager(); |
|
||||
c.em.initChildrenComp(this.getWrapper()); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Load components from the passed object, if the object is empty will try to fetch them |
|
||||
* autonomously from the selected storage |
|
||||
* The fetched data will be added to the collection |
|
||||
* @param {Object} data Object of data to load |
|
||||
* @return {Object} Loaded data |
|
||||
*/ |
|
||||
load: function(data){ |
|
||||
var d = data || ''; |
|
||||
if(!d && c.stm) |
|
||||
d = c.em.getCacheLoad(); |
|
||||
var obj = ''; |
|
||||
if(d.components){ |
|
||||
try{ |
|
||||
obj = JSON.parse(d.components); |
|
||||
}catch(err){} |
|
||||
}else if(d.html) |
|
||||
obj = d.html; |
|
||||
|
|
||||
if(obj) |
|
||||
this.getComponents().reset(obj); |
|
||||
return obj; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Store components on the selected storage |
|
||||
* @param {Boolean} noStore If true, won't store |
|
||||
* @return {Object} Data to store |
|
||||
*/ |
|
||||
store: function(noStore){ |
|
||||
if(!c.stm) |
|
||||
return; |
|
||||
var obj = {}; |
|
||||
var keys = this.storageKey(); |
|
||||
if(keys.indexOf('html') >= 0) |
|
||||
obj.html = c.em.getHtml(); |
|
||||
if(keys.indexOf('components') >= 0) |
|
||||
obj.components = JSON.stringify(c.em.getComponents()); |
|
||||
if(!noStore) |
|
||||
c.stm.store(obj); |
|
||||
return obj; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns privately the main wrapper |
|
||||
* @return {Object} |
|
||||
* @private |
|
||||
*/ |
|
||||
getComponent : function(){ |
|
||||
return component; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns root component inside the canvas. Something like <body> inside HTML page |
|
||||
* The wrapper doesn't differ from the original Component Model |
|
||||
* @return {Component} Root Component |
|
||||
* @example |
|
||||
* // Change background of the wrapper and set some attribute
|
|
||||
* var wrapper = domComponents.getWrapper(); |
|
||||
* wrapper.set('style', {'background-color': 'red'}); |
|
||||
* wrapper.set('attributes', {'title': 'Hello!'}); |
|
||||
*/ |
|
||||
getWrapper: function(){ |
|
||||
return this.getComponent(); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns wrapper's children collection. Once you have the collection you can |
|
||||
* add other Components(Models) inside. Each component can have several nested |
|
||||
* components inside and you can nest them as more as you wish. |
|
||||
* @return {Components} Collection of components |
|
||||
* @example |
|
||||
* // Let's add some component
|
|
||||
* var wrapperChildren = domComponents.getComponents(); |
|
||||
* var comp1 = wrapperChildren.add({ |
|
||||
* style: { 'background-color': 'red'} |
|
||||
* }); |
|
||||
* var comp2 = wrapperChildren.add({ |
|
||||
* tagName: 'span', |
|
||||
* attributes: { title: 'Hello!'} |
|
||||
* }); |
|
||||
* // Now let's add an other one inside first component
|
|
||||
* // First we have to get the collection inside. Each
|
|
||||
* // component has 'components' property
|
|
||||
* var comp1Children = comp1.get('components'); |
|
||||
* // Procede as before. You could also add multiple objects
|
|
||||
* comp1Children.add([ |
|
||||
* { style: { 'background-color': 'blue'}}, |
|
||||
* { style: { height: '100px', width: '100px'}} |
|
||||
* ]); |
|
||||
* // Remove comp2
|
|
||||
* wrapperChildren.remove(comp2); |
|
||||
*/ |
|
||||
getComponents: function(){ |
|
||||
return this.getWrapper().get('components'); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new components to the wrapper's children. It's the same |
|
||||
* as 'domComponents.getComponents().add(...)' |
|
||||
* @param {Object|Component|Array<Object>} component Component/s to add |
|
||||
* @param {string} [component.tagName='div'] Tag name |
|
||||
* @param {string} [component.type=''] Type of the component. Available: ''(default), 'text', 'image' |
|
||||
* @param {boolean} [component.removable=true] If component is removable |
|
||||
* @param {boolean} [component.draggable=true] If is possible to move the component around the structure |
|
||||
* @param {boolean} [component.droppable=true] If is possible to drop inside other components |
|
||||
* @param {boolean} [component.badgable=true] If the badge is visible when the component is selected |
|
||||
* @param {boolean} [component.stylable=true] If is possible to style component |
|
||||
* @param {boolean} [component.copyable=true] If is possible to copy&paste the component |
|
||||
* @param {string} [component.content=''] String inside component |
|
||||
* @param {Object} [component.style={}] Style object |
|
||||
* @param {Object} [component.attributes={}] Attribute object |
|
||||
* @return {Component|Array<Component>} Component/s added |
|
||||
* @example |
|
||||
* // Example of a new component with some extra property
|
|
||||
* var comp1 = domComponents.addComponent({ |
|
||||
* tagName: 'div', |
|
||||
* removable: true, // Can't remove it
|
|
||||
* draggable: true, // Can't move it
|
|
||||
* copyable: true, // Disable copy/past
|
|
||||
* content: 'Content text', // Text inside component
|
|
||||
* style: { color: 'red'}, |
|
||||
* attributes: { title: 'here' } |
|
||||
* }); |
|
||||
*/ |
|
||||
addComponent: function(component){ |
|
||||
return this.getComponents().add(component); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Render and returns wrapper element with all components inside. |
|
||||
* Once the wrapper is rendered, and it's what happens when you init the editor, |
|
||||
* the all new components will be added automatically and property changes are all |
|
||||
* updated immediately |
|
||||
* @return {HTMLElement} |
|
||||
*/ |
|
||||
render: function(){ |
|
||||
return componentView.render().el; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Remove all components |
|
||||
* @return {this} |
|
||||
*/ |
|
||||
clear: function(){ |
|
||||
var c = this.getComponents(); |
|
||||
for(var i = 0, len = c.length; i < len; i++) |
|
||||
c.pop(); |
|
||||
return this; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Set components |
|
||||
* @param {Object|string} components HTML string or components model |
|
||||
* @return {this} |
|
||||
* @private |
|
||||
*/ |
|
||||
setComponents: function(components){ |
|
||||
this.clear().addComponent(components); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Add new component type |
|
||||
* @param {string} type |
|
||||
* @param {Object} methods |
|
||||
* @private |
|
||||
*/ |
|
||||
addType: function(type, methods) { |
|
||||
var compType = this.getType(type); |
|
||||
if(compType) { |
|
||||
compType.model = methods.model; |
|
||||
compType.view = methods.view; |
|
||||
} else { |
|
||||
methods.id = type; |
|
||||
defaultTypes.unshift(methods); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get component type |
|
||||
* @param {string} type |
|
||||
* @private |
|
||||
*/ |
|
||||
getType: function(type) { |
|
||||
var df = defaultTypes; |
|
||||
|
|
||||
for (var it = 0; it < df.length; it++) { |
|
||||
var dfId = df[it].id; |
|
||||
if(dfId == type) { |
|
||||
return df[it]; |
|
||||
} |
|
||||
} |
|
||||
return; |
|
||||
}, |
|
||||
|
|
||||
}; |
|
||||
}; |
|
||||
}); |
|
||||
@ -1,371 +1,370 @@ |
|||||
define(['backbone','./Components', 'SelectorManager/model/Selectors', 'TraitManager/model/Traits'], |
var Backbone = require('backbone'); |
||||
function (Backbone, Components, Selectors, Traits) { |
var Components = require('./Components'); |
||||
|
var Selectors = require('selector_manager/model/Selectors'); |
||||
|
var Traits = require('trait_manager/model/Traits'); |
||||
|
|
||||
return Backbone.Model.extend({ |
module.exports = Backbone.Model.extend({ |
||||
|
|
||||
defaults: { |
defaults: { |
||||
// HTML tag of the component
|
// HTML tag of the component
|
||||
tagName: 'div', |
tagName: 'div', |
||||
|
|
||||
// Component type, eg. 'text', 'image', 'video', etc.
|
// Component type, eg. 'text', 'image', 'video', etc.
|
||||
type: '', |
type: '', |
||||
|
|
||||
// True if the component is removable from the canvas
|
// True if the component is removable from the canvas
|
||||
removable: true, |
removable: true, |
||||
|
|
||||
// Indicates if it's possible to drag the component inside other
|
// Indicates if it's possible to drag the component inside other
|
||||
// Tip: Indicate an array of selectors where it could be dropped inside
|
// Tip: Indicate an array of selectors where it could be dropped inside
|
||||
draggable: true, |
draggable: true, |
||||
|
|
||||
// Indicates if it's possible to drop other components inside
|
// Indicates if it's possible to drop other components inside
|
||||
// Tip: Indicate an array of selectors which could be dropped inside
|
// Tip: Indicate an array of selectors which could be dropped inside
|
||||
droppable: true, |
droppable: true, |
||||
|
|
||||
// Set false if don't want to see the badge (with the name) over the component
|
// Set false if don't want to see the badge (with the name) over the component
|
||||
badgable: true, |
badgable: true, |
||||
|
|
||||
// True if it's possible to style it
|
// True if it's possible to style it
|
||||
// Tip: Indicate an array of CSS properties which is possible to style
|
// Tip: Indicate an array of CSS properties which is possible to style
|
||||
stylable: true, |
stylable: true, |
||||
|
|
||||
// Highlightable with 'dotted' style if true
|
// Highlightable with 'dotted' style if true
|
||||
highlightable: true, |
highlightable: true, |
||||
|
|
||||
// True if it's possible to clone the component
|
// True if it's possible to clone the component
|
||||
copyable: true, |
copyable: true, |
||||
|
|
||||
// Indicates if it's possible to resize the component (at the moment implemented only on Image Components)
|
// Indicates if it's possible to resize the component (at the moment implemented only on Image Components)
|
||||
resizable: false, |
resizable: false, |
||||
|
|
||||
// Allow to edit the content of the component (used on Text components)
|
// Allow to edit the content of the component (used on Text components)
|
||||
editable: false, |
editable: false, |
||||
|
|
||||
// Hide the component inside Layers
|
// Hide the component inside Layers
|
||||
hiddenLayer: false, |
hiddenLayer: false, |
||||
|
|
||||
// This property is used by the HTML exporter as void elements do not
|
// This property is used by the HTML exporter as void elements do not
|
||||
// have closing tag, eg. <br/>, <hr/>, etc.
|
// have closing tag, eg. <br/>, <hr/>, etc.
|
||||
void: false, |
void: false, |
||||
|
|
||||
// Indicates if the component is in some CSS state like ':hover', ':active', etc.
|
// Indicates if the component is in some CSS state like ':hover', ':active', etc.
|
||||
state: '', |
state: '', |
||||
|
|
||||
// State, eg. 'selected'
|
// State, eg. 'selected'
|
||||
status: '', |
status: '', |
||||
|
|
||||
// Content of the component (not escaped) which will be appended before children rendering
|
// Content of the component (not escaped) which will be appended before children rendering
|
||||
content: '', |
content: '', |
||||
|
|
||||
// Component related style
|
// Component related style
|
||||
style: {}, |
style: {}, |
||||
|
|
||||
// Key-value object of the component's attributes
|
// Key-value object of the component's attributes
|
||||
attributes: '', |
attributes: '', |
||||
|
|
||||
// Array of classes
|
// Array of classes
|
||||
classes: '', |
classes: '', |
||||
|
|
||||
// Component's javascript
|
// Component's javascript
|
||||
script: '', |
script: '', |
||||
|
|
||||
// Traits
|
// Traits
|
||||
traits: ['id', 'title'], |
traits: ['id', 'title'], |
||||
|
|
||||
/** |
/** |
||||
* Set an array of items to show up inside the toolbar (eg. move, clone, delete) |
* Set an array of items to show up inside the toolbar (eg. move, clone, delete) |
||||
* when the component is selected |
* when the component is selected |
||||
* toolbar: [{ |
* toolbar: [{ |
||||
* attributes: {class: 'fa fa-arrows'}, |
* attributes: {class: 'fa fa-arrows'}, |
||||
* command: 'tlb-move', |
* command: 'tlb-move', |
||||
* },{ |
* },{ |
||||
* attributes: {class: 'fa fa-clone'}, |
* attributes: {class: 'fa fa-clone'}, |
||||
* command: 'tlb-clone', |
* command: 'tlb-clone', |
||||
* }] |
* }] |
||||
*/ |
*/ |
||||
toolbar: null, |
toolbar: null, |
||||
|
|
||||
// TODO
|
// TODO
|
||||
previousModel: '', |
previousModel: '', |
||||
mirror: '', |
mirror: '', |
||||
}, |
}, |
||||
|
|
||||
initialize: function(o, opt) { |
initialize(o, opt) { |
||||
// Check void elements
|
// Check void elements
|
||||
if(opt && opt.config && opt.config.voidElements.indexOf(this.get('tagName')) >= 0) |
if(opt && opt.config && opt.config.voidElements.indexOf(this.get('tagName')) >= 0) |
||||
this.set('void', true); |
this.set('void', true); |
||||
|
|
||||
this.opt = opt; |
this.opt = opt; |
||||
this.sm = opt ? opt.sm || {} : {}; |
this.sm = opt ? opt.sm || {} : {}; |
||||
this.config = o || {}; |
this.config = o || {}; |
||||
this.defaultC = this.config.components || []; |
this.defaultC = this.config.components || []; |
||||
this.defaultCl = this.normalizeClasses(this.get('classes') || this.config.classes || []); |
this.defaultCl = this.normalizeClasses(this.get('classes') || this.config.classes || []); |
||||
this.components = new Components(this.defaultC, opt); |
this.components = new Components(this.defaultC, opt); |
||||
this.components.parent = this; |
this.components.parent = this; |
||||
this.listenTo(this, 'change:script', this.scriptUpdated); |
this.listenTo(this, 'change:script', this.scriptUpdated); |
||||
this.set('attributes', this.get('attributes') || {}); |
this.set('attributes', this.get('attributes') || {}); |
||||
this.set('components', this.components); |
this.set('components', this.components); |
||||
this.set('classes', new Selectors(this.defaultCl)); |
this.set('classes', new Selectors(this.defaultCl)); |
||||
var traits = new Traits(); |
var traits = new Traits(); |
||||
traits.setTarget(this); |
traits.setTarget(this); |
||||
traits.add(this.get('traits')); |
traits.add(this.get('traits')); |
||||
this.set('traits', traits); |
this.set('traits', traits); |
||||
this.initToolbar(); |
this.initToolbar(); |
||||
|
|
||||
// Normalize few properties from strings to arrays
|
// Normalize few properties from strings to arrays
|
||||
var toNormalize = ['stylable']; |
var toNormalize = ['stylable']; |
||||
toNormalize.forEach(function(name) { |
toNormalize.forEach(function(name) { |
||||
var value = this.get(name); |
var value = this.get(name); |
||||
|
|
||||
if (typeof value == 'string') { |
if (typeof value == 'string') { |
||||
var newValue = value.split(',').map(function(prop) { |
var newValue = value.split(',').map(prop => prop.trim()); |
||||
return prop.trim(); |
this.set(name, newValue); |
||||
}); |
} |
||||
this.set(name, newValue); |
}, this); |
||||
} |
|
||||
}, this); |
this.init(); |
||||
|
}, |
||||
this.init(); |
|
||||
}, |
/** |
||||
|
* Initialize callback |
||||
/** |
*/ |
||||
* Initialize callback |
init() {}, |
||||
*/ |
|
||||
init: function () {}, |
/** |
||||
|
* Script updated |
||||
/** |
*/ |
||||
* Script updated |
scriptUpdated() { |
||||
*/ |
this.set('scriptUpdated', 1); |
||||
scriptUpdated: function() { |
}, |
||||
this.set('scriptUpdated', 1); |
|
||||
}, |
/** |
||||
|
* Init toolbar |
||||
/** |
*/ |
||||
* Init toolbar |
initToolbar() { |
||||
*/ |
var model = this; |
||||
initToolbar: function () { |
if(!model.get('toolbar')) { |
||||
var model = this; |
var tb = []; |
||||
if(!model.get('toolbar')) { |
if(model.get('draggable')) { |
||||
var tb = []; |
tb.push({ |
||||
if(model.get('draggable')) { |
attributes: {class: 'fa fa-arrows'}, |
||||
tb.push({ |
command: 'tlb-move', |
||||
attributes: {class: 'fa fa-arrows'}, |
|
||||
command: 'tlb-move', |
|
||||
}); |
|
||||
} |
|
||||
if(model.get('copyable')) { |
|
||||
tb.push({ |
|
||||
attributes: {class: 'fa fa-clone'}, |
|
||||
command: 'tlb-clone', |
|
||||
}); |
|
||||
} |
|
||||
if(model.get('removable')) { |
|
||||
tb.push({ |
|
||||
attributes: {class: 'fa fa-trash-o'}, |
|
||||
command: 'tlb-delete', |
|
||||
}); |
|
||||
} |
|
||||
model.set('toolbar', tb); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Load traits |
|
||||
* @param {Array} traits |
|
||||
* @private |
|
||||
*/ |
|
||||
loadTraits: function(traits) { |
|
||||
var trt = new Traits(); |
|
||||
trt.setTarget(this); |
|
||||
trt.add(traits); |
|
||||
this.set('traits', trt); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Normalize input classes from array to array of objects |
|
||||
* @param {Array} arr |
|
||||
* @return {Array} |
|
||||
* @private |
|
||||
*/ |
|
||||
normalizeClasses: function(arr) { |
|
||||
var res = []; |
|
||||
|
|
||||
if(!this.sm.get) |
|
||||
return; |
|
||||
|
|
||||
var clm = this.sm.get('SelectorManager'); |
|
||||
if(!clm) |
|
||||
return; |
|
||||
|
|
||||
arr.forEach(function(val){ |
|
||||
var name = ''; |
|
||||
|
|
||||
if(typeof val === 'string') |
|
||||
name = val; |
|
||||
else |
|
||||
name = val.name; |
|
||||
|
|
||||
var model = clm.add(name); |
|
||||
res.push(model); |
|
||||
}); |
|
||||
return res; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Override original clone method |
|
||||
* @private |
|
||||
*/ |
|
||||
clone: function(reset) { |
|
||||
var attr = _.clone(this.attributes), |
|
||||
comp = this.get('components'), |
|
||||
traits = this.get('traits'), |
|
||||
cls = this.get('classes'); |
|
||||
attr.components = []; |
|
||||
attr.classes = []; |
|
||||
attr.traits = []; |
|
||||
|
|
||||
comp.each(function(md,i) { |
|
||||
attr.components[i] = md.clone(1); |
|
||||
}); |
|
||||
traits.each(function(md, i) { |
|
||||
attr.traits[i] = md.clone(); |
|
||||
}); |
}); |
||||
cls.each(function(md,i) { |
} |
||||
attr.classes[i] = md.get('name'); |
if(model.get('copyable')) { |
||||
|
tb.push({ |
||||
|
attributes: {class: 'fa fa-clone'}, |
||||
|
command: 'tlb-clone', |
||||
}); |
}); |
||||
|
} |
||||
attr.status = ''; |
if(model.get('removable')) { |
||||
attr.view = ''; |
tb.push({ |
||||
|
attributes: {class: 'fa fa-trash-o'}, |
||||
if(reset){ |
command: 'tlb-delete', |
||||
this.opt.collection = null; |
|
||||
} |
|
||||
|
|
||||
return new this.constructor(attr, this.opt); |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Get name of the component |
|
||||
* @return {string} |
|
||||
* @private |
|
||||
* */ |
|
||||
getName: function() { |
|
||||
if(!this.name){ |
|
||||
var id = this.cid.replace(/\D/g,''), |
|
||||
type = this.get('type'); |
|
||||
var tag = this.get('tagName'); |
|
||||
tag = tag == 'div' ? 'box' : tag; |
|
||||
tag = type ? type : tag; |
|
||||
this.name = tag.charAt(0).toUpperCase() + tag.slice(1); |
|
||||
} |
|
||||
return this.name; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Return HTML string of the component |
|
||||
* @param {Object} opts Options |
|
||||
* @return {string} HTML string |
|
||||
* @private |
|
||||
*/ |
|
||||
toHTML: function(opts) { |
|
||||
var code = ''; |
|
||||
var m = this; |
|
||||
var tag = m.get('tagName'), |
|
||||
sTag = m.get('void'), |
|
||||
attrId = ''; |
|
||||
// Build the string of attributes
|
|
||||
var strAttr = ''; |
|
||||
var attr = this.getAttrToHTML(); |
|
||||
for(var prop in attr){ |
|
||||
var val = attr[prop]; |
|
||||
strAttr += typeof val !== undefined && val !== '' ? |
|
||||
' ' + prop + '="' + val + '"' : ''; |
|
||||
} |
|
||||
// Build the string of classes
|
|
||||
var strCls = ''; |
|
||||
m.get('classes').each(function(m){ |
|
||||
strCls += ' ' + m.get('name'); |
|
||||
}); |
}); |
||||
strCls = strCls !== '' ? ' class="' + strCls.trim() + '"' : ''; |
} |
||||
|
model.set('toolbar', tb); |
||||
// If style is not empty I need an ID attached to the component
|
} |
||||
// TODO: need to refactor in case of 'ID Trait'
|
}, |
||||
if(!_.isEmpty(m.get('style'))) |
|
||||
attrId = ' id="' + m.cid + '" '; |
/** |
||||
|
* Load traits |
||||
|
* @param {Array} traits |
||||
|
* @private |
||||
|
*/ |
||||
|
loadTraits(traits) { |
||||
|
var trt = new Traits(); |
||||
|
trt.setTarget(this); |
||||
|
trt.add(traits); |
||||
|
this.set('traits', trt); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Normalize input classes from array to array of objects |
||||
|
* @param {Array} arr |
||||
|
* @return {Array} |
||||
|
* @private |
||||
|
*/ |
||||
|
normalizeClasses(arr) { |
||||
|
var res = []; |
||||
|
|
||||
|
if(!this.sm.get) |
||||
|
return; |
||||
|
|
||||
|
var clm = this.sm.get('SelectorManager'); |
||||
|
if(!clm) |
||||
|
return; |
||||
|
|
||||
|
arr.forEach(val => { |
||||
|
var name = ''; |
||||
|
|
||||
|
if(typeof val === 'string') |
||||
|
name = val; |
||||
|
else |
||||
|
name = val.name; |
||||
|
|
||||
|
var model = clm.add(name); |
||||
|
res.push(model); |
||||
|
}); |
||||
|
return res; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Override original clone method |
||||
|
* @private |
||||
|
*/ |
||||
|
clone(reset) { |
||||
|
var attr = _.clone(this.attributes), |
||||
|
comp = this.get('components'), |
||||
|
traits = this.get('traits'), |
||||
|
cls = this.get('classes'); |
||||
|
attr.components = []; |
||||
|
attr.classes = []; |
||||
|
attr.traits = []; |
||||
|
|
||||
|
comp.each((md, i) => { |
||||
|
attr.components[i] = md.clone(1); |
||||
|
}); |
||||
|
traits.each((md, i) => { |
||||
|
attr.traits[i] = md.clone(); |
||||
|
}); |
||||
|
cls.each((md, i) => { |
||||
|
attr.classes[i] = md.get('name'); |
||||
|
}); |
||||
|
|
||||
code += '<' + tag + strCls + attrId + strAttr + (sTag ? '/' : '') + '>' + m.get('content'); |
attr.status = ''; |
||||
|
attr.view = ''; |
||||
|
|
||||
|
if(reset){ |
||||
|
this.opt.collection = null; |
||||
|
} |
||||
|
|
||||
|
return new this.constructor(attr, this.opt); |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Get name of the component |
||||
|
* @return {string} |
||||
|
* @private |
||||
|
* */ |
||||
|
getName() { |
||||
|
if(!this.name){ |
||||
|
var id = this.cid.replace(/\D/g,''), |
||||
|
type = this.get('type'); |
||||
|
var tag = this.get('tagName'); |
||||
|
tag = tag == 'div' ? 'box' : tag; |
||||
|
tag = type ? type : tag; |
||||
|
this.name = tag.charAt(0).toUpperCase() + tag.slice(1); |
||||
|
} |
||||
|
return this.name; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Return HTML string of the component |
||||
|
* @param {Object} opts Options |
||||
|
* @return {string} HTML string |
||||
|
* @private |
||||
|
*/ |
||||
|
toHTML(opts) { |
||||
|
var code = ''; |
||||
|
var m = this; |
||||
|
var tag = m.get('tagName'), |
||||
|
sTag = m.get('void'), |
||||
|
attrId = ''; |
||||
|
// Build the string of attributes
|
||||
|
var strAttr = ''; |
||||
|
var attr = this.getAttrToHTML(); |
||||
|
for(var prop in attr){ |
||||
|
var val = attr[prop]; |
||||
|
strAttr += typeof val !== undefined && val !== '' ? |
||||
|
' ' + prop + '="' + val + '"' : ''; |
||||
|
} |
||||
|
// Build the string of classes
|
||||
|
var strCls = ''; |
||||
|
m.get('classes').each(m => { |
||||
|
strCls += ' ' + m.get('name'); |
||||
|
}); |
||||
|
strCls = strCls !== '' ? ' class="' + strCls.trim() + '"' : ''; |
||||
|
|
||||
m.get('components').each(function(m) { |
// If style is not empty I need an ID attached to the component
|
||||
code += m.toHTML(); |
// TODO: need to refactor in case of 'ID Trait'
|
||||
}); |
if(!_.isEmpty(m.get('style'))) |
||||
|
attrId = ' id="' + m.cid + '" '; |
||||
|
|
||||
if(!sTag) |
code += '<' + tag + strCls + attrId + strAttr + (sTag ? '/' : '') + '>' + m.get('content'); |
||||
code += '</'+tag+'>'; |
|
||||
|
|
||||
return code; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Returns object of attributes for HTML |
|
||||
* @return {Object} |
|
||||
* @private |
|
||||
*/ |
|
||||
getAttrToHTML: function() { |
|
||||
var attr = this.get('attributes') || {}; |
|
||||
delete attr.style; |
|
||||
return attr; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Return a shallow copy of the model's attributes for JSON |
|
||||
* stringification. |
|
||||
* @return {Object} |
|
||||
* @private |
|
||||
*/ |
|
||||
toJSON: function() { |
|
||||
var obj = Backbone.Model.prototype.toJSON.apply(this, arguments); |
|
||||
var scriptStr = this.getScriptString(); |
|
||||
|
|
||||
if (scriptStr) { |
|
||||
obj.script = scriptStr; |
|
||||
} |
|
||||
|
|
||||
return obj; |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* Return script in string format, cleans 'function() {..' from scripts |
|
||||
* if it's a function |
|
||||
* @param {string|Function} script |
|
||||
* @return {string} |
|
||||
* @private |
|
||||
*/ |
|
||||
getScriptString: function (script) { |
|
||||
var scr = script || this.get('script'); |
|
||||
|
|
||||
// Need to cast script functions to string
|
|
||||
if (typeof scr == 'function') { |
|
||||
var scrStr = scr.toString().trim(); |
|
||||
scrStr = scrStr.replace(/^function\s?\(\)\s?\{/, ''); |
|
||||
scrStr = scrStr.replace(/\}$/, ''); |
|
||||
scr = scrStr; |
|
||||
} |
|
||||
|
|
||||
return scr; |
|
||||
} |
|
||||
|
|
||||
},{ |
m.get('components').each(m => { |
||||
|
code += m.toHTML(); |
||||
|
}); |
||||
|
|
||||
/** |
if(!sTag) |
||||
* Detect if the passed element is a valid component. |
code += '</'+tag+'>'; |
||||
* In case the element is valid an object abstracted |
|
||||
* from the element will be returned |
return code; |
||||
* @param {HTMLElement} |
}, |
||||
* @return {Object} |
|
||||
* @private |
/** |
||||
*/ |
* Returns object of attributes for HTML |
||||
isComponent: function(el) { |
* @return {Object} |
||||
return {tagName: el.tagName ? el.tagName.toLowerCase() : ''}; |
* @private |
||||
}, |
*/ |
||||
|
getAttrToHTML() { |
||||
|
var attr = this.get('attributes') || {}; |
||||
|
delete attr.style; |
||||
|
return attr; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Return a shallow copy of the model's attributes for JSON |
||||
|
* stringification. |
||||
|
* @return {Object} |
||||
|
* @private |
||||
|
*/ |
||||
|
toJSON(...args) { |
||||
|
var obj = Backbone.Model.prototype.toJSON.apply(this, args); |
||||
|
var scriptStr = this.getScriptString(); |
||||
|
|
||||
|
if (scriptStr) { |
||||
|
obj.script = scriptStr; |
||||
|
} |
||||
|
|
||||
|
return obj; |
||||
|
}, |
||||
|
|
||||
|
/** |
||||
|
* Return script in string format, cleans 'function() {..' from scripts |
||||
|
* if it's a function |
||||
|
* @param {string|Function} script |
||||
|
* @return {string} |
||||
|
* @private |
||||
|
*/ |
||||
|
getScriptString(script) { |
||||
|
var scr = script || this.get('script'); |
||||
|
|
||||
|
// Need to cast script functions to string
|
||||
|
if (typeof scr == 'function') { |
||||
|
var scrStr = scr.toString().trim(); |
||||
|
scrStr = scrStr.replace(/^function\s?\(\)\s?\{/, ''); |
||||
|
scrStr = scrStr.replace(/\}$/, ''); |
||||
|
scr = scrStr; |
||||
|
} |
||||
|
|
||||
|
return scr; |
||||
|
} |
||||
|
|
||||
|
},{ |
||||
|
|
||||
|
/** |
||||
|
* Detect if the passed element is a valid component. |
||||
|
* In case the element is valid an object abstracted |
||||
|
* from the element will be returned |
||||
|
* @param {HTMLElement} |
||||
|
* @return {Object} |
||||
|
* @private |
||||
|
*/ |
||||
|
isComponent(el) { |
||||
|
return {tagName: el.tagName ? el.tagName.toLowerCase() : ''}; |
||||
|
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,103 +1,101 @@ |
|||||
define(['./Component'], |
var Component = require('./Component'); |
||||
function (Component) { |
|
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
type: 'image', |
type: 'image', |
||||
tagName: 'img', |
tagName: 'img', |
||||
src: '', |
src: '', |
||||
void: 1, |
void: 1, |
||||
droppable: false, |
droppable: false, |
||||
resizable: true, |
resizable: true, |
||||
traits: ['alt'] |
traits: ['alt'] |
||||
}), |
}), |
||||
|
|
||||
initialize: function(o, opt) { |
initialize(o, opt) { |
||||
Component.prototype.initialize.apply(this, arguments); |
Component.prototype.initialize.apply(this, arguments); |
||||
var attr = this.get('attributes'); |
var attr = this.get('attributes'); |
||||
if(attr.src) |
if(attr.src) |
||||
this.set('src', attr.src); |
this.set('src', attr.src); |
||||
}, |
}, |
||||
|
|
||||
initToolbar: function() { |
initToolbar(...args) { |
||||
Component.prototype.initToolbar.apply(this, arguments); |
Component.prototype.initToolbar.apply(this, args); |
||||
|
|
||||
if (this.sm && this.sm.get) { |
if (this.sm && this.sm.get) { |
||||
var cmd = this.sm.get('Commands'); |
var cmd = this.sm.get('Commands'); |
||||
var cmdName = 'image-editor'; |
var cmdName = 'image-editor'; |
||||
|
|
||||
// Add Image Editor button only if the default command exists
|
// Add Image Editor button only if the default command exists
|
||||
if (cmd.has(cmdName)) { |
if (cmd.has(cmdName)) { |
||||
var tb = this.get('toolbar'); |
var tb = this.get('toolbar'); |
||||
tb.push({ |
tb.push({ |
||||
attributes: {class: 'fa fa-pencil'}, |
attributes: {class: 'fa fa-pencil'}, |
||||
command: cmdName, |
command: cmdName, |
||||
}); |
}); |
||||
this.set('toolbar', tb); |
this.set('toolbar', tb); |
||||
} |
} |
||||
} |
} |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Returns object of attributes for HTML |
* Returns object of attributes for HTML |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getAttrToHTML: function() { |
getAttrToHTML(...args) { |
||||
var attr = Component.prototype.getAttrToHTML.apply(this, arguments); |
var attr = Component.prototype.getAttrToHTML.apply(this, args); |
||||
delete attr.onmousedown; |
delete attr.onmousedown; |
||||
var src = this.get('src'); |
var src = this.get('src'); |
||||
if(src) |
if(src) |
||||
attr.src = src; |
attr.src = src; |
||||
return attr; |
return attr; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Parse uri |
* Parse uri |
||||
* @param {string} uri |
* @param {string} uri |
||||
* @return {object} |
* @return {object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
parseUri: function(uri) { |
parseUri(uri) { |
||||
var el = document.createElement('a'); |
var el = document.createElement('a'); |
||||
el.href = uri; |
el.href = uri; |
||||
var query = {}; |
var query = {}; |
||||
var qrs = el.search.substring(1).split('&'); |
var qrs = el.search.substring(1).split('&'); |
||||
for (var i = 0; i < qrs.length; i++) { |
for (var i = 0; i < qrs.length; i++) { |
||||
var pair = qrs[i].split('='); |
var pair = qrs[i].split('='); |
||||
var name = decodeURIComponent(pair[0]); |
var name = decodeURIComponent(pair[0]); |
||||
if(name) |
if(name) |
||||
query[name] = decodeURIComponent(pair[1]); |
query[name] = decodeURIComponent(pair[1]); |
||||
} |
} |
||||
return { |
return { |
||||
hostname: el.hostname, |
hostname: el.hostname, |
||||
pathname: el.pathname, |
pathname: el.pathname, |
||||
protocol: el.protocol, |
protocol: el.protocol, |
||||
search: el.search, |
search: el.search, |
||||
hash: el.hash, |
hash: el.hash, |
||||
port: el.port, |
port: el.port, |
||||
query: query, |
query, |
||||
}; |
}; |
||||
}, |
}, |
||||
|
|
||||
},{ |
},{ |
||||
|
|
||||
/** |
/** |
||||
* Detect if the passed element is a valid component. |
* Detect if the passed element is a valid component. |
||||
* In case the element is valid an object abstracted |
* In case the element is valid an object abstracted |
||||
* from the element will be returned |
* from the element will be returned |
||||
* @param {HTMLElement} |
* @param {HTMLElement} |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
isComponent: function(el) { |
isComponent(el) { |
||||
var result = ''; |
var result = ''; |
||||
if(el.tagName == 'IMG'){ |
if(el.tagName == 'IMG'){ |
||||
result = {type: 'image'}; |
result = {type: 'image'}; |
||||
} |
} |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,42 +1,40 @@ |
|||||
define(['./ComponentText'], |
var Component = require('./ComponentText'); |
||||
function (Component) { |
|
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
type: 'link', |
type: 'link', |
||||
tagName: 'a', |
tagName: 'a', |
||||
traits: ['title', 'href', 'target'], |
traits: ['title', 'href', 'target'], |
||||
}), |
}), |
||||
|
|
||||
/** |
/** |
||||
* Returns object of attributes for HTML |
* Returns object of attributes for HTML |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getAttrToHTML: function() { |
getAttrToHTML(...args) { |
||||
var attr = Component.prototype.getAttrToHTML.apply(this, arguments); |
var attr = Component.prototype.getAttrToHTML.apply(this, args); |
||||
delete attr.onmousedown; |
delete attr.onmousedown; |
||||
return attr; |
return attr; |
||||
}, |
}, |
||||
|
|
||||
},{ |
},{ |
||||
|
|
||||
/** |
/** |
||||
* Detect if the passed element is a valid component. |
* Detect if the passed element is a valid component. |
||||
* In case the element is valid an object abstracted |
* In case the element is valid an object abstracted |
||||
* from the element will be returned |
* from the element will be returned |
||||
* @param {HTMLElement} |
* @param {HTMLElement} |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
isComponent: function(el) { |
isComponent(el) { |
||||
var result = ''; |
var result = ''; |
||||
if(el.tagName == 'A'){ |
if(el.tagName == 'A'){ |
||||
result = {type: 'link'}; |
result = {type: 'link'}; |
||||
} |
} |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,108 +1,107 @@ |
|||||
define(['./ComponentImage', './Component'], |
var Component = require('./ComponentImage'); |
||||
function (Component, OComponent) { |
var OComponent = require('./Component'); |
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
type: 'map', |
type: 'map', |
||||
void: 0, |
void: 0, |
||||
mapUrl: 'https://maps.google.com/maps', |
mapUrl: 'https://maps.google.com/maps', |
||||
tagName: 'iframe', |
tagName: 'iframe', |
||||
mapType: 'q', |
mapType: 'q', |
||||
address: '', |
address: '', |
||||
zoom: '1', |
zoom: '1', |
||||
attributes: {frameborder: 0}, |
attributes: {frameborder: 0}, |
||||
toolbar: OComponent.prototype.defaults.toolbar, |
toolbar: OComponent.prototype.defaults.toolbar, |
||||
traits: [{ |
traits: [{ |
||||
label: 'Address', |
label: 'Address', |
||||
name: 'address', |
name: 'address', |
||||
placeholder: 'eg. London, UK', |
placeholder: 'eg. London, UK', |
||||
changeProp: 1, |
changeProp: 1, |
||||
},{ |
},{ |
||||
type: 'select', |
type: 'select', |
||||
label: 'Map type', |
label: 'Map type', |
||||
name: 'mapType', |
name: 'mapType', |
||||
changeProp: 1, |
changeProp: 1, |
||||
options: [ |
options: [ |
||||
{value: 'q', name: 'Roadmap'}, |
{value: 'q', name: 'Roadmap'}, |
||||
{value: 'w', name: 'Satellite'} |
{value: 'w', name: 'Satellite'} |
||||
] |
] |
||||
},{ |
},{ |
||||
label: 'Zoom', |
label: 'Zoom', |
||||
name: 'zoom', |
name: 'zoom', |
||||
type: 'range', |
type: 'range', |
||||
min: '1', |
min: '1', |
||||
max: '20', |
max: '20', |
||||
changeProp: 1, |
changeProp: 1, |
||||
}], |
}], |
||||
}), |
}), |
||||
|
|
||||
|
|
||||
initialize: function(o, opt) { |
initialize(o, opt) { |
||||
if(this.get('src')) |
if(this.get('src')) |
||||
this.parseFromSrc(); |
this.parseFromSrc(); |
||||
else |
else |
||||
this.updateSrc(); |
this.updateSrc(); |
||||
Component.prototype.initialize.apply(this, arguments); |
Component.prototype.initialize.apply(this, arguments); |
||||
this.listenTo(this, 'change:address change:zoom change:mapType', this.updateSrc); |
this.listenTo(this, 'change:address change:zoom change:mapType', this.updateSrc); |
||||
}, |
}, |
||||
|
|
||||
updateSrc: function() { |
updateSrc() { |
||||
this.set('src', this.getMapUrl()); |
this.set('src', this.getMapUrl()); |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Returns url of the map |
* Returns url of the map |
||||
* @return {string} |
* @return {string} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
getMapUrl: function() { |
getMapUrl() { |
||||
var md = this; |
var md = this; |
||||
var addr = md.get('address'); |
var addr = md.get('address'); |
||||
var zoom = md.get('zoom'); |
var zoom = md.get('zoom'); |
||||
var type = md.get('mapType'); |
var type = md.get('mapType'); |
||||
var size = ''; |
var size = ''; |
||||
addr = addr ? '&q=' + addr : ''; |
addr = addr ? '&q=' + addr : ''; |
||||
zoom = zoom ? '&z=' + zoom : ''; |
zoom = zoom ? '&z=' + zoom : ''; |
||||
type = type ? '&t=' + type : ''; |
type = type ? '&t=' + type : ''; |
||||
var result = md.get('mapUrl')+'?' + addr + zoom + type; |
var result = md.get('mapUrl')+'?' + addr + zoom + type; |
||||
result += '&output=embed'; |
result += '&output=embed'; |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
/** |
/** |
||||
* Set attributes by src string |
* Set attributes by src string |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
parseFromSrc: function() { |
parseFromSrc() { |
||||
var uri = this.parseUri(this.get('src')); |
var uri = this.parseUri(this.get('src')); |
||||
var qr = uri.query; |
var qr = uri.query; |
||||
if(qr.q) |
if(qr.q) |
||||
this.set('address', qr.q); |
this.set('address', qr.q); |
||||
if(qr.z) |
if(qr.z) |
||||
this.set('zoom', qr.z); |
this.set('zoom', qr.z); |
||||
if(qr.t) |
if(qr.t) |
||||
this.set('mapType', qr.t); |
this.set('mapType', qr.t); |
||||
}, |
}, |
||||
|
|
||||
},{ |
},{ |
||||
|
|
||||
/** |
/** |
||||
* Detect if the passed element is a valid component. |
* Detect if the passed element is a valid component. |
||||
* In case the element is valid an object abstracted |
* In case the element is valid an object abstracted |
||||
* from the element will be returned |
* from the element will be returned |
||||
* @param {HTMLElement} |
* @param {HTMLElement} |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
isComponent: function(el) { |
isComponent(el) { |
||||
var result = ''; |
var result = ''; |
||||
if(el.tagName == 'IFRAME' && |
if(el.tagName == 'IFRAME' && |
||||
/maps\.google\.com/.test(el.src) ){ |
/maps\.google\.com/.test(el.src) ){ |
||||
result = {type: 'map', src: el.src}; |
result = {type: 'map', src: el.src}; |
||||
} |
} |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,29 +1,27 @@ |
|||||
define(['./Component'], |
var Component = require('./Component'); |
||||
function (Component) { |
|
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
type: 'script', |
type: 'script', |
||||
droppable: false, |
droppable: false, |
||||
draggable: false, |
draggable: false, |
||||
hiddenLayer: true, |
hiddenLayer: true, |
||||
}), |
}), |
||||
|
|
||||
}, { |
}, { |
||||
|
|
||||
isComponent: function(el) { |
isComponent(el) { |
||||
if (el.tagName == 'SCRIPT') { |
if (el.tagName == 'SCRIPT') { |
||||
var result = {type: 'script'}; |
var result = {type: 'script'}; |
||||
|
|
||||
if (el.src) { |
if (el.src) { |
||||
result.src = el.src; |
result.src = el.src; |
||||
result.onload = el.onload; |
result.onload = el.onload; |
||||
} |
} |
||||
|
|
||||
return result; |
return result; |
||||
} |
} |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,91 +1,89 @@ |
|||||
define(['./Component'], |
var Component = require('./Component'); |
||||
function (Component) { |
|
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
type: 'table', |
type: 'table', |
||||
tagName: 'table', |
tagName: 'table', |
||||
droppable: ['tr', 'tbody', 'thead', 'tfoot'], |
droppable: ['tr', 'tbody', 'thead', 'tfoot'], |
||||
columns: 3, |
columns: 3, |
||||
rows: 2, |
rows: 2, |
||||
/* |
/* |
||||
traits: [{ |
traits: [{ |
||||
label: 'Columns', |
label: 'Columns', |
||||
name: 'columns', |
name: 'columns', |
||||
changeProp: 1, |
changeProp: 1, |
||||
},{ |
},{ |
||||
label: 'Rows', |
label: 'Rows', |
||||
name: 'rows', |
name: 'rows', |
||||
changeProp: 1, |
changeProp: 1, |
||||
}] |
}] |
||||
*/ |
*/ |
||||
}), |
}), |
||||
|
|
||||
initialize: function(o, opt) { |
initialize(o, opt) { |
||||
Component.prototype.initialize.apply(this, arguments); |
Component.prototype.initialize.apply(this, arguments); |
||||
var components = this.get('components'); |
var components = this.get('components'); |
||||
var rows = this.get('rows'); |
var rows = this.get('rows'); |
||||
var columns = this.get('columns'); |
var columns = this.get('columns'); |
||||
|
|
||||
// Init components if empty
|
// Init components if empty
|
||||
if(!components.length){ |
if(!components.length){ |
||||
var rowsToAdd = []; |
var rowsToAdd = []; |
||||
|
|
||||
while(rows--){ |
while(rows--){ |
||||
var columnsToAdd = []; |
var columnsToAdd = []; |
||||
var clm = columns; |
var clm = columns; |
||||
|
|
||||
while (clm--) { |
while (clm--) { |
||||
columnsToAdd.push({ |
columnsToAdd.push({ |
||||
type: 'cell', |
type: 'cell', |
||||
classes: ['cell'] |
classes: ['cell'] |
||||
}); |
}); |
||||
} |
} |
||||
|
|
||||
rowsToAdd.push({ |
rowsToAdd.push({ |
||||
type: 'row', |
type: 'row', |
||||
classes: ['row'], |
classes: ['row'], |
||||
components: columnsToAdd |
components: columnsToAdd |
||||
}); |
}); |
||||
} |
} |
||||
components.add(rowsToAdd); |
components.add(rowsToAdd); |
||||
} |
} |
||||
|
|
||||
// Clean table from non rows
|
// Clean table from non rows
|
||||
var rowsColl = []; |
var rowsColl = []; |
||||
components.each(function(model){ |
components.each(model => { |
||||
if(model.get('type') != 'row'){ |
if(model.get('type') != 'row'){ |
||||
model.get('components').each(function(row) { |
model.get('components').each(row => { |
||||
if(row.get('type') == 'row'){ |
if(row.get('type') == 'row'){ |
||||
row.collection = components; |
row.collection = components; |
||||
rowsColl.push(row); |
rowsColl.push(row); |
||||
} |
} |
||||
}); |
}); |
||||
}else{ |
}else{ |
||||
rowsColl.push(model); |
rowsColl.push(model); |
||||
} |
} |
||||
}); |
}); |
||||
components.reset(rowsColl); |
components.reset(rowsColl); |
||||
}, |
}, |
||||
|
|
||||
},{ |
},{ |
||||
|
|
||||
/** |
/** |
||||
* Detect if the passed element is a valid component. |
* Detect if the passed element is a valid component. |
||||
* In case the element is valid an object abstracted |
* In case the element is valid an object abstracted |
||||
* from the element will be returned |
* from the element will be returned |
||||
* @param {HTMLElement} |
* @param {HTMLElement} |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
isComponent: function(el) { |
isComponent(el) { |
||||
var result = ''; |
var result = ''; |
||||
if(el.tagName == 'TABLE'){ |
if(el.tagName == 'TABLE'){ |
||||
result = {type: 'table'}; |
result = {type: 'table'}; |
||||
} |
} |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,35 +1,33 @@ |
|||||
define(['./Component'], |
var Component = require('./Component'); |
||||
function (Component) { |
|
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
type: 'cell', |
type: 'cell', |
||||
tagName: 'td', |
tagName: 'td', |
||||
draggable: ['tr'], |
draggable: ['tr'], |
||||
}), |
}), |
||||
|
|
||||
},{ |
},{ |
||||
|
|
||||
/** |
/** |
||||
* Detect if the passed element is a valid component. |
* Detect if the passed element is a valid component. |
||||
* In case the element is valid an object abstracted |
* In case the element is valid an object abstracted |
||||
* from the element will be returned |
* from the element will be returned |
||||
* @param {HTMLElement} |
* @param {HTMLElement} |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
isComponent: function(el) { |
isComponent(el) { |
||||
var result = ''; |
var result = ''; |
||||
var tag = el.tagName; |
var tag = el.tagName; |
||||
if(tag == 'TD' || tag == 'TH'){ |
if(tag == 'TD' || tag == 'TH'){ |
||||
result = { |
result = { |
||||
type: 'cell', |
type: 'cell', |
||||
tagName: tag.toLowerCase() |
tagName: tag.toLowerCase() |
||||
}; |
}; |
||||
} |
} |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,46 +1,44 @@ |
|||||
define(['./Component'], |
var Component = require('./Component'); |
||||
function (Component) { |
|
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
type: 'row', |
type: 'row', |
||||
tagName: 'tr', |
tagName: 'tr', |
||||
draggable: ['table', 'tbody', 'thead'], |
draggable: ['table', 'tbody', 'thead'], |
||||
droppable: ['th', 'td'] |
droppable: ['th', 'td'] |
||||
}), |
}), |
||||
|
|
||||
initialize: function(o, opt) { |
initialize(o, opt) { |
||||
Component.prototype.initialize.apply(this, arguments); |
Component.prototype.initialize.apply(this, arguments); |
||||
|
|
||||
// Clean the row from non cell components
|
// Clean the row from non cell components
|
||||
var cells = []; |
var cells = []; |
||||
var components = this.get('components'); |
var components = this.get('components'); |
||||
components.each(function(model){ |
components.each(model => { |
||||
if(model.get('type') == 'cell'){ |
if(model.get('type') == 'cell'){ |
||||
cells.push(model); |
cells.push(model); |
||||
} |
} |
||||
}); |
}); |
||||
components.reset(cells); |
components.reset(cells); |
||||
} |
} |
||||
|
|
||||
},{ |
},{ |
||||
|
|
||||
/** |
/** |
||||
* Detect if the passed element is a valid component. |
* Detect if the passed element is a valid component. |
||||
* In case the element is valid an object abstracted |
* In case the element is valid an object abstracted |
||||
* from the element will be returned |
* from the element will be returned |
||||
* @param {HTMLElement} |
* @param {HTMLElement} |
||||
* @return {Object} |
* @return {Object} |
||||
* @private |
* @private |
||||
*/ |
*/ |
||||
isComponent: function(el) { |
isComponent(el) { |
||||
var result = ''; |
var result = ''; |
||||
if(el.tagName == 'TR'){ |
if(el.tagName == 'TR'){ |
||||
result = {type: 'row'}; |
result = {type: 'row'}; |
||||
} |
} |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,13 +1,11 @@ |
|||||
define(['./Component'], |
var Component = require('./Component'); |
||||
function (Component) { |
|
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
type: 'text', |
type: 'text', |
||||
droppable: false, |
droppable: false, |
||||
editable: true, |
editable: true, |
||||
}), |
}), |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
@ -1,29 +1,27 @@ |
|||||
define(['./Component'], |
var Component = require('./Component'); |
||||
function (Component) { |
|
||||
|
|
||||
return Component.extend({ |
module.exports = Component.extend({ |
||||
|
|
||||
defaults: _.extend({}, Component.prototype.defaults, { |
defaults: _.extend({}, Component.prototype.defaults, { |
||||
droppable: false, |
droppable: false, |
||||
editable: true, |
editable: true, |
||||
}), |
}), |
||||
|
|
||||
toHTML: function() { |
toHTML() { |
||||
return this.get('content'); |
return this.get('content'); |
||||
}, |
}, |
||||
|
|
||||
}, { |
}, { |
||||
|
|
||||
isComponent: function(el) { |
isComponent(el) { |
||||
var result = ''; |
var result = ''; |
||||
if(el.nodeType === 3){ |
if(el.nodeType === 3){ |
||||
result = { |
result = { |
||||
type: 'textnode', |
type: 'textnode', |
||||
content: el.textContent |
content: el.textContent |
||||
}; |
}; |
||||
} |
} |
||||
return result; |
return result; |
||||
}, |
}, |
||||
|
|
||||
}); |
|
||||
}); |
}); |
||||
|
|||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue