Page Builder by SiteOrigin - Version 2.10.3

Version Description

  • 2 April 2019 =
  • Layout builder widget: Call styles sanitization in update.
  • Live editor: Only call process_raw_widgets once for preview data.
  • Add a setting for whether to display SiteOrigin Page Builder post state.
  • Sidebars emulator: Cache the result of url_to_postid().
  • Prevent affecting child layouts with parent layouts' CSS.
Download this release

Release Info

Developer gpriday
Plugin Icon 128x128 Page Builder by SiteOrigin
Version 2.10.3
Comparing to
See all releases

Code changes from version 2.10.2 to 2.10.3

compat/js/siteorigin-panels-layout-block.js CHANGED
@@ -1,352 +1,352 @@
1
- "use strict";
2
-
3
- function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
-
5
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
-
7
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
8
-
9
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
10
-
11
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
12
-
13
- function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
14
-
15
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
16
-
17
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
18
-
19
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
20
-
21
- var _lodash = lodash,
22
- isEqual = _lodash.isEqual,
23
- debounce = _lodash.debounce,
24
- isEmpty = _lodash.isEmpty,
25
- isFunction = _lodash.isFunction;
26
- var registerBlockType = wp.blocks.registerBlockType;
27
- var _wp$element = wp.element,
28
- Component = _wp$element.Component,
29
- Fragment = _wp$element.Fragment,
30
- RawHTML = _wp$element.RawHTML,
31
- createRef = _wp$element.createRef;
32
- var BlockControls = wp.editor.BlockControls;
33
- var _wp$components = wp.components,
34
- Toolbar = _wp$components.Toolbar,
35
- IconButton = _wp$components.IconButton,
36
- Spinner = _wp$components.Spinner;
37
- var __ = wp.i18n.__;
38
- var _window = window,
39
- soPanelsBlockEditorAdmin = _window.soPanelsBlockEditorAdmin;
40
-
41
- var SiteOriginPanelsLayoutBlock =
42
- /*#__PURE__*/
43
- function (_Component) {
44
- _inherits(SiteOriginPanelsLayoutBlock, _Component);
45
-
46
- function SiteOriginPanelsLayoutBlock(props) {
47
- var _this;
48
-
49
- _classCallCheck(this, SiteOriginPanelsLayoutBlock);
50
-
51
- _this = _possibleConstructorReturn(this, _getPrototypeOf(SiteOriginPanelsLayoutBlock).call(this, props));
52
- var editMode = soPanelsBlockEditorAdmin.defaultMode === 'edit' || isEmpty(props.panelsData);
53
- _this.state = {
54
- editing: editMode,
55
- loadingPreview: !editMode,
56
- previewHtml: ''
57
- };
58
- _this.panelsContainer = createRef();
59
- _this.previewContainer = createRef();
60
- _this.panelsInitialized = false;
61
- _this.previewInitialized = false;
62
- return _this;
63
- }
64
-
65
- _createClass(SiteOriginPanelsLayoutBlock, [{
66
- key: "componentDidMount",
67
- value: function componentDidMount() {
68
- this.isStillMounted = true;
69
-
70
- if (this.state.editing) {
71
- this.setupPanels();
72
- } else if (!this.state.editing && !this.previewInitialized) {
73
- this.fetchPreview(this.props);
74
- this.fetchPreview = debounce(this.fetchPreview, 500);
75
- }
76
- }
77
- }, {
78
- key: "componentWillUnmount",
79
- value: function componentWillUnmount() {
80
- this.isStillMounted = false;
81
-
82
- if (this.builderView) {
83
- this.builderView.off('content_change');
84
- }
85
- }
86
- }, {
87
- key: "componentDidUpdate",
88
- value: function componentDidUpdate(prevProps) {
89
- // let propsChanged = !isEqual( prevProps.panelsData, this.props.panelsData );
90
- if (this.state.editing && !this.panelsInitialized) {
91
- this.setupPanels();
92
- } else if (this.state.loadingPreview) {
93
- this.fetchPreview(this.props);
94
- } else if (!this.previewInitialized && this.previewContainer.current) {
95
- $(document).trigger('panels_setup_preview');
96
- this.previewInitialized = true;
97
- }
98
- }
99
- }, {
100
- key: "setupPanels",
101
- value: function setupPanels() {
102
- var _this2 = this;
103
-
104
- var $panelsContainer = jQuery(this.panelsContainer.current);
105
- var config = {
106
- editorType: 'standalone'
107
- };
108
- var builderModel = new panels.model.builder();
109
- this.builderView = new panels.view.builder({
110
- model: builderModel,
111
- config: config
112
- }); // Make sure panelsData is defined and clone so that we don't alter the underlying attribute.
113
-
114
- var panelsData = JSON.parse(JSON.stringify($.extend({}, this.props.panelsData))); // Disable block selection while dragging rows or widgets.
115
-
116
- var rowOrWidgetMouseDown = function rowOrWidgetMouseDown() {
117
- if (isFunction(_this2.props.onRowOrWidgetMouseDown)) {
118
- _this2.props.onRowOrWidgetMouseDown();
119
- }
120
-
121
- var rowOrWidgetMouseUp = function rowOrWidgetMouseUp() {
122
- $(document).off('mouseup', rowOrWidgetMouseUp);
123
-
124
- if (isFunction(_this2.props.onRowOrWidgetMouseUp)) {
125
- _this2.props.onRowOrWidgetMouseUp();
126
- }
127
- };
128
-
129
- $(document).on('mouseup', rowOrWidgetMouseUp);
130
- };
131
-
132
- this.builderView.on('row_added', function () {
133
- _this2.builderView.$('.so-row-move').off('mousedown', rowOrWidgetMouseDown);
134
-
135
- _this2.builderView.$('.so-row-move').on('mousedown', rowOrWidgetMouseDown);
136
-
137
- _this2.builderView.$('.so-widget').off('mousedown', rowOrWidgetMouseDown);
138
-
139
- _this2.builderView.$('.so-widget').on('mousedown', rowOrWidgetMouseDown);
140
- });
141
- this.builderView.on('widget_added', function () {
142
- _this2.builderView.$('.so-widget').off('mousedown', rowOrWidgetMouseDown);
143
-
144
- _this2.builderView.$('.so-widget').on('mousedown', rowOrWidgetMouseDown);
145
- });
146
- this.builderView.render().attach({
147
- container: $panelsContainer
148
- }).setData(panelsData);
149
- this.builderView.trigger('builder_resize');
150
- this.builderView.on('content_change', function () {
151
- var newPanelsData = _this2.builderView.getData();
152
-
153
- _this2.panelsDataChanged = !isEqual(panelsData, newPanelsData);
154
-
155
- if (_this2.panelsDataChanged) {
156
- if (_this2.props.onContentChange && isFunction(_this2.props.onContentChange)) {
157
- _this2.props.onContentChange(newPanelsData);
158
- }
159
-
160
- _this2.setState({
161
- loadingPreview: true,
162
- previewHtml: ''
163
- });
164
- }
165
- });
166
- $(document).trigger('panels_setup', this.builderView);
167
- this.panelsInitialized = true;
168
- }
169
- }, {
170
- key: "fetchPreview",
171
- value: function fetchPreview(props) {
172
- var _this3 = this;
173
-
174
- if (!this.isStillMounted) {
175
- return;
176
- }
177
-
178
- this.previewInitialized = false;
179
- var fetchRequest = this.currentFetchRequest = $.post({
180
- url: soPanelsBlockEditorAdmin.previewUrl,
181
- data: {
182
- action: 'so_panels_layout_block_preview',
183
- panelsData: JSON.stringify(props.panelsData)
184
- }
185
- }).then(function (preview) {
186
- if (_this3.isStillMounted && fetchRequest === _this3.currentFetchRequest && preview) {
187
- _this3.setState({
188
- previewHtml: preview,
189
- loadingPreview: false
190
- });
191
- }
192
- });
193
- return fetchRequest;
194
- }
195
- }, {
196
- key: "render",
197
- value: function render() {
198
- var _this4 = this;
199
-
200
- var panelsData = this.props.panelsData;
201
-
202
- var switchToEditing = function switchToEditing() {
203
- _this4.panelsInitialized = false;
204
-
205
- _this4.setState({
206
- editing: true
207
- });
208
- };
209
-
210
- var switchToPreview = function switchToPreview() {
211
- if (panelsData) {
212
- _this4.setState({
213
- editing: false
214
- });
215
- }
216
- };
217
-
218
- if (this.state.editing) {
219
- return React.createElement(Fragment, null, React.createElement(BlockControls, null, React.createElement(Toolbar, null, React.createElement(IconButton, {
220
- icon: "visibility",
221
- className: "components-icon-button components-toolbar__control",
222
- label: __('Preview layout.', 'siteorigin-panels'),
223
- onClick: switchToPreview
224
- }))), React.createElement("div", {
225
- key: "layout-block",
226
- className: "siteorigin-panels-layout-block-container",
227
- ref: this.panelsContainer
228
- }));
229
- } else {
230
- var loadingPreview = this.state.loadingPreview;
231
- return React.createElement(Fragment, null, React.createElement(BlockControls, null, React.createElement(Toolbar, null, React.createElement(IconButton, {
232
- icon: "edit",
233
- className: "components-icon-button components-toolbar__control",
234
- label: __('Edit layout.', 'siteorigin-panels'),
235
- onClick: switchToEditing
236
- }))), React.createElement("div", {
237
- key: "preview",
238
- className: "so-panels-block-layout-preview-container"
239
- }, loadingPreview ? React.createElement("div", {
240
- className: "so-panels-spinner-container"
241
- }, React.createElement("span", null, React.createElement(Spinner, null))) : React.createElement("div", {
242
- className: "so-panels-raw-html-container",
243
- ref: this.previewContainer
244
- }, React.createElement(RawHTML, null, this.state.previewHtml))));
245
- }
246
- }
247
- }]);
248
-
249
- return SiteOriginPanelsLayoutBlock;
250
- }(Component);
251
-
252
- registerBlockType('siteorigin-panels/layout-block', {
253
- title: __('SiteOrigin Layout', 'siteorigin-panels'),
254
- description: __("Build a layout using SiteOrigin's Page Builder.", 'siteorigin-panels'),
255
- icon: function icon() {
256
- return React.createElement("span", {
257
- className: "siteorigin-panels-block-icon"
258
- });
259
- },
260
- category: 'layout',
261
- keywords: ['page builder', 'column,grid', 'panel'],
262
- supports: {
263
- html: false
264
- },
265
- attributes: {
266
- panelsData: {
267
- type: 'object'
268
- }
269
- },
270
- edit: function edit(_ref) {
271
- var attributes = _ref.attributes,
272
- setAttributes = _ref.setAttributes,
273
- toggleSelection = _ref.toggleSelection;
274
-
275
- var onLayoutBlockContentChange = function onLayoutBlockContentChange(newPanelsData) {
276
- if (!_.isEmpty(newPanelsData.widgets)) {
277
- // Send panels data to server for sanitization.
278
- $.post(soPanelsBlockEditorAdmin.sanitizeUrl, {
279
- action: 'so_panels_layout_block_sanitize',
280
- panelsData: JSON.stringify(newPanelsData)
281
- }, function (sanitizedPanelsData) {
282
- if (sanitizedPanelsData !== '') {
283
- setAttributes({
284
- panelsData: sanitizedPanelsData
285
- });
286
- }
287
- });
288
- }
289
- };
290
-
291
- var disableSelection = function disableSelection() {
292
- toggleSelection(false);
293
- };
294
-
295
- var enableSelection = function enableSelection() {
296
- toggleSelection(true);
297
- };
298
-
299
- return React.createElement(SiteOriginPanelsLayoutBlock, {
300
- panelsData: attributes.panelsData,
301
- onContentChange: onLayoutBlockContentChange,
302
- onRowOrWidgetMouseDown: disableSelection,
303
- onRowOrWidgetMouseUp: enableSelection
304
- });
305
- },
306
- save: function save() {
307
- // Render in PHP
308
- return null;
309
- }
310
- });
311
-
312
- (function ($) {
313
- if (soPanelsBlockEditorAdmin.showAddButton) {
314
- $(function () {
315
- setTimeout(function () {
316
- var editorDispatch = wp.data.dispatch('core/editor');
317
- var editorSelect = wp.data.select('core/editor');
318
- var tmpl = $('#siteorigin-panels-add-layout-block-button').html();
319
- var $addButton = $(tmpl).insertAfter('.editor-writing-flow > div:first');
320
- $addButton.on('click', function () {
321
- var layoutBlock = wp.blocks.createBlock('siteorigin-panels/layout-block', {});
322
- var isEmpty = editorSelect.isEditedPostEmpty();
323
-
324
- if (isEmpty) {
325
- var blocks = editorSelect.getBlocks();
326
-
327
- if (blocks.length) {
328
- editorDispatch.replaceBlock(blocks[0].clientId, layoutBlock);
329
- } else {
330
- editorDispatch.insertBlock(layoutBlock);
331
- }
332
- } else {
333
- editorDispatch.insertBlock(layoutBlock);
334
- }
335
- });
336
-
337
- var hideButtonIfBlocks = function hideButtonIfBlocks() {
338
- var isEmpty = wp.data.select('core/editor').isEditedPostEmpty();
339
-
340
- if (isEmpty) {
341
- $addButton.show();
342
- } else {
343
- $addButton.hide();
344
- }
345
- };
346
-
347
- wp.data.subscribe(hideButtonIfBlocks);
348
- hideButtonIfBlocks();
349
- }, 100);
350
- });
351
- }
352
  })(jQuery);
1
+ "use strict";
2
+
3
+ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
+
5
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6
+
7
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
8
+
9
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
10
+
11
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
12
+
13
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
14
+
15
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
16
+
17
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
18
+
19
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
20
+
21
+ var _lodash = lodash,
22
+ isEqual = _lodash.isEqual,
23
+ debounce = _lodash.debounce,
24
+ isEmpty = _lodash.isEmpty,
25
+ isFunction = _lodash.isFunction;
26
+ var registerBlockType = wp.blocks.registerBlockType;
27
+ var _wp$element = wp.element,
28
+ Component = _wp$element.Component,
29
+ Fragment = _wp$element.Fragment,
30
+ RawHTML = _wp$element.RawHTML,
31
+ createRef = _wp$element.createRef;
32
+ var BlockControls = wp.editor.BlockControls;
33
+ var _wp$components = wp.components,
34
+ Toolbar = _wp$components.Toolbar,
35
+ IconButton = _wp$components.IconButton,
36
+ Spinner = _wp$components.Spinner;
37
+ var __ = wp.i18n.__;
38
+ var _window = window,
39
+ soPanelsBlockEditorAdmin = _window.soPanelsBlockEditorAdmin;
40
+
41
+ var SiteOriginPanelsLayoutBlock =
42
+ /*#__PURE__*/
43
+ function (_Component) {
44
+ _inherits(SiteOriginPanelsLayoutBlock, _Component);
45
+
46
+ function SiteOriginPanelsLayoutBlock(props) {
47
+ var _this;
48
+
49
+ _classCallCheck(this, SiteOriginPanelsLayoutBlock);
50
+
51
+ _this = _possibleConstructorReturn(this, _getPrototypeOf(SiteOriginPanelsLayoutBlock).call(this, props));
52
+ var editMode = soPanelsBlockEditorAdmin.defaultMode === 'edit' || isEmpty(props.panelsData);
53
+ _this.state = {
54
+ editing: editMode,
55
+ loadingPreview: !editMode,
56
+ previewHtml: ''
57
+ };
58
+ _this.panelsContainer = createRef();
59
+ _this.previewContainer = createRef();
60
+ _this.panelsInitialized = false;
61
+ _this.previewInitialized = false;
62
+ return _this;
63
+ }
64
+
65
+ _createClass(SiteOriginPanelsLayoutBlock, [{
66
+ key: "componentDidMount",
67
+ value: function componentDidMount() {
68
+ this.isStillMounted = true;
69
+
70
+ if (this.state.editing) {
71
+ this.setupPanels();
72
+ } else if (!this.state.editing && !this.previewInitialized) {
73
+ this.fetchPreview(this.props);
74
+ this.fetchPreview = debounce(this.fetchPreview, 500);
75
+ }
76
+ }
77
+ }, {
78
+ key: "componentWillUnmount",
79
+ value: function componentWillUnmount() {
80
+ this.isStillMounted = false;
81
+
82
+ if (this.builderView) {
83
+ this.builderView.off('content_change');
84
+ }
85
+ }
86
+ }, {
87
+ key: "componentDidUpdate",
88
+ value: function componentDidUpdate(prevProps) {
89
+ // let propsChanged = !isEqual( prevProps.panelsData, this.props.panelsData );
90
+ if (this.state.editing && !this.panelsInitialized) {
91
+ this.setupPanels();
92
+ } else if (this.state.loadingPreview) {
93
+ this.fetchPreview(this.props);
94
+ } else if (!this.previewInitialized && this.previewContainer.current) {
95
+ $(document).trigger('panels_setup_preview');
96
+ this.previewInitialized = true;
97
+ }
98
+ }
99
+ }, {
100
+ key: "setupPanels",
101
+ value: function setupPanels() {
102
+ var _this2 = this;
103
+
104
+ var $panelsContainer = jQuery(this.panelsContainer.current);
105
+ var config = {
106
+ editorType: 'standalone'
107
+ };
108
+ var builderModel = new panels.model.builder();
109
+ this.builderView = new panels.view.builder({
110
+ model: builderModel,
111
+ config: config
112
+ }); // Make sure panelsData is defined and clone so that we don't alter the underlying attribute.
113
+
114
+ var panelsData = JSON.parse(JSON.stringify($.extend({}, this.props.panelsData))); // Disable block selection while dragging rows or widgets.
115
+
116
+ var rowOrWidgetMouseDown = function rowOrWidgetMouseDown() {
117
+ if (isFunction(_this2.props.onRowOrWidgetMouseDown)) {
118
+ _this2.props.onRowOrWidgetMouseDown();
119
+ }
120
+
121
+ var rowOrWidgetMouseUp = function rowOrWidgetMouseUp() {
122
+ $(document).off('mouseup', rowOrWidgetMouseUp);
123
+
124
+ if (isFunction(_this2.props.onRowOrWidgetMouseUp)) {
125
+ _this2.props.onRowOrWidgetMouseUp();
126
+ }
127
+ };
128
+
129
+ $(document).on('mouseup', rowOrWidgetMouseUp);
130
+ };
131
+
132
+ this.builderView.on('row_added', function () {
133
+ _this2.builderView.$('.so-row-move').off('mousedown', rowOrWidgetMouseDown);
134
+
135
+ _this2.builderView.$('.so-row-move').on('mousedown', rowOrWidgetMouseDown);
136
+
137
+ _this2.builderView.$('.so-widget').off('mousedown', rowOrWidgetMouseDown);
138
+
139
+ _this2.builderView.$('.so-widget').on('mousedown', rowOrWidgetMouseDown);
140
+ });
141
+ this.builderView.on('widget_added', function () {
142
+ _this2.builderView.$('.so-widget').off('mousedown', rowOrWidgetMouseDown);
143
+
144
+ _this2.builderView.$('.so-widget').on('mousedown', rowOrWidgetMouseDown);
145
+ });
146
+ this.builderView.render().attach({
147
+ container: $panelsContainer
148
+ }).setData(panelsData);
149
+ this.builderView.trigger('builder_resize');
150
+ this.builderView.on('content_change', function () {
151
+ var newPanelsData = _this2.builderView.getData();
152
+
153
+ _this2.panelsDataChanged = !isEqual(panelsData, newPanelsData);
154
+
155
+ if (_this2.panelsDataChanged) {
156
+ if (_this2.props.onContentChange && isFunction(_this2.props.onContentChange)) {
157
+ _this2.props.onContentChange(newPanelsData);
158
+ }
159
+
160
+ _this2.setState({
161
+ loadingPreview: true,
162
+ previewHtml: ''
163
+ });
164
+ }
165
+ });
166
+ $(document).trigger('panels_setup', this.builderView);
167
+ this.panelsInitialized = true;
168
+ }
169
+ }, {
170
+ key: "fetchPreview",
171
+ value: function fetchPreview(props) {
172
+ var _this3 = this;
173
+
174
+ if (!this.isStillMounted) {
175
+ return;
176
+ }
177
+
178
+ this.previewInitialized = false;
179
+ var fetchRequest = this.currentFetchRequest = $.post({
180
+ url: soPanelsBlockEditorAdmin.previewUrl,
181
+ data: {
182
+ action: 'so_panels_layout_block_preview',
183
+ panelsData: JSON.stringify(props.panelsData)
184
+ }
185
+ }).then(function (preview) {
186
+ if (_this3.isStillMounted && fetchRequest === _this3.currentFetchRequest && preview) {
187
+ _this3.setState({
188
+ previewHtml: preview,
189
+ loadingPreview: false
190
+ });
191
+ }
192
+ });
193
+ return fetchRequest;
194
+ }
195
+ }, {
196
+ key: "render",
197
+ value: function render() {
198
+ var _this4 = this;
199
+
200
+ var panelsData = this.props.panelsData;
201
+
202
+ var switchToEditing = function switchToEditing() {
203
+ _this4.panelsInitialized = false;
204
+
205
+ _this4.setState({
206
+ editing: true
207
+ });
208
+ };
209
+
210
+ var switchToPreview = function switchToPreview() {
211
+ if (panelsData) {
212
+ _this4.setState({
213
+ editing: false
214
+ });
215
+ }
216
+ };
217
+
218
+ if (this.state.editing) {
219
+ return React.createElement(Fragment, null, React.createElement(BlockControls, null, React.createElement(Toolbar, null, React.createElement(IconButton, {
220
+ icon: "visibility",
221
+ className: "components-icon-button components-toolbar__control",
222
+ label: __('Preview layout.', 'siteorigin-panels'),
223
+ onClick: switchToPreview
224
+ }))), React.createElement("div", {
225
+ key: "layout-block",
226
+ className: "siteorigin-panels-layout-block-container",
227
+ ref: this.panelsContainer
228
+ }));
229
+ } else {
230
+ var loadingPreview = this.state.loadingPreview;
231
+ return React.createElement(Fragment, null, React.createElement(BlockControls, null, React.createElement(Toolbar, null, React.createElement(IconButton, {
232
+ icon: "edit",
233
+ className: "components-icon-button components-toolbar__control",
234
+ label: __('Edit layout.', 'siteorigin-panels'),
235
+ onClick: switchToEditing
236
+ }))), React.createElement("div", {
237
+ key: "preview",
238
+ className: "so-panels-block-layout-preview-container"
239
+ }, loadingPreview ? React.createElement("div", {
240
+ className: "so-panels-spinner-container"
241
+ }, React.createElement("span", null, React.createElement(Spinner, null))) : React.createElement("div", {
242
+ className: "so-panels-raw-html-container",
243
+ ref: this.previewContainer
244
+ }, React.createElement(RawHTML, null, this.state.previewHtml))));
245
+ }
246
+ }
247
+ }]);
248
+
249
+ return SiteOriginPanelsLayoutBlock;
250
+ }(Component);
251
+
252
+ registerBlockType('siteorigin-panels/layout-block', {
253
+ title: __('SiteOrigin Layout', 'siteorigin-panels'),
254
+ description: __("Build a layout using SiteOrigin's Page Builder.", 'siteorigin-panels'),
255
+ icon: function icon() {
256
+ return React.createElement("span", {
257
+ className: "siteorigin-panels-block-icon"
258
+ });
259
+ },
260
+ category: 'layout',
261
+ keywords: ['page builder', 'column,grid', 'panel'],
262
+ supports: {
263
+ html: false
264
+ },
265
+ attributes: {
266
+ panelsData: {
267
+ type: 'object'
268
+ }
269
+ },
270
+ edit: function edit(_ref) {
271
+ var attributes = _ref.attributes,
272
+ setAttributes = _ref.setAttributes,
273
+ toggleSelection = _ref.toggleSelection;
274
+
275
+ var onLayoutBlockContentChange = function onLayoutBlockContentChange(newPanelsData) {
276
+ if (!_.isEmpty(newPanelsData.widgets)) {
277
+ // Send panelsData to server for sanitization.
278
+ $.post(soPanelsBlockEditorAdmin.sanitizeUrl, {
279
+ action: 'so_panels_layout_block_sanitize',
280
+ panelsData: JSON.stringify(newPanelsData)
281
+ }, function (sanitizedPanelsData) {
282
+ if (sanitizedPanelsData !== '') {
283
+ setAttributes({
284
+ panelsData: sanitizedPanelsData
285
+ });
286
+ }
287
+ });
288
+ }
289
+ };
290
+
291
+ var disableSelection = function disableSelection() {
292
+ toggleSelection(false);
293
+ };
294
+
295
+ var enableSelection = function enableSelection() {
296
+ toggleSelection(true);
297
+ };
298
+
299
+ return React.createElement(SiteOriginPanelsLayoutBlock, {
300
+ panelsData: attributes.panelsData,
301
+ onContentChange: onLayoutBlockContentChange,
302
+ onRowOrWidgetMouseDown: disableSelection,
303
+ onRowOrWidgetMouseUp: enableSelection
304
+ });
305
+ },
306
+ save: function save() {
307
+ // Render in PHP
308
+ return null;
309
+ }
310
+ });
311
+
312
+ (function ($) {
313
+ if (soPanelsBlockEditorAdmin.showAddButton) {
314
+ $(function () {
315
+ setTimeout(function () {
316
+ var editorDispatch = wp.data.dispatch('core/editor');
317
+ var editorSelect = wp.data.select('core/editor');
318
+ var tmpl = $('#siteorigin-panels-add-layout-block-button').html();
319
+ var $addButton = $(tmpl).insertAfter('.editor-writing-flow > div:first');
320
+ $addButton.on('click', function () {
321
+ var layoutBlock = wp.blocks.createBlock('siteorigin-panels/layout-block', {});
322
+ var isEmpty = editorSelect.isEditedPostEmpty();
323
+
324
+ if (isEmpty) {
325
+ var blocks = editorSelect.getBlocks();
326
+
327
+ if (blocks.length) {
328
+ editorDispatch.replaceBlock(blocks[0].clientId, layoutBlock);
329
+ } else {
330
+ editorDispatch.insertBlock(layoutBlock);
331
+ }
332
+ } else {
333
+ editorDispatch.insertBlock(layoutBlock);
334
+ }
335
+ });
336
+
337
+ var hideButtonIfBlocks = function hideButtonIfBlocks() {
338
+ var isEmpty = wp.data.select('core/editor').isEditedPostEmpty();
339
+
340
+ if (isEmpty) {
341
+ $addButton.show();
342
+ } else {
343
+ $addButton.hide();
344
+ }
345
+ };
346
+
347
+ wp.data.subscribe(hideButtonIfBlocks);
348
+ hideButtonIfBlocks();
349
+ }, 100);
350
+ });
351
+ }
352
  })(jQuery);
inc/admin.php CHANGED
@@ -78,7 +78,9 @@ class SiteOrigin_Panels_Admin {
78
  add_filter( 'gutenberg_can_edit_post_type', array( $this, 'show_classic_editor_for_panels' ), 10, 2 );
79
  add_filter( 'use_block_editor_for_post_type', array( $this, 'show_classic_editor_for_panels' ), 10, 2 );
80
  add_action( 'admin_print_scripts-edit.php', array( $this, 'add_panels_add_new_button' ) );
81
- add_filter( 'display_post_states', array( $this, 'add_panels_post_state' ), 10, 2 );
 
 
82
  }
83
  }
84
 
78
  add_filter( 'gutenberg_can_edit_post_type', array( $this, 'show_classic_editor_for_panels' ), 10, 2 );
79
  add_filter( 'use_block_editor_for_post_type', array( $this, 'show_classic_editor_for_panels' ), 10, 2 );
80
  add_action( 'admin_print_scripts-edit.php', array( $this, 'add_panels_add_new_button' ) );
81
+ if( siteorigin_panels_setting( 'admin-post-state' ) ) {
82
+ add_filter( 'display_post_states', array( $this, 'add_panels_post_state' ), 10, 2 );
83
+ }
84
  }
85
  }
86
 
inc/css-builder.php CHANGED
@@ -109,7 +109,7 @@ class SiteOrigin_Panels_Css_Builder {
109
  $selector[] = '#pl-' . $li;
110
  }
111
  $selector[] = is_string( $ri ) ? ( '#' . $ri ) : '#pg-' . $li . '-' . $ri;
112
- $selector[] = '.panel-grid-cell';
113
  } elseif ( $ri !== false && $ci !== false ) {
114
  // This applies to a specific cell
115
  if ( $specify_layout ) {
109
  $selector[] = '#pl-' . $li;
110
  }
111
  $selector[] = is_string( $ri ) ? ( '#' . $ri ) : '#pg-' . $li . '-' . $ri;
112
+ $selector[] = '> .panel-grid-cell';
113
  } elseif ( $ri !== false && $ci !== false ) {
114
  // This applies to a specific cell
115
  if ( $specify_layout ) {
inc/live-editor.php CHANGED
@@ -9,7 +9,6 @@ class SiteOrigin_Panels_Live_Editor {
9
 
10
  function __construct() {
11
  add_action( 'template_redirect', array( $this, 'xss_headers' ) );
12
- add_action( 'get_post_metadata', array( $this, 'post_metadata' ), 10, 3 );
13
  add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
14
 
15
  // Don't display the admin bar when in live editor mode
@@ -33,40 +32,6 @@ class SiteOrigin_Panels_Live_Editor {
33
  }
34
  }
35
 
36
- /**
37
- * Edit the page builder data when we're viewing the live editor version
38
- *
39
- * @param $value
40
- * @param $post_id
41
- * @param $meta_key
42
- *
43
- * @return array
44
- */
45
- function post_metadata( $value, $post_id, $meta_key ) {
46
- if (
47
- $meta_key == 'panels_data' &&
48
- current_user_can( 'edit_post', $post_id ) &&
49
- ! empty( $_POST['live_editor_panels_data'] ) &&
50
- $_POST['live_editor_post_ID'] == $post_id
51
- ) {
52
- $data = json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true );
53
-
54
- if (
55
- ! empty( $data['widgets'] ) && (
56
- ! class_exists( 'SiteOrigin_Widget_Field_Class_Loader' ) ||
57
- method_exists( 'SiteOrigin_Widget_Field_Class_Loader', 'extend' )
58
- )
59
- ) {
60
- $data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $data['widgets'], false, false );
61
- }
62
-
63
- $value = array( $data );
64
- }
65
-
66
- return $value;
67
- }
68
-
69
-
70
  /**
71
  * Load the frontend scripts for the live editor
72
  */
9
 
10
  function __construct() {
11
  add_action( 'template_redirect', array( $this, 'xss_headers' ) );
 
12
  add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
13
 
14
  // Don't display the admin bar when in live editor mode
32
  }
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  /**
36
  * Load the frontend scripts for the live editor
37
  */
inc/renderer.php CHANGED
@@ -210,11 +210,12 @@ class SiteOrigin_Panels_Renderer {
210
  $css->add_cell_css( $post_id, $ri, false, '', array(
211
  'margin-right' => 0,
212
  ), $panels_mobile_width );
 
 
 
 
213
  }
214
 
215
- $css->add_cell_css( $post_id, $ri, false, '', array(
216
- 'width' => '100%',
217
- ), $panels_mobile_width );
218
 
219
  foreach ( $row['cells'] as $ci => $cell ) {
220
  if ( ( $collapse_order == 'left-top' && $ci != $cell_count - 1 ) || ( $collapse_order == 'right-top' && $ci !== 0 ) ) {
@@ -602,7 +603,19 @@ class SiteOrigin_Panels_Renderer {
602
  * @return array
603
  */
604
  private function get_panels_data_for_post( $post_id ) {
605
- if ( strpos( $post_id, 'prebuilt:' ) === 0 ) {
 
 
 
 
 
 
 
 
 
 
 
 
606
  list( $null, $prebuilt_id ) = explode( ':', $post_id, 2 );
607
  $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
608
  $panels_data = ! empty( $layouts[ $prebuilt_id ] ) ? $layouts[ $prebuilt_id ] : array();
210
  $css->add_cell_css( $post_id, $ri, false, '', array(
211
  'margin-right' => 0,
212
  ), $panels_mobile_width );
213
+
214
+ $css->add_cell_css( $post_id, $ri, false, '', array(
215
+ 'width' => '100%',
216
+ ), $panels_mobile_width );
217
  }
218
 
 
 
 
219
 
220
  foreach ( $row['cells'] as $ci => $cell ) {
221
  if ( ( $collapse_order == 'left-top' && $ci != $cell_count - 1 ) || ( $collapse_order == 'right-top' && $ci !== 0 ) ) {
603
  * @return array
604
  */
605
  private function get_panels_data_for_post( $post_id ) {
606
+ if ( SiteOrigin_Panels::is_live_editor() ) {
607
+ if (
608
+ current_user_can( 'edit_post', $post_id ) &&
609
+ ! empty( $_POST['live_editor_panels_data'] ) &&
610
+ $_POST['live_editor_post_ID'] == $post_id
611
+ ) {
612
+ $panels_data = json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true );
613
+
614
+ if ( ! empty( $panels_data['widgets'] ) ) {
615
+ $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'] );
616
+ }
617
+ }
618
+ } else if ( strpos( $post_id, 'prebuilt:' ) === 0 ) {
619
  list( $null, $prebuilt_id ) = explode( ':', $post_id, 2 );
620
  $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
621
  $panels_data = ! empty( $layouts[ $prebuilt_id ] ) ? $layouts[ $prebuilt_id ] : array();
inc/settings.php CHANGED
@@ -119,6 +119,7 @@ class SiteOrigin_Panels_Settings {
119
  // The general fields
120
  $defaults['post-types'] = array( 'page', 'post' );
121
  $defaults['live-editor-quick-link'] = true;
 
122
  $defaults['admin-widget-count'] = false;
123
  $defaults['parallax-motion'] = '';
124
  $defaults['sidebars-emulator'] = true;
@@ -261,6 +262,16 @@ class SiteOrigin_Panels_Settings {
261
  'description' => __( 'Display a Live Editor button in the admin bar.', 'siteorigin-panels' ),
262
  );
263
 
 
 
 
 
 
 
 
 
 
 
264
  $fields['general']['fields']['admin-widget-count'] = array(
265
  'type' => 'checkbox',
266
  'label' => __( 'Display Widget Count', 'siteorigin-panels' ),
119
  // The general fields
120
  $defaults['post-types'] = array( 'page', 'post' );
121
  $defaults['live-editor-quick-link'] = true;
122
+ $defaults['admin-post-state'] = true;
123
  $defaults['admin-widget-count'] = false;
124
  $defaults['parallax-motion'] = '';
125
  $defaults['sidebars-emulator'] = true;
262
  'description' => __( 'Display a Live Editor button in the admin bar.', 'siteorigin-panels' ),
263
  );
264
 
265
+ $fields['general']['fields']['admin-post-state'] = array(
266
+ 'type' => 'checkbox',
267
+ 'label' => __( 'Display Post State', 'siteorigin-panels' ),
268
+ 'description' => sprintf(
269
+ __( "Display a %sSiteOrigin Page Builder%s post state in the admin lists of posts/pages to indicate Page Builder is active.", 'siteorigin-panels' ),
270
+ '<strong>',
271
+ '</strong>'
272
+ ),
273
+ );
274
+
275
  $fields['general']['fields']['admin-widget-count'] = array(
276
  'type' => 'checkbox',
277
  'label' => __( 'Display Widget Count', 'siteorigin-panels' ),
inc/widgets/layout.php CHANGED
@@ -58,14 +58,18 @@ class SiteOrigin_Panels_Widgets_Layout extends WP_Widget {
58
  $new['panels_data'] = json_decode( $new['panels_data'], true );
59
  }
60
 
61
- if ( ! empty( $new['panels_data'] ) && ! empty( $new['panels_data']['widgets'] ) ) {
62
- $new['panels_data']['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets(
63
- $new['panels_data']['widgets'],
64
- ! empty( $old['panels_data']['widgets'] ) ? $old['panels_data']['widgets'] : false
65
- );
66
- foreach( $new['panels_data']['widgets'] as & $widget ) {
67
- $widget['panels_info']['class'] = str_replace( '\\', '&#92;', $widget['panels_info']['class'] );
 
 
68
  }
 
 
69
  }
70
 
71
  return $new;
58
  $new['panels_data'] = json_decode( $new['panels_data'], true );
59
  }
60
 
61
+ if ( ! empty( $new['panels_data'] ) ) {
62
+ if ( ! empty( $new['panels_data']['widgets'] ) ) {
63
+ $new['panels_data']['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets(
64
+ $new['panels_data']['widgets'],
65
+ ! empty( $old['panels_data']['widgets'] ) ? $old['panels_data']['widgets'] : false
66
+ );
67
+ foreach( $new['panels_data']['widgets'] as & $widget ) {
68
+ $widget['panels_info']['class'] = str_replace( '\\', '&#92;', $widget['panels_info']['class'] );
69
+ }
70
  }
71
+
72
+ $new['panels_data'] = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $new['panels_data'] );
73
  }
74
 
75
  return $new;
js/siteorigin-panels-2101.js DELETED
@@ -1,7438 +0,0 @@
1
- (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
2
- var panels = window.panels;
3
-
4
- module.exports = Backbone.Collection.extend( {
5
- model: panels.model.cell,
6
-
7
- initialize: function () {
8
- },
9
-
10
- /**
11
- * Get the total weight for the cells in this collection.
12
- * @returns {number}
13
- */
14
- totalWeight: function () {
15
- var totalWeight = 0;
16
- this.each( function ( cell ) {
17
- totalWeight += cell.get( 'weight' );
18
- } );
19
-
20
- return totalWeight;
21
- },
22
-
23
- } );
24
-
25
- },{}],2:[function(require,module,exports){
26
- var panels = window.panels;
27
-
28
- module.exports = Backbone.Collection.extend( {
29
- model: panels.model.historyEntry,
30
-
31
- /**
32
- * The builder model
33
- */
34
- builder: null,
35
-
36
- /**
37
- * The maximum number of items in the history
38
- */
39
- maxSize: 12,
40
-
41
- initialize: function () {
42
- this.on( 'add', this.onAddEntry, this );
43
- },
44
-
45
- /**
46
- * Add an entry to the collection.
47
- *
48
- * @param text The text that defines the action taken to get to this
49
- * @param data
50
- */
51
- addEntry: function ( text, data ) {
52
-
53
- if ( _.isEmpty( data ) ) {
54
- data = this.builder.getPanelsData();
55
- }
56
-
57
- var entry = new panels.model.historyEntry( {
58
- text: text,
59
- data: JSON.stringify( data ),
60
- time: parseInt( new Date().getTime() / 1000 ),
61
- collection: this
62
- } );
63
-
64
- this.add( entry );
65
- },
66
-
67
- /**
68
- * Resize the collection so it's not bigger than this.maxSize
69
- */
70
- onAddEntry: function ( entry ) {
71
-
72
- if ( this.models.length > 1 ) {
73
- var lastEntry = this.at( this.models.length - 2 );
74
-
75
- if (
76
- (
77
- entry.get( 'text' ) === lastEntry.get( 'text' ) && entry.get( 'time' ) - lastEntry.get( 'time' ) < 15
78
- ) ||
79
- (
80
- entry.get( 'data' ) === lastEntry.get( 'data' )
81
- )
82
- ) {
83
- // If both entries have the same text and are within 20 seconds of each other, or have the same data, then remove most recent
84
- this.remove( entry );
85
- lastEntry.set( 'count', lastEntry.get( 'count' ) + 1 );
86
- }
87
- }
88
-
89
- // Make sure that there are not to many entries in this collection
90
- while ( this.models.length > this.maxSize ) {
91
- this.shift();
92
- }
93
- }
94
- } );
95
-
96
- },{}],3:[function(require,module,exports){
97
- var panels = window.panels;
98
-
99
- module.exports = Backbone.Collection.extend( {
100
- model: panels.model.row,
101
-
102
- /**
103
- * Destroy all the rows in this collection
104
- */
105
- empty: function () {
106
- var model;
107
- do {
108
- model = this.collection.first();
109
- if ( ! model ) {
110
- break;
111
- }
112
-
113
- model.destroy();
114
- } while ( true );
115
- }
116
-
117
- } );
118
-
119
- },{}],4:[function(require,module,exports){
120
- var panels = window.panels;
121
-
122
- module.exports = Backbone.Collection.extend( {
123
- model: panels.model.widget,
124
-
125
- initialize: function () {
126
-
127
- }
128
-
129
- } );
130
-
131
- },{}],5:[function(require,module,exports){
132
- var panels = window.panels, $ = jQuery;
133
-
134
- module.exports = panels.view.dialog.extend( {
135
- dialogClass: 'so-panels-dialog-add-builder',
136
-
137
- render: function () {
138
- // Render the dialog and attach it to the builder interface
139
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-builder' ).html(), {} ) );
140
- this.$( '.so-content .siteorigin-panels-builder' ).append( this.builder.$el );
141
- },
142
-
143
- initializeDialog: function () {
144
- var thisView = this;
145
- this.once( 'open_dialog_complete', function () {
146
- thisView.builder.initSortable();
147
- } );
148
-
149
- this.on( 'open_dialog_complete', function () {
150
- thisView.builder.trigger( 'builder_resize' );
151
- } );
152
- }
153
- } );
154
-
155
- },{}],6:[function(require,module,exports){
156
- var panels = window.panels, $ = jQuery;
157
-
158
- module.exports = panels.view.dialog.extend( {
159
-
160
- historyEntryTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-history-entry' ).html() ) ),
161
-
162
- entries: {},
163
- currentEntry: null,
164
- revertEntry: null,
165
- selectedEntry: null,
166
-
167
- previewScrollTop: null,
168
-
169
- dialogClass: 'so-panels-dialog-history',
170
- dialogIcon: 'history',
171
-
172
- events: {
173
- 'click .so-close': 'closeDialog',
174
- 'click .so-restore': 'restoreSelectedEntry'
175
- },
176
-
177
- initializeDialog: function () {
178
- this.entries = new panels.collection.historyEntries();
179
-
180
- this.on( 'open_dialog', this.setCurrentEntry, this );
181
- this.on( 'open_dialog', this.renderHistoryEntries, this );
182
- },
183
-
184
- render: function () {
185
- var thisView = this;
186
-
187
- // Render the dialog and attach it to the builder interface
188
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-history' ).html(), {} ) );
189
-
190
- this.$( 'iframe.siteorigin-panels-history-iframe' ).load( function () {
191
- var $$ = $( this );
192
- $$.show();
193
-
194
- $$.contents().scrollTop( thisView.previewScrollTop );
195
- } );
196
- },
197
-
198
- /**
199
- * Set the original entry. This should be set when creating the dialog.
200
- *
201
- * @param {panels.model.builder} builder
202
- */
203
- setRevertEntry: function ( builder ) {
204
- this.revertEntry = new panels.model.historyEntry( {
205
- data: JSON.stringify( builder.getPanelsData() ),
206
- time: parseInt( new Date().getTime() / 1000 )
207
- } );
208
- },
209
-
210
- /**
211
- * This is triggered when the dialog is opened.
212
- */
213
- setCurrentEntry: function () {
214
- this.currentEntry = new panels.model.historyEntry( {
215
- data: JSON.stringify( this.builder.model.getPanelsData() ),
216
- time: parseInt( new Date().getTime() / 1000 )
217
- } );
218
-
219
- this.selectedEntry = this.currentEntry;
220
- this.previewEntry( this.currentEntry );
221
- this.$( '.so-buttons .so-restore' ).addClass( 'disabled' );
222
- },
223
-
224
- /**
225
- * Render the history entries in the sidebar
226
- */
227
- renderHistoryEntries: function () {
228
- // Set up an interval that will display the time since every 10 seconds
229
- var thisView = this;
230
-
231
- var c = this.$( '.history-entries' ).empty();
232
-
233
- if ( this.currentEntry.get( 'data' ) !== this.revertEntry.get( 'data' ) || ! _.isEmpty( this.entries.models ) ) {
234
- $( this.historyEntryTemplate( {title: panelsOptions.loc.history.revert, count: 1} ) )
235
- .data( 'historyEntry', this.revertEntry )
236
- .prependTo( c );
237
- }
238
-
239
- // Now load all the entries in this.entries
240
- this.entries.each( function ( entry ) {
241
-
242
- var html = thisView.historyEntryTemplate( {
243
- title: panelsOptions.loc.history[entry.get( 'text' )],
244
- count: entry.get( 'count' )
245
- } );
246
-
247
- $( html )
248
- .data( 'historyEntry', entry )
249
- .prependTo( c );
250
- } );
251
-
252
-
253
- $( this.historyEntryTemplate( {title: panelsOptions.loc.history['current'], count: 1} ) )
254
- .data( 'historyEntry', this.currentEntry )
255
- .addClass( 'so-selected' )
256
- .prependTo( c );
257
-
258
- // Handle loading and selecting
259
- c.find( '.history-entry' ).click( function () {
260
- var $$ = jQuery( this );
261
- c.find( '.history-entry' ).not( $$ ).removeClass( 'so-selected' );
262
- $$.addClass( 'so-selected' );
263
-
264
- var entry = $$.data( 'historyEntry' );
265
-
266
- thisView.selectedEntry = entry;
267
-
268
- if ( thisView.selectedEntry.cid !== thisView.currentEntry.cid ) {
269
- thisView.$( '.so-buttons .so-restore' ).removeClass( 'disabled' );
270
- } else {
271
- thisView.$( '.so-buttons .so-restore' ).addClass( 'disabled' );
272
- }
273
-
274
- thisView.previewEntry( entry );
275
- } );
276
-
277
- this.updateEntryTimes();
278
- },
279
-
280
- /**
281
- * Preview an entry
282
- *
283
- * @param entry
284
- */
285
- previewEntry: function ( entry ) {
286
- var iframe = this.$( 'iframe.siteorigin-panels-history-iframe' );
287
- iframe.hide();
288
- this.previewScrollTop = iframe.contents().scrollTop();
289
-
290
- this.$( 'form.history-form input[name="live_editor_panels_data"]' ).val( entry.get( 'data' ) );
291
- this.$( 'form.history-form input[name="live_editor_post_ID"]' ).val( this.builder.config.postId );
292
- this.$( 'form.history-form' ).submit();
293
- },
294
-
295
- /**
296
- * Restore the current entry
297
- */
298
- restoreSelectedEntry: function () {
299
-
300
- if ( this.$( '.so-buttons .so-restore' ).hasClass( 'disabled' ) ) {
301
- return false;
302
- }
303
-
304
- if ( this.currentEntry.get( 'data' ) === this.selectedEntry.get( 'data' ) ) {
305
- this.closeDialog();
306
- return false;
307
- }
308
-
309
- // Add an entry for this restore event
310
- if ( this.selectedEntry.get( 'text' ) !== 'restore' ) {
311
- this.builder.addHistoryEntry( 'restore', this.builder.model.getPanelsData() );
312
- }
313
-
314
- this.builder.model.loadPanelsData( JSON.parse( this.selectedEntry.get( 'data' ) ) );
315
-
316
- this.closeDialog();
317
-
318
- return false;
319
- },
320
-
321
- /**
322
- * Update the entry times for the list of entries down the side
323
- */
324
- updateEntryTimes: function () {
325
- var thisView = this;
326
-
327
- this.$( '.history-entries .history-entry' ).each( function () {
328
- var $$ = jQuery( this );
329
-
330
- var time = $$.find( '.timesince' );
331
- var entry = $$.data( 'historyEntry' );
332
-
333
- time.html( thisView.timeSince( entry.get( 'time' ) ) );
334
- } );
335
- },
336
-
337
- /**
338
- * Gets the time since as a nice string.
339
- *
340
- * @param date
341
- */
342
- timeSince: function ( time ) {
343
- var diff = parseInt( new Date().getTime() / 1000 ) - time;
344
-
345
- var parts = [];
346
- var interval;
347
-
348
- // There are 3600 seconds in an hour
349
- if ( diff > 3600 ) {
350
- interval = Math.floor( diff / 3600 );
351
- if ( interval === 1 ) {
352
- parts.push( panelsOptions.loc.time.hour.replace( '%d', interval ) );
353
- } else {
354
- parts.push( panelsOptions.loc.time.hours.replace( '%d', interval ) );
355
- }
356
- diff -= interval * 3600;
357
- }
358
-
359
- // There are 60 seconds in a minute
360
- if ( diff > 60 ) {
361
- interval = Math.floor( diff / 60 );
362
- if ( interval === 1 ) {
363
- parts.push( panelsOptions.loc.time.minute.replace( '%d', interval ) );
364
- } else {
365
- parts.push( panelsOptions.loc.time.minutes.replace( '%d', interval ) );
366
- }
367
- diff -= interval * 60;
368
- }
369
-
370
- if ( diff > 0 ) {
371
- if ( diff === 1 ) {
372
- parts.push( panelsOptions.loc.time.second.replace( '%d', diff ) );
373
- } else {
374
- parts.push( panelsOptions.loc.time.seconds.replace( '%d', diff ) );
375
- }
376
- }
377
-
378
- // Return the amount of time ago
379
- return _.isEmpty( parts ) ? panelsOptions.loc.time.now : panelsOptions.loc.time.ago.replace( '%s', parts.slice( 0, 2 ).join( ', ' ) );
380
-
381
- }
382
-
383
- } );
384
-
385
- },{}],7:[function(require,module,exports){
386
- var panels = window.panels, $ = jQuery;
387
-
388
- module.exports = panels.view.dialog.extend( {
389
-
390
- directoryTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-directory-items' ).html() ) ),
391
-
392
- builder: null,
393
- dialogClass: 'so-panels-dialog-prebuilt-layouts',
394
- dialogIcon: 'layouts',
395
-
396
- layoutCache: {},
397
- currentTab: false,
398
- directoryPage: 1,
399
-
400
- events: {
401
- 'click .so-close': 'closeDialog',
402
- 'click .so-sidebar-tabs li a': 'tabClickHandler',
403
- 'click .so-content .layout': 'layoutClickHandler',
404
- 'keyup .so-sidebar-search': 'searchHandler',
405
-
406
- // The directory items
407
- 'click .so-screenshot, .so-title': 'directoryItemClickHandler'
408
- },
409
-
410
- /**
411
- * Initialize the prebuilt dialog.
412
- */
413
- initializeDialog: function () {
414
- var thisView = this;
415
-
416
- this.on( 'open_dialog', function () {
417
- thisView.$( '.so-sidebar-tabs li a' ).first().click();
418
- thisView.$( '.so-status' ).removeClass( 'so-panels-loading' );
419
- } );
420
-
421
- this.on( 'button_click', this.toolbarButtonClick, this );
422
- },
423
-
424
- /**
425
- * Render the prebuilt layouts dialog
426
- */
427
- render: function () {
428
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-prebuilt' ).html(), {} ) );
429
-
430
- this.initToolbar();
431
- },
432
-
433
- /**
434
- *
435
- * @param e
436
- * @return {boolean}
437
- */
438
- tabClickHandler: function ( e ) {
439
- e.preventDefault();
440
- // Reset selected item state when changing tabs
441
- this.selectedLayoutItem = null;
442
- this.uploadedLayout = null;
443
- this.updateButtonState( false );
444
-
445
- this.$( '.so-sidebar-tabs li' ).removeClass( 'tab-active' );
446
-
447
- var $$ = $( e.target );
448
- var tab = $$.attr( 'href' ).split( '#' )[1];
449
- $$.parent().addClass( 'tab-active' );
450
-
451
- var thisView = this;
452
-
453
- // Empty everything
454
- this.$( '.so-content' ).empty();
455
-
456
- thisView.currentTab = tab;
457
- if ( tab == 'import' ) {
458
- this.displayImportExport();
459
- } else {
460
- this.displayLayoutDirectory( '', 1, tab );
461
- }
462
-
463
- thisView.$( '.so-sidebar-search' ).val( '' );
464
- },
465
-
466
- /**
467
- * Display and setup the import/export form
468
- */
469
- displayImportExport: function () {
470
- var c = this.$( '.so-content' ).empty().removeClass( 'so-panels-loading' );
471
- c.html( $( '#siteorigin-panels-dialog-prebuilt-importexport' ).html() );
472
-
473
- var thisView = this;
474
- var uploadUi = thisView.$( '.import-upload-ui' );
475
-
476
- // Create the uploader
477
- var uploader = new plupload.Uploader( {
478
- runtimes: 'html5,silverlight,flash,html4',
479
-
480
- browse_button: uploadUi.find( '.file-browse-button' ).get( 0 ),
481
- container: uploadUi.get( 0 ),
482
- drop_element: uploadUi.find( '.drag-upload-area' ).get( 0 ),
483
-
484
- file_data_name: 'panels_import_data',
485
- multiple_queues: false,
486
- max_file_size: panelsOptions.plupload.max_file_size,
487
- url: panelsOptions.plupload.url,
488
- flash_swf_url: panelsOptions.plupload.flash_swf_url,
489
- silverlight_xap_url: panelsOptions.plupload.silverlight_xap_url,
490
- filters: [
491
- {title: panelsOptions.plupload.filter_title, extensions: 'json'}
492
- ],
493
-
494
- multipart_params: {
495
- action: 'so_panels_import_layout'
496
- },
497
-
498
- init: {
499
- PostInit: function ( uploader ) {
500
- if ( uploader.features.dragdrop ) {
501
- uploadUi.addClass( 'has-drag-drop' );
502
- }
503
- uploadUi.find( '.progress-precent' ).css( 'width', '0%' );
504
- },
505
- FilesAdded: function ( uploader ) {
506
- uploadUi.find( '.file-browse-button' ).blur();
507
- uploadUi.find( '.drag-upload-area' ).removeClass( 'file-dragover' );
508
- uploadUi.find( '.progress-bar' ).fadeIn( 'fast' );
509
- thisView.$( '.js-so-selected-file' ).text( panelsOptions.loc.prebuilt_loading );
510
- uploader.start();
511
- },
512
- UploadProgress: function ( uploader, file ) {
513
- uploadUi.find( '.progress-precent' ).css( 'width', file.percent + '%' );
514
- },
515
- FileUploaded: function ( uploader, file, response ) {
516
- var layout = JSON.parse( response.response );
517
- if ( ! _.isUndefined( layout.widgets ) ) {
518
-
519
- thisView.uploadedLayout = layout;
520
- uploadUi.find( '.progress-bar' ).hide();
521
- thisView.$( '.js-so-selected-file' ).text(
522
- panelsOptions.loc.ready_to_insert.replace( '%s', file.name )
523
- );
524
- thisView.updateButtonState( true );
525
- } else {
526
- alert( panelsOptions.plupload.error_message );
527
- }
528
- },
529
- Error: function () {
530
- alert( panelsOptions.plupload.error_message );
531
- }
532
- }
533
- } );
534
- uploader.init();
535
-
536
- if ( /Edge\/\d./i.test(navigator.userAgent) ){
537
- // A very dirty fix for a Microsoft Edge issue.
538
- // TODO find a more elegant fix if Edge gains market share
539
- setTimeout( function(){
540
- uploader.refresh();
541
- }, 250 );
542
- }
543
-
544
- // This is
545
- uploadUi.find( '.drag-upload-area' )
546
- .on( 'dragover', function () {
547
- $( this ).addClass( 'file-dragover' );
548
- } )
549
- .on( 'dragleave', function () {
550
- $( this ).removeClass( 'file-dragover' );
551
- } );
552
-
553
- // Handle exporting the file
554
- c.find( '.so-export' ).submit( function ( e ) {
555
- var $$ = $( this );
556
- var panelsData = thisView.builder.model.getPanelsData();
557
- var postName = $('input[name="post_title"]').val();
558
- if ( ! postName ) {
559
- postName = $('input[name="post_ID"]').val();
560
- }
561
- panelsData.name = postName;
562
- $$.find( 'input[name="panels_export_data"]' ).val( JSON.stringify( panelsData ) );
563
- } );
564
-
565
- },
566
-
567
- /**
568
- * Display the layout directory tab.
569
- *
570
- * @param query
571
- */
572
- displayLayoutDirectory: function ( search, page, type ) {
573
- var thisView = this;
574
- var c = this.$( '.so-content' ).empty().addClass( 'so-panels-loading' );
575
-
576
- if ( search === undefined ) {
577
- search = '';
578
- }
579
- if ( page === undefined ) {
580
- page = 1;
581
- }
582
- if ( type === undefined ) {
583
- type = 'directory-siteorigin';
584
- }
585
-
586
- if ( type.match('^directory-') && ! panelsOptions.directory_enabled ) {
587
- // Display the button to enable the prebuilt layout
588
- c.removeClass( 'so-panels-loading' ).html( $( '#siteorigin-panels-directory-enable' ).html() );
589
- c.find( '.so-panels-enable-directory' ).click( function ( e ) {
590
- e.preventDefault();
591
- // Sent the query to enable the directory, then enable the directory
592
- $.get(
593
- panelsOptions.ajaxurl,
594
- {action: 'so_panels_directory_enable'},
595
- function () {
596
-
597
- }
598
- );
599
-
600
- // Enable the layout directory
601
- panelsOptions.directory_enabled = true;
602
- c.addClass( 'so-panels-loading' );
603
- thisView.displayLayoutDirectory( search, page, type );
604
- } );
605
- return;
606
- }
607
-
608
- // Get all the items for the current query
609
- $.get(
610
- panelsOptions.ajaxurl,
611
- {
612
- action: 'so_panels_layouts_query',
613
- search: search,
614
- page: page,
615
- type: type,
616
- },
617
- function ( data ) {
618
- // Skip this if we're no longer viewing the layout directory
619
- if ( thisView.currentTab !== type ) {
620
- return;
621
- }
622
-
623
- // Add the directory items
624
- c.removeClass( 'so-panels-loading' ).html( thisView.directoryTemplate( data ) );
625
-
626
- // Lets setup the next and previous buttons
627
- var prev = c.find( '.so-previous' ), next = c.find( '.so-next' );
628
-
629
- if ( page <= 1 ) {
630
- prev.addClass( 'button-disabled' );
631
- } else {
632
- prev.click( function ( e ) {
633
- e.preventDefault();
634
- thisView.displayLayoutDirectory( search, page - 1, thisView.currentTab );
635
- } );
636
- }
637
-
638
- if ( page === data.max_num_pages || data.max_num_pages === 0 ) {
639
- next.addClass( 'button-disabled' );
640
- } else {
641
- next.click( function ( e ) {
642
- e.preventDefault();
643
- thisView.displayLayoutDirectory( search, page + 1, thisView.currentTab );
644
- } );
645
- }
646
-
647
- // Handle nice preloading of the screenshots
648
- c.find( '.so-screenshot' ).each( function () {
649
- var $$ = $( this ), $a = $$.find( '.so-screenshot-wrapper' );
650
- $a.css( 'height', ( $a.width() / 4 * 3 ) + 'px' ).addClass( 'so-loading' );
651
-
652
- if ( $$.data( 'src' ) !== '' ) {
653
- // Set the initial height
654
- var $img = $( '<img/>' ).attr( 'src', $$.data( 'src' ) ).load( function () {
655
- $a.removeClass( 'so-loading' ).css( 'height', 'auto' );
656
- $img.appendTo( $a ).hide().fadeIn( 'fast' );
657
- } );
658
- } else {
659
- $( '<img/>' ).attr( 'src', panelsOptions.prebuiltDefaultScreenshot ).appendTo( $a ).hide().fadeIn( 'fast' );
660
- }
661
-
662
- } );
663
-
664
- // Set the title
665
- c.find( '.so-directory-browse' ).html( data.title );
666
- },
667
- 'json'
668
- );
669
- },
670
-
671
- /**
672
- * Set the selected state for the clicked layout directory item and remove previously selected item.
673
- * Enable the toolbar buttons.
674
- */
675
- directoryItemClickHandler: function ( e ) {
676
- var $directoryItem = this.$( e.target ).closest( '.so-directory-item' );
677
- this.$( '.so-directory-items' ).find( '.selected' ).removeClass( 'selected' );
678
- $directoryItem.addClass( 'selected' );
679
- this.selectedLayoutItem = {lid: $directoryItem.data( 'layout-id' ), type: $directoryItem.data( 'layout-type' )};
680
- this.updateButtonState( true );
681
-
682
- },
683
-
684
- /**
685
- * Load a particular layout into the builder.
686
- *
687
- * @param id
688
- */
689
- toolbarButtonClick: function ( $button ) {
690
- if ( ! this.canAddLayout() ) {
691
- return false;
692
- }
693
- var position = $button.data( 'value' );
694
- if ( _.isUndefined( position ) ) {
695
- return false;
696
- }
697
- this.updateButtonState( false );
698
-
699
- if ( $button.hasClass( 'so-needs-confirm' ) && ! $button.hasClass( 'so-confirmed' ) ) {
700
- this.updateButtonState( true );
701
- if ( $button.hasClass( 'so-confirming' ) ) {
702
- return;
703
- }
704
- $button.addClass( 'so-confirming' );
705
- var originalText = $button.html();
706
- $button.html( '<span class="dashicons dashicons-yes"></span>' + $button.data( 'confirm' ) );
707
- setTimeout( function () {
708
- $button.removeClass( 'so-confirmed' ).html( originalText );
709
- }, 2500 );
710
- setTimeout( function () {
711
- $button.removeClass( 'so-confirming' );
712
- $button.addClass( 'so-confirmed' );
713
- }, 200 );
714
- return false;
715
- }
716
- this.addingLayout = true;
717
- if ( this.currentTab === 'import' ) {
718
- this.addLayoutToBuilder( this.uploadedLayout, position );
719
- } else {
720
- this.loadSelectedLayout().then( function ( layout ) {
721
- this.addLayoutToBuilder( layout, position );
722
- }.bind( this ) );
723
- }
724
- },
725
-
726
- canAddLayout: function () {
727
- return (
728
- this.selectedLayoutItem || this.uploadedLayout
729
- ) && ! this.addingLayout;
730
- },
731
-
732
- /**
733
- * Load the layout according to selectedLayoutItem.
734
- */
735
- loadSelectedLayout: function () {
736
- this.setStatusMessage( panelsOptions.loc.prebuilt_loading, true );
737
-
738
- var args = _.extend( this.selectedLayoutItem, {action: 'so_panels_get_layout'} );
739
- var deferredLayout = new $.Deferred();
740
-
741
- $.get(
742
- panelsOptions.ajaxurl,
743
- args,
744
- function ( layout ) {
745
- var msg = '';
746
- if ( ! layout.success ) {
747
- msg = layout.data.message;
748
- deferredLayout.reject( layout.data );
749
- } else {
750
- deferredLayout.resolve( layout.data );
751
- }
752
- this.setStatusMessage( msg, false, ! layout.success );
753
- this.updateButtonState( true );
754
- }.bind( this )
755
- );
756
- return deferredLayout.promise();
757
- },
758
-
759
- /**
760
- * Handle an update to the search
761
- */
762
- searchHandler: function ( e ) {
763
- if ( e.keyCode === 13 ) {
764
- this.displayLayoutDirectory( $( e.currentTarget ).val(), 1, this.currentTab );
765
- }
766
- },
767
-
768
- /**
769
- * Attempt to set the 'Insert' button's state according to the `enabled` argument, also checking whether the
770
- * requirements for inserting a layout have valid values.
771
- */
772
- updateButtonState: function ( enabled ) {
773
- enabled = enabled && (
774
- this.selectedLayoutItem || this.uploadedLayout
775
- );
776
- var $button = this.$( '.so-import-layout' );
777
- $button.prop( "disabled", ! enabled );
778
- if ( enabled ) {
779
- $button.removeClass( 'disabled' );
780
- } else {
781
- $button.addClass( 'disabled' );
782
- }
783
- },
784
-
785
- addLayoutToBuilder: function ( layout, position ) {
786
- this.builder.addHistoryEntry( 'prebuilt_loaded' );
787
- this.builder.model.loadPanelsData( layout, position );
788
- this.addingLayout = false;
789
- this.closeDialog();
790
- }
791
- } );
792
-
793
- },{}],8:[function(require,module,exports){
794
- var panels = window.panels, $ = jQuery;
795
-
796
- module.exports = panels.view.dialog.extend({
797
-
798
- cellPreviewTemplate: _.template( panels.helpers.utils.processTemplate( $('#siteorigin-panels-dialog-row-cell-preview').html() ) ),
799
-
800
- editableLabel: true,
801
-
802
- events: {
803
- 'click .so-close': 'closeDialog',
804
-
805
- // Toolbar buttons
806
- 'click .so-toolbar .so-save': 'saveHandler',
807
- 'click .so-toolbar .so-insert': 'insertHandler',
808
- 'click .so-toolbar .so-delete': 'deleteHandler',
809
- 'click .so-toolbar .so-duplicate': 'duplicateHandler',
810
-
811
- // Changing the row
812
- 'change .row-set-form > *': 'setCellsFromForm',
813
- 'click .row-set-form button.set-row': 'setCellsFromForm',
814
- },
815
-
816
- rowView: null,
817
- dialogIcon: 'add-row',
818
- dialogClass: 'so-panels-dialog-row-edit',
819
- styleType: 'row',
820
-
821
- dialogType: 'edit',
822
-
823
- /**
824
- * The current settings, not yet saved to the model
825
- */
826
- row: {
827
- // This will be a clone of cells collection.
828
- cells: null,
829
- // The style settings of the row
830
- style: {}
831
- },
832
-
833
- cellStylesCache: [],
834
-
835
- initializeDialog: function () {
836
- this.on('open_dialog', function () {
837
- if (!_.isUndefined(this.model) && !_.isEmpty(this.model.get('cells'))) {
838
- this.setRowModel(this.model);
839
- } else {
840
- this.setRowModel(null);
841
- }
842
-
843
- this.regenerateRowPreview();
844
- this.renderStyles();
845
- }, this);
846
-
847
- // This is the default row layout
848
- this.row = {
849
- cells: new panels.collection.cells([{weight: 0.5}, {weight: 0.5}]),
850
- style: {}
851
- };
852
-
853
- // Refresh panels data after both dialog form components are loaded
854
- this.dialogFormsLoaded = 0;
855
- var thisView = this;
856
- this.on('form_loaded styles_loaded', function () {
857
- this.dialogFormsLoaded++;
858
- if (this.dialogFormsLoaded === 2) {
859
- thisView.updateModel({
860
- refreshArgs: {
861
- silent: true
862
- }
863
- });
864
- }
865
- });
866
-
867
- this.on('close_dialog', this.closeHandler);
868
-
869
- this.on( 'edit_label', function ( text ) {
870
- // If text is set to default values, just clear it.
871
- if ( text === panelsOptions.loc.row.add || text === panelsOptions.loc.row.edit ) {
872
- text = '';
873
- }
874
- this.model.set( 'label', text );
875
- if ( _.isEmpty( text ) ) {
876
- var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
877
- this.$( '.so-title').text( title );
878
- }
879
- }.bind( this ) );
880
- },
881
-
882
- /**
883
- *
884
- * @param dialogType Either "edit" or "create"
885
- */
886
- setRowDialogType: function (dialogType) {
887
- this.dialogType = dialogType;
888
- },
889
-
890
- /**
891
- * Render the new row dialog
892
- */
893
- render: function () {
894
- var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
895
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-row' ).html(), {
896
- title: title,
897
- dialogType: this.dialogType
898
- } ) );
899
-
900
- var titleElt = this.$( '.so-title' );
901
-
902
- if ( this.model.has( 'label' ) && ! _.isEmpty( this.model.get( 'label' ) ) ) {
903
- titleElt.text( this.model.get( 'label' ) );
904
- }
905
- this.$( '.so-edit-title' ).val( titleElt.text() );
906
-
907
- if (!this.builder.supports('addRow')) {
908
- this.$('.so-buttons .so-duplicate').remove();
909
- }
910
- if (!this.builder.supports('deleteRow')) {
911
- this.$('.so-buttons .so-delete').remove();
912
- }
913
-
914
- if (!_.isUndefined(this.model)) {
915
- // Set the initial value of the
916
- this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
917
- if ( this.model.has( 'ratio' ) ) {
918
- this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
919
- }
920
- if ( this.model.has( 'ratio_direction' ) ) {
921
- this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
922
- }
923
- }
924
-
925
- this.$('input.so-row-field').keyup(function () {
926
- $(this).trigger('change');
927
- });
928
-
929
- return this;
930
- },
931
-
932
- renderStyles: function () {
933
- if ( this.styles ) {
934
- this.styles.off( 'styles_loaded' );
935
- this.styles.remove();
936
- }
937
-
938
- // Now we need to attach the style window
939
- this.styles = new panels.view.styles();
940
- this.styles.model = this.model;
941
- this.styles.render('row', this.builder.config.postId, {
942
- builderType: this.builder.config.builderType,
943
- dialog: this
944
- });
945
-
946
- var $rightSidebar = this.$('.so-sidebar.so-right-sidebar');
947
- this.styles.attach( $rightSidebar );
948
-
949
- // Handle the loading class
950
- this.styles.on('styles_loaded', function (hasStyles) {
951
- if ( ! hasStyles ) {
952
- // If we don't have styles remove the view.
953
- this.styles.remove();
954
-
955
- // If the sidebar is empty, hide it.
956
- if ( $rightSidebar.children().length === 0 ) {
957
- $rightSidebar.closest('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
958
- $rightSidebar.hide();
959
- }
960
- }
961
- }, this);
962
- },
963
-
964
- /**
965
- * Set the row model we'll be using for this dialog.
966
- *
967
- * @param model
968
- */
969
- setRowModel: function (model) {
970
- this.model = model;
971
-
972
- if (_.isEmpty(this.model)) {
973
- return this;
974
- }
975
-
976
- // Set the rows to be a copy of the model
977
- this.row = {
978
- cells: this.model.get('cells').clone(),
979
- style: {},
980
- ratio: this.model.get('ratio'),
981
- ratio_direction: this.model.get('ratio_direction'),
982
- };
983
-
984
- // Set the initial value of the cell field.
985
- this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
986
- if ( this.model.has( 'ratio' ) ) {
987
- this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
988
- }
989
- if ( this.model.has( 'ratio_direction' ) ) {
990
- this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
991
- }
992
-
993
- this.clearCellStylesCache();
994
-
995
- return this;
996
- },
997
-
998
- /**
999
- * Regenerate the row preview and resizing interface.
1000
- */
1001
- regenerateRowPreview: function () {
1002
- var thisDialog = this;
1003
- var rowPreview = this.$('.row-preview');
1004
-
1005
- // If no selected cell, select the first cell.
1006
- var selectedIndex = this.getSelectedCellIndex();
1007
-
1008
- rowPreview.empty();
1009
-
1010
- var timeout;
1011
-
1012
- // Represent the cells
1013
- this.row.cells.each(function (cellModel, i) {
1014
- var newCell = $(this.cellPreviewTemplate({weight: cellModel.get('weight')}));
1015
- rowPreview.append(newCell);
1016
-
1017
- if(i == selectedIndex) {
1018
- newCell.find('.preview-cell-in').addClass('cell-selected');
1019
- }
1020
-
1021
- var prevCell = newCell.prev();
1022
- var handle;
1023
-
1024
- if (prevCell.length) {
1025
- handle = $('<div class="resize-handle"></div>');
1026
- handle
1027
- .appendTo(newCell)
1028
- .dblclick(function () {
1029
- var prevCellModel = thisDialog.row.cells.at(i - 1);
1030
- var t = cellModel.get('weight') + prevCellModel.get('weight');
1031
- cellModel.set('weight', t / 2);
1032
- prevCellModel.set('weight', t / 2);
1033
- thisDialog.scaleRowWidths();
1034
- });
1035
-
1036
- handle.draggable({
1037
- axis: 'x',
1038
- containment: rowPreview,
1039
- start: function (e, ui) {
1040
-
1041
- // Create the clone for the current cell
1042
- var newCellClone = newCell.clone().appendTo(ui.helper).css({
1043
- position: 'absolute',
1044
- top: '0',
1045
- width: newCell.outerWidth(),
1046
- left: 6,
1047
- height: newCell.outerHeight()
1048
- });
1049
- newCellClone.find('.resize-handle').remove();
1050
-
1051
- // Create the clone for the previous cell
1052
- var prevCellClone = prevCell.clone().appendTo(ui.helper).css({
1053
- position: 'absolute',
1054
- top: '0',
1055
- width: prevCell.outerWidth(),
1056
- right: 6,
1057
- height: prevCell.outerHeight()
1058
- });
1059
- prevCellClone.find('.resize-handle').remove();
1060
-
1061
- $(this).data({
1062
- 'newCellClone': newCellClone,
1063
- 'prevCellClone': prevCellClone
1064
- });
1065
-
1066
- // Hide the
1067
- newCell.find('> .preview-cell-in').css('visibility', 'hidden');
1068
- prevCell.find('> .preview-cell-in').css('visibility', 'hidden');
1069
- },
1070
- drag: function (e, ui) {
1071
- // Calculate the new cell and previous cell widths as a percent
1072
- var cellWeight = thisDialog.row.cells.at(i).get('weight');
1073
- var prevCellWeight = thisDialog.row.cells.at(i - 1).get('weight');
1074
- var ncw = cellWeight - (
1075
- (
1076
- ui.position.left + 6
1077
- ) / rowPreview.width()
1078
- );
1079
- var pcw = prevCellWeight + (
1080
- (
1081
- ui.position.left + 6
1082
- ) / rowPreview.width()
1083
- );
1084
-
1085
- var helperLeft = ui.helper.offset().left - rowPreview.offset().left - 6;
1086
-
1087
- $(this).data('newCellClone').css('width', rowPreview.width() * ncw)
1088
- .find('.preview-cell-weight').html(Math.round(ncw * 1000) / 10);
1089
-
1090
- $(this).data('prevCellClone').css('width', rowPreview.width() * pcw)
1091
- .find('.preview-cell-weight').html(Math.round(pcw * 1000) / 10);
1092
- },
1093
- stop: function (e, ui) {
1094
- // Remove the clones
1095
- $(this).data('newCellClone').remove();
1096
- $(this).data('prevCellClone').remove();
1097
-
1098
- // Reshow the main cells
1099
- newCell.find('.preview-cell-in').css('visibility', 'visible');
1100
- prevCell.find('.preview-cell-in').css('visibility', 'visible');
1101
-
1102
- // Calculate the new cell weights
1103
- var offset = ui.position.left + 6;
1104
- var percent = offset / rowPreview.width();
1105
-
1106
- // Ignore this if any of the cells are below 2% in width.
1107
- var cellModel = thisDialog.row.cells.at(i);
1108
- var prevCellModel = thisDialog.row.cells.at(i - 1);
1109
- if (cellModel.get('weight') - percent > 0.02 && prevCellModel.get('weight') + percent > 0.02) {
1110
- cellModel.set('weight', cellModel.get('weight') - percent);
1111
- prevCellModel.set('weight', prevCellModel.get('weight') + percent);
1112
- }
1113
-
1114
- thisDialog.scaleRowWidths();
1115
- ui.helper.css('left', -6);
1116
- }
1117
- });
1118
- }
1119
-
1120
- newCell.click(function (event) {
1121
-
1122
- if ( ! ( $(event.target).is('.preview-cell') || $(event.target).is('.preview-cell-in') ) ) {
1123
- return;
1124
- }
1125
-
1126
- var cell = $(event.target);
1127
- cell.closest('.row-preview').find('.preview-cell .preview-cell-in').removeClass('cell-selected');
1128
- cell.addClass('cell-selected');
1129
-
1130
- this.openSelectedCellStyles();
1131
-
1132
- }.bind(this));
1133
-
1134
- // Make this row weight click editable
1135
- newCell.find('.preview-cell-weight').click(function (ci) {
1136
-
1137
- // Disable the draggable while entering values
1138
- thisDialog.$('.resize-handle').css('pointer-event', 'none').draggable('disable');
1139
-
1140
- rowPreview.find('.preview-cell-weight').each(function () {
1141
- var $$ = jQuery(this).hide();
1142
- $('<input type="text" class="preview-cell-weight-input no-user-interacted" />')
1143
- .val(parseFloat($$.html())).insertAfter($$)
1144
- .focus(function () {
1145
- clearTimeout(timeout);
1146
- })
1147
- .keyup(function (e) {
1148
- if (e.keyCode !== 9) {
1149
- // Only register the interaction if the user didn't press tab
1150
- $(this).removeClass('no-user-interacted');
1151
- }
1152
-
1153
- // Enter is clicked
1154
- if (e.keyCode === 13) {
1155
- e.preventDefault();
1156
- $(this).blur();
1157
- }
1158
- })
1159
- .keydown(function (e) {
1160
- if (e.keyCode === 9) {
1161
- e.preventDefault();
1162
-
1163
- // Tab will always cycle around the row inputs
1164
- var inputs = rowPreview.find('.preview-cell-weight-input');
1165
- var i = inputs.index($(this));
1166
- if (i === inputs.length - 1) {
1167
- inputs.eq(0).focus().select();
1168
- } else {
1169
- inputs.eq(i + 1).focus().select();
1170
- }
1171
- }
1172
- })
1173
- .blur(function () {
1174
- rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
1175
- if (isNaN(parseFloat($(el).val()))) {
1176
- $(el).val(Math.floor(thisDialog.row.cells.at(i).get('weight') * 1000) / 10);
1177
- }
1178
- });
1179
-
1180
- timeout = setTimeout(function () {
1181
- // If there are no weight inputs, then skip this
1182
- if (rowPreview.find('.preview-cell-weight-input').length === 0) {
1183
- return false;
1184
- }
1185
-
1186
- // Go through all the inputs
1187
- var rowWeights = [],
1188
- rowChanged = [],
1189
- changedSum = 0,
1190
- unchangedSum = 0;
1191
-
1192
- rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
1193
- var val = parseFloat($(el).val());
1194
- if (isNaN(val)) {
1195
- val = 1 / thisDialog.row.cells.length;
1196
- } else {
1197
- val = Math.round(val * 10) / 1000;
1198
- }
1199
-
1200
- // Check within 3 decimal points
1201
- var changed = !$(el).hasClass('no-user-interacted');
1202
-
1203
- rowWeights.push(val);
1204
- rowChanged.push(changed);
1205
-
1206
- if (changed) {
1207
- changedSum += val;
1208
- } else {
1209
- unchangedSum += val;
1210
- }
1211
- });
1212
-
1213
- if (changedSum > 0 && unchangedSum > 0 && (
1214
- 1 - changedSum
1215
- ) > 0) {
1216
- // Balance out the unchanged rows to occupy the weight left over by the changed sum
1217
- for (var i = 0; i < rowWeights.length; i++) {
1218
- if (!rowChanged[i]) {
1219
- rowWeights[i] = (
1220
- rowWeights[i] / unchangedSum
1221
- ) * (
1222
- 1 - changedSum
1223
- );
1224
- }
1225
- }
1226
- }
1227
-
1228
- // Last check to ensure total weight is 1
1229
- var sum = _.reduce(rowWeights, function (memo, num) {
1230
- return memo + num;
1231
- });
1232
- rowWeights = rowWeights.map(function (w) {
1233
- return w / sum;
1234
- });
1235
-
1236
- // Set the new cell weights and regenerate the preview.
1237
- if (Math.min.apply(Math, rowWeights) > 0.01) {
1238
- thisDialog.row.cells.each(function (cell, i) {
1239
- cell.set('weight', rowWeights[i]);
1240
- });
1241
- }
1242
-
1243
- // Now lets animate the cells into their new widths
1244
- rowPreview.find('.preview-cell').each(function (i, el) {
1245
- var cellWeight = thisDialog.row.cells.at(i).get('weight');
1246
- $(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
1247
- $(el).find('.preview-cell-weight-input').val(Math.round(cellWeight * 1000) / 10);
1248
- });
1249
-
1250
- // So the draggable handle is not hidden.
1251
- rowPreview.find('.preview-cell').css('overflow', 'visible');
1252
- setTimeout(thisDialog.regenerateRowPreview.bind(thisDialog), 260);
1253
-
1254
- }, 100);
1255
- })
1256
- .click(function () {
1257
- $(this).select();
1258
- });
1259
- });
1260
-
1261
- $(this).siblings('.preview-cell-weight-input').select();
1262
-
1263
- });
1264
-
1265
- }, this);
1266
-
1267
- this.openSelectedCellStyles();
1268
-
1269
- this.trigger('form_loaded', this);
1270
- },
1271
-
1272
- getSelectedCellIndex: function() {
1273
- var selectedIndex = -1;
1274
- this.$('.preview-cell .preview-cell-in').each(function(index, el) {
1275
- if($(el).is('.cell-selected')) {
1276
- selectedIndex = index;
1277
- }
1278
- });
1279
- return selectedIndex;
1280
- },
1281
-
1282
- openSelectedCellStyles: function() {
1283
- if (!_.isUndefined(this.cellStyles)) {
1284
- if (this.cellStyles.stylesLoaded) {
1285
- var style = {};
1286
- try {
1287
- style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
1288
- }
1289
- catch (err) {
1290
- console.log('Error retrieving cell styles - ' + err.message);
1291
- }
1292
-
1293
- this.cellStyles.model.set('style', style);
1294
- }
1295
- this.cellStyles.detach();
1296
- }
1297
-
1298
- this.cellStyles = this.getSelectedCellStyles();
1299
-
1300
- if ( this.cellStyles ) {
1301
- var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
1302
- this.cellStyles.attach( $rightSidebar );
1303
- this.cellStyles.on( 'styles_loaded', function ( hasStyles ) {
1304
- if ( hasStyles ) {
1305
- $rightSidebar.closest('.so-panels-dialog').addClass('so-panels-dialog-has-right-sidebar');
1306
- $rightSidebar.show();
1307
- }
1308
- } );
1309
- }
1310
- },
1311
-
1312
- getSelectedCellStyles: function () {
1313
- var cellIndex = this.getSelectedCellIndex();
1314
- if ( cellIndex > -1 ) {
1315
- var cellStyles = this.cellStylesCache[cellIndex];
1316
- if ( !cellStyles ) {
1317
- cellStyles = new panels.view.styles();
1318
- cellStyles.model = this.row.cells.at( cellIndex );
1319
- cellStyles.render( 'cell', this.builder.config.postId, {
1320
- builderType: this.builder.config.builderType,
1321
- dialog: this,
1322
- index: cellIndex,
1323
- } );
1324
- this.cellStylesCache[cellIndex] = cellStyles;
1325
- }
1326
- }
1327
-
1328
- return cellStyles;
1329
- },
1330
-
1331
- clearCellStylesCache: function () {
1332
- // Call remove() on all cell styles to remove data, event listeners etc.
1333
- this.cellStylesCache.forEach(function (cellStyles) {
1334
- cellStyles.remove();
1335
- });
1336
- this.cellStylesCache = [];
1337
- },
1338
-
1339
- /**
1340
- * Visually scale the row widths based on the cell weights
1341
- */
1342
- scaleRowWidths: function () {
1343
- var thisDialog = this;
1344
- this.$('.row-preview .preview-cell').each(function (i, el) {
1345
- var cell = thisDialog.row.cells.at(i);
1346
- $(el)
1347
- .css('width', cell.get('weight') * 100 + "%")
1348
- .find('.preview-cell-weight').html(Math.round(cell.get('weight') * 1000) / 10);
1349
- });
1350
- },
1351
-
1352
- /**
1353
- * Get the weights from the
1354
- */
1355
- setCellsFromForm: function () {
1356
-
1357
- try {
1358
- var f = {
1359
- 'cells': parseInt(this.$('.row-set-form input[name="cells"]').val()),
1360
- 'ratio': parseFloat(this.$('.row-set-form select[name="ratio"]').val()),
1361
- 'direction': this.$('.row-set-form select[name="ratio_direction"]').val()
1362
- };
1363
-
1364
- if (_.isNaN(f.cells)) {
1365
- f.cells = 1;
1366
- }
1367
- if (isNaN(f.ratio)) {
1368
- f.ratio = 1;
1369
- }
1370
- if (f.cells < 1) {
1371
- f.cells = 1;
1372
- this.$('.row-set-form input[name="cells"]').val(f.cells);
1373
- }
1374
- else if (f.cells > 12) {
1375
- f.cells = 12;
1376
- this.$('.row-set-form input[name="cells"]').val(f.cells);
1377
- }
1378
-
1379
- this.$('.row-set-form select[name="ratio"]').val(f.ratio);
1380
-
1381
- var cells = [];
1382
- var cellCountChanged = (
1383
- this.row.cells.length !== f.cells
1384
- );
1385
-
1386
- // Now, lets create some cells
1387
- var currentWeight = 1;
1388
- for (var i = 0; i < f.cells; i++) {
1389
- cells.push(currentWeight);
1390
- currentWeight *= f.ratio;
1391
- }
1392
-
1393
- // Now lets make sure that the row weights add up to 1
1394
-
1395
- var totalRowWeight = _.reduce(cells, function (memo, weight) {
1396
- return memo + weight;
1397
- });
1398
- cells = _.map(cells, function (cell) {
1399
- return cell / totalRowWeight;
1400
- });
1401
-
1402
- // Don't return cells that are too small
1403
- cells = _.filter(cells, function (cell) {
1404
- return cell > 0.01;
1405
- });
1406
-
1407
- if (f.direction === 'left') {
1408
- cells = cells.reverse();
1409
- }
1410
-
1411
- // Discard deleted cells.
1412
- this.row.cells = new panels.collection.cells(this.row.cells.first(cells.length));
1413
-
1414
- _.each(cells, function (cellWeight, index) {
1415
- var cell = this.row.cells.at(index);
1416
- if (!cell) {
1417
- cell = new panels.model.cell({weight: cellWeight, row: this.model});
1418
- this.row.cells.add(cell);
1419
- } else {
1420
- cell.set('weight', cellWeight);
1421
- }
1422
- }.bind(this));
1423
-
1424
- this.row.ratio = f.ratio;
1425
- this.row.ratio_direction = f.direction;
1426
-
1427
- if (cellCountChanged) {
1428
- this.regenerateRowPreview();
1429
- } else {
1430
- var thisDialog = this;
1431
-
1432
- // Now lets animate the cells into their new widths
1433
- this.$('.preview-cell').each(function (i, el) {
1434
- var cellWeight = thisDialog.row.cells.at(i).get('weight');
1435
- $(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
1436
- $(el).find('.preview-cell-weight').html(Math.round(cellWeight * 1000) / 10);
1437
- });
1438
-
1439
- // So the draggable handle is not hidden.
1440
- this.$('.preview-cell').css('overflow', 'visible');
1441
-
1442
- setTimeout(thisDialog.regenerateRowPreview.bind(thisDialog), 260);
1443
- }
1444
- }
1445
- catch (err) {
1446
- console.log('Error setting cells - ' + err.message);
1447
- }
1448
-
1449
-
1450
- // Remove the button primary class
1451
- this.$('.row-set-form .so-button-row-set').removeClass('button-primary');
1452
- },
1453
-
1454
- /**
1455
- * Handle a click on the dialog left bar tab
1456
- */
1457
- tabClickHandler: function ($t) {
1458
- if ($t.attr('href') === '#row-layout') {
1459
- this.$('.so-panels-dialog').addClass('so-panels-dialog-has-right-sidebar');
1460
- } else {
1461
- this.$('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
1462
- }
1463
- },
1464
-
1465
- /**
1466
- * Update the current model with what we have in the dialog
1467
- */
1468
- updateModel: function (args) {
1469
- args = _.extend({
1470
- refresh: true,
1471
- refreshArgs: null
1472
- }, args);
1473
-
1474
- // Set the cells
1475
- if (!_.isEmpty(this.model)) {
1476
- this.model.setCells( this.row.cells );
1477
- this.model.set( 'ratio', this.row.ratio );
1478
- this.model.set( 'ratio_direction', this.row.ratio_direction );
1479
- }
1480
-
1481
- // Update the row styles if they've loaded
1482
- if (!_.isUndefined(this.styles) && this.styles.stylesLoaded) {
1483
- // This is an edit dialog, so there are styles
1484
- var style = {};
1485
- try {
1486
- style = this.getFormValues('.so-sidebar .so-visual-styles.so-row-styles').style;
1487
- }
1488
- catch (err) {
1489
- console.log('Error retrieving row styles - ' + err.message);
1490
- }
1491
-
1492
- this.model.set('style', style);
1493
- }
1494
-
1495
- // Update the cell styles if any are showing.
1496
- if (!_.isUndefined(this.cellStyles) && this.cellStyles.stylesLoaded) {
1497
-
1498
- var style = {};
1499
- try {
1500
- style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
1501
- }
1502
- catch (err) {
1503
- console.log('Error retrieving cell styles - ' + err.message);
1504
- }
1505
-
1506
- this.cellStyles.model.set('style', style);
1507
- }
1508
-
1509
- if (args.refresh) {
1510
- this.builder.model.refreshPanelsData(args.refreshArgs);
1511
- }
1512
- },
1513
-
1514
- /**
1515
- * Insert the new row
1516
- */
1517
- insertHandler: function () {
1518
- this.builder.addHistoryEntry('row_added');
1519
-
1520
- this.updateModel();
1521
-
1522
- var activeCell = this.builder.getActiveCell({
1523
- createCell: false,
1524
- });
1525
-
1526
- var options = {};
1527
- if (activeCell !== null) {
1528
- options.at = this.builder.model.get('rows').indexOf(activeCell.row) + 1;
1529
- }
1530
-
1531
- // Set up the model and add it to the builder
1532
- this.model.collection = this.builder.model.get('rows');
1533
- this.builder.model.get('rows').add(this.model, options);
1534
-
1535
- this.closeDialog();
1536
-
1537
- this.builder.model.refreshPanelsData();
1538
-
1539
- return false;
1540
- },
1541
-
1542
- /**
1543
- * We'll just save this model and close the dialog
1544
- */
1545
- saveHandler: function () {
1546
- this.builder.addHistoryEntry('row_edited');
1547
- this.updateModel();
1548
- this.closeDialog();
1549
-
1550
- this.builder.model.refreshPanelsData();
1551
-
1552
- return false;
1553
- },
1554
-
1555
- /**
1556
- * The user clicks delete, so trigger deletion on the row model
1557
- */
1558
- deleteHandler: function () {
1559
- // Trigger a destroy on the model that will happen with a visual indication to the user
1560
- this.rowView.visualDestroyModel();
1561
- this.closeDialog({silent: true});
1562
-
1563
- return false;
1564
- },
1565
-
1566
- /**
1567
- * Duplicate this row
1568
- */
1569
- duplicateHandler: function () {
1570
- this.builder.addHistoryEntry('row_duplicated');
1571
-
1572
- var duplicateRow = this.model.clone(this.builder.model);
1573
-
1574
- this.builder.model.get('rows').add( duplicateRow, {
1575
- at: this.builder.model.get('rows').indexOf(this.model) + 1
1576
- } );
1577
-
1578
- this.closeDialog({silent: true});
1579
-
1580
- return false;
1581
- },
1582
-
1583
- closeHandler: function() {
1584
- this.clearCellStylesCache();
1585
- if( ! _.isUndefined(this.cellStyles) ) {
1586
- this.cellStyles = undefined;
1587
- }
1588
- },
1589
-
1590
- });
1591
-
1592
- },{}],9:[function(require,module,exports){
1593
- var panels = window.panels, $ = jQuery;
1594
- var jsWidget = require( '../view/widgets/js-widget' );
1595
-
1596
- module.exports = panels.view.dialog.extend( {
1597
-
1598
- builder: null,
1599
- sidebarWidgetTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-widget-sidebar-widget' ).html() ) ),
1600
-
1601
- dialogClass: 'so-panels-dialog-edit-widget',
1602
- dialogIcon: 'add-widget',
1603
-
1604
- widgetView: false,
1605
- savingWidget: false,
1606
- editableLabel: true,
1607
-
1608
- events: {
1609
- 'click .so-close': 'saveHandler',
1610
- 'click .so-nav.so-previous': 'navToPrevious',
1611
- 'click .so-nav.so-next': 'navToNext',
1612
-
1613
- // Action handlers
1614
- 'click .so-toolbar .so-delete': 'deleteHandler',
1615
- 'click .so-toolbar .so-duplicate': 'duplicateHandler'
1616
- },
1617
-
1618
- initializeDialog: function () {
1619
- var thisView = this;
1620
- this.listenTo( this.model, 'change:values', this.handleChangeValues );
1621
- this.listenTo( this.model, 'destroy', this.remove );
1622
-
1623
- // Refresh panels data after both dialog form components are loaded
1624
- this.dialogFormsLoaded = 0;
1625
- this.on( 'form_loaded styles_loaded', function () {
1626
- this.dialogFormsLoaded ++;
1627
- if ( this.dialogFormsLoaded === 2 ) {
1628
- thisView.updateModel( {
1629
- refreshArgs: {
1630
- silent: true
1631
- }
1632
- } );
1633
- }
1634
- } );
1635
-
1636
- this.on( 'edit_label', function ( text ) {
1637
- // If text is set to default value, just clear it.
1638
- if ( text === panelsOptions.widgets[ this.model.get( 'class' ) ][ 'title' ] ) {
1639
- text = '';
1640
- }
1641
- this.model.set( 'label', text );
1642
- if ( _.isEmpty( text ) ) {
1643
- this.$( '.so-title' ).text( this.model.getWidgetField( 'title' ) );
1644
- }
1645
- }.bind( this ) );
1646
- },
1647
-
1648
- /**
1649
- * Render the widget dialog.
1650
- */
1651
- render: function () {
1652
- // Render the dialog and attach it to the builder interface
1653
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-widget' ).html(), {} ) );
1654
- this.loadForm();
1655
-
1656
- var title = this.model.getWidgetField( 'title' );
1657
- this.$( '.so-title .widget-name' ).html( title );
1658
- this.$( '.so-edit-title' ).val( title );
1659
-
1660
- if( ! this.builder.supports( 'addWidget' ) ) {
1661
- this.$( '.so-buttons .so-duplicate' ).remove();
1662
- }
1663
- if( ! this.builder.supports( 'deleteWidget' ) ) {
1664
- this.$( '.so-buttons .so-delete' ).remove();
1665
- }
1666
-
1667
- // Now we need to attach the style window
1668
- this.styles = new panels.view.styles();
1669
- this.styles.model = this.model;
1670
- this.styles.render( 'widget', this.builder.config.postId, {
1671
- builderType: this.builder.config.builderType,
1672
- dialog: this
1673
- } );
1674
-
1675
- var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
1676
- this.styles.attach( $rightSidebar );
1677
-
1678
- // Handle the loading class
1679
- this.styles.on( 'styles_loaded', function ( hasStyles ) {
1680
- // If we don't have styles remove the empty sidebar.
1681
- if ( ! hasStyles ) {
1682
- $rightSidebar.closest( '.so-panels-dialog' ).removeClass( 'so-panels-dialog-has-right-sidebar' );
1683
- $rightSidebar.remove();
1684
- }
1685
- }, this );
1686
- },
1687
-
1688
- /**
1689
- * Get the previous widget editing dialog by looking at the dom.
1690
- * @returns {*}
1691
- */
1692
- getPrevDialog: function () {
1693
- var widgets = this.builder.$( '.so-cells .cell .so-widget' );
1694
- if ( widgets.length <= 1 ) {
1695
- return false;
1696
- }
1697
- var currentIndex = widgets.index( this.widgetView.$el );
1698
-
1699
- if ( currentIndex === 0 ) {
1700
- return false;
1701
- } else {
1702
- var widgetView;
1703
- do {
1704
- widgetView = widgets.eq( --currentIndex ).data( 'view' );
1705
- if ( ! _.isUndefined( widgetView ) && ! widgetView.model.get( 'read_only' ) ) {
1706
- return widgetView.getEditDialog();
1707
- }
1708
- } while( ! _.isUndefined( widgetView ) && currentIndex > 0 );
1709
- }
1710
-
1711
- return false;
1712
- },
1713
-
1714
- /**
1715
- * Get the next widget editing dialog by looking at the dom.
1716
- * @returns {*}
1717
- */
1718
- getNextDialog: function () {
1719
- var widgets = this.builder.$( '.so-cells .cell .so-widget' );
1720
- if ( widgets.length <= 1 ) {
1721
- return false;
1722
- }
1723
-
1724
- var currentIndex = widgets.index( this.widgetView.$el );
1725
-
1726
- if ( currentIndex === widgets.length - 1 ) {
1727
- return false;
1728
- } else {
1729
- var widgetView;
1730
- do {
1731
- widgetView = widgets.eq( ++currentIndex ).data( 'view' );
1732
- if ( ! _.isUndefined( widgetView ) && ! widgetView.model.get( 'read_only' ) ) {
1733
- return widgetView.getEditDialog();
1734
- }
1735
- } while( ! _.isUndefined( widgetView ) );
1736
- }
1737
-
1738
- return false;
1739
- },
1740
-
1741
- /**
1742
- * Load the widget form from the server.
1743
- * This is called when rendering the dialog for the first time.
1744
- */
1745
- loadForm: function () {
1746
- // don't load the form if this dialog hasn't been rendered yet
1747
- if ( ! this.$( '> *' ).length ) {
1748
- return;
1749
- }
1750
-
1751
- this.$( '.so-content' ).addClass( 'so-panels-loading' );
1752
-
1753
- var data = {
1754
- 'action': 'so_panels_widget_form',
1755
- 'widget': this.model.get( 'class' ),
1756
- 'instance': JSON.stringify( this.model.get( 'values' ) ),
1757
- 'raw': this.model.get( 'raw' )
1758
- };
1759
-
1760
- var $soContent = this.$( '.so-content' );
1761
-
1762
- $.post( panelsOptions.ajaxurl, data, null, 'html' )
1763
- .done( function ( result ) {
1764
- // Add in the CID of the widget model
1765
- var html = result.replace( /{\$id}/g, this.model.cid );
1766
-
1767
- // Load this content into the form
1768
- $soContent
1769
- .removeClass( 'so-panels-loading' )
1770
- .html( html );
1771
-
1772
- // Trigger all the necessary events
1773
- this.trigger( 'form_loaded', this );
1774
-
1775
- // For legacy compatibility, trigger a panelsopen event
1776
- this.$( '.panel-dialog' ).trigger( 'panelsopen' );
1777
-
1778
- // If the main dialog is closed from this point on, save the widget content
1779
- this.on( 'close_dialog', this.updateModel, this );
1780
-
1781
- var widgetContent = $soContent.find( '> .widget-content' );
1782
- // If there's a widget content wrapper, this is one of the new widgets in WP 4.8 which need some special
1783
- // handling in JS.
1784
- if ( widgetContent.length > 0 ) {
1785
- jsWidget.addWidget( $soContent, this.model.widget_id );
1786
- }
1787
-
1788
- }.bind( this ) )
1789
- .fail( function ( error ) {
1790
- var html;
1791
- if ( error && error.responseText ) {
1792
- html = error.responseText;
1793
- } else {
1794
- html = panelsOptions.forms.loadingFailed;
1795
- }
1796
-
1797
- $soContent
1798
- .removeClass( 'so-panels-loading' )
1799
- .html( html );
1800
- } );
1801
- },
1802
-
1803
- /**
1804
- * Save the widget from the form to the model
1805
- */
1806
- updateModel: function ( args ) {
1807
- args = _.extend( {
1808
- refresh: true,
1809
- refreshArgs: null
1810
- }, args );
1811
-
1812
- // Get the values from the form and assign the new values to the model
1813
- this.savingWidget = true;
1814
-
1815
- if ( ! this.model.get( 'missing' ) ) {
1816
- // Only get the values for non missing widgets.
1817
- var values = this.getFormValues();
1818
- if ( _.isUndefined( values.widgets ) ) {
1819
- values = {};
1820
- } else {
1821
- values = values.widgets;
1822
- values = values[Object.keys( values )[0]];
1823
- }
1824
-
1825
- this.model.setValues( values );
1826
- this.model.set( 'raw', true ); // We've saved from the widget form, so this is now raw
1827
- }
1828
-
1829
- if ( this.styles.stylesLoaded ) {
1830
- // If the styles view has loaded
1831
- var style = {};
1832
- try {
1833
- style = this.getFormValues( '.so-sidebar .so-visual-styles' ).style;
1834
- }
1835
- catch ( e ) {
1836
- }
1837
- this.model.set( 'style', style );
1838
- }
1839
-
1840
- this.savingWidget = false;
1841
-
1842
- if ( args.refresh ) {
1843
- this.builder.model.refreshPanelsData( args.refreshArgs );
1844
- }
1845
- },
1846
-
1847
- /**
1848
- *
1849
- */
1850
- handleChangeValues: function () {
1851
- if ( ! this.savingWidget ) {
1852
- // Reload the form when we've changed the model and we're not currently saving from the form
1853
- this.loadForm();
1854
- }
1855
- },
1856
-
1857
- /**
1858
- * Save a history entry for this widget. Called when the dialog is closed.
1859
- */
1860
- saveHandler: function () {
1861
- this.builder.addHistoryEntry( 'widget_edited' );
1862
- this.closeDialog();
1863
- },
1864
-
1865
- /**
1866
- * When the user clicks delete.
1867
- *
1868
- * @returns {boolean}
1869
- */
1870
- deleteHandler: function () {
1871
- this.widgetView.visualDestroyModel();
1872
- this.closeDialog( {silent: true} );
1873
- this.builder.model.refreshPanelsData();
1874
-
1875
- return false;
1876
- },
1877
-
1878
- duplicateHandler: function () {
1879
- // Call the widget duplicate handler directly
1880
- this.widgetView.duplicateHandler();
1881
-
1882
- this.closeDialog( {silent: true} );
1883
- this.builder.model.refreshPanelsData();
1884
-
1885
- return false;
1886
- }
1887
-
1888
- } );
1889
-
1890
- },{"../view/widgets/js-widget":31}],10:[function(require,module,exports){
1891
- var panels = window.panels, $ = jQuery;
1892
-
1893
- module.exports = panels.view.dialog.extend( {
1894
-
1895
- builder: null,
1896
- widgetTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-widgets-widget' ).html() ) ),
1897
- filter: {},
1898
-
1899
- dialogClass: 'so-panels-dialog-add-widget',
1900
- dialogIcon: 'add-widget',
1901
-
1902
- events: {
1903
- 'click .so-close': 'closeDialog',
1904
- 'click .widget-type': 'widgetClickHandler',
1905
- 'keyup .so-sidebar-search': 'searchHandler'
1906
- },
1907
-
1908
- /**
1909
- * Initialize the widget adding dialog
1910
- */
1911
- initializeDialog: function () {
1912
-
1913
- this.on( 'open_dialog', function () {
1914
- this.filter.search = '';
1915
- this.filterWidgets( this.filter );
1916
- }, this );
1917
-
1918
- this.on( 'open_dialog_complete', function () {
1919
- // Clear the search and re-filter the widgets when we open the dialog
1920
- this.$( '.so-sidebar-search' ).val( '' ).focus();
1921
- this.balanceWidgetHeights();
1922
- } );
1923
-
1924
- // We'll implement a custom tab click handler
1925
- this.on( 'tab_click', this.tabClickHandler, this );
1926
- },
1927
-
1928
- render: function () {
1929
- // Render the dialog and attach it to the builder interface
1930
- this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-widgets' ).html(), {} ) );
1931
-
1932
- // Add all the widgets
1933
- _.each( panelsOptions.widgets, function ( widget ) {
1934
- var $w = $( this.widgetTemplate( {
1935
- title: widget.title,
1936
- description: widget.description
1937
- } ) );
1938
-
1939
- if ( _.isUndefined( widget.icon ) ) {
1940
- widget.icon = 'dashicons dashicons-admin-generic';
1941
- }
1942
-
1943
- $( '<span class="widget-icon" />' ).addClass( widget.icon ).prependTo( $w.find( '.widget-type-wrapper' ) );
1944
-
1945
- $w.data( 'class', widget.class ).appendTo( this.$( '.widget-type-list' ) );
1946
- }, this );
1947
-
1948
- // Add the sidebar tabs
1949
- var tabs = this.$( '.so-sidebar-tabs' );
1950
- _.each( panelsOptions.widget_dialog_tabs, function ( tab ) {
1951
- $( this.dialogTabTemplate( {'title': tab.title} ) ).data( {
1952
- 'message': tab.message,
1953
- 'filter': tab.filter
1954
- } ).appendTo( tabs );
1955
- }, this );
1956
-
1957
- // We'll be using tabs, so initialize them
1958
- this.initTabs();
1959
-
1960
- var thisDialog = this;
1961
- $( window ).resize( function () {
1962
- thisDialog.balanceWidgetHeights();
1963
- } );
1964
- },
1965
-
1966
- /**
1967
- * Handle a tab being clicked
1968
- */
1969
- tabClickHandler: function ( $t ) {
1970
- // Get the filter from the tab, and filter the widgets
1971
- this.filter = $t.parent().data( 'filter' );
1972
- this.filter.search = this.$( '.so-sidebar-search' ).val();
1973
-
1974
- var message = $t.parent().data( 'message' );
1975
- if ( _.isEmpty( message ) ) {
1976
- message = '';
1977
- }
1978
-
1979
- this.$( '.so-toolbar .so-status' ).html( message );
1980
-
1981
- this.filterWidgets( this.filter );
1982
-
1983
- return false;
1984
- },
1985
-
1986
- /**
1987
- * Handle changes to the search value
1988
- */
1989
- searchHandler: function ( e ) {
1990
- if( e.which === 13 ) {
1991
- var visibleWidgets = this.$( '.widget-type-list .widget-type:visible' );
1992
- if( visibleWidgets.length === 1 ) {
1993
- visibleWidgets.click();
1994
- }
1995
- }
1996
- else {
1997
- this.filter.search = $( e.target ).val().trim();
1998
- this.filterWidgets( this.filter );
1999
- }
2000
- },
2001
-
2002
- /**
2003
- * Filter the widgets that we're displaying
2004
- * @param filter
2005
- */
2006
- filterWidgets: function ( filter ) {
2007
- if ( _.isUndefined( filter ) ) {
2008
- filter = {};
2009
- }
2010
-
2011
- if ( _.isUndefined( filter.groups ) ) {
2012
- filter.groups = '';
2013
- }
2014
-
2015
- this.$( '.widget-type-list .widget-type' ).each( function () {
2016
- var $$ = $( this ), showWidget;
2017
- var widgetClass = $$.data( 'class' );
2018
-
2019
- var widgetData = (
2020
- ! _.isUndefined( panelsOptions.widgets[widgetClass] )
2021
- ) ? panelsOptions.widgets[widgetClass] : null;
2022
-
2023
- if ( _.isEmpty( filter.groups ) ) {
2024
- // This filter doesn't specify groups, so show all
2025
- showWidget = true;
2026
- } else if ( widgetData !== null && ! _.isEmpty( _.intersection( filter.groups, panelsOptions.widgets[widgetClass].groups ) ) ) {
2027
- // This widget is in the filter group
2028
- showWidget = true;
2029
- } else {
2030
- // This widget is not in the filter group
2031
- showWidget = false;
2032
- }
2033
-
2034
- // This can probably be done with a more intelligent operator
2035
- if ( showWidget ) {
2036
-
2037
- if ( ! _.isUndefined( filter.search ) && filter.search !== '' ) {
2038
- // Check if the widget title contains the search term
2039
- if ( widgetData.title.toLowerCase().indexOf( filter.search.toLowerCase() ) === - 1 ) {
2040
- showWidget = false;
2041
- }
2042
- }
2043
-
2044
- }
2045
-
2046
- if ( showWidget ) {
2047
- $$.show();
2048
- } else {
2049
- $$.hide();
2050
- }
2051
- } );
2052
-
2053
- // Balance the tags after filtering
2054
- this.balanceWidgetHeights();
2055
- },
2056
-
2057
- /**
2058
- * Add the widget to the current builder
2059
- *
2060
- * @param e
2061
- */
2062
- widgetClickHandler: function ( e ) {
2063
- // Add the history entry
2064
- this.builder.trigger('before_user_adds_widget');
2065
- this.builder.addHistoryEntry( 'widget_added' );
2066
-
2067
- var $w = $( e.currentTarget );
2068
-
2069
- var widget = new panels.model.widget( {
2070
- class: $w.data( 'class' )
2071
- } );
2072
-
2073
- // Add the widget to the cell model
2074
- widget.cell = this.builder.getActiveCell();
2075
- widget.cell.get('widgets').add( widget );
2076
-
2077
- this.closeDialog();
2078
- this.builder.model.refreshPanelsData();
2079
-
2080
- this.builder.trigger('after_user_adds_widget', widget);
2081
- },
2082
-
2083
- /**
2084
- * Balance widgets in a given row so they have enqual height.
2085
- * @param e
2086
- */
2087
- balanceWidgetHeights: function ( e ) {
2088
- var widgetRows = [[]];
2089
- var previousWidget = null;
2090
-
2091
- // Work out how many widgets there are per row
2092
- var perRow = Math.round( this.$( '.widget-type' ).parent().width() / this.$( '.widget-type' ).width() );
2093
-
2094
- // Add clears to create balanced rows
2095
- this.$( '.widget-type' )
2096
- .css( 'clear', 'none' )
2097
- .filter( ':visible' )
2098
- .each( function ( i, el ) {
2099
- if ( i % perRow === 0 && i !== 0 ) {
2100
- $( el ).css( 'clear', 'both' );
2101
- }
2102
- } );
2103
-
2104
- // Group the widgets into rows
2105
- this.$( '.widget-type-wrapper' )
2106
- .css( 'height', 'auto' )
2107
- .filter( ':visible' )
2108
- .each( function ( i, el ) {
2109
- var $el = $( el );
2110
- if ( previousWidget !== null && previousWidget.position().top !== $el.position().top ) {
2111
- widgetRows[widgetRows.length] = [];
2112
- }
2113
- previousWidget = $el;
2114
- widgetRows[widgetRows.length - 1].push( $el );
2115
- } );
2116
-
2117
- // Balance the height of the widgets within the row.
2118
- _.each( widgetRows, function ( row, i ) {
2119
- var maxHeight = _.max( row.map( function ( el ) {
2120
- return el.height();
2121
- } ) );
2122
- // Set the height of each widget in the row
2123
- _.each( row, function ( el ) {
2124
- el.height( maxHeight );
2125
- } );
2126
-
2127
- } );
2128
- }
2129
- } );
2130
-
2131
- },{}],11:[function(require,module,exports){
2132
- module.exports = {
2133
- /**
2134
- * Check if we have copy paste available.
2135
- * @returns {boolean|*}
2136
- */
2137
- canCopyPaste: function(){
2138
- return typeof(Storage) !== "undefined" && panelsOptions.user;
2139
- },
2140
-
2141
- /**
2142
- * Set the model that we're going to store in the clipboard
2143
- */
2144
- setModel: function( model ){
2145
- if( ! this.canCopyPaste() ) {
2146
- return false;
2147
- }
2148
-
2149
- var serial = panels.helpers.serialize.serialize( model );
2150
- if( model instanceof panels.model.row ) {
2151
- serial.thingType = 'row-model';
2152
- } else if( model instanceof panels.model.widget ) {
2153
- serial.thingType = 'widget-model';
2154
- }
2155
-
2156
- // Store this in local storage
2157
- localStorage[ 'panels_clipboard_' + panelsOptions.user ] = JSON.stringify( serial );
2158
- return true;
2159
- },
2160
-
2161
- /**
2162
- * Check if the current model stored in the clipboard is the expected type
2163
- */
2164
- isModel: function( expected ){
2165
- if( ! this.canCopyPaste() ) {
2166
- return false;
2167
- }
2168
-
2169
- var clipboardObject = localStorage[ 'panels_clipboard_' + panelsOptions.user ];
2170
- if( clipboardObject !== undefined ) {
2171
- clipboardObject = JSON.parse(clipboardObject);
2172
- return clipboardObject.thingType && clipboardObject.thingType === expected;
2173
- }
2174
-
2175
- return false;
2176
- },
2177
-
2178
- /**
2179
- * Get the model currently stored in the clipboard
2180
- */
2181
- getModel: function( expected ){
2182
- if( ! this.canCopyPaste() ) {
2183
- return null;
2184
- }
2185
-
2186
- var clipboardObject = localStorage[ 'panels_clipboard_' + panelsOptions.user ];
2187
- if( clipboardObject !== undefined ) {
2188
- clipboardObject = JSON.parse( clipboardObject );
2189
- if( clipboardObject.thingType && clipboardObject.thingType === expected ) {
2190
- return panels.helpers.serialize.unserialize( clipboardObject, clipboardObject.thingType, null );
2191
- }
2192
- }
2193
-
2194
- return null;
2195
- },
2196
- };
2197
-
2198
- },{}],12:[function(require,module,exports){
2199
- module.exports = {
2200
- /**
2201
- * Lock window scrolling for the main overlay
2202
- */
2203
- lock: function () {
2204
- if ( jQuery( 'body' ).css( 'overflow' ) === 'hidden' ) {
2205
- return;
2206
- }
2207
-
2208
- // lock scroll position, but retain settings for later
2209
- var scrollPosition = [
2210
- self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
2211
- self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
2212
- ];
2213
-
2214
- jQuery( 'body' )
2215
- .data( {
2216
- 'scroll-position': scrollPosition
2217
- } )
2218
- .css( 'overflow', 'hidden' );
2219
-
2220
- if( ! _.isUndefined( scrollPosition ) ) {
2221
- window.scrollTo( scrollPosition[0], scrollPosition[1] );
2222
- }
2223
- },
2224
-
2225
- /**
2226
- * Unlock window scrolling
2227
- */
2228
- unlock: function () {
2229
- if ( jQuery( 'body' ).css( 'overflow' ) !== 'hidden' ) {
2230
- return;
2231
- }
2232
-
2233
- // Check that there are no more dialogs or a live editor
2234
- if ( ! jQuery( '.so-panels-dialog-wrapper' ).is( ':visible' ) && ! jQuery( '.so-panels-live-editor' ).is( ':visible' ) ) {
2235
- jQuery( 'body' ).css( 'overflow', 'visible' );
2236
- var scrollPosition = jQuery( 'body' ).data( 'scroll-position' );
2237
-
2238
- if( ! _.isUndefined( scrollPosition ) ) {
2239
- window.scrollTo( scrollPosition[0], scrollPosition[1] );
2240
- }
2241
- }
2242
- },
2243
- };
2244
-
2245
- },{}],13:[function(require,module,exports){
2246
- /*
2247
- This is a modified version of https://github.com/underdogio/backbone-serialize/
2248
- */
2249
-
2250
- /* global Backbone, module, panels */
2251
-
2252
- module.exports = {
2253
- serialize: function( thing ){
2254
- var val;
2255
-
2256
- if( thing instanceof Backbone.Model ) {
2257
- var retObj = {};
2258
- for ( var key in thing.attributes ) {
2259
- if (thing.attributes.hasOwnProperty( key ) ) {
2260
- // Skip these to avoid recursion
2261
- if( key === 'builder' || key === 'collection' ) { continue; }
2262
-
2263
- // If the value is a Model or a Collection, then serialize them as well
2264
- val = thing.attributes[key];
2265
- if ( val instanceof Backbone.Model || val instanceof Backbone.Collection ) {
2266
- retObj[key] = this.serialize( val );
2267
- } else {
2268
- // Otherwise, save the original value
2269
- retObj[key] = val;
2270
- }
2271
- }
2272
- }
2273
- return retObj;
2274
- }
2275
- else if( thing instanceof Backbone.Collection ) {
2276
- // Walk over all of our models
2277
- var retArr = [];
2278
-
2279
- for ( var i = 0; i < thing.models.length; i++ ) {
2280
- // If the model is serializable, then serialize it
2281
- val = thing.models[i];
2282
-
2283
- if ( val instanceof Backbone.Model || val instanceof Backbone.Collection ) {
2284
- retArr.push( this.serialize( val ) );
2285
- } else {
2286
- // Otherwise (it is an object), return it in its current form
2287
- retArr.push( val );
2288
- }
2289
- }
2290
-
2291
- // Return the serialized models
2292
- return retArr;
2293
- }
2294
- },
2295
-
2296
- unserialize: function( thing, thingType, parent ) {
2297
- var retObj;
2298
-
2299
- switch( thingType ) {
2300
- case 'row-model' :
2301
- retObj = new panels.model.row();
2302
- retObj.builder = parent;
2303
- var atts = { style: thing.style };
2304
- if ( thing.hasOwnProperty( 'label' ) ) {
2305
- atts.label = thing.label;
2306
- }
2307
- if ( thing.hasOwnProperty( 'color_label' ) ) {
2308
- atts.color_label = thing.color_label;
2309
- }
2310
- retObj.set( atts );
2311
- retObj.setCells( this.unserialize( thing.cells, 'cell-collection', retObj ) );
2312
- break;
2313
-
2314
- case 'cell-model' :
2315
- retObj = new panels.model.cell();
2316
- retObj.row = parent;
2317
- retObj.set( 'weight', thing.weight );
2318
- retObj.set( 'style', thing.style );
2319
- retObj.set( 'widgets', this.unserialize( thing.widgets, 'widget-collection', retObj ) );
2320
- break;
2321
-
2322
- case 'widget-model' :
2323
- retObj = new panels.model.widget();
2324
- retObj.cell = parent;
2325
- for ( var key in thing ) {
2326
- if ( thing.hasOwnProperty( key ) ) {
2327
- retObj.set( key, thing[key] );
2328
- }
2329
- }
2330
- retObj.set( 'widget_id', panels.helpers.utils.generateUUID() );
2331
- break;
2332
-
2333
- case 'cell-collection':
2334
- retObj = new panels.collection.cells();
2335
- for( var i = 0; i < thing.length; i++ ) {
2336
- retObj.push( this.unserialize( thing[i], 'cell-model', parent ) );
2337
- }
2338
- break;
2339
-
2340
- case 'widget-collection':
2341
- retObj = new panels.collection.widgets();
2342
- for( var i = 0; i < thing.length; i++ ) {
2343
- retObj.push( this.unserialize( thing[i], 'widget-model', parent ) );
2344
- }
2345
- break;
2346
-
2347
- default:
2348
- console.log( 'Unknown Thing - ' + thingType );
2349
- break;
2350
- }
2351
-
2352
- return retObj;
2353
- }
2354
- };
2355
-
2356
- },{}],14:[function(require,module,exports){
2357
- module.exports = {
2358
-
2359
- generateUUID: function(){
2360
- var d = new Date().getTime();
2361
- if( window.performance && typeof window.performance.now === "function" ){
2362
- d += performance.now(); //use high-precision timer if available
2363
- }
2364
- var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( /[xy]/g, function(c) {
2365
- var r = (d + Math.random()*16)%16 | 0;
2366
- d = Math.floor(d/16);
2367
- return ( c == 'x' ? r : (r&0x3|0x8) ).toString(16);
2368
- } );
2369
- return uuid;
2370
- },
2371
-
2372
- processTemplate: function ( s ) {
2373
- if ( _.isUndefined( s ) || _.isNull( s ) ) {
2374
- return '';
2375
- }
2376
- s = s.replace( /{{%/g, '<%' );
2377
- s = s.replace( /%}}/g, '%>' );
2378
- s = s.trim();
2379
- return s;
2380
- },
2381
-
2382
- // From this SO post: http://stackoverflow.com/questions/6139107/programmatically-select-text-in-a-contenteditable-html-element
2383
- selectElementContents: function( element ) {
2384
- var range = document.createRange();
2385
- range.selectNodeContents( element );
2386
- var sel = window.getSelection();
2387
- sel.removeAllRanges();
2388
- sel.addRange( range );
2389
- },
2390
-
2391
- }
2392
-
2393
- },{}],15:[function(require,module,exports){
2394
- /* global _, jQuery, panels */
2395
-
2396
- var panels = window.panels, $ = jQuery;
2397
-
2398
- module.exports = function ( config, force ) {
2399
-
2400
- return this.each( function () {
2401
- var $$ = jQuery( this );
2402
-
2403
- if ( $$.data( 'soPanelsBuilderWidgetInitialized' ) && ! force ) {
2404
- return;
2405
- }
2406
- var widgetId = $$.closest( 'form' ).find( '.widget-id' ).val();
2407
-
2408
- // Create a config for this specific widget
2409
- var thisConfig = $.extend(true, {}, config);
2410
-
2411
- // Exit if this isn't a real widget
2412
- if ( ! _.isUndefined( widgetId ) && widgetId.indexOf( '__i__' ) > - 1 ) {
2413
- return;
2414
- }
2415
-
2416
- // Create the main builder model
2417
- var builderModel = new panels.model.builder();
2418
-
2419
- // Now for the view to display the builder
2420
- var builderView = new panels.view.builder( {
2421
- model: builderModel,
2422
- config: thisConfig
2423
- } );
2424
-
2425
- // Save panels data when we close the dialog, if we're in a dialog
2426
- var dialog = $$.closest( '.so-panels-dialog-wrapper' ).data( 'view' );
2427
- if ( ! _.isUndefined( dialog ) ) {
2428
- dialog.on( 'close_dialog', function () {
2429
- builderModel.refreshPanelsData();
2430
- } );
2431
-
2432
- dialog.on( 'open_dialog_complete', function () {
2433
- // Make sure the new layout widget is always properly setup
2434
- builderView.trigger( 'builder_resize' );
2435
- } );
2436
-
2437
- dialog.model.on( 'destroy', function () {
2438
- // Destroy the builder
2439
- builderModel.emptyRows().destroy();
2440
- } );
2441
-
2442
- // Set the parent for all the sub dialogs
2443
- builderView.setDialogParents( panelsOptions.loc.layout_widget, dialog );
2444
- }
2445
-
2446
- // Basic setup for the builder
2447
- var isWidget = Boolean( $$.closest( '.widget-content' ).length );
2448
- builderView
2449
- .render()
2450
- .attach( {
2451
- container: $$,
2452
- dialog: isWidget || $$.data('mode') === 'dialog',
2453
- type: $$.data( 'type' )
2454
- } )
2455
- .setDataField( $$.find( 'input.panels-data' ) );
2456
-
2457
- if ( isWidget || $$.data('mode') === 'dialog' ) {
2458
- // Set up the dialog opening
2459
- builderView.setDialogParents( panelsOptions.loc.layout_widget, builderView.dialog );
2460
- $$.find( '.siteorigin-panels-display-builder' ).click( function ( e ) {
2461
- e.preventDefault();
2462
- builderView.dialog.openDialog();
2463
- } );
2464
- } else {
2465
- // Remove the dialog opener button, this is already being displayed in a page builder dialog.
2466
- $$.find( '.siteorigin-panels-display-builder' ).parent().remove();
2467
- }
2468
-
2469
- // Trigger a global jQuery event after we've setup the builder view
2470
- $( document ).trigger( 'panels_setup', builderView );
2471
-
2472
- $$.data( 'soPanelsBuilderWidgetInitialized', true );
2473
- } );
2474
- };
2475
-
2476
- },{}],16:[function(require,module,exports){
2477
- /**
2478
- * Everything we need for SiteOrigin Page Builder.
2479
- *
2480
- * @copyright Greg Priday 2013 - 2016 - <https://siteorigin.com/>
2481
- * @license GPL 3.0 http://www.gnu.org/licenses/gpl.html
2482
- */
2483
-
2484
- /* global Backbone, _, jQuery, tinyMCE, panelsOptions, plupload, confirm, console, require */
2485
-
2486
- var panels = {};
2487
-
2488
- // Store everything globally
2489
- window.panels = panels;
2490
- window.siteoriginPanels = panels;
2491
-
2492
- // Helpers
2493
- panels.helpers = {};
2494
- panels.helpers.clipboard = require( './helpers/clipboard' );
2495
- panels.helpers.utils = require( './helpers/utils' );
2496
- panels.helpers.serialize = require( './helpers/serialize' );
2497
- panels.helpers.pageScroll = require( './helpers/page-scroll' );
2498
-
2499
- // The models
2500
- panels.model = {};
2501
- panels.model.widget = require( './model/widget' );
2502
- panels.model.cell = require( './model/cell' );
2503
- panels.model.row = require( './model/row' );
2504
- panels.model.builder = require( './model/builder' );
2505
- panels.model.historyEntry = require( './model/history-entry' );
2506
-
2507
- // The collections
2508
- panels.collection = {};
2509
- panels.collection.widgets = require( './collection/widgets' );
2510
- panels.collection.cells = require( './collection/cells' );
2511
- panels.collection.rows = require( './collection/rows' );
2512
- panels.collection.historyEntries = require( './collection/history-entries' );
2513
-
2514
- // The views
2515
- panels.view = {};
2516
- panels.view.widget = require( './view/widget' );
2517
- panels.view.cell = require( './view/cell' );
2518
- panels.view.row = require( './view/row' );
2519
- panels.view.builder = require( './view/builder' );
2520
- panels.view.dialog = require( './view/dialog' );
2521
- panels.view.styles = require( './view/styles' );
2522
- panels.view.liveEditor = require( './view/live-editor' );
2523
-
2524
- // The dialogs
2525
- panels.dialog = {};
2526
- panels.dialog.builder = require( './dialog/builder' );
2527
- panels.dialog.widgets = require( './dialog/widgets' );
2528
- panels.dialog.widget = require( './dialog/widget' );
2529
- panels.dialog.prebuilt = require( './dialog/prebuilt' );
2530
- panels.dialog.row = require( './dialog/row' );
2531
- panels.dialog.history = require( './dialog/history' );
2532
-
2533
- // The utils
2534
- panels.utils = {};
2535
- panels.utils.menu = require( './utils/menu' );
2536
-
2537
- // jQuery Plugins
2538
- jQuery.fn.soPanelsSetupBuilderWidget = require( './jquery/setup-builder-widget' );
2539
-
2540
-
2541
- // Set up Page Builder if we're on the main interface
2542
- jQuery( function ( $ ) {
2543
-
2544
- var container,
2545
- field,
2546
- form,
2547
- builderConfig;
2548
-
2549
- var $panelsMetabox = $( '#siteorigin-panels-metabox' );
2550
- form = $( 'form#post' );
2551
- if ( $panelsMetabox.length && form.length ) {
2552
- // This is usually the case when we're in the post edit interface
2553
- container = $panelsMetabox;
2554
- field = $panelsMetabox.find( '.siteorigin-panels-data-field' );
2555
-
2556
- builderConfig = {
2557
- editorType: 'tinyMCE',
2558
- postId: $( '#post_ID' ).val(),
2559
- editorId: '#content',
2560
- builderType: $panelsMetabox.data( 'builder-type' ),
2561
- builderSupports: $panelsMetabox.data( 'builder-supports' ),
2562
- loadOnAttach: panelsOptions.loadOnAttach && $( '#auto_draft' ).val() == 1,
2563
- loadLiveEditor: $panelsMetabox.data('live-editor') == 1,
2564
- liveEditorPreview: container.data('preview-url')
2565
- };
2566
- }
2567
- else if ( $( '.siteorigin-panels-builder-form' ).length ) {
2568
- // We're dealing with another interface like the custom home page interface
2569
- var $$ = $( '.siteorigin-panels-builder-form' );
2570
-
2571
- container = $$.find( '.siteorigin-panels-builder-container' );
2572
- field = $$.find( 'input[name="panels_data"]' );
2573
- form = $$;
2574
-
2575
- builderConfig = {
2576
- editorType: 'standalone',
2577
- postId: $$.data( 'post-id' ),
2578
- editorId: '#post_content',
2579
- builderType: $$.data( 'type' ),
2580
- builderSupports: $$.data( 'builder-supports' ),
2581
- loadLiveEditor: false,
2582
- liveEditorPreview: $$.data( 'preview-url' )
2583
- };
2584
- }
2585
-
2586
- if ( ! _.isUndefined( container ) ) {
2587
- // If we have a container, then set up the main builder
2588
- var panels = window.siteoriginPanels;
2589
-
2590
- // Create the main builder model
2591
- var builderModel = new panels.model.builder();
2592
-
2593
- // Now for the view to display the builder
2594
- var builderView = new panels.view.builder( {
2595
- model: builderModel,
2596
- config: builderConfig
2597
- } );
2598
-
2599
- // Set up the builder view
2600
- builderView
2601
- .render()
2602
- .attach( {
2603
- container: container
2604
- } )
2605
- .setDataField( field )
2606
- .attachToEditor();
2607
-
2608
- // When the form is submitted, update the panels data
2609
- form.submit( function () {
2610
- // Refresh the data
2611
- builderModel.refreshPanelsData();
2612
- } );
2613
-
2614
- container.removeClass( 'so-panels-loading' );
2615
-
2616
- // Trigger a global jQuery event after we've setup the builder view. Everything is accessible form there
2617
- $( document ).trigger( 'panels_setup', builderView, window.panels );
2618
- }
2619
-
2620
- // Setup new widgets when they're added in the standard widget interface
2621
- $( document ).on( 'widget-added', function ( e, widget ) {
2622
- $( widget ).find( '.siteorigin-page-builder-widget' ).soPanelsSetupBuilderWidget();
2623
- } );
2624
-
2625
- // Setup existing widgets on the page (for the widgets interface)
2626
- if ( ! $( 'body' ).hasClass( 'wp-customizer' ) ) {
2627
- $( function () {
2628
- $( '.siteorigin-page-builder-widget' ).soPanelsSetupBuilderWidget();
2629
- } );
2630
- }
2631
- } );
2632
-
2633
- },{"./collection/cells":1,"./collection/history-entries":2,"./collection/rows":3,"./collection/widgets":4,"./dialog/builder":5,"./dialog/history":6,"./dialog/prebuilt":7,"./dialog/row":8,"./dialog/widget":9,"./dialog/widgets":10,"./helpers/clipboard":11,"./helpers/page-scroll":12,"./helpers/serialize":13,"./helpers/utils":14,"./jquery/setup-builder-widget":15,"./model/builder":17,"./model/cell":18,"./model/history-entry":19,"./model/row":20,"./model/widget":21,"./utils/menu":22,"./view/builder":23,"./view/cell":24,"./view/dialog":25,"./view/live-editor":26,"./view/row":27,"./view/styles":28,"./view/widget":29}],17:[function(require,module,exports){
2634
- module.exports = Backbone.Model.extend({
2635
- layoutPosition: {
2636
- BEFORE: 'before',
2637
- AFTER: 'after',
2638
- REPLACE: 'replace',
2639
- },
2640
-
2641
- rows: {},
2642
-
2643
- defaults: {
2644
- 'data': {
2645
- 'widgets': [],
2646
- 'grids': [],
2647
- 'grid_cells': []
2648
- }
2649
- },
2650
-
2651
- initialize: function () {
2652
- // These are the main rows in the interface
2653
- this.set( 'rows', new panels.collection.rows() );
2654
- },
2655
-
2656
- /**
2657
- * Add a new row to this builder.
2658
- *
2659
- * @param attrs
2660
- * @param cells
2661
- * @param options
2662
- */
2663
- addRow: function (attrs, cells, options) {
2664
- options = _.extend({
2665
- noAnimate: false
2666
- }, options);
2667
-
2668
- var cellCollection = new panels.collection.cells(cells);
2669
-
2670
- attrs = _.extend({
2671
- collection: this.get('rows'),
2672
- cells: cellCollection,
2673
- }, attrs);
2674
-
2675
- // Create the actual row
2676
- var row = new panels.model.row(attrs);
2677
- row.builder = this;
2678
-
2679
- this.get('rows').add( row, options );
2680
-
2681
- return row;
2682
- },
2683
-
2684
- /**
2685
- * Load the panels data into the builder
2686
- *
2687
- * @param data Object the layout and widgets data to load.
2688
- * @param position string Where to place the new layout. Allowed options are 'before', 'after'. Anything else will
2689
- * cause the new layout to replace the old one.
2690
- */
2691
- loadPanelsData: function ( data, position ) {
2692
- try {
2693
- if ( position === this.layoutPosition.BEFORE ) {
2694
- data = this.concatPanelsData( data, this.getPanelsData() );
2695
- } else if ( position === this.layoutPosition.AFTER ) {
2696
- data = this.concatPanelsData( this.getPanelsData(), data );
2697
- }
2698
-
2699
- // Start by destroying any rows that currently exist. This will in turn destroy cells, widgets and all the associated views
2700
- this.emptyRows();
2701
-
2702
- // This will empty out the current rows and reload the builder data.
2703
- this.set( 'data', JSON.parse( JSON.stringify( data ) ), {silent: true} );
2704
-
2705
- var cit = 0;
2706
- var rows = [];
2707
-
2708
- if ( _.isUndefined( data.grid_cells ) ) {
2709
- this.trigger( 'load_panels_data' );
2710
- return;
2711
- }
2712
-
2713
- var gi;
2714
- for ( var ci = 0; ci < data.grid_cells.length; ci ++ ) {
2715
- gi = parseInt( data.grid_cells[ci].grid );
2716
- if ( _.isUndefined( rows[gi] ) ) {
2717
- rows[gi] = [];
2718
- }
2719
-
2720
- rows[gi].push( data.grid_cells[ci] );
2721
- }
2722
-
2723
- var builderModel = this;
2724
- _.each( rows, function ( row, i ) {
2725
- var rowAttrs = {};
2726
-
2727
- if ( ! _.isUndefined( data.grids[i].style ) ) {
2728
- rowAttrs.style = data.grids[i].style;
2729
- }
2730
-
2731
- if ( ! _.isUndefined( data.grids[i].ratio) ) {
2732
- rowAttrs.ratio = data.grids[i].ratio;
2733
- }
2734
-
2735
- if ( ! _.isUndefined( data.grids[i].ratio_direction) ) {
2736
- rowAttrs.ratio_direction = data.grids[i].ratio_direction
2737
- }
2738
-
2739
- if ( ! _.isUndefined( data.grids[i].color_label) ) {
2740
- rowAttrs.color_label = data.grids[i].color_label;
2741
- }
2742
-
2743
- if ( ! _.isUndefined( data.grids[i].label) ) {
2744
- rowAttrs.label = data.grids[i].label;
2745
- }
2746
- // This will create and add the row model and its cells
2747
- builderModel.addRow(rowAttrs, row, {noAnimate: true} );
2748
- } );
2749
-
2750
-
2751
- if ( _.isUndefined( data.widgets ) ) {
2752
- return;
2753
- }
2754
-
2755
- // Add the widgets
2756
- _.each( data.widgets, function ( widgetData ) {
2757
- var panels_info = null;
2758
- if ( ! _.isUndefined( widgetData.panels_info ) ) {
2759
- panels_info = widgetData.panels_info;
2760
- delete widgetData.panels_info;
2761
- } else {
2762
- panels_info = widgetData.info;
2763
- delete widgetData.info;
2764
- }
2765
-
2766
- var row = builderModel.get('rows').at( parseInt( panels_info.grid ) );
2767
- var cell = row.get('cells').at( parseInt( panels_info.cell ) );
2768
-
2769
- var newWidget = new panels.model.widget( {
2770
- class: panels_info.class,
2771
- values: widgetData
2772
- } );
2773
-
2774
- if ( ! _.isUndefined( panels_info.style ) ) {
2775
- newWidget.set( 'style', panels_info.style );
2776
- }
2777
-
2778
- if ( ! _.isUndefined( panels_info.read_only ) ) {
2779
- newWidget.set( 'read_only', panels_info.read_only );
2780
- }
2781
- if ( ! _.isUndefined( panels_info.widget_id ) ) {
2782
- newWidget.set( 'widget_id', panels_info.widget_id );
2783
- }
2784
- else {
2785
- newWidget.set( 'widget_id', panels.helpers.utils.generateUUID() );
2786
- }
2787
-
2788
- if ( ! _.isUndefined( panels_info.label ) ) {
2789
- newWidget.set( 'label', panels_info.label );
2790
- }
2791
-
2792
- newWidget.cell = cell;
2793
- cell.get('widgets').add( newWidget, { noAnimate: true } );
2794
- } );
2795
-
2796
- this.trigger( 'load_panels_data' );
2797
- }
2798
- catch ( err ) {
2799
- console.log( 'Error loading data: ' + err.message );
2800
-
2801
- }
2802
- },
2803
-
2804
- /**
2805
- * Concatenate the second set of Page Builder data to the first. There is some validation of input, but for the most
2806
- * part it's up to the caller to ensure the Page Builder data is well formed.
2807
- */
2808
- concatPanelsData: function ( panelsDataA, panelsDataB ) {
2809
-
2810
- if ( _.isUndefined( panelsDataB ) || _.isUndefined( panelsDataB.grids ) || _.isEmpty( panelsDataB.grids ) ||
2811
- _.isUndefined( panelsDataB.grid_cells ) || _.isEmpty( panelsDataB.grid_cells ) ) {
2812
- return panelsDataA;
2813
- }
2814
-
2815
- if ( _.isUndefined( panelsDataA ) || _.isUndefined( panelsDataA.grids ) || _.isEmpty( panelsDataA.grids ) ) {
2816
- return panelsDataB;
2817
- }
2818
-
2819
- var gridsBOffset = panelsDataA.grids.length;
2820
- var widgetsBOffset = ! _.isUndefined( panelsDataA.widgets ) ? panelsDataA.widgets.length : 0;
2821
- var newPanelsData = {grids: [], 'grid_cells': [], 'widgets': []};
2822
-
2823
- // Concatenate grids (rows)
2824
- newPanelsData.grids = panelsDataA.grids.concat( panelsDataB.grids );
2825
-
2826
- // Create a copy of panelsDataA grid_cells and widgets
2827
- if ( ! _.isUndefined( panelsDataA.grid_cells ) ) {
2828
- newPanelsData.grid_cells = panelsDataA.grid_cells.slice();
2829
- }
2830
- if ( ! _.isUndefined( panelsDataA.widgets ) ) {
2831
- newPanelsData.widgets = panelsDataA.widgets.slice();
2832
- }
2833
-
2834
- var i;
2835
- // Concatenate grid cells (row columns)
2836
- for ( i = 0; i < panelsDataB.grid_cells.length; i ++ ) {
2837
- var gridCellB = panelsDataB.grid_cells[i];
2838
- gridCellB.grid = parseInt( gridCellB.grid ) + gridsBOffset;
2839
- newPanelsData.grid_cells.push( gridCellB );
2840
- }
2841
-
2842
- // Concatenate widgets
2843
- if ( ! _.isUndefined( panelsDataB.widgets ) ) {
2844
- for ( i = 0; i < panelsDataB.widgets.length; i ++ ) {
2845
- var widgetB = panelsDataB.widgets[i];
2846
- widgetB.panels_info.grid = parseInt( widgetB.panels_info.grid ) + gridsBOffset;
2847
- widgetB.panels_info.id = parseInt( widgetB.panels_info.id ) + widgetsBOffset;
2848
- newPanelsData.widgets.push( widgetB );
2849
- }
2850
- }
2851
-
2852
- return newPanelsData;
2853
- },
2854
-
2855
- /**
2856
- * Convert the content of the builder into a object that represents the page builder data
2857
- */
2858
- getPanelsData: function () {
2859
-
2860
- var builder = this;
2861
-
2862
- var data = {
2863
- 'widgets': [],
2864
- 'grids': [],
2865
- 'grid_cells': []
2866
- };
2867
- var widgetId = 0;
2868
-
2869
- this.get('rows').each( function ( row, ri ) {
2870
-
2871
- row.get('cells').each( function ( cell, ci ) {
2872
-
2873
- cell.get('widgets').each( function ( widget, wi ) {
2874
- // Add the data for the widget, including the panels_info field.
2875
- var panels_info = {
2876
- class: widget.get( 'class' ),
2877
- raw: widget.get( 'raw' ),
2878
- grid: ri,
2879
- cell: ci,
2880
- // Strictly this should be an index
2881
- id: widgetId ++,
2882
- widget_id: widget.get( 'widget_id' ),
2883
- style: widget.get( 'style' ),
2884
- label: widget.get( 'label' ),
2885
- };
2886
-
2887
- if( _.isEmpty( panels_info.widget_id ) ) {
2888
- panels_info.widget_id = panels.helpers.utils.generateUUID();
2889
- }
2890
-
2891
- var values = _.extend( _.clone( widget.get( 'values' ) ), {
2892
- panels_info: panels_info
2893
- } );
2894
- data.widgets.push( values );
2895
- } );
2896
-
2897
- // Add the cell info
2898
- data.grid_cells.push( {
2899
- grid: ri,
2900
- index: ci,
2901
- weight: cell.get( 'weight' ),
2902
- style: cell.get( 'style' ),
2903
- } );
2904
-
2905
- } );
2906
-
2907
- data.grids.push( {
2908
- cells: row.get('cells').length,
2909
- style: row.get( 'style' ),
2910
- ratio: row.get('ratio'),
2911
- ratio_direction: row.get('ratio_direction'),
2912
- color_label: row.get( 'color_label' ),
2913
- label: row.get( 'label' ),
2914
- } );
2915
-
2916
- } );
2917
-
2918
- return data;
2919
-
2920
- },
2921
-
2922
- /**
2923
- * This will check all the current entries and refresh the panels data
2924
- */
2925
- refreshPanelsData: function ( args ) {
2926
- args = _.extend( {
2927
- silent: false
2928
- }, args );
2929
-
2930
- var oldData = this.get( 'data' );
2931
- var newData = this.getPanelsData();
2932
- this.set( 'data', newData, {silent: true} );
2933
-
2934
- if ( ! args.silent && JSON.stringify( newData ) !== JSON.stringify( oldData ) ) {
2935
- // The default change event doesn't trigger on deep changes, so we'll trigger our own
2936
- this.trigger( 'change' );
2937
- this.trigger( 'change:data' );
2938
- this.trigger( 'refresh_panels_data', newData, args );
2939
- }
2940
- },
2941
-
2942
- /**
2943
- * Empty all the rows and the cells/widgets they contain.
2944
- */
2945
- emptyRows: function () {
2946
- _.invoke( this.get('rows').toArray(), 'destroy' );
2947
- this.get('rows').reset();
2948
-
2949
- return this;
2950
- },
2951
-
2952
- isValidLayoutPosition: function ( position ) {
2953
- return position === this.layoutPosition.BEFORE ||
2954
- position === this.layoutPosition.AFTER ||
2955
- position === this.layoutPosition.REPLACE;
2956
- },
2957
-
2958
- /**
2959
- * Convert HTML into Panels Data
2960
- * @param html
2961
- */
2962
- getPanelsDataFromHtml: function( html, editorClass ){
2963
- var thisModel = this;
2964
- var $html = jQuery( '<div id="wrapper">' + html + '</div>' );
2965
-
2966
- if( $html.find('.panel-layout .panel-grid').length ) {
2967
- // This looks like Page Builder html, lets try parse it
2968
- var panels_data = {
2969
- grids: [],
2970
- grid_cells: [],
2971
- widgets: [],
2972
- };
2973
-
2974
- // The Regex object that'll match SiteOrigin widgets
2975
- var re = new RegExp( panelsOptions.siteoriginWidgetRegex , "i" );
2976
- var decodeEntities = (function() {
2977
- // this prevents any overhead from creating the object each time
2978
- var element = document.createElement('div');
2979
-
2980
- function decodeHTMLEntities (str) {
2981
- if(str && typeof str === 'string') {
2982
- // strip script/html tags
2983
- str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
2984
- str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
2985
- element.innerHTML = str;
2986
- str = element.textContent;
2987
- element.textContent = '';
2988
- }
2989
-
2990
- return str;
2991
- }
2992
-
2993
- return decodeHTMLEntities;
2994
- })();
2995
-
2996
- // Remove all wrapping divs from a widget to get its html
2997
- var getTextWidgetContents = function( $el ){
2998
- var $divs = $el.find( 'div' );
2999
- if( ! $divs.length ) {
3000
- return $el.html();
3001
- }
3002
-
3003
- var i;
3004
- for( i = 0; i < $divs.length - 1; i++ ) {
3005
- if( jQuery.trim( $divs.eq(i).text() ) != jQuery.trim( $divs.eq(i+1).text() ) ) {
3006
- break;
3007
- }
3008
- }
3009
-
3010
- var title = $divs.eq( i ).find( '.widget-title:header' ),
3011
- titleText = '';
3012
-
3013
- if( title.length ) {
3014
- titleText = title.html();
3015
- title.remove();
3016
- }
3017
-
3018
- return {
3019
- title: titleText,
3020
- text: $divs.eq(i).html(),
3021
- };
3022
- };
3023
-
3024
- var $layout = $html.find( '.panel-layout' ).eq(0);
3025
- var filterNestedLayout = function( i, el ){
3026
- return jQuery( el ).closest( '.panel-layout' ).is( $layout );
3027
- };
3028
-
3029
- $html.find('> .panel-layout > .panel-grid').filter( filterNestedLayout ).each( function( ri, el ){
3030
- var $row = jQuery( el ),
3031
- $cells = $row.find( '.panel-grid-cell' ).filter( filterNestedLayout );
3032
-
3033
- panels_data.grids.push( {
3034
- cells: $cells.length,
3035
- style: $row.data( 'style' ),
3036
- ratio: $row.data( 'ratio' ),
3037
- ratio_direction: $row.data( 'ratio-direction' ),
3038
- color_label: $row.data( 'color-label' ),
3039
- label: $row.data( 'label' ),
3040
- } );
3041
-
3042
- $cells.each( function( ci, el ){
3043
- var $cell = jQuery( el ),
3044
- $widgets = $cell.find( '.so-panel' ).filter( filterNestedLayout );
3045
-
3046
- panels_data.grid_cells.push( {
3047
- grid: ri,
3048
- weight: ! _.isUndefined( $cell.data( 'weight' ) ) ? parseFloat( $cell.data( 'weight' ) ) : 1,
3049
- style: $cell.data( 'style' ),
3050
- } );
3051
-
3052
- $widgets.each( function( wi, el ){
3053
- var $widget = jQuery(el),
3054
- widgetContent = $widget.find('.panel-widget-style').length ? $widget.find('.panel-widget-style').html() : $widget.html(),
3055
- panels_info = {
3056
- grid: ri,
3057
- cell: ci,
3058
- style: $widget.data( 'style' ),
3059
- raw: false,
3060
- label: $widget.data( 'label' )
3061
- };
3062
-
3063
- widgetContent = widgetContent.trim();
3064
-
3065
- // Check if this is a SiteOrigin Widget
3066
- var match = re.exec( widgetContent );
3067
- if( ! _.isNull( match ) && widgetContent.replace( re, '' ).trim() === '' ) {
3068
- try {
3069
- var classMatch = /class="(.*?)"/.exec( match[3] ),
3070
- dataInput = jQuery( match[5] ),
3071
- data = JSON.parse( decodeEntities( dataInput.val( ) ) ),
3072
- newWidget = data.instance;
3073
-
3074
- panels_info.class = classMatch[1].replace( /\\\\+/g, '\\' );
3075
- panels_info.raw = false;
3076
-
3077
- newWidget.panels_info = panels_info;
3078
- panels_data.widgets.push( newWidget );
3079
- }
3080
- catch ( err ) {
3081
- // There was a problem, so treat this as a standard editor widget
3082
- panels_info.class = editorClass;
3083
- panels_data.widgets.push( _.extend( getTextWidgetContents( $widget ), {
3084
- filter: "1",
3085
- type: "visual",
3086
- panels_info: panels_info
3087
- } ) );
3088
- }
3089
-
3090
- // Continue
3091
- return true;
3092
- }
3093
- else if( widgetContent.indexOf( 'panel-layout' ) !== -1 ) {
3094
- // Check if this is a layout widget
3095
- var $widgetContent = jQuery( '<div>' + widgetContent + '</div>' );
3096
- if( $widgetContent.find('.panel-layout .panel-grid').length ) {
3097
- // This is a standard editor class widget
3098
- panels_info.class = 'SiteOrigin_Panels_Widgets_Layout';
3099
- panels_data.widgets.push( {
3100
- panels_data: thisModel.getPanelsDataFromHtml( widgetContent, editorClass ),
3101
- panels_info: panels_info
3102
- } );
3103
-
3104
- // continue
3105
- return true;
3106
- }
3107
- }
3108
-
3109
- // This is a standard editor class widget
3110
- panels_info.class = editorClass;
3111
- panels_data.widgets.push( _.extend( getTextWidgetContents( $widget ), {
3112
- filter: "1",
3113
- type: "visual",
3114
- panels_info: panels_info
3115
- } ) );
3116
- return true;
3117
- } );
3118
- } );
3119
- } );
3120
-
3121
- // Remove all the Page Builder content
3122
- $html.find('.panel-layout').remove();
3123
- $html.find('style[data-panels-style-for-post]').remove();
3124
-
3125
- // If there's anything left, add it to an editor widget at the end of panels_data
3126
- if( $html.html().replace(/^\s+|\s+$/gm,'').length ) {
3127
- panels_data.grids.push( {
3128
- cells: 1,
3129
- style: {},
3130
- } );
3131
- panels_data.grid_cells.push( {
3132
- grid: panels_data.grids.length - 1,
3133
- weight: 1,
3134
- } );
3135
- panels_data.widgets.push( {
3136
- filter: "1",
3137
- text: $html.html().replace(/^\s+|\s+$/gm,''),
3138
- title: "",
3139
- type: "visual",
3140
- panels_info: {
3141
- class: editorClass,
3142
- raw: false,
3143
- grid: panels_data.grids.length - 1,
3144
- cell: 0
3145
- }
3146
- } );
3147
- }
3148
-
3149
- return panels_data;
3150
- }
3151
- else {
3152
- // This is probably just old school post content
3153
- return {
3154
- grid_cells: [ { grid: 0, weight: 1 } ],
3155
- grids: [ { cells: 1 } ],
3156
- widgets: [
3157
- {
3158
- filter: "1",
3159
- text: html,
3160
- title: "",
3161
- type: "visual",
3162
- panels_info: {
3163
- class: editorClass,
3164
- raw: false,
3165
- grid: 0,
3166
- cell: 0
3167
- }
3168
- }
3169
- ]
3170
- };
3171
- }
3172
- }
3173
- } );
3174
-
3175
- },{}],18:[function(require,module,exports){
3176
- module.exports = Backbone.Model.extend( {
3177
- /* A collection of widgets */
3178
- widgets: {},
3179
-
3180
- /* The row this model belongs to */
3181
- row: null,
3182
-
3183
- defaults: {
3184
- weight: 0,
3185
- style: {}
3186
- },
3187
-
3188
- indexes: null,
3189
-
3190
- /**
3191
- * Set up the cell model
3192
- */
3193
- initialize: function () {
3194
- this.set( 'widgets', new panels.collection.widgets() );
3195
- this.on( 'destroy', this.onDestroy, this );
3196
- },
3197
-
3198
- /**
3199
- * Triggered when we destroy a cell
3200
- */
3201
- onDestroy: function () {
3202
- // Destroy all the widgets
3203
- _.invoke( this.get('widgets').toArray(), 'destroy' );
3204
- this.get('widgets').reset();
3205
- },
3206
-
3207
- /**
3208
- * Create a clone of the cell, along with all its widgets
3209
- */
3210
- clone: function ( row, cloneOptions ) {
3211
- if ( _.isUndefined( row ) ) {
3212
- row = this.row;
3213
- }
3214
- cloneOptions = _.extend( {cloneWidgets: true}, cloneOptions );
3215
-
3216
- var clone = new this.constructor( this.attributes );
3217
- clone.set( 'collection', row.get('cells'), {silent: true} );
3218
- clone.row = row;
3219
-
3220
- if ( cloneOptions.cloneWidgets ) {
3221
- // Now we're going add all the widgets that belong to this, to the clone
3222
- this.get('widgets').each( function ( widget ) {
3223
- clone.get('widgets').add( widget.clone( clone, cloneOptions ), {silent: true} );
3224
- } );
3225
- }
3226
-
3227
- return clone;
3228
- }
3229
-
3230
- } );
3231
-
3232
- },{}],19:[function(require,module,exports){
3233
- module.exports = Backbone.Model.extend( {
3234
- defaults: {
3235
- text: '',
3236
- data: '',
3237
- time: null,
3238
- count: 1
3239
- }
3240
- } );
3241
-
3242
- },{}],20:[function(require,module,exports){
3243
- module.exports = Backbone.Model.extend( {
3244
- /* The builder model */
3245
- builder: null,
3246
-
3247
- defaults: {
3248
- style: {}
3249
- },
3250
-
3251
- indexes: null,
3252
-
3253
- /**
3254
- * Initialize the row model
3255
- */
3256
- initialize: function () {
3257
- if ( _.isEmpty(this.get('cells') ) ) {
3258
- this.set('cells', new panels.collection.cells());
3259
- }
3260
- else {
3261
- // Make sure that the cells have this row set as their parent
3262
- this.get('cells').each( function( cell ){
3263
- cell.row = this;
3264
- }.bind( this ) );
3265
- }
3266
- this.on( 'destroy', this.onDestroy, this );
3267
- },
3268
-
3269
- /**
3270
- * Add cells to the model row
3271
- *
3272
- * @param newCells the updated collection of cell models
3273
- */
3274
- setCells: function ( newCells ) {
3275
- var currentCells = this.get('cells') || new panels.collection.cells();
3276
- var cellsToRemove = [];
3277
-
3278
- currentCells.each(function (cell, i) {
3279
- var newCell = newCells.at(i);
3280
- if(newCell) {
3281
- cell.set('weight', newCell.get('weight'));
3282
- } else {
3283
- var newParentCell = currentCells.at( newCells.length - 1 );
3284
-
3285
- // First move all the widgets to the new cell
3286
- var widgetsToMove = cell.get('widgets').models.slice();
3287
- for ( var j = 0; j < widgetsToMove.length; j++ ) {
3288
- widgetsToMove[j].moveToCell( newParentCell, { silent: false } );
3289
- }
3290
-
3291
- cellsToRemove.push(cell);
3292
- }
3293
- });
3294
-
3295
- _.each(cellsToRemove, function(cell) {
3296
- currentCells.remove(cell);
3297
- });
3298
-
3299
- if( newCells.length > currentCells.length) {
3300
- _.each(newCells.slice(currentCells.length, newCells.length), function (newCell) {
3301
- // TODO: make sure row and collection is set correctly when cell is created then we can just add new cells
3302
- newCell.set({collection: currentCells});
3303
- newCell.row = this;
3304
- currentCells.add(newCell);
3305
- }.bind(this));
3306
- }
3307
-
3308
- // Rescale the cells when we add or remove
3309
- this.reweightCells();
3310
- },
3311
-
3312
- /**
3313
- * Make sure that all the cell weights add up to 1
3314
- */
3315
- reweightCells: function () {
3316
- var totalWeight = 0;
3317
- var cells = this.get('cells');
3318
- cells.each( function ( cell ) {
3319
- totalWeight += cell.get( 'weight' );
3320
- } );
3321
-
3322
- cells.each( function ( cell ) {
3323
- cell.set( 'weight', cell.get( 'weight' ) / totalWeight );
3324
- } );
3325
-
3326
- // This is for the row view to hook into and resize
3327
- this.trigger( 'reweight_cells' );
3328
- },
3329
-
3330
- /**
3331
- * Triggered when the model is destroyed
3332
- */
3333
- onDestroy: function () {
3334
- // Also destroy all the cells
3335
- _.invoke( this.get('cells').toArray(), 'destroy' );
3336
- this.get('cells').reset();
3337
- },
3338
-
3339
- /**
3340
- * Create a clone of the row, along with all its cells
3341
- *
3342
- * @param {panels.model.builder} builder The builder model to attach this to.
3343
- *
3344
- * @return {panels.model.row} The cloned row.
3345
- */
3346
- clone: function ( builder ) {
3347
- if ( _.isUndefined( builder ) ) {
3348
- builder = this.builder;
3349
- }
3350
-
3351
- var clone = new this.constructor( this.attributes );
3352
- clone.set( 'collection', builder.get('rows'), {silent: true} );
3353
- clone.builder = builder;
3354
-
3355
- var cellClones = new panels.collection.cells();
3356
- this.get('cells').each( function ( cell ) {
3357
- cellClones.add( cell.clone( clone ), {silent: true} );
3358
- } );
3359
-
3360
- clone.set( 'cells', cellClones );
3361
-
3362
- return clone;
3363
- }
3364
- } );
3365
-
3366
- },{}],21:[function(require,module,exports){
3367
- /**
3368
- * Model for an instance of a widget
3369
- */
3370
- module.exports = Backbone.Model.extend( {
3371
-
3372
- cell: null,
3373
-
3374
- defaults: {
3375
- // The PHP Class of the widget
3376
- class: null,
3377
-
3378
- // Is this class missing? Missing widgets are a special case.
3379
- missing: false,
3380
-
3381
- // The values of the widget
3382
- values: {},
3383
-
3384
- // Have the current values been passed through the widgets update function
3385
- raw: false,
3386
-
3387
- // Visual style fields
3388
- style: {},
3389
-
3390
- read_only: false,
3391
- widget_id: '',
3392
- },
3393
-
3394
- indexes: null,
3395
-
3396
- initialize: function () {
3397
- var widgetClass = this.get( 'class' );
3398
- if ( _.isUndefined( panelsOptions.widgets[widgetClass] ) || ! panelsOptions.widgets[widgetClass].installed ) {
3399
- this.set( 'missing', true );
3400
- }
3401
- },
3402
-
3403
- /**
3404
- * @param field
3405
- * @returns {*}
3406
- */
3407
- getWidgetField: function ( field ) {
3408
- if ( _.isUndefined( panelsOptions.widgets[this.get( 'class' )] ) ) {
3409
- if ( field === 'title' || field === 'description' ) {
3410
- return panelsOptions.loc.missing_widget[field];
3411
- } else {
3412
- return '';
3413
- }
3414
- } else if ( this.has( 'label' ) && ! _.isEmpty( this.get( 'label' ) ) ) {
3415
- // Use the label instead of the actual widget title
3416
- return this.get( 'label' );
3417
- } else {
3418
- return panelsOptions.widgets[ this.get( 'class' ) ][ field ];
3419
- }
3420
- },
3421
-
3422
- /**
3423
- * Move this widget model to a new cell. Called by the views.
3424
- *
3425
- * @param panels.model.cell newCell
3426
- * @param object options The options passed to the
3427
- *
3428
- * @return boolean Indicating if the widget was moved into a different cell
3429
- */
3430
- moveToCell: function ( newCell, options, at ) {
3431
- options = _.extend( {
3432
- silent: true,
3433
- }, options );
3434
-
3435
- this.cell = newCell;
3436
- this.collection.remove( this, options );
3437
- newCell.get('widgets').add( this, _.extend( {
3438
- at: at
3439
- }, options ) );
3440
-
3441
- // This should be used by views to reposition everything.
3442
- this.trigger( 'move_to_cell', newCell, at );
3443
-
3444
- return this;
3445
- },
3446
-
3447
- /**
3448
- * This is basically a wrapper for set that checks if we need to trigger a change
3449
- */
3450
- setValues: function ( values ) {
3451
- var hasChanged = false;
3452
- if ( JSON.stringify( values ) !== JSON.stringify( this.get( 'values' ) ) ) {
3453
- hasChanged = true;
3454
- }
3455
-
3456
- this.set( 'values', values, {silent: true} );
3457
-
3458
- if ( hasChanged ) {
3459
- // We'll trigger our own change events.
3460
- // NB: Must include the model being changed (i.e. `this`) as a workaround for a bug in Backbone 1.2.3
3461
- this.trigger( 'change', this );
3462
- this.trigger( 'change:values' );
3463
- }
3464
- },
3465
-
3466
- /**
3467
- * Create a clone of this widget attached to the given cell.
3468
- *
3469
- * @param {panels.model.cell} cell The cell model we're attaching this widget clone to.
3470
- * @returns {panels.model.widget}
3471
- */
3472
- clone: function ( cell, options ) {
3473
- if ( _.isUndefined( cell ) ) {
3474
- cell = this.cell;
3475
- }
3476
-
3477
- var clone = new this.constructor( this.attributes );
3478
-
3479
- // Create a deep clone of the original values
3480
- var cloneValues = JSON.parse( JSON.stringify( this.get( 'values' ) ) );
3481
-
3482
- // We want to exclude any fields that start with _ from the clone. Assuming these are internal.
3483
- var cleanClone = function ( vals ) {
3484
- _.each( vals, function ( el, i ) {
3485
- if ( _.isString( i ) && i[0] === '_' ) {
3486
- delete vals[i];
3487
- }
3488
- else if ( _.isObject( vals[i] ) ) {
3489
- cleanClone( vals[i] );
3490
- }
3491
- } );
3492
-
3493
- return vals;
3494
- };
3495
- cloneValues = cleanClone( cloneValues );
3496
-
3497
- if ( this.get( 'class' ) === "SiteOrigin_Panels_Widgets_Layout" ) {
3498
- // Special case of this being a layout widget, it needs a new ID
3499
- cloneValues.builder_id = Math.random().toString( 36 ).substr( 2 );
3500
- }
3501
-
3502
- clone.set( 'widget_id', '' );
3503
- clone.set( 'values', cloneValues, {silent: true} );
3504
- clone.set( 'collection', cell.get('widgets'), {silent: true} );
3505
- clone.cell = cell;
3506
-
3507
- // This is used to force a form reload later on
3508
- clone.isDuplicate = true;
3509
-
3510
- return clone;
3511
- },
3512
-
3513
- /**
3514
- * Gets the value that makes most sense as the title.
3515
- */
3516
- getTitle: function () {
3517
- var widgetData = panelsOptions.widgets[this.get( 'class' )];
3518
-
3519
- if ( _.isUndefined( widgetData ) ) {
3520
- return this.get( 'class' ).replace( /_/g, ' ' );
3521
- }
3522
- else if ( ! _.isUndefined( widgetData.panels_title ) ) {
3523
- // This means that the widget has told us which field it wants us to use as a title
3524
- if ( widgetData.panels_title === false ) {
3525
- return panelsOptions.widgets[this.get( 'class' )].description;
3526
- }
3527
- }
3528
-
3529
- var values = this.get( 'values' );
3530
-
3531
- // Create a list of fields to check for a title
3532
- var titleFields = ['title', 'text'];
3533
-
3534
- for ( var k in values ) {
3535
- if ( values.hasOwnProperty( k ) ) {
3536
- titleFields.push( k );
3537
- }
3538
- }
3539
-
3540
- titleFields = _.uniq( titleFields );
3541
-
3542
- for ( var i in titleFields ) {
3543
- if (
3544
- ! _.isUndefined( values[titleFields[i]] ) &&
3545
- _.isString( values[titleFields[i]] ) &&
3546
- values[titleFields[i]] !== '' &&
3547
- values[titleFields[i]] !== 'on' &&
3548
- titleFields[i][0] !== '_' && ! jQuery.isNumeric( values[titleFields[i]] )
3549
- ) {
3550
- var title = values[titleFields[i]];
3551
- title = title.replace( /<\/?[^>]+(>|$)/g, "" );
3552
- var parts = title.split( " " );
3553
- parts = parts.slice( 0, 20 );
3554
- return parts.join( ' ' );
3555
- }
3556
- }
3557
-
3558
- // If we still have nothing, then just return the widget description
3559
- return this.getWidgetField( 'description' );
3560
- }
3561
-
3562
- } );
3563
-
3564
- },{}],22:[function(require,module,exports){
3565
- var panels = window.panels, $ = jQuery;
3566
-
3567
- module.exports = Backbone.View.extend( {
3568
- wrapperTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-context-menu' ).html() ) ),
3569
- sectionTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-context-menu-section' ).html() ) ),
3570
-
3571
- contexts: [],
3572
- active: false,
3573
-
3574
- events: {
3575
- 'keyup .so-search-wrapper input': 'searchKeyUp'
3576
- },
3577
-
3578
- /**
3579
- * Intialize the context menu
3580
- */
3581
- initialize: function () {
3582
- this.listenContextMenu();
3583
- this.render();
3584
- this.attach();
3585
- },
3586
-
3587
- /**
3588
- * Listen for the right click context menu
3589
- */
3590
- listenContextMenu: function () {
3591
- var thisView = this;
3592
-
3593
- $( window ).on( 'contextmenu', function ( e ) {
3594
- if ( thisView.active && ! thisView.isOverEl( thisView.$el, e ) ) {
3595
- thisView.closeMenu();
3596
- thisView.active = false;
3597
- e.preventDefault();
3598
- return false;
3599
- }
3600
-
3601
- if ( thisView.active ) {
3602
- // Lets not double up on the context menu
3603
- return true;
3604
- }
3605
-
3606
- // Other components should listen to activate_context
3607
- thisView.active = false;
3608
- thisView.trigger( 'activate_context', e, thisView );
3609
-
3610
- if ( thisView.active ) {
3611
- // We don't want the default event to happen.
3612
- e.preventDefault();
3613
-
3614
- thisView.openMenu( {
3615
- left: e.pageX,
3616
- top: e.pageY
3617
- } );
3618
- }
3619
- } );
3620
- },
3621
-
3622
- render: function () {
3623
- this.setElement( this.wrapperTemplate() );
3624
- },
3625
-
3626
- attach: function () {
3627
- this.$el.appendTo( 'body' );
3628
- },
3629
-
3630
- /**
3631
- * Display the actual context menu.
3632
- *
3633
- * @param position
3634
- */
3635
- openMenu: function ( position ) {
3636
- this.trigger( 'open_menu' );
3637
-
3638
- // Start listening for situations when we should close the menu
3639
- $( window ).on( 'keyup', {menu: this}, this.keyboardListen );
3640
- $( window ).on( 'click', {menu: this}, this.clickOutsideListen );
3641
-
3642
- // Set the maximum height of the menu
3643
- this.$el.css( 'max-height', $( window ).height() - 20 );
3644
-
3645
- // Correct the left position
3646
- if ( position.left + this.$el.outerWidth() + 10 >= $( window ).width() ) {
3647
- position.left = $( window ).width() - this.$el.outerWidth() - 10;
3648
- }
3649
- if ( position.left <= 0 ) {
3650
- position.left = 10;
3651
- }
3652
-
3653
- // Check top position
3654
- if ( position.top + this.$el.outerHeight() - $( window ).scrollTop() + 10 >= $( window ).height() ) {
3655
- position.top = $( window ).height() + $( window ).scrollTop() - this.$el.outerHeight() - 10;
3656
- }
3657
- if ( position.left <= 0 ) {
3658
- position.left = 10;
3659
- }
3660
-
3661
- // position the contextual menu
3662
- this.$el.css( {
3663
- left: position.left + 1,
3664
- top: position.top + 1
3665
- } ).show();
3666
- this.$( '.so-search-wrapper input' ).focus();
3667
- },
3668
-
3669
- closeMenu: function () {
3670
- this.trigger( 'close_menu' );
3671
-
3672
- // Stop listening for situations when we should close the menu
3673
- $( window ).off( 'keyup', this.keyboardListen );
3674
- $( window ).off( 'click', this.clickOutsideListen );
3675
-
3676
- this.active = false;
3677
- this.$el.empty().hide();
3678
- },
3679
-
3680
- /**
3681
- * Keyboard events handler
3682
- */
3683
- keyboardListen: function ( e ) {
3684
- var menu = e.data.menu;
3685
-
3686
- switch ( e.which ) {
3687
- case 27:
3688
- menu.closeMenu();
3689
- break;
3690
- }
3691
- },
3692
-
3693
- /**
3694
- * Listen for a click outside the menu to close it.
3695
- * @param e
3696
- */
3697
- clickOutsideListen: function ( e ) {
3698
- var menu = e.data.menu;
3699
- if ( e.which !== 3 && menu.$el.is( ':visible' ) && ! menu.isOverEl( menu.$el, e ) ) {
3700
- menu.closeMenu();
3701
- }
3702
- },
3703
-
3704
- /**
3705
- * Add a new section to the contextual menu.
3706
- *
3707
- * @param settings
3708
- * @param items
3709
- * @param callback
3710
- */
3711
- addSection: function ( id, settings, items, callback ) {
3712
- var thisView = this;
3713
- settings = _.extend( {
3714
- display: 5,
3715
- defaultDisplay: false,
3716
- search: true,
3717
-
3718
- // All the labels
3719
- sectionTitle: '',
3720
- searchPlaceholder: '',
3721
-
3722
- // This is the key to be used in items for the title. Makes it easier to list objects
3723
- titleKey: 'title'
3724
- }, settings );
3725
-
3726
- // Create the new section
3727
- var section = $( this.sectionTemplate( {
3728
- settings: settings,
3729
- items: items
3730
- } ) ).attr( 'id', 'panels-menu-section-' + id );
3731
- this.$el.append( section );
3732
-
3733
- section.find( '.so-item:not(.so-confirm)' ).click( function () {
3734
- var $$ = $( this );
3735
- callback( $$.data( 'key' ) );
3736
- thisView.closeMenu();
3737
- } );
3738
-
3739
- section.find( '.so-item.so-confirm' ).click( function () {
3740
- var $$ = $( this );
3741
-
3742
- if ( $$.hasClass( 'so-confirming' ) ) {
3743
- callback( $$.data( 'key' ) );
3744
- thisView.closeMenu();
3745
- return;
3746
- }
3747
-
3748
- $$
3749
- .data( 'original-text', $$.html() )
3750
- .addClass( 'so-confirming' )
3751
- .html( '<span class="dashicons dashicons-yes"></span> ' + panelsOptions.loc.dropdown_confirm );
3752
-
3753
- setTimeout( function () {
3754
- $$.removeClass( 'so-confirming' );
3755
- $$.html( $$.data( 'original-text' ) );
3756
- }, 2500 );
3757
- } );
3758
-
3759
- section.data( 'settings', settings ).find( '.so-search-wrapper input' ).trigger( 'keyup' );
3760
-
3761
- this.active = true;
3762
- },
3763
-
3764
- /**
3765
- * Check if a section exists in the current menu.
3766
- *
3767
- * @param id
3768
- * @returns {boolean}
3769
- */
3770
- hasSection: function( id ){
3771
- return this.$el.find( '#panels-menu-section-' + id ).length > 0;
3772
- },
3773
-
3774
- /**
3775
- * Handle searching inside a section.
3776
- *
3777
- * @param e
3778
- * @returns {boolean}
3779
- */
3780
- searchKeyUp: function ( e ) {
3781
- var
3782
- $$ = $( e.currentTarget ),
3783
- section = $$.closest( '.so-section' ),
3784
- settings = section.data( 'settings' );
3785
-
3786
- if ( e.which === 38 || e.which === 40 ) {
3787
- // First, lets check if this is an up, down or enter press
3788
- var
3789
- items = section.find( 'ul li:visible' ),
3790
- activeItem = items.filter( '.so-active' ).eq( 0 );
3791
-
3792
- if ( activeItem.length ) {
3793
- items.removeClass( 'so-active' );
3794
-
3795
- var activeIndex = items.index( activeItem );
3796
-
3797
- if ( e.which === 38 ) {
3798
- if ( activeIndex - 1 < 0 ) {
3799
- activeItem = items.last();
3800
- } else {
3801
- activeItem = items.eq( activeIndex - 1 );
3802
- }
3803
- }
3804
- else if ( e.which === 40 ) {
3805
- if ( activeIndex + 1 >= items.length ) {
3806
- activeItem = items.first();
3807
- } else {
3808
- activeItem = items.eq( activeIndex + 1 );
3809
- }
3810
- }
3811
- }
3812
- else if ( e.which === 38 ) {
3813
- activeItem = items.last();
3814
- }
3815
- else if ( e.which === 40 ) {
3816
- activeItem = items.first();
3817
- }
3818
-
3819
- activeItem.addClass( 'so-active' );
3820
- return false;
3821
- }
3822
- if ( e.which === 13 ) {
3823
- if ( section.find( 'ul li:visible' ).length === 1 ) {
3824
- // We'll treat a single visible item as active when enter is clicked
3825
- section.find( 'ul li:visible' ).trigger( 'click' );
3826
- return false;
3827
- }
3828
- section.find( 'ul li.so-active:visible' ).trigger( 'click' );
3829
- return false;
3830
- }
3831
-
3832
- if ( $$.val() === '' ) {
3833
- // We'll display the defaultDisplay items
3834
- if ( settings.defaultDisplay ) {
3835
- section.find( '.so-item' ).hide();
3836
- for ( var i = 0; i < settings.defaultDisplay.length; i ++ ) {
3837
- section.find( '.so-item[data-key="' + settings.defaultDisplay[i] + '"]' ).show();
3838
- }
3839
- } else {
3840
- // We'll just display all the items
3841
- section.find( '.so-item' ).show();
3842
- }
3843
- } else {
3844
- section.find( '.so-item' ).hide().each( function () {
3845
- var item = $( this );
3846
- if ( item.html().toLowerCase().indexOf( $$.val().toLowerCase() ) !== - 1 ) {
3847
- item.show();
3848
- }
3849
- } );
3850
- }
3851
-
3852
- // Now, we'll only show the first settings.display visible items
3853
- section.find( '.so-item:visible:gt(' + (
3854
- settings.display - 1
3855
- ) + ')' ).hide();
3856
-
3857
-
3858
- if ( section.find( '.so-item:visible' ).length === 0 && $$.val() !== '' ) {
3859
- section.find( '.so-no-results' ).show();
3860
- } else {
3861
- section.find( '.so-no-results' ).hide();
3862
- }
3863
- },
3864
-
3865
- /**
3866
- * Check if the given mouse event is over the element
3867
- * @param el
3868
- * @param event
3869
- */
3870
- isOverEl: function ( el, event ) {
3871
- var elPos = [
3872
- [el.offset().left, el.offset().top],
3873
- [el.offset().left + el.outerWidth(), el.offset().top + el.outerHeight()]
3874
- ];
3875
-
3876
- // Return if this event is over the given element
3877
- return (
3878
- event.pageX >= elPos[0][0] && event.pageX <= elPos[1][0] &&
3879
- event.pageY >= elPos[0][1] && event.pageY <= elPos[1][1]
3880
- );
3881
- }
3882
-
3883
- } );
3884
-
3885
- },{}],23:[function(require,module,exports){
3886
- var panels = window.panels, $ = jQuery;
3887
-
3888
- module.exports = Backbone.View.extend( {
3889
-
3890
- // Config options
3891
- config: {},
3892
-
3893
- template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder' ).html() ) ),
3894
- dialogs: {},
3895
- rowsSortable: null,
3896
- dataField: false,
3897
- currentData: '',
3898
-
3899
- attachedToEditor: false,
3900
- attachedVisible: false,
3901
- liveEditor: undefined,
3902
- menu: false,
3903
-
3904
- activeCell: null,
3905
-
3906
- events: {
3907
- 'click .so-tool-button.so-widget-add': 'displayAddWidgetDialog',
3908
- 'click .so-tool-button.so-row-add': 'displayAddRowDialog',
3909
- 'click .so-tool-button.so-prebuilt-add': 'displayAddPrebuiltDialog',
3910
- 'click .so-tool-button.so-history': 'displayHistoryDialog',
3911
- 'click .so-tool-button.so-live-editor': 'displayLiveEditor'
3912
- },
3913
-
3914
- /* A row collection */
3915
- rows: null,
3916
-
3917
- /**
3918
- * Initialize the builder
3919
- */
3920
- initialize: function ( options ) {
3921
- var builder = this;
3922
-
3923
- this.config = _.extend( {
3924
- loadLiveEditor: false,
3925
- builderSupports: {}
3926
- }, options.config );
3927
-
3928
- // These are the actions that a user can perform in the builder
3929
- this.config.builderSupports = _.extend( {
3930
- addRow: true,
3931
- editRow: true,
3932
- deleteRow: true,
3933
- moveRow: true,
3934
- addWidget: true,
3935
- editWidget: true,
3936
- deleteWidget: true,
3937
- moveWidget: true,
3938
- prebuilt: true,
3939
- history: true,
3940
- liveEditor: true,
3941
- revertToEditor: true
3942
- }, this.config.builderSupports );
3943
-
3944
- // Automatically load the live editor as soon as it's ready
3945
- if ( options.config.loadLiveEditor ) {
3946
- this.on( 'builder_live_editor_added', function () {
3947
- this.displayLiveEditor();
3948
- } );
3949
- }
3950
-
3951
- // Now lets create all the dialog boxes that the main builder interface uses
3952
- this.dialogs = {
3953
- widgets: new panels.dialog.widgets(),
3954
- row: new panels.dialog.row(),
3955
- prebuilt: new panels.dialog.prebuilt()
3956
- };
3957
-
3958
- // Set the builder for each dialog and render it.
3959
- _.each( this.dialogs, function ( p, i, d ) {
3960
- d[ i ].setBuilder( builder );
3961
- } );
3962
-
3963
- this.dialogs.row.setRowDialogType( 'create' );
3964
-
3965
- // This handles a new row being added to the collection - we'll display it in the interface
3966
- this.listenTo( this.model.get( 'rows' ), 'add', this.onAddRow );
3967
-
3968
- // Reflow the entire builder when ever the
3969
- $( window ).resize( function ( e ) {
3970
- if ( e.target === window ) {
3971
- builder.trigger( 'builder_resize' );
3972
- }
3973
- } );
3974
-
3975
- // When the data changes in the model, store it in the field
3976
- this.listenTo( this.model, 'change:data load_panels_data', this.storeModelData );
3977
- this.listenTo( this.model, 'change:data load_panels_data', this.toggleWelcomeDisplay );
3978
-
3979
- // Handle a content change
3980
- this.on( 'content_change', this.handleContentChange, this );
3981
- this.on( 'display_builder', this.handleDisplayBuilder, this );
3982
- this.on( 'hide_builder', this.handleHideBuilder, this );
3983
- this.on( 'builder_rendered builder_resize', this.handleBuilderSizing, this );
3984
-
3985
- this.on( 'display_builder', this.wrapEditorExpandAdjust, this );
3986
-
3987
- // Create the context menu for this builder
3988
- this.menu = new panels.utils.menu( {} );
3989
- this.listenTo( this.menu, 'activate_context', this.activateContextMenu )
3990
-
3991
- if ( this.config.loadOnAttach ) {
3992
- this.on( 'builder_attached_to_editor', function () {
3993
- this.displayAttachedBuilder( { confirm: false } );
3994
- }, this );
3995
- }
3996
-
3997
-
3998
- return this;
3999
- },
4000
-
4001
- /**
4002
- * Render the builder interface.
4003
- *
4004
- * @return {panels.view.builder}
4005
- */
4006
- render: function () {
4007
- // this.$el.html( this.template() );
4008
- this.setElement( this.template() );
4009
- this.$el
4010
- .attr( 'id', 'siteorigin-panels-builder-' + this.cid )
4011
- .addClass( 'so-builder-container' );
4012
-
4013
- this.trigger( 'builder_rendered' );
4014
-
4015
- return this;
4016
- },
4017
-
4018
- /**
4019
- * Attach the builder to the given container
4020
- *
4021
- * @param container
4022
- * @returns {panels.view.builder}
4023
- */
4024
- attach: function ( options ) {
4025
-
4026
- options = _.extend( {
4027
- container: false,
4028
- dialog: false
4029
- }, options );
4030
-
4031
- if ( options.dialog ) {
4032
- // We're going to add this to a dialog
4033
- this.dialog = new panels.dialog.builder();
4034
- this.dialog.builder = this;
4035
- } else {
4036
- // Attach this in the standard way
4037
- this.$el.appendTo( options.container );
4038
- this.metabox = options.container.closest( '.postbox' );
4039
- this.initSortable();
4040
- this.trigger( 'attached_to_container', options.container );
4041
- }
4042
-
4043
- this.trigger( 'builder_attached' );
4044
-
4045
- // Add support for components we have
4046
-
4047
- if ( this.supports( 'liveEditor' ) ) {
4048
- this.addLiveEditor();
4049
- }
4050
- if ( this.supports( 'history' ) ) {
4051
- this.addHistoryBrowser();
4052
- }
4053
-
4054
- // Hide toolbar buttons we don't support
4055
- var toolbar = this.$( '.so-builder-toolbar' );
4056
- var welcomeMessageContainer = this.$( '.so-panels-welcome-message' );
4057
- var welcomeMessage = panelsOptions.loc.welcomeMessage;
4058
-
4059
- var supportedItems = [];
4060
-
4061
- if ( !this.supports( 'addWidget' ) ) {
4062
- toolbar.find( '.so-widget-add' ).hide();
4063
- } else {
4064
- supportedItems.push( welcomeMessage.addWidgetButton );
4065
- }
4066
- if ( !this.supports( 'addRow' ) ) {
4067
- toolbar.find( '.so-row-add' ).hide();
4068
- } else {
4069
- supportedItems.push( welcomeMessage.addRowButton );
4070
- }
4071
- if ( !this.supports( 'prebuilt' ) ) {
4072
- toolbar.find( '.so-prebuilt-add' ).hide();
4073
- } else {
4074
- supportedItems.push( welcomeMessage.addPrebuiltButton );
4075
- }
4076
-
4077
- var msg = '';
4078
- if ( supportedItems.length === 3 ) {
4079
- msg = welcomeMessage.threeEnabled;
4080
- } else if ( supportedItems.length === 2 ) {
4081
- msg = welcomeMessage.twoEnabled;
4082
- } else if ( supportedItems.length === 1 ) {
4083
- msg = welcomeMessage.oneEnabled;
4084
- } else if ( supportedItems.length === 0 ) {
4085
- msg = welcomeMessage.addingDisabled;
4086
- }
4087
-
4088
- var resTemplate = _.template( panels.helpers.utils.processTemplate( msg ) );
4089
- var msgHTML = resTemplate( { items: supportedItems } ) + ' ' + welcomeMessage.docsMessage;
4090
- welcomeMessageContainer.find( '.so-message-wrapper' ).html( msgHTML );
4091
-
4092
- return this;
4093
- },
4094
-
4095
- /**
4096
- * This will move the Page Builder meta box into the editor if we're in the post/page edit interface.
4097
- *
4098
- * @returns {panels.view.builder}
4099
- */
4100
- attachToEditor: function () {
4101
- if ( this.config.editorType !== 'tinyMCE' ) {
4102
- return this;
4103
- }
4104
-
4105
- this.attachedToEditor = true;
4106
- var metabox = this.metabox;
4107
- var thisView = this;
4108
-
4109
- // Handle switching between the page builder and other tabs
4110
- $( '#wp-content-wrap .wp-editor-tabs' )
4111
- .find( '.wp-switch-editor' )
4112
- .click( function ( e ) {
4113
- e.preventDefault();
4114
- $( '#wp-content-editor-container' ).show();
4115
-
4116
- // metabox.hide();
4117
- $( '#wp-content-wrap' ).removeClass( 'panels-active' );
4118
- $( '#content-resize-handle' ).show();
4119
-
4120
- // Make sure the word count is visible
4121
- thisView.trigger( 'hide_builder' );
4122
- } ).end()
4123
- .append(
4124
- $( '<button type="button" id="content-panels" class="hide-if-no-js wp-switch-editor switch-panels">' + metabox.find( '.hndle span' ).html() + '</button>' )
4125
- .click( function ( e ) {
4126
- if ( thisView.displayAttachedBuilder( { confirm: true } ) ) {
4127
- e.preventDefault();
4128
- }
4129
- } )
4130
- );
4131
-
4132
- // Switch back to the standard editor
4133
- if ( this.supports( 'revertToEditor' ) ) {
4134
- metabox.find( '.so-switch-to-standard' ).click( function ( e ) {
4135
- e.preventDefault();
4136
-
4137
- if ( !confirm( panelsOptions.loc.confirm_stop_builder ) ) {
4138
- return;
4139
- }
4140
-
4141
- // User is switching to the standard visual editor
4142
- thisView.addHistoryEntry( 'back_to_editor' );
4143
- thisView.model.loadPanelsData( false );
4144
-
4145
- // Switch back to the standard editor
4146
- $( '#wp-content-wrap' ).show();
4147
- metabox.hide();
4148
-
4149
- // Resize to trigger reflow of WordPress editor stuff
4150
- $( window ).resize();
4151
-
4152
- thisView.attachedVisible = false;
4153
- thisView.trigger( 'hide_builder' );
4154
- } ).show();
4155
- }
4156
-
4157
- // Move the panels box into a tab of the content editor
4158
- metabox.insertAfter( '#wp-content-wrap' ).hide().addClass( 'attached-to-editor' );
4159
-
4160
- // Switch to the Page Builder interface as soon as we load the page if there are widgets or the normal editor
4161
- // isn't supported.
4162
- var data = this.model.get( 'data' );
4163
- if ( !_.isEmpty( data.widgets ) || !_.isEmpty( data.grids ) || !this.supports( 'revertToEditor' ) ) {
4164
- this.displayAttachedBuilder( { confirm: false } );
4165
- }
4166
-
4167
- // We will also make this sticky if its attached to an editor.
4168
- var stickToolbar = function () {
4169
- var toolbar = thisView.$( '.so-builder-toolbar' );
4170
-
4171
- if ( thisView.$el.hasClass( 'so-display-narrow' ) ) {
4172
- // In this case, we don't want to stick the toolbar.
4173
- toolbar.css( {
4174
- top: 0,
4175
- left: 0,
4176
- width: '100%',
4177
- position: 'absolute'
4178
- } );
4179
- thisView.$el.css( 'padding-top', toolbar.outerHeight() );
4180
- return;
4181
- }
4182
-
4183
- var newTop = $( window ).scrollTop() - thisView.$el.offset().top;
4184
-
4185
- if ( $( '#wpadminbar' ).css( 'position' ) === 'fixed' ) {
4186
- newTop += $( '#wpadminbar' ).outerHeight();
4187
- }
4188
-
4189
- var limits = {
4190
- top: 0,
4191
- bottom: thisView.$el.outerHeight() - toolbar.outerHeight() + 20
4192
- };
4193
-
4194
- if ( newTop > limits.top && newTop < limits.bottom ) {
4195
- if ( toolbar.css( 'position' ) !== 'fixed' ) {
4196
- // The toolbar needs to stick to the top, over the interface
4197
- toolbar.css( {
4198
- top: $( '#wpadminbar' ).outerHeight(),
4199
- left: thisView.$el.offset().left,
4200
- width: thisView.$el.outerWidth(),
4201
- position: 'fixed'
4202
- } );
4203
- }
4204
- } else {
4205
- // The toolbar needs to be at the top or bottom of the interface
4206
- toolbar.css( {
4207
- top: Math.min( Math.max( newTop, 0 ), thisView.$el.outerHeight() - toolbar.outerHeight() + 20 ),
4208
- left: 0,
4209
- width: '100%',
4210
- position: 'absolute'
4211
- } );
4212
- }
4213
-
4214
- thisView.$el.css( 'padding-top', toolbar.outerHeight() );
4215
- };
4216
-
4217
- this.on( 'builder_resize', stickToolbar, this );
4218
- $( document ).scroll( stickToolbar );
4219
- stickToolbar();
4220
-
4221
- this.trigger( 'builder_attached_to_editor' );
4222
-
4223
- return this;
4224
- },
4225
-
4226
- /**
4227
- * Display the builder interface when attached to a WordPress editor
4228
- */
4229
- displayAttachedBuilder: function ( options ) {
4230
- options = _.extend( {
4231
- confirm: true
4232
- }, options );
4233
-
4234
- // Switch to the Page Builder interface
4235
-
4236
- if ( options.confirm ) {
4237
- var editor = typeof tinyMCE !== 'undefined' ? tinyMCE.get( 'content' ) : false;
4238
- var editorContent = ( editor && _.isFunction( editor.getContent ) ) ? editor.getContent() : $( 'textarea#content' ).val();
4239
-
4240
- if ( editorContent !== '' && !confirm( panelsOptions.loc.confirm_use_builder ) ) {
4241
- return false;
4242
- }
4243
- }
4244
-
4245
- // Hide the standard content editor
4246
- $( '#wp-content-wrap' ).hide();
4247
-
4248
-
4249
- $( '#editor-expand-toggle' ).on( 'change.editor-expand', function () {
4250
- if ( !$( this ).prop( 'checked' ) ) {
4251
- $( '#wp-content-wrap' ).hide();
4252
- }
4253
- } );
4254
-
4255
- // Show page builder and the inside div
4256
- this.metabox.show().find( '> .inside' ).show();
4257
-
4258
- // Triggers full refresh
4259
- $( window ).resize();
4260
- $( document ).scroll();
4261
-
4262
- // Make sure the word count is visible
4263
- this.attachedVisible = true;
4264
- this.trigger( 'display_builder' );
4265
-
4266
- return true;
4267
- },
4268
-
4269
- /**
4270
- * Initialize the row sortables
4271
- */
4272
- initSortable: function () {
4273
- if ( !this.supports( 'moveRow' ) ) {
4274
- return this;
4275
- }
4276
-
4277
- var builderView = this;
4278
- var builderID = builderView.$el.attr( 'id' );
4279
-
4280
- // Create the sortable for the rows
4281
- this.rowsSortable = this.$( '.so-rows-container' ).sortable( {
4282
- appendTo: '#wpwrap',
4283
- items: '.so-row-container',
4284
- handle: '.so-row-move',
4285
- // For the block editor, where it's possible to have multiple Page Builder blocks on a page.
4286
- // Also specify builderID when not in the block editor to prevent being able to drop rows from builder in a dialog
4287
- // into builder on the page under the dialog.
4288
- connectWith: '#' + builderID + '.so-rows-container,.block-editor .so-rows-container',
4289
- axis: 'y',
4290
- tolerance: 'pointer',
4291
- scroll: false,
4292
- remove: function ( e, ui ) {
4293
- builderView.model.get( 'rows' ).remove(
4294
- $( ui.item ).data( 'view' ).model,
4295
- { silent: true }
4296
- );
4297
- builderView.model.refreshPanelsData();
4298
- },
4299
- receive: function ( e, ui ) {
4300
- builderView.model.get( 'rows' ).add(
4301
- $( ui.item ).data( 'view' ).model,
4302
- { silent: true, at: $( ui.item ).index() }
4303
- );
4304
- builderView.model.refreshPanelsData();
4305
- },
4306
- stop: function ( e, ui ) {
4307
- var $$ = $( ui.item ),
4308
- row = $$.data( 'view' ),
4309
- rows = builderView.model.get( 'rows' );
4310
-
4311
- // If this hasn't already been removed and added to a different builder.
4312
- if ( rows.get( row.model ) ) {
4313
- builderView.addHistoryEntry( 'row_moved' );
4314
-
4315
- rows.remove( row.model, {
4316
- 'silent': true
4317
- } );
4318
- rows.add( row.model, {
4319
- 'silent': true,
4320
- 'at': $$.index()
4321
- } );
4322
-
4323
- row.trigger( 'move', $$.index() );
4324
-
4325
- builderView.model.refreshPanelsData();
4326
- }
4327
- }
4328
- } );
4329
-
4330
- return this;
4331
- },
4332
-
4333
- /**
4334
- * Refresh the row sortable
4335
- */
4336
- refreshSortable: function () {
4337
- // Refresh the sortable to account for the new row
4338
- if ( !_.isNull( this.rowsSortable ) ) {
4339
- this.rowsSortable.sortable( 'refresh' );
4340
- }
4341
- },
4342
-
4343
- /**
4344
- * Set the field that's used to store the data
4345
- * @param field
4346
- * @param options
4347
- */
4348
- setDataField: function ( field, options ) {
4349
- options = _.extend( {
4350
- load: true
4351
- }, options );
4352
-
4353
- this.dataField = field;
4354
- this.dataField.data( 'builder', this );
4355
-
4356
- if ( options.load && field.val() !== '' ) {
4357
- var data = this.dataField.val();
4358
- try {
4359
- data = JSON.parse( data );
4360
- }
4361
- catch ( err ) {
4362
- console.log( "Failed to parse Page Builder layout data from supplied data field." );
4363
- data = {};
4364
- }
4365
-
4366
- this.setData( data );
4367
- }
4368
-
4369
- return this;
4370
- },
4371
-
4372
- /**
4373
- * Set the current panels data to be used.
4374
- *
4375
- * @param data
4376
- */
4377
- setData: function( data ) {
4378
- this.model.loadPanelsData( data );
4379
- this.currentData = data;
4380
- this.toggleWelcomeDisplay();
4381
- },
4382
-
4383
- /**
4384
- * Get the current panels data.
4385
- *
4386
- */
4387
- getData: function() {
4388
- return this.model.get( 'data' );
4389
- },
4390
-
4391
- /**
4392
- * Store the model data in the data html field set in this.setDataField.
4393
- */
4394
- storeModelData: function () {
4395
- var data = JSON.stringify( this.model.get( 'data' ) );
4396
-
4397
- if ( $( this.dataField ).val() !== data ) {
4398
- // If the data is different, set it and trigger a content_change event
4399
- $( this.dataField ).val( data );
4400
- $( this.dataField ).trigger( 'change' );
4401
- this.trigger( 'content_change' );
4402
- }
4403
- },
4404
-
4405
- /**
4406
- * HAndle the visual side of adding a new row to the builder.
4407
- *
4408
- * @param row
4409
- * @param collection
4410
- * @param options
4411
- */
4412
- onAddRow: function ( row, collection, options ) {
4413
- options = _.extend( { noAnimate: false }, options );
4414
- // Create a view for the row
4415
- var rowView = new panels.view.row( { model: row } );
4416
- rowView.builder = this;
4417
- rowView.render();
4418
-
4419
- // Attach the row elements to this builder
4420
- if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
4421
- // Insert this at the end of the widgets container
4422
- rowView.$el.appendTo( this.$( '.so-rows-container' ) );
4423
- } else {
4424
- // We need to insert this at a specific position
4425
- rowView.$el.insertAfter(
4426
- this.$( '.so-rows-container .so-row-container' ).eq( options.at - 1 )
4427
- );
4428
- }
4429
-
4430
- if ( options.noAnimate === false ) {
4431
- rowView.visualCreate();
4432
- }
4433
-
4434
- this.refreshSortable();
4435
- rowView.resize();
4436
- this.trigger( 'row_added' );
4437
- },
4438
-
4439
- /**
4440
- * Display the dialog to add a new widget.
4441
- *
4442
- * @returns {boolean}
4443
- */
4444
- displayAddWidgetDialog: function () {
4445
- this.dialogs.widgets.openDialog();
4446
- },
4447
-
4448
- /**
4449
- * Display the dialog to add a new row.
4450
- */
4451
- displayAddRowDialog: function () {
4452
- var row = new panels.model.row();
4453
- var cells = new panels.collection.cells( [ { weight: 0.5 }, { weight: 0.5 } ] );
4454
- cells.each( function ( cell ) {
4455
- cell.row = row;
4456
- } );
4457
- row.set( 'cells', cells );
4458
- row.builder = this.model;
4459
-
4460
- this.dialogs.row.setRowModel( row );
4461
- this.dialogs.row.openDialog();
4462
- },
4463
-
4464
- /**
4465
- * Display the dialog to add prebuilt layouts.
4466
- *
4467
- * @returns {boolean}
4468
- */
4469
- displayAddPrebuiltDialog: function () {
4470
- this.dialogs.prebuilt.openDialog();
4471
- },
4472
-
4473
- /**
4474
- * Display the history dialog.
4475
- *
4476
- * @returns {boolean}
4477
- */
4478
- displayHistoryDialog: function () {
4479
- this.dialogs.history.openDialog();
4480
- },
4481
-
4482
- /**
4483
- * Handle pasting a row into the builder.
4484
- */
4485
- pasteRowHandler: function () {
4486
- var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
4487
-
4488
- if ( !_.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
4489
- this.addHistoryEntry( 'row_pasted' );
4490
- pastedModel.builder = this.model;
4491
- this.model.get( 'rows' ).add( pastedModel, {
4492
- at: this.model.get( 'rows' ).indexOf( this.model ) + 1
4493
- } );
4494
- this.model.refreshPanelsData();
4495
- }
4496
- },
4497
-
4498
- /**
4499
- * Get the model for the currently selected cell
4500
- */
4501
- getActiveCell: function ( options ) {
4502
- options = _.extend( {
4503
- createCell: true,
4504
- }, options );
4505
-
4506
- if ( !this.model.get( 'rows' ).length ) {
4507
- // There aren't any rows yet
4508
- if ( options.createCell ) {
4509
- // Create a row with a single cell
4510
- this.model.addRow( {}, [ { weight: 1 } ], { noAnimate: true } );
4511
- } else {
4512
- return null;
4513
- }
4514
- }
4515
-
4516
- // Make sure the active cell isn't empty, and it's in a row that exists
4517
- var activeCell = this.activeCell;
4518
- if ( _.isEmpty( activeCell ) || this.model.get( 'rows' ).indexOf( activeCell.model.row ) === -1 ) {
4519
- return this.model.get( 'rows' ).last().get( 'cells' ).first();
4520
- } else {
4521
- return activeCell.model;
4522
- }
4523
- },
4524
-
4525
- /**
4526
- * Add a live editor to the builder
4527
- *
4528
- * @returns {panels.view.builder}
4529
- */
4530
- addLiveEditor: function () {
4531
- if ( _.isEmpty( this.config.liveEditorPreview ) ) {
4532
- return this;
4533
- }
4534
-
4535
- // Create the live editor and set the builder to this.
4536
- this.liveEditor = new panels.view.liveEditor( {
4537
- builder: this,
4538
- previewUrl: this.config.liveEditorPreview
4539
- } );
4540
-
4541
- // Display the live editor button in the toolbar
4542
- if ( this.liveEditor.hasPreviewUrl() ) {
4543
- this.$( '.so-builder-toolbar .so-live-editor' ).show();
4544
- }
4545
-
4546
- this.trigger( 'builder_live_editor_added' );
4547
-
4548
- return this;
4549
- },
4550
-
4551
- /**
4552
- * Show the current live editor
4553
- */
4554
- displayLiveEditor: function () {
4555
- if ( _.isUndefined( this.liveEditor ) ) {
4556
- return;
4557
- }
4558
-
4559
- this.liveEditor.open();
4560
- },
4561
-
4562
- /**
4563
- * Add the history browser.
4564
- *
4565
- * @return {panels.view.builder}
4566
- */
4567
- addHistoryBrowser: function () {
4568
- if ( _.isEmpty( this.config.liveEditorPreview ) ) {
4569
- return this;
4570
- }
4571
-
4572
- this.dialogs.history = new panels.dialog.history();
4573
- this.dialogs.history.builder = this;
4574
- this.dialogs.history.entries.builder = this.model;
4575
-
4576
- // Set the revert entry
4577
- this.dialogs.history.setRevertEntry( this.model );
4578
-
4579
- // Display the live editor button in the toolbar
4580
- this.$( '.so-builder-toolbar .so-history' ).show();
4581
- },
4582
-
4583
- /**
4584
- * Add an entry.
4585
- *
4586
- * @param text
4587
- * @param data
4588
- */
4589
- addHistoryEntry: function ( text, data ) {
4590
- if ( _.isUndefined( data ) ) {
4591
- data = null;
4592
- }
4593
-
4594
- if ( !_.isUndefined( this.dialogs.history ) ) {
4595
- this.dialogs.history.entries.addEntry( text, data );
4596
- }
4597
- },
4598
-
4599
- supports: function ( thing ) {
4600
-
4601
- if ( thing === 'rowAction' ) {
4602
- // Check if this supports any row action
4603
- return this.supports( 'addRow' ) || this.supports( 'editRow' ) || this.supports( 'deleteRow' );
4604
- } else if ( thing === 'widgetAction' ) {
4605
- // Check if this supports any widget action
4606
- return this.supports( 'addWidget' ) || this.supports( 'editWidget' ) || this.supports( 'deleteWidget' );
4607
- }
4608
-
4609
- return _.isUndefined( this.config.builderSupports[ thing ] ) ? false : this.config.builderSupports[ thing ];
4610
- },
4611
-
4612
- /**
4613
- * Handle a change of the content
4614
- */
4615
- handleContentChange: function () {
4616
-
4617
- // Make sure we actually need to copy content.
4618
- if ( panelsOptions.copy_content && this.attachedToEditor && this.$el.is( ':visible' ) ) {
4619
-
4620
- var panelsData = this.model.getPanelsData();
4621
- if ( !_.isEmpty( panelsData.widgets ) ) {
4622
- // We're going to create a copy of page builder content into the post content
4623
- $.post(
4624
- panelsOptions.ajaxurl,
4625
- {
4626
- action: 'so_panels_builder_content',
4627
- panels_data: JSON.stringify( panelsData ),
4628
- post_id: this.config.postId
4629
- },
4630
- function ( content ) {
4631
- if ( content !== '' ) {
4632
- this.updateEditorContent( content );
4633
- }
4634
- }.bind( this )
4635
- );
4636
- }
4637
- }
4638
- },
4639
-
4640
- /**
4641
- * Update editor content with the given content.
4642
- *
4643
- * @param content
4644
- */
4645
- updateEditorContent: function ( content ) {
4646
- // Switch back to the standard editor
4647
- if ( this.config.editorType !== 'tinyMCE' || typeof tinyMCE === 'undefined' || _.isNull( tinyMCE.get( "content" ) ) ) {
4648
- var $editor = $( this.config.editorId );
4649
- $editor.val( content ).trigger( 'change' ).trigger( 'keyup' );
4650
- } else {
4651
- var contentEd = tinyMCE.get( "content" );
4652
-
4653
- contentEd.setContent( content );
4654
-
4655
- contentEd.fire( 'change' );
4656
- contentEd.fire( 'keyup' );
4657
- }
4658
-
4659
- this.triggerYoastSeoChange();
4660
- },
4661
-
4662
- /**
4663
- * Trigger a change on Yoast SEO
4664
- */
4665
- triggerYoastSeoChange: function () {
4666
- if ( $( '#yoast_wpseo_focuskw_text_input' ).length ) {
4667
- var element = document.getElementById( 'yoast_wpseo_focuskw_text_input' ), event;
4668
-
4669
- if ( document.createEvent ) {
4670
- event = document.createEvent( "HTMLEvents" );
4671
- event.initEvent( "keyup", true, true );
4672
- } else {
4673
- event = document.createEventObject();
4674
- event.eventType = "keyup";
4675
- }
4676
-
4677
- event.eventName = "keyup";
4678
-
4679
- if ( document.createEvent ) {
4680
- element.dispatchEvent( event );
4681
- } else {
4682
- element.fireEvent( "on" + event.eventType, event );
4683
- }
4684
- }
4685
- },
4686
-
4687
- /**
4688
- * Handle displaying the builder
4689
- */
4690
- handleDisplayBuilder: function () {
4691
- var editor = typeof tinyMCE !== 'undefined' ? tinyMCE.get( 'content' ) : false;
4692
- var editorContent = ( editor && _.isFunction( editor.getContent ) ) ? editor.getContent() : $( 'textarea#content' ).val();
4693
-
4694
- if (
4695
- (
4696
- _.isEmpty( this.model.get( 'data' ) ) ||
4697
- ( _.isEmpty( this.model.get( 'data' ).widgets ) && _.isEmpty( this.model.get( 'data' ).grids ) )
4698
- ) &&
4699
- editorContent !== ''
4700
- ) {
4701
- var editorClass = panelsOptions.text_widget;
4702
- // There is a small chance a theme will have removed this, so check
4703
- if ( _.isEmpty( editorClass ) ) {
4704
- return;
4705
- }
4706
-
4707
- // Create the existing page content in a single widget
4708
- this.model.loadPanelsData( this.model.getPanelsDataFromHtml( editorContent, editorClass ) );
4709
- this.model.trigger( 'change' );
4710
- this.model.trigger( 'change:data' );
4711
- }
4712
-
4713
- $( '#post-status-info' ).addClass( 'for-siteorigin-panels' );
4714
- },
4715
-
4716
- handleHideBuilder: function () {
4717
- $( '#post-status-info' ).show().removeClass( 'for-siteorigin-panels' );
4718
- },
4719
-
4720
- wrapEditorExpandAdjust: function () {
4721
- try {
4722
- var events = ( $.hasData( window ) && $._data( window ) ).events.scroll,
4723
- event;
4724
-
4725
- for ( var i = 0; i < events.length; i++ ) {
4726
- if ( events[ i ].namespace === 'editor-expand' ) {
4727
- event = events[ i ];
4728
-
4729
- // Wrap the call
4730
- $( window ).unbind( 'scroll', event.handler );
4731
- $( window ).bind( 'scroll', function ( e ) {
4732
- if ( !this.attachedVisible ) {
4733
- event.handler( e );
4734
- }
4735
- }.bind( this ) );
4736
-
4737
- break;
4738
- }
4739
- }
4740
- }
4741
- catch ( e ) {
4742
- // We tried, we failed
4743
- return;
4744
- }
4745
- },
4746
-
4747
- /**
4748
- * Either add or remove the narrow class
4749
- * @returns {exports}
4750
- */
4751
- handleBuilderSizing: function () {
4752
- var width = this.$el.width();
4753
-
4754
- if ( !width ) {
4755
- return this;
4756
- }
4757
-
4758
- if ( width < 575 ) {
4759
- this.$el.addClass( 'so-display-narrow' );
4760
- } else {
4761
- this.$el.removeClass( 'so-display-narrow' );
4762
- }
4763
-
4764
- return this;
4765
- },
4766
-
4767
- /**
4768
- * Set the parent dialog for all the dialogs in this builder.
4769
- *
4770
- * @param text
4771
- * @param dialog
4772
- */
4773
- setDialogParents: function ( text, dialog ) {
4774
- _.each( this.dialogs, function ( p, i, d ) {
4775
- d[ i ].setParent( text, dialog );
4776
- } );
4777
-
4778
- // For any future dialogs
4779
- this.on( 'add_dialog', function ( newDialog ) {
4780
- newDialog.setParent( text, dialog );
4781
- }, this );
4782
- },
4783
-
4784
- /**
4785
- * This shows or hides the welcome display depending on whether there are any rows in the collection.
4786
- */
4787
- toggleWelcomeDisplay: function () {
4788
- if ( !this.model.get( 'rows' ).isEmpty() ) {
4789
- this.$( '.so-panels-welcome-message' ).hide();
4790
- } else {
4791
- this.$( '.so-panels-welcome-message' ).show();
4792
- }
4793
- },
4794
-
4795
- /**
4796
- * Activate the contextual menu
4797
- * @param e
4798
- * @param menu
4799
- */
4800
- activateContextMenu: function ( e, menu ) {
4801
- var builder = this;
4802
-
4803
- // Only run this if the event target is a descendant of this builder's DOM element.
4804
- if ( $.contains( builder.$el.get( 0 ), e.target ) ) {
4805
- // Get the element we're currently hovering over
4806
- var over = $( [] )
4807
- .add( builder.$( '.so-panels-welcome-message:visible' ) )
4808
- .add( builder.$( '.so-rows-container > .so-row-container' ) )
4809
- .add( builder.$( '.so-cells > .cell' ) )
4810
- .add( builder.$( '.cell-wrapper > .so-widget' ) )
4811
- .filter( function ( i ) {
4812
- return menu.isOverEl( $( this ), e );
4813
- } );
4814
-
4815
- var activeView = over.last().data( 'view' );
4816
- if ( activeView !== undefined && activeView.buildContextualMenu !== undefined ) {
4817
- // We'll pass this to the current active view so it can populate the contextual menu
4818
- activeView.buildContextualMenu( e, menu );
4819
- }
4820
- else if ( over.last().hasClass( 'so-panels-welcome-message' ) ) {
4821
- // The user opened the contextual menu on the welcome message
4822
- this.buildContextualMenu( e, menu );
4823
- }
4824
- }
4825
- },
4826
-
4827
- /**
4828
- * Build the contextual menu for the main builder - before any content has been added.
4829
- */
4830
- buildContextualMenu: function ( e, menu ) {
4831
- var actions = {};
4832
-
4833
- if ( this.supports( 'addRow' ) ) {
4834
- actions.add_row = { title: panelsOptions.loc.contextual.add_row };
4835
- }
4836
-
4837
- if ( panels.helpers.clipboard.canCopyPaste() ) {
4838
- if ( panels.helpers.clipboard.isModel( 'row-model' ) && this.supports( 'addRow' ) ) {
4839
- actions.paste_row = { title: panelsOptions.loc.contextual.row_paste };
4840
- }
4841
- }
4842
-
4843
- if ( !_.isEmpty( actions ) ) {
4844
- menu.addSection(
4845
- 'builder-actions',
4846
- {
4847
- sectionTitle: panelsOptions.loc.contextual.row_actions,
4848
- search: false,
4849
- },
4850
- actions,
4851
- function ( c ) {
4852
- switch ( c ) {
4853
- case 'add_row':
4854
- this.displayAddRowDialog();
4855
- break;
4856
-
4857
- case 'paste_row':
4858
- this.pasteRowHandler();
4859
- break;
4860
- }
4861
- }.bind( this )
4862
- );
4863
- }
4864
- },
4865
- } );
4866
-
4867
- },{}],24:[function(require,module,exports){
4868
- var panels = window.panels, $ = jQuery;
4869
-
4870
- module.exports = Backbone.View.extend( {
4871
- template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-cell' ).html() ) ),
4872
- events: {
4873
- 'click .cell-wrapper': 'handleCellClick'
4874
- },
4875
-
4876
- /* The row view that this cell is a part of */
4877
- row: null,
4878
- widgetSortable: null,
4879
-
4880
- initialize: function () {
4881
- this.listenTo(this.model.get('widgets'), 'add', this.onAddWidget );
4882
- },
4883
-
4884
- /**
4885
- * Render the actual cell
4886
- */
4887
- render: function () {
4888
- var templateArgs = {
4889
- weight: this.model.get( 'weight' ),
4890
- totalWeight: this.row.model.get('cells').totalWeight()
4891
- };
4892
-
4893
- this.setElement( this.template( templateArgs ) );
4894
- this.$el.data( 'view', this );
4895
-
4896
- // Now lets render any widgets that are currently in the row
4897
- var thisView = this;
4898
- this.model.get('widgets').each( function ( widget ) {
4899
- var widgetView = new panels.view.widget( {model: widget} );
4900
- widgetView.cell = thisView;
4901
- widgetView.render();
4902
-
4903
- widgetView.$el.appendTo( thisView.$( '.widgets-container' ) );
4904
- } );
4905
-
4906
- this.initSortable();
4907
- this.initResizable();
4908
-
4909
- return this;
4910
- },
4911
-
4912
- /**
4913
- * Initialize the widget sortable
4914
- */
4915
- initSortable: function () {
4916
- if( ! this.row.builder.supports( 'moveWidget' ) ) {
4917
- return this;
4918
- }
4919
-
4920
- var cellView = this;
4921
- var builder = cellView.row.builder;
4922
-
4923
- // Go up the view hierarchy until we find the ID attribute
4924
- var builderID = builder.$el.attr( 'id' );
4925
- var builderModel = builder.model;
4926
-
4927
- // Create a widget sortable that's connected with all other cells
4928
- this.widgetSortable = this.$( '.widgets-container' ).sortable( {
4929
- placeholder: "so-widget-sortable-highlight",
4930
- connectWith: '#' + builderID + ' .so-cells .cell .widgets-container,.block-editor .so-cells .cell .widgets-container',
4931
- tolerance: 'pointer',
4932
- scroll: false,
4933
- over: function ( e, ui ) {
4934
- // This will make all the rows in the current builder resize
4935
- cellView.row.builder.trigger( 'widget_sortable_move' );
4936
- },
4937
- remove: function ( e, ui ) {
4938
- cellView.model.get( 'widgets' ).remove(
4939
- $( ui.item ).data( 'view' ).model,
4940
- { silent: true }
4941
- );
4942
- builderModel.refreshPanelsData();
4943
- },
4944
- receive: function ( e, ui ) {
4945
- var widgetModel = $( ui.item ).data( 'view' ).model;
4946
- widgetModel.cell = cellView.model;
4947
- cellView.model.get( 'widgets' ).add(
4948
- widgetModel,
4949
- { silent: true, at: $( ui.item ).index() }
4950
- );
4951
- builderModel.refreshPanelsData();
4952
- },
4953
- stop: function ( e, ui ) {
4954
- var $$ = $( ui.item ),
4955
- widget = $$.data( 'view' ),
4956
- targetCell = $$.closest( '.cell' ).data( 'view' );
4957
-
4958
-
4959
- // If this hasn't already been removed and added to a different builder.
4960
- if ( cellView.model.get( 'widgets' ).get( widget.model ) ) {
4961
-
4962
- cellView.row.builder.addHistoryEntry( 'widget_moved' );
4963
-
4964
- // Move the model and the view to the new cell
4965
- widget.model.moveToCell( targetCell.model, {}, $$.index() );
4966
- widget.cell = targetCell;
4967
-
4968
- builderModel.refreshPanelsData();
4969
- }
4970
- },
4971
- helper: function ( e, el ) {
4972
- var helper = el.clone()
4973
- .css( {
4974
- 'width': el.outerWidth(),
4975
- 'z-index': 10000,
4976
- 'position': 'fixed'
4977
- } )
4978
- .addClass( 'widget-being-dragged' ).appendTo( 'body' );
4979
-
4980
- // Center the helper to the mouse cursor.
4981
- if ( el.outerWidth() > 720 ) {
4982
- helper.animate( {
4983
- 'margin-left': e.pageX - el.offset().left - (
4984
- 480 / 2
4985
- ),
4986
- 'width': 480
4987
- }, 'fast' );
4988
- }
4989
-
4990
- return helper;
4991
- }
4992
- } );
4993
-
4994
- return this;
4995
- },
4996
-
4997
- /**
4998
- * Refresh the widget sortable when a new widget is added
4999
- */
5000
- refreshSortable: function () {
5001
- if ( ! _.isNull( this.widgetSortable ) ) {
5002
- this.widgetSortable.sortable( 'refresh' );
5003
- }
5004
- },
5005
-
5006
- /**
5007
- * This will make the cell resizble
5008
- */
5009
- initResizable: function () {
5010
- if( ! this.row.builder.supports( 'editRow' ) ) {
5011
- return this;
5012
- }
5013
-
5014
- // var neighbor = this.$el.previous().data('view');
5015
- var handle = this.$( '.resize-handle' ).css( 'position', 'absolute' );
5016
- var container = this.row.$el;
5017
- var cellView = this;
5018
-
5019
- // The view of the cell to the left is stored when dragging starts.
5020
- var previousCell;
5021
-
5022
- handle.draggable( {
5023
- axis: 'x',
5024
- containment: container,
5025
- start: function ( e, ui ) {
5026
- // Set the containment to the cell parent
5027
- previousCell = cellView.$el.prev().data( 'view' );
5028
- if ( _.isUndefined( previousCell ) ) {
5029
- return;
5030
- }
5031
-
5032
- // Create the clone for the current cell
5033
- var newCellClone = cellView.$el.clone().appendTo( ui.helper ).css( {
5034
- position: 'absolute',
5035
- top: '0',
5036
- width: cellView.$el.outerWidth(),
5037
- left: 5,
5038
- height: cellView.$el.outerHeight()
5039
- } );
5040
- newCellClone.find( '.resize-handle' ).remove();
5041
-
5042
- // Create the clone for the previous cell
5043
- var prevCellClone = previousCell.$el.clone().appendTo( ui.helper ).css( {
5044
- position: 'absolute',
5045
- top: '0',
5046
- width: previousCell.$el.outerWidth(),
5047
- right: 5,
5048
- height: previousCell.$el.outerHeight()
5049
- } );
5050
- prevCellClone.find( '.resize-handle' ).remove();
5051
-
5052
- $( this ).data( {
5053
- 'newCellClone': newCellClone,
5054
- 'prevCellClone': prevCellClone
5055
- } );
5056
- },
5057
- drag: function ( e, ui ) {
5058
- // Calculate the new cell and previous cell widths as a percent
5059
- var containerWidth = cellView.row.$el.width() + 10;
5060
- var ncw = cellView.model.get( 'weight' ) - (
5061
- (
5062
- ui.position.left + handle.outerWidth() / 2
5063
- ) / containerWidth
5064
- );
5065
- var pcw = previousCell.model.get( 'weight' ) + (
5066
- (
5067
- ui.position.left + handle.outerWidth() / 2
5068
- ) / containerWidth
5069
- );
5070
-
5071
- $( this ).data( 'newCellClone' ).css( 'width', containerWidth * ncw )
5072
- .find( '.preview-cell-weight' ).html( Math.round( ncw * 1000 ) / 10 );
5073
-
5074
- $( this ).data( 'prevCellClone' ).css( 'width', containerWidth * pcw )
5075
- .find( '.preview-cell-weight' ).html( Math.round( pcw * 1000 ) / 10 );
5076
- },
5077
- stop: function ( e, ui ) {
5078
- // Remove the clones
5079
- $( this ).data( 'newCellClone' ).remove();
5080
- $( this ).data( 'prevCellClone' ).remove();
5081
-
5082
- var containerWidth = cellView.row.$el.width() + 10;
5083
- var ncw = cellView.model.get( 'weight' ) - (
5084
- (
5085
- ui.position.left + handle.outerWidth() / 2
5086
- ) / containerWidth
5087
- );
5088
- var pcw = previousCell.model.get( 'weight' ) + (
5089
- (
5090
- ui.position.left + handle.outerWidth() / 2
5091
- ) / containerWidth
5092
- );
5093
-
5094
- if ( ncw > 0.02 && pcw > 0.02 ) {
5095
- cellView.row.builder.addHistoryEntry( 'cell_resized' );
5096
- cellView.model.set( 'weight', ncw );
5097
- previousCell.model.set( 'weight', pcw );
5098
- cellView.row.resize();
5099
- }
5100
-
5101
- ui.helper.css( 'left', - handle.outerWidth() / 2 );
5102
-
5103
- // Refresh the panels data
5104
- cellView.row.builder.model.refreshPanelsData();
5105
- }
5106
- } );
5107
-
5108
- return this;
5109
- },
5110
-
5111
- /**
5112
- * This is triggered when ever a widget is added to the row collection.
5113
- *
5114
- * @param widget
5115
- */
5116
- onAddWidget: function ( widget, collection, options ) {
5117
- options = _.extend( {noAnimate: false}, options );
5118
-
5119
- // Create the view for the widget
5120
- var view = new panels.view.widget( {
5121
- model: widget
5122
- } );
5123
- view.cell = this;
5124
-
5125
- if ( _.isUndefined( widget.isDuplicate ) ) {
5126
- widget.isDuplicate = false;
5127
- }
5128
-
5129
- // Render and load the form if this is a duplicate
5130
- view.render( {
5131
- 'loadForm': widget.isDuplicate
5132
- } );
5133
-
5134
- if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
5135
- // Insert this at the end of the widgets container
5136
- view.$el.appendTo( this.$( '.widgets-container' ) );
5137
- } else {
5138
- // We need to insert this at a specific position
5139
- view.$el.insertAfter(
5140
- this.$( '.widgets-container .so-widget' ).eq( options.at - 1 )
5141
- );
5142
- }
5143
-
5144
- if ( options.noAnimate === false ) {
5145
- // We need an animation
5146
- view.visualCreate();
5147
- }
5148
-
5149
- this.refreshSortable();
5150
- this.row.resize();
5151
- this.row.builder.trigger( 'widget_added' );
5152
- },
5153
-
5154
- /**
5155
- * Handle this cell being clicked on
5156
- *
5157
- * @param e
5158
- * @returns {boolean}
5159
- */
5160
- handleCellClick: function ( e ) {
5161
- // Remove all existing selected cell indication for this builder
5162
- this.row.builder.$el.find( '.so-cells .cell' ).removeClass( 'cell-selected' );
5163
-
5164
- if( this.row.builder.activeCell === this && ! this.model.get('widgets').length ) {
5165
- // This is a click on an empty cell
5166
- this.row.builder.activeCell = null;
5167
- }
5168
- else {
5169
- this.$el.addClass( 'cell-selected' );
5170
- this.row.builder.activeCell = this;
5171
- }
5172
- },
5173
-
5174
- /**
5175
- * Insert a widget from the clipboard
5176
- */
5177
- pasteHandler: function(){
5178
- var pastedModel = panels.helpers.clipboard.getModel( 'widget-model' );
5179
- if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.widget ) {
5180
- this.row.builder.addHistoryEntry( 'widget_pasted' );
5181
- pastedModel.cell = this.model;
5182
- this.model.get('widgets').add( pastedModel );
5183
- this.row.builder.model.refreshPanelsData();
5184
- }
5185
- },
5186
-
5187
- /**
5188
- * Build up the contextual menu for a cell
5189
- *
5190
- * @param e
5191
- * @param menu
5192
- */
5193
- buildContextualMenu: function ( e, menu ) {
5194
- var thisView = this;
5195
-
5196
- if( ! menu.hasSection( 'add-widget-below' ) ) {
5197
- menu.addSection(
5198
- 'add-widget-cell',
5199
- {
5200
- sectionTitle: panelsOptions.loc.contextual.add_widget_cell,
5201
- searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
5202
- defaultDisplay: panelsOptions.contextual.default_widgets
5203
- },
5204
- panelsOptions.widgets,
5205
- function ( c ) {
5206
- thisView.row.builder.trigger('before_user_adds_widget')
5207
- thisView.row.builder.addHistoryEntry( 'widget_added' );
5208
-
5209
- var widget = new panels.model.widget( {
5210
- class: c
5211
- } );
5212
-
5213
- // Add the widget to the cell model
5214
- widget.cell = thisView.model;
5215
- widget.cell.get('widgets').add( widget );
5216
-
5217
- thisView.row.builder.model.refreshPanelsData();
5218
- thisView.row.builder.trigger('after_user_adds_widget', widget);
5219
- }
5220
- );
5221
- }
5222
-
5223
- var actions = {};
5224
- if ( this.row.builder.supports('addWidget') && panels.helpers.clipboard.isModel( 'widget-model' ) ) {
5225
- actions.paste = {title: panelsOptions.loc.contextual.cell_paste_widget};
5226
- }
5227
-
5228
- if( ! _.isEmpty( actions ) ) {
5229
- menu.addSection(
5230
- 'cell-actions',
5231
- {
5232
- sectionTitle: panelsOptions.loc.contextual.cell_actions,
5233
- search: false,
5234
- },
5235
- actions,
5236
- function ( c ) {
5237
- switch ( c ) {
5238
- case 'paste':
5239
- this.pasteHandler();
5240
- break;
5241
- }
5242
-
5243
- this.row.builder.model.refreshPanelsData();
5244
- }.bind( this )
5245
- );
5246
- }
5247
-
5248
- // Add the contextual menu for the parent row
5249
- this.row.buildContextualMenu( e, menu );
5250
- }
5251
- } );
5252
-
5253
- },{}],25:[function(require,module,exports){
5254
- var panels = window.panels, $ = jQuery;
5255
-
5256
- module.exports = Backbone.View.extend( {
5257
- dialogTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog' ).html() ) ),
5258
- dialogTabTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-tab' ).html() ) ),
5259
-
5260
- tabbed: false,
5261
- rendered: false,
5262
- builder: false,
5263
- className: 'so-panels-dialog-wrapper',
5264
- dialogClass: '',
5265
- dialogIcon: '',
5266
- parentDialog: false,
5267
- dialogOpen: false,
5268
- editableLabel: false,
5269
-
5270
- events: {
5271
- 'click .so-close': 'closeDialog',
5272
- 'click .so-nav.so-previous': 'navToPrevious',
5273
- 'click .so-nav.so-next': 'navToNext',
5274
- },
5275
-
5276
- initialize: function () {
5277
- // The first time this dialog is opened, render it
5278
- this.once( 'open_dialog', this.render );
5279
- this.once( 'open_dialog', this.attach );
5280
- this.once( 'open_dialog', this.setDialogClass );
5281
-
5282
- this.trigger( 'initialize_dialog', this );
5283
-
5284
- if ( ! _.isUndefined( this.initializeDialog ) ) {
5285
- this.initializeDialog();
5286
- }
5287
-
5288
- _.bindAll( this, 'initSidebars', 'hasSidebar', 'onResize', 'toggleLeftSideBar', 'toggleRightSideBar' );
5289
- },
5290
-
5291
- /**
5292
- * Returns the next dialog in the sequence. Should be overwritten by a child dialog.
5293
- * @returns {null}
5294
- */
5295
- getNextDialog: function () {
5296
- return null;
5297
- },
5298
-
5299
- /**
5300
- * Returns the previous dialog in this sequence. Should be overwritten by child dialog.
5301
- * @returns {null}
5302
- */
5303
- getPrevDialog: function () {
5304
- return null;
5305
- },
5306
-
5307
- /**
5308
- * Adds a dialog class to uniquely identify this dialog type
5309
- */
5310
- setDialogClass: function () {
5311
- if ( this.dialogClass !== '' ) {
5312
- this.$( '.so-panels-dialog' ).addClass( this.dialogClass );
5313
- }
5314
- },
5315
-
5316
- /**
5317
- * Set the builder that controls this dialog.
5318
- * @param {panels.view.builder} builder
5319
- */
5320
- setBuilder: function ( builder ) {
5321
- this.builder = builder;
5322
-
5323
- // Trigger an add dialog event on the builder so it can modify the dialog in any way
5324
- builder.trigger( 'add_dialog', this, this.builder );
5325
-
5326
- return this;
5327
- },
5328
-
5329
- /**
5330
- * Attach the dialog to the window
5331
- */
5332
- attach: function () {
5333
- this.$el.appendTo( 'body' );
5334
-
5335
- return this;
5336
- },
5337
-
5338
- /**
5339
- * Converts an HTML representation of the dialog into arguments for a dialog box
5340
- * @param html HTML for the dialog
5341
- * @param args Arguments passed to the template
5342
- * @returns {}
5343
- */
5344
- parseDialogContent: function ( html, args ) {
5345
- // Add a CID
5346
- args = _.extend( {cid: this.cid}, args );
5347
-
5348
-
5349
- var c = $( (
5350
- _.template( panels.helpers.utils.processTemplate( html ) )
5351
- )( args ) );
5352
- var r = {
5353
- title: c.find( '.title' ).html(),
5354
- buttons: c.find( '.buttons' ).html(),
5355
- content: c.find( '.content' ).html()
5356
- };
5357
-
5358
- if ( c.has( '.left-sidebar' ) ) {
5359
- r.left_sidebar = c.find( '.left-sidebar' ).html();
5360
- }
5361
-
5362
- if ( c.has( '.right-sidebar' ) ) {
5363
- r.right_sidebar = c.find( '.right-sidebar' ).html();
5364
- }
5365
-
5366
- return r;
5367
-
5368
- },
5369
-
5370
- /**
5371
- * Render the dialog and initialize the tabs
5372
- *
5373
- * @param attributes
5374
- * @returns {panels.view.dialog}
5375
- */
5376
- renderDialog: function ( attributes ) {
5377
- attributes = _.extend( {
5378
- editableLabel: this.editableLabel,
5379
- dialogIcon: this.dialogIcon,
5380
- }, attributes );
5381
-
5382
- this.$el.html( this.dialogTemplate( attributes ) ).hide();
5383
- this.$el.data( 'view', this );
5384
- this.$el.addClass( 'so-panels-dialog-wrapper' );
5385
-
5386
- if ( this.parentDialog !== false ) {
5387
- // Add a link to the parent dialog as a sort of crumbtrail.
5388
- var thisDialog = this;
5389
- var dialogParent = $( '<h3 class="so-parent-link"></h3>' ).html( this.parentDialog.text + '<div class="so-separator"></div>' );
5390
- dialogParent.click( function ( e ) {
5391
- e.preventDefault();
5392
- thisDialog.closeDialog();
5393
- thisDialog.parentDialog.openDialog();
5394
- } );
5395
- this.$( '.so-title-bar .so-title' ).before( dialogParent );
5396
- }
5397
-
5398
- if( this.$( '.so-title-bar .so-title-editable' ).length ) {
5399
- // Added here because .so-edit-title is only available after the template has been rendered.
5400
- this.initEditableLabel();
5401
- }
5402
-
5403
- setTimeout( this.initSidebars, 1 );
5404
-
5405
- return this;
5406
- },
5407
-
5408
- initSidebars: function () {
5409
- var $leftButton = this.$( '.so-show-left-sidebar' ).hide();
5410
- var $rightButton = this.$( '.so-show-right-sidebar' ).hide();
5411
- var hasLeftSidebar = this.hasSidebar( 'left' );
5412
- var hasRightSidebar = this.hasSidebar( 'right' );
5413
- // Set up resize handling
5414
- if ( hasLeftSidebar || hasRightSidebar ) {
5415
- $( window ).on( 'resize', this.onResize );
5416
- if ( hasLeftSidebar ) {
5417
- $leftButton.show();
5418
- $leftButton.on( 'click', this.toggleLeftSideBar );
5419
- }
5420
- if ( hasRightSidebar ) {
5421
- $rightButton.show();
5422
- $rightButton.on( 'click', this.toggleRightSideBar );
5423
- }
5424
- }
5425
-
5426
- this.onResize();
5427
- },
5428
-
5429
- /**
5430
- * Initialize the sidebar tabs
5431
- */
5432
- initTabs: function () {
5433
- var tabs = this.$( '.so-sidebar-tabs li a' );
5434
-
5435
- if ( tabs.length === 0 ) {
5436
- return this;
5437
- }
5438
-
5439
- var thisDialog = this;
5440
- tabs.click( function ( e ) {
5441
- e.preventDefault();
5442
- var $$ = $( this );
5443
-
5444
- thisDialog.$( '.so-sidebar-tabs li' ).removeClass( 'tab-active' );
5445
- thisDialog.$( '.so-content .so-content-tabs > *' ).hide();
5446
-
5447
- $$.parent().addClass( 'tab-active' );
5448
-
5449
- var url = $$.attr( 'href' );
5450
- if ( ! _.isUndefined( url ) && url.charAt( 0 ) === '#' ) {
5451
- // Display the new tab
5452
- var tabName = url.split( '#' )[1];
5453
- thisDialog.$( '.so-content .so-content-tabs .tab-' + tabName ).show();
5454
- }
5455
-
5456
- // This lets other dialogs implement their own custom handlers
5457
- thisDialog.trigger( 'tab_click', $$ );
5458
-
5459
- } );
5460
-
5461
- // Trigger a click on the first tab
5462
- this.$( '.so-sidebar-tabs li a' ).first().click();
5463
- return this;
5464
- },
5465
-
5466
- initToolbar: function () {
5467
- // Trigger simplified click event for elements marked as toolbar buttons.
5468
- var buttons = this.$( '.so-toolbar .so-buttons .so-toolbar-button' );
5469
- buttons.click( function ( e ) {
5470
- e.preventDefault();
5471
-
5472
- this.trigger( 'button_click', $( e.currentTarget ) );
5473
- }.bind( this ) );
5474
-
5475
- // Handle showing and hiding the dropdown list items
5476
- var $dropdowns = this.$( '.so-toolbar .so-buttons .so-dropdown-button' );
5477
- $dropdowns.click( function ( e ) {
5478
- e.preventDefault();
5479
- var $dropdownButton = $( e.currentTarget );
5480
- var $dropdownList = $dropdownButton.siblings( '.so-dropdown-links-wrapper' );
5481
- if ( $dropdownList.is( '.hidden' ) ) {
5482
- $dropdownList.removeClass( 'hidden' );
5483
- } else {
5484
- $dropdownList.addClass( 'hidden' );
5485
- }
5486
-
5487
- }.bind( this ) );
5488
-
5489
- // Hide dropdown list on click anywhere, unless it's a dropdown option which requires confirmation in it's
5490
- // unconfirmed state.
5491
- $( 'html' ).click( function ( e ) {
5492
- this.$( '.so-dropdown-links-wrapper' ).not( '.hidden' ).each( function ( index, el ) {
5493
- var $dropdownList = $( el );
5494
- var $trgt = $( e.target );
5495
- if ( $trgt.length === 0 || !(
5496
- (
5497
- $trgt.is('.so-needs-confirm') && !$trgt.is('.so-confirmed')
5498
- ) || $trgt.is('.so-dropdown-button')
5499
- ) ) {
5500
- $dropdownList.addClass('hidden');
5501
- }
5502
- } );
5503
- }.bind( this ) );
5504
- },
5505
-
5506
- /**
5507
- * Initialize the editable dialog title
5508
- */
5509
- initEditableLabel: function(){
5510
- var $editElt = this.$( '.so-title-bar .so-title-editable' );
5511
-
5512
- $editElt.keypress( function ( event ) {
5513
- var enterPressed = event.type === 'keypress' && event.keyCode === 13;
5514
- if ( enterPressed ) {
5515
- // Need to make sure tab focus is on another element, otherwise pressing enter multiple times refocuses
5516
- // the element and allows newlines.
5517
- var tabbables = $( ':tabbable' );
5518
- var curTabIndex = tabbables.index( $editElt );
5519
- tabbables.eq( curTabIndex + 1 ).focus();
5520
- // After the above, we're somehow left with the first letter of text selected,
5521
- // so this removes the selection.
5522
- window.getSelection().removeAllRanges();
5523
- }
5524
- return !enterPressed;
5525
- } ).blur( function () {
5526
- var newValue = $editElt.text().replace( /^\s+|\s+$/gm, '' );
5527
- var oldValue = $editElt.data( 'original-value' ).replace( /^\s+|\s+$/gm, '' );
5528
- if ( newValue !== oldValue ) {
5529
- $editElt.text( newValue );
5530
- this.trigger( 'edit_label', newValue );
5531
- }
5532
-
5533
- }.bind( this ) );
5534
-
5535
- $editElt.focus( function() {
5536
- $editElt.data( 'original-value', $editElt.text() );
5537
- panels.helpers.utils.selectElementContents( this );
5538
- } );
5539
- },
5540
-
5541
- /**
5542
- * Quickly setup the dialog by opening and closing it.
5543
- */
5544
- setupDialog: function () {
5545
- this.openDialog();
5546
- this.closeDialog();
5547
- },
5548
-
5549
- /**
5550
- * Refresh the next and previous buttons.
5551
- */
5552
- refreshDialogNav: function () {
5553
- this.$( '.so-title-bar .so-nav' ).show().removeClass( 'so-disabled' );
5554
-
5555
- // Lets also hide the next and previous if we don't have a next and previous dialog
5556
- var nextDialog = this.getNextDialog();
5557
- var nextButton = this.$( '.so-title-bar .so-next' );
5558
-
5559
- var prevDialog = this.getPrevDialog();
5560
- var prevButton = this.$( '.so-title-bar .so-previous' );
5561
-
5562
- if ( nextDialog === null ) {
5563
- nextButton.hide();
5564
- }
5565
- else if ( nextDialog === false ) {
5566
- nextButton.addClass( 'so-disabled' );
5567
- }
5568
-
5569
- if ( prevDialog === null ) {
5570
- prevButton.hide();
5571
- }
5572
- else if ( prevDialog === false ) {
5573
- prevButton.addClass( 'so-disabled' );
5574
- }
5575
- },
5576
-
5577
- /**
5578
- * Open the dialog
5579
- */
5580
- openDialog: function ( options ) {
5581
- options = _.extend( {
5582
- silent: false
5583
- }, options );
5584
-
5585
- if ( ! options.silent ) {
5586
- this.trigger( 'open_dialog' );
5587
- }
5588
-
5589
- this.dialogOpen = true;
5590
-
5591
- this.refreshDialogNav();
5592
-
5593
- // Stop scrolling for the main body
5594
- panels.helpers.pageScroll.lock();
5595
-
5596
- // Start listen for keyboard keypresses.
5597
- $( window ).on( 'keyup', this.keyboardListen );
5598
-
5599
- this.onResize();
5600
-
5601
- this.$el.show();
5602
-
5603
- if ( ! options.silent ) {
5604
- // This triggers once everything is visible
5605
- this.trigger( 'open_dialog_complete' );
5606
- this.builder.trigger( 'open_dialog', this );
5607
- $( document ).trigger( 'open_dialog', this );
5608
- }
5609
- },
5610
-
5611
- /**
5612
- * Close the dialog
5613
- *
5614
- * @param e
5615
- * @returns {boolean}
5616
- */
5617
- closeDialog: function ( options ) {
5618
- options = _.extend( {
5619
- silent: false
5620
- }, options );
5621
-
5622
- if ( ! options.silent ) {
5623
- this.trigger( 'close_dialog' );
5624
- }
5625
-
5626
- this.dialogOpen = false;
5627
-
5628
- this.$el.hide();
5629
- panels.helpers.pageScroll.unlock();
5630
-
5631
- // Stop listen for keyboard keypresses.
5632
- $( window ).off( 'keyup', this.keyboardListen );
5633
-
5634
- if ( ! options.silent ) {
5635
- // This triggers once everything is hidden
5636
- this.trigger( 'close_dialog_complete' );
5637
- this.builder.trigger( 'close_dialog', this );
5638
- }
5639
- },
5640
-
5641
- /**
5642
- * Keyboard events handler
5643
- */
5644
- keyboardListen: function ( e ) {
5645
- // [Esc] to close
5646
- if ( e.which === 27 ) {
5647
- $( '.so-panels-dialog-wrapper .so-close' ).trigger( 'click' );
5648
- }
5649
- },
5650
-
5651
- /**
5652
- * Navigate to the previous dialog
5653
- */
5654
- navToPrevious: function () {
5655
- this.closeDialog();
5656
-
5657
- var prev = this.getPrevDialog();
5658
- if ( prev !== null && prev !== false ) {
5659
- prev.openDialog();
5660
- }
5661
- },
5662
-
5663
- /**
5664
- * Navigate to the next dialog
5665
- */
5666
- navToNext: function () {
5667
- this.closeDialog();
5668
-
5669
- var next = this.getNextDialog();
5670
- if ( next !== null && next !== false ) {
5671
- next.openDialog();
5672
- }
5673
- },
5674
-
5675
- /**
5676
- * Get the values from the form and convert them into a data array
5677
- */
5678
- getFormValues: function ( formSelector ) {
5679
- if ( _.isUndefined( formSelector ) ) {
5680
- formSelector = '.so-content';
5681
- }
5682
-
5683
- var $f = this.$( formSelector );
5684
-
5685
- var data = {}, parts;
5686
-
5687
- // Find all the named fields in the form
5688
- $f.find( '[name]' ).each( function () {
5689
- var $$ = $( this );
5690
-
5691
- try {
5692
-
5693
- var name = /([A-Za-z_]+)\[(.*)\]/.exec( $$.attr( 'name' ) );
5694
- if ( _.isEmpty( name ) ) {
5695
- return true;
5696
- }
5697
-
5698
- // Create an array with the parts of the name
5699
- if ( _.isUndefined( name[2] ) ) {
5700
- parts = $$.attr( 'name' );
5701
- } else {
5702
- parts = name[2].split( '][' );
5703
- parts.unshift( name[1] );
5704
- }
5705
-
5706
- parts = parts.map( function ( e ) {
5707
- if ( ! isNaN( parseFloat( e ) ) && isFinite( e ) ) {
5708
- return parseInt( e );
5709
- } else {
5710
- return e;
5711
- }
5712
- } );
5713
-
5714
- var sub = data;
5715
- var fieldValue = null;
5716
-
5717
- var fieldType = (
5718
- _.isString( $$.attr( 'type' ) ) ? $$.attr( 'type' ).toLowerCase() : false
5719
- );
5720
-
5721
- // First we need to get the value from the field
5722
- if ( fieldType === 'checkbox' ) {
5723
- if ( $$.is( ':checked' ) ) {
5724
- fieldValue = $$.val() !== '' ? $$.val() : true;
5725
- } else {
5726
- fieldValue = null;
5727
- }
5728
- }
5729
- else if ( fieldType === 'radio' ) {
5730
- if ( $$.is( ':checked' ) ) {
5731
- fieldValue = $$.val();
5732
- } else {
5733
- //skip over unchecked radios
5734
- return;
5735
- }
5736
- }
5737
- else if ( $$.prop( 'tagName' ) === 'SELECT' ) {
5738
- var selected = $$.find( 'option:selected' );
5739
-
5740
- if ( selected.length === 1 ) {
5741
- fieldValue = $$.find( 'option:selected' ).val();
5742
- }
5743
- else if ( selected.length > 1 ) {
5744
- // This is a mutli-select field
5745
- fieldValue = _.map( $$.find( 'option:selected' ), function ( n, i ) {
5746
- return $( n ).val();
5747
- } );
5748
- }
5749
-
5750
- } else {
5751
- // This is a fallback that will work for most fields
5752
- fieldValue = $$.val();
5753
- }
5754
-
5755
- // Now, we need to filter this value if necessary
5756
- if ( ! _.isUndefined( $$.data( 'panels-filter' ) ) ) {
5757
- switch ( $$.data( 'panels-filter' ) ) {
5758
- case 'json_parse':
5759
- // Attempt to parse the JSON value of this field
5760
- try {
5761
- fieldValue = JSON.parse( fieldValue );
5762
- }
5763
- catch ( err ) {
5764
- fieldValue = '';
5765
- }
5766
- break;
5767
- }
5768
- }
5769
-
5770
- // Now convert this into an array
5771
- if ( fieldValue !== null ) {
5772
- for ( var i = 0; i < parts.length; i ++ ) {
5773
- if ( i === parts.length - 1 ) {
5774
- if ( parts[i] === '' ) {
5775
- // This needs to be an array
5776
- sub.push( fieldValue );
5777
- } else {
5778
- sub[parts[i]] = fieldValue;
5779
- }
5780
- } else {
5781
- if ( _.isUndefined( sub[parts[i]] ) ) {
5782
- if ( parts[i + 1] === '' ) {
5783
- sub[parts[i]] = [];
5784
- } else {
5785
- sub[parts[i]] = {};
5786
- }
5787
- }
5788
- sub = sub[parts[i]];
5789
- }
5790
- }
5791
- }
5792
- }
5793
- catch ( error ) {
5794
- // Ignore this error, just log the message for debugging
5795
- console.log( 'Field [' + $$.attr('name') + '] could not be processed and was skipped - ' + error.message );
5796
- }
5797
-
5798
- } ); // End of each through input fields
5799
-
5800
- return data;
5801
- },
5802
-
5803
- /**
5804
- * Set a status message for the dialog
5805
- */
5806
- setStatusMessage: function ( message, loading, error ) {
5807
- var msg = error ? '<span class="dashicons dashicons-warning"></span>' + message : message;
5808
- this.$( '.so-toolbar .so-status' ).html( msg );
5809
- if ( ! _.isUndefined( loading ) && loading ) {
5810
- this.$( '.so-toolbar .so-status' ).addClass( 'so-panels-loading' );
5811
- } else {
5812
- this.$( '.so-toolbar .so-status' ).removeClass( 'so-panels-loading' );
5813
- }
5814
- },
5815
-
5816
- /**
5817
- * Set the parent after.
5818
- */
5819
- setParent: function ( text, dialog ) {
5820
- this.parentDialog = {
5821
- text: text,
5822
- dialog: dialog
5823
- };
5824
- },
5825
-
5826
- onResize: function () {
5827
- var mediaQuery = window.matchMedia( '(max-width: 980px)' );
5828
- var sides = [ 'left', 'right' ];
5829
-
5830
- sides.forEach( function ( side ) {
5831
- var $sideBar = this.$( '.so-' + side + '-sidebar' );
5832
- var $showSideBarButton = this.$( '.so-show-' + side + '-sidebar' );
5833
- if ( this.hasSidebar( side ) ) {
5834
- $showSideBarButton.hide();
5835
- if ( mediaQuery.matches ) {
5836
- $showSideBarButton.show();
5837
- $showSideBarButton.closest( '.so-title-bar' ).addClass( 'so-has-' + side + '-button' );
5838
- $sideBar.hide();
5839
- $sideBar.closest( '.so-panels-dialog' ).removeClass( 'so-panels-dialog-has-' + side + '-sidebar' );
5840
- } else {
5841
- $showSideBarButton.hide();
5842
- $showSideBarButton.closest( '.so-title-bar' ).removeClass( 'so-has-' + side + '-button' );
5843
- $sideBar.show();
5844
- $sideBar.closest( '.so-panels-dialog' ).addClass( 'so-panels-dialog-has-' + side + '-sidebar' );
5845
- }
5846
- } else {
5847
- $sideBar.hide();
5848
- $showSideBarButton.hide();
5849
- }
5850
- }.bind( this ) );
5851
- },
5852
-
5853
- hasSidebar: function ( side ) {
5854
- return this.$( '.so-' + side + '-sidebar' ).children().length > 0;
5855
- },
5856
-
5857
- toggleLeftSideBar: function () {
5858
- this.toggleSidebar( 'left' );
5859
- },
5860
-
5861
- toggleRightSideBar: function () {
5862
- this.toggleSidebar( 'right' );
5863
- },
5864
-
5865
- toggleSidebar: function ( side ) {
5866
- var sidebar = this.$( '.so-' + side + '-sidebar' );
5867
-
5868
- if ( sidebar.is( ':visible' ) ) {
5869
- sidebar.hide();
5870
- } else {
5871
- sidebar.show();
5872
- }
5873
- },
5874
-
5875
- } );
5876
-
5877
- },{}],26:[function(require,module,exports){
5878
- var panels = window.panels, $ = jQuery;
5879
-
5880
- module.exports = Backbone.View.extend( {
5881
- template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-live-editor' ).html() ) ),
5882
-
5883
- previewScrollTop: 0,
5884
- loadTimes: [],
5885
- previewFrameId: 1,
5886
-
5887
- previewUrl: null,
5888
- previewIframe: null,
5889
-
5890
- events: {
5891
- 'click .live-editor-close': 'close',
5892
- 'click .live-editor-collapse': 'collapse',
5893
- 'click .live-editor-mode': 'mobileToggle'
5894
- },
5895
-
5896
- initialize: function ( options ) {
5897
- options = _.extend( {
5898
- builder: false,
5899
- previewUrl: false,
5900
- }, options );
5901
-
5902
- if( _.isEmpty( options.previewUrl ) ) {
5903
- options.previewUrl = panelsOptions.ajaxurl + "&action=so_panels_live_editor_preview";
5904
- }
5905
-
5906
- this.builder = options.builder;
5907
- this.previewUrl = options.previewUrl;
5908
-
5909
- this.listenTo( this.builder.model, 'refresh_panels_data', this.handleRefreshData );
5910
- this.listenTo( this.builder.model, 'load_panels_data', this.handleLoadData );
5911
- },
5912
-
5913
- /**
5914
- * Render the live editor
5915
- */
5916
- render: function () {
5917
- this.setElement( this.template() );
5918
- this.$el.hide();
5919
-
5920
- var isMouseDown = false;
5921
- $( document )
5922
- .mousedown( function () {
5923
- isMouseDown = true;
5924
- } )
5925
- .mouseup( function () {
5926
- isMouseDown = false;
5927
- } );
5928
-
5929
- // Handle highlighting the relevant widget in the live editor preview
5930
- var liveEditorView = this;
5931
- this.$el.on( 'mouseenter', '.so-widget-wrapper', function () {
5932
- var $$ = $( this ),
5933
- previewWidget = $$.data( 'live-editor-preview-widget' );
5934
-
5935
- if ( ! isMouseDown && previewWidget !== undefined && previewWidget.length && ! liveEditorView.$( '.so-preview-overlay' ).is( ':visible' ) ) {
5936
- liveEditorView.highlightElement( previewWidget );
5937
- liveEditorView.scrollToElement( previewWidget );
5938
- }
5939
- } );
5940
-
5941
- this.$el.on( 'mouseleave', '.so-widget-wrapper', function () {
5942
- this.resetHighlights();
5943
- }.bind(this) );
5944
-
5945
- this.listenTo( this.builder, 'open_dialog', function () {
5946
- this.resetHighlights();
5947
- } );
5948
-
5949
- return this;
5950
- },
5951
-
5952
- /**
5953
- * Attach the live editor to the document
5954
- */
5955
- attach: function () {
5956
- this.$el.appendTo( 'body' );
5957
- },
5958
-
5959
- /**
5960
- * Display the live editor
5961
- */
5962
- open: function () {
5963
- if ( this.$el.html() === '' ) {
5964
- this.render();
5965
- }
5966
- if ( this.$el.closest( 'body' ).length === 0 ) {
5967
- this.attach();
5968
- }
5969
-
5970
- // Disable page scrolling
5971
- panels.helpers.pageScroll.lock();
5972
-
5973
- if ( this.$el.is( ':visible' ) ) {
5974
- return this;
5975
- }
5976
-
5977
- // Refresh the preview display
5978
- this.$el.show();
5979
- this.refreshPreview( this.builder.model.getPanelsData() );
5980
-
5981
- // Move the builder view into the Live Editor
5982
- this.originalContainer = this.builder.$el.parent();
5983
- this.builder.$el.appendTo( this.$( '.so-live-editor-builder' ) );
5984
- this.builder.$( '.so-tool-button.so-live-editor' ).hide();
5985
- this.builder.trigger( 'builder_resize' );
5986
-
5987
-
5988
- if( $('#original_post_status' ).val() === 'auto-draft' && ! this.autoSaved ) {
5989
- // The live editor requires a saved draft post, so we'll create one for auto-draft posts
5990
- var thisView = this;
5991
-
5992
- if ( wp.autosave ) {
5993
- // Set a temporary post title so the autosave triggers properly
5994
- if( $('#title[name="post_title"]' ).val() === '' ) {
5995
- $('#title[name="post_title"]' ).val( panelsOptions.loc.draft ).trigger('keydown');
5996
- }
5997
-
5998
- $( document ).one( 'heartbeat-tick.autosave', function(){
5999
- thisView.autoSaved = true;
6000
- thisView.refreshPreview( thisView.builder.model.getPanelsData() );
6001
- } );
6002
- wp.autosave.server.triggerSave();
6003
- }
6004
- }
6005
- },
6006
-
6007
- /**
6008
- * Close the live editor
6009
- */
6010
- close: function () {
6011
- if ( ! this.$el.is( ':visible' ) ) {
6012
- return this;
6013
- }
6014
-
6015
- this.$el.hide();
6016
- panels.helpers.pageScroll.unlock();
6017
-
6018
- // Move the builder back to its original container
6019
- this.builder.$el.appendTo( this.originalContainer );
6020
- this.builder.$( '.so-tool-button.so-live-editor' ).show();
6021
- this.builder.trigger( 'builder_resize' );
6022
- },
6023
-
6024
- /**
6025
- * Collapse the live editor
6026
- */
6027
- collapse: function () {
6028
- this.$el.toggleClass( 'so-collapsed' );
6029
-
6030
- var text = this.$( '.live-editor-collapse span' );
6031
- text.html( text.data( this.$el.hasClass( 'so-collapsed' ) ? 'expand' : 'collapse' ) );
6032
- },
6033
-
6034
- /**
6035
- * Create an overlay in the preview.
6036
- *
6037
- * @param over
6038
- * @return {*|Object} The item we're hovering over.
6039
- */
6040
- highlightElement: function ( over ) {
6041
- if( ! _.isUndefined( this.resetHighlightTimeout ) ) {
6042
- clearTimeout( this.resetHighlightTimeout );
6043
- }
6044
-
6045
- // Remove any old overlays
6046
-
6047
- var body = this.previewIframe.contents().find( 'body' );
6048
- body.find( '.panel-grid .panel-grid-cell .so-panel' )
6049
- .filter( function () {
6050
- // Filter to only include non nested
6051
- return $( this ).parents( '.so-panel' ).length === 0;
6052
- } )
6053
- .not( over )
6054
- .addClass( 'so-panels-faded' );
6055
-
6056
- over.removeClass( 'so-panels-faded' ).addClass( 'so-panels-highlighted' );
6057
- },
6058
-
6059
- /**
6060
- * Reset highlights in the live preview
6061
- */
6062
- resetHighlights: function() {
6063
-
6064
- var body = this.previewIframe.contents().find( 'body' );
6065
- this.resetHighlightTimeout = setTimeout( function(){
6066
- body.find( '.panel-grid .panel-grid-cell .so-panel' )
6067
- .removeClass( 'so-panels-faded so-panels-highlighted' );
6068
- }, 100 );
6069
- },
6070
-
6071
- /**
6072
- * Scroll over an element in the live preview
6073
- * @param over
6074
- */
6075
- scrollToElement: function( over ) {
6076
- var contentWindow = this.$( '.so-preview iframe' )[0].contentWindow;
6077
- contentWindow.liveEditorScrollTo( over );
6078
- },
6079
-
6080
- handleRefreshData: function ( newData, args ) {
6081
- if ( ! this.$el.is( ':visible' ) ) {
6082
- return this;
6083
- }
6084
-
6085
- this.refreshPreview( newData );
6086
- },
6087
-
6088
- handleLoadData: function () {
6089
- if ( ! this.$el.is( ':visible' ) ) {
6090
- return this;
6091
- }
6092
-
6093
- this.refreshPreview( this.builder.model.getPanelsData() );
6094
- },
6095
-
6096
- /**
6097
- * Refresh the Live Editor preview.
6098
- * @returns {exports}
6099
- */
6100
- refreshPreview: function ( data ) {
6101
- var loadTimePrediction = this.loadTimes.length ?
6102
- _.reduce( this.loadTimes, function ( memo, num ) {
6103
- return memo + num;
6104
- }, 0 ) / this.loadTimes.length : 1000;
6105
-
6106
- // Store the last preview iframe position
6107
- if( ! _.isNull( this.previewIframe ) ) {
6108
- if ( ! this.$( '.so-preview-overlay' ).is( ':visible' ) ) {
6109
- this.previewScrollTop = this.previewIframe.contents().scrollTop();
6110
- }
6111
- }
6112
-
6113
- // Add a loading bar
6114
- this.$( '.so-preview-overlay' ).show();
6115
- this.$( '.so-preview-overlay .so-loading-bar' )
6116
- .clearQueue()
6117
- .css( 'width', '0%' )
6118
- .animate( {width: '100%'}, parseInt( loadTimePrediction ) + 100 );
6119
-
6120
-
6121
- this.postToIframe(
6122
- {
6123
- live_editor_panels_data: JSON.stringify( data ),
6124
- live_editor_post_ID: this.builder.config.postId
6125
- },
6126
- this.previewUrl,
6127
- this.$('.so-preview')
6128
- );
6129
-
6130
- this.previewIframe.data( 'load-start', new Date().getTime() );
6131
- },
6132
-
6133
- /**
6134
- * Use a temporary form to post data to an iframe.
6135
- *
6136
- * @param data The data to send
6137
- * @param url The preview URL
6138
- * @param target The target iframe
6139
- */
6140
- postToIframe: function( data, url, target ){
6141
- // Store the old preview
6142
-
6143
- if( ! _.isNull( this.previewIframe ) ) {
6144
- this.previewIframe.remove();
6145
- }
6146
-
6147
- var iframeId = 'siteorigin-panels-live-preview-' + this.previewFrameId;
6148
-
6149
- // Remove the old preview frame
6150
- this.previewIframe = $('<iframe src="javascript:false;" />')
6151
- .attr( {
6152
- 'id' : iframeId,
6153
- 'name' : iframeId,
6154
- } )
6155
- .appendTo( target )
6156
-
6157
- this.setupPreviewFrame( this.previewIframe );
6158
-
6159
- // We can use a normal POST form submit
6160
- var tempForm = $('<form id="soPostToPreviewFrame" method="post" />')
6161
- .attr( {
6162
- id: iframeId,
6163
- target: this.previewIframe.attr('id'),
6164
- action: url
6165
- } )
6166
- .appendTo( 'body' );
6167
-
6168
- $.each( data, function( name, value ){
6169
- $('<input type="hidden" />')
6170
- .attr( {
6171
- name: name,
6172
- value: value
6173
- } )
6174
- .appendTo( tempForm );
6175
- } );
6176
-
6177
- tempForm
6178
- .submit()
6179
- .remove();
6180
-
6181
- this.previewFrameId++;
6182
-
6183
- return this.previewIframe;
6184
- },
6185
-
6186
- /**
6187
- * Do all the basic setup for the preview Iframe element
6188
- * @param iframe
6189
- */
6190
- setupPreviewFrame: function( iframe ){
6191
- var thisView = this;
6192
- iframe
6193
- .data( 'iframeready', false )
6194
- .on( 'iframeready', function () {
6195
- var $$ = $( this ),
6196
- $iframeContents = $$.contents();
6197
-
6198
- if( $$.data( 'iframeready' ) ) {
6199
- // Skip this if the iframeready function has already run
6200
- return;
6201
- }
6202
-
6203
- $$.data( 'iframeready', true );
6204
-
6205
- if ( $$.data( 'load-start' ) !== undefined ) {
6206
- thisView.loadTimes.unshift( new Date().getTime() - $$.data( 'load-start' ) );
6207
-
6208
- if ( ! _.isEmpty( thisView.loadTimes ) ) {
6209
- thisView.loadTimes = thisView.loadTimes.slice( 0, 4 );
6210
- }
6211
- }
6212
-
6213
- setTimeout( function(){
6214
- // Scroll to the correct position
6215
- $iframeContents.scrollTop( thisView.previewScrollTop );
6216
- thisView.$( '.so-preview-overlay' ).hide();
6217
- }, 100 );
6218
-
6219
-
6220
- // Lets find all the first level grids. This is to account for the Page Builder layout widget.
6221
- var layoutWrapper = $iframeContents.find( '#pl-' + thisView.builder.config.postId );
6222
- layoutWrapper.find( '.panel-grid .panel-grid-cell .so-panel' )
6223
- .filter( function () {
6224
- // Filter to only include non nested
6225
- return $( this ).closest( '.panel-layout' ).is( layoutWrapper );
6226
- } )
6227
- .each( function ( i, el ) {
6228
- var $$ = $( el );
6229
- var widgetEdit = thisView.$( '.so-live-editor-builder .so-widget-wrapper' ).eq( $$.data( 'index' ) );
6230
- widgetEdit.data( 'live-editor-preview-widget', $$ );
6231
-
6232
- $$
6233
- .css( {
6234
- 'cursor': 'pointer'
6235
- } )
6236
- .mouseenter( function () {
6237
- widgetEdit.parent().addClass( 'so-hovered' );
6238
- thisView.highlightElement( $$ );
6239
- } )
6240
- .mouseleave( function () {
6241
- widgetEdit.parent().removeClass( 'so-hovered' );
6242
- thisView.resetHighlights();
6243
- } )
6244
- .click( function ( e ) {
6245
- e.preventDefault();
6246
- // When we click a widget, send that click to the form
6247
- widgetEdit.find( '.title h4' ).click();
6248
- } );
6249
- } );
6250
-
6251
- // Prevent default clicks inside the preview iframe
6252
- $iframeContents.find( "a" ).css( {'pointer-events': 'none'} ).click( function ( e ) {
6253
- e.preventDefault();
6254
- } );
6255
-
6256
- } )
6257
- .on( 'load', function(){
6258
- var $$ = $( this );
6259
- if( ! $$.data( 'iframeready' ) ) {
6260
- $$.trigger('iframeready');
6261
- }
6262
- } );
6263
- },
6264
-
6265
- /**
6266
- * Return true if the live editor has a valid preview URL.
6267
- * @return {boolean}
6268
- */
6269
- hasPreviewUrl: function () {
6270
- return this.$( 'form.live-editor-form' ).attr( 'action' ) !== '';
6271
- },
6272
-
6273
- /**
6274
- * Toggle the size of the preview iframe to simulate mobile devices.
6275
- * @param e
6276
- */
6277
- mobileToggle: function( e ){
6278
- var button = $( e.currentTarget );
6279
- this.$('.live-editor-mode' ).not( button ).removeClass('so-active');
6280
- button.addClass( 'so-active' );
6281
-
6282
- this.$el
6283
- .removeClass( 'live-editor-desktop-mode live-editor-tablet-mode live-editor-mobile-mode' )
6284
- .addClass( 'live-editor-' + button.data( 'mode' ) + '-mode' );
6285
-
6286
- }
6287
- } );
6288
-
6289
- },{}],27:[function(require,module,exports){
6290
- var panels = window.panels, $ = jQuery;
6291
-
6292
- module.exports = Backbone.View.extend( {
6293
- template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-row' ).html() ) ),
6294
-
6295
- events: {
6296
- 'click .so-row-settings': 'editSettingsHandler',
6297
- 'click .so-row-duplicate': 'duplicateHandler',
6298
- 'click .so-row-delete': 'confirmedDeleteHandler',
6299
- 'click .so-row-color': 'rowColorChangeHandler',
6300
- },
6301
-
6302
- builder: null,
6303
- dialog: null,
6304
-
6305
- /**
6306
- * Initialize the row view
6307
- */
6308
- initialize: function () {
6309
-
6310
- var rowCells = this.model.get('cells');
6311
- this.listenTo(rowCells, 'add', this.handleCellAdd );
6312
- this.listenTo(rowCells, 'remove', this.handleCellRemove );
6313
-
6314
- this.listenTo( this.model, 'reweight_cells', this.resize );
6315
- this.listenTo( this.model, 'destroy', this.onModelDestroy );
6316
-
6317
- var thisView = this;
6318
- rowCells.each( function ( cell ) {
6319
- thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
6320
- } );
6321
-
6322
- // When ever a new cell is added, listen to it for new widgets
6323
- rowCells.on( 'add', function ( cell ) {
6324
- thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
6325
- }, this );
6326
-
6327
- this.listenTo( this.model, 'change:label', this.onLabelChange );
6328
- },
6329
-
6330
- /**
6331
- * Render the row.
6332
- *
6333
- * @returns {panels.view.row}
6334
- */
6335
- render: function () {
6336
- var rowColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
6337
- var rowLabel = this.model.has( 'label' ) ? this.model.get( 'label' ) : '';
6338
- this.setElement( this.template( { rowColorLabel: rowColorLabel, rowLabel: rowLabel } ) );
6339
- this.$el.data( 'view', this );
6340
-
6341
- // Create views for the cells in this row
6342
- var thisView = this;
6343
- this.model.get('cells').each( function ( cell ) {
6344
- var cellView = new panels.view.cell( {
6345
- model: cell
6346
- } );
6347
- cellView.row = thisView;
6348
- cellView.render();
6349
- cellView.$el.appendTo( thisView.$( '.so-cells' ) );
6350
- } );
6351
-
6352
- // Remove any unsupported actions
6353
- if( ! this.builder.supports( 'rowAction' ) ) {
6354
- this.$('.so-row-toolbar .so-dropdown-wrapper' ).remove();
6355
- this.$el.addClass('so-row-no-actions');
6356
- }
6357
- else {
6358
- if( ! this.builder.supports( 'editRow' ) ) {
6359
- this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-settings' ).parent().remove();
6360
- this.$el.addClass('so-row-no-edit');
6361
- }
6362
- if( ! this.builder.supports( 'addRow' ) ) {
6363
- this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-duplicate' ).parent().remove();
6364
- this.$el.addClass('so-row-no-duplicate');
6365
- }
6366
- if( ! this.builder.supports( 'deleteRow' ) ) {
6367
- this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-delete' ).parent().remove();
6368
- this.$el.addClass('so-row-no-delete');
6369
- }
6370
- }
6371
- if( ! this.builder.supports( 'moveRow' ) ) {
6372
- this.$('.so-row-toolbar .so-row-move' ).remove();
6373
- this.$el.addClass('so-row-no-move');
6374
- }
6375
- if( !$.trim( this.$('.so-row-toolbar').html() ).length ) {
6376
- this.$('.so-row-toolbar' ).remove();
6377
- }
6378
-
6379
- // Resize the rows when ever the widget sortable moves
6380
- this.listenTo( this.builder, 'widget_sortable_move', this.resize );
6381
- this.listenTo( this.builder, 'builder_resize', this.resize );
6382
-
6383
- this.resize();
6384
-
6385
- return this;
6386
- },
6387
-
6388
- /**
6389
- * Give a visual indication of the creation of this row
6390
- */
6391
- visualCreate: function () {
6392
- this.$el.hide().fadeIn( 'fast' );
6393
- },
6394
-
6395
- /**
6396
- * Visually resize the row so that all cell heights are the same and the widths so that they balance to 100%
6397
- *
6398
- * @param e
6399
- */
6400
- resize: function ( e ) {
6401
- // Don't resize this
6402
- if ( ! this.$el.is( ':visible' ) ) {
6403
- return;
6404
- }
6405
-
6406
- // Reset everything to have an automatic height
6407
- this.$( '.so-cells .cell-wrapper' ).css( 'min-height', 0 );
6408
- this.$( '.so-cells .resize-handle' ).css( 'height', 0 );
6409
-
6410
- // We'll tie the values to the row view, to prevent issue with values going to different rows
6411
- var height = 0;
6412
- this.$( '.so-cells .cell' ).each( function () {
6413
- height = Math.max(
6414
- height,
6415
- $( this ).height()
6416
- );
6417
-
6418
- $( this ).css(
6419
- 'width',
6420
- ( $( this ).data( 'view' ).model.get( 'weight' ) * 100) + "%"
6421
- );
6422
- } );
6423
-
6424
- // Resize all the grids and cell wrappers
6425
- this.$( '.so-cells .cell-wrapper' ).css( 'min-height', Math.max( height, 63 ) );
6426
- this.$( '.so-cells .resize-handle' ).css( 'height', this.$( '.so-cells .cell-wrapper' ).outerHeight() );
6427
- },
6428
-
6429
- /**
6430
- * Remove the view from the dom.
6431
- */
6432
- onModelDestroy: function () {
6433
- this.remove();
6434
- },
6435
-
6436
- /**
6437
- * Fade out the view and destroy the model
6438
- */
6439
- visualDestroyModel: function () {
6440
- this.builder.addHistoryEntry( 'row_deleted' );
6441
- var thisView = this;
6442
- this.$el.fadeOut( 'normal', function () {
6443
- thisView.model.destroy();
6444
- thisView.builder.model.refreshPanelsData();
6445
- } );
6446
- },
6447
-
6448
- onLabelChange: function( model, text ) {
6449
- if ( this.$('.so-row-label').length == 0 ) {
6450
- this.$( '.so-row-toolbar' ).prepend( '<h3 class="so-row-label">' + text + '</h3>' );
6451
- } else {
6452
- this.$('.so-row-label').text( text );
6453
- }
6454
- },
6455
-
6456
- /**
6457
- * Duplicate this row.
6458
- *
6459
- * @return {boolean}
6460
- */
6461
- duplicateHandler: function () {
6462
- this.builder.addHistoryEntry( 'row_duplicated' );
6463
-
6464
- var duplicateRow = this.model.clone( this.builder.model );
6465
-
6466
- this.builder.model.get('rows').add( duplicateRow, {
6467
- at: this.builder.model.get('rows').indexOf( this.model ) + 1
6468
- } );
6469
-
6470
- this.builder.model.refreshPanelsData();
6471
- },
6472
-
6473
- /**
6474
- * Copy the row to a localStorage
6475
- */
6476
- copyHandler: function(){
6477
- panels.helpers.clipboard.setModel( this.model );
6478
- },
6479
-
6480
- /**
6481
- * Create a new row and insert it
6482
- */
6483
- pasteHandler: function(){
6484
- var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
6485
-
6486
- if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
6487
- this.builder.addHistoryEntry( 'row_pasted' );
6488
- pastedModel.builder = this.builder.model;
6489
- this.builder.model.get('rows').add( pastedModel, {
6490
- at: this.builder.model.get('rows').indexOf( this.model ) + 1
6491
- } );
6492
- this.builder.model.refreshPanelsData();
6493
- }
6494
- },
6495
-
6496
- /**
6497
- * Handles deleting the row with a confirmation.
6498
- */
6499
- confirmedDeleteHandler: function ( e ) {
6500
- var $$ = $( e.target );
6501
-
6502
- // The user clicked on the dashicon
6503
- if ( $$.hasClass( 'dashicons' ) ) {
6504
- $$ = $$.parent();
6505
- }
6506
-
6507
- if ( $$.hasClass( 'so-confirmed' ) ) {
6508
- this.visualDestroyModel();
6509
- } else {
6510
- var originalText = $$.html();
6511
-
6512
- $$.addClass( 'so-confirmed' ).html(
6513
- '<span class="dashicons dashicons-yes"></span>' + panelsOptions.loc.dropdown_confirm
6514
- );
6515
-
6516
- setTimeout( function () {
6517
- $$.removeClass( 'so-confirmed' ).html( originalText );
6518
- }, 2500 );
6519
- }
6520
- },
6521
-
6522
- /**
6523
- * Handle displaying the settings dialog
6524
- */
6525
- editSettingsHandler: function () {
6526
- if ( ! this.builder.supports( 'editRow' ) ) {
6527
- return;
6528
- }
6529
- // Lets open up an instance of the settings dialog
6530
- if ( this.dialog === null ) {
6531
- // Create the dialog
6532
- this.dialog = new panels.dialog.row();
6533
- this.dialog.setBuilder( this.builder ).setRowModel( this.model );
6534
- this.dialog.rowView = this;
6535
- }
6536
-
6537
- this.dialog.openDialog();
6538
-
6539
- return this;
6540
- },
6541
-
6542
- /**
6543
- * Handle deleting this entire row.
6544
- */
6545
- deleteHandler: function () {
6546
- this.model.destroy();
6547
- return this;
6548
- },
6549
-
6550
- /**
6551
- * Change the row background color.
6552
- */
6553
- rowColorChangeHandler: function ( event ) {
6554
- this.$( '.so-row-color' ).removeClass( 'so-row-color-selected' );
6555
- var clickedColorElem = $( event.target );
6556
- var newColorLabel = clickedColorElem.data( 'color-label' );
6557
- var oldColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
6558
- clickedColorElem.addClass( 'so-row-color-selected' );
6559
- this.$el.removeClass( 'so-row-color-' + oldColorLabel );
6560
- this.$el.addClass( 'so-row-color-' + newColorLabel );
6561
- this.model.set( 'color_label', newColorLabel );
6562
- },
6563
-
6564
- /**
6565
- * Handle a new cell being added to this row view. For now we'll assume the new cell is always last
6566
- */
6567
- handleCellAdd: function ( cell ) {
6568
- var cellView = new panels.view.cell( {
6569
- model: cell
6570
- } );
6571
- cellView.row = this;
6572
- cellView.render();
6573
- cellView.$el.appendTo( this.$( '.so-cells' ) );
6574
- },
6575
-
6576
- /**
6577
- * Handle a cell being removed from this row view
6578
- */
6579
- handleCellRemove: function ( cell ) {
6580
- // Find the view that ties in to the cell we're removing
6581
- this.$( '.so-cells > .cell' ).each( function () {
6582
- var view = $( this ).data( 'view' );
6583
- if ( _.isUndefined( view ) ) {
6584
- return;
6585
- }
6586
-
6587
- if ( view.model.cid === cell.cid ) {
6588
- // Remove this view
6589
- view.remove();
6590
- }
6591
- } );
6592
- },
6593
-
6594
- /**
6595
- * Build up the contextual menu for a row
6596
- *
6597
- * @param e
6598
- * @param menu
6599
- */
6600
- buildContextualMenu: function ( e, menu ) {
6601
- var options = [];
6602
- for ( var i = 1; i < 5; i ++ ) {
6603
- options.push( {
6604
- title: i + ' ' + panelsOptions.loc.contextual.column
6605
- } );
6606
- }
6607
-
6608
- if( this.builder.supports( 'addRow' ) ) {
6609
- menu.addSection(
6610
- 'add-row',
6611
- {
6612
- sectionTitle: panelsOptions.loc.contextual.add_row,
6613
- search: false
6614
- },
6615
- options,
6616
- function ( c ) {
6617
- this.builder.addHistoryEntry( 'row_added' );
6618
-
6619
- var columns = Number( c ) + 1;
6620
- var weights = [];
6621
- for ( var i = 0; i < columns; i ++ ) {
6622
- weights.push( {weight: 100 / columns } );
6623
- }
6624
-
6625
- // Create the actual row
6626
- var newRow = new panels.model.row( {
6627
- collection: this.collection
6628
- } );
6629
-
6630
- var cells = new panels.collection.cells(weights);
6631
- cells.each(function (cell) {
6632
- cell.row = newRow;
6633
- });
6634
- newRow.setCells(cells);
6635
- newRow.builder = this.builder.model;
6636
-
6637
- this.builder.model.get('rows').add( newRow, {
6638
- at: this.builder.model.get('rows').indexOf( this.model ) + 1
6639
- } );
6640
-
6641
- this.builder.model.refreshPanelsData();
6642
- }.bind( this )
6643
- );
6644
- }
6645
-
6646
- var actions = {};
6647
-
6648
- if( this.builder.supports( 'editRow' ) ) {
6649
- actions.edit = { title: panelsOptions.loc.contextual.row_edit };
6650
- }
6651
-
6652
- // Copy and paste functions
6653
- if ( panels.helpers.clipboard.canCopyPaste() ) {
6654
- actions.copy = { title: panelsOptions.loc.contextual.row_copy };
6655
- if ( this.builder.supports( 'addRow' ) && panels.helpers.clipboard.isModel( 'row-model' ) ) {
6656
- actions.paste = { title: panelsOptions.loc.contextual.row_paste };
6657
- }
6658
- }
6659
-
6660
- if( this.builder.supports( 'addRow' ) ) {
6661
- actions.duplicate = { title: panelsOptions.loc.contextual.row_duplicate };
6662
- }
6663
-
6664
- if( this.builder.supports( 'deleteRow' ) ) {
6665
- actions.delete = { title: panelsOptions.loc.contextual.row_delete, confirm: true };
6666
- }
6667
-
6668
- if( ! _.isEmpty( actions ) ) {
6669
- menu.addSection(
6670
- 'row-actions',
6671
- {
6672
- sectionTitle: panelsOptions.loc.contextual.row_actions,
6673
- search: false,
6674
- },
6675
- actions,
6676
- function ( c ) {
6677
- switch ( c ) {
6678
- case 'edit':
6679
- this.editSettingsHandler();
6680
- break;
6681
- case 'copy':
6682
- this.copyHandler();
6683
- break;
6684
- case 'paste':
6685
- this.pasteHandler();
6686
- break;
6687
- case 'duplicate':
6688
- this.duplicateHandler();
6689
- break;
6690
- case 'delete':
6691
- this.visualDestroyModel();
6692
- break;
6693
- }
6694
- }.bind( this )
6695
- );
6696
- }
6697
- },
6698
- } );
6699
-
6700
- },{}],28:[function(require,module,exports){
6701
- var panels = window.panels, $ = jQuery;
6702
-
6703
- module.exports = Backbone.View.extend( {
6704
-
6705
- stylesLoaded: false,
6706
-
6707
- initialize: function () {
6708
-
6709
- },
6710
-
6711
- /**
6712
- * Render the visual styles object.
6713
- *
6714
- * @param stylesType
6715
- * @param postId
6716
- * @param args
6717
- */
6718
- render: function ( stylesType, postId, args ) {
6719
- if ( _.isUndefined( stylesType ) ) {
6720
- return;
6721
- }
6722
-
6723
- // Add in the default args
6724
- args = _.extend( {
6725
- builderType: '',
6726
- dialog: null
6727
- }, args );
6728
-
6729
- this.$el.addClass( 'so-visual-styles so-' + stylesType + '-styles so-panels-loading' );
6730
-
6731
- var postArgs = {
6732
- builderType: args.builderType
6733
- };
6734
-
6735
- if ( stylesType === 'cell') {
6736
- postArgs.index = args.index;
6737
- }
6738
-
6739
- // Load the form
6740
- $.post(
6741
- panelsOptions.ajaxurl,
6742
- {
6743
- action: 'so_panels_style_form',
6744
- type: stylesType,
6745
- style: this.model.get( 'style' ),
6746
- args: JSON.stringify( postArgs ),
6747
- postId: postId
6748
- },
6749
- null,
6750
- 'html'
6751
- ).done( function ( response ) {
6752
- this.$el.html( response );
6753
- this.setupFields();
6754
- this.stylesLoaded = true;
6755
- this.trigger( 'styles_loaded', !_.isEmpty( response ) );
6756
- if ( !_.isNull( args.dialog ) ) {
6757
- args.dialog.trigger( 'styles_loaded', !_.isEmpty( response ) );
6758
- }
6759
- }.bind( this ) )
6760
- .fail( function ( error ) {
6761
- var html;
6762
- if ( error && error.responseText ) {
6763
- html = error.responseText;
6764
- } else {
6765
- html = panelsOptions.forms.loadingFailed;
6766
- }
6767
-
6768
- this.$el.html( html );
6769
- }.bind( this ) )
6770
- .always( function () {
6771
- this.$el.removeClass( 'so-panels-loading' );
6772
- }.bind( this ) );
6773
-
6774
- return this;
6775
- },
6776
-
6777
- /**
6778
- * Attach the style view to the DOM.
6779
- *
6780
- * @param wrapper
6781
- */
6782
- attach: function ( wrapper ) {
6783
- wrapper.append( this.$el );
6784
- },
6785
-
6786
- /**
6787
- * Detach the styles view from the DOM
6788
- */
6789
- detach: function () {
6790
- this.$el.detach();
6791
- },
6792
-
6793
- /**
6794
- * Setup all the fields
6795
- */
6796
- setupFields: function () {
6797
-
6798
- // Set up the sections as collapsible
6799
- this.$( '.style-section-wrapper' ).each( function () {
6800
- var $s = $( this );
6801
-
6802
- $s.find( '.style-section-head' ).click( function ( e ) {
6803
- e.preventDefault();
6804
- $s.find( '.style-section-fields' ).slideToggle( 'fast' );
6805
- } );
6806
- } );
6807
-
6808
- // Set up the color fields
6809
- if ( ! _.isUndefined( $.fn.wpColorPicker ) ) {
6810
- if ( _.isObject( panelsOptions.wpColorPickerOptions.palettes ) && ! $.isArray( panelsOptions.wpColorPickerOptions.palettes ) ) {
6811
- panelsOptions.wpColorPickerOptions.palettes = $.map( panelsOptions.wpColorPickerOptions.palettes, function ( el ) {
6812
- return el;
6813
- } );
6814
- }
6815
- this.$( '.so-wp-color-field' ).wpColorPicker( panelsOptions.wpColorPickerOptions );
6816
- }
6817
-
6818
- // Set up the image select fields
6819
- this.$( '.style-field-image' ).each( function () {
6820
- var frame = null;
6821
- var $s = $( this );
6822
-
6823
- $s.find( '.so-image-selector' ).click( function ( e ) {
6824
- e.preventDefault();
6825
-
6826
- if ( frame === null ) {
6827
- // Create the media frame.
6828
- frame = wp.media( {
6829
- // Set the title of the modal.
6830
- title: 'choose',
6831
-
6832
- // Tell the modal to show only images.
6833
- library: {
6834
- type: 'image'
6835
- },
6836
-
6837
- // Customize the submit button.
6838
- button: {
6839
- // Set the text of the button.
6840
- text: 'Done',
6841
- close: true
6842
- }
6843
- } );
6844
-
6845
- frame.on( 'select', function () {
6846
- var attachment = frame.state().get( 'selection' ).first().attributes;
6847
-
6848
- var url = attachment.url;
6849
- if ( ! _.isUndefined( attachment.sizes ) ) {
6850
- try {
6851
- url = attachment.sizes.thumbnail.url;
6852
- }
6853
- catch ( e ) {
6854
- // We'll use the full image instead
6855
- url = attachment.sizes.full.url;
6856
- }
6857
- }
6858
- $s.find( '.current-image' ).css( 'background-image', 'url(' + url + ')' );
6859
-
6860
- // Store the ID
6861
- $s.find( '.so-image-selector > input' ).val( attachment.id );
6862
-
6863
- $s.find( '.remove-image' ).removeClass( 'hidden' );
6864
- } );
6865
- }
6866
-
6867
- frame.open();
6868
-
6869
- } );
6870
-
6871
- // Handle clicking on remove
6872
- $s.find( '.remove-image' ).click( function ( e ) {
6873
- e.preventDefault();
6874
- $s.find( '.current-image' ).css( 'background-image', 'none' );
6875
- $s.find( '.so-image-selector > input' ).val( '' );
6876
- $s.find( '.remove-image' ).addClass( 'hidden' );
6877
- } );
6878
- } );
6879
-
6880
- // Set up all the measurement fields
6881
- this.$( '.style-field-measurement' ).each( function () {
6882
- var $$ = $( this );
6883
-
6884
- var text = $$.find( 'input[type="text"]' );
6885
- var unit = $$.find( 'select' );
6886
- var hidden = $$.find( 'input[type="hidden"]' );
6887
-
6888
- text.focus( function(){
6889
- $(this).select();
6890
- } );
6891
-
6892
- /**
6893
- * Load value into the visible input fields.
6894
- * @param value
6895
- */
6896
- var loadValue = function( value ) {
6897
- if( value === '' ) {
6898
- return;
6899
- }
6900
-
6901
- var re = /(?:([0-9\.,\-]+)(.*))+/;
6902
- var valueList = hidden.val().split( ' ' );
6903
- var valueListValue = [];
6904
- for ( var i in valueList ) {
6905
- var match = re.exec( valueList[i] );
6906
- if ( ! _.isNull( match ) && ! _.isUndefined( match[1] ) && ! _.isUndefined( match[2] ) ) {
6907
- valueListValue.push( match[1] );
6908
- unit.val( match[2] );
6909
- }
6910
- }
6911
-
6912
- if( text.length === 1 ) {
6913
- // This is a single input text field
6914
- text.val( valueListValue.join( ' ' ) );
6915
- }
6916
- else {
6917
- // We're dealing with a multiple field
6918
- if( valueListValue.length === 1 ) {
6919
- valueListValue = [ valueListValue[0], valueListValue[0], valueListValue[0], valueListValue[0] ];
6920
- }
6921
- else if( valueListValue.length === 2 ) {
6922
- valueListValue = [ valueListValue[0], valueListValue[1], valueListValue[0], valueListValue[1] ];
6923
- }
6924
- else if( valueListValue.length === 3 ) {
6925
- valueListValue = [ valueListValue[0], valueListValue[1], valueListValue[2], valueListValue[1] ];
6926
- }
6927
-
6928
- // Store this in the visible fields
6929
- text.each( function( i, el ) {
6930
- $( el ).val( valueListValue[i] );
6931
- } );
6932
- }
6933
- };
6934
- loadValue( hidden.val() );
6935
-
6936
- /**
6937
- * Set value of the hidden field based on inputs
6938
- */
6939
- var setValue = function( e ){
6940
- var i;
6941
-
6942
- if( text.length === 1 ) {
6943
- // We're dealing with a single measurement
6944
- var fullString = text
6945
- .val()
6946
- .split( ' ' )
6947
- .filter( function ( value ) {
6948
- return value !== '';
6949
- } )
6950
- .map( function ( value ) {
6951
- return value + unit.val();
6952
- } )
6953
- .join( ' ' );
6954
- hidden.val( fullString );
6955
- }
6956
- else {
6957
- var target = $( e.target ),
6958
- valueList = [],
6959
- emptyIndex = [],
6960
- fullIndex = [];
6961
-
6962
- text.each( function( i, el ) {
6963
- var value = $( el ).val( ) !== '' ? parseFloat( $( el ).val( ) ) : null;
6964
- valueList.push( value );
6965
-
6966
- if( value === null ) {
6967
- emptyIndex.push( i );
6968
- }
6969
- else {
6970
- fullIndex.push( i );
6971
- }
6972
- } );
6973
-
6974
- if( emptyIndex.length === 3 && fullIndex[0] === text.index( target ) ) {
6975
- text.val( target.val() );
6976
- valueList = [ target.val(), target.val(), target.val(), target.val() ];
6977
- }
6978
-
6979
- if( JSON.stringify( valueList ) === JSON.stringify( [ null, null, null, null ] ) ) {
6980
- hidden.val('');
6981
- }
6982
- else {
6983
- hidden.val( valueList.map( function( k ){
6984
- return ( k === null ? 0 : k ) + unit.val();
6985
- } ).join( ' ' ) );
6986
- }
6987
- }
6988
- };
6989
-
6990
- // Set the value when ever anything changes
6991
- text.change( setValue );
6992
- unit.change( setValue );
6993
- } );
6994
- }
6995
-
6996
- } );
6997
-
6998
- },{}],29:[function(require,module,exports){
6999
- var panels = window.panels, $ = jQuery;
7000
-
7001
- module.exports = Backbone.View.extend( {
7002
- template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-widget' ).html() ) ),
7003
-
7004
- // The cell view that this widget belongs to
7005
- cell: null,
7006
-
7007
- // The edit dialog
7008
- dialog: null,
7009
-
7010
- events: {
7011
- 'click .widget-edit': 'editHandler',
7012
- 'click .title h4': 'editHandler',
7013
- 'click .actions .widget-duplicate': 'duplicateHandler',
7014
- 'click .actions .widget-delete': 'deleteHandler'
7015
- },
7016
-
7017
- /**
7018
- * Initialize the widget
7019
- */
7020
- initialize: function () {
7021
- this.listenTo(this.model, 'destroy', this.onModelDestroy);
7022
- this.listenTo(this.model, 'change:values', this.onModelChange);
7023
- this.listenTo(this.model, 'change:label', this.onLabelChange);
7024
- },
7025
-
7026
- /**
7027
- * Render the widget
7028
- */
7029
- render: function ( options ) {
7030
- options = _.extend( {'loadForm': false}, options );
7031
-
7032
- this.setElement( this.template( {
7033
- title: this.model.getWidgetField( 'title' ),
7034
- description: this.model.getTitle()
7035
- } ) );
7036
-
7037
- this.$el.data( 'view', this );
7038
-
7039
- // Remove any unsupported actions
7040
- if( ! this.cell.row.builder.supports( 'editWidget' ) || this.model.get( 'read_only' ) ) {
7041
- this.$( '.actions .widget-edit' ).remove();
7042
- this.$el.addClass('so-widget-no-edit');
7043
- }
7044
- if( ! this.cell.row.builder.supports( 'addWidget' ) ) {
7045
- this.$( '.actions .widget-duplicate' ).remove();
7046
- this.$el.addClass('so-widget-no-duplicate');
7047
- }
7048
- if( ! this.cell.row.builder.supports( 'deleteWidget' ) ) {
7049
- this.$( '.actions .widget-delete' ).remove();
7050
- this.$el.addClass('so-widget-no-delete');
7051
- }
7052
- if( ! this.cell.row.builder.supports( 'moveWidget' ) ) {
7053
- this.$el.addClass('so-widget-no-move');
7054
- }
7055
- if( !$.trim( this.$('.actions').html() ).length ) {
7056
- this.$( '.actions' ).remove();
7057
- }
7058
-
7059
- if( this.model.get( 'read_only' ) ) {
7060
- this.$el.addClass('so-widget-read-only');
7061
- }
7062
-
7063
- if ( _.size( this.model.get( 'values' ) ) === 0 || options.loadForm ) {
7064
- // If this widget doesn't have a value, create a form and save it
7065
- var dialog = this.getEditDialog();
7066
-
7067
- // Save the widget as soon as the form is loaded
7068
- dialog.once( 'form_loaded', dialog.saveWidget, dialog );
7069
-
7070
- // Setup the dialog to load the form
7071
- dialog.setupDialog();
7072
- }
7073
-
7074
- // Add the global builder listeners
7075
- this.listenTo(this.cell.row.builder, 'after_user_adds_widget', this.afterUserAddsWidgetHandler);
7076
-
7077
- return this;
7078
- },
7079
-
7080
- /**
7081
- * Display an animation that implies creation using a visual animation
7082
- */
7083
- visualCreate: function () {
7084
- this.$el.hide().fadeIn( 'fast' );
7085
- },
7086
-
7087
- /**
7088
- * Get the dialog view of the form that edits this widget
7089
- *
7090
- * @returns {null}
7091
- */
7092
- getEditDialog: function () {
7093
- if ( this.dialog === null ) {
7094
- this.dialog = new panels.dialog.widget( {
7095
- model: this.model
7096
- } );
7097
- this.dialog.setBuilder( this.cell.row.builder );
7098
-
7099
- // Store the widget view
7100
- this.dialog.widgetView = this;
7101
- }
7102
- return this.dialog;
7103
- },
7104
-
7105
- /**
7106
- * Handle clicking on edit widget.
7107
- */
7108
- editHandler: function () {
7109
- // Create a new dialog for editing this
7110
- if ( ! this.cell.row.builder.supports( 'editWidget' ) || this.model.get( 'read_only' ) ) {
7111
- return this;
7112
- }
7113
-
7114
- this.getEditDialog().openDialog();
7115
- return this;
7116
- },
7117
-
7118
- /**
7119
- * Handle clicking on duplicate.
7120
- *
7121
- * @returns {boolean}
7122
- */
7123
- duplicateHandler: function () {
7124
- // Add the history entry
7125
- this.cell.row.builder.addHistoryEntry( 'widget_duplicated' );
7126
-
7127
- // Create the new widget and connect it to the widget collection for the current row
7128
- var newWidget = this.model.clone( this.model.cell );
7129
-
7130
- this.cell.model.get('widgets').add( newWidget, {
7131
- // Add this after the existing model
7132
- at: this.model.collection.indexOf( this.model ) + 1
7133
- } );
7134
-
7135
- this.cell.row.builder.model.refreshPanelsData();
7136
- return this;
7137
- },
7138
-
7139
- /**
7140
- * Copy the row to a cookie based clipboard
7141
- */
7142
- copyHandler: function(){
7143
- panels.helpers.clipboard.setModel( this.model );
7144
- },
7145
-
7146
- /**
7147
- * Handle clicking on delete.
7148
- *
7149
- * @returns {boolean}
7150
- */
7151
- deleteHandler: function () {
7152
- this.visualDestroyModel();
7153
- return this;
7154
- },
7155
-
7156
- onModelChange: function () {
7157
- // Update the description when ever the model changes
7158
- this.$( '.description' ).html( this.model.getTitle() );
7159
- },
7160
-
7161
- onLabelChange: function( model ) {
7162
- this.$( '.title > h4' ).text( model.getWidgetField( 'title' ) );
7163
- },
7164
-
7165
- /**
7166
- * When the model is destroyed, fade it out
7167
- */
7168
- onModelDestroy: function () {
7169
- this.remove();
7170
- },
7171
-
7172
- /**
7173
- * Visually destroy a model
7174
- */
7175
- visualDestroyModel: function () {
7176
- // Add the history entry
7177
- this.cell.row.builder.addHistoryEntry( 'widget_deleted' );
7178
-
7179
- this.$el.fadeOut( 'fast', function () {
7180
- this.cell.row.resize();
7181
- this.model.destroy();
7182
- this.cell.row.builder.model.refreshPanelsData();
7183
- this.remove();
7184
- }.bind(this) );
7185
-
7186
- return this;
7187
- },
7188
-
7189
- /**
7190
- * Build up the contextual menu for a widget
7191
- *
7192
- * @param e
7193
- * @param menu
7194
- */
7195
- buildContextualMenu: function ( e, menu ) {
7196
- if( this.cell.row.builder.supports( 'addWidget' ) ) {
7197
- menu.addSection(
7198
- 'add-widget-below',
7199
- {
7200
- sectionTitle: panelsOptions.loc.contextual.add_widget_below,
7201
- searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
7202
- defaultDisplay: panelsOptions.contextual.default_widgets
7203
- },
7204
- panelsOptions.widgets,
7205
- function ( c ) {
7206
- this.cell.row.builder.trigger('before_user_adds_widget');
7207
- this.cell.row.builder.addHistoryEntry( 'widget_added' );
7208
-
7209
- var widget = new panels.model.widget( {
7210
- class: c
7211
- } );
7212
- widget.cell = this.cell.model;
7213
-
7214
- // Insert the new widget below
7215
- this.cell.model.get('widgets').add( widget, {
7216
- // Add this after the existing model
7217
- at: this.model.collection.indexOf( this.model ) + 1
7218
- } );
7219
-
7220
- this.cell.row.builder.model.refreshPanelsData();
7221
-
7222
- this.cell.row.builder.trigger('after_user_adds_widget', widget);
7223
- }.bind( this )
7224
- );
7225
- }
7226
-
7227
- var actions = {};
7228
-
7229
- if( this.cell.row.builder.supports( 'editWidget' ) && ! this.model.get( 'read_only' ) ) {
7230
- actions.edit = { title: panelsOptions.loc.contextual.widget_edit };
7231
- }
7232
-
7233
- // Copy and paste functions
7234
- if ( panels.helpers.clipboard.canCopyPaste() ) {
7235
- actions.copy = {title: panelsOptions.loc.contextual.widget_copy};
7236
- }
7237
-
7238
- if( this.cell.row.builder.supports( 'addWidget' ) ) {
7239
- actions.duplicate = { title: panelsOptions.loc.contextual.widget_duplicate };
7240
- }
7241
-
7242
- if( this.cell.row.builder.supports( 'deleteWidget' ) ) {
7243
- actions.delete = { title: panelsOptions.loc.contextual.widget_delete, confirm: true };
7244
- }
7245
-
7246
- if( ! _.isEmpty( actions ) ) {
7247
- menu.addSection(
7248
- 'widget-actions',
7249
- {
7250
- sectionTitle: panelsOptions.loc.contextual.widget_actions,
7251
- search: false,
7252
- },
7253
- actions,
7254
- function ( c ) {
7255
- switch ( c ) {
7256
- case 'edit':
7257
- this.editHandler();
7258
- break;
7259
- case 'copy':
7260
- this.copyHandler();
7261
- break;
7262
- case 'duplicate':
7263
- this.duplicateHandler();
7264
- break;
7265
- case 'delete':
7266
- this.visualDestroyModel();
7267
- break;
7268
- }
7269
- }.bind( this )
7270
- );
7271
- }
7272
-
7273
- // Lets also add the contextual menu for the entire row
7274
- this.cell.buildContextualMenu( e, menu );
7275
- },
7276
-
7277
- /**
7278
- * Handler for any action after the user adds a new widget.
7279
- * @param widget
7280
- */
7281
- afterUserAddsWidgetHandler: function( widget ) {
7282
- if( this.model === widget && panelsOptions.instant_open ) {
7283
- setTimeout(this.editHandler.bind(this), 350);
7284
- }
7285
- }
7286
-
7287
- } );
7288
-
7289
- },{}],30:[function(require,module,exports){
7290
- var $ = jQuery;
7291
-
7292
- var customHtmlWidget = {
7293
- addWidget: function( idBase, widgetContainer, widgetId ) {
7294
- var component = wp.customHtmlWidgets;
7295
-
7296
- var fieldContainer = $( '<div></div>' );
7297
- var syncContainer = widgetContainer.find( '.widget-content:first' );
7298
- syncContainer.before( fieldContainer );
7299
-
7300
- var widgetControl = new component.CustomHtmlWidgetControl( {
7301
- el: fieldContainer,
7302
- syncContainer: syncContainer,
7303
- } );
7304
-
7305
- widgetControl.initializeEditor();
7306
-
7307
- // HACK: To ensure CodeMirror resize for the gutter.
7308
- widgetControl.editor.codemirror.refresh();
7309
-
7310
- return widgetControl;
7311
- }
7312
- };
7313
-
7314
- module.exports = customHtmlWidget;
7315
-
7316
- },{}],31:[function(require,module,exports){
7317
- var customHtmlWidget = require( './custom-html-widget' );
7318
- var mediaWidget = require( './media-widget' );
7319
- var textWidget = require( './text-widget' );
7320
-
7321
- var jsWidget = {
7322
- CUSTOM_HTML: 'custom_html',
7323
- MEDIA_AUDIO: 'media_audio',
7324
- MEDIA_GALLERY: 'media_gallery',
7325
- MEDIA_IMAGE: 'media_image',
7326
- MEDIA_VIDEO: 'media_video',
7327
- TEXT: 'text',
7328
-
7329
- addWidget: function( widgetContainer, widgetId ) {
7330
- var idBase = widgetContainer.find( '> .id_base' ).val();
7331
- var widget;
7332
-
7333
- switch ( idBase ) {
7334
- case this.CUSTOM_HTML:
7335
- widget = customHtmlWidget;
7336
- break;
7337
- case this.MEDIA_AUDIO:
7338
- case this.MEDIA_GALLERY:
7339
- case this.MEDIA_IMAGE:
7340
- case this.MEDIA_VIDEO:
7341
- widget = mediaWidget;
7342
- break;
7343
- case this.TEXT:
7344
- widget = textWidget;
7345
- break
7346
- }
7347
-
7348
- widget.addWidget( idBase, widgetContainer, widgetId );
7349
- },
7350
- };
7351
-
7352
- module.exports = jsWidget;
7353
-
7354
- },{"./custom-html-widget":30,"./media-widget":32,"./text-widget":33}],32:[function(require,module,exports){
7355
- var $ = jQuery;
7356
-
7357
- var mediaWidget = {
7358
- addWidget: function( idBase, widgetContainer, widgetId ) {
7359
- var component = wp.mediaWidgets;
7360
-
7361
- var ControlConstructor = component.controlConstructors[ idBase ];
7362
- if ( ! ControlConstructor ) {
7363
- return;
7364
- }
7365
-
7366
- var ModelConstructor = component.modelConstructors[ idBase ] || component.MediaWidgetModel;
7367
- var syncContainer = widgetContainer.find( '> .widget-content' );
7368
- var controlContainer = $( '<div class="media-widget-control"></div>' );
7369
- syncContainer.before( controlContainer );
7370
-
7371
- var modelAttributes = {};
7372
- syncContainer.find( '.media-widget-instance-property' ).each( function() {
7373
- var input = $( this );
7374
- modelAttributes[ input.data( 'property' ) ] = input.val();
7375
- });
7376
- modelAttributes.widget_id = widgetId;
7377
-
7378
- var widgetModel = new ModelConstructor( modelAttributes );
7379
-
7380
- var widgetControl = new ControlConstructor({
7381
- el: controlContainer,
7382
- syncContainer: syncContainer,
7383
- model: widgetModel,
7384
- });
7385
-
7386
- widgetControl.render();
7387
-
7388
- return widgetControl;
7389
- }
7390
- };
7391
-
7392
- module.exports = mediaWidget;
7393
-
7394
- },{}],33:[function(require,module,exports){
7395
- var $ = jQuery;
7396
-
7397
- var textWidget = {
7398
- addWidget: function( idBase, widgetContainer, widgetId ) {
7399
- var component = wp.textWidgets;
7400
-
7401
- var options = {};
7402
- var visualField = widgetContainer.find( '.visual' );
7403
- // 'visual' field and syncContainer were introduced together in 4.8.1
7404
- if ( visualField.length > 0 ) {
7405
- // If 'visual' field has no value it's a legacy text widget.
7406
- if ( ! visualField.val() ) {
7407
- return null;
7408
- }
7409
-
7410
- var fieldContainer = $( '<div></div>' );
7411
- var syncContainer = widgetContainer.find( '.widget-content:first' );
7412
- syncContainer.before( fieldContainer );
7413
-
7414
- options = {
7415
- el: fieldContainer,
7416
- syncContainer: syncContainer,
7417
- };
7418
- } else {
7419
- options = { el: widgetContainer };
7420
- }
7421
-
7422
- var widgetControl = new component.TextWidgetControl( options );
7423
- var wpEditor = wp.oldEditor ? wp.oldEditor : wp.editor;
7424
- if ( wpEditor && wpEditor.hasOwnProperty( 'autop' ) ) {
7425
- wp.editor.autop = wpEditor.autop;
7426
- wp.editor.removep = wpEditor.removep;
7427
- wp.editor.initialize = wpEditor.initialize
7428
- }
7429
-
7430
- widgetControl.initializeEditor();
7431
-
7432
- return widgetControl;
7433
- }
7434
- };
7435
-
7436
- module.exports = textWidget;
7437
-
7438
- },{}]},{},[16]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/siteorigin-panels-2101.min.js DELETED
@@ -1 +0,0 @@
1
- !function o(n,a,r){function d(t,e){if(!a[t]){if(!n[t]){var i="function"==typeof require&&require;if(!e&&i)return i(t,!0);if(h)return h(t,!0);var s=new Error("Cannot find module '"+t+"'");throw s.code="MODULE_NOT_FOUND",s}var l=a[t]={exports:{}};n[t][0].call(l.exports,function(e){return d(n[t][1][e]||e)},l,l.exports,o,n,a,r)}return a[t].exports}for(var h="function"==typeof require&&require,e=0;e<r.length;e++)d(r[e]);return d}({1:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.cell,initialize:function(){},totalWeight:function(){var t=0;return this.each(function(e){t+=e.get("weight")}),t}})},{}],2:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.historyEntry,builder:null,maxSize:12,initialize:function(){this.on("add",this.onAddEntry,this)},addEntry:function(e,t){_.isEmpty(t)&&(t=this.builder.getPanelsData());var i=new s.model.historyEntry({text:e,data:JSON.stringify(t),time:parseInt((new Date).getTime()/1e3),collection:this});this.add(i)},onAddEntry:function(e){if(1<this.models.length){var t=this.at(this.models.length-2);(e.get("text")===t.get("text")&&e.get("time")-t.get("time")<15||e.get("data")===t.get("data"))&&(this.remove(e),t.set("count",t.get("count")+1))}for(;this.models.length>this.maxSize;)this.shift()}})},{}],3:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.row,empty:function(){for(var e;;){if(!(e=this.collection.first()))break;e.destroy()}}})},{}],4:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.widget,initialize:function(){}})},{}],5:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({dialogClass:"so-panels-dialog-add-builder",render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-builder").html(),{})),this.$(".so-content .siteorigin-panels-builder").append(this.builder.$el)},initializeDialog:function(){var e=this;this.once("open_dialog_complete",function(){e.builder.initSortable()}),this.on("open_dialog_complete",function(){e.builder.trigger("builder_resize")})}})},{}],6:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({historyEntryTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-history-entry").html())),entries:{},currentEntry:null,revertEntry:null,selectedEntry:null,previewScrollTop:null,dialogClass:"so-panels-dialog-history",dialogIcon:"history",events:{"click .so-close":"closeDialog","click .so-restore":"restoreSelectedEntry"},initializeDialog:function(){this.entries=new s.collection.historyEntries,this.on("open_dialog",this.setCurrentEntry,this),this.on("open_dialog",this.renderHistoryEntries,this)},render:function(){var t=this;this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-history").html(),{})),this.$("iframe.siteorigin-panels-history-iframe").load(function(){var e=l(this);e.show(),e.contents().scrollTop(t.previewScrollTop)})},setRevertEntry:function(e){this.revertEntry=new s.model.historyEntry({data:JSON.stringify(e.getPanelsData()),time:parseInt((new Date).getTime()/1e3)})},setCurrentEntry:function(){this.currentEntry=new s.model.historyEntry({data:JSON.stringify(this.builder.model.getPanelsData()),time:parseInt((new Date).getTime()/1e3)}),this.selectedEntry=this.currentEntry,this.previewEntry(this.currentEntry),this.$(".so-buttons .so-restore").addClass("disabled")},renderHistoryEntries:function(){var i=this,s=this.$(".history-entries").empty();this.currentEntry.get("data")===this.revertEntry.get("data")&&_.isEmpty(this.entries.models)||l(this.historyEntryTemplate({title:panelsOptions.loc.history.revert,count:1})).data("historyEntry",this.revertEntry).prependTo(s),this.entries.each(function(e){var t=i.historyEntryTemplate({title:panelsOptions.loc.history[e.get("text")],count:e.get("count")});l(t).data("historyEntry",e).prependTo(s)}),l(this.historyEntryTemplate({title:panelsOptions.loc.history.current,count:1})).data("historyEntry",this.currentEntry).addClass("so-selected").prependTo(s),s.find(".history-entry").click(function(){var e=jQuery(this);s.find(".history-entry").not(e).removeClass("so-selected"),e.addClass("so-selected");var t=e.data("historyEntry");i.selectedEntry=t,i.selectedEntry.cid!==i.currentEntry.cid?i.$(".so-buttons .so-restore").removeClass("disabled"):i.$(".so-buttons .so-restore").addClass("disabled"),i.previewEntry(t)}),this.updateEntryTimes()},previewEntry:function(e){var t=this.$("iframe.siteorigin-panels-history-iframe");t.hide(),this.previewScrollTop=t.contents().scrollTop(),this.$('form.history-form input[name="live_editor_panels_data"]').val(e.get("data")),this.$('form.history-form input[name="live_editor_post_ID"]').val(this.builder.config.postId),this.$("form.history-form").submit()},restoreSelectedEntry:function(){return this.$(".so-buttons .so-restore").hasClass("disabled")||(this.currentEntry.get("data")===this.selectedEntry.get("data")||("restore"!==this.selectedEntry.get("text")&&this.builder.addHistoryEntry("restore",this.builder.model.getPanelsData()),this.builder.model.loadPanelsData(JSON.parse(this.selectedEntry.get("data")))),this.closeDialog()),!1},updateEntryTimes:function(){var s=this;this.$(".history-entries .history-entry").each(function(){var e=jQuery(this),t=e.find(".timesince"),i=e.data("historyEntry");t.html(s.timeSince(i.get("time")))})},timeSince:function(e){var t,i=parseInt((new Date).getTime()/1e3)-e,s=[];return 3600<i&&(1===(t=Math.floor(i/3600))?s.push(panelsOptions.loc.time.hour.replace("%d",t)):s.push(panelsOptions.loc.time.hours.replace("%d",t)),i-=3600*t),60<i&&(1===(t=Math.floor(i/60))?s.push(panelsOptions.loc.time.minute.replace("%d",t)):s.push(panelsOptions.loc.time.minutes.replace("%d",t)),i-=60*t),0<i&&(1===i?s.push(panelsOptions.loc.time.second.replace("%d",i)):s.push(panelsOptions.loc.time.seconds.replace("%d",i))),_.isEmpty(s)?panelsOptions.loc.time.now:panelsOptions.loc.time.ago.replace("%s",s.slice(0,2).join(", "))}})},{}],7:[function(e,t,i){var s=window.panels,r=jQuery;t.exports=s.view.dialog.extend({directoryTemplate:_.template(s.helpers.utils.processTemplate(r("#siteorigin-panels-directory-items").html())),builder:null,dialogClass:"so-panels-dialog-prebuilt-layouts",dialogIcon:"layouts",layoutCache:{},currentTab:!1,directoryPage:1,events:{"click .so-close":"closeDialog","click .so-sidebar-tabs li a":"tabClickHandler","click .so-content .layout":"layoutClickHandler","keyup .so-sidebar-search":"searchHandler","click .so-screenshot, .so-title":"directoryItemClickHandler"},initializeDialog:function(){var e=this;this.on("open_dialog",function(){e.$(".so-sidebar-tabs li a").first().click(),e.$(".so-status").removeClass("so-panels-loading")}),this.on("button_click",this.toolbarButtonClick,this)},render:function(){this.renderDialog(this.parseDialogContent(r("#siteorigin-panels-dialog-prebuilt").html(),{})),this.initToolbar()},tabClickHandler:function(e){e.preventDefault(),this.selectedLayoutItem=null,this.uploadedLayout=null,this.updateButtonState(!1),this.$(".so-sidebar-tabs li").removeClass("tab-active");var t=r(e.target),i=t.attr("href").split("#")[1];t.parent().addClass("tab-active");this.$(".so-content").empty(),"import"==(this.currentTab=i)?this.displayImportExport():this.displayLayoutDirectory("",1,i),this.$(".so-sidebar-search").val("")},displayImportExport:function(){var e=this.$(".so-content").empty().removeClass("so-panels-loading");e.html(r("#siteorigin-panels-dialog-prebuilt-importexport").html());var l=this,o=l.$(".import-upload-ui"),t=new plupload.Uploader({runtimes:"html5,silverlight,flash,html4",browse_button:o.find(".file-browse-button").get(0),container:o.get(0),drop_element:o.find(".drag-upload-area").get(0),file_data_name:"panels_import_data",multiple_queues:!1,max_file_size:panelsOptions.plupload.max_file_size,url:panelsOptions.plupload.url,flash_swf_url:panelsOptions.plupload.flash_swf_url,silverlight_xap_url:panelsOptions.plupload.silverlight_xap_url,filters:[{title:panelsOptions.plupload.filter_title,extensions:"json"}],multipart_params:{action:"so_panels_import_layout"},init:{PostInit:function(e){e.features.dragdrop&&o.addClass("has-drag-drop"),o.find(".progress-precent").css("width","0%")},FilesAdded:function(e){o.find(".file-browse-button").blur(),o.find(".drag-upload-area").removeClass("file-dragover"),o.find(".progress-bar").fadeIn("fast"),l.$(".js-so-selected-file").text(panelsOptions.loc.prebuilt_loading),e.start()},UploadProgress:function(e,t){o.find(".progress-precent").css("width",t.percent+"%")},FileUploaded:function(e,t,i){var s=JSON.parse(i.response);_.isUndefined(s.widgets)?alert(panelsOptions.plupload.error_message):(l.uploadedLayout=s,o.find(".progress-bar").hide(),l.$(".js-so-selected-file").text(panelsOptions.loc.ready_to_insert.replace("%s",t.name)),l.updateButtonState(!0))},Error:function(){alert(panelsOptions.plupload.error_message)}}});t.init(),/Edge\/\d./i.test(navigator.userAgent)&&setTimeout(function(){t.refresh()},250),o.find(".drag-upload-area").on("dragover",function(){r(this).addClass("file-dragover")}).on("dragleave",function(){r(this).removeClass("file-dragover")}),e.find(".so-export").submit(function(e){var t=r(this),i=l.builder.model.getPanelsData(),s=r('input[name="post_title"]').val();s||(s=r('input[name="post_ID"]').val()),i.name=s,t.find('input[name="panels_export_data"]').val(JSON.stringify(i))})},displayLayoutDirectory:function(s,l,o){var n=this,a=this.$(".so-content").empty().addClass("so-panels-loading");if(void 0===s&&(s=""),void 0===l&&(l=1),void 0===o&&(o="directory-siteorigin"),o.match("^directory-")&&!panelsOptions.directory_enabled)return a.removeClass("so-panels-loading").html(r("#siteorigin-panels-directory-enable").html()),void a.find(".so-panels-enable-directory").click(function(e){e.preventDefault(),r.get(panelsOptions.ajaxurl,{action:"so_panels_directory_enable"},function(){}),panelsOptions.directory_enabled=!0,a.addClass("so-panels-loading"),n.displayLayoutDirectory(s,l,o)});r.get(panelsOptions.ajaxurl,{action:"so_panels_layouts_query",search:s,page:l,type:o},function(e){if(n.currentTab===o){a.removeClass("so-panels-loading").html(n.directoryTemplate(e));var t=a.find(".so-previous"),i=a.find(".so-next");l<=1?t.addClass("button-disabled"):t.click(function(e){e.preventDefault(),n.displayLayoutDirectory(s,l-1,n.currentTab)}),l===e.max_num_pages||0===e.max_num_pages?i.addClass("button-disabled"):i.click(function(e){e.preventDefault(),n.displayLayoutDirectory(s,l+1,n.currentTab)}),a.find(".so-screenshot").each(function(){var e=r(this),t=e.find(".so-screenshot-wrapper");if(t.css("height",t.width()/4*3+"px").addClass("so-loading"),""!==e.data("src"))var i=r("<img/>").attr("src",e.data("src")).load(function(){t.removeClass("so-loading").css("height","auto"),i.appendTo(t).hide().fadeIn("fast")});else r("<img/>").attr("src",panelsOptions.prebuiltDefaultScreenshot).appendTo(t).hide().fadeIn("fast")}),a.find(".so-directory-browse").html(e.title)}},"json")},directoryItemClickHandler:function(e){var t=this.$(e.target).closest(".so-directory-item");this.$(".so-directory-items").find(".selected").removeClass("selected"),t.addClass("selected"),this.selectedLayoutItem={lid:t.data("layout-id"),type:t.data("layout-type")},this.updateButtonState(!0)},toolbarButtonClick:function(e){if(!this.canAddLayout())return!1;var t=e.data("value");if(_.isUndefined(t))return!1;if(this.updateButtonState(!1),e.hasClass("so-needs-confirm")&&!e.hasClass("so-confirmed")){if(this.updateButtonState(!0),e.hasClass("so-confirming"))return;e.addClass("so-confirming");var i=e.html();return e.html('<span class="dashicons dashicons-yes"></span>'+e.data("confirm")),setTimeout(function(){e.removeClass("so-confirmed").html(i)},2500),setTimeout(function(){e.removeClass("so-confirming"),e.addClass("so-confirmed")},200),!1}this.addingLayout=!0,"import"===this.currentTab?this.addLayoutToBuilder(this.uploadedLayout,t):this.loadSelectedLayout().then(function(e){this.addLayoutToBuilder(e,t)}.bind(this))},canAddLayout:function(){return(this.selectedLayoutItem||this.uploadedLayout)&&!this.addingLayout},loadSelectedLayout:function(){this.setStatusMessage(panelsOptions.loc.prebuilt_loading,!0);var e=_.extend(this.selectedLayoutItem,{action:"so_panels_get_layout"}),i=new r.Deferred;return r.get(panelsOptions.ajaxurl,e,function(e){var t="";e.success?i.resolve(e.data):(t=e.data.message,i.reject(e.data)),this.setStatusMessage(t,!1,!e.success),this.updateButtonState(!0)}.bind(this)),i.promise()},searchHandler:function(e){13===e.keyCode&&this.displayLayoutDirectory(r(e.currentTarget).val(),1,this.currentTab)},updateButtonState:function(e){e=e&&(this.selectedLayoutItem||this.uploadedLayout);var t=this.$(".so-import-layout");t.prop("disabled",!e),e?t.removeClass("disabled"):t.addClass("disabled")},addLayoutToBuilder:function(e,t){this.builder.addHistoryEntry("prebuilt_loaded"),this.builder.model.loadPanelsData(e,t),this.addingLayout=!1,this.closeDialog()}})},{}],8:[function(e,t,i){var a=window.panels,h=jQuery;t.exports=a.view.dialog.extend({cellPreviewTemplate:_.template(a.helpers.utils.processTemplate(h("#siteorigin-panels-dialog-row-cell-preview").html())),editableLabel:!0,events:{"click .so-close":"closeDialog","click .so-toolbar .so-save":"saveHandler","click .so-toolbar .so-insert":"insertHandler","click .so-toolbar .so-delete":"deleteHandler","click .so-toolbar .so-duplicate":"duplicateHandler","change .row-set-form > *":"setCellsFromForm","click .row-set-form button.set-row":"setCellsFromForm"},rowView:null,dialogIcon:"add-row",dialogClass:"so-panels-dialog-row-edit",styleType:"row",dialogType:"edit",row:{cells:null,style:{}},cellStylesCache:[],initializeDialog:function(){this.on("open_dialog",function(){_.isUndefined(this.model)||_.isEmpty(this.model.get("cells"))?this.setRowModel(null):this.setRowModel(this.model),this.regenerateRowPreview(),this.renderStyles()},this),this.row={cells:new a.collection.cells([{weight:.5},{weight:.5}]),style:{}},this.dialogFormsLoaded=0;var e=this;this.on("form_loaded styles_loaded",function(){this.dialogFormsLoaded++,2===this.dialogFormsLoaded&&e.updateModel({refreshArgs:{silent:!0}})}),this.on("close_dialog",this.closeHandler),this.on("edit_label",function(e){if(e!==panelsOptions.loc.row.add&&e!==panelsOptions.loc.row.edit||(e=""),this.model.set("label",e),_.isEmpty(e)){var t="create"===this.dialogType?panelsOptions.loc.row.add:panelsOptions.loc.row.edit;this.$(".so-title").text(t)}}.bind(this))},setRowDialogType:function(e){this.dialogType=e},render:function(){var e="create"===this.dialogType?panelsOptions.loc.row.add:panelsOptions.loc.row.edit;this.renderDialog(this.parseDialogContent(h("#siteorigin-panels-dialog-row").html(),{title:e,dialogType:this.dialogType}));var t=this.$(".so-title");return this.model.has("label")&&!_.isEmpty(this.model.get("label"))&&t.text(this.model.get("label")),this.$(".so-edit-title").val(t.text()),this.builder.supports("addRow")||this.$(".so-buttons .so-duplicate").remove(),this.builder.supports("deleteRow")||this.$(".so-buttons .so-delete").remove(),_.isUndefined(this.model)||(this.$('input[name="cells"].so-row-field').val(this.model.get("cells").length),this.model.has("ratio")&&this.$('select[name="ratio"].so-row-field').val(this.model.get("ratio")),this.model.has("ratio_direction")&&this.$('select[name="ratio_direction"].so-row-field').val(this.model.get("ratio_direction"))),this.$("input.so-row-field").keyup(function(){h(this).trigger("change")}),this},renderStyles:function(){this.styles&&(this.styles.off("styles_loaded"),this.styles.remove()),this.styles=new a.view.styles,this.styles.model=this.model,this.styles.render("row",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this});var t=this.$(".so-sidebar.so-right-sidebar");this.styles.attach(t),this.styles.on("styles_loaded",function(e){e||(this.styles.remove(),0===t.children().length&&(t.closest(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar"),t.hide()))},this)},setRowModel:function(e){return this.model=e,_.isEmpty(this.model)||(this.row={cells:this.model.get("cells").clone(),style:{},ratio:this.model.get("ratio"),ratio_direction:this.model.get("ratio_direction")},this.$('input[name="cells"].so-row-field').val(this.model.get("cells").length),this.model.has("ratio")&&this.$('select[name="ratio"].so-row-field').val(this.model.get("ratio")),this.model.has("ratio_direction")&&this.$('select[name="ratio_direction"].so-row-field').val(this.model.get("ratio_direction")),this.clearCellStylesCache()),this},regenerateRowPreview:function(){var t,r=this,d=this.$(".row-preview"),s=this.getSelectedCellIndex();d.empty(),this.row.cells.each(function(i,n){var o=h(this.cellPreviewTemplate({weight:i.get("weight")}));d.append(o),n==s&&o.find(".preview-cell-in").addClass("cell-selected");var e,a=o.prev();a.length&&((e=h('<div class="resize-handle"></div>')).appendTo(o).dblclick(function(){var e=r.row.cells.at(n-1),t=i.get("weight")+e.get("weight");i.set("weight",t/2),e.set("weight",t/2),r.scaleRowWidths()}),e.draggable({axis:"x",containment:d,start:function(e,t){var i=o.clone().appendTo(t.helper).css({position:"absolute",top:"0",width:o.outerWidth(),left:6,height:o.outerHeight()});i.find(".resize-handle").remove();var s=a.clone().appendTo(t.helper).css({position:"absolute",top:"0",width:a.outerWidth(),right:6,height:a.outerHeight()});s.find(".resize-handle").remove(),h(this).data({newCellClone:i,prevCellClone:s}),o.find("> .preview-cell-in").css("visibility","hidden"),a.find("> .preview-cell-in").css("visibility","hidden")},drag:function(e,t){var i=r.row.cells.at(n).get("weight"),s=r.row.cells.at(n-1).get("weight"),l=i-(t.position.left+6)/d.width(),o=s+(t.position.left+6)/d.width();t.helper.offset().left,d.offset().left;h(this).data("newCellClone").css("width",d.width()*l).find(".preview-cell-weight").html(Math.round(1e3*l)/10),h(this).data("prevCellClone").css("width",d.width()*o).find(".preview-cell-weight").html(Math.round(1e3*o)/10)},stop:function(e,t){h(this).data("newCellClone").remove(),h(this).data("prevCellClone").remove(),o.find(".preview-cell-in").css("visibility","visible"),a.find(".preview-cell-in").css("visibility","visible");var i=(t.position.left+6)/d.width(),s=r.row.cells.at(n),l=r.row.cells.at(n-1);.02<s.get("weight")-i&&.02<l.get("weight")+i&&(s.set("weight",s.get("weight")-i),l.set("weight",l.get("weight")+i)),r.scaleRowWidths(),t.helper.css("left",-6)}})),o.click(function(e){if(h(e.target).is(".preview-cell")||h(e.target).is(".preview-cell-in")){var t=h(e.target);t.closest(".row-preview").find(".preview-cell .preview-cell-in").removeClass("cell-selected"),t.addClass("cell-selected"),this.openSelectedCellStyles()}}.bind(this)),o.find(".preview-cell-weight").click(function(e){r.$(".resize-handle").css("pointer-event","none").draggable("disable"),d.find(".preview-cell-weight").each(function(){var e=jQuery(this).hide();h('<input type="text" class="preview-cell-weight-input no-user-interacted" />').val(parseFloat(e.html())).insertAfter(e).focus(function(){clearTimeout(t)}).keyup(function(e){9!==e.keyCode&&h(this).removeClass("no-user-interacted"),13===e.keyCode&&(e.preventDefault(),h(this).blur())}).keydown(function(e){if(9===e.keyCode){e.preventDefault();var t=d.find(".preview-cell-weight-input"),i=t.index(h(this));i===t.length-1?t.eq(0).focus().select():t.eq(i+1).focus().select()}}).blur(function(){d.find(".preview-cell-weight-input").each(function(e,t){isNaN(parseFloat(h(t).val()))&&h(t).val(Math.floor(1e3*r.row.cells.at(e).get("weight"))/10)}),t=setTimeout(function(){if(0===d.find(".preview-cell-weight-input").length)return!1;var l=[],o=[],n=0,a=0;if(d.find(".preview-cell-weight-input").each(function(e,t){var i=parseFloat(h(t).val());i=isNaN(i)?1/r.row.cells.length:Math.round(10*i)/1e3;var s=!h(t).hasClass("no-user-interacted");l.push(i),o.push(s),s?n+=i:a+=i}),0<n&&0<a&&0<1-n)for(var e=0;e<l.length;e++)o[e]||(l[e]=l[e]/a*(1-n));var t=_.reduce(l,function(e,t){return e+t});l=l.map(function(e){return e/t}),.01<Math.min.apply(Math,l)&&r.row.cells.each(function(e,t){e.set("weight",l[t])}),d.find(".preview-cell").each(function(e,t){var i=r.row.cells.at(e).get("weight");h(t).animate({width:Math.round(1e3*i)/10+"%"},250),h(t).find(".preview-cell-weight-input").val(Math.round(1e3*i)/10)}),d.find(".preview-cell").css("overflow","visible"),setTimeout(r.regenerateRowPreview.bind(r),260)},100)}).click(function(){h(this).select()})}),h(this).siblings(".preview-cell-weight-input").select()})},this),this.openSelectedCellStyles(),this.trigger("form_loaded",this)},getSelectedCellIndex:function(){var i=-1;return this.$(".preview-cell .preview-cell-in").each(function(e,t){h(t).is(".cell-selected")&&(i=e)}),i},openSelectedCellStyles:function(){if(!_.isUndefined(this.cellStyles)){if(this.cellStyles.stylesLoaded){var e={};try{e=this.getFormValues(".so-sidebar .so-visual-styles.so-cell-styles").style}catch(e){console.log("Error retrieving cell styles - "+e.message)}this.cellStyles.model.set("style",e)}this.cellStyles.detach()}if(this.cellStyles=this.getSelectedCellStyles(),this.cellStyles){var t=this.$(".so-sidebar.so-right-sidebar");this.cellStyles.attach(t),this.cellStyles.on("styles_loaded",function(e){e&&(t.closest(".so-panels-dialog").addClass("so-panels-dialog-has-right-sidebar"),t.show())})}},getSelectedCellStyles:function(){var e=this.getSelectedCellIndex();if(-1<e){var t=this.cellStylesCache[e];t||((t=new a.view.styles).model=this.row.cells.at(e),t.render("cell",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this,index:e}),this.cellStylesCache[e]=t)}return t},clearCellStylesCache:function(){this.cellStylesCache.forEach(function(e){e.remove()}),this.cellStylesCache=[]},scaleRowWidths:function(){var s=this;this.$(".row-preview .preview-cell").each(function(e,t){var i=s.row.cells.at(e);h(t).css("width",100*i.get("weight")+"%").find(".preview-cell-weight").html(Math.round(1e3*i.get("weight"))/10)})},setCellsFromForm:function(){try{var e={cells:parseInt(this.$('.row-set-form input[name="cells"]').val()),ratio:parseFloat(this.$('.row-set-form select[name="ratio"]').val()),direction:this.$('.row-set-form select[name="ratio_direction"]').val()};_.isNaN(e.cells)&&(e.cells=1),isNaN(e.ratio)&&(e.ratio=1),e.cells<1?(e.cells=1,this.$('.row-set-form input[name="cells"]').val(e.cells)):12<e.cells&&(e.cells=12,this.$('.row-set-form input[name="cells"]').val(e.cells)),this.$('.row-set-form select[name="ratio"]').val(e.ratio);for(var t=[],i=this.row.cells.length!==e.cells,s=1,l=0;l<e.cells;l++)t.push(s),s*=e.ratio;var o=_.reduce(t,function(e,t){return e+t});if(t=_.map(t,function(e){return e/o}),t=_.filter(t,function(e){return.01<e}),"left"===e.direction&&(t=t.reverse()),this.row.cells=new a.collection.cells(this.row.cells.first(t.length)),_.each(t,function(e,t){var i=this.row.cells.at(t);i?i.set("weight",e):(i=new a.model.cell({weight:e,row:this.model}),this.row.cells.add(i))}.bind(this)),this.row.ratio=e.ratio,this.row.ratio_direction=e.direction,i)this.regenerateRowPreview();else{var n=this;this.$(".preview-cell").each(function(e,t){var i=n.row.cells.at(e).get("weight");h(t).animate({width:Math.round(1e3*i)/10+"%"},250),h(t).find(".preview-cell-weight").html(Math.round(1e3*i)/10)}),this.$(".preview-cell").css("overflow","visible"),setTimeout(n.regenerateRowPreview.bind(n),260)}}catch(e){console.log("Error setting cells - "+e.message)}this.$(".row-set-form .so-button-row-set").removeClass("button-primary")},tabClickHandler:function(e){"#row-layout"===e.attr("href")?this.$(".so-panels-dialog").addClass("so-panels-dialog-has-right-sidebar"):this.$(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar")},updateModel:function(e){if(e=_.extend({refresh:!0,refreshArgs:null},e),_.isEmpty(this.model)||(this.model.setCells(this.row.cells),this.model.set("ratio",this.row.ratio),this.model.set("ratio_direction",this.row.ratio_direction)),!_.isUndefined(this.styles)&&this.styles.stylesLoaded){var t={};try{t=this.getFormValues(".so-sidebar .so-visual-styles.so-row-styles").style}catch(e){console.log("Error retrieving row styles - "+e.message)}this.model.set("style",t)}if(!_.isUndefined(this.cellStyles)&&this.cellStyles.stylesLoaded){t={};try{t=this.getFormValues(".so-sidebar .so-visual-styles.so-cell-styles").style}catch(e){console.log("Error retrieving cell styles - "+e.message)}this.cellStyles.model.set("style",t)}e.refresh&&this.builder.model.refreshPanelsData(e.refreshArgs)},insertHandler:function(){this.builder.addHistoryEntry("row_added"),this.updateModel();var e=this.builder.getActiveCell({createCell:!1}),t={};return null!==e&&(t.at=this.builder.model.get("rows").indexOf(e.row)+1),this.model.collection=this.builder.model.get("rows"),this.builder.model.get("rows").add(this.model,t),this.closeDialog(),this.builder.model.refreshPanelsData(),!1},saveHandler:function(){return this.builder.addHistoryEntry("row_edited"),this.updateModel(),this.closeDialog(),this.builder.model.refreshPanelsData(),!1},deleteHandler:function(){return this.rowView.visualDestroyModel(),this.closeDialog({silent:!0}),!1},duplicateHandler:function(){this.builder.addHistoryEntry("row_duplicated");var e=this.model.clone(this.builder.model);return this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.closeDialog({silent:!0}),!1},closeHandler:function(){this.clearCellStylesCache(),_.isUndefined(this.cellStyles)||(this.cellStyles=void 0)}})},{}],9:[function(e,t,i){var s=window.panels,l=jQuery,o=e("../view/widgets/js-widget");t.exports=s.view.dialog.extend({builder:null,sidebarWidgetTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-widget-sidebar-widget").html())),dialogClass:"so-panels-dialog-edit-widget",dialogIcon:"add-widget",widgetView:!1,savingWidget:!1,editableLabel:!0,events:{"click .so-close":"saveHandler","click .so-nav.so-previous":"navToPrevious","click .so-nav.so-next":"navToNext","click .so-toolbar .so-delete":"deleteHandler","click .so-toolbar .so-duplicate":"duplicateHandler"},initializeDialog:function(){var e=this;this.listenTo(this.model,"change:values",this.handleChangeValues),this.listenTo(this.model,"destroy",this.remove),this.dialogFormsLoaded=0,this.on("form_loaded styles_loaded",function(){this.dialogFormsLoaded++,2===this.dialogFormsLoaded&&e.updateModel({refreshArgs:{silent:!0}})}),this.on("edit_label",function(e){e===panelsOptions.widgets[this.model.get("class")].title&&(e=""),this.model.set("label",e),_.isEmpty(e)&&this.$(".so-title").text(this.model.getWidgetField("title"))}.bind(this))},render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-widget").html(),{})),this.loadForm();var e=this.model.getWidgetField("title");this.$(".so-title .widget-name").html(e),this.$(".so-edit-title").val(e),this.builder.supports("addWidget")||this.$(".so-buttons .so-duplicate").remove(),this.builder.supports("deleteWidget")||this.$(".so-buttons .so-delete").remove(),this.styles=new s.view.styles,this.styles.model=this.model,this.styles.render("widget",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this});var t=this.$(".so-sidebar.so-right-sidebar");this.styles.attach(t),this.styles.on("styles_loaded",function(e){e||(t.closest(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar"),t.remove())},this)},getPrevDialog:function(){var e=this.builder.$(".so-cells .cell .so-widget");if(e.length<=1)return!1;var t,i=e.index(this.widgetView.$el);if(0===i)return!1;do{if(t=e.eq(--i).data("view"),!_.isUndefined(t)&&!t.model.get("read_only"))return t.getEditDialog()}while(!_.isUndefined(t)&&0<i);return!1},getNextDialog:function(){var e=this.builder.$(".so-cells .cell .so-widget");if(e.length<=1)return!1;var t,i=e.index(this.widgetView.$el);if(i===e.length-1)return!1;do{if(t=e.eq(++i).data("view"),!_.isUndefined(t)&&!t.model.get("read_only"))return t.getEditDialog()}while(!_.isUndefined(t));return!1},loadForm:function(){if(this.$("> *").length){this.$(".so-content").addClass("so-panels-loading");var e={action:"so_panels_widget_form",widget:this.model.get("class"),instance:JSON.stringify(this.model.get("values")),raw:this.model.get("raw")},i=this.$(".so-content");l.post(panelsOptions.ajaxurl,e,null,"html").done(function(e){var t=e.replace(/{\$id}/g,this.model.cid);i.removeClass("so-panels-loading").html(t),this.trigger("form_loaded",this),this.$(".panel-dialog").trigger("panelsopen"),this.on("close_dialog",this.updateModel,this),0<i.find("> .widget-content").length&&o.addWidget(i,this.model.widget_id)}.bind(this)).fail(function(e){var t;t=e&&e.responseText?e.responseText:panelsOptions.forms.loadingFailed,i.removeClass("so-panels-loading").html(t)})}},updateModel:function(e){if(e=_.extend({refresh:!0,refreshArgs:null},e),this.savingWidget=!0,!this.model.get("missing")){var t=this.getFormValues();t=_.isUndefined(t.widgets)?{}:(t=t.widgets)[Object.keys(t)[0]],this.model.setValues(t),this.model.set("raw",!0)}if(this.styles.stylesLoaded){var i={};try{i=this.getFormValues(".so-sidebar .so-visual-styles").style}catch(e){}this.model.set("style",i)}this.savingWidget=!1,e.refresh&&this.builder.model.refreshPanelsData(e.refreshArgs)},handleChangeValues:function(){this.savingWidget||this.loadForm()},saveHandler:function(){this.builder.addHistoryEntry("widget_edited"),this.closeDialog()},deleteHandler:function(){return this.widgetView.visualDestroyModel(),this.closeDialog({silent:!0}),this.builder.model.refreshPanelsData(),!1},duplicateHandler:function(){return this.widgetView.duplicateHandler(),this.closeDialog({silent:!0}),this.builder.model.refreshPanelsData(),!1}})},{"../view/widgets/js-widget":31}],10:[function(e,t,i){var s=window.panels,o=jQuery;t.exports=s.view.dialog.extend({builder:null,widgetTemplate:_.template(s.helpers.utils.processTemplate(o("#siteorigin-panels-dialog-widgets-widget").html())),filter:{},dialogClass:"so-panels-dialog-add-widget",dialogIcon:"add-widget",events:{"click .so-close":"closeDialog","click .widget-type":"widgetClickHandler","keyup .so-sidebar-search":"searchHandler"},initializeDialog:function(){this.on("open_dialog",function(){this.filter.search="",this.filterWidgets(this.filter)},this),this.on("open_dialog_complete",function(){this.$(".so-sidebar-search").val("").focus(),this.balanceWidgetHeights()}),this.on("tab_click",this.tabClickHandler,this)},render:function(){this.renderDialog(this.parseDialogContent(o("#siteorigin-panels-dialog-widgets").html(),{})),_.each(panelsOptions.widgets,function(e){var t=o(this.widgetTemplate({title:e.title,description:e.description}));_.isUndefined(e.icon)&&(e.icon="dashicons dashicons-admin-generic"),o('<span class="widget-icon" />').addClass(e.icon).prependTo(t.find(".widget-type-wrapper")),t.data("class",e.class).appendTo(this.$(".widget-type-list"))},this);var t=this.$(".so-sidebar-tabs");_.each(panelsOptions.widget_dialog_tabs,function(e){o(this.dialogTabTemplate({title:e.title})).data({message:e.message,filter:e.filter}).appendTo(t)},this),this.initTabs();var e=this;o(window).resize(function(){e.balanceWidgetHeights()})},tabClickHandler:function(e){this.filter=e.parent().data("filter"),this.filter.search=this.$(".so-sidebar-search").val();var t=e.parent().data("message");return _.isEmpty(t)&&(t=""),this.$(".so-toolbar .so-status").html(t),this.filterWidgets(this.filter),!1},searchHandler:function(e){if(13===e.which){var t=this.$(".widget-type-list .widget-type:visible");1===t.length&&t.click()}else this.filter.search=o(e.target).val().trim(),this.filterWidgets(this.filter)},filterWidgets:function(l){_.isUndefined(l)&&(l={}),_.isUndefined(l.groups)&&(l.groups=""),this.$(".widget-type-list .widget-type").each(function(){var e,t=o(this),i=t.data("class"),s=_.isUndefined(panelsOptions.widgets[i])?null:panelsOptions.widgets[i];(e=!!_.isEmpty(l.groups)||null!==s&&!_.isEmpty(_.intersection(l.groups,panelsOptions.widgets[i].groups)))&&(_.isUndefined(l.search)||""===l.search||-1===s.title.toLowerCase().indexOf(l.search.toLowerCase())&&(e=!1)),e?t.show():t.hide()}),this.balanceWidgetHeights()},widgetClickHandler:function(e){this.builder.trigger("before_user_adds_widget"),this.builder.addHistoryEntry("widget_added");var t=o(e.currentTarget),i=new s.model.widget({class:t.data("class")});i.cell=this.builder.getActiveCell(),i.cell.get("widgets").add(i),this.closeDialog(),this.builder.model.refreshPanelsData(),this.builder.trigger("after_user_adds_widget",i)},balanceWidgetHeights:function(e){var s=[[]],l=null,i=Math.round(this.$(".widget-type").parent().width()/this.$(".widget-type").width());this.$(".widget-type").css("clear","none").filter(":visible").each(function(e,t){e%i==0&&0!==e&&o(t).css("clear","both")}),this.$(".widget-type-wrapper").css("height","auto").filter(":visible").each(function(e,t){var i=o(t);null!==l&&l.position().top!==i.position().top&&(s[s.length]=[]),l=i,s[s.length-1].push(i)}),_.each(s,function(e,t){var i=_.max(e.map(function(e){return e.height()}));_.each(e,function(e){e.height(i)})})}})},{}],11:[function(e,t,i){t.exports={canCopyPaste:function(){return"undefined"!=typeof Storage&&panelsOptions.user},setModel:function(e){if(!this.canCopyPaste())return!1;var t=panels.helpers.serialize.serialize(e);return e instanceof panels.model.row?t.thingType="row-model":e instanceof panels.model.widget&&(t.thingType="widget-model"),localStorage["panels_clipboard_"+panelsOptions.user]=JSON.stringify(t),!0},isModel:function(e){if(!this.canCopyPaste())return!1;var t=localStorage["panels_clipboard_"+panelsOptions.user];return void 0!==t&&((t=JSON.parse(t)).thingType&&t.thingType===e)},getModel:function(e){if(!this.canCopyPaste())return null;var t=localStorage["panels_clipboard_"+panelsOptions.user];return void 0!==t&&(t=JSON.parse(t)).thingType&&t.thingType===e?panels.helpers.serialize.unserialize(t,t.thingType,null):null}}},{}],12:[function(e,t,i){t.exports={lock:function(){if("hidden"!==jQuery("body").css("overflow")){var e=[self.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft,self.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop];jQuery("body").data({"scroll-position":e}).css("overflow","hidden"),_.isUndefined(e)||window.scrollTo(e[0],e[1])}},unlock:function(){if("hidden"===jQuery("body").css("overflow")&&!jQuery(".so-panels-dialog-wrapper").is(":visible")&&!jQuery(".so-panels-live-editor").is(":visible")){jQuery("body").css("overflow","visible");var e=jQuery("body").data("scroll-position");_.isUndefined(e)||window.scrollTo(e[0],e[1])}}}},{}],13:[function(e,t,i){t.exports={serialize:function(e){var t;if(e instanceof Backbone.Model){var i={};for(var s in e.attributes)if(e.attributes.hasOwnProperty(s)){if("builder"===s||"collection"===s)continue;(t=e.attributes[s])instanceof Backbone.Model||t instanceof Backbone.Collection?i[s]=this.serialize(t):i[s]=t}return i}if(e instanceof Backbone.Collection){for(var l=[],o=0;o<e.models.length;o++)(t=e.models[o])instanceof Backbone.Model||t instanceof Backbone.Collection?l.push(this.serialize(t)):l.push(t);return l}},unserialize:function(e,t,i){var s;switch(t){case"row-model":(s=new panels.model.row).builder=i;var l={style:e.style};e.hasOwnProperty("label")&&(l.label=e.label),e.hasOwnProperty("color_label")&&(l.color_label=e.color_label),s.set(l),s.setCells(this.unserialize(e.cells,"cell-collection",s));break;case"cell-model":(s=new panels.model.cell).row=i,s.set("weight",e.weight),s.set("style",e.style),s.set("widgets",this.unserialize(e.widgets,"widget-collection",s));break;case"widget-model":for(var o in(s=new panels.model.widget).cell=i,e)e.hasOwnProperty(o)&&s.set(o,e[o]);s.set("widget_id",panels.helpers.utils.generateUUID());break;case"cell-collection":s=new panels.collection.cells;for(var n=0;n<e.length;n++)s.push(this.unserialize(e[n],"cell-model",i));break;case"widget-collection":s=new panels.collection.widgets;for(n=0;n<e.length;n++)s.push(this.unserialize(e[n],"widget-model",i));break;default:console.log("Unknown Thing - "+t)}return s}}},{}],14:[function(e,t,i){t.exports={generateUUID:function(){var i=(new Date).getTime();return window.performance&&"function"==typeof window.performance.now&&(i+=performance.now()),"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=(i+16*Math.random())%16|0;return i=Math.floor(i/16),("x"==e?t:3&t|8).toString(16)})},processTemplate:function(e){return _.isUndefined(e)||_.isNull(e)?"":e=(e=(e=e.replace(/{{%/g,"<%")).replace(/%}}/g,"%>")).trim()},selectElementContents:function(e){var t=document.createRange();t.selectNodeContents(e);var i=window.getSelection();i.removeAllRanges(),i.addRange(t)}}},{}],15:[function(e,t,i){var d=window.panels,h=jQuery;t.exports=function(a,r){return this.each(function(){var e=jQuery(this);if(!e.data("soPanelsBuilderWidgetInitialized")||r){var t=e.closest("form").find(".widget-id").val(),i=h.extend(!0,{},a);if(_.isUndefined(t)||!(-1<t.indexOf("__i__"))){var s=new d.model.builder,l=new d.view.builder({model:s,config:i}),o=e.closest(".so-panels-dialog-wrapper").data("view");_.isUndefined(o)||(o.on("close_dialog",function(){s.refreshPanelsData()}),o.on("open_dialog_complete",function(){l.trigger("builder_resize")}),o.model.on("destroy",function(){s.emptyRows().destroy()}),l.setDialogParents(panelsOptions.loc.layout_widget,o));var n=Boolean(e.closest(".widget-content").length);l.render().attach({container:e,dialog:n||"dialog"===e.data("mode"),type:e.data("type")}).setDataField(e.find("input.panels-data")),n||"dialog"===e.data("mode")?(l.setDialogParents(panelsOptions.loc.layout_widget,l.dialog),e.find(".siteorigin-panels-display-builder").click(function(e){e.preventDefault(),l.dialog.openDialog()})):e.find(".siteorigin-panels-display-builder").parent().remove(),h(document).trigger("panels_setup",l),e.data("soPanelsBuilderWidgetInitialized",!0)}}})}},{}],16:[function(e,t,i){var s={};window.panels=s,(window.siteoriginPanels=s).helpers={},s.helpers.clipboard=e("./helpers/clipboard"),s.helpers.utils=e("./helpers/utils"),s.helpers.serialize=e("./helpers/serialize"),s.helpers.pageScroll=e("./helpers/page-scroll"),s.model={},s.model.widget=e("./model/widget"),s.model.cell=e("./model/cell"),s.model.row=e("./model/row"),s.model.builder=e("./model/builder"),s.model.historyEntry=e("./model/history-entry"),s.collection={},s.collection.widgets=e("./collection/widgets"),s.collection.cells=e("./collection/cells"),s.collection.rows=e("./collection/rows"),s.collection.historyEntries=e("./collection/history-entries"),s.view={},s.view.widget=e("./view/widget"),s.view.cell=e("./view/cell"),s.view.row=e("./view/row"),s.view.builder=e("./view/builder"),s.view.dialog=e("./view/dialog"),s.view.styles=e("./view/styles"),s.view.liveEditor=e("./view/live-editor"),s.dialog={},s.dialog.builder=e("./dialog/builder"),s.dialog.widgets=e("./dialog/widgets"),s.dialog.widget=e("./dialog/widget"),s.dialog.prebuilt=e("./dialog/prebuilt"),s.dialog.row=e("./dialog/row"),s.dialog.history=e("./dialog/history"),s.utils={},s.utils.menu=e("./utils/menu"),jQuery.fn.soPanelsSetupBuilderWidget=e("./jquery/setup-builder-widget"),jQuery(function(i){var e,t,s,l,o=i("#siteorigin-panels-metabox");if(s=i("form#post"),o.length&&s.length)t=(e=o).find(".siteorigin-panels-data-field"),l={editorType:"tinyMCE",postId:i("#post_ID").val(),editorId:"#content",builderType:o.data("builder-type"),builderSupports:o.data("builder-supports"),loadOnAttach:panelsOptions.loadOnAttach&&1==i("#auto_draft").val(),loadLiveEditor:1==o.data("live-editor"),liveEditorPreview:e.data("preview-url")};else if(i(".siteorigin-panels-builder-form").length){var n=i(".siteorigin-panels-builder-form");e=n.find(".siteorigin-panels-builder-container"),t=n.find('input[name="panels_data"]'),l={editorType:"standalone",postId:(s=n).data("post-id"),editorId:"#post_content",builderType:n.data("type"),builderSupports:n.data("builder-supports"),loadLiveEditor:!1,liveEditorPreview:n.data("preview-url")}}if(!_.isUndefined(e)){var a=window.siteoriginPanels,r=new a.model.builder,d=new a.view.builder({model:r,config:l});d.render().attach({container:e}).setDataField(t).attachToEditor(),s.submit(function(){r.refreshPanelsData()}),e.removeClass("so-panels-loading"),i(document).trigger("panels_setup",d,window.panels)}i(document).on("widget-added",function(e,t){i(t).find(".siteorigin-page-builder-widget").soPanelsSetupBuilderWidget()}),i("body").hasClass("wp-customizer")||i(function(){i(".siteorigin-page-builder-widget").soPanelsSetupBuilderWidget()})})},{"./collection/cells":1,"./collection/history-entries":2,"./collection/rows":3,"./collection/widgets":4,"./dialog/builder":5,"./dialog/history":6,"./dialog/prebuilt":7,"./dialog/row":8,"./dialog/widget":9,"./dialog/widgets":10,"./helpers/clipboard":11,"./helpers/page-scroll":12,"./helpers/serialize":13,"./helpers/utils":14,"./jquery/setup-builder-widget":15,"./model/builder":17,"./model/cell":18,"./model/history-entry":19,"./model/row":20,"./model/widget":21,"./utils/menu":22,"./view/builder":23,"./view/cell":24,"./view/dialog":25,"./view/live-editor":26,"./view/row":27,"./view/styles":28,"./view/widget":29}],17:[function(e,t,i){t.exports=Backbone.Model.extend({layoutPosition:{BEFORE:"before",AFTER:"after",REPLACE:"replace"},rows:{},defaults:{data:{widgets:[],grids:[],grid_cells:[]}},initialize:function(){this.set("rows",new panels.collection.rows)},addRow:function(e,t,i){i=_.extend({noAnimate:!1},i);var s=new panels.collection.cells(t);e=_.extend({collection:this.get("rows"),cells:s},e);var l=new panels.model.row(e);return(l.builder=this).get("rows").add(l,i),l},loadPanelsData:function(s,e){try{e===this.layoutPosition.BEFORE?s=this.concatPanelsData(s,this.getPanelsData()):e===this.layoutPosition.AFTER&&(s=this.concatPanelsData(this.getPanelsData(),s)),this.emptyRows(),this.set("data",JSON.parse(JSON.stringify(s)),{silent:!0});var t,i=[];if(_.isUndefined(s.grid_cells))return void this.trigger("load_panels_data");for(var l=0;l<s.grid_cells.length;l++)t=parseInt(s.grid_cells[l].grid),_.isUndefined(i[t])&&(i[t]=[]),i[t].push(s.grid_cells[l]);var o=this;if(_.each(i,function(e,t){var i={};_.isUndefined(s.grids[t].style)||(i.style=s.grids[t].style),_.isUndefined(s.grids[t].ratio)||(i.ratio=s.grids[t].ratio),_.isUndefined(s.grids[t].ratio_direction)||(i.ratio_direction=s.grids[t].ratio_direction),_.isUndefined(s.grids[t].color_label)||(i.color_label=s.grids[t].color_label),_.isUndefined(s.grids[t].label)||(i.label=s.grids[t].label),o.addRow(i,e,{noAnimate:!0})}),_.isUndefined(s.widgets))return;_.each(s.widgets,function(e){var t=null;_.isUndefined(e.panels_info)?(t=e.info,delete e.info):(t=e.panels_info,delete e.panels_info);var i=o.get("rows").at(parseInt(t.grid)).get("cells").at(parseInt(t.cell)),s=new panels.model.widget({class:t.class,values:e});_.isUndefined(t.style)||s.set("style",t.style),_.isUndefined(t.read_only)||s.set("read_only",t.read_only),_.isUndefined(t.widget_id)?s.set("widget_id",panels.helpers.utils.generateUUID()):s.set("widget_id",t.widget_id),_.isUndefined(t.label)||s.set("label",t.label),(s.cell=i).get("widgets").add(s,{noAnimate:!0})}),this.trigger("load_panels_data")}catch(e){console.log("Error loading data: "+e.message)}},concatPanelsData:function(e,t){if(_.isUndefined(t)||_.isUndefined(t.grids)||_.isEmpty(t.grids)||_.isUndefined(t.grid_cells)||_.isEmpty(t.grid_cells))return e;if(_.isUndefined(e)||_.isUndefined(e.grids)||_.isEmpty(e.grids))return t;var i,s=e.grids.length,l=_.isUndefined(e.widgets)?0:e.widgets.length,o={grids:[],grid_cells:[],widgets:[]};for(o.grids=e.grids.concat(t.grids),_.isUndefined(e.grid_cells)||(o.grid_cells=e.grid_cells.slice()),_.isUndefined(e.widgets)||(o.widgets=e.widgets.slice()),i=0;i<t.grid_cells.length;i++){var n=t.grid_cells[i];n.grid=parseInt(n.grid)+s,o.grid_cells.push(n)}if(!_.isUndefined(t.widgets))for(i=0;i<t.widgets.length;i++){var a=t.widgets[i];a.panels_info.grid=parseInt(a.panels_info.grid)+s,a.panels_info.id=parseInt(a.panels_info.id)+l,o.widgets.push(a)}return o},getPanelsData:function(){var n={widgets:[],grids:[],grid_cells:[]},a=0;return this.get("rows").each(function(e,o){e.get("cells").each(function(e,l){e.get("widgets").each(function(e,t){var i={class:e.get("class"),raw:e.get("raw"),grid:o,cell:l,id:a++,widget_id:e.get("widget_id"),style:e.get("style"),label:e.get("label")};_.isEmpty(i.widget_id)&&(i.widget_id=panels.helpers.utils.generateUUID());var s=_.extend(_.clone(e.get("values")),{panels_info:i});n.widgets.push(s)}),n.grid_cells.push({grid:o,index:l,weight:e.get("weight"),style:e.get("style")})}),n.grids.push({cells:e.get("cells").length,style:e.get("style"),ratio:e.get("ratio"),ratio_direction:e.get("ratio_direction"),color_label:e.get("color_label"),label:e.get("label")})}),n},refreshPanelsData:function(e){e=_.extend({silent:!1},e);var t=this.get("data"),i=this.getPanelsData();this.set("data",i,{silent:!0}),e.silent||JSON.stringify(i)===JSON.stringify(t)||(this.trigger("change"),this.trigger("change:data"),this.trigger("refresh_panels_data",i,e))},emptyRows:function(){return _.invoke(this.get("rows").toArray(),"destroy"),this.get("rows").reset(),this},isValidLayoutPosition:function(e){return e===this.layoutPosition.BEFORE||e===this.layoutPosition.AFTER||e===this.layoutPosition.REPLACE},getPanelsDataFromHtml:function(e,c){var t,u=this,i=jQuery('<div id="wrapper">'+e+"</div>");if(i.find(".panel-layout .panel-grid").length){var p={grids:[],grid_cells:[],widgets:[]},g=new RegExp(panelsOptions.siteoriginWidgetRegex,"i"),f=(t=document.createElement("div"),function(e){return e&&"string"==typeof e&&(e=(e=e.replace(/<script[^>]*>([\S\s]*?)<\/script>/gim,"")).replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gim,""),t.innerHTML=e,e=t.textContent,t.textContent=""),e}),w=function(e){var t,i=e.find("div");if(!i.length)return e.html();for(t=0;t<i.length-1&&jQuery.trim(i.eq(t).text())==jQuery.trim(i.eq(t+1).text());t++);var s=i.eq(t).find(".widget-title:header"),l="";return s.length&&(l=s.html(),s.remove()),{title:l,text:i.eq(t).html()}},s=i.find(".panel-layout").eq(0),l=function(e,t){return jQuery(t).closest(".panel-layout").is(s)};return i.find("> .panel-layout > .panel-grid").filter(l).each(function(h,e){var t=jQuery(e),i=t.find(".panel-grid-cell").filter(l);p.grids.push({cells:i.length,style:t.data("style"),ratio:t.data("ratio"),ratio_direction:t.data("ratio-direction"),color_label:t.data("color-label"),label:t.data("label")}),i.each(function(d,e){var t=jQuery(e),i=t.find(".so-panel").filter(l);p.grid_cells.push({grid:h,weight:_.isUndefined(t.data("weight"))?1:parseFloat(t.data("weight")),style:t.data("style")}),i.each(function(e,t){var i=jQuery(t),s=i.find(".panel-widget-style").length?i.find(".panel-widget-style").html():i.html(),l={grid:h,cell:d,style:i.data("style"),raw:!1,label:i.data("label")};s=s.trim();var o=g.exec(s);if(_.isNull(o)||""!==s.replace(g,"").trim())return-1!==s.indexOf("panel-layout")&&jQuery("<div>"+s+"</div>").find(".panel-layout .panel-grid").length?(l.class="SiteOrigin_Panels_Widgets_Layout",p.widgets.push({panels_data:u.getPanelsDataFromHtml(s,c),panels_info:l})):(l.class=c,p.widgets.push(_.extend(w(i),{filter:"1",type:"visual",panels_info:l}))),!0;try{var n=/class="(.*?)"/.exec(o[3]),a=jQuery(o[5]),r=JSON.parse(f(a.val())).instance;l.class=n[1].replace(/\\\\+/g,"\\"),l.raw=!1,r.panels_info=l,p.widgets.push(r)}catch(e){l.class=c,p.widgets.push(_.extend(w(i),{filter:"1",type:"visual",panels_info:l}))}return!0})})}),i.find(".panel-layout").remove(),i.find("style[data-panels-style-for-post]").remove(),i.html().replace(/^\s+|\s+$/gm,"").length&&(p.grids.push({cells:1,style:{}}),p.grid_cells.push({grid:p.grids.length-1,weight:1}),p.widgets.push({filter:"1",text:i.html().replace(/^\s+|\s+$/gm,""),title:"",type:"visual",panels_info:{class:c,raw:!1,grid:p.grids.length-1,cell:0}})),p}return{grid_cells:[{grid:0,weight:1}],grids:[{cells:1}],widgets:[{filter:"1",text:e,title:"",type:"visual",panels_info:{class:c,raw:!1,grid:0,cell:0}}]}}})},{}],18:[function(e,t,i){t.exports=Backbone.Model.extend({widgets:{},row:null,defaults:{weight:0,style:{}},indexes:null,initialize:function(){this.set("widgets",new panels.collection.widgets),this.on("destroy",this.onDestroy,this)},onDestroy:function(){_.invoke(this.get("widgets").toArray(),"destroy"),this.get("widgets").reset()},clone:function(e,t){_.isUndefined(e)&&(e=this.row),t=_.extend({cloneWidgets:!0},t);var i=new this.constructor(this.attributes);return i.set("collection",e.get("cells"),{silent:!0}),i.row=e,t.cloneWidgets&&this.get("widgets").each(function(e){i.get("widgets").add(e.clone(i,t),{silent:!0})}),i}})},{}],19:[function(e,t,i){t.exports=Backbone.Model.extend({defaults:{text:"",data:"",time:null,count:1}})},{}],20:[function(e,t,i){t.exports=Backbone.Model.extend({builder:null,defaults:{style:{}},indexes:null,initialize:function(){_.isEmpty(this.get("cells"))?this.set("cells",new panels.collection.cells):this.get("cells").each(function(e){e.row=this}.bind(this)),this.on("destroy",this.onDestroy,this)},setCells:function(n){var a=this.get("cells")||new panels.collection.cells,r=[];a.each(function(e,t){var i=n.at(t);if(i)e.set("weight",i.get("weight"));else{for(var s=a.at(n.length-1),l=e.get("widgets").models.slice(),o=0;o<l.length;o++)l[o].moveToCell(s,{silent:!1});r.push(e)}}),_.each(r,function(e){a.remove(e)}),n.length>a.length&&_.each(n.slice(a.length,n.length),function(e){e.set({collection:a}),e.row=this,a.add(e)}.bind(this)),this.reweightCells()},reweightCells:function(){var t=0,e=this.get("cells");e.each(function(e){t+=e.get("weight")}),e.each(function(e){e.set("weight",e.get("weight")/t)}),this.trigger("reweight_cells")},onDestroy:function(){_.invoke(this.get("cells").toArray(),"destroy"),this.get("cells").reset()},clone:function(e){_.isUndefined(e)&&(e=this.builder);var t=new this.constructor(this.attributes);t.set("collection",e.get("rows"),{silent:!0}),t.builder=e;var i=new panels.collection.cells;return this.get("cells").each(function(e){i.add(e.clone(t),{silent:!0})}),t.set("cells",i),t}})},{}],21:[function(e,t,i){t.exports=Backbone.Model.extend({cell:null,defaults:{class:null,missing:!1,values:{},raw:!1,style:{},read_only:!1,widget_id:""},indexes:null,initialize:function(){var e=this.get("class");!_.isUndefined(panelsOptions.widgets[e])&&panelsOptions.widgets[e].installed||this.set("missing",!0)},getWidgetField:function(e){return _.isUndefined(panelsOptions.widgets[this.get("class")])?"title"===e||"description"===e?panelsOptions.loc.missing_widget[e]:"":this.has("label")&&!_.isEmpty(this.get("label"))?this.get("label"):panelsOptions.widgets[this.get("class")][e]},moveToCell:function(e,t,i){return t=_.extend({silent:!0},t),this.cell=e,this.collection.remove(this,t),e.get("widgets").add(this,_.extend({at:i},t)),this.trigger("move_to_cell",e,i),this},setValues:function(e){var t=!1;JSON.stringify(e)!==JSON.stringify(this.get("values"))&&(t=!0),this.set("values",e,{silent:!0}),t&&(this.trigger("change",this),this.trigger("change:values"))},clone:function(e,t){_.isUndefined(e)&&(e=this.cell);var i=new this.constructor(this.attributes),s=JSON.parse(JSON.stringify(this.get("values"))),l=function(i){return _.each(i,function(e,t){_.isString(t)&&"_"===t[0]?delete i[t]:_.isObject(i[t])&&l(i[t])}),i};return s=l(s),"SiteOrigin_Panels_Widgets_Layout"===this.get("class")&&(s.builder_id=Math.random().toString(36).substr(2)),i.set("widget_id",""),i.set("values",s,{silent:!0}),i.set("collection",e.get("widgets"),{silent:!0}),i.cell=e,i.isDuplicate=!0,i},getTitle:function(){var e=panelsOptions.widgets[this.get("class")];if(_.isUndefined(e))return this.get("class").replace(/_/g," ");if(!_.isUndefined(e.panels_title)&&!1===e.panels_title)return panelsOptions.widgets[this.get("class")].description;var t=this.get("values"),i=["title","text"];for(var s in t)t.hasOwnProperty(s)&&i.push(s);for(var l in i=_.uniq(i))if(!_.isUndefined(t[i[l]])&&_.isString(t[i[l]])&&""!==t[i[l]]&&"on"!==t[i[l]]&&"_"!==i[l][0]&&!jQuery.isNumeric(t[i[l]])){var o=t[i[l]],n=(o=o.replace(/<\/?[^>]+(>|$)/g,"")).split(" ");return(n=n.slice(0,20)).join(" ")}return this.getWidgetField("description")}})},{}],22:[function(e,t,i){var s=window.panels,r=jQuery;t.exports=Backbone.View.extend({wrapperTemplate:_.template(s.helpers.utils.processTemplate(r("#siteorigin-panels-context-menu").html())),sectionTemplate:_.template(s.helpers.utils.processTemplate(r("#siteorigin-panels-context-menu-section").html())),contexts:[],active:!1,events:{"keyup .so-search-wrapper input":"searchKeyUp"},initialize:function(){this.listenContextMenu(),this.render(),this.attach()},listenContextMenu:function(){var t=this;r(window).on("contextmenu",function(e){return t.active&&!t.isOverEl(t.$el,e)?(t.closeMenu(),t.active=!1,e.preventDefault(),!1):!!t.active||(t.active=!1,t.trigger("activate_context",e,t),void(t.active&&(e.preventDefault(),t.openMenu({left:e.pageX,top:e.pageY}))))})},render:function(){this.setElement(this.wrapperTemplate())},attach:function(){this.$el.appendTo("body")},openMenu:function(e){this.trigger("open_menu"),r(window).on("keyup",{menu:this},this.keyboardListen),r(window).on("click",{menu:this},this.clickOutsideListen),this.$el.css("max-height",r(window).height()-20),e.left+this.$el.outerWidth()+10>=r(window).width()&&(e.left=r(window).width()-this.$el.outerWidth()-10),e.left<=0&&(e.left=10),e.top+this.$el.outerHeight()-r(window).scrollTop()+10>=r(window).height()&&(e.top=r(window).height()+r(window).scrollTop()-this.$el.outerHeight()-10),e.left<=0&&(e.left=10),this.$el.css({left:e.left+1,top:e.top+1}).show(),this.$(".so-search-wrapper input").focus()},closeMenu:function(){this.trigger("close_menu"),r(window).off("keyup",this.keyboardListen),r(window).off("click",this.clickOutsideListen),this.active=!1,this.$el.empty().hide()},keyboardListen:function(e){var t=e.data.menu;switch(e.which){case 27:t.closeMenu()}},clickOutsideListen:function(e){var t=e.data.menu;3!==e.which&&t.$el.is(":visible")&&!t.isOverEl(t.$el,e)&&t.closeMenu()},addSection:function(e,t,i,s){var l=this;t=_.extend({display:5,defaultDisplay:!1,search:!0,sectionTitle:"",searchPlaceholder:"",titleKey:"title"},t);var o=r(this.sectionTemplate({settings:t,items:i})).attr("id","panels-menu-section-"+e);this.$el.append(o),o.find(".so-item:not(.so-confirm)").click(function(){var e=r(this);s(e.data("key")),l.closeMenu()}),o.find(".so-item.so-confirm").click(function(){var e=r(this);if(e.hasClass("so-confirming"))return s(e.data("key")),void l.closeMenu();e.data("original-text",e.html()).addClass("so-confirming").html('<span class="dashicons dashicons-yes"></span> '+panelsOptions.loc.dropdown_confirm),setTimeout(function(){e.removeClass("so-confirming"),e.html(e.data("original-text"))},2500)}),o.data("settings",t).find(".so-search-wrapper input").trigger("keyup"),this.active=!0},hasSection:function(e){return 0<this.$el.find("#panels-menu-section-"+e).length},searchKeyUp:function(e){var t=r(e.currentTarget),i=t.closest(".so-section"),s=i.data("settings");if(38===e.which||40===e.which){var l=i.find("ul li:visible"),o=l.filter(".so-active").eq(0);if(o.length){l.removeClass("so-active");var n=l.index(o);38===e.which?o=n-1<0?l.last():l.eq(n-1):40===e.which&&(o=n+1>=l.length?l.first():l.eq(n+1))}else 38===e.which?o=l.last():40===e.which&&(o=l.first());return o.addClass("so-active"),!1}if(13===e.which)return 1===i.find("ul li:visible").length?i.find("ul li:visible").trigger("click"):i.find("ul li.so-active:visible").trigger("click"),!1;if(""===t.val())if(s.defaultDisplay){i.find(".so-item").hide();for(var a=0;a<s.defaultDisplay.length;a++)i.find('.so-item[data-key="'+s.defaultDisplay[a]+'"]').show()}else i.find(".so-item").show();else i.find(".so-item").hide().each(function(){var e=r(this);-1!==e.html().toLowerCase().indexOf(t.val().toLowerCase())&&e.show()});i.find(".so-item:visible:gt("+(s.display-1)+")").hide(),0===i.find(".so-item:visible").length&&""!==t.val()?i.find(".so-no-results").show():i.find(".so-no-results").hide()},isOverEl:function(e,t){var i=[[e.offset().left,e.offset().top],[e.offset().left+e.outerWidth(),e.offset().top+e.outerHeight()]];return t.pageX>=i[0][0]&&t.pageX<=i[1][0]&&t.pageY>=i[0][1]&&t.pageY<=i[1][1]}})},{}],23:[function(e,t,i){var a=window.panels,n=jQuery;t.exports=Backbone.View.extend({config:{},template:_.template(a.helpers.utils.processTemplate(n("#siteorigin-panels-builder").html())),dialogs:{},rowsSortable:null,dataField:!1,currentData:"",attachedToEditor:!1,attachedVisible:!1,liveEditor:void 0,menu:!1,activeCell:null,events:{"click .so-tool-button.so-widget-add":"displayAddWidgetDialog","click .so-tool-button.so-row-add":"displayAddRowDialog","click .so-tool-button.so-prebuilt-add":"displayAddPrebuiltDialog","click .so-tool-button.so-history":"displayHistoryDialog","click .so-tool-button.so-live-editor":"displayLiveEditor"},rows:null,initialize:function(e){var s=this;return this.config=_.extend({loadLiveEditor:!1,builderSupports:{}},e.config),this.config.builderSupports=_.extend({addRow:!0,editRow:!0,deleteRow:!0,moveRow:!0,addWidget:!0,editWidget:!0,deleteWidget:!0,moveWidget:!0,prebuilt:!0,history:!0,liveEditor:!0,revertToEditor:!0},this.config.builderSupports),e.config.loadLiveEditor&&this.on("builder_live_editor_added",function(){this.displayLiveEditor()}),this.dialogs={widgets:new a.dialog.widgets,row:new a.dialog.row,prebuilt:new a.dialog.prebuilt},_.each(this.dialogs,function(e,t,i){i[t].setBuilder(s)}),this.dialogs.row.setRowDialogType("create"),this.listenTo(this.model.get("rows"),"add",this.onAddRow),n(window).resize(function(e){e.target===window&&s.trigger("builder_resize")}),this.listenTo(this.model,"change:data load_panels_data",this.storeModelData),this.listenTo(this.model,"change:data load_panels_data",this.toggleWelcomeDisplay),this.on("content_change",this.handleContentChange,this),this.on("display_builder",this.handleDisplayBuilder,this),this.on("hide_builder",this.handleHideBuilder,this),this.on("builder_rendered builder_resize",this.handleBuilderSizing,this),this.on("display_builder",this.wrapEditorExpandAdjust,this),this.menu=new a.utils.menu({}),this.listenTo(this.menu,"activate_context",this.activateContextMenu),this.config.loadOnAttach&&this.on("builder_attached_to_editor",function(){this.displayAttachedBuilder({confirm:!1})},this),this},render:function(){return this.setElement(this.template()),this.$el.attr("id","siteorigin-panels-builder-"+this.cid).addClass("so-builder-container"),this.trigger("builder_rendered"),this},attach:function(e){(e=_.extend({container:!1,dialog:!1},e)).dialog?(this.dialog=new a.dialog.builder,this.dialog.builder=this):(this.$el.appendTo(e.container),this.metabox=e.container.closest(".postbox"),this.initSortable(),this.trigger("attached_to_container",e.container)),this.trigger("builder_attached"),this.supports("liveEditor")&&this.addLiveEditor(),this.supports("history")&&this.addHistoryBrowser();var t=this.$(".so-builder-toolbar"),i=this.$(".so-panels-welcome-message"),s=panelsOptions.loc.welcomeMessage,l=[];this.supports("addWidget")?l.push(s.addWidgetButton):t.find(".so-widget-add").hide(),this.supports("addRow")?l.push(s.addRowButton):t.find(".so-row-add").hide(),this.supports("prebuilt")?l.push(s.addPrebuiltButton):t.find(".so-prebuilt-add").hide();var o="";3===l.length?o=s.threeEnabled:2===l.length?o=s.twoEnabled:1===l.length?o=s.oneEnabled:0===l.length&&(o=s.addingDisabled);var n=_.template(a.helpers.utils.processTemplate(o))({items:l})+" "+s.docsMessage;return i.find(".so-message-wrapper").html(n),this},attachToEditor:function(){if("tinyMCE"!==this.config.editorType)return this;this.attachedToEditor=!0;var t=this.metabox,l=this;n("#wp-content-wrap .wp-editor-tabs").find(".wp-switch-editor").click(function(e){e.preventDefault(),n("#wp-content-editor-container").show(),n("#wp-content-wrap").removeClass("panels-active"),n("#content-resize-handle").show(),l.trigger("hide_builder")}).end().append(n('<button type="button" id="content-panels" class="hide-if-no-js wp-switch-editor switch-panels">'+t.find(".hndle span").html()+"</button>").click(function(e){l.displayAttachedBuilder({confirm:!0})&&e.preventDefault()})),this.supports("revertToEditor")&&t.find(".so-switch-to-standard").click(function(e){e.preventDefault(),confirm(panelsOptions.loc.confirm_stop_builder)&&(l.addHistoryEntry("back_to_editor"),l.model.loadPanelsData(!1),n("#wp-content-wrap").show(),t.hide(),n(window).resize(),l.attachedVisible=!1,l.trigger("hide_builder"))}).show(),t.insertAfter("#wp-content-wrap").hide().addClass("attached-to-editor");var e=this.model.get("data");_.isEmpty(e.widgets)&&_.isEmpty(e.grids)&&this.supports("revertToEditor")||this.displayAttachedBuilder({confirm:!1});var i=function(){var e=l.$(".so-builder-toolbar");if(l.$el.hasClass("so-display-narrow"))return e.css({top:0,left:0,width:"100%",position:"absolute"}),void l.$el.css("padding-top",e.outerHeight());var t=n(window).scrollTop()-l.$el.offset().top;"fixed"===n("#wpadminbar").css("position")&&(t+=n("#wpadminbar").outerHeight());var i=0,s=l.$el.outerHeight()-e.outerHeight()+20;i<t&&t<s?"fixed"!==e.css("position")&&e.css({top:n("#wpadminbar").outerHeight(),left:l.$el.offset().left,width:l.$el.outerWidth(),position:"fixed"}):e.css({top:Math.min(Math.max(t,0),l.$el.outerHeight()-e.outerHeight()+20),left:0,width:"100%",position:"absolute"}),l.$el.css("padding-top",e.outerHeight())};return this.on("builder_resize",i,this),n(document).scroll(i),i(),this.trigger("builder_attached_to_editor"),this},displayAttachedBuilder:function(e){if((e=_.extend({confirm:!0},e)).confirm){var t="undefined"!=typeof tinyMCE&&tinyMCE.get("content");if(""!==(t&&_.isFunction(t.getContent)?t.getContent():n("textarea#content").val())&&!confirm(panelsOptions.loc.confirm_use_builder))return!1}return n("#wp-content-wrap").hide(),n("#editor-expand-toggle").on("change.editor-expand",function(){n(this).prop("checked")||n("#wp-content-wrap").hide()}),this.metabox.show().find("> .inside").show(),n(window).resize(),n(document).scroll(),this.attachedVisible=!0,this.trigger("display_builder"),!0},initSortable:function(){if(!this.supports("moveRow"))return this;var o=this,e=o.$el.attr("id");return this.rowsSortable=this.$(".so-rows-container").sortable({appendTo:"#wpwrap",items:".so-row-container",handle:".so-row-move",connectWith:"#"+e+".so-rows-container,.block-editor .so-rows-container",axis:"y",tolerance:"pointer",scroll:!1,remove:function(e,t){o.model.get("rows").remove(n(t.item).data("view").model,{silent:!0}),o.model.refreshPanelsData()},receive:function(e,t){o.model.get("rows").add(n(t.item).data("view").model,{silent:!0,at:n(t.item).index()}),o.model.refreshPanelsData()},stop:function(e,t){var i=n(t.item),s=i.data("view"),l=o.model.get("rows");l.get(s.model)&&(o.addHistoryEntry("row_moved"),l.remove(s.model,{silent:!0}),l.add(s.model,{silent:!0,at:i.index()}),s.trigger("move",i.index()),o.model.refreshPanelsData())}}),this},refreshSortable:function(){_.isNull(this.rowsSortable)||this.rowsSortable.sortable("refresh")},setDataField:function(e,t){if(t=_.extend({load:!0},t),this.dataField=e,this.dataField.data("builder",this),t.load&&""!==e.val()){var i=this.dataField.val();try{i=JSON.parse(i)}catch(e){console.log("Failed to parse Page Builder layout data from supplied data field."),i={}}this.setData(i)}return this},setData:function(e){this.model.loadPanelsData(e),this.currentData=e,this.toggleWelcomeDisplay()},getData:function(){return this.model.get("data")},storeModelData:function(){var e=JSON.stringify(this.model.get("data"));n(this.dataField).val()!==e&&(n(this.dataField).val(e),n(this.dataField).trigger("change"),this.trigger("content_change"))},onAddRow:function(e,t,i){i=_.extend({noAnimate:!1},i);var s=new a.view.row({model:e});s.builder=this,s.render(),_.isUndefined(i.at)||t.length<=1?s.$el.appendTo(this.$(".so-rows-container")):s.$el.insertAfter(this.$(".so-rows-container .so-row-container").eq(i.at-1)),!1===i.noAnimate&&s.visualCreate(),this.refreshSortable(),s.resize(),this.trigger("row_added")},displayAddWidgetDialog:function(){this.dialogs.widgets.openDialog()},displayAddRowDialog:function(){var t=new a.model.row,e=new a.collection.cells([{weight:.5},{weight:.5}]);e.each(function(e){e.row=t}),t.set("cells",e),t.builder=this.model,this.dialogs.row.setRowModel(t),this.dialogs.row.openDialog()},displayAddPrebuiltDialog:function(){this.dialogs.prebuilt.openDialog()},displayHistoryDialog:function(){this.dialogs.history.openDialog()},pasteRowHandler:function(){var e=a.helpers.clipboard.getModel("row-model");!_.isEmpty(e)&&e instanceof a.model.row&&(this.addHistoryEntry("row_pasted"),e.builder=this.model,this.model.get("rows").add(e,{at:this.model.get("rows").indexOf(this.model)+1}),this.model.refreshPanelsData())},getActiveCell:function(e){if(e=_.extend({createCell:!0},e),!this.model.get("rows").length){if(!e.createCell)return null;this.model.addRow({},[{weight:1}],{noAnimate:!0})}var t=this.activeCell;return _.isEmpty(t)||-1===this.model.get("rows").indexOf(t.model.row)?this.model.get("rows").last().get("cells").first():t.model},addLiveEditor:function(){return _.isEmpty(this.config.liveEditorPreview)||(this.liveEditor=new a.view.liveEditor({builder:this,previewUrl:this.config.liveEditorPreview}),this.liveEditor.hasPreviewUrl()&&this.$(".so-builder-toolbar .so-live-editor").show(),this.trigger("builder_live_editor_added")),this},displayLiveEditor:function(){_.isUndefined(this.liveEditor)||this.liveEditor.open()},addHistoryBrowser:function(){if(_.isEmpty(this.config.liveEditorPreview))return this;this.dialogs.history=new a.dialog.history,(this.dialogs.history.builder=this).dialogs.history.entries.builder=this.model,this.dialogs.history.setRevertEntry(this.model),this.$(".so-builder-toolbar .so-history").show()},addHistoryEntry:function(e,t){_.isUndefined(t)&&(t=null),_.isUndefined(this.dialogs.history)||this.dialogs.history.entries.addEntry(e,t)},supports:function(e){return"rowAction"===e?this.supports("addRow")||this.supports("editRow")||this.supports("deleteRow"):"widgetAction"===e?this.supports("addWidget")||this.supports("editWidget")||this.supports("deleteWidget"):!_.isUndefined(this.config.builderSupports[e])&&this.config.builderSupports[e]},handleContentChange:function(){if(panelsOptions.copy_content&&this.attachedToEditor&&this.$el.is(":visible")){var e=this.model.getPanelsData();_.isEmpty(e.widgets)||n.post(panelsOptions.ajaxurl,{action:"so_panels_builder_content",panels_data:JSON.stringify(e),post_id:this.config.postId},function(e){""!==e&&this.updateEditorContent(e)}.bind(this))}},updateEditorContent:function(e){if("tinyMCE"!==this.config.editorType||"undefined"==typeof tinyMCE||_.isNull(tinyMCE.get("content"))){n(this.config.editorId).val(e).trigger("change").trigger("keyup")}else{var t=tinyMCE.get("content");t.setContent(e),t.fire("change"),t.fire("keyup")}this.triggerYoastSeoChange()},triggerYoastSeoChange:function(){if(n("#yoast_wpseo_focuskw_text_input").length){var e,t=document.getElementById("yoast_wpseo_focuskw_text_input");document.createEvent?(e=document.createEvent("HTMLEvents")).initEvent("keyup",!0,!0):(e=document.createEventObject()).eventType="keyup",e.eventName="keyup",document.createEvent?t.dispatchEvent(e):t.fireEvent("on"+e.eventType,e)}},handleDisplayBuilder:function(){var e="undefined"!=typeof tinyMCE&&tinyMCE.get("content"),t=e&&_.isFunction(e.getContent)?e.getContent():n("textarea#content").val();if((_.isEmpty(this.model.get("data"))||_.isEmpty(this.model.get("data").widgets)&&_.isEmpty(this.model.get("data").grids))&&""!==t){var i=panelsOptions.text_widget;if(_.isEmpty(i))return;this.model.loadPanelsData(this.model.getPanelsDataFromHtml(t,i)),this.model.trigger("change"),this.model.trigger("change:data")}n("#post-status-info").addClass("for-siteorigin-panels")},handleHideBuilder:function(){n("#post-status-info").show().removeClass("for-siteorigin-panels")},wrapEditorExpandAdjust:function(){try{for(var t,e=(n.hasData(window)&&n._data(window)).events.scroll,i=0;i<e.length;i++)if("editor-expand"===e[i].namespace){t=e[i],n(window).unbind("scroll",t.handler),n(window).bind("scroll",function(e){this.attachedVisible||t.handler(e)}.bind(this));break}}catch(e){return}},handleBuilderSizing:function(){var e=this.$el.width();return e&&(e<575?this.$el.addClass("so-display-narrow"):this.$el.removeClass("so-display-narrow")),this},setDialogParents:function(s,l){_.each(this.dialogs,function(e,t,i){i[t].setParent(s,l)}),this.on("add_dialog",function(e){e.setParent(s,l)},this)},toggleWelcomeDisplay:function(){this.model.get("rows").isEmpty()?this.$(".so-panels-welcome-message").show():this.$(".so-panels-welcome-message").hide()},activateContextMenu:function(t,i){var e=this;if(n.contains(e.$el.get(0),t.target)){var s=n([]).add(e.$(".so-panels-welcome-message:visible")).add(e.$(".so-rows-container > .so-row-container")).add(e.$(".so-cells > .cell")).add(e.$(".cell-wrapper > .so-widget")).filter(function(e){return i.isOverEl(n(this),t)}),l=s.last().data("view");void 0!==l&&void 0!==l.buildContextualMenu?l.buildContextualMenu(t,i):s.last().hasClass("so-panels-welcome-message")&&this.buildContextualMenu(t,i)}},buildContextualMenu:function(e,t){var i={};this.supports("addRow")&&(i.add_row={title:panelsOptions.loc.contextual.add_row}),a.helpers.clipboard.canCopyPaste()&&a.helpers.clipboard.isModel("row-model")&&this.supports("addRow")&&(i.paste_row={title:panelsOptions.loc.contextual.row_paste}),_.isEmpty(i)||t.addSection("builder-actions",{sectionTitle:panelsOptions.loc.contextual.row_actions,search:!1},i,function(e){switch(e){case"add_row":this.displayAddRowDialog();break;case"paste_row":this.pasteRowHandler()}}.bind(this))}})},{}],24:[function(e,t,i){var l=window.panels,r=jQuery;t.exports=Backbone.View.extend({template:_.template(l.helpers.utils.processTemplate(r("#siteorigin-panels-builder-cell").html())),events:{"click .cell-wrapper":"handleCellClick"},row:null,widgetSortable:null,initialize:function(){this.listenTo(this.model.get("widgets"),"add",this.onAddWidget)},render:function(){var e={weight:this.model.get("weight"),totalWeight:this.row.model.get("cells").totalWeight()};this.setElement(this.template(e)),this.$el.data("view",this);var i=this;return this.model.get("widgets").each(function(e){var t=new l.view.widget({model:e});t.cell=i,t.render(),t.$el.appendTo(i.$(".widgets-container"))}),this.initSortable(),this.initResizable(),this},initSortable:function(){if(!this.row.builder.supports("moveWidget"))return this;var o=this,e=o.row.builder,t=e.$el.attr("id"),n=e.model;return this.widgetSortable=this.$(".widgets-container").sortable({placeholder:"so-widget-sortable-highlight",connectWith:"#"+t+" .so-cells .cell .widgets-container,.block-editor .so-cells .cell .widgets-container",tolerance:"pointer",scroll:!1,over:function(e,t){o.row.builder.trigger("widget_sortable_move")},remove:function(e,t){o.model.get("widgets").remove(r(t.item).data("view").model,{silent:!0}),n.refreshPanelsData()},receive:function(e,t){var i=r(t.item).data("view").model;i.cell=o.model,o.model.get("widgets").add(i,{silent:!0,at:r(t.item).index()}),n.refreshPanelsData()},stop:function(e,t){var i=r(t.item),s=i.data("view"),l=i.closest(".cell").data("view");o.model.get("widgets").get(s.model)&&(o.row.builder.addHistoryEntry("widget_moved"),s.model.moveToCell(l.model,{},i.index()),s.cell=l,n.refreshPanelsData())},helper:function(e,t){var i=t.clone().css({width:t.outerWidth(),"z-index":1e4,position:"fixed"}).addClass("widget-being-dragged").appendTo("body");return 720<t.outerWidth()&&i.animate({"margin-left":e.pageX-t.offset().left-240,width:480},"fast"),i}}),this},refreshSortable:function(){_.isNull(this.widgetSortable)||this.widgetSortable.sortable("refresh")},initResizable:function(){if(!this.row.builder.supports("editRow"))return this;var o,n=this.$(".resize-handle").css("position","absolute"),e=this.row.$el,a=this;return n.draggable({axis:"x",containment:e,start:function(e,t){if(o=a.$el.prev().data("view"),!_.isUndefined(o)){var i=a.$el.clone().appendTo(t.helper).css({position:"absolute",top:"0",width:a.$el.outerWidth(),left:5,height:a.$el.outerHeight()});i.find(".resize-handle").remove();var s=o.$el.clone().appendTo(t.helper).css({position:"absolute",top:"0",width:o.$el.outerWidth(),right:5,height:o.$el.outerHeight()});s.find(".resize-handle").remove(),r(this).data({newCellClone:i,prevCellClone:s})}},drag:function(e,t){var i=a.row.$el.width()+10,s=a.model.get("weight")-(t.position.left+n.outerWidth()/2)/i,l=o.model.get("weight")+(t.position.left+n.outerWidth()/2)/i;r(this).data("newCellClone").css("width",i*s).find(".preview-cell-weight").html(Math.round(1e3*s)/10),r(this).data("prevCellClone").css("width",i*l).find(".preview-cell-weight").html(Math.round(1e3*l)/10)},stop:function(e,t){r(this).data("newCellClone").remove(),r(this).data("prevCellClone").remove();var i=a.row.$el.width()+10,s=a.model.get("weight")-(t.position.left+n.outerWidth()/2)/i,l=o.model.get("weight")+(t.position.left+n.outerWidth()/2)/i;.02<s&&.02<l&&(a.row.builder.addHistoryEntry("cell_resized"),a.model.set("weight",s),o.model.set("weight",l),a.row.resize()),t.helper.css("left",-n.outerWidth()/2),a.row.builder.model.refreshPanelsData()}}),this},onAddWidget:function(e,t,i){i=_.extend({noAnimate:!1},i);var s=new l.view.widget({model:e});s.cell=this,_.isUndefined(e.isDuplicate)&&(e.isDuplicate=!1),s.render({loadForm:e.isDuplicate}),_.isUndefined(i.at)||t.length<=1?s.$el.appendTo(this.$(".widgets-container")):s.$el.insertAfter(this.$(".widgets-container .so-widget").eq(i.at-1)),!1===i.noAnimate&&s.visualCreate(),this.refreshSortable(),this.row.resize(),this.row.builder.trigger("widget_added")},handleCellClick:function(e){this.row.builder.$el.find(".so-cells .cell").removeClass("cell-selected"),this.row.builder.activeCell!==this||this.model.get("widgets").length?(this.$el.addClass("cell-selected"),this.row.builder.activeCell=this):this.row.builder.activeCell=null},pasteHandler:function(){var e=l.helpers.clipboard.getModel("widget-model");!_.isEmpty(e)&&e instanceof l.model.widget&&(this.row.builder.addHistoryEntry("widget_pasted"),e.cell=this.model,this.model.get("widgets").add(e),this.row.builder.model.refreshPanelsData())},buildContextualMenu:function(e,t){var i=this;t.hasSection("add-widget-below")||t.addSection("add-widget-cell",{sectionTitle:panelsOptions.loc.contextual.add_widget_cell,searchPlaceholder:panelsOptions.loc.contextual.search_widgets,defaultDisplay:panelsOptions.contextual.default_widgets},panelsOptions.widgets,function(e){i.row.builder.trigger("before_user_adds_widget"),i.row.builder.addHistoryEntry("widget_added");var t=new l.model.widget({class:e});t.cell=i.model,t.cell.get("widgets").add(t),i.row.builder.model.refreshPanelsData(),i.row.builder.trigger("after_user_adds_widget",t)});var s={};this.row.builder.supports("addWidget")&&l.helpers.clipboard.isModel("widget-model")&&(s.paste={title:panelsOptions.loc.contextual.cell_paste_widget}),_.isEmpty(s)||t.addSection("cell-actions",{sectionTitle:panelsOptions.loc.contextual.cell_actions,search:!1},s,function(e){switch(e){case"paste":this.pasteHandler()}this.row.builder.model.refreshPanelsData()}.bind(this)),this.row.buildContextualMenu(e,t)}})},{}],25:[function(e,t,i){var o=window.panels,d=jQuery;t.exports=Backbone.View.extend({dialogTemplate:_.template(o.helpers.utils.processTemplate(d("#siteorigin-panels-dialog").html())),dialogTabTemplate:_.template(o.helpers.utils.processTemplate(d("#siteorigin-panels-dialog-tab").html())),tabbed:!1,rendered:!1,builder:!1,className:"so-panels-dialog-wrapper",dialogClass:"",dialogIcon:"",parentDialog:!1,dialogOpen:!1,editableLabel:!1,events:{"click .so-close":"closeDialog","click .so-nav.so-previous":"navToPrevious","click .so-nav.so-next":"navToNext"},initialize:function(){this.once("open_dialog",this.render),this.once("open_dialog",this.attach),this.once("open_dialog",this.setDialogClass),this.trigger("initialize_dialog",this),_.isUndefined(this.initializeDialog)||this.initializeDialog(),_.bindAll(this,"initSidebars","hasSidebar","onResize","toggleLeftSideBar","toggleRightSideBar")},getNextDialog:function(){return null},getPrevDialog:function(){return null},setDialogClass:function(){""!==this.dialogClass&&this.$(".so-panels-dialog").addClass(this.dialogClass)},setBuilder:function(e){return(this.builder=e).trigger("add_dialog",this,this.builder),this},attach:function(){return this.$el.appendTo("body"),this},parseDialogContent:function(e,t){t=_.extend({cid:this.cid},t);var i=d(_.template(o.helpers.utils.processTemplate(e))(t)),s={title:i.find(".title").html(),buttons:i.find(".buttons").html(),content:i.find(".content").html()};return i.has(".left-sidebar")&&(s.left_sidebar=i.find(".left-sidebar").html()),i.has(".right-sidebar")&&(s.right_sidebar=i.find(".right-sidebar").html()),s},renderDialog:function(e){if(e=_.extend({editableLabel:this.editableLabel,dialogIcon:this.dialogIcon},e),this.$el.html(this.dialogTemplate(e)).hide(),this.$el.data("view",this),this.$el.addClass("so-panels-dialog-wrapper"),!1!==this.parentDialog){var t=this,i=d('<h3 class="so-parent-link"></h3>').html(this.parentDialog.text+'<div class="so-separator"></div>');i.click(function(e){e.preventDefault(),t.closeDialog(),t.parentDialog.openDialog()}),this.$(".so-title-bar .so-title").before(i)}return this.$(".so-title-bar .so-title-editable").length&&this.initEditableLabel(),setTimeout(this.initSidebars,1),this},initSidebars:function(){var e=this.$(".so-show-left-sidebar").hide(),t=this.$(".so-show-right-sidebar").hide(),i=this.hasSidebar("left"),s=this.hasSidebar("right");(i||s)&&(d(window).on("resize",this.onResize),i&&(e.show(),e.on("click",this.toggleLeftSideBar)),s&&(t.show(),t.on("click",this.toggleRightSideBar))),this.onResize()},initTabs:function(){var e=this.$(".so-sidebar-tabs li a");if(0===e.length)return this;var l=this;return e.click(function(e){e.preventDefault();var t=d(this);l.$(".so-sidebar-tabs li").removeClass("tab-active"),l.$(".so-content .so-content-tabs > *").hide(),t.parent().addClass("tab-active");var i=t.attr("href");if(!_.isUndefined(i)&&"#"===i.charAt(0)){var s=i.split("#")[1];l.$(".so-content .so-content-tabs .tab-"+s).show()}l.trigger("tab_click",t)}),this.$(".so-sidebar-tabs li a").first().click(),this},initToolbar:function(){this.$(".so-toolbar .so-buttons .so-toolbar-button").click(function(e){e.preventDefault(),this.trigger("button_click",d(e.currentTarget))}.bind(this)),this.$(".so-toolbar .so-buttons .so-dropdown-button").click(function(e){e.preventDefault();var t=d(e.currentTarget).siblings(".so-dropdown-links-wrapper");t.is(".hidden")?t.removeClass("hidden"):t.addClass("hidden")}.bind(this)),d("html").click(function(l){this.$(".so-dropdown-links-wrapper").not(".hidden").each(function(e,t){var i=d(t),s=d(l.target);0!==s.length&&(s.is(".so-needs-confirm")&&!s.is(".so-confirmed")||s.is(".so-dropdown-button"))||i.addClass("hidden")})}.bind(this))},initEditableLabel:function(){var l=this.$(".so-title-bar .so-title-editable");l.keypress(function(e){var t="keypress"===e.type&&13===e.keyCode;if(t){var i=d(":tabbable"),s=i.index(l);i.eq(s+1).focus(),window.getSelection().removeAllRanges()}return!t}).blur(function(){var e=l.text().replace(/^\s+|\s+$/gm,"");e!==l.data("original-value").replace(/^\s+|\s+$/gm,"")&&(l.text(e),this.trigger("edit_label",e))}.bind(this)),l.focus(function(){l.data("original-value",l.text()),o.helpers.utils.selectElementContents(this)})},setupDialog:function(){this.openDialog(),this.closeDialog()},refreshDialogNav:function(){this.$(".so-title-bar .so-nav").show().removeClass("so-disabled");var e=this.getNextDialog(),t=this.$(".so-title-bar .so-next"),i=this.getPrevDialog(),s=this.$(".so-title-bar .so-previous");null===e?t.hide():!1===e&&t.addClass("so-disabled"),null===i?s.hide():!1===i&&s.addClass("so-disabled")},openDialog:function(e){(e=_.extend({silent:!1},e)).silent||this.trigger("open_dialog"),this.dialogOpen=!0,this.refreshDialogNav(),o.helpers.pageScroll.lock(),d(window).on("keyup",this.keyboardListen),this.onResize(),this.$el.show(),e.silent||(this.trigger("open_dialog_complete"),this.builder.trigger("open_dialog",this),d(document).trigger("open_dialog",this))},closeDialog:function(e){(e=_.extend({silent:!1},e)).silent||this.trigger("close_dialog"),this.dialogOpen=!1,this.$el.hide(),o.helpers.pageScroll.unlock(),d(window).off("keyup",this.keyboardListen),e.silent||(this.trigger("close_dialog_complete"),this.builder.trigger("close_dialog",this))},keyboardListen:function(e){27===e.which&&d(".so-panels-dialog-wrapper .so-close").trigger("click")},navToPrevious:function(){this.closeDialog();var e=this.getPrevDialog();null!==e&&!1!==e&&e.openDialog()},navToNext:function(){this.closeDialog();var e=this.getNextDialog();null!==e&&!1!==e&&e.openDialog()},getFormValues:function(e){_.isUndefined(e)&&(e=".so-content");var a,t=this.$(e),r={};return t.find("[name]").each(function(){var t=d(this);try{var e=/([A-Za-z_]+)\[(.*)\]/.exec(t.attr("name"));if(_.isEmpty(e))return!0;_.isUndefined(e[2])?a=t.attr("name"):(a=e[2].split("][")).unshift(e[1]),a=a.map(function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e});var i=r,s=null,l=!!_.isString(t.attr("type"))&&t.attr("type").toLowerCase();if("checkbox"===l)s=t.is(":checked")?""===t.val()||t.val():null;else if("radio"===l){if(!t.is(":checked"))return;s=t.val()}else if("SELECT"===t.prop("tagName")){var o=t.find("option:selected");1===o.length?s=t.find("option:selected").val():1<o.length&&(s=_.map(t.find("option:selected"),function(e,t){return d(e).val()}))}else s=t.val();if(!_.isUndefined(t.data("panels-filter")))switch(t.data("panels-filter")){case"json_parse":try{s=JSON.parse(s)}catch(e){s=""}}if(null!==s)for(var n=0;n<a.length;n++)n===a.length-1?""===a[n]?i.push(s):i[a[n]]=s:(_.isUndefined(i[a[n]])&&(""===a[n+1]?i[a[n]]=[]:i[a[n]]={}),i=i[a[n]])}catch(e){console.log("Field ["+t.attr("name")+"] could not be processed and was skipped - "+e.message)}}),r},setStatusMessage:function(e,t,i){var s=i?'<span class="dashicons dashicons-warning"></span>'+e:e;this.$(".so-toolbar .so-status").html(s),!_.isUndefined(t)&&t?this.$(".so-toolbar .so-status").addClass("so-panels-loading"):this.$(".so-toolbar .so-status").removeClass("so-panels-loading")},setParent:function(e,t){this.parentDialog={text:e,dialog:t}},onResize:function(){var s=window.matchMedia("(max-width: 980px)");["left","right"].forEach(function(e){var t=this.$(".so-"+e+"-sidebar"),i=this.$(".so-show-"+e+"-sidebar");this.hasSidebar(e)?(i.hide(),s.matches?(i.show(),i.closest(".so-title-bar").addClass("so-has-"+e+"-button"),t.hide(),t.closest(".so-panels-dialog").removeClass("so-panels-dialog-has-"+e+"-sidebar")):(i.hide(),i.closest(".so-title-bar").removeClass("so-has-"+e+"-button"),t.show(),t.closest(".so-panels-dialog").addClass("so-panels-dialog-has-"+e+"-sidebar"))):(t.hide(),i.hide())}.bind(this))},hasSidebar:function(e){return 0<this.$(".so-"+e+"-sidebar").children().length},toggleLeftSideBar:function(){this.toggleSidebar("left")},toggleRightSideBar:function(){this.toggleSidebar("right")},toggleSidebar:function(e){var t=this.$(".so-"+e+"-sidebar");t.is(":visible")?t.hide():t.show()}})},{}],26:[function(e,t,i){var s=window.panels,o=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(o("#siteorigin-panels-live-editor").html())),previewScrollTop:0,loadTimes:[],previewFrameId:1,previewUrl:null,previewIframe:null,events:{"click .live-editor-close":"close","click .live-editor-collapse":"collapse","click .live-editor-mode":"mobileToggle"},initialize:function(e){e=_.extend({builder:!1,previewUrl:!1},e),_.isEmpty(e.previewUrl)&&(e.previewUrl=panelsOptions.ajaxurl+"&action=so_panels_live_editor_preview"),this.builder=e.builder,this.previewUrl=e.previewUrl,this.listenTo(this.builder.model,"refresh_panels_data",this.handleRefreshData),this.listenTo(this.builder.model,"load_panels_data",this.handleLoadData)},render:function(){this.setElement(this.template()),this.$el.hide();var t=!1;o(document).mousedown(function(){t=!0}).mouseup(function(){t=!1});var i=this;return this.$el.on("mouseenter",".so-widget-wrapper",function(){var e=o(this).data("live-editor-preview-widget");t||void 0===e||!e.length||i.$(".so-preview-overlay").is(":visible")||(i.highlightElement(e),i.scrollToElement(e))}),this.$el.on("mouseleave",".so-widget-wrapper",function(){this.resetHighlights()}.bind(this)),this.listenTo(this.builder,"open_dialog",function(){this.resetHighlights()}),this},attach:function(){this.$el.appendTo("body")},open:function(){if(""===this.$el.html()&&this.render(),0===this.$el.closest("body").length&&this.attach(),s.helpers.pageScroll.lock(),this.$el.is(":visible"))return this;if(this.$el.show(),this.refreshPreview(this.builder.model.getPanelsData()),this.originalContainer=this.builder.$el.parent(),this.builder.$el.appendTo(this.$(".so-live-editor-builder")),this.builder.$(".so-tool-button.so-live-editor").hide(),this.builder.trigger("builder_resize"),"auto-draft"===o("#original_post_status").val()&&!this.autoSaved){var e=this;wp.autosave&&(""===o('#title[name="post_title"]').val()&&o('#title[name="post_title"]').val(panelsOptions.loc.draft).trigger("keydown"),o(document).one("heartbeat-tick.autosave",function(){e.autoSaved=!0,e.refreshPreview(e.builder.model.getPanelsData())}),wp.autosave.server.triggerSave())}},close:function(){if(!this.$el.is(":visible"))return this;this.$el.hide(),s.helpers.pageScroll.unlock(),this.builder.$el.appendTo(this.originalContainer),this.builder.$(".so-tool-button.so-live-editor").show(),this.builder.trigger("builder_resize")},collapse:function(){this.$el.toggleClass("so-collapsed");var e=this.$(".live-editor-collapse span");e.html(e.data(this.$el.hasClass("so-collapsed")?"expand":"collapse"))},highlightElement:function(e){_.isUndefined(this.resetHighlightTimeout)||clearTimeout(this.resetHighlightTimeout),this.previewIframe.contents().find("body").find(".panel-grid .panel-grid-cell .so-panel").filter(function(){return 0===o(this).parents(".so-panel").length}).not(e).addClass("so-panels-faded"),e.removeClass("so-panels-faded").addClass("so-panels-highlighted")},resetHighlights:function(){var e=this.previewIframe.contents().find("body");this.resetHighlightTimeout=setTimeout(function(){e.find(".panel-grid .panel-grid-cell .so-panel").removeClass("so-panels-faded so-panels-highlighted")},100)},scrollToElement:function(e){this.$(".so-preview iframe")[0].contentWindow.liveEditorScrollTo(e)},handleRefreshData:function(e,t){if(!this.$el.is(":visible"))return this;this.refreshPreview(e)},handleLoadData:function(){if(!this.$el.is(":visible"))return this;this.refreshPreview(this.builder.model.getPanelsData())},refreshPreview:function(e){var t=this.loadTimes.length?_.reduce(this.loadTimes,function(e,t){return e+t},0)/this.loadTimes.length:1e3;_.isNull(this.previewIframe)||this.$(".so-preview-overlay").is(":visible")||(this.previewScrollTop=this.previewIframe.contents().scrollTop()),this.$(".so-preview-overlay").show(),this.$(".so-preview-overlay .so-loading-bar").clearQueue().css("width","0%").animate({width:"100%"},parseInt(t)+100),this.postToIframe({live_editor_panels_data:JSON.stringify(e),live_editor_post_ID:this.builder.config.postId},this.previewUrl,this.$(".so-preview")),this.previewIframe.data("load-start",(new Date).getTime())},postToIframe:function(e,t,i){_.isNull(this.previewIframe)||this.previewIframe.remove();var s="siteorigin-panels-live-preview-"+this.previewFrameId;this.previewIframe=o('<iframe src="javascript:false;" />').attr({id:s,name:s}).appendTo(i),this.setupPreviewFrame(this.previewIframe);var l=o('<form id="soPostToPreviewFrame" method="post" />').attr({id:s,target:this.previewIframe.attr("id"),action:t}).appendTo("body");return o.each(e,function(e,t){o('<input type="hidden" />').attr({name:e,value:t}).appendTo(l)}),l.submit().remove(),this.previewFrameId++,this.previewIframe},setupPreviewFrame:function(e){var l=this;e.data("iframeready",!1).on("iframeready",function(){var e=o(this),t=e.contents();if(!e.data("iframeready")){e.data("iframeready",!0),void 0!==e.data("load-start")&&(l.loadTimes.unshift((new Date).getTime()-e.data("load-start")),_.isEmpty(l.loadTimes)||(l.loadTimes=l.loadTimes.slice(0,4))),setTimeout(function(){t.scrollTop(l.previewScrollTop),l.$(".so-preview-overlay").hide()},100);var i=t.find("#pl-"+l.builder.config.postId);i.find(".panel-grid .panel-grid-cell .so-panel").filter(function(){return o(this).closest(".panel-layout").is(i)}).each(function(e,t){var i=o(t),s=l.$(".so-live-editor-builder .so-widget-wrapper").eq(i.data("index"));s.data("live-editor-preview-widget",i),i.css({cursor:"pointer"}).mouseenter(function(){s.parent().addClass("so-hovered"),l.highlightElement(i)}).mouseleave(function(){s.parent().removeClass("so-hovered"),l.resetHighlights()}).click(function(e){e.preventDefault(),s.find(".title h4").click()})}),t.find("a").css({"pointer-events":"none"}).click(function(e){e.preventDefault()})}}).on("load",function(){var e=o(this);e.data("iframeready")||e.trigger("iframeready")})},hasPreviewUrl:function(){return""!==this.$("form.live-editor-form").attr("action")},mobileToggle:function(e){var t=o(e.currentTarget);this.$(".live-editor-mode").not(t).removeClass("so-active"),t.addClass("so-active"),this.$el.removeClass("live-editor-desktop-mode live-editor-tablet-mode live-editor-mobile-mode").addClass("live-editor-"+t.data("mode")+"-mode")}})},{}],27:[function(e,t,i){var n=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(n.helpers.utils.processTemplate(l("#siteorigin-panels-builder-row").html())),events:{"click .so-row-settings":"editSettingsHandler","click .so-row-duplicate":"duplicateHandler","click .so-row-delete":"confirmedDeleteHandler","click .so-row-color":"rowColorChangeHandler"},builder:null,dialog:null,initialize:function(){var e=this.model.get("cells");this.listenTo(e,"add",this.handleCellAdd),this.listenTo(e,"remove",this.handleCellRemove),this.listenTo(this.model,"reweight_cells",this.resize),this.listenTo(this.model,"destroy",this.onModelDestroy);var t=this;e.each(function(e){t.listenTo(e.get("widgets"),"add",t.resize)}),e.on("add",function(e){t.listenTo(e.get("widgets"),"add",t.resize)},this),this.listenTo(this.model,"change:label",this.onLabelChange)},render:function(){var e=this.model.has("color_label")?this.model.get("color_label"):1,t=this.model.has("label")?this.model.get("label"):"";this.setElement(this.template({rowColorLabel:e,rowLabel:t})),this.$el.data("view",this);var i=this;return this.model.get("cells").each(function(e){var t=new n.view.cell({model:e});t.row=i,t.render(),t.$el.appendTo(i.$(".so-cells"))}),this.builder.supports("rowAction")?(this.builder.supports("editRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-settings").parent().remove(),this.$el.addClass("so-row-no-edit")),this.builder.supports("addRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-duplicate").parent().remove(),this.$el.addClass("so-row-no-duplicate")),this.builder.supports("deleteRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-delete").parent().remove(),this.$el.addClass("so-row-no-delete"))):(this.$(".so-row-toolbar .so-dropdown-wrapper").remove(),this.$el.addClass("so-row-no-actions")),this.builder.supports("moveRow")||(this.$(".so-row-toolbar .so-row-move").remove(),this.$el.addClass("so-row-no-move")),l.trim(this.$(".so-row-toolbar").html()).length||this.$(".so-row-toolbar").remove(),this.listenTo(this.builder,"widget_sortable_move",this.resize),this.listenTo(this.builder,"builder_resize",this.resize),this.resize(),this},visualCreate:function(){this.$el.hide().fadeIn("fast")},resize:function(e){if(this.$el.is(":visible")){this.$(".so-cells .cell-wrapper").css("min-height",0),this.$(".so-cells .resize-handle").css("height",0);var t=0;this.$(".so-cells .cell").each(function(){t=Math.max(t,l(this).height()),l(this).css("width",100*l(this).data("view").model.get("weight")+"%")}),this.$(".so-cells .cell-wrapper").css("min-height",Math.max(t,63)),this.$(".so-cells .resize-handle").css("height",this.$(".so-cells .cell-wrapper").outerHeight())}},onModelDestroy:function(){this.remove()},visualDestroyModel:function(){this.builder.addHistoryEntry("row_deleted");var e=this;this.$el.fadeOut("normal",function(){e.model.destroy(),e.builder.model.refreshPanelsData()})},onLabelChange:function(e,t){0==this.$(".so-row-label").length?this.$(".so-row-toolbar").prepend('<h3 class="so-row-label">'+t+"</h3>"):this.$(".so-row-label").text(t)},duplicateHandler:function(){this.builder.addHistoryEntry("row_duplicated");var e=this.model.clone(this.builder.model);this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData()},copyHandler:function(){n.helpers.clipboard.setModel(this.model)},pasteHandler:function(){var e=n.helpers.clipboard.getModel("row-model");!_.isEmpty(e)&&e instanceof n.model.row&&(this.builder.addHistoryEntry("row_pasted"),e.builder=this.builder.model,this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData())},confirmedDeleteHandler:function(e){var t=l(e.target);if(t.hasClass("dashicons")&&(t=t.parent()),t.hasClass("so-confirmed"))this.visualDestroyModel();else{var i=t.html();t.addClass("so-confirmed").html('<span class="dashicons dashicons-yes"></span>'+panelsOptions.loc.dropdown_confirm),setTimeout(function(){t.removeClass("so-confirmed").html(i)},2500)}},editSettingsHandler:function(){if(this.builder.supports("editRow"))return null===this.dialog&&(this.dialog=new n.dialog.row,this.dialog.setBuilder(this.builder).setRowModel(this.model),this.dialog.rowView=this),this.dialog.openDialog(),this},deleteHandler:function(){return this.model.destroy(),this},rowColorChangeHandler:function(e){this.$(".so-row-color").removeClass("so-row-color-selected");var t=l(e.target),i=t.data("color-label"),s=this.model.has("color_label")?this.model.get("color_label"):1;t.addClass("so-row-color-selected"),this.$el.removeClass("so-row-color-"+s),this.$el.addClass("so-row-color-"+i),this.model.set("color_label",i)},handleCellAdd:function(e){var t=new n.view.cell({model:e});t.row=this,t.render(),t.$el.appendTo(this.$(".so-cells"))},handleCellRemove:function(t){this.$(".so-cells > .cell").each(function(){var e=l(this).data("view");_.isUndefined(e)||e.model.cid===t.cid&&e.remove()})},buildContextualMenu:function(e,t){for(var i=[],s=1;s<5;s++)i.push({title:s+" "+panelsOptions.loc.contextual.column});this.builder.supports("addRow")&&t.addSection("add-row",{sectionTitle:panelsOptions.loc.contextual.add_row,search:!1},i,function(e){this.builder.addHistoryEntry("row_added");for(var t=Number(e)+1,i=[],s=0;s<t;s++)i.push({weight:100/t});var l=new n.model.row({collection:this.collection}),o=new n.collection.cells(i);o.each(function(e){e.row=l}),l.setCells(o),l.builder=this.builder.model,this.builder.model.get("rows").add(l,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData()}.bind(this));var l={};this.builder.supports("editRow")&&(l.edit={title:panelsOptions.loc.contextual.row_edit}),n.helpers.clipboard.canCopyPaste()&&(l.copy={title:panelsOptions.loc.contextual.row_copy},this.builder.supports("addRow")&&n.helpers.clipboard.isModel("row-model")&&(l.paste={title:panelsOptions.loc.contextual.row_paste})),this.builder.supports("addRow")&&(l.duplicate={title:panelsOptions.loc.contextual.row_duplicate}),this.builder.supports("deleteRow")&&(l.delete={title:panelsOptions.loc.contextual.row_delete,confirm:!0}),_.isEmpty(l)||t.addSection("row-actions",{sectionTitle:panelsOptions.loc.contextual.row_actions,search:!1},l,function(e){switch(e){case"edit":this.editSettingsHandler();break;case"copy":this.copyHandler();break;case"paste":this.pasteHandler();break;case"duplicate":this.duplicateHandler();break;case"delete":this.visualDestroyModel()}}.bind(this))}})},{}],28:[function(e,t,i){window.panels;var d=jQuery;t.exports=Backbone.View.extend({stylesLoaded:!1,initialize:function(){},render:function(e,t,i){if(!_.isUndefined(e)){i=_.extend({builderType:"",dialog:null},i),this.$el.addClass("so-visual-styles so-"+e+"-styles so-panels-loading");var s={builderType:i.builderType};return"cell"===e&&(s.index=i.index),d.post(panelsOptions.ajaxurl,{action:"so_panels_style_form",type:e,style:this.model.get("style"),args:JSON.stringify(s),postId:t},null,"html").done(function(e){this.$el.html(e),this.setupFields(),this.stylesLoaded=!0,this.trigger("styles_loaded",!_.isEmpty(e)),_.isNull(i.dialog)||i.dialog.trigger("styles_loaded",!_.isEmpty(e))}.bind(this)).fail(function(e){var t;t=e&&e.responseText?e.responseText:panelsOptions.forms.loadingFailed,this.$el.html(t)}.bind(this)).always(function(){this.$el.removeClass("so-panels-loading")}.bind(this)),this}},attach:function(e){e.append(this.$el)},detach:function(){this.$el.detach()},setupFields:function(){this.$(".style-section-wrapper").each(function(){var t=d(this);t.find(".style-section-head").click(function(e){e.preventDefault(),t.find(".style-section-fields").slideToggle("fast")})}),_.isUndefined(d.fn.wpColorPicker)||(_.isObject(panelsOptions.wpColorPickerOptions.palettes)&&!d.isArray(panelsOptions.wpColorPickerOptions.palettes)&&(panelsOptions.wpColorPickerOptions.palettes=d.map(panelsOptions.wpColorPickerOptions.palettes,function(e){return e})),this.$(".so-wp-color-field").wpColorPicker(panelsOptions.wpColorPickerOptions)),this.$(".style-field-image").each(function(){var s=null,l=d(this);l.find(".so-image-selector").click(function(e){e.preventDefault(),null===s&&(s=wp.media({title:"choose",library:{type:"image"},button:{text:"Done",close:!0}})).on("select",function(){var t=s.state().get("selection").first().attributes,i=t.url;if(!_.isUndefined(t.sizes))try{i=t.sizes.thumbnail.url}catch(e){i=t.sizes.full.url}l.find(".current-image").css("background-image","url("+i+")"),l.find(".so-image-selector > input").val(t.id),l.find(".remove-image").removeClass("hidden")}),s.open()}),l.find(".remove-image").click(function(e){e.preventDefault(),l.find(".current-image").css("background-image","none"),l.find(".so-image-selector > input").val(""),l.find(".remove-image").addClass("hidden")})}),this.$(".style-field-measurement").each(function(){var e=d(this),n=e.find('input[type="text"]'),a=e.find("select"),r=e.find('input[type="hidden"]');n.focus(function(){d(this).select()});!function(e){if(""!==e){var t=/(?:([0-9\.,\-]+)(.*))+/,i=r.val().split(" "),s=[];for(var l in i){var o=t.exec(i[l]);_.isNull(o)||_.isUndefined(o[1])||_.isUndefined(o[2])||(s.push(o[1]),a.val(o[2]))}1===n.length?n.val(s.join(" ")):(1===s.length?s=[s[0],s[0],s[0],s[0]]:2===s.length?s=[s[0],s[1],s[0],s[1]]:3===s.length&&(s=[s[0],s[1],s[2],s[1]]),n.each(function(e,t){d(t).val(s[e])}))}}(r.val());var t=function(e){if(1===n.length){var t=n.val().split(" ").filter(function(e){return""!==e}).map(function(e){return e+a.val()}).join(" ");r.val(t)}else{var i=d(e.target),s=[],l=[],o=[];n.each(function(e,t){var i=""!==d(t).val()?parseFloat(d(t).val()):null;s.push(i),null===i?l.push(e):o.push(e)}),3===l.length&&o[0]===n.index(i)&&(n.val(i.val()),s=[i.val(),i.val(),i.val(),i.val()]),JSON.stringify(s)===JSON.stringify([null,null,null,null])?r.val(""):r.val(s.map(function(e){return(null===e?0:e)+a.val()}).join(" "))}};n.change(t),a.change(t)})}})},{}],29:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder-widget").html())),cell:null,dialog:null,events:{"click .widget-edit":"editHandler","click .title h4":"editHandler","click .actions .widget-duplicate":"duplicateHandler","click .actions .widget-delete":"deleteHandler"},initialize:function(){this.listenTo(this.model,"destroy",this.onModelDestroy),this.listenTo(this.model,"change:values",this.onModelChange),this.listenTo(this.model,"change:label",this.onLabelChange)},render:function(e){if(e=_.extend({loadForm:!1},e),this.setElement(this.template({title:this.model.getWidgetField("title"),description:this.model.getTitle()})),this.$el.data("view",this),this.cell.row.builder.supports("editWidget")&&!this.model.get("read_only")||(this.$(".actions .widget-edit").remove(),this.$el.addClass("so-widget-no-edit")),this.cell.row.builder.supports("addWidget")||(this.$(".actions .widget-duplicate").remove(),this.$el.addClass("so-widget-no-duplicate")),this.cell.row.builder.supports("deleteWidget")||(this.$(".actions .widget-delete").remove(),this.$el.addClass("so-widget-no-delete")),this.cell.row.builder.supports("moveWidget")||this.$el.addClass("so-widget-no-move"),l.trim(this.$(".actions").html()).length||this.$(".actions").remove(),this.model.get("read_only")&&this.$el.addClass("so-widget-read-only"),0===_.size(this.model.get("values"))||e.loadForm){var t=this.getEditDialog();t.once("form_loaded",t.saveWidget,t),t.setupDialog()}return this.listenTo(this.cell.row.builder,"after_user_adds_widget",this.afterUserAddsWidgetHandler),this},visualCreate:function(){this.$el.hide().fadeIn("fast")},getEditDialog:function(){return null===this.dialog&&(this.dialog=new s.dialog.widget({model:this.model}),this.dialog.setBuilder(this.cell.row.builder),this.dialog.widgetView=this),this.dialog},editHandler:function(){return!this.cell.row.builder.supports("editWidget")||this.model.get("read_only")||this.getEditDialog().openDialog(),this},duplicateHandler:function(){this.cell.row.builder.addHistoryEntry("widget_duplicated");var e=this.model.clone(this.model.cell);return this.cell.model.get("widgets").add(e,{at:this.model.collection.indexOf(this.model)+1}),this.cell.row.builder.model.refreshPanelsData(),this},copyHandler:function(){s.helpers.clipboard.setModel(this.model)},deleteHandler:function(){return this.visualDestroyModel(),this},onModelChange:function(){this.$(".description").html(this.model.getTitle())},onLabelChange:function(e){this.$(".title > h4").text(e.getWidgetField("title"))},onModelDestroy:function(){this.remove()},visualDestroyModel:function(){return this.cell.row.builder.addHistoryEntry("widget_deleted"),this.$el.fadeOut("fast",function(){this.cell.row.resize(),this.model.destroy(),this.cell.row.builder.model.refreshPanelsData(),this.remove()}.bind(this)),this},buildContextualMenu:function(e,t){this.cell.row.builder.supports("addWidget")&&t.addSection("add-widget-below",{sectionTitle:panelsOptions.loc.contextual.add_widget_below,searchPlaceholder:panelsOptions.loc.contextual.search_widgets,defaultDisplay:panelsOptions.contextual.default_widgets},panelsOptions.widgets,function(e){this.cell.row.builder.trigger("before_user_adds_widget"),this.cell.row.builder.addHistoryEntry("widget_added");var t=new s.model.widget({class:e});t.cell=this.cell.model,this.cell.model.get("widgets").add(t,{at:this.model.collection.indexOf(this.model)+1}),this.cell.row.builder.model.refreshPanelsData(),this.cell.row.builder.trigger("after_user_adds_widget",t)}.bind(this));var i={};this.cell.row.builder.supports("editWidget")&&!this.model.get("read_only")&&(i.edit={title:panelsOptions.loc.contextual.widget_edit}),s.helpers.clipboard.canCopyPaste()&&(i.copy={title:panelsOptions.loc.contextual.widget_copy}),this.cell.row.builder.supports("addWidget")&&(i.duplicate={title:panelsOptions.loc.contextual.widget_duplicate}),this.cell.row.builder.supports("deleteWidget")&&(i.delete={title:panelsOptions.loc.contextual.widget_delete,confirm:!0}),_.isEmpty(i)||t.addSection("widget-actions",{sectionTitle:panelsOptions.loc.contextual.widget_actions,search:!1},i,function(e){switch(e){case"edit":this.editHandler();break;case"copy":this.copyHandler();break;case"duplicate":this.duplicateHandler();break;case"delete":this.visualDestroyModel()}}.bind(this)),this.cell.buildContextualMenu(e,t)},afterUserAddsWidgetHandler:function(e){this.model===e&&panelsOptions.instant_open&&setTimeout(this.editHandler.bind(this),350)}})},{}],30:[function(e,t,i){var a=jQuery,s={addWidget:function(e,t,i){var s=wp.customHtmlWidgets,l=a("<div></div>"),o=t.find(".widget-content:first");o.before(l);var n=new s.CustomHtmlWidgetControl({el:l,syncContainer:o});return n.initializeEditor(),n.editor.codemirror.refresh(),n}};t.exports=s},{}],31:[function(e,t,i){var l=e("./custom-html-widget"),o=e("./media-widget"),n=e("./text-widget"),s={CUSTOM_HTML:"custom_html",MEDIA_AUDIO:"media_audio",MEDIA_GALLERY:"media_gallery",MEDIA_IMAGE:"media_image",MEDIA_VIDEO:"media_video",TEXT:"text",addWidget:function(e,t){var i,s=e.find("> .id_base").val();switch(s){case this.CUSTOM_HTML:i=l;break;case this.MEDIA_AUDIO:case this.MEDIA_GALLERY:case this.MEDIA_IMAGE:case this.MEDIA_VIDEO:i=o;break;case this.TEXT:i=n}i.addWidget(s,e,t)}};t.exports=s},{"./custom-html-widget":30,"./media-widget":32,"./text-widget":33}],32:[function(e,t,i){var h=jQuery,s={addWidget:function(e,t,i){var s=wp.mediaWidgets,l=s.controlConstructors[e];if(l){var o=s.modelConstructors[e]||s.MediaWidgetModel,n=t.find("> .widget-content"),a=h('<div class="media-widget-control"></div>');n.before(a);var r={};n.find(".media-widget-instance-property").each(function(){var e=h(this);r[e.data("property")]=e.val()}),r.widget_id=i;var d=new l({el:a,syncContainer:n,model:new o(r)});return d.render(),d}}};t.exports=s},{}],33:[function(e,t,i){var h=jQuery,s={addWidget:function(e,t,i){var s=wp.textWidgets,l={},o=t.find(".visual");if(0<o.length){if(!o.val())return null;var n=h("<div></div>"),a=t.find(".widget-content:first");a.before(n),l={el:n,syncContainer:a}}else l={el:t};var r=new s.TextWidgetControl(l),d=wp.oldEditor?wp.oldEditor:wp.editor;return d&&d.hasOwnProperty("autop")&&(wp.editor.autop=d.autop,wp.editor.removep=d.removep,wp.editor.initialize=d.initialize),r.initializeEditor(),r}};t.exports=s},{}]},{},[16]);
 
js/{siteorigin-panels-2102.js → siteorigin-panels-2103.js} RENAMED
File without changes
js/{siteorigin-panels-2102.min.js → siteorigin-panels-2103.min.js} RENAMED
File without changes
js/styling-2101.js DELETED
@@ -1,62 +0,0 @@
1
- /* global _, jQuery */
2
-
3
- jQuery( function ( $ ) {
4
-
5
- var fullContainer = $( panelsStyles.fullContainer );
6
- if ( fullContainer.length === 0 ) {
7
- fullContainer = $( 'body' );
8
- }
9
-
10
- // Stretch all the full width rows
11
- var stretchFullWidthRows = function () {
12
- var $panelsRow = $( '.siteorigin-panels-stretch.panel-row-style' );
13
- $panelsRow.each( function () {
14
- var $$ = $( this );
15
-
16
- var stretchType = $$.data( 'stretch-type' );
17
- var defaultSidePadding = stretchType === 'full-stretched-padded' ? '' : 0;
18
-
19
- // Reset all the styles associated with row stretching
20
- $$.css( {
21
- 'margin-left': 0,
22
- 'margin-right': 0,
23
- 'padding-left': defaultSidePadding,
24
- 'padding-right': defaultSidePadding
25
- } );
26
-
27
- var leftSpace = $$.offset().left - fullContainer.offset().left,
28
- rightSpace = fullContainer.outerWidth() - leftSpace - $$.parent().outerWidth();
29
-
30
- $$.css( {
31
- 'margin-left': - leftSpace,
32
- 'margin-right': - rightSpace,
33
- 'padding-left': stretchType === 'full' ? leftSpace : defaultSidePadding,
34
- 'padding-right': stretchType === 'full' ? rightSpace : defaultSidePadding
35
- } );
36
-
37
- var cells = $$.find( '> .panel-grid-cell' );
38
-
39
- if ( stretchType === 'full-stretched' && cells.length === 1 ) {
40
- cells.css( {
41
- 'padding-left': 0,
42
- 'padding-right': 0
43
- } );
44
- }
45
-
46
- $$.css( {
47
- 'border-left': 0,
48
- 'border-right': 0
49
- } );
50
- } );
51
-
52
- if ( $panelsRow.length ) {
53
- $( window ).trigger( 'panelsStretchRows' );
54
- }
55
- }
56
- $( window ).on( 'resize load', stretchFullWidthRows );
57
- stretchFullWidthRows();
58
-
59
- // This should have been done in the footer, but run it here just incase.
60
- $( 'body' ).removeClass( 'siteorigin-panels-before-js' );
61
-
62
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/styling-2101.min.js DELETED
@@ -1 +0,0 @@
1
- jQuery(function(a){var d=a(panelsStyles.fullContainer);0===d.length&&(d=a("body"));var e=function(){var e=a(".siteorigin-panels-stretch.panel-row-style");e.each(function(){var e=a(this),t=e.data("stretch-type"),r="full-stretched-padded"===t?"":0;e.css({"margin-left":0,"margin-right":0,"padding-left":r,"padding-right":r});var i=e.offset().left-d.offset().left,n=d.outerWidth()-i-e.parent().outerWidth();e.css({"margin-left":-i,"margin-right":-n,"padding-left":"full"===t?i:r,"padding-right":"full"===t?n:r});var l=e.find("> .panel-grid-cell");"full-stretched"===t&&1===l.length&&l.css({"padding-left":0,"padding-right":0}),e.css({"border-left":0,"border-right":0})}),e.length&&a(window).trigger("panelsStretchRows")};a(window).on("resize load",e),e(),a("body").removeClass("siteorigin-panels-before-js")});
 
js/{styling-2102.js → styling-2103.js} RENAMED
File without changes
js/{styling-2102.min.js → styling-2103.min.js} RENAMED
File without changes
lang/siteorigin-panels.pot CHANGED
@@ -44,7 +44,7 @@ msgstr ""
44
  msgid "(email SiteOrigin support)"
45
  msgstr ""
46
 
47
- #: inc/admin-dashboard.php:95, inc/admin.php:159
48
  msgid "Support Forum"
49
  msgstr ""
50
 
@@ -109,7 +109,7 @@ msgstr ""
109
  msgid "WordPress Widgets"
110
  msgstr ""
111
 
112
- #: inc/admin-widget-dialog.php:185, inc/settings.php:339
113
  msgid "Recommended Widgets"
114
  msgstr ""
115
 
@@ -121,371 +121,371 @@ msgstr ""
121
  msgid "Installing %s"
122
  msgstr ""
123
 
124
- #: inc/admin.php:162, tpl/js-templates.php:44
125
  msgid "Addons"
126
  msgstr ""
127
 
128
- #: inc/admin.php:176, inc/admin.php:572, inc/admin.php:1170, inc/admin.php:1175, inc/settings.php:198, tpl/js-templates.php:197
129
  msgid "Page Builder"
130
  msgstr ""
131
 
132
- #: inc/admin.php:328
133
  msgid "All Widgets"
134
  msgstr ""
135
 
136
- #: inc/admin.php:355
137
  msgid "Missing Widget"
138
  msgstr ""
139
 
140
- #: inc/admin.php:356
141
  msgid "Page Builder doesn't know about this widget."
142
  msgstr ""
143
 
144
  #. translators: Number of seconds since
145
- #: inc/admin.php:360
146
  msgid "%d seconds"
147
  msgstr ""
148
 
149
  #. translators: Number of minutes since
150
- #: inc/admin.php:362
151
  msgid "%d minutes"
152
  msgstr ""
153
 
154
  #. translators: Number of hours since
155
- #: inc/admin.php:364
156
  msgid "%d hours"
157
  msgstr ""
158
 
159
  #. translators: A single second since
160
- #: inc/admin.php:367
161
  msgid "%d second"
162
  msgstr ""
163
 
164
  #. translators: A single minute since
165
- #: inc/admin.php:369
166
  msgid "%d minute"
167
  msgstr ""
168
 
169
  #. translators: A single hour since
170
- #: inc/admin.php:371
171
  msgid "%d hour"
172
  msgstr ""
173
 
174
  #. translators: Time ago - eg. "1 minute before".
175
- #: inc/admin.php:374
176
  msgid "%s before"
177
  msgstr ""
178
 
179
- #: inc/admin.php:375
180
  msgid "Now"
181
  msgstr ""
182
 
183
- #: inc/admin.php:379
184
  msgid "Current"
185
  msgstr ""
186
 
187
- #: inc/admin.php:380
188
  msgid "Original"
189
  msgstr ""
190
 
191
- #: inc/admin.php:381
192
  msgid "Version restored"
193
  msgstr ""
194
 
195
- #: inc/admin.php:382
196
  msgid "Converted to editor"
197
  msgstr ""
198
 
199
  #. translators: Message displayed in the history when a widget is deleted
200
- #: inc/admin.php:386
201
  msgid "Widget deleted"
202
  msgstr ""
203
 
204
  #. translators: Message displayed in the history when a widget is added
205
- #: inc/admin.php:388
206
  msgid "Widget added"
207
  msgstr ""
208
 
209
  #. translators: Message displayed in the history when a widget is edited
210
- #: inc/admin.php:390
211
  msgid "Widget edited"
212
  msgstr ""
213
 
214
  #. translators: Message displayed in the history when a widget is duplicated
215
- #: inc/admin.php:392
216
  msgid "Widget duplicated"
217
  msgstr ""
218
 
219
  #. translators: Message displayed in the history when a widget position is changed
220
- #: inc/admin.php:394
221
  msgid "Widget moved"
222
  msgstr ""
223
 
224
  #. translators: Message displayed in the history when a row is deleted
225
- #: inc/admin.php:398
226
  msgid "Row deleted"
227
  msgstr ""
228
 
229
  #. translators: Message displayed in the history when a row is added
230
- #: inc/admin.php:400
231
  msgid "Row added"
232
  msgstr ""
233
 
234
  #. translators: Message displayed in the history when a row is edited
235
- #: inc/admin.php:402
236
  msgid "Row edited"
237
  msgstr ""
238
 
239
  #. translators: Message displayed in the history when a row position is changed
240
- #: inc/admin.php:404
241
  msgid "Row moved"
242
  msgstr ""
243
 
244
  #. translators: Message displayed in the history when a row is duplicated
245
- #: inc/admin.php:406
246
  msgid "Row duplicated"
247
  msgstr ""
248
 
249
  #. translators: Message displayed in the history when a row is pasted
250
- #: inc/admin.php:408
251
  msgid "Row pasted"
252
  msgstr ""
253
 
254
- #: inc/admin.php:411
255
  msgid "Cell resized"
256
  msgstr ""
257
 
258
- #: inc/admin.php:414
259
  msgid "Prebuilt layout loaded"
260
  msgstr ""
261
 
262
- #: inc/admin.php:418
263
  msgid "Loading prebuilt layout"
264
  msgstr ""
265
 
266
- #: inc/admin.php:419
267
  msgid "Would you like to copy this editor's existing content to Page Builder?"
268
  msgstr ""
269
 
270
- #: inc/admin.php:420
271
  msgid "Would you like to clear your Page Builder content and revert to using the standard visual editor?"
272
  msgstr ""
273
 
274
  #. translators: This is the title for a widget called "Layout Builder"
275
- #: inc/admin.php:422
276
  msgid "Layout Builder Widget"
277
  msgstr ""
278
 
279
  #. translators: A standard confirmation message
280
- #: inc/admin.php:424, tpl/js-templates.php:97, tpl/js-templates.php:422
281
  msgid "Are you sure?"
282
  msgstr ""
283
 
284
  #. translators: When a layout file is ready to be inserted. %s is the filename.
285
- #: inc/admin.php:426
286
  msgid "%s is ready to insert."
287
  msgstr ""
288
 
289
- #: inc/admin.php:430
290
  msgid "Add Widget Below"
291
  msgstr ""
292
 
293
- #: inc/admin.php:431
294
  msgid "Add Widget to Cell"
295
  msgstr ""
296
 
297
- #: inc/admin.php:432, tpl/js-templates.php:224
298
  msgid "Search Widgets"
299
  msgstr ""
300
 
301
- #: inc/admin.php:434, tpl/js-templates.php:17, tpl/js-templates.php:19
302
  msgid "Add Row"
303
  msgstr ""
304
 
305
- #: inc/admin.php:435
306
  msgid "Column"
307
  msgstr ""
308
 
309
- #: inc/admin.php:437
310
  msgid "Cell Actions"
311
  msgstr ""
312
 
313
- #: inc/admin.php:438
314
  msgid "Paste Widget"
315
  msgstr ""
316
 
317
- #: inc/admin.php:440
318
  msgid "Widget Actions"
319
  msgstr ""
320
 
321
- #: inc/admin.php:441
322
  msgid "Edit Widget"
323
  msgstr ""
324
 
325
- #: inc/admin.php:442
326
  msgid "Duplicate Widget"
327
  msgstr ""
328
 
329
- #: inc/admin.php:443
330
  msgid "Delete Widget"
331
  msgstr ""
332
 
333
- #: inc/admin.php:444
334
  msgid "Copy Widget"
335
  msgstr ""
336
 
337
- #: inc/admin.php:445
338
  msgid "Paste Widget Below"
339
  msgstr ""
340
 
341
- #: inc/admin.php:447
342
  msgid "Row Actions"
343
  msgstr ""
344
 
345
- #: inc/admin.php:448, tpl/js-templates.php:95
346
  msgid "Edit Row"
347
  msgstr ""
348
 
349
- #: inc/admin.php:449, tpl/js-templates.php:96
350
  msgid "Duplicate Row"
351
  msgstr ""
352
 
353
- #: inc/admin.php:450, tpl/js-templates.php:97
354
  msgid "Delete Row"
355
  msgstr ""
356
 
357
- #: inc/admin.php:451
358
  msgid "Copy Row"
359
  msgstr ""
360
 
361
- #: inc/admin.php:452
362
  msgid "Paste Row"
363
  msgstr ""
364
 
365
- #: inc/admin.php:454
366
  msgid "Draft"
367
  msgstr ""
368
 
369
- #: inc/admin.php:455
370
  msgid "Untitled"
371
  msgstr ""
372
 
373
- #: inc/admin.php:457
374
  msgid "New Row"
375
  msgstr ""
376
 
377
- #: inc/admin.php:458, inc/admin.php:466, inc/styles.php:184, tpl/js-templates.php:62
378
  msgid "Row"
379
  msgstr ""
380
 
381
- #: inc/admin.php:461
382
  msgid "Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements."
383
  msgstr ""
384
 
385
- #: inc/admin.php:462
386
  msgid "Add a {{%= items[0] %}} to get started."
387
  msgstr ""
388
 
389
- #: inc/admin.php:463
390
  msgid "Add a {{%= items[0] %}} or {{%= items[1] %}} to get started."
391
  msgstr ""
392
 
393
- #: inc/admin.php:464
394
  msgid "Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started."
395
  msgstr ""
396
 
397
- #: inc/admin.php:465, inc/styles.php:318, tpl/js-templates.php:61
398
  msgid "Widget"
399
  msgstr ""
400
 
401
- #: inc/admin.php:467, tpl/js-templates.php:63
402
  msgid "Prebuilt Layout"
403
  msgstr ""
404
 
405
- #: inc/admin.php:469
406
  msgid "Read our %s if you need help."
407
  msgstr ""
408
 
409
- #: inc/admin.php:470, tpl/js-templates.php:64
410
  msgid "documentation"
411
  msgstr ""
412
 
413
- #: inc/admin.php:479
414
  msgid "Page Builder layouts"
415
  msgstr ""
416
 
417
- #: inc/admin.php:480
418
  msgid "Error uploading or importing file."
419
  msgstr ""
420
 
421
- #: inc/admin.php:487
422
  msgid "Unknown error. Failed to load the form. Please check your internet connection, contact your web site administrator, or try again later."
423
  msgstr ""
424
 
425
  #. translators: This is the default name given to a user's home page
426
- #: inc/admin.php:655, inc/home.php:26
427
  msgid "Home Page"
428
  msgstr ""
429
 
430
- #: inc/admin.php:756
431
  msgid "Untitled Widget"
432
  msgstr ""
433
 
434
- #: inc/admin.php:936
435
  msgid "You need to install 1{%1$s} to use the widget 2{%2$s}."
436
  msgstr ""
437
 
438
- #: inc/admin.php:942
439
  msgid "Save and reload this page to start using the widget after you've installed it."
440
  msgstr ""
441
 
442
- #: inc/admin.php:958
443
  msgid "The widget 1{%1$s} is not available. Please try locate and install the missing plugin. Post on the 2{support forums} if you need help."
444
  msgstr ""
445
 
446
- #: inc/admin.php:1073, inc/styles-admin.php:23
447
  msgid "The supplied nonce is invalid."
448
  msgstr ""
449
 
450
- #: inc/admin.php:1074, inc/styles-admin.php:24
451
  msgid "Invalid nonce."
452
  msgstr ""
453
 
454
- #: inc/admin.php:1080
455
  msgid "Please specify the type of widget form to be rendered."
456
  msgstr ""
457
 
458
- #: inc/admin.php:1081
459
  msgid "Missing widget type."
460
  msgstr ""
461
 
462
- #: inc/admin.php:1188
463
  msgid "%s Widget"
464
  msgid_plural "%s Widgets"
465
  msgstr[0] ""
466
  msgstr[1] ""
467
 
468
- #: inc/admin.php:1231
469
  msgid "Get a lightbox addon for SiteOrigin widgets"
470
  msgstr ""
471
 
472
- #: inc/admin.php:1235
473
  msgid "Get the row, cell and widget animations addon"
474
  msgstr ""
475
 
476
- #: inc/admin.php:1239
477
  msgid "Get premium email support for SiteOrigin Page Builder"
478
  msgstr ""
479
 
480
- #: inc/admin.php:1430
481
  msgid "Toggle editor selection menu"
482
  msgstr ""
483
 
484
- #: inc/admin.php:1431, inc/admin.php:1478, inc/settings.php:198, settings/tpl/settings.php:9
485
  msgid "SiteOrigin Page Builder"
486
  msgstr ""
487
 
488
- #: inc/admin.php:1432
489
  msgid "Block Editor"
490
  msgstr ""
491
 
@@ -545,243 +545,251 @@ msgstr ""
545
  msgid "Page Builder Content"
546
  msgstr ""
547
 
548
- #: inc/settings.php:225
549
  msgid "Page Builder Settings"
550
  msgstr ""
551
 
552
- #: inc/settings.php:241
553
  msgid "General"
554
  msgstr ""
555
 
556
- #: inc/settings.php:247
557
  msgid "Post Types"
558
  msgstr ""
559
 
560
- #: inc/settings.php:249
561
  msgid "The post types on which to use Page Builder."
562
  msgstr ""
563
 
564
- #: inc/settings.php:254
565
  msgid "Use Classic Editor for new posts"
566
  msgstr ""
567
 
568
- #: inc/settings.php:255
569
  msgid "New posts of the above Post Types will be created using the Classic Editor."
570
  msgstr ""
571
 
572
- #: inc/settings.php:260
573
  msgid "Live Editor Quick Link"
574
  msgstr ""
575
 
576
- #: inc/settings.php:261
577
  msgid "Display a Live Editor button in the admin bar."
578
  msgstr ""
579
 
580
- #: inc/settings.php:266
 
 
 
 
 
 
 
 
581
  msgid "Display Widget Count"
582
  msgstr ""
583
 
584
- #: inc/settings.php:267
585
  msgid "Display a widget count in the admin lists of posts/pages where you're using Page Builder."
586
  msgstr ""
587
 
588
- #: inc/settings.php:272
589
  msgid "Limit Parallax Motion"
590
  msgstr ""
591
 
592
- #: inc/settings.php:273
593
  msgid "How many pixels of scrolling result in a single pixel of parallax motion. 0 means automatic. Lower values give more noticeable effect."
594
  msgstr ""
595
 
596
- #: inc/settings.php:278
597
  msgid "Sidebars Emulator"
598
  msgstr ""
599
 
600
- #: inc/settings.php:279
601
  msgid "Page Builder will create an emulated sidebar, that contains all widgets in the page."
602
  msgstr ""
603
 
604
- #: inc/settings.php:284
605
  msgid "Upgrade Teaser"
606
  msgstr ""
607
 
608
- #: inc/settings.php:286
609
  msgid "Display the %sSiteOrigin Premium%s upgrade teaser in the Page Builder toolbar."
610
  msgstr ""
611
 
612
- #: inc/settings.php:294
613
  msgid "Default To Page Builder Interface"
614
  msgstr ""
615
 
616
- #: inc/settings.php:296
617
  msgid "New Classic Editor posts/pages that you create will start with the Page Builder loaded. The %s\"Use Classic Editor for new posts\"%s setting must be enabled."
618
  msgstr ""
619
 
620
- #: inc/settings.php:303
621
  msgid "Layout Block Default Mode"
622
  msgstr ""
623
 
624
- #: inc/settings.php:306, tpl/js-templates.php:141
625
  msgid "Edit"
626
  msgstr ""
627
 
628
- #: inc/settings.php:307
629
  msgid "Preview"
630
  msgstr ""
631
 
632
- #: inc/settings.php:309
633
  msgid "Whether to display layout blocks in edit mode or preview mode in the block editor."
634
  msgstr ""
635
 
636
- #: inc/settings.php:315
637
  msgid "Widgets"
638
  msgstr ""
639
 
640
- #: inc/settings.php:321
641
  msgid "Widget Title HTML"
642
  msgstr ""
643
 
644
- #: inc/settings.php:322
645
  msgid "The HTML used for widget titles. {{title}} is replaced with the widget title."
646
  msgstr ""
647
 
648
- #: inc/settings.php:327
649
  msgid "Add Widget Class"
650
  msgstr ""
651
 
652
- #: inc/settings.php:328
653
  msgid "Add the widget class to Page Builder widgets. Disable this if you're experiencing conflicts."
654
  msgstr ""
655
 
656
- #: inc/settings.php:333
657
  msgid "Legacy Bundled Widgets"
658
  msgstr ""
659
 
660
- #: inc/settings.php:334
661
  msgid "Load legacy widgets from Page Builder 1."
662
  msgstr ""
663
 
664
- #: inc/settings.php:340
665
  msgid "Display recommend widgets in Page Builder add widget dialog."
666
  msgstr ""
667
 
668
- #: inc/settings.php:345
669
  msgid "Instant Open Widgets"
670
  msgstr ""
671
 
672
- #: inc/settings.php:346
673
  msgid "Open a widget form as soon as its added to a page."
674
  msgstr ""
675
 
676
- #: inc/settings.php:352, inc/styles-admin.php:88
677
  msgid "Layout"
678
  msgstr ""
679
 
680
- #: inc/settings.php:360
681
  msgid "Responsive Layout"
682
  msgstr ""
683
 
684
- #: inc/settings.php:361
685
  msgid "Collapse widgets, rows and columns on mobile devices."
686
  msgstr ""
687
 
688
- #: inc/settings.php:366
689
  msgid "Use Tablet Layout"
690
  msgstr ""
691
 
692
- #: inc/settings.php:367
693
  msgid "Collapses columns differently on tablet devices."
694
  msgstr ""
695
 
696
- #: inc/settings.php:373
697
  msgid "Detect older browsers"
698
  msgstr ""
699
 
700
- #: inc/settings.php:374
701
  msgid "Never"
702
  msgstr ""
703
 
704
- #: inc/settings.php:375
705
  msgid "Always"
706
  msgstr ""
707
 
708
- #: inc/settings.php:377
709
  msgid "Use Legacy Layout Engine"
710
  msgstr ""
711
 
712
- #: inc/settings.php:378
713
  msgid "The CSS and HTML uses floats instead of flexbox for compatibility with very old browsers."
714
  msgstr ""
715
 
716
- #: inc/settings.php:384
717
  msgid "Tablet Width"
718
  msgstr ""
719
 
720
- #: inc/settings.php:385
721
  msgid "Device width, in pixels, to collapse into a tablet view ."
722
  msgstr ""
723
 
724
- #: inc/settings.php:391
725
  msgid "Mobile Width"
726
  msgstr ""
727
 
728
- #: inc/settings.php:392
729
  msgid "Device width, in pixels, to collapse into a mobile view ."
730
  msgstr ""
731
 
732
- #: inc/settings.php:398
733
  msgid "Row/Widget Bottom Margin"
734
  msgstr ""
735
 
736
- #: inc/settings.php:399
737
  msgid "Default margin below rows and widgets."
738
  msgstr ""
739
 
740
- #: inc/settings.php:404
741
  msgid "Last Row With Margin"
742
  msgstr ""
743
 
744
- #: inc/settings.php:405
745
  msgid "Allow margin in last row."
746
  msgstr ""
747
 
748
- #: inc/settings.php:411
749
  msgid "Row Gutter"
750
  msgstr ""
751
 
752
- #: inc/settings.php:412
753
  msgid "Default spacing between columns in each row."
754
  msgstr ""
755
 
756
- #: inc/settings.php:418
757
  msgid "Full Width Container"
758
  msgstr ""
759
 
760
- #: inc/settings.php:419
761
  msgid "The container used for the full width layout."
762
  msgstr ""
763
 
764
- #: inc/settings.php:426
765
  msgid "Content"
766
  msgstr ""
767
 
768
- #: inc/settings.php:432
769
  msgid "Copy Content"
770
  msgstr ""
771
 
772
- #: inc/settings.php:433
773
  msgid "Copy content from Page Builder to post content."
774
  msgstr ""
775
 
776
- #: inc/settings.php:438
777
  msgid "Copy Styles"
778
  msgstr ""
779
 
780
- #: inc/settings.php:439
781
  msgid "Include styles into your Post Content. This keeps page layouts, even when Page Builder is deactivated."
782
  msgstr ""
783
 
784
- #: inc/settings.php:486, inc/styles-admin.php:269
785
  msgid "Enabled"
786
  msgstr ""
787
 
@@ -1082,11 +1090,11 @@ msgstr ""
1082
  msgid "A complete SiteOrigin Page Builder layout as a widget."
1083
  msgstr ""
1084
 
1085
- #: inc/widgets/layout.php:79
1086
  msgid "This widget can currently only be used in the WordPress admin interface."
1087
  msgstr ""
1088
 
1089
- #: inc/widgets/layout.php:104
1090
  msgid "Open Builder"
1091
  msgstr ""
1092
 
44
  msgid "(email SiteOrigin support)"
45
  msgstr ""
46
 
47
+ #: inc/admin-dashboard.php:95, inc/admin.php:161
48
  msgid "Support Forum"
49
  msgstr ""
50
 
109
  msgid "WordPress Widgets"
110
  msgstr ""
111
 
112
+ #: inc/admin-widget-dialog.php:185, inc/settings.php:350
113
  msgid "Recommended Widgets"
114
  msgstr ""
115
 
121
  msgid "Installing %s"
122
  msgstr ""
123
 
124
+ #: inc/admin.php:164, tpl/js-templates.php:44
125
  msgid "Addons"
126
  msgstr ""
127
 
128
+ #: inc/admin.php:178, inc/admin.php:574, inc/admin.php:1172, inc/admin.php:1177, inc/settings.php:199, tpl/js-templates.php:197
129
  msgid "Page Builder"
130
  msgstr ""
131
 
132
+ #: inc/admin.php:330
133
  msgid "All Widgets"
134
  msgstr ""
135
 
136
+ #: inc/admin.php:357
137
  msgid "Missing Widget"
138
  msgstr ""
139
 
140
+ #: inc/admin.php:358
141
  msgid "Page Builder doesn't know about this widget."
142
  msgstr ""
143
 
144
  #. translators: Number of seconds since
145
+ #: inc/admin.php:362
146
  msgid "%d seconds"
147
  msgstr ""
148
 
149
  #. translators: Number of minutes since
150
+ #: inc/admin.php:364
151
  msgid "%d minutes"
152
  msgstr ""
153
 
154
  #. translators: Number of hours since
155
+ #: inc/admin.php:366
156
  msgid "%d hours"
157
  msgstr ""
158
 
159
  #. translators: A single second since
160
+ #: inc/admin.php:369
161
  msgid "%d second"
162
  msgstr ""
163
 
164
  #. translators: A single minute since
165
+ #: inc/admin.php:371
166
  msgid "%d minute"
167
  msgstr ""
168
 
169
  #. translators: A single hour since
170
+ #: inc/admin.php:373
171
  msgid "%d hour"
172
  msgstr ""
173
 
174
  #. translators: Time ago - eg. "1 minute before".
175
+ #: inc/admin.php:376
176
  msgid "%s before"
177
  msgstr ""
178
 
179
+ #: inc/admin.php:377
180
  msgid "Now"
181
  msgstr ""
182
 
183
+ #: inc/admin.php:381
184
  msgid "Current"
185
  msgstr ""
186
 
187
+ #: inc/admin.php:382
188
  msgid "Original"
189
  msgstr ""
190
 
191
+ #: inc/admin.php:383
192
  msgid "Version restored"
193
  msgstr ""
194
 
195
+ #: inc/admin.php:384
196
  msgid "Converted to editor"
197
  msgstr ""
198
 
199
  #. translators: Message displayed in the history when a widget is deleted
200
+ #: inc/admin.php:388
201
  msgid "Widget deleted"
202
  msgstr ""
203
 
204
  #. translators: Message displayed in the history when a widget is added
205
+ #: inc/admin.php:390
206
  msgid "Widget added"
207
  msgstr ""
208
 
209
  #. translators: Message displayed in the history when a widget is edited
210
+ #: inc/admin.php:392
211
  msgid "Widget edited"
212
  msgstr ""
213
 
214
  #. translators: Message displayed in the history when a widget is duplicated
215
+ #: inc/admin.php:394
216
  msgid "Widget duplicated"
217
  msgstr ""
218
 
219
  #. translators: Message displayed in the history when a widget position is changed
220
+ #: inc/admin.php:396
221
  msgid "Widget moved"
222
  msgstr ""
223
 
224
  #. translators: Message displayed in the history when a row is deleted
225
+ #: inc/admin.php:400
226
  msgid "Row deleted"
227
  msgstr ""
228
 
229
  #. translators: Message displayed in the history when a row is added
230
+ #: inc/admin.php:402
231
  msgid "Row added"
232
  msgstr ""
233
 
234
  #. translators: Message displayed in the history when a row is edited
235
+ #: inc/admin.php:404
236
  msgid "Row edited"
237
  msgstr ""
238
 
239
  #. translators: Message displayed in the history when a row position is changed
240
+ #: inc/admin.php:406
241
  msgid "Row moved"
242
  msgstr ""
243
 
244
  #. translators: Message displayed in the history when a row is duplicated
245
+ #: inc/admin.php:408
246
  msgid "Row duplicated"
247
  msgstr ""
248
 
249
  #. translators: Message displayed in the history when a row is pasted
250
+ #: inc/admin.php:410
251
  msgid "Row pasted"
252
  msgstr ""
253
 
254
+ #: inc/admin.php:413
255
  msgid "Cell resized"
256
  msgstr ""
257
 
258
+ #: inc/admin.php:416
259
  msgid "Prebuilt layout loaded"
260
  msgstr ""
261
 
262
+ #: inc/admin.php:420
263
  msgid "Loading prebuilt layout"
264
  msgstr ""
265
 
266
+ #: inc/admin.php:421
267
  msgid "Would you like to copy this editor's existing content to Page Builder?"
268
  msgstr ""
269
 
270
+ #: inc/admin.php:422
271
  msgid "Would you like to clear your Page Builder content and revert to using the standard visual editor?"
272
  msgstr ""
273
 
274
  #. translators: This is the title for a widget called "Layout Builder"
275
+ #: inc/admin.php:424
276
  msgid "Layout Builder Widget"
277
  msgstr ""
278
 
279
  #. translators: A standard confirmation message
280
+ #: inc/admin.php:426, tpl/js-templates.php:97, tpl/js-templates.php:422
281
  msgid "Are you sure?"
282
  msgstr ""
283
 
284
  #. translators: When a layout file is ready to be inserted. %s is the filename.
285
+ #: inc/admin.php:428
286
  msgid "%s is ready to insert."
287
  msgstr ""
288
 
289
+ #: inc/admin.php:432
290
  msgid "Add Widget Below"
291
  msgstr ""
292
 
293
+ #: inc/admin.php:433
294
  msgid "Add Widget to Cell"
295
  msgstr ""
296
 
297
+ #: inc/admin.php:434, tpl/js-templates.php:224
298
  msgid "Search Widgets"
299
  msgstr ""
300
 
301
+ #: inc/admin.php:436, tpl/js-templates.php:17, tpl/js-templates.php:19
302
  msgid "Add Row"
303
  msgstr ""
304
 
305
+ #: inc/admin.php:437
306
  msgid "Column"
307
  msgstr ""
308
 
309
+ #: inc/admin.php:439
310
  msgid "Cell Actions"
311
  msgstr ""
312
 
313
+ #: inc/admin.php:440
314
  msgid "Paste Widget"
315
  msgstr ""
316
 
317
+ #: inc/admin.php:442
318
  msgid "Widget Actions"
319
  msgstr ""
320
 
321
+ #: inc/admin.php:443
322
  msgid "Edit Widget"
323
  msgstr ""
324
 
325
+ #: inc/admin.php:444
326
  msgid "Duplicate Widget"
327
  msgstr ""
328
 
329
+ #: inc/admin.php:445
330
  msgid "Delete Widget"
331
  msgstr ""
332
 
333
+ #: inc/admin.php:446
334
  msgid "Copy Widget"
335
  msgstr ""
336
 
337
+ #: inc/admin.php:447
338
  msgid "Paste Widget Below"
339
  msgstr ""
340
 
341
+ #: inc/admin.php:449
342
  msgid "Row Actions"
343
  msgstr ""
344
 
345
+ #: inc/admin.php:450, tpl/js-templates.php:95
346
  msgid "Edit Row"
347
  msgstr ""
348
 
349
+ #: inc/admin.php:451, tpl/js-templates.php:96
350
  msgid "Duplicate Row"
351
  msgstr ""
352
 
353
+ #: inc/admin.php:452, tpl/js-templates.php:97
354
  msgid "Delete Row"
355
  msgstr ""
356
 
357
+ #: inc/admin.php:453
358
  msgid "Copy Row"
359
  msgstr ""
360
 
361
+ #: inc/admin.php:454
362
  msgid "Paste Row"
363
  msgstr ""
364
 
365
+ #: inc/admin.php:456
366
  msgid "Draft"
367
  msgstr ""
368
 
369
+ #: inc/admin.php:457
370
  msgid "Untitled"
371
  msgstr ""
372
 
373
+ #: inc/admin.php:459
374
  msgid "New Row"
375
  msgstr ""
376
 
377
+ #: inc/admin.php:460, inc/admin.php:468, inc/styles.php:184, tpl/js-templates.php:62
378
  msgid "Row"
379
  msgstr ""
380
 
381
+ #: inc/admin.php:463
382
  msgid "Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements."
383
  msgstr ""
384
 
385
+ #: inc/admin.php:464
386
  msgid "Add a {{%= items[0] %}} to get started."
387
  msgstr ""
388
 
389
+ #: inc/admin.php:465
390
  msgid "Add a {{%= items[0] %}} or {{%= items[1] %}} to get started."
391
  msgstr ""
392
 
393
+ #: inc/admin.php:466
394
  msgid "Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started."
395
  msgstr ""
396
 
397
+ #: inc/admin.php:467, inc/styles.php:318, tpl/js-templates.php:61
398
  msgid "Widget"
399
  msgstr ""
400
 
401
+ #: inc/admin.php:469, tpl/js-templates.php:63
402
  msgid "Prebuilt Layout"
403
  msgstr ""
404
 
405
+ #: inc/admin.php:471
406
  msgid "Read our %s if you need help."
407
  msgstr ""
408
 
409
+ #: inc/admin.php:472, tpl/js-templates.php:64
410
  msgid "documentation"
411
  msgstr ""
412
 
413
+ #: inc/admin.php:481
414
  msgid "Page Builder layouts"
415
  msgstr ""
416
 
417
+ #: inc/admin.php:482
418
  msgid "Error uploading or importing file."
419
  msgstr ""
420
 
421
+ #: inc/admin.php:489
422
  msgid "Unknown error. Failed to load the form. Please check your internet connection, contact your web site administrator, or try again later."
423
  msgstr ""
424
 
425
  #. translators: This is the default name given to a user's home page
426
+ #: inc/admin.php:657, inc/home.php:26
427
  msgid "Home Page"
428
  msgstr ""
429
 
430
+ #: inc/admin.php:758
431
  msgid "Untitled Widget"
432
  msgstr ""
433
 
434
+ #: inc/admin.php:938
435
  msgid "You need to install 1{%1$s} to use the widget 2{%2$s}."
436
  msgstr ""
437
 
438
+ #: inc/admin.php:944
439
  msgid "Save and reload this page to start using the widget after you've installed it."
440
  msgstr ""
441
 
442
+ #: inc/admin.php:960
443
  msgid "The widget 1{%1$s} is not available. Please try locate and install the missing plugin. Post on the 2{support forums} if you need help."
444
  msgstr ""
445
 
446
+ #: inc/admin.php:1075, inc/styles-admin.php:23
447
  msgid "The supplied nonce is invalid."
448
  msgstr ""
449
 
450
+ #: inc/admin.php:1076, inc/styles-admin.php:24
451
  msgid "Invalid nonce."
452
  msgstr ""
453
 
454
+ #: inc/admin.php:1082
455
  msgid "Please specify the type of widget form to be rendered."
456
  msgstr ""
457
 
458
+ #: inc/admin.php:1083
459
  msgid "Missing widget type."
460
  msgstr ""
461
 
462
+ #: inc/admin.php:1190
463
  msgid "%s Widget"
464
  msgid_plural "%s Widgets"
465
  msgstr[0] ""
466
  msgstr[1] ""
467
 
468
+ #: inc/admin.php:1233
469
  msgid "Get a lightbox addon for SiteOrigin widgets"
470
  msgstr ""
471
 
472
+ #: inc/admin.php:1237
473
  msgid "Get the row, cell and widget animations addon"
474
  msgstr ""
475
 
476
+ #: inc/admin.php:1241
477
  msgid "Get premium email support for SiteOrigin Page Builder"
478
  msgstr ""
479
 
480
+ #: inc/admin.php:1432
481
  msgid "Toggle editor selection menu"
482
  msgstr ""
483
 
484
+ #: inc/admin.php:1433, inc/admin.php:1480, inc/settings.php:199, settings/tpl/settings.php:9
485
  msgid "SiteOrigin Page Builder"
486
  msgstr ""
487
 
488
+ #: inc/admin.php:1434
489
  msgid "Block Editor"
490
  msgstr ""
491
 
545
  msgid "Page Builder Content"
546
  msgstr ""
547
 
548
+ #: inc/settings.php:226
549
  msgid "Page Builder Settings"
550
  msgstr ""
551
 
552
+ #: inc/settings.php:242
553
  msgid "General"
554
  msgstr ""
555
 
556
+ #: inc/settings.php:248
557
  msgid "Post Types"
558
  msgstr ""
559
 
560
+ #: inc/settings.php:250
561
  msgid "The post types on which to use Page Builder."
562
  msgstr ""
563
 
564
+ #: inc/settings.php:255
565
  msgid "Use Classic Editor for new posts"
566
  msgstr ""
567
 
568
+ #: inc/settings.php:256
569
  msgid "New posts of the above Post Types will be created using the Classic Editor."
570
  msgstr ""
571
 
572
+ #: inc/settings.php:261
573
  msgid "Live Editor Quick Link"
574
  msgstr ""
575
 
576
+ #: inc/settings.php:262
577
  msgid "Display a Live Editor button in the admin bar."
578
  msgstr ""
579
 
580
+ #: inc/settings.php:267
581
+ msgid "Display Post State"
582
+ msgstr ""
583
+
584
+ #: inc/settings.php:269
585
+ msgid "Display a %sSiteOrigin Page Builder%s post state in the admin lists of posts/pages to indicate Page Builder is active."
586
+ msgstr ""
587
+
588
+ #: inc/settings.php:277
589
  msgid "Display Widget Count"
590
  msgstr ""
591
 
592
+ #: inc/settings.php:278
593
  msgid "Display a widget count in the admin lists of posts/pages where you're using Page Builder."
594
  msgstr ""
595
 
596
+ #: inc/settings.php:283
597
  msgid "Limit Parallax Motion"
598
  msgstr ""
599
 
600
+ #: inc/settings.php:284
601
  msgid "How many pixels of scrolling result in a single pixel of parallax motion. 0 means automatic. Lower values give more noticeable effect."
602
  msgstr ""
603
 
604
+ #: inc/settings.php:289
605
  msgid "Sidebars Emulator"
606
  msgstr ""
607
 
608
+ #: inc/settings.php:290
609
  msgid "Page Builder will create an emulated sidebar, that contains all widgets in the page."
610
  msgstr ""
611
 
612
+ #: inc/settings.php:295
613
  msgid "Upgrade Teaser"
614
  msgstr ""
615
 
616
+ #: inc/settings.php:297
617
  msgid "Display the %sSiteOrigin Premium%s upgrade teaser in the Page Builder toolbar."
618
  msgstr ""
619
 
620
+ #: inc/settings.php:305
621
  msgid "Default To Page Builder Interface"
622
  msgstr ""
623
 
624
+ #: inc/settings.php:307
625
  msgid "New Classic Editor posts/pages that you create will start with the Page Builder loaded. The %s\"Use Classic Editor for new posts\"%s setting must be enabled."
626
  msgstr ""
627
 
628
+ #: inc/settings.php:314
629
  msgid "Layout Block Default Mode"
630
  msgstr ""
631
 
632
+ #: inc/settings.php:317, tpl/js-templates.php:141
633
  msgid "Edit"
634
  msgstr ""
635
 
636
+ #: inc/settings.php:318
637
  msgid "Preview"
638
  msgstr ""
639
 
640
+ #: inc/settings.php:320
641
  msgid "Whether to display layout blocks in edit mode or preview mode in the block editor."
642
  msgstr ""
643
 
644
+ #: inc/settings.php:326
645
  msgid "Widgets"
646
  msgstr ""
647
 
648
+ #: inc/settings.php:332
649
  msgid "Widget Title HTML"
650
  msgstr ""
651
 
652
+ #: inc/settings.php:333
653
  msgid "The HTML used for widget titles. {{title}} is replaced with the widget title."
654
  msgstr ""
655
 
656
+ #: inc/settings.php:338
657
  msgid "Add Widget Class"
658
  msgstr ""
659
 
660
+ #: inc/settings.php:339
661
  msgid "Add the widget class to Page Builder widgets. Disable this if you're experiencing conflicts."
662
  msgstr ""
663
 
664
+ #: inc/settings.php:344
665
  msgid "Legacy Bundled Widgets"
666
  msgstr ""
667
 
668
+ #: inc/settings.php:345
669
  msgid "Load legacy widgets from Page Builder 1."
670
  msgstr ""
671
 
672
+ #: inc/settings.php:351
673
  msgid "Display recommend widgets in Page Builder add widget dialog."
674
  msgstr ""
675
 
676
+ #: inc/settings.php:356
677
  msgid "Instant Open Widgets"
678
  msgstr ""
679
 
680
+ #: inc/settings.php:357
681
  msgid "Open a widget form as soon as its added to a page."
682
  msgstr ""
683
 
684
+ #: inc/settings.php:363, inc/styles-admin.php:88
685
  msgid "Layout"
686
  msgstr ""
687
 
688
+ #: inc/settings.php:371
689
  msgid "Responsive Layout"
690
  msgstr ""
691
 
692
+ #: inc/settings.php:372
693
  msgid "Collapse widgets, rows and columns on mobile devices."
694
  msgstr ""
695
 
696
+ #: inc/settings.php:377
697
  msgid "Use Tablet Layout"
698
  msgstr ""
699
 
700
+ #: inc/settings.php:378
701
  msgid "Collapses columns differently on tablet devices."
702
  msgstr ""
703
 
704
+ #: inc/settings.php:384
705
  msgid "Detect older browsers"
706
  msgstr ""
707
 
708
+ #: inc/settings.php:385
709
  msgid "Never"
710
  msgstr ""
711
 
712
+ #: inc/settings.php:386
713
  msgid "Always"
714
  msgstr ""
715
 
716
+ #: inc/settings.php:388
717
  msgid "Use Legacy Layout Engine"
718
  msgstr ""
719
 
720
+ #: inc/settings.php:389
721
  msgid "The CSS and HTML uses floats instead of flexbox for compatibility with very old browsers."
722
  msgstr ""
723
 
724
+ #: inc/settings.php:395
725
  msgid "Tablet Width"
726
  msgstr ""
727
 
728
+ #: inc/settings.php:396
729
  msgid "Device width, in pixels, to collapse into a tablet view ."
730
  msgstr ""
731
 
732
+ #: inc/settings.php:402
733
  msgid "Mobile Width"
734
  msgstr ""
735
 
736
+ #: inc/settings.php:403
737
  msgid "Device width, in pixels, to collapse into a mobile view ."
738
  msgstr ""
739
 
740
+ #: inc/settings.php:409
741
  msgid "Row/Widget Bottom Margin"
742
  msgstr ""
743
 
744
+ #: inc/settings.php:410
745
  msgid "Default margin below rows and widgets."
746
  msgstr ""
747
 
748
+ #: inc/settings.php:415
749
  msgid "Last Row With Margin"
750
  msgstr ""
751
 
752
+ #: inc/settings.php:416
753
  msgid "Allow margin in last row."
754
  msgstr ""
755
 
756
+ #: inc/settings.php:422
757
  msgid "Row Gutter"
758
  msgstr ""
759
 
760
+ #: inc/settings.php:423
761
  msgid "Default spacing between columns in each row."
762
  msgstr ""
763
 
764
+ #: inc/settings.php:429
765
  msgid "Full Width Container"
766
  msgstr ""
767
 
768
+ #: inc/settings.php:430
769
  msgid "The container used for the full width layout."
770
  msgstr ""
771
 
772
+ #: inc/settings.php:437
773
  msgid "Content"
774
  msgstr ""
775
 
776
+ #: inc/settings.php:443
777
  msgid "Copy Content"
778
  msgstr ""
779
 
780
+ #: inc/settings.php:444
781
  msgid "Copy content from Page Builder to post content."
782
  msgstr ""
783
 
784
+ #: inc/settings.php:449
785
  msgid "Copy Styles"
786
  msgstr ""
787
 
788
+ #: inc/settings.php:450
789
  msgid "Include styles into your Post Content. This keeps page layouts, even when Page Builder is deactivated."
790
  msgstr ""
791
 
792
+ #: inc/settings.php:497, inc/styles-admin.php:269
793
  msgid "Enabled"
794
  msgstr ""
795
 
1090
  msgid "A complete SiteOrigin Page Builder layout as a widget."
1091
  msgstr ""
1092
 
1093
+ #: inc/widgets/layout.php:83
1094
  msgid "This widget can currently only be used in the WordPress admin interface."
1095
  msgstr ""
1096
 
1097
+ #: inc/widgets/layout.php:108
1098
  msgid "Open Builder"
1099
  msgstr ""
1100
 
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Tags: page builder, responsive, widget, widgets, builder, page, admin, gallery, content, cms, pages, post, css, layout, grid
3
  Requires at least: 4.4
4
  Tested up to: 5.1
5
- Stable tag: 2.10.2
6
- Build time: 2019-02-28T11:29:02-08:00
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
  Donate link: https://siteorigin.com/downloads/premium/
@@ -96,6 +96,13 @@ We've tried to ensure that Page Builder is compatible with most plugin widgets.
96
 
97
  == Changelog ==
98
 
 
 
 
 
 
 
 
99
  = 2.10.2 - 28 February 2019 =
100
  * Don't remove left/right border when Full Width Stretch Padding is enabled on row.
101
  * Display widget count for inline-save.
2
  Tags: page builder, responsive, widget, widgets, builder, page, admin, gallery, content, cms, pages, post, css, layout, grid
3
  Requires at least: 4.4
4
  Tested up to: 5.1
5
+ Stable tag: 2.10.3
6
+ Build time: 2019-04-02T10:40:39-07:00
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
  Donate link: https://siteorigin.com/downloads/premium/
96
 
97
  == Changelog ==
98
 
99
+ = 2.10.3 - 2 April 2019 =
100
+ * Layout builder widget: Call styles sanitization in update.
101
+ * Live editor: Only call `process_raw_widgets` once for preview data.
102
+ * Add a setting for whether to display SiteOrigin Page Builder post state.
103
+ * Sidebars emulator: Cache the result of url_to_postid().
104
+ * Prevent affecting child layouts with parent layouts' CSS.
105
+
106
  = 2.10.2 - 28 February 2019 =
107
  * Don't remove left/right border when Full Width Stretch Padding is enabled on row.
108
  * Display widget count for inline-save.
siteorigin-panels.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Page Builder by SiteOrigin
4
  Plugin URI: https://siteorigin.com/page-builder/
5
  Description: A drag and drop, responsive page builder that simplifies building your website.
6
- Version: 2.10.2
7
  Author: SiteOrigin
8
  Author URI: https://siteorigin.com
9
  License: GPL3
@@ -11,12 +11,12 @@ License URI: http://www.gnu.org/licenses/gpl.html
11
  Donate link: http://siteorigin.com/page-builder/#donate
12
  */
13
 
14
- define( 'SITEORIGIN_PANELS_VERSION', '2.10.2' );
15
  if ( ! defined( 'SITEORIGIN_PANELS_JS_SUFFIX' ) ) {
16
  define( 'SITEORIGIN_PANELS_JS_SUFFIX', '.min' );
17
  }
18
  define( 'SITEORIGIN_PANELS_CSS_SUFFIX', '.min' );
19
- define( 'SITEORIGIN_PANELS_VERSION_SUFFIX', '-2102' );
20
 
21
  require_once plugin_dir_path( __FILE__ ) . 'inc/functions.php';
22
 
3
  Plugin Name: Page Builder by SiteOrigin
4
  Plugin URI: https://siteorigin.com/page-builder/
5
  Description: A drag and drop, responsive page builder that simplifies building your website.
6
+ Version: 2.10.3
7
  Author: SiteOrigin
8
  Author URI: https://siteorigin.com
9
  License: GPL3
11
  Donate link: http://siteorigin.com/page-builder/#donate
12
  */
13
 
14
+ define( 'SITEORIGIN_PANELS_VERSION', '2.10.3' );
15
  if ( ! defined( 'SITEORIGIN_PANELS_JS_SUFFIX' ) ) {
16
  define( 'SITEORIGIN_PANELS_JS_SUFFIX', '.min' );
17
  }
18
  define( 'SITEORIGIN_PANELS_CSS_SUFFIX', '.min' );
19
+ define( 'SITEORIGIN_PANELS_VERSION_SUFFIX', '-2103' );
20
 
21
  require_once plugin_dir_path( __FILE__ ) . 'inc/functions.php';
22