Add container background image support to editor [MAILPOET-1403]

This commit is contained in:
Rostislav Wolny
2018-07-16 17:04:51 +02:00
parent 2d30a0884b
commit d8581f761f
8 changed files with 144 additions and 18 deletions

View File

@ -30,6 +30,15 @@ define([
var src = jQuery(event.target).val();
var image = new Image();
if (!src && this.options.onSelect) {
this.view[this.options.onSelect]({
src: null,
width: null,
height: null
});
return;
}
image.onload = function () {
if (this.options.onSelect) {
this.view[this.options.onSelect]({

View File

@ -40,6 +40,10 @@ define([
return this._getDefaults({
type: 'container',
orientation: 'vertical',
image: {
src: null,
display: 'scale'
},
styles: {
block: {
backgroundColor: 'transparent'
@ -239,16 +243,19 @@ define([
});
Module.ContainerBlockSettingsView = base.BlockSettingsView.extend({
behaviors: _.extend({}, base.BlockSettingsView.prototype.behaviors, {
MediaManagerBehavior: {
onSelect: 'onImageSelect'
}
}),
getTemplate: function () { return window.templates.containerBlockSettings; },
events: function () {
return {
'change .mailpoet_field_container_background_color': _.partial(this.changeColorField, 'styles.block.backgroundColor'),
'click .mailpoet_done_editing': 'close'
'click .mailpoet_done_editing': 'close',
'change .mailpoet_field_display_type': 'changeDisplayType'
};
},
regions: {
columnsSettingsRegion: '.mailpoet_container_columns_settings'
},
initialize: function () {
base.BlockSettingsView.prototype.initialize.apply(this, arguments);
@ -256,8 +263,14 @@ define([
collection: this.model.get('blocks')
});
},
onRender: function () {
this.showChildView('columnsSettingsRegion', this._columnsSettingsView);
changeDisplayType: function (event) {
this.model.get('image').set('display', event.target.value);
this.model.trigger('change');
},
onImageSelect: function (image) {
this.model.set('image.src', image.src);
this.model.trigger('change');
this.render();
}
});

View File

@ -124,7 +124,11 @@ define([
this.$('.mailpoet_field_image_width_input').val(width);
},
onImageSelect: function (image) {
this.model.set(image);
if (image.src === null) {
this.model.set({ src: '' });
} else {
this.model.set(image);
}
// Rerender settings view due to changes from outside of settings view
this.render();
}

View File

@ -29,6 +29,10 @@ define([
expect(model.get('styles.block.backgroundColor')).to.match(/^(#[abcdef0-9]{6})|transparent$/);
});
it('has a image display style', function () {
expect(model.get('image.display')).to.equal('scale');
});
it('has a collection of blocks', function () {
expect(model.get('blocks')).to.be.instanceof(Backbone.Collection);
});
@ -42,6 +46,10 @@ define([
block: {
backgroundColor: '#123456'
}
},
image: {
src: null,
display: 'scale'
}
}
}
@ -49,6 +57,7 @@ define([
innerModel = new (ContainerBlock.ContainerBlockModel)();
expect(innerModel.get('styles.block.backgroundColor')).to.equal('#123456');
expect(innerModel.get('image.display')).to.equal('scale');
});
it('do not update blockDefaults.container when changed', function () {
@ -130,7 +139,22 @@ define([
describe('once rendered', function () {
describe('on root level', function () {
var model = new (ContainerBlock.ContainerBlockModel)();
var imageSrc = 'http://example.org/someNewImage.png';
var model = new (ContainerBlock.ContainerBlockModel)({
type: 'container',
orientation: 'vertical',
image: {
src: imageSrc,
display: 'scale',
width: 123,
height: 456
},
styles: {
block: {
backgroundColor: 'transparent'
}
}
});
var view;
beforeEach(function () {
@ -159,6 +183,15 @@ define([
it('has a duplication tool', function () {
expect(view.$('.mailpoet_duplicate_block')).to.have.length(1);
});
it('has a background image set', function () {
var style = view.$('style').text();
expect(style).contains('.mailpoet_editor_view_' + view.cid);
expect(style).contains('background-color: #ffffff !important;');
expect(style).contains('background-image: url(http://example.org/someNewImage.png);');
expect(style).contains('background-position: center;');
expect(style).contains('background-size: cover;');
});
});
describe.skip('on non-root levels', function () {
@ -211,11 +244,13 @@ define([
describe('once rendered', function () {
var model;
var view;
var newSrc = 'http://example.org/someNewImage.png';
beforeEach(function () {
global.stubChannel(EditorApplication);
global.stubAvailableStyles(EditorApplication);
model = new (ContainerBlock.ContainerBlockModel)();
view = new (ContainerBlock.ContainerBlockSettingsView)({ model: model });
view.render();
});
it('updates the model when background color changes', function () {
@ -223,6 +258,23 @@ define([
expect(model.get('styles.block.backgroundColor')).to.equal('#123456');
});
it('updates the model background image display type changes', function () {
view.$('.mailpoet_field_display_type:nth(2)').attr('checked', true).change();
expect(model.get('image.display')).to.equal('tile');
});
it('updates the model when background image src changes', function () {
global.stubImage(123, 456);
view.$('.mailpoet_field_image_address').val(newSrc).trigger('input');
expect(model.get('image.src')).to.equal(newSrc);
});
it('updates the model when background image src is deleted', function () {
global.stubImage(123, 456);
view.$('.mailpoet_field_image_address').val('').trigger('input');
expect(model.get('image.src')).to.equal(null);
});
it.skip('closes the sidepanel after "Done" is clicked', function () {
var mock = sinon.mock().once();
global.MailPoet.Modal.cancel = mock;

View File

@ -1113,6 +1113,10 @@
},
},
container: {
image: {
src: null,
display: 'scale',
},
styles: {
block: {
backgroundColor: 'transparent',

View File

@ -1,8 +1,22 @@
{{#ifCond model.styles.block.backgroundColor '!=' 'transparent'}}
<style type="text/css">
.mailpoet_editor_view_{{ viewCid }} { background-color: {{ model.styles.block.backgroundColor }}; }
.mailpoet_editor_view_{{ viewCid }} .mailpoet_container { background-color: {{ model.styles.block.backgroundColor }}; }
</style>
{{/ifCond}}
{{#if model.image.src}}
<style type="text/css">
.mailpoet_editor_view_{{ viewCid }} {
background-color: {{#ifCond model.styles.block.backgroundColor '!=' 'transparent'}}{{ model.styles.block.backgroundColor }}{{else}}#ffffff{{/ifCond}} !important;
background-image: url({{ model.image.src }});
background-position: center;
background-repeat: {{#ifCond model.image.display '==' 'tile'}}repeat{{else}}no-repeat{{/ifCond}};
background-size: {{#ifCond model.image.display '==' 'scale'}}cover{{else}}contain{{/ifCond}};
}
.mailpoet_editor_view_{{ viewCid }} .mailpoet_container { background: transparent; }
</style>
{{else}}
{{#ifCond model.styles.block.backgroundColor '!=' 'transparent'}}
<style type="text/css">
.mailpoet_editor_view_{{ viewCid }} { background-color: {{ model.styles.block.backgroundColor }}; }
.mailpoet_editor_view_{{ viewCid }} .mailpoet_container { background-color: {{ model.styles.block.backgroundColor }}; }
</style>
{{/ifCond}}
{{/if}}
<div class="mailpoet_container {{#ifCond model.orientation '===' 'horizontal'}}mailpoet_container_horizontal{{/ifCond}}{{#ifCond model.orientation '===' 'vertical'}}mailpoet_container_vertical{{/ifCond}}"></div>
<div class="mailpoet_tools"></div><div class="mailpoet_block_highlight">

View File

@ -4,11 +4,41 @@
<div class="mailpoet_form_field_input_option">
<input type="text" name="background-color" class="mailpoet_field_container_background_color mailpoet_color" value="{{ model.styles.block.backgroundColor }}" />
</div>
<div class="mailpoet_form_field_title mailpoet_form_field_title_inline"><%= __('Background') %></div>
<div class="mailpoet_form_field_title mailpoet_form_field_title_inline"><%= __('Background color') %></div>
</label>
</div>
<div class="mailpoet_container_columns_settings"></div>
<div class="mailpoet_form_field">
<label>
<div class="mailpoet_form_field_title"><%= __('Background image') %></div>
<div class="mailpoet_form_field_input_option">
<input type="text" name="src" class="mailpoet_input mailpoet_field_image_address" value="{{ model.image.src }}" placeholder="http://" /><br />
</div>
</label>
</div>
<div class="mailpoet_form_field">
<input type="button" name="select-image" class="button button-secondary mailpoet_button_full mailpoet_field_image_select_image" value="{{#if model.image.src}}<%= __('Select another image') | escape('html_attr') %>{{else}}<%= __('Select image') | escape('html_attr') %>{{/if}}" />
</div>
<div class="mailpoet_form_field">
<div class="mailpoet_form_field_title"><%= __('Display options') %></div>
<div class="mailpoet_form_field_radio_option">
<label>
<input type="radio" name="display_type" class="mailpoet_field_display_type" value="scale" {{#ifCond model.image.display '===' 'scale'}}CHECKED{{/ifCond}}/>
<%= __('Scale') %>
</label>
</div>
<div class="mailpoet_form_field_radio_option">
<label>
<input type="radio" name="display_type" class="mailpoet_field_display_type" value="fit" {{#ifCond model.image.display '===' 'fit'}}CHECKED{{/ifCond}}/>
<%= __('Fit') %>
</label>
</div>
<div class="mailpoet_form_field_radio_option">
<label>
<input type="radio" name="display_type" class="mailpoet_field_display_type" value="tile" {{#ifCond model.image.display '===' 'tile'}}CHECKED{{/ifCond}}/>
<%= __('Tile') %>
</label>
</div>
</div>
<div class="mailpoet_form_field">
<input type="button" class="button button-primary mailpoet_done_editing" value="<%= __('Done') | escape('html_attr') %>" />

View File

@ -2,7 +2,7 @@
<div class="mailpoet_content" style="{{#ifCond model.styles.block.textAlign '==' 'left'}}margin: 0 auto 0 0; {{/ifCond}}{{#ifCond model.styles.block.textAlign '==' 'center'}}margin: auto; {{/ifCond}}{{#ifCond model.styles.block.textAlign '==' 'right'}}margin: 0 0 0 auto; {{/ifCond}}width: {{model.width}}">
<div class="mailpoet_image">
<a href="{{ model.link }}" onClick="return false;">
<img src="{{#ifCond model.src '!=' ''}}{{ model.src }}{{ else }}{{ imageMissingSrc }}{{/ifCond}}" alt="{{ model.alt }}" onerror="if(this.src != '{{ imageMissingSrc }}') {this.src = '{{ imageMissingSrc }}'; this.style.width='auto';}" width="{{model.width}}" />
<img src="{{#ifCond model.src '!=' ''}}{{ model.src }}{{ else }}{{ imageMissingSrc }}{{/ifCond}}" alt="{{ model.alt }}" onerror="if(this.src != '{{ imageMissingSrc }}') {this.src = '{{ imageMissingSrc }}';}" width="{{model.width}}" />
</a>
<div class="mailpoet_image_resize_handle_container">
<div class="mailpoet_image_resize_handle">