mirror of https://github.com/artf/grapesjs.git
10 changed files with 294 additions and 266 deletions
File diff suppressed because one or more lines are too long
@ -1,97 +1,97 @@ |
|||
define(['./Component'], |
|||
function (Component) { |
|||
function (Component) { |
|||
|
|||
return Component.extend({ |
|||
return Component.extend({ |
|||
|
|||
defaults: _.extend({}, Component.prototype.defaults, { |
|||
type: 'image', |
|||
tagName: 'img', |
|||
src: '', |
|||
void: 1, |
|||
droppable: false, |
|||
resizable: true, |
|||
traits: ['alt'], |
|||
toolbar: [{ |
|||
attributes: {class: 'fa fa-arrows'}, |
|||
command: 'tlb-move', |
|||
},{ |
|||
attributes: {class: 'fa fa-clone'}, |
|||
command: 'tlb-clone', |
|||
},{ |
|||
attributes: {class: 'fa fa-pencil'}, |
|||
command: 'tlb-edit', |
|||
},{ |
|||
attributes: {class: 'fa fa-trash-o'}, |
|||
command: 'tlb-delete', |
|||
}], |
|||
}), |
|||
defaults: _.extend({}, Component.prototype.defaults, { |
|||
type: 'image', |
|||
tagName: 'img', |
|||
src: '', |
|||
void: 1, |
|||
droppable: false, |
|||
resizable: true, |
|||
traits: ['alt'], |
|||
toolbar: [{ |
|||
attributes: {class: 'fa fa-arrows'}, |
|||
command: 'tlb-move', |
|||
},{ |
|||
attributes: {class: 'fa fa-clone'}, |
|||
command: 'tlb-clone', |
|||
},{ |
|||
attributes: {class: 'fa fa-pencil'}, |
|||
command: 'tlb-edit', |
|||
},{ |
|||
attributes: {class: 'fa fa-trash-o'}, |
|||
command: 'tlb-delete', |
|||
}], |
|||
}), |
|||
|
|||
initialize: function(o, opt) { |
|||
Component.prototype.initialize.apply(this, arguments); |
|||
var attr = this.get('attributes'); |
|||
if(attr.src) |
|||
this.set('src', attr.src); |
|||
}, |
|||
initialize: function(o, opt) { |
|||
Component.prototype.initialize.apply(this, arguments); |
|||
var attr = this.get('attributes'); |
|||
if(attr.src) |
|||
this.set('src', attr.src); |
|||
}, |
|||
|
|||
/** |
|||
* Returns object of attributes for HTML |
|||
* @return {Object} |
|||
* @private |
|||
*/ |
|||
getAttrToHTML: function() { |
|||
var attr = Component.prototype.getAttrToHTML.apply(this, arguments); |
|||
delete attr.onmousedown; |
|||
var src = this.get('src'); |
|||
if(src) |
|||
attr.src = src; |
|||
return attr; |
|||
}, |
|||
/** |
|||
* Returns object of attributes for HTML |
|||
* @return {Object} |
|||
* @private |
|||
*/ |
|||
getAttrToHTML: function() { |
|||
var attr = Component.prototype.getAttrToHTML.apply(this, arguments); |
|||
delete attr.onmousedown; |
|||
var src = this.get('src'); |
|||
if(src) |
|||
attr.src = src; |
|||
return attr; |
|||
}, |
|||
|
|||
/** |
|||
* Parse uri |
|||
* @param {string} uri |
|||
* @return {object} |
|||
* @private |
|||
*/ |
|||
parseUri: function(uri) { |
|||
var el = document.createElement('a'); |
|||
el.href = uri; |
|||
var query = {}; |
|||
var qrs = el.search.substring(1).split('&'); |
|||
for (var i = 0; i < qrs.length; i++) { |
|||
var pair = qrs[i].split('='); |
|||
var name = decodeURIComponent(pair[0]); |
|||
if(name) |
|||
query[name] = decodeURIComponent(pair[1]); |
|||
} |
|||
return { |
|||
hostname: el.hostname, |
|||
pathname: el.pathname, |
|||
protocol: el.protocol, |
|||
search: el.search, |
|||
hash: el.hash, |
|||
port: el.port, |
|||
query: query, |
|||
}; |
|||
}, |
|||
/** |
|||
* Parse uri |
|||
* @param {string} uri |
|||
* @return {object} |
|||
* @private |
|||
*/ |
|||
parseUri: function(uri) { |
|||
var el = document.createElement('a'); |
|||
el.href = uri; |
|||
var query = {}; |
|||
var qrs = el.search.substring(1).split('&'); |
|||
for (var i = 0; i < qrs.length; i++) { |
|||
var pair = qrs[i].split('='); |
|||
var name = decodeURIComponent(pair[0]); |
|||
if(name) |
|||
query[name] = decodeURIComponent(pair[1]); |
|||
} |
|||
return { |
|||
hostname: el.hostname, |
|||
pathname: el.pathname, |
|||
protocol: el.protocol, |
|||
search: el.search, |
|||
hash: el.hash, |
|||
port: el.port, |
|||
query: query, |
|||
}; |
|||
}, |
|||
|
|||
},{ |
|||
},{ |
|||
|
|||
/** |
|||
* 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: function(el) { |
|||
var result = ''; |
|||
if(el.tagName == 'IMG'){ |
|||
result = {type: 'image'}; |
|||
} |
|||
return result; |
|||
}, |
|||
/** |
|||
* 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: function(el) { |
|||
var result = ''; |
|||
if(el.tagName == 'IMG'){ |
|||
result = {type: 'image'}; |
|||
} |
|||
return result; |
|||
}, |
|||
|
|||
}); |
|||
}); |
|||
}); |
|||
|
|||
@ -1,72 +1,72 @@ |
|||
define(['backbone', './ComponentView'], |
|||
function (Backbone, ComponentView) { |
|||
function (Backbone, ComponentView) { |
|||
|
|||
return ComponentView.extend({ |
|||
return ComponentView.extend({ |
|||
|
|||
tagName: 'img', |
|||
tagName: 'img', |
|||
|
|||
events: { |
|||
'dblclick': 'openModal', |
|||
'click': 'initResize', |
|||
}, |
|||
events: { |
|||
'dblclick': 'openModal', |
|||
'click': 'initResize', |
|||
}, |
|||
|
|||
initialize: function(o) { |
|||
ComponentView.prototype.initialize.apply(this, arguments); |
|||
this.listenTo(this.model, 'change:src', this.updateSrc); |
|||
this.listenTo(this.model, 'dblclick active', this.openModal); |
|||
this.classEmpty = this.ppfx + 'plh-image'; |
|||
initialize: function(o) { |
|||
ComponentView.prototype.initialize.apply(this, arguments); |
|||
this.listenTo(this.model, 'change:src', this.updateSrc); |
|||
this.listenTo(this.model, 'dblclick active', this.openModal); |
|||
this.classEmpty = this.ppfx + 'plh-image'; |
|||
|
|||
if(this.config.modal) |
|||
this.modal = this.config.modal; |
|||
if(this.config.modal) |
|||
this.modal = this.config.modal; |
|||
|
|||
if(this.config.am) |
|||
this.am = this.config.am; |
|||
}, |
|||
if(this.config.am) |
|||
this.am = this.config.am; |
|||
}, |
|||
|
|||
/** |
|||
* Update src attribute |
|||
* @private |
|||
* */ |
|||
updateSrc: function() { |
|||
var src = this.model.get("src"); |
|||
this.$el.attr('src', src); |
|||
if(!src) |
|||
this.$el.addClass(this.classEmpty); |
|||
else |
|||
this.$el.removeClass(this.classEmpty); |
|||
}, |
|||
/** |
|||
* Update src attribute |
|||
* @private |
|||
* */ |
|||
updateSrc: function() { |
|||
var src = this.model.get("src"); |
|||
this.$el.attr('src', src); |
|||
if(!src) |
|||
this.$el.addClass(this.classEmpty); |
|||
else |
|||
this.$el.removeClass(this.classEmpty); |
|||
}, |
|||
|
|||
/** |
|||
* Open dialog for image changing |
|||
* @param {Object} e Event |
|||
* @private |
|||
* */ |
|||
openModal: function(e) { |
|||
var em = this.opts.config.em; |
|||
var editor = em ? em.get('Editor') : ''; |
|||
/** |
|||
* Open dialog for image changing |
|||
* @param {Object} e Event |
|||
* @private |
|||
* */ |
|||
openModal: function(e) { |
|||
var em = this.opts.config.em; |
|||
var editor = em ? em.get('Editor') : ''; |
|||
|
|||
if(editor) { |
|||
editor.runCommand('open-assets', { |
|||
target: this.model, |
|||
onSelect: function() { |
|||
editor.Modal.close(); |
|||
editor.AssetManager.setTarget(null); |
|||
} |
|||
}); |
|||
} |
|||
}, |
|||
if(editor) { |
|||
editor.runCommand('open-assets', { |
|||
target: this.model, |
|||
onSelect: function() { |
|||
editor.Modal.close(); |
|||
editor.AssetManager.setTarget(null); |
|||
} |
|||
}); |
|||
} |
|||
}, |
|||
|
|||
render: function() { |
|||
this.updateAttributes(); |
|||
this.updateClasses(); |
|||
render: function() { |
|||
this.updateAttributes(); |
|||
this.updateClasses(); |
|||
|
|||
var actCls = this.$el.attr('class') || ''; |
|||
if(!this.model.get('src')) |
|||
this.$el.attr('class', (actCls + ' ' + this.classEmpty).trim()); |
|||
var actCls = this.$el.attr('class') || ''; |
|||
if(!this.model.get('src')) |
|||
this.$el.attr('class', (actCls + ' ' + this.classEmpty).trim()); |
|||
|
|||
// Avoid strange behaviours while try to drag
|
|||
this.$el.attr('onmousedown', 'return false'); |
|||
return this; |
|||
}, |
|||
}); |
|||
// Avoid strange behaviours while try to drag
|
|||
this.$el.attr('onmousedown', 'return false'); |
|||
return this; |
|||
}, |
|||
}); |
|||
}); |
|||
|
|||
@ -1,96 +1,101 @@ |
|||
define(['backbone', './ComponentView'], |
|||
function (Backbone, ComponentView) { |
|||
|
|||
return ComponentView.extend({ |
|||
|
|||
events: { |
|||
'dblclick': 'enableEditing', |
|||
'change': 'parseRender', |
|||
}, |
|||
|
|||
initialize: function(o) { |
|||
ComponentView.prototype.initialize.apply(this, arguments); |
|||
_.bindAll(this,'disableEditing'); |
|||
this.listenTo(this.model, 'focus active', this.enableEditing); |
|||
this.rte = this.config.rte || ''; |
|||
this.activeRte = null; |
|||
this.em = this.config.em; |
|||
}, |
|||
|
|||
/** |
|||
* Enable the component to be editable |
|||
* @param {Event} e |
|||
* @private |
|||
* */ |
|||
enableEditing: function(e) { |
|||
var editable = this.model.get('editable'); |
|||
if(this.rte && editable) { |
|||
this.activeRte = this.rte.attach(this, this.activeRte); |
|||
this.rte.focus(this, this.activeRte); |
|||
} |
|||
this.toggleEvents(1); |
|||
}, |
|||
|
|||
/** |
|||
* Disable this component to be editable |
|||
* @param {Event} |
|||
* @private |
|||
* */ |
|||
disableEditing: function(e) { |
|||
var editable = this.model.get('editable'); |
|||
if(this.rte && editable) { |
|||
this.rte.detach(this, this.activeRte); |
|||
} |
|||
if(!this.rte.customRte && editable) { |
|||
this.parseRender(); |
|||
} |
|||
this.toggleEvents(); |
|||
}, |
|||
|
|||
/** |
|||
* Isolate disable propagation method |
|||
* @param {Event} |
|||
* @private |
|||
* */ |
|||
disablePropagation: function(e){ |
|||
e.stopPropagation(); |
|||
}, |
|||
|
|||
/** |
|||
* Parse content and re-render it |
|||
* @private |
|||
*/ |
|||
parseRender: function(){ |
|||
var comps = this.model.get('components'); |
|||
var opts = {silent: true}; |
|||
|
|||
// Avoid re-render on reset with silent option
|
|||
comps.reset(null, opts); |
|||
comps.add(this.$el.html(), opts); |
|||
this.model.set('content', ''); |
|||
this.render(); |
|||
|
|||
// As the reset was in silent mode I need to notify
|
|||
// the navigator about the change
|
|||
comps.trigger('resetNavigator'); |
|||
}, |
|||
|
|||
/** |
|||
* Enable/Disable events |
|||
* @param {Boolean} enable |
|||
*/ |
|||
toggleEvents: function(enable) { |
|||
var method = enable ? 'on' : 'off'; |
|||
|
|||
// The ownerDocument is from the frame
|
|||
var elDocs = [this.el.ownerDocument, document, this.rte]; |
|||
$(elDocs).off('mousedown', this.disableEditing); |
|||
$(elDocs)[method]('mousedown', this.disableEditing); |
|||
|
|||
// Avoid closing edit mode on component click
|
|||
this.$el.off('mousedown', this.disablePropagation); |
|||
this.$el[method]('mousedown', this.disablePropagation); |
|||
}, |
|||
|
|||
}); |
|||
function (Backbone, ComponentView) { |
|||
|
|||
return ComponentView.extend({ |
|||
|
|||
events: { |
|||
'dblclick': 'enableEditing', |
|||
'change': 'parseRender', |
|||
}, |
|||
|
|||
initialize: function(o) { |
|||
ComponentView.prototype.initialize.apply(this, arguments); |
|||
_.bindAll(this,'disableEditing'); |
|||
this.listenTo(this.model, 'focus active', this.enableEditing); |
|||
this.rte = this.config.rte || ''; |
|||
this.activeRte = null; |
|||
this.em = this.config.em; |
|||
}, |
|||
|
|||
/** |
|||
* Enable the component to be editable |
|||
* @param {Event} e |
|||
* @private |
|||
* */ |
|||
enableEditing: function(e) { |
|||
var editable = this.model.get('editable'); |
|||
if(this.rte && editable) { |
|||
this.activeRte = this.rte.attach(this, this.activeRte); |
|||
this.rte.focus(this, this.activeRte); |
|||
} |
|||
this.toggleEvents(1); |
|||
}, |
|||
|
|||
/** |
|||
* Disable this component to be editable |
|||
* @param {Event} |
|||
* @private |
|||
* */ |
|||
disableEditing: function(e) { |
|||
var model = this.model; |
|||
var editable = model.get('editable'); |
|||
|
|||
if(this.rte && editable) { |
|||
this.rte.detach(this, this.activeRte); |
|||
model.set('content', this.el.innerHTML); |
|||
} |
|||
|
|||
if(!this.rte.customRte && editable) { |
|||
this.parseRender(); |
|||
} |
|||
|
|||
this.toggleEvents(); |
|||
}, |
|||
|
|||
/** |
|||
* Isolate disable propagation method |
|||
* @param {Event} |
|||
* @private |
|||
* */ |
|||
disablePropagation: function(e){ |
|||
e.stopPropagation(); |
|||
}, |
|||
|
|||
/** |
|||
* Parse content and re-render it |
|||
* @private |
|||
*/ |
|||
parseRender: function(){ |
|||
var comps = this.model.get('components'); |
|||
var opts = {silent: true}; |
|||
|
|||
// Avoid re-render on reset with silent option
|
|||
comps.reset(null, opts); |
|||
comps.add(this.$el.html(), opts); |
|||
this.model.set('content', ''); |
|||
this.render(); |
|||
|
|||
// As the reset was in silent mode I need to notify
|
|||
// the navigator about the change
|
|||
comps.trigger('resetNavigator'); |
|||
}, |
|||
|
|||
/** |
|||
* Enable/Disable events |
|||
* @param {Boolean} enable |
|||
*/ |
|||
toggleEvents: function(enable) { |
|||
var method = enable ? 'on' : 'off'; |
|||
|
|||
// The ownerDocument is from the frame
|
|||
var elDocs = [this.el.ownerDocument, document, this.rte]; |
|||
$(elDocs).off('mousedown', this.disableEditing); |
|||
$(elDocs)[method]('mousedown', this.disableEditing); |
|||
|
|||
// Avoid closing edit mode on component click
|
|||
this.$el.off('mousedown', this.disablePropagation); |
|||
this.$el[method]('mousedown', this.disablePropagation); |
|||
}, |
|||
|
|||
}); |
|||
}); |
|||
|
|||
Loading…
Reference in new issue