Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
ca157fc91d | |||
1fbe5d7bc6 | |||
71c031ccf9 | |||
6a956472fe | |||
0c4407f43a | |||
b6c864e7a1 | |||
3d9dc6465d | |||
9a6fec094a | |||
61af224d7d | |||
9b41641e97 | |||
4e2e9f6f8f | |||
c29dc8b4c7 | |||
98a3c6b156 | |||
69c540288b | |||
651c9f5692 | |||
9ad3778cf7 | |||
c90e0e9f64 | |||
cb1730c4e2 | |||
3dd8a973fd | |||
c3ea088fca | |||
a11d6d7868 | |||
a596add838 | |||
7e7103ddab | |||
0064970ed7 | |||
9d93f3ea95 | |||
ff2a3cd19e | |||
8419d95ea1 | |||
26241afb86 |
@ -12,7 +12,6 @@
|
||||
"prefer-arrow-callback": 0,
|
||||
"radix": 0,
|
||||
"no-alert": 0,
|
||||
"block-scoped-var": 0,
|
||||
"guard-for-in": 0,
|
||||
"no-prototype-builtins": 0,
|
||||
"no-restricted-syntax": 0,
|
||||
@ -38,20 +37,16 @@
|
||||
"global-require": 0,
|
||||
"no-throw-literal": 0,
|
||||
"no-extra-bind": 0,
|
||||
"one-var-declaration-per-line": 0,
|
||||
"consistent-return": 0,
|
||||
"no-shadow": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"brace-style": 0,
|
||||
"no-else-return": 0,
|
||||
"no-use-before-define": 0,
|
||||
"one-var": 0,
|
||||
"camelcase": 0,
|
||||
"padded-blocks": 0,
|
||||
"strict": 0,
|
||||
"vars-on-top": 0,
|
||||
"no-var": 0,
|
||||
"no-unused-vars": 0,
|
||||
"space-infix-ops": 0,
|
||||
"object-shorthand": 0,
|
||||
"new-parens": 0,
|
||||
"eol-last": 0,
|
||||
|
@ -48,7 +48,7 @@
|
||||
"camelcase": 0,
|
||||
"eqeqeq": 0,
|
||||
"no-lonely-if": 0,
|
||||
"block-scoped-var": 0,
|
||||
"space-unary-ops": 0,
|
||||
"no-extra-bind": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"no-case-declarations": 0,
|
||||
@ -59,12 +59,11 @@
|
||||
"no-extra-boolean-cast": 0,
|
||||
"dot-notation": 0,
|
||||
"no-shadow": 0,
|
||||
"one-var": 0,
|
||||
"no-alert": 0,
|
||||
"one-var-declaration-per-line": 0,
|
||||
"no-script-url": 0,
|
||||
"wrap-iife": 0,
|
||||
"vars-on-top": 0,
|
||||
"space-infix-ops": 0,
|
||||
"no-irregular-whitespace": 0,
|
||||
"padded-blocks": 0,
|
||||
"no-underscore-dangle": 0
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
},
|
||||
"rules": {
|
||||
"import/no-amd": 0,
|
||||
"one-var": 0,
|
||||
"no-whitespace-before-property": 0,
|
||||
"global-require": 0,
|
||||
"keyword-spacing": 0,
|
||||
@ -18,14 +17,11 @@
|
||||
"func-call-spacing": 0,
|
||||
"max-len": 0,
|
||||
"space-unary-ops": 0,
|
||||
"no-unused-vars": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-shadow": 0,
|
||||
"padded-blocks": 0,
|
||||
"vars-on-top": 0,
|
||||
"space-before-blocks": 0,
|
||||
"object-curly-spacing": 0,
|
||||
"one-var-declaration-per-line": 0,
|
||||
"func-names": 0,
|
||||
"space-before-function-paren": 0
|
||||
}
|
||||
|
@ -2,11 +2,10 @@ function requestFailed(errorMessage, xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
return xhr.responseJSON;
|
||||
}
|
||||
var message = errorMessage.replace('%d', xhr.status);
|
||||
return {
|
||||
errors: [
|
||||
{
|
||||
message: message
|
||||
message: errorMessage.replace('%d', xhr.status)
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -54,21 +53,23 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function (mp, jQuery, _) {
|
||||
};
|
||||
},
|
||||
request: function (method, options) {
|
||||
// set options
|
||||
var params;
|
||||
var deferred;
|
||||
// set options
|
||||
this.init(options);
|
||||
|
||||
// set request params
|
||||
var params = this.getParams();
|
||||
// set request params
|
||||
params = this.getParams();
|
||||
|
||||
// remove null values from the data object
|
||||
// remove null values from the data object
|
||||
if (_.isObject(params.data)) {
|
||||
params.data = _.pick(params.data, function (value) {
|
||||
return (value !== null);
|
||||
});
|
||||
}
|
||||
|
||||
// ajax request
|
||||
var deferred = jQuery.post(
|
||||
// ajax request
|
||||
deferred = jQuery.post(
|
||||
this.options.url,
|
||||
params,
|
||||
null,
|
||||
|
@ -43,9 +43,10 @@ define('date',
|
||||
},
|
||||
format: function (date, opts) {
|
||||
var options = opts || {};
|
||||
var momentDate;
|
||||
this.init(options);
|
||||
|
||||
var momentDate = Moment(date, this.convertFormat(options.parseFormat));
|
||||
momentDate = Moment(date, this.convertFormat(options.parseFormat));
|
||||
if (options.offset === 0) momentDate = momentDate.utc();
|
||||
return momentDate.format(this.convertFormat(this.options.format));
|
||||
},
|
||||
@ -71,6 +72,11 @@ define('date',
|
||||
});
|
||||
},
|
||||
convertFormat: function (format) {
|
||||
var replacements;
|
||||
var convertedFormat;
|
||||
var escapeToken;
|
||||
var index;
|
||||
var token;
|
||||
var format_mappings = {
|
||||
date: {
|
||||
d: 'DD',
|
||||
@ -140,12 +146,11 @@ define('date',
|
||||
|
||||
if (!format || format.length <= 0) return format;
|
||||
|
||||
var replacements = format_mappings['date'];
|
||||
replacements = format_mappings['date'];
|
||||
convertedFormat = [];
|
||||
escapeToken = false;
|
||||
|
||||
var convertedFormat = [];
|
||||
var escapeToken = false;
|
||||
|
||||
for (var index = 0, token = ''; format.charAt(index); index += 1) {
|
||||
for (index = 0, token = ''; format.charAt(index); index += 1) {
|
||||
token = format.charAt(index);
|
||||
if (escapeToken === true) {
|
||||
convertedFormat.push('[' + token + ']');
|
||||
|
@ -7,6 +7,10 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var Observable;
|
||||
var WysijaHistory;
|
||||
var WysijaForm;
|
||||
|
||||
Event.cacheDelegated = {};
|
||||
Object.extend(document, (function () {
|
||||
var cache = Event.cacheDelegated;
|
||||
@ -30,18 +34,21 @@ Object.extend(document, (function () {
|
||||
}
|
||||
|
||||
function destroyWrapper(selector, eventName, handler) {
|
||||
var wrapper;
|
||||
var c = getCacheForSelector(selector);
|
||||
if (!c[eventName]) return false;
|
||||
var wrapper = findWrapper(selector, eventName, handler);
|
||||
wrapper = findWrapper(selector, eventName, handler);
|
||||
c[eventName] = c[eventName].without(wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function createWrapper(selector, eventName, handler, context) {
|
||||
var wrapper, c = getWrappersForSelector(selector, eventName);
|
||||
var wrapper;
|
||||
var element;
|
||||
var c = getWrappersForSelector(selector, eventName);
|
||||
if (c.pluck('handler').include(handler)) return false;
|
||||
wrapper = function (event) {
|
||||
var element = event.findElement(selector);
|
||||
element = event.findElement(selector);
|
||||
if (element) handler.call(context || element, event, element);
|
||||
};
|
||||
wrapper.handler = handler;
|
||||
@ -49,13 +56,14 @@ Object.extend(document, (function () {
|
||||
return wrapper;
|
||||
}
|
||||
return {
|
||||
delegate: function (selector, eventName, handler, context) {
|
||||
delegate: function (selector, eventName) {
|
||||
var wrapper = createWrapper.apply(null, arguments);
|
||||
if (wrapper) document.observe(eventName, wrapper);
|
||||
return document;
|
||||
},
|
||||
stopDelegating: function (selector, eventName, handler) {
|
||||
stopDelegating: function (selector, eventName) {
|
||||
var length = arguments.length;
|
||||
var wrapper;
|
||||
switch (length) {
|
||||
case 2:
|
||||
getWrappersForSelector(selector, eventName).each(function (wrapper) {
|
||||
@ -73,7 +81,7 @@ Object.extend(document, (function () {
|
||||
});
|
||||
break;
|
||||
default:
|
||||
var wrapper = destroyWrapper.apply(null, arguments);
|
||||
wrapper = destroyWrapper.apply(null, arguments);
|
||||
if (wrapper) document.stopObserving(eventName, wrapper);
|
||||
}
|
||||
return document;
|
||||
@ -81,7 +89,7 @@ Object.extend(document, (function () {
|
||||
};
|
||||
})());
|
||||
|
||||
var Observable = (function () {
|
||||
Observable = (function () {
|
||||
function getEventName(nameA, namespace) {
|
||||
var name = nameA.substring(2);
|
||||
if (namespace) name = namespace + ':' + name;
|
||||
@ -89,8 +97,8 @@ var Observable = (function () {
|
||||
}
|
||||
|
||||
function getHandlers(klass) {
|
||||
var proto = klass.prototype,
|
||||
namespace = proto.namespace;
|
||||
var proto = klass.prototype;
|
||||
var namespace = proto.namespace;
|
||||
return Object.keys(proto).grep(/^on/).inject(window.$H(), function (handlers, name) {
|
||||
if (name === 'onDomLoaded') return handlers;
|
||||
handlers.set(getEventName(name, namespace), getWrapper(proto[name], klass));
|
||||
@ -111,9 +119,9 @@ var Observable = (function () {
|
||||
}
|
||||
return {
|
||||
observe: function (selector) {
|
||||
var klass = this;
|
||||
if (!this.handlers) this.handlers = {};
|
||||
if (this.handlers[selector]) return;
|
||||
var klass = this;
|
||||
if (this.prototype.onDomLoaded) {
|
||||
if (document.loaded) {
|
||||
onDomLoad(selector, klass);
|
||||
@ -146,8 +154,9 @@ Object.extend(window.Droppables, {
|
||||
return proceed(drop);
|
||||
}),
|
||||
show: function (point, element) {
|
||||
var drop;
|
||||
var affected = [];
|
||||
if (!this.drops.length) return;
|
||||
var drop, affected = [];
|
||||
this.drops.each(function (drop) {
|
||||
if (window.Droppables.isAffected(point, element, drop)) affected.push(drop);
|
||||
});
|
||||
@ -159,13 +168,13 @@ Object.extend(window.Droppables, {
|
||||
if (drop !== this.last_active) window.Droppables.activate(drop, element);
|
||||
}
|
||||
},
|
||||
displayArea: function (draggable) {
|
||||
displayArea: function () {
|
||||
if (!this.drops.length) return;
|
||||
|
||||
// hide controls when displaying drop areas.
|
||||
WysijaForm.hideBlockControls();
|
||||
|
||||
this.drops.each(function (drop, iterator) {
|
||||
this.drops.each(function (drop) {
|
||||
if (drop.element.hasClassName('block_placeholder')) {
|
||||
drop.element.addClassName('active');
|
||||
}
|
||||
@ -173,7 +182,7 @@ Object.extend(window.Droppables, {
|
||||
},
|
||||
hideArea: function () {
|
||||
if (!this.drops.length) return;
|
||||
this.drops.each(function (drop, iterator) {
|
||||
this.drops.each(function (drop) {
|
||||
if (drop.element.hasClassName('block_placeholder')) {
|
||||
drop.element.removeClassName('active');
|
||||
} else if (drop.element.hasClassName('image_placeholder')) {
|
||||
@ -195,7 +204,7 @@ Object.extend(window.Droppables, {
|
||||
- set a maximum number of items to be stored
|
||||
|
||||
*/
|
||||
var WysijaHistory = {
|
||||
WysijaHistory = {
|
||||
container: 'mailpoet_form_history',
|
||||
size: 30,
|
||||
enqueue: function (element) {
|
||||
@ -239,7 +248,7 @@ var WysijaHistory = {
|
||||
};
|
||||
|
||||
/* MailPoet Form */
|
||||
var WysijaForm = {
|
||||
WysijaForm = {
|
||||
version: '0.7',
|
||||
options: {
|
||||
container: 'mailpoet_form_container',
|
||||
@ -292,6 +301,7 @@ var WysijaForm = {
|
||||
});
|
||||
},
|
||||
load: function (data) {
|
||||
var settings_elements;
|
||||
if (data === undefined) return;
|
||||
|
||||
// load body
|
||||
@ -302,7 +312,7 @@ var WysijaForm = {
|
||||
});
|
||||
|
||||
// load settings
|
||||
var settings_elements = window.$('mailpoet_form_settings').getElements();
|
||||
settings_elements = window.$('mailpoet_form_settings').getElements();
|
||||
settings_elements.each(function (setting) {
|
||||
// skip lists
|
||||
if (setting.name === 'segments') {
|
||||
@ -324,13 +334,13 @@ var WysijaForm = {
|
||||
}
|
||||
},
|
||||
save: function () {
|
||||
var position = 1,
|
||||
data = {
|
||||
name: window.$F('mailpoet_form_name'),
|
||||
settings: window.$('mailpoet_form_settings').serialize(true),
|
||||
body: [],
|
||||
styles: (window.MailPoet.CodeEditor !== undefined) ? window.MailPoet.CodeEditor.getValue() : null
|
||||
};
|
||||
var position = 1;
|
||||
var data = {
|
||||
name: window.$F('mailpoet_form_name'),
|
||||
settings: window.$('mailpoet_form_settings').serialize(true),
|
||||
body: [],
|
||||
styles: (window.MailPoet.CodeEditor !== undefined) ? window.MailPoet.CodeEditor.getValue() : null
|
||||
};
|
||||
// body
|
||||
WysijaForm.getBlocks().each(function (b) {
|
||||
var block_data = (typeof (b.block['save']) === 'function') ? b.block.save() : null;
|
||||
@ -401,6 +411,7 @@ var WysijaForm = {
|
||||
return data;
|
||||
},
|
||||
toggleWidgets: function () {
|
||||
var hasSegmentSelection;
|
||||
window.$$('a[wysija_unique="1"]').invoke('removeClassName', 'disabled');
|
||||
|
||||
// loop through each unique field already inserted in the editor and disable its toolbar equivalent
|
||||
@ -411,7 +422,7 @@ var WysijaForm = {
|
||||
}
|
||||
});
|
||||
|
||||
var hasSegmentSelection = WysijaForm.hasSegmentSelection();
|
||||
hasSegmentSelection = WysijaForm.hasSegmentSelection();
|
||||
|
||||
if (hasSegmentSelection) {
|
||||
window.$('mailpoet_form_segments').writeAttribute('required', false).disable();
|
||||
@ -426,8 +437,9 @@ var WysijaForm = {
|
||||
},
|
||||
isSegmentSelectionValid: function () {
|
||||
var segment_selection = window.$$('#' + WysijaForm.options.editor + ' [wysija_id="segments"]')[0];
|
||||
var block;
|
||||
if (segment_selection !== undefined) {
|
||||
var block = WysijaForm.get(segment_selection).block.getData();
|
||||
block = WysijaForm.get(segment_selection).block.getData();
|
||||
return (
|
||||
(block.params.values !== undefined)
|
||||
&&
|
||||
@ -437,10 +449,12 @@ var WysijaForm = {
|
||||
return false;
|
||||
},
|
||||
setBlockPositions: function (event, target) {
|
||||
var index = 1;
|
||||
var block_placeholder;
|
||||
var previous_placeholder;
|
||||
// release dragging lock
|
||||
WysijaForm.locks.dragging = false;
|
||||
|
||||
var index = 1;
|
||||
WysijaForm.getBlocks().each(function (container) {
|
||||
container.setPosition(index++);
|
||||
// remove z-index value to avoid issues when resizing images
|
||||
@ -453,8 +467,8 @@ var WysijaForm = {
|
||||
|
||||
if (target !== undefined) {
|
||||
// get placeholders (previous placeholder matches the placeholder linked to the next block)
|
||||
var block_placeholder = window.$(target.element.readAttribute('wysija_placeholder')),
|
||||
previous_placeholder = target.element.previous('.block_placeholder');
|
||||
block_placeholder = window.$(target.element.readAttribute('wysija_placeholder'));
|
||||
previous_placeholder = target.element.previous('.block_placeholder');
|
||||
|
||||
if (block_placeholder !== null) {
|
||||
// put block placeholder before the current block
|
||||
@ -479,23 +493,17 @@ var WysijaForm = {
|
||||
},
|
||||
setSettingsPosition: function () {
|
||||
// get viewport offsets and dimensions
|
||||
var viewportHeight = document.viewport.getHeight(),
|
||||
blockPadding = 5;
|
||||
var viewportHeight = document.viewport.getHeight();
|
||||
|
||||
window.$(WysijaForm.options.container).select('.wysija_settings').each(function (element) {
|
||||
// get parent dimensions and position
|
||||
var parentDim = element.up('.mailpoet_form_block').getDimensions(),
|
||||
parentPos = element.up('.mailpoet_form_block').cumulativeOffset(),
|
||||
is_visible = (parentPos.top <= (WysijaForm.scroll.top + viewportHeight)),
|
||||
buttonMargin = 5,
|
||||
relativeTop = buttonMargin;
|
||||
var parentDim = element.up('.mailpoet_form_block').getDimensions();
|
||||
var parentPos = element.up('.mailpoet_form_block').cumulativeOffset();
|
||||
var is_visible = (parentPos.top <= (WysijaForm.scroll.top + viewportHeight));
|
||||
var buttonMargin = 5;
|
||||
var relativeTop = buttonMargin;
|
||||
|
||||
if (is_visible) {
|
||||
// desired position is set to center of viewport
|
||||
var absoluteTop = parseInt(WysijaForm.scroll.top + ((viewportHeight / 2) - (element.getHeight() / 2)), 10),
|
||||
parentTop = parseInt(parentPos.top - blockPadding, 10),
|
||||
parentBottom = parseInt(parentPos.top + parentDim.height - blockPadding, 10);
|
||||
|
||||
// always center
|
||||
relativeTop = parseInt((parentDim.height / 2) - (element.getHeight() / 2), 10);
|
||||
}
|
||||
@ -519,9 +527,10 @@ var WysijaForm = {
|
||||
|
||||
},
|
||||
setToolbarPosition: function () {
|
||||
var position;
|
||||
WysijaForm.initToolbarPosition();
|
||||
|
||||
var position = {
|
||||
position = {
|
||||
top: WysijaForm.toolbar.y + 'px',
|
||||
visibility: 'visible'
|
||||
};
|
||||
@ -585,10 +594,12 @@ var WysijaForm = {
|
||||
instances: {},
|
||||
get: function (element, typ) {
|
||||
var type = typ;
|
||||
var id;
|
||||
var instance;
|
||||
if (type === undefined) type = 'block';
|
||||
// identify element
|
||||
var id = element.identify();
|
||||
var instance = WysijaForm.instances[id] || new WysijaForm[type.capitalize().camelize()](id);
|
||||
id = element.identify();
|
||||
instance = WysijaForm.instances[id] || new WysijaForm[type.capitalize().camelize()](id);
|
||||
|
||||
WysijaForm.instances[id] = instance;
|
||||
return instance;
|
||||
@ -636,8 +647,8 @@ var WysijaForm = {
|
||||
},
|
||||
encodeURIComponent: function (str) {
|
||||
// check if it's a url and if so, prevent encoding of protocol
|
||||
var regexp = new RegExp(/^http[s]?:\/\//),
|
||||
protocol = regexp.exec(str);
|
||||
var regexp = new RegExp(/^http[s]?:\/\//);
|
||||
var protocol = regexp.exec(str);
|
||||
|
||||
if (protocol === null) {
|
||||
// this is not a url so encode the whole thing
|
||||
@ -680,13 +691,13 @@ WysijaForm.DraggableItem = window.Class.create({
|
||||
},
|
||||
STYLES: new window.Template('position: absolute; top: #{top}px; left: #{left}px;'),
|
||||
cloneElement: function () {
|
||||
var clone = this.element.clone(),
|
||||
offset = this.element.cumulativeOffset(),
|
||||
list = this.getList(),
|
||||
styles = this.STYLES.evaluate({
|
||||
top: offset.top - list.scrollTop,
|
||||
left: offset.left - list.scrollLeft
|
||||
});
|
||||
var clone = this.element.clone();
|
||||
var offset = this.element.cumulativeOffset();
|
||||
var list = this.getList();
|
||||
var styles = this.STYLES.evaluate({
|
||||
top: offset.top - list.scrollTop,
|
||||
left: offset.left - list.scrollLeft
|
||||
});
|
||||
clone.setStyle(styles);
|
||||
|
||||
clone.addClassName('mailpoet_form_widget');
|
||||
@ -767,15 +778,17 @@ WysijaForm.Block = window.Class.create({
|
||||
}
|
||||
},
|
||||
makeBlockDroppable: function () {
|
||||
var block_placeholder;
|
||||
if (this.isBlockDroppableEnabled() === false) {
|
||||
var block_placeholder = this.getBlockDroppable();
|
||||
block_placeholder = this.getBlockDroppable();
|
||||
window.Droppables.add(block_placeholder.identify(), WysijaForm.blockDropOptions);
|
||||
block_placeholder.addClassName('enabled');
|
||||
}
|
||||
},
|
||||
removeBlockDroppable: function () {
|
||||
var block_placeholder;
|
||||
if (this.isBlockDroppableEnabled()) {
|
||||
var block_placeholder = this.getBlockDroppable();
|
||||
block_placeholder = this.getBlockDroppable();
|
||||
window.Droppables.remove(block_placeholder.identify());
|
||||
block_placeholder.removeClassName('enabled');
|
||||
}
|
||||
@ -807,6 +820,7 @@ WysijaForm.Block = window.Class.create({
|
||||
return this.element.down('.wysija_controls');
|
||||
},
|
||||
setupControls: function () {
|
||||
var block;
|
||||
// enable controls
|
||||
this.controls = this.getControls();
|
||||
|
||||
@ -857,9 +871,8 @@ WysijaForm.Block = window.Class.create({
|
||||
if (this.settingsButton !== null) {
|
||||
this.settingsButton.observe('click', function (event) {
|
||||
// TODO: refactor
|
||||
var block = window.$(event.target).up('.mailpoet_form_block') || null;
|
||||
block = window.$(event.target).up('.mailpoet_form_block') || null;
|
||||
if (block !== null) {
|
||||
var field = WysijaForm.getFieldData(block);
|
||||
this.editSettings();
|
||||
}
|
||||
}.bind(this));
|
||||
@ -905,18 +918,23 @@ WysijaForm.Block = window.Class.create({
|
||||
/* Invoked on item dropped */
|
||||
WysijaForm.Block.create = function (createBlock, target) {
|
||||
var block = createBlock;
|
||||
var body;
|
||||
var block_template;
|
||||
var template;
|
||||
var output;
|
||||
var settings_segments;
|
||||
if (window.$('form_template_' + block.type) === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var body = window.$(WysijaForm.options.body),
|
||||
block_template = window.Handlebars.compile(window.$('form_template_block').innerHTML),
|
||||
template = window.Handlebars.compile(window.$('form_template_' + block.type).innerHTML),
|
||||
output = '';
|
||||
body = window.$(WysijaForm.options.body);
|
||||
block_template = window.Handlebars.compile(window.$('form_template_block').innerHTML);
|
||||
template = window.Handlebars.compile(window.$('form_template_' + block.type).innerHTML);
|
||||
output = '';
|
||||
|
||||
if (block.type === 'segment') {
|
||||
if (block.params.values === undefined) {
|
||||
var settings_segments = window.jQuery('#mailpoet_form_segments').val();
|
||||
settings_segments = window.jQuery('#mailpoet_form_segments').val();
|
||||
if (settings_segments !== null && settings_segments.length > 0) {
|
||||
block.params.values = window.mailpoet_segments.filter(function (segment) {
|
||||
return (settings_segments.indexOf(segment.id) !== -1);
|
||||
@ -936,14 +954,13 @@ WysijaForm.Block.create = function (createBlock, target) {
|
||||
}
|
||||
|
||||
// if the drop target was the bottom placeholder
|
||||
var element = null;
|
||||
if (target.identify() === 'block_placeholder') {
|
||||
// insert block at the bottom
|
||||
element = body.insert(output);
|
||||
body.insert(output);
|
||||
// block = body.childElements().last();
|
||||
} else {
|
||||
// insert block before the drop target
|
||||
element = target.insert({
|
||||
target.insert({
|
||||
before: output
|
||||
});
|
||||
// block = target.previous('.mailpoet_form_block');
|
||||
@ -984,8 +1001,8 @@ WysijaForm.Widget = window.Class.create(WysijaForm.Block, {
|
||||
this.setupControls();
|
||||
},
|
||||
save: function () {
|
||||
info('widget -> save');
|
||||
var data = this.getData();
|
||||
info('widget -> save');
|
||||
|
||||
if (data.element !== undefined) {
|
||||
delete data.element;
|
||||
@ -994,8 +1011,8 @@ WysijaForm.Widget = window.Class.create(WysijaForm.Block, {
|
||||
return data;
|
||||
},
|
||||
setData: function (data) {
|
||||
var current_data = this.getData(),
|
||||
params = window.$H(current_data.params).merge(data.params).toObject();
|
||||
var current_data = this.getData();
|
||||
var params = window.$H(current_data.params).merge(data.params).toObject();
|
||||
|
||||
// update type if it changed
|
||||
if (data.type !== undefined && data.type !== current_data.type) {
|
||||
@ -1020,16 +1037,20 @@ WysijaForm.Widget = window.Class.create(WysijaForm.Block, {
|
||||
this.removeBlock();
|
||||
},
|
||||
redraw: function (data) {
|
||||
var options;
|
||||
var block_template;
|
||||
var template;
|
||||
var params;
|
||||
// set parameters
|
||||
this.setData(data);
|
||||
var options = this.getData();
|
||||
options = this.getData();
|
||||
// redraw block
|
||||
var block_template = window.Handlebars.compile(window.$('form_template_block').innerHTML),
|
||||
template = window.Handlebars.compile(window.$('form_template_' + options.type).innerHTML),
|
||||
data = window.$H(options).merge({
|
||||
template: template(options)
|
||||
}).toObject();
|
||||
this.element.replace(block_template(data));
|
||||
block_template = window.Handlebars.compile(window.$('form_template_block').innerHTML);
|
||||
template = window.Handlebars.compile(window.$('form_template_' + options.type).innerHTML);
|
||||
params = window.$H(options).merge({
|
||||
template: template(options)
|
||||
}).toObject();
|
||||
this.element.replace(block_template(params));
|
||||
|
||||
WysijaForm.init();
|
||||
},
|
||||
@ -1061,8 +1082,8 @@ function info(value) {
|
||||
var noop = function () {};
|
||||
var methods = ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'markTimeline', 'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn'];
|
||||
var length = methods.length;
|
||||
window.console = {};
|
||||
var console = {};
|
||||
window.console = {};
|
||||
while (length--) {
|
||||
console[methods[length]] = noop;
|
||||
}
|
||||
|
@ -1,26 +1,28 @@
|
||||
define('handlebars_helpers', ['handlebars'], function (Handlebars) {
|
||||
// Handlebars helpers
|
||||
Handlebars.registerHelper('concat', function () {
|
||||
var size = (arguments.length - 1),
|
||||
output = '';
|
||||
for (var i = 0; i < size; i++) {
|
||||
var size = (arguments.length - 1);
|
||||
var output = '';
|
||||
var i;
|
||||
for (i = 0; i < size; i++) {
|
||||
output += arguments[i];
|
||||
}
|
||||
return output;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('number_format', function (value, block) {
|
||||
Handlebars.registerHelper('number_format', function (value) {
|
||||
return Number(value).toLocaleString();
|
||||
});
|
||||
Handlebars.registerHelper('date_format', function (timestamp, block) {
|
||||
var f;
|
||||
if (window.moment) {
|
||||
if (timestamp === undefined || isNaN(timestamp) || timestamp <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set date format
|
||||
var f = block.hash.format || 'MMM Do, YYYY';
|
||||
// check if we passed a timestamp
|
||||
// set date format
|
||||
f = block.hash.format || 'MMM Do, YYYY';
|
||||
// check if we passed a timestamp
|
||||
if (parseInt(timestamp, 10) == timestamp) {
|
||||
return window.moment.unix(timestamp).format(f);
|
||||
} else {
|
||||
@ -59,25 +61,24 @@ define('handlebars_helpers', ['handlebars'], function (Handlebars) {
|
||||
case '||':
|
||||
return (v1 || v2) ? options.fn(this) : options.inverse(this);
|
||||
case 'in':
|
||||
var values = v2.split(',');
|
||||
return (v2.indexOf(v1) !== -1) ? options.fn(this) : options.inverse(this);
|
||||
default:
|
||||
return options.inverse(this);
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('nl2br', function (value, block) {
|
||||
Handlebars.registerHelper('nl2br', function (value) {
|
||||
return value.gsub('\n', '<br />');
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('json_encode', function (value, block) {
|
||||
Handlebars.registerHelper('json_encode', function (value) {
|
||||
return JSON.stringify(value);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('json_decode', function (value, block) {
|
||||
Handlebars.registerHelper('json_decode', function (value) {
|
||||
return JSON.parse(value);
|
||||
});
|
||||
Handlebars.registerHelper('url', function (value, block) {
|
||||
Handlebars.registerHelper('url', function (value) {
|
||||
var url = window.location.protocol + '//' + window.location.host + window.location.pathname;
|
||||
|
||||
return url + value;
|
||||
@ -90,16 +91,17 @@ define('handlebars_helpers', ['handlebars'], function (Handlebars) {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
Handlebars.registerHelper('lookup', function (obj, field, options) {
|
||||
Handlebars.registerHelper('lookup', function (obj, field) {
|
||||
return obj && obj[field];
|
||||
});
|
||||
|
||||
|
||||
Handlebars.registerHelper('rsa_key', function (value, block) {
|
||||
// extract all lines into an array
|
||||
Handlebars.registerHelper('rsa_key', function (value) {
|
||||
var lines;
|
||||
// extract all lines into an array
|
||||
if (value === undefined) return '';
|
||||
|
||||
var lines = value.trim().split('\n');
|
||||
lines = value.trim().split('\n');
|
||||
|
||||
// remove header & footer
|
||||
lines.shift();
|
||||
@ -109,7 +111,7 @@ define('handlebars_helpers', ['handlebars'], function (Handlebars) {
|
||||
return lines.join('');
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('trim', function (value, block) {
|
||||
Handlebars.registerHelper('trim', function (value) {
|
||||
if (value === null || value === undefined) return '';
|
||||
return value.trim();
|
||||
});
|
||||
@ -126,10 +128,10 @@ define('handlebars_helpers', ['handlebars'], function (Handlebars) {
|
||||
*/
|
||||
Handlebars.registerHelper('ellipsis', function (str, limit, append) {
|
||||
var strAppend = append;
|
||||
var sanitized = str.replace(/(<([^>]+)>)/g, '');
|
||||
if (strAppend === undefined) {
|
||||
strAppend = '';
|
||||
}
|
||||
var sanitized = str.replace(/(<([^>]+)>)/g, '');
|
||||
if (sanitized.length > limit) {
|
||||
return sanitized.substr(0, limit - strAppend.length) + strAppend;
|
||||
} else {
|
||||
|
@ -24,20 +24,20 @@ define(
|
||||
* http://benalman.com/about/license/
|
||||
*/
|
||||
$.fn.serializeObject = function (coerce) {
|
||||
var obj = {},
|
||||
coerce_types = { true: !0, false: !1, null: null };
|
||||
var obj = {};
|
||||
var coerce_types = { true: !0, false: !1, null: null };
|
||||
|
||||
// Iterate over all name=value pairs.
|
||||
$.each(this.serializeArray(), function (j, v) {
|
||||
var key = v.name,
|
||||
val = v.value,
|
||||
cur = obj,
|
||||
i = 0,
|
||||
var key = v.name;
|
||||
var val = v.value;
|
||||
var cur = obj;
|
||||
var i = 0;
|
||||
|
||||
// If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
|
||||
// into its component parts.
|
||||
keys = key.split(']['),
|
||||
keys_last = keys.length - 1;
|
||||
// If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
|
||||
// into its component parts.
|
||||
var keys = key.split('][');
|
||||
var keys_last = keys.length - 1;
|
||||
|
||||
// If the first keys part contains [ and the last ends with ], then []
|
||||
// are correctly balanced.
|
||||
@ -106,4 +106,4 @@ define(
|
||||
|
||||
return $;
|
||||
}
|
||||
);
|
||||
);
|
||||
|
@ -658,8 +658,8 @@ const Listing = React.createClass({
|
||||
});
|
||||
},
|
||||
handleSelectItem: function (id, is_checked) {
|
||||
let selected_ids = this.state.selected_ids,
|
||||
selection = false;
|
||||
let selected_ids = this.state.selected_ids;
|
||||
let selection = false;
|
||||
|
||||
if (is_checked) {
|
||||
selected_ids = jQuery.merge(selected_ids, [id]);
|
||||
|
@ -116,6 +116,7 @@ define('modal', ['mailpoet', 'jquery'],
|
||||
}
|
||||
},
|
||||
init: function (options) {
|
||||
var modal;
|
||||
if (this.initialized === true) {
|
||||
this.close();
|
||||
}
|
||||
@ -134,7 +135,7 @@ define('modal', ['mailpoet', 'jquery'],
|
||||
if (this.options.type !== null) {
|
||||
// insert modal depending on its type
|
||||
if (this.options.type === 'popup') {
|
||||
var modal = this.compileTemplate(
|
||||
modal = this.compileTemplate(
|
||||
this.templates[this.options.type]
|
||||
);
|
||||
// create modal
|
||||
@ -178,7 +179,7 @@ define('modal', ['mailpoet', 'jquery'],
|
||||
|
||||
return this;
|
||||
},
|
||||
initOverlay: function (toggle) {
|
||||
initOverlay: function () {
|
||||
if (jQuery('#mailpoet_modal_overlay').length === 0) {
|
||||
// insert overlay into the DOM
|
||||
jQuery('body').append(this.templates.overlay);
|
||||
@ -343,20 +344,21 @@ define('modal', ['mailpoet', 'jquery'],
|
||||
return this;
|
||||
},
|
||||
setPosition: function () {
|
||||
var screenWidth;
|
||||
var screenHeight;
|
||||
var modalWidth;
|
||||
var modalHeight;
|
||||
switch (this.options.type) {
|
||||
case 'popup':
|
||||
var screenWidth = jQuery(window).width(),
|
||||
screenHeight = jQuery(window).height(),
|
||||
modalWidth = jQuery('.mailpoet_' + this.options.type + '_wrapper').width(),
|
||||
modalHeight = jQuery('.mailpoet_' + this.options.type + '_wrapper').height();
|
||||
screenWidth = jQuery(window).width();
|
||||
screenHeight = jQuery(window).height();
|
||||
modalWidth = jQuery('.mailpoet_'+ this.options.type +'_wrapper').width();
|
||||
modalHeight = jQuery('.mailpoet_'+ this.options.type +'_wrapper').height();
|
||||
|
||||
var top = Math.max(48, parseInt((screenHeight / 2) - (modalHeight / 2))),
|
||||
left = Math.max(0, parseInt((screenWidth / 2) - (modalWidth / 2)));
|
||||
|
||||
// set position of popup depending on screen dimensions.
|
||||
// set position of popup depending on screen dimensions.
|
||||
jQuery('#mailpoet_popup').css({
|
||||
top: top,
|
||||
left: left
|
||||
top: Math.max(48, parseInt((screenHeight / 2) - (modalHeight / 2))),
|
||||
left: Math.max(0, parseInt((screenWidth / 2) - (modalWidth / 2)))
|
||||
});
|
||||
break;
|
||||
case 'panel':
|
||||
@ -436,7 +438,7 @@ define('modal', ['mailpoet', 'jquery'],
|
||||
.removeClass('mailpoet_modal_highlight');
|
||||
return this;
|
||||
},
|
||||
hideModal: function (callback) {
|
||||
hideModal: function () {
|
||||
// set modal as closed
|
||||
this.opened = false;
|
||||
|
||||
@ -451,7 +453,7 @@ define('modal', ['mailpoet', 'jquery'],
|
||||
|
||||
return this;
|
||||
},
|
||||
showOverlay: function (force) {
|
||||
showOverlay: function () {
|
||||
jQuery('#mailpoet_modal_overlay').show();
|
||||
return this;
|
||||
},
|
||||
|
@ -1,12 +1,8 @@
|
||||
define([
|
||||
'backbone',
|
||||
'backbone.marionette',
|
||||
'backbone.radio',
|
||||
'jquery',
|
||||
'underscore',
|
||||
'handlebars',
|
||||
'handlebars_helpers'
|
||||
], function (Backbone, Marionette, BackboneRadio, jQuery, _, Handlebars) {
|
||||
'backbone.radio'
|
||||
], function (Backbone, Marionette, BackboneRadio) {
|
||||
var Radio = BackboneRadio;
|
||||
|
||||
var AppView = Marionette.View.extend({
|
||||
|
@ -8,13 +8,13 @@ define([
|
||||
'newsletter_editor/behaviors/BehaviorsLookup',
|
||||
'mailpoet',
|
||||
'spectrum'
|
||||
], function (Marionette, BehaviorsLookup, MailPoet, Spectrum) {
|
||||
], function (Marionette, BehaviorsLookup, MailPoet) {
|
||||
var BL = BehaviorsLookup;
|
||||
|
||||
BL.ColorPickerBehavior = Marionette.Behavior.extend({
|
||||
onRender: function () {
|
||||
var that = this,
|
||||
preferredFormat = 'hex6';
|
||||
var that = this;
|
||||
var preferredFormat = 'hex6';
|
||||
this.view.$('.mailpoet_color').each(function () {
|
||||
var $input = that.view.$(this);
|
||||
var updateColorInput = function (color) {
|
||||
|
@ -25,11 +25,11 @@ define([
|
||||
this.addDropZone();
|
||||
}
|
||||
},
|
||||
addDropZone: function (_event) {
|
||||
var that = this,
|
||||
view = this.view,
|
||||
domElement = that.$el.get(0),
|
||||
acceptableElementSelector;
|
||||
addDropZone: function () {
|
||||
var that = this;
|
||||
var view = this.view;
|
||||
var domElement = that.$el.get(0);
|
||||
var acceptableElementSelector;
|
||||
|
||||
// TODO: Extract this limitation code to be controlled from containers
|
||||
if (this.view.renderOptions.depth === 0) {
|
||||
@ -47,11 +47,11 @@ define([
|
||||
interact(domElement).dropzone({
|
||||
accept: acceptableElementSelector,
|
||||
overlap: 'pointer', // Mouse pointer denotes location of a droppable
|
||||
ondragenter: function (event) {
|
||||
ondragenter: function () {
|
||||
// 1. Visually mark block as active for dropping
|
||||
view.$el.addClass('mailpoet_drop_active');
|
||||
},
|
||||
ondragleave: function (event) {
|
||||
ondragleave: function () {
|
||||
// 1. Remove visual markings of active dropping container
|
||||
// 2. Remove visual markings of drop position visualization
|
||||
that.cleanup();
|
||||
@ -63,20 +63,26 @@ define([
|
||||
// 3b. If insertion is special, compute position (which side) and which cell the insertion belongs to
|
||||
// 4. If insertion at that position is not visualized, display position visualization there, remove other visualizations from this container
|
||||
var dropPosition = that.getDropPosition(
|
||||
event.dragmove.pageX,
|
||||
event.dragmove.pageY,
|
||||
view.$el,
|
||||
view.model.get('orientation'),
|
||||
view.model.get('blocks').length
|
||||
),
|
||||
element = view.$el,
|
||||
markerWidth = '',
|
||||
markerHeight = '',
|
||||
containerOffset = element.offset(),
|
||||
viewCollection = that.getCollection(),
|
||||
marker, targetModel, targetView, targetElement,
|
||||
topOffset, leftOffset, isLastBlockInsertion,
|
||||
$targetBlock, margin;
|
||||
event.dragmove.pageX,
|
||||
event.dragmove.pageY,
|
||||
view.$el,
|
||||
view.model.get('orientation'),
|
||||
view.model.get('blocks').length
|
||||
);
|
||||
var element = view.$el;
|
||||
var markerWidth = '';
|
||||
var markerHeight = '';
|
||||
var containerOffset = element.offset();
|
||||
var viewCollection = that.getCollection();
|
||||
var marker;
|
||||
var targetModel;
|
||||
var targetView;
|
||||
var targetElement;
|
||||
var topOffset;
|
||||
var leftOffset;
|
||||
var isLastBlockInsertion;
|
||||
var $targetBlock;
|
||||
var margin;
|
||||
|
||||
if (dropPosition === undefined) return;
|
||||
|
||||
@ -178,15 +184,19 @@ define([
|
||||
// 4. Perform cleanup actions
|
||||
|
||||
var dropPosition = that.getDropPosition(
|
||||
event.dragEvent.pageX,
|
||||
event.dragEvent.pageY,
|
||||
view.$el,
|
||||
view.model.get('orientation'),
|
||||
view.model.get('blocks').length
|
||||
),
|
||||
droppableModel = event.draggable.getDropModel(),
|
||||
viewCollection = that.getCollection(),
|
||||
droppedView, droppedModel, index, tempCollection, tempCollection2;
|
||||
event.dragEvent.pageX,
|
||||
event.dragEvent.pageY,
|
||||
view.$el,
|
||||
view.model.get('orientation'),
|
||||
view.model.get('blocks').length
|
||||
);
|
||||
var droppableModel = event.draggable.getDropModel();
|
||||
var viewCollection = that.getCollection();
|
||||
var droppedView;
|
||||
var index;
|
||||
var tempCollection;
|
||||
var tempCollection2;
|
||||
var tempModel;
|
||||
|
||||
if (dropPosition === undefined) return;
|
||||
|
||||
@ -210,7 +220,7 @@ define([
|
||||
} else {
|
||||
// Special insertion by replacing target block with collection
|
||||
// and inserting dropModel into that
|
||||
var tempModel = viewCollection.at(dropPosition.index);
|
||||
tempModel = viewCollection.at(dropPosition.index);
|
||||
|
||||
tempCollection = new (window.EditorApplication.getBlockTypeModel('container'))({
|
||||
orientation: (view.model.get('orientation') === 'vertical') ? 'horizontal' : 'vertical'
|
||||
@ -272,26 +282,30 @@ define([
|
||||
this.view.$('.mailpoet_drop_marker').remove();
|
||||
},
|
||||
getDropPosition: function (eventX, eventY, is_unsafe) {
|
||||
var SPECIAL_AREA_INSERTION_WIDTH = 0.00, // Disable special insertion. Default: 0.3
|
||||
var SPECIAL_AREA_INSERTION_WIDTH = 0.00; // Disable special insertion. Default: 0.3
|
||||
|
||||
element = this.view.$el,
|
||||
orientation = this.view.model.get('orientation'),
|
||||
var element = this.view.$el;
|
||||
var orientation = this.view.model.get('orientation');
|
||||
|
||||
elementOffset = element.offset(),
|
||||
elementPageX = elementOffset.left,
|
||||
elementPageY = elementOffset.top,
|
||||
elementWidth = element.outerWidth(true),
|
||||
elementHeight = element.outerHeight(true),
|
||||
var elementOffset = element.offset();
|
||||
var elementPageX = elementOffset.left;
|
||||
var elementPageY = elementOffset.top;
|
||||
var elementWidth = element.outerWidth(true);
|
||||
var elementHeight = element.outerHeight(true);
|
||||
|
||||
relativeX = eventX - elementPageX,
|
||||
relativeY = eventY - elementPageY,
|
||||
var relativeX = eventX - elementPageX;
|
||||
var relativeY = eventY - elementPageY;
|
||||
|
||||
relativeOffset, elementLength,
|
||||
var relativeOffset;
|
||||
var elementLength;
|
||||
|
||||
canAcceptNormalInsertion = this._canAcceptNormalInsertion(),
|
||||
canAcceptSpecialInsertion = this._canAcceptSpecialInsertion(),
|
||||
var canAcceptNormalInsertion = this._canAcceptNormalInsertion();
|
||||
var canAcceptSpecialInsertion = this._canAcceptSpecialInsertion();
|
||||
|
||||
insertionType, index, position, indexAndPosition;
|
||||
var insertionType;
|
||||
var index;
|
||||
var position;
|
||||
var indexAndPosition;
|
||||
|
||||
var unsafe = !!is_unsafe;
|
||||
|
||||
@ -359,12 +373,14 @@ define([
|
||||
// target element if event happens on the second half of the element.
|
||||
// Halves depend on orientation.
|
||||
|
||||
var index = this._computeCellIndex(eventX, eventY),
|
||||
// TODO: Handle case when there are no children, container is empty
|
||||
targetView = this.getChildren().findByModel(this.getCollection().at(index)),
|
||||
orientation = this.view.model.get('orientation'),
|
||||
element = targetView.$el,
|
||||
eventOffset, closeOffset, elementDimension;
|
||||
var index = this._computeCellIndex(eventX, eventY);
|
||||
// TODO: Handle case when there are no children, container is empty
|
||||
var targetView = this.getChildren().findByModel(this.getCollection().at(index));
|
||||
var orientation = this.view.model.get('orientation');
|
||||
var element = targetView.$el;
|
||||
var eventOffset;
|
||||
var closeOffset;
|
||||
var elementDimension;
|
||||
|
||||
if (orientation === 'vertical') {
|
||||
eventOffset = eventY;
|
||||
@ -394,39 +410,40 @@ define([
|
||||
return this._computeCellIndex(eventX, eventY);
|
||||
},
|
||||
_computeCellIndex: function (eventX, eventY) {
|
||||
var orientation = this.view.model.get('orientation'),
|
||||
eventOffset = (orientation === 'vertical') ? eventY : eventX,
|
||||
resultView = this.getChildren().find(function (view) {
|
||||
var element = view.$el,
|
||||
closeOffset, farOffset;
|
||||
var orientation = this.view.model.get('orientation');
|
||||
var eventOffset = (orientation === 'vertical') ? eventY : eventX;
|
||||
var resultView = this.getChildren().find(function (view) {
|
||||
var element = view.$el;
|
||||
var closeOffset;
|
||||
var farOffset;
|
||||
|
||||
if (orientation === 'vertical') {
|
||||
closeOffset = element.offset().top;
|
||||
farOffset = element.outerHeight(true);
|
||||
} else {
|
||||
closeOffset = element.offset().left;
|
||||
farOffset = element.outerWidth(true);
|
||||
}
|
||||
farOffset += closeOffset;
|
||||
if (orientation === 'vertical') {
|
||||
closeOffset = element.offset().top;
|
||||
farOffset = element.outerHeight(true);
|
||||
} else {
|
||||
closeOffset = element.offset().left;
|
||||
farOffset = element.outerWidth(true);
|
||||
}
|
||||
farOffset += closeOffset;
|
||||
|
||||
return closeOffset <= eventOffset && eventOffset <= farOffset;
|
||||
});
|
||||
return closeOffset <= eventOffset && eventOffset <= farOffset;
|
||||
});
|
||||
|
||||
var index = (typeof resultView === 'object') ? resultView._index : 0;
|
||||
|
||||
return index;
|
||||
},
|
||||
_canAcceptNormalInsertion: function () {
|
||||
var orientation = this.view.model.get('orientation'),
|
||||
depth = this.view.renderOptions.depth,
|
||||
childCount = this.getChildren().length;
|
||||
var orientation = this.view.model.get('orientation');
|
||||
var depth = this.view.renderOptions.depth;
|
||||
var childCount = this.getChildren().length;
|
||||
// Note that depth is zero indexed. Root container has depth=0
|
||||
return orientation === 'vertical' || (orientation === 'horizontal' && depth === 1 && childCount < this.options.columnLimit);
|
||||
},
|
||||
_canAcceptSpecialInsertion: function () {
|
||||
var orientation = this.view.model.get('orientation'),
|
||||
depth = this.view.renderOptions.depth,
|
||||
childCount = this.getChildren().length;
|
||||
var orientation = this.view.model.get('orientation');
|
||||
var depth = this.view.renderOptions.depth;
|
||||
var childCount = this.getChildren().length;
|
||||
return depth === 0 || (depth === 1 && orientation === 'horizontal' && childCount <= this.options.columnLimit);
|
||||
},
|
||||
getCollectionView: function () {
|
||||
|
@ -28,12 +28,12 @@ define([
|
||||
throw "Missing 'drop' function for DraggableBehavior";
|
||||
},
|
||||
|
||||
onDrop: function (model, view) {},
|
||||
testAttachToInstance: function (model, view) { return true; }
|
||||
onDrop: function () {},
|
||||
testAttachToInstance: function () { return true; }
|
||||
},
|
||||
onRender: function () {
|
||||
var that = this,
|
||||
interactable;
|
||||
var that = this;
|
||||
var interactable;
|
||||
|
||||
// Give instances more control over whether Draggable should be applied
|
||||
if (!this.options.testAttachToInstance(this.view.model, this.view)) return;
|
||||
@ -49,16 +49,19 @@ define([
|
||||
|
||||
onstart: function (startEvent) {
|
||||
var event = startEvent;
|
||||
var centerXOffset;
|
||||
var centerYOffset;
|
||||
var tempClone;
|
||||
var clone;
|
||||
var $clone;
|
||||
|
||||
if (that.options.cloneOriginal === true) {
|
||||
// Use substitution instead of a clone
|
||||
var tempClone = (_.isFunction(that.options.onDragSubstituteBy)) ? that.options.onDragSubstituteBy(that) : undefined,
|
||||
// Or use a clone
|
||||
clone = tempClone || event.target.cloneNode(true),
|
||||
|
||||
$original = jQuery(event.target),
|
||||
$clone = jQuery(clone),
|
||||
centerXOffset, centerYOffset, parentOffset;
|
||||
tempClone = (_.isFunction(that.options.onDragSubstituteBy)) ? that.options.onDragSubstituteBy(that) : undefined;
|
||||
// Or use a clone
|
||||
clone = tempClone || event.target.cloneNode(true);
|
||||
jQuery(event.target);
|
||||
$clone = jQuery(clone);
|
||||
|
||||
$clone.addClass('mailpoet_droppable_active');
|
||||
$clone.css('position', 'absolute');
|
||||
@ -85,10 +88,10 @@ define([
|
||||
},
|
||||
// call this function on every dragmove event
|
||||
onmove: function (event) {
|
||||
var target = event.target,
|
||||
// keep the dragged position in the data-x/data-y attributes
|
||||
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
|
||||
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
|
||||
var target = event.target;
|
||||
// keep the dragged position in the data-x/data-y attributes
|
||||
var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
|
||||
var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
|
||||
|
||||
// translate the element
|
||||
target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
|
||||
|
@ -14,12 +14,13 @@ define([
|
||||
defaults: {
|
||||
elementSelector: null,
|
||||
resizeHandleSelector: true, // true will use edges of the element itself
|
||||
transformationFunction: function (y) { return y; }, // for blocks that use the default onResize function
|
||||
minLength: 0,
|
||||
maxLength: Infinity,
|
||||
modelField: 'styles.block.height',
|
||||
onResize: function (event) {
|
||||
var currentLength = parseFloat(this.view.model.get(this.options.modelField)),
|
||||
newLength = currentLength + event.y;
|
||||
var currentLength = parseFloat(this.view.model.get(this.options.modelField));
|
||||
var newLength = currentLength + this.options.transformationFunction(event.dy);
|
||||
newLength = Math.min(this.options.maxLength, Math.max(this.options.minLength, newLength));
|
||||
this.view.model.set(this.options.modelField, newLength + 'px');
|
||||
}
|
||||
@ -36,8 +37,8 @@ define([
|
||||
}
|
||||
},
|
||||
attachResize: function () {
|
||||
var domElement = (this.options.elementSelector === null) ? this.view.$el.get(0) : this.view.$(this.options.elementSelector).get(0),
|
||||
that = this;
|
||||
var domElement = (this.options.elementSelector === null) ? this.view.$el.get(0) : this.view.$(this.options.elementSelector).get(0);
|
||||
var that = this;
|
||||
interact(domElement).resizable({
|
||||
// axis: 'y',
|
||||
edges: {
|
||||
@ -47,7 +48,7 @@ define([
|
||||
bottom: (typeof this.options.resizeHandleSelector === 'string') ? this.view.$(this.options.resizeHandleSelector).get(0) : this.options.resizeHandleSelector
|
||||
}
|
||||
})
|
||||
.on('resizestart', function (event) {
|
||||
.on('resizestart', function () {
|
||||
that.isBeingResized = true;
|
||||
that.$el.addClass('mailpoet_resize_active');
|
||||
})
|
||||
@ -55,7 +56,7 @@ define([
|
||||
var onResize = that.options.onResize.bind(that);
|
||||
return onResize(event);
|
||||
})
|
||||
.on('resizeend', function (event) {
|
||||
.on('resizeend', function () {
|
||||
that.isBeingResized = null;
|
||||
that.$el.removeClass('mailpoet_resize_active');
|
||||
});
|
||||
|
@ -24,9 +24,9 @@ define([
|
||||
ui.item.removeData('previousIndex');
|
||||
},
|
||||
update: function (event, ui) {
|
||||
var previousIndex = ui.item.data('previousIndex'),
|
||||
newIndex = ui.item.index(),
|
||||
model = collection.at(previousIndex);
|
||||
var previousIndex = ui.item.data('previousIndex');
|
||||
var newIndex = ui.item.index();
|
||||
var model = collection.at(previousIndex);
|
||||
|
||||
// Replicate DOM changes. Move target model to a new position
|
||||
// within the collection
|
||||
|
@ -42,7 +42,7 @@ define([
|
||||
relative_urls: false,
|
||||
remove_script_host: false,
|
||||
convert_urls: true,
|
||||
urlconverter_callback: function (url, node, on_save, name) {
|
||||
urlconverter_callback: function (url) {
|
||||
if (url.match(/\[.+\]/g)) {
|
||||
// Do not convert URLs with shortcodes
|
||||
return url;
|
||||
@ -57,7 +57,7 @@ define([
|
||||
plugins: this.options.plugins,
|
||||
|
||||
setup: function (editor) {
|
||||
editor.on('change', function (e) {
|
||||
editor.on('change', function () {
|
||||
that.view.triggerMethod('text:editor:change', editor.getContent());
|
||||
});
|
||||
|
||||
@ -71,12 +71,12 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
editor.on('focus', function (e) {
|
||||
editor.on('focus', function () {
|
||||
that.view.triggerMethod('text:editor:focus');
|
||||
that._isActivationClick = true;
|
||||
});
|
||||
|
||||
editor.on('blur', function (e) {
|
||||
editor.on('blur', function () {
|
||||
that.view.triggerMethod('text:editor:blur');
|
||||
});
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
|
||||
Module.ALCSupervisor = SuperModel.extend({
|
||||
initialize: function () {
|
||||
@ -43,12 +43,13 @@ define([
|
||||
);
|
||||
},
|
||||
refresh: function () {
|
||||
var blocks;
|
||||
var models = App.findModels(function (model) {
|
||||
return model.get('type') === 'automatedLatestContent';
|
||||
}) || [];
|
||||
|
||||
if (models.length === 0) return;
|
||||
var blocks = _.map(models, function (model) {
|
||||
blocks = _.map(models, function (model) {
|
||||
return model.toJSON();
|
||||
});
|
||||
|
||||
@ -60,8 +61,8 @@ define([
|
||||
_.each(
|
||||
_.zip(models, renderedBlocks),
|
||||
function (args) {
|
||||
var model = args[0],
|
||||
contents = args[1];
|
||||
var model = args[0];
|
||||
var contents = args[1];
|
||||
model.trigger('refreshPosts', contents);
|
||||
}
|
||||
);
|
||||
@ -150,12 +151,12 @@ define([
|
||||
}),
|
||||
onDragSubstituteBy: function () { return Module.AutomatedLatestContentWidgetView; },
|
||||
onRender: function () {
|
||||
var ContainerView = App.getBlockTypeView('container'),
|
||||
renderOptions = {
|
||||
disableTextEditor: true,
|
||||
disableDragAndDrop: true,
|
||||
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay')
|
||||
};
|
||||
var ContainerView = App.getBlockTypeView('container');
|
||||
var renderOptions = {
|
||||
disableTextEditor: true,
|
||||
disableDragAndDrop: true,
|
||||
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay')
|
||||
};
|
||||
this.toolsView = new Module.AutomatedLatestContentBlockToolsView({ model: this.model });
|
||||
this.showChildView('toolsRegion', this.toolsView);
|
||||
this.showChildView('postsRegion', new ContainerView({ model: this.model.get('_container'), renderOptions: renderOptions }));
|
||||
@ -213,12 +214,13 @@ define([
|
||||
},
|
||||
transport: function (options, success, failure) {
|
||||
var taxonomies;
|
||||
var termsPromise;
|
||||
var promise = CommunicationComponent.getTaxonomies(
|
||||
that.model.get('contentType')
|
||||
).then(function (tax) {
|
||||
taxonomies = tax;
|
||||
// Fetch available terms based on the list of taxonomies already fetched
|
||||
var promise = CommunicationComponent.getTerms({
|
||||
termsPromise = CommunicationComponent.getTerms({
|
||||
search: options.data.term,
|
||||
taxonomies: _.keys(taxonomies)
|
||||
}).then(function (terms) {
|
||||
@ -227,7 +229,7 @@ define([
|
||||
terms: terms
|
||||
};
|
||||
});
|
||||
return promise;
|
||||
return termsPromise;
|
||||
});
|
||||
|
||||
promise.then(success);
|
||||
@ -264,9 +266,9 @@ define([
|
||||
}
|
||||
}).trigger('change');
|
||||
},
|
||||
toggleDisplayOptions: function (event) {
|
||||
var el = this.$('.mailpoet_automated_latest_content_display_options'),
|
||||
showControl = this.$('.mailpoet_automated_latest_content_show_display_options');
|
||||
toggleDisplayOptions: function () {
|
||||
var el = this.$('.mailpoet_automated_latest_content_display_options');
|
||||
var showControl = this.$('.mailpoet_automated_latest_content_show_display_options');
|
||||
if (el.hasClass('mailpoet_closed')) {
|
||||
el.removeClass('mailpoet_closed');
|
||||
showControl.addClass('mailpoet_hidden');
|
||||
@ -275,7 +277,7 @@ define([
|
||||
showControl.removeClass('mailpoet_hidden');
|
||||
}
|
||||
},
|
||||
showButtonSettings: function (event) {
|
||||
showButtonSettings: function () {
|
||||
var buttonModule = ButtonBlock;
|
||||
(new buttonModule.ButtonBlockSettingsView({
|
||||
model: this.model.get('readMoreButton'),
|
||||
@ -286,7 +288,7 @@ define([
|
||||
}
|
||||
})).render();
|
||||
},
|
||||
showDividerSettings: function (event) {
|
||||
showDividerSettings: function () {
|
||||
var dividerModule = DividerBlock;
|
||||
(new dividerModule.DividerBlockSettingsView({
|
||||
model: this.model.get('divider'),
|
||||
@ -349,8 +351,8 @@ define([
|
||||
this.changeField('titleFormat', event);
|
||||
},
|
||||
_updateContentTypes: function (postTypes) {
|
||||
var select = this.$('.mailpoet_automated_latest_content_content_type'),
|
||||
selectedValue = this.model.get('contentType');
|
||||
var select = this.$('.mailpoet_automated_latest_content_content_type');
|
||||
var selectedValue = this.model.get('contentType');
|
||||
|
||||
select.find('option').remove();
|
||||
_.each(postTypes, function (type) {
|
||||
@ -378,7 +380,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('automatedLatestContent', {
|
||||
blockModel: Module.AutomatedLatestContentBlockModel,
|
||||
blockView: Module.AutomatedLatestContentBlockView
|
||||
@ -391,7 +393,7 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
App.on('start', function (App, options) {
|
||||
App.on('start', function (App) {
|
||||
var Application = App;
|
||||
Application._ALCSupervisor = new Module.ALCSupervisor();
|
||||
Application._ALCSupervisor.refresh();
|
||||
|
@ -12,17 +12,16 @@ define([
|
||||
'jquery',
|
||||
'mailpoet',
|
||||
'modal'
|
||||
], function (App, Marionette, SuperModel, _, jQuery, MailPoet, Modal) {
|
||||
], function (App, Marionette, SuperModel, _, jQuery, MailPoet) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
AugmentedView = Marionette.View.extend({});
|
||||
var Module = {};
|
||||
var AugmentedView = Marionette.View.extend({});
|
||||
|
||||
Module.BlockModel = SuperModel.extend({
|
||||
stale: [], // Attributes to be removed upon saving
|
||||
initialize: function () {
|
||||
var that = this;
|
||||
this.on('change', function () {
|
||||
App.getChannel().trigger('autoSave');
|
||||
});
|
||||
@ -68,7 +67,8 @@ define([
|
||||
options.dragBehavior.view.model.destroy();
|
||||
},
|
||||
onDragSubstituteBy: function (behavior) {
|
||||
var WidgetView, node;
|
||||
var WidgetView;
|
||||
var node;
|
||||
// When block is being dragged, display the widget icon instead.
|
||||
// This will create an instance of block's widget view and
|
||||
// use it's rendered DOM element instead of the content block
|
||||
@ -98,13 +98,13 @@ define([
|
||||
this.on('dom:refresh', this.showBlock, this);
|
||||
this._isFirstRender = true;
|
||||
},
|
||||
showTools: function (_event) {
|
||||
showTools: function () {
|
||||
if (!this.showingToolsDisabled) {
|
||||
this.$('> .mailpoet_tools').addClass('mailpoet_display_tools');
|
||||
this.toolsView.triggerMethod('showTools');
|
||||
}
|
||||
},
|
||||
hideTools: function (e) {
|
||||
hideTools: function () {
|
||||
this.$('> .mailpoet_tools').removeClass('mailpoet_display_tools');
|
||||
this.toolsView.triggerMethod('hideTools');
|
||||
},
|
||||
@ -240,8 +240,9 @@ define([
|
||||
ColorPickerBehavior: {}
|
||||
},
|
||||
initialize: function (params) {
|
||||
var panelParams;
|
||||
this.model.trigger('startEditing');
|
||||
var panelParams = {
|
||||
panelParams = {
|
||||
element: this.$el,
|
||||
template: '',
|
||||
position: 'right',
|
||||
@ -262,7 +263,7 @@ define([
|
||||
model: this.model.toJSON()
|
||||
};
|
||||
},
|
||||
close: function (event) {
|
||||
close: function () {
|
||||
this.destroy();
|
||||
},
|
||||
changeField: function (field, event) {
|
||||
|
@ -11,8 +11,8 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
|
||||
Module.ButtonBlockModel = base.BlockModel.extend({
|
||||
defaults: function () {
|
||||
@ -132,7 +132,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('button', {
|
||||
blockModel: Module.ButtonBlockModel,
|
||||
blockView: Module.ButtonBlockView
|
||||
|
@ -14,9 +14,9 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock,
|
||||
BlockCollection;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
var BlockCollection;
|
||||
|
||||
BlockCollection = Backbone.Collection.extend({
|
||||
model: base.BlockModel,
|
||||
@ -24,7 +24,6 @@ define([
|
||||
this.on('add change remove', function () { App.getChannel().trigger('autoSave'); });
|
||||
},
|
||||
parse: function (response) {
|
||||
var self = this;
|
||||
return _.map(response, function (block) {
|
||||
var Type = App.getBlockTypeModel(block.type);
|
||||
// TODO: If type has no registered model, use a backup one
|
||||
@ -66,7 +65,7 @@ define([
|
||||
return response;
|
||||
},
|
||||
getChildren: function () {
|
||||
var models = this.get('blocks').map(function (model, index, list) {
|
||||
var models = this.get('blocks').map(function (model) {
|
||||
return [model, model.getChildren()];
|
||||
});
|
||||
|
||||
@ -121,7 +120,8 @@ define([
|
||||
options.dragBehavior.view.model.destroy();
|
||||
},
|
||||
onDragSubstituteBy: function (behavior) {
|
||||
var WidgetView, node;
|
||||
var WidgetView;
|
||||
var node;
|
||||
// When block is being dragged, display the widget icon instead.
|
||||
// This will create an instance of block's widget view and
|
||||
// use it's rendered DOM element instead of the content block
|
||||
@ -190,24 +190,24 @@ define([
|
||||
}
|
||||
},
|
||||
toggleEditingLayer: function (event) {
|
||||
var that = this,
|
||||
$toggleButton = this.$('> .mailpoet_tools .mailpoet_newsletter_layer_selector'),
|
||||
$overlay = jQuery('.mailpoet_layer_overlay'),
|
||||
$container = this.$('> .mailpoet_container'),
|
||||
enableContainerLayer = function () {
|
||||
that.$el.addClass('mailpoet_container_layer_active');
|
||||
$toggleButton.addClass('mailpoet_container_layer_active');
|
||||
$container.addClass('mailpoet_layer_highlight');
|
||||
$overlay.click(disableContainerLayer);
|
||||
$overlay.show();
|
||||
},
|
||||
disableContainerLayer = function () {
|
||||
that.$el.removeClass('mailpoet_container_layer_active');
|
||||
$toggleButton.removeClass('mailpoet_container_layer_active');
|
||||
$container.removeClass('mailpoet_layer_highlight');
|
||||
$overlay.hide();
|
||||
$overlay.off('click');
|
||||
};
|
||||
var that = this;
|
||||
var $toggleButton = this.$('> .mailpoet_tools .mailpoet_newsletter_layer_selector');
|
||||
var $overlay = jQuery('.mailpoet_layer_overlay');
|
||||
var $container = this.$('> .mailpoet_container');
|
||||
var enableContainerLayer = function () {
|
||||
that.$el.addClass('mailpoet_container_layer_active');
|
||||
$toggleButton.addClass('mailpoet_container_layer_active');
|
||||
$container.addClass('mailpoet_layer_highlight');
|
||||
$overlay.click(disableContainerLayer);
|
||||
$overlay.show();
|
||||
};
|
||||
var disableContainerLayer = function () {
|
||||
that.$el.removeClass('mailpoet_container_layer_active');
|
||||
$toggleButton.removeClass('mailpoet_container_layer_active');
|
||||
$container.removeClass('mailpoet_layer_highlight');
|
||||
$overlay.hide();
|
||||
$overlay.off('click');
|
||||
};
|
||||
if ($toggleButton.hasClass('mailpoet_container_layer_active')) {
|
||||
disableContainerLayer();
|
||||
} else {
|
||||
@ -336,7 +336,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('container', {
|
||||
blockModel: Module.ContainerBlockModel,
|
||||
blockView: Module.ContainerBlockView
|
||||
|
@ -5,14 +5,13 @@ define([
|
||||
'newsletter_editor/App',
|
||||
'newsletter_editor/blocks/base',
|
||||
'underscore',
|
||||
'jquery',
|
||||
'mailpoet'
|
||||
], function (App, BaseBlock, _, jQuery, MailPoet) {
|
||||
'jquery'
|
||||
], function (App, BaseBlock, _, jQuery) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
|
||||
Module.DividerBlockModel = base.BlockModel.extend({
|
||||
defaults: function () {
|
||||
@ -49,8 +48,8 @@ define([
|
||||
}, base.BlockView.prototype.behaviors),
|
||||
onDragSubstituteBy: function () { return Module.DividerWidgetView; },
|
||||
initialize: function () {
|
||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||
var that = this;
|
||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||
|
||||
// Listen for attempts to change all dividers in one go
|
||||
this._replaceDividerHandler = function (data) { that.model.set(data); that.model.trigger('applyToAll'); };
|
||||
@ -119,7 +118,7 @@ define([
|
||||
repaintDividerStyleOptions: function () {
|
||||
this.$('.mailpoet_field_divider_style > div').css('border-top-color', this.model.get('styles.block.borderColor'));
|
||||
},
|
||||
applyToAll: function (event) {
|
||||
applyToAll: function () {
|
||||
App.getChannel().trigger('replaceAllDividers', this.model.toJSON());
|
||||
},
|
||||
updateValueAndCall: function (fieldToUpdate, callable, event) {
|
||||
@ -139,7 +138,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('divider', {
|
||||
blockModel: Module.DividerBlockModel,
|
||||
blockView: Module.DividerBlockView
|
||||
|
@ -10,8 +10,8 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
|
||||
Module.FooterBlockModel = base.BlockModel.extend({
|
||||
defaults: function () {
|
||||
@ -110,7 +110,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('footer', {
|
||||
blockModel: Module.FooterBlockModel,
|
||||
blockView: Module.FooterBlockView
|
||||
|
@ -10,8 +10,8 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
|
||||
Module.HeaderBlockModel = base.BlockModel.extend({
|
||||
defaults: function () {
|
||||
@ -110,7 +110,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('header', {
|
||||
blockModel: Module.HeaderBlockModel,
|
||||
blockView: Module.HeaderBlockView
|
||||
|
@ -11,9 +11,9 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock,
|
||||
ImageWidgetView;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
var ImageWidgetView;
|
||||
|
||||
Module.ImageBlockModel = base.BlockModel.extend({
|
||||
defaults: function () {
|
||||
@ -48,8 +48,8 @@ define([
|
||||
elementSelector: '.mailpoet_image',
|
||||
resizeHandleSelector: '.mailpoet_image_resize_handle',
|
||||
onResize: function (event) {
|
||||
var corner = this.$('.mailpoet_image').offset(),
|
||||
width = event.pageX - corner.left;
|
||||
var corner = this.$('.mailpoet_image').offset();
|
||||
var width = event.pageX - corner.left;
|
||||
this.view.model.set('width', width + 'px');
|
||||
}
|
||||
},
|
||||
@ -127,13 +127,16 @@ define([
|
||||
}
|
||||
},
|
||||
showMediaManager: function () {
|
||||
var that = this;
|
||||
var MediaManager;
|
||||
var theFrame;
|
||||
if (this._mediaManager) {
|
||||
this._mediaManager.resetSelections();
|
||||
this._mediaManager.open();
|
||||
return;
|
||||
}
|
||||
|
||||
var MediaManager = window.wp.media.view.MediaFrame.Select.extend({
|
||||
MediaManager = window.wp.media.view.MediaFrame.Select.extend({
|
||||
|
||||
initialize: function () {
|
||||
window.wp.media.view.MediaFrame.prototype.initialize.apply(this, arguments);
|
||||
@ -196,6 +199,7 @@ define([
|
||||
},
|
||||
|
||||
bindHandlers: function () {
|
||||
var handlers;
|
||||
// from Select
|
||||
this.on('router:create:browse', this.createRouter, this);
|
||||
this.on('router:render:browse', this.browseRouter, this);
|
||||
@ -210,7 +214,7 @@ define([
|
||||
|
||||
this.on('updateExcluded', this.browseContent, this);
|
||||
|
||||
var handlers = {
|
||||
handlers = {
|
||||
content: {
|
||||
embed: 'embedContent',
|
||||
'edit-selection': 'editSelectionContent'
|
||||
@ -244,9 +248,9 @@ define([
|
||||
},
|
||||
|
||||
editSelectionContent: function () {
|
||||
var state = this.state(),
|
||||
selection = state.get('selection'),
|
||||
view;
|
||||
var state = this.state();
|
||||
var selection = state.get('selection');
|
||||
var view;
|
||||
|
||||
view = new window.wp.media.view.AttachmentsBrowser({
|
||||
controller: this,
|
||||
@ -302,8 +306,8 @@ define([
|
||||
requires: { selection: true },
|
||||
|
||||
click: function () {
|
||||
var state = controller.state(),
|
||||
selection = state.get('selection');
|
||||
var state = controller.state();
|
||||
var selection = state.get('selection');
|
||||
|
||||
controller.close();
|
||||
state.trigger('insert', selection).reset();
|
||||
@ -321,46 +325,42 @@ define([
|
||||
|
||||
});
|
||||
|
||||
var theFrame = new MediaManager({
|
||||
id: 'mailpoet-media-manager',
|
||||
frame: 'select',
|
||||
title: 'Select image',
|
||||
editing: false,
|
||||
multiple: false,
|
||||
library: {
|
||||
type: 'image'
|
||||
},
|
||||
displaySettings: false,
|
||||
button: {
|
||||
text: 'Select'
|
||||
}
|
||||
}),
|
||||
that = this;
|
||||
theFrame = new MediaManager({
|
||||
id: 'mailpoet-media-manager',
|
||||
frame: 'select',
|
||||
title: 'Select image',
|
||||
editing: false,
|
||||
multiple: false,
|
||||
library: {
|
||||
type: 'image'
|
||||
},
|
||||
displaySettings: false,
|
||||
button: {
|
||||
text: 'Select'
|
||||
}
|
||||
});
|
||||
this._mediaManager = theFrame;
|
||||
|
||||
this._mediaManager.on('insert', function () {
|
||||
// Append media manager image selections to Images tab
|
||||
var selection = theFrame.state().get('selection');
|
||||
selection.each(function (attachment) {
|
||||
var sizes = attachment.get('sizes'),
|
||||
// Following advice from Becs, the target width should
|
||||
// be a double of one column width to render well on
|
||||
// retina screen devices
|
||||
targetImageWidth = 1320,
|
||||
var sizes = attachment.get('sizes');
|
||||
// Following advice from Becs, the target width should
|
||||
// be a double of one column width to render well on
|
||||
// retina screen devices
|
||||
var targetImageWidth = 1320;
|
||||
|
||||
// For main image use the size, that's closest to being 660px in width
|
||||
sizeKeys = _.keys(sizes),
|
||||
// Pick the width that is closest to target width
|
||||
var increasingByWidthDifference = _.sortBy(
|
||||
_.keys(sizes),
|
||||
function (size) { return Math.abs(targetImageWidth - sizes[size].width); }
|
||||
);
|
||||
var bestWidth = sizes[_.first(increasingByWidthDifference)].width;
|
||||
var imagesOfBestWidth = _.filter(_.values(sizes), function (size) { return size.width === bestWidth; });
|
||||
|
||||
// Pick the width that is closest to target width
|
||||
increasingByWidthDifference = _.sortBy(
|
||||
_.keys(sizes),
|
||||
function (size) { return Math.abs(targetImageWidth - sizes[size].width); }
|
||||
),
|
||||
bestWidth = sizes[_.first(increasingByWidthDifference)].width,
|
||||
imagesOfBestWidth = _.filter(_.values(sizes), function (size) { return size.width === bestWidth; }),
|
||||
|
||||
// Maximize the height if there are multiple images with same width
|
||||
mainSize = _.max(imagesOfBestWidth, function (size) { return size.height; });
|
||||
// Maximize the height if there are multiple images with same width
|
||||
var mainSize = _.max(imagesOfBestWidth, function (size) { return size.height; });
|
||||
|
||||
that.model.set({
|
||||
height: mainSize.height + 'px',
|
||||
@ -413,7 +413,7 @@ define([
|
||||
});
|
||||
Module.ImageWidgetView = ImageWidgetView;
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('image', {
|
||||
blockModel: Module.ImageBlockModel,
|
||||
blockView: Module.ImageBlockView
|
||||
|
@ -39,8 +39,13 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
var PostsDisplayOptionsSettingsView;
|
||||
var SinglePostSelectionSettingsView;
|
||||
var EmptyPostSelectionSettingsView;
|
||||
var PostSelectionSettingsView;
|
||||
var PostsSelectionCollectionView;
|
||||
|
||||
Module.PostsBlockModel = base.BlockModel.extend({
|
||||
stale: ['_selectedPosts', '_availablePosts', '_transformedPosts'],
|
||||
@ -89,10 +94,9 @@ define([
|
||||
};
|
||||
},
|
||||
initialize: function () {
|
||||
var that = this,
|
||||
POST_REFRESH_DELAY_MS = 500,
|
||||
refreshAvailablePosts = _.debounce(this.fetchAvailablePosts.bind(this), POST_REFRESH_DELAY_MS),
|
||||
refreshTransformedPosts = _.debounce(this._refreshTransformedPosts.bind(this), POST_REFRESH_DELAY_MS);
|
||||
var POST_REFRESH_DELAY_MS = 500;
|
||||
var refreshAvailablePosts = _.debounce(this.fetchAvailablePosts.bind(this), POST_REFRESH_DELAY_MS);
|
||||
var refreshTransformedPosts = _.debounce(this._refreshTransformedPosts.bind(this), POST_REFRESH_DELAY_MS);
|
||||
|
||||
// Attach Radio.Requests API primarily for highlighting
|
||||
_.extend(this, Radio.Requests);
|
||||
@ -120,9 +124,9 @@ define([
|
||||
});
|
||||
},
|
||||
_loadMorePosts: function () {
|
||||
var that = this,
|
||||
postCount = this.get('_availablePosts').length,
|
||||
nextOffset = this.get('offset') + Number(this.get('amount'));
|
||||
var that = this;
|
||||
var postCount = this.get('_availablePosts').length;
|
||||
var nextOffset = this.get('offset') + Number(this.get('amount'));
|
||||
|
||||
if (postCount === 0 || postCount < nextOffset) {
|
||||
// No more posts to load
|
||||
@ -141,8 +145,8 @@ define([
|
||||
});
|
||||
},
|
||||
_refreshTransformedPosts: function () {
|
||||
var that = this,
|
||||
data = this.toJSON();
|
||||
var that = this;
|
||||
var data = this.toJSON();
|
||||
|
||||
data.posts = this.get('_selectedPosts').pluck('ID');
|
||||
|
||||
@ -158,10 +162,9 @@ define([
|
||||
});
|
||||
},
|
||||
_insertSelectedPosts: function () {
|
||||
var that = this,
|
||||
data = this.toJSON(),
|
||||
index = this.collection.indexOf(this),
|
||||
collection = this.collection;
|
||||
var data = this.toJSON();
|
||||
var index = this.collection.indexOf(this);
|
||||
var collection = this.collection;
|
||||
|
||||
data.posts = this.get('_selectedPosts').pluck('ID');
|
||||
|
||||
@ -190,17 +193,19 @@ define([
|
||||
this.model.reply('blockView', this.notifyAboutSelf, this);
|
||||
},
|
||||
onRender: function () {
|
||||
var ContainerView;
|
||||
var renderOptions;
|
||||
if (!this.getRegion('toolsRegion').hasView()) {
|
||||
this.showChildView('toolsRegion', this.toolsView);
|
||||
}
|
||||
this.trigger('showSettings');
|
||||
|
||||
var ContainerView = App.getBlockTypeView('container'),
|
||||
renderOptions = {
|
||||
disableTextEditor: true,
|
||||
disableDragAndDrop: true,
|
||||
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay')
|
||||
};
|
||||
ContainerView = App.getBlockTypeView('container');
|
||||
renderOptions = {
|
||||
disableTextEditor: true,
|
||||
disableDragAndDrop: true,
|
||||
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay')
|
||||
};
|
||||
this.showChildView('postsRegion', new ContainerView({ model: this.model.get('_transformedPosts'), renderOptions: renderOptions }));
|
||||
},
|
||||
notifyAboutSelf: function () {
|
||||
@ -237,8 +242,8 @@ define([
|
||||
this.displayOptionsView = new PostsDisplayOptionsSettingsView({ model: this.model });
|
||||
},
|
||||
onRender: function () {
|
||||
var that = this,
|
||||
blockView = this.model.request('blockView');
|
||||
var that = this;
|
||||
this.model.request('blockView');
|
||||
|
||||
this.showChildView('selectionRegion', this.selectionView);
|
||||
this.showChildView('displayOptionsRegion', this.displayOptionsView);
|
||||
@ -283,7 +288,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
var PostsSelectionCollectionView = Marionette.CollectionView.extend({
|
||||
PostsSelectionCollectionView = Marionette.CollectionView.extend({
|
||||
className: 'mailpoet_post_scroll_container',
|
||||
childView: function () { return SinglePostSelectionSettingsView; },
|
||||
emptyView: function () { return EmptyPostSelectionSettingsView; },
|
||||
@ -307,7 +312,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
var PostSelectionSettingsView = Marionette.View.extend({
|
||||
PostSelectionSettingsView = Marionette.View.extend({
|
||||
getTemplate: function () { return window.templates.postSelectionPostsBlockSettings; },
|
||||
regions: {
|
||||
posts: '.mailpoet_post_selection_container'
|
||||
@ -334,9 +339,10 @@ define([
|
||||
}
|
||||
},
|
||||
onRender: function () {
|
||||
var postsView;
|
||||
// Dynamically update available post types
|
||||
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
||||
var postsView = new PostsSelectionCollectionView({
|
||||
postsView = new PostsSelectionCollectionView({
|
||||
collection: this.model.get('_availablePosts'),
|
||||
blockModel: this.model
|
||||
});
|
||||
@ -358,12 +364,13 @@ define([
|
||||
},
|
||||
transport: function (options, success, failure) {
|
||||
var taxonomies;
|
||||
var termsPromise;
|
||||
var promise = CommunicationComponent.getTaxonomies(
|
||||
that.model.get('contentType')
|
||||
).then(function (tax) {
|
||||
taxonomies = tax;
|
||||
// Fetch available terms based on the list of taxonomies already fetched
|
||||
var promise = CommunicationComponent.getTerms({
|
||||
termsPromise = CommunicationComponent.getTerms({
|
||||
search: options.data.term,
|
||||
taxonomies: _.keys(taxonomies)
|
||||
}).then(function (terms) {
|
||||
@ -372,7 +379,7 @@ define([
|
||||
terms: terms
|
||||
};
|
||||
});
|
||||
return promise;
|
||||
return termsPromise;
|
||||
});
|
||||
|
||||
promise.then(success);
|
||||
@ -413,8 +420,8 @@ define([
|
||||
this.model.set(field, jQuery(event.target).val());
|
||||
},
|
||||
_updateContentTypes: function (postTypes) {
|
||||
var select = this.$('.mailpoet_settings_posts_content_type'),
|
||||
selectedValue = this.model.get('contentType');
|
||||
var select = this.$('.mailpoet_settings_posts_content_type');
|
||||
var selectedValue = this.model.get('contentType');
|
||||
|
||||
select.find('option').remove();
|
||||
_.each(postTypes, function (type) {
|
||||
@ -427,11 +434,11 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
var EmptyPostSelectionSettingsView = Marionette.View.extend({
|
||||
EmptyPostSelectionSettingsView = Marionette.View.extend({
|
||||
getTemplate: function () { return window.templates.emptyPostPostsBlockSettings; }
|
||||
});
|
||||
|
||||
var SinglePostSelectionSettingsView = Marionette.View.extend({
|
||||
SinglePostSelectionSettingsView = Marionette.View.extend({
|
||||
getTemplate: function () { return window.templates.singlePostPostsBlockSettings; },
|
||||
events: function () {
|
||||
return {
|
||||
@ -448,8 +455,8 @@ define([
|
||||
this.blockModel = options.blockModel;
|
||||
},
|
||||
postSelectionChange: function (event) {
|
||||
var checkBox = jQuery(event.target),
|
||||
selectedPostsCollection = this.blockModel.get('_selectedPosts');
|
||||
var checkBox = jQuery(event.target);
|
||||
var selectedPostsCollection = this.blockModel.get('_selectedPosts');
|
||||
if (checkBox.prop('checked')) {
|
||||
selectedPostsCollection.add(this.model);
|
||||
} else {
|
||||
@ -458,7 +465,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
var PostsDisplayOptionsSettingsView = base.BlockSettingsView.extend({
|
||||
PostsDisplayOptionsSettingsView = base.BlockSettingsView.extend({
|
||||
getTemplate: function () { return window.templates.displayOptionsPostsBlockSettings; },
|
||||
events: function () {
|
||||
return {
|
||||
@ -488,7 +495,7 @@ define([
|
||||
model: this.model.toJSON()
|
||||
};
|
||||
},
|
||||
showButtonSettings: function (event) {
|
||||
showButtonSettings: function () {
|
||||
var buttonModule = ButtonBlock;
|
||||
(new buttonModule.ButtonBlockSettingsView({
|
||||
model: this.model.get('readMoreButton'),
|
||||
@ -499,7 +506,7 @@ define([
|
||||
}
|
||||
})).render();
|
||||
},
|
||||
showDividerSettings: function (event) {
|
||||
showDividerSettings: function () {
|
||||
var dividerModule = DividerBlock;
|
||||
(new dividerModule.DividerBlockSettingsView({
|
||||
model: this.model.get('divider'),
|
||||
@ -575,7 +582,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('posts', {
|
||||
blockModel: Module.PostsBlockModel,
|
||||
blockView: Module.PostsBlockView
|
||||
|
@ -13,12 +13,13 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock,
|
||||
SocialBlockSettingsIconSelectorView,
|
||||
SocialBlockSettingsIconView,
|
||||
SocialBlockSettingsIconCollectionView,
|
||||
SocialBlockSettingsStylesView;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
var SocialBlockSettingsIconSelectorView;
|
||||
var SocialBlockSettingsIconView;
|
||||
var SocialBlockSettingsIconCollectionView;
|
||||
var SocialBlockSettingsStylesView;
|
||||
var SocialIconView;
|
||||
|
||||
Module.SocialIconModel = SuperModel.extend({
|
||||
defaults: function () {
|
||||
@ -33,12 +34,12 @@ define([
|
||||
text: defaultValues.get('title')
|
||||
};
|
||||
},
|
||||
initialize: function (options) {
|
||||
initialize: function () {
|
||||
var that = this;
|
||||
// Make model swap to default values for that type when iconType changes
|
||||
this.on('change:iconType', function () {
|
||||
var defaultValues = App.getConfig().get('socialIcons').get(that.get('iconType')),
|
||||
iconSet = that.collection.iconBlockModel.getIconSet();
|
||||
var defaultValues = App.getConfig().get('socialIcons').get(that.get('iconType'));
|
||||
var iconSet = that.collection.iconBlockModel.getIconSet();
|
||||
this.set({
|
||||
link: defaultValues.get('defaultLink'),
|
||||
image: iconSet.get(that.get('iconType')),
|
||||
@ -83,7 +84,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
var SocialIconView = Marionette.View.extend({
|
||||
SocialIconView = Marionette.View.extend({
|
||||
tagName: 'span',
|
||||
getTemplate: function () { return window.templates.socialIconBlock; },
|
||||
modelEvents: {
|
||||
@ -175,10 +176,10 @@ define([
|
||||
}
|
||||
},
|
||||
templateContext: function () {
|
||||
var icons = App.getConfig().get('socialIcons'),
|
||||
// Construct icon type list of format [{iconType: 'type', title: 'Title'}, ...]
|
||||
availableIconTypes = _.map(_.keys(icons.attributes), function (key) { return { iconType: key, title: icons.get(key).get('title') }; }),
|
||||
allIconSets = App.getAvailableStyles().get('socialIconSets');
|
||||
var icons = App.getConfig().get('socialIcons');
|
||||
// Construct icon type list of format [{iconType: 'type', title: 'Title'}, ...]
|
||||
var availableIconTypes = _.map(_.keys(icons.attributes), function (key) { return { iconType: key, title: icons.get(key).get('title') }; });
|
||||
var allIconSets = App.getAvailableStyles().get('socialIconSets');
|
||||
return _.extend({}, base.BlockView.prototype.templateContext.apply(this, arguments), {
|
||||
iconTypes: availableIconTypes,
|
||||
currentType: icons.get(this.model.get('iconType')).toJSON(),
|
||||
@ -297,7 +298,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('social', {
|
||||
blockModel: Module.SocialBlockModel,
|
||||
blockView: Module.SocialBlockView
|
||||
|
@ -9,8 +9,8 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
|
||||
Module.SpacerBlockModel = base.BlockModel.extend({
|
||||
defaults: function () {
|
||||
@ -87,7 +87,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('spacer', {
|
||||
blockModel: Module.SpacerBlockModel,
|
||||
blockView: Module.SpacerBlockView
|
||||
|
@ -10,8 +10,8 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
base = BaseBlock;
|
||||
var Module = {};
|
||||
var base = BaseBlock;
|
||||
|
||||
Module.TextBlockModel = base.BlockModel.extend({
|
||||
defaults: function () {
|
||||
@ -94,7 +94,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
App.registerBlockType('text', {
|
||||
blockModel: Module.TextBlockModel,
|
||||
blockView: Module.TextBlockView
|
||||
|
@ -7,15 +7,15 @@
|
||||
*/
|
||||
|
||||
(function (root, factory) {
|
||||
var Marionette = require('backbone.marionette');
|
||||
var Radio = require('backbone.radio');
|
||||
var _ = require('underscore');
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['backbone.marionette', 'backbone.radio', 'underscore'], function (Marionette, Radio, _) {
|
||||
return factory(Marionette, Radio, _);
|
||||
});
|
||||
}
|
||||
else if (typeof exports !== 'undefined') {
|
||||
var Marionette = require('backbone.marionette');
|
||||
var Radio = require('backbone.radio');
|
||||
var _ = require('underscore');
|
||||
module.exports = factory(Marionette, Radio, _);
|
||||
}
|
||||
else {
|
||||
|
@ -98,7 +98,7 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
App.on('start', function (App, options) {
|
||||
App.on('start', function () {
|
||||
// Prefetch post types
|
||||
Module.getPostTypes();
|
||||
});
|
||||
|
@ -13,7 +13,7 @@ define([
|
||||
// handled by other components.
|
||||
Module.NewsletterModel = SuperModel.extend({
|
||||
whitelisted: ['id', 'subject', 'preheader'],
|
||||
initialize: function (options) {
|
||||
initialize: function () {
|
||||
this.on('change', function () {
|
||||
App.getChannel().trigger('autoSave');
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('start', function (App, options) {
|
||||
App.on('start', function (App) {
|
||||
App._appView.showChildView('headingRegion', new Module.HeadingView({ model: App.getNewsletter() }));
|
||||
MailPoet.helpTooltip.show(document.getElementById('tooltip-designer-subject-line'), {
|
||||
tooltipId: 'tooltip-designer-subject-line-ti',
|
||||
|
@ -28,8 +28,8 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {},
|
||||
saveTimeout;
|
||||
var Module = {};
|
||||
var saveTimeout;
|
||||
|
||||
// Save editor contents to server
|
||||
Module.save = function () {
|
||||
@ -76,10 +76,9 @@ define([
|
||||
// Temporary workaround for html2canvas-alpha2.
|
||||
// Removes 1px left transparent border from resulting canvas.
|
||||
|
||||
var oldContext = oldCanvas.getContext('2d'),
|
||||
newCanvas = document.createElement('canvas'),
|
||||
newContext = newCanvas.getContext('2d'),
|
||||
leftBorderWidth = 1;
|
||||
var newCanvas = document.createElement('canvas');
|
||||
var newContext = newCanvas.getContext('2d');
|
||||
var leftBorderWidth = 1;
|
||||
|
||||
newCanvas.width = oldCanvas.width;
|
||||
newCanvas.height = oldCanvas.height;
|
||||
@ -95,8 +94,7 @@ define([
|
||||
};
|
||||
|
||||
Module.saveTemplate = function (options) {
|
||||
var that = this,
|
||||
promise = jQuery.Deferred();
|
||||
var promise = jQuery.Deferred();
|
||||
|
||||
promise.then(function (thumbnail) {
|
||||
var data = _.extend(options || {}, {
|
||||
@ -122,7 +120,6 @@ define([
|
||||
};
|
||||
|
||||
Module.exportTemplate = function (options) {
|
||||
var that = this;
|
||||
return Module.getThumbnail(
|
||||
jQuery('#mailpoet_editor_content > .mailpoet_block').get(0)
|
||||
).then(function (thumbnail) {
|
||||
@ -155,7 +152,7 @@ define([
|
||||
'click .mailpoet_save_export': 'toggleExportTemplate',
|
||||
'click .mailpoet_export_template': 'exportTemplate'
|
||||
},
|
||||
initialize: function (options) {
|
||||
initialize: function () {
|
||||
App.getChannel().on('beforeEditorSave', this.beforeSave, this);
|
||||
App.getChannel().on('afterEditorSave', this.afterSave, this);
|
||||
},
|
||||
@ -170,7 +167,7 @@ define([
|
||||
// TODO: Add a loading animation instead
|
||||
this.$('.mailpoet_autosaved_at').text(MailPoet.I18n.t('saving'));
|
||||
},
|
||||
afterSave: function (json, response) {
|
||||
afterSave: function (json) {
|
||||
this.validateNewsletter(json);
|
||||
// Update 'Last saved timer'
|
||||
this.$('.mailpoet_editor_last_saved').removeClass('mailpoet_hidden');
|
||||
@ -192,9 +189,9 @@ define([
|
||||
this.$('.mailpoet_save_as_template_container').addClass('mailpoet_hidden');
|
||||
},
|
||||
saveAsTemplate: function () {
|
||||
var templateName = this.$('.mailpoet_save_as_template_name').val(),
|
||||
templateDescription = this.$('.mailpoet_save_as_template_description').val(),
|
||||
that = this;
|
||||
var templateName = this.$('.mailpoet_save_as_template_name').val();
|
||||
var templateDescription = this.$('.mailpoet_save_as_template_description').val();
|
||||
var that = this;
|
||||
|
||||
if (templateName === '') {
|
||||
MailPoet.Notice.error(
|
||||
@ -248,9 +245,9 @@ define([
|
||||
this.$('.mailpoet_export_template_container').addClass('mailpoet_hidden');
|
||||
},
|
||||
exportTemplate: function () {
|
||||
var templateName = this.$('.mailpoet_export_template_name').val(),
|
||||
templateDescription = this.$('.mailpoet_export_template_description').val(),
|
||||
that = this;
|
||||
var templateName = this.$('.mailpoet_export_template_name').val();
|
||||
var templateDescription = this.$('.mailpoet_export_template_description').val();
|
||||
var that = this;
|
||||
|
||||
if (templateName === '') {
|
||||
MailPoet.Notice.error(
|
||||
@ -285,18 +282,19 @@ define([
|
||||
this.hideOptionContents();
|
||||
if (!this.$('.mailpoet_save_next').hasClass('button-disabled')) {
|
||||
Module._cancelAutosave();
|
||||
Module.save().done(function (response) {
|
||||
Module.save().done(function () {
|
||||
window.location.href = App.getConfig().get('urls.send');
|
||||
});
|
||||
}
|
||||
},
|
||||
validateNewsletter: function (jsonObject) {
|
||||
var contents;
|
||||
if (!App._contentContainer.isValid()) {
|
||||
this.showValidationError(App._contentContainer.validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
var contents = JSON.stringify(jsonObject);
|
||||
contents = JSON.stringify(jsonObject);
|
||||
if (App.getConfig().get('validation.validateUnsubscribeLinkPresent') &&
|
||||
contents.indexOf('[link:subscription_unsubscribe_url]') < 0 &&
|
||||
contents.indexOf('[link:subscription_unsubscribe]') < 0) {
|
||||
@ -340,9 +338,11 @@ define([
|
||||
};
|
||||
|
||||
Module.beforeExitWithUnsavedChanges = function (e) {
|
||||
var message;
|
||||
var event;
|
||||
if (saveTimeout) {
|
||||
var message = MailPoet.I18n.t('unsavedChangesWillBeLost');
|
||||
var event = e || window.event;
|
||||
message = MailPoet.I18n.t('unsavedChangesWillBeLost');
|
||||
event = e || window.event;
|
||||
|
||||
if (event) {
|
||||
event.returnValue = message;
|
||||
@ -352,7 +352,7 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
var Application = App;
|
||||
Application.save = Module.save;
|
||||
Application.getChannel().on('autoSave', Module.autoSave);
|
||||
@ -362,7 +362,7 @@ define([
|
||||
Application.getChannel().reply('save', Application.save);
|
||||
});
|
||||
|
||||
App.on('start', function (App, options) {
|
||||
App.on('start', function (App) {
|
||||
var saveView = new Module.SaveView();
|
||||
App._appView.showChildView('bottomRegion', saveView);
|
||||
});
|
||||
|
@ -6,8 +6,7 @@ define([
|
||||
'backbone.marionette',
|
||||
'backbone.supermodel',
|
||||
'underscore',
|
||||
'jquery',
|
||||
'sticky-kit'
|
||||
'jquery'
|
||||
], function (
|
||||
App,
|
||||
CommunicationComponent,
|
||||
@ -16,14 +15,13 @@ define([
|
||||
Marionette,
|
||||
SuperModel,
|
||||
_,
|
||||
jQuery,
|
||||
StickyKit
|
||||
jQuery
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var Module = {};
|
||||
|
||||
var SidebarView;
|
||||
// Widget handlers for use to create new content blocks via drag&drop
|
||||
Module._contentWidgets = new (Backbone.Collection.extend({
|
||||
model: SuperModel.extend({
|
||||
@ -52,7 +50,7 @@ define([
|
||||
Module.registerLayoutWidget = function (widget) { return Module._layoutWidgets.add(widget); };
|
||||
Module.getLayoutWidgets = function () { return Module._layoutWidgets; };
|
||||
|
||||
var SidebarView = Marionette.View.extend({
|
||||
SidebarView = Marionette.View.extend({
|
||||
getTemplate: function () { return window.templates.sidebar; },
|
||||
regions: {
|
||||
contentRegion: '.mailpoet_content_region',
|
||||
@ -62,8 +60,8 @@ define([
|
||||
},
|
||||
events: {
|
||||
'click .mailpoet_sidebar_region h3, .mailpoet_sidebar_region .handlediv': function (event) {
|
||||
var $openRegion = this.$el.find('.mailpoet_sidebar_region:not(.closed)'),
|
||||
$targetRegion = this.$el.find(event.target).closest('.mailpoet_sidebar_region');
|
||||
var $openRegion = this.$el.find('.mailpoet_sidebar_region:not(.closed)');
|
||||
var $targetRegion = this.$el.find(event.target).closest('.mailpoet_sidebar_region');
|
||||
|
||||
$openRegion.find('.mailpoet_region_content').velocity(
|
||||
'slideUp',
|
||||
@ -90,7 +88,7 @@ define([
|
||||
}
|
||||
}
|
||||
},
|
||||
initialize: function (options) {
|
||||
initialize: function () {
|
||||
jQuery(window)
|
||||
.on('resize', this.updateHorizontalScroll.bind(this))
|
||||
.on('scroll', this.updateHorizontalScroll.bind(this));
|
||||
@ -113,9 +111,8 @@ define([
|
||||
// position of the sidebar would be scrollable and not fixed
|
||||
// partially out of visible screen
|
||||
this.$el.parent().each(function () {
|
||||
var calculated_left, self;
|
||||
|
||||
self = jQuery(this);
|
||||
var calculated_left;
|
||||
var self = jQuery(this);
|
||||
|
||||
if (self.css('position') === 'fixed') {
|
||||
calculated_left = self.parent().offset().left - jQuery(window).scrollLeft();
|
||||
@ -271,7 +268,7 @@ define([
|
||||
previewUrl: response.meta.preview_url
|
||||
});
|
||||
|
||||
var view = this.previewView.render();
|
||||
this.previewView.render();
|
||||
this.previewView.$el.css('height', '100%');
|
||||
|
||||
MailPoet.Modal.popup({
|
||||
@ -324,7 +321,7 @@ define([
|
||||
App.getChannel().request('save').always(function () {
|
||||
CommunicationComponent.previewNewsletter(data).always(function () {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).done(function (response) {
|
||||
}).done(function () {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterPreviewSent'),
|
||||
{ scroll: true }
|
||||
@ -363,7 +360,7 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
App.on('before:start', function (App) {
|
||||
var Application = App;
|
||||
Application.registerWidget = Module.registerWidget;
|
||||
Application.getWidgets = Module.getWidgets;
|
||||
@ -371,9 +368,8 @@ define([
|
||||
Application.getLayoutWidgets = Module.getLayoutWidgets;
|
||||
});
|
||||
|
||||
App.on('start', function (App, options) {
|
||||
var stylesModel = App.getGlobalStyles(),
|
||||
sidebarView = new SidebarView();
|
||||
App.on('start', function (App) {
|
||||
var sidebarView = new SidebarView();
|
||||
|
||||
App._appView.showChildView('sidebarRegion', sidebarView);
|
||||
|
||||
|
@ -71,17 +71,19 @@ define([
|
||||
|
||||
App.on('before:start', function (App, options) {
|
||||
var Application = App;
|
||||
var body;
|
||||
var globalStyles;
|
||||
// Expose style methods to global application
|
||||
Application.getGlobalStyles = Module.getGlobalStyles;
|
||||
Application.setGlobalStyles = Module.setGlobalStyles;
|
||||
Application.getAvailableStyles = Module.getAvailableStyles;
|
||||
|
||||
var body = options.newsletter.body;
|
||||
var globalStyles = (_.has(body, 'globalStyles')) ? body.globalStyles : {};
|
||||
body = options.newsletter.body;
|
||||
globalStyles = (_.has(body, 'globalStyles')) ? body.globalStyles : {};
|
||||
this.setGlobalStyles(globalStyles);
|
||||
});
|
||||
|
||||
App.on('start', function (App, options) {
|
||||
App.on('start', function (App) {
|
||||
var stylesView = new Module.StylesView({ model: App.getGlobalStyles() });
|
||||
App._appView.showChildView('stylesRegion', stylesView);
|
||||
});
|
||||
|
@ -10,31 +10,33 @@
|
||||
|
||||
/* jshint unused:false */
|
||||
/* global tinymce:true */
|
||||
tinymce.PluginManager.add('mailpoet_shortcodes', function (editor, url) {
|
||||
tinymce.PluginManager.add('mailpoet_shortcodes', function (editor) {
|
||||
var appendLabelAndClose = function (shortcode) {
|
||||
editor.insertContent(shortcode);
|
||||
editor.windowManager.close();
|
||||
},
|
||||
generateOnClickFunc = function (shortcode) {
|
||||
return function () {
|
||||
appendLabelAndClose(shortcode);
|
||||
};
|
||||
editor.insertContent(shortcode);
|
||||
editor.windowManager.close();
|
||||
};
|
||||
var generateOnClickFunc = function (shortcode) {
|
||||
return function () {
|
||||
appendLabelAndClose(shortcode);
|
||||
};
|
||||
};
|
||||
|
||||
editor.addButton('mailpoet_shortcodes', {
|
||||
icon: 'mailpoet_shortcodes',
|
||||
onclick: function () {
|
||||
var shortcodes = [],
|
||||
configShortcodes = editor.settings.mailpoet_shortcodes;
|
||||
var shortcodes = [];
|
||||
var configShortcodes = editor.settings.mailpoet_shortcodes;
|
||||
var segment;
|
||||
var i;
|
||||
|
||||
for (var segment in configShortcodes) {
|
||||
for (segment in configShortcodes) {
|
||||
if (configShortcodes.hasOwnProperty(segment)) {
|
||||
shortcodes.push({
|
||||
type: 'label',
|
||||
text: segment
|
||||
});
|
||||
|
||||
for (var i = 0; i < configShortcodes[segment].length; i += 1) {
|
||||
for (i = 0; i < configShortcodes[segment].length; i += 1) {
|
||||
shortcodes.push({
|
||||
type: 'button',
|
||||
text: configShortcodes[segment][i].text,
|
||||
|
@ -179,11 +179,11 @@ const _StatisticsMixin = {
|
||||
const percentage_opened_display = MailPoet.Num.toLocaleFixed(percentage_opened, 1);
|
||||
const percentage_unsubscribed_display = MailPoet.Num.toLocaleFixed(percentage_unsubscribed, 1);
|
||||
|
||||
let show_stats_timeout,
|
||||
newsletter_date,
|
||||
sent_hours_ago,
|
||||
too_early_for_stats,
|
||||
show_kb_link;
|
||||
let show_stats_timeout;
|
||||
let newsletter_date;
|
||||
let sent_hours_ago;
|
||||
let too_early_for_stats;
|
||||
let show_kb_link;
|
||||
if (current_time !== undefined) {
|
||||
// standard emails and post notifications:
|
||||
// display green box for newsletters that were just sent
|
||||
|
@ -47,6 +47,8 @@ define('notice', ['mailpoet', 'jquery'], function (mp, jQuery) {
|
||||
return this;
|
||||
},
|
||||
createNotice: function () {
|
||||
var onClose;
|
||||
var positionAfter;
|
||||
// clone element
|
||||
this.element = jQuery('#mailpoet_notice_' + this.options.type).clone();
|
||||
|
||||
@ -62,7 +64,6 @@ define('notice', ['mailpoet', 'jquery'], function (mp, jQuery) {
|
||||
this.element.removeAttr('id');
|
||||
|
||||
// insert notice after its parent
|
||||
var positionAfter;
|
||||
if (typeof this.options.positionAfter === 'object') {
|
||||
positionAfter = this.options.positionAfter;
|
||||
} else if (typeof this.options.positionAfter === 'string') {
|
||||
@ -73,7 +74,7 @@ define('notice', ['mailpoet', 'jquery'], function (mp, jQuery) {
|
||||
positionAfter.after(this.element);
|
||||
|
||||
// setup onClose callback
|
||||
var onClose = null;
|
||||
onClose = null;
|
||||
if (this.options.onClose !== null) {
|
||||
onClose = this.options.onClose;
|
||||
}
|
||||
@ -177,12 +178,13 @@ define('notice', ['mailpoet', 'jquery'], function (mp, jQuery) {
|
||||
}
|
||||
},
|
||||
hide: function (all) {
|
||||
var id;
|
||||
if (all !== undefined && all === true) {
|
||||
// all notices
|
||||
jQuery('.mailpoet_notice:not([id])').trigger('close');
|
||||
} else if (all !== undefined && jQuery.isArray(all)) {
|
||||
// array of ids
|
||||
for (var id in all) {
|
||||
for (id in all) {
|
||||
jQuery('[data-id="' + all[id] + '"]').trigger('close');
|
||||
}
|
||||
} if (all !== undefined) {
|
||||
|
@ -5,8 +5,7 @@ define([
|
||||
],
|
||||
function (
|
||||
MailPoet,
|
||||
jQuery,
|
||||
Parsley
|
||||
jQuery
|
||||
) {
|
||||
jQuery(function ($) {
|
||||
function isSameDomain(url) {
|
||||
@ -20,7 +19,7 @@ function (
|
||||
$('form.mailpoet_form').each(function () {
|
||||
var form = $(this);
|
||||
|
||||
form.parsley().on('form:validated', function (parsley) {
|
||||
form.parsley().on('form:validated', function () {
|
||||
// clear messages
|
||||
form.find('.mailpoet_message > p').hide();
|
||||
|
||||
@ -84,4 +83,4 @@ function (
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -5,7 +5,7 @@ define(
|
||||
function (
|
||||
MailPoet
|
||||
) {
|
||||
|
||||
var element;
|
||||
function eventHandler() {
|
||||
if (confirm(MailPoet.I18n.t('reinstallConfirmation'))) {
|
||||
MailPoet.trackEvent(
|
||||
@ -36,8 +36,8 @@ define(
|
||||
return false;
|
||||
}
|
||||
|
||||
var element = document.getElementById('mailpoet_reinstall');
|
||||
element = document.getElementById('mailpoet_reinstall');
|
||||
if (element) {
|
||||
element.addEventListener('click', eventHandler, false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -51,7 +51,7 @@ define(
|
||||
jQuery('#mailpoet_sending_method_setup').fadeIn();
|
||||
}
|
||||
},
|
||||
tabs: function (tabStr, section) {
|
||||
tabs: function (tabStr) {
|
||||
// set default tab
|
||||
var tab = tabStr || 'mta';
|
||||
|
||||
@ -86,4 +86,4 @@ define(
|
||||
if (!Backbone.History.started) Backbone.history.start();
|
||||
});
|
||||
}
|
||||
);
|
||||
);
|
||||
|
@ -3,98 +3,104 @@ define(
|
||||
'underscore',
|
||||
'jquery',
|
||||
'mailpoet',
|
||||
'handlebars',
|
||||
'select2'
|
||||
'handlebars'
|
||||
],
|
||||
function (
|
||||
_,
|
||||
jQuery,
|
||||
MailPoet,
|
||||
Handlebars,
|
||||
select2
|
||||
Handlebars
|
||||
) {
|
||||
if (!jQuery('#mailpoet_subscribers_export').length) {
|
||||
return;
|
||||
}
|
||||
jQuery(document).ready(function () {
|
||||
var segmentsContainerElement;
|
||||
var subscriberFieldsContainerElement;
|
||||
var exportConfirmedOptionElement;
|
||||
var groupBySegmentOptionElement;
|
||||
var nextStepButton;
|
||||
var renderSegmentsAndFields;
|
||||
var subscribers_export_template;
|
||||
if (!window.exportData.segments) {
|
||||
return;
|
||||
}
|
||||
var subscribers_export_template =
|
||||
subscribers_export_template =
|
||||
Handlebars.compile(jQuery('#mailpoet_subscribers_export_template').html());
|
||||
|
||||
// render template
|
||||
jQuery('#mailpoet_subscribers_export > div.inside').html(subscribers_export_template(window.exportData));
|
||||
|
||||
// define reusable variables
|
||||
var segmentsContainerElement = jQuery('#export_lists'),
|
||||
subscriberFieldsContainerElement = jQuery('#export_columns'),
|
||||
exportConfirmedOptionElement = jQuery(':radio[name="option_confirmed"]'),
|
||||
groupBySegmentOptionElement = jQuery(':checkbox[name="option_group_by_list"]'),
|
||||
nextStepButton = jQuery('a.mailpoet_export_process'),
|
||||
renderSegmentsAndFields = function (container, data) {
|
||||
if (container.data('select2')) {
|
||||
container
|
||||
.html('')
|
||||
.select2('destroy');
|
||||
}
|
||||
segmentsContainerElement = jQuery('#export_lists');
|
||||
subscriberFieldsContainerElement = jQuery('#export_columns');
|
||||
exportConfirmedOptionElement = jQuery(':radio[name="option_confirmed"]');
|
||||
groupBySegmentOptionElement = jQuery(':checkbox[name="option_group_by_list"]');
|
||||
nextStepButton = jQuery('a.mailpoet_export_process');
|
||||
renderSegmentsAndFields = function (container, data) {
|
||||
if (container.data('select2')) {
|
||||
container
|
||||
.select2({
|
||||
data: data,
|
||||
width: '20em',
|
||||
templateResult: function (item) {
|
||||
return (item.subscriberCount > 0)
|
||||
? item.name + ' (' + parseInt(item.subscriberCount).toLocaleString() + ')'
|
||||
: item.name;
|
||||
},
|
||||
templateSelection: function (item) {
|
||||
return (item.subscriberCount > 0)
|
||||
? item.name + ' (' + parseInt(item.subscriberCount).toLocaleString() + ')'
|
||||
: item.name;
|
||||
}
|
||||
})
|
||||
.on('select2:selecting', function (selectEvent) {
|
||||
var selectElement = this,
|
||||
selectedOptionId = selectEvent.params.args.data.id,
|
||||
fieldsToExclude = [
|
||||
'select',
|
||||
'deselect'
|
||||
];
|
||||
if (_.contains(fieldsToExclude, selectedOptionId)) {
|
||||
selectEvent.preventDefault();
|
||||
if (selectedOptionId === 'deselect') {
|
||||
jQuery(selectElement).val('').trigger('change');
|
||||
} else {
|
||||
var allOptions = [];
|
||||
_.each(container.find('option'), function (field) {
|
||||
if (!_.contains(fieldsToExclude, field.value)) {
|
||||
allOptions.push(field.value);
|
||||
}
|
||||
});
|
||||
jQuery(selectElement).val(allOptions).trigger('change');
|
||||
}
|
||||
jQuery(selectElement).select2('close');
|
||||
}
|
||||
})
|
||||
.on('change', function () {
|
||||
if ((window.exportData.segments && segmentsContainerElement.select2('data').length && subscriberFieldsContainerElement.select2('data').length)
|
||||
||
|
||||
(!window.exportData.segments && subscriberFieldsContainerElement.select2('data').length)
|
||||
) {
|
||||
toggleNextStepButton('on');
|
||||
}
|
||||
else {
|
||||
toggleNextStepButton('off');
|
||||
.html('')
|
||||
.select2('destroy');
|
||||
}
|
||||
container
|
||||
.select2({
|
||||
data: data,
|
||||
width: '20em',
|
||||
templateResult: function (item) {
|
||||
return (item.subscriberCount > 0)
|
||||
? item.name + ' (' + parseInt(item.subscriberCount).toLocaleString() + ')'
|
||||
: item.name;
|
||||
},
|
||||
templateSelection: function (item) {
|
||||
return (item.subscriberCount > 0)
|
||||
? item.name + ' (' + parseInt(item.subscriberCount).toLocaleString() + ')'
|
||||
: item.name;
|
||||
}
|
||||
})
|
||||
.on('select2:selecting', function (selectEvent) {
|
||||
var selectElement = this;
|
||||
var selectedOptionId = selectEvent.params.args.data.id;
|
||||
var fieldsToExclude = [
|
||||
'select',
|
||||
'deselect'
|
||||
];
|
||||
var allOptions;
|
||||
if (_.contains(fieldsToExclude, selectedOptionId)) {
|
||||
selectEvent.preventDefault();
|
||||
if (selectedOptionId === 'deselect') {
|
||||
jQuery(selectElement).val('').trigger('change');
|
||||
} else {
|
||||
allOptions = [];
|
||||
_.each(container.find('option'), function (field) {
|
||||
if (!_.contains(fieldsToExclude, field.value)) {
|
||||
allOptions.push(field.value);
|
||||
}
|
||||
});
|
||||
jQuery(selectElement).val(allOptions).trigger('change');
|
||||
}
|
||||
jQuery(selectElement).select2('close');
|
||||
}
|
||||
})
|
||||
.on('change', function () {
|
||||
if ((window.exportData.segments && segmentsContainerElement.select2('data').length && subscriberFieldsContainerElement.select2('data').length)
|
||||
||
|
||||
(!window.exportData.segments && subscriberFieldsContainerElement.select2('data').length)
|
||||
) {
|
||||
toggleNextStepButton('on');
|
||||
}
|
||||
else {
|
||||
toggleNextStepButton('off');
|
||||
}
|
||||
|
||||
if (segmentsContainerElement.select2('data').length > 1 && window.exportData.groupBySegmentOption) {
|
||||
jQuery('.mailpoet_group_by_list').show();
|
||||
}
|
||||
else if (window.exportData.groupBySegmentOption) {
|
||||
jQuery('.mailpoet_group_by_list').hide();
|
||||
}
|
||||
});
|
||||
};
|
||||
if (segmentsContainerElement.select2('data').length > 1 && window.exportData.groupBySegmentOption) {
|
||||
jQuery('.mailpoet_group_by_list').show();
|
||||
}
|
||||
else if (window.exportData.groupBySegmentOption) {
|
||||
jQuery('.mailpoet_group_by_list').hide();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// set confirmed subscribers export option to false
|
||||
window.exportData.exportConfirmedOption = false;
|
||||
@ -133,11 +139,12 @@ define(
|
||||
}
|
||||
|
||||
nextStepButton.click(function () {
|
||||
var exportFormat;
|
||||
if (jQuery(this).hasClass('button-disabled')) {
|
||||
return;
|
||||
}
|
||||
MailPoet.Modal.loading(true);
|
||||
var exportFormat = jQuery(':radio[name="option_format"]:checked').val();
|
||||
exportFormat = jQuery(':radio[name="option_format"]:checked').val();
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'ImportExport',
|
||||
@ -149,7 +156,7 @@ define(
|
||||
segments: (window.exportData.segments) ? segmentsContainerElement.val() : false,
|
||||
subscriber_fields: subscriberFieldsContainerElement.val()
|
||||
})
|
||||
}).always(function (response) {
|
||||
}).always(function () {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).done(function (response) {
|
||||
var resultMessage = MailPoet.I18n.t('exportMessage')
|
||||
|
@ -7,8 +7,7 @@ define(
|
||||
'handlebars',
|
||||
'papaparse',
|
||||
'asyncqueue',
|
||||
'moment',
|
||||
'select2'
|
||||
'moment'
|
||||
],
|
||||
function (
|
||||
Backbone,
|
||||
@ -18,16 +17,16 @@ define(
|
||||
Handlebars,
|
||||
Papa,
|
||||
AsyncQueue,
|
||||
Moment,
|
||||
select2
|
||||
Moment
|
||||
) {
|
||||
if (!jQuery('#mailpoet_subscribers_import').length) {
|
||||
return;
|
||||
}
|
||||
jQuery(document).ready(function () {
|
||||
var router;
|
||||
jQuery('input[name="select_method"]').attr('checked', false);
|
||||
// configure router
|
||||
var router = new (Backbone.Router.extend({
|
||||
router = new (Backbone.Router.extend({
|
||||
routes: {
|
||||
'': 'home',
|
||||
step1: 'step1',
|
||||
@ -50,8 +49,20 @@ define(
|
||||
* STEP 1 (upload or copy/paste)
|
||||
*/
|
||||
router.on('route:step1', function () {
|
||||
var methodProcessContainerTemplate;
|
||||
var currentStepE;
|
||||
var methodSelectionElement;
|
||||
var pasteInputElement;
|
||||
var pasteInputPlaceholderElement;
|
||||
var pasteProcessButtonElement;
|
||||
var mailChimpKeyInputElement;
|
||||
var mailChimpKeyVerifyButtonElement;
|
||||
var mailChimpListsContainerElement;
|
||||
var mailChimpProcessButtonElement;
|
||||
var uploadElement;
|
||||
var uploadProcessButtonElement;
|
||||
// set or reset temporary validation rule on all columns
|
||||
window.mailpoetColumns = jQuery.map(window.mailpoetColumns, function (column, columnIndex) {
|
||||
window.mailpoetColumns = jQuery.map(window.mailpoetColumns, function (column) {
|
||||
var col = column;
|
||||
col.validation_rule = false;
|
||||
return col;
|
||||
@ -63,36 +74,34 @@ define(
|
||||
}
|
||||
|
||||
// render process button for each method
|
||||
var methodProcessContainerTemplate =
|
||||
methodProcessContainerTemplate =
|
||||
Handlebars.compile(jQuery('#method_process_template').html());
|
||||
jQuery('.mailpoet_method_process').html(methodProcessContainerTemplate());
|
||||
|
||||
// define reusable variables
|
||||
var currentStepE = jQuery(location.hash),
|
||||
methodSelectionElement = jQuery('#select_method'),
|
||||
pasteInputElement = jQuery('#paste_input'),
|
||||
pasteInputPlaceholderElement =
|
||||
pasteInputElement.data('placeholder').replace(/\\n/g, '\n'),
|
||||
pasteProcessButtonElement =
|
||||
jQuery('#method_paste > div.mailpoet_method_process')
|
||||
.find('a.mailpoet_process'),
|
||||
mailChimpKeyInputElement = jQuery('#mailchimp_key'),
|
||||
mailChimpKeyVerifyButtonElement = jQuery('#mailchimp_key_verify'),
|
||||
mailChimpListsContainerElement = jQuery('#mailchimp_lists'),
|
||||
mailChimpProcessButtonElement =
|
||||
jQuery('#method_mailchimp > div.mailpoet_method_process')
|
||||
.find('a.mailpoet_process'),
|
||||
uploadElement = jQuery('#file_local'),
|
||||
uploadProcessButtonElement =
|
||||
jQuery('#method_file > div.mailpoet_method_process')
|
||||
.find('a.mailpoet_process');
|
||||
currentStepE = jQuery(location.hash);
|
||||
methodSelectionElement = jQuery('#select_method');
|
||||
pasteInputElement = jQuery('#paste_input');
|
||||
pasteInputPlaceholderElement =
|
||||
pasteInputElement.data('placeholder').replace(/\\n/g, '\n');
|
||||
pasteProcessButtonElement =
|
||||
jQuery('#method_paste > div.mailpoet_method_process')
|
||||
.find('a.mailpoet_process');
|
||||
mailChimpKeyInputElement = jQuery('#mailchimp_key');
|
||||
mailChimpKeyVerifyButtonElement = jQuery('#mailchimp_key_verify');
|
||||
mailChimpListsContainerElement = jQuery('#mailchimp_lists');
|
||||
mailChimpProcessButtonElement = jQuery('#method_mailchimp > div.mailpoet_method_process')
|
||||
.find('a.mailpoet_process');
|
||||
uploadElement = jQuery('#file_local');
|
||||
uploadProcessButtonElement =
|
||||
jQuery('#method_file > div.mailpoet_method_process')
|
||||
.find('a.mailpoet_process');
|
||||
|
||||
// define method change behavior
|
||||
methodSelectionElement.change(function () {
|
||||
var available_methods = jQuery(':radio[name="select_method"]');
|
||||
var selected_method = available_methods.index(available_methods.filter(':checked'));
|
||||
MailPoet.Notice.hide();
|
||||
var available_methods = jQuery(':radio[name="select_method"]'),
|
||||
selected_method =
|
||||
available_methods.index(available_methods.filter(':checked'));
|
||||
// hide all methods
|
||||
currentStepE.find('.inside')
|
||||
.children('div[id^="method_"]')
|
||||
@ -131,9 +140,9 @@ define(
|
||||
});
|
||||
|
||||
pasteProcessButtonElement.click(function () {
|
||||
var pasteSize = encodeURI(pasteInputElement.val()).split(/%..|./).length - 1;
|
||||
MailPoet.Notice.hide();
|
||||
// get an approximate size of textarea paste in bytes
|
||||
var pasteSize = encodeURI(pasteInputElement.val()).split(/%..|./).length - 1;
|
||||
if (pasteSize > window.maxPostSizeBytes) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('maxPostSizeNotice'));
|
||||
return;
|
||||
@ -149,8 +158,8 @@ define(
|
||||
* CSV file
|
||||
*/
|
||||
uploadElement.change(function () {
|
||||
MailPoet.Notice.hide();
|
||||
var ext = this.value.match(/\.(.+)$/);
|
||||
MailPoet.Notice.hide();
|
||||
if (ext === null || ext[1].toLowerCase() !== 'csv') {
|
||||
this.value = '';
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('wrongFileFormat'));
|
||||
@ -234,7 +243,7 @@ define(
|
||||
api_key: mailChimpKeyInputElement.val(),
|
||||
lists: mailChimpListsContainerElement.find('select').val()
|
||||
}
|
||||
}).always(function (response) {
|
||||
}).always(function () {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).done(function (response) {
|
||||
window.importData.step1 = response.data;
|
||||
@ -294,48 +303,48 @@ define(
|
||||
}
|
||||
|
||||
function parseCSV(isFile) {
|
||||
var processedSubscribers = [],
|
||||
parsedEmails = [],
|
||||
duplicateEmails = [],
|
||||
invalidEmails = [],
|
||||
emailColumnPosition = null,
|
||||
columnCount = null,
|
||||
isHeaderFound = false,
|
||||
advancedOptionHeader = true,
|
||||
advancedOptionDelimiter = '',
|
||||
advancedOptionNewline = '',
|
||||
advancedOptionComments = false,
|
||||
// trim spaces, commas, periods,
|
||||
// single/double quotes and convert to lowercase
|
||||
detectAndCleanupEmail = function (emailString) {
|
||||
var test;
|
||||
// decode HTML entities
|
||||
var email = jQuery('<div />').html(emailString).text();
|
||||
email = email
|
||||
.toLowerCase()
|
||||
// left/right trim spaces, punctuation (e.g., " 'email@email.com'; ")
|
||||
// right trim non-printable characters (e.g., "email@email.com<6F>")
|
||||
.replace(/^["';.,\s]+|[^\x20-\x7E]+$|["';.,_\s]+$/g, '')
|
||||
// remove spaces (e.g., "email @ email . com")
|
||||
// remove urlencoded characters
|
||||
.replace(/\s+|%\d+|,+/g, '');
|
||||
// detect e-mails that will be otherwise rejected by email regex
|
||||
test = /<(.*?)>/.exec(email);
|
||||
if (test) {
|
||||
// is the email inside angle brackets (e.g., 'some@email.com <some@email.com>')?
|
||||
email = test[1].trim();
|
||||
}
|
||||
test = /mailto:(?:\s+)?(.*)/.exec(email);
|
||||
if (test) {
|
||||
// is the email in 'mailto:email' format?
|
||||
email = test[1].trim();
|
||||
}
|
||||
// test for valid characters using WP's rule (https://core.trac.wordpress.org/browser/tags/4.7.3/src/wp-includes/formatting.php#L2902)
|
||||
if (!/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.\-@]+$/.test(email)) {
|
||||
return false;
|
||||
}
|
||||
return email;
|
||||
};
|
||||
var processedSubscribers = [];
|
||||
var parsedEmails = [];
|
||||
var duplicateEmails = [];
|
||||
var invalidEmails = [];
|
||||
var emailColumnPosition = null;
|
||||
var columnCount = null;
|
||||
var isHeaderFound = false;
|
||||
var advancedOptionHeader = true;
|
||||
var advancedOptionDelimiter = '';
|
||||
var advancedOptionNewline = '';
|
||||
var advancedOptionComments = false;
|
||||
// trim spaces, commas, periods,
|
||||
// single/double quotes and convert to lowercase
|
||||
var detectAndCleanupEmail = function (emailString) {
|
||||
var test;
|
||||
// decode HTML entities
|
||||
var email = jQuery('<div />').html(emailString).text();
|
||||
email = email
|
||||
.toLowerCase()
|
||||
// left/right trim spaces, punctuation (e.g., " 'email@email.com'; ")
|
||||
// right trim non-printable characters (e.g., "email@email.com<6F>")
|
||||
.replace(/^["';.,\s]+|[^\x20-\x7E]+$|["';.,_\s]+$/g, '')
|
||||
// remove spaces (e.g., "email @ email . com")
|
||||
// remove urlencoded characters
|
||||
.replace(/\s+|%\d+|,+/g, '');
|
||||
// detect e-mails that will be otherwise rejected by email regex
|
||||
test = /<(.*?)>/.exec(email);
|
||||
if (test) {
|
||||
// is the email inside angle brackets (e.g., 'some@email.com <some@email.com>')?
|
||||
email = test[1].trim();
|
||||
}
|
||||
test = /mailto:(?:\s+)?(.*)/.exec(email);
|
||||
if (test) {
|
||||
// is the email in 'mailto:email' format?
|
||||
email = test[1].trim();
|
||||
}
|
||||
// test for valid characters using WP's rule (https://core.trac.wordpress.org/browser/tags/4.7.3/src/wp-includes/formatting.php#L2902)
|
||||
if (!/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.\-@]+$/.test(email)) {
|
||||
return false;
|
||||
}
|
||||
return email;
|
||||
};
|
||||
|
||||
return {
|
||||
skipEmptyLines: true,
|
||||
@ -347,11 +356,18 @@ define(
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('dataProcessingError'));
|
||||
},
|
||||
complete: function (CSV) {
|
||||
for (var rowCount in CSV.data) {
|
||||
var rowData = CSV.data[rowCount].map(function (el) {
|
||||
var email;
|
||||
var emailAddress;
|
||||
var column;
|
||||
var rowCount;
|
||||
var rowData;
|
||||
var rowColumnCount;
|
||||
var errorNotice;
|
||||
for (rowCount in CSV.data) {
|
||||
rowData = CSV.data[rowCount].map(function (el) {
|
||||
return el.trim();
|
||||
});
|
||||
var rowColumnCount = rowData.length;
|
||||
rowColumnCount = rowData.length;
|
||||
// set the number of row elements based on the first non-empty row
|
||||
if (columnCount === null) {
|
||||
columnCount = rowColumnCount;
|
||||
@ -365,14 +381,14 @@ define(
|
||||
// determine position of email address inside an array; this is
|
||||
// done once and then email regex is run just on that element for each row
|
||||
if (emailColumnPosition === null) {
|
||||
for (var column in rowData) {
|
||||
var email = detectAndCleanupEmail(rowData[column]);
|
||||
for (column in rowData) {
|
||||
emailAddress = detectAndCleanupEmail(rowData[column]);
|
||||
if (emailColumnPosition === null
|
||||
&& window.emailRegex.test(email)) {
|
||||
&& window.emailRegex.test(emailAddress)) {
|
||||
emailColumnPosition = column;
|
||||
parsedEmails[email] = true; // add current e-mail to an object index
|
||||
rowData[column] = email;
|
||||
processedSubscribers[email] = rowData;
|
||||
parsedEmails[emailAddress] = true; // add current e-mail to an object index
|
||||
rowData[column] = emailAddress;
|
||||
processedSubscribers[emailAddress] = rowData;
|
||||
}
|
||||
}
|
||||
if (emailColumnPosition === null
|
||||
@ -383,7 +399,7 @@ define(
|
||||
}
|
||||
}
|
||||
else if (rowData[emailColumnPosition] !== '') {
|
||||
var email = detectAndCleanupEmail(rowData[emailColumnPosition]);
|
||||
email = detectAndCleanupEmail(rowData[emailColumnPosition]);
|
||||
if (_.has(parsedEmails, email)) {
|
||||
duplicateEmails.push(email);
|
||||
}
|
||||
@ -427,7 +443,7 @@ define(
|
||||
}
|
||||
else {
|
||||
MailPoet.Modal.loading(false);
|
||||
var errorNotice = MailPoet.I18n.t('noValidRecords');
|
||||
errorNotice = MailPoet.I18n.t('noValidRecords');
|
||||
errorNotice = errorNotice.replace('[link]', MailPoet.I18n.t('csvKBLink'));
|
||||
errorNotice = errorNotice.replace('[/link]', '</a>');
|
||||
MailPoet.Notice.error(errorNotice);
|
||||
@ -438,37 +454,41 @@ define(
|
||||
});
|
||||
|
||||
router.on('route:step2', function () {
|
||||
var nextStepButton;
|
||||
var previousStepButton;
|
||||
var subscribers;
|
||||
var subscribersDataTemplate;
|
||||
var subscribersDataTemplatePartial;
|
||||
var subscribersDataParseResultsTemplate;
|
||||
var segmentSelectElement;
|
||||
var maxRowsToShow;
|
||||
var filler;
|
||||
var fillerArray;
|
||||
var fillerPosition;
|
||||
var import_results;
|
||||
var duplicates;
|
||||
var email;
|
||||
if (typeof (window.importData.step1) === 'undefined') {
|
||||
router.navigate('step1', { trigger: true });
|
||||
return;
|
||||
}
|
||||
// define reusable variables
|
||||
var nextStepButton = jQuery('#step2_process'),
|
||||
previousStepButton = jQuery('#return_to_step1'),
|
||||
nextStepButton = jQuery('#step2_process');
|
||||
previousStepButton = jQuery('#return_to_step1');
|
||||
// create a copy of subscribers object for further manipulation
|
||||
subscribers = jQuery.extend(true, {}, window.importData.step1),
|
||||
subscribersDataTemplate =
|
||||
Handlebars
|
||||
.compile(jQuery('#subscribers_data_template')
|
||||
.html()),
|
||||
subscribersDataTemplatePartial =
|
||||
Handlebars
|
||||
.compile(jQuery('#subscribers_data_template_partial')
|
||||
.html()),
|
||||
subscribersDataParseResultsTemplate =
|
||||
Handlebars
|
||||
.compile(jQuery('#subscribers_data_parse_results_template')
|
||||
.html()),
|
||||
segmentSelectElement = jQuery('#mailpoet_segments_select'),
|
||||
maxRowsToShow = 10,
|
||||
filler = '. . .',
|
||||
subscribers = jQuery.extend(true, {}, window.importData.step1);
|
||||
subscribersDataTemplate = Handlebars.compile(jQuery('#subscribers_data_template').html());
|
||||
subscribersDataTemplatePartial = Handlebars.compile(jQuery('#subscribers_data_template_partial').html());
|
||||
subscribersDataParseResultsTemplate = Handlebars.compile(jQuery('#subscribers_data_parse_results_template').html());
|
||||
segmentSelectElement = jQuery('#mailpoet_segments_select');
|
||||
maxRowsToShow = 10;
|
||||
filler = '. . .';
|
||||
// create an array of filler data with the same number of
|
||||
// elements as in the subscribers' data row
|
||||
fillerArray = Array.apply(
|
||||
null,
|
||||
new Array(subscribers.subscribers[0].length)
|
||||
).map(String.prototype.valueOf, filler),
|
||||
fillerPosition;
|
||||
fillerArray = Array.apply(
|
||||
null,
|
||||
new Array(subscribers.subscribers[0].length)
|
||||
).map(String.prototype.valueOf, filler);
|
||||
|
||||
showCurrentStep();
|
||||
|
||||
@ -480,12 +500,12 @@ define(
|
||||
if (subscribers.invalid.length || subscribers.duplicate.length) {
|
||||
// count repeating e-mails inside duplicate array and present them in
|
||||
// 'email (xN)' format
|
||||
var duplicates = {};
|
||||
duplicates = {};
|
||||
subscribers.duplicate.forEach(function (email) {
|
||||
duplicates[email] = (duplicates[email] || 0) + 1;
|
||||
});
|
||||
subscribers.duplicate = [];
|
||||
for (var email in duplicates) {
|
||||
for (email in duplicates) {
|
||||
if (duplicates[email] > 1) {
|
||||
subscribers.duplicate.push(email + ' (x' + duplicates[email] + ')');
|
||||
}
|
||||
@ -494,7 +514,7 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
var import_results = {
|
||||
import_results = {
|
||||
notice: MailPoet.I18n.t('importNoticeSkipped').replace(
|
||||
'%1$s',
|
||||
'<strong>' + (subscribers.invalid.length + subscribers.duplicate.length) + '</strong>'
|
||||
@ -599,13 +619,14 @@ define(
|
||||
description: segmentDescription
|
||||
}
|
||||
}).done(function (response) {
|
||||
var selected_values;
|
||||
window.mailpoetSegments.push({
|
||||
id: response.data.id,
|
||||
name: response.data.name,
|
||||
subscriberCount: 0
|
||||
});
|
||||
|
||||
var selected_values = segmentSelectElement.val();
|
||||
selected_values = segmentSelectElement.val();
|
||||
if (selected_values === null) {
|
||||
selected_values = [response.data.id];
|
||||
} else {
|
||||
@ -642,20 +663,25 @@ define(
|
||||
Handlebars.registerHelper(
|
||||
'show_and_match_columns',
|
||||
function (subscribers, options) {
|
||||
var displayedColumns = [],
|
||||
displayedColumnsIds = [];
|
||||
var displayedColumns = [];
|
||||
var displayedColumnsIds = [];
|
||||
var i;
|
||||
var columnData;
|
||||
var columnId;
|
||||
var headerName;
|
||||
var headerNameMatch;
|
||||
// go through all elements of the first row in subscribers data
|
||||
for (var i in subscribers.subscribers[0]) {
|
||||
var columnData = subscribers.subscribers[0][i],
|
||||
columnId = 'ignore'; // set default column type
|
||||
for (i in subscribers.subscribers[0]) {
|
||||
columnData = subscribers.subscribers[0][i];
|
||||
columnId = 'ignore'; // set default column type
|
||||
// if the column is not undefined and has a valid e-mail, set type as email
|
||||
if (columnData % 1 !== 0 && window.emailRegex.test(columnData)) {
|
||||
columnId = 'email';
|
||||
} else if (subscribers.header) {
|
||||
var headerName = subscribers.header[i],
|
||||
headerNameMatch = window.mailpoetColumns.map(function (el) {
|
||||
return el.name;
|
||||
}).indexOf(headerName);
|
||||
headerName = subscribers.header[i];
|
||||
headerNameMatch = window.mailpoetColumns.map(function (el) {
|
||||
return el.name;
|
||||
}).indexOf(headerName);
|
||||
// set column type using header
|
||||
if (headerNameMatch !== -1) {
|
||||
columnId = window.mailpoetColumns[headerNameMatch].id;
|
||||
@ -733,8 +759,8 @@ define(
|
||||
}
|
||||
})
|
||||
.on('select2:selecting', function (selectEvent) {
|
||||
var selectElement = this,
|
||||
selectedOptionId = selectEvent.params.args.data.id;
|
||||
var selectElement = this;
|
||||
var selectedOptionId = selectEvent.params.args.data.id;
|
||||
// CREATE CUSTOM FIELD
|
||||
if (selectedOptionId === 'create') {
|
||||
selectEvent.preventDefault();
|
||||
@ -743,7 +769,7 @@ define(
|
||||
title: MailPoet.I18n.t('addNewField'),
|
||||
template: jQuery('#form_template_field_form').html()
|
||||
});
|
||||
jQuery('#form_field_new').parsley().on('form:submit', function (parsley) {
|
||||
jQuery('#form_field_new').parsley().on('form:submit', function () {
|
||||
// get data
|
||||
var data = jQuery(this.$element).serializeObject();
|
||||
|
||||
@ -807,8 +833,8 @@ define(
|
||||
// check for duplicate values in all select options
|
||||
jQuery('select.mailpoet_subscribers_column_data_match')
|
||||
.each(function () {
|
||||
var element = this,
|
||||
elementId = jQuery(element).val();
|
||||
var element = this;
|
||||
var elementId = jQuery(element).val();
|
||||
// if another column has the same value and it's not an 'ignore', prompt user
|
||||
if (elementId === selectedOptionId
|
||||
&& elementId !== 'ignore') {
|
||||
@ -824,28 +850,34 @@ define(
|
||||
}
|
||||
})
|
||||
.on('select2:select', function (selectEvent) {
|
||||
var selectElement = this,
|
||||
selectedOptionId = selectEvent.params.data.id;
|
||||
var selectElement = this;
|
||||
var selectedOptionId = selectEvent.params.data.id;
|
||||
jQuery(selectElement).data('column-id', selectedOptionId);
|
||||
filterSubscribers();
|
||||
});
|
||||
|
||||
// filter subscribers' data to detect dates, emails, etc.
|
||||
function filterSubscribers() {
|
||||
var subscribersClone = jQuery.extend(true, {}, subscribers);
|
||||
var preventNextStep = false;
|
||||
var displayedColumns;
|
||||
jQuery(
|
||||
'[data-id="notice_invalidEmail"], [data-id="notice_invalidDate"]')
|
||||
.remove();
|
||||
var subscribersClone = jQuery.extend(true, {}, subscribers),
|
||||
preventNextStep = false,
|
||||
displayedColumns = jQuery.map(
|
||||
jQuery('.mailpoet_subscribers_column_data_match'), function (element, elementIndex) {
|
||||
var columnId = jQuery(element).data('column-id');
|
||||
var validationRule = jQuery(element).data('validation-rule');
|
||||
jQuery(element).val(columnId).trigger('change');
|
||||
return { id: columnId, index: elementIndex, validationRule: validationRule, element: element };
|
||||
});
|
||||
displayedColumns = jQuery.map(
|
||||
jQuery('.mailpoet_subscribers_column_data_match'), function (element, elementIndex) {
|
||||
var columnId = jQuery(element).data('column-id');
|
||||
var validationRule = jQuery(element).data('validation-rule');
|
||||
jQuery(element).val(columnId).trigger('change');
|
||||
return { id: columnId, index: elementIndex, validationRule: validationRule, element: element };
|
||||
});
|
||||
// iterate through the object of mailpoet columns
|
||||
jQuery.map(window.mailpoetColumns, function (column, columnIndex) {
|
||||
jQuery.map(window.mailpoetColumns, function (column) {
|
||||
var firstRowData;
|
||||
var validationRule;
|
||||
var testedFormat;
|
||||
var format;
|
||||
var allowedDateFormats;
|
||||
// check if the column id matches the selected id of one of the
|
||||
// subscriber's data columns
|
||||
var matchedColumn = _.find(displayedColumns, function (data) { return data.id === column.id; });
|
||||
@ -869,7 +901,7 @@ define(
|
||||
}
|
||||
// DATE filter: if column type is date, check if we can recognize it
|
||||
if (column.type === 'date' && matchedColumn) {
|
||||
var allowedDateFormats = [
|
||||
allowedDateFormats = [
|
||||
Moment.ISO_8601,
|
||||
'YYYY/MM/DD',
|
||||
'MM/DD/YYYY',
|
||||
@ -880,8 +912,8 @@ define(
|
||||
'YYYY/MM',
|
||||
'YYYY'
|
||||
];
|
||||
var firstRowData = subscribersClone.subscribers[0][matchedColumn.index];
|
||||
var validationRule = false;
|
||||
firstRowData = subscribersClone.subscribers[0][matchedColumn.index];
|
||||
validationRule = false;
|
||||
// check if date exists
|
||||
if (firstRowData.trim() === '') {
|
||||
subscribersClone.subscribers[0][matchedColumn.index] =
|
||||
@ -892,10 +924,10 @@ define(
|
||||
preventNextStep = true;
|
||||
}
|
||||
else {
|
||||
for (var format in allowedDateFormats) {
|
||||
var testedFormat = allowedDateFormats[format];
|
||||
for (format in allowedDateFormats) {
|
||||
testedFormat = allowedDateFormats[format];
|
||||
if (Moment(firstRowData, testedFormat, true).isValid()) {
|
||||
var validationRule = (typeof (testedFormat) === 'function') ?
|
||||
validationRule = (typeof (testedFormat) === 'function') ?
|
||||
'datetime' :
|
||||
testedFormat;
|
||||
// set validation on the column element
|
||||
@ -910,8 +942,8 @@ define(
|
||||
jQuery.map(subscribersClone.subscribers, function (dataSubscribers, index) {
|
||||
var data = dataSubscribers;
|
||||
var rowData = data[matchedColumn.index];
|
||||
if (index === fillerPosition || rowData.trim() === '') return;
|
||||
var date = Moment(rowData, testedFormat, true);
|
||||
if (index === fillerPosition || rowData.trim() === '') return;
|
||||
// validate date
|
||||
if (date.isValid()) {
|
||||
data[matchedColumn.index] = new Handlebars.SafeString(
|
||||
@ -970,33 +1002,35 @@ define(
|
||||
});
|
||||
|
||||
nextStepButton.off().on('click', function () {
|
||||
var columns = {};
|
||||
var queue = new jQuery.AsyncQueue();
|
||||
var batchNumber = 0;
|
||||
var batchSize = 2000;
|
||||
var timestamp = Date.now() / 1000;
|
||||
var subscribers = [];
|
||||
var importResults = {
|
||||
created: 0,
|
||||
updated: 0,
|
||||
errors: [],
|
||||
segments: []
|
||||
};
|
||||
var subscribers;
|
||||
var splitSubscribers;
|
||||
|
||||
if (jQuery(this).hasClass('button-disabled')) {
|
||||
return;
|
||||
}
|
||||
MailPoet.Modal.loading(true);
|
||||
|
||||
var columns = {},
|
||||
queue = new jQuery.AsyncQueue(),
|
||||
batchNumber = 0,
|
||||
batchSize = 2000,
|
||||
timestamp = Date.now() / 1000,
|
||||
subscribers = [],
|
||||
importResults = {
|
||||
created: 0,
|
||||
updated: 0,
|
||||
errors: [],
|
||||
segments: []
|
||||
},
|
||||
splitSubscribers = function (subscribers, size) {
|
||||
return subscribers.reduce(function (res, item, index) {
|
||||
if (index % size === 0) {
|
||||
res.push([]);
|
||||
}
|
||||
res[res.length - 1].push(item);
|
||||
return res;
|
||||
}, []);
|
||||
},
|
||||
subscribers = splitSubscribers(window.importData.step1.subscribers, batchSize);
|
||||
splitSubscribers = function (subscribers, size) {
|
||||
return subscribers.reduce(function (res, item, index) {
|
||||
if (index % size === 0) {
|
||||
res.push([]);
|
||||
}
|
||||
res[res.length - 1].push(item);
|
||||
return res;
|
||||
}, []);
|
||||
};
|
||||
subscribers = splitSubscribers(window.importData.step1.subscribers, batchSize);
|
||||
|
||||
_.each(jQuery('select.mailpoet_subscribers_column_data_match'),
|
||||
function (column, columnIndex) {
|
||||
@ -1067,6 +1101,9 @@ define(
|
||||
});
|
||||
|
||||
router.on('route:step3', function () {
|
||||
var subscribersDataImportResultsTemplate;
|
||||
var exportMenuElement;
|
||||
var importResults;
|
||||
if (typeof (window.importData.step2) === 'undefined') {
|
||||
router.navigate('step2', { trigger: true });
|
||||
return;
|
||||
@ -1085,25 +1122,23 @@ define(
|
||||
});
|
||||
|
||||
// display statistics
|
||||
var subscribersDataImportResultsTemplate =
|
||||
Handlebars
|
||||
.compile(jQuery('#subscribers_data_import_results_template')
|
||||
.html()),
|
||||
exportMenuElement = jQuery('span.mailpoet_export'),
|
||||
importResults = {
|
||||
created: (window.importData.step2.created)
|
||||
? MailPoet.I18n.t('subscribersCreated')
|
||||
.replace('%1$s', '<strong>' + window.importData.step2.created.toLocaleString() + '</strong>')
|
||||
.replace('%2$s', '"' + window.importData.step2.segments.join('", "') + '"')
|
||||
: false,
|
||||
updated: (window.importData.step2.updated)
|
||||
? MailPoet.I18n.t('subscribersUpdated')
|
||||
.replace('%1$s', '<strong>' + window.importData.step2.updated.toLocaleString() + '</strong>')
|
||||
.replace('%2$s', '"' + window.importData.step2.segments.join('", "') + '"')
|
||||
: false,
|
||||
no_action: (!window.importData.step2.created && !window.importData.step2.updated),
|
||||
added_to_segment_with_welcome_notification: window.importData.step2.added_to_segment_with_welcome_notification
|
||||
};
|
||||
subscribersDataImportResultsTemplate =
|
||||
Handlebars.compile(jQuery('#subscribers_data_import_results_template').html());
|
||||
exportMenuElement = jQuery('span.mailpoet_export');
|
||||
importResults = {
|
||||
created: (window.importData.step2.created)
|
||||
? MailPoet.I18n.t('subscribersCreated')
|
||||
.replace('%1$s', '<strong>' + window.importData.step2.created.toLocaleString() + '</strong>')
|
||||
.replace('%2$s', '"' + window.importData.step2.segments.join('", "') + '"')
|
||||
: false,
|
||||
updated: (window.importData.step2.updated)
|
||||
? MailPoet.I18n.t('subscribersUpdated')
|
||||
.replace('%1$s', '<strong>' + window.importData.step2.updated.toLocaleString() + '</strong>')
|
||||
.replace('%2$s', '"' + window.importData.step2.segments.join('", "') + '"')
|
||||
: false,
|
||||
no_action: (!window.importData.step2.created && !window.importData.step2.updated),
|
||||
added_to_segment_with_welcome_notification: window.importData.step2.added_to_segment_with_welcome_notification
|
||||
};
|
||||
|
||||
jQuery('#subscribers_data_import_results')
|
||||
.html(subscribersDataImportResultsTemplate(importResults))
|
||||
|
@ -57,7 +57,7 @@ class API {
|
||||
$this->setRequestData($_POST);
|
||||
|
||||
if($this->checkToken() === false) {
|
||||
$error_message = __('Invalid API request.', 'mailpoet');
|
||||
$error_message = __('Sorry, but we couldn\'t connect to the MailPoet server. Please refresh the web page and try again.', 'mailpoet');
|
||||
$error_response = $this->createErrorResponse(Error::UNAUTHORIZED, $error_message, Response::STATUS_UNAUTHORIZED);
|
||||
return $error_response->send();
|
||||
}
|
||||
@ -200,4 +200,4 @@ class API {
|
||||
);
|
||||
return $error_response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,13 @@ class Image {
|
||||
if(!empty($element['link'])) {
|
||||
$image_template = '<a href="' . $element['link'] . '">' . $image_template . '</a>';
|
||||
}
|
||||
$align = 'center';
|
||||
if(!empty($element['styles']['block']['textAlign']) && in_array($element['styles']['block']['textAlign'], array('left', 'right'))) {
|
||||
$align = $element['styles']['block']['textAlign'];
|
||||
}
|
||||
$template = '
|
||||
<tr>
|
||||
<td class="mailpoet_image ' . (($element['fullWidth'] === false) ? 'mailpoet_padded_bottom mailpoet_padded_side' : '') . '" align="center" valign="top">
|
||||
<td class="mailpoet_image ' . (($element['fullWidth'] === false) ? 'mailpoet_padded_bottom mailpoet_padded_side' : '') . '" align="' . $align . '" valign="top">
|
||||
' . $image_template . '
|
||||
</td>
|
||||
</tr>';
|
||||
|
@ -4,7 +4,7 @@ if(!defined('ABSPATH')) exit;
|
||||
|
||||
/*
|
||||
* Plugin Name: MailPoet 3 (new)
|
||||
* Version: 3.0.3
|
||||
* Version: 3.0.6
|
||||
* Plugin URI: http://www.mailpoet.com
|
||||
* Description: Create and send newsletters, post notifications and welcome emails from your WordPress.
|
||||
* Author: MailPoet
|
||||
@ -20,7 +20,7 @@ if(!defined('ABSPATH')) exit;
|
||||
*/
|
||||
|
||||
$mailpoet_plugin = array(
|
||||
'version' => '3.0.3',
|
||||
'version' => '3.0.6',
|
||||
'filename' => __FILE__,
|
||||
'path' => dirname(__FILE__),
|
||||
'autoloader' => dirname(__FILE__) . '/vendor/autoload.php',
|
||||
|
11
readme.txt
11
readme.txt
@ -4,7 +4,7 @@ Tags: newsletter, email, welcome email, post notification, autoresponder, signup
|
||||
Requires at least: 4.6
|
||||
Tested up to: 4.8
|
||||
Requires PHP: 5.3
|
||||
Stable tag: 3.0.3
|
||||
Stable tag: 3.0.5
|
||||
License: GPLv3
|
||||
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
@ -114,6 +114,15 @@ Stop by our [support site](https://www.mailpoet.com/support).
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 3.0.6 - 2017-10-10 =
|
||||
* Fixed: subscription forms to not throw form validation engine errors;
|
||||
|
||||
= 3.0.5 - 2017-10-10 =
|
||||
* Added: images can now be aligned left, center or right in email designer;
|
||||
|
||||
= 3.0.4 - 2017-10-05 =
|
||||
* Fixed: dividers and spacers' height can be changed on mouse drag again;
|
||||
|
||||
= 3.0.3 - 2017-10-03 =
|
||||
* Fixed: mixed collation error in WordPress user synchronization. Thanks Chris, Till, Robin, Robero, @Seph, @kaiwen and others for the reports!
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
var fs = require('fs');
|
||||
module.exports = {
|
||||
loadFileToContainer: function (path, window, containerTagName, opts) {
|
||||
var contents = fs.readFileSync(path),
|
||||
container = window.document.createElement(containerTagName);
|
||||
var contents = fs.readFileSync(path);
|
||||
var container = window.document.createElement(containerTagName);
|
||||
var options = opts || {};
|
||||
container.innerHTML = contents;
|
||||
|
||||
|
@ -3,6 +3,7 @@ var sinon = require('sinon');
|
||||
var sinonChai = require('sinon-chai');
|
||||
var chaiJq = require('chai-jq');
|
||||
var _ = require('underscore');
|
||||
var jsdom = require('jsdom').jsdom;
|
||||
|
||||
chai.use(sinonChai);
|
||||
chai.use(chaiJq);
|
||||
@ -11,7 +12,6 @@ global.expect = chai.expect;
|
||||
global.sinon = sinon;
|
||||
|
||||
if (!global.document || !global.window) {
|
||||
var jsdom = require('jsdom').jsdom;
|
||||
|
||||
global.document = jsdom('<html><head><script></script></head><body></body></html>', {}, {
|
||||
FetchExternalResources: ['script'],
|
||||
|
@ -21,6 +21,8 @@ define([
|
||||
|
||||
describe('Automated Latest Content Supervisor', function() {
|
||||
var model;
|
||||
var mock;
|
||||
var module;
|
||||
beforeEach(function() {
|
||||
model = new AutomatedLatestContentBlock.ALCSupervisor();
|
||||
});
|
||||
@ -29,33 +31,33 @@ define([
|
||||
global.stubChannel(EditorApplication);
|
||||
EditorApplication.findModels = sinon.stub().returns([new Backbone.SuperModel()]);
|
||||
|
||||
var mock = sinon.mock({ getBulkTransformedPosts: function() {} })
|
||||
mock = sinon.mock({ getBulkTransformedPosts: function() {} })
|
||||
.expects('getBulkTransformedPosts').once().returns(jQuery.Deferred());
|
||||
|
||||
var module = AutomatedLatestContentInjector({
|
||||
module = AutomatedLatestContentInjector({
|
||||
'newsletter_editor/components/communication': {
|
||||
getBulkTransformedPosts: mock
|
||||
}
|
||||
});
|
||||
|
||||
var model = new module.ALCSupervisor();
|
||||
model = new module.ALCSupervisor();
|
||||
model.refresh();
|
||||
|
||||
mock.verify();
|
||||
});
|
||||
|
||||
it('refreshes posts for given blocks', function() {
|
||||
var block1 = new Backbone.SuperModel(),
|
||||
block2 = new Backbone.SuperModel(),
|
||||
postsSet1 = [
|
||||
{ type: 'customTypeOne' }
|
||||
],
|
||||
postsSet2 = [
|
||||
{ type: 'customTypeTwo' },
|
||||
{ type: 'customTypeTwo' }
|
||||
],
|
||||
mock1 = sinon.mock(block1),
|
||||
mock2 = sinon.mock(block2);
|
||||
var block1 = new Backbone.SuperModel();
|
||||
var block2 = new Backbone.SuperModel();
|
||||
var postsSet1 = [
|
||||
{ type: 'customTypeOne' }
|
||||
];
|
||||
var postsSet2 = [
|
||||
{ type: 'customTypeTwo' },
|
||||
{ type: 'customTypeTwo' }
|
||||
];
|
||||
var mock1 = sinon.mock(block1);
|
||||
var mock2 = sinon.mock(block2);
|
||||
|
||||
mock1.expects('trigger').once().withArgs('refreshPosts', postsSet1);
|
||||
mock2.expects('trigger').once().withArgs('refreshPosts', postsSet2);
|
||||
@ -69,7 +71,8 @@ define([
|
||||
|
||||
describe('Automated latest content', function () {
|
||||
describe('model', function () {
|
||||
var model, module;
|
||||
var model;
|
||||
var module;
|
||||
|
||||
before(function() {
|
||||
module = AutomatedLatestContentBlock;
|
||||
@ -172,6 +175,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
automatedLatestContent: {
|
||||
@ -219,7 +223,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (module.AutomatedLatestContentBlockModel)();
|
||||
model = new (module.AutomatedLatestContentBlockModel)();
|
||||
|
||||
expect(model.get('amount')).to.equal('17');
|
||||
expect(model.get('contentType')).to.equal('mailpoet_page');
|
||||
@ -251,8 +255,9 @@ define([
|
||||
});
|
||||
|
||||
it('accepts displayable posts', function() {
|
||||
var model;
|
||||
EditorApplication.getBlockTypeModel = sinon.stub().returns(ContainerBlock.ContainerBlockModel);
|
||||
var model = new (module.AutomatedLatestContentBlockModel)();
|
||||
model = new (module.AutomatedLatestContentBlockModel)();
|
||||
|
||||
model.updatePosts([{
|
||||
type: 'someCustomType'
|
||||
@ -264,7 +269,9 @@ define([
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
var model, view, module;
|
||||
var model;
|
||||
var view;
|
||||
var module;
|
||||
|
||||
before(function() {
|
||||
module = AutomatedLatestContentBlock;
|
||||
@ -290,11 +297,8 @@ define([
|
||||
});
|
||||
|
||||
describe('replaceAllButtonStyles', function () {
|
||||
var model, view, module, onStub;
|
||||
|
||||
before(function() {
|
||||
module = AutomatedLatestContentBlock;
|
||||
});
|
||||
var onStub;
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
onStub = sinon.stub();
|
||||
@ -302,8 +306,7 @@ define([
|
||||
global.stubConfig(EditorApplication);
|
||||
EditorApplication.getBlockTypeModel = sinon.stub().returns(Backbone.Model);
|
||||
EditorApplication.getBlockTypeView = sinon.stub().returns(Backbone.View);
|
||||
model = {set: sinon.stub()};
|
||||
view = new (module.AutomatedLatestContentBlockView)({model: model});
|
||||
view = new (AutomatedLatestContentBlock.AutomatedLatestContentBlockView)({model: {set: sinon.stub()}});
|
||||
});
|
||||
|
||||
it('listens to the event', function () {
|
||||
@ -321,13 +324,15 @@ define([
|
||||
}
|
||||
};
|
||||
callback(data);
|
||||
expect(model.set).to.have.been.callCount(1);
|
||||
expect(model.set).to.have.been.calledWithMatch(sinon.match.has('readMoreButton', data));
|
||||
expect(view.model.set).to.have.been.callCount(1);
|
||||
expect(view.model.set).to.have.been.calledWithMatch(sinon.match.has('readMoreButton', data));
|
||||
});
|
||||
});
|
||||
|
||||
describe('block settings view', function () {
|
||||
var model, view, module;
|
||||
var model;
|
||||
var view;
|
||||
var module;
|
||||
|
||||
before(function() {
|
||||
module = AutomatedLatestContentInjector({
|
||||
@ -496,7 +501,8 @@ define([
|
||||
});
|
||||
|
||||
describe('when "title only" display type is selected', function() {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
beforeEach(function() {
|
||||
model = new (module.AutomatedLatestContentBlockModel)();
|
||||
view = new (module.AutomatedLatestContentBlockSettingsView)({model: model});
|
||||
@ -509,7 +515,8 @@ define([
|
||||
});
|
||||
|
||||
describe('when "title as list" is selected', function() {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
beforeEach(function() {
|
||||
model = new (module.AutomatedLatestContentBlockModel)();
|
||||
view = new (module.AutomatedLatestContentBlockSettingsView)({model: model});
|
||||
|
@ -108,6 +108,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
button: {
|
||||
@ -131,7 +132,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (ButtonBlock.ButtonBlockModel)();
|
||||
model = new (ButtonBlock.ButtonBlockModel)();
|
||||
|
||||
expect(model.get('text')).to.equal('Some new text');
|
||||
expect(model.get('url')).to.equal('http://somenewurl.com');
|
||||
@ -173,7 +174,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
before(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -264,8 +266,9 @@ define([
|
||||
});
|
||||
|
||||
describe('replaceAllButtonStyles', function () {
|
||||
var model, view, onStub;
|
||||
|
||||
var model;
|
||||
var view;
|
||||
var onStub;
|
||||
|
||||
beforeEach(function () {
|
||||
onStub = sinon.stub();
|
||||
@ -317,7 +320,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
before(function() {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
|
@ -13,8 +13,9 @@ define([
|
||||
|
||||
describe('model', function () {
|
||||
describe('by default', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication);
|
||||
var model = new ModelClass();
|
||||
model = new ModelClass();
|
||||
|
||||
it('has container type', function () {
|
||||
expect(model.get('type')).to.equal('container');
|
||||
@ -33,6 +34,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
container: {
|
||||
@ -44,7 +46,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (ContainerBlock.ContainerBlockModel)();
|
||||
model = new (ContainerBlock.ContainerBlockModel)();
|
||||
|
||||
expect(model.get('styles.block.backgroundColor')).to.equal('#123456');
|
||||
});
|
||||
@ -52,10 +54,10 @@ define([
|
||||
|
||||
describe('when creating with children', function () {
|
||||
var testModel = {
|
||||
type: 'sampleType',
|
||||
someField: 'Some Content'
|
||||
},
|
||||
model;
|
||||
type: 'sampleType',
|
||||
someField: 'Some Content'
|
||||
};
|
||||
var model;
|
||||
|
||||
it('will recursively create children', function () {
|
||||
EditorApplication.getBlockTypeModel = sinon.stub().returns(Backbone.Model);
|
||||
@ -107,10 +109,12 @@ define([
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
var model = new (ContainerBlock.ContainerBlockModel)(),
|
||||
view = new (ContainerBlock.ContainerBlockView)({model: model});
|
||||
model = new (ContainerBlock.ContainerBlockModel)();
|
||||
view = new (ContainerBlock.ContainerBlockView)({model: model});
|
||||
|
||||
it('renders', function () {
|
||||
expect(view.render).to.not.throw();
|
||||
@ -119,8 +123,8 @@ define([
|
||||
describe('once rendered', function () {
|
||||
|
||||
describe('on root level', function () {
|
||||
var model = new (ContainerBlock.ContainerBlockModel)(),
|
||||
view;
|
||||
var model = new (ContainerBlock.ContainerBlockModel)();
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -151,8 +155,8 @@ define([
|
||||
});
|
||||
|
||||
describe.skip('on non-root levels', function () {
|
||||
var model = new (ContainerBlock.ContainerBlockModel)(),
|
||||
view;
|
||||
var model = new (ContainerBlock.ContainerBlockModel)();
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -187,17 +191,20 @@ define([
|
||||
});
|
||||
|
||||
describe('settings view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
var model = new (ContainerBlock.ContainerBlockModel)(),
|
||||
view = new (ContainerBlock.ContainerBlockSettingsView)({model: model});
|
||||
model = new (ContainerBlock.ContainerBlockModel)();
|
||||
view = new (ContainerBlock.ContainerBlockSettingsView)({model: model});
|
||||
|
||||
it('renders', function () {
|
||||
expect(view.render).to.not.throw();
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
beforeEach(function() {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
|
@ -70,6 +70,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
divider: {
|
||||
@ -85,7 +86,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (DividerBlock.DividerBlockModel)();
|
||||
model = new (DividerBlock.DividerBlockModel)();
|
||||
|
||||
expect(model.get('styles.block.backgroundColor')).to.equal('#123456');
|
||||
expect(model.get('styles.block.padding')).to.equal('37px');
|
||||
@ -137,13 +138,15 @@ define([
|
||||
});
|
||||
|
||||
describe('settings view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication, {
|
||||
dividers: ['solid', 'inset']
|
||||
});
|
||||
var model = new (DividerBlock.DividerBlockModel)(),
|
||||
view = new (DividerBlock.DividerBlockSettingsView)({model: model});
|
||||
model = new (DividerBlock.DividerBlockModel)();
|
||||
view = new (DividerBlock.DividerBlockSettingsView)({model: model});
|
||||
|
||||
it('renders', function () {
|
||||
expect(view.render).to.not.throw();
|
||||
@ -151,7 +154,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
before(function() {
|
||||
global.stubChannel(EditorApplication);
|
||||
|
@ -79,6 +79,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
footer: {
|
||||
@ -101,7 +102,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (FooterBlock.FooterBlockModel)();
|
||||
model = new (FooterBlock.FooterBlockModel)();
|
||||
|
||||
expect(model.get('text')).to.equal('some custom config text');
|
||||
expect(model.get('styles.block.backgroundColor')).to.equal('#123456');
|
||||
@ -116,11 +117,12 @@ define([
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
var model = new (FooterBlock.FooterBlockModel)(),
|
||||
view;
|
||||
model = new (FooterBlock.FooterBlockModel)();
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -134,13 +136,15 @@ define([
|
||||
});
|
||||
|
||||
describe('settings view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication, {
|
||||
fonts: ['Arial', 'Tahoma'],
|
||||
textSizes: ['16px', '20px']
|
||||
});
|
||||
var model = new (FooterBlock.FooterBlockModel)(),
|
||||
view = new (FooterBlock.FooterBlockSettingsView)({model: model});
|
||||
model = new (FooterBlock.FooterBlockModel)();
|
||||
view = new (FooterBlock.FooterBlockSettingsView)({model: model});
|
||||
|
||||
it('renders', function () {
|
||||
expect(view.render).to.not.throw();
|
||||
@ -148,7 +152,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
beforeEach(function() {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -188,7 +193,7 @@ define([
|
||||
expect(model.get('styles.link.textDecoration')).to.equal('underline');
|
||||
});
|
||||
|
||||
it('updates the model when background color changes', function () {
|
||||
it('updates the model when text alignment changes', function () {
|
||||
view.$('.mailpoet_field_footer_alignment').last().prop('checked', true).change();
|
||||
expect(model.get('styles.text.textAlign')).to.equal('right');
|
||||
});
|
||||
|
@ -79,6 +79,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
header: {
|
||||
@ -101,7 +102,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (HeaderBlock.HeaderBlockModel)();
|
||||
model = new (HeaderBlock.HeaderBlockModel)();
|
||||
|
||||
expect(model.get('text')).to.equal('some custom config text');
|
||||
expect(model.get('styles.block.backgroundColor')).to.equal('#123456');
|
||||
@ -115,11 +116,12 @@ define([
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
var model = new (HeaderBlock.HeaderBlockModel)(),
|
||||
view;
|
||||
model = new (HeaderBlock.HeaderBlockModel)();
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -133,14 +135,16 @@ define([
|
||||
});
|
||||
|
||||
describe('settings view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication, {
|
||||
fonts: ['Arial', 'Tahoma'],
|
||||
textSizes: ['16px', '20px']
|
||||
});
|
||||
var model = new (HeaderBlock.HeaderBlockModel)(),
|
||||
view = new (HeaderBlock.HeaderBlockSettingsView)({model: model});
|
||||
model = new (HeaderBlock.HeaderBlockModel)();
|
||||
view = new (HeaderBlock.HeaderBlockSettingsView)({model: model});
|
||||
|
||||
it('renders', function () {
|
||||
expect(view.render).to.not.throw();
|
||||
@ -148,7 +152,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
beforeEach(function() {
|
||||
global.stubChannel(EditorApplication);
|
||||
|
@ -74,6 +74,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
image: {
|
||||
@ -91,7 +92,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (ImageBlock.ImageBlockModel)();
|
||||
model = new (ImageBlock.ImageBlockModel)();
|
||||
|
||||
expect(model.get('link')).to.equal('http://example.org/customConfigPage');
|
||||
expect(model.get('src')).to.equal('http://example.org/someCustomConfigImage.png');
|
||||
@ -104,11 +105,12 @@ define([
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication);
|
||||
var model = new (ImageBlock.ImageBlockModel)(),
|
||||
view;
|
||||
model = new (ImageBlock.ImageBlockModel)();
|
||||
|
||||
beforeEach(function () {
|
||||
view = new (ImageBlock.ImageBlockView)({model: model});
|
||||
@ -158,7 +160,8 @@ define([
|
||||
});
|
||||
|
||||
describe('block settings view', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
var newWidth = 123;
|
||||
var newHeight = 456;
|
||||
var newLink = 'http://example.org/someNewLink';
|
||||
@ -206,11 +209,15 @@ define([
|
||||
});
|
||||
|
||||
it('updates the model when padding changes', function () {
|
||||
var newValue = 'false';
|
||||
view.$('.mailpoet_field_image_full_width').prop('checked', false).change();
|
||||
expect(model.get('fullWidth')).to.equal(false);
|
||||
});
|
||||
|
||||
it('updates the model when alignment changes', function () {
|
||||
view.$('.mailpoet_field_image_alignment').first().prop('checked', true).change();
|
||||
expect(model.get('styles.block.textAlign')).to.equal('left');
|
||||
});
|
||||
|
||||
it.skip('closes the sidepanel after "Done" is clicked', function() {
|
||||
var mock = sinon.mock().once();
|
||||
global.MailPoet.Modal.cancel = mock;
|
||||
|
@ -132,6 +132,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
posts: {
|
||||
@ -179,7 +180,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (PostsBlock.PostsBlockModel)();
|
||||
model = new (PostsBlock.PostsBlockModel)();
|
||||
|
||||
expect(model.get('amount')).to.equal('17');
|
||||
expect(model.get('contentType')).to.equal('mailpoet_page');
|
||||
@ -261,7 +262,8 @@ define([
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -285,7 +287,8 @@ define([
|
||||
});
|
||||
|
||||
describe('block settings view', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
before(function () {
|
||||
CommunicationComponent.getPostTypes = function() {
|
||||
@ -421,7 +424,8 @@ define([
|
||||
});
|
||||
|
||||
describe('when "title only" display type is selected', function() {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
beforeEach(function() {
|
||||
model = new (PostsBlock.PostsBlockModel)();
|
||||
model.request = sinon.stub().returns({$el: {}});
|
||||
|
@ -29,6 +29,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
social: {
|
||||
@ -36,7 +37,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (SocialBlock.SocialBlockModel)();
|
||||
model = new (SocialBlock.SocialBlockModel)();
|
||||
|
||||
expect(model.get('iconSet')).to.equal('customConfigIconSet');
|
||||
});
|
||||
@ -130,7 +131,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
|
||||
before(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -215,7 +217,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubAvailableStyles(EditorApplication, {
|
||||
|
@ -55,6 +55,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
spacer: {
|
||||
@ -67,7 +68,7 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (SpacerBlock.SpacerBlockModel)();
|
||||
model = new (SpacerBlock.SpacerBlockModel)();
|
||||
|
||||
expect(model.get('styles.block.backgroundColor')).to.equal('#567890');
|
||||
expect(model.get('styles.block.height')).to.equal('19px');
|
||||
@ -119,11 +120,12 @@ define([
|
||||
});
|
||||
|
||||
describe('settings view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
|
||||
var model = new (SpacerBlock.SpacerBlockModel)(),
|
||||
view;
|
||||
model = new (SpacerBlock.SpacerBlockModel)();
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubChannel(EditorApplication);
|
||||
@ -135,7 +137,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var view, model;
|
||||
var view;
|
||||
var model;
|
||||
beforeEach(function() {
|
||||
global.stubChannel(EditorApplication);
|
||||
global.stubConfig(EditorApplication);
|
||||
|
@ -23,6 +23,7 @@ define([
|
||||
});
|
||||
|
||||
it('uses defaults from config when they are set', function () {
|
||||
var model;
|
||||
global.stubConfig(EditorApplication, {
|
||||
blockDefaults: {
|
||||
text: {
|
||||
@ -30,16 +31,18 @@ define([
|
||||
}
|
||||
}
|
||||
});
|
||||
var model = new (TextBlock.TextBlockModel)();
|
||||
model = new (TextBlock.TextBlockModel)();
|
||||
|
||||
expect(model.get('text')).to.equal('some custom config text');
|
||||
});
|
||||
});
|
||||
|
||||
describe('block view', function () {
|
||||
var model;
|
||||
var view;
|
||||
global.stubConfig(EditorApplication);
|
||||
var model = new (TextBlock.TextBlockModel)(),
|
||||
view = new (TextBlock.TextBlockView)({model: model});
|
||||
model = new (TextBlock.TextBlockModel)();
|
||||
view = new (TextBlock.TextBlockView)({model: model});
|
||||
|
||||
it('renders', function () {
|
||||
expect(view.render).to.not.throw();
|
||||
@ -47,8 +50,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function () {
|
||||
var model = new (TextBlock.TextBlockModel)(),
|
||||
view;
|
||||
var model = new (TextBlock.TextBlockModel)();
|
||||
var view;
|
||||
|
||||
beforeEach(function () {
|
||||
global.stubConfig(EditorApplication);
|
||||
|
@ -32,15 +32,15 @@ define([
|
||||
});
|
||||
|
||||
it('caches results', function() {
|
||||
var deferred = jQuery.Deferred(),
|
||||
mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred),
|
||||
module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
var deferred = jQuery.Deferred();
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred);
|
||||
var module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
deferred.resolve({
|
||||
post: 'val1',
|
||||
page: 'val2'
|
||||
@ -54,16 +54,16 @@ define([
|
||||
|
||||
describe('getTaxonomies', function() {
|
||||
it('sends post type to endpoint', function() {
|
||||
var spy,
|
||||
post = function(params) {
|
||||
var deferred = jQuery.Deferred();
|
||||
deferred.resolve({
|
||||
category: 'val1',
|
||||
post_tag: 'val2'
|
||||
});
|
||||
return deferred;
|
||||
},
|
||||
module;
|
||||
var spy;
|
||||
var post = function() {
|
||||
var deferred = jQuery.Deferred();
|
||||
deferred.resolve({
|
||||
category: 'val1',
|
||||
post_tag: 'val2'
|
||||
});
|
||||
return deferred;
|
||||
};
|
||||
var module;
|
||||
spy = sinon.spy(post);
|
||||
module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
@ -99,15 +99,15 @@ define([
|
||||
});
|
||||
|
||||
it('caches results', function() {
|
||||
var deferred = jQuery.Deferred(),
|
||||
mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred),
|
||||
module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
var deferred = jQuery.Deferred();
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred);
|
||||
var module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
deferred.resolve({ category: 'val1' });
|
||||
module.getTaxonomies('page');
|
||||
module.getTaxonomies('page');
|
||||
@ -119,7 +119,7 @@ define([
|
||||
describe('getTerms', function() {
|
||||
it('sends terms to endpoint', function() {
|
||||
var spy;
|
||||
var post = function(params) {
|
||||
var post = function() {
|
||||
var deferred = jQuery.Deferred();
|
||||
deferred.resolve({});
|
||||
return deferred;
|
||||
@ -163,15 +163,15 @@ define([
|
||||
});
|
||||
|
||||
it('caches results', function() {
|
||||
var deferred = jQuery.Deferred(),
|
||||
mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred),
|
||||
module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
var deferred = jQuery.Deferred();
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred);
|
||||
var module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
deferred.resolve({ term1: 'term1val1', term2: 'term2val2' });
|
||||
module.getTerms({ taxonomies: ['category'] });
|
||||
module.getTerms({ taxonomies: ['category'] });
|
||||
@ -182,13 +182,13 @@ define([
|
||||
|
||||
describe('getPosts', function() {
|
||||
it('sends options to endpoint', function() {
|
||||
var spy,
|
||||
post = function(params) {
|
||||
var deferred = jQuery.Deferred();
|
||||
deferred.resolve({});
|
||||
return deferred;
|
||||
},
|
||||
module;
|
||||
var spy;
|
||||
var post = function() {
|
||||
var deferred = jQuery.Deferred();
|
||||
deferred.resolve({});
|
||||
return deferred;
|
||||
};
|
||||
var module;
|
||||
spy = sinon.spy(post);
|
||||
module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
@ -231,15 +231,15 @@ define([
|
||||
});
|
||||
|
||||
it('caches results', function() {
|
||||
var deferred = jQuery.Deferred(),
|
||||
mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred),
|
||||
module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
var deferred = jQuery.Deferred();
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred);
|
||||
var module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
deferred.resolve({
|
||||
type: 'posts',
|
||||
search: 'some search term'
|
||||
@ -253,13 +253,13 @@ define([
|
||||
|
||||
describe('getTransformedPosts', function() {
|
||||
it('sends options to endpoint', function() {
|
||||
var spy,
|
||||
post = function(params) {
|
||||
var deferred = jQuery.Deferred();
|
||||
deferred.resolve({});
|
||||
return deferred;
|
||||
},
|
||||
module;
|
||||
var spy;
|
||||
var post = function() {
|
||||
var deferred = jQuery.Deferred();
|
||||
deferred.resolve({});
|
||||
return deferred;
|
||||
};
|
||||
var module;
|
||||
spy = sinon.spy(post);
|
||||
module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
@ -302,15 +302,15 @@ define([
|
||||
});
|
||||
|
||||
it('caches results', function() {
|
||||
var deferred = jQuery.Deferred(),
|
||||
mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred),
|
||||
module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
var deferred = jQuery.Deferred();
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(deferred);
|
||||
var module = CommunicationInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
deferred.resolve({
|
||||
type: 'posts',
|
||||
posts: [1, 3]
|
||||
|
@ -7,10 +7,11 @@ define([
|
||||
|
||||
describe('Config', function () {
|
||||
it('loads and stores configuration', function() {
|
||||
var model;
|
||||
ConfigComponent.setConfig({
|
||||
testConfig: 'testValue'
|
||||
});
|
||||
var model = ConfigComponent.getConfig();
|
||||
model = ConfigComponent.getConfig();
|
||||
expect(model.get('testConfig')).to.equal('testValue');
|
||||
});
|
||||
});
|
||||
|
@ -65,8 +65,8 @@ define([
|
||||
|
||||
describe('block types', function() {
|
||||
it('registers a block type view and model', function() {
|
||||
var blockModel = new Backbone.SuperModel(),
|
||||
blockView = new Backbone.View();
|
||||
var blockModel = new Backbone.SuperModel();
|
||||
var blockView = new Backbone.View();
|
||||
ContentComponent.registerBlockType('testType', {
|
||||
blockModel: blockModel,
|
||||
blockView: blockView
|
||||
@ -78,13 +78,16 @@ define([
|
||||
|
||||
describe('transformation to json', function() {
|
||||
it('includes content, globalStyles and initial newsletter fields', function() {
|
||||
var json;
|
||||
var dataField = {
|
||||
containerModelField: 'containerModelValue'
|
||||
}, stylesField = {
|
||||
globalStylesField: 'globalStylesValue'
|
||||
}, newsletterFields = {
|
||||
subject: 'test newsletter subject'
|
||||
};
|
||||
containerModelField: 'containerModelValue'
|
||||
};
|
||||
var stylesField = {
|
||||
globalStylesField: 'globalStylesValue'
|
||||
};
|
||||
var newsletterFields = {
|
||||
subject: 'test newsletter subject'
|
||||
};
|
||||
EditorApplication._contentContainer = {
|
||||
toJSON: function() {
|
||||
return dataField;
|
||||
@ -104,7 +107,7 @@ define([
|
||||
}
|
||||
};
|
||||
};
|
||||
var json = ContentComponent.toJSON();
|
||||
json = ContentComponent.toJSON();
|
||||
expect(json).to.deep.equal(_.extend({
|
||||
body: {
|
||||
content: dataField,
|
||||
|
@ -23,7 +23,8 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function() {
|
||||
var view, model;
|
||||
var view;
|
||||
var model;
|
||||
beforeEach(function() {
|
||||
model = new Backbone.SuperModel({
|
||||
subject: 'a test subject',
|
||||
|
@ -38,8 +38,9 @@ define([
|
||||
});
|
||||
|
||||
it('triggers afterEditorSave event', function() {
|
||||
var spy = sinon.spy(),
|
||||
promise = jQuery.Deferred();
|
||||
var module;
|
||||
var spy = sinon.spy();
|
||||
var promise = jQuery.Deferred();
|
||||
global.stubChannel(EditorApplication, {
|
||||
trigger: spy
|
||||
});
|
||||
@ -48,7 +49,7 @@ define([
|
||||
type: 'container'
|
||||
}
|
||||
});
|
||||
var module = SaveInjector({
|
||||
module = SaveInjector({
|
||||
'newsletter_editor/components/communication': {
|
||||
saveNewsletter: sinon.stub().returns(promise)
|
||||
}
|
||||
@ -74,19 +75,20 @@ define([
|
||||
});
|
||||
|
||||
it('encodes newsletter body in JSON format', function() {
|
||||
var body = {type: 'testType'},
|
||||
mock = sinon.mock()
|
||||
.once()
|
||||
.withArgs({
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.returns(jQuery.Deferred());
|
||||
var module;
|
||||
var body = {type: 'testType'};
|
||||
var mock = sinon.mock()
|
||||
.once()
|
||||
.withArgs({
|
||||
body: JSON.stringify(body)
|
||||
})
|
||||
.returns(jQuery.Deferred());
|
||||
global.stubChannel(EditorApplication);
|
||||
|
||||
EditorApplication.toJSON = sinon.stub().returns({
|
||||
body: body
|
||||
});
|
||||
var module = SaveInjector({
|
||||
module = SaveInjector({
|
||||
'newsletter_editor/components/communication': {
|
||||
saveNewsletter: mock
|
||||
}
|
||||
@ -134,15 +136,17 @@ define([
|
||||
});
|
||||
|
||||
it('triggers template saving when clicked on "save as template" button', function() {
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(jQuery.Deferred()),
|
||||
html2canvasMock = jQuery.Deferred();
|
||||
var mock = sinon.mock({ post: function() {} }).expects('post').once().returns(jQuery.Deferred());
|
||||
var html2canvasMock = jQuery.Deferred();
|
||||
var module;
|
||||
var view;
|
||||
|
||||
html2canvasMock.resolve({
|
||||
toDataURL: function() { return 'somedataurl'; }
|
||||
});
|
||||
|
||||
EditorApplication.getBody = sinon.stub();
|
||||
var module = SaveInjector({
|
||||
module = SaveInjector({
|
||||
mailpoet: {
|
||||
Ajax: {
|
||||
post: mock
|
||||
@ -163,7 +167,7 @@ define([
|
||||
};
|
||||
}
|
||||
});
|
||||
var view = new (module.SaveView)();
|
||||
view = new (module.SaveView)();
|
||||
view.render();
|
||||
|
||||
view.$('.mailpoet_save_as_template_name').val('A sample template');
|
||||
@ -174,18 +178,19 @@ define([
|
||||
});
|
||||
|
||||
it('saves newsletter when clicked on "next" button', function() {
|
||||
var spy = sinon.spy(),
|
||||
module = SaveInjector({
|
||||
'newsletter_editor/components/communication': {
|
||||
saveNewsletter: function() {
|
||||
return jQuery.Deferred();
|
||||
}
|
||||
var spy = sinon.spy();
|
||||
var view;
|
||||
var module = SaveInjector({
|
||||
'newsletter_editor/components/communication': {
|
||||
saveNewsletter: function() {
|
||||
return jQuery.Deferred();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
global.stubChannel(EditorApplication, {
|
||||
trigger: spy
|
||||
});
|
||||
var view = new (module.SaveView)();
|
||||
view = new (module.SaveView)();
|
||||
view.render();
|
||||
|
||||
view.$('.mailpoet_save_next').click();
|
||||
|
@ -47,7 +47,9 @@ define([
|
||||
});
|
||||
|
||||
describe('once rendered', function() {
|
||||
var model, availableStyles, view;
|
||||
var model;
|
||||
var availableStyles;
|
||||
var view;
|
||||
before(function() {
|
||||
model = new Backbone.SuperModel({
|
||||
text: {
|
||||
|
@ -9,10 +9,11 @@ define([
|
||||
|
||||
describe('Styles', function () {
|
||||
it('loads and stores globally available styles', function() {
|
||||
var model;
|
||||
StylesComponent.setGlobalStyles({
|
||||
testStyle: 'testValue'
|
||||
});
|
||||
var model = StylesComponent.getGlobalStyles();
|
||||
model = StylesComponent.getGlobalStyles();
|
||||
expect(model.get('testStyle')).to.equal('testValue');
|
||||
});
|
||||
|
||||
@ -35,7 +36,8 @@ define([
|
||||
});
|
||||
|
||||
describe('view', function() {
|
||||
var model, view;
|
||||
var model;
|
||||
var view;
|
||||
beforeEach(function() {
|
||||
model = new (StylesComponent.StylesModel)();
|
||||
view = new (StylesComponent.StylesView)({ model: model });
|
||||
|
@ -133,6 +133,29 @@ class RendererTest extends \MailPoetTest {
|
||||
expect($DOM('tr > td > img', 0)->attr('style'))->notEmpty();
|
||||
}
|
||||
|
||||
function testItRendersAlignedImage() {
|
||||
$newsletter = $this->newsletter['body'];
|
||||
$template = $newsletter['content']['blocks'][0]['blocks'][0]['blocks'][1];
|
||||
// default alignment (center)
|
||||
unset($template['styles']['block']['textAlign']);
|
||||
$DOM = $this->DOM_parser->parseStr(Image::render($template, $columnCount = 1));
|
||||
expect($DOM('tr > td', 0)->attr('align'))->equals('center');
|
||||
$template['styles']['block']['textAlign'] = 'center';
|
||||
$DOM = $this->DOM_parser->parseStr(Image::render($template, $columnCount = 1));
|
||||
expect($DOM('tr > td', 0)->attr('align'))->equals('center');
|
||||
$template['styles']['block']['textAlign'] = 'something odd';
|
||||
$DOM = $this->DOM_parser->parseStr(Image::render($template, $columnCount = 1));
|
||||
expect($DOM('tr > td', 0)->attr('align'))->equals('center');
|
||||
// left alignment
|
||||
$template['styles']['block']['textAlign'] = 'left';
|
||||
$DOM = $this->DOM_parser->parseStr(Image::render($template, $columnCount = 1));
|
||||
expect($DOM('tr > td', 0)->attr('align'))->equals('left');
|
||||
// right alignment
|
||||
$template['styles']['block']['textAlign'] = 'right';
|
||||
$DOM = $this->DOM_parser->parseStr(Image::render($template, $columnCount = 1));
|
||||
expect($DOM('tr > td', 0)->attr('align'))->equals('right');
|
||||
}
|
||||
|
||||
function testItDoesNotRenderImageWithoutSrc() {
|
||||
$image = array(
|
||||
'src' => '',
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="mailpoet_tools"></div>
|
||||
<div class="mailpoet_content" style="text-align: {{ model.styles.block.textAlign }}; width: {{model.width}}">
|
||||
<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}}" />
|
||||
|
@ -27,23 +27,23 @@
|
||||
<label>
|
||||
<div class="mailpoet_form_field_title"><%= __('Width') %></div>
|
||||
<div class="mailpoet_form_field_input_option">
|
||||
<input
|
||||
<input
|
||||
class="mailpoet_input mailpoet_input_small mailpoet_field_image_width_input"
|
||||
name="image-width-input"
|
||||
type="number"
|
||||
value="{{getNumber model.width}}"
|
||||
name="image-width-input"
|
||||
type="number"
|
||||
value="{{getNumber model.width}}"
|
||||
min="36"
|
||||
max="660"
|
||||
step="2"
|
||||
step="2"
|
||||
/> px
|
||||
<input
|
||||
class="mailpoet_range mailpoet_range_small mailpoet_field_image_width"
|
||||
name="image-width"
|
||||
type="range"
|
||||
value="{{getNumber model.width}}"
|
||||
<input
|
||||
class="mailpoet_range mailpoet_range_small mailpoet_field_image_width"
|
||||
name="image-width"
|
||||
type="range"
|
||||
value="{{getNumber model.width}}"
|
||||
min="36"
|
||||
max="660"
|
||||
step="2"
|
||||
step="2"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
@ -57,6 +57,27 @@
|
||||
<span id="tooltip-designer-full-width" class="tooltip-help-designer-full-width"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mailpoet_form_field">
|
||||
<div class="mailpoet_form_field_title"><%= __('Alignment') %></div>
|
||||
<div class="mailpoet_form_field_radio_option">
|
||||
<label>
|
||||
<input type="radio" name="alignment" class="mailpoet_field_image_alignment" value="left" {{#ifCond model.styles.block.textAlign '===' 'left'}}CHECKED{{/ifCond}}/>
|
||||
<%= __('Left') %>
|
||||
</label>
|
||||
</div>
|
||||
<div class="mailpoet_form_field_radio_option">
|
||||
<label>
|
||||
<input type="radio" name="alignment" class="mailpoet_field_image_alignment" value="center" {{#ifCond model.styles.block.textAlign '===' 'center'}}CHECKED{{/ifCond}}/>
|
||||
<%= __('Center') %>
|
||||
</label>
|
||||
</div>
|
||||
<div class="mailpoet_form_field_radio_option">
|
||||
<label>
|
||||
<input type="radio" name="alignment" class="mailpoet_field_image_alignment" value="right" {{#ifCond model.styles.block.textAlign '===' 'right'}}CHECKED{{/ifCond}}/>
|
||||
<%= __('Right') %>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="mailpoet_form_field">
|
||||
<input type="button" name="select-another-image" class="button button-secondary mailpoet_button_full mailpoet_field_image_select_another_image" value="<%= __('Select another image') | escape('html_attr') %>" />
|
||||
|
Reference in New Issue
Block a user